Pull networking updates from David Miller: "Highlights: 1) Support more Realtek wireless chips, from Jes Sorenson. 2) New BPF types for per-cpu hash and arrap maps, from Alexei Starovoitov. 3) Make several TCP sysctls per-namespace, from Nikolay Borisov. 4) Allow the use of SO_REUSEPORT in order to do per-thread processing of incoming TCP/UDP connections. The muxing can be done using a BPF program which hashes the incoming packet. From Craig Gallek. 5) Add a multiplexer for TCP streams, to provide a messaged based interface. BPF programs can be used to determine the message boundaries. From Tom Herbert. 6) Add 802.1AE MACSEC support, from Sabrina Dubroca. 7) Avoid factorial complexity when taking down an inetdev interface with lots of configured addresses. We were doing things like traversing the entire address less for each address removed, and flushing the entire netfilter conntrack table for every address as well. 8) Add and use SKB bulk free infrastructure, from Jesper Brouer. 9) Allow offloading u32 classifiers to hardware, and implement for ixgbe, from John Fastabend. 10) Allow configuring IRQ coalescing parameters on a per-queue basis, from Kan Liang. 11) Extend ethtool so that larger link mode masks can be supported. From David Decotigny. 12) Introduce devlink, which can be used to configure port link types (ethernet vs Infiniband, etc.), port splitting, and switch device level attributes as a whole. From Jiri Pirko. 13) Hardware offload support for flower classifiers, from Amir Vadai. 14) Add "Local Checksum Offload". Basically, for a tunneled packet the checksum of the outer header is 'constant' (because with the checksum field filled into the inner protocol header, the payload of the outer frame checksums to 'zero'), and we can take advantage of that in various ways. From Edward Cree" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1548 commits) bonding: fix bond_get_stats() net: bcmgenet: fix dma api length mismatch net/mlx4_core: Fix backward compatibility on VFs phy: mdio-thunder: Fix some Kconfig typos lan78xx: add ndo_get_stats64 lan78xx: handle statistics counter rollover RDS: TCP: Remove unused constant RDS: TCP: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket net: smc911x: convert pxa dma to dmaengine team: remove duplicate set of flag IFF_MULTICAST bonding: remove duplicate set of flag IFF_MULTICAST net: fix a comment typo ethernet: micrel: fix some error codes ip_tunnels, bpf: define IP_TUNNEL_OPTS_MAX and use it bpf, dst: add and use dst_tclassid helper bpf: make skb->tc_classid also readable net: mvneta: bm: clarify dependencies cls_bpf: reset class and reuse major in da ldmvsw: Checkpatch sunvnet.c and sunvnet_common.c ldmvsw: Add ldmvsw.c driver code ...
Unified · Split
| @@ -1,29 +0,0 @@ | ||
| 1 | −rfkill - radio frequency (RF) connector kill switch support | |
| 2 | − | |
| 3 | −For details to this subsystem look at Documentation/rfkill.txt. | |
| 4 | − | |
| 5 | −What: /sys/class/rfkill/rfkill[0-9]+/state | |
| 6 | −Date: 09-Jul-2007 | |
| 7 | −KernelVersion v2.6.22 | |
| 8 | −Contact: linux-wireless@vger.kernel.org | |
| 9 | −Description: Current state of the transmitter. | |
| 10 | − This file is deprecated and scheduled to be removed in 2014, | |
| 11 | − because its not possible to express the 'soft and hard block' | |
| 12 | − state of the rfkill driver. | |
| 13 | −Values: A numeric value. | |
| 14 | − 0: RFKILL_STATE_SOFT_BLOCKED | |
| 15 | − transmitter is turned off by software | |
| 16 | − 1: RFKILL_STATE_UNBLOCKED | |
| 17 | − transmitter is (potentially) active | |
| 18 | − 2: RFKILL_STATE_HARD_BLOCKED | |
| 19 | − transmitter is forced off by something outside of | |
| 20 | − the driver's control. | |
| 21 | − | |
| 22 | −What: /sys/class/rfkill/rfkill[0-9]+/claim | |
| 23 | −Date: 09-Jul-2007 | |
| 24 | −KernelVersion v2.6.22 | |
| 25 | −Contact: linux-wireless@vger.kernel.org | |
| 26 | −Description: This file is deprecated because there no longer is a way to | |
| 27 | − claim just control over a single rfkill instance. | |
| 28 | − This file is scheduled to be removed in 2012. | |
| 29 | −Values: 0: Kernel handles events | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +rfkill - radio frequency (RF) connector kill switch support | |
| 2 | + | |
| 3 | +For details to this subsystem look at Documentation/rfkill.txt. | |
| 4 | + | |
| 5 | +What: /sys/class/rfkill/rfkill[0-9]+/claim | |
| 6 | +Date: 09-Jul-2007 | |
| 7 | +KernelVersion v2.6.22 | |
| 8 | +Contact: linux-wireless@vger.kernel.org | |
| 9 | +Description: This file was deprecated because there no longer was a way to | |
| 10 | + claim just control over a single rfkill instance. | |
| 11 | + This file was scheduled to be removed in 2012, and was removed | |
| 12 | + in 2016. | |
| 13 | +Values: 0: Kernel handles events | |
| @@ -2,9 +2,8 @@ rfkill - radio frequency (RF) connector kill switch support · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | For details to this subsystem look at Documentation/rfkill.txt. |
| 4 | 4 | |
| 5 | −For the deprecated /sys/class/rfkill/*/state and | |
| 6 | −/sys/class/rfkill/*/claim knobs of this interface look in | |
| 7 | −Documentation/ABI/obsolete/sysfs-class-rfkill. | |
| 5 | +For the deprecated /sys/class/rfkill/*/claim knobs of this interface look in | |
| 6 | +Documentation/ABI/removed/sysfs-class-rfkill. | |
| 8 | 7 | |
| 9 | 8 | What: /sys/class/rfkill |
| 10 | 9 | Date: 09-Jul-2007 |
| @@ -42,6 +41,28 @@ Values: A numeric value. · 31 unmodified lines | ||
| 42 | 41 | 1: true |
| 43 | 42 | |
| 44 | 43 | |
| 44 | +What: /sys/class/rfkill/rfkill[0-9]+/state | |
| 45 | +Date: 09-Jul-2007 | |
| 46 | +KernelVersion v2.6.22 | |
| 47 | +Contact: linux-wireless@vger.kernel.org | |
| 48 | +Description: Current state of the transmitter. | |
| 49 | + This file was scheduled to be removed in 2014, but due to its | |
| 50 | + large number of users it will be sticking around for a bit | |
| 51 | + longer. Despite it being marked as stabe, the newer "hard" and | |
| 52 | + "soft" interfaces should be preffered, since it is not possible | |
| 53 | + to express the 'soft and hard block' state of the rfkill driver | |
| 54 | + through this interface. There will likely be another attempt to | |
| 55 | + remove it in the future. | |
| 56 | +Values: A numeric value. | |
| 57 | + 0: RFKILL_STATE_SOFT_BLOCKED | |
| 58 | + transmitter is turned off by software | |
| 59 | + 1: RFKILL_STATE_UNBLOCKED | |
| 60 | + transmitter is (potentially) active | |
| 61 | + 2: RFKILL_STATE_HARD_BLOCKED | |
| 62 | + transmitter is forced off by something outside of | |
| 63 | + the driver's control. | |
| 64 | + | |
| 65 | + | |
| 45 | 66 | What: /sys/class/rfkill/rfkill[0-9]+/hard |
| 46 | 67 | Date: 12-March-2010 |
| 47 | 68 | KernelVersion v2.6.34 |
| @@ -1,4 +1,20 @@ | ||
| 1 | 1 | |
| 2 | +What: /sys/class/net/<iface>/batman-adv/throughput_override | |
| 3 | +Date: Feb 2014 | |
| 4 | +Contact: Antonio Quartulli <antonio@meshcoding.com> | |
| 5 | +description: | |
| 6 | + Defines the throughput value to be used by B.A.T.M.A.N. V | |
| 7 | + when estimating the link throughput using this interface. | |
| 8 | + If the value is set to 0 then batman-adv will try to | |
| 9 | + estimate the throughput by itself. | |
| 10 | + | |
| 11 | +What: /sys/class/net/<iface>/batman-adv/elp_interval | |
| 12 | +Date: Feb 2014 | |
| 13 | +Contact: Linus Lüssing <linus.luessing@web.de> | |
| 14 | +Description: | |
| 15 | + Defines the interval in milliseconds in which batman | |
| 16 | + sends its probing packets for link quality measurements. | |
| 17 | + | |
| 2 | 18 | What: /sys/class/net/<iface>/batman-adv/iface_status |
| 3 | 19 | Date: May 2010 |
| 4 | 20 | Contact: Marek Lindner <mareklindner@neomailbox.ch> |
| @@ -12,4 +28,3 @@ Description: · 7 unmodified lines | ||
| 12 | 28 | The /sys/class/net/<iface>/batman-adv/mesh_iface file |
| 13 | 29 | displays the batman mesh interface this <iface> |
| 14 | 30 | currently is associated with. |
| 15 | − | |
| @@ -7,6 +7,13 @@ Required properties: · 6 unmodified lines | ||
| 7 | 7 | - max-speed: see ethernet.txt file in the same directory. |
| 8 | 8 | - phy: see ethernet.txt file in the same directory. |
| 9 | 9 | |
| 10 | +Optional properties: | |
| 11 | +- phy-reset-gpios : Should specify the gpio for phy reset | |
| 12 | +- phy-reset-duration : Reset duration in milliseconds. Should present | |
| 13 | + only if property "phy-reset-gpios" is available. Missing the property | |
| 14 | + will have the duration be 1 millisecond. Numbers greater than 1000 are | |
| 15 | + invalid and 1 millisecond will be used instead. | |
| 16 | + | |
| 10 | 17 | Clock handling: |
| 11 | 18 | The clock frequency is needed to calculate and set polling period of EMAC. |
| 12 | 19 | It must be provided by one of: |
| @@ -0,0 +1,15 @@ | ||
| 1 | +IFI CANFD controller | |
| 2 | +-------------------- | |
| 3 | + | |
| 4 | +Required properties: | |
| 5 | + - compatible: Should be "ifi,canfd-1.0" | |
| 6 | + - reg: Should contain CAN controller registers location and length | |
| 7 | + - interrupts: Should contain IRQ line for the CAN controller | |
| 8 | + | |
| 9 | +Example: | |
| 10 | + | |
| 11 | + canfd0: canfd@ff220000 { | |
| 12 | + compatible = "ifi,canfd-1.0"; | |
| 13 | + reg = <0xff220000 0x00001000>; | |
| 14 | + interrupts = <0 43 0>; | |
| 15 | + }; | |
| @@ -6,6 +6,17 @@ Required properties: · 5 unmodified lines | ||
| 6 | 6 | "renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC. |
| 7 | 7 | "renesas,can-r8a7790" if CAN controller is a part of R8A7790 SoC. |
| 8 | 8 | "renesas,can-r8a7791" if CAN controller is a part of R8A7791 SoC. |
| 9 | + "renesas,can-r8a7792" if CAN controller is a part of R8A7792 SoC. | |
| 10 | + "renesas,can-r8a7793" if CAN controller is a part of R8A7793 SoC. | |
| 11 | + "renesas,can-r8a7794" if CAN controller is a part of R8A7794 SoC. | |
| 12 | + "renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC. | |
| 13 | + "renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device. | |
| 14 | + "renesas,rcar-gen2-can" for a generic R-Car Gen2 compatible device. | |
| 15 | + "renesas,rcar-gen3-can" for a generic R-Car Gen3 compatible device. | |
| 16 | + When compatible with the generic version, nodes must list the | |
| 17 | + SoC-specific version corresponding to the platform first | |
| 18 | + followed by the generic version. | |
| 19 | + | |
| 9 | 20 | - reg: physical base address and size of the R-Car CAN register map. |
| 10 | 21 | - interrupts: interrupt specifier for the sole interrupt. |
| 11 | 22 | - clocks: phandles and clock specifiers for 3 CAN clock inputs. |
| @@ -13,6 +24,15 @@ Required properties: · 1 unmodified line | ||
| 13 | 24 | - pinctrl-0: pin control group to be used for this controller. |
| 14 | 25 | - pinctrl-names: must be "default". |
| 15 | 26 | |
| 27 | +Required properties for "renesas,can-r8a7795" compatible: | |
| 28 | +In R8A7795 SoC, "clkp2" can be CANFD clock. This is a div6 clock and can be | |
| 29 | +used by both CAN and CAN FD controller at the same time. It needs to be scaled | |
| 30 | +to maximum frequency if any of these controllers use it. This is done using | |
| 31 | +the below properties. | |
| 32 | + | |
| 33 | +- assigned-clocks: phandle of clkp2(CANFD) clock. | |
| 34 | +- assigned-clock-rates: maximum frequency of this clock. | |
| 35 | + | |
| 16 | 36 | Optional properties: |
| 17 | 37 | - renesas,can-clock-select: R-Car CAN Clock Source Select. Valid values are: |
| 18 | 38 | <0x0> (default) : Peripheral clock (clkp1) |
| @@ -25,7 +45,7 @@ Example · 6 unmodified lines | ||
| 25 | 45 | SoC common .dtsi file: |
| 26 | 46 | |
| 27 | 47 | can0: can@e6e80000 { |
| 28 | − compatible = "renesas,can-r8a7791"; | |
| 48 | + compatible = "renesas,can-r8a7791", "renesas,rcar-gen2-can"; | |
| 29 | 49 | reg = <0 0xe6e80000 0 0x1000>; |
| 30 | 50 | interrupts = <0 186 IRQ_TYPE_LEVEL_HIGH>; |
| 31 | 51 | clocks = <&mstp9_clks R8A7791_CLK_RCAN0>, |
| @@ -2,7 +2,7 @@ Memory mapped SJA1000 CAN controller from NXP (formerly Philips) · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | Required properties: |
| 4 | 4 | |
| 5 | −- compatible : should be "nxp,sja1000". | |
| 5 | +- compatible : should be one of "nxp,sja1000", "technologic,sja1000". | |
| 6 | 6 | |
| 7 | 7 | - reg : should specify the chip select, address offset and size required |
| 8 | 8 | to map the registers of the SJA1000. The size is usually 0x80. |
| @@ -14,6 +14,7 @@ Optional properties: · 5 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | - reg-io-width : Specify the size (in bytes) of the IO accesses that |
| 16 | 16 | should be performed on the device. Valid value is 1, 2 or 4. |
| 17 | + This property is ignored for technologic version. | |
| 17 | 18 | Default to 1 (8 bits). |
| 18 | 19 | |
| 19 | 20 | - nxp,external-clock-frequency : Frequency of the external oscillator |
| @@ -1,9 +1,12 @@ | ||
| 1 | 1 | * System Management Interface (SMI) / MDIO |
| 2 | 2 | |
| 3 | 3 | Properties: |
| 4 | −- compatible: "cavium,octeon-3860-mdio" | |
| 4 | +- compatible: One of: | |
| 5 | 5 | |
| 6 | − Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. | |
| 6 | + "cavium,octeon-3860-mdio": Compatibility with all cn3XXX, cn5XXX | |
| 7 | + and cn6XXX SOCs. | |
| 8 | + | |
| 9 | + "cavium,thunder-8890-mdio": Compatibility with all cn8XXX SOCs. | |
| 7 | 10 | |
| 8 | 11 | - reg: The base address of the MDIO bus controller register bank. |
| 9 | 12 | |
| @@ -25,3 +28,57 @@ Example: · 15 unmodified lines | ||
| 25 | 28 | reg = <0>; |
| 26 | 29 | }; |
| 27 | 30 | }; |
| 31 | + | |
| 32 | + | |
| 33 | +* System Management Interface (SMI) / MDIO Nexus | |
| 34 | + | |
| 35 | + Several mdio buses may be gathered as children of a single PCI | |
| 36 | + device, this PCI device is the nexus of the buses. | |
| 37 | + | |
| 38 | +Properties: | |
| 39 | + | |
| 40 | +- compatible: "cavium,thunder-8890-mdio-nexus"; | |
| 41 | + | |
| 42 | +- reg: The PCI device and function numbers of the nexus device. | |
| 43 | + | |
| 44 | +- #address-cells: Must be <2>. | |
| 45 | + | |
| 46 | +- #size-cells: Must be <2>. | |
| 47 | + | |
| 48 | +- ranges: As needed for mapping of the MDIO bus device registers. | |
| 49 | + | |
| 50 | +- assigned-addresses: As needed for mapping of the MDIO bus device registers. | |
| 51 | + | |
| 52 | +Example: | |
| 53 | + | |
| 54 | + mdio-nexus@1,3 { | |
| 55 | + compatible = "cavium,thunder-8890-mdio-nexus"; | |
| 56 | + #address-cells = <2>; | |
| 57 | + #size-cells = <2>; | |
| 58 | + reg = <0x0b00 0 0 0 0>; /* DEVFN = 0x0b (1:3) */ | |
| 59 | + assigned-addresses = <0x03000000 0x87e0 0x05000000 0x0 0x800000>; | |
| 60 | + ranges = <0x87e0 0x05000000 0x03000000 0x87e0 0x05000000 0x0 0x800000>; | |
| 61 | + | |
| 62 | + mdio0@87e0,05003800 { | |
| 63 | + compatible = "cavium,thunder-8890-mdio"; | |
| 64 | + #address-cells = <1>; | |
| 65 | + #size-cells = <0>; | |
| 66 | + reg = <0x87e0 0x05003800 0x0 0x30>; | |
| 67 | + | |
| 68 | + ethernet-phy@0 { | |
| 69 | + ... | |
| 70 | + reg = <0>; | |
| 71 | + }; | |
| 72 | + }; | |
| 73 | + mdio0@87e0,05003880 { | |
| 74 | + compatible = "cavium,thunder-8890-mdio"; | |
| 75 | + #address-cells = <1>; | |
| 76 | + #size-cells = <0>; | |
| 77 | + reg = <0x87e0 0x05003880 0x0 0x30>; | |
| 78 | + | |
| 79 | + ethernet-phy@0 { | |
| 80 | + ... | |
| 81 | + reg = <0>; | |
| 82 | + }; | |
| 83 | + }; | |
| 84 | + }; | |
| @@ -1,8 +1,10 @@ | ||
| 1 | −* ARC EMAC 10/100 Ethernet platform driver for Rockchip Rk3066/RK3188 SoCs | |
| 1 | +* ARC EMAC 10/100 Ethernet platform driver for Rockchip RK3036/RK3066/RK3188 SoCs | |
| 2 | 2 | |
| 3 | 3 | Required properties: |
| 4 | −- compatible: Should be "rockchip,rk3066-emac" or "rockchip,rk3188-emac" | |
| 5 | − according to the target SoC. | |
| 4 | +- compatible: should be "rockchip,<name>-emac" | |
| 5 | + "rockchip,rk3036-emac": found on RK3036 SoCs | |
| 6 | + "rockchip,rk3066-emac": found on RK3066 SoCs | |
| 7 | + "rockchip,rk3188-emac": found on RK3188 SoCs | |
| 6 | 8 | - reg: Address and length of the register set for the device |
| 7 | 9 | - interrupts: Should contain the EMAC interrupts |
| 8 | 10 | - rockchip,grf: phandle to the syscon grf used to control speed and mode |
| @@ -12,6 +12,9 @@ Optional properties: · 11 unmodified lines | ||
| 12 | 12 | only if property "phy-reset-gpios" is available. Missing the property |
| 13 | 13 | will have the duration be 1 millisecond. Numbers greater than 1000 are |
| 14 | 14 | invalid and 1 millisecond will be used instead. |
| 15 | +- phy-reset-active-high : If present then the reset sequence using the GPIO | |
| 16 | + specified in the "phy-reset-gpios" property is reversed (H=reset state, | |
| 17 | + L=operation state). | |
| 15 | 18 | - phy-supply : regulator that powers the Ethernet PHY. |
| 16 | 19 | - phy-handle : phandle to the PHY device connected to this device. |
| 17 | 20 | - fixed-link : Assume a fixed link. See fixed-link.txt in the same directory. |
| @@ -25,6 +25,8 @@ Required properties: · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | Optional properties for PHY child node: |
| 27 | 27 | - reset-gpios : Should specify the gpio for phy reset |
| 28 | +- magic-packet : If present, indicates that the hardware supports waking | |
| 29 | + up via magic packet. | |
| 28 | 30 | |
| 29 | 31 | Examples: |
| 30 | 32 | |
| @@ -18,15 +18,30 @@ Optional properties: · 17 unmodified lines | ||
| 18 | 18 | "core" for core clock and "bus" for the optional bus clock. |
| 19 | 19 | |
| 20 | 20 | |
| 21 | +Optional properties (valid only for Armada XP/38x): | |
| 22 | + | |
| 23 | +- buffer-manager: a phandle to a buffer manager node. Please refer to | |
| 24 | + Documentation/devicetree/bindings/net/marvell-neta-bm.txt | |
| 25 | +- bm,pool-long: ID of a pool, that will accept all packets of a size | |
| 26 | + higher than 'short' pool's threshold (if set) and up to MTU value. | |
| 27 | + Obligatory, when the port is supposed to use hardware | |
| 28 | + buffer management. | |
| 29 | +- bm,pool-short: ID of a pool, that will be used for accepting | |
| 30 | + packets of a size lower than given threshold. If not set, the port | |
| 31 | + will use a single 'long' pool for all packets, as defined above. | |
| 32 | + | |
| 21 | 33 | Example: |
| 22 | 34 | |
| 23 | −ethernet@d0070000 { | |
| 35 | +ethernet@70000 { | |
| 24 | 36 | compatible = "marvell,armada-370-neta"; |
| 25 | − reg = <0xd0070000 0x2500>; | |
| 37 | + reg = <0x70000 0x2500>; | |
| 26 | 38 | interrupts = <8>; |
| 27 | 39 | clocks = <&gate_clk 4>; |
| 28 | 40 | tx-csum-limit = <9800> |
| 29 | 41 | status = "okay"; |
| 30 | 42 | phy = <&phy0>; |
| 31 | 43 | phy-mode = "rgmii-id"; |
| 44 | + buffer-manager = <&bm>; | |
| 45 | + bm,pool-long = <0>; | |
| 46 | + bm,pool-short = <1>; | |
| 32 | 47 | }; |
| @@ -0,0 +1,49 @@ | ||
| 1 | +* Marvell Armada 380/XP Buffer Manager driver (BM) | |
| 2 | + | |
| 3 | +Required properties: | |
| 4 | + | |
| 5 | +- compatible: should be "marvell,armada-380-neta-bm". | |
| 6 | +- reg: address and length of the register set for the device. | |
| 7 | +- clocks: a pointer to the reference clock for this device. | |
| 8 | +- internal-mem: a phandle to BM internal SRAM definition. | |
| 9 | + | |
| 10 | +Optional properties (port): | |
| 11 | + | |
| 12 | +- pool<0 : 3>,capacity: size of external buffer pointers' ring maintained | |
| 13 | + in DRAM. Can be set for each pool (id 0 : 3) separately. The value has | |
| 14 | + to be chosen between 128 and 16352 and it also has to be aligned to 32. | |
| 15 | + Otherwise the driver would adjust a given number or choose default if | |
| 16 | + not set. | |
| 17 | +- pool<0 : 3>,pkt-size: maximum size of a packet accepted by a given buffer | |
| 18 | + pointers' pool (id 0 : 3). It will be taken into consideration only when pool | |
| 19 | + type is 'short'. For 'long' ones it would be overridden by port's MTU. | |
| 20 | + If not set a driver will choose a default value. | |
| 21 | + | |
| 22 | +In order to see how to hook the BM to a given ethernet port, please | |
| 23 | +refer to Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt. | |
| 24 | + | |
| 25 | +Example: | |
| 26 | + | |
| 27 | +- main node: | |
| 28 | + | |
| 29 | +bm: bm@c8000 { | |
| 30 | + compatible = "marvell,armada-380-neta-bm"; | |
| 31 | + reg = <0xc8000 0xac>; | |
| 32 | + clocks = <&gateclk 13>; | |
| 33 | + internal-mem = <&bm_bppi>; | |
| 34 | + status = "okay"; | |
| 35 | + pool2,capacity = <4096>; | |
| 36 | + pool1,pkt-size = <512>; | |
| 37 | +}; | |
| 38 | + | |
| 39 | +- internal SRAM node: | |
| 40 | + | |
| 41 | +bm_bppi: bm-bppi { | |
| 42 | + compatible = "mmio-sram"; | |
| 43 | + reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>; | |
| 44 | + ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>; | |
| 45 | + #address-cells = <1>; | |
| 46 | + #size-cells = <1>; | |
| 47 | + clocks = <&gateclk 13>; | |
| 48 | + status = "okay"; | |
| 49 | +}; | |
| @@ -0,0 +1,77 @@ | ||
| 1 | +MediaTek Frame Engine Ethernet controller | |
| 2 | +========================================= | |
| 3 | + | |
| 4 | +The frame engine ethernet controller can be found on MediaTek SoCs. These SoCs | |
| 5 | +have dual GMAC each represented by a child node.. | |
| 6 | + | |
| 7 | +* Ethernet controller node | |
| 8 | + | |
| 9 | +Required properties: | |
| 10 | +- compatible: Should be "mediatek,mt7623-eth" | |
| 11 | +- reg: Address and length of the register set for the device | |
| 12 | +- interrupts: Should contain the frame engines interrupt | |
| 13 | +- clocks: the clock used by the core | |
| 14 | +- clock-names: the names of the clock listed in the clocks property. These are | |
| 15 | + "ethif", "esw", "gp2", "gp1" | |
| 16 | +- power-domains: phandle to the power domain that the ethernet is part of | |
| 17 | +- resets: Should contain a phandle to the ethsys reset signal | |
| 18 | +- reset-names: Should contain the reset signal name "eth" | |
| 19 | +- mediatek,ethsys: phandle to the syscon node that handles the port setup | |
| 20 | +- mediatek,pctl: phandle to the syscon node that handles the ports slew rate | |
| 21 | + and driver current | |
| 22 | + | |
| 23 | +Optional properties: | |
| 24 | +- interrupt-parent: Should be the phandle for the interrupt controller | |
| 25 | + that services interrupts for this device | |
| 26 | + | |
| 27 | + | |
| 28 | +* Ethernet MAC node | |
| 29 | + | |
| 30 | +Required properties: | |
| 31 | +- compatible: Should be "mediatek,eth-mac" | |
| 32 | +- reg: The number of the MAC | |
| 33 | +- phy-handle: see ethernet.txt file in the same directory. | |
| 34 | + | |
| 35 | +Example: | |
| 36 | + | |
| 37 | +eth: ethernet@1b100000 { | |
| 38 | + compatible = "mediatek,mt7623-eth"; | |
| 39 | + reg = <0 0x1b100000 0 0x20000>; | |
| 40 | + clocks = <&topckgen CLK_TOP_ETHIF_SEL>, | |
| 41 | + <ðsys CLK_ETHSYS_ESW>, | |
| 42 | + <ðsys CLK_ETHSYS_GP2>, | |
| 43 | + <ðsys CLK_ETHSYS_GP1>; | |
| 44 | + clock-names = "ethif", "esw", "gp2", "gp1"; | |
| 45 | + interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_LOW>; | |
| 46 | + power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; | |
| 47 | + resets = <ðsys MT2701_ETHSYS_ETH_RST>; | |
| 48 | + reset-names = "eth"; | |
| 49 | + mediatek,ethsys = <ðsys>; | |
| 50 | + mediatek,pctl = <&syscfg_pctl_a>; | |
| 51 | + #address-cells = <1>; | |
| 52 | + #size-cells = <0>; | |
| 53 | + | |
| 54 | + gmac1: mac@0 { | |
| 55 | + compatible = "mediatek,eth-mac"; | |
| 56 | + reg = <0>; | |
| 57 | + phy-handle = <&phy0>; | |
| 58 | + }; | |
| 59 | + | |
| 60 | + gmac2: mac@1 { | |
| 61 | + compatible = "mediatek,eth-mac"; | |
| 62 | + reg = <1>; | |
| 63 | + phy-handle = <&phy1>; | |
| 64 | + }; | |
| 65 | + | |
| 66 | + mdio-bus { | |
| 67 | + phy0: ethernet-phy@0 { | |
| 68 | + reg = <0>; | |
| 69 | + phy-mode = "rgmii"; | |
| 70 | + }; | |
| 71 | + | |
| 72 | + phy1: ethernet-phy@1 { | |
| 73 | + reg = <1>; | |
| 74 | + phy-mode = "rgmii"; | |
| 75 | + }; | |
| 76 | + }; | |
| 77 | +}; | |
| @@ -0,0 +1,20 @@ | ||
| 1 | +Micrel KS8995 SPI controlled Ethernet Switch families | |
| 2 | + | |
| 3 | +Required properties (according to spi-bus.txt): | |
| 4 | +- compatible: either "micrel,ks8995", "micrel,ksz8864" or "micrel,ksz8795" | |
| 5 | + | |
| 6 | +Optional properties: | |
| 7 | +- reset-gpios : phandle of gpio that will be used to reset chip during probe | |
| 8 | + | |
| 9 | +Example: | |
| 10 | + | |
| 11 | +spi-master { | |
| 12 | + ... | |
| 13 | + switch@0 { | |
| 14 | + compatible = "micrel,ksz8795"; | |
| 15 | + | |
| 16 | + reg = <0>; | |
| 17 | + spi-max-frequency = <50000000>; | |
| 18 | + reset-gpios = <&gpio0 46 GPIO_ACTIVE_LOW>; | |
| 19 | + }; | |
| 20 | +}; | |
| @@ -17,7 +17,25 @@ Required properties: · 16 unmodified lines | ||
| 17 | 17 | The 1st cell is reset pre-delay in micro seconds. |
| 18 | 18 | The 2nd cell is reset pulse in micro seconds. |
| 19 | 19 | The 3rd cell is reset post-delay in micro seconds. |
| 20 | + | |
| 21 | +Optional properties: | |
| 22 | +- resets: Should contain a phandle to the STMMAC reset signal, if any | |
| 23 | +- reset-names: Should contain the reset signal name "stmmaceth", if a | |
| 24 | + reset phandle is given | |
| 25 | +- max-frame-size: See ethernet.txt file in the same directory | |
| 26 | +- clocks: If present, the first clock should be the GMAC main clock and | |
| 27 | + the second clock should be peripheral's register interface clock. Further | |
| 28 | + clocks may be specified in derived bindings. | |
| 29 | +- clock-names: One name for each entry in the clocks property, the | |
| 30 | + first one should be "stmmaceth" and the second one should be "pclk". | |
| 31 | +- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is | |
| 32 | + available this clock is used for programming the Timestamp Addend Register. | |
| 33 | + If not passed then the system clock will be used and this is fine on some | |
| 34 | + platforms. | |
| 35 | +- tx-fifo-depth: See ethernet.txt file in the same directory | |
| 36 | +- rx-fifo-depth: See ethernet.txt file in the same directory | |
| 20 | 37 | - snps,pbl Programmable Burst Length |
| 38 | +- snps,aal Address-Aligned Beats | |
| 21 | 39 | - snps,fixed-burst Program the DMA to use the fixed burst mode |
| 22 | 40 | - snps,mixed-burst Program the DMA to use the mixed burst mode |
| 23 | 41 | - snps,force_thresh_dma_mode Force DMA to use the threshold mode for |
| @@ -29,27 +47,28 @@ Required properties: · 5 unmodified lines | ||
| 29 | 47 | supported by this device instance |
| 30 | 48 | - snps,perfect-filter-entries: Number of perfect filter entries supported |
| 31 | 49 | by this device instance |
| 32 | − | |
| 33 | −Optional properties: | |
| 34 | −- resets: Should contain a phandle to the STMMAC reset signal, if any | |
| 35 | −- reset-names: Should contain the reset signal name "stmmaceth", if a | |
| 36 | − reset phandle is given | |
| 37 | −- max-frame-size: See ethernet.txt file in the same directory | |
| 38 | −- clocks: If present, the first clock should be the GMAC main clock | |
| 39 | − The optional second clock should be peripheral's register interface clock. | |
| 40 | − The third optional clock should be the ptp reference clock. | |
| 41 | − Further clocks may be specified in derived bindings. | |
| 42 | −- clock-names: One name for each entry in the clocks property. | |
| 43 | − The first one should be "stmmaceth". | |
| 44 | − The optional second one should be "pclk". | |
| 45 | − The optional third one should be "clk_ptp_ref". | |
| 46 | −- snps,burst_len: The AXI burst lenth value of the AXI BUS MODE register. | |
| 47 | −- tx-fifo-depth: See ethernet.txt file in the same directory | |
| 48 | −- rx-fifo-depth: See ethernet.txt file in the same directory | |
| 50 | +- AXI BUS Mode parameters: below the list of all the parameters to program the | |
| 51 | + AXI register inside the DMA module: | |
| 52 | + - snps,lpi_en: enable Low Power Interface | |
| 53 | + - snps,xit_frm: unlock on WoL | |
| 54 | + - snps,wr_osr_lmt: max write oustanding req. limit | |
| 55 | + - snps,rd_osr_lmt: max read oustanding req. limit | |
| 56 | + - snps,kbbe: do not cross 1KiB boundary. | |
| 57 | + - snps,axi_all: align address | |
| 58 | + - snps,blen: this is a vector of supported burst length. | |
| 59 | + - snps,fb: fixed-burst | |
| 60 | + - snps,mb: mixed-burst | |
| 61 | + - snps,rb: rebuild INCRx Burst | |
| 49 | 62 | - mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus. |
| 50 | 63 | |
| 51 | 64 | Examples: |
| 52 | 65 | |
| 66 | + stmmac_axi_setup: stmmac-axi-config { | |
| 67 | + snps,wr_osr_lmt = <0xf>; | |
| 68 | + snps,rd_osr_lmt = <0xf>; | |
| 69 | + snps,blen = <256 128 64 32 0 0 0>; | |
| 70 | + }; | |
| 71 | + | |
| 53 | 72 | gmac0: ethernet@e0800000 { |
| 54 | 73 | compatible = "st,spear600-gmac"; |
| 55 | 74 | reg = <0xe0800000 0x8000>; |
| @@ -65,6 +84,7 @@ Examples: · 9 unmodified lines | ||
| 65 | 84 | tx-fifo-depth = <16384>; |
| 66 | 85 | clocks = <&clock>; |
| 67 | 86 | clock-names = "stmmaceth"; |
| 87 | + snps,axi-config = <&stmmac_axi_setup>; | |
| 68 | 88 | mdio0 { |
| 69 | 89 | #address-cells = <1>; |
| 70 | 90 | #size-cells = <0>; |
| @@ -1,17 +1,46 @@ | ||
| 1 | 1 | * Qualcomm Atheros ath10k wireless devices |
| 2 | 2 | |
| 3 | −For ath10k devices the calibration data can be provided through Device | |
| 4 | −Tree. The node is a child node of the PCI controller. | |
| 5 | − | |
| 6 | 3 | Required properties: |
| 7 | −-compatible : Should be "qcom,ath10k" | |
| 4 | +- compatible: Should be one of the following: | |
| 5 | + * "qcom,ath10k" | |
| 6 | + * "qcom,ipq4019-wifi" | |
| 7 | + | |
| 8 | +PCI based devices uses compatible string "qcom,ath10k" and takes only | |
| 9 | +calibration data via "qcom,ath10k-calibration-data". Rest of the properties | |
| 10 | +are not applicable for PCI based devices. | |
| 11 | + | |
| 12 | +AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi" | |
| 13 | +and also uses most of the properties defined in this doc. | |
| 8 | 14 | |
| 9 | 15 | Optional properties: |
| 16 | +- reg: Address and length of the register set for the device. | |
| 17 | +- resets: Must contain an entry for each entry in reset-names. | |
| 18 | + See ../reset/reseti.txt for details. | |
| 19 | +- reset-names: Must include the list of following reset names, | |
| 20 | + "wifi_cpu_init" | |
| 21 | + "wifi_radio_srif" | |
| 22 | + "wifi_radio_warm" | |
| 23 | + "wifi_radio_cold" | |
| 24 | + "wifi_core_warm" | |
| 25 | + "wifi_core_cold" | |
| 26 | +- clocks: List of clock specifiers, must contain an entry for each required | |
| 27 | + entry in clock-names. | |
| 28 | +- clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref", | |
| 29 | + "wifi_wcss_rtc". | |
| 30 | +- interrupts: List of interrupt lines. Must contain an entry | |
| 31 | + for each entry in the interrupt-names property. | |
| 32 | +- interrupt-names: Must include the entries for MSI interrupt | |
| 33 | + names ("msi0" to "msi15") and legacy interrupt | |
| 34 | + name ("legacy"), | |
| 35 | +- qcom,msi_addr: MSI interrupt address. | |
| 36 | +- qcom,msi_base: Base value to add before writing MSI data into | |
| 37 | + MSI address register. | |
| 10 | 38 | - qcom,ath10k-calibration-data : calibration data as an array, the |
| 11 | 39 | length can vary between hw versions |
| 12 | 40 | |
| 41 | +Example (to supply the calibration data alone): | |
| 13 | 42 | |
| 14 | −Example: | |
| 43 | +In this example, the node is defined as child node of the PCI controller. | |
| 15 | 44 | |
| 16 | 45 | pci { |
| 17 | 46 | pcie@0 { |
| @@ -28,3 +57,53 @@ pci { · 10 unmodified lines | ||
| 28 | 57 | }; |
| 29 | 58 | }; |
| 30 | 59 | }; |
| 60 | + | |
| 61 | +Example (to supply ipq4019 SoC wifi block details): | |
| 62 | + | |
| 63 | +wifi0: wifi@a000000 { | |
| 64 | + compatible = "qcom,ipq4019-wifi"; | |
| 65 | + reg = <0xa000000 0x200000>; | |
| 66 | + resets = <&gcc WIFI0_CPU_INIT_RESET>, | |
| 67 | + <&gcc WIFI0_RADIO_SRIF_RESET>, | |
| 68 | + <&gcc WIFI0_RADIO_WARM_RESET>, | |
| 69 | + <&gcc WIFI0_RADIO_COLD_RESET>, | |
| 70 | + <&gcc WIFI0_CORE_WARM_RESET>, | |
| 71 | + <&gcc WIFI0_CORE_COLD_RESET>; | |
| 72 | + reset-names = "wifi_cpu_init", | |
| 73 | + "wifi_radio_srif", | |
| 74 | + "wifi_radio_warm", | |
| 75 | + "wifi_radio_cold", | |
| 76 | + "wifi_core_warm", | |
| 77 | + "wifi_core_cold"; | |
| 78 | + clocks = <&gcc GCC_WCSS2G_CLK>, | |
| 79 | + <&gcc GCC_WCSS2G_REF_CLK>, | |
| 80 | + <&gcc GCC_WCSS2G_RTC_CLK>; | |
| 81 | + clock-names = "wifi_wcss_cmd", | |
| 82 | + "wifi_wcss_ref", | |
| 83 | + "wifi_wcss_rtc"; | |
| 84 | + interrupts = <0 0x20 0x1>, | |
| 85 | + <0 0x21 0x1>, | |
| 86 | + <0 0x22 0x1>, | |
| 87 | + <0 0x23 0x1>, | |
| 88 | + <0 0x24 0x1>, | |
| 89 | + <0 0x25 0x1>, | |
| 90 | + <0 0x26 0x1>, | |
| 91 | + <0 0x27 0x1>, | |
| 92 | + <0 0x28 0x1>, | |
| 93 | + <0 0x29 0x1>, | |
| 94 | + <0 0x2a 0x1>, | |
| 95 | + <0 0x2b 0x1>, | |
| 96 | + <0 0x2c 0x1>, | |
| 97 | + <0 0x2d 0x1>, | |
| 98 | + <0 0x2e 0x1>, | |
| 99 | + <0 0x2f 0x1>, | |
| 100 | + <0 0xa8 0x0>; | |
| 101 | + interrupt-names = "msi0", "msi1", "msi2", "msi3", | |
| 102 | + "msi4", "msi5", "msi6", "msi7", | |
| 103 | + "msi8", "msi9", "msi10", "msi11", | |
| 104 | + "msi12", "msi13", "msi14", "msi15", | |
| 105 | + "legacy"; | |
| 106 | + qcom,msi_addr = <0x0b006040>; | |
| 107 | + qcom,msi_base = <0x40>; | |
| 108 | + qcom,ath10k-calibration-data = [ 01 02 03 ... ]; | |
| 109 | +}; | |
| @@ -0,0 +1,36 @@ | ||
| 1 | +* Texas Instruments wl1271 wireless lan controller | |
| 2 | + | |
| 3 | +The wl1271 chip can be connected via SPI or via SDIO. This | |
| 4 | +document describes the binding for the SPI connected chip. | |
| 5 | + | |
| 6 | +Required properties: | |
| 7 | +- compatible : Should be "ti,wl1271" | |
| 8 | +- reg : Chip select address of device | |
| 9 | +- spi-max-frequency : Maximum SPI clocking speed of device in Hz | |
| 10 | +- ref-clock-frequency : Reference clock frequency | |
| 11 | +- interrupt-parent, interrupts : | |
| 12 | + Should contain parameters for 1 interrupt line. | |
| 13 | + Interrupt parameters: parent, line number, type. | |
| 14 | +- vwlan-supply : Point the node of the regulator that powers/enable the wl1271 chip | |
| 15 | + | |
| 16 | +Optional properties: | |
| 17 | +- clock-xtal : boolean, clock is generated from XTAL | |
| 18 | + | |
| 19 | +- Please consult Documentation/devicetree/bindings/spi/spi-bus.txt | |
| 20 | + for optional SPI connection related properties, | |
| 21 | + | |
| 22 | +Examples: | |
| 23 | + | |
| 24 | +&spi1 { | |
| 25 | + wl1271@1 { | |
| 26 | + compatible = "ti,wl1271"; | |
| 27 | + | |
| 28 | + reg = <1>; | |
| 29 | + spi-max-frequency = <48000000>; | |
| 30 | + clock-xtal; | |
| 31 | + ref-clock-frequency = <38400000>; | |
| 32 | + interrupt-parent = <&gpio3>; | |
| 33 | + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; | |
| 34 | + vwlan-supply = <&vwlan_fixed>; | |
| 35 | + }; | |
| 36 | +}; | |
| @@ -25,6 +25,11 @@ Required properties in the sram node: · 24 unmodified lines | ||
| 25 | 25 | - ranges : standard definition, should translate from local addresses |
| 26 | 26 | within the sram to bus addresses |
| 27 | 27 | |
| 28 | +Optional properties in the sram node: | |
| 29 | + | |
| 30 | +- no-memory-wc : the flag indicating, that SRAM memory region has not to | |
| 31 | + be remapped as write combining. WC is used by default. | |
| 32 | + | |
| 28 | 33 | Required properties in the area nodes: |
| 29 | 34 | |
| 30 | 35 | - reg : iomem address range, relative to the SRAM range |
| @@ -112,6 +112,7 @@ hp Hewlett Packard · 111 unmodified lines | ||
| 112 | 112 | i2se I2SE GmbH |
| 113 | 113 | ibm International Business Machines (IBM) |
| 114 | 114 | idt Integrated Device Technologies, Inc. |
| 115 | +ifi Ingenieurburo Fur Ic-Technologie (I/F/I) | |
| 115 | 116 | iom Iomega Corporation |
| 116 | 117 | img Imagination Technologies Ltd. |
| 117 | 118 | ingenic Ingenic Semiconductor |
| @@ -44,6 +44,8 @@ can.txt · 43 unmodified lines | ||
| 44 | 44 | - documentation on CAN protocol family. |
| 45 | 45 | cdc_mbim.txt |
| 46 | 46 | - 3G/LTE USB modem (Mobile Broadband Interface Model) |
| 47 | +checksum-offloads.txt | |
| 48 | + - Explanation of checksum offloads; LCO, RCO | |
| 47 | 49 | cops.txt |
| 48 | 50 | - info on the COPS LocalTalk Linux driver |
| 49 | 51 | cs89x0.txt |
| @@ -187,7 +187,7 @@ interfaces to the kernel module settings. · 186 unmodified lines | ||
| 187 | 187 | |
| 188 | 188 | For more information, please see the manpage (man batctl). |
| 189 | 189 | |
| 190 | −batctl is available on http://www.open-mesh.org/ | |
| 190 | +batctl is available on https://www.open-mesh.org/ | |
| 191 | 191 | |
| 192 | 192 | |
| 193 | 193 | CONTACT |
| @@ -0,0 +1,119 @@ | ||
| 1 | +Checksum Offloads in the Linux Networking Stack | |
| 2 | + | |
| 3 | + | |
| 4 | +Introduction | |
| 5 | +============ | |
| 6 | + | |
| 7 | +This document describes a set of techniques in the Linux networking stack | |
| 8 | + to take advantage of checksum offload capabilities of various NICs. | |
| 9 | + | |
| 10 | +The following technologies are described: | |
| 11 | + * TX Checksum Offload | |
| 12 | + * LCO: Local Checksum Offload | |
| 13 | + * RCO: Remote Checksum Offload | |
| 14 | + | |
| 15 | +Things that should be documented here but aren't yet: | |
| 16 | + * RX Checksum Offload | |
| 17 | + * CHECKSUM_UNNECESSARY conversion | |
| 18 | + | |
| 19 | + | |
| 20 | +TX Checksum Offload | |
| 21 | +=================== | |
| 22 | + | |
| 23 | +The interface for offloading a transmit checksum to a device is explained | |
| 24 | + in detail in comments near the top of include/linux/skbuff.h. | |
| 25 | +In brief, it allows to request the device fill in a single ones-complement | |
| 26 | + checksum defined by the sk_buff fields skb->csum_start and | |
| 27 | + skb->csum_offset. The device should compute the 16-bit ones-complement | |
| 28 | + checksum (i.e. the 'IP-style' checksum) from csum_start to the end of the | |
| 29 | + packet, and fill in the result at (csum_start + csum_offset). | |
| 30 | +Because csum_offset cannot be negative, this ensures that the previous | |
| 31 | + value of the checksum field is included in the checksum computation, thus | |
| 32 | + it can be used to supply any needed corrections to the checksum (such as | |
| 33 | + the sum of the pseudo-header for UDP or TCP). | |
| 34 | +This interface only allows a single checksum to be offloaded. Where | |
| 35 | + encapsulation is used, the packet may have multiple checksum fields in | |
| 36 | + different header layers, and the rest will have to be handled by another | |
| 37 | + mechanism such as LCO or RCO. | |
| 38 | +No offloading of the IP header checksum is performed; it is always done in | |
| 39 | + software. This is OK because when we build the IP header, we obviously | |
| 40 | + have it in cache, so summing it isn't expensive. It's also rather short. | |
| 41 | +The requirements for GSO are more complicated, because when segmenting an | |
| 42 | + encapsulated packet both the inner and outer checksums may need to be | |
| 43 | + edited or recomputed for each resulting segment. See the skbuff.h comment | |
| 44 | + (section 'E') for more details. | |
| 45 | + | |
| 46 | +A driver declares its offload capabilities in netdev->hw_features; see | |
| 47 | + Documentation/networking/netdev-features for more. Note that a device | |
| 48 | + which only advertises NETIF_F_IP[V6]_CSUM must still obey the csum_start | |
| 49 | + and csum_offset given in the SKB; if it tries to deduce these itself in | |
| 50 | + hardware (as some NICs do) the driver should check that the values in the | |
| 51 | + SKB match those which the hardware will deduce, and if not, fall back to | |
| 52 | + checksumming in software instead (with skb_checksum_help or one of the | |
| 53 | + skb_csum_off_chk* functions as mentioned in include/linux/skbuff.h). This | |
| 54 | + is a pain, but that's what you get when hardware tries to be clever. | |
| 55 | + | |
| 56 | +The stack should, for the most part, assume that checksum offload is | |
| 57 | + supported by the underlying device. The only place that should check is | |
| 58 | + validate_xmit_skb(), and the functions it calls directly or indirectly. | |
| 59 | + That function compares the offload features requested by the SKB (which | |
| 60 | + may include other offloads besides TX Checksum Offload) and, if they are | |
| 61 | + not supported or enabled on the device (determined by netdev->features), | |
| 62 | + performs the corresponding offload in software. In the case of TX | |
| 63 | + Checksum Offload, that means calling skb_checksum_help(skb). | |
| 64 | + | |
| 65 | + | |
| 66 | +LCO: Local Checksum Offload | |
| 67 | +=========================== | |
| 68 | + | |
| 69 | +LCO is a technique for efficiently computing the outer checksum of an | |
| 70 | + encapsulated datagram when the inner checksum is due to be offloaded. | |
| 71 | +The ones-complement sum of a correctly checksummed TCP or UDP packet is | |
| 72 | + equal to the sum of the pseudo header, because everything else gets | |
| 73 | + 'cancelled out' by the checksum field. This is because the sum was | |
| 74 | + complemented before being written to the checksum field. | |
| 75 | +More generally, this holds in any case where the 'IP-style' ones complement | |
| 76 | + checksum is used, and thus any checksum that TX Checksum Offload supports. | |
| 77 | +That is, if we have set up TX Checksum Offload with a start/offset pair, we | |
| 78 | + know that _after the device has filled in that checksum_, the ones | |
| 79 | + complement sum from csum_start to the end of the packet will be equal to | |
| 80 | + _whatever value we put in the checksum field beforehand_. This allows us | |
| 81 | + to compute the outer checksum without looking at the payload: we simply | |
| 82 | + stop summing when we get to csum_start, then add the 16-bit word at | |
| 83 | + (csum_start + csum_offset). | |
| 84 | +Then, when the true inner checksum is filled in (either by hardware or by | |
| 85 | + skb_checksum_help()), the outer checksum will become correct by virtue of | |
| 86 | + the arithmetic. | |
| 87 | + | |
| 88 | +LCO is performed by the stack when constructing an outer UDP header for an | |
| 89 | + encapsulation such as VXLAN or GENEVE, in udp_set_csum(). Similarly for | |
| 90 | + the IPv6 equivalents, in udp6_set_csum(). | |
| 91 | +It is also performed when constructing an IPv4 GRE header, in | |
| 92 | + net/ipv4/ip_gre.c:build_header(). It is *not* currently performed when | |
| 93 | + constructing an IPv6 GRE header; the GRE checksum is computed over the | |
| 94 | + whole packet in net/ipv6/ip6_gre.c:ip6gre_xmit2(), but it should be | |
| 95 | + possible to use LCO here as IPv6 GRE still uses an IP-style checksum. | |
| 96 | +All of the LCO implementations use a helper function lco_csum(), in | |
| 97 | + include/linux/skbuff.h. | |
| 98 | + | |
| 99 | +LCO can safely be used for nested encapsulations; in this case, the outer | |
| 100 | + encapsulation layer will sum over both its own header and the 'middle' | |
| 101 | + header. This does mean that the 'middle' header will get summed multiple | |
| 102 | + times, but there doesn't seem to be a way to avoid that without incurring | |
| 103 | + bigger costs (e.g. in SKB bloat). | |
| 104 | + | |
| 105 | + | |
| 106 | +RCO: Remote Checksum Offload | |
| 107 | +============================ | |
| 108 | + | |
| 109 | +RCO is a technique for eliding the inner checksum of an encapsulated | |
| 110 | + datagram, allowing the outer checksum to be offloaded. It does, however, | |
| 111 | + involve a change to the encapsulation protocols, which the receiver must | |
| 112 | + also support. For this reason, it is disabled by default. | |
| 113 | +RCO is detailed in the following Internet-Drafts: | |
| 114 | +https://tools.ietf.org/html/draft-herbert-remotecsumoffload-00 | |
| 115 | +https://tools.ietf.org/html/draft-herbert-vxlan-rco-00 | |
| 116 | +In Linux, RCO is implemented individually in each encapsulation protocol, | |
| 117 | + and most tunnel types have flags controlling its use. For instance, VXLAN | |
| 118 | + has the flag VXLAN_F_REMCSUM_TX (per struct vxlan_rdst) to indicate that | |
| 119 | + RCO should be used when transmitting to a given remote destination. | |
| @@ -521,20 +521,17 @@ See Documentation/hwmon/sysfs-interface for details. · 520 unmodified lines | ||
| 521 | 521 | Bridge layer |
| 522 | 522 | ------------ |
| 523 | 523 | |
| 524 | −- port_join_bridge: bridge layer function invoked when a given switch port is | |
| 524 | +- port_bridge_join: bridge layer function invoked when a given switch port is | |
| 525 | 525 | added to a bridge, this function should be doing the necessary at the switch |
| 526 | 526 | level to permit the joining port from being added to the relevant logical |
| 527 | − domain for it to ingress/egress traffic with other members of the bridge. DSA | |
| 528 | − does nothing but calculate a bitmask of switch ports currently members of the | |
| 529 | − specified bridge being requested the join | |
| 527 | + domain for it to ingress/egress traffic with other members of the bridge. | |
| 530 | 528 | |
| 531 | −- port_leave_bridge: bridge layer function invoked when a given switch port is | |
| 529 | +- port_bridge_leave: bridge layer function invoked when a given switch port is | |
| 532 | 530 | removed from a bridge, this function should be doing the necessary at the |
| 533 | 531 | switch level to deny the leaving port from ingress/egress traffic from the |
| 534 | 532 | remaining bridge members. When the port leaves the bridge, it should be aged |
| 535 | 533 | out at the switch hardware for the switch to (re) learn MAC addresses behind |
| 536 | − this port. DSA calculates the bitmask of ports still members of the bridge | |
| 537 | − being left | |
| 534 | + this port. | |
| 538 | 535 | |
| 539 | 536 | - port_stp_update: bridge layer function invoked when a given switch port STP |
| 540 | 537 | state is computed by the bridge layer and should be propagated to switch |
| @@ -545,20 +542,15 @@ Bridge layer · 4 unmodified lines | ||
| 545 | 542 | Bridge VLAN filtering |
| 546 | 543 | --------------------- |
| 547 | 544 | |
| 548 | −- port_pvid_get: bridge layer function invoked when a Port-based VLAN ID is | |
| 549 | − queried for the given switch port | |
| 550 | − | |
| 551 | −- port_pvid_set: bridge layer function invoked when a Port-based VLAN ID needs | |
| 552 | − to be configured on the given switch port | |
| 553 | − | |
| 554 | 545 | - port_vlan_add: bridge layer function invoked when a VLAN is configured |
| 555 | 546 | (tagged or untagged) for the given switch port |
| 556 | 547 | |
| 557 | 548 | - port_vlan_del: bridge layer function invoked when a VLAN is removed from the |
| 558 | 549 | given switch port |
| 559 | 550 | |
| 560 | −- vlan_getnext: bridge layer function invoked to query the next configured VLAN | |
| 561 | − in the switch, i.e. returns the bitmaps of members and untagged ports | |
| 551 | +- port_vlan_dump: bridge layer function invoked with a switchdev callback | |
| 552 | + function that the driver has to call for each VLAN the given port is a member | |
| 553 | + of. A switchdev object is used to carry the VID and bridge flags. | |
| 562 | 554 | |
| 563 | 555 | - port_fdb_add: bridge layer function invoked when the bridge wants to install a |
| 564 | 556 | Forwarding Database entry, the switch hardware should be programmed with the |
| @@ -1216,6 +1216,19 @@ promote_secondaries - BOOLEAN · 1215 unmodified lines | ||
| 1216 | 1216 | promote a corresponding secondary IP address instead of |
| 1217 | 1217 | removing all the corresponding secondary IP addresses. |
| 1218 | 1218 | |
| 1219 | +drop_unicast_in_l2_multicast - BOOLEAN | |
| 1220 | + Drop any unicast IP packets that are received in link-layer | |
| 1221 | + multicast (or broadcast) frames. | |
| 1222 | + This behavior (for multicast) is actually a SHOULD in RFC | |
| 1223 | + 1122, but is disabled by default for compatibility reasons. | |
| 1224 | + Default: off (0) | |
| 1225 | + | |
| 1226 | +drop_gratuitous_arp - BOOLEAN | |
| 1227 | + Drop all gratuitous ARP frames, for example if there's a known | |
| 1228 | + good ARP proxy on the network and such frames need not be used | |
| 1229 | + (or in the case of 802.11, must not be used to prevent attacks.) | |
| 1230 | + Default: off (0) | |
| 1231 | + | |
| 1219 | 1232 | |
| 1220 | 1233 | tag - INTEGER |
| 1221 | 1234 | Allows you to write a number, which can be used as required. |
| @@ -1550,6 +1563,15 @@ temp_prefered_lft - INTEGER · 328 unmodified lines | ||
| 1550 | 1563 | Preferred lifetime (in seconds) for temporary addresses. |
| 1551 | 1564 | Default: 86400 (1 day) |
| 1552 | 1565 | |
| 1566 | +keep_addr_on_down - INTEGER | |
| 1567 | + Keep all IPv6 addresses on an interface down event. If set static | |
| 1568 | + global addresses with no expiration time are not flushed. | |
| 1569 | + >0 : enabled | |
| 1570 | + 0 : system default | |
| 1571 | + <0 : disabled | |
| 1572 | + | |
| 1573 | + Default: 0 (addresses are removed) | |
| 1574 | + | |
| 1553 | 1575 | max_desync_factor - INTEGER |
| 1554 | 1576 | Maximum value for DESYNC_FACTOR, which is a random value |
| 1555 | 1577 | that ensures that clients don't synchronize with each |
| @@ -1661,6 +1683,19 @@ stable_secret - IPv6 address · 105 unmodified lines | ||
| 1661 | 1683 | |
| 1662 | 1684 | By default the stable secret is unset. |
| 1663 | 1685 | |
| 1686 | +drop_unicast_in_l2_multicast - BOOLEAN | |
| 1687 | + Drop any unicast IPv6 packets that are received in link-layer | |
| 1688 | + multicast (or broadcast) frames. | |
| 1689 | + | |
| 1690 | + By default this is turned off. | |
| 1691 | + | |
| 1692 | +drop_unsolicited_na - BOOLEAN | |
| 1693 | + Drop all unsolicited neighbor advertisements, for example if there's | |
| 1694 | + a known good NA proxy on the network and such frames need not be used | |
| 1695 | + (or in the case of 802.11, must not be used to prevent attacks.) | |
| 1696 | + | |
| 1697 | + By default this is turned off. | |
| 1698 | + | |
| 1664 | 1699 | icmp/*: |
| 1665 | 1700 | ratelimit - INTEGER |
| 1666 | 1701 | Limit the maximal rates for sending ICMPv6 packets. |
| @@ -0,0 +1,285 @@ | ||
| 1 | +Kernel Connection Mulitplexor | |
| 2 | +----------------------------- | |
| 3 | + | |
| 4 | +Kernel Connection Multiplexor (KCM) is a mechanism that provides a message based | |
| 5 | +interface over TCP for generic application protocols. With KCM an application | |
| 6 | +can efficiently send and receive application protocol messages over TCP using | |
| 7 | +datagram sockets. | |
| 8 | + | |
| 9 | +KCM implements an NxM multiplexor in the kernel as diagrammed below: | |
| 10 | + | |
| 11 | ++------------+ +------------+ +------------+ +------------+ | |
| 12 | +| KCM socket | | KCM socket | | KCM socket | | KCM socket | | |
| 13 | ++------------+ +------------+ +------------+ +------------+ | |
| 14 | + | | | | | |
| 15 | + +-----------+ | | +----------+ | |
| 16 | + | | | | | |
| 17 | + +----------------------------------+ | |
| 18 | + | Multiplexor | | |
| 19 | + +----------------------------------+ | |
| 20 | + | | | | | | |
| 21 | + +---------+ | | | ------------+ | |
| 22 | + | | | | | | |
| 23 | ++----------+ +----------+ +----------+ +----------+ +----------+ | |
| 24 | +| Psock | | Psock | | Psock | | Psock | | Psock | | |
| 25 | ++----------+ +----------+ +----------+ +----------+ +----------+ | |
| 26 | + | | | | | | |
| 27 | ++----------+ +----------+ +----------+ +----------+ +----------+ | |
| 28 | +| TCP sock | | TCP sock | | TCP sock | | TCP sock | | TCP sock | | |
| 29 | ++----------+ +----------+ +----------+ +----------+ +----------+ | |
| 30 | + | |
| 31 | +KCM sockets | |
| 32 | +----------- | |
| 33 | + | |
| 34 | +The KCM sockets provide the user interface to the muliplexor. All the KCM sockets | |
| 35 | +bound to a multiplexor are considered to have equivalent function, and I/O | |
| 36 | +operations in different sockets may be done in parallel without the need for | |
| 37 | +synchronization between threads in userspace. | |
| 38 | + | |
| 39 | +Multiplexor | |
| 40 | +----------- | |
| 41 | + | |
| 42 | +The multiplexor provides the message steering. In the transmit path, messages | |
| 43 | +written on a KCM socket are sent atomically on an appropriate TCP socket. | |
| 44 | +Similarly, in the receive path, messages are constructed on each TCP socket | |
| 45 | +(Psock) and complete messages are steered to a KCM socket. | |
| 46 | + | |
| 47 | +TCP sockets & Psocks | |
| 48 | +-------------------- | |
| 49 | + | |
| 50 | +TCP sockets may be bound to a KCM multiplexor. A Psock structure is allocated | |
| 51 | +for each bound TCP socket, this structure holds the state for constructing | |
| 52 | +messages on receive as well as other connection specific information for KCM. | |
| 53 | + | |
| 54 | +Connected mode semantics | |
| 55 | +------------------------ | |
| 56 | + | |
| 57 | +Each multiplexor assumes that all attached TCP connections are to the same | |
| 58 | +destination and can use the different connections for load balancing when | |
| 59 | +transmitting. The normal send and recv calls (include sendmmsg and recvmmsg) | |
| 60 | +can be used to send and receive messages from the KCM socket. | |
| 61 | + | |
| 62 | +Socket types | |
| 63 | +------------ | |
| 64 | + | |
| 65 | +KCM supports SOCK_DGRAM and SOCK_SEQPACKET socket types. | |
| 66 | + | |
| 67 | +Message delineation | |
| 68 | +------------------- | |
| 69 | + | |
| 70 | +Messages are sent over a TCP stream with some application protocol message | |
| 71 | +format that typically includes a header which frames the messages. The length | |
| 72 | +of a received message can be deduced from the application protocol header | |
| 73 | +(often just a simple length field). | |
| 74 | + | |
| 75 | +A TCP stream must be parsed to determine message boundaries. Berkeley Packet | |
| 76 | +Filter (BPF) is used for this. When attaching a TCP socket to a multiplexor a | |
| 77 | +BPF program must be specified. The program is called at the start of receiving | |
| 78 | +a new message and is given an skbuff that contains the bytes received so far. | |
| 79 | +It parses the message header and returns the length of the message. Given this | |
| 80 | +information, KCM will construct the message of the stated length and deliver it | |
| 81 | +to a KCM socket. | |
| 82 | + | |
| 83 | +TCP socket management | |
| 84 | +--------------------- | |
| 85 | + | |
| 86 | +When a TCP socket is attached to a KCM multiplexor data ready (POLLIN) and | |
| 87 | +write space available (POLLOUT) events are handled by the multiplexor. If there | |
| 88 | +is a state change (disconnection) or other error on a TCP socket, an error is | |
| 89 | +posted on the TCP socket so that a POLLERR event happens and KCM discontinues | |
| 90 | +using the socket. When the application gets the error notification for a | |
| 91 | +TCP socket, it should unattach the socket from KCM and then handle the error | |
| 92 | +condition (the typical response is to close the socket and create a new | |
| 93 | +connection if necessary). | |
| 94 | + | |
| 95 | +KCM limits the maximum receive message size to be the size of the receive | |
| 96 | +socket buffer on the attached TCP socket (the socket buffer size can be set by | |
| 97 | +SO_RCVBUF). If the length of a new message reported by the BPF program is | |
| 98 | +greater than this limit a corresponding error (EMSGSIZE) is posted on the TCP | |
| 99 | +socket. The BPF program may also enforce a maximum messages size and report an | |
| 100 | +error when it is exceeded. | |
| 101 | + | |
| 102 | +A timeout may be set for assembling messages on a receive socket. The timeout | |
| 103 | +value is taken from the receive timeout of the attached TCP socket (this is set | |
| 104 | +by SO_RCVTIMEO). If the timer expires before assembly is complete an error | |
| 105 | +(ETIMEDOUT) is posted on the socket. | |
| 106 | + | |
| 107 | +User interface | |
| 108 | +============== | |
| 109 | + | |
| 110 | +Creating a multiplexor | |
| 111 | +---------------------- | |
| 112 | + | |
| 113 | +A new multiplexor and initial KCM socket is created by a socket call: | |
| 114 | + | |
| 115 | + socket(AF_KCM, type, protocol) | |
| 116 | + | |
| 117 | + - type is either SOCK_DGRAM or SOCK_SEQPACKET | |
| 118 | + - protocol is KCMPROTO_CONNECTED | |
| 119 | + | |
| 120 | +Cloning KCM sockets | |
| 121 | +------------------- | |
| 122 | + | |
| 123 | +After the first KCM socket is created using the socket call as described | |
| 124 | +above, additional sockets for the multiplexor can be created by cloning | |
| 125 | +a KCM socket. This is accomplished by an ioctl on a KCM socket: | |
| 126 | + | |
| 127 | + /* From linux/kcm.h */ | |
| 128 | + struct kcm_clone { | |
| 129 | + int fd; | |
| 130 | + }; | |
| 131 | + | |
| 132 | + struct kcm_clone info; | |
| 133 | + | |
| 134 | + memset(&info, 0, sizeof(info)); | |
| 135 | + | |
| 136 | + err = ioctl(kcmfd, SIOCKCMCLONE, &info); | |
| 137 | + | |
| 138 | + if (!err) | |
| 139 | + newkcmfd = info.fd; | |
| 140 | + | |
| 141 | +Attach transport sockets | |
| 142 | +------------------------ | |
| 143 | + | |
| 144 | +Attaching of transport sockets to a multiplexor is performed by calling an | |
| 145 | +ioctl on a KCM socket for the multiplexor. e.g.: | |
| 146 | + | |
| 147 | + /* From linux/kcm.h */ | |
| 148 | + struct kcm_attach { | |
| 149 | + int fd; | |
| 150 | + int bpf_fd; | |
| 151 | + }; | |
| 152 | + | |
| 153 | + struct kcm_attach info; | |
| 154 | + | |
| 155 | + memset(&info, 0, sizeof(info)); | |
| 156 | + | |
| 157 | + info.fd = tcpfd; | |
| 158 | + info.bpf_fd = bpf_prog_fd; | |
| 159 | + | |
| 160 | + ioctl(kcmfd, SIOCKCMATTACH, &info); | |
| 161 | + | |
| 162 | +The kcm_attach structure contains: | |
| 163 | + fd: file descriptor for TCP socket being attached | |
| 164 | + bpf_prog_fd: file descriptor for compiled BPF program downloaded | |
| 165 | + | |
| 166 | +Unattach transport sockets | |
| 167 | +-------------------------- | |
| 168 | + | |
| 169 | +Unattaching a transport socket from a multiplexor is straightforward. An | |
| 170 | +"unattach" ioctl is done with the kcm_unattach structure as the argument: | |
| 171 | + | |
| 172 | + /* From linux/kcm.h */ | |
| 173 | + struct kcm_unattach { | |
| 174 | + int fd; | |
| 175 | + }; | |
| 176 | + | |
| 177 | + struct kcm_unattach info; | |
| 178 | + | |
| 179 | + memset(&info, 0, sizeof(info)); | |
| 180 | + | |
| 181 | + info.fd = cfd; | |
| 182 | + | |
| 183 | + ioctl(fd, SIOCKCMUNATTACH, &info); | |
| 184 | + | |
| 185 | +Disabling receive on KCM socket | |
| 186 | +------------------------------- | |
| 187 | + | |
| 188 | +A setsockopt is used to disable or enable receiving on a KCM socket. | |
| 189 | +When receive is disabled, any pending messages in the socket's | |
| 190 | +receive buffer are moved to other sockets. This feature is useful | |
| 191 | +if an application thread knows that it will be doing a lot of | |
| 192 | +work on a request and won't be able to service new messages for a | |
| 193 | +while. Example use: | |
| 194 | + | |
| 195 | + int val = 1; | |
| 196 | + | |
| 197 | + setsockopt(kcmfd, SOL_KCM, KCM_RECV_DISABLE, &val, sizeof(val)) | |
| 198 | + | |
| 199 | +BFP programs for message delineation | |
| 200 | +------------------------------------ | |
| 201 | + | |
| 202 | +BPF programs can be compiled using the BPF LLVM backend. For exmple, | |
| 203 | +the BPF program for parsing Thrift is: | |
| 204 | + | |
| 205 | + #include "bpf.h" /* for __sk_buff */ | |
| 206 | + #include "bpf_helpers.h" /* for load_word intrinsic */ | |
| 207 | + | |
| 208 | + SEC("socket_kcm") | |
| 209 | + int bpf_prog1(struct __sk_buff *skb) | |
| 210 | + { | |
| 211 | + return load_word(skb, 0) + 4; | |
| 212 | + } | |
| 213 | + | |
| 214 | + char _license[] SEC("license") = "GPL"; | |
| 215 | + | |
| 216 | +Use in applications | |
| 217 | +=================== | |
| 218 | + | |
| 219 | +KCM accelerates application layer protocols. Specifically, it allows | |
| 220 | +applications to use a message based interface for sending and receiving | |
| 221 | +messages. The kernel provides necessary assurances that messages are sent | |
| 222 | +and received atomically. This relieves much of the burden applications have | |
| 223 | +in mapping a message based protocol onto the TCP stream. KCM also make | |
| 224 | +application layer messages a unit of work in the kernel for the purposes of | |
| 225 | +steerng and scheduling, which in turn allows a simpler networking model in | |
| 226 | +multithreaded applications. | |
| 227 | + | |
| 228 | +Configurations | |
| 229 | +-------------- | |
| 230 | + | |
| 231 | +In an Nx1 configuration, KCM logically provides multiple socket handles | |
| 232 | +to the same TCP connection. This allows parallelism between in I/O | |
| 233 | +operations on the TCP socket (for instance copyin and copyout of data is | |
| 234 | +parallelized). In an application, a KCM socket can be opened for each | |
| 235 | +processing thread and inserted into the epoll (similar to how SO_REUSEPORT | |
| 236 | +is used to allow multiple listener sockets on the same port). | |
| 237 | + | |
| 238 | +In a MxN configuration, multiple connections are established to the | |
| 239 | +same destination. These are used for simple load balancing. | |
| 240 | + | |
| 241 | +Message batching | |
| 242 | +---------------- | |
| 243 | + | |
| 244 | +The primary purpose of KCM is load balancing between KCM sockets and hence | |
| 245 | +threads in a nominal use case. Perfect load balancing, that is steering | |
| 246 | +each received message to a different KCM socket or steering each sent | |
| 247 | +message to a different TCP socket, can negatively impact performance | |
| 248 | +since this doesn't allow for affinities to be established. Balancing | |
| 249 | +based on groups, or batches of messages, can be beneficial for performance. | |
| 250 | + | |
| 251 | +On transmit, there are three ways an application can batch (pipeline) | |
| 252 | +messages on a KCM socket. | |
| 253 | + 1) Send multiple messages in a single sendmmsg. | |
| 254 | + 2) Send a group of messages each with a sendmsg call, where all messages | |
| 255 | + except the last have MSG_BATCH in the flags of sendmsg call. | |
| 256 | + 3) Create "super message" composed of multiple messages and send this | |
| 257 | + with a single sendmsg. | |
| 258 | + | |
| 259 | +On receive, the KCM module attempts to queue messages received on the | |
| 260 | +same KCM socket during each TCP ready callback. The targeted KCM socket | |
| 261 | +changes at each receive ready callback on the KCM socket. The application | |
| 262 | +does not need to configure this. | |
| 263 | + | |
| 264 | +Error handling | |
| 265 | +-------------- | |
| 266 | + | |
| 267 | +An application should include a thread to monitor errors raised on | |
| 268 | +the TCP connection. Normally, this will be done by placing each | |
| 269 | +TCP socket attached to a KCM multiplexor in epoll set for POLLERR | |
| 270 | +event. If an error occurs on an attached TCP socket, KCM sets an EPIPE | |
| 271 | +on the socket thus waking up the application thread. When the application | |
| 272 | +sees the error (which may just be a disconnect) it should unattach the | |
| 273 | +socket from KCM and then close it. It is assumed that once an error is | |
| 274 | +posted on the TCP socket the data stream is unrecoverable (i.e. an error | |
| 275 | +may have occurred in in the middle of receiving a messssge). | |
| 276 | + | |
| 277 | +TCP connection monitoring | |
| 278 | +------------------------- | |
| 279 | + | |
| 280 | +In KCM there is no means to correlate a message to the TCP socket that | |
| 281 | +was used to send or receive the message (except in the case there is | |
| 282 | +only one attached TCP socket). However, the application does retain | |
| 283 | +an open file descriptor to the socket so it will be able to get statistics | |
| 284 | +from the socket which can be used in detecting issues (such as high | |
| 285 | +retransmissions on the socket). | |
| @@ -28,6 +28,23 @@ radiotap headers and used to control injection: · 27 unmodified lines | ||
| 28 | 28 | IEEE80211_RADIOTAP_F_TX_NOACK: frame should be sent without waiting for |
| 29 | 29 | an ACK even if it is a unicast frame |
| 30 | 30 | |
| 31 | + * IEEE80211_RADIOTAP_RATE | |
| 32 | + | |
| 33 | + legacy rate for the transmission (only for devices without own rate control) | |
| 34 | + | |
| 35 | + * IEEE80211_RADIOTAP_MCS | |
| 36 | + | |
| 37 | + HT rate for the transmission (only for devices without own rate control). | |
| 38 | + Also some flags are parsed | |
| 39 | + | |
| 40 | + IEEE80211_TX_RC_SHORT_GI: use short guard interval | |
| 41 | + IEEE80211_TX_RC_40_MHZ_WIDTH: send in HT40 mode | |
| 42 | + | |
| 43 | + * IEEE80211_RADIOTAP_DATA_RETRIES | |
| 44 | + | |
| 45 | + number of retries when either IEEE80211_RADIOTAP_RATE or | |
| 46 | + IEEE80211_RADIOTAP_MCS was used | |
| 47 | + | |
| 31 | 48 | The injection code can also skip all other currently defined radiotap fields |
| 32 | 49 | facilitating replay of captured radiotap headers directly. |
| 33 | 50 | |
| @@ -1,332 +0,0 @@ | ||
| 1 | −This file documents how to use memory mapped I/O with netlink. | |
| 2 | − | |
| 3 | −Author: Patrick McHardy <kaber@trash.net> | |
| 4 | − | |
| 5 | −Overview | |
| 6 | −-------- | |
| 7 | − | |
| 8 | −Memory mapped netlink I/O can be used to increase throughput and decrease | |
| 9 | −overhead of unicast receive and transmit operations. Some netlink subsystems | |
| 10 | −require high throughput, these are mainly the netfilter subsystems | |
| 11 | −nfnetlink_queue and nfnetlink_log, but it can also help speed up large | |
| 12 | −dump operations of f.i. the routing database. | |
| 13 | − | |
| 14 | −Memory mapped netlink I/O used two circular ring buffers for RX and TX which | |
| 15 | −are mapped into the processes address space. | |
| 16 | − | |
| 17 | −The RX ring is used by the kernel to directly construct netlink messages into | |
| 18 | −user-space memory without copying them as done with regular socket I/O, | |
| 19 | −additionally as long as the ring contains messages no recvmsg() or poll() | |
| 20 | −syscalls have to be issued by user-space to get more message. | |
| 21 | − | |
| 22 | −The TX ring is used to process messages directly from user-space memory, the | |
| 23 | −kernel processes all messages contained in the ring using a single sendmsg() | |
| 24 | −call. | |
| 25 | − | |
| 26 | −Usage overview | |
| 27 | −-------------- | |
| 28 | − | |
| 29 | −In order to use memory mapped netlink I/O, user-space needs three main changes: | |
| 30 | − | |
| 31 | −- ring setup | |
| 32 | −- conversion of the RX path to get messages from the ring instead of recvmsg() | |
| 33 | −- conversion of the TX path to construct messages into the ring | |
| 34 | − | |
| 35 | −Ring setup is done using setsockopt() to provide the ring parameters to the | |
| 36 | −kernel, then a call to mmap() to map the ring into the processes address space: | |
| 37 | − | |
| 38 | −- setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, ¶ms, sizeof(params)); | |
| 39 | −- setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, ¶ms, sizeof(params)); | |
| 40 | −- ring = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) | |
| 41 | − | |
| 42 | −Usage of either ring is optional, but even if only the RX ring is used the | |
| 43 | −mapping still needs to be writable in order to update the frame status after | |
| 44 | −processing. | |
| 45 | − | |
| 46 | −Conversion of the reception path involves calling poll() on the file | |
| 47 | −descriptor, once the socket is readable the frames from the ring are | |
| 48 | −processed in order until no more messages are available, as indicated by | |
| 49 | −a status word in the frame header. | |
| 50 | − | |
| 51 | −On kernel side, in order to make use of memory mapped I/O on receive, the | |
| 52 | −originating netlink subsystem needs to support memory mapped I/O, otherwise | |
| 53 | −it will use an allocated socket buffer as usual and the contents will be | |
| 54 | − copied to the ring on transmission, nullifying most of the performance gains. | |
| 55 | −Dumps of kernel databases automatically support memory mapped I/O. | |
| 56 | − | |
| 57 | −Conversion of the transmit path involves changing message construction to | |
| 58 | −use memory from the TX ring instead of (usually) a buffer declared on the | |
| 59 | −stack and setting up the frame header appropriately. Optionally poll() can | |
| 60 | −be used to wait for free frames in the TX ring. | |
| 61 | − | |
| 62 | −Structured and definitions for using memory mapped I/O are contained in | |
| 63 | −<linux/netlink.h>. | |
| 64 | − | |
| 65 | −RX and TX rings | |
| 66 | −---------------- | |
| 67 | − | |
| 68 | −Each ring contains a number of continuous memory blocks, containing frames of | |
| 69 | −fixed size dependent on the parameters used for ring setup. | |
| 70 | − | |
| 71 | −Ring: [ block 0 ] | |
| 72 | − [ frame 0 ] | |
| 73 | − [ frame 1 ] | |
| 74 | − [ block 1 ] | |
| 75 | − [ frame 2 ] | |
| 76 | − [ frame 3 ] | |
| 77 | − ... | |
| 78 | − [ block n ] | |
| 79 | − [ frame 2 * n ] | |
| 80 | − [ frame 2 * n + 1 ] | |
| 81 | − | |
| 82 | −The blocks are only visible to the kernel, from the point of view of user-space | |
| 83 | −the ring just contains the frames in a continuous memory zone. | |
| 84 | − | |
| 85 | −The ring parameters used for setting up the ring are defined as follows: | |
| 86 | − | |
| 87 | −struct nl_mmap_req { | |
| 88 | − unsigned int nm_block_size; | |
| 89 | − unsigned int nm_block_nr; | |
| 90 | − unsigned int nm_frame_size; | |
| 91 | − unsigned int nm_frame_nr; | |
| 92 | −}; | |
| 93 | − | |
| 94 | −Frames are grouped into blocks, where each block is a continuous region of memory | |
| 95 | −and holds nm_block_size / nm_frame_size frames. The total number of frames in | |
| 96 | −the ring is nm_frame_nr. The following invariants hold: | |
| 97 | − | |
| 98 | −- frames_per_block = nm_block_size / nm_frame_size | |
| 99 | − | |
| 100 | −- nm_frame_nr = frames_per_block * nm_block_nr | |
| 101 | − | |
| 102 | −Some parameters are constrained, specifically: | |
| 103 | − | |
| 104 | −- nm_block_size must be a multiple of the architectures memory page size. | |
| 105 | − The getpagesize() function can be used to get the page size. | |
| 106 | − | |
| 107 | −- nm_frame_size must be equal or larger to NL_MMAP_HDRLEN, IOW a frame must be | |
| 108 | − able to hold at least the frame header | |
| 109 | − | |
| 110 | −- nm_frame_size must be smaller or equal to nm_block_size | |
| 111 | − | |
| 112 | −- nm_frame_size must be a multiple of NL_MMAP_MSG_ALIGNMENT | |
| 113 | − | |
| 114 | −- nm_frame_nr must equal the actual number of frames as specified above. | |
| 115 | − | |
| 116 | −When the kernel can't allocate physically continuous memory for a ring block, | |
| 117 | −it will fall back to use physically discontinuous memory. This might affect | |
| 118 | −performance negatively, in order to avoid this the nm_frame_size parameter | |
| 119 | −should be chosen to be as small as possible for the required frame size and | |
| 120 | −the number of blocks should be increased instead. | |
| 121 | − | |
| 122 | −Ring frames | |
| 123 | −------------ | |
| 124 | − | |
| 125 | −Each frames contain a frame header, consisting of a synchronization word and some | |
| 126 | −meta-data, and the message itself. | |
| 127 | − | |
| 128 | −Frame: [ header message ] | |
| 129 | − | |
| 130 | −The frame header is defined as follows: | |
| 131 | − | |
| 132 | −struct nl_mmap_hdr { | |
| 133 | − unsigned int nm_status; | |
| 134 | − unsigned int nm_len; | |
| 135 | − __u32 nm_group; | |
| 136 | − /* credentials */ | |
| 137 | − __u32 nm_pid; | |
| 138 | − __u32 nm_uid; | |
| 139 | − __u32 nm_gid; | |
| 140 | −}; | |
| 141 | − | |
| 142 | −- nm_status is used for synchronizing processing between the kernel and user- | |
| 143 | − space and specifies ownership of the frame as well as the operation to perform | |
| 144 | − | |
| 145 | −- nm_len contains the length of the message contained in the data area | |
| 146 | − | |
| 147 | −- nm_group specified the destination multicast group of message | |
| 148 | − | |
| 149 | −- nm_pid, nm_uid and nm_gid contain the netlink pid, UID and GID of the sending | |
| 150 | − process. These values correspond to the data available using SOCK_PASSCRED in | |
| 151 | − the SCM_CREDENTIALS cmsg. | |
| 152 | − | |
| 153 | −The possible values in the status word are: | |
| 154 | − | |
| 155 | −- NL_MMAP_STATUS_UNUSED: | |
| 156 | − RX ring: frame belongs to the kernel and contains no message | |
| 157 | − for user-space. Approriate action is to invoke poll() | |
| 158 | − to wait for new messages. | |
| 159 | − | |
| 160 | − TX ring: frame belongs to user-space and can be used for | |
| 161 | − message construction. | |
| 162 | − | |
| 163 | −- NL_MMAP_STATUS_RESERVED: | |
| 164 | − RX ring only: frame is currently used by the kernel for message | |
| 165 | − construction and contains no valid message yet. | |
| 166 | − Appropriate action is to invoke poll() to wait for | |
| 167 | − new messages. | |
| 168 | − | |
| 169 | −- NL_MMAP_STATUS_VALID: | |
| 170 | − RX ring: frame contains a valid message. Approriate action is | |
| 171 | − to process the message and release the frame back to | |
| 172 | − the kernel by setting the status to | |
| 173 | − NL_MMAP_STATUS_UNUSED or queue the frame by setting the | |
| 174 | − status to NL_MMAP_STATUS_SKIP. | |
| 175 | − | |
| 176 | − TX ring: the frame contains a valid message from user-space to | |
| 177 | − be processed by the kernel. After completing processing | |
| 178 | − the kernel will release the frame back to user-space by | |
| 179 | − setting the status to NL_MMAP_STATUS_UNUSED. | |
| 180 | − | |
| 181 | −- NL_MMAP_STATUS_COPY: | |
| 182 | − RX ring only: a message is ready to be processed but could not be | |
| 183 | − stored in the ring, either because it exceeded the | |
| 184 | − frame size or because the originating subsystem does | |
| 185 | − not support memory mapped I/O. Appropriate action is | |
| 186 | − to invoke recvmsg() to receive the message and release | |
| 187 | − the frame back to the kernel by setting the status to | |
| 188 | − NL_MMAP_STATUS_UNUSED. | |
| 189 | − | |
| 190 | −- NL_MMAP_STATUS_SKIP: | |
| 191 | − RX ring only: user-space queued the message for later processing, but | |
| 192 | − processed some messages following it in the ring. The | |
| 193 | − kernel should skip this frame when looking for unused | |
| 194 | − frames. | |
| 195 | − | |
| 196 | −The data area of a frame begins at a offset of NL_MMAP_HDRLEN relative to the | |
| 197 | −frame header. | |
| 198 | − | |
| 199 | −TX limitations | |
| 200 | −-------------- | |
| 201 | − | |
| 202 | −As of Jan 2015 the message is always copied from the ring frame to an | |
| 203 | −allocated buffer due to unresolved security concerns. | |
| 204 | −See commit 4682a0358639b29cf ("netlink: Always copy on mmap TX."). | |
| 205 | − | |
| 206 | −Example | |
| 207 | −------- | |
| 208 | − | |
| 209 | −Ring setup: | |
| 210 | − | |
| 211 | − unsigned int block_size = 16 * getpagesize(); | |
| 212 | − struct nl_mmap_req req = { | |
| 213 | − .nm_block_size = block_size, | |
| 214 | − .nm_block_nr = 64, | |
| 215 | − .nm_frame_size = 16384, | |
| 216 | − .nm_frame_nr = 64 * block_size / 16384, | |
| 217 | − }; | |
| 218 | − unsigned int ring_size; | |
| 219 | − void *rx_ring, *tx_ring; | |
| 220 | − | |
| 221 | − /* Configure ring parameters */ | |
| 222 | − if (setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req)) < 0) | |
| 223 | − exit(1); | |
| 224 | − if (setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req)) < 0) | |
| 225 | − exit(1) | |
| 226 | − | |
| 227 | − /* Calculate size of each individual ring */ | |
| 228 | − ring_size = req.nm_block_nr * req.nm_block_size; | |
| 229 | − | |
| 230 | − /* Map RX/TX rings. The TX ring is located after the RX ring */ | |
| 231 | − rx_ring = mmap(NULL, 2 * ring_size, PROT_READ | PROT_WRITE, | |
| 232 | − MAP_SHARED, fd, 0); | |
| 233 | − if ((long)rx_ring == -1L) | |
| 234 | − exit(1); | |
| 235 | − tx_ring = rx_ring + ring_size: | |
| 236 | − | |
| 237 | −Message reception: | |
| 238 | − | |
| 239 | −This example assumes some ring parameters of the ring setup are available. | |
| 240 | − | |
| 241 | − unsigned int frame_offset = 0; | |
| 242 | − struct nl_mmap_hdr *hdr; | |
| 243 | − struct nlmsghdr *nlh; | |
| 244 | − unsigned char buf[16384]; | |
| 245 | − ssize_t len; | |
| 246 | − | |
| 247 | − while (1) { | |
| 248 | − struct pollfd pfds[1]; | |
| 249 | − | |
| 250 | − pfds[0].fd = fd; | |
| 251 | − pfds[0].events = POLLIN | POLLERR; | |
| 252 | − pfds[0].revents = 0; | |
| 253 | − | |
| 254 | − if (poll(pfds, 1, -1) < 0 && errno != -EINTR) | |
| 255 | − exit(1); | |
| 256 | − | |
| 257 | − /* Check for errors. Error handling omitted */ | |
| 258 | − if (pfds[0].revents & POLLERR) | |
| 259 | − <handle error> | |
| 260 | − | |
| 261 | − /* If no new messages, poll again */ | |
| 262 | − if (!(pfds[0].revents & POLLIN)) | |
| 263 | − continue; | |
| 264 | − | |
| 265 | − /* Process all frames */ | |
| 266 | − while (1) { | |
| 267 | − /* Get next frame header */ | |
| 268 | − hdr = rx_ring + frame_offset; | |
| 269 | − | |
| 270 | − if (hdr->nm_status == NL_MMAP_STATUS_VALID) { | |
| 271 | − /* Regular memory mapped frame */ | |
| 272 | − nlh = (void *)hdr + NL_MMAP_HDRLEN; | |
| 273 | − len = hdr->nm_len; | |
| 274 | − | |
| 275 | − /* Release empty message immediately. May happen | |
| 276 | − * on error during message construction. | |
| 277 | − */ | |
| 278 | − if (len == 0) | |
| 279 | − goto release; | |
| 280 | − } else if (hdr->nm_status == NL_MMAP_STATUS_COPY) { | |
| 281 | − /* Frame queued to socket receive queue */ | |
| 282 | − len = recv(fd, buf, sizeof(buf), MSG_DONTWAIT); | |
| 283 | − if (len <= 0) | |
| 284 | − break; | |
| 285 | − nlh = buf; | |
| 286 | − } else | |
| 287 | − /* No more messages to process, continue polling */ | |
| 288 | − break; | |
| 289 | − | |
| 290 | − process_msg(nlh); | |
| 291 | −release: | |
| 292 | − /* Release frame back to the kernel */ | |
| 293 | − hdr->nm_status = NL_MMAP_STATUS_UNUSED; | |
| 294 | − | |
| 295 | − /* Advance frame offset to next frame */ | |
| 296 | − frame_offset = (frame_offset + frame_size) % ring_size; | |
| 297 | − } | |
| 298 | − } | |
| 299 | − | |
| 300 | −Message transmission: | |
| 301 | − | |
| 302 | −This example assumes some ring parameters of the ring setup are available. | |
| 303 | −A single message is constructed and transmitted, to send multiple messages | |
| 304 | −at once they would be constructed in consecutive frames before a final call | |
| 305 | −to sendto(). | |
| 306 | − | |
| 307 | − unsigned int frame_offset = 0; | |
| 308 | − struct nl_mmap_hdr *hdr; | |
| 309 | − struct nlmsghdr *nlh; | |
| 310 | − struct sockaddr_nl addr = { | |
| 311 | − .nl_family = AF_NETLINK, | |
| 312 | − }; | |
| 313 | − | |
| 314 | − hdr = tx_ring + frame_offset; | |
| 315 | − if (hdr->nm_status != NL_MMAP_STATUS_UNUSED) | |
| 316 | − /* No frame available. Use poll() to avoid. */ | |
| 317 | − exit(1); | |
| 318 | − | |
| 319 | − nlh = (void *)hdr + NL_MMAP_HDRLEN; | |
| 320 | − | |
| 321 | − /* Build message */ | |
| 322 | − build_message(nlh); | |
| 323 | − | |
| 324 | − /* Fill frame header: length and status need to be set */ | |
| 325 | − hdr->nm_len = nlh->nlmsg_len; | |
| 326 | − hdr->nm_status = NL_MMAP_STATUS_VALID; | |
| 327 | − | |
| 328 | − if (sendto(fd, NULL, 0, 0, &addr, sizeof(addr)) < 0) | |
| 329 | − exit(1); | |
| 330 | − | |
| 331 | − /* Advance frame offset to next frame */ | |
| 332 | − frame_offset = (frame_offset + frame_size) % ring_size; | |
| @@ -267,13 +267,23 @@ Writing a PHY driver · 266 unmodified lines | ||
| 267 | 267 | config_intr: Enable or disable interrupts |
| 268 | 268 | remove: Does any driver take-down |
| 269 | 269 | ts_info: Queries about the HW timestamping status |
| 270 | + match_phy_device: used for Clause 45 capable PHYs to match devices | |
| 271 | + in package and ensure they are compatible | |
| 270 | 272 | hwtstamp: Set the PHY HW timestamping configuration |
| 271 | 273 | rxtstamp: Requests a receive timestamp at the PHY level for a 'skb' |
| 272 | 274 | txtsamp: Requests a transmit timestamp at the PHY level for a 'skb' |
| 273 | 275 | set_wol: Enable Wake-on-LAN at the PHY level |
| 274 | 276 | get_wol: Get the Wake-on-LAN status at the PHY level |
| 277 | + link_change_notify: called to inform the core is about to change the | |
| 278 | + link state, can be used to work around bogus PHY between state changes | |
| 275 | 279 | read_mmd_indirect: Read PHY MMD indirect register |
| 276 | 280 | write_mmd_indirect: Write PHY MMD indirect register |
| 281 | + module_info: Get the size and type of an EEPROM contained in an plug-in | |
| 282 | + module | |
| 283 | + module_eeprom: Get EEPROM information of a plug-in module | |
| 284 | + get_sset_count: Get number of strings sets that get_strings will count | |
| 285 | + get_strings: Get strings from requested objects (statistics) | |
| 286 | + get_stats: Get the extended statistics from the PHY device | |
| 277 | 287 | |
| 278 | 288 | Of these, only config_aneg and read_status are required to be |
| 279 | 289 | assigned by the driver code. The rest are optional. Also, it is |
| @@ -19,9 +19,7 @@ to N*N if you use a connection-oriented socket transport like TCP. · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | RDS is not Infiniband-specific; it was designed to support different |
| 21 | 21 | transports. The current implementation used to support RDS over TCP as well |
| 22 | −as IB. Work is in progress to support RDS over iWARP, and using DCE to | |
| 23 | −guarantee no dropped packets on Ethernet, it may be possible to use RDS over | |
| 24 | −UDP in the future. | |
| 22 | +as IB. | |
| 25 | 23 | |
| 26 | 24 | The high-level semantics of RDS from the application's point of view are |
| 27 | 25 | |
| @@ -83,6 +83,8 @@ rfkill drivers that control devices that can be hard-blocked unless they also · 82 unmodified lines | ||
| 83 | 83 | assign the poll_hw_block() callback (then the rfkill core will poll the |
| 84 | 84 | device). Don't do this unless you cannot get the event in any other way. |
| 85 | 85 | |
| 86 | +RFKill provides per-switch LED triggers, which can be used to drive LEDs | |
| 87 | +according to the switch state (LED_FULL when blocked, LED_OFF otherwise). | |
| 86 | 88 | |
| 87 | 89 | |
| 88 | 90 | 5. Userspace support |
| @@ -151,7 +151,7 @@ S: Maintained · 150 unmodified lines | ||
| 151 | 151 | F: drivers/scsi/53c700* |
| 152 | 152 | |
| 153 | 153 | 6LOWPAN GENERIC (BTLE/IEEE 802.15.4) |
| 154 | −M: Alexander Aring <alex.aring@gmail.com> | |
| 154 | +M: Alexander Aring <aar@pengutronix.de> | |
| 155 | 155 | M: Jukka Rissanen <jukka.rissanen@linux.intel.com> |
| 156 | 156 | L: linux-bluetooth@vger.kernel.org |
| 157 | 157 | L: linux-wpan@vger.kernel.org |
| @@ -2176,7 +2176,8 @@ M: Marek Lindner <mareklindner@neomailbox.ch> · 2018 unmodified lines | ||
| 2176 | 2176 | M: Simon Wunderlich <sw@simonwunderlich.de> |
| 2177 | 2177 | M: Antonio Quartulli <a@unstable.cc> |
| 2178 | 2178 | L: b.a.t.m.a.n@lists.open-mesh.org |
| 2179 | −W: http://www.open-mesh.org/ | |
| 2179 | +W: https://www.open-mesh.org/ | |
| 2180 | +Q: https://patchwork.open-mesh.org/project/batman/list/ | |
| 2180 | 2181 | S: Maintained |
| 2181 | 2182 | F: net/batman-adv/ |
| 2182 | 2183 | |
| @@ -2447,6 +2448,7 @@ F: include/linux/bcm963xx_nvram.h · 264 unmodified lines | ||
| 2447 | 2448 | F: include/linux/bcm963xx_tag.h |
| 2448 | 2449 | |
| 2449 | 2450 | BROADCOM TG3 GIGABIT ETHERNET DRIVER |
| 2451 | +M: Siva Reddy Kallam <siva.kallam@broadcom.com> | |
| 2450 | 2452 | M: Prashant Sreedharan <prashant@broadcom.com> |
| 2451 | 2453 | M: Michael Chan <mchan@broadcom.com> |
| 2452 | 2454 | L: netdev@vger.kernel.org |
| @@ -3523,6 +3525,14 @@ F: include/linux/device-mapper.h · 1070 unmodified lines | ||
| 3523 | 3525 | F: include/linux/dm-*.h |
| 3524 | 3526 | F: include/uapi/linux/dm-*.h |
| 3525 | 3527 | |
| 3528 | +DEVLINK | |
| 3529 | +M: Jiri Pirko <jiri@mellanox.com> | |
| 3530 | +L: netdev@vger.kernel.org | |
| 3531 | +S: Supported | |
| 3532 | +F: net/core/devlink.c | |
| 3533 | +F: include/net/devlink.h | |
| 3534 | +F: include/uapi/linux/devlink.h | |
| 3535 | + | |
| 3526 | 3536 | DIALOG SEMICONDUCTOR DRIVERS |
| 3527 | 3537 | M: Support Opensource <support.opensource@diasemi.com> |
| 3528 | 3538 | W: http://www.dialog-semiconductor.com/products |
| @@ -5447,10 +5457,11 @@ S: Supported · 1918 unmodified lines | ||
| 5447 | 5457 | F: drivers/idle/i7300_idle.c |
| 5448 | 5458 | |
| 5449 | 5459 | IEEE 802.15.4 SUBSYSTEM |
| 5450 | −M: Alexander Aring <alex.aring@gmail.com> | |
| 5460 | +M: Alexander Aring <aar@pengutronix.de> | |
| 5451 | 5461 | L: linux-wpan@vger.kernel.org |
| 5452 | −W: https://github.com/linux-wpan | |
| 5453 | −T: git git://github.com/linux-wpan/linux-wpan-next.git | |
| 5462 | +W: http://wpan.cakelab.org/ | |
| 5463 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git | |
| 5464 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git | |
| 5454 | 5465 | S: Maintained |
| 5455 | 5466 | F: net/ieee802154/ |
| 5456 | 5467 | F: net/mac802154/ |
| @@ -7043,6 +7054,13 @@ F: include/uapi/linux/meye.h · 1586 unmodified lines | ||
| 7043 | 7054 | F: include/uapi/linux/ivtv* |
| 7044 | 7055 | F: include/uapi/linux/uvcvideo.h |
| 7045 | 7056 | |
| 7057 | +MEDIATEK ETHERNET DRIVER | |
| 7058 | +M: Felix Fietkau <nbd@openwrt.org> | |
| 7059 | +M: John Crispin <blogic@openwrt.org> | |
| 7060 | +L: netdev@vger.kernel.org | |
| 7061 | +S: Maintained | |
| 7062 | +F: drivers/net/ethernet/mediatek/ | |
| 7063 | + | |
| 7046 | 7064 | MEDIATEK MT7601U WIRELESS LAN DRIVER |
| 7047 | 7065 | M: Jakub Kicinski <kubakici@wp.pl> |
| 7048 | 7066 | L: linux-wireless@vger.kernel.org |
| @@ -7540,7 +7558,6 @@ F: net/netrom/ · 491 unmodified lines | ||
| 7540 | 7558 | |
| 7541 | 7559 | NETRONOME ETHERNET DRIVERS |
| 7542 | 7560 | M: Jakub Kicinski <jakub.kicinski@netronome.com> |
| 7543 | −M: Rolf Neugebauer <rolf.neugebauer@netronome.com> | |
| 7544 | 7561 | L: oss-drivers@netronome.com |
| 7545 | 7562 | S: Maintained |
| 7546 | 7563 | F: drivers/net/ethernet/netronome/ |
| @@ -7677,7 +7694,6 @@ F: net/nfc/ · 130 unmodified lines | ||
| 7677 | 7694 | F: include/net/nfc/ |
| 7678 | 7695 | F: include/uapi/linux/nfc.h |
| 7679 | 7696 | F: drivers/nfc/ |
| 7680 | −F: include/linux/platform_data/microread.h | |
| 7681 | 7697 | F: include/linux/platform_data/nfcmrvl.h |
| 7682 | 7698 | F: include/linux/platform_data/nxp-nci.h |
| 7683 | 7699 | F: include/linux/platform_data/pn544.h |
| @@ -9138,10 +9154,14 @@ S: Maintained · 1454 unmodified lines | ||
| 9138 | 9154 | F: drivers/net/ethernet/rdc/r6040.c |
| 9139 | 9155 | |
| 9140 | 9156 | RDS - RELIABLE DATAGRAM SOCKETS |
| 9141 | −M: Chien Yen <chien.yen@oracle.com> | |
| 9157 | +M: Santosh Shilimkar <santosh.shilimkar@oracle.com> | |
| 9158 | +L: netdev@vger.kernel.org | |
| 9159 | +L: linux-rdma@vger.kernel.org | |
| 9142 | 9160 | L: rds-devel@oss.oracle.com (moderated for non-subscribers) |
| 9161 | +W: https://oss.oracle.com/projects/rds/ | |
| 9143 | 9162 | S: Supported |
| 9144 | 9163 | F: net/rds/ |
| 9164 | +F: Documentation/networking/rds.txt | |
| 9145 | 9165 | |
| 9146 | 9166 | READ-COPY UPDATE (RCU) |
| 9147 | 9167 | M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
| @@ -9542,6 +9562,7 @@ F: drivers/media/i2c/s5k5baf.c · 394 unmodified lines | ||
| 9542 | 9562 | |
| 9543 | 9563 | SAMSUNG S3FWRN5 NFC DRIVER |
| 9544 | 9564 | M: Robert Baldyga <r.baldyga@samsung.com> |
| 9565 | +M: Krzysztof Opasiak <k.opasiak@samsung.com> | |
| 9545 | 9566 | L: linux-nfc@lists.01.org (moderated for non-subscribers) |
| 9546 | 9567 | S: Supported |
| 9547 | 9568 | F: drivers/nfc/s3fwrn5 |
| @@ -11405,6 +11426,13 @@ S: Maintained · 1857 unmodified lines | ||
| 11405 | 11426 | F: drivers/usb/host/isp116x* |
| 11406 | 11427 | F: include/linux/usb/isp116x.h |
| 11407 | 11428 | |
| 11429 | +USB LAN78XX ETHERNET DRIVER | |
| 11430 | +M: Woojung Huh <woojung.huh@microchip.com> | |
| 11431 | +M: Microchip Linux Driver Support <UNGLinuxDriver@microchip.com> | |
| 11432 | +L: netdev@vger.kernel.org | |
| 11433 | +S: Maintained | |
| 11434 | +F: drivers/net/usb/lan78xx.* | |
| 11435 | + | |
| 11408 | 11436 | USB MASS STORAGE DRIVER |
| 11409 | 11437 | M: Matthew Dharm <mdharm-usb@one-eyed-alien.net> |
| 11410 | 11438 | L: linux-usb@vger.kernel.org |
| @@ -13,14 +13,11 @@ extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); · 12 unmodified lines | ||
| 13 | 13 | * computes the checksum of the TCP/UDP pseudo-header |
| 14 | 14 | * returns a 16-bit checksum, already complemented |
| 15 | 15 | */ |
| 16 | −extern __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |
| 17 | − unsigned short len, | |
| 18 | − unsigned short proto, | |
| 19 | − __wsum sum); | |
| 16 | +__sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |
| 17 | + __u32 len, __u8 proto, __wsum sum); | |
| 20 | 18 | |
| 21 | 19 | __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 22 | − unsigned short len, unsigned short proto, | |
| 23 | − __wsum sum); | |
| 20 | + __u32 len, __u8 proto, __wsum sum); | |
| 24 | 21 | |
| 25 | 22 | /* |
| 26 | 23 | * computes the checksum of a memory block at buff, length len, |
| @@ -70,6 +67,5 @@ static inline __sum16 csum_fold(__wsum csum) · 43 unmodified lines | ||
| 70 | 67 | #define _HAVE_ARCH_IPV6_CSUM |
| 71 | 68 | extern __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 72 | 69 | const struct in6_addr *daddr, |
| 73 | − __u32 len, unsigned short proto, | |
| 74 | − __wsum sum); | |
| 70 | + __u32 len, __u8 proto, __wsum sum); | |
| 75 | 71 | #endif |
| @@ -95,4 +95,6 @@ · 94 unmodified lines | ||
| 95 | 95 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 96 | 96 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 97 | 97 | |
| 98 | +#define SO_CNX_ADVICE 53 | |
| 99 | + | |
| 98 | 100 | #endif /* _UAPI_ASM_SOCKET_H */ |
| @@ -42,9 +42,7 @@ static inline unsigned short from64to16(unsigned long x) · 41 unmodified lines | ||
| 42 | 42 | * returns a 16-bit checksum, already complemented. |
| 43 | 43 | */ |
| 44 | 44 | __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 45 | − unsigned short len, | |
| 46 | − unsigned short proto, | |
| 47 | − __wsum sum) | |
| 45 | + __u32 len, __u8 proto, __wsum sum) | |
| 48 | 46 | { |
| 49 | 47 | return (__force __sum16)~from64to16( |
| 50 | 48 | (__force u64)saddr + (__force u64)daddr + |
| @@ -52,9 +50,7 @@ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, · 1 unmodified line | ||
| 52 | 50 | } |
| 53 | 51 | |
| 54 | 52 | __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 55 | − unsigned short len, | |
| 56 | − unsigned short proto, | |
| 57 | − __wsum sum) | |
| 53 | + __u32 len, __u8 proto, __wsum sum) | |
| 58 | 54 | { |
| 59 | 55 | unsigned long result; |
| 60 | 56 | |
| @@ -70,8 +70,8 @@ ip_fast_csum(const void *iph, unsigned int ihl) · 69 unmodified lines | ||
| 70 | 70 | * SA [4], DA [4], zeroes [1], Proto[1], TCP Seg(hdr+data) Len [2] |
| 71 | 71 | */ |
| 72 | 72 | static inline __wsum |
| 73 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 74 | − unsigned short proto, __wsum sum) | |
| 73 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 74 | + __u8 proto, __wsum sum) | |
| 75 | 75 | { |
| 76 | 76 | __asm__ __volatile__( |
| 77 | 77 | " add.f %0, %0, %1 \n" |
| @@ -61,7 +61,8 @@ · 60 unmodified lines | ||
| 61 | 61 | ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 |
| 62 | 62 | MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 |
| 63 | 63 | MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 |
| 64 | − MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | |
| 64 | + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | |
| 65 | + MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | |
| 65 | 66 | |
| 66 | 67 | internal-regs { |
| 67 | 68 | spi1: spi@10680 { |
| @@ -138,12 +139,18 @@ · 70 unmodified lines | ||
| 138 | 139 | status = "okay"; |
| 139 | 140 | phy = <&phy2>; |
| 140 | 141 | phy-mode = "sgmii"; |
| 142 | + buffer-manager = <&bm>; | |
| 143 | + bm,pool-long = <1>; | |
| 144 | + bm,pool-short = <3>; | |
| 141 | 145 | }; |
| 142 | 146 | |
| 143 | 147 | ethernet@34000 { |
| 144 | 148 | status = "okay"; |
| 145 | 149 | phy = <&phy1>; |
| 146 | 150 | phy-mode = "sgmii"; |
| 151 | + buffer-manager = <&bm>; | |
| 152 | + bm,pool-long = <2>; | |
| 153 | + bm,pool-short = <3>; | |
| 147 | 154 | }; |
| 148 | 155 | |
| 149 | 156 | ethernet@70000 { |
| @@ -157,6 +164,13 @@ · 7 unmodified lines | ||
| 157 | 164 | status = "okay"; |
| 158 | 165 | phy = <&phy0>; |
| 159 | 166 | phy-mode = "rgmii-id"; |
| 167 | + buffer-manager = <&bm>; | |
| 168 | + bm,pool-long = <0>; | |
| 169 | + bm,pool-short = <3>; | |
| 170 | + }; | |
| 171 | + | |
| 172 | + bm@c8000 { | |
| 173 | + status = "okay"; | |
| 160 | 174 | }; |
| 161 | 175 | |
| 162 | 176 | nfc: flash@d0000 { |
| @@ -178,6 +192,10 @@ · 15 unmodified lines | ||
| 178 | 192 | }; |
| 179 | 193 | }; |
| 180 | 194 | |
| 195 | + bm-bppi { | |
| 196 | + status = "okay"; | |
| 197 | + }; | |
| 198 | + | |
| 181 | 199 | pcie-controller { |
| 182 | 200 | status = "okay"; |
| 183 | 201 | |
| @@ -78,6 +78,9 @@ · 77 unmodified lines | ||
| 78 | 78 | internal-regs { |
| 79 | 79 | ethernet@30000 { |
| 80 | 80 | phy-mode = "sgmii"; |
| 81 | + buffer-manager = <&bm>; | |
| 82 | + bm,pool-long = <2>; | |
| 83 | + bm,pool-short = <1>; | |
| 81 | 84 | status = "okay"; |
| 82 | 85 | |
| 83 | 86 | fixed-link { |
| @@ -88,6 +91,9 @@ · 4 unmodified lines | ||
| 88 | 91 | |
| 89 | 92 | ethernet@34000 { |
| 90 | 93 | phy-mode = "sgmii"; |
| 94 | + buffer-manager = <&bm>; | |
| 95 | + bm,pool-long = <3>; | |
| 96 | + bm,pool-short = <1>; | |
| 91 | 97 | status = "okay"; |
| 92 | 98 | |
| 93 | 99 | fixed-link { |
| @@ -66,7 +66,8 @@ · 65 unmodified lines | ||
| 66 | 66 | ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 |
| 67 | 67 | MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 |
| 68 | 68 | MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 |
| 69 | − MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | |
| 69 | + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | |
| 70 | + MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | |
| 70 | 71 | |
| 71 | 72 | internal-regs { |
| 72 | 73 | spi@10600 { |
| @@ -99,6 +100,9 @@ · 26 unmodified lines | ||
| 99 | 100 | status = "okay"; |
| 100 | 101 | phy = <&phy1>; |
| 101 | 102 | phy-mode = "rgmii-id"; |
| 103 | + buffer-manager = <&bm>; | |
| 104 | + bm,pool-long = <2>; | |
| 105 | + bm,pool-short = <3>; | |
| 102 | 106 | }; |
| 103 | 107 | |
| 104 | 108 | usb@58000 { |
| @@ -109,6 +113,9 @@ · 4 unmodified lines | ||
| 109 | 113 | status = "okay"; |
| 110 | 114 | phy = <&phy0>; |
| 111 | 115 | phy-mode = "rgmii-id"; |
| 116 | + buffer-manager = <&bm>; | |
| 117 | + bm,pool-long = <0>; | |
| 118 | + bm,pool-short = <1>; | |
| 112 | 119 | }; |
| 113 | 120 | |
| 114 | 121 | mdio@72004 { |
| @@ -129,6 +136,10 @@ · 14 unmodified lines | ||
| 129 | 136 | status = "okay"; |
| 130 | 137 | }; |
| 131 | 138 | |
| 139 | + bm@c8000 { | |
| 140 | + status = "okay"; | |
| 141 | + }; | |
| 142 | + | |
| 132 | 143 | flash@d0000 { |
| 133 | 144 | status = "okay"; |
| 134 | 145 | num-cs = <1>; |
| @@ -169,6 +180,10 @@ · 34 unmodified lines | ||
| 169 | 180 | }; |
| 170 | 181 | }; |
| 171 | 182 | |
| 183 | + bm-bppi { | |
| 184 | + status = "okay"; | |
| 185 | + }; | |
| 186 | + | |
| 172 | 187 | pcie-controller { |
| 173 | 188 | status = "okay"; |
| 174 | 189 | /* |
| @@ -60,7 +60,8 @@ · 59 unmodified lines | ||
| 60 | 60 | ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 |
| 61 | 61 | MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 |
| 62 | 62 | MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 |
| 63 | − MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | |
| 63 | + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | |
| 64 | + MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | |
| 64 | 65 | |
| 65 | 66 | internal-regs { |
| 66 | 67 | spi@10600 { |
| @@ -133,6 +134,9 @@ · 66 unmodified lines | ||
| 133 | 134 | status = "okay"; |
| 134 | 135 | phy = <&phy1>; |
| 135 | 136 | phy-mode = "rgmii-id"; |
| 137 | + buffer-manager = <&bm>; | |
| 138 | + bm,pool-long = <2>; | |
| 139 | + bm,pool-short = <3>; | |
| 136 | 140 | }; |
| 137 | 141 | |
| 138 | 142 | /* CON4 */ |
| @@ -152,6 +156,9 @@ · 13 unmodified lines | ||
| 152 | 156 | status = "okay"; |
| 153 | 157 | phy = <&phy0>; |
| 154 | 158 | phy-mode = "rgmii-id"; |
| 159 | + buffer-manager = <&bm>; | |
| 160 | + bm,pool-long = <0>; | |
| 161 | + bm,pool-short = <1>; | |
| 155 | 162 | }; |
| 156 | 163 | |
| 157 | 164 | |
| @@ -186,6 +193,10 @@ · 28 unmodified lines | ||
| 186 | 193 | }; |
| 187 | 194 | }; |
| 188 | 195 | |
| 196 | + bm@c8000 { | |
| 197 | + status = "okay"; | |
| 198 | + }; | |
| 199 | + | |
| 189 | 200 | sata@e0000 { |
| 190 | 201 | pinctrl-names = "default"; |
| 191 | 202 | pinctrl-0 = <&sata2_pins>, <&sata3_pins>; |
| @@ -240,6 +251,10 @@ · 48 unmodified lines | ||
| 240 | 251 | }; |
| 241 | 252 | }; |
| 242 | 253 | |
| 254 | + bm-bppi { | |
| 255 | + status = "okay"; | |
| 256 | + }; | |
| 257 | + | |
| 243 | 258 | pcie-controller { |
| 244 | 259 | status = "okay"; |
| 245 | 260 | /* |
| @@ -58,7 +58,8 @@ · 57 unmodified lines | ||
| 58 | 58 | ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 |
| 59 | 59 | MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 |
| 60 | 60 | MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 |
| 61 | − MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | |
| 61 | + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | |
| 62 | + MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | |
| 62 | 63 | |
| 63 | 64 | internal-regs { |
| 64 | 65 | ethernet@70000 { |
| @@ -66,6 +67,9 @@ · 1 unmodified line | ||
| 66 | 67 | pinctrl-names = "default"; |
| 67 | 68 | phy = <&phy_dedicated>; |
| 68 | 69 | phy-mode = "rgmii-id"; |
| 70 | + buffer-manager = <&bm>; | |
| 71 | + bm,pool-long = <0>; | |
| 72 | + bm,pool-short = <1>; | |
| 69 | 73 | status = "okay"; |
| 70 | 74 | }; |
| 71 | 75 | |
| @@ -110,6 +114,15 @@ · 38 unmodified lines | ||
| 110 | 114 | pinctrl-names = "default"; |
| 111 | 115 | status = "okay"; |
| 112 | 116 | }; |
| 117 | + | |
| 118 | + bm@c8000 { | |
| 119 | + status = "okay"; | |
| 120 | + }; | |
| 113 | 121 | }; |
| 122 | + | |
| 123 | + bm-bppi { | |
| 124 | + status = "okay"; | |
| 125 | + }; | |
| 126 | + | |
| 114 | 127 | }; |
| 115 | 128 | }; |
| @@ -540,6 +540,14 @@ · 539 unmodified lines | ||
| 540 | 540 | status = "disabled"; |
| 541 | 541 | }; |
| 542 | 542 | |
| 543 | + bm: bm@c8000 { | |
| 544 | + compatible = "marvell,armada-380-neta-bm"; | |
| 545 | + reg = <0xc8000 0xac>; | |
| 546 | + clocks = <&gateclk 13>; | |
| 547 | + internal-mem = <&bm_bppi>; | |
| 548 | + status = "disabled"; | |
| 549 | + }; | |
| 550 | + | |
| 543 | 551 | sata@e0000 { |
| 544 | 552 | compatible = "marvell,armada-380-ahci"; |
| 545 | 553 | reg = <0xe0000 0x2000>; |
| @@ -618,6 +626,17 @@ · 72 unmodified lines | ||
| 618 | 626 | #size-cells = <1>; |
| 619 | 627 | ranges = <0 MBUS_ID(0x09, 0x15) 0 0x800>; |
| 620 | 628 | }; |
| 629 | + | |
| 630 | + bm_bppi: bm-bppi { | |
| 631 | + compatible = "mmio-sram"; | |
| 632 | + reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>; | |
| 633 | + ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>; | |
| 634 | + #address-cells = <1>; | |
| 635 | + #size-cells = <1>; | |
| 636 | + clocks = <&gateclk 13>; | |
| 637 | + no-memory-wc; | |
| 638 | + status = "disabled"; | |
| 639 | + }; | |
| 621 | 640 | }; |
| 622 | 641 | |
| 623 | 642 | clocks { |
| @@ -77,7 +77,8 @@ · 76 unmodified lines | ||
| 77 | 77 | MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 |
| 78 | 78 | MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000 |
| 79 | 79 | MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000 |
| 80 | − MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>; | |
| 80 | + MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000 | |
| 81 | + MBUS_ID(0x0c, 0x04) 0 0 0xf1200000 0x100000>; | |
| 81 | 82 | |
| 82 | 83 | devbus-bootcs { |
| 83 | 84 | status = "okay"; |
| @@ -181,21 +182,33 @@ · 97 unmodified lines | ||
| 181 | 182 | status = "okay"; |
| 182 | 183 | phy = <&phy0>; |
| 183 | 184 | phy-mode = "rgmii-id"; |
| 185 | + buffer-manager = <&bm>; | |
| 186 | + bm,pool-long = <0>; | |
| 184 | 187 | }; |
| 185 | 188 | ethernet@74000 { |
| 186 | 189 | status = "okay"; |
| 187 | 190 | phy = <&phy1>; |
| 188 | 191 | phy-mode = "rgmii-id"; |
| 192 | + buffer-manager = <&bm>; | |
| 193 | + bm,pool-long = <1>; | |
| 189 | 194 | }; |
| 190 | 195 | ethernet@30000 { |
| 191 | 196 | status = "okay"; |
| 192 | 197 | phy = <&phy2>; |
| 193 | 198 | phy-mode = "sgmii"; |
| 199 | + buffer-manager = <&bm>; | |
| 200 | + bm,pool-long = <2>; | |
| 194 | 201 | }; |
| 195 | 202 | ethernet@34000 { |
| 196 | 203 | status = "okay"; |
| 197 | 204 | phy = <&phy3>; |
| 198 | 205 | phy-mode = "sgmii"; |
| 206 | + buffer-manager = <&bm>; | |
| 207 | + bm,pool-long = <3>; | |
| 208 | + }; | |
| 209 | + | |
| 210 | + bm@c0000 { | |
| 211 | + status = "okay"; | |
| 199 | 212 | }; |
| 200 | 213 | |
| 201 | 214 | mvsdio@d4000 { |
| @@ -230,5 +243,9 @@ · 28 unmodified lines | ||
| 230 | 243 | }; |
| 231 | 244 | }; |
| 232 | 245 | }; |
| 246 | + | |
| 247 | + bm-bppi { | |
| 248 | + status = "okay"; | |
| 249 | + }; | |
| 233 | 250 | }; |
| 234 | 251 | }; |
| @@ -96,7 +96,8 @@ · 95 unmodified lines | ||
| 96 | 96 | MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 |
| 97 | 97 | MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000 |
| 98 | 98 | MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000 |
| 99 | − MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>; | |
| 99 | + MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000 | |
| 100 | + MBUS_ID(0x0c, 0x04) 0 0 0xf1200000 0x100000>; | |
| 100 | 101 | |
| 101 | 102 | devbus-bootcs { |
| 102 | 103 | status = "okay"; |
| @@ -196,21 +197,29 @@ · 93 unmodified lines | ||
| 196 | 197 | status = "okay"; |
| 197 | 198 | phy = <&phy0>; |
| 198 | 199 | phy-mode = "qsgmii"; |
| 200 | + buffer-manager = <&bm>; | |
| 201 | + bm,pool-long = <0>; | |
| 199 | 202 | }; |
| 200 | 203 | ethernet@74000 { |
| 201 | 204 | status = "okay"; |
| 202 | 205 | phy = <&phy1>; |
| 203 | 206 | phy-mode = "qsgmii"; |
| 207 | + buffer-manager = <&bm>; | |
| 208 | + bm,pool-long = <1>; | |
| 204 | 209 | }; |
| 205 | 210 | ethernet@30000 { |
| 206 | 211 | status = "okay"; |
| 207 | 212 | phy = <&phy2>; |
| 208 | 213 | phy-mode = "qsgmii"; |
| 214 | + buffer-manager = <&bm>; | |
| 215 | + bm,pool-long = <2>; | |
| 209 | 216 | }; |
| 210 | 217 | ethernet@34000 { |
| 211 | 218 | status = "okay"; |
| 212 | 219 | phy = <&phy3>; |
| 213 | 220 | phy-mode = "qsgmii"; |
| 221 | + buffer-manager = <&bm>; | |
| 222 | + bm,pool-long = <3>; | |
| 214 | 223 | }; |
| 215 | 224 | |
| 216 | 225 | /* Front-side USB slot */ |
| @@ -235,6 +244,10 @@ · 18 unmodified lines | ||
| 235 | 244 | }; |
| 236 | 245 | }; |
| 237 | 246 | |
| 247 | + bm@c0000 { | |
| 248 | + status = "okay"; | |
| 249 | + }; | |
| 250 | + | |
| 238 | 251 | nand@d0000 { |
| 239 | 252 | status = "okay"; |
| 240 | 253 | num-cs = <1>; |
| @@ -243,5 +256,9 @@ · 2 unmodified lines | ||
| 243 | 256 | nand-on-flash-bbt; |
| 244 | 257 | }; |
| 245 | 258 | }; |
| 259 | + | |
| 260 | + bm-bppi { | |
| 261 | + status = "okay"; | |
| 262 | + }; | |
| 246 | 263 | }; |
| 247 | 264 | }; |
| @@ -67,7 +67,8 @@ · 66 unmodified lines | ||
| 67 | 67 | MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 |
| 68 | 68 | MBUS_ID(0x01, 0x2f) 0 0 0xe8000000 0x8000000 |
| 69 | 69 | MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000 |
| 70 | − MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>; | |
| 70 | + MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000 | |
| 71 | + MBUS_ID(0x0c, 0x04) 0 0 0xd1200000 0x100000>; | |
| 71 | 72 | |
| 72 | 73 | devbus-bootcs { |
| 73 | 74 | status = "okay"; |
| @@ -176,21 +177,29 @@ · 102 unmodified lines | ||
| 176 | 177 | status = "okay"; |
| 177 | 178 | phy = <&phy0>; |
| 178 | 179 | phy-mode = "sgmii"; |
| 180 | + buffer-manager = <&bm>; | |
| 181 | + bm,pool-long = <0>; | |
| 179 | 182 | }; |
| 180 | 183 | ethernet@74000 { |
| 181 | 184 | status = "okay"; |
| 182 | 185 | phy = <&phy1>; |
| 183 | 186 | phy-mode = "sgmii"; |
| 187 | + buffer-manager = <&bm>; | |
| 188 | + bm,pool-long = <1>; | |
| 184 | 189 | }; |
| 185 | 190 | ethernet@30000 { |
| 186 | 191 | status = "okay"; |
| 187 | 192 | phy = <&phy2>; |
| 188 | 193 | phy-mode = "sgmii"; |
| 194 | + buffer-manager = <&bm>; | |
| 195 | + bm,pool-long = <2>; | |
| 189 | 196 | }; |
| 190 | 197 | ethernet@34000 { |
| 191 | 198 | status = "okay"; |
| 192 | 199 | phy = <&phy3>; |
| 193 | 200 | phy-mode = "sgmii"; |
| 201 | + buffer-manager = <&bm>; | |
| 202 | + bm,pool-long = <3>; | |
| 194 | 203 | }; |
| 195 | 204 | i2c@11000 { |
| 196 | 205 | status = "okay"; |
| @@ -219,6 +228,14 @@ · 22 unmodified lines | ||
| 219 | 228 | usb@51000 { |
| 220 | 229 | status = "okay"; |
| 221 | 230 | }; |
| 231 | + | |
| 232 | + bm@c0000 { | |
| 233 | + status = "okay"; | |
| 234 | + }; | |
| 235 | + }; | |
| 236 | + | |
| 237 | + bm-bppi { | |
| 238 | + status = "okay"; | |
| 222 | 239 | }; |
| 223 | 240 | }; |
| 224 | 241 | }; |
| @@ -253,6 +253,14 @@ · 252 unmodified lines | ||
| 253 | 253 | marvell,crypto-sram-size = <0x800>; |
| 254 | 254 | }; |
| 255 | 255 | |
| 256 | + bm: bm@c0000 { | |
| 257 | + compatible = "marvell,armada-380-neta-bm"; | |
| 258 | + reg = <0xc0000 0xac>; | |
| 259 | + clocks = <&gateclk 13>; | |
| 260 | + internal-mem = <&bm_bppi>; | |
| 261 | + status = "disabled"; | |
| 262 | + }; | |
| 263 | + | |
| 256 | 264 | xor@f0900 { |
| 257 | 265 | compatible = "marvell,orion-xor"; |
| 258 | 266 | reg = <0xF0900 0x100 |
| @@ -291,6 +299,17 @@ · 32 unmodified lines | ||
| 291 | 299 | #size-cells = <1>; |
| 292 | 300 | ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>; |
| 293 | 301 | }; |
| 302 | + | |
| 303 | + bm_bppi: bm-bppi { | |
| 304 | + compatible = "mmio-sram"; | |
| 305 | + reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>; | |
| 306 | + ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>; | |
| 307 | + #address-cells = <1>; | |
| 308 | + #size-cells = <1>; | |
| 309 | + clocks = <&gateclk 13>; | |
| 310 | + no-memory-wc; | |
| 311 | + status = "disabled"; | |
| 312 | + }; | |
| 294 | 313 | }; |
| 295 | 314 | |
| 296 | 315 | clocks { |
| @@ -457,6 +457,18 @@ · 456 unmodified lines | ||
| 457 | 457 | reg = <0x0 0x2d24000 0x0 0x4000>; |
| 458 | 458 | }; |
| 459 | 459 | |
| 460 | + ptp_clock@2d10e00 { | |
| 461 | + compatible = "fsl,etsec-ptp"; | |
| 462 | + reg = <0x0 0x2d10e00 0x0 0xb0>; | |
| 463 | + interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>; | |
| 464 | + fsl,tclk-period = <5>; | |
| 465 | + fsl,tmr-prsc = <2>; | |
| 466 | + fsl,tmr-add = <0xaaaaaaab>; | |
| 467 | + fsl,tmr-fiper1 = <999999990>; | |
| 468 | + fsl,tmr-fiper2 = <99990>; | |
| 469 | + fsl,max-adj = <499999999>; | |
| 470 | + }; | |
| 471 | + | |
| 460 | 472 | enet0: ethernet@2d10000 { |
| 461 | 473 | compatible = "fsl,etsec2"; |
| 462 | 474 | device_type = "network"; |
| @@ -47,6 +47,20 @@ · 46 unmodified lines | ||
| 47 | 47 | compatible = "rockchip,rk3036-evb", "rockchip,rk3036"; |
| 48 | 48 | }; |
| 49 | 49 | |
| 50 | +&emac { | |
| 51 | + pinctrl-names = "default"; | |
| 52 | + pinctrl-0 = <&emac_xfer>, <&emac_mdio>; | |
| 53 | + phy = <&phy0>; | |
| 54 | + phy-reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>; /* PHY_RST */ | |
| 55 | + phy-reset-duration = <10>; /* millisecond */ | |
| 56 | + | |
| 57 | + status = "okay"; | |
| 58 | + | |
| 59 | + phy0: ethernet-phy@0 { | |
| 60 | + reg = <0>; | |
| 61 | + }; | |
| 62 | +}; | |
| 63 | + | |
| 50 | 64 | &i2c1 { |
| 51 | 65 | status = "okay"; |
| 52 | 66 | |
| @@ -60,6 +60,20 @@ · 59 unmodified lines | ||
| 60 | 60 | status = "okay"; |
| 61 | 61 | }; |
| 62 | 62 | |
| 63 | +&emac { | |
| 64 | + pinctrl-names = "default"; | |
| 65 | + pinctrl-0 = <&emac_xfer>, <&emac_mdio>; | |
| 66 | + phy = <&phy0>; | |
| 67 | + phy-reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>; /* PHY_RST */ | |
| 68 | + phy-reset-duration = <10>; /* millisecond */ | |
| 69 | + | |
| 70 | + status = "okay"; | |
| 71 | + | |
| 72 | + phy0: ethernet-phy@0 { | |
| 73 | + reg = <0>; | |
| 74 | + }; | |
| 75 | +}; | |
| 76 | + | |
| 63 | 77 | &emmc { |
| 64 | 78 | status = "okay"; |
| 65 | 79 | }; |
| @@ -186,6 +186,27 @@ · 185 unmodified lines | ||
| 186 | 186 | status = "disabled"; |
| 187 | 187 | }; |
| 188 | 188 | |
| 189 | + emac: ethernet@10200000 { | |
| 190 | + compatible = "rockchip,rk3036-emac", "snps,arc-emac"; | |
| 191 | + reg = <0x10200000 0x4000>; | |
| 192 | + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; | |
| 193 | + #address-cells = <1>; | |
| 194 | + #size-cells = <0>; | |
| 195 | + rockchip,grf = <&grf>; | |
| 196 | + clocks = <&cru HCLK_MAC>, <&cru SCLK_MACREF>, <&cru SCLK_MAC>; | |
| 197 | + clock-names = "hclk", "macref", "macclk"; | |
| 198 | + /* | |
| 199 | + * Fix the emac parent clock is DPLL instead of APLL. | |
| 200 | + * since that will cause some unstable things if the cpufreq | |
| 201 | + * is working. (e.g: the accurate 50MHz what mac_ref need) | |
| 202 | + */ | |
| 203 | + assigned-clocks = <&cru SCLK_MACPLL>; | |
| 204 | + assigned-clock-parents = <&cru PLL_DPLL>; | |
| 205 | + max-speed = <100>; | |
| 206 | + phy-mode = "rmii"; | |
| 207 | + status = "disabled"; | |
| 208 | + }; | |
| 209 | + | |
| 189 | 210 | sdmmc: dwmmc@10214000 { |
| 190 | 211 | compatible = "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc"; |
| 191 | 212 | reg = <0x10214000 0x4000>; |
| @@ -556,6 +577,24 @@ · 364 unmodified lines | ||
| 556 | 577 | }; |
| 557 | 578 | }; |
| 558 | 579 | |
| 580 | + emac { | |
| 581 | + emac_xfer: emac-xfer { | |
| 582 | + rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_default>, /* crs_dvalid */ | |
| 583 | + <2 13 RK_FUNC_1 &pcfg_pull_default>, /* tx_en */ | |
| 584 | + <2 14 RK_FUNC_1 &pcfg_pull_default>, /* mac_clk */ | |
| 585 | + <2 15 RK_FUNC_1 &pcfg_pull_default>, /* rx_err */ | |
| 586 | + <2 16 RK_FUNC_1 &pcfg_pull_default>, /* rxd1 */ | |
| 587 | + <2 17 RK_FUNC_1 &pcfg_pull_default>, /* rxd0 */ | |
| 588 | + <2 18 RK_FUNC_1 &pcfg_pull_default>, /* txd1 */ | |
| 589 | + <2 19 RK_FUNC_1 &pcfg_pull_default>; /* txd0 */ | |
| 590 | + }; | |
| 591 | + | |
| 592 | + emac_mdio: emac-mdio { | |
| 593 | + rockchip,pins = <2 12 RK_FUNC_1 &pcfg_pull_default>, /* mac_md */ | |
| 594 | + <2 25 RK_FUNC_1 &pcfg_pull_default>; /* mac_mdclk */ | |
| 595 | + }; | |
| 596 | + }; | |
| 597 | + | |
| 559 | 598 | i2c0 { |
| 560 | 599 | i2c0_xfer: i2c0-xfer { |
| 561 | 600 | rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>, |
| @@ -91,7 +91,7 @@ CONFIG_SATA_MV=y · 90 unmodified lines | ||
| 91 | 91 | CONFIG_NETDEVICES=y |
| 92 | 92 | CONFIG_NET_DSA_MV88E6060=y |
| 93 | 93 | CONFIG_NET_DSA_MV88E6131=y |
| 94 | −CONFIG_NET_DSA_MV88E6123_61_65=y | |
| 94 | +CONFIG_NET_DSA_MV88E6123=y | |
| 95 | 95 | CONFIG_NET_DSA_MV88E6171=y |
| 96 | 96 | CONFIG_NET_DSA_MV88E6352=y |
| 97 | 97 | CONFIG_MV643XX_ETH=y |
| @@ -92,7 +92,7 @@ CONFIG_SATA_MV=y · 91 unmodified lines | ||
| 92 | 92 | CONFIG_NETDEVICES=y |
| 93 | 93 | CONFIG_NET_DSA_MV88E6060=y |
| 94 | 94 | CONFIG_NET_DSA_MV88E6131=y |
| 95 | −CONFIG_NET_DSA_MV88E6123_61_65=y | |
| 95 | +CONFIG_NET_DSA_MV88E6123=y | |
| 96 | 96 | CONFIG_NET_DSA_MV88E6171=y |
| 97 | 97 | CONFIG_NET_DSA_MV88E6352=y |
| 98 | 98 | CONFIG_MV643XX_ETH=y |
| @@ -86,7 +86,7 @@ CONFIG_SATA_MV=y · 85 unmodified lines | ||
| 86 | 86 | CONFIG_NETDEVICES=y |
| 87 | 87 | CONFIG_MII=y |
| 88 | 88 | CONFIG_NET_DSA_MV88E6131=y |
| 89 | −CONFIG_NET_DSA_MV88E6123_61_65=y | |
| 89 | +CONFIG_NET_DSA_MV88E6123=y | |
| 90 | 90 | CONFIG_MV643XX_ETH=y |
| 91 | 91 | CONFIG_MARVELL_PHY=y |
| 92 | 92 | # CONFIG_INPUT_MOUSEDEV is not set |
| @@ -84,10 +84,10 @@ ip_fast_csum(const void *iph, unsigned int ihl) · 83 unmodified lines | ||
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | static inline __wsum |
| 87 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 88 | − unsigned short proto, __wsum sum) | |
| 87 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 88 | + __u8 proto, __wsum sum) | |
| 89 | 89 | { |
| 90 | − u32 lenprot = len | proto << 16; | |
| 90 | + u32 lenprot = len + proto; | |
| 91 | 91 | if (__builtin_constant_p(sum) && sum == 0) { |
| 92 | 92 | __asm__( |
| 93 | 93 | "adds %0, %1, %2 @ csum_tcpudp_nofold0 \n\t" |
| @@ -121,8 +121,8 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, · 27 unmodified lines | ||
| 121 | 121 | * returns a 16-bit checksum, already complemented |
| 122 | 122 | */ |
| 123 | 123 | static inline __sum16 |
| 124 | −csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, | |
| 125 | − unsigned short proto, __wsum sum) | |
| 124 | +csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, | |
| 125 | + __u8 proto, __wsum sum) | |
| 126 | 126 | { |
| 127 | 127 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| 128 | 128 | } |
| @@ -144,8 +144,8 @@ __csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __ · 15 unmodified lines | ||
| 144 | 144 | __be32 proto, __wsum sum); |
| 145 | 145 | |
| 146 | 146 | static inline __sum16 |
| 147 | −csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, | |
| 148 | − unsigned short proto, __wsum sum) | |
| 147 | +csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, | |
| 148 | + __u32 len, __u8 proto, __wsum sum) | |
| 149 | 149 | { |
| 150 | 150 | return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl(len), |
| 151 | 151 | htonl(proto), sum)); |
| @@ -17,23 +17,25 @@ · 16 unmodified lines | ||
| 17 | 17 | * |
| 18 | 18 | */ |
| 19 | 19 | |
| 20 | +#include <linux/property.h> | |
| 20 | 21 | #include <linux/gpio/machine.h> |
| 21 | 22 | #include <linux/platform_device.h> |
| 22 | −#include <linux/rfkill-gpio.h> | |
| 23 | 23 | |
| 24 | 24 | #include "board.h" |
| 25 | 25 | |
| 26 | −static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = { | |
| 27 | − .name = "wifi_rfkill", | |
| 28 | − .type = RFKILL_TYPE_WLAN, | |
| 26 | +static struct property_entry __initdata wifi_rfkill_prop[] = { | |
| 27 | + PROPERTY_ENTRY_STRING("name", "wifi_rfkill"), | |
| 28 | + PROPERTY_ENTRY_STRING("type", "wlan"), | |
| 29 | + { }, | |
| 30 | +}; | |
| 31 | + | |
| 32 | +static struct property_set __initdata wifi_rfkill_pset = { | |
| 33 | + .properties = wifi_rfkill_prop, | |
| 29 | 34 | }; |
| 30 | 35 | |
| 31 | 36 | static struct platform_device wifi_rfkill_device = { |
| 32 | 37 | .name = "rfkill_gpio", |
| 33 | 38 | .id = -1, |
| 34 | − .dev = { | |
| 35 | − .platform_data = &wifi_rfkill_platform_data, | |
| 36 | − }, | |
| 37 | 39 | }; |
| 38 | 40 | |
| 39 | 41 | static struct gpiod_lookup_table wifi_gpio_lookup = { |
| @@ -47,6 +49,7 @@ static struct gpiod_lookup_table wifi_gpio_lookup = { · 7 unmodified lines | ||
| 47 | 49 | |
| 48 | 50 | void __init tegra_paz00_wifikill_init(void) |
| 49 | 51 | { |
| 52 | + platform_device_add_properties(&wifi_rfkill_device, &wifi_rfkill_pset); | |
| 50 | 53 | gpiod_add_lookup_table(&wifi_gpio_lookup); |
| 51 | 54 | platform_device_register(&wifi_rfkill_device); |
| 52 | 55 | } |
| @@ -621,7 +621,13 @@ · 620 unmodified lines | ||
| 621 | 621 | <0x0 0x1f600000 0x0 0Xd100>, |
| 622 | 622 | <0x0 0x20000000 0x0 0X220000>; |
| 623 | 623 | interrupts = <0 108 4>, |
| 624 | − <0 109 4>; | |
| 624 | + <0 109 4>, | |
| 625 | + <0 110 4>, | |
| 626 | + <0 111 4>, | |
| 627 | + <0 112 4>, | |
| 628 | + <0 113 4>, | |
| 629 | + <0 114 4>, | |
| 630 | + <0 115 4>; | |
| 625 | 631 | port-id = <1>; |
| 626 | 632 | dma-coherent; |
| 627 | 633 | clocks = <&xge1clk 0>; |
| @@ -964,7 +964,13 @@ · 963 unmodified lines | ||
| 964 | 964 | <0x0 0x18000000 0x0 0X200>; |
| 965 | 965 | reg-names = "enet_csr", "ring_csr", "ring_cmd"; |
| 966 | 966 | interrupts = <0x0 0x60 0x4>, |
| 967 | − <0x0 0x61 0x4>; | |
| 967 | + <0x0 0x61 0x4>, | |
| 968 | + <0x0 0x62 0x4>, | |
| 969 | + <0x0 0x63 0x4>, | |
| 970 | + <0x0 0x64 0x4>, | |
| 971 | + <0x0 0x65 0x4>, | |
| 972 | + <0x0 0x66 0x4>, | |
| 973 | + <0x0 0x67 0x4>; | |
| 968 | 974 | dma-coherent; |
| 969 | 975 | clocks = <&xge0clk 0>; |
| 970 | 976 | /* mac address will be overwritten by the bootloader */ |
| @@ -111,9 +111,8 @@ static inline __sum16 csum_fold(__wsum sum) · 110 unmodified lines | ||
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 114 | − unsigned short len, | |
| 115 | − unsigned short proto, | |
| 116 | − __wsum sum) | |
| 114 | + __u32 len, __u8 proto, | |
| 115 | + __wsum sum) | |
| 117 | 116 | { |
| 118 | 117 | asm(" add %0, %1\n" |
| 119 | 118 | " adc %0, %0, %2\n" |
| @@ -132,9 +131,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 12 unmodified lines | ||
| 132 | 131 | * returns a 16-bit checksum, already complemented |
| 133 | 132 | */ |
| 134 | 133 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 135 | − unsigned short len, | |
| 136 | − unsigned short proto, | |
| 137 | − __wsum sum) | |
| 134 | + __u32 len, __u8 proto, | |
| 135 | + __wsum sum) | |
| 138 | 136 | { |
| 139 | 137 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 140 | 138 | } |
| @@ -88,4 +88,6 @@ · 87 unmodified lines | ||
| 88 | 88 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 89 | 89 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 90 | 90 | |
| 91 | +#define SO_CNX_ADVICE 53 | |
| 92 | + | |
| 91 | 93 | #endif /* _UAPI__ASM_AVR32_SOCKET_H */ |
| @@ -14,8 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | */ |
| 15 | 15 | |
| 16 | 16 | static inline __wsum |
| 17 | −__csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 18 | − unsigned short proto, __wsum sum) | |
| 17 | +__csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 18 | + __u8 proto, __wsum sum) | |
| 19 | 19 | { |
| 20 | 20 | unsigned int carry; |
| 21 | 21 | |
| @@ -10,8 +10,8 @@ · 9 unmodified lines | ||
| 10 | 10 | #define _ASM_C6X_CHECKSUM_H |
| 11 | 11 | |
| 12 | 12 | static inline __wsum |
| 13 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 14 | − unsigned short proto, __wsum sum) | |
| 13 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 14 | + __u8 proto, __wsum sum) | |
| 15 | 15 | { |
| 16 | 16 | unsigned long long tmp; |
| 17 | 17 | |
| @@ -9,8 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | 11 | static inline __wsum |
| 12 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 13 | − unsigned short proto, __wsum sum) | |
| 12 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 13 | + __u8 proto, __wsum sum) | |
| 14 | 14 | { |
| 15 | 15 | __wsum res; |
| 16 | 16 | __asm__ ("add.d %2, %0\n\t" |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | */ |
| 12 | 12 | static inline __wsum |
| 13 | 13 | csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 14 | − unsigned short len, unsigned short proto, __wsum sum) | |
| 14 | + __u32 len, __u8 proto, __wsum sum) | |
| 15 | 15 | { |
| 16 | 16 | __wsum res; |
| 17 | 17 | |
| @@ -63,9 +63,8 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 62 unmodified lines | ||
| 63 | 63 | */ |
| 64 | 64 | |
| 65 | 65 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 66 | − unsigned short len, | |
| 67 | − unsigned short proto, | |
| 68 | − __wsum sum) | |
| 66 | + __u32 len, __u8 proto, | |
| 67 | + __wsum sum) | |
| 69 | 68 | { |
| 70 | 69 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 71 | 70 | } |
| @@ -105,8 +105,8 @@ static inline __sum16 csum_fold(__wsum sum) · 104 unmodified lines | ||
| 105 | 105 | * returns a 16-bit checksum, already complemented |
| 106 | 106 | */ |
| 107 | 107 | static inline __wsum |
| 108 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 109 | − unsigned short proto, __wsum sum) | |
| 108 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 109 | + __u8 proto, __wsum sum) | |
| 110 | 110 | { |
| 111 | 111 | asm(" addcc %1,%0,%0,icc0 \n" |
| 112 | 112 | " addxcc %2,%0,%0,icc0 \n" |
| @@ -120,8 +120,8 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, · 7 unmodified lines | ||
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | static inline __sum16 |
| 123 | −csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, | |
| 124 | − unsigned short proto, __wsum sum) | |
| 123 | +csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, | |
| 124 | + __u8 proto, __wsum sum) | |
| 125 | 125 | { |
| 126 | 126 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 127 | 127 | } |
| @@ -135,7 +135,7 @@ extern __sum16 ip_compute_csum(const void *buff, int len); · 7 unmodified lines | ||
| 135 | 135 | #define _HAVE_ARCH_IPV6_CSUM |
| 136 | 136 | static inline __sum16 |
| 137 | 137 | csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, |
| 138 | − __u32 len, unsigned short proto, __wsum sum) | |
| 138 | + __u32 len, __u8 proto, __wsum sum) | |
| 139 | 139 | { |
| 140 | 140 | unsigned long tmp, tmp2; |
| 141 | 141 | |
| @@ -88,5 +88,7 @@ · 87 unmodified lines | ||
| 88 | 88 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 89 | 89 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 90 | 90 | |
| 91 | +#define SO_CNX_ADVICE 53 | |
| 92 | + | |
| 91 | 93 | #endif /* _ASM_SOCKET_H */ |
| 92 | 94 | |
| @@ -38,12 +38,12 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, · 37 unmodified lines | ||
| 38 | 38 | * returns a 16-bit checksum, already complemented |
| 39 | 39 | */ |
| 40 | 40 | #define csum_tcpudp_nofold csum_tcpudp_nofold |
| 41 | −__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, | |
| 42 | − unsigned short len, unsigned short proto, __wsum sum); | |
| 41 | +__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |
| 42 | + __u32 len, __u8 proto, __wsum sum); | |
| 43 | 43 | |
| 44 | 44 | #define csum_tcpudp_magic csum_tcpudp_magic |
| 45 | −__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, | |
| 46 | − unsigned short len, unsigned short proto, __wsum sum); | |
| 45 | +__sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |
| 46 | + __u32 len, __u8 proto, __wsum sum); | |
| 47 | 47 | |
| 48 | 48 | #include <asm-generic/checksum.h> |
| 49 | 49 | |
| @@ -60,18 +60,16 @@ static inline unsigned short from64to16(u64 x) · 59 unmodified lines | ||
| 60 | 60 | * computes the checksum of the TCP/UDP pseudo-header |
| 61 | 61 | * returns a 16-bit checksum, already complemented. |
| 62 | 62 | */ |
| 63 | −__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, | |
| 64 | − unsigned short len, unsigned short proto, | |
| 65 | − __wsum sum) | |
| 63 | +__sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |
| 64 | + __u32 len, __u8 proto, __wsum sum) | |
| 66 | 65 | { |
| 67 | 66 | return (__force __sum16)~from64to16( |
| 68 | 67 | (__force u64)saddr + (__force u64)daddr + |
| 69 | 68 | (__force u64)sum + ((len + proto) << 8)); |
| 70 | 69 | } |
| 71 | 70 | |
| 72 | −__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, | |
| 73 | − unsigned short len, unsigned short proto, | |
| 74 | − __wsum sum) | |
| 71 | +__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |
| 72 | + __u32 len, __u8 proto, __wsum sum) | |
| 75 | 73 | { |
| 76 | 74 | u64 result; |
| 77 | 75 | |
| @@ -16,15 +16,11 @@ extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); · 15 unmodified lines | ||
| 16 | 16 | * Computes the checksum of the TCP/UDP pseudo-header returns a 16-bit |
| 17 | 17 | * checksum, already complemented |
| 18 | 18 | */ |
| 19 | −extern __sum16 csum_tcpudp_magic (__be32 saddr, __be32 daddr, | |
| 20 | − unsigned short len, | |
| 21 | − unsigned short proto, | |
| 22 | − __wsum sum); | |
| 19 | +extern __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |
| 20 | + __u32 len, __u8 proto, __wsum sum); | |
| 23 | 21 | |
| 24 | −extern __wsum csum_tcpudp_nofold (__be32 saddr, __be32 daddr, | |
| 25 | − unsigned short len, | |
| 26 | − unsigned short proto, | |
| 27 | − __wsum sum); | |
| 22 | +extern __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |
| 23 | + __u32 len, __u8 proto, __wsum sum); | |
| 28 | 24 | |
| 29 | 25 | /* |
| 30 | 26 | * Computes the checksum of a memory block at buff, length len, |
| @@ -73,7 +69,7 @@ static inline __sum16 csum_fold(__wsum csum) · 42 unmodified lines | ||
| 73 | 69 | #define _HAVE_ARCH_IPV6_CSUM 1 |
| 74 | 70 | struct in6_addr; |
| 75 | 71 | extern __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 76 | − const struct in6_addr *daddr, __u32 len, unsigned short proto, | |
| 77 | − __wsum csum); | |
| 72 | + const struct in6_addr *daddr, | |
| 73 | + __u32 len, __u8 proto, __wsum csum); | |
| 78 | 74 | |
| 79 | 75 | #endif /* _ASM_IA64_CHECKSUM_H */ |
| @@ -97,4 +97,6 @@ · 96 unmodified lines | ||
| 97 | 97 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 98 | 98 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 99 | 99 | |
| 100 | +#define SO_CNX_ADVICE 53 | |
| 101 | + | |
| 100 | 102 | #endif /* _ASM_IA64_SOCKET_H */ |
| @@ -34,8 +34,8 @@ from64to16 (unsigned long x) · 33 unmodified lines | ||
| 34 | 34 | * returns a 16-bit checksum, already complemented. |
| 35 | 35 | */ |
| 36 | 36 | __sum16 |
| 37 | −csum_tcpudp_magic (__be32 saddr, __be32 daddr, unsigned short len, | |
| 38 | − unsigned short proto, __wsum sum) | |
| 37 | +csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, | |
| 38 | + __u8 proto, __wsum sum) | |
| 39 | 39 | { |
| 40 | 40 | return (__force __sum16)~from64to16( |
| 41 | 41 | (__force u64)saddr + (__force u64)daddr + |
| @@ -45,8 +45,8 @@ csum_tcpudp_magic (__be32 saddr, __be32 daddr, unsigned short len, · 3 unmodified lines | ||
| 45 | 45 | EXPORT_SYMBOL(csum_tcpudp_magic); |
| 46 | 46 | |
| 47 | 47 | __wsum |
| 48 | −csum_tcpudp_nofold (__be32 saddr, __be32 daddr, unsigned short len, | |
| 49 | − unsigned short proto, __wsum sum) | |
| 48 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 49 | + __u8 proto, __wsum sum) | |
| 50 | 50 | { |
| 51 | 51 | unsigned long result; |
| 52 | 52 | |
| @@ -114,9 +114,8 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 113 unmodified lines | ||
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 116 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 117 | − unsigned short len, | |
| 118 | − unsigned short proto, | |
| 119 | − __wsum sum) | |
| 117 | + __u32 len, __u8 proto, | |
| 118 | + __wsum sum) | |
| 120 | 119 | { |
| 121 | 120 | #if defined(__LITTLE_ENDIAN) |
| 122 | 121 | unsigned long len_proto = (proto + len) << 8; |
| @@ -145,9 +144,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 22 unmodified lines | ||
| 145 | 144 | * returns a 16-bit checksum, already complemented |
| 146 | 145 | */ |
| 147 | 146 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 148 | − unsigned short len, | |
| 149 | − unsigned short proto, | |
| 150 | − __wsum sum) | |
| 147 | + __u32 len, __u8 proto, | |
| 148 | + __wsum sum) | |
| 151 | 149 | { |
| 152 | 150 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 153 | 151 | } |
| @@ -88,4 +88,6 @@ · 87 unmodified lines | ||
| 88 | 88 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 89 | 89 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 90 | 90 | |
| 91 | +#define SO_CNX_ADVICE 53 | |
| 92 | + | |
| 91 | 93 | #endif /* _ASM_M32R_SOCKET_H */ |
| @@ -117,7 +117,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) · 116 unmodified lines | ||
| 117 | 117 | #define _HAVE_ARCH_IPV6_CSUM |
| 118 | 118 | static __inline__ __sum16 |
| 119 | 119 | csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, |
| 120 | − __u32 len, unsigned short proto, __wsum sum) | |
| 120 | + __u32 len, __u8 proto, __wsum sum) | |
| 121 | 121 | { |
| 122 | 122 | register unsigned long tmp; |
| 123 | 123 | __asm__("addl %2@,%0\n\t" |
| @@ -59,8 +59,7 @@ extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); · 58 unmodified lines | ||
| 59 | 59 | * returns a 16-bit checksum, already complemented |
| 60 | 60 | */ |
| 61 | 61 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 62 | − unsigned short len, | |
| 63 | − unsigned short proto, | |
| 62 | + __u32 len, __u8 proto, | |
| 64 | 63 | __wsum sum) |
| 65 | 64 | { |
| 66 | 65 | unsigned long len_proto = (proto + len) << 8; |
| @@ -78,8 +77,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 11 unmodified lines | ||
| 78 | 77 | } |
| 79 | 78 | |
| 80 | 79 | static inline __sum16 |
| 81 | −csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, | |
| 82 | − unsigned short proto, __wsum sum) | |
| 80 | +csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, | |
| 81 | + __u8 proto, __wsum sum) | |
| 83 | 82 | { |
| 84 | 83 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| 85 | 84 | } |
| @@ -16,8 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | */ |
| 17 | 17 | #define csum_tcpudp_nofold csum_tcpudp_nofold |
| 18 | 18 | static inline __wsum |
| 19 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 20 | − unsigned short proto, __wsum sum) | |
| 19 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 20 | + __u8 proto, __wsum sum) | |
| 21 | 21 | { |
| 22 | 22 | __asm__("add %0, %0, %1\n\t" |
| 23 | 23 | "addc %0, %0, %2\n\t" |
| @@ -160,9 +160,9 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 159 unmodified lines | ||
| 160 | 160 | } |
| 161 | 161 | #define ip_fast_csum ip_fast_csum |
| 162 | 162 | |
| 163 | −static inline __wsum csum_tcpudp_nofold(__be32 saddr, | |
| 164 | − __be32 daddr, unsigned short len, unsigned short proto, | |
| 165 | − __wsum sum) | |
| 163 | +static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |
| 164 | + __u32 len, __u8 proto, | |
| 165 | + __wsum sum) | |
| 166 | 166 | { |
| 167 | 167 | __asm__( |
| 168 | 168 | " .set push # csum_tcpudp_nofold\n" |
| @@ -215,7 +215,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) · 46 unmodified lines | ||
| 215 | 215 | #define _HAVE_ARCH_IPV6_CSUM |
| 216 | 216 | static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 217 | 217 | const struct in6_addr *daddr, |
| 218 | − __u32 len, unsigned short proto, | |
| 218 | + __u32 len, __u8 proto, | |
| 219 | 219 | __wsum sum) |
| 220 | 220 | { |
| 221 | 221 | __wsum tmp; |
| @@ -106,4 +106,6 @@ · 105 unmodified lines | ||
| 106 | 106 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 107 | 107 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 108 | 108 | |
| 109 | +#define SO_CNX_ADVICE 53 | |
| 110 | + | |
| 109 | 111 | #endif /* _UAPI_ASM_SOCKET_H */ |
| @@ -320,11 +320,12 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) · 319 unmodified lines | ||
| 320 | 320 | #if IS_ENABLED(CONFIG_TC35815) |
| 321 | 321 | static u32 tx4939_get_eth_speed(struct net_device *dev) |
| 322 | 322 | { |
| 323 | − struct ethtool_cmd cmd; | |
| 324 | − if (__ethtool_get_settings(dev, &cmd)) | |
| 323 | + struct ethtool_link_ksettings cmd; | |
| 324 | + | |
| 325 | + if (__ethtool_get_link_ksettings(dev, &cmd)) | |
| 325 | 326 | return 100; /* default 100Mbps */ |
| 326 | 327 | |
| 327 | − return ethtool_cmd_speed(&cmd); | |
| 328 | + return cmd.base.speed; | |
| 328 | 329 | } |
| 329 | 330 | |
| 330 | 331 | static int tx4939_netdev_event(struct notifier_block *this, |
| @@ -37,16 +37,11 @@ static inline __sum16 csum_fold(__wsum sum) · 36 unmodified lines | ||
| 37 | 37 | return (~sum) >> 16; |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | −static inline __wsum csum_tcpudp_nofold(unsigned long saddr, | |
| 41 | − unsigned long daddr, | |
| 42 | − unsigned short len, | |
| 43 | − unsigned short proto, | |
| 40 | +static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |
| 41 | + __u32 len, __u8 proto, | |
| 44 | 42 | __wsum sum) |
| 45 | 43 | { |
| 46 | − __wsum tmp; | |
| 47 | − | |
| 48 | − tmp = (__wsum) ntohs(len) << 16; | |
| 49 | − tmp += (__wsum) proto << 8; | |
| 44 | + __wsum tmp = (__wsum)((len + proto) << 8); | |
| 50 | 45 | |
| 51 | 46 | asm( |
| 52 | 47 | " add %1,%0 \n" |
| @@ -64,10 +59,8 @@ static inline __wsum csum_tcpudp_nofold(unsigned long saddr, · 11 unmodified lines | ||
| 64 | 59 | * computes the checksum of the TCP/UDP pseudo-header |
| 65 | 60 | * returns a 16-bit checksum, already complemented |
| 66 | 61 | */ |
| 67 | −static inline __sum16 csum_tcpudp_magic(unsigned long saddr, | |
| 68 | − unsigned long daddr, | |
| 69 | − unsigned short len, | |
| 70 | − unsigned short proto, | |
| 62 | +static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |
| 63 | + __u32 len, __u8 proto, | |
| 71 | 64 | __wsum sum) |
| 72 | 65 | { |
| 73 | 66 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| @@ -88,4 +88,6 @@ · 87 unmodified lines | ||
| 88 | 88 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 89 | 89 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 90 | 90 | |
| 91 | +#define SO_CNX_ADVICE 53 | |
| 92 | + | |
| 91 | 93 | #endif /* _ASM_SOCKET_H */ |
| @@ -45,8 +45,7 @@ static inline __sum16 csum_fold(__wsum sum) · 44 unmodified lines | ||
| 45 | 45 | */ |
| 46 | 46 | #define csum_tcpudp_nofold csum_tcpudp_nofold |
| 47 | 47 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 48 | − unsigned short len, | |
| 49 | − unsigned short proto, | |
| 48 | + __u32 len, __u8 proto, | |
| 50 | 49 | __wsum sum) |
| 51 | 50 | { |
| 52 | 51 | __asm__ __volatile__( |
| @@ -60,7 +59,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 7 unmodified lines | ||
| 60 | 59 | "cmpltu r8, %0, %3\n" |
| 61 | 60 | "add %0, %0, r8\n" /* add carry */ |
| 62 | 61 | : "=r" (sum), "=r" (saddr) |
| 63 | − : "r" (daddr), "r" ((ntohs(len) << 16) + (proto * 256)), | |
| 62 | + : "r" (daddr), "r" ((len + proto) << 8), | |
| 64 | 63 | "0" (sum), |
| 65 | 64 | "1" (saddr) |
| 66 | 65 | : "r8"); |
| @@ -69,8 +68,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 2 unmodified lines | ||
| 69 | 68 | } |
| 70 | 69 | |
| 71 | 70 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 72 | − unsigned short len, | |
| 73 | − unsigned short proto, __wsum sum) | |
| 71 | + __u32 len, __u8 proto, | |
| 72 | + __wsum sum) | |
| 74 | 73 | { |
| 75 | 74 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| 76 | 75 | } |
| @@ -85,9 +85,8 @@ static inline __sum16 csum_fold(__wsum csum) · 84 unmodified lines | ||
| 85 | 85 | } |
| 86 | 86 | |
| 87 | 87 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 88 | − unsigned short len, | |
| 89 | − unsigned short proto, | |
| 90 | − __wsum sum) | |
| 88 | + __u32 len, __u8 proto, | |
| 89 | + __wsum sum) | |
| 91 | 90 | { |
| 92 | 91 | __asm__( |
| 93 | 92 | " add %1, %0, %0\n" |
| @@ -104,9 +103,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 10 unmodified lines | ||
| 104 | 103 | * returns a 16-bit checksum, already complemented |
| 105 | 104 | */ |
| 106 | 105 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 107 | − unsigned short len, | |
| 108 | − unsigned short proto, | |
| 109 | − __wsum sum) | |
| 106 | + __u32 len, __u8 proto, | |
| 107 | + __wsum sum) | |
| 110 | 108 | { |
| 111 | 109 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 112 | 110 | } |
| @@ -124,7 +122,7 @@ static inline __sum16 ip_compute_csum(const void *buf, int len) · 11 unmodified lines | ||
| 124 | 122 | #define _HAVE_ARCH_IPV6_CSUM |
| 125 | 123 | static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 126 | 124 | const struct in6_addr *daddr, |
| 127 | − __u32 len, unsigned short proto, | |
| 125 | + __u32 len, __u8 proto, | |
| 128 | 126 | __wsum sum) |
| 129 | 127 | { |
| 130 | 128 | __asm__ __volatile__ ( |
| @@ -87,4 +87,6 @@ · 86 unmodified lines | ||
| 87 | 87 | #define SO_ATTACH_REUSEPORT_CBPF 0x402C |
| 88 | 88 | #define SO_ATTACH_REUSEPORT_EBPF 0x402D |
| 89 | 89 | |
| 90 | +#define SO_CNX_ADVICE 0x402E | |
| 91 | + | |
| 90 | 92 | #endif /* _UAPI_ASM_SOCKET_H */ |
| @@ -95,4 +95,6 @@ · 94 unmodified lines | ||
| 95 | 95 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 96 | 96 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 97 | 97 | |
| 98 | +#define SO_CNX_ADVICE 53 | |
| 99 | + | |
| 98 | 100 | #endif /* _ASM_POWERPC_SOCKET_H */ |
| @@ -91,8 +91,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 90 unmodified lines | ||
| 91 | 91 | * returns a 32-bit checksum |
| 92 | 92 | */ |
| 93 | 93 | static inline __wsum |
| 94 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |
| 95 | − unsigned short len, unsigned short proto, | |
| 94 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, __u8 proto, | |
| 96 | 95 | __wsum sum) |
| 97 | 96 | { |
| 98 | 97 | __u32 csum = (__force __u32)sum; |
| @@ -118,8 +117,7 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 19 unmodified lines | ||
| 118 | 117 | */ |
| 119 | 118 | |
| 120 | 119 | static inline __sum16 |
| 121 | −csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |
| 122 | − unsigned short len, unsigned short proto, | |
| 120 | +csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, __u8 proto, | |
| 123 | 121 | __wsum sum) |
| 124 | 122 | { |
| 125 | 123 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| @@ -94,4 +94,6 @@ · 93 unmodified lines | ||
| 94 | 94 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 95 | 95 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 96 | 96 | |
| 97 | +#define SO_CNX_ADVICE 53 | |
| 98 | + | |
| 97 | 99 | #endif /* _ASM_SOCKET_H */ |
| @@ -127,10 +127,10 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 126 unmodified lines | ||
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | static inline __wsum |
| 130 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 131 | − unsigned short proto, __wsum sum) | |
| 130 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 131 | + __u8 proto, __wsum sum) | |
| 132 | 132 | { |
| 133 | − unsigned long tmp = (ntohs(len) << 16) + proto * 256; | |
| 133 | + unsigned long tmp = (len + proto) << 8; | |
| 134 | 134 | __asm__ __volatile__( |
| 135 | 135 | ".set volatile\n\t" |
| 136 | 136 | "add\t%0, %0, %2\n\t" |
| @@ -161,8 +161,8 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, · 24 unmodified lines | ||
| 161 | 161 | * returns a 16-bit checksum, already complemented |
| 162 | 162 | */ |
| 163 | 163 | static inline __sum16 |
| 164 | −csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, | |
| 165 | − unsigned short proto, __wsum sum) | |
| 164 | +csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len, | |
| 165 | + __u8 proto, __wsum sum) | |
| 166 | 166 | { |
| 167 | 167 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| 168 | 168 | } |
| @@ -179,9 +179,8 @@ static inline unsigned short ip_compute_csum(const void *buff, int len) · 10 unmodified lines | ||
| 179 | 179 | |
| 180 | 180 | #define _HAVE_ARCH_IPV6_CSUM |
| 181 | 181 | static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 182 | − const struct in6_addr *daddr, | |
| 183 | − __u32 len, unsigned short proto, | |
| 184 | − __wsum sum) | |
| 182 | + const struct in6_addr *daddr, | |
| 183 | + __u32 len, __u8 proto, __wsum sum) | |
| 185 | 184 | { |
| 186 | 185 | __asm__ __volatile__( |
| 187 | 186 | ".set\tvolatile\t\t\t# csum_ipv6_magic\n\t" |
| @@ -115,8 +115,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 114 unmodified lines | ||
| 115 | 115 | } |
| 116 | 116 | |
| 117 | 117 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 118 | − unsigned short len, | |
| 119 | − unsigned short proto, | |
| 118 | + __u32 len, __u8 proto, | |
| 120 | 119 | __wsum sum) |
| 121 | 120 | { |
| 122 | 121 | #ifdef __LITTLE_ENDIAN__ |
| @@ -142,8 +141,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 19 unmodified lines | ||
| 142 | 141 | * returns a 16-bit checksum, already complemented |
| 143 | 142 | */ |
| 144 | 143 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 145 | − unsigned short len, | |
| 146 | − unsigned short proto, | |
| 144 | + __u32 len, __u8 proto, | |
| 147 | 145 | __wsum sum) |
| 148 | 146 | { |
| 149 | 147 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| @@ -161,8 +159,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) · 11 unmodified lines | ||
| 161 | 159 | #define _HAVE_ARCH_IPV6_CSUM |
| 162 | 160 | static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 163 | 161 | const struct in6_addr *daddr, |
| 164 | − __u32 len, unsigned short proto, | |
| 165 | − __wsum sum) | |
| 162 | + __u32 len, __u8 proto, __wsum sum) | |
| 166 | 163 | { |
| 167 | 164 | unsigned int __dummy; |
| 168 | 165 | __asm__("clrt\n\t" |
| @@ -102,6 +102,7 @@ CONFIG_SUNLANCE=m · 101 unmodified lines | ||
| 102 | 102 | CONFIG_HAPPYMEAL=m |
| 103 | 103 | CONFIG_SUNGEM=m |
| 104 | 104 | CONFIG_SUNVNET=m |
| 105 | +CONFIG_LDMVSW=m | |
| 105 | 106 | CONFIG_NET_PCI=y |
| 106 | 107 | CONFIG_E1000=m |
| 107 | 108 | CONFIG_E1000E=m |
| @@ -170,9 +170,8 @@ static inline __sum16 csum_fold(__wsum sum) · 169 unmodified lines | ||
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 173 | − unsigned short len, | |
| 174 | − unsigned short proto, | |
| 175 | − __wsum sum) | |
| 173 | + __u32 len, __u8 proto, | |
| 174 | + __wsum sum) | |
| 176 | 175 | { |
| 177 | 176 | __asm__ __volatile__("addcc\t%1, %0, %0\n\t" |
| 178 | 177 | "addxcc\t%2, %0, %0\n\t" |
| @@ -190,9 +189,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 11 unmodified lines | ||
| 190 | 189 | * returns a 16-bit checksum, already complemented |
| 191 | 190 | */ |
| 192 | 191 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 193 | − unsigned short len, | |
| 194 | − unsigned short proto, | |
| 195 | − __wsum sum) | |
| 192 | + __u32 len, __u8 proto, | |
| 193 | + __wsum sum) | |
| 196 | 194 | { |
| 197 | 195 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 198 | 196 | } |
| @@ -201,8 +199,7 @@ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, · 2 unmodified lines | ||
| 201 | 199 | |
| 202 | 200 | static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 203 | 201 | const struct in6_addr *daddr, |
| 204 | − __u32 len, unsigned short proto, | |
| 205 | − __wsum sum) | |
| 202 | + __u32 len, __u8 proto, __wsum sum) | |
| 206 | 203 | { |
| 207 | 204 | __asm__ __volatile__ ( |
| 208 | 205 | "addcc %3, %4, %%g4\n\t" |
| @@ -96,8 +96,7 @@ static inline __sum16 csum_fold(__wsum sum) · 95 unmodified lines | ||
| 96 | 96 | } |
| 97 | 97 | |
| 98 | 98 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 99 | − unsigned int len, | |
| 100 | − unsigned short proto, | |
| 99 | + __u32 len, __u8 proto, | |
| 101 | 100 | __wsum sum) |
| 102 | 101 | { |
| 103 | 102 | __asm__ __volatile__( |
| @@ -116,8 +115,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 12 unmodified lines | ||
| 116 | 115 | * returns a 16-bit checksum, already complemented |
| 117 | 116 | */ |
| 118 | 117 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 119 | − unsigned short len, | |
| 120 | − unsigned short proto, | |
| 118 | + __u32 len, __u8 proto, | |
| 121 | 119 | __wsum sum) |
| 122 | 120 | { |
| 123 | 121 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| @@ -127,8 +125,7 @@ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, · 3 unmodified lines | ||
| 127 | 125 | |
| 128 | 126 | static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 129 | 127 | const struct in6_addr *daddr, |
| 130 | − __u32 len, unsigned short proto, | |
| 131 | − __wsum sum) | |
| 128 | + __u32 len, __u8 proto, __wsum sum) | |
| 132 | 129 | { |
| 133 | 130 | __asm__ __volatile__ ( |
| 134 | 131 | " addcc %3, %4, %%g7\n" |
| @@ -84,6 +84,8 @@ · 83 unmodified lines | ||
| 84 | 84 | #define SO_ATTACH_REUSEPORT_CBPF 0x0035 |
| 85 | 85 | #define SO_ATTACH_REUSEPORT_EBPF 0x0036 |
| 86 | 86 | |
| 87 | +#define SO_CNX_ADVICE 0x0037 | |
| 88 | + | |
| 87 | 89 | /* Security levels - as per NRL IPv6 - don't actually do anything */ |
| 88 | 90 | #define SO_SECURITY_AUTHENTICATION 0x5001 |
| 89 | 91 | #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 |
| @@ -222,7 +222,7 @@ CONFIG_TUN=y · 221 unmodified lines | ||
| 222 | 222 | CONFIG_VETH=m |
| 223 | 223 | CONFIG_NET_DSA_MV88E6060=y |
| 224 | 224 | CONFIG_NET_DSA_MV88E6131=y |
| 225 | −CONFIG_NET_DSA_MV88E6123_61_65=y | |
| 225 | +CONFIG_NET_DSA_MV88E6123=y | |
| 226 | 226 | CONFIG_SKY2=y |
| 227 | 227 | CONFIG_PTP_1588_CLOCK_TILEGX=y |
| 228 | 228 | # CONFIG_WLAN is not set |
| @@ -341,7 +341,7 @@ CONFIG_TUN=y · 340 unmodified lines | ||
| 341 | 341 | CONFIG_VETH=m |
| 342 | 342 | CONFIG_NET_DSA_MV88E6060=y |
| 343 | 343 | CONFIG_NET_DSA_MV88E6131=y |
| 344 | −CONFIG_NET_DSA_MV88E6123_61_65=y | |
| 344 | +CONFIG_NET_DSA_MV88E6123=y | |
| 345 | 345 | # CONFIG_NET_VENDOR_3COM is not set |
| 346 | 346 | CONFIG_E1000E=y |
| 347 | 347 | # CONFIG_WLAN is not set |
| @@ -20,8 +20,8 @@ · 19 unmodified lines | ||
| 20 | 20 | */ |
| 21 | 21 | |
| 22 | 22 | static inline __wsum |
| 23 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 24 | − unsigned short proto, __wsum sum) | |
| 23 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 24 | + __u8 proto, __wsum sum) | |
| 25 | 25 | { |
| 26 | 26 | __asm__( |
| 27 | 27 | "add.a %0, %1, %2\n" |
| @@ -2194,11 +2194,11 @@ static int backtrace_stack(void *data, char *name) · 2193 unmodified lines | ||
| 2194 | 2194 | return 0; |
| 2195 | 2195 | } |
| 2196 | 2196 | |
| 2197 | −static void backtrace_address(void *data, unsigned long addr, int reliable) | |
| 2197 | +static int backtrace_address(void *data, unsigned long addr, int reliable) | |
| 2198 | 2198 | { |
| 2199 | 2199 | struct perf_callchain_entry *entry = data; |
| 2200 | 2200 | |
| 2201 | − perf_callchain_store(entry, addr); | |
| 2201 | + return perf_callchain_store(entry, addr); | |
| 2202 | 2202 | } |
| 2203 | 2203 | |
| 2204 | 2204 | static const struct stacktrace_ops backtrace_ops = { |
| @@ -112,8 +112,7 @@ static inline __sum16 csum_fold(__wsum sum) · 111 unmodified lines | ||
| 112 | 112 | } |
| 113 | 113 | |
| 114 | 114 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 115 | − unsigned short len, | |
| 116 | − unsigned short proto, | |
| 115 | + __u32 len, __u8 proto, | |
| 117 | 116 | __wsum sum) |
| 118 | 117 | { |
| 119 | 118 | asm("addl %1, %0 ;\n" |
| @@ -131,8 +130,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 11 unmodified lines | ||
| 131 | 130 | * returns a 16-bit checksum, already complemented |
| 132 | 131 | */ |
| 133 | 132 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 134 | − unsigned short len, | |
| 135 | − unsigned short proto, | |
| 133 | + __u32 len, __u8 proto, | |
| 136 | 134 | __wsum sum) |
| 137 | 135 | { |
| 138 | 136 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| @@ -151,8 +149,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) · 12 unmodified lines | ||
| 151 | 149 | #define _HAVE_ARCH_IPV6_CSUM |
| 152 | 150 | static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 153 | 151 | const struct in6_addr *daddr, |
| 154 | − __u32 len, unsigned short proto, | |
| 155 | − __wsum sum) | |
| 152 | + __u32 len, __u8 proto, __wsum sum) | |
| 156 | 153 | { |
| 157 | 154 | asm("addl 0(%1), %0 ;\n" |
| 158 | 155 | "adcl 4(%1), %0 ;\n" |
| @@ -84,8 +84,8 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 83 unmodified lines | ||
| 84 | 84 | * 32bit unfolded. |
| 85 | 85 | */ |
| 86 | 86 | static inline __wsum |
| 87 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 88 | − unsigned short proto, __wsum sum) | |
| 87 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 88 | + __u8 proto, __wsum sum) | |
| 89 | 89 | { |
| 90 | 90 | asm(" addl %1, %0\n" |
| 91 | 91 | " adcl %2, %0\n" |
| @@ -110,8 +110,8 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, · 18 unmodified lines | ||
| 110 | 110 | * complemented and ready to be filled in. |
| 111 | 111 | */ |
| 112 | 112 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 113 | − unsigned short len, | |
| 114 | − unsigned short proto, __wsum sum) | |
| 113 | + __u32 len, __u8 proto, | |
| 114 | + __wsum sum) | |
| 115 | 115 | { |
| 116 | 116 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); |
| 117 | 117 | } |
| @@ -177,7 +177,7 @@ struct in6_addr; · 59 unmodified lines | ||
| 177 | 177 | #define _HAVE_ARCH_IPV6_CSUM 1 |
| 178 | 178 | extern __sum16 |
| 179 | 179 | csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, |
| 180 | − __u32 len, unsigned short proto, __wsum sum); | |
| 180 | + __u32 len, __u8 proto, __wsum sum); | |
| 181 | 181 | |
| 182 | 182 | static inline unsigned add32_with_carry(unsigned a, unsigned b) |
| 183 | 183 | { |
| @@ -37,7 +37,7 @@ print_context_stack_bp(struct thread_info *tinfo, · 36 unmodified lines | ||
| 37 | 37 | /* Generic stack tracer with callbacks */ |
| 38 | 38 | |
| 39 | 39 | struct stacktrace_ops { |
| 40 | − void (*address)(void *data, unsigned long address, int reliable); | |
| 40 | + int (*address)(void *data, unsigned long address, int reliable); | |
| 41 | 41 | /* On negative return stop dumping */ |
| 42 | 42 | int (*stack)(void *data, char *name); |
| 43 | 43 | walk_stack_t walk_stack; |
| @@ -135,7 +135,8 @@ print_context_stack_bp(struct thread_info *tinfo, · 134 unmodified lines | ||
| 135 | 135 | if (!__kernel_text_address(addr)) |
| 136 | 136 | break; |
| 137 | 137 | |
| 138 | − ops->address(data, addr, 1); | |
| 138 | + if (ops->address(data, addr, 1)) | |
| 139 | + break; | |
| 139 | 140 | frame = frame->next_frame; |
| 140 | 141 | ret_addr = &frame->return_address; |
| 141 | 142 | print_ftrace_graph_addr(addr, data, ops, tinfo, graph); |
| @@ -154,10 +155,11 @@ static int print_trace_stack(void *data, char *name) · 12 unmodified lines | ||
| 154 | 155 | /* |
| 155 | 156 | * Print one address/symbol entries per line. |
| 156 | 157 | */ |
| 157 | −static void print_trace_address(void *data, unsigned long addr, int reliable) | |
| 158 | +static int print_trace_address(void *data, unsigned long addr, int reliable) | |
| 158 | 159 | { |
| 159 | 160 | touch_nmi_watchdog(); |
| 160 | 161 | printk_stack_address(addr, reliable, data); |
| 162 | + return 0; | |
| 161 | 163 | } |
| 162 | 164 | |
| 163 | 165 | static const struct stacktrace_ops print_trace_ops = { |
| @@ -14,30 +14,34 @@ static int save_stack_stack(void *data, char *name) · 13 unmodified lines | ||
| 14 | 14 | return 0; |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | −static void | |
| 17 | +static int | |
| 18 | 18 | __save_stack_address(void *data, unsigned long addr, bool reliable, bool nosched) |
| 19 | 19 | { |
| 20 | 20 | struct stack_trace *trace = data; |
| 21 | 21 | #ifdef CONFIG_FRAME_POINTER |
| 22 | 22 | if (!reliable) |
| 23 | − return; | |
| 23 | + return 0; | |
| 24 | 24 | #endif |
| 25 | 25 | if (nosched && in_sched_functions(addr)) |
| 26 | − return; | |
| 26 | + return 0; | |
| 27 | 27 | if (trace->skip > 0) { |
| 28 | 28 | trace->skip--; |
| 29 | − return; | |
| 29 | + return 0; | |
| 30 | 30 | } |
| 31 | − if (trace->nr_entries < trace->max_entries) | |
| 31 | + if (trace->nr_entries < trace->max_entries) { | |
| 32 | 32 | trace->entries[trace->nr_entries++] = addr; |
| 33 | + return 0; | |
| 34 | + } else { | |
| 35 | + return -1; /* no more room, stop walking the stack */ | |
| 36 | + } | |
| 33 | 37 | } |
| 34 | 38 | |
| 35 | −static void save_stack_address(void *data, unsigned long addr, int reliable) | |
| 39 | +static int save_stack_address(void *data, unsigned long addr, int reliable) | |
| 36 | 40 | { |
| 37 | 41 | return __save_stack_address(data, addr, reliable, false); |
| 38 | 42 | } |
| 39 | 43 | |
| 40 | −static void | |
| 44 | +static int | |
| 41 | 45 | save_stack_address_nosched(void *data, unsigned long addr, int reliable) |
| 42 | 46 | { |
| 43 | 47 | return __save_stack_address(data, addr, reliable, true); |
| @@ -135,7 +135,7 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck); · 134 unmodified lines | ||
| 135 | 135 | |
| 136 | 136 | __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 137 | 137 | const struct in6_addr *daddr, |
| 138 | − __u32 len, unsigned short proto, __wsum sum) | |
| 138 | + __u32 len, __u8 proto, __wsum sum) | |
| 139 | 139 | { |
| 140 | 140 | __u64 rest, sum64; |
| 141 | 141 | |
| @@ -23,12 +23,13 @@ static int backtrace_stack(void *data, char *name) · 22 unmodified lines | ||
| 23 | 23 | return 0; |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | −static void backtrace_address(void *data, unsigned long addr, int reliable) | |
| 26 | +static int backtrace_address(void *data, unsigned long addr, int reliable) | |
| 27 | 27 | { |
| 28 | 28 | unsigned int *depth = data; |
| 29 | 29 | |
| 30 | 30 | if ((*depth)--) |
| 31 | 31 | oprofile_add_trace(addr); |
| 32 | + return 0; | |
| 32 | 33 | } |
| 33 | 34 | |
| 34 | 35 | static struct stacktrace_ops backtrace_ops = { |
| @@ -87,8 +87,8 @@ static inline __sum16 csum_fold(__wsum sum) · 86 unmodified lines | ||
| 87 | 87 | * 32bit unfolded. |
| 88 | 88 | */ |
| 89 | 89 | static inline __wsum |
| 90 | −csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | |
| 91 | − unsigned short proto, __wsum sum) | |
| 90 | +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | |
| 91 | + __u8 proto, __wsum sum) | |
| 92 | 92 | { |
| 93 | 93 | asm(" addl %1, %0\n" |
| 94 | 94 | " adcl %2, %0\n" |
| @@ -104,9 +104,8 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, · 9 unmodified lines | ||
| 104 | 104 | * returns a 16-bit checksum, already complemented |
| 105 | 105 | */ |
| 106 | 106 | static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 107 | − unsigned short len, | |
| 108 | − unsigned short proto, | |
| 109 | − __wsum sum) | |
| 107 | + __u32 len, __u8 proto, | |
| 108 | + __wsum sum) | |
| 110 | 109 | { |
| 111 | 110 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 112 | 111 | } |
| @@ -13,7 +13,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) · 12 unmodified lines | ||
| 13 | 13 | #define _HAVE_ARCH_IPV6_CSUM |
| 14 | 14 | static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 15 | 15 | const struct in6_addr *daddr, |
| 16 | − __u32 len, unsigned short proto, | |
| 16 | + __u32 len, __u8 proto, | |
| 17 | 17 | __wsum sum) |
| 18 | 18 | { |
| 19 | 19 | __asm__( |
| @@ -123,9 +123,8 @@ static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 122 unmodified lines | ||
| 123 | 123 | } |
| 124 | 124 | |
| 125 | 125 | static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, |
| 126 | − unsigned short len, | |
| 127 | − unsigned short proto, | |
| 128 | − __wsum sum) | |
| 126 | + __u32 len, __u8 proto, | |
| 127 | + __wsum sum) | |
| 129 | 128 | { |
| 130 | 129 | |
| 131 | 130 | #ifdef __XTENSA_EL__ |
| @@ -157,9 +156,8 @@ static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, · 25 unmodified lines | ||
| 157 | 156 | * returns a 16-bit checksum, already complemented |
| 158 | 157 | */ |
| 159 | 158 | static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, |
| 160 | − unsigned short len, | |
| 161 | − unsigned short proto, | |
| 162 | − __wsum sum) | |
| 159 | + __u32 len, __u8 proto, | |
| 160 | + __wsum sum) | |
| 163 | 161 | { |
| 164 | 162 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); |
| 165 | 163 | } |
| @@ -177,7 +175,7 @@ static __inline__ __sum16 ip_compute_csum(const void *buff, int len) · 11 unmodified lines | ||
| 177 | 175 | #define _HAVE_ARCH_IPV6_CSUM |
| 178 | 176 | static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, |
| 179 | 177 | const struct in6_addr *daddr, |
| 180 | − __u32 len, unsigned short proto, | |
| 178 | + __u32 len, __u8 proto, | |
| 181 | 179 | __wsum sum) |
| 182 | 180 | { |
| 183 | 181 | unsigned int __dummy; |
| @@ -99,4 +99,6 @@ · 98 unmodified lines | ||
| 99 | 99 | #define SO_ATTACH_REUSEPORT_CBPF 51 |
| 100 | 100 | #define SO_ATTACH_REUSEPORT_EBPF 52 |
| 101 | 101 | |
| 102 | +#define SO_CNX_ADVICE 53 | |
| 103 | + | |
| 102 | 104 | #endif /* _XTENSA_SOCKET_H */ |
| @@ -70,6 +70,11 @@ config BCMA_DRIVER_MIPS · 69 unmodified lines | ||
| 70 | 70 | |
| 71 | 71 | If unsure, say N |
| 72 | 72 | |
| 73 | +config BCMA_PFLASH | |
| 74 | + bool | |
| 75 | + depends on BCMA_DRIVER_MIPS | |
| 76 | + default y | |
| 77 | + | |
| 73 | 78 | config BCMA_SFLASH |
| 74 | 79 | bool |
| 75 | 80 | depends on BCMA_DRIVER_MIPS |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | bcma-y += main.o scan.o core.o sprom.o |
| 2 | 2 | bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o |
| 3 | 3 | bcma-y += driver_chipcommon_b.o |
| 4 | +bcma-$(CONFIG_BCMA_PFLASH) += driver_chipcommon_pflash.o | |
| 4 | 5 | bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o |
| 5 | 6 | bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o |
| 6 | 7 | bcma-$(CONFIG_BCMA_DRIVER_PCI) += driver_pci.o |
| @@ -47,10 +47,6 @@ int bcma_sprom_get(struct bcma_bus *bus); · 46 unmodified lines | ||
| 47 | 47 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); |
| 48 | 48 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); |
| 49 | 49 | void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); |
| 50 | −#ifdef CONFIG_BCMA_DRIVER_MIPS | |
| 51 | −void bcma_chipco_serial_init(struct bcma_drv_cc *cc); | |
| 52 | −extern struct platform_device bcma_pflash_dev; | |
| 53 | −#endif /* CONFIG_BCMA_DRIVER_MIPS */ | |
| 54 | 50 | |
| 55 | 51 | /* driver_chipcommon_b.c */ |
| 56 | 52 | int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb); |
| @@ -62,6 +58,21 @@ void bcma_pmu_init(struct bcma_drv_cc *cc); · 5 unmodified lines | ||
| 62 | 58 | u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc); |
| 63 | 59 | u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc); |
| 64 | 60 | |
| 61 | +/************************************************** | |
| 62 | + * driver_chipcommon_sflash.c | |
| 63 | + **************************************************/ | |
| 64 | + | |
| 65 | +#ifdef CONFIG_BCMA_PFLASH | |
| 66 | +extern struct platform_device bcma_pflash_dev; | |
| 67 | +int bcma_pflash_init(struct bcma_drv_cc *cc); | |
| 68 | +#else | |
| 69 | +static inline int bcma_pflash_init(struct bcma_drv_cc *cc) | |
| 70 | +{ | |
| 71 | + bcma_err(cc->core->bus, "Parallel flash not supported\n"); | |
| 72 | + return 0; | |
| 73 | +} | |
| 74 | +#endif /* CONFIG_BCMA_PFLASH */ | |
| 75 | + | |
| 65 | 76 | #ifdef CONFIG_BCMA_SFLASH |
| 66 | 77 | /* driver_chipcommon_sflash.c */ |
| 67 | 78 | int bcma_sflash_init(struct bcma_drv_cc *cc); |
| @@ -15,6 +15,8 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/platform_device.h> |
| 16 | 16 | #include <linux/bcma/bcma.h> |
| 17 | 17 | |
| 18 | +static void bcma_chipco_serial_init(struct bcma_drv_cc *cc); | |
| 19 | + | |
| 18 | 20 | static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, |
| 19 | 21 | u32 mask, u32 value) |
| 20 | 22 | { |
| @@ -113,8 +115,37 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) · 92 unmodified lines | ||
| 113 | 115 | return 0; |
| 114 | 116 | } |
| 115 | 117 | |
| 118 | +static void bcma_core_chipcommon_flash_detect(struct bcma_drv_cc *cc) | |
| 119 | +{ | |
| 120 | + struct bcma_bus *bus = cc->core->bus; | |
| 121 | + | |
| 122 | + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | |
| 123 | + case BCMA_CC_FLASHT_STSER: | |
| 124 | + case BCMA_CC_FLASHT_ATSER: | |
| 125 | + bcma_debug(bus, "Found serial flash\n"); | |
| 126 | + bcma_sflash_init(cc); | |
| 127 | + break; | |
| 128 | + case BCMA_CC_FLASHT_PARA: | |
| 129 | + bcma_debug(bus, "Found parallel flash\n"); | |
| 130 | + bcma_pflash_init(cc); | |
| 131 | + break; | |
| 132 | + default: | |
| 133 | + bcma_err(bus, "Flash type not supported\n"); | |
| 134 | + } | |
| 135 | + | |
| 136 | + if (cc->core->id.rev == 38 || | |
| 137 | + bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | |
| 138 | + if (cc->capabilities & BCMA_CC_CAP_NFLASH) { | |
| 139 | + bcma_debug(bus, "Found NAND flash\n"); | |
| 140 | + bcma_nflash_init(cc); | |
| 141 | + } | |
| 142 | + } | |
| 143 | +} | |
| 144 | + | |
| 116 | 145 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) |
| 117 | 146 | { |
| 147 | + struct bcma_bus *bus = cc->core->bus; | |
| 148 | + | |
| 118 | 149 | if (cc->early_setup_done) |
| 119 | 150 | return; |
| 120 | 151 | |
| @@ -129,6 +160,12 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) · 8 unmodified lines | ||
| 129 | 160 | if (cc->capabilities & BCMA_CC_CAP_PMU) |
| 130 | 161 | bcma_pmu_early_init(cc); |
| 131 | 162 | |
| 163 | + if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC) | |
| 164 | + bcma_chipco_serial_init(cc); | |
| 165 | + | |
| 166 | + if (bus->hosttype == BCMA_HOSTTYPE_SOC) | |
| 167 | + bcma_core_chipcommon_flash_detect(cc); | |
| 168 | + | |
| 132 | 169 | cc->early_setup_done = true; |
| 133 | 170 | } |
| 134 | 171 | |
| @@ -185,11 +222,12 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) · 50 unmodified lines | ||
| 185 | 222 | ticks = 2; |
| 186 | 223 | else if (ticks > maxt) |
| 187 | 224 | ticks = maxt; |
| 188 | − bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); | |
| 225 | + bcma_pmu_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); | |
| 189 | 226 | } else { |
| 190 | 227 | struct bcma_bus *bus = cc->core->bus; |
| 191 | 228 | |
| 192 | 229 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 && |
| 230 | + bus->chipinfo.id != BCMA_CHIP_ID_BCM47094 && | |
| 193 | 231 | bus->chipinfo.id != BCMA_CHIP_ID_BCM53018) |
| 194 | 232 | bcma_core_set_clockmode(cc->core, |
| 195 | 233 | ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC); |
| @@ -314,9 +352,9 @@ u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value) · 118 unmodified lines | ||
| 314 | 352 | return res; |
| 315 | 353 | } |
| 316 | 354 | |
| 317 | −#ifdef CONFIG_BCMA_DRIVER_MIPS | |
| 318 | −void bcma_chipco_serial_init(struct bcma_drv_cc *cc) | |
| 355 | +static void bcma_chipco_serial_init(struct bcma_drv_cc *cc) | |
| 319 | 356 | { |
| 357 | +#if IS_BUILTIN(CONFIG_BCM47XX) | |
| 320 | 358 | unsigned int irq; |
| 321 | 359 | u32 baud_base; |
| 322 | 360 | u32 i; |
| @@ -358,5 +396,5 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) · 35 unmodified lines | ||
| 358 | 396 | ports[i].baud_base = baud_base; |
| 359 | 397 | ports[i].reg_shift = 0; |
| 360 | 398 | } |
| 399 | +#endif /* CONFIG_BCM47XX */ | |
| 361 | 400 | } |
| 362 | −#endif /* CONFIG_BCMA_DRIVER_MIPS */ | |
| @@ -0,0 +1,49 @@ | ||
| 1 | +/* | |
| 2 | + * Broadcom specific AMBA | |
| 3 | + * ChipCommon parallel flash | |
| 4 | + * | |
| 5 | + * Licensed under the GNU/GPL. See COPYING for details. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include "bcma_private.h" | |
| 9 | + | |
| 10 | +#include <linux/bcma/bcma.h> | |
| 11 | +#include <linux/mtd/physmap.h> | |
| 12 | +#include <linux/platform_device.h> | |
| 13 | + | |
| 14 | +static const char * const part_probes[] = { "bcm47xxpart", NULL }; | |
| 15 | + | |
| 16 | +static struct physmap_flash_data bcma_pflash_data = { | |
| 17 | + .part_probe_types = part_probes, | |
| 18 | +}; | |
| 19 | + | |
| 20 | +static struct resource bcma_pflash_resource = { | |
| 21 | + .name = "bcma_pflash", | |
| 22 | + .flags = IORESOURCE_MEM, | |
| 23 | +}; | |
| 24 | + | |
| 25 | +struct platform_device bcma_pflash_dev = { | |
| 26 | + .name = "physmap-flash", | |
| 27 | + .dev = { | |
| 28 | + .platform_data = &bcma_pflash_data, | |
| 29 | + }, | |
| 30 | + .resource = &bcma_pflash_resource, | |
| 31 | + .num_resources = 1, | |
| 32 | +}; | |
| 33 | + | |
| 34 | +int bcma_pflash_init(struct bcma_drv_cc *cc) | |
| 35 | +{ | |
| 36 | + struct bcma_pflash *pflash = &cc->pflash; | |
| 37 | + | |
| 38 | + pflash->present = true; | |
| 39 | + | |
| 40 | + if (!(bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & BCMA_CC_FLASH_CFG_DS)) | |
| 41 | + bcma_pflash_data.width = 1; | |
| 42 | + else | |
| 43 | + bcma_pflash_data.width = 2; | |
| 44 | + | |
| 45 | + bcma_pflash_resource.start = BCMA_SOC_FLASH2; | |
| 46 | + bcma_pflash_resource.end = BCMA_SOC_FLASH2 + BCMA_SOC_FLASH2_SZ; | |
| 47 | + | |
| 48 | + return 0; | |
| 49 | +} | |
| @@ -15,44 +15,44 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) |
| 17 | 17 | { |
| 18 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | |
| 19 | − bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | |
| 20 | − return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | |
| 18 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); | |
| 19 | + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); | |
| 20 | + return bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); | |
| 21 | 21 | } |
| 22 | 22 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); |
| 23 | 23 | |
| 24 | 24 | void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) |
| 25 | 25 | { |
| 26 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | |
| 27 | − bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | |
| 28 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); | |
| 26 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); | |
| 27 | + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); | |
| 28 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); | |
| 29 | 29 | } |
| 30 | 30 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); |
| 31 | 31 | |
| 32 | 32 | void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, |
| 33 | 33 | u32 set) |
| 34 | 34 | { |
| 35 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | |
| 36 | − bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | |
| 37 | − bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set); | |
| 35 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); | |
| 36 | + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); | |
| 37 | + bcma_pmu_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); | |
| 38 | 38 | } |
| 39 | 39 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); |
| 40 | 40 | |
| 41 | 41 | void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, |
| 42 | 42 | u32 offset, u32 mask, u32 set) |
| 43 | 43 | { |
| 44 | − bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); | |
| 45 | − bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); | |
| 46 | − bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set); | |
| 44 | + bcma_pmu_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); | |
| 45 | + bcma_pmu_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); | |
| 46 | + bcma_pmu_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); | |
| 47 | 47 | } |
| 48 | 48 | EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); |
| 49 | 49 | |
| 50 | 50 | void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, |
| 51 | 51 | u32 set) |
| 52 | 52 | { |
| 53 | − bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset); | |
| 54 | − bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR); | |
| 55 | − bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set); | |
| 53 | + bcma_pmu_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); | |
| 54 | + bcma_pmu_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); | |
| 55 | + bcma_pmu_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); | |
| 56 | 56 | } |
| 57 | 57 | EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); |
| 58 | 58 | |
| @@ -60,18 +60,18 @@ static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) · 1 unmodified line | ||
| 60 | 60 | { |
| 61 | 61 | u32 ilp_ctl, alp_hz; |
| 62 | 62 | |
| 63 | − if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) & | |
| 63 | + if (!(bcma_pmu_read32(cc, BCMA_CC_PMU_STAT) & | |
| 64 | 64 | BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) |
| 65 | 65 | return 0; |
| 66 | 66 | |
| 67 | − bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, | |
| 68 | − BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); | |
| 67 | + bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, | |
| 68 | + BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); | |
| 69 | 69 | usleep_range(1000, 2000); |
| 70 | 70 | |
| 71 | − ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ); | |
| 71 | + ilp_ctl = bcma_pmu_read32(cc, BCMA_CC_PMU_XTAL_FREQ); | |
| 72 | 72 | ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; |
| 73 | 73 | |
| 74 | − bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); | |
| 74 | + bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); | |
| 75 | 75 | |
| 76 | 76 | alp_hz = ilp_ctl * 32768 / 4; |
| 77 | 77 | return (alp_hz + 50000) / 100000 * 100; |
| @@ -127,8 +127,8 @@ static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) · 49 unmodified lines | ||
| 127 | 127 | mask = (u32)~(BCMA_RES_4314_HT_AVAIL | |
| 128 | 128 | BCMA_RES_4314_MACPHY_CLK_AVAIL); |
| 129 | 129 | |
| 130 | − bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); | |
| 131 | − bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); | |
| 130 | + bcma_pmu_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); | |
| 131 | + bcma_pmu_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); | |
| 132 | 132 | bcma_wait_value(cc->core, BCMA_CLKCTLST, |
| 133 | 133 | BCMA_CLKCTLST_HAVEHT, 0, 20000); |
| 134 | 134 | break; |
| @@ -140,7 +140,7 @@ static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) · 5 unmodified lines | ||
| 140 | 140 | |
| 141 | 141 | /* Flush */ |
| 142 | 142 | if (cc->pmu.rev >= 2) |
| 143 | − bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); | |
| 143 | + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); | |
| 144 | 144 | |
| 145 | 145 | /* TODO: Do we need to update OTP? */ |
| 146 | 146 | } |
| @@ -195,9 +195,9 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) · 48 unmodified lines | ||
| 195 | 195 | |
| 196 | 196 | /* Set the resource masks. */ |
| 197 | 197 | if (min_msk) |
| 198 | − bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); | |
| 198 | + bcma_pmu_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); | |
| 199 | 199 | if (max_msk) |
| 200 | − bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); | |
| 200 | + bcma_pmu_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); | |
| 201 | 201 | |
| 202 | 202 | /* |
| 203 | 203 | * Add some delay; allow resources to come up and settle. |
| @@ -269,23 +269,33 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) · 65 unmodified lines | ||
| 269 | 269 | |
| 270 | 270 | void bcma_pmu_early_init(struct bcma_drv_cc *cc) |
| 271 | 271 | { |
| 272 | + struct bcma_bus *bus = cc->core->bus; | |
| 272 | 273 | u32 pmucap; |
| 273 | 274 | |
| 274 | − pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); | |
| 275 | + if (cc->core->id.rev >= 35 && | |
| 276 | + cc->capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { | |
| 277 | + cc->pmu.core = bcma_find_core(bus, BCMA_CORE_PMU); | |
| 278 | + if (!cc->pmu.core) | |
| 279 | + bcma_warn(bus, "Couldn't find expected PMU core"); | |
| 280 | + } | |
| 281 | + if (!cc->pmu.core) | |
| 282 | + cc->pmu.core = cc->core; | |
| 283 | + | |
| 284 | + pmucap = bcma_pmu_read32(cc, BCMA_CC_PMU_CAP); | |
| 275 | 285 | cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); |
| 276 | 286 | |
| 277 | − bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", | |
| 278 | − cc->pmu.rev, pmucap); | |
| 287 | + bcma_debug(bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, | |
| 288 | + pmucap); | |
| 279 | 289 | } |
| 280 | 290 | |
| 281 | 291 | void bcma_pmu_init(struct bcma_drv_cc *cc) |
| 282 | 292 | { |
| 283 | 293 | if (cc->pmu.rev == 1) |
| 284 | − bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, | |
| 285 | − ~BCMA_CC_PMU_CTL_NOILPONW); | |
| 294 | + bcma_pmu_mask32(cc, BCMA_CC_PMU_CTL, | |
| 295 | + ~BCMA_CC_PMU_CTL_NOILPONW); | |
| 286 | 296 | else |
| 287 | − bcma_cc_set32(cc, BCMA_CC_PMU_CTL, | |
| 288 | − BCMA_CC_PMU_CTL_NOILPONW); | |
| 297 | + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, | |
| 298 | + BCMA_CC_PMU_CTL_NOILPONW); | |
| 289 | 299 | |
| 290 | 300 | bcma_pmu_pll_init(cc); |
| 291 | 301 | bcma_pmu_resources_init(cc); |
| @@ -472,8 +482,8 @@ u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) · 180 unmodified lines | ||
| 472 | 482 | static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, |
| 473 | 483 | u32 value) |
| 474 | 484 | { |
| 475 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | |
| 476 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); | |
| 485 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); | |
| 486 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); | |
| 477 | 487 | } |
| 478 | 488 | |
| 479 | 489 | void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) |
| @@ -497,20 +507,20 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) · 17 unmodified lines | ||
| 497 | 507 | bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; |
| 498 | 508 | |
| 499 | 509 | /* RMW only the P1 divider */ |
| 500 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, | |
| 510 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, | |
| 501 | 511 | BCMA_CC_PMU_PLL_CTL0 + phypll_offset); |
| 502 | − tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | |
| 512 | + tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); | |
| 503 | 513 | tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); |
| 504 | 514 | tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); |
| 505 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); | |
| 515 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); | |
| 506 | 516 | |
| 507 | 517 | /* RMW only the int feedback divider */ |
| 508 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, | |
| 518 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, | |
| 509 | 519 | BCMA_CC_PMU_PLL_CTL2 + phypll_offset); |
| 510 | − tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | |
| 520 | + tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); | |
| 511 | 521 | tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); |
| 512 | 522 | tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; |
| 513 | − bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); | |
| 523 | + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); | |
| 514 | 524 | |
| 515 | 525 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
| 516 | 526 | break; |
| @@ -646,7 +656,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) · 129 unmodified lines | ||
| 646 | 656 | break; |
| 647 | 657 | } |
| 648 | 658 | |
| 649 | − tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL); | |
| 650 | − bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp); | |
| 659 | + tmp |= bcma_pmu_read32(cc, BCMA_CC_PMU_CTL); | |
| 660 | + bcma_pmu_write32(cc, BCMA_CC_PMU_CTL, tmp); | |
| 651 | 661 | } |
| 652 | 662 | EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); |
| @@ -38,6 +38,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { · 37 unmodified lines | ||
| 38 | 38 | { "M25P32", 0x15, 0x10000, 64, }, |
| 39 | 39 | { "M25P64", 0x16, 0x10000, 128, }, |
| 40 | 40 | { "M25FL128", 0x17, 0x10000, 256, }, |
| 41 | + { "MX25L25635F", 0x18, 0x10000, 512, }, | |
| 41 | 42 | { NULL }, |
| 42 | 43 | }; |
| 43 | 44 | |
| @@ -192,6 +192,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) · 191 unmodified lines | ||
| 192 | 192 | case BCMA_CHIP_ID_BCM4707: |
| 193 | 193 | case BCMA_CHIP_ID_BCM5357: |
| 194 | 194 | case BCMA_CHIP_ID_BCM53572: |
| 195 | + case BCMA_CHIP_ID_BCM47094: | |
| 195 | 196 | chip->ngpio = 32; |
| 196 | 197 | break; |
| 197 | 198 | default: |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include <linux/bcma/bcma.h> |
| 16 | 16 | |
| 17 | −#include <linux/mtd/physmap.h> | |
| 18 | −#include <linux/platform_device.h> | |
| 19 | 17 | #include <linux/serial.h> |
| 20 | 18 | #include <linux/serial_core.h> |
| 21 | 19 | #include <linux/serial_reg.h> |
| @@ -32,26 +30,6 @@ enum bcma_boot_dev { · 10 unmodified lines | ||
| 32 | 30 | BCMA_BOOT_DEV_NAND, |
| 33 | 31 | }; |
| 34 | 32 | |
| 35 | −static const char * const part_probes[] = { "bcm47xxpart", NULL }; | |
| 36 | − | |
| 37 | −static struct physmap_flash_data bcma_pflash_data = { | |
| 38 | − .part_probe_types = part_probes, | |
| 39 | −}; | |
| 40 | − | |
| 41 | −static struct resource bcma_pflash_resource = { | |
| 42 | − .name = "bcma_pflash", | |
| 43 | − .flags = IORESOURCE_MEM, | |
| 44 | −}; | |
| 45 | − | |
| 46 | −struct platform_device bcma_pflash_dev = { | |
| 47 | − .name = "physmap-flash", | |
| 48 | − .dev = { | |
| 49 | − .platform_data = &bcma_pflash_data, | |
| 50 | − }, | |
| 51 | − .resource = &bcma_pflash_resource, | |
| 52 | − .num_resources = 1, | |
| 53 | −}; | |
| 54 | − | |
| 55 | 33 | /* The 47162a0 hangs when reading MIPS DMP registers registers */ |
| 56 | 34 | static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) |
| 57 | 35 | { |
| @@ -272,48 +250,11 @@ static enum bcma_boot_dev bcma_boot_dev(struct bcma_bus *bus) · 214 unmodified lines | ||
| 272 | 250 | return BCMA_BOOT_DEV_SERIAL; |
| 273 | 251 | } |
| 274 | 252 | |
| 275 | −static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) | |
| 253 | +static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore) | |
| 276 | 254 | { |
| 277 | 255 | struct bcma_bus *bus = mcore->core->bus; |
| 278 | − struct bcma_drv_cc *cc = &bus->drv_cc; | |
| 279 | − struct bcma_pflash *pflash = &cc->pflash; | |
| 280 | 256 | enum bcma_boot_dev boot_dev; |
| 281 | 257 | |
| 282 | − switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | |
| 283 | − case BCMA_CC_FLASHT_STSER: | |
| 284 | − case BCMA_CC_FLASHT_ATSER: | |
| 285 | − bcma_debug(bus, "Found serial flash\n"); | |
| 286 | − bcma_sflash_init(cc); | |
| 287 | − break; | |
| 288 | − case BCMA_CC_FLASHT_PARA: | |
| 289 | − bcma_debug(bus, "Found parallel flash\n"); | |
| 290 | − pflash->present = true; | |
| 291 | − pflash->window = BCMA_SOC_FLASH2; | |
| 292 | − pflash->window_size = BCMA_SOC_FLASH2_SZ; | |
| 293 | − | |
| 294 | − if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & | |
| 295 | − BCMA_CC_FLASH_CFG_DS) == 0) | |
| 296 | − pflash->buswidth = 1; | |
| 297 | − else | |
| 298 | − pflash->buswidth = 2; | |
| 299 | − | |
| 300 | − bcma_pflash_data.width = pflash->buswidth; | |
| 301 | − bcma_pflash_resource.start = pflash->window; | |
| 302 | − bcma_pflash_resource.end = pflash->window + pflash->window_size; | |
| 303 | − | |
| 304 | − break; | |
| 305 | − default: | |
| 306 | − bcma_err(bus, "Flash type not supported\n"); | |
| 307 | − } | |
| 308 | − | |
| 309 | − if (cc->core->id.rev == 38 || | |
| 310 | − bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | |
| 311 | − if (cc->capabilities & BCMA_CC_CAP_NFLASH) { | |
| 312 | − bcma_debug(bus, "Found NAND flash\n"); | |
| 313 | − bcma_nflash_init(cc); | |
| 314 | − } | |
| 315 | − } | |
| 316 | − | |
| 317 | 258 | /* Determine flash type this SoC boots from */ |
| 318 | 259 | boot_dev = bcma_boot_dev(bus); |
| 319 | 260 | switch (boot_dev) { |
| @@ -337,13 +278,10 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) · 17 unmodified lines | ||
| 337 | 278 | |
| 338 | 279 | void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) |
| 339 | 280 | { |
| 340 | − struct bcma_bus *bus = mcore->core->bus; | |
| 341 | − | |
| 342 | 281 | if (mcore->early_setup_done) |
| 343 | 282 | return; |
| 344 | 283 | |
| 345 | − bcma_chipco_serial_init(&bus->drv_cc); | |
| 346 | − bcma_core_mips_flash_detect(mcore); | |
| 284 | + bcma_core_mips_nvram_init(mcore); | |
| 347 | 285 | |
| 348 | 286 | mcore->early_setup_done = true; |
| 349 | 287 | } |
| @@ -294,7 +294,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { · 293 unmodified lines | ||
| 294 | 294 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, |
| 295 | 295 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, |
| 296 | 296 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) }, |
| 297 | − { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, | |
| 297 | + { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) }, | |
| 298 | 298 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, |
| 299 | 299 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, |
| 300 | 300 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, |
| @@ -350,7 +350,7 @@ static int bcma_register_devices(struct bcma_bus *bus) · 349 unmodified lines | ||
| 350 | 350 | bcma_register_core(bus, core); |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | −#ifdef CONFIG_BCMA_DRIVER_MIPS | |
| 353 | +#ifdef CONFIG_BCMA_PFLASH | |
| 354 | 354 | if (bus->drv_cc.pflash.present) { |
| 355 | 355 | err = platform_device_register(&bcma_pflash_dev); |
| 356 | 356 | if (err) |
| @@ -98,6 +98,9 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { · 97 unmodified lines | ||
| 98 | 98 | { BCMA_CORE_SHIM, "SHIM" }, |
| 99 | 99 | { BCMA_CORE_PCIE2, "PCIe Gen2" }, |
| 100 | 100 | { BCMA_CORE_ARM_CR4, "ARM CR4" }, |
| 101 | + { BCMA_CORE_GCI, "GCI" }, | |
| 102 | + { BCMA_CORE_CMEM, "CNDS DDR2/3 memory controller" }, | |
| 103 | + { BCMA_CORE_ARM_CA7, "ARM CA7" }, | |
| 101 | 104 | { BCMA_CORE_DEFAULT, "Default" }, |
| 102 | 105 | }; |
| 103 | 106 | |
| @@ -315,6 +318,8 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, · 211 unmodified lines | ||
| 315 | 318 | switch (core->id.id) { |
| 316 | 319 | case BCMA_CORE_4706_MAC_GBIT_COMMON: |
| 317 | 320 | case BCMA_CORE_NS_CHIPCOMMON_B: |
| 321 | + case BCMA_CORE_PMU: | |
| 322 | + case BCMA_CORE_GCI: | |
| 318 | 323 | /* Not used yet: case BCMA_CORE_OOB_ROUTER: */ |
| 319 | 324 | break; |
| 320 | 325 | default: |
| @@ -169,6 +169,17 @@ config BT_HCIUART_QCA · 168 unmodified lines | ||
| 169 | 169 | |
| 170 | 170 | Say Y here to compile support for QCA protocol. |
| 171 | 171 | |
| 172 | +config BT_HCIUART_AG6XX | |
| 173 | + bool "Intel AG6XX protocol support" | |
| 174 | + depends on BT_HCIUART | |
| 175 | + select BT_HCIUART_H4 | |
| 176 | + select BT_INTEL | |
| 177 | + help | |
| 178 | + The Intel/AG6XX protocol support enables Bluetooth HCI over serial | |
| 179 | + port interface for Intel ibt 2.1 Bluetooth controllers. | |
| 180 | + | |
| 181 | + Say Y here to compile support for Intel AG6XX protocol. | |
| 182 | + | |
| 172 | 183 | config BT_HCIBCM203X |
| 173 | 184 | tristate "HCI BCM203x USB driver" |
| 174 | 185 | depends on USB |
| @@ -36,6 +36,7 @@ hci_uart-$(CONFIG_BT_HCIUART_3WIRE) += hci_h5.o · 35 unmodified lines | ||
| 36 | 36 | hci_uart-$(CONFIG_BT_HCIUART_INTEL) += hci_intel.o |
| 37 | 37 | hci_uart-$(CONFIG_BT_HCIUART_BCM) += hci_bcm.o |
| 38 | 38 | hci_uart-$(CONFIG_BT_HCIUART_QCA) += hci_qca.o |
| 39 | +hci_uart-$(CONFIG_BT_HCIUART_AG6XX) += hci_ag6xx.o | |
| 39 | 40 | hci_uart-objs := $(hci_uart-y) |
| 40 | 41 | |
| 41 | 42 | ccflags-y += -D__CHECK_ENDIAN__ |
| @@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = { · 81 unmodified lines | ||
| 82 | 82 | { USB_DEVICE(0x0489, 0xe05f) }, |
| 83 | 83 | { USB_DEVICE(0x0489, 0xe076) }, |
| 84 | 84 | { USB_DEVICE(0x0489, 0xe078) }, |
| 85 | + { USB_DEVICE(0x0489, 0xe095) }, | |
| 85 | 86 | { USB_DEVICE(0x04c5, 0x1330) }, |
| 86 | 87 | { USB_DEVICE(0x04CA, 0x3004) }, |
| 87 | 88 | { USB_DEVICE(0x04CA, 0x3005) }, |
| @@ -92,6 +93,7 @@ static const struct usb_device_id ath3k_table[] = { · 4 unmodified lines | ||
| 92 | 93 | { USB_DEVICE(0x04CA, 0x300d) }, |
| 93 | 94 | { USB_DEVICE(0x04CA, 0x300f) }, |
| 94 | 95 | { USB_DEVICE(0x04CA, 0x3010) }, |
| 96 | + { USB_DEVICE(0x04CA, 0x3014) }, | |
| 95 | 97 | { USB_DEVICE(0x0930, 0x0219) }, |
| 96 | 98 | { USB_DEVICE(0x0930, 0x021c) }, |
| 97 | 99 | { USB_DEVICE(0x0930, 0x0220) }, |
| @@ -113,10 +115,12 @@ static const struct usb_device_id ath3k_table[] = { · 15 unmodified lines | ||
| 113 | 115 | { USB_DEVICE(0x13d3, 0x3362) }, |
| 114 | 116 | { USB_DEVICE(0x13d3, 0x3375) }, |
| 115 | 117 | { USB_DEVICE(0x13d3, 0x3393) }, |
| 118 | + { USB_DEVICE(0x13d3, 0x3395) }, | |
| 116 | 119 | { USB_DEVICE(0x13d3, 0x3402) }, |
| 117 | 120 | { USB_DEVICE(0x13d3, 0x3408) }, |
| 118 | 121 | { USB_DEVICE(0x13d3, 0x3423) }, |
| 119 | 122 | { USB_DEVICE(0x13d3, 0x3432) }, |
| 123 | + { USB_DEVICE(0x13d3, 0x3472) }, | |
| 120 | 124 | { USB_DEVICE(0x13d3, 0x3474) }, |
| 121 | 125 | |
| 122 | 126 | /* Atheros AR5BBU12 with sflash firmware */ |
| @@ -144,6 +148,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { · 21 unmodified lines | ||
| 144 | 148 | { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, |
| 145 | 149 | { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, |
| 146 | 150 | { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, |
| 151 | + { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 }, | |
| 147 | 152 | { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, |
| 148 | 153 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, |
| 149 | 154 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
| @@ -154,6 +159,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { · 4 unmodified lines | ||
| 154 | 159 | { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 }, |
| 155 | 160 | { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, |
| 156 | 161 | { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, |
| 162 | + { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, | |
| 157 | 163 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
| 158 | 164 | { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, |
| 159 | 165 | { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, |
| @@ -175,10 +181,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = { · 15 unmodified lines | ||
| 175 | 181 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
| 176 | 182 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
| 177 | 183 | { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, |
| 184 | + { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 }, | |
| 178 | 185 | { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, |
| 179 | 186 | { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, |
| 180 | 187 | { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, |
| 181 | 188 | { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, |
| 189 | + { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, | |
| 182 | 190 | { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, |
| 183 | 191 | |
| 184 | 192 | /* Atheros AR5BBU22 with sflash firmware */ |
| @@ -497,6 +505,7 @@ static int ath3k_probe(struct usb_interface *intf, · 312 unmodified lines | ||
| 497 | 505 | /* match device ID in ath3k blacklist table */ |
| 498 | 506 | if (!id->driver_info) { |
| 499 | 507 | const struct usb_device_id *match; |
| 508 | + | |
| 500 | 509 | match = usb_match_id(intf, ath3k_blist_tbl); |
| 501 | 510 | if (match) |
| 502 | 511 | id = match; |
| @@ -467,7 +467,7 @@ int btbcm_setup_patchram(struct hci_dev *hdev) · 466 unmodified lines | ||
| 467 | 467 | err = request_firmware(&fw, fw_name, &hdev->dev); |
| 468 | 468 | if (err < 0) { |
| 469 | 469 | BT_INFO("%s: BCM: Patch %s not found", hdev->name, fw_name); |
| 470 | − return 0; | |
| 470 | + goto done; | |
| 471 | 471 | } |
| 472 | 472 | |
| 473 | 473 | btbcm_patchram(hdev, fw); |
| @@ -501,6 +501,7 @@ int btbcm_setup_patchram(struct hci_dev *hdev) · 27 unmodified lines | ||
| 501 | 501 | BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); |
| 502 | 502 | kfree_skb(skb); |
| 503 | 503 | |
| 504 | +done: | |
| 504 | 505 | btbcm_check_bdaddr(hdev); |
| 505 | 506 | |
| 506 | 507 | set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); |
| @@ -371,7 +371,7 @@ static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card, · 370 unmodified lines | ||
| 371 | 371 | if (firmwarestat == FIRMWARE_READY) |
| 372 | 372 | return 0; |
| 373 | 373 | |
| 374 | − msleep(10); | |
| 374 | + msleep(100); | |
| 375 | 375 | } |
| 376 | 376 | |
| 377 | 377 | return -ETIMEDOUT; |
| @@ -196,6 +196,7 @@ static const struct usb_device_id blacklist_table[] = { · 195 unmodified lines | ||
| 196 | 196 | { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, |
| 197 | 197 | { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, |
| 198 | 198 | { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, |
| 199 | + { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 }, | |
| 199 | 200 | { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, |
| 200 | 201 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, |
| 201 | 202 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
| @@ -206,6 +207,7 @@ static const struct usb_device_id blacklist_table[] = { · 4 unmodified lines | ||
| 206 | 207 | { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 }, |
| 207 | 208 | { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, |
| 208 | 209 | { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, |
| 210 | + { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, | |
| 209 | 211 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
| 210 | 212 | { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, |
| 211 | 213 | { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, |
| @@ -227,10 +229,12 @@ static const struct usb_device_id blacklist_table[] = { · 15 unmodified lines | ||
| 227 | 229 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
| 228 | 230 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
| 229 | 231 | { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, |
| 232 | + { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 }, | |
| 230 | 233 | { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, |
| 231 | 234 | { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, |
| 232 | 235 | { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, |
| 233 | 236 | { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, |
| 237 | + { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, | |
| 234 | 238 | { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, |
| 235 | 239 | |
| 236 | 240 | /* Atheros AR5BBU12 with sflash firmware */ |
| @@ -0,0 +1,337 @@ | ||
| 1 | +/* | |
| 2 | + * | |
| 3 | + * Bluetooth HCI UART driver for Intel/AG6xx devices | |
| 4 | + * | |
| 5 | + * Copyright (C) 2016 Intel Corporation | |
| 6 | + * | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + * | |
| 18 | + * You should have received a copy of the GNU General Public License | |
| 19 | + * along with this program; if not, write to the Free Software | |
| 20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 | + * | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#include <linux/kernel.h> | |
| 25 | +#include <linux/errno.h> | |
| 26 | +#include <linux/skbuff.h> | |
| 27 | +#include <linux/firmware.h> | |
| 28 | +#include <linux/module.h> | |
| 29 | +#include <linux/tty.h> | |
| 30 | + | |
| 31 | +#include <net/bluetooth/bluetooth.h> | |
| 32 | +#include <net/bluetooth/hci_core.h> | |
| 33 | + | |
| 34 | +#include "hci_uart.h" | |
| 35 | +#include "btintel.h" | |
| 36 | + | |
| 37 | +struct ag6xx_data { | |
| 38 | + struct sk_buff *rx_skb; | |
| 39 | + struct sk_buff_head txq; | |
| 40 | +}; | |
| 41 | + | |
| 42 | +struct pbn_entry { | |
| 43 | + __le32 addr; | |
| 44 | + __le32 plen; | |
| 45 | + __u8 data[0]; | |
| 46 | +} __packed; | |
| 47 | + | |
| 48 | +static int ag6xx_open(struct hci_uart *hu) | |
| 49 | +{ | |
| 50 | + struct ag6xx_data *ag6xx; | |
| 51 | + | |
| 52 | + BT_DBG("hu %p", hu); | |
| 53 | + | |
| 54 | + ag6xx = kzalloc(sizeof(*ag6xx), GFP_KERNEL); | |
| 55 | + if (!ag6xx) | |
| 56 | + return -ENOMEM; | |
| 57 | + | |
| 58 | + skb_queue_head_init(&ag6xx->txq); | |
| 59 | + | |
| 60 | + hu->priv = ag6xx; | |
| 61 | + return 0; | |
| 62 | +} | |
| 63 | + | |
| 64 | +static int ag6xx_close(struct hci_uart *hu) | |
| 65 | +{ | |
| 66 | + struct ag6xx_data *ag6xx = hu->priv; | |
| 67 | + | |
| 68 | + BT_DBG("hu %p", hu); | |
| 69 | + | |
| 70 | + skb_queue_purge(&ag6xx->txq); | |
| 71 | + kfree_skb(ag6xx->rx_skb); | |
| 72 | + kfree(ag6xx); | |
| 73 | + | |
| 74 | + hu->priv = NULL; | |
| 75 | + return 0; | |
| 76 | +} | |
| 77 | + | |
| 78 | +static int ag6xx_flush(struct hci_uart *hu) | |
| 79 | +{ | |
| 80 | + struct ag6xx_data *ag6xx = hu->priv; | |
| 81 | + | |
| 82 | + BT_DBG("hu %p", hu); | |
| 83 | + | |
| 84 | + skb_queue_purge(&ag6xx->txq); | |
| 85 | + return 0; | |
| 86 | +} | |
| 87 | + | |
| 88 | +static struct sk_buff *ag6xx_dequeue(struct hci_uart *hu) | |
| 89 | +{ | |
| 90 | + struct ag6xx_data *ag6xx = hu->priv; | |
| 91 | + struct sk_buff *skb; | |
| 92 | + | |
| 93 | + skb = skb_dequeue(&ag6xx->txq); | |
| 94 | + if (!skb) | |
| 95 | + return skb; | |
| 96 | + | |
| 97 | + /* Prepend skb with frame type */ | |
| 98 | + memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); | |
| 99 | + return skb; | |
| 100 | +} | |
| 101 | + | |
| 102 | +static int ag6xx_enqueue(struct hci_uart *hu, struct sk_buff *skb) | |
| 103 | +{ | |
| 104 | + struct ag6xx_data *ag6xx = hu->priv; | |
| 105 | + | |
| 106 | + skb_queue_tail(&ag6xx->txq, skb); | |
| 107 | + return 0; | |
| 108 | +} | |
| 109 | + | |
| 110 | +static const struct h4_recv_pkt ag6xx_recv_pkts[] = { | |
| 111 | + { H4_RECV_ACL, .recv = hci_recv_frame }, | |
| 112 | + { H4_RECV_SCO, .recv = hci_recv_frame }, | |
| 113 | + { H4_RECV_EVENT, .recv = hci_recv_frame }, | |
| 114 | +}; | |
| 115 | + | |
| 116 | +static int ag6xx_recv(struct hci_uart *hu, const void *data, int count) | |
| 117 | +{ | |
| 118 | + struct ag6xx_data *ag6xx = hu->priv; | |
| 119 | + | |
| 120 | + if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) | |
| 121 | + return -EUNATCH; | |
| 122 | + | |
| 123 | + ag6xx->rx_skb = h4_recv_buf(hu->hdev, ag6xx->rx_skb, data, count, | |
| 124 | + ag6xx_recv_pkts, | |
| 125 | + ARRAY_SIZE(ag6xx_recv_pkts)); | |
| 126 | + if (IS_ERR(ag6xx->rx_skb)) { | |
| 127 | + int err = PTR_ERR(ag6xx->rx_skb); | |
| 128 | + bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err); | |
| 129 | + ag6xx->rx_skb = NULL; | |
| 130 | + return err; | |
| 131 | + } | |
| 132 | + | |
| 133 | + return count; | |
| 134 | +} | |
| 135 | + | |
| 136 | +static int intel_mem_write(struct hci_dev *hdev, u32 addr, u32 plen, | |
| 137 | + const void *data) | |
| 138 | +{ | |
| 139 | + /* Can write a maximum of 247 bytes per HCI command. | |
| 140 | + * HCI cmd Header (3), Intel mem write header (6), data (247). | |
| 141 | + */ | |
| 142 | + while (plen > 0) { | |
| 143 | + struct sk_buff *skb; | |
| 144 | + u8 cmd_param[253], fragment_len = (plen > 247) ? 247 : plen; | |
| 145 | + __le32 leaddr = cpu_to_le32(addr); | |
| 146 | + | |
| 147 | + memcpy(cmd_param, &leaddr, 4); | |
| 148 | + cmd_param[4] = 0; | |
| 149 | + cmd_param[5] = fragment_len; | |
| 150 | + memcpy(cmd_param + 6, data, fragment_len); | |
| 151 | + | |
| 152 | + skb = __hci_cmd_sync(hdev, 0xfc8e, fragment_len + 6, cmd_param, | |
| 153 | + HCI_INIT_TIMEOUT); | |
| 154 | + if (IS_ERR(skb)) | |
| 155 | + return PTR_ERR(skb); | |
| 156 | + kfree_skb(skb); | |
| 157 | + | |
| 158 | + plen -= fragment_len; | |
| 159 | + data += fragment_len; | |
| 160 | + addr += fragment_len; | |
| 161 | + } | |
| 162 | + | |
| 163 | + return 0; | |
| 164 | +} | |
| 165 | + | |
| 166 | +static int ag6xx_setup(struct hci_uart *hu) | |
| 167 | +{ | |
| 168 | + struct hci_dev *hdev = hu->hdev; | |
| 169 | + struct sk_buff *skb; | |
| 170 | + struct intel_version ver; | |
| 171 | + const struct firmware *fw; | |
| 172 | + const u8 *fw_ptr; | |
| 173 | + char fwname[64]; | |
| 174 | + bool patched = false; | |
| 175 | + int err; | |
| 176 | + | |
| 177 | + hu->hdev->set_diag = btintel_set_diag; | |
| 178 | + hu->hdev->set_bdaddr = btintel_set_bdaddr; | |
| 179 | + | |
| 180 | + err = btintel_enter_mfg(hdev); | |
| 181 | + if (err) | |
| 182 | + return err; | |
| 183 | + | |
| 184 | + err = btintel_read_version(hdev, &ver); | |
| 185 | + if (err) | |
| 186 | + return err; | |
| 187 | + | |
| 188 | + btintel_version_info(hdev, &ver); | |
| 189 | + | |
| 190 | + /* The hardware platform number has a fixed value of 0x37 and | |
| 191 | + * for now only accept this single value. | |
| 192 | + */ | |
| 193 | + if (ver.hw_platform != 0x37) { | |
| 194 | + bt_dev_err(hdev, "Unsupported Intel hardware platform: 0x%X", | |
| 195 | + ver.hw_platform); | |
| 196 | + return -EINVAL; | |
| 197 | + } | |
| 198 | + | |
| 199 | + /* Only the hardware variant iBT 2.1 (AG6XX) is supported by this | |
| 200 | + * firmware setup method. | |
| 201 | + */ | |
| 202 | + if (ver.hw_variant != 0x0a) { | |
| 203 | + bt_dev_err(hdev, "Unsupported Intel hardware variant: 0x%x", | |
| 204 | + ver.hw_variant); | |
| 205 | + return -EINVAL; | |
| 206 | + } | |
| 207 | + | |
| 208 | + snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bddata", | |
| 209 | + ver.hw_platform, ver.hw_variant); | |
| 210 | + | |
| 211 | + err = request_firmware(&fw, fwname, &hdev->dev); | |
| 212 | + if (err < 0) { | |
| 213 | + bt_dev_err(hdev, "Failed to open Intel bddata file: %s (%d)", | |
| 214 | + fwname, err); | |
| 215 | + goto patch; | |
| 216 | + } | |
| 217 | + fw_ptr = fw->data; | |
| 218 | + | |
| 219 | + bt_dev_info(hdev, "Applying bddata (%s)", fwname); | |
| 220 | + | |
| 221 | + skb = __hci_cmd_sync_ev(hdev, 0xfc2f, fw->size, fw->data, | |
| 222 | + HCI_EV_CMD_STATUS, HCI_CMD_TIMEOUT); | |
| 223 | + if (IS_ERR(skb)) { | |
| 224 | + bt_dev_err(hdev, "Applying bddata failed (%ld)", PTR_ERR(skb)); | |
| 225 | + release_firmware(fw); | |
| 226 | + return PTR_ERR(skb); | |
| 227 | + } | |
| 228 | + kfree_skb(skb); | |
| 229 | + | |
| 230 | + release_firmware(fw); | |
| 231 | + | |
| 232 | +patch: | |
| 233 | + /* If there is no applied patch, fw_patch_num is always 0x00. In other | |
| 234 | + * cases, current firmware is already patched. No need to patch it. | |
| 235 | + */ | |
| 236 | + if (ver.fw_patch_num) { | |
| 237 | + bt_dev_info(hdev, "Device is already patched. patch num: %02x", | |
| 238 | + ver.fw_patch_num); | |
| 239 | + patched = true; | |
| 240 | + goto complete; | |
| 241 | + } | |
| 242 | + | |
| 243 | + snprintf(fwname, sizeof(fwname), | |
| 244 | + "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.pbn", | |
| 245 | + ver.hw_platform, ver.hw_variant, ver.hw_revision, | |
| 246 | + ver.fw_variant, ver.fw_revision, ver.fw_build_num, | |
| 247 | + ver.fw_build_ww, ver.fw_build_yy); | |
| 248 | + | |
| 249 | + err = request_firmware(&fw, fwname, &hdev->dev); | |
| 250 | + if (err < 0) { | |
| 251 | + bt_dev_err(hdev, "Failed to open Intel patch file: %s(%d)", | |
| 252 | + fwname, err); | |
| 253 | + goto complete; | |
| 254 | + } | |
| 255 | + fw_ptr = fw->data; | |
| 256 | + | |
| 257 | + bt_dev_info(hdev, "Patching firmware file (%s)", fwname); | |
| 258 | + | |
| 259 | + /* PBN patch file contains a list of binary patches to be applied on top | |
| 260 | + * of the embedded firmware. Each patch entry header contains the target | |
| 261 | + * address and patch size. | |
| 262 | + * | |
| 263 | + * Patch entry: | |
| 264 | + * | addr(le) | patch_len(le) | patch_data | | |
| 265 | + * | 4 Bytes | 4 Bytes | n Bytes | | |
| 266 | + * | |
| 267 | + * PBN file is terminated by a patch entry whose address is 0xffffffff. | |
| 268 | + */ | |
| 269 | + while (fw->size > fw_ptr - fw->data) { | |
| 270 | + struct pbn_entry *pbn = (void *)fw_ptr; | |
| 271 | + u32 addr, plen; | |
| 272 | + | |
| 273 | + if (pbn->addr == 0xffffffff) { | |
| 274 | + bt_dev_info(hdev, "Patching complete"); | |
| 275 | + patched = true; | |
| 276 | + break; | |
| 277 | + } | |
| 278 | + | |
| 279 | + addr = le32_to_cpu(pbn->addr); | |
| 280 | + plen = le32_to_cpu(pbn->plen); | |
| 281 | + | |
| 282 | + if (fw->data + fw->size <= pbn->data + plen) { | |
| 283 | + bt_dev_info(hdev, "Invalid patch len (%d)", plen); | |
| 284 | + break; | |
| 285 | + } | |
| 286 | + | |
| 287 | + bt_dev_info(hdev, "Patching %td/%zu", (fw_ptr - fw->data), | |
| 288 | + fw->size); | |
| 289 | + | |
| 290 | + err = intel_mem_write(hdev, addr, plen, pbn->data); | |
| 291 | + if (err) { | |
| 292 | + bt_dev_err(hdev, "Patching failed"); | |
| 293 | + break; | |
| 294 | + } | |
| 295 | + | |
| 296 | + fw_ptr = pbn->data + plen; | |
| 297 | + } | |
| 298 | + | |
| 299 | + release_firmware(fw); | |
| 300 | + | |
| 301 | +complete: | |
| 302 | + /* Exit manufacturing mode and reset */ | |
| 303 | + err = btintel_exit_mfg(hdev, true, patched); | |
| 304 | + if (err) | |
| 305 | + return err; | |
| 306 | + | |
| 307 | + /* Set the event mask for Intel specific vendor events. This enables | |
| 308 | + * a few extra events that are useful during general operation. | |
| 309 | + */ | |
| 310 | + btintel_set_event_mask_mfg(hdev, false); | |
| 311 | + | |
| 312 | + btintel_check_bdaddr(hdev); | |
| 313 | + return 0; | |
| 314 | +} | |
| 315 | + | |
| 316 | +static const struct hci_uart_proto ag6xx_proto = { | |
| 317 | + .id = HCI_UART_AG6XX, | |
| 318 | + .name = "AG6XX", | |
| 319 | + .manufacturer = 2, | |
| 320 | + .open = ag6xx_open, | |
| 321 | + .close = ag6xx_close, | |
| 322 | + .flush = ag6xx_flush, | |
| 323 | + .setup = ag6xx_setup, | |
| 324 | + .recv = ag6xx_recv, | |
| 325 | + .enqueue = ag6xx_enqueue, | |
| 326 | + .dequeue = ag6xx_dequeue, | |
| 327 | +}; | |
| 328 | + | |
| 329 | +int __init ag6xx_init(void) | |
| 330 | +{ | |
| 331 | + return hci_uart_register_proto(&ag6xx_proto); | |
| 332 | +} | |
| 333 | + | |
| 334 | +int __exit ag6xx_deinit(void) | |
| 335 | +{ | |
| 336 | + return hci_uart_unregister_proto(&ag6xx_proto); | |
| 337 | +} | |
| @@ -820,10 +820,13 @@ static const struct acpi_device_id bcm_acpi_match[] = { · 819 unmodified lines | ||
| 820 | 820 | { "BCM2E3D", 0 }, |
| 821 | 821 | { "BCM2E3F", 0 }, |
| 822 | 822 | { "BCM2E40", 0 }, |
| 823 | + { "BCM2E54", 0 }, | |
| 824 | + { "BCM2E55", 0 }, | |
| 823 | 825 | { "BCM2E64", 0 }, |
| 824 | 826 | { "BCM2E65", 0 }, |
| 825 | 827 | { "BCM2E67", 0 }, |
| 826 | 828 | { "BCM2E7B", 0 }, |
| 829 | + { "BCM2E7C", 0 }, | |
| 827 | 830 | { }, |
| 828 | 831 | }; |
| 829 | 832 | MODULE_DEVICE_TABLE(acpi, bcm_acpi_match); |
| @@ -488,7 +488,7 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed) · 487 unmodified lines | ||
| 488 | 488 | clear_bit(STATE_BOOTING, &intel->flags); |
| 489 | 489 | |
| 490 | 490 | /* In case of timeout, try to continue anyway */ |
| 491 | − if (err && err != ETIMEDOUT) | |
| 491 | + if (err && err != -ETIMEDOUT) | |
| 492 | 492 | return err; |
| 493 | 493 | |
| 494 | 494 | bt_dev_info(hdev, "Change controller speed to %d", speed); |
| @@ -581,7 +581,7 @@ static int intel_setup(struct hci_uart *hu) · 86 unmodified lines | ||
| 581 | 581 | clear_bit(STATE_BOOTING, &intel->flags); |
| 582 | 582 | |
| 583 | 583 | /* In case of timeout, try to continue anyway */ |
| 584 | − if (err && err != ETIMEDOUT) | |
| 584 | + if (err && err != -ETIMEDOUT) | |
| 585 | 585 | return err; |
| 586 | 586 | |
| 587 | 587 | set_bit(STATE_BOOTLOADER, &intel->flags); |
| @@ -804,6 +804,9 @@ static int __init hci_uart_init(void) · 803 unmodified lines | ||
| 804 | 804 | #ifdef CONFIG_BT_HCIUART_QCA |
| 805 | 805 | qca_init(); |
| 806 | 806 | #endif |
| 807 | +#ifdef CONFIG_BT_HCIUART_AG6XX | |
| 808 | + ag6xx_init(); | |
| 809 | +#endif | |
| 807 | 810 | |
| 808 | 811 | return 0; |
| 809 | 812 | } |
| @@ -836,6 +839,9 @@ static void __exit hci_uart_exit(void) · 26 unmodified lines | ||
| 836 | 839 | #ifdef CONFIG_BT_HCIUART_QCA |
| 837 | 840 | qca_deinit(); |
| 838 | 841 | #endif |
| 842 | +#ifdef CONFIG_BT_HCIUART_AG6XX | |
| 843 | + ag6xx_deinit(); | |
| 844 | +#endif | |
| 839 | 845 | |
| 840 | 846 | /* Release tty registration of line discipline */ |
| 841 | 847 | err = tty_unregister_ldisc(N_HCI); |
| @@ -35,7 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #define HCIUARTGETFLAGS _IOR('U', 204, int) |
| 36 | 36 | |
| 37 | 37 | /* UART protocols */ |
| 38 | −#define HCI_UART_MAX_PROTO 9 | |
| 38 | +#define HCI_UART_MAX_PROTO 10 | |
| 39 | 39 | |
| 40 | 40 | #define HCI_UART_H4 0 |
| 41 | 41 | #define HCI_UART_BCSP 1 |
| @@ -46,6 +46,7 @@ · 4 unmodified lines | ||
| 46 | 46 | #define HCI_UART_INTEL 6 |
| 47 | 47 | #define HCI_UART_BCM 7 |
| 48 | 48 | #define HCI_UART_QCA 8 |
| 49 | +#define HCI_UART_AG6XX 9 | |
| 49 | 50 | |
| 50 | 51 | #define HCI_UART_RAW_DEVICE 0 |
| 51 | 52 | #define HCI_UART_RESET_ON_INIT 1 |
| @@ -182,3 +183,8 @@ int bcm_deinit(void); · 130 unmodified lines | ||
| 182 | 183 | int qca_init(void); |
| 183 | 184 | int qca_deinit(void); |
| 184 | 185 | #endif |
| 186 | + | |
| 187 | +#ifdef CONFIG_BT_HCIUART_AG6XX | |
| 188 | +int ag6xx_init(void); | |
| 189 | +int ag6xx_deinit(void); | |
| 190 | +#endif | |
| @@ -948,6 +948,58 @@ void mvebu_mbus_get_pcie_io_aperture(struct resource *res) · 947 unmodified lines | ||
| 948 | 948 | *res = mbus_state.pcie_io_aperture; |
| 949 | 949 | } |
| 950 | 950 | |
| 951 | +int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 *target, u8 *attr) | |
| 952 | +{ | |
| 953 | + const struct mbus_dram_target_info *dram; | |
| 954 | + int i; | |
| 955 | + | |
| 956 | + /* Get dram info */ | |
| 957 | + dram = mv_mbus_dram_info(); | |
| 958 | + if (!dram) { | |
| 959 | + pr_err("missing DRAM information\n"); | |
| 960 | + return -ENODEV; | |
| 961 | + } | |
| 962 | + | |
| 963 | + /* Try to find matching DRAM window for phyaddr */ | |
| 964 | + for (i = 0; i < dram->num_cs; i++) { | |
| 965 | + const struct mbus_dram_window *cs = dram->cs + i; | |
| 966 | + | |
| 967 | + if (cs->base <= phyaddr && | |
| 968 | + phyaddr <= (cs->base + cs->size - 1)) { | |
| 969 | + *target = dram->mbus_dram_target_id; | |
| 970 | + *attr = cs->mbus_attr; | |
| 971 | + return 0; | |
| 972 | + } | |
| 973 | + } | |
| 974 | + | |
| 975 | + pr_err("invalid dram address 0x%x\n", phyaddr); | |
| 976 | + return -EINVAL; | |
| 977 | +} | |
| 978 | +EXPORT_SYMBOL_GPL(mvebu_mbus_get_dram_win_info); | |
| 979 | + | |
| 980 | +int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target, | |
| 981 | + u8 *attr) | |
| 982 | +{ | |
| 983 | + int win; | |
| 984 | + | |
| 985 | + for (win = 0; win < mbus_state.soc->num_wins; win++) { | |
| 986 | + u64 wbase; | |
| 987 | + int enabled; | |
| 988 | + | |
| 989 | + mvebu_mbus_read_window(&mbus_state, win, &enabled, &wbase, | |
| 990 | + size, target, attr, NULL); | |
| 991 | + | |
| 992 | + if (!enabled) | |
| 993 | + continue; | |
| 994 | + | |
| 995 | + if (wbase <= phyaddr && phyaddr <= wbase + *size) | |
| 996 | + return win; | |
| 997 | + } | |
| 998 | + | |
| 999 | + return -EINVAL; | |
| 1000 | +} | |
| 1001 | +EXPORT_SYMBOL_GPL(mvebu_mbus_get_io_win_info); | |
| 1002 | + | |
| 951 | 1003 | static __init int mvebu_mbus_debugfs_init(void) |
| 952 | 1004 | { |
| 953 | 1005 | struct mvebu_mbus_state *s = &mbus_state; |
| @@ -343,7 +343,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { · 342 unmodified lines | ||
| 343 | 343 | RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, |
| 344 | 344 | RK2928_CLKGATE_CON(10), 5, GFLAGS), |
| 345 | 345 | |
| 346 | − COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0, | |
| 346 | + COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_3plls_p, CLK_SET_RATE_NO_REPARENT, | |
| 347 | 347 | RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS), |
| 348 | 348 | MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT, |
| 349 | 349 | RK2928_CLKSEL_CON(21), 3, 1, MFLAGS), |
| @@ -404,7 +404,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { · 54 unmodified lines | ||
| 404 | 404 | GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS), |
| 405 | 405 | GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), |
| 406 | 406 | GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), |
| 407 | − GATE(0, "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS), | |
| 407 | + GATE(HCLK_MAC, "hclk_mac", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), | |
| 408 | 408 | |
| 409 | 409 | /* pclk_peri gates */ |
| 410 | 410 | GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS), |
| @@ -25,6 +25,8 @@ · 24 unmodified lines | ||
| 25 | 25 | * |
| 26 | 26 | **************************************************************************/ |
| 27 | 27 | |
| 28 | +#include <linux/kernel.h> | |
| 29 | + | |
| 28 | 30 | #ifdef __KERNEL__ |
| 29 | 31 | |
| 30 | 32 | #include <drm/vmwgfx_drm.h> |
| @@ -36,7 +38,6 @@ · 5 unmodified lines | ||
| 36 | 38 | #define ARRAY_SIZE(_A) (sizeof(_A) / sizeof((_A)[0])) |
| 37 | 39 | #endif /* ARRAY_SIZE */ |
| 38 | 40 | |
| 39 | −#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) | |
| 40 | 41 | #define max_t(type, x, y) ((x) > (y) ? (x) : (y)) |
| 41 | 42 | #define surf_size_struct SVGA3dSize |
| 42 | 43 | #define u32 uint32 |
| @@ -987,12 +988,12 @@ svga3dsurface_get_size_in_blocks(const struct svga3d_surface_desc *desc, · 944 unmodified lines | ||
| 987 | 988 | const surf_size_struct *pixel_size, |
| 988 | 989 | surf_size_struct *block_size) |
| 989 | 990 | { |
| 990 | − block_size->width = DIV_ROUND_UP(pixel_size->width, | |
| 991 | − desc->block_size.width); | |
| 992 | − block_size->height = DIV_ROUND_UP(pixel_size->height, | |
| 993 | − desc->block_size.height); | |
| 994 | − block_size->depth = DIV_ROUND_UP(pixel_size->depth, | |
| 995 | − desc->block_size.depth); | |
| 991 | + block_size->width = __KERNEL_DIV_ROUND_UP(pixel_size->width, | |
| 992 | + desc->block_size.width); | |
| 993 | + block_size->height = __KERNEL_DIV_ROUND_UP(pixel_size->height, | |
| 994 | + desc->block_size.height); | |
| 995 | + block_size->depth = __KERNEL_DIV_ROUND_UP(pixel_size->depth, | |
| 996 | + desc->block_size.depth); | |
| 996 | 997 | } |
| 997 | 998 | |
| 998 | 999 | static inline bool |
| @@ -1100,8 +1101,9 @@ svga3dsurface_get_pixel_offset(SVGA3dSurfaceFormat format, · 101 unmodified lines | ||
| 1100 | 1101 | const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format); |
| 1101 | 1102 | const u32 bw = desc->block_size.width, bh = desc->block_size.height; |
| 1102 | 1103 | const u32 bd = desc->block_size.depth; |
| 1103 | − const u32 rowstride = DIV_ROUND_UP(width, bw) * desc->bytes_per_block; | |
| 1104 | − const u32 imgstride = DIV_ROUND_UP(height, bh) * rowstride; | |
| 1104 | + const u32 rowstride = __KERNEL_DIV_ROUND_UP(width, bw) * | |
| 1105 | + desc->bytes_per_block; | |
| 1106 | + const u32 imgstride = __KERNEL_DIV_ROUND_UP(height, bh) * rowstride; | |
| 1105 | 1107 | const u32 offset = (z / bd * imgstride + |
| 1106 | 1108 | y / bh * rowstride + |
| 1107 | 1109 | x / bw * desc->bytes_per_block); |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | config MLX4_INFINIBAND |
| 2 | 2 | tristate "Mellanox ConnectX HCA support" |
| 3 | 3 | depends on NETDEVICES && ETHERNET && PCI && INET |
| 4 | + depends on MAY_USE_DEVLINK | |
| 4 | 5 | select NET_VENDOR_MELLANOX |
| 5 | 6 | select MLX4_CORE |
| 6 | 7 | ---help--- |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <linux/if_vlan.h> |
| 42 | 42 | #include <net/ipv6.h> |
| 43 | 43 | #include <net/addrconf.h> |
| 44 | +#include <net/devlink.h> | |
| 44 | 45 | |
| 45 | 46 | #include <rdma/ib_smi.h> |
| 46 | 47 | #include <rdma/ib_user_verbs.h> |
| @@ -2585,6 +2586,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) · 2538 unmodified lines | ||
| 2585 | 2586 | } |
| 2586 | 2587 | |
| 2587 | 2588 | ibdev->ib_active = true; |
| 2589 | + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | |
| 2590 | + devlink_port_type_ib_set(mlx4_get_devlink_port(dev, i), | |
| 2591 | + &ibdev->ib_dev); | |
| 2588 | 2592 | |
| 2589 | 2593 | if (mlx4_is_mfunc(ibdev->dev)) |
| 2590 | 2594 | init_pkeys(ibdev); |
| @@ -2709,7 +2713,10 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) · 118 unmodified lines | ||
| 2709 | 2713 | { |
| 2710 | 2714 | struct mlx4_ib_dev *ibdev = ibdev_ptr; |
| 2711 | 2715 | int p; |
| 2716 | + int i; | |
| 2712 | 2717 | |
| 2718 | + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | |
| 2719 | + devlink_port_type_clear(mlx4_get_devlink_port(dev, i)); | |
| 2713 | 2720 | ibdev->ib_active = false; |
| 2714 | 2721 | flush_workqueue(wq); |
| 2715 | 2722 | |
| @@ -42,6 +42,7 @@ · 41 unmodified lines | ||
| 42 | 42 | #include <rdma/ib_user_verbs.h> |
| 43 | 43 | #include <rdma/ib_addr.h> |
| 44 | 44 | #include <rdma/ib_cache.h> |
| 45 | +#include <linux/mlx5/port.h> | |
| 45 | 46 | #include <linux/mlx5/vport.h> |
| 46 | 47 | #include <rdma/ib_smi.h> |
| 47 | 48 | #include <rdma/ib_umem.h> |
| @@ -269,7 +269,6 @@ int usnic_ib_query_device(struct ib_device *ibdev, · 268 unmodified lines | ||
| 269 | 269 | struct usnic_ib_dev *us_ibdev = to_usdev(ibdev); |
| 270 | 270 | union ib_gid gid; |
| 271 | 271 | struct ethtool_drvinfo info; |
| 272 | − struct ethtool_cmd cmd; | |
| 273 | 272 | int qp_per_vf; |
| 274 | 273 | |
| 275 | 274 | usnic_dbg("\n"); |
| @@ -278,7 +277,6 @@ int usnic_ib_query_device(struct ib_device *ibdev, · 2 unmodified lines | ||
| 278 | 277 | |
| 279 | 278 | mutex_lock(&us_ibdev->usdev_lock); |
| 280 | 279 | us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info); |
| 281 | − us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd); | |
| 282 | 280 | memset(props, 0, sizeof(*props)); |
| 283 | 281 | usnic_mac_ip_to_gid(us_ibdev->ufdev->mac, us_ibdev->ufdev->inaddr, |
| 284 | 282 | &gid.raw[0]); |
| @@ -326,12 +324,12 @@ int usnic_ib_query_port(struct ib_device *ibdev, u8 port, · 41 unmodified lines | ||
| 326 | 324 | struct ib_port_attr *props) |
| 327 | 325 | { |
| 328 | 326 | struct usnic_ib_dev *us_ibdev = to_usdev(ibdev); |
| 329 | − struct ethtool_cmd cmd; | |
| 327 | + struct ethtool_link_ksettings cmd; | |
| 330 | 328 | |
| 331 | 329 | usnic_dbg("\n"); |
| 332 | 330 | |
| 333 | 331 | mutex_lock(&us_ibdev->usdev_lock); |
| 334 | − us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd); | |
| 332 | + __ethtool_get_link_ksettings(us_ibdev->netdev, &cmd); | |
| 335 | 333 | memset(props, 0, sizeof(*props)); |
| 336 | 334 | |
| 337 | 335 | props->lid = 0; |
| @@ -355,8 +353,8 @@ int usnic_ib_query_port(struct ib_device *ibdev, u8 port, · 17 unmodified lines | ||
| 355 | 353 | props->pkey_tbl_len = 1; |
| 356 | 354 | props->bad_pkey_cntr = 0; |
| 357 | 355 | props->qkey_viol_cntr = 0; |
| 358 | − eth_speed_to_ib_speed(cmd.speed, &props->active_speed, | |
| 359 | − &props->active_width); | |
| 356 | + eth_speed_to_ib_speed(cmd.base.speed, &props->active_speed, | |
| 357 | + &props->active_width); | |
| 360 | 358 | props->max_mtu = IB_MTU_4096; |
| 361 | 359 | props->active_mtu = iboe_get_mtu(us_ibdev->ufdev->mtu); |
| 362 | 360 | /* Userspace will adjust for hdrs */ |
| @@ -192,8 +192,6 @@ static diva_os_spin_lock_t dbg_q_lock; · 191 unmodified lines | ||
| 192 | 192 | static diva_os_spin_lock_t dbg_adapter_lock; |
| 193 | 193 | static int dbg_q_busy; |
| 194 | 194 | static volatile dword dbg_sequence; |
| 195 | −static dword start_sec; | |
| 196 | −static dword start_usec; | |
| 197 | 195 | |
| 198 | 196 | /* |
| 199 | 197 | INTERFACE: |
| @@ -215,8 +213,6 @@ int diva_maint_init(byte *base, unsigned long length, int do_init) { · 15 unmodified lines | ||
| 215 | 213 | |
| 216 | 214 | dbg_base = base; |
| 217 | 215 | |
| 218 | − diva_os_get_time(&start_sec, &start_usec); | |
| 219 | − | |
| 220 | 216 | *(dword *)base = (dword)DBG_MAGIC; /* Store Magic */ |
| 221 | 217 | base += sizeof(dword); |
| 222 | 218 | length -= sizeof(dword); |
| @@ -45,7 +45,6 @@ char *DRIVERRELEASE_MNT = "2.0"; · 44 unmodified lines | ||
| 45 | 45 | |
| 46 | 46 | static wait_queue_head_t msgwaitq; |
| 47 | 47 | static unsigned long opened; |
| 48 | −static struct timeval start_time; | |
| 49 | 48 | |
| 50 | 49 | extern int mntfunc_init(int *, void **, unsigned long); |
| 51 | 50 | extern void mntfunc_finit(void); |
| @@ -88,28 +87,12 @@ int diva_os_copy_from_user(void *os_handle, void *dst, const void __user *src, · 36 unmodified lines | ||
| 88 | 87 | */ |
| 89 | 88 | void diva_os_get_time(dword *sec, dword *usec) |
| 90 | 89 | { |
| 91 | − struct timeval tv; | |
| 92 | − | |
| 93 | − do_gettimeofday(&tv); | |
| 94 | − | |
| 95 | − if (tv.tv_sec > start_time.tv_sec) { | |
| 96 | − if (start_time.tv_usec > tv.tv_usec) { | |
| 97 | − tv.tv_sec--; | |
| 98 | − tv.tv_usec += 1000000; | |
| 99 | − } | |
| 100 | − *sec = (dword) (tv.tv_sec - start_time.tv_sec); | |
| 101 | − *usec = (dword) (tv.tv_usec - start_time.tv_usec); | |
| 102 | − } else if (tv.tv_sec == start_time.tv_sec) { | |
| 103 | − *sec = 0; | |
| 104 | − if (start_time.tv_usec < tv.tv_usec) { | |
| 105 | − *usec = (dword) (tv.tv_usec - start_time.tv_usec); | |
| 106 | − } else { | |
| 107 | − *usec = 0; | |
| 108 | − } | |
| 109 | − } else { | |
| 110 | − *sec = (dword) tv.tv_sec; | |
| 111 | − *usec = (dword) tv.tv_usec; | |
| 112 | − } | |
| 90 | + struct timespec64 time; | |
| 91 | + | |
| 92 | + ktime_get_ts64(&time); | |
| 93 | + | |
| 94 | + *sec = (dword) time.tv_sec; | |
| 95 | + *usec = (dword) (time.tv_nsec / NSEC_PER_USEC); | |
| 113 | 96 | } |
| 114 | 97 | |
| 115 | 98 | /* |
| @@ -213,7 +196,6 @@ static int __init maint_init(void) · 97 unmodified lines | ||
| 213 | 196 | int ret = 0; |
| 214 | 197 | void *buffer = NULL; |
| 215 | 198 | |
| 216 | − do_gettimeofday(&start_time); | |
| 217 | 199 | init_waitqueue_head(&msgwaitq); |
| 218 | 200 | |
| 219 | 201 | printk(KERN_INFO "%s\n", DRIVERNAME); |
| @@ -99,32 +99,32 @@ struct ipac_hw { · 98 unmodified lines | ||
| 99 | 99 | |
| 100 | 100 | /* All registers original Siemens Spec */ |
| 101 | 101 | /* IPAC/ISAC registers */ |
| 102 | −#define ISAC_MASK 0x20 | |
| 103 | 102 | #define ISAC_ISTA 0x20 |
| 104 | −#define ISAC_STAR 0x21 | |
| 103 | +#define ISAC_MASK 0x20 | |
| 105 | 104 | #define ISAC_CMDR 0x21 |
| 105 | +#define ISAC_STAR 0x21 | |
| 106 | +#define ISAC_MODE 0x22 | |
| 107 | +#define ISAC_TIMR 0x23 | |
| 106 | 108 | #define ISAC_EXIR 0x24 |
| 107 | −#define ISAC_ADF2 0x39 | |
| 109 | +#define ISAC_RBCL 0x25 | |
| 110 | +#define ISAC_RSTA 0x27 | |
| 111 | +#define ISAC_RBCH 0x2A | |
| 108 | 112 | #define ISAC_SPCR 0x30 |
| 109 | −#define ISAC_ADF1 0x38 | |
| 110 | 113 | #define ISAC_CIR0 0x31 |
| 111 | 114 | #define ISAC_CIX0 0x31 |
| 112 | −#define ISAC_CIR1 0x33 | |
| 113 | −#define ISAC_CIX1 0x33 | |
| 114 | −#define ISAC_STCR 0x37 | |
| 115 | −#define ISAC_MODE 0x22 | |
| 116 | −#define ISAC_RSTA 0x27 | |
| 117 | −#define ISAC_RBCL 0x25 | |
| 118 | −#define ISAC_RBCH 0x2A | |
| 119 | −#define ISAC_TIMR 0x23 | |
| 120 | −#define ISAC_SQXR 0x3b | |
| 121 | −#define ISAC_SQRR 0x3b | |
| 122 | −#define ISAC_MOSR 0x3a | |
| 123 | −#define ISAC_MOCR 0x3a | |
| 124 | 115 | #define ISAC_MOR0 0x32 |
| 125 | 116 | #define ISAC_MOX0 0x32 |
| 117 | +#define ISAC_CIR1 0x33 | |
| 118 | +#define ISAC_CIX1 0x33 | |
| 126 | 119 | #define ISAC_MOR1 0x34 |
| 127 | 120 | #define ISAC_MOX1 0x34 |
| 121 | +#define ISAC_STCR 0x37 | |
| 122 | +#define ISAC_ADF1 0x38 | |
| 123 | +#define ISAC_ADF2 0x39 | |
| 124 | +#define ISAC_MOCR 0x3a | |
| 125 | +#define ISAC_MOSR 0x3a | |
| 126 | +#define ISAC_SQRR 0x3b | |
| 127 | +#define ISAC_SQXR 0x3b | |
| 128 | 128 | |
| 129 | 129 | #define ISAC_RBCH_XAC 0x80 |
| 130 | 130 | |
| @@ -212,13 +212,14 @@ struct ipac_hw { · 81 unmodified lines | ||
| 212 | 212 | #define ISAC_CMD_DUI 0xF |
| 213 | 213 | |
| 214 | 214 | /* ISAC/ISACX/IPAC/IPACX L1 indications */ |
| 215 | −#define ISAC_IND_RS 0x1 | |
| 216 | −#define ISAC_IND_PU 0x7 | |
| 217 | 215 | #define ISAC_IND_DR 0x0 |
| 216 | +#define ISAC_IND_RS 0x1 | |
| 218 | 217 | #define ISAC_IND_SD 0x2 |
| 219 | 218 | #define ISAC_IND_DIS 0x3 |
| 220 | −#define ISAC_IND_EI 0x6 | |
| 221 | 219 | #define ISAC_IND_RSY 0x4 |
| 220 | +#define ISAC_IND_DR6 0x5 | |
| 221 | +#define ISAC_IND_EI 0x6 | |
| 222 | +#define ISAC_IND_PU 0x7 | |
| 222 | 223 | #define ISAC_IND_ARD 0x8 |
| 223 | 224 | #define ISAC_IND_TI 0xA |
| 224 | 225 | #define ISAC_IND_ATI 0xB |
| @@ -339,9 +340,9 @@ struct ipac_hw { · 114 unmodified lines | ||
| 339 | 340 | #define ISACX__AUX 0x08 |
| 340 | 341 | #define ISACX__CIC 0x10 |
| 341 | 342 | #define ISACX__ST 0x20 |
| 343 | +#define IPACX__ON 0x2C | |
| 342 | 344 | #define IPACX__ICB 0x40 |
| 343 | 345 | #define IPACX__ICA 0x80 |
| 344 | −#define IPACX__ON 0x2C | |
| 345 | 346 | |
| 346 | 347 | /* ISACX/IPACX _CMDRD (W) */ |
| 347 | 348 | #define ISACX_CMDRD_XRES 0x01 |
| @@ -80,6 +80,7 @@ isac_ph_state_bh(struct dchannel *dch) · 79 unmodified lines | ||
| 80 | 80 | l1_event(dch->l1, HW_DEACT_CNF); |
| 81 | 81 | break; |
| 82 | 82 | case ISAC_IND_DR: |
| 83 | + case ISAC_IND_DR6: | |
| 83 | 84 | dch->state = 3; |
| 84 | 85 | l1_event(dch->l1, HW_DEACT_IND); |
| 85 | 86 | break; |
| @@ -660,6 +661,7 @@ isac_l1cmd(struct dchannel *dch, u32 cmd) · 574 unmodified lines | ||
| 660 | 661 | spin_lock_irqsave(isac->hwlock, flags); |
| 661 | 662 | if ((isac->state == ISAC_IND_EI) || |
| 662 | 663 | (isac->state == ISAC_IND_DR) || |
| 664 | + (isac->state == ISAC_IND_DR6) || | |
| 663 | 665 | (isac->state == ISAC_IND_RS)) |
| 664 | 666 | ph_command(isac, ISAC_CMD_TIM); |
| 665 | 667 | else |
| @@ -360,7 +360,10 @@ static int sram_probe(struct platform_device *pdev) · 359 unmodified lines | ||
| 360 | 360 | return -EBUSY; |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | − sram->virt_base = devm_ioremap_wc(sram->dev, res->start, size); | |
| 363 | + if (of_property_read_bool(pdev->dev.of_node, "no-memory-wc")) | |
| 364 | + sram->virt_base = devm_ioremap(sram->dev, res->start, size); | |
| 365 | + else | |
| 366 | + sram->virt_base = devm_ioremap_wc(sram->dev, res->start, size); | |
| 364 | 367 | if (IS_ERR(sram->virt_base)) |
| 365 | 368 | return PTR_ERR(sram->virt_base); |
| 366 | 369 | |
| @@ -193,6 +193,13 @@ config GENEVE · 192 unmodified lines | ||
| 193 | 193 | To compile this driver as a module, choose M here: the module |
| 194 | 194 | will be called geneve. |
| 195 | 195 | |
| 196 | +config MACSEC | |
| 197 | + tristate "IEEE 802.1AE MAC-level encryption (MACsec)" | |
| 198 | + select CRYPTO_AES | |
| 199 | + select CRYPTO_GCM | |
| 200 | + ---help--- | |
| 201 | + MACsec is an encryption standard for Ethernet. | |
| 202 | + | |
| 196 | 203 | config NETCONSOLE |
| 197 | 204 | tristate "Network console logging support" |
| 198 | 205 | ---help--- |
| @@ -10,6 +10,7 @@ obj-$(CONFIG_IPVLAN) += ipvlan/ · 9 unmodified lines | ||
| 10 | 10 | obj-$(CONFIG_DUMMY) += dummy.o |
| 11 | 11 | obj-$(CONFIG_EQUALIZER) += eql.o |
| 12 | 12 | obj-$(CONFIG_IFB) += ifb.o |
| 13 | +obj-$(CONFIG_MACSEC) += macsec.o | |
| 13 | 14 | obj-$(CONFIG_MACVLAN) += macvlan.o |
| 14 | 15 | obj-$(CONFIG_MACVTAP) += macvtap.o |
| 15 | 16 | obj-$(CONFIG_MII) += mii.o |
| @@ -357,6 +357,14 @@ static u8 __get_duplex(struct port *port) · 356 unmodified lines | ||
| 357 | 357 | return retval; |
| 358 | 358 | } |
| 359 | 359 | |
| 360 | +static void __ad_actor_update_port(struct port *port) | |
| 361 | +{ | |
| 362 | + const struct bonding *bond = bond_get_bond_by_slave(port->slave); | |
| 363 | + | |
| 364 | + port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr; | |
| 365 | + port->actor_system_priority = BOND_AD_INFO(bond).system.sys_priority; | |
| 366 | +} | |
| 367 | + | |
| 360 | 368 | /* Conversions */ |
| 361 | 369 | |
| 362 | 370 | /** |
| @@ -1963,9 +1971,7 @@ void bond_3ad_bind_slave(struct slave *slave) · 1600 unmodified lines | ||
| 1963 | 1971 | port->actor_admin_port_key = bond->params.ad_user_port_key << 6; |
| 1964 | 1972 | ad_update_actor_keys(port, false); |
| 1965 | 1973 | /* actor system is the bond's system */ |
| 1966 | − port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr; | |
| 1967 | − port->actor_system_priority = | |
| 1968 | − BOND_AD_INFO(bond).system.sys_priority; | |
| 1974 | + __ad_actor_update_port(port); | |
| 1969 | 1975 | /* tx timer(to verify that no more than MAX_TX_IN_SECOND |
| 1970 | 1976 | * lacpdu's are sent in one second) |
| 1971 | 1977 | */ |
| @@ -2147,6 +2153,38 @@ out: · 175 unmodified lines | ||
| 2147 | 2153 | spin_unlock_bh(&bond->mode_lock); |
| 2148 | 2154 | } |
| 2149 | 2155 | |
| 2156 | +/** | |
| 2157 | + * bond_3ad_update_ad_actor_settings - reflect change of actor settings to ports | |
| 2158 | + * @bond: bonding struct to work on | |
| 2159 | + * | |
| 2160 | + * If an ad_actor setting gets changed we need to update the individual port | |
| 2161 | + * settings so the bond device will use the new values when it gets upped. | |
| 2162 | + */ | |
| 2163 | +void bond_3ad_update_ad_actor_settings(struct bonding *bond) | |
| 2164 | +{ | |
| 2165 | + struct list_head *iter; | |
| 2166 | + struct slave *slave; | |
| 2167 | + | |
| 2168 | + ASSERT_RTNL(); | |
| 2169 | + | |
| 2170 | + BOND_AD_INFO(bond).system.sys_priority = bond->params.ad_actor_sys_prio; | |
| 2171 | + if (is_zero_ether_addr(bond->params.ad_actor_system)) | |
| 2172 | + BOND_AD_INFO(bond).system.sys_mac_addr = | |
| 2173 | + *((struct mac_addr *)bond->dev->dev_addr); | |
| 2174 | + else | |
| 2175 | + BOND_AD_INFO(bond).system.sys_mac_addr = | |
| 2176 | + *((struct mac_addr *)bond->params.ad_actor_system); | |
| 2177 | + | |
| 2178 | + spin_lock_bh(&bond->mode_lock); | |
| 2179 | + bond_for_each_slave(bond, slave, iter) { | |
| 2180 | + struct port *port = &(SLAVE_AD_INFO(slave))->port; | |
| 2181 | + | |
| 2182 | + __ad_actor_update_port(port); | |
| 2183 | + port->ntt = true; | |
| 2184 | + } | |
| 2185 | + spin_unlock_bh(&bond->mode_lock); | |
| 2186 | +} | |
| 2187 | + | |
| 2150 | 2188 | /** |
| 2151 | 2189 | * bond_3ad_state_machine_handler - handle state machines timeout |
| 2152 | 2190 | * @bond: bonding struct to work on |
| @@ -159,7 +159,7 @@ static int tlb_initialize(struct bonding *bond) · 158 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | new_hashtbl = kzalloc(size, GFP_KERNEL); |
| 161 | 161 | if (!new_hashtbl) |
| 162 | − return -1; | |
| 162 | + return -ENOMEM; | |
| 163 | 163 | |
| 164 | 164 | spin_lock_bh(&bond->mode_lock); |
| 165 | 165 | |
| @@ -376,22 +376,20 @@ down: · 375 unmodified lines | ||
| 376 | 376 | static void bond_update_speed_duplex(struct slave *slave) |
| 377 | 377 | { |
| 378 | 378 | struct net_device *slave_dev = slave->dev; |
| 379 | − struct ethtool_cmd ecmd; | |
| 380 | − u32 slave_speed; | |
| 379 | + struct ethtool_link_ksettings ecmd; | |
| 381 | 380 | int res; |
| 382 | 381 | |
| 383 | 382 | slave->speed = SPEED_UNKNOWN; |
| 384 | 383 | slave->duplex = DUPLEX_UNKNOWN; |
| 385 | 384 | |
| 386 | − res = __ethtool_get_settings(slave_dev, &ecmd); | |
| 385 | + res = __ethtool_get_link_ksettings(slave_dev, &ecmd); | |
| 387 | 386 | if (res < 0) |
| 388 | 387 | return; |
| 389 | 388 | |
| 390 | − slave_speed = ethtool_cmd_speed(&ecmd); | |
| 391 | − if (slave_speed == 0 || slave_speed == ((__u32) -1)) | |
| 389 | + if (ecmd.base.speed == 0 || ecmd.base.speed == ((__u32)-1)) | |
| 392 | 390 | return; |
| 393 | 391 | |
| 394 | − switch (ecmd.duplex) { | |
| 392 | + switch (ecmd.base.duplex) { | |
| 395 | 393 | case DUPLEX_FULL: |
| 396 | 394 | case DUPLEX_HALF: |
| 397 | 395 | break; |
| @@ -399,8 +397,8 @@ static void bond_update_speed_duplex(struct slave *slave) · 1 unmodified line | ||
| 399 | 397 | return; |
| 400 | 398 | } |
| 401 | 399 | |
| 402 | − slave->speed = slave_speed; | |
| 403 | − slave->duplex = ecmd.duplex; | |
| 400 | + slave->speed = ecmd.base.speed; | |
| 401 | + slave->duplex = ecmd.base.duplex; | |
| 404 | 402 | |
| 405 | 403 | return; |
| 406 | 404 | } |
| @@ -620,8 +618,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, · 213 unmodified lines | ||
| 620 | 618 | static void bond_set_dev_addr(struct net_device *bond_dev, |
| 621 | 619 | struct net_device *slave_dev) |
| 622 | 620 | { |
| 623 | − netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", | |
| 624 | − bond_dev, slave_dev, slave_dev->addr_len); | |
| 621 | + netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->name=%s slave_dev->addr_len=%d\n", | |
| 622 | + bond_dev, slave_dev, slave_dev->name, slave_dev->addr_len); | |
| 625 | 623 | memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); |
| 626 | 624 | bond_dev->addr_assign_type = NET_ADDR_STOLEN; |
| 627 | 625 | call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); |
| @@ -930,11 +928,10 @@ void bond_select_active_slave(struct bonding *bond) · 302 unmodified lines | ||
| 930 | 928 | if (!rv) |
| 931 | 929 | return; |
| 932 | 930 | |
| 933 | − if (netif_carrier_ok(bond->dev)) { | |
| 931 | + if (netif_carrier_ok(bond->dev)) | |
| 934 | 932 | netdev_info(bond->dev, "first active interface up!\n"); |
| 935 | − } else { | |
| 933 | + else | |
| 936 | 934 | netdev_info(bond->dev, "now running without any active interface!\n"); |
| 937 | − } | |
| 938 | 935 | } |
| 939 | 936 | } |
| 940 | 937 | |
| @@ -1180,9 +1177,8 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) · 239 unmodified lines | ||
| 1180 | 1177 | } |
| 1181 | 1178 | } |
| 1182 | 1179 | |
| 1183 | − if (bond_should_deliver_exact_match(skb, slave, bond)) { | |
| 1180 | + if (bond_should_deliver_exact_match(skb, slave, bond)) | |
| 1184 | 1181 | return RX_HANDLER_EXACT; |
| 1185 | − } | |
| 1186 | 1182 | |
| 1187 | 1183 | skb->dev = bond->dev; |
| 1188 | 1184 | |
| @@ -1243,7 +1239,7 @@ static struct slave *bond_alloc_slave(struct bonding *bond) · 54 unmodified lines | ||
| 1243 | 1239 | { |
| 1244 | 1240 | struct slave *slave = NULL; |
| 1245 | 1241 | |
| 1246 | − slave = kzalloc(sizeof(struct slave), GFP_KERNEL); | |
| 1242 | + slave = kzalloc(sizeof(*slave), GFP_KERNEL); | |
| 1247 | 1243 | if (!slave) |
| 1248 | 1244 | return NULL; |
| 1249 | 1245 | |
| @@ -1383,8 +1379,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) · 133 unmodified lines | ||
| 1383 | 1379 | if (slave_dev->flags & IFF_UP) { |
| 1384 | 1380 | netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n", |
| 1385 | 1381 | slave_dev->name); |
| 1386 | − res = -EPERM; | |
| 1387 | − goto err_undo_flags; | |
| 1382 | + return -EPERM; | |
| 1388 | 1383 | } |
| 1389 | 1384 | |
| 1390 | 1385 | /* set bonding device ether type by slave - bonding netdevices are |
| @@ -1404,8 +1399,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) · 13 unmodified lines | ||
| 1404 | 1399 | res = notifier_to_errno(res); |
| 1405 | 1400 | if (res) { |
| 1406 | 1401 | netdev_err(bond_dev, "refused to change device type\n"); |
| 1407 | − res = -EBUSY; | |
| 1408 | − goto err_undo_flags; | |
| 1402 | + return -EBUSY; | |
| 1409 | 1403 | } |
| 1410 | 1404 | |
| 1411 | 1405 | /* Flush unicast and multicast addresses */ |
| @@ -1425,8 +1419,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) · 13 unmodified lines | ||
| 1425 | 1419 | } else if (bond_dev->type != slave_dev->type) { |
| 1426 | 1420 | netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n", |
| 1427 | 1421 | slave_dev->name, slave_dev->type, bond_dev->type); |
| 1428 | − res = -EINVAL; | |
| 1429 | − goto err_undo_flags; | |
| 1422 | + return -EINVAL; | |
| 1430 | 1423 | } |
| 1431 | 1424 | |
| 1432 | 1425 | if (slave_ops->ndo_set_mac_address == NULL) { |
| @@ -3308,6 +3301,30 @@ static int bond_close(struct net_device *bond_dev) · 1875 unmodified lines | ||
| 3308 | 3301 | return 0; |
| 3309 | 3302 | } |
| 3310 | 3303 | |
| 3304 | +/* fold stats, assuming all rtnl_link_stats64 fields are u64, but | |
| 3305 | + * that some drivers can provide 32bit values only. | |
| 3306 | + */ | |
| 3307 | +static void bond_fold_stats(struct rtnl_link_stats64 *_res, | |
| 3308 | + const struct rtnl_link_stats64 *_new, | |
| 3309 | + const struct rtnl_link_stats64 *_old) | |
| 3310 | +{ | |
| 3311 | + const u64 *new = (const u64 *)_new; | |
| 3312 | + const u64 *old = (const u64 *)_old; | |
| 3313 | + u64 *res = (u64 *)_res; | |
| 3314 | + int i; | |
| 3315 | + | |
| 3316 | + for (i = 0; i < sizeof(*_res) / sizeof(u64); i++) { | |
| 3317 | + u64 nv = new[i]; | |
| 3318 | + u64 ov = old[i]; | |
| 3319 | + | |
| 3320 | + /* detects if this particular field is 32bit only */ | |
| 3321 | + if (((nv | ov) >> 32) == 0) | |
| 3322 | + res[i] += (u32)nv - (u32)ov; | |
| 3323 | + else | |
| 3324 | + res[i] += nv - ov; | |
| 3325 | + } | |
| 3326 | +} | |
| 3327 | + | |
| 3311 | 3328 | static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, |
| 3312 | 3329 | struct rtnl_link_stats64 *stats) |
| 3313 | 3330 | { |
| @@ -3316,43 +3333,23 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, · 2 unmodified lines | ||
| 3316 | 3333 | struct list_head *iter; |
| 3317 | 3334 | struct slave *slave; |
| 3318 | 3335 | |
| 3336 | + spin_lock(&bond->stats_lock); | |
| 3319 | 3337 | memcpy(stats, &bond->bond_stats, sizeof(*stats)); |
| 3320 | 3338 | |
| 3321 | − bond_for_each_slave(bond, slave, iter) { | |
| 3322 | − const struct rtnl_link_stats64 *sstats = | |
| 3339 | + rcu_read_lock(); | |
| 3340 | + bond_for_each_slave_rcu(bond, slave, iter) { | |
| 3341 | + const struct rtnl_link_stats64 *new = | |
| 3323 | 3342 | dev_get_stats(slave->dev, &temp); |
| 3324 | − struct rtnl_link_stats64 *pstats = &slave->slave_stats; | |
| 3325 | − | |
| 3326 | − stats->rx_packets += sstats->rx_packets - pstats->rx_packets; | |
| 3327 | − stats->rx_bytes += sstats->rx_bytes - pstats->rx_bytes; | |
| 3328 | − stats->rx_errors += sstats->rx_errors - pstats->rx_errors; | |
| 3329 | − stats->rx_dropped += sstats->rx_dropped - pstats->rx_dropped; | |
| 3330 | − | |
| 3331 | − stats->tx_packets += sstats->tx_packets - pstats->tx_packets;; | |
| 3332 | − stats->tx_bytes += sstats->tx_bytes - pstats->tx_bytes; | |
| 3333 | − stats->tx_errors += sstats->tx_errors - pstats->tx_errors; | |
| 3334 | − stats->tx_dropped += sstats->tx_dropped - pstats->tx_dropped; | |
| 3335 | − | |
| 3336 | − stats->multicast += sstats->multicast - pstats->multicast; | |
| 3337 | − stats->collisions += sstats->collisions - pstats->collisions; | |
| 3338 | − | |
| 3339 | − stats->rx_length_errors += sstats->rx_length_errors - pstats->rx_length_errors; | |
| 3340 | − stats->rx_over_errors += sstats->rx_over_errors - pstats->rx_over_errors; | |
| 3341 | − stats->rx_crc_errors += sstats->rx_crc_errors - pstats->rx_crc_errors; | |
| 3342 | − stats->rx_frame_errors += sstats->rx_frame_errors - pstats->rx_frame_errors; | |
| 3343 | − stats->rx_fifo_errors += sstats->rx_fifo_errors - pstats->rx_fifo_errors; | |
| 3344 | − stats->rx_missed_errors += sstats->rx_missed_errors - pstats->rx_missed_errors; | |
| 3345 | − | |
| 3346 | − stats->tx_aborted_errors += sstats->tx_aborted_errors - pstats->tx_aborted_errors; | |
| 3347 | − stats->tx_carrier_errors += sstats->tx_carrier_errors - pstats->tx_carrier_errors; | |
| 3348 | − stats->tx_fifo_errors += sstats->tx_fifo_errors - pstats->tx_fifo_errors; | |
| 3349 | − stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors - pstats->tx_heartbeat_errors; | |
| 3350 | − stats->tx_window_errors += sstats->tx_window_errors - pstats->tx_window_errors; | |
| 3343 | + | |
| 3344 | + bond_fold_stats(stats, new, &slave->slave_stats); | |
| 3351 | 3345 | |
| 3352 | 3346 | /* save off the slave stats for the next run */ |
| 3353 | − memcpy(pstats, sstats, sizeof(*sstats)); | |
| 3347 | + memcpy(&slave->slave_stats, new, sizeof(*new)); | |
| 3354 | 3348 | } |
| 3349 | + rcu_read_unlock(); | |
| 3350 | + | |
| 3355 | 3351 | memcpy(&bond->bond_stats, stats, sizeof(*stats)); |
| 3352 | + spin_unlock(&bond->stats_lock); | |
| 3356 | 3353 | |
| 3357 | 3354 | return stats; |
| 3358 | 3355 | } |
| @@ -4166,6 +4163,7 @@ void bond_setup(struct net_device *bond_dev) · 807 unmodified lines | ||
| 4166 | 4163 | struct bonding *bond = netdev_priv(bond_dev); |
| 4167 | 4164 | |
| 4168 | 4165 | spin_lock_init(&bond->mode_lock); |
| 4166 | + spin_lock_init(&bond->stats_lock); | |
| 4169 | 4167 | bond->params = bonding_defaults; |
| 4170 | 4168 | |
| 4171 | 4169 | /* Initialize pointers */ |
| @@ -4181,7 +4179,7 @@ void bond_setup(struct net_device *bond_dev) · 9 unmodified lines | ||
| 4181 | 4179 | SET_NETDEV_DEVTYPE(bond_dev, &bond_type); |
| 4182 | 4180 | |
| 4183 | 4181 | /* Initialize the device options */ |
| 4184 | − bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; | |
| 4182 | + bond_dev->flags |= IFF_MASTER; | |
| 4185 | 4183 | bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT | IFF_NO_QUEUE; |
| 4186 | 4184 | bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); |
| 4187 | 4185 | |
| @@ -402,7 +402,6 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = { · 401 unmodified lines | ||
| 402 | 402 | .id = BOND_OPT_AD_ACTOR_SYS_PRIO, |
| 403 | 403 | .name = "ad_actor_sys_prio", |
| 404 | 404 | .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_8023AD)), |
| 405 | − .flags = BOND_OPTFLAG_IFDOWN, | |
| 406 | 405 | .values = bond_ad_actor_sys_prio_tbl, |
| 407 | 406 | .set = bond_option_ad_actor_sys_prio_set, |
| 408 | 407 | }, |
| @@ -410,7 +409,7 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = { · 1 unmodified line | ||
| 410 | 409 | .id = BOND_OPT_AD_ACTOR_SYSTEM, |
| 411 | 410 | .name = "ad_actor_system", |
| 412 | 411 | .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_8023AD)), |
| 413 | − .flags = BOND_OPTFLAG_RAWVAL | BOND_OPTFLAG_IFDOWN, | |
| 412 | + .flags = BOND_OPTFLAG_RAWVAL, | |
| 414 | 413 | .set = bond_option_ad_actor_system_set, |
| 415 | 414 | }, |
| 416 | 415 | [BOND_OPT_AD_USER_PORT_KEY] = { |
| @@ -1392,6 +1391,8 @@ static int bond_option_ad_actor_sys_prio_set(struct bonding *bond, · 975 unmodified lines | ||
| 1392 | 1391 | newval->value); |
| 1393 | 1392 | |
| 1394 | 1393 | bond->params.ad_actor_sys_prio = newval->value; |
| 1394 | + bond_3ad_update_ad_actor_settings(bond); | |
| 1395 | + | |
| 1395 | 1396 | return 0; |
| 1396 | 1397 | } |
| 1397 | 1398 | |
| @@ -1418,6 +1419,8 @@ static int bond_option_ad_actor_system_set(struct bonding *bond, · 20 unmodified lines | ||
| 1418 | 1419 | |
| 1419 | 1420 | netdev_info(bond->dev, "Setting ad_actor_system to %pM\n", mac); |
| 1420 | 1421 | ether_addr_copy(bond->params.ad_actor_system, mac); |
| 1422 | + bond_3ad_update_ad_actor_settings(bond); | |
| 1423 | + | |
| 1421 | 1424 | return 0; |
| 1422 | 1425 | |
| 1423 | 1426 | err: |
| @@ -70,13 +70,6 @@ config CAN_AT91 · 69 unmodified lines | ||
| 70 | 70 | This is a driver for the SoC CAN controller in Atmel's AT91SAM9263 |
| 71 | 71 | and AT91SAM9X5 processors. |
| 72 | 72 | |
| 73 | −config CAN_TI_HECC | |
| 74 | − depends on ARM | |
| 75 | − tristate "TI High End CAN Controller" | |
| 76 | − ---help--- | |
| 77 | − Driver for TI HECC (High End CAN Controller) module found on many | |
| 78 | − TI devices. The device specifications are available from www.ti.com | |
| 79 | − | |
| 80 | 73 | config CAN_BFIN |
| 81 | 74 | depends on BF534 || BF536 || BF537 || BF538 || BF539 || BF54x |
| 82 | 75 | tristate "Analog Devices Blackfin on-chip CAN" |
| @@ -86,30 +79,12 @@ config CAN_BFIN · 3 unmodified lines | ||
| 86 | 79 | To compile this driver as a module, choose M here: the |
| 87 | 80 | module will be called bfin_can. |
| 88 | 81 | |
| 89 | −config CAN_JANZ_ICAN3 | |
| 90 | − tristate "Janz VMOD-ICAN3 Intelligent CAN controller" | |
| 91 | − depends on MFD_JANZ_CMODIO | |
| 92 | − ---help--- | |
| 93 | − Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which | |
| 94 | − connects to a MODULbus carrier board. | |
| 95 | − | |
| 96 | − This driver can also be built as a module. If so, the module will be | |
| 97 | − called janz-ican3.ko. | |
| 98 | − | |
| 99 | 82 | config CAN_FLEXCAN |
| 100 | 83 | tristate "Support for Freescale FLEXCAN based chips" |
| 101 | 84 | depends on ARM || PPC |
| 102 | 85 | ---help--- |
| 103 | 86 | Say Y here if you want to support for Freescale FlexCAN. |
| 104 | 87 | |
| 105 | −config PCH_CAN | |
| 106 | − tristate "Intel EG20T PCH CAN controller" | |
| 107 | − depends on PCI && (X86_32 || COMPILE_TEST) | |
| 108 | − ---help--- | |
| 109 | − This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which | |
| 110 | − is an IOH for x86 embedded processor (Intel Atom E6xx series). | |
| 111 | − This driver can access CAN bus. | |
| 112 | − | |
| 113 | 88 | config CAN_GRCAN |
| 114 | 89 | tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices" |
| 115 | 90 | depends on OF && HAS_DMA |
| @@ -119,9 +94,19 @@ config CAN_GRCAN · 3 unmodified lines | ||
| 119 | 94 | endian syntheses of the cores would need some modifications on |
| 120 | 95 | the hardware level to work. |
| 121 | 96 | |
| 97 | +config CAN_JANZ_ICAN3 | |
| 98 | + tristate "Janz VMOD-ICAN3 Intelligent CAN controller" | |
| 99 | + depends on MFD_JANZ_CMODIO | |
| 100 | + ---help--- | |
| 101 | + Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which | |
| 102 | + connects to a MODULbus carrier board. | |
| 103 | + | |
| 104 | + This driver can also be built as a module. If so, the module will be | |
| 105 | + called janz-ican3.ko. | |
| 106 | + | |
| 122 | 107 | config CAN_RCAR |
| 123 | 108 | tristate "Renesas R-Car CAN controller" |
| 124 | − depends on ARM | |
| 109 | + depends on ARCH_RENESAS || ARM | |
| 125 | 110 | ---help--- |
| 126 | 111 | Say Y here if you want to use CAN controller found on Renesas R-Car |
| 127 | 112 | SoCs. |
| @@ -139,6 +124,13 @@ config CAN_SUN4I · 11 unmodified lines | ||
| 139 | 124 | To compile this driver as a module, choose M here: the module will |
| 140 | 125 | be called sun4i_can. |
| 141 | 126 | |
| 127 | +config CAN_TI_HECC | |
| 128 | + depends on ARM | |
| 129 | + tristate "TI High End CAN Controller" | |
| 130 | + ---help--- | |
| 131 | + Driver for TI HECC (High End CAN Controller) module found on many | |
| 132 | + TI devices. The device specifications are available from www.ti.com | |
| 133 | + | |
| 142 | 134 | config CAN_XILINXCAN |
| 143 | 135 | tristate "Xilinx CAN" |
| 144 | 136 | depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST |
| @@ -147,22 +139,24 @@ config CAN_XILINXCAN · 2 unmodified lines | ||
| 147 | 139 | Xilinx CAN driver. This driver supports both soft AXI CAN IP and |
| 148 | 140 | Zynq CANPS IP. |
| 149 | 141 | |
| 150 | −source "drivers/net/can/mscan/Kconfig" | |
| 151 | − | |
| 152 | −source "drivers/net/can/sja1000/Kconfig" | |
| 142 | +config PCH_CAN | |
| 143 | + tristate "Intel EG20T PCH CAN controller" | |
| 144 | + depends on PCI && (X86_32 || COMPILE_TEST) | |
| 145 | + ---help--- | |
| 146 | + This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which | |
| 147 | + is an IOH for x86 embedded processor (Intel Atom E6xx series). | |
| 148 | + This driver can access CAN bus. | |
| 153 | 149 | |
| 154 | 150 | source "drivers/net/can/c_can/Kconfig" |
| 155 | − | |
| 156 | −source "drivers/net/can/m_can/Kconfig" | |
| 157 | − | |
| 158 | 151 | source "drivers/net/can/cc770/Kconfig" |
| 159 | − | |
| 152 | +source "drivers/net/can/ifi_canfd/Kconfig" | |
| 153 | +source "drivers/net/can/m_can/Kconfig" | |
| 154 | +source "drivers/net/can/mscan/Kconfig" | |
| 155 | +source "drivers/net/can/sja1000/Kconfig" | |
| 156 | +source "drivers/net/can/softing/Kconfig" | |
| 160 | 157 | source "drivers/net/can/spi/Kconfig" |
| 161 | − | |
| 162 | 158 | source "drivers/net/can/usb/Kconfig" |
| 163 | 159 | |
| 164 | −source "drivers/net/can/softing/Kconfig" | |
| 165 | − | |
| 166 | 160 | endif |
| 167 | 161 | |
| 168 | 162 | config CAN_DEBUG_DEVICES |
| @@ -14,21 +14,22 @@ obj-y += spi/ · 13 unmodified lines | ||
| 14 | 14 | obj-y += usb/ |
| 15 | 15 | obj-y += softing/ |
| 16 | 16 | |
| 17 | −obj-$(CONFIG_CAN_SJA1000) += sja1000/ | |
| 18 | −obj-$(CONFIG_CAN_MSCAN) += mscan/ | |
| 19 | −obj-$(CONFIG_CAN_C_CAN) += c_can/ | |
| 20 | −obj-$(CONFIG_CAN_M_CAN) += m_can/ | |
| 21 | −obj-$(CONFIG_CAN_CC770) += cc770/ | |
| 22 | 17 | obj-$(CONFIG_CAN_AT91) += at91_can.o |
| 23 | −obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o | |
| 24 | 18 | obj-$(CONFIG_CAN_BFIN) += bfin_can.o |
| 25 | −obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o | |
| 19 | +obj-$(CONFIG_CAN_CC770) += cc770/ | |
| 20 | +obj-$(CONFIG_CAN_C_CAN) += c_can/ | |
| 26 | 21 | obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o |
| 27 | −obj-$(CONFIG_PCH_CAN) += pch_can.o | |
| 28 | 22 | obj-$(CONFIG_CAN_GRCAN) += grcan.o |
| 23 | +obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd/ | |
| 24 | +obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o | |
| 25 | +obj-$(CONFIG_CAN_MSCAN) += mscan/ | |
| 26 | +obj-$(CONFIG_CAN_M_CAN) += m_can/ | |
| 29 | 27 | obj-$(CONFIG_CAN_RCAR) += rcar_can.o |
| 28 | +obj-$(CONFIG_CAN_SJA1000) += sja1000/ | |
| 30 | 29 | obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o |
| 30 | +obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o | |
| 31 | 31 | obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o |
| 32 | +obj-$(CONFIG_PCH_CAN) += pch_can.o | |
| 32 | 33 | |
| 33 | 34 | subdir-ccflags-y += -D__CHECK_ENDIAN__ |
| 34 | 35 | subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG |
| @@ -0,0 +1,8 @@ | ||
| 1 | +config CAN_IFI_CANFD | |
| 2 | + depends on HAS_IOMEM | |
| 3 | + tristate "IFI CAN_FD IP" | |
| 4 | + ---help--- | |
| 5 | + This driver adds support for the I/F/I CAN_FD soft IP block | |
| 6 | + connected to the "platform bus" (Linux abstraction for directly | |
| 7 | + to the processor attached devices). The CAN_FD is most often | |
| 8 | + synthesised into an FPGA or CPLD. | |
| @@ -0,0 +1,5 @@ | ||
| 1 | +# | |
| 2 | +# Makefile for the IFI CANFD controller driver. | |
| 3 | +# | |
| 4 | + | |
| 5 | +obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd.o | |
| @@ -0,0 +1,944 @@ | ||
| 1 | +/* | |
| 2 | + * CAN bus driver for IFI CANFD controller | |
| 3 | + * | |
| 4 | + * Copyright (C) 2016 Marek Vasut <marex@denx.de> | |
| 5 | + * | |
| 6 | + * Details about this controller can be found at | |
| 7 | + * http://www.ifi-pld.de/IP/CANFD/canfd.html | |
| 8 | + * | |
| 9 | + * This file is licensed under the terms of the GNU General Public | |
| 10 | + * License version 2. This program is licensed "as is" without any | |
| 11 | + * warranty of any kind, whether express or implied. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/clk.h> | |
| 15 | +#include <linux/delay.h> | |
| 16 | +#include <linux/interrupt.h> | |
| 17 | +#include <linux/io.h> | |
| 18 | +#include <linux/kernel.h> | |
| 19 | +#include <linux/module.h> | |
| 20 | +#include <linux/netdevice.h> | |
| 21 | +#include <linux/of.h> | |
| 22 | +#include <linux/of_device.h> | |
| 23 | +#include <linux/platform_device.h> | |
| 24 | + | |
| 25 | +#include <linux/can/dev.h> | |
| 26 | + | |
| 27 | +#define IFI_CANFD_STCMD 0x0 | |
| 28 | +#define IFI_CANFD_STCMD_HARDRESET 0xDEADCAFD | |
| 29 | +#define IFI_CANFD_STCMD_ENABLE BIT(0) | |
| 30 | +#define IFI_CANFD_STCMD_ERROR_ACTIVE BIT(2) | |
| 31 | +#define IFI_CANFD_STCMD_ERROR_PASSIVE BIT(3) | |
| 32 | +#define IFI_CANFD_STCMD_BUSOFF BIT(4) | |
| 33 | +#define IFI_CANFD_STCMD_BUSMONITOR BIT(16) | |
| 34 | +#define IFI_CANFD_STCMD_LOOPBACK BIT(18) | |
| 35 | +#define IFI_CANFD_STCMD_DISABLE_CANFD BIT(24) | |
| 36 | +#define IFI_CANFD_STCMD_ENABLE_ISO BIT(25) | |
| 37 | +#define IFI_CANFD_STCMD_NORMAL_MODE ((u32)BIT(31)) | |
| 38 | + | |
| 39 | +#define IFI_CANFD_RXSTCMD 0x4 | |
| 40 | +#define IFI_CANFD_RXSTCMD_REMOVE_MSG BIT(0) | |
| 41 | +#define IFI_CANFD_RXSTCMD_RESET BIT(7) | |
| 42 | +#define IFI_CANFD_RXSTCMD_EMPTY BIT(8) | |
| 43 | +#define IFI_CANFD_RXSTCMD_OVERFLOW BIT(13) | |
| 44 | + | |
| 45 | +#define IFI_CANFD_TXSTCMD 0x8 | |
| 46 | +#define IFI_CANFD_TXSTCMD_ADD_MSG BIT(0) | |
| 47 | +#define IFI_CANFD_TXSTCMD_HIGH_PRIO BIT(1) | |
| 48 | +#define IFI_CANFD_TXSTCMD_RESET BIT(7) | |
| 49 | +#define IFI_CANFD_TXSTCMD_EMPTY BIT(8) | |
| 50 | +#define IFI_CANFD_TXSTCMD_FULL BIT(12) | |
| 51 | +#define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13) | |
| 52 | + | |
| 53 | +#define IFI_CANFD_INTERRUPT 0xc | |
| 54 | +#define IFI_CANFD_INTERRUPT_ERROR_WARNING ((u32)BIT(1)) | |
| 55 | +#define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16) | |
| 56 | +#define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22) | |
| 57 | +#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY BIT(24) | |
| 58 | +#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER BIT(25) | |
| 59 | +#define IFI_CANFD_INTERRUPT_SET_IRQ ((u32)BIT(31)) | |
| 60 | + | |
| 61 | +#define IFI_CANFD_IRQMASK 0x10 | |
| 62 | +#define IFI_CANFD_IRQMASK_SET_ERR BIT(7) | |
| 63 | +#define IFI_CANFD_IRQMASK_SET_TS BIT(15) | |
| 64 | +#define IFI_CANFD_IRQMASK_TXFIFO_EMPTY BIT(16) | |
| 65 | +#define IFI_CANFD_IRQMASK_SET_TX BIT(23) | |
| 66 | +#define IFI_CANFD_IRQMASK_RXFIFO_NEMPTY BIT(24) | |
| 67 | +#define IFI_CANFD_IRQMASK_SET_RX ((u32)BIT(31)) | |
| 68 | + | |
| 69 | +#define IFI_CANFD_TIME 0x14 | |
| 70 | +#define IFI_CANFD_FTIME 0x18 | |
| 71 | +#define IFI_CANFD_TIME_TIMEB_OFF 0 | |
| 72 | +#define IFI_CANFD_TIME_TIMEA_OFF 8 | |
| 73 | +#define IFI_CANFD_TIME_PRESCALE_OFF 16 | |
| 74 | +#define IFI_CANFD_TIME_SJW_OFF_ISO 25 | |
| 75 | +#define IFI_CANFD_TIME_SJW_OFF_BOSCH 28 | |
| 76 | +#define IFI_CANFD_TIME_SET_SJW_BOSCH BIT(6) | |
| 77 | +#define IFI_CANFD_TIME_SET_TIMEB_BOSCH BIT(7) | |
| 78 | +#define IFI_CANFD_TIME_SET_PRESC_BOSCH BIT(14) | |
| 79 | +#define IFI_CANFD_TIME_SET_TIMEA_BOSCH BIT(15) | |
| 80 | + | |
| 81 | +#define IFI_CANFD_TDELAY 0x1c | |
| 82 | + | |
| 83 | +#define IFI_CANFD_ERROR 0x20 | |
| 84 | +#define IFI_CANFD_ERROR_TX_OFFSET 0 | |
| 85 | +#define IFI_CANFD_ERROR_TX_MASK 0xff | |
| 86 | +#define IFI_CANFD_ERROR_RX_OFFSET 16 | |
| 87 | +#define IFI_CANFD_ERROR_RX_MASK 0xff | |
| 88 | + | |
| 89 | +#define IFI_CANFD_ERRCNT 0x24 | |
| 90 | + | |
| 91 | +#define IFI_CANFD_SUSPEND 0x28 | |
| 92 | + | |
| 93 | +#define IFI_CANFD_REPEAT 0x2c | |
| 94 | + | |
| 95 | +#define IFI_CANFD_TRAFFIC 0x30 | |
| 96 | + | |
| 97 | +#define IFI_CANFD_TSCONTROL 0x34 | |
| 98 | + | |
| 99 | +#define IFI_CANFD_TSC 0x38 | |
| 100 | + | |
| 101 | +#define IFI_CANFD_TST 0x3c | |
| 102 | + | |
| 103 | +#define IFI_CANFD_RES1 0x40 | |
| 104 | + | |
| 105 | +#define IFI_CANFD_RES2 0x44 | |
| 106 | + | |
| 107 | +#define IFI_CANFD_PAR 0x48 | |
| 108 | + | |
| 109 | +#define IFI_CANFD_CANCLOCK 0x4c | |
| 110 | + | |
| 111 | +#define IFI_CANFD_SYSCLOCK 0x50 | |
| 112 | + | |
| 113 | +#define IFI_CANFD_VER 0x54 | |
| 114 | + | |
| 115 | +#define IFI_CANFD_IP_ID 0x58 | |
| 116 | +#define IFI_CANFD_IP_ID_VALUE 0xD073CAFD | |
| 117 | + | |
| 118 | +#define IFI_CANFD_TEST 0x5c | |
| 119 | + | |
| 120 | +#define IFI_CANFD_RXFIFO_TS_63_32 0x60 | |
| 121 | + | |
| 122 | +#define IFI_CANFD_RXFIFO_TS_31_0 0x64 | |
| 123 | + | |
| 124 | +#define IFI_CANFD_RXFIFO_DLC 0x68 | |
| 125 | +#define IFI_CANFD_RXFIFO_DLC_DLC_OFFSET 0 | |
| 126 | +#define IFI_CANFD_RXFIFO_DLC_DLC_MASK 0xf | |
| 127 | +#define IFI_CANFD_RXFIFO_DLC_RTR BIT(4) | |
| 128 | +#define IFI_CANFD_RXFIFO_DLC_EDL BIT(5) | |
| 129 | +#define IFI_CANFD_RXFIFO_DLC_BRS BIT(6) | |
| 130 | +#define IFI_CANFD_RXFIFO_DLC_ESI BIT(7) | |
| 131 | +#define IFI_CANFD_RXFIFO_DLC_OBJ_OFFSET 8 | |
| 132 | +#define IFI_CANFD_RXFIFO_DLC_OBJ_MASK 0x1ff | |
| 133 | +#define IFI_CANFD_RXFIFO_DLC_FNR_OFFSET 24 | |
| 134 | +#define IFI_CANFD_RXFIFO_DLC_FNR_MASK 0xff | |
| 135 | + | |
| 136 | +#define IFI_CANFD_RXFIFO_ID 0x6c | |
| 137 | +#define IFI_CANFD_RXFIFO_ID_ID_OFFSET 0 | |
| 138 | +#define IFI_CANFD_RXFIFO_ID_ID_STD_MASK CAN_SFF_MASK | |
| 139 | +#define IFI_CANFD_RXFIFO_ID_ID_STD_OFFSET 0 | |
| 140 | +#define IFI_CANFD_RXFIFO_ID_ID_STD_WIDTH 10 | |
| 141 | +#define IFI_CANFD_RXFIFO_ID_ID_XTD_MASK CAN_EFF_MASK | |
| 142 | +#define IFI_CANFD_RXFIFO_ID_ID_XTD_OFFSET 11 | |
| 143 | +#define IFI_CANFD_RXFIFO_ID_ID_XTD_WIDTH 18 | |
| 144 | +#define IFI_CANFD_RXFIFO_ID_IDE BIT(29) | |
| 145 | + | |
| 146 | +#define IFI_CANFD_RXFIFO_DATA 0x70 /* 0x70..0xac */ | |
| 147 | + | |
| 148 | +#define IFI_CANFD_TXFIFO_SUSPEND_US 0xb0 | |
| 149 | + | |
| 150 | +#define IFI_CANFD_TXFIFO_REPEATCOUNT 0xb4 | |
| 151 | + | |
| 152 | +#define IFI_CANFD_TXFIFO_DLC 0xb8 | |
| 153 | +#define IFI_CANFD_TXFIFO_DLC_DLC_OFFSET 0 | |
| 154 | +#define IFI_CANFD_TXFIFO_DLC_DLC_MASK 0xf | |
| 155 | +#define IFI_CANFD_TXFIFO_DLC_RTR BIT(4) | |
| 156 | +#define IFI_CANFD_TXFIFO_DLC_EDL BIT(5) | |
| 157 | +#define IFI_CANFD_TXFIFO_DLC_BRS BIT(6) | |
| 158 | +#define IFI_CANFD_TXFIFO_DLC_FNR_OFFSET 24 | |
| 159 | +#define IFI_CANFD_TXFIFO_DLC_FNR_MASK 0xff | |
| 160 | + | |
| 161 | +#define IFI_CANFD_TXFIFO_ID 0xbc | |
| 162 | +#define IFI_CANFD_TXFIFO_ID_ID_OFFSET 0 | |
| 163 | +#define IFI_CANFD_TXFIFO_ID_ID_STD_MASK CAN_SFF_MASK | |
| 164 | +#define IFI_CANFD_TXFIFO_ID_ID_STD_OFFSET 0 | |
| 165 | +#define IFI_CANFD_TXFIFO_ID_ID_STD_WIDTH 10 | |
| 166 | +#define IFI_CANFD_TXFIFO_ID_ID_XTD_MASK CAN_EFF_MASK | |
| 167 | +#define IFI_CANFD_TXFIFO_ID_ID_XTD_OFFSET 11 | |
| 168 | +#define IFI_CANFD_TXFIFO_ID_ID_XTD_WIDTH 18 | |
| 169 | +#define IFI_CANFD_TXFIFO_ID_IDE BIT(29) | |
| 170 | + | |
| 171 | +#define IFI_CANFD_TXFIFO_DATA 0xc0 /* 0xb0..0xfc */ | |
| 172 | + | |
| 173 | +#define IFI_CANFD_FILTER_MASK(n) (0x800 + ((n) * 8) + 0) | |
| 174 | +#define IFI_CANFD_FILTER_MASK_EXT BIT(29) | |
| 175 | +#define IFI_CANFD_FILTER_MASK_EDL BIT(30) | |
| 176 | +#define IFI_CANFD_FILTER_MASK_VALID ((u32)BIT(31)) | |
| 177 | + | |
| 178 | +#define IFI_CANFD_FILTER_IDENT(n) (0x800 + ((n) * 8) + 4) | |
| 179 | +#define IFI_CANFD_FILTER_IDENT_IDE BIT(29) | |
| 180 | +#define IFI_CANFD_FILTER_IDENT_CANFD BIT(30) | |
| 181 | +#define IFI_CANFD_FILTER_IDENT_VALID ((u32)BIT(31)) | |
| 182 | + | |
| 183 | +/* IFI CANFD private data structure */ | |
| 184 | +struct ifi_canfd_priv { | |
| 185 | + struct can_priv can; /* must be the first member */ | |
| 186 | + struct napi_struct napi; | |
| 187 | + struct net_device *ndev; | |
| 188 | + void __iomem *base; | |
| 189 | +}; | |
| 190 | + | |
| 191 | +static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable) | |
| 192 | +{ | |
| 193 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 194 | + u32 enirq = 0; | |
| 195 | + | |
| 196 | + if (enable) { | |
| 197 | + enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY | | |
| 198 | + IFI_CANFD_IRQMASK_RXFIFO_NEMPTY; | |
| 199 | + } | |
| 200 | + | |
| 201 | + writel(IFI_CANFD_IRQMASK_SET_ERR | | |
| 202 | + IFI_CANFD_IRQMASK_SET_TS | | |
| 203 | + IFI_CANFD_IRQMASK_SET_TX | | |
| 204 | + IFI_CANFD_IRQMASK_SET_RX | enirq, | |
| 205 | + priv->base + IFI_CANFD_IRQMASK); | |
| 206 | +} | |
| 207 | + | |
| 208 | +static void ifi_canfd_read_fifo(struct net_device *ndev) | |
| 209 | +{ | |
| 210 | + struct net_device_stats *stats = &ndev->stats; | |
| 211 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 212 | + struct canfd_frame *cf; | |
| 213 | + struct sk_buff *skb; | |
| 214 | + const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY | | |
| 215 | + IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER; | |
| 216 | + u32 rxdlc, rxid; | |
| 217 | + u32 dlc, id; | |
| 218 | + int i; | |
| 219 | + | |
| 220 | + rxdlc = readl(priv->base + IFI_CANFD_RXFIFO_DLC); | |
| 221 | + if (rxdlc & IFI_CANFD_RXFIFO_DLC_EDL) | |
| 222 | + skb = alloc_canfd_skb(ndev, &cf); | |
| 223 | + else | |
| 224 | + skb = alloc_can_skb(ndev, (struct can_frame **)&cf); | |
| 225 | + | |
| 226 | + if (!skb) { | |
| 227 | + stats->rx_dropped++; | |
| 228 | + return; | |
| 229 | + } | |
| 230 | + | |
| 231 | + dlc = (rxdlc >> IFI_CANFD_RXFIFO_DLC_DLC_OFFSET) & | |
| 232 | + IFI_CANFD_RXFIFO_DLC_DLC_MASK; | |
| 233 | + if (rxdlc & IFI_CANFD_RXFIFO_DLC_EDL) | |
| 234 | + cf->len = can_dlc2len(dlc); | |
| 235 | + else | |
| 236 | + cf->len = get_can_dlc(dlc); | |
| 237 | + | |
| 238 | + rxid = readl(priv->base + IFI_CANFD_RXFIFO_ID); | |
| 239 | + id = (rxid >> IFI_CANFD_RXFIFO_ID_ID_OFFSET); | |
| 240 | + if (id & IFI_CANFD_RXFIFO_ID_IDE) { | |
| 241 | + id &= IFI_CANFD_RXFIFO_ID_ID_XTD_MASK; | |
| 242 | + /* | |
| 243 | + * In case the Extended ID frame is received, the standard | |
| 244 | + * and extended part of the ID are swapped in the register, | |
| 245 | + * so swap them back to obtain the correct ID. | |
| 246 | + */ | |
| 247 | + id = (id >> IFI_CANFD_RXFIFO_ID_ID_XTD_OFFSET) | | |
| 248 | + ((id & IFI_CANFD_RXFIFO_ID_ID_STD_MASK) << | |
| 249 | + IFI_CANFD_RXFIFO_ID_ID_XTD_WIDTH); | |
| 250 | + id |= CAN_EFF_FLAG; | |
| 251 | + } else { | |
| 252 | + id &= IFI_CANFD_RXFIFO_ID_ID_STD_MASK; | |
| 253 | + } | |
| 254 | + cf->can_id = id; | |
| 255 | + | |
| 256 | + if (rxdlc & IFI_CANFD_RXFIFO_DLC_ESI) { | |
| 257 | + cf->flags |= CANFD_ESI; | |
| 258 | + netdev_dbg(ndev, "ESI Error\n"); | |
| 259 | + } | |
| 260 | + | |
| 261 | + if (!(rxdlc & IFI_CANFD_RXFIFO_DLC_EDL) && | |
| 262 | + (rxdlc & IFI_CANFD_RXFIFO_DLC_RTR)) { | |
| 263 | + cf->can_id |= CAN_RTR_FLAG; | |
| 264 | + } else { | |
| 265 | + if (rxdlc & IFI_CANFD_RXFIFO_DLC_BRS) | |
| 266 | + cf->flags |= CANFD_BRS; | |
| 267 | + | |
| 268 | + for (i = 0; i < cf->len; i += 4) { | |
| 269 | + *(u32 *)(cf->data + i) = | |
| 270 | + readl(priv->base + IFI_CANFD_RXFIFO_DATA + i); | |
| 271 | + } | |
| 272 | + } | |
| 273 | + | |
| 274 | + /* Remove the packet from FIFO */ | |
| 275 | + writel(IFI_CANFD_RXSTCMD_REMOVE_MSG, priv->base + IFI_CANFD_RXSTCMD); | |
| 276 | + writel(rx_irq_mask, priv->base + IFI_CANFD_INTERRUPT); | |
| 277 | + | |
| 278 | + stats->rx_packets++; | |
| 279 | + stats->rx_bytes += cf->len; | |
| 280 | + | |
| 281 | + netif_receive_skb(skb); | |
| 282 | +} | |
| 283 | + | |
| 284 | +static int ifi_canfd_do_rx_poll(struct net_device *ndev, int quota) | |
| 285 | +{ | |
| 286 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 287 | + u32 pkts = 0; | |
| 288 | + u32 rxst; | |
| 289 | + | |
| 290 | + rxst = readl(priv->base + IFI_CANFD_RXSTCMD); | |
| 291 | + if (rxst & IFI_CANFD_RXSTCMD_EMPTY) { | |
| 292 | + netdev_dbg(ndev, "No messages in RX FIFO\n"); | |
| 293 | + return 0; | |
| 294 | + } | |
| 295 | + | |
| 296 | + for (;;) { | |
| 297 | + if (rxst & IFI_CANFD_RXSTCMD_EMPTY) | |
| 298 | + break; | |
| 299 | + if (quota <= 0) | |
| 300 | + break; | |
| 301 | + | |
| 302 | + ifi_canfd_read_fifo(ndev); | |
| 303 | + quota--; | |
| 304 | + pkts++; | |
| 305 | + rxst = readl(priv->base + IFI_CANFD_RXSTCMD); | |
| 306 | + } | |
| 307 | + | |
| 308 | + if (pkts) | |
| 309 | + can_led_event(ndev, CAN_LED_EVENT_RX); | |
| 310 | + | |
| 311 | + return pkts; | |
| 312 | +} | |
| 313 | + | |
| 314 | +static int ifi_canfd_handle_lost_msg(struct net_device *ndev) | |
| 315 | +{ | |
| 316 | + struct net_device_stats *stats = &ndev->stats; | |
| 317 | + struct sk_buff *skb; | |
| 318 | + struct can_frame *frame; | |
| 319 | + | |
| 320 | + netdev_err(ndev, "RX FIFO overflow, message(s) lost.\n"); | |
| 321 | + | |
| 322 | + stats->rx_errors++; | |
| 323 | + stats->rx_over_errors++; | |
| 324 | + | |
| 325 | + skb = alloc_can_err_skb(ndev, &frame); | |
| 326 | + if (unlikely(!skb)) | |
| 327 | + return 0; | |
| 328 | + | |
| 329 | + frame->can_id |= CAN_ERR_CRTL; | |
| 330 | + frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | |
| 331 | + | |
| 332 | + netif_receive_skb(skb); | |
| 333 | + | |
| 334 | + return 1; | |
| 335 | +} | |
| 336 | + | |
| 337 | +static int ifi_canfd_get_berr_counter(const struct net_device *ndev, | |
| 338 | + struct can_berr_counter *bec) | |
| 339 | +{ | |
| 340 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 341 | + u32 err; | |
| 342 | + | |
| 343 | + err = readl(priv->base + IFI_CANFD_ERROR); | |
| 344 | + bec->rxerr = (err >> IFI_CANFD_ERROR_RX_OFFSET) & | |
| 345 | + IFI_CANFD_ERROR_RX_MASK; | |
| 346 | + bec->txerr = (err >> IFI_CANFD_ERROR_TX_OFFSET) & | |
| 347 | + IFI_CANFD_ERROR_TX_MASK; | |
| 348 | + | |
| 349 | + return 0; | |
| 350 | +} | |
| 351 | + | |
| 352 | +static int ifi_canfd_handle_state_change(struct net_device *ndev, | |
| 353 | + enum can_state new_state) | |
| 354 | +{ | |
| 355 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 356 | + struct net_device_stats *stats = &ndev->stats; | |
| 357 | + struct can_frame *cf; | |
| 358 | + struct sk_buff *skb; | |
| 359 | + struct can_berr_counter bec; | |
| 360 | + | |
| 361 | + switch (new_state) { | |
| 362 | + case CAN_STATE_ERROR_ACTIVE: | |
| 363 | + /* error warning state */ | |
| 364 | + priv->can.can_stats.error_warning++; | |
| 365 | + priv->can.state = CAN_STATE_ERROR_WARNING; | |
| 366 | + break; | |
| 367 | + case CAN_STATE_ERROR_PASSIVE: | |
| 368 | + /* error passive state */ | |
| 369 | + priv->can.can_stats.error_passive++; | |
| 370 | + priv->can.state = CAN_STATE_ERROR_PASSIVE; | |
| 371 | + break; | |
| 372 | + case CAN_STATE_BUS_OFF: | |
| 373 | + /* bus-off state */ | |
| 374 | + priv->can.state = CAN_STATE_BUS_OFF; | |
| 375 | + ifi_canfd_irq_enable(ndev, 0); | |
| 376 | + priv->can.can_stats.bus_off++; | |
| 377 | + can_bus_off(ndev); | |
| 378 | + break; | |
| 379 | + default: | |
| 380 | + break; | |
| 381 | + } | |
| 382 | + | |
| 383 | + /* propagate the error condition to the CAN stack */ | |
| 384 | + skb = alloc_can_err_skb(ndev, &cf); | |
| 385 | + if (unlikely(!skb)) | |
| 386 | + return 0; | |
| 387 | + | |
| 388 | + ifi_canfd_get_berr_counter(ndev, &bec); | |
| 389 | + | |
| 390 | + switch (new_state) { | |
| 391 | + case CAN_STATE_ERROR_ACTIVE: | |
| 392 | + /* error warning state */ | |
| 393 | + cf->can_id |= CAN_ERR_CRTL; | |
| 394 | + cf->data[1] = (bec.txerr > bec.rxerr) ? | |
| 395 | + CAN_ERR_CRTL_TX_WARNING : | |
| 396 | + CAN_ERR_CRTL_RX_WARNING; | |
| 397 | + cf->data[6] = bec.txerr; | |
| 398 | + cf->data[7] = bec.rxerr; | |
| 399 | + break; | |
| 400 | + case CAN_STATE_ERROR_PASSIVE: | |
| 401 | + /* error passive state */ | |
| 402 | + cf->can_id |= CAN_ERR_CRTL; | |
| 403 | + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; | |
| 404 | + if (bec.txerr > 127) | |
| 405 | + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; | |
| 406 | + cf->data[6] = bec.txerr; | |
| 407 | + cf->data[7] = bec.rxerr; | |
| 408 | + break; | |
| 409 | + case CAN_STATE_BUS_OFF: | |
| 410 | + /* bus-off state */ | |
| 411 | + cf->can_id |= CAN_ERR_BUSOFF; | |
| 412 | + break; | |
| 413 | + default: | |
| 414 | + break; | |
| 415 | + } | |
| 416 | + | |
| 417 | + stats->rx_packets++; | |
| 418 | + stats->rx_bytes += cf->can_dlc; | |
| 419 | + netif_receive_skb(skb); | |
| 420 | + | |
| 421 | + return 1; | |
| 422 | +} | |
| 423 | + | |
| 424 | +static int ifi_canfd_handle_state_errors(struct net_device *ndev, u32 stcmd) | |
| 425 | +{ | |
| 426 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 427 | + int work_done = 0; | |
| 428 | + u32 isr; | |
| 429 | + | |
| 430 | + /* | |
| 431 | + * The ErrWarn condition is a little special, since the bit is | |
| 432 | + * located in the INTERRUPT register instead of STCMD register. | |
| 433 | + */ | |
| 434 | + isr = readl(priv->base + IFI_CANFD_INTERRUPT); | |
| 435 | + if ((isr & IFI_CANFD_INTERRUPT_ERROR_WARNING) && | |
| 436 | + (priv->can.state != CAN_STATE_ERROR_WARNING)) { | |
| 437 | + /* Clear the interrupt */ | |
| 438 | + writel(IFI_CANFD_INTERRUPT_ERROR_WARNING, | |
| 439 | + priv->base + IFI_CANFD_INTERRUPT); | |
| 440 | + netdev_dbg(ndev, "Error, entered warning state\n"); | |
| 441 | + work_done += ifi_canfd_handle_state_change(ndev, | |
| 442 | + CAN_STATE_ERROR_WARNING); | |
| 443 | + } | |
| 444 | + | |
| 445 | + if ((stcmd & IFI_CANFD_STCMD_ERROR_PASSIVE) && | |
| 446 | + (priv->can.state != CAN_STATE_ERROR_PASSIVE)) { | |
| 447 | + netdev_dbg(ndev, "Error, entered passive state\n"); | |
| 448 | + work_done += ifi_canfd_handle_state_change(ndev, | |
| 449 | + CAN_STATE_ERROR_PASSIVE); | |
| 450 | + } | |
| 451 | + | |
| 452 | + if ((stcmd & IFI_CANFD_STCMD_BUSOFF) && | |
| 453 | + (priv->can.state != CAN_STATE_BUS_OFF)) { | |
| 454 | + netdev_dbg(ndev, "Error, entered bus-off state\n"); | |
| 455 | + work_done += ifi_canfd_handle_state_change(ndev, | |
| 456 | + CAN_STATE_BUS_OFF); | |
| 457 | + } | |
| 458 | + | |
| 459 | + return work_done; | |
| 460 | +} | |
| 461 | + | |
| 462 | +static int ifi_canfd_poll(struct napi_struct *napi, int quota) | |
| 463 | +{ | |
| 464 | + struct net_device *ndev = napi->dev; | |
| 465 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 466 | + const u32 stcmd_state_mask = IFI_CANFD_STCMD_ERROR_PASSIVE | | |
| 467 | + IFI_CANFD_STCMD_BUSOFF; | |
| 468 | + int work_done = 0; | |
| 469 | + | |
| 470 | + u32 stcmd = readl(priv->base + IFI_CANFD_STCMD); | |
| 471 | + u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD); | |
| 472 | + | |
| 473 | + /* Handle bus state changes */ | |
| 474 | + if ((stcmd & stcmd_state_mask) || | |
| 475 | + ((stcmd & IFI_CANFD_STCMD_ERROR_ACTIVE) == 0)) | |
| 476 | + work_done += ifi_canfd_handle_state_errors(ndev, stcmd); | |
| 477 | + | |
| 478 | + /* Handle lost messages on RX */ | |
| 479 | + if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW) | |
| 480 | + work_done += ifi_canfd_handle_lost_msg(ndev); | |
| 481 | + | |
| 482 | + /* Handle normal messages on RX */ | |
| 483 | + if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY)) | |
| 484 | + work_done += ifi_canfd_do_rx_poll(ndev, quota - work_done); | |
| 485 | + | |
| 486 | + if (work_done < quota) { | |
| 487 | + napi_complete(napi); | |
| 488 | + ifi_canfd_irq_enable(ndev, 1); | |
| 489 | + } | |
| 490 | + | |
| 491 | + return work_done; | |
| 492 | +} | |
| 493 | + | |
| 494 | +static irqreturn_t ifi_canfd_isr(int irq, void *dev_id) | |
| 495 | +{ | |
| 496 | + struct net_device *ndev = (struct net_device *)dev_id; | |
| 497 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 498 | + struct net_device_stats *stats = &ndev->stats; | |
| 499 | + const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY | | |
| 500 | + IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER; | |
| 501 | + const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY | | |
| 502 | + IFI_CANFD_INTERRUPT_TXFIFO_REMOVE; | |
| 503 | + const u32 clr_irq_mask = ~(IFI_CANFD_INTERRUPT_SET_IRQ | | |
| 504 | + IFI_CANFD_INTERRUPT_ERROR_WARNING); | |
| 505 | + u32 isr; | |
| 506 | + | |
| 507 | + isr = readl(priv->base + IFI_CANFD_INTERRUPT); | |
| 508 | + | |
| 509 | + /* No interrupt */ | |
| 510 | + if (isr == 0) | |
| 511 | + return IRQ_NONE; | |
| 512 | + | |
| 513 | + /* Clear all pending interrupts but ErrWarn */ | |
| 514 | + writel(clr_irq_mask, priv->base + IFI_CANFD_INTERRUPT); | |
| 515 | + | |
| 516 | + /* RX IRQ, start NAPI */ | |
| 517 | + if (isr & rx_irq_mask) { | |
| 518 | + ifi_canfd_irq_enable(ndev, 0); | |
| 519 | + napi_schedule(&priv->napi); | |
| 520 | + } | |
| 521 | + | |
| 522 | + /* TX IRQ */ | |
| 523 | + if (isr & tx_irq_mask) { | |
| 524 | + stats->tx_bytes += can_get_echo_skb(ndev, 0); | |
| 525 | + stats->tx_packets++; | |
| 526 | + can_led_event(ndev, CAN_LED_EVENT_TX); | |
| 527 | + netif_wake_queue(ndev); | |
| 528 | + } | |
| 529 | + | |
| 530 | + return IRQ_HANDLED; | |
| 531 | +} | |
| 532 | + | |
| 533 | +static const struct can_bittiming_const ifi_canfd_bittiming_const = { | |
| 534 | + .name = KBUILD_MODNAME, | |
| 535 | + .tseg1_min = 1, /* Time segment 1 = prop_seg + phase_seg1 */ | |
| 536 | + .tseg1_max = 64, | |
| 537 | + .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ | |
| 538 | + .tseg2_max = 64, | |
| 539 | + .sjw_max = 16, | |
| 540 | + .brp_min = 2, | |
| 541 | + .brp_max = 256, | |
| 542 | + .brp_inc = 1, | |
| 543 | +}; | |
| 544 | + | |
| 545 | +static const struct can_bittiming_const ifi_canfd_data_bittiming_const = { | |
| 546 | + .name = KBUILD_MODNAME, | |
| 547 | + .tseg1_min = 1, /* Time segment 1 = prop_seg + phase_seg1 */ | |
| 548 | + .tseg1_max = 64, | |
| 549 | + .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ | |
| 550 | + .tseg2_max = 64, | |
| 551 | + .sjw_max = 16, | |
| 552 | + .brp_min = 2, | |
| 553 | + .brp_max = 256, | |
| 554 | + .brp_inc = 1, | |
| 555 | +}; | |
| 556 | + | |
| 557 | +static void ifi_canfd_set_bittiming(struct net_device *ndev) | |
| 558 | +{ | |
| 559 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 560 | + const struct can_bittiming *bt = &priv->can.bittiming; | |
| 561 | + const struct can_bittiming *dbt = &priv->can.data_bittiming; | |
| 562 | + u16 brp, sjw, tseg1, tseg2; | |
| 563 | + u32 noniso_arg = 0; | |
| 564 | + u32 time_off; | |
| 565 | + | |
| 566 | + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && | |
| 567 | + !(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) { | |
| 568 | + time_off = IFI_CANFD_TIME_SJW_OFF_ISO; | |
| 569 | + } else { | |
| 570 | + noniso_arg = IFI_CANFD_TIME_SET_TIMEB_BOSCH | | |
| 571 | + IFI_CANFD_TIME_SET_TIMEA_BOSCH | | |
| 572 | + IFI_CANFD_TIME_SET_PRESC_BOSCH | | |
| 573 | + IFI_CANFD_TIME_SET_SJW_BOSCH; | |
| 574 | + time_off = IFI_CANFD_TIME_SJW_OFF_BOSCH; | |
| 575 | + } | |
| 576 | + | |
| 577 | + /* Configure bit timing */ | |
| 578 | + brp = bt->brp - 2; | |
| 579 | + sjw = bt->sjw - 1; | |
| 580 | + tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | |
| 581 | + tseg2 = bt->phase_seg2 - 2; | |
| 582 | + writel((tseg2 << IFI_CANFD_TIME_TIMEB_OFF) | | |
| 583 | + (tseg1 << IFI_CANFD_TIME_TIMEA_OFF) | | |
| 584 | + (brp << IFI_CANFD_TIME_PRESCALE_OFF) | | |
| 585 | + (sjw << time_off) | | |
| 586 | + noniso_arg, | |
| 587 | + priv->base + IFI_CANFD_TIME); | |
| 588 | + | |
| 589 | + /* Configure data bit timing */ | |
| 590 | + brp = dbt->brp - 2; | |
| 591 | + sjw = dbt->sjw - 1; | |
| 592 | + tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1; | |
| 593 | + tseg2 = dbt->phase_seg2 - 2; | |
| 594 | + writel((tseg2 << IFI_CANFD_TIME_TIMEB_OFF) | | |
| 595 | + (tseg1 << IFI_CANFD_TIME_TIMEA_OFF) | | |
| 596 | + (brp << IFI_CANFD_TIME_PRESCALE_OFF) | | |
| 597 | + (sjw << time_off) | | |
| 598 | + noniso_arg, | |
| 599 | + priv->base + IFI_CANFD_FTIME); | |
| 600 | +} | |
| 601 | + | |
| 602 | +static void ifi_canfd_set_filter(struct net_device *ndev, const u32 id, | |
| 603 | + const u32 mask, const u32 ident) | |
| 604 | +{ | |
| 605 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 606 | + | |
| 607 | + writel(mask, priv->base + IFI_CANFD_FILTER_MASK(id)); | |
| 608 | + writel(ident, priv->base + IFI_CANFD_FILTER_IDENT(id)); | |
| 609 | +} | |
| 610 | + | |
| 611 | +static void ifi_canfd_set_filters(struct net_device *ndev) | |
| 612 | +{ | |
| 613 | + /* Receive all CAN frames (standard ID) */ | |
| 614 | + ifi_canfd_set_filter(ndev, 0, | |
| 615 | + IFI_CANFD_FILTER_MASK_VALID | | |
| 616 | + IFI_CANFD_FILTER_MASK_EXT, | |
| 617 | + IFI_CANFD_FILTER_IDENT_VALID); | |
| 618 | + | |
| 619 | + /* Receive all CAN frames (extended ID) */ | |
| 620 | + ifi_canfd_set_filter(ndev, 1, | |
| 621 | + IFI_CANFD_FILTER_MASK_VALID | | |
| 622 | + IFI_CANFD_FILTER_MASK_EXT, | |
| 623 | + IFI_CANFD_FILTER_IDENT_VALID | | |
| 624 | + IFI_CANFD_FILTER_IDENT_IDE); | |
| 625 | + | |
| 626 | + /* Receive all CANFD frames */ | |
| 627 | + ifi_canfd_set_filter(ndev, 2, | |
| 628 | + IFI_CANFD_FILTER_MASK_VALID | | |
| 629 | + IFI_CANFD_FILTER_MASK_EDL | | |
| 630 | + IFI_CANFD_FILTER_MASK_EXT, | |
| 631 | + IFI_CANFD_FILTER_IDENT_VALID | | |
| 632 | + IFI_CANFD_FILTER_IDENT_CANFD | | |
| 633 | + IFI_CANFD_FILTER_IDENT_IDE); | |
| 634 | +} | |
| 635 | + | |
| 636 | +static void ifi_canfd_start(struct net_device *ndev) | |
| 637 | +{ | |
| 638 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 639 | + u32 stcmd; | |
| 640 | + | |
| 641 | + /* Reset the IP */ | |
| 642 | + writel(IFI_CANFD_STCMD_HARDRESET, priv->base + IFI_CANFD_STCMD); | |
| 643 | + writel(0, priv->base + IFI_CANFD_STCMD); | |
| 644 | + | |
| 645 | + ifi_canfd_set_bittiming(ndev); | |
| 646 | + ifi_canfd_set_filters(ndev); | |
| 647 | + | |
| 648 | + /* Reset FIFOs */ | |
| 649 | + writel(IFI_CANFD_RXSTCMD_RESET, priv->base + IFI_CANFD_RXSTCMD); | |
| 650 | + writel(0, priv->base + IFI_CANFD_RXSTCMD); | |
| 651 | + writel(IFI_CANFD_TXSTCMD_RESET, priv->base + IFI_CANFD_TXSTCMD); | |
| 652 | + writel(0, priv->base + IFI_CANFD_TXSTCMD); | |
| 653 | + | |
| 654 | + /* Repeat transmission until successful */ | |
| 655 | + writel(0, priv->base + IFI_CANFD_REPEAT); | |
| 656 | + writel(0, priv->base + IFI_CANFD_SUSPEND); | |
| 657 | + | |
| 658 | + /* Clear all pending interrupts */ | |
| 659 | + writel((u32)(~IFI_CANFD_INTERRUPT_SET_IRQ), | |
| 660 | + priv->base + IFI_CANFD_INTERRUPT); | |
| 661 | + | |
| 662 | + stcmd = IFI_CANFD_STCMD_ENABLE | IFI_CANFD_STCMD_NORMAL_MODE; | |
| 663 | + | |
| 664 | + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) | |
| 665 | + stcmd |= IFI_CANFD_STCMD_BUSMONITOR; | |
| 666 | + | |
| 667 | + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) | |
| 668 | + stcmd |= IFI_CANFD_STCMD_LOOPBACK; | |
| 669 | + | |
| 670 | + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) | |
| 671 | + stcmd |= IFI_CANFD_STCMD_ENABLE_ISO; | |
| 672 | + | |
| 673 | + if (!(priv->can.ctrlmode & (CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO))) | |
| 674 | + stcmd |= IFI_CANFD_STCMD_DISABLE_CANFD; | |
| 675 | + | |
| 676 | + priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
| 677 | + | |
| 678 | + ifi_canfd_irq_enable(ndev, 1); | |
| 679 | + | |
| 680 | + /* Enable controller */ | |
| 681 | + writel(stcmd, priv->base + IFI_CANFD_STCMD); | |
| 682 | +} | |
| 683 | + | |
| 684 | +static void ifi_canfd_stop(struct net_device *ndev) | |
| 685 | +{ | |
| 686 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 687 | + | |
| 688 | + /* Reset the IP */ | |
| 689 | + writel(IFI_CANFD_STCMD_HARDRESET, priv->base + IFI_CANFD_STCMD); | |
| 690 | + | |
| 691 | + /* Mask all interrupts */ | |
| 692 | + writel(~0, priv->base + IFI_CANFD_IRQMASK); | |
| 693 | + | |
| 694 | + /* Clear all pending interrupts */ | |
| 695 | + writel((u32)(~IFI_CANFD_INTERRUPT_SET_IRQ), | |
| 696 | + priv->base + IFI_CANFD_INTERRUPT); | |
| 697 | + | |
| 698 | + /* Set the state as STOPPED */ | |
| 699 | + priv->can.state = CAN_STATE_STOPPED; | |
| 700 | +} | |
| 701 | + | |
| 702 | +static int ifi_canfd_set_mode(struct net_device *ndev, enum can_mode mode) | |
| 703 | +{ | |
| 704 | + switch (mode) { | |
| 705 | + case CAN_MODE_START: | |
| 706 | + ifi_canfd_start(ndev); | |
| 707 | + netif_wake_queue(ndev); | |
| 708 | + break; | |
| 709 | + default: | |
| 710 | + return -EOPNOTSUPP; | |
| 711 | + } | |
| 712 | + | |
| 713 | + return 0; | |
| 714 | +} | |
| 715 | + | |
| 716 | +static int ifi_canfd_open(struct net_device *ndev) | |
| 717 | +{ | |
| 718 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 719 | + int ret; | |
| 720 | + | |
| 721 | + ret = open_candev(ndev); | |
| 722 | + if (ret) { | |
| 723 | + netdev_err(ndev, "Failed to open CAN device\n"); | |
| 724 | + return ret; | |
| 725 | + } | |
| 726 | + | |
| 727 | + /* Register interrupt handler */ | |
| 728 | + ret = request_irq(ndev->irq, ifi_canfd_isr, IRQF_SHARED, | |
| 729 | + ndev->name, ndev); | |
| 730 | + if (ret < 0) { | |
| 731 | + netdev_err(ndev, "Failed to request interrupt\n"); | |
| 732 | + goto err_irq; | |
| 733 | + } | |
| 734 | + | |
| 735 | + ifi_canfd_start(ndev); | |
| 736 | + | |
| 737 | + can_led_event(ndev, CAN_LED_EVENT_OPEN); | |
| 738 | + napi_enable(&priv->napi); | |
| 739 | + netif_start_queue(ndev); | |
| 740 | + | |
| 741 | + return 0; | |
| 742 | +err_irq: | |
| 743 | + close_candev(ndev); | |
| 744 | + return ret; | |
| 745 | +} | |
| 746 | + | |
| 747 | +static int ifi_canfd_close(struct net_device *ndev) | |
| 748 | +{ | |
| 749 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 750 | + | |
| 751 | + netif_stop_queue(ndev); | |
| 752 | + napi_disable(&priv->napi); | |
| 753 | + | |
| 754 | + ifi_canfd_stop(ndev); | |
| 755 | + | |
| 756 | + free_irq(ndev->irq, ndev); | |
| 757 | + | |
| 758 | + close_candev(ndev); | |
| 759 | + | |
| 760 | + can_led_event(ndev, CAN_LED_EVENT_STOP); | |
| 761 | + | |
| 762 | + return 0; | |
| 763 | +} | |
| 764 | + | |
| 765 | +static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb, | |
| 766 | + struct net_device *ndev) | |
| 767 | +{ | |
| 768 | + struct ifi_canfd_priv *priv = netdev_priv(ndev); | |
| 769 | + struct canfd_frame *cf = (struct canfd_frame *)skb->data; | |
| 770 | + u32 txst, txid, txdlc; | |
| 771 | + int i; | |
| 772 | + | |
| 773 | + if (can_dropped_invalid_skb(ndev, skb)) | |
| 774 | + return NETDEV_TX_OK; | |
| 775 | + | |
| 776 | + /* Check if the TX buffer is full */ | |
| 777 | + txst = readl(priv->base + IFI_CANFD_TXSTCMD); | |
| 778 | + if (txst & IFI_CANFD_TXSTCMD_FULL) { | |
| 779 | + netif_stop_queue(ndev); | |
| 780 | + netdev_err(ndev, "BUG! TX FIFO full when queue awake!\n"); | |
| 781 | + return NETDEV_TX_BUSY; | |
| 782 | + } | |
| 783 | + | |
| 784 | + netif_stop_queue(ndev); | |
| 785 | + | |
| 786 | + if (cf->can_id & CAN_EFF_FLAG) { | |
| 787 | + txid = cf->can_id & CAN_EFF_MASK; | |
| 788 | + /* | |
| 789 | + * In case the Extended ID frame is transmitted, the | |
| 790 | + * standard and extended part of the ID are swapped | |
| 791 | + * in the register, so swap them back to send the | |
| 792 | + * correct ID. | |
| 793 | + */ | |
| 794 | + txid = (txid >> IFI_CANFD_TXFIFO_ID_ID_XTD_WIDTH) | | |
| 795 | + ((txid & IFI_CANFD_TXFIFO_ID_ID_XTD_MASK) << | |
| 796 | + IFI_CANFD_TXFIFO_ID_ID_XTD_OFFSET); | |
| 797 | + txid |= IFI_CANFD_TXFIFO_ID_IDE; | |
| 798 | + } else { | |
| 799 | + txid = cf->can_id & CAN_SFF_MASK; | |
| 800 | + } | |
| 801 | + | |
| 802 | + txdlc = can_len2dlc(cf->len); | |
| 803 | + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { | |
| 804 | + txdlc |= IFI_CANFD_TXFIFO_DLC_EDL; | |
| 805 | + if (cf->flags & CANFD_BRS) | |
| 806 | + txdlc |= IFI_CANFD_TXFIFO_DLC_BRS; | |
| 807 | + } | |
| 808 | + | |
| 809 | + if (cf->can_id & CAN_RTR_FLAG) | |
| 810 | + txdlc |= IFI_CANFD_TXFIFO_DLC_RTR; | |
| 811 | + | |
| 812 | + /* message ram configuration */ | |
| 813 | + writel(txid, priv->base + IFI_CANFD_TXFIFO_ID); | |
| 814 | + writel(txdlc, priv->base + IFI_CANFD_TXFIFO_DLC); | |
| 815 | + | |
| 816 | + for (i = 0; i < cf->len; i += 4) { | |
| 817 | + writel(*(u32 *)(cf->data + i), | |
| 818 | + priv->base + IFI_CANFD_TXFIFO_DATA + i); | |
| 819 | + } | |
| 820 | + | |
| 821 | + writel(0, priv->base + IFI_CANFD_TXFIFO_REPEATCOUNT); | |
| 822 | + writel(0, priv->base + IFI_CANFD_TXFIFO_SUSPEND_US); | |
| 823 | + | |
| 824 | + can_put_echo_skb(skb, ndev, 0); | |
| 825 | + | |
| 826 | + /* Start the transmission */ | |
| 827 | + writel(IFI_CANFD_TXSTCMD_ADD_MSG, priv->base + IFI_CANFD_TXSTCMD); | |
| 828 | + | |
| 829 | + return NETDEV_TX_OK; | |
| 830 | +} | |
| 831 | + | |
| 832 | +static const struct net_device_ops ifi_canfd_netdev_ops = { | |
| 833 | + .ndo_open = ifi_canfd_open, | |
| 834 | + .ndo_stop = ifi_canfd_close, | |
| 835 | + .ndo_start_xmit = ifi_canfd_start_xmit, | |
| 836 | + .ndo_change_mtu = can_change_mtu, | |
| 837 | +}; | |
| 838 | + | |
| 839 | +static int ifi_canfd_plat_probe(struct platform_device *pdev) | |
| 840 | +{ | |
| 841 | + struct device *dev = &pdev->dev; | |
| 842 | + struct net_device *ndev; | |
| 843 | + struct ifi_canfd_priv *priv; | |
| 844 | + struct resource *res; | |
| 845 | + void __iomem *addr; | |
| 846 | + int irq, ret; | |
| 847 | + u32 id; | |
| 848 | + | |
| 849 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 850 | + addr = devm_ioremap_resource(dev, res); | |
| 851 | + irq = platform_get_irq(pdev, 0); | |
| 852 | + if (IS_ERR(addr) || irq < 0) | |
| 853 | + return -EINVAL; | |
| 854 | + | |
| 855 | + id = readl(addr + IFI_CANFD_IP_ID); | |
| 856 | + if (id != IFI_CANFD_IP_ID_VALUE) { | |
| 857 | + dev_err(dev, "This block is not IFI CANFD, id=%08x\n", id); | |
| 858 | + return -EINVAL; | |
| 859 | + } | |
| 860 | + | |
| 861 | + ndev = alloc_candev(sizeof(*priv), 1); | |
| 862 | + if (!ndev) | |
| 863 | + return -ENOMEM; | |
| 864 | + | |
| 865 | + ndev->irq = irq; | |
| 866 | + ndev->flags |= IFF_ECHO; /* we support local echo */ | |
| 867 | + ndev->netdev_ops = &ifi_canfd_netdev_ops; | |
| 868 | + | |
| 869 | + priv = netdev_priv(ndev); | |
| 870 | + priv->ndev = ndev; | |
| 871 | + priv->base = addr; | |
| 872 | + | |
| 873 | + netif_napi_add(ndev, &priv->napi, ifi_canfd_poll, 64); | |
| 874 | + | |
| 875 | + priv->can.state = CAN_STATE_STOPPED; | |
| 876 | + | |
| 877 | + priv->can.clock.freq = readl(addr + IFI_CANFD_CANCLOCK); | |
| 878 | + | |
| 879 | + priv->can.bittiming_const = &ifi_canfd_bittiming_const; | |
| 880 | + priv->can.data_bittiming_const = &ifi_canfd_data_bittiming_const; | |
| 881 | + priv->can.do_set_mode = ifi_canfd_set_mode; | |
| 882 | + priv->can.do_get_berr_counter = ifi_canfd_get_berr_counter; | |
| 883 | + | |
| 884 | + /* IFI CANFD can do both Bosch FD and ISO FD */ | |
| 885 | + priv->can.ctrlmode = CAN_CTRLMODE_FD; | |
| 886 | + | |
| 887 | + /* IFI CANFD can do both Bosch FD and ISO FD */ | |
| 888 | + priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | | |
| 889 | + CAN_CTRLMODE_LISTENONLY | | |
| 890 | + CAN_CTRLMODE_FD | | |
| 891 | + CAN_CTRLMODE_FD_NON_ISO; | |
| 892 | + | |
| 893 | + platform_set_drvdata(pdev, ndev); | |
| 894 | + SET_NETDEV_DEV(ndev, dev); | |
| 895 | + | |
| 896 | + ret = register_candev(ndev); | |
| 897 | + if (ret) { | |
| 898 | + dev_err(dev, "Failed to register (ret=%d)\n", ret); | |
| 899 | + goto err_reg; | |
| 900 | + } | |
| 901 | + | |
| 902 | + devm_can_led_init(ndev); | |
| 903 | + | |
| 904 | + dev_info(dev, "Driver registered: regs=%p, irq=%d, clock=%d\n", | |
| 905 | + priv->base, ndev->irq, priv->can.clock.freq); | |
| 906 | + | |
| 907 | + return 0; | |
| 908 | + | |
| 909 | +err_reg: | |
| 910 | + free_candev(ndev); | |
| 911 | + return ret; | |
| 912 | +} | |
| 913 | + | |
| 914 | +static int ifi_canfd_plat_remove(struct platform_device *pdev) | |
| 915 | +{ | |
| 916 | + struct net_device *ndev = platform_get_drvdata(pdev); | |
| 917 | + | |
| 918 | + unregister_candev(ndev); | |
| 919 | + platform_set_drvdata(pdev, NULL); | |
| 920 | + free_candev(ndev); | |
| 921 | + | |
| 922 | + return 0; | |
| 923 | +} | |
| 924 | + | |
| 925 | +static const struct of_device_id ifi_canfd_of_table[] = { | |
| 926 | + { .compatible = "ifi,canfd-1.0", .data = NULL }, | |
| 927 | + { /* sentinel */ }, | |
| 928 | +}; | |
| 929 | +MODULE_DEVICE_TABLE(of, ifi_canfd_of_table); | |
| 930 | + | |
| 931 | +static struct platform_driver ifi_canfd_plat_driver = { | |
| 932 | + .driver = { | |
| 933 | + .name = KBUILD_MODNAME, | |
| 934 | + .of_match_table = ifi_canfd_of_table, | |
| 935 | + }, | |
| 936 | + .probe = ifi_canfd_plat_probe, | |
| 937 | + .remove = ifi_canfd_plat_remove, | |
| 938 | +}; | |
| 939 | + | |
| 940 | +module_platform_driver(ifi_canfd_plat_driver); | |
| 941 | + | |
| 942 | +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | |
| 943 | +MODULE_LICENSE("GPL v2"); | |
| 944 | +MODULE_DESCRIPTION("CAN bus driver for IFI CANFD controller"); | |
| @@ -904,6 +904,9 @@ static const struct of_device_id rcar_can_of_table[] __maybe_unused = { · 903 unmodified lines | ||
| 904 | 904 | { .compatible = "renesas,can-r8a7779" }, |
| 905 | 905 | { .compatible = "renesas,can-r8a7790" }, |
| 906 | 906 | { .compatible = "renesas,can-r8a7791" }, |
| 907 | + { .compatible = "renesas,rcar-gen1-can" }, | |
| 908 | + { .compatible = "renesas,rcar-gen2-can" }, | |
| 909 | + { .compatible = "renesas,rcar-gen3-can" }, | |
| 907 | 910 | { } |
| 908 | 911 | }; |
| 909 | 912 | MODULE_DEVICE_TABLE(of, rcar_can_of_table); |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/can/platform/sja1000.h> |
| 28 | 28 | #include <linux/io.h> |
| 29 | 29 | #include <linux/of.h> |
| 30 | +#include <linux/of_device.h> | |
| 30 | 31 | #include <linux/of_irq.h> |
| 31 | 32 | |
| 32 | 33 | #include "sja1000.h" |
| @@ -40,6 +41,15 @@ MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus"); · 7 unmodified lines | ||
| 40 | 41 | MODULE_ALIAS("platform:" DRV_NAME); |
| 41 | 42 | MODULE_LICENSE("GPL v2"); |
| 42 | 43 | |
| 44 | +struct sja1000_of_data { | |
| 45 | + size_t priv_sz; | |
| 46 | + int (*init)(struct sja1000_priv *priv, struct device_node *of); | |
| 47 | +}; | |
| 48 | + | |
| 49 | +struct technologic_priv { | |
| 50 | + spinlock_t io_lock; | |
| 51 | +}; | |
| 52 | + | |
| 43 | 53 | static u8 sp_read_reg8(const struct sja1000_priv *priv, int reg) |
| 44 | 54 | { |
| 45 | 55 | return ioread8(priv->reg_base + reg); |
| @@ -70,6 +80,43 @@ static void sp_write_reg32(const struct sja1000_priv *priv, int reg, u8 val) · 24 unmodified lines | ||
| 70 | 80 | iowrite8(val, priv->reg_base + reg * 4); |
| 71 | 81 | } |
| 72 | 82 | |
| 83 | +static u8 sp_technologic_read_reg16(const struct sja1000_priv *priv, int reg) | |
| 84 | +{ | |
| 85 | + struct technologic_priv *tp = priv->priv; | |
| 86 | + unsigned long flags; | |
| 87 | + u8 val; | |
| 88 | + | |
| 89 | + spin_lock_irqsave(&tp->io_lock, flags); | |
| 90 | + iowrite16(reg, priv->reg_base + 0); | |
| 91 | + val = ioread16(priv->reg_base + 2); | |
| 92 | + spin_unlock_irqrestore(&tp->io_lock, flags); | |
| 93 | + | |
| 94 | + return val; | |
| 95 | +} | |
| 96 | + | |
| 97 | +static void sp_technologic_write_reg16(const struct sja1000_priv *priv, | |
| 98 | + int reg, u8 val) | |
| 99 | +{ | |
| 100 | + struct technologic_priv *tp = priv->priv; | |
| 101 | + unsigned long flags; | |
| 102 | + | |
| 103 | + spin_lock_irqsave(&tp->io_lock, flags); | |
| 104 | + iowrite16(reg, priv->reg_base + 0); | |
| 105 | + iowrite16(val, priv->reg_base + 2); | |
| 106 | + spin_unlock_irqrestore(&tp->io_lock, flags); | |
| 107 | +} | |
| 108 | + | |
| 109 | +static int sp_technologic_init(struct sja1000_priv *priv, struct device_node *of) | |
| 110 | +{ | |
| 111 | + struct technologic_priv *tp = priv->priv; | |
| 112 | + | |
| 113 | + priv->read_reg = sp_technologic_read_reg16; | |
| 114 | + priv->write_reg = sp_technologic_write_reg16; | |
| 115 | + spin_lock_init(&tp->io_lock); | |
| 116 | + | |
| 117 | + return 0; | |
| 118 | +} | |
| 119 | + | |
| 73 | 120 | static void sp_populate(struct sja1000_priv *priv, |
| 74 | 121 | struct sja1000_platform_data *pdata, |
| 75 | 122 | unsigned long resource_mem_flags) |
| @@ -154,6 +201,18 @@ static void sp_populate_of(struct sja1000_priv *priv, struct device_node *of) · 78 unmodified lines | ||
| 154 | 201 | priv->cdr |= CDR_CBP; /* default */ |
| 155 | 202 | } |
| 156 | 203 | |
| 204 | +static struct sja1000_of_data technologic_data = { | |
| 205 | + .priv_sz = sizeof(struct technologic_priv), | |
| 206 | + .init = sp_technologic_init, | |
| 207 | +}; | |
| 208 | + | |
| 209 | +static const struct of_device_id sp_of_table[] = { | |
| 210 | + { .compatible = "nxp,sja1000", .data = NULL, }, | |
| 211 | + { .compatible = "technologic,sja1000", .data = &technologic_data, }, | |
| 212 | + { /* sentinel */ }, | |
| 213 | +}; | |
| 214 | +MODULE_DEVICE_TABLE(of, sp_of_table); | |
| 215 | + | |
| 157 | 216 | static int sp_probe(struct platform_device *pdev) |
| 158 | 217 | { |
| 159 | 218 | int err, irq = 0; |
| @@ -163,6 +222,9 @@ static int sp_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 163 | 222 | struct resource *res_mem, *res_irq = NULL; |
| 164 | 223 | struct sja1000_platform_data *pdata; |
| 165 | 224 | struct device_node *of = pdev->dev.of_node; |
| 225 | + const struct of_device_id *of_id; | |
| 226 | + const struct sja1000_of_data *of_data = NULL; | |
| 227 | + size_t priv_sz = 0; | |
| 166 | 228 | |
| 167 | 229 | pdata = dev_get_platdata(&pdev->dev); |
| 168 | 230 | if (!pdata && !of) { |
| @@ -191,7 +253,13 @@ static int sp_probe(struct platform_device *pdev) · 22 unmodified lines | ||
| 191 | 253 | if (!irq && !res_irq) |
| 192 | 254 | return -ENODEV; |
| 193 | 255 | |
| 194 | − dev = alloc_sja1000dev(0); | |
| 256 | + of_id = of_match_device(sp_of_table, &pdev->dev); | |
| 257 | + if (of_id && of_id->data) { | |
| 258 | + of_data = of_id->data; | |
| 259 | + priv_sz = of_data->priv_sz; | |
| 260 | + } | |
| 261 | + | |
| 262 | + dev = alloc_sja1000dev(priv_sz); | |
| 195 | 263 | if (!dev) |
| 196 | 264 | return -ENOMEM; |
| 197 | 265 | priv = netdev_priv(dev); |
| @@ -208,10 +276,17 @@ static int sp_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 208 | 276 | dev->irq = irq; |
| 209 | 277 | priv->reg_base = addr; |
| 210 | 278 | |
| 211 | − if (of) | |
| 279 | + if (of) { | |
| 212 | 280 | sp_populate_of(priv, of); |
| 213 | − else | |
| 281 | + | |
| 282 | + if (of_data && of_data->init) { | |
| 283 | + err = of_data->init(priv, of); | |
| 284 | + if (err) | |
| 285 | + goto exit_free; | |
| 286 | + } | |
| 287 | + } else { | |
| 214 | 288 | sp_populate(priv, pdata, res_mem->flags); |
| 289 | + } | |
| 215 | 290 | |
| 216 | 291 | platform_set_drvdata(pdev, dev); |
| 217 | 292 | SET_NETDEV_DEV(dev, &pdev->dev); |
| @@ -242,12 +317,6 @@ static int sp_remove(struct platform_device *pdev) · 24 unmodified lines | ||
| 242 | 317 | return 0; |
| 243 | 318 | } |
| 244 | 319 | |
| 245 | −static const struct of_device_id sp_of_table[] = { | |
| 246 | − {.compatible = "nxp,sja1000"}, | |
| 247 | − {}, | |
| 248 | −}; | |
| 249 | −MODULE_DEVICE_TABLE(of, sp_of_table); | |
| 250 | − | |
| 251 | 320 | static struct platform_driver sp_driver = { |
| 252 | 321 | .probe = sp_probe, |
| 253 | 322 | .remove = sp_remove, |
| @@ -281,11 +281,9 @@ static void ems_usb_read_interrupt_callback(struct urb *urb) · 280 unmodified lines | ||
| 281 | 281 | switch (urb->status) { |
| 282 | 282 | case 0: |
| 283 | 283 | dev->free_slots = dev->intr_in_buffer[1]; |
| 284 | − if(dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH){ | |
| 285 | − if (netif_queue_stopped(netdev)){ | |
| 286 | − netif_wake_queue(netdev); | |
| 287 | − } | |
| 288 | − } | |
| 284 | + if (dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH && | |
| 285 | + netif_queue_stopped(netdev)) | |
| 286 | + netif_wake_queue(netdev); | |
| 289 | 287 | break; |
| 290 | 288 | |
| 291 | 289 | case -ECONNRESET: /* unlink */ |
| @@ -27,7 +27,7 @@ config NET_DSA_MV88E6131 · 26 unmodified lines | ||
| 27 | 27 | This enables support for the Marvell 88E6085/6095/6095F/6131 |
| 28 | 28 | ethernet switch chips. |
| 29 | 29 | |
| 30 | −config NET_DSA_MV88E6123_61_65 | |
| 30 | +config NET_DSA_MV88E6123 | |
| 31 | 31 | tristate "Marvell 88E6123/6161/6165 ethernet switch chip support" |
| 32 | 32 | depends on NET_DSA |
| 33 | 33 | select NET_DSA_MV88E6XXX |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o |
| 2 | 2 | obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o |
| 3 | 3 | mv88e6xxx_drv-y += mv88e6xxx.o |
| 4 | −ifdef CONFIG_NET_DSA_MV88E6123_61_65 | |
| 5 | −mv88e6xxx_drv-y += mv88e6123_61_65.o | |
| 4 | +ifdef CONFIG_NET_DSA_MV88E6123 | |
| 5 | +mv88e6xxx_drv-y += mv88e6123.o | |
| 6 | 6 | endif |
| 7 | 7 | ifdef CONFIG_NET_DSA_MV88E6131 |
| 8 | 8 | mv88e6xxx_drv-y += mv88e6131.o |
| @@ -483,16 +483,17 @@ static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port) · 482 unmodified lines | ||
| 483 | 483 | } |
| 484 | 484 | |
| 485 | 485 | static int bcm_sf2_sw_br_join(struct dsa_switch *ds, int port, |
| 486 | − u32 br_port_mask) | |
| 486 | + struct net_device *bridge) | |
| 487 | 487 | { |
| 488 | 488 | struct bcm_sf2_priv *priv = ds_to_priv(ds); |
| 489 | 489 | unsigned int i; |
| 490 | 490 | u32 reg, p_ctl; |
| 491 | 491 | |
| 492 | + priv->port_sts[port].bridge_dev = bridge; | |
| 492 | 493 | p_ctl = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(port)); |
| 493 | 494 | |
| 494 | 495 | for (i = 0; i < priv->hw_params.num_ports; i++) { |
| 495 | − if (!((1 << i) & br_port_mask)) | |
| 496 | + if (priv->port_sts[i].bridge_dev != bridge) | |
| 496 | 497 | continue; |
| 497 | 498 | |
| 498 | 499 | /* Add this local port to the remote port VLAN control |
| @@ -515,10 +516,10 @@ static int bcm_sf2_sw_br_join(struct dsa_switch *ds, int port, · 16 unmodified lines | ||
| 515 | 516 | return 0; |
| 516 | 517 | } |
| 517 | 518 | |
| 518 | −static int bcm_sf2_sw_br_leave(struct dsa_switch *ds, int port, | |
| 519 | − u32 br_port_mask) | |
| 519 | +static void bcm_sf2_sw_br_leave(struct dsa_switch *ds, int port) | |
| 520 | 520 | { |
| 521 | 521 | struct bcm_sf2_priv *priv = ds_to_priv(ds); |
| 522 | + struct net_device *bridge = priv->port_sts[port].bridge_dev; | |
| 522 | 523 | unsigned int i; |
| 523 | 524 | u32 reg, p_ctl; |
| 524 | 525 | |
| @@ -526,7 +527,7 @@ static int bcm_sf2_sw_br_leave(struct dsa_switch *ds, int port, · 1 unmodified line | ||
| 526 | 527 | |
| 527 | 528 | for (i = 0; i < priv->hw_params.num_ports; i++) { |
| 528 | 529 | /* Don't touch the remaining ports */ |
| 529 | − if (!((1 << i) & br_port_mask)) | |
| 530 | + if (priv->port_sts[i].bridge_dev != bridge) | |
| 530 | 531 | continue; |
| 531 | 532 | |
| 532 | 533 | reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i)); |
| @@ -541,8 +542,7 @@ static int bcm_sf2_sw_br_leave(struct dsa_switch *ds, int port, · 8 unmodified lines | ||
| 541 | 542 | |
| 542 | 543 | core_writel(priv, p_ctl, CORE_PORT_VLAN_CTL_PORT(port)); |
| 543 | 544 | priv->port_sts[port].vlan_ctl_mask = p_ctl; |
| 544 | − | |
| 545 | − return 0; | |
| 545 | + priv->port_sts[port].bridge_dev = NULL; | |
| 546 | 546 | } |
| 547 | 547 | |
| 548 | 548 | static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, |
| @@ -1385,8 +1385,8 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = { · 836 unmodified lines | ||
| 1385 | 1385 | .port_disable = bcm_sf2_port_disable, |
| 1386 | 1386 | .get_eee = bcm_sf2_sw_get_eee, |
| 1387 | 1387 | .set_eee = bcm_sf2_sw_set_eee, |
| 1388 | − .port_join_bridge = bcm_sf2_sw_br_join, | |
| 1389 | − .port_leave_bridge = bcm_sf2_sw_br_leave, | |
| 1388 | + .port_bridge_join = bcm_sf2_sw_br_join, | |
| 1389 | + .port_bridge_leave = bcm_sf2_sw_br_leave, | |
| 1390 | 1390 | .port_stp_update = bcm_sf2_sw_br_set_stp_state, |
| 1391 | 1391 | .port_fdb_prepare = bcm_sf2_sw_fdb_prepare, |
| 1392 | 1392 | .port_fdb_add = bcm_sf2_sw_fdb_add, |
| @@ -50,6 +50,8 @@ struct bcm_sf2_port_status { · 49 unmodified lines | ||
| 50 | 50 | struct ethtool_eee eee; |
| 51 | 51 | |
| 52 | 52 | u32 vlan_ctl_mask; |
| 53 | + | |
| 54 | + struct net_device *bridge_dev; | |
| 53 | 55 | }; |
| 54 | 56 | |
| 55 | 57 | struct bcm_sf2_arl_entry { |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <net/dsa.h> |
| 18 | 18 | #include "mv88e6xxx.h" |
| 19 | 19 | |
| 20 | −static const struct mv88e6xxx_switch_id mv88e6123_61_65_table[] = { | |
| 20 | +static const struct mv88e6xxx_switch_id mv88e6123_table[] = { | |
| 21 | 21 | { PORT_SWITCH_ID_6123, "Marvell 88E6123" }, |
| 22 | 22 | { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" }, |
| 23 | 23 | { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" }, |
| @@ -29,13 +29,13 @@ static const struct mv88e6xxx_switch_id mv88e6123_61_65_table[] = { · 5 unmodified lines | ||
| 29 | 29 | { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, |
| 30 | 30 | }; |
| 31 | 31 | |
| 32 | −static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr) | |
| 32 | +static char *mv88e6123_probe(struct device *host_dev, int sw_addr) | |
| 33 | 33 | { |
| 34 | − return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_61_65_table, | |
| 35 | − ARRAY_SIZE(mv88e6123_61_65_table)); | |
| 34 | + return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table, | |
| 35 | + ARRAY_SIZE(mv88e6123_table)); | |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | −static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) | |
| 38 | +static int mv88e6123_setup_global(struct dsa_switch *ds) | |
| 39 | 39 | { |
| 40 | 40 | u32 upstream_port = dsa_upstream_port(ds); |
| 41 | 41 | int ret; |
| @@ -68,7 +68,7 @@ static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) · 26 unmodified lines | ||
| 68 | 68 | return 0; |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | −static int mv88e6123_61_65_setup(struct dsa_switch *ds) | |
| 71 | +static int mv88e6123_setup(struct dsa_switch *ds) | |
| 72 | 72 | { |
| 73 | 73 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
| 74 | 74 | int ret; |
| @@ -93,18 +93,18 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds) · 18 unmodified lines | ||
| 93 | 93 | if (ret < 0) |
| 94 | 94 | return ret; |
| 95 | 95 | |
| 96 | − ret = mv88e6123_61_65_setup_global(ds); | |
| 96 | + ret = mv88e6123_setup_global(ds); | |
| 97 | 97 | if (ret < 0) |
| 98 | 98 | return ret; |
| 99 | 99 | |
| 100 | 100 | return mv88e6xxx_setup_ports(ds); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | −struct dsa_switch_driver mv88e6123_61_65_switch_driver = { | |
| 103 | +struct dsa_switch_driver mv88e6123_switch_driver = { | |
| 104 | 104 | .tag_protocol = DSA_TAG_PROTO_EDSA, |
| 105 | 105 | .priv_size = sizeof(struct mv88e6xxx_priv_state), |
| 106 | − .probe = mv88e6123_61_65_probe, | |
| 107 | − .setup = mv88e6123_61_65_setup, | |
| 106 | + .probe = mv88e6123_probe, | |
| 107 | + .setup = mv88e6123_setup, | |
| 108 | 108 | .set_addr = mv88e6xxx_set_addr_indirect, |
| 109 | 109 | .phy_read = mv88e6xxx_phy_read, |
| 110 | 110 | .phy_write = mv88e6xxx_phy_write, |
| @@ -103,14 +103,14 @@ struct dsa_switch_driver mv88e6171_switch_driver = { · 102 unmodified lines | ||
| 103 | 103 | #endif |
| 104 | 104 | .get_regs_len = mv88e6xxx_get_regs_len, |
| 105 | 105 | .get_regs = mv88e6xxx_get_regs, |
| 106 | − .port_join_bridge = mv88e6xxx_port_bridge_join, | |
| 107 | − .port_leave_bridge = mv88e6xxx_port_bridge_leave, | |
| 106 | + .port_bridge_join = mv88e6xxx_port_bridge_join, | |
| 107 | + .port_bridge_leave = mv88e6xxx_port_bridge_leave, | |
| 108 | 108 | .port_stp_update = mv88e6xxx_port_stp_update, |
| 109 | − .port_pvid_get = mv88e6xxx_port_pvid_get, | |
| 109 | + .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, | |
| 110 | 110 | .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, |
| 111 | 111 | .port_vlan_add = mv88e6xxx_port_vlan_add, |
| 112 | 112 | .port_vlan_del = mv88e6xxx_port_vlan_del, |
| 113 | − .vlan_getnext = mv88e6xxx_vlan_getnext, | |
| 113 | + .port_vlan_dump = mv88e6xxx_port_vlan_dump, | |
| 114 | 114 | .port_fdb_prepare = mv88e6xxx_port_fdb_prepare, |
| 115 | 115 | .port_fdb_add = mv88e6xxx_port_fdb_add, |
| 116 | 116 | .port_fdb_del = mv88e6xxx_port_fdb_del, |
| @@ -324,14 +324,14 @@ struct dsa_switch_driver mv88e6352_switch_driver = { · 323 unmodified lines | ||
| 324 | 324 | .set_eeprom = mv88e6352_set_eeprom, |
| 325 | 325 | .get_regs_len = mv88e6xxx_get_regs_len, |
| 326 | 326 | .get_regs = mv88e6xxx_get_regs, |
| 327 | − .port_join_bridge = mv88e6xxx_port_bridge_join, | |
| 328 | − .port_leave_bridge = mv88e6xxx_port_bridge_leave, | |
| 327 | + .port_bridge_join = mv88e6xxx_port_bridge_join, | |
| 328 | + .port_bridge_leave = mv88e6xxx_port_bridge_leave, | |
| 329 | 329 | .port_stp_update = mv88e6xxx_port_stp_update, |
| 330 | − .port_pvid_get = mv88e6xxx_port_pvid_get, | |
| 330 | + .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, | |
| 331 | 331 | .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, |
| 332 | 332 | .port_vlan_add = mv88e6xxx_port_vlan_add, |
| 333 | 333 | .port_vlan_del = mv88e6xxx_port_vlan_del, |
| 334 | − .vlan_getnext = mv88e6xxx_vlan_getnext, | |
| 334 | + .port_vlan_dump = mv88e6xxx_port_vlan_dump, | |
| 335 | 335 | .port_fdb_prepare = mv88e6xxx_port_fdb_prepare, |
| 336 | 336 | .port_fdb_add = mv88e6xxx_port_fdb_add, |
| 337 | 337 | .port_fdb_del = mv88e6xxx_port_fdb_del, |
| @@ -1051,48 +1051,78 @@ static int _mv88e6xxx_atu_remove(struct dsa_switch *ds, u16 fid, int port, · 1050 unmodified lines | ||
| 1051 | 1051 | return _mv88e6xxx_atu_move(ds, fid, port, 0x0f, static_too); |
| 1052 | 1052 | } |
| 1053 | 1053 | |
| 1054 | −static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state) | |
| 1054 | +static const char * const mv88e6xxx_port_state_names[] = { | |
| 1055 | + [PORT_CONTROL_STATE_DISABLED] = "Disabled", | |
| 1056 | + [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", | |
| 1057 | + [PORT_CONTROL_STATE_LEARNING] = "Learning", | |
| 1058 | + [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", | |
| 1059 | +}; | |
| 1060 | + | |
| 1061 | +static int _mv88e6xxx_port_state(struct dsa_switch *ds, int port, u8 state) | |
| 1055 | 1062 | { |
| 1056 | − struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | |
| 1057 | 1063 | int reg, ret = 0; |
| 1058 | 1064 | u8 oldstate; |
| 1059 | 1065 | |
| 1060 | − mutex_lock(&ps->smi_mutex); | |
| 1061 | − | |
| 1062 | 1066 | reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL); |
| 1063 | − if (reg < 0) { | |
| 1064 | − ret = reg; | |
| 1065 | − goto abort; | |
| 1066 | − } | |
| 1067 | + if (reg < 0) | |
| 1068 | + return reg; | |
| 1067 | 1069 | |
| 1068 | 1070 | oldstate = reg & PORT_CONTROL_STATE_MASK; |
| 1071 | + | |
| 1069 | 1072 | if (oldstate != state) { |
| 1070 | 1073 | /* Flush forwarding database if we're moving a port |
| 1071 | 1074 | * from Learning or Forwarding state to Disabled or |
| 1072 | 1075 | * Blocking or Listening state. |
| 1073 | 1076 | */ |
| 1074 | − if (oldstate >= PORT_CONTROL_STATE_LEARNING && | |
| 1075 | − state <= PORT_CONTROL_STATE_BLOCKING) { | |
| 1077 | + if ((oldstate == PORT_CONTROL_STATE_LEARNING || | |
| 1078 | + oldstate == PORT_CONTROL_STATE_FORWARDING) | |
| 1079 | + && (state == PORT_CONTROL_STATE_DISABLED || | |
| 1080 | + state == PORT_CONTROL_STATE_BLOCKING)) { | |
| 1076 | 1081 | ret = _mv88e6xxx_atu_remove(ds, 0, port, false); |
| 1077 | 1082 | if (ret) |
| 1078 | − goto abort; | |
| 1083 | + return ret; | |
| 1079 | 1084 | } |
| 1085 | + | |
| 1080 | 1086 | reg = (reg & ~PORT_CONTROL_STATE_MASK) | state; |
| 1081 | 1087 | ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL, |
| 1082 | 1088 | reg); |
| 1089 | + if (ret) | |
| 1090 | + return ret; | |
| 1091 | + | |
| 1092 | + netdev_dbg(ds->ports[port], "PortState %s (was %s)\n", | |
| 1093 | + mv88e6xxx_port_state_names[state], | |
| 1094 | + mv88e6xxx_port_state_names[oldstate]); | |
| 1083 | 1095 | } |
| 1084 | 1096 | |
| 1085 | −abort: | |
| 1086 | − mutex_unlock(&ps->smi_mutex); | |
| 1087 | 1097 | return ret; |
| 1088 | 1098 | } |
| 1089 | 1099 | |
| 1090 | −static int _mv88e6xxx_port_vlan_map_set(struct dsa_switch *ds, int port, | |
| 1091 | − u16 output_ports) | |
| 1100 | +static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) | |
| 1092 | 1101 | { |
| 1093 | 1102 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
| 1103 | + struct net_device *bridge = ps->ports[port].bridge_dev; | |
| 1094 | 1104 | const u16 mask = (1 << ps->num_ports) - 1; |
| 1105 | + u16 output_ports = 0; | |
| 1095 | 1106 | int reg; |
| 1107 | + int i; | |
| 1108 | + | |
| 1109 | + /* allow CPU port or DSA link(s) to send frames to every port */ | |
| 1110 | + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { | |
| 1111 | + output_ports = mask; | |
| 1112 | + } else { | |
| 1113 | + for (i = 0; i < ps->num_ports; ++i) { | |
| 1114 | + /* allow sending frames to every group member */ | |
| 1115 | + if (bridge && ps->ports[i].bridge_dev == bridge) | |
| 1116 | + output_ports |= BIT(i); | |
| 1117 | + | |
| 1118 | + /* allow sending frames to CPU port and DSA link(s) */ | |
| 1119 | + if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) | |
| 1120 | + output_ports |= BIT(i); | |
| 1121 | + } | |
| 1122 | + } | |
| 1123 | + | |
| 1124 | + /* prevent frames from going back out of the port they came in on */ | |
| 1125 | + output_ports &= ~BIT(port); | |
| 1096 | 1126 | |
| 1097 | 1127 | reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN); |
| 1098 | 1128 | if (reg < 0) |
| @@ -1126,48 +1156,55 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) · 27 unmodified lines | ||
| 1126 | 1156 | break; |
| 1127 | 1157 | } |
| 1128 | 1158 | |
| 1129 | − netdev_dbg(ds->ports[port], "port state %d [%d]\n", state, stp_state); | |
| 1130 | − | |
| 1131 | 1159 | /* mv88e6xxx_port_stp_update may be called with softirqs disabled, |
| 1132 | 1160 | * so we can not update the port state directly but need to schedule it. |
| 1133 | 1161 | */ |
| 1134 | − ps->port_state[port] = stp_state; | |
| 1135 | − set_bit(port, &ps->port_state_update_mask); | |
| 1162 | + ps->ports[port].state = stp_state; | |
| 1163 | + set_bit(port, ps->port_state_update_mask); | |
| 1136 | 1164 | schedule_work(&ps->bridge_work); |
| 1137 | 1165 | |
| 1138 | 1166 | return 0; |
| 1139 | 1167 | } |
| 1140 | 1168 | |
| 1141 | −static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) | |
| 1169 | +static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new, | |
| 1170 | + u16 *old) | |
| 1142 | 1171 | { |
| 1172 | + u16 pvid; | |
| 1143 | 1173 | int ret; |
| 1144 | 1174 | |
| 1145 | 1175 | ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_DEFAULT_VLAN); |
| 1146 | 1176 | if (ret < 0) |
| 1147 | 1177 | return ret; |
| 1148 | 1178 | |
| 1149 | − *pvid = ret & PORT_DEFAULT_VLAN_MASK; | |
| 1179 | + pvid = ret & PORT_DEFAULT_VLAN_MASK; | |
| 1150 | 1180 | |
| 1151 | − return 0; | |
| 1152 | −} | |
| 1181 | + if (new) { | |
| 1182 | + ret &= ~PORT_DEFAULT_VLAN_MASK; | |
| 1183 | + ret |= *new & PORT_DEFAULT_VLAN_MASK; | |
| 1153 | 1184 | |
| 1154 | −int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) | |
| 1155 | −{ | |
| 1156 | − int ret; | |
| 1185 | + ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), | |
| 1186 | + PORT_DEFAULT_VLAN, ret); | |
| 1187 | + if (ret < 0) | |
| 1188 | + return ret; | |
| 1157 | 1189 | |
| 1158 | − ret = mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_DEFAULT_VLAN); | |
| 1159 | − if (ret < 0) | |
| 1160 | − return ret; | |
| 1190 | + netdev_dbg(ds->ports[port], "DefaultVID %d (was %d)\n", *new, | |
| 1191 | + pvid); | |
| 1192 | + } | |
| 1161 | 1193 | |
| 1162 | − *pvid = ret & PORT_DEFAULT_VLAN_MASK; | |
| 1194 | + if (old) | |
| 1195 | + *old = pvid; | |
| 1163 | 1196 | |
| 1164 | 1197 | return 0; |
| 1165 | 1198 | } |
| 1166 | 1199 | |
| 1200 | +static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) | |
| 1201 | +{ | |
| 1202 | + return _mv88e6xxx_port_pvid(ds, port, NULL, pvid); | |
| 1203 | +} | |
| 1204 | + | |
| 1167 | 1205 | static int _mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid) |
| 1168 | 1206 | { |
| 1169 | − return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN, | |
| 1170 | − pvid & PORT_DEFAULT_VLAN_MASK); | |
| 1207 | + return _mv88e6xxx_port_pvid(ds, port, &pvid, NULL); | |
| 1171 | 1208 | } |
| 1172 | 1209 | |
| 1173 | 1210 | static int _mv88e6xxx_vtu_wait(struct dsa_switch *ds) |
| @@ -1306,6 +1343,57 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, · 132 unmodified lines | ||
| 1306 | 1343 | return 0; |
| 1307 | 1344 | } |
| 1308 | 1345 | |
| 1346 | +int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, | |
| 1347 | + struct switchdev_obj_port_vlan *vlan, | |
| 1348 | + int (*cb)(struct switchdev_obj *obj)) | |
| 1349 | +{ | |
| 1350 | + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | |
| 1351 | + struct mv88e6xxx_vtu_stu_entry next; | |
| 1352 | + u16 pvid; | |
| 1353 | + int err; | |
| 1354 | + | |
| 1355 | + mutex_lock(&ps->smi_mutex); | |
| 1356 | + | |
| 1357 | + err = _mv88e6xxx_port_pvid_get(ds, port, &pvid); | |
| 1358 | + if (err) | |
| 1359 | + goto unlock; | |
| 1360 | + | |
| 1361 | + err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK); | |
| 1362 | + if (err) | |
| 1363 | + goto unlock; | |
| 1364 | + | |
| 1365 | + do { | |
| 1366 | + err = _mv88e6xxx_vtu_getnext(ds, &next); | |
| 1367 | + if (err) | |
| 1368 | + break; | |
| 1369 | + | |
| 1370 | + if (!next.valid) | |
| 1371 | + break; | |
| 1372 | + | |
| 1373 | + if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) | |
| 1374 | + continue; | |
| 1375 | + | |
| 1376 | + /* reinit and dump this VLAN obj */ | |
| 1377 | + vlan->vid_begin = vlan->vid_end = next.vid; | |
| 1378 | + vlan->flags = 0; | |
| 1379 | + | |
| 1380 | + if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED) | |
| 1381 | + vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED; | |
| 1382 | + | |
| 1383 | + if (next.vid == pvid) | |
| 1384 | + vlan->flags |= BRIDGE_VLAN_INFO_PVID; | |
| 1385 | + | |
| 1386 | + err = cb(&vlan->obj); | |
| 1387 | + if (err) | |
| 1388 | + break; | |
| 1389 | + } while (next.vid < GLOBAL_VTU_VID_MASK); | |
| 1390 | + | |
| 1391 | +unlock: | |
| 1392 | + mutex_unlock(&ps->smi_mutex); | |
| 1393 | + | |
| 1394 | + return err; | |
| 1395 | +} | |
| 1396 | + | |
| 1309 | 1397 | static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, |
| 1310 | 1398 | struct mv88e6xxx_vtu_stu_entry *entry) |
| 1311 | 1399 | { |
| @@ -1420,16 +1508,122 @@ loadpurge: · 108 unmodified lines | ||
| 1420 | 1508 | return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_LOAD_PURGE); |
| 1421 | 1509 | } |
| 1422 | 1510 | |
| 1423 | −static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, | |
| 1424 | − struct mv88e6xxx_vtu_stu_entry *entry) | |
| 1511 | +static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, | |
| 1512 | + u16 *old) | |
| 1513 | +{ | |
| 1514 | + u16 fid; | |
| 1515 | + int ret; | |
| 1516 | + | |
| 1517 | + /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */ | |
| 1518 | + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN); | |
| 1519 | + if (ret < 0) | |
| 1520 | + return ret; | |
| 1521 | + | |
| 1522 | + fid = (ret & PORT_BASE_VLAN_FID_3_0_MASK) >> 12; | |
| 1523 | + | |
| 1524 | + if (new) { | |
| 1525 | + ret &= ~PORT_BASE_VLAN_FID_3_0_MASK; | |
| 1526 | + ret |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK; | |
| 1527 | + | |
| 1528 | + ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, | |
| 1529 | + ret); | |
| 1530 | + if (ret < 0) | |
| 1531 | + return ret; | |
| 1532 | + } | |
| 1533 | + | |
| 1534 | + /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */ | |
| 1535 | + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_1); | |
| 1536 | + if (ret < 0) | |
| 1537 | + return ret; | |
| 1538 | + | |
| 1539 | + fid |= (ret & PORT_CONTROL_1_FID_11_4_MASK) << 4; | |
| 1540 | + | |
| 1541 | + if (new) { | |
| 1542 | + ret &= ~PORT_CONTROL_1_FID_11_4_MASK; | |
| 1543 | + ret |= (*new >> 4) & PORT_CONTROL_1_FID_11_4_MASK; | |
| 1544 | + | |
| 1545 | + ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1, | |
| 1546 | + ret); | |
| 1547 | + if (ret < 0) | |
| 1548 | + return ret; | |
| 1549 | + | |
| 1550 | + netdev_dbg(ds->ports[port], "FID %d (was %d)\n", *new, fid); | |
| 1551 | + } | |
| 1552 | + | |
| 1553 | + if (old) | |
| 1554 | + *old = fid; | |
| 1555 | + | |
| 1556 | + return 0; | |
| 1557 | +} | |
| 1558 | + | |
| 1559 | +static int _mv88e6xxx_port_fid_get(struct dsa_switch *ds, int port, u16 *fid) | |
| 1560 | +{ | |
| 1561 | + return _mv88e6xxx_port_fid(ds, port, NULL, fid); | |
| 1562 | +} | |
| 1563 | + | |
| 1564 | +static int _mv88e6xxx_port_fid_set(struct dsa_switch *ds, int port, u16 fid) | |
| 1565 | +{ | |
| 1566 | + return _mv88e6xxx_port_fid(ds, port, &fid, NULL); | |
| 1567 | +} | |
| 1568 | + | |
| 1569 | +static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid) | |
| 1570 | +{ | |
| 1571 | + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | |
| 1572 | + DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID); | |
| 1573 | + struct mv88e6xxx_vtu_stu_entry vlan; | |
| 1574 | + int i, err; | |
| 1575 | + | |
| 1576 | + bitmap_zero(fid_bitmap, MV88E6XXX_N_FID); | |
| 1577 | + | |
| 1578 | + /* Set every FID bit used by the (un)bridged ports */ | |
| 1579 | + for (i = 0; i < ps->num_ports; ++i) { | |
| 1580 | + err = _mv88e6xxx_port_fid_get(ds, i, fid); | |
| 1581 | + if (err) | |
| 1582 | + return err; | |
| 1583 | + | |
| 1584 | + set_bit(*fid, fid_bitmap); | |
| 1585 | + } | |
| 1586 | + | |
| 1587 | + /* Set every FID bit used by the VLAN entries */ | |
| 1588 | + err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK); | |
| 1589 | + if (err) | |
| 1590 | + return err; | |
| 1591 | + | |
| 1592 | + do { | |
| 1593 | + err = _mv88e6xxx_vtu_getnext(ds, &vlan); | |
| 1594 | + if (err) | |
| 1595 | + return err; | |
| 1596 | + | |
| 1597 | + if (!vlan.valid) | |
| 1598 | + break; | |
| 1599 | + | |
| 1600 | + set_bit(vlan.fid, fid_bitmap); | |
| 1601 | + } while (vlan.vid < GLOBAL_VTU_VID_MASK); | |
| 1602 | + | |
| 1603 | + /* The reset value 0x000 is used to indicate that multiple address | |
| 1604 | + * databases are not needed. Return the next positive available. | |
| 1605 | + */ | |
| 1606 | + *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1); | |
| 1607 | + if (unlikely(*fid == MV88E6XXX_N_FID)) | |
| 1608 | + return -ENOSPC; | |
| 1609 | + | |
| 1610 | + /* Clear the database */ | |
| 1611 | + return _mv88e6xxx_atu_flush(ds, *fid, true); | |
| 1612 | +} | |
| 1613 | + | |
| 1614 | +static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid, | |
| 1615 | + struct mv88e6xxx_vtu_stu_entry *entry) | |
| 1425 | 1616 | { |
| 1426 | 1617 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
| 1427 | 1618 | struct mv88e6xxx_vtu_stu_entry vlan = { |
| 1428 | 1619 | .valid = true, |
| 1429 | 1620 | .vid = vid, |
| 1430 | − .fid = vid, /* We use one FID per VLAN */ | |
| 1431 | 1621 | }; |
| 1432 | − int i; | |
| 1622 | + int i, err; | |
| 1623 | + | |
| 1624 | + err = _mv88e6xxx_fid_new(ds, &vlan.fid); | |
| 1625 | + if (err) | |
| 1626 | + return err; | |
| 1433 | 1627 | |
| 1434 | 1628 | /* exclude all ports except the CPU and DSA ports */ |
| 1435 | 1629 | for (i = 0; i < ps->num_ports; ++i) |
| @@ -1440,7 +1634,6 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, · 4 unmodified lines | ||
| 1440 | 1634 | if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || |
| 1441 | 1635 | mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) { |
| 1442 | 1636 | struct mv88e6xxx_vtu_stu_entry vstp; |
| 1443 | − int err; | |
| 1444 | 1637 | |
| 1445 | 1638 | /* Adding a VTU entry requires a valid STU entry. As VSTP is not |
| 1446 | 1639 | * implemented, only one STU entry is needed to cover all VTU |
| @@ -1460,24 +1653,152 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, · 13 unmodified lines | ||
| 1460 | 1653 | if (err) |
| 1461 | 1654 | return err; |
| 1462 | 1655 | } |
| 1463 | − | |
| 1464 | − /* Clear all MAC addresses from the new database */ | |
| 1465 | − err = _mv88e6xxx_atu_flush(ds, vlan.fid, true); | |
| 1466 | − if (err) | |
| 1467 | − return err; | |
| 1468 | 1656 | } |
| 1469 | 1657 | |
| 1470 | 1658 | *entry = vlan; |
| 1471 | 1659 | return 0; |
| 1472 | 1660 | } |
| 1473 | 1661 | |
| 1662 | +static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid, | |
| 1663 | + struct mv88e6xxx_vtu_stu_entry *entry, bool creat) | |
| 1664 | +{ | |
| 1665 | + int err; | |
| 1666 | + | |
| 1667 | + if (!vid) | |
| 1668 | + return -EINVAL; | |
| 1669 | + | |
| 1670 | + err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); | |
| 1671 | + if (err) | |
| 1672 | + return err; | |
| 1673 | + | |
| 1674 | + err = _mv88e6xxx_vtu_getnext(ds, entry); | |
| 1675 | + if (err) | |
| 1676 | + return err; | |
| 1677 | + | |
| 1678 | + if (entry->vid != vid || !entry->valid) { | |
| 1679 | + if (!creat) | |
| 1680 | + return -EOPNOTSUPP; | |
| 1681 | + /* -ENOENT would've been more appropriate, but switchdev expects | |
| 1682 | + * -EOPNOTSUPP to inform bridge about an eventual software VLAN. | |
| 1683 | + */ | |
| 1684 | + | |
| 1685 | + err = _mv88e6xxx_vtu_new(ds, vid, entry); | |
| 1686 | + } | |
| 1687 | + | |
| 1688 | + return err; | |
| 1689 | +} | |
| 1690 | + | |
| 1691 | +static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, | |
| 1692 | + u16 vid_begin, u16 vid_end) | |
| 1693 | +{ | |
| 1694 | + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | |
| 1695 | + struct mv88e6xxx_vtu_stu_entry vlan; | |
| 1696 | + int i, err; | |
| 1697 | + | |
| 1698 | + if (!vid_begin) | |
| 1699 | + return -EOPNOTSUPP; | |
| 1700 | + | |
| 1701 | + mutex_lock(&ps->smi_mutex); | |
| 1702 | + | |
| 1703 | + err = _mv88e6xxx_vtu_vid_write(ds, vid_begin - 1); | |
| 1704 | + if (err) | |
| 1705 | + goto unlock; | |
| 1706 | + | |
| 1707 | + do { | |
| 1708 | + err = _mv88e6xxx_vtu_getnext(ds, &vlan); | |
| 1709 | + if (err) | |
| 1710 | + goto unlock; | |
| 1711 | + | |
| 1712 | + if (!vlan.valid) | |
| 1713 | + break; | |
| 1714 | + | |
| 1715 | + if (vlan.vid > vid_end) | |
| 1716 | + break; | |
| 1717 | + | |
| 1718 | + for (i = 0; i < ps->num_ports; ++i) { | |
| 1719 | + if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i)) | |
| 1720 | + continue; | |
| 1721 | + | |
| 1722 | + if (vlan.data[i] == | |
| 1723 | + GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) | |
| 1724 | + continue; | |
| 1725 | + | |
| 1726 | + if (ps->ports[i].bridge_dev == | |
| 1727 | + ps->ports[port].bridge_dev) | |
| 1728 | + break; /* same bridge, check next VLAN */ | |
| 1729 | + | |
| 1730 | + netdev_warn(ds->ports[port], | |
| 1731 | + "hardware VLAN %d already used by %s\n", | |
| 1732 | + vlan.vid, | |
| 1733 | + netdev_name(ps->ports[i].bridge_dev)); | |
| 1734 | + err = -EOPNOTSUPP; | |
| 1735 | + goto unlock; | |
| 1736 | + } | |
| 1737 | + } while (vlan.vid < vid_end); | |
| 1738 | + | |
| 1739 | +unlock: | |
| 1740 | + mutex_unlock(&ps->smi_mutex); | |
| 1741 | + | |
| 1742 | + return err; | |
| 1743 | +} | |
| 1744 | + | |
| 1745 | +static const char * const mv88e6xxx_port_8021q_mode_names[] = { | |
| 1746 | + [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", | |
| 1747 | + [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", | |
| 1748 | + [PORT_CONTROL_2_8021Q_CHECK] = "Check", | |
| 1749 | + [PORT_CONTROL_2_8021Q_SECURE] = "Secure", | |
| 1750 | +}; | |
| 1751 | + | |
| 1752 | +int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, | |
| 1753 | + bool vlan_filtering) | |
| 1754 | +{ | |
| 1755 | + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | |
| 1756 | + u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : | |
| 1757 | + PORT_CONTROL_2_8021Q_DISABLED; | |
| 1758 | + int ret; | |
| 1759 | + | |
| 1760 | + mutex_lock(&ps->smi_mutex); | |
| 1761 | + | |
| 1762 | + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_2); | |
| 1763 | + if (ret < 0) | |
| 1764 | + goto unlock; | |
| 1765 | + | |
| 1766 | + old = ret & PORT_CONTROL_2_8021Q_MASK; | |
| 1767 | + | |
| 1768 | + if (new != old) { | |
| 1769 | + ret &= ~PORT_CONTROL_2_8021Q_MASK; | |
| 1770 | + ret |= new & PORT_CONTROL_2_8021Q_MASK; | |
| 1771 | + | |
| 1772 | + ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_2, | |
| 1773 | + ret); | |
| 1774 | + if (ret < 0) | |
| 1775 | + goto unlock; | |
| 1776 | + | |
| 1777 | + netdev_dbg(ds->ports[port], "802.1Q Mode %s (was %s)\n", | |
| 1778 | + mv88e6xxx_port_8021q_mode_names[new], | |
| 1779 | + mv88e6xxx_port_8021q_mode_names[old]); | |
| 1780 | + } | |
| 1781 | + | |
| 1782 | + ret = 0; | |
| 1783 | +unlock: | |
| 1784 | + mutex_unlock(&ps->smi_mutex); | |
| 1785 | + | |
| 1786 | + return ret; | |
| 1787 | +} | |
| 1788 | + | |
| 1474 | 1789 | int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, |
| 1475 | 1790 | const struct switchdev_obj_port_vlan *vlan, |
| 1476 | 1791 | struct switchdev_trans *trans) |
| 1477 | 1792 | { |
| 1478 | − /* We reserve a few VLANs to isolate unbridged ports */ | |
| 1479 | − if (vlan->vid_end >= 4000) | |
| 1480 | − return -EOPNOTSUPP; | |
| 1793 | + int err; | |
| 1794 | + | |
| 1795 | + /* If the requested port doesn't belong to the same bridge as the VLAN | |
| 1796 | + * members, do not support it (yet) and fallback to software VLAN. | |
| 1797 | + */ | |
| 1798 | + err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin, | |
| 1799 | + vlan->vid_end); | |
| 1800 | + if (err) | |
| 1801 | + return err; | |
| 1481 | 1802 | |
| 1482 | 1803 | /* We don't need any dynamic resource from the kernel (yet), |
| 1483 | 1804 | * so skip the prepare phase. |
| @@ -1491,20 +1812,10 @@ static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, · 7 unmodified lines | ||
| 1491 | 1812 | struct mv88e6xxx_vtu_stu_entry vlan; |
| 1492 | 1813 | int err; |
| 1493 | 1814 | |
| 1494 | − err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); | |
| 1495 | − if (err) | |
| 1496 | − return err; | |
| 1497 | − | |
| 1498 | − err = _mv88e6xxx_vtu_getnext(ds, &vlan); | |
| 1815 | + err = _mv88e6xxx_vtu_get(ds, vid, &vlan, true); | |
| 1499 | 1816 | if (err) |
| 1500 | 1817 | return err; |
| 1501 | 1818 | |
| 1502 | − if (vlan.vid != vid || !vlan.valid) { | |
| 1503 | − err = _mv88e6xxx_vlan_init(ds, vid, &vlan); | |
| 1504 | − if (err) | |
| 1505 | − return err; | |
| 1506 | − } | |
| 1507 | − | |
| 1508 | 1819 | vlan.data[port] = untagged ? |
| 1509 | 1820 | GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED : |
| 1510 | 1821 | GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED; |
| @@ -1545,16 +1856,12 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) · 34 unmodified lines | ||
| 1545 | 1856 | struct mv88e6xxx_vtu_stu_entry vlan; |
| 1546 | 1857 | int i, err; |
| 1547 | 1858 | |
| 1548 | − err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); | |
| 1549 | − if (err) | |
| 1550 | − return err; | |
| 1551 | − | |
| 1552 | − err = _mv88e6xxx_vtu_getnext(ds, &vlan); | |
| 1859 | + err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false); | |
| 1553 | 1860 | if (err) |
| 1554 | 1861 | return err; |
| 1555 | 1862 | |
| 1556 | − if (vlan.vid != vid || !vlan.valid || | |
| 1557 | − vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) | |
| 1863 | + /* Tell switchdev if this VLAN is handled in software */ | |
| 1864 | + if (vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) | |
| 1558 | 1865 | return -EOPNOTSUPP; |
| 1559 | 1866 | |
| 1560 | 1867 | vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; |
| @@ -1582,7 +1889,6 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, · 21 unmodified lines | ||
| 1582 | 1889 | const struct switchdev_obj_port_vlan *vlan) |
| 1583 | 1890 | { |
| 1584 | 1891 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
| 1585 | − const u16 defpvid = 4000 + ds->index * DSA_MAX_PORTS + port; | |
| 1586 | 1892 | u16 pvid, vid; |
| 1587 | 1893 | int err = 0; |
| 1588 | 1894 | |
| @@ -1598,8 +1904,7 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, · 9 unmodified lines | ||
| 1598 | 1904 | goto unlock; |
| 1599 | 1905 | |
| 1600 | 1906 | if (vid == pvid) { |
| 1601 | − /* restore reserved VLAN ID */ | |
| 1602 | − err = _mv88e6xxx_port_pvid_set(ds, port, defpvid); | |
| 1907 | + err = _mv88e6xxx_port_pvid_set(ds, port, 0); | |
| 1603 | 1908 | if (err) |
| 1604 | 1909 | goto unlock; |
| 1605 | 1910 | } |
| @@ -1611,52 +1916,6 @@ unlock: · 5 unmodified lines | ||
| 1611 | 1916 | return err; |
| 1612 | 1917 | } |
| 1613 | 1918 | |
| 1614 | −int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid, | |
| 1615 | − unsigned long *ports, unsigned long *untagged) | |
| 1616 | −{ | |
| 1617 | − struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | |
| 1618 | − struct mv88e6xxx_vtu_stu_entry next; | |
| 1619 | − int port; | |
| 1620 | − int err; | |
| 1621 | − | |
| 1622 | − if (*vid == 4095) | |
| 1623 | − return -ENOENT; | |
| 1624 | − | |
| 1625 | − mutex_lock(&ps->smi_mutex); | |
| 1626 | − err = _mv88e6xxx_vtu_vid_write(ds, *vid); | |
| 1627 | − if (err) | |
| 1628 | − goto unlock; | |
| 1629 | − | |
| 1630 | − err = _mv88e6xxx_vtu_getnext(ds, &next); | |
| 1631 | −unlock: | |
| 1632 | − mutex_unlock(&ps->smi_mutex); | |
| 1633 | − | |
| 1634 | − if (err) | |
| 1635 | − return err; | |
| 1636 | − | |
| 1637 | − if (!next.valid) | |
| 1638 | − return -ENOENT; | |
| 1639 | − | |
| 1640 | − *vid = next.vid; | |
| 1641 | − | |
| 1642 | − for (port = 0; port < ps->num_ports; ++port) { | |
| 1643 | − clear_bit(port, ports); | |
| 1644 | − clear_bit(port, untagged); | |
| 1645 | − | |
| 1646 | − if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) | |
| 1647 | − continue; | |
| 1648 | − | |
| 1649 | − if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED || | |
| 1650 | − next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED) | |
| 1651 | − set_bit(port, ports); | |
| 1652 | − | |
| 1653 | − if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED) | |
| 1654 | − set_bit(port, untagged); | |
| 1655 | − } | |
| 1656 | − | |
| 1657 | − return 0; | |
| 1658 | −} | |
| 1659 | − | |
| 1660 | 1919 | static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, |
| 1661 | 1920 | const unsigned char *addr) |
| 1662 | 1921 | { |
| @@ -1718,8 +1977,18 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, · 55 unmodified lines | ||
| 1718 | 1977 | u8 state) |
| 1719 | 1978 | { |
| 1720 | 1979 | struct mv88e6xxx_atu_entry entry = { 0 }; |
| 1980 | + struct mv88e6xxx_vtu_stu_entry vlan; | |
| 1981 | + int err; | |
| 1721 | 1982 | |
| 1722 | − entry.fid = vid; /* We use one FID per VLAN */ | |
| 1983 | + /* Null VLAN ID corresponds to the port private database */ | |
| 1984 | + if (vid == 0) | |
| 1985 | + err = _mv88e6xxx_port_fid_get(ds, port, &vlan.fid); | |
| 1986 | + else | |
| 1987 | + err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false); | |
| 1988 | + if (err) | |
| 1989 | + return err; | |
| 1990 | + | |
| 1991 | + entry.fid = vlan.fid; | |
| 1723 | 1992 | entry.state = state; |
| 1724 | 1993 | ether_addr_copy(entry.mac, addr); |
| 1725 | 1994 | if (state != GLOBAL_ATU_DATA_STATE_UNUSED) { |
| @@ -1734,10 +2003,6 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, · 8 unmodified lines | ||
| 1734 | 2003 | const struct switchdev_obj_port_fdb *fdb, |
| 1735 | 2004 | struct switchdev_trans *trans) |
| 1736 | 2005 | { |
| 1737 | − /* We don't use per-port FDB */ | |
| 1738 | − if (fdb->vid == 0) | |
| 1739 | − return -EOPNOTSUPP; | |
| 1740 | − | |
| 1741 | 2006 | /* We don't need any dynamic resource from the kernel (yet), |
| 1742 | 2007 | * so skip the prepare phase. |
| 1743 | 2008 | */ |
| @@ -1824,6 +2089,47 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, · 80 unmodified lines | ||
| 1824 | 2089 | return 0; |
| 1825 | 2090 | } |
| 1826 | 2091 | |
| 2092 | +static int _mv88e6xxx_port_fdb_dump_one(struct dsa_switch *ds, u16 fid, u16 vid, | |
| 2093 | + int port, | |
| 2094 | + struct switchdev_obj_port_fdb *fdb, | |
| 2095 | + int (*cb)(struct switchdev_obj *obj)) | |
| 2096 | +{ | |
| 2097 | + struct mv88e6xxx_atu_entry addr = { | |
| 2098 | + .mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, | |
| 2099 | + }; | |
| 2100 | + int err; | |
| 2101 | + | |
| 2102 | + err = _mv88e6xxx_atu_mac_write(ds, addr.mac); | |
| 2103 | + if (err) | |
| 2104 | + return err; | |
| 2105 | + | |
| 2106 | + do { | |
| 2107 | + err = _mv88e6xxx_atu_getnext(ds, fid, &addr); | |
| 2108 | + if (err) | |
| 2109 | + break; | |
| 2110 | + | |
| 2111 | + if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED) | |
| 2112 | + break; | |
| 2113 | + | |
| 2114 | + if (!addr.trunk && addr.portv_trunkid & BIT(port)) { | |
| 2115 | + bool is_static = addr.state == | |
| 2116 | + (is_multicast_ether_addr(addr.mac) ? | |
| 2117 | + GLOBAL_ATU_DATA_STATE_MC_STATIC : | |
| 2118 | + GLOBAL_ATU_DATA_STATE_UC_STATIC); | |
| 2119 | + | |
| 2120 | + fdb->vid = vid; | |
| 2121 | + ether_addr_copy(fdb->addr, addr.mac); | |
| 2122 | + fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE; | |
| 2123 | + | |
| 2124 | + err = cb(&fdb->obj); | |
| 2125 | + if (err) | |
| 2126 | + break; | |
| 2127 | + } | |
| 2128 | + } while (!is_broadcast_ether_addr(addr.mac)); | |
| 2129 | + | |
| 2130 | + return err; | |
| 2131 | +} | |
| 2132 | + | |
| 1827 | 2133 | int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, |
| 1828 | 2134 | struct switchdev_obj_port_fdb *fdb, |
| 1829 | 2135 | int (*cb)(struct switchdev_obj *obj)) |
| @@ -1832,56 +2138,80 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, · 2 unmodified lines | ||
| 1832 | 2138 | struct mv88e6xxx_vtu_stu_entry vlan = { |
| 1833 | 2139 | .vid = GLOBAL_VTU_VID_MASK, /* all ones */ |
| 1834 | 2140 | }; |
| 2141 | + u16 fid; | |
| 1835 | 2142 | int err; |
| 1836 | 2143 | |
| 1837 | 2144 | mutex_lock(&ps->smi_mutex); |
| 1838 | 2145 | |
| 2146 | + /* Dump port's default Filtering Information Database (VLAN ID 0) */ | |
| 2147 | + err = _mv88e6xxx_port_fid_get(ds, port, &fid); | |
| 2148 | + if (err) | |
| 2149 | + goto unlock; | |
| 2150 | + | |
| 2151 | + err = _mv88e6xxx_port_fdb_dump_one(ds, fid, 0, port, fdb, cb); | |
| 2152 | + if (err) | |
| 2153 | + goto unlock; | |
| 2154 | + | |
| 2155 | + /* Dump VLANs' Filtering Information Databases */ | |
| 1839 | 2156 | err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid); |
| 1840 | 2157 | if (err) |
| 1841 | 2158 | goto unlock; |
| 1842 | 2159 | |
| 1843 | 2160 | do { |
| 1844 | − struct mv88e6xxx_atu_entry addr = { | |
| 1845 | − .mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, | |
| 1846 | − }; | |
| 1847 | − | |
| 1848 | 2161 | err = _mv88e6xxx_vtu_getnext(ds, &vlan); |
| 1849 | 2162 | if (err) |
| 1850 | − goto unlock; | |
| 2163 | + break; | |
| 1851 | 2164 | |
| 1852 | 2165 | if (!vlan.valid) |
| 1853 | 2166 | break; |
| 1854 | 2167 | |
| 1855 | − err = _mv88e6xxx_atu_mac_write(ds, addr.mac); | |
| 2168 | + err = _mv88e6xxx_port_fdb_dump_one(ds, vlan.fid, vlan.vid, port, | |
| 2169 | + fdb, cb); | |
| 1856 | 2170 | if (err) |
| 1857 | − goto unlock; | |
| 2171 | + break; | |
| 2172 | + } while (vlan.vid < GLOBAL_VTU_VID_MASK); | |
| 1858 | 2173 | |
| 1859 | − do { | |
| 1860 | − err = _mv88e6xxx_atu_getnext(ds, vlan.fid, &addr); | |
| 1861 | − if (err) | |
| 1862 | − goto unlock; | |
| 2174 | +unlock: | |
| 2175 | + mutex_unlock(&ps->smi_mutex); | |
| 1863 | 2176 | |
| 1864 | − if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED) | |
| 1865 | − break; | |
| 2177 | + return err; | |
| 2178 | +} | |
| 1866 | 2179 | |
| 1867 | − if (!addr.trunk && addr.portv_trunkid & BIT(port)) { | |
| 1868 | − bool is_static = addr.state == | |
| 1869 | − (is_multicast_ether_addr(addr.mac) ? | |
| 1870 | − GLOBAL_ATU_DATA_STATE_MC_STATIC : | |
| 1871 | − GLOBAL_ATU_DATA_STATE_UC_STATIC); | |
| 2180 | +int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, | |
| 2181 | + struct net_device *bridge) | |
| 2182 | +{ | |
| 2183 | + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); | |
| 2184 | + u16 fid; | |
| 2185 | + int i, err; | |
| 1872 | 2186 | |
| 1873 | − fdb->vid = vlan.vid; | |
| 1874 | − ether_addr_copy(fdb->addr, addr.mac); | |
| 1875 | − fdb->ndm_state = is_static ? NUD_NOARP : | |
| 1876 | − NUD_REACHABLE; | |
| 2187 | + mutex_lock(&ps->smi_mutex); | |
| 1877 | 2188 | |
| 1878 | − err = cb(&fdb->obj); | |
| 1879 | − if (err) | |
| 1880 | − goto unlock; | |
| 1881 | − } | |
| 1882 | − } while (!is_broadcast_ether_addr(addr.mac)); | |
| 2189 | + /* Get or create the bridge FID and assign it to the port */ | |
| 2190 | + for (i = 0; i < ps->num_ports; ++i) | |
| 2191 | + if (ps->ports[i].bridge_dev == bridge) | |
| 2192 | + break; | |
| 1883 | 2193 | |
| 1884 | − } while (vlan.vid < GLOBAL_VTU_VID_MASK); | |
| 2194 | + if (i < ps->num_ports) | |
| 2195 | + err = _mv88e6xxx_port_fid_get(ds, i, &fid); | |
| 2196 | + else | |
| 2197 | + err = _mv88e6xxx_fid_new(ds, &fid); | |
| 2198 | + if (err) | |
| 2199 | + goto unlock; | |
| 2200 | + | |
| 2201 | + err = _mv88e6xxx_port_fid_set(ds, port, fid); | |
| 2202 | + if (err) | |
| 2203 | + goto unlock; | |
| 2204 | + | |
| 2205 | + /* Assign the bridge and remap each port's VLANTable */ | |
| 2206 | + ps->ports[port].bridge_dev = bridge; | |
| 2207 | + | |
| 2208 | + for (i = 0; i < ps->num_ports; ++i) { | |
| 2209 | + if (ps->ports[i].bridge_dev == bridge) { | |
| 2210 | + err = _mv88e6xxx_port_based_vlan_map(ds, i); | |
| 2211 | + if (err) | |
| 2212 | + break; | |
| 2213 | + } | |
| 2214 | + } | |
| 1885 | 2215 | |
| 1886 | 2216 | unlock: |
| 1887 | 2217 | mutex_unlock(&ps->smi_mutex); |
| @@ -1889,28 +2219,29 @@ unlock: · 1 unmodified line | ||
| 1889 | 2219 | return err; |
| 1890 | 2220 | } |
| 1891 | 2221 | |
| 1892 | −int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members) | |
| 1893 | −{ | |
| 1894 | − return 0; | |
| 1895 | −} | |
| 1896 | − | |
| 1897 | −int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members) | |
| 1898 | −{ | |
| 1899 | − return 0; | |
| 1900 | −} | |
| 1901 | − | |
| 1902 | −static int mv88e6xxx_setup_port_default_vlan(struct dsa_switch *ds, int port) | |
| 2222 | +void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port) | |
| 1903 | 2223 | { |
| 1904 | 2224 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
| 1905 | − const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port; | |
| 1906 | − int err; | |
| 2225 | + struct net_device *bridge = ps->ports[port].bridge_dev; | |
| 2226 | + u16 fid; | |
| 2227 | + int i; | |
| 1907 | 2228 | |
| 1908 | 2229 | mutex_lock(&ps->smi_mutex); |
| 1909 | − err = _mv88e6xxx_port_vlan_add(ds, port, pvid, true); | |
| 1910 | − if (!err) | |
| 1911 | − err = _mv88e6xxx_port_pvid_set(ds, port, pvid); | |
| 2230 | + | |
| 2231 | + /* Give the port a fresh Filtering Information Database */ | |
| 2232 | + if (_mv88e6xxx_fid_new(ds, &fid) || | |
| 2233 | + _mv88e6xxx_port_fid_set(ds, port, fid)) | |
| 2234 | + netdev_warn(ds->ports[port], "failed to assign a new FID\n"); | |
| 2235 | + | |
| 2236 | + /* Unassign the bridge and remap each port's VLANTable */ | |
| 2237 | + ps->ports[port].bridge_dev = NULL; | |
| 2238 | + | |
| 2239 | + for (i = 0; i < ps->num_ports; ++i) | |
| 2240 | + if (i == port || ps->ports[i].bridge_dev == bridge) | |
| 2241 | + if (_mv88e6xxx_port_based_vlan_map(ds, i)) | |
| 2242 | + netdev_warn(ds->ports[i], "failed to remap\n"); | |
| 2243 | + | |
| 1912 | 2244 | mutex_unlock(&ps->smi_mutex); |
| 1913 | − return err; | |
| 1914 | 2245 | } |
| 1915 | 2246 | |
| 1916 | 2247 | static void mv88e6xxx_bridge_work(struct work_struct *work) |
| @@ -1922,11 +2253,15 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) · 5 unmodified lines | ||
| 1922 | 2253 | ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work); |
| 1923 | 2254 | ds = ((struct dsa_switch *)ps) - 1; |
| 1924 | 2255 | |
| 1925 | − while (ps->port_state_update_mask) { | |
| 1926 | − port = __ffs(ps->port_state_update_mask); | |
| 1927 | − clear_bit(port, &ps->port_state_update_mask); | |
| 1928 | − mv88e6xxx_set_port_state(ds, port, ps->port_state[port]); | |
| 1929 | − } | |
| 2256 | + mutex_lock(&ps->smi_mutex); | |
| 2257 | + | |
| 2258 | + for (port = 0; port < ps->num_ports; ++port) | |
| 2259 | + if (test_and_clear_bit(port, ps->port_state_update_mask) && | |
| 2260 | + _mv88e6xxx_port_state(ds, port, ps->ports[port].state)) | |
| 2261 | + netdev_warn(ds->ports[port], "failed to update state to %s\n", | |
| 2262 | + mv88e6xxx_port_state_names[ps->ports[port].state]); | |
| 2263 | + | |
| 2264 | + mutex_unlock(&ps->smi_mutex); | |
| 1930 | 2265 | } |
| 1931 | 2266 | |
| 1932 | 2267 | static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) |
| @@ -2033,7 +2368,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 100 unmodified lines | ||
| 2033 | 2368 | } |
| 2034 | 2369 | |
| 2035 | 2370 | /* Port Control 2: don't force a good FCS, set the maximum frame size to |
| 2036 | − * 10240 bytes, enable secure 802.1q tags, don't discard tagged or | |
| 2371 | + * 10240 bytes, disable 802.1q tags checking, don't discard tagged or | |
| 2037 | 2372 | * untagged frames on this port, do a destination address lookup on all |
| 2038 | 2373 | * received packets as usual, disable ARP mirroring and don't send a |
| 2039 | 2374 | * copy of all transmitted/received frames on this port to the CPU. |
| @@ -2058,7 +2393,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 18 unmodified lines | ||
| 2058 | 2393 | reg |= PORT_CONTROL_2_FORWARD_UNKNOWN; |
| 2059 | 2394 | } |
| 2060 | 2395 | |
| 2061 | − reg |= PORT_CONTROL_2_8021Q_SECURE; | |
| 2396 | + reg |= PORT_CONTROL_2_8021Q_DISABLED; | |
| 2062 | 2397 | |
| 2063 | 2398 | if (reg) { |
| 2064 | 2399 | ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), |
| @@ -2155,12 +2490,15 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) · 90 unmodified lines | ||
| 2155 | 2490 | if (ret) |
| 2156 | 2491 | goto abort; |
| 2157 | 2492 | |
| 2158 | − /* Port based VLAN map: do not give each port its own address | |
| 2159 | − * database, and allow every port to egress frames on all other ports. | |
| 2493 | + /* Port based VLAN map: give each port its own address | |
| 2494 | + * database, and allow bidirectional communication between the | |
| 2495 | + * CPU and DSA port(s), and the other ports. | |
| 2160 | 2496 | */ |
| 2161 | − reg = BIT(ps->num_ports) - 1; /* all ports */ | |
| 2162 | − reg &= ~BIT(port); /* except itself */ | |
| 2163 | − ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg); | |
| 2497 | + ret = _mv88e6xxx_port_fid_set(ds, port, port + 1); | |
| 2498 | + if (ret) | |
| 2499 | + goto abort; | |
| 2500 | + | |
| 2501 | + ret = _mv88e6xxx_port_based_vlan_map(ds, port); | |
| 2164 | 2502 | if (ret) |
| 2165 | 2503 | goto abort; |
| 2166 | 2504 | |
| @@ -2184,13 +2522,6 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds) · 17 unmodified lines | ||
| 2184 | 2522 | ret = mv88e6xxx_setup_port(ds, i); |
| 2185 | 2523 | if (ret < 0) |
| 2186 | 2524 | return ret; |
| 2187 | − | |
| 2188 | − if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) | |
| 2189 | − continue; | |
| 2190 | − | |
| 2191 | − ret = mv88e6xxx_setup_port_default_vlan(ds, i); | |
| 2192 | − if (ret < 0) | |
| 2193 | − return ret; | |
| 2194 | 2525 | } |
| 2195 | 2526 | return 0; |
| 2196 | 2527 | } |
| @@ -2648,8 +2979,8 @@ static int __init mv88e6xxx_init(void) · 451 unmodified lines | ||
| 2648 | 2979 | #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) |
| 2649 | 2980 | register_switch_driver(&mv88e6131_switch_driver); |
| 2650 | 2981 | #endif |
| 2651 | −#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65) | |
| 2652 | − register_switch_driver(&mv88e6123_61_65_switch_driver); | |
| 2982 | +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123) | |
| 2983 | + register_switch_driver(&mv88e6123_switch_driver); | |
| 2653 | 2984 | #endif |
| 2654 | 2985 | #if IS_ENABLED(CONFIG_NET_DSA_MV88E6352) |
| 2655 | 2986 | register_switch_driver(&mv88e6352_switch_driver); |
| @@ -2669,8 +3000,8 @@ static void __exit mv88e6xxx_cleanup(void) · 13 unmodified lines | ||
| 2669 | 3000 | #if IS_ENABLED(CONFIG_NET_DSA_MV88E6352) |
| 2670 | 3001 | unregister_switch_driver(&mv88e6352_switch_driver); |
| 2671 | 3002 | #endif |
| 2672 | −#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65) | |
| 2673 | − unregister_switch_driver(&mv88e6123_61_65_switch_driver); | |
| 3003 | +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123) | |
| 3004 | + unregister_switch_driver(&mv88e6123_switch_driver); | |
| 2674 | 3005 | #endif |
| 2675 | 3006 | #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) |
| 2676 | 3007 | unregister_switch_driver(&mv88e6131_switch_driver); |
| @@ -133,7 +133,9 @@ · 132 unmodified lines | ||
| 133 | 133 | #define PORT_CONTROL_STATE_LEARNING 0x02 |
| 134 | 134 | #define PORT_CONTROL_STATE_FORWARDING 0x03 |
| 135 | 135 | #define PORT_CONTROL_1 0x05 |
| 136 | +#define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0) | |
| 136 | 137 | #define PORT_BASE_VLAN 0x06 |
| 138 | +#define PORT_BASE_VLAN_FID_3_0_MASK (0xf << 12) | |
| 137 | 139 | #define PORT_DEFAULT_VLAN 0x07 |
| 138 | 140 | #define PORT_DEFAULT_VLAN_MASK 0xfff |
| 139 | 141 | #define PORT_CONTROL_2 0x08 |
| @@ -355,6 +357,8 @@ · 215 unmodified lines | ||
| 355 | 357 | #define GLOBAL2_QOS_WEIGHT 0x1c |
| 356 | 358 | #define GLOBAL2_MISC 0x1d |
| 357 | 359 | |
| 360 | +#define MV88E6XXX_N_FID 4096 | |
| 361 | + | |
| 358 | 362 | struct mv88e6xxx_switch_id { |
| 359 | 363 | u16 id; |
| 360 | 364 | char *name; |
| @@ -379,6 +383,11 @@ struct mv88e6xxx_vtu_stu_entry { · 18 unmodified lines | ||
| 379 | 383 | u8 data[DSA_MAX_PORTS]; |
| 380 | 384 | }; |
| 381 | 385 | |
| 386 | +struct mv88e6xxx_priv_port { | |
| 387 | + struct net_device *bridge_dev; | |
| 388 | + u8 state; | |
| 389 | +}; | |
| 390 | + | |
| 382 | 391 | struct mv88e6xxx_priv_state { |
| 383 | 392 | /* When using multi-chip addressing, this mutex protects |
| 384 | 393 | * access to the indirect access registers. (In single-chip |
| @@ -415,8 +424,9 @@ struct mv88e6xxx_priv_state { · 30 unmodified lines | ||
| 415 | 424 | int id; /* switch product id */ |
| 416 | 425 | int num_ports; /* number of switch ports */ |
| 417 | 426 | |
| 418 | − unsigned long port_state_update_mask; | |
| 419 | − u8 port_state[DSA_MAX_PORTS]; | |
| 427 | + struct mv88e6xxx_priv_port ports[DSA_MAX_PORTS]; | |
| 428 | + | |
| 429 | + DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS); | |
| 420 | 430 | |
| 421 | 431 | struct work_struct bridge_work; |
| 422 | 432 | }; |
| @@ -476,9 +486,12 @@ int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum, · 53 unmodified lines | ||
| 476 | 486 | int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e); |
| 477 | 487 | int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, |
| 478 | 488 | struct phy_device *phydev, struct ethtool_eee *e); |
| 479 | −int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members); | |
| 480 | −int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members); | |
| 489 | +int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, | |
| 490 | + struct net_device *bridge); | |
| 491 | +void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port); | |
| 481 | 492 | int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); |
| 493 | +int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, | |
| 494 | + bool vlan_filtering); | |
| 482 | 495 | int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, |
| 483 | 496 | const struct switchdev_obj_port_vlan *vlan, |
| 484 | 497 | struct switchdev_trans *trans); |
| @@ -487,9 +500,9 @@ int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, · 2 unmodified lines | ||
| 487 | 500 | struct switchdev_trans *trans); |
| 488 | 501 | int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, |
| 489 | 502 | const struct switchdev_obj_port_vlan *vlan); |
| 490 | −int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *vid); | |
| 491 | −int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid, | |
| 492 | − unsigned long *ports, unsigned long *untagged); | |
| 503 | +int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, | |
| 504 | + struct switchdev_obj_port_vlan *vlan, | |
| 505 | + int (*cb)(struct switchdev_obj *obj)); | |
| 493 | 506 | int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, |
| 494 | 507 | const struct switchdev_obj_port_fdb *fdb, |
| 495 | 508 | struct switchdev_trans *trans); |
| @@ -506,7 +519,7 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, · 10 unmodified lines | ||
| 506 | 519 | int reg, int val); |
| 507 | 520 | |
| 508 | 521 | extern struct dsa_switch_driver mv88e6131_switch_driver; |
| 509 | −extern struct dsa_switch_driver mv88e6123_61_65_switch_driver; | |
| 522 | +extern struct dsa_switch_driver mv88e6123_switch_driver; | |
| 510 | 523 | extern struct dsa_switch_driver mv88e6352_switch_driver; |
| 511 | 524 | extern struct dsa_switch_driver mv88e6171_switch_driver; |
| 512 | 525 | |
| @@ -1601,15 +1601,9 @@ vortex_up(struct net_device *dev) · 1600 unmodified lines | ||
| 1601 | 1601 | dev->name, media_tbl[dev->if_port].name); |
| 1602 | 1602 | } |
| 1603 | 1603 | |
| 1604 | − init_timer(&vp->timer); | |
| 1605 | − vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); | |
| 1606 | − vp->timer.data = (unsigned long)dev; | |
| 1607 | − vp->timer.function = vortex_timer; /* timer handler */ | |
| 1608 | − add_timer(&vp->timer); | |
| 1609 | − | |
| 1610 | − init_timer(&vp->rx_oom_timer); | |
| 1611 | − vp->rx_oom_timer.data = (unsigned long)dev; | |
| 1612 | − vp->rx_oom_timer.function = rx_oom_timer; | |
| 1604 | + setup_timer(&vp->timer, vortex_timer, (unsigned long)dev); | |
| 1605 | + mod_timer(&vp->timer, RUN_AT(media_tbl[dev->if_port].wait)); | |
| 1606 | + setup_timer(&vp->rx_oom_timer, rx_oom_timer, (unsigned long)dev); | |
| 1613 | 1607 | |
| 1614 | 1608 | if (vortex_debug > 1) |
| 1615 | 1609 | pr_debug("%s: Initial media type %s.\n", |
| @@ -106,6 +106,7 @@ config LANTIQ_ETOP · 105 unmodified lines | ||
| 106 | 106 | Support for the MII0 inside the Lantiq SoC |
| 107 | 107 | |
| 108 | 108 | source "drivers/net/ethernet/marvell/Kconfig" |
| 109 | +source "drivers/net/ethernet/mediatek/Kconfig" | |
| 109 | 110 | source "drivers/net/ethernet/mellanox/Kconfig" |
| 110 | 111 | source "drivers/net/ethernet/micrel/Kconfig" |
| 111 | 112 | source "drivers/net/ethernet/microchip/Kconfig" |
| @@ -138,7 +139,6 @@ config NET_NETX · 26 unmodified lines | ||
| 138 | 139 | source "drivers/net/ethernet/nuvoton/Kconfig" |
| 139 | 140 | source "drivers/net/ethernet/nvidia/Kconfig" |
| 140 | 141 | source "drivers/net/ethernet/nxp/Kconfig" |
| 141 | −source "drivers/net/ethernet/octeon/Kconfig" | |
| 142 | 142 | source "drivers/net/ethernet/oki-semi/Kconfig" |
| 143 | 143 | |
| 144 | 144 | config ETHOC |
| @@ -46,6 +46,7 @@ obj-$(CONFIG_JME) += jme.o · 45 unmodified lines | ||
| 46 | 46 | obj-$(CONFIG_KORINA) += korina.o |
| 47 | 47 | obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o |
| 48 | 48 | obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/ |
| 49 | +obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/ | |
| 49 | 50 | obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/ |
| 50 | 51 | obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/ |
| 51 | 52 | obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ |
| @@ -58,7 +59,6 @@ obj-$(CONFIG_NET_NETX) += netx-eth.o · 6 unmodified lines | ||
| 58 | 59 | obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/ |
| 59 | 60 | obj-$(CONFIG_NET_VENDOR_NVIDIA) += nvidia/ |
| 60 | 61 | obj-$(CONFIG_LPC_ENET) += nxp/ |
| 61 | −obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/ | |
| 62 | 62 | obj-$(CONFIG_NET_VENDOR_OKI) += oki-semi/ |
| 63 | 63 | obj-$(CONFIG_ETHOC) += ethoc.o |
| 64 | 64 | obj-$(CONFIG_NET_PACKET_ENGINE) += packetengines/ |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -768,12 +768,16 @@ · 705 unmodified lines | ||
| 768 | 768 | #define MTL_Q_TQDR 0x08 |
| 769 | 769 | #define MTL_Q_RQOMR 0x40 |
| 770 | 770 | #define MTL_Q_RQMPOCR 0x44 |
| 771 | −#define MTL_Q_RQDR 0x4c | |
| 771 | +#define MTL_Q_RQDR 0x48 | |
| 772 | 772 | #define MTL_Q_RQFCR 0x50 |
| 773 | 773 | #define MTL_Q_IER 0x70 |
| 774 | 774 | #define MTL_Q_ISR 0x74 |
| 775 | 775 | |
| 776 | 776 | /* MTL queue register entry bit positions and sizes */ |
| 777 | +#define MTL_Q_RQDR_PRXQ_INDEX 16 | |
| 778 | +#define MTL_Q_RQDR_PRXQ_WIDTH 14 | |
| 779 | +#define MTL_Q_RQDR_RXQSTS_INDEX 4 | |
| 780 | +#define MTL_Q_RQDR_RXQSTS_WIDTH 2 | |
| 777 | 781 | #define MTL_Q_RQFCR_RFA_INDEX 1 |
| 778 | 782 | #define MTL_Q_RQFCR_RFA_WIDTH 6 |
| 779 | 783 | #define MTL_Q_RQFCR_RFD_INDEX 17 |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -146,6 +146,7 @@ static int xgbe_dcb_ieee_setets(struct net_device *netdev, · 83 unmodified lines | ||
| 146 | 146 | { |
| 147 | 147 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
| 148 | 148 | unsigned int i, tc_ets, tc_ets_weight; |
| 149 | + u8 max_tc = 0; | |
| 149 | 150 | |
| 150 | 151 | tc_ets = 0; |
| 151 | 152 | tc_ets_weight = 0; |
| @@ -157,12 +158,9 @@ static int xgbe_dcb_ieee_setets(struct net_device *netdev, · 5 unmodified lines | ||
| 157 | 158 | netif_dbg(pdata, drv, netdev, "PRIO%u: TC=%hhu\n", i, |
| 158 | 159 | ets->prio_tc[i]); |
| 159 | 160 | |
| 160 | − if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && | |
| 161 | − (i >= pdata->hw_feat.tc_cnt)) | |
| 162 | − return -EINVAL; | |
| 163 | − | |
| 164 | − if (ets->prio_tc[i] >= pdata->hw_feat.tc_cnt) | |
| 165 | − return -EINVAL; | |
| 161 | + max_tc = max_t(u8, max_tc, ets->prio_tc[i]); | |
| 162 | + if ((ets->tc_tx_bw[i] || ets->tc_tsa[i])) | |
| 163 | + max_tc = max_t(u8, max_tc, i); | |
| 166 | 164 | |
| 167 | 165 | switch (ets->tc_tsa[i]) { |
| 168 | 166 | case IEEE_8021QAZ_TSA_STRICT: |
| @@ -171,15 +169,28 @@ static int xgbe_dcb_ieee_setets(struct net_device *netdev, · 2 unmodified lines | ||
| 171 | 169 | tc_ets = 1; |
| 172 | 170 | tc_ets_weight += ets->tc_tx_bw[i]; |
| 173 | 171 | break; |
| 174 | − | |
| 175 | 172 | default: |
| 173 | + netif_err(pdata, drv, netdev, | |
| 174 | + "unsupported TSA algorithm (%hhu)\n", | |
| 175 | + ets->tc_tsa[i]); | |
| 176 | 176 | return -EINVAL; |
| 177 | 177 | } |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | + /* Check maximum traffic class requested */ | |
| 181 | + if (max_tc >= pdata->hw_feat.tc_cnt) { | |
| 182 | + netif_err(pdata, drv, netdev, | |
| 183 | + "exceeded number of supported traffic classes\n"); | |
| 184 | + return -EINVAL; | |
| 185 | + } | |
| 186 | + | |
| 180 | 187 | /* Weights must add up to 100% */ |
| 181 | − if (tc_ets && (tc_ets_weight != 100)) | |
| 188 | + if (tc_ets && (tc_ets_weight != 100)) { | |
| 189 | + netif_err(pdata, drv, netdev, | |
| 190 | + "sum of ETS algorithm weights is not 100 (%u)\n", | |
| 191 | + tc_ets_weight); | |
| 182 | 192 | return -EINVAL; |
| 193 | + } | |
| 183 | 194 | |
| 184 | 195 | if (!pdata->ets) { |
| 185 | 196 | pdata->ets = devm_kzalloc(pdata->dev, sizeof(*pdata->ets), |
| @@ -188,6 +199,7 @@ static int xgbe_dcb_ieee_setets(struct net_device *netdev, · 2 unmodified lines | ||
| 188 | 199 | return -ENOMEM; |
| 189 | 200 | } |
| 190 | 201 | |
| 202 | + pdata->num_tcs = max_tc + 1; | |
| 191 | 203 | memcpy(pdata->ets, ets, sizeof(*pdata->ets)); |
| 192 | 204 | |
| 193 | 205 | pdata->hw_if.config_dcb_tc(pdata); |
| @@ -221,6 +233,13 @@ static int xgbe_dcb_ieee_setpfc(struct net_device *netdev, · 27 unmodified lines | ||
| 221 | 233 | "cap=%hhu, en=%#hhx, mbc=%hhu, delay=%hhu\n", |
| 222 | 234 | pfc->pfc_cap, pfc->pfc_en, pfc->mbc, pfc->delay); |
| 223 | 235 | |
| 236 | + /* Check PFC for supported number of traffic classes */ | |
| 237 | + if (pfc->pfc_en & ~((1 << pdata->hw_feat.tc_cnt) - 1)) { | |
| 238 | + netif_err(pdata, drv, netdev, | |
| 239 | + "PFC requested for unsupported traffic class\n"); | |
| 240 | + return -EINVAL; | |
| 241 | + } | |
| 242 | + | |
| 224 | 243 | if (!pdata->pfc) { |
| 225 | 244 | pdata->pfc = devm_kzalloc(pdata->dev, sizeof(*pdata->pfc), |
| 226 | 245 | GFP_KERNEL); |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -518,13 +518,45 @@ static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) · 455 unmodified lines | ||
| 518 | 518 | |
| 519 | 519 | static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata) |
| 520 | 520 | { |
| 521 | + struct ieee_pfc *pfc = pdata->pfc; | |
| 522 | + struct ieee_ets *ets = pdata->ets; | |
| 521 | 523 | unsigned int max_q_count, q_count; |
| 522 | 524 | unsigned int reg, reg_val; |
| 523 | 525 | unsigned int i; |
| 524 | 526 | |
| 525 | 527 | /* Set MTL flow control */ |
| 526 | − for (i = 0; i < pdata->rx_q_count; i++) | |
| 527 | − XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 1); | |
| 528 | + for (i = 0; i < pdata->rx_q_count; i++) { | |
| 529 | + unsigned int ehfc = 0; | |
| 530 | + | |
| 531 | + if (pfc && ets) { | |
| 532 | + unsigned int prio; | |
| 533 | + | |
| 534 | + for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { | |
| 535 | + unsigned int tc; | |
| 536 | + | |
| 537 | + /* Does this queue handle the priority? */ | |
| 538 | + if (pdata->prio2q_map[prio] != i) | |
| 539 | + continue; | |
| 540 | + | |
| 541 | + /* Get the Traffic Class for this priority */ | |
| 542 | + tc = ets->prio_tc[prio]; | |
| 543 | + | |
| 544 | + /* Check if flow control should be enabled */ | |
| 545 | + if (pfc->pfc_en & (1 << tc)) { | |
| 546 | + ehfc = 1; | |
| 547 | + break; | |
| 548 | + } | |
| 549 | + } | |
| 550 | + } else { | |
| 551 | + ehfc = 1; | |
| 552 | + } | |
| 553 | + | |
| 554 | + XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, ehfc); | |
| 555 | + | |
| 556 | + netif_dbg(pdata, drv, pdata->netdev, | |
| 557 | + "flow control %s for RXq%u\n", | |
| 558 | + ehfc ? "enabled" : "disabled", i); | |
| 559 | + } | |
| 528 | 560 | |
| 529 | 561 | /* Set MAC flow control */ |
| 530 | 562 | max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES; |
| @@ -702,6 +734,113 @@ static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata) · 171 unmodified lines | ||
| 702 | 734 | return 0; |
| 703 | 735 | } |
| 704 | 736 | |
| 737 | +static int xgbe_enable_rx_vlan_stripping(struct xgbe_prv_data *pdata) | |
| 738 | +{ | |
| 739 | + /* Put the VLAN tag in the Rx descriptor */ | |
| 740 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLRXS, 1); | |
| 741 | + | |
| 742 | + /* Don't check the VLAN type */ | |
| 743 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, DOVLTC, 1); | |
| 744 | + | |
| 745 | + /* Check only C-TAG (0x8100) packets */ | |
| 746 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ERSVLM, 0); | |
| 747 | + | |
| 748 | + /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */ | |
| 749 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ESVL, 0); | |
| 750 | + | |
| 751 | + /* Enable VLAN tag stripping */ | |
| 752 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0x3); | |
| 753 | + | |
| 754 | + return 0; | |
| 755 | +} | |
| 756 | + | |
| 757 | +static int xgbe_disable_rx_vlan_stripping(struct xgbe_prv_data *pdata) | |
| 758 | +{ | |
| 759 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0); | |
| 760 | + | |
| 761 | + return 0; | |
| 762 | +} | |
| 763 | + | |
| 764 | +static int xgbe_enable_rx_vlan_filtering(struct xgbe_prv_data *pdata) | |
| 765 | +{ | |
| 766 | + /* Enable VLAN filtering */ | |
| 767 | + XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1); | |
| 768 | + | |
| 769 | + /* Enable VLAN Hash Table filtering */ | |
| 770 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1); | |
| 771 | + | |
| 772 | + /* Disable VLAN tag inverse matching */ | |
| 773 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0); | |
| 774 | + | |
| 775 | + /* Only filter on the lower 12-bits of the VLAN tag */ | |
| 776 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1); | |
| 777 | + | |
| 778 | + /* In order for the VLAN Hash Table filtering to be effective, | |
| 779 | + * the VLAN tag identifier in the VLAN Tag Register must not | |
| 780 | + * be zero. Set the VLAN tag identifier to "1" to enable the | |
| 781 | + * VLAN Hash Table filtering. This implies that a VLAN tag of | |
| 782 | + * 1 will always pass filtering. | |
| 783 | + */ | |
| 784 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1); | |
| 785 | + | |
| 786 | + return 0; | |
| 787 | +} | |
| 788 | + | |
| 789 | +static int xgbe_disable_rx_vlan_filtering(struct xgbe_prv_data *pdata) | |
| 790 | +{ | |
| 791 | + /* Disable VLAN filtering */ | |
| 792 | + XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0); | |
| 793 | + | |
| 794 | + return 0; | |
| 795 | +} | |
| 796 | + | |
| 797 | +static u32 xgbe_vid_crc32_le(__le16 vid_le) | |
| 798 | +{ | |
| 799 | + u32 poly = 0xedb88320; /* CRCPOLY_LE */ | |
| 800 | + u32 crc = ~0; | |
| 801 | + u32 temp = 0; | |
| 802 | + unsigned char *data = (unsigned char *)&vid_le; | |
| 803 | + unsigned char data_byte = 0; | |
| 804 | + int i, bits; | |
| 805 | + | |
| 806 | + bits = get_bitmask_order(VLAN_VID_MASK); | |
| 807 | + for (i = 0; i < bits; i++) { | |
| 808 | + if ((i % 8) == 0) | |
| 809 | + data_byte = data[i / 8]; | |
| 810 | + | |
| 811 | + temp = ((crc & 1) ^ data_byte) & 1; | |
| 812 | + crc >>= 1; | |
| 813 | + data_byte >>= 1; | |
| 814 | + | |
| 815 | + if (temp) | |
| 816 | + crc ^= poly; | |
| 817 | + } | |
| 818 | + | |
| 819 | + return crc; | |
| 820 | +} | |
| 821 | + | |
| 822 | +static int xgbe_update_vlan_hash_table(struct xgbe_prv_data *pdata) | |
| 823 | +{ | |
| 824 | + u32 crc; | |
| 825 | + u16 vid; | |
| 826 | + __le16 vid_le; | |
| 827 | + u16 vlan_hash_table = 0; | |
| 828 | + | |
| 829 | + /* Generate the VLAN Hash Table value */ | |
| 830 | + for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) { | |
| 831 | + /* Get the CRC32 value of the VLAN ID */ | |
| 832 | + vid_le = cpu_to_le16(vid); | |
| 833 | + crc = bitrev32(~xgbe_vid_crc32_le(vid_le)) >> 28; | |
| 834 | + | |
| 835 | + vlan_hash_table |= (1 << crc); | |
| 836 | + } | |
| 837 | + | |
| 838 | + /* Set the VLAN Hash Table filtering register */ | |
| 839 | + XGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table); | |
| 840 | + | |
| 841 | + return 0; | |
| 842 | +} | |
| 843 | + | |
| 705 | 844 | static int xgbe_set_promiscuous_mode(struct xgbe_prv_data *pdata, |
| 706 | 845 | unsigned int enable) |
| 707 | 846 | { |
| @@ -714,6 +853,14 @@ static int xgbe_set_promiscuous_mode(struct xgbe_prv_data *pdata, · 6 unmodified lines | ||
| 714 | 853 | enable ? "entering" : "leaving"); |
| 715 | 854 | XGMAC_IOWRITE_BITS(pdata, MAC_PFR, PR, val); |
| 716 | 855 | |
| 856 | + /* Hardware will still perform VLAN filtering in promiscuous mode */ | |
| 857 | + if (enable) { | |
| 858 | + xgbe_disable_rx_vlan_filtering(pdata); | |
| 859 | + } else { | |
| 860 | + if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) | |
| 861 | + xgbe_enable_rx_vlan_filtering(pdata); | |
| 862 | + } | |
| 863 | + | |
| 717 | 864 | return 0; |
| 718 | 865 | } |
| 719 | 866 | |
| @@ -875,6 +1022,7 @@ static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata) · 155 unmodified lines | ||
| 875 | 1022 | static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, |
| 876 | 1023 | int mmd_reg) |
| 877 | 1024 | { |
| 1025 | + unsigned long flags; | |
| 878 | 1026 | unsigned int mmd_address; |
| 879 | 1027 | int mmd_data; |
| 880 | 1028 | |
| @@ -892,10 +1040,10 @@ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, · 11 unmodified lines | ||
| 892 | 1040 | * register offsets must therefore be adjusted by left shifting the |
| 893 | 1041 | * offset 2 bits and reading 32 bits of data. |
| 894 | 1042 | */ |
| 895 | − mutex_lock(&pdata->xpcs_mutex); | |
| 1043 | + spin_lock_irqsave(&pdata->xpcs_lock, flags); | |
| 896 | 1044 | XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8); |
| 897 | 1045 | mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2); |
| 898 | − mutex_unlock(&pdata->xpcs_mutex); | |
| 1046 | + spin_unlock_irqrestore(&pdata->xpcs_lock, flags); | |
| 899 | 1047 | |
| 900 | 1048 | return mmd_data; |
| 901 | 1049 | } |
| @@ -904,6 +1052,7 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, · 2 unmodified lines | ||
| 904 | 1052 | int mmd_reg, int mmd_data) |
| 905 | 1053 | { |
| 906 | 1054 | unsigned int mmd_address; |
| 1055 | + unsigned long flags; | |
| 907 | 1056 | |
| 908 | 1057 | if (mmd_reg & MII_ADDR_C45) |
| 909 | 1058 | mmd_address = mmd_reg & ~MII_ADDR_C45; |
| @@ -919,10 +1068,10 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, · 9 unmodified lines | ||
| 919 | 1068 | * register offsets must therefore be adjusted by left shifting the |
| 920 | 1069 | * offset 2 bits and reading 32 bits of data. |
| 921 | 1070 | */ |
| 922 | − mutex_lock(&pdata->xpcs_mutex); | |
| 1071 | + spin_lock_irqsave(&pdata->xpcs_lock, flags); | |
| 923 | 1072 | XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8); |
| 924 | 1073 | XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data); |
| 925 | − mutex_unlock(&pdata->xpcs_mutex); | |
| 1074 | + spin_unlock_irqrestore(&pdata->xpcs_lock, flags); | |
| 926 | 1075 | } |
| 927 | 1076 | |
| 928 | 1077 | static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc) |
| @@ -944,116 +1093,6 @@ static int xgbe_enable_rx_csum(struct xgbe_prv_data *pdata) · 15 unmodified lines | ||
| 944 | 1093 | return 0; |
| 945 | 1094 | } |
| 946 | 1095 | |
| 947 | −static int xgbe_enable_rx_vlan_stripping(struct xgbe_prv_data *pdata) | |
| 948 | −{ | |
| 949 | − /* Put the VLAN tag in the Rx descriptor */ | |
| 950 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLRXS, 1); | |
| 951 | − | |
| 952 | − /* Don't check the VLAN type */ | |
| 953 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, DOVLTC, 1); | |
| 954 | − | |
| 955 | − /* Check only C-TAG (0x8100) packets */ | |
| 956 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ERSVLM, 0); | |
| 957 | − | |
| 958 | − /* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */ | |
| 959 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ESVL, 0); | |
| 960 | − | |
| 961 | − /* Enable VLAN tag stripping */ | |
| 962 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0x3); | |
| 963 | − | |
| 964 | − return 0; | |
| 965 | −} | |
| 966 | − | |
| 967 | −static int xgbe_disable_rx_vlan_stripping(struct xgbe_prv_data *pdata) | |
| 968 | −{ | |
| 969 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, EVLS, 0); | |
| 970 | − | |
| 971 | − return 0; | |
| 972 | −} | |
| 973 | − | |
| 974 | −static int xgbe_enable_rx_vlan_filtering(struct xgbe_prv_data *pdata) | |
| 975 | −{ | |
| 976 | − /* Enable VLAN filtering */ | |
| 977 | − XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1); | |
| 978 | − | |
| 979 | − /* Enable VLAN Hash Table filtering */ | |
| 980 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1); | |
| 981 | − | |
| 982 | − /* Disable VLAN tag inverse matching */ | |
| 983 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0); | |
| 984 | − | |
| 985 | − /* Only filter on the lower 12-bits of the VLAN tag */ | |
| 986 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1); | |
| 987 | − | |
| 988 | − /* In order for the VLAN Hash Table filtering to be effective, | |
| 989 | − * the VLAN tag identifier in the VLAN Tag Register must not | |
| 990 | − * be zero. Set the VLAN tag identifier to "1" to enable the | |
| 991 | − * VLAN Hash Table filtering. This implies that a VLAN tag of | |
| 992 | − * 1 will always pass filtering. | |
| 993 | − */ | |
| 994 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1); | |
| 995 | − | |
| 996 | − return 0; | |
| 997 | −} | |
| 998 | − | |
| 999 | −static int xgbe_disable_rx_vlan_filtering(struct xgbe_prv_data *pdata) | |
| 1000 | −{ | |
| 1001 | − /* Disable VLAN filtering */ | |
| 1002 | − XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0); | |
| 1003 | − | |
| 1004 | − return 0; | |
| 1005 | −} | |
| 1006 | − | |
| 1007 | −#ifndef CRCPOLY_LE | |
| 1008 | −#define CRCPOLY_LE 0xedb88320 | |
| 1009 | −#endif | |
| 1010 | −static u32 xgbe_vid_crc32_le(__le16 vid_le) | |
| 1011 | −{ | |
| 1012 | − u32 poly = CRCPOLY_LE; | |
| 1013 | − u32 crc = ~0; | |
| 1014 | − u32 temp = 0; | |
| 1015 | − unsigned char *data = (unsigned char *)&vid_le; | |
| 1016 | − unsigned char data_byte = 0; | |
| 1017 | − int i, bits; | |
| 1018 | − | |
| 1019 | − bits = get_bitmask_order(VLAN_VID_MASK); | |
| 1020 | − for (i = 0; i < bits; i++) { | |
| 1021 | − if ((i % 8) == 0) | |
| 1022 | − data_byte = data[i / 8]; | |
| 1023 | − | |
| 1024 | − temp = ((crc & 1) ^ data_byte) & 1; | |
| 1025 | − crc >>= 1; | |
| 1026 | − data_byte >>= 1; | |
| 1027 | − | |
| 1028 | − if (temp) | |
| 1029 | − crc ^= poly; | |
| 1030 | − } | |
| 1031 | − | |
| 1032 | − return crc; | |
| 1033 | −} | |
| 1034 | − | |
| 1035 | −static int xgbe_update_vlan_hash_table(struct xgbe_prv_data *pdata) | |
| 1036 | −{ | |
| 1037 | − u32 crc; | |
| 1038 | − u16 vid; | |
| 1039 | − __le16 vid_le; | |
| 1040 | − u16 vlan_hash_table = 0; | |
| 1041 | − | |
| 1042 | − /* Generate the VLAN Hash Table value */ | |
| 1043 | − for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) { | |
| 1044 | − /* Get the CRC32 value of the VLAN ID */ | |
| 1045 | − vid_le = cpu_to_le16(vid); | |
| 1046 | − crc = bitrev32(~xgbe_vid_crc32_le(vid_le)) >> 28; | |
| 1047 | − | |
| 1048 | − vlan_hash_table |= (1 << crc); | |
| 1049 | − } | |
| 1050 | − | |
| 1051 | − /* Set the VLAN Hash Table filtering register */ | |
| 1052 | − XGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table); | |
| 1053 | − | |
| 1054 | − return 0; | |
| 1055 | −} | |
| 1056 | − | |
| 1057 | 1096 | static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata) |
| 1058 | 1097 | { |
| 1059 | 1098 | struct xgbe_ring_desc *rdesc = rdata->rdesc; |
| @@ -1288,11 +1327,42 @@ static int xgbe_config_tstamp(struct xgbe_prv_data *pdata, · 228 unmodified lines | ||
| 1288 | 1327 | return 0; |
| 1289 | 1328 | } |
| 1290 | 1329 | |
| 1330 | +static void xgbe_config_tc(struct xgbe_prv_data *pdata) | |
| 1331 | +{ | |
| 1332 | + unsigned int offset, queue, prio; | |
| 1333 | + u8 i; | |
| 1334 | + | |
| 1335 | + netdev_reset_tc(pdata->netdev); | |
| 1336 | + if (!pdata->num_tcs) | |
| 1337 | + return; | |
| 1338 | + | |
| 1339 | + netdev_set_num_tc(pdata->netdev, pdata->num_tcs); | |
| 1340 | + | |
| 1341 | + for (i = 0, queue = 0, offset = 0; i < pdata->num_tcs; i++) { | |
| 1342 | + while ((queue < pdata->tx_q_count) && | |
| 1343 | + (pdata->q2tc_map[queue] == i)) | |
| 1344 | + queue++; | |
| 1345 | + | |
| 1346 | + netif_dbg(pdata, drv, pdata->netdev, "TC%u using TXq%u-%u\n", | |
| 1347 | + i, offset, queue - 1); | |
| 1348 | + netdev_set_tc_queue(pdata->netdev, i, queue - offset, offset); | |
| 1349 | + offset = queue; | |
| 1350 | + } | |
| 1351 | + | |
| 1352 | + if (!pdata->ets) | |
| 1353 | + return; | |
| 1354 | + | |
| 1355 | + for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) | |
| 1356 | + netdev_set_prio_tc_map(pdata->netdev, prio, | |
| 1357 | + pdata->ets->prio_tc[prio]); | |
| 1358 | +} | |
| 1359 | + | |
| 1291 | 1360 | static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata) |
| 1292 | 1361 | { |
| 1293 | 1362 | struct ieee_ets *ets = pdata->ets; |
| 1294 | 1363 | unsigned int total_weight, min_weight, weight; |
| 1295 | − unsigned int i; | |
| 1364 | + unsigned int mask, reg, reg_val; | |
| 1365 | + unsigned int i, prio; | |
| 1296 | 1366 | |
| 1297 | 1367 | if (!ets) |
| 1298 | 1368 | return; |
| @@ -1309,6 +1379,25 @@ static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata) · 10 unmodified lines | ||
| 1309 | 1379 | min_weight = 1; |
| 1310 | 1380 | |
| 1311 | 1381 | for (i = 0; i < pdata->hw_feat.tc_cnt; i++) { |
| 1382 | + /* Map the priorities to the traffic class */ | |
| 1383 | + mask = 0; | |
| 1384 | + for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { | |
| 1385 | + if (ets->prio_tc[prio] == i) | |
| 1386 | + mask |= (1 << prio); | |
| 1387 | + } | |
| 1388 | + mask &= 0xff; | |
| 1389 | + | |
| 1390 | + netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n", | |
| 1391 | + i, mask); | |
| 1392 | + reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG)); | |
| 1393 | + reg_val = XGMAC_IOREAD(pdata, reg); | |
| 1394 | + | |
| 1395 | + reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3)); | |
| 1396 | + reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3)); | |
| 1397 | + | |
| 1398 | + XGMAC_IOWRITE(pdata, reg, reg_val); | |
| 1399 | + | |
| 1400 | + /* Set the traffic class algorithm */ | |
| 1312 | 1401 | switch (ets->tc_tsa[i]) { |
| 1313 | 1402 | case IEEE_8021QAZ_TSA_STRICT: |
| 1314 | 1403 | netif_dbg(pdata, drv, pdata->netdev, |
| @@ -1329,38 +1418,12 @@ static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata) · 14 unmodified lines | ||
| 1329 | 1418 | break; |
| 1330 | 1419 | } |
| 1331 | 1420 | } |
| 1421 | + | |
| 1422 | + xgbe_config_tc(pdata); | |
| 1332 | 1423 | } |
| 1333 | 1424 | |
| 1334 | 1425 | static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata) |
| 1335 | 1426 | { |
| 1336 | − struct ieee_pfc *pfc = pdata->pfc; | |
| 1337 | − struct ieee_ets *ets = pdata->ets; | |
| 1338 | − unsigned int mask, reg, reg_val; | |
| 1339 | − unsigned int tc, prio; | |
| 1340 | − | |
| 1341 | − if (!pfc || !ets) | |
| 1342 | − return; | |
| 1343 | − | |
| 1344 | − for (tc = 0; tc < pdata->hw_feat.tc_cnt; tc++) { | |
| 1345 | − mask = 0; | |
| 1346 | − for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) { | |
| 1347 | − if ((pfc->pfc_en & (1 << prio)) && | |
| 1348 | − (ets->prio_tc[prio] == tc)) | |
| 1349 | − mask |= (1 << prio); | |
| 1350 | − } | |
| 1351 | − mask &= 0xff; | |
| 1352 | − | |
| 1353 | − netif_dbg(pdata, drv, pdata->netdev, "TC%u PFC mask=%#x\n", | |
| 1354 | − tc, mask); | |
| 1355 | − reg = MTL_TCPM0R + (MTL_TCPM_INC * (tc / MTL_TCPM_TC_PER_REG)); | |
| 1356 | − reg_val = XGMAC_IOREAD(pdata, reg); | |
| 1357 | − | |
| 1358 | − reg_val &= ~(0xff << ((tc % MTL_TCPM_TC_PER_REG) << 3)); | |
| 1359 | − reg_val |= (mask << ((tc % MTL_TCPM_TC_PER_REG) << 3)); | |
| 1360 | − | |
| 1361 | − XGMAC_IOWRITE(pdata, reg, reg_val); | |
| 1362 | − } | |
| 1363 | − | |
| 1364 | 1427 | xgbe_config_flow_control(pdata); |
| 1365 | 1428 | } |
| 1366 | 1429 | |
| @@ -2595,6 +2658,32 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata) · 1228 unmodified lines | ||
| 2595 | 2658 | } |
| 2596 | 2659 | } |
| 2597 | 2660 | |
| 2661 | +static void xgbe_prepare_rx_stop(struct xgbe_prv_data *pdata, | |
| 2662 | + unsigned int queue) | |
| 2663 | +{ | |
| 2664 | + unsigned int rx_status; | |
| 2665 | + unsigned long rx_timeout; | |
| 2666 | + | |
| 2667 | + /* The Rx engine cannot be stopped if it is actively processing | |
| 2668 | + * packets. Wait for the Rx queue to empty the Rx fifo. Don't | |
| 2669 | + * wait forever though... | |
| 2670 | + */ | |
| 2671 | + rx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ); | |
| 2672 | + while (time_before(jiffies, rx_timeout)) { | |
| 2673 | + rx_status = XGMAC_MTL_IOREAD(pdata, queue, MTL_Q_RQDR); | |
| 2674 | + if ((XGMAC_GET_BITS(rx_status, MTL_Q_RQDR, PRXQ) == 0) && | |
| 2675 | + (XGMAC_GET_BITS(rx_status, MTL_Q_RQDR, RXQSTS) == 0)) | |
| 2676 | + break; | |
| 2677 | + | |
| 2678 | + usleep_range(500, 1000); | |
| 2679 | + } | |
| 2680 | + | |
| 2681 | + if (!time_before(jiffies, rx_timeout)) | |
| 2682 | + netdev_info(pdata->netdev, | |
| 2683 | + "timed out waiting for Rx queue %u to empty\n", | |
| 2684 | + queue); | |
| 2685 | +} | |
| 2686 | + | |
| 2598 | 2687 | static void xgbe_enable_rx(struct xgbe_prv_data *pdata) |
| 2599 | 2688 | { |
| 2600 | 2689 | struct xgbe_channel *channel; |
| @@ -2633,6 +2722,10 @@ static void xgbe_disable_rx(struct xgbe_prv_data *pdata) · 32 unmodified lines | ||
| 2633 | 2722 | XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 0); |
| 2634 | 2723 | XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 0); |
| 2635 | 2724 | |
| 2725 | + /* Prepare for Rx DMA channel stop */ | |
| 2726 | + for (i = 0; i < pdata->rx_q_count; i++) | |
| 2727 | + xgbe_prepare_rx_stop(pdata, i); | |
| 2728 | + | |
| 2636 | 2729 | /* Disable each Rx queue */ |
| 2637 | 2730 | XGMAC_IOWRITE(pdata, MAC_RQC0R, 0); |
| 2638 | 2731 | |
| @@ -2881,6 +2974,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) · 242 unmodified lines | ||
| 2881 | 2974 | hw_if->get_tx_tstamp = xgbe_get_tx_tstamp; |
| 2882 | 2975 | |
| 2883 | 2976 | /* For Data Center Bridging config */ |
| 2977 | + hw_if->config_tc = xgbe_config_tc; | |
| 2884 | 2978 | hw_if->config_dcb_tc = xgbe_config_dcb_tc; |
| 2885 | 2979 | hw_if->config_dcb_pfc = xgbe_config_dcb_pfc; |
| 2886 | 2980 | |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -356,7 +356,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) · 293 unmodified lines | ||
| 356 | 356 | xgbe_disable_rx_tx_ints(pdata); |
| 357 | 357 | |
| 358 | 358 | /* Turn on polling */ |
| 359 | − __napi_schedule(&pdata->napi); | |
| 359 | + __napi_schedule_irqoff(&pdata->napi); | |
| 360 | 360 | } |
| 361 | 361 | } |
| 362 | 362 | |
| @@ -409,7 +409,7 @@ static irqreturn_t xgbe_dma_isr(int irq, void *data) · 46 unmodified lines | ||
| 409 | 409 | disable_irq_nosync(channel->dma_irq); |
| 410 | 410 | |
| 411 | 411 | /* Turn on polling */ |
| 412 | − __napi_schedule(&channel->napi); | |
| 412 | + __napi_schedule_irqoff(&channel->napi); | |
| 413 | 413 | } |
| 414 | 414 | |
| 415 | 415 | return IRQ_HANDLED; |
| @@ -1626,30 +1626,22 @@ static void xgbe_poll_controller(struct net_device *netdev) · 1210 unmodified lines | ||
| 1626 | 1626 | } |
| 1627 | 1627 | #endif /* End CONFIG_NET_POLL_CONTROLLER */ |
| 1628 | 1628 | |
| 1629 | −static int xgbe_setup_tc(struct net_device *netdev, u8 tc) | |
| 1629 | +static int xgbe_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, | |
| 1630 | + struct tc_to_netdev *tc_to_netdev) | |
| 1630 | 1631 | { |
| 1631 | 1632 | struct xgbe_prv_data *pdata = netdev_priv(netdev); |
| 1632 | − unsigned int offset, queue; | |
| 1633 | − u8 i; | |
| 1633 | + u8 tc; | |
| 1634 | 1634 | |
| 1635 | − if (tc && (tc != pdata->hw_feat.tc_cnt)) | |
| 1635 | + if (tc_to_netdev->type != TC_SETUP_MQPRIO) | |
| 1636 | 1636 | return -EINVAL; |
| 1637 | 1637 | |
| 1638 | − if (tc) { | |
| 1639 | − netdev_set_num_tc(netdev, tc); | |
| 1640 | − for (i = 0, queue = 0, offset = 0; i < tc; i++) { | |
| 1641 | − while ((queue < pdata->tx_q_count) && | |
| 1642 | − (pdata->q2tc_map[queue] == i)) | |
| 1643 | − queue++; | |
| 1644 | − | |
| 1645 | − netif_dbg(pdata, drv, netdev, "TC%u using TXq%u-%u\n", | |
| 1646 | − i, offset, queue - 1); | |
| 1647 | − netdev_set_tc_queue(netdev, i, queue - offset, offset); | |
| 1648 | − offset = queue; | |
| 1649 | − } | |
| 1650 | − } else { | |
| 1651 | − netdev_reset_tc(netdev); | |
| 1652 | − } | |
| 1638 | + tc = tc_to_netdev->tc; | |
| 1639 | + | |
| 1640 | + if (tc > pdata->hw_feat.tc_cnt) | |
| 1641 | + return -EINVAL; | |
| 1642 | + | |
| 1643 | + pdata->num_tcs = tc; | |
| 1644 | + pdata->hw_if.config_tc(pdata); | |
| 1653 | 1645 | |
| 1654 | 1646 | return 0; |
| 1655 | 1647 | } |
| @@ -2062,7 +2054,7 @@ static int xgbe_one_poll(struct napi_struct *napi, int budget) · 406 unmodified lines | ||
| 2062 | 2054 | /* If we processed everything, we are done */ |
| 2063 | 2055 | if (processed < budget) { |
| 2064 | 2056 | /* Turn off polling */ |
| 2065 | − napi_complete(napi); | |
| 2057 | + napi_complete_done(napi, processed); | |
| 2066 | 2058 | |
| 2067 | 2059 | /* Enable Tx and Rx interrupts */ |
| 2068 | 2060 | enable_irq(channel->dma_irq); |
| @@ -2104,7 +2096,7 @@ static int xgbe_all_poll(struct napi_struct *napi, int budget) · 35 unmodified lines | ||
| 2104 | 2096 | /* If we processed everything, we are done */ |
| 2105 | 2097 | if (processed < budget) { |
| 2106 | 2098 | /* Turn off polling */ |
| 2107 | − napi_complete(napi); | |
| 2099 | + napi_complete_done(napi, processed); | |
| 2108 | 2100 | |
| 2109 | 2101 | /* Enable Tx and Rx interrupts */ |
| 2110 | 2102 | xgbe_enable_rx_tx_ints(pdata); |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -318,8 +318,20 @@ static int xgbe_set_settings(struct net_device *netdev, · 255 unmodified lines | ||
| 318 | 318 | if (cmd->autoneg == AUTONEG_DISABLE) { |
| 319 | 319 | switch (speed) { |
| 320 | 320 | case SPEED_10000: |
| 321 | + break; | |
| 321 | 322 | case SPEED_2500: |
| 323 | + if (pdata->speed_set != XGBE_SPEEDSET_2500_10000) { | |
| 324 | + netdev_err(netdev, "unsupported speed %u\n", | |
| 325 | + speed); | |
| 326 | + return -EINVAL; | |
| 327 | + } | |
| 328 | + break; | |
| 322 | 329 | case SPEED_1000: |
| 330 | + if (pdata->speed_set != XGBE_SPEEDSET_1000_10000) { | |
| 331 | + netdev_err(netdev, "unsupported speed %u\n", | |
| 332 | + speed); | |
| 333 | + return -EINVAL; | |
| 334 | + } | |
| 323 | 335 | break; |
| 324 | 336 | default: |
| 325 | 337 | netdev_err(netdev, "unsupported speed %u\n", speed); |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -363,7 +363,7 @@ static int xgbe_probe(struct platform_device *pdev) · 300 unmodified lines | ||
| 363 | 363 | platform_set_drvdata(pdev, netdev); |
| 364 | 364 | |
| 365 | 365 | spin_lock_init(&pdata->lock); |
| 366 | − mutex_init(&pdata->xpcs_mutex); | |
| 366 | + spin_lock_init(&pdata->xpcs_lock); | |
| 367 | 367 | mutex_init(&pdata->rss_mutex); |
| 368 | 368 | spin_lock_init(&pdata->tstamp_lock); |
| 369 | 369 | |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -626,10 +626,22 @@ static irqreturn_t xgbe_an_isr(int irq, void *data) · 563 unmodified lines | ||
| 626 | 626 | |
| 627 | 627 | netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n"); |
| 628 | 628 | |
| 629 | − /* Interrupt reason must be read and cleared outside of IRQ context */ | |
| 630 | − disable_irq_nosync(pdata->an_irq); | |
| 629 | + /* Disable AN interrupts */ | |
| 630 | + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); | |
| 631 | + | |
| 632 | + /* Save the interrupt(s) that fired */ | |
| 633 | + pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT); | |
| 631 | 634 | |
| 632 | − queue_work(pdata->an_workqueue, &pdata->an_irq_work); | |
| 635 | + if (pdata->an_int) { | |
| 636 | + /* Clear the interrupt(s) that fired and process them */ | |
| 637 | + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int); | |
| 638 | + | |
| 639 | + queue_work(pdata->an_workqueue, &pdata->an_irq_work); | |
| 640 | + } else { | |
| 641 | + /* Enable AN interrupts */ | |
| 642 | + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, | |
| 643 | + XGBE_AN_INT_MASK); | |
| 644 | + } | |
| 633 | 645 | |
| 634 | 646 | return IRQ_HANDLED; |
| 635 | 647 | } |
| @@ -673,34 +685,26 @@ static void xgbe_an_state_machine(struct work_struct *work) · 37 unmodified lines | ||
| 673 | 685 | struct xgbe_prv_data, |
| 674 | 686 | an_work); |
| 675 | 687 | enum xgbe_an cur_state = pdata->an_state; |
| 676 | − unsigned int int_reg, int_mask; | |
| 677 | 688 | |
| 678 | 689 | mutex_lock(&pdata->an_mutex); |
| 679 | 690 | |
| 680 | − /* Read the interrupt */ | |
| 681 | − int_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT); | |
| 682 | − if (!int_reg) | |
| 691 | + if (!pdata->an_int) | |
| 683 | 692 | goto out; |
| 684 | 693 | |
| 685 | 694 | next_int: |
| 686 | − if (int_reg & XGBE_AN_PG_RCV) { | |
| 695 | + if (pdata->an_int & XGBE_AN_PG_RCV) { | |
| 687 | 696 | pdata->an_state = XGBE_AN_PAGE_RECEIVED; |
| 688 | − int_mask = XGBE_AN_PG_RCV; | |
| 689 | − } else if (int_reg & XGBE_AN_INC_LINK) { | |
| 697 | + pdata->an_int &= ~XGBE_AN_PG_RCV; | |
| 698 | + } else if (pdata->an_int & XGBE_AN_INC_LINK) { | |
| 690 | 699 | pdata->an_state = XGBE_AN_INCOMPAT_LINK; |
| 691 | − int_mask = XGBE_AN_INC_LINK; | |
| 692 | − } else if (int_reg & XGBE_AN_INT_CMPLT) { | |
| 700 | + pdata->an_int &= ~XGBE_AN_INC_LINK; | |
| 701 | + } else if (pdata->an_int & XGBE_AN_INT_CMPLT) { | |
| 693 | 702 | pdata->an_state = XGBE_AN_COMPLETE; |
| 694 | − int_mask = XGBE_AN_INT_CMPLT; | |
| 703 | + pdata->an_int &= ~XGBE_AN_INT_CMPLT; | |
| 695 | 704 | } else { |
| 696 | 705 | pdata->an_state = XGBE_AN_ERROR; |
| 697 | − int_mask = 0; | |
| 698 | 706 | } |
| 699 | 707 | |
| 700 | − /* Clear the interrupt to be processed */ | |
| 701 | − int_reg &= ~int_mask; | |
| 702 | − XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, int_reg); | |
| 703 | − | |
| 704 | 708 | pdata->an_result = pdata->an_state; |
| 705 | 709 | |
| 706 | 710 | again: |
| @@ -740,14 +744,14 @@ again: · 33 unmodified lines | ||
| 740 | 744 | } |
| 741 | 745 | |
| 742 | 746 | if (pdata->an_state == XGBE_AN_NO_LINK) { |
| 743 | − int_reg = 0; | |
| 747 | + pdata->an_int = 0; | |
| 744 | 748 | XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); |
| 745 | 749 | } else if (pdata->an_state == XGBE_AN_ERROR) { |
| 746 | 750 | netdev_err(pdata->netdev, |
| 747 | 751 | "error during auto-negotiation, state=%u\n", |
| 748 | 752 | cur_state); |
| 749 | 753 | |
| 750 | − int_reg = 0; | |
| 754 | + pdata->an_int = 0; | |
| 751 | 755 | XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); |
| 752 | 756 | } |
| 753 | 757 | |
| @@ -765,11 +769,12 @@ again: · 11 unmodified lines | ||
| 765 | 769 | if (cur_state != pdata->an_state) |
| 766 | 770 | goto again; |
| 767 | 771 | |
| 768 | − if (int_reg) | |
| 772 | + if (pdata->an_int) | |
| 769 | 773 | goto next_int; |
| 770 | 774 | |
| 771 | 775 | out: |
| 772 | − enable_irq(pdata->an_irq); | |
| 776 | + /* Enable AN interrupts on the way out */ | |
| 777 | + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK); | |
| 773 | 778 | |
| 774 | 779 | mutex_unlock(&pdata->an_mutex); |
| 775 | 780 | } |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * |
| 7 | 7 | * License 1: GPLv2 |
| 8 | 8 | * |
| 9 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 9 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 10 | 10 | * |
| 11 | 11 | * This file is free software; you may copy, redistribute and/or modify |
| 12 | 12 | * it under the terms of the GNU General Public License as published by |
| @@ -56,7 +56,7 @@ · 43 unmodified lines | ||
| 56 | 56 | * |
| 57 | 57 | * License 2: Modified BSD |
| 58 | 58 | * |
| 59 | − * Copyright (c) 2014 Advanced Micro Devices, Inc. | |
| 59 | + * Copyright (c) 2014-2016 Advanced Micro Devices, Inc. | |
| 60 | 60 | * All rights reserved. |
| 61 | 61 | * |
| 62 | 62 | * Redistribution and use in source and binary forms, with or without |
| @@ -673,6 +673,7 @@ struct xgbe_hw_if { · 610 unmodified lines | ||
| 673 | 673 | u64 (*get_tx_tstamp)(struct xgbe_prv_data *); |
| 674 | 674 | |
| 675 | 675 | /* For Data Center Bridging config */ |
| 676 | + void (*config_tc)(struct xgbe_prv_data *); | |
| 676 | 677 | void (*config_dcb_tc)(struct xgbe_prv_data *); |
| 677 | 678 | void (*config_dcb_pfc)(struct xgbe_prv_data *); |
| 678 | 679 | |
| @@ -773,8 +774,8 @@ struct xgbe_prv_data { · 94 unmodified lines | ||
| 773 | 774 | /* Overall device lock */ |
| 774 | 775 | spinlock_t lock; |
| 775 | 776 | |
| 776 | − /* XPCS indirect addressing mutex */ | |
| 777 | − struct mutex xpcs_mutex; | |
| 777 | + /* XPCS indirect addressing lock */ | |
| 778 | + spinlock_t xpcs_lock; | |
| 778 | 779 | |
| 779 | 780 | /* RSS addressing mutex */ |
| 780 | 781 | struct mutex rss_mutex; |
| @@ -880,6 +881,7 @@ struct xgbe_prv_data { · 99 unmodified lines | ||
| 880 | 881 | struct ieee_pfc *pfc; |
| 881 | 882 | unsigned int q2tc_map[XGBE_MAX_QUEUES]; |
| 882 | 883 | unsigned int prio2q_map[IEEE_8021QAZ_MAX_TCS]; |
| 884 | + u8 num_tcs; | |
| 883 | 885 | |
| 884 | 886 | /* Hardware features of the device */ |
| 885 | 887 | struct xgbe_hw_features hw_feat; |
| @@ -925,6 +927,7 @@ struct xgbe_prv_data { · 39 unmodified lines | ||
| 925 | 927 | u32 serdes_dfe_tap_ena[XGBE_SPEEDS]; |
| 926 | 928 | |
| 927 | 929 | /* Auto-negotiation state machine support */ |
| 930 | + unsigned int an_int; | |
| 928 | 931 | struct mutex an_mutex; |
| 929 | 932 | enum xgbe_an an_result; |
| 930 | 933 | enum xgbe_an an_state; |
| @@ -3,5 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | # |
| 4 | 4 | |
| 5 | 5 | xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \ |
| 6 | − xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o | |
| 6 | + xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o \ | |
| 7 | + xgene_enet_cle.o | |
| 7 | 8 | obj-$(CONFIG_NET_XGENE) += xgene-enet.o |
| @@ -0,0 +1,734 @@ | ||
| 1 | +/* Applied Micro X-Gene SoC Ethernet Classifier structures | |
| 2 | + * | |
| 3 | + * Copyright (c) 2016, Applied Micro Circuits Corporation | |
| 4 | + * Authors: Khuong Dinh <kdinh@apm.com> | |
| 5 | + * Tanmay Inamdar <tinamdar@apm.com> | |
| 6 | + * Iyappan Subramanian <isubramanian@apm.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify it | |
| 9 | + * under the terms of the GNU General Public License as published by the | |
| 10 | + * Free Software Foundation; either version 2 of the License, or (at your | |
| 11 | + * option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + * | |
| 18 | + * You should have received a copy of the GNU General Public License | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include "xgene_enet_main.h" | |
| 23 | + | |
| 24 | +/* interfaces to convert structures to HW recognized bit formats */ | |
| 25 | +static void xgene_cle_sband_to_hw(u8 frag, enum xgene_cle_prot_version ver, | |
| 26 | + enum xgene_cle_prot_type type, u32 len, | |
| 27 | + u32 *reg) | |
| 28 | +{ | |
| 29 | + *reg = SET_VAL(SB_IPFRAG, frag) | | |
| 30 | + SET_VAL(SB_IPPROT, type) | | |
| 31 | + SET_VAL(SB_IPVER, ver) | | |
| 32 | + SET_VAL(SB_HDRLEN, len); | |
| 33 | +} | |
| 34 | + | |
| 35 | +static void xgene_cle_idt_to_hw(u32 dstqid, u32 fpsel, | |
| 36 | + u32 nfpsel, u32 *idt_reg) | |
| 37 | +{ | |
| 38 | + *idt_reg = SET_VAL(IDT_DSTQID, dstqid) | | |
| 39 | + SET_VAL(IDT_FPSEL, fpsel) | | |
| 40 | + SET_VAL(IDT_NFPSEL, nfpsel); | |
| 41 | +} | |
| 42 | + | |
| 43 | +static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata, | |
| 44 | + struct xgene_cle_dbptr *dbptr, u32 *buf) | |
| 45 | +{ | |
| 46 | + buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) | | |
| 47 | + SET_VAL(CLE_DSTQIDL, dbptr->dstqid); | |
| 48 | + | |
| 49 | + buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) | | |
| 50 | + SET_VAL(CLE_PRIORITY, dbptr->cle_priority); | |
| 51 | +} | |
| 52 | + | |
| 53 | +static void xgene_cle_kn_to_hw(struct xgene_cle_ptree_kn *kn, u32 *buf) | |
| 54 | +{ | |
| 55 | + u32 i, j = 0; | |
| 56 | + u32 data; | |
| 57 | + | |
| 58 | + buf[j++] = SET_VAL(CLE_TYPE, kn->node_type); | |
| 59 | + for (i = 0; i < kn->num_keys; i++) { | |
| 60 | + struct xgene_cle_ptree_key *key = &kn->key[i]; | |
| 61 | + | |
| 62 | + if (!(i % 2)) { | |
| 63 | + buf[j] = SET_VAL(CLE_KN_PRIO, key->priority) | | |
| 64 | + SET_VAL(CLE_KN_RPTR, key->result_pointer); | |
| 65 | + } else { | |
| 66 | + data = SET_VAL(CLE_KN_PRIO, key->priority) | | |
| 67 | + SET_VAL(CLE_KN_RPTR, key->result_pointer); | |
| 68 | + buf[j++] |= (data << 16); | |
| 69 | + } | |
| 70 | + } | |
| 71 | +} | |
| 72 | + | |
| 73 | +static void xgene_cle_dn_to_hw(struct xgene_cle_ptree_ewdn *dn, | |
| 74 | + u32 *buf, u32 jb) | |
| 75 | +{ | |
| 76 | + struct xgene_cle_ptree_branch *br; | |
| 77 | + u32 i, j = 0; | |
| 78 | + u32 npp; | |
| 79 | + | |
| 80 | + buf[j++] = SET_VAL(CLE_DN_TYPE, dn->node_type) | | |
| 81 | + SET_VAL(CLE_DN_LASTN, dn->last_node) | | |
| 82 | + SET_VAL(CLE_DN_HLS, dn->hdr_len_store) | | |
| 83 | + SET_VAL(CLE_DN_EXT, dn->hdr_extn) | | |
| 84 | + SET_VAL(CLE_DN_BSTOR, dn->byte_store) | | |
| 85 | + SET_VAL(CLE_DN_SBSTOR, dn->search_byte_store) | | |
| 86 | + SET_VAL(CLE_DN_RPTR, dn->result_pointer); | |
| 87 | + | |
| 88 | + for (i = 0; i < dn->num_branches; i++) { | |
| 89 | + br = &dn->branch[i]; | |
| 90 | + npp = br->next_packet_pointer; | |
| 91 | + | |
| 92 | + if ((br->jump_rel == JMP_ABS) && (npp < CLE_PKTRAM_SIZE)) | |
| 93 | + npp += jb; | |
| 94 | + | |
| 95 | + buf[j++] = SET_VAL(CLE_BR_VALID, br->valid) | | |
| 96 | + SET_VAL(CLE_BR_NPPTR, npp) | | |
| 97 | + SET_VAL(CLE_BR_JB, br->jump_bw) | | |
| 98 | + SET_VAL(CLE_BR_JR, br->jump_rel) | | |
| 99 | + SET_VAL(CLE_BR_OP, br->operation) | | |
| 100 | + SET_VAL(CLE_BR_NNODE, br->next_node) | | |
| 101 | + SET_VAL(CLE_BR_NBR, br->next_branch); | |
| 102 | + | |
| 103 | + buf[j++] = SET_VAL(CLE_BR_DATA, br->data) | | |
| 104 | + SET_VAL(CLE_BR_MASK, br->mask); | |
| 105 | + } | |
| 106 | +} | |
| 107 | + | |
| 108 | +static int xgene_cle_poll_cmd_done(void __iomem *base, | |
| 109 | + enum xgene_cle_cmd_type cmd) | |
| 110 | +{ | |
| 111 | + u32 status, loop = 10; | |
| 112 | + int ret = -EBUSY; | |
| 113 | + | |
| 114 | + while (loop--) { | |
| 115 | + status = ioread32(base + INDCMD_STATUS); | |
| 116 | + if (status & cmd) { | |
| 117 | + ret = 0; | |
| 118 | + break; | |
| 119 | + } | |
| 120 | + usleep_range(1000, 2000); | |
| 121 | + } | |
| 122 | + | |
| 123 | + return ret; | |
| 124 | +} | |
| 125 | + | |
| 126 | +static int xgene_cle_dram_wr(struct xgene_enet_cle *cle, u32 *data, u8 nregs, | |
| 127 | + u32 index, enum xgene_cle_dram_type type, | |
| 128 | + enum xgene_cle_cmd_type cmd) | |
| 129 | +{ | |
| 130 | + enum xgene_cle_parser parser = cle->active_parser; | |
| 131 | + void __iomem *base = cle->base; | |
| 132 | + u32 i, j, ind_addr; | |
| 133 | + u8 port, nparsers; | |
| 134 | + int ret = 0; | |
| 135 | + | |
| 136 | + /* PTREE_RAM onwards, DRAM regions are common for all parsers */ | |
| 137 | + nparsers = (type >= PTREE_RAM) ? 1 : cle->parsers; | |
| 138 | + | |
| 139 | + for (i = 0; i < nparsers; i++) { | |
| 140 | + port = i; | |
| 141 | + if ((type < PTREE_RAM) && (parser != PARSER_ALL)) | |
| 142 | + port = parser; | |
| 143 | + | |
| 144 | + ind_addr = XGENE_CLE_DRAM(type + (port * 4)) | index; | |
| 145 | + iowrite32(ind_addr, base + INDADDR); | |
| 146 | + for (j = 0; j < nregs; j++) | |
| 147 | + iowrite32(data[j], base + DATA_RAM0 + (j * 4)); | |
| 148 | + iowrite32(cmd, base + INDCMD); | |
| 149 | + | |
| 150 | + ret = xgene_cle_poll_cmd_done(base, cmd); | |
| 151 | + if (ret) | |
| 152 | + break; | |
| 153 | + } | |
| 154 | + | |
| 155 | + return ret; | |
| 156 | +} | |
| 157 | + | |
| 158 | +static void xgene_cle_enable_ptree(struct xgene_enet_pdata *pdata, | |
| 159 | + struct xgene_enet_cle *cle) | |
| 160 | +{ | |
| 161 | + struct xgene_cle_ptree *ptree = &cle->ptree; | |
| 162 | + void __iomem *addr, *base = cle->base; | |
| 163 | + u32 offset = CLE_PORT_OFFSET; | |
| 164 | + u32 i; | |
| 165 | + | |
| 166 | + /* 1G port has to advance 4 bytes and 10G has to advance 8 bytes */ | |
| 167 | + ptree->start_pkt += cle->jump_bytes; | |
| 168 | + for (i = 0; i < cle->parsers; i++) { | |
| 169 | + if (cle->active_parser != PARSER_ALL) | |
| 170 | + addr = base + cle->active_parser * offset; | |
| 171 | + else | |
| 172 | + addr = base + (i * offset); | |
| 173 | + | |
| 174 | + iowrite32(ptree->start_node & 0x3fff, addr + SNPTR0); | |
| 175 | + iowrite32(ptree->start_pkt & 0x1ff, addr + SPPTR0); | |
| 176 | + } | |
| 177 | +} | |
| 178 | + | |
| 179 | +static int xgene_cle_setup_dbptr(struct xgene_enet_pdata *pdata, | |
| 180 | + struct xgene_enet_cle *cle) | |
| 181 | +{ | |
| 182 | + struct xgene_cle_ptree *ptree = &cle->ptree; | |
| 183 | + u32 buf[CLE_DRAM_REGS]; | |
| 184 | + u32 i; | |
| 185 | + int ret; | |
| 186 | + | |
| 187 | + memset(buf, 0, sizeof(buf)); | |
| 188 | + for (i = 0; i < ptree->num_dbptr; i++) { | |
| 189 | + xgene_cle_dbptr_to_hw(pdata, &ptree->dbptr[i], buf); | |
| 190 | + ret = xgene_cle_dram_wr(cle, buf, 6, i + ptree->start_dbptr, | |
| 191 | + DB_RAM, CLE_CMD_WR); | |
| 192 | + if (ret) | |
| 193 | + return ret; | |
| 194 | + } | |
| 195 | + | |
| 196 | + return 0; | |
| 197 | +} | |
| 198 | + | |
| 199 | +static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata, | |
| 200 | + struct xgene_enet_cle *cle) | |
| 201 | +{ | |
| 202 | + struct xgene_cle_ptree *ptree = &cle->ptree; | |
| 203 | + struct xgene_cle_ptree_ewdn *dn = ptree->dn; | |
| 204 | + struct xgene_cle_ptree_kn *kn = ptree->kn; | |
| 205 | + u32 buf[CLE_DRAM_REGS]; | |
| 206 | + int i, j, ret; | |
| 207 | + | |
| 208 | + memset(buf, 0, sizeof(buf)); | |
| 209 | + for (i = 0; i < ptree->num_dn; i++) { | |
| 210 | + xgene_cle_dn_to_hw(&dn[i], buf, cle->jump_bytes); | |
| 211 | + ret = xgene_cle_dram_wr(cle, buf, 17, i + ptree->start_node, | |
| 212 | + PTREE_RAM, CLE_CMD_WR); | |
| 213 | + if (ret) | |
| 214 | + return ret; | |
| 215 | + } | |
| 216 | + | |
| 217 | + /* continue node index for key node */ | |
| 218 | + memset(buf, 0, sizeof(buf)); | |
| 219 | + for (j = i; j < (ptree->num_kn + ptree->num_dn); j++) { | |
| 220 | + xgene_cle_kn_to_hw(&kn[j - ptree->num_dn], buf); | |
| 221 | + ret = xgene_cle_dram_wr(cle, buf, 17, j + ptree->start_node, | |
| 222 | + PTREE_RAM, CLE_CMD_WR); | |
| 223 | + if (ret) | |
| 224 | + return ret; | |
| 225 | + } | |
| 226 | + | |
| 227 | + return 0; | |
| 228 | +} | |
| 229 | + | |
| 230 | +static int xgene_cle_setup_ptree(struct xgene_enet_pdata *pdata, | |
| 231 | + struct xgene_enet_cle *cle) | |
| 232 | +{ | |
| 233 | + int ret; | |
| 234 | + | |
| 235 | + ret = xgene_cle_setup_node(pdata, cle); | |
| 236 | + if (ret) | |
| 237 | + return ret; | |
| 238 | + | |
| 239 | + ret = xgene_cle_setup_dbptr(pdata, cle); | |
| 240 | + if (ret) | |
| 241 | + return ret; | |
| 242 | + | |
| 243 | + xgene_cle_enable_ptree(pdata, cle); | |
| 244 | + | |
| 245 | + return 0; | |
| 246 | +} | |
| 247 | + | |
| 248 | +static void xgene_cle_setup_def_dbptr(struct xgene_enet_pdata *pdata, | |
| 249 | + struct xgene_enet_cle *enet_cle, | |
| 250 | + struct xgene_cle_dbptr *dbptr, | |
| 251 | + u32 index, u8 priority) | |
| 252 | +{ | |
| 253 | + void __iomem *base = enet_cle->base; | |
| 254 | + void __iomem *base_addr; | |
| 255 | + u32 buf[CLE_DRAM_REGS]; | |
| 256 | + u32 def_cls, offset; | |
| 257 | + u32 i, j; | |
| 258 | + | |
| 259 | + memset(buf, 0, sizeof(buf)); | |
| 260 | + xgene_cle_dbptr_to_hw(pdata, dbptr, buf); | |
| 261 | + | |
| 262 | + for (i = 0; i < enet_cle->parsers; i++) { | |
| 263 | + if (enet_cle->active_parser != PARSER_ALL) { | |
| 264 | + offset = enet_cle->active_parser * | |
| 265 | + CLE_PORT_OFFSET; | |
| 266 | + } else { | |
| 267 | + offset = i * CLE_PORT_OFFSET; | |
| 268 | + } | |
| 269 | + | |
| 270 | + base_addr = base + DFCLSRESDB00 + offset; | |
| 271 | + for (j = 0; j < 6; j++) | |
| 272 | + iowrite32(buf[j], base_addr + (j * 4)); | |
| 273 | + | |
| 274 | + def_cls = ((priority & 0x7) << 10) | (index & 0x3ff); | |
| 275 | + iowrite32(def_cls, base + DFCLSRESDBPTR0 + offset); | |
| 276 | + } | |
| 277 | +} | |
| 278 | + | |
| 279 | +static int xgene_cle_set_rss_sband(struct xgene_enet_cle *cle) | |
| 280 | +{ | |
| 281 | + u32 idx = CLE_PKTRAM_SIZE / sizeof(u32); | |
| 282 | + u32 mac_hdr_len = ETH_HLEN; | |
| 283 | + u32 sband, reg = 0; | |
| 284 | + u32 ipv4_ihl = 5; | |
| 285 | + u32 hdr_len; | |
| 286 | + int ret; | |
| 287 | + | |
| 288 | + /* Sideband: IPV4/TCP packets */ | |
| 289 | + hdr_len = (mac_hdr_len << 5) | ipv4_ihl; | |
| 290 | + xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_TCP, hdr_len, ®); | |
| 291 | + sband = reg; | |
| 292 | + | |
| 293 | + /* Sideband: IPv4/UDP packets */ | |
| 294 | + hdr_len = (mac_hdr_len << 5) | ipv4_ihl; | |
| 295 | + xgene_cle_sband_to_hw(1, XGENE_CLE_IPV4, XGENE_CLE_UDP, hdr_len, ®); | |
| 296 | + sband |= (reg << 16); | |
| 297 | + | |
| 298 | + ret = xgene_cle_dram_wr(cle, &sband, 1, idx, PKT_RAM, CLE_CMD_WR); | |
| 299 | + if (ret) | |
| 300 | + return ret; | |
| 301 | + | |
| 302 | + /* Sideband: IPv4/RAW packets */ | |
| 303 | + hdr_len = (mac_hdr_len << 5) | ipv4_ihl; | |
| 304 | + xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER, | |
| 305 | + hdr_len, ®); | |
| 306 | + sband = reg; | |
| 307 | + | |
| 308 | + /* Sideband: Ethernet II/RAW packets */ | |
| 309 | + hdr_len = (mac_hdr_len << 5); | |
| 310 | + xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER, | |
| 311 | + hdr_len, ®); | |
| 312 | + sband |= (reg << 16); | |
| 313 | + | |
| 314 | + ret = xgene_cle_dram_wr(cle, &sband, 1, idx + 1, PKT_RAM, CLE_CMD_WR); | |
| 315 | + if (ret) | |
| 316 | + return ret; | |
| 317 | + | |
| 318 | + return 0; | |
| 319 | +} | |
| 320 | + | |
| 321 | +static int xgene_cle_set_rss_skeys(struct xgene_enet_cle *cle) | |
| 322 | +{ | |
| 323 | + u32 secret_key_ipv4[4]; /* 16 Bytes*/ | |
| 324 | + int ret = 0; | |
| 325 | + | |
| 326 | + get_random_bytes(secret_key_ipv4, 16); | |
| 327 | + ret = xgene_cle_dram_wr(cle, secret_key_ipv4, 4, 0, | |
| 328 | + RSS_IPV4_HASH_SKEY, CLE_CMD_WR); | |
| 329 | + return ret; | |
| 330 | +} | |
| 331 | + | |
| 332 | +static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata) | |
| 333 | +{ | |
| 334 | + u32 fpsel, dstqid, nfpsel, idt_reg, idx; | |
| 335 | + int i, ret = 0; | |
| 336 | + u16 pool_id; | |
| 337 | + | |
| 338 | + for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) { | |
| 339 | + idx = i % pdata->rxq_cnt; | |
| 340 | + pool_id = pdata->rx_ring[idx]->buf_pool->id; | |
| 341 | + fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20; | |
| 342 | + dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]); | |
| 343 | + nfpsel = 0; | |
| 344 | + idt_reg = 0; | |
| 345 | + | |
| 346 | + xgene_cle_idt_to_hw(dstqid, fpsel, nfpsel, &idt_reg); | |
| 347 | + ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i, | |
| 348 | + RSS_IDT, CLE_CMD_WR); | |
| 349 | + if (ret) | |
| 350 | + return ret; | |
| 351 | + } | |
| 352 | + | |
| 353 | + ret = xgene_cle_set_rss_skeys(&pdata->cle); | |
| 354 | + if (ret) | |
| 355 | + return ret; | |
| 356 | + | |
| 357 | + return 0; | |
| 358 | +} | |
| 359 | + | |
| 360 | +static int xgene_cle_setup_rss(struct xgene_enet_pdata *pdata) | |
| 361 | +{ | |
| 362 | + struct xgene_enet_cle *cle = &pdata->cle; | |
| 363 | + void __iomem *base = cle->base; | |
| 364 | + u32 offset, val = 0; | |
| 365 | + int i, ret = 0; | |
| 366 | + | |
| 367 | + offset = CLE_PORT_OFFSET; | |
| 368 | + for (i = 0; i < cle->parsers; i++) { | |
| 369 | + if (cle->active_parser != PARSER_ALL) | |
| 370 | + offset = cle->active_parser * CLE_PORT_OFFSET; | |
| 371 | + else | |
| 372 | + offset = i * CLE_PORT_OFFSET; | |
| 373 | + | |
| 374 | + /* enable RSS */ | |
| 375 | + val = (RSS_IPV4_12B << 1) | 0x1; | |
| 376 | + writel(val, base + RSS_CTRL0 + offset); | |
| 377 | + } | |
| 378 | + | |
| 379 | + /* setup sideband data */ | |
| 380 | + ret = xgene_cle_set_rss_sband(cle); | |
| 381 | + if (ret) | |
| 382 | + return ret; | |
| 383 | + | |
| 384 | + /* setup indirection table */ | |
| 385 | + ret = xgene_cle_set_rss_idt(pdata); | |
| 386 | + if (ret) | |
| 387 | + return ret; | |
| 388 | + | |
| 389 | + return 0; | |
| 390 | +} | |
| 391 | + | |
| 392 | +static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata) | |
| 393 | +{ | |
| 394 | + struct xgene_enet_cle *enet_cle = &pdata->cle; | |
| 395 | + struct xgene_cle_dbptr dbptr[DB_MAX_PTRS]; | |
| 396 | + struct xgene_cle_ptree_branch *br; | |
| 397 | + u32 def_qid, def_fpsel, pool_id; | |
| 398 | + struct xgene_cle_ptree *ptree; | |
| 399 | + struct xgene_cle_ptree_kn kn; | |
| 400 | + int ret; | |
| 401 | + struct xgene_cle_ptree_ewdn ptree_dn[] = { | |
| 402 | + { | |
| 403 | + /* PKT_TYPE_NODE */ | |
| 404 | + .node_type = EWDN, | |
| 405 | + .last_node = 0, | |
| 406 | + .hdr_len_store = 1, | |
| 407 | + .hdr_extn = NO_BYTE, | |
| 408 | + .byte_store = NO_BYTE, | |
| 409 | + .search_byte_store = NO_BYTE, | |
| 410 | + .result_pointer = DB_RES_DROP, | |
| 411 | + .num_branches = 2, | |
| 412 | + .branch = { | |
| 413 | + { | |
| 414 | + /* IPV4 */ | |
| 415 | + .valid = 0, | |
| 416 | + .next_packet_pointer = 22, | |
| 417 | + .jump_bw = JMP_FW, | |
| 418 | + .jump_rel = JMP_ABS, | |
| 419 | + .operation = EQT, | |
| 420 | + .next_node = PKT_PROT_NODE, | |
| 421 | + .next_branch = 0, | |
| 422 | + .data = 0x8, | |
| 423 | + .mask = 0xffff | |
| 424 | + }, | |
| 425 | + { | |
| 426 | + .valid = 0, | |
| 427 | + .next_packet_pointer = 262, | |
| 428 | + .jump_bw = JMP_FW, | |
| 429 | + .jump_rel = JMP_ABS, | |
| 430 | + .operation = EQT, | |
| 431 | + .next_node = LAST_NODE, | |
| 432 | + .next_branch = 0, | |
| 433 | + .data = 0x0, | |
| 434 | + .mask = 0xffff | |
| 435 | + } | |
| 436 | + }, | |
| 437 | + }, | |
| 438 | + { | |
| 439 | + /* PKT_PROT_NODE */ | |
| 440 | + .node_type = EWDN, | |
| 441 | + .last_node = 0, | |
| 442 | + .hdr_len_store = 1, | |
| 443 | + .hdr_extn = NO_BYTE, | |
| 444 | + .byte_store = NO_BYTE, | |
| 445 | + .search_byte_store = NO_BYTE, | |
| 446 | + .result_pointer = DB_RES_DROP, | |
| 447 | + .num_branches = 3, | |
| 448 | + .branch = { | |
| 449 | + { | |
| 450 | + /* TCP */ | |
| 451 | + .valid = 1, | |
| 452 | + .next_packet_pointer = 26, | |
| 453 | + .jump_bw = JMP_FW, | |
| 454 | + .jump_rel = JMP_ABS, | |
| 455 | + .operation = EQT, | |
| 456 | + .next_node = RSS_IPV4_TCP_NODE, | |
| 457 | + .next_branch = 0, | |
| 458 | + .data = 0x0600, | |
| 459 | + .mask = 0xffff | |
| 460 | + }, | |
| 461 | + { | |
| 462 | + /* UDP */ | |
| 463 | + .valid = 1, | |
| 464 | + .next_packet_pointer = 26, | |
| 465 | + .jump_bw = JMP_FW, | |
| 466 | + .jump_rel = JMP_ABS, | |
| 467 | + .operation = EQT, | |
| 468 | + .next_node = RSS_IPV4_UDP_NODE, | |
| 469 | + .next_branch = 0, | |
| 470 | + .data = 0x1100, | |
| 471 | + .mask = 0xffff | |
| 472 | + }, | |
| 473 | + { | |
| 474 | + .valid = 0, | |
| 475 | + .next_packet_pointer = 260, | |
| 476 | + .jump_bw = JMP_FW, | |
| 477 | + .jump_rel = JMP_ABS, | |
| 478 | + .operation = EQT, | |
| 479 | + .next_node = LAST_NODE, | |
| 480 | + .next_branch = 0, | |
| 481 | + .data = 0x0, | |
| 482 | + .mask = 0xffff | |
| 483 | + } | |
| 484 | + } | |
| 485 | + }, | |
| 486 | + { | |
| 487 | + /* RSS_IPV4_TCP_NODE */ | |
| 488 | + .node_type = EWDN, | |
| 489 | + .last_node = 0, | |
| 490 | + .hdr_len_store = 1, | |
| 491 | + .hdr_extn = NO_BYTE, | |
| 492 | + .byte_store = NO_BYTE, | |
| 493 | + .search_byte_store = BOTH_BYTES, | |
| 494 | + .result_pointer = DB_RES_DROP, | |
| 495 | + .num_branches = 6, | |
| 496 | + .branch = { | |
| 497 | + { | |
| 498 | + /* SRC IPV4 B01 */ | |
| 499 | + .valid = 0, | |
| 500 | + .next_packet_pointer = 28, | |
| 501 | + .jump_bw = JMP_FW, | |
| 502 | + .jump_rel = JMP_ABS, | |
| 503 | + .operation = EQT, | |
| 504 | + .next_node = RSS_IPV4_TCP_NODE, | |
| 505 | + .next_branch = 1, | |
| 506 | + .data = 0x0, | |
| 507 | + .mask = 0xffff | |
| 508 | + }, | |
| 509 | + { | |
| 510 | + /* SRC IPV4 B23 */ | |
| 511 | + .valid = 0, | |
| 512 | + .next_packet_pointer = 30, | |
| 513 | + .jump_bw = JMP_FW, | |
| 514 | + .jump_rel = JMP_ABS, | |
| 515 | + .operation = EQT, | |
| 516 | + .next_node = RSS_IPV4_TCP_NODE, | |
| 517 | + .next_branch = 2, | |
| 518 | + .data = 0x0, | |
| 519 | + .mask = 0xffff | |
| 520 | + }, | |
| 521 | + { | |
| 522 | + /* DST IPV4 B01 */ | |
| 523 | + .valid = 0, | |
| 524 | + .next_packet_pointer = 32, | |
| 525 | + .jump_bw = JMP_FW, | |
| 526 | + .jump_rel = JMP_ABS, | |
| 527 | + .operation = EQT, | |
| 528 | + .next_node = RSS_IPV4_TCP_NODE, | |
| 529 | + .next_branch = 3, | |
| 530 | + .data = 0x0, | |
| 531 | + .mask = 0xffff | |
| 532 | + }, | |
| 533 | + { | |
| 534 | + /* DST IPV4 B23 */ | |
| 535 | + .valid = 0, | |
| 536 | + .next_packet_pointer = 34, | |
| 537 | + .jump_bw = JMP_FW, | |
| 538 | + .jump_rel = JMP_ABS, | |
| 539 | + .operation = EQT, | |
| 540 | + .next_node = RSS_IPV4_TCP_NODE, | |
| 541 | + .next_branch = 4, | |
| 542 | + .data = 0x0, | |
| 543 | + .mask = 0xffff | |
| 544 | + }, | |
| 545 | + { | |
| 546 | + /* TCP SRC Port */ | |
| 547 | + .valid = 0, | |
| 548 | + .next_packet_pointer = 36, | |
| 549 | + .jump_bw = JMP_FW, | |
| 550 | + .jump_rel = JMP_ABS, | |
| 551 | + .operation = EQT, | |
| 552 | + .next_node = RSS_IPV4_TCP_NODE, | |
| 553 | + .next_branch = 5, | |
| 554 | + .data = 0x0, | |
| 555 | + .mask = 0xffff | |
| 556 | + }, | |
| 557 | + { | |
| 558 | + /* TCP DST Port */ | |
| 559 | + .valid = 0, | |
| 560 | + .next_packet_pointer = 256, | |
| 561 | + .jump_bw = JMP_FW, | |
| 562 | + .jump_rel = JMP_ABS, | |
| 563 | + .operation = EQT, | |
| 564 | + .next_node = LAST_NODE, | |
| 565 | + .next_branch = 0, | |
| 566 | + .data = 0x0, | |
| 567 | + .mask = 0xffff | |
| 568 | + } | |
| 569 | + } | |
| 570 | + }, | |
| 571 | + { | |
| 572 | + /* RSS_IPV4_UDP_NODE */ | |
| 573 | + .node_type = EWDN, | |
| 574 | + .last_node = 0, | |
| 575 | + .hdr_len_store = 1, | |
| 576 | + .hdr_extn = NO_BYTE, | |
| 577 | + .byte_store = NO_BYTE, | |
| 578 | + .search_byte_store = BOTH_BYTES, | |
| 579 | + .result_pointer = DB_RES_DROP, | |
| 580 | + .num_branches = 6, | |
| 581 | + .branch = { | |
| 582 | + { | |
| 583 | + /* SRC IPV4 B01 */ | |
| 584 | + .valid = 0, | |
| 585 | + .next_packet_pointer = 28, | |
| 586 | + .jump_bw = JMP_FW, | |
| 587 | + .jump_rel = JMP_ABS, | |
| 588 | + .operation = EQT, | |
| 589 | + .next_node = RSS_IPV4_UDP_NODE, | |
| 590 | + .next_branch = 1, | |
| 591 | + .data = 0x0, | |
| 592 | + .mask = 0xffff | |
| 593 | + }, | |
| 594 | + { | |
| 595 | + /* SRC IPV4 B23 */ | |
| 596 | + .valid = 0, | |
| 597 | + .next_packet_pointer = 30, | |
| 598 | + .jump_bw = JMP_FW, | |
| 599 | + .jump_rel = JMP_ABS, | |
| 600 | + .operation = EQT, | |
| 601 | + .next_node = RSS_IPV4_UDP_NODE, | |
| 602 | + .next_branch = 2, | |
| 603 | + .data = 0x0, | |
| 604 | + .mask = 0xffff | |
| 605 | + }, | |
| 606 | + { | |
| 607 | + /* DST IPV4 B01 */ | |
| 608 | + .valid = 0, | |
| 609 | + .next_packet_pointer = 32, | |
| 610 | + .jump_bw = JMP_FW, | |
| 611 | + .jump_rel = JMP_ABS, | |
| 612 | + .operation = EQT, | |
| 613 | + .next_node = RSS_IPV4_UDP_NODE, | |
| 614 | + .next_branch = 3, | |
| 615 | + .data = 0x0, | |
| 616 | + .mask = 0xffff | |
| 617 | + }, | |
| 618 | + { | |
| 619 | + /* DST IPV4 B23 */ | |
| 620 | + .valid = 0, | |
| 621 | + .next_packet_pointer = 34, | |
| 622 | + .jump_bw = JMP_FW, | |
| 623 | + .jump_rel = JMP_ABS, | |
| 624 | + .operation = EQT, | |
| 625 | + .next_node = RSS_IPV4_UDP_NODE, | |
| 626 | + .next_branch = 4, | |
| 627 | + .data = 0x0, | |
| 628 | + .mask = 0xffff | |
| 629 | + }, | |
| 630 | + { | |
| 631 | + /* TCP SRC Port */ | |
| 632 | + .valid = 0, | |
| 633 | + .next_packet_pointer = 36, | |
| 634 | + .jump_bw = JMP_FW, | |
| 635 | + .jump_rel = JMP_ABS, | |
| 636 | + .operation = EQT, | |
| 637 | + .next_node = RSS_IPV4_UDP_NODE, | |
| 638 | + .next_branch = 5, | |
| 639 | + .data = 0x0, | |
| 640 | + .mask = 0xffff | |
| 641 | + }, | |
| 642 | + { | |
| 643 | + /* TCP DST Port */ | |
| 644 | + .valid = 0, | |
| 645 | + .next_packet_pointer = 256, | |
| 646 | + .jump_bw = JMP_FW, | |
| 647 | + .jump_rel = JMP_ABS, | |
| 648 | + .operation = EQT, | |
| 649 | + .next_node = LAST_NODE, | |
| 650 | + .next_branch = 0, | |
| 651 | + .data = 0x0, | |
| 652 | + .mask = 0xffff | |
| 653 | + } | |
| 654 | + } | |
| 655 | + }, | |
| 656 | + { | |
| 657 | + /* LAST NODE */ | |
| 658 | + .node_type = EWDN, | |
| 659 | + .last_node = 1, | |
| 660 | + .hdr_len_store = 1, | |
| 661 | + .hdr_extn = NO_BYTE, | |
| 662 | + .byte_store = NO_BYTE, | |
| 663 | + .search_byte_store = NO_BYTE, | |
| 664 | + .result_pointer = DB_RES_DROP, | |
| 665 | + .num_branches = 1, | |
| 666 | + .branch = { | |
| 667 | + { | |
| 668 | + .valid = 0, | |
| 669 | + .next_packet_pointer = 0, | |
| 670 | + .jump_bw = JMP_FW, | |
| 671 | + .jump_rel = JMP_ABS, | |
| 672 | + .operation = EQT, | |
| 673 | + .next_node = MAX_NODES, | |
| 674 | + .next_branch = 0, | |
| 675 | + .data = 0, | |
| 676 | + .mask = 0xffff | |
| 677 | + } | |
| 678 | + } | |
| 679 | + } | |
| 680 | + }; | |
| 681 | + | |
| 682 | + ptree = &enet_cle->ptree; | |
| 683 | + ptree->start_pkt = 12; /* Ethertype */ | |
| 684 | + if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { | |
| 685 | + ret = xgene_cle_setup_rss(pdata); | |
| 686 | + if (ret) { | |
| 687 | + netdev_err(pdata->ndev, "RSS initialization failed\n"); | |
| 688 | + return ret; | |
| 689 | + } | |
| 690 | + } else { | |
| 691 | + br = &ptree_dn[PKT_PROT_NODE].branch[0]; | |
| 692 | + br->valid = 0; | |
| 693 | + br->next_packet_pointer = 260; | |
| 694 | + br->next_node = LAST_NODE; | |
| 695 | + br->data = 0x0000; | |
| 696 | + br->mask = 0xffff; | |
| 697 | + } | |
| 698 | + | |
| 699 | + def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]); | |
| 700 | + pool_id = pdata->rx_ring[0]->buf_pool->id; | |
| 701 | + def_fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20; | |
| 702 | + | |
| 703 | + memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS); | |
| 704 | + dbptr[DB_RES_ACCEPT].fpsel = def_fpsel; | |
| 705 | + dbptr[DB_RES_ACCEPT].dstqid = def_qid; | |
| 706 | + dbptr[DB_RES_ACCEPT].cle_priority = 1; | |
| 707 | + | |
| 708 | + dbptr[DB_RES_DEF].fpsel = def_fpsel; | |
| 709 | + dbptr[DB_RES_DEF].dstqid = def_qid; | |
| 710 | + dbptr[DB_RES_DEF].cle_priority = 7; | |
| 711 | + xgene_cle_setup_def_dbptr(pdata, enet_cle, &dbptr[DB_RES_DEF], | |
| 712 | + DB_RES_ACCEPT, 7); | |
| 713 | + | |
| 714 | + dbptr[DB_RES_DROP].drop = 1; | |
| 715 | + | |
| 716 | + memset(&kn, 0, sizeof(kn)); | |
| 717 | + kn.node_type = KN; | |
| 718 | + kn.num_keys = 1; | |
| 719 | + kn.key[0].priority = 0; | |
| 720 | + kn.key[0].result_pointer = DB_RES_ACCEPT; | |
| 721 | + | |
| 722 | + ptree->dn = ptree_dn; | |
| 723 | + ptree->kn = &kn; | |
| 724 | + ptree->dbptr = dbptr; | |
| 725 | + ptree->num_dn = MAX_NODES; | |
| 726 | + ptree->num_kn = 1; | |
| 727 | + ptree->num_dbptr = DB_MAX_PTRS; | |
| 728 | + | |
| 729 | + return xgene_cle_setup_ptree(pdata, enet_cle); | |
| 730 | +} | |
| 731 | + | |
| 732 | +struct xgene_cle_ops xgene_cle3in_ops = { | |
| 733 | + .cle_init = xgene_enet_cle_init, | |
| 734 | +}; | |
| @@ -0,0 +1,295 @@ | ||
| 1 | +/* Applied Micro X-Gene SoC Ethernet Classifier structures | |
| 2 | + * | |
| 3 | + * Copyright (c) 2016, Applied Micro Circuits Corporation | |
| 4 | + * Authors: Khuong Dinh <kdinh@apm.com> | |
| 5 | + * Tanmay Inamdar <tinamdar@apm.com> | |
| 6 | + * Iyappan Subramanian <isubramanian@apm.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify it | |
| 9 | + * under the terms of the GNU General Public License as published by the | |
| 10 | + * Free Software Foundation; either version 2 of the License, or (at your | |
| 11 | + * option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + * | |
| 18 | + * You should have received a copy of the GNU General Public License | |
| 19 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#ifndef __XGENE_ENET_CLE_H__ | |
| 23 | +#define __XGENE_ENET_CLE_H__ | |
| 24 | + | |
| 25 | +#include <linux/io.h> | |
| 26 | +#include <linux/random.h> | |
| 27 | + | |
| 28 | +/* Register offsets */ | |
| 29 | +#define INDADDR 0x04 | |
| 30 | +#define INDCMD 0x08 | |
| 31 | +#define INDCMD_STATUS 0x0c | |
| 32 | +#define DATA_RAM0 0x10 | |
| 33 | +#define SNPTR0 0x0100 | |
| 34 | +#define SPPTR0 0x0104 | |
| 35 | +#define DFCLSRESDBPTR0 0x0108 | |
| 36 | +#define DFCLSRESDB00 0x010c | |
| 37 | +#define RSS_CTRL0 0x0000013c | |
| 38 | + | |
| 39 | +#define CLE_CMD_TO 10 /* ms */ | |
| 40 | +#define CLE_PKTRAM_SIZE 256 /* bytes */ | |
| 41 | +#define CLE_PORT_OFFSET 0x200 | |
| 42 | +#define CLE_DRAM_REGS 17 | |
| 43 | + | |
| 44 | +#define CLE_DN_TYPE_LEN 2 | |
| 45 | +#define CLE_DN_TYPE_POS 0 | |
| 46 | +#define CLE_DN_LASTN_LEN 1 | |
| 47 | +#define CLE_DN_LASTN_POS 2 | |
| 48 | +#define CLE_DN_HLS_LEN 1 | |
| 49 | +#define CLE_DN_HLS_POS 3 | |
| 50 | +#define CLE_DN_EXT_LEN 2 | |
| 51 | +#define CLE_DN_EXT_POS 4 | |
| 52 | +#define CLE_DN_BSTOR_LEN 2 | |
| 53 | +#define CLE_DN_BSTOR_POS 6 | |
| 54 | +#define CLE_DN_SBSTOR_LEN 2 | |
| 55 | +#define CLE_DN_SBSTOR_POS 8 | |
| 56 | +#define CLE_DN_RPTR_LEN 12 | |
| 57 | +#define CLE_DN_RPTR_POS 12 | |
| 58 | + | |
| 59 | +#define CLE_BR_VALID_LEN 1 | |
| 60 | +#define CLE_BR_VALID_POS 0 | |
| 61 | +#define CLE_BR_NPPTR_LEN 9 | |
| 62 | +#define CLE_BR_NPPTR_POS 1 | |
| 63 | +#define CLE_BR_JB_LEN 1 | |
| 64 | +#define CLE_BR_JB_POS 10 | |
| 65 | +#define CLE_BR_JR_LEN 1 | |
| 66 | +#define CLE_BR_JR_POS 11 | |
| 67 | +#define CLE_BR_OP_LEN 3 | |
| 68 | +#define CLE_BR_OP_POS 12 | |
| 69 | +#define CLE_BR_NNODE_LEN 9 | |
| 70 | +#define CLE_BR_NNODE_POS 15 | |
| 71 | +#define CLE_BR_NBR_LEN 5 | |
| 72 | +#define CLE_BR_NBR_POS 24 | |
| 73 | + | |
| 74 | +#define CLE_BR_DATA_LEN 16 | |
| 75 | +#define CLE_BR_DATA_POS 0 | |
| 76 | +#define CLE_BR_MASK_LEN 16 | |
| 77 | +#define CLE_BR_MASK_POS 16 | |
| 78 | + | |
| 79 | +#define CLE_KN_PRIO_POS 0 | |
| 80 | +#define CLE_KN_PRIO_LEN 3 | |
| 81 | +#define CLE_KN_RPTR_POS 3 | |
| 82 | +#define CLE_KN_RPTR_LEN 10 | |
| 83 | +#define CLE_TYPE_POS 0 | |
| 84 | +#define CLE_TYPE_LEN 2 | |
| 85 | + | |
| 86 | +#define CLE_DSTQIDL_POS 25 | |
| 87 | +#define CLE_DSTQIDL_LEN 7 | |
| 88 | +#define CLE_DSTQIDH_POS 0 | |
| 89 | +#define CLE_DSTQIDH_LEN 5 | |
| 90 | +#define CLE_FPSEL_POS 21 | |
| 91 | +#define CLE_FPSEL_LEN 4 | |
| 92 | +#define CLE_PRIORITY_POS 5 | |
| 93 | +#define CLE_PRIORITY_LEN 3 | |
| 94 | + | |
| 95 | +#define JMP_ABS 0 | |
| 96 | +#define JMP_REL 1 | |
| 97 | +#define JMP_FW 0 | |
| 98 | +#define JMP_BW 1 | |
| 99 | + | |
| 100 | +enum xgene_cle_ptree_nodes { | |
| 101 | + PKT_TYPE_NODE, | |
| 102 | + PKT_PROT_NODE, | |
| 103 | + RSS_IPV4_TCP_NODE, | |
| 104 | + RSS_IPV4_UDP_NODE, | |
| 105 | + LAST_NODE, | |
| 106 | + MAX_NODES | |
| 107 | +}; | |
| 108 | + | |
| 109 | +enum xgene_cle_byte_store { | |
| 110 | + NO_BYTE, | |
| 111 | + FIRST_BYTE, | |
| 112 | + SECOND_BYTE, | |
| 113 | + BOTH_BYTES | |
| 114 | +}; | |
| 115 | + | |
| 116 | +/* Preclassification operation types */ | |
| 117 | +enum xgene_cle_node_type { | |
| 118 | + INV, | |
| 119 | + KN, | |
| 120 | + EWDN, | |
| 121 | + RES_NODE | |
| 122 | +}; | |
| 123 | + | |
| 124 | +/* Preclassification operation types */ | |
| 125 | +enum xgene_cle_op_type { | |
| 126 | + EQT, | |
| 127 | + NEQT, | |
| 128 | + LTEQT, | |
| 129 | + GTEQT, | |
| 130 | + AND, | |
| 131 | + NAND | |
| 132 | +}; | |
| 133 | + | |
| 134 | +enum xgene_cle_parser { | |
| 135 | + PARSER0, | |
| 136 | + PARSER1, | |
| 137 | + PARSER2, | |
| 138 | + PARSER_ALL | |
| 139 | +}; | |
| 140 | + | |
| 141 | +#define XGENE_CLE_DRAM(type) (((type) & 0xf) << 28) | |
| 142 | +enum xgene_cle_dram_type { | |
| 143 | + PKT_RAM, | |
| 144 | + RSS_IDT, | |
| 145 | + RSS_IPV4_HASH_SKEY, | |
| 146 | + PTREE_RAM = 0xc, | |
| 147 | + AVL_RAM, | |
| 148 | + DB_RAM | |
| 149 | +}; | |
| 150 | + | |
| 151 | +enum xgene_cle_cmd_type { | |
| 152 | + CLE_CMD_WR = 1, | |
| 153 | + CLE_CMD_RD = 2, | |
| 154 | + CLE_CMD_AVL_ADD = 8, | |
| 155 | + CLE_CMD_AVL_DEL = 16, | |
| 156 | + CLE_CMD_AVL_SRCH = 32 | |
| 157 | +}; | |
| 158 | + | |
| 159 | +enum xgene_cle_ipv4_rss_hashtype { | |
| 160 | + RSS_IPV4_8B, | |
| 161 | + RSS_IPV4_12B, | |
| 162 | +}; | |
| 163 | + | |
| 164 | +enum xgene_cle_prot_type { | |
| 165 | + XGENE_CLE_TCP, | |
| 166 | + XGENE_CLE_UDP, | |
| 167 | + XGENE_CLE_ESP, | |
| 168 | + XGENE_CLE_OTHER | |
| 169 | +}; | |
| 170 | + | |
| 171 | +enum xgene_cle_prot_version { | |
| 172 | + XGENE_CLE_IPV4, | |
| 173 | +}; | |
| 174 | + | |
| 175 | +enum xgene_cle_ptree_dbptrs { | |
| 176 | + DB_RES_DROP, | |
| 177 | + DB_RES_DEF, | |
| 178 | + DB_RES_ACCEPT, | |
| 179 | + DB_MAX_PTRS | |
| 180 | +}; | |
| 181 | + | |
| 182 | +/* RSS sideband signal info */ | |
| 183 | +#define SB_IPFRAG_POS 0 | |
| 184 | +#define SB_IPFRAG_LEN 1 | |
| 185 | +#define SB_IPPROT_POS 1 | |
| 186 | +#define SB_IPPROT_LEN 2 | |
| 187 | +#define SB_IPVER_POS 3 | |
| 188 | +#define SB_IPVER_LEN 1 | |
| 189 | +#define SB_HDRLEN_POS 4 | |
| 190 | +#define SB_HDRLEN_LEN 12 | |
| 191 | + | |
| 192 | +/* RSS indirection table */ | |
| 193 | +#define XGENE_CLE_IDT_ENTRIES 128 | |
| 194 | +#define IDT_DSTQID_POS 0 | |
| 195 | +#define IDT_DSTQID_LEN 12 | |
| 196 | +#define IDT_FPSEL_POS 12 | |
| 197 | +#define IDT_FPSEL_LEN 4 | |
| 198 | +#define IDT_NFPSEL_POS 16 | |
| 199 | +#define IDT_NFPSEL_LEN 4 | |
| 200 | + | |
| 201 | +struct xgene_cle_ptree_branch { | |
| 202 | + bool valid; | |
| 203 | + u16 next_packet_pointer; | |
| 204 | + bool jump_bw; | |
| 205 | + bool jump_rel; | |
| 206 | + u8 operation; | |
| 207 | + u16 next_node; | |
| 208 | + u8 next_branch; | |
| 209 | + u16 data; | |
| 210 | + u16 mask; | |
| 211 | +}; | |
| 212 | + | |
| 213 | +struct xgene_cle_ptree_ewdn { | |
| 214 | + u8 node_type; | |
| 215 | + bool last_node; | |
| 216 | + bool hdr_len_store; | |
| 217 | + u8 hdr_extn; | |
| 218 | + u8 byte_store; | |
| 219 | + u8 search_byte_store; | |
| 220 | + u16 result_pointer; | |
| 221 | + u8 num_branches; | |
| 222 | + struct xgene_cle_ptree_branch branch[6]; | |
| 223 | +}; | |
| 224 | + | |
| 225 | +struct xgene_cle_ptree_key { | |
| 226 | + u8 priority; | |
| 227 | + u16 result_pointer; | |
| 228 | +}; | |
| 229 | + | |
| 230 | +struct xgene_cle_ptree_kn { | |
| 231 | + u8 node_type; | |
| 232 | + u8 num_keys; | |
| 233 | + struct xgene_cle_ptree_key key[32]; | |
| 234 | +}; | |
| 235 | + | |
| 236 | +struct xgene_cle_dbptr { | |
| 237 | + u8 split_boundary; | |
| 238 | + u8 mirror_nxtfpsel; | |
| 239 | + u8 mirror_fpsel; | |
| 240 | + u16 mirror_dstqid; | |
| 241 | + u8 drop; | |
| 242 | + u8 mirror; | |
| 243 | + u8 hdr_data_split; | |
| 244 | + u64 hopinfomsbs; | |
| 245 | + u8 DR; | |
| 246 | + u8 HR; | |
| 247 | + u64 hopinfomlsbs; | |
| 248 | + u16 h0enq_num; | |
| 249 | + u8 h0fpsel; | |
| 250 | + u8 nxtfpsel; | |
| 251 | + u8 fpsel; | |
| 252 | + u16 dstqid; | |
| 253 | + u8 cle_priority; | |
| 254 | + u8 cle_flowgroup; | |
| 255 | + u8 cle_perflow; | |
| 256 | + u8 cle_insert_timestamp; | |
| 257 | + u8 stash; | |
| 258 | + u8 in; | |
| 259 | + u8 perprioen; | |
| 260 | + u8 perflowgroupen; | |
| 261 | + u8 perflowen; | |
| 262 | + u8 selhash; | |
| 263 | + u8 selhdrext; | |
| 264 | + u8 mirror_nxtfpsel_msb; | |
| 265 | + u8 mirror_fpsel_msb; | |
| 266 | + u8 hfpsel_msb; | |
| 267 | + u8 nxtfpsel_msb; | |
| 268 | + u8 fpsel_msb; | |
| 269 | +}; | |
| 270 | + | |
| 271 | +struct xgene_cle_ptree { | |
| 272 | + struct xgene_cle_ptree_ewdn *dn; | |
| 273 | + struct xgene_cle_ptree_kn *kn; | |
| 274 | + struct xgene_cle_dbptr *dbptr; | |
| 275 | + u32 num_dn; | |
| 276 | + u32 num_kn; | |
| 277 | + u32 num_dbptr; | |
| 278 | + u32 start_node; | |
| 279 | + u32 start_pkt; | |
| 280 | + u32 start_dbptr; | |
| 281 | +}; | |
| 282 | + | |
| 283 | +struct xgene_enet_cle { | |
| 284 | + void __iomem *base; | |
| 285 | + struct xgene_cle_ptree ptree; | |
| 286 | + enum xgene_cle_parser active_parser; | |
| 287 | + u32 parsers; | |
| 288 | + u32 max_nodes; | |
| 289 | + u32 max_dbptrs; | |
| 290 | + u32 jump_bytes; | |
| 291 | +}; | |
| 292 | + | |
| 293 | +extern struct xgene_cle_ops xgene_cle3in_ops; | |
| 294 | + | |
| 295 | +#endif /* __XGENE_ENET_CLE_H__ */ | |
| @@ -204,6 +204,17 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring) · 203 unmodified lines | ||
| 204 | 204 | return num_msgs; |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | +static void xgene_enet_setup_coalescing(struct xgene_enet_desc_ring *ring) | |
| 208 | +{ | |
| 209 | + u32 data = 0x7777; | |
| 210 | + | |
| 211 | + xgene_enet_ring_wr32(ring, CSR_PBM_COAL, 0x8e); | |
| 212 | + xgene_enet_ring_wr32(ring, CSR_PBM_CTICK1, data); | |
| 213 | + xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data << 16); | |
| 214 | + xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x40); | |
| 215 | + xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x80); | |
| 216 | +} | |
| 217 | + | |
| 207 | 218 | void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, |
| 208 | 219 | struct xgene_enet_pdata *pdata, |
| 209 | 220 | enum xgene_enet_err_code status) |
| @@ -892,4 +903,5 @@ struct xgene_ring_ops xgene_ring1_ops = { · 682 unmodified lines | ||
| 892 | 903 | .clear = xgene_enet_clear_ring, |
| 893 | 904 | .wr_cmd = xgene_enet_wr_cmd, |
| 894 | 905 | .len = xgene_enet_ring_len, |
| 906 | + .coalesce = xgene_enet_setup_coalescing, | |
| 895 | 907 | }; |
| @@ -54,6 +54,11 @@ enum xgene_enet_rm { · 53 unmodified lines | ||
| 54 | 54 | #define IS_BUFFER_POOL BIT(20) |
| 55 | 55 | #define PREFETCH_BUF_EN BIT(21) |
| 56 | 56 | #define CSR_RING_ID_BUF 0x000c |
| 57 | +#define CSR_PBM_COAL 0x0014 | |
| 58 | +#define CSR_PBM_CTICK1 0x001c | |
| 59 | +#define CSR_PBM_CTICK2 0x0020 | |
| 60 | +#define CSR_THRESHOLD0_SET1 0x0030 | |
| 61 | +#define CSR_THRESHOLD1_SET1 0x0034 | |
| 57 | 62 | #define CSR_RING_NE_INT_MODE 0x017c |
| 58 | 63 | #define CSR_RING_CONFIG 0x006c |
| 59 | 64 | #define CSR_RING_WR_BASE 0x0070 |
| @@ -101,6 +106,7 @@ enum xgene_enet_rm { · 41 unmodified lines | ||
| 101 | 106 | #define MAC_OFFSET 0x30 |
| 102 | 107 | |
| 103 | 108 | #define BLOCK_ETH_CSR_OFFSET 0x2000 |
| 109 | +#define BLOCK_ETH_CLE_CSR_OFFSET 0x6000 | |
| 104 | 110 | #define BLOCK_ETH_RING_IF_OFFSET 0x9000 |
| 105 | 111 | #define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000 |
| 106 | 112 | #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 |
| @@ -93,13 +93,6 @@ static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool, · 92 unmodified lines | ||
| 93 | 93 | return 0; |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | −static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring) | |
| 97 | −{ | |
| 98 | − struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); | |
| 99 | − | |
| 100 | − return ((u16)pdata->rm << 10) | ring->num; | |
| 101 | −} | |
| 102 | − | |
| 103 | 96 | static u8 xgene_enet_hdr_len(const void *data) |
| 104 | 97 | { |
| 105 | 98 | const struct ethhdr *eth = data; |
| @@ -189,7 +182,6 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring, · 83 unmodified lines | ||
| 189 | 182 | static u64 xgene_enet_work_msg(struct sk_buff *skb) |
| 190 | 183 | { |
| 191 | 184 | struct net_device *ndev = skb->dev; |
| 192 | − struct xgene_enet_pdata *pdata = netdev_priv(ndev); | |
| 193 | 185 | struct iphdr *iph; |
| 194 | 186 | u8 l3hlen = 0, l4hlen = 0; |
| 195 | 187 | u8 ethhdr, proto = 0, csum_enable = 0; |
| @@ -235,10 +227,6 @@ static u64 xgene_enet_work_msg(struct sk_buff *skb) · 39 unmodified lines | ||
| 235 | 227 | if (!mss || ((skb->len - hdr_len) <= mss)) |
| 236 | 228 | goto out; |
| 237 | 229 | |
| 238 | − if (mss != pdata->mss) { | |
| 239 | − pdata->mss = mss; | |
| 240 | − pdata->mac_ops->set_mss(pdata); | |
| 241 | − } | |
| 242 | 230 | hopinfo |= SET_BIT(ET); |
| 243 | 231 | } |
| 244 | 232 | } else if (iph->protocol == IPPROTO_UDP) { |
| @@ -420,7 +408,7 @@ out: · 175 unmodified lines | ||
| 420 | 408 | raw_desc->m0 = cpu_to_le64(SET_VAL(LL, ll) | SET_VAL(NV, nv) | |
| 421 | 409 | SET_VAL(USERINFO, tx_ring->tail)); |
| 422 | 410 | tx_ring->cp_ring->cp_skb[tx_ring->tail] = skb; |
| 423 | − pdata->tx_level += count; | |
| 411 | + pdata->tx_level[tx_ring->cp_ring->index] += count; | |
| 424 | 412 | tx_ring->tail = tail; |
| 425 | 413 | |
| 426 | 414 | return count; |
| @@ -430,15 +418,17 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb, · 3 unmodified lines | ||
| 430 | 418 | struct net_device *ndev) |
| 431 | 419 | { |
| 432 | 420 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); |
| 433 | − struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring; | |
| 434 | − u32 tx_level = pdata->tx_level; | |
| 421 | + struct xgene_enet_desc_ring *tx_ring; | |
| 422 | + int index = skb->queue_mapping; | |
| 423 | + u32 tx_level = pdata->tx_level[index]; | |
| 435 | 424 | int count; |
| 436 | 425 | |
| 437 | − if (tx_level < pdata->txc_level) | |
| 438 | − tx_level += ((typeof(pdata->tx_level))~0U); | |
| 426 | + tx_ring = pdata->tx_ring[index]; | |
| 427 | + if (tx_level < pdata->txc_level[index]) | |
| 428 | + tx_level += ((typeof(pdata->tx_level[index]))~0U); | |
| 439 | 429 | |
| 440 | − if ((tx_level - pdata->txc_level) > pdata->tx_qcnt_hi) { | |
| 441 | − netif_stop_queue(ndev); | |
| 430 | + if ((tx_level - pdata->txc_level[index]) > pdata->tx_qcnt_hi) { | |
| 431 | + netif_stop_subqueue(ndev, index); | |
| 442 | 432 | return NETDEV_TX_BUSY; |
| 443 | 433 | } |
| 444 | 434 | |
| @@ -536,7 +526,8 @@ static bool is_rx_desc(struct xgene_enet_raw_desc *raw_desc) · 91 unmodified lines | ||
| 536 | 526 | static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring, |
| 537 | 527 | int budget) |
| 538 | 528 | { |
| 539 | − struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); | |
| 529 | + struct net_device *ndev = ring->ndev; | |
| 530 | + struct xgene_enet_pdata *pdata = netdev_priv(ndev); | |
| 540 | 531 | struct xgene_enet_raw_desc *raw_desc, *exp_desc; |
| 541 | 532 | u16 head = ring->head; |
| 542 | 533 | u16 slots = ring->slots - 1; |
| @@ -580,7 +571,7 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring, · 37 unmodified lines | ||
| 580 | 571 | desc_count++; |
| 581 | 572 | processed++; |
| 582 | 573 | if (is_completion) |
| 583 | − pdata->txc_level += desc_count; | |
| 574 | + pdata->txc_level[ring->index] += desc_count; | |
| 584 | 575 | |
| 585 | 576 | if (ret) |
| 586 | 577 | break; |
| @@ -590,8 +581,8 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring, · 3 unmodified lines | ||
| 590 | 581 | pdata->ring_ops->wr_cmd(ring, -count); |
| 591 | 582 | ring->head = head; |
| 592 | 583 | |
| 593 | − if (netif_queue_stopped(ring->ndev)) | |
| 594 | − netif_start_queue(ring->ndev); | |
| 584 | + if (__netif_subqueue_stopped(ndev, ring->index)) | |
| 585 | + netif_start_subqueue(ndev, ring->index); | |
| 595 | 586 | } |
| 596 | 587 | |
| 597 | 588 | return processed; |
| @@ -616,8 +607,16 @@ static int xgene_enet_napi(struct napi_struct *napi, const int budget) · 18 unmodified lines | ||
| 616 | 607 | static void xgene_enet_timeout(struct net_device *ndev) |
| 617 | 608 | { |
| 618 | 609 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); |
| 610 | + struct netdev_queue *txq; | |
| 611 | + int i; | |
| 619 | 612 | |
| 620 | 613 | pdata->mac_ops->reset(pdata); |
| 614 | + | |
| 615 | + for (i = 0; i < pdata->txq_cnt; i++) { | |
| 616 | + txq = netdev_get_tx_queue(ndev, i); | |
| 617 | + txq->trans_start = jiffies; | |
| 618 | + netif_tx_start_queue(txq); | |
| 619 | + } | |
| 621 | 620 | } |
| 622 | 621 | |
| 623 | 622 | static int xgene_enet_register_irq(struct net_device *ndev) |
| @@ -625,17 +624,21 @@ static int xgene_enet_register_irq(struct net_device *ndev) · 1 unmodified line | ||
| 625 | 624 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); |
| 626 | 625 | struct device *dev = ndev_to_dev(ndev); |
| 627 | 626 | struct xgene_enet_desc_ring *ring; |
| 628 | − int ret; | |
| 627 | + int ret = 0, i; | |
| 629 | 628 | |
| 630 | − ring = pdata->rx_ring; | |
| 631 | − irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); | |
| 632 | − ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq, | |
| 633 | − IRQF_SHARED, ring->irq_name, ring); | |
| 634 | − if (ret) | |
| 635 | − netdev_err(ndev, "Failed to request irq %s\n", ring->irq_name); | |
| 629 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 630 | + ring = pdata->rx_ring[i]; | |
| 631 | + irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); | |
| 632 | + ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq, | |
| 633 | + IRQF_SHARED, ring->irq_name, ring); | |
| 634 | + if (ret) { | |
| 635 | + netdev_err(ndev, "Failed to request irq %s\n", | |
| 636 | + ring->irq_name); | |
| 637 | + } | |
| 638 | + } | |
| 636 | 639 | |
| 637 | − if (pdata->cq_cnt) { | |
| 638 | − ring = pdata->tx_ring->cp_ring; | |
| 640 | + for (i = 0; i < pdata->cq_cnt; i++) { | |
| 641 | + ring = pdata->tx_ring[i]->cp_ring; | |
| 639 | 642 | irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); |
| 640 | 643 | ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq, |
| 641 | 644 | IRQF_SHARED, ring->irq_name, ring); |
| @@ -653,15 +656,19 @@ static void xgene_enet_free_irq(struct net_device *ndev) · 11 unmodified lines | ||
| 653 | 656 | struct xgene_enet_pdata *pdata; |
| 654 | 657 | struct xgene_enet_desc_ring *ring; |
| 655 | 658 | struct device *dev; |
| 659 | + int i; | |
| 656 | 660 | |
| 657 | 661 | pdata = netdev_priv(ndev); |
| 658 | 662 | dev = ndev_to_dev(ndev); |
| 659 | − ring = pdata->rx_ring; | |
| 660 | − irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); | |
| 661 | − devm_free_irq(dev, ring->irq, ring); | |
| 662 | 663 | |
| 663 | − if (pdata->cq_cnt) { | |
| 664 | − ring = pdata->tx_ring->cp_ring; | |
| 664 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 665 | + ring = pdata->rx_ring[i]; | |
| 666 | + irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); | |
| 667 | + devm_free_irq(dev, ring->irq, ring); | |
| 668 | + } | |
| 669 | + | |
| 670 | + for (i = 0; i < pdata->cq_cnt; i++) { | |
| 671 | + ring = pdata->tx_ring[i]->cp_ring; | |
| 665 | 672 | irq_clear_status_flags(ring->irq, IRQ_DISABLE_UNLAZY); |
| 666 | 673 | devm_free_irq(dev, ring->irq, ring); |
| 667 | 674 | } |
| @@ -670,12 +677,15 @@ static void xgene_enet_free_irq(struct net_device *ndev) · 2 unmodified lines | ||
| 670 | 677 | static void xgene_enet_napi_enable(struct xgene_enet_pdata *pdata) |
| 671 | 678 | { |
| 672 | 679 | struct napi_struct *napi; |
| 680 | + int i; | |
| 673 | 681 | |
| 674 | − napi = &pdata->rx_ring->napi; | |
| 675 | − napi_enable(napi); | |
| 682 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 683 | + napi = &pdata->rx_ring[i]->napi; | |
| 684 | + napi_enable(napi); | |
| 685 | + } | |
| 676 | 686 | |
| 677 | − if (pdata->cq_cnt) { | |
| 678 | − napi = &pdata->tx_ring->cp_ring->napi; | |
| 687 | + for (i = 0; i < pdata->cq_cnt; i++) { | |
| 688 | + napi = &pdata->tx_ring[i]->cp_ring->napi; | |
| 679 | 689 | napi_enable(napi); |
| 680 | 690 | } |
| 681 | 691 | } |
| @@ -683,12 +693,15 @@ static void xgene_enet_napi_enable(struct xgene_enet_pdata *pdata) · 1 unmodified line | ||
| 683 | 693 | static void xgene_enet_napi_disable(struct xgene_enet_pdata *pdata) |
| 684 | 694 | { |
| 685 | 695 | struct napi_struct *napi; |
| 696 | + int i; | |
| 686 | 697 | |
| 687 | − napi = &pdata->rx_ring->napi; | |
| 688 | − napi_disable(napi); | |
| 698 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 699 | + napi = &pdata->rx_ring[i]->napi; | |
| 700 | + napi_disable(napi); | |
| 701 | + } | |
| 689 | 702 | |
| 690 | − if (pdata->cq_cnt) { | |
| 691 | − napi = &pdata->tx_ring->cp_ring->napi; | |
| 703 | + for (i = 0; i < pdata->cq_cnt; i++) { | |
| 704 | + napi = &pdata->tx_ring[i]->cp_ring->napi; | |
| 692 | 705 | napi_disable(napi); |
| 693 | 706 | } |
| 694 | 707 | } |
| @@ -699,6 +712,14 @@ static int xgene_enet_open(struct net_device *ndev) · 4 unmodified lines | ||
| 699 | 712 | const struct xgene_mac_ops *mac_ops = pdata->mac_ops; |
| 700 | 713 | int ret; |
| 701 | 714 | |
| 715 | + ret = netif_set_real_num_tx_queues(ndev, pdata->txq_cnt); | |
| 716 | + if (ret) | |
| 717 | + return ret; | |
| 718 | + | |
| 719 | + ret = netif_set_real_num_rx_queues(ndev, pdata->rxq_cnt); | |
| 720 | + if (ret) | |
| 721 | + return ret; | |
| 722 | + | |
| 702 | 723 | mac_ops->tx_enable(pdata); |
| 703 | 724 | mac_ops->rx_enable(pdata); |
| 704 | 725 | |
| @@ -721,6 +742,7 @@ static int xgene_enet_close(struct net_device *ndev) · 16 unmodified lines | ||
| 721 | 742 | { |
| 722 | 743 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); |
| 723 | 744 | const struct xgene_mac_ops *mac_ops = pdata->mac_ops; |
| 745 | + int i; | |
| 724 | 746 | |
| 725 | 747 | netif_stop_queue(ndev); |
| 726 | 748 | |
| @@ -734,7 +756,8 @@ static int xgene_enet_close(struct net_device *ndev) · 7 unmodified lines | ||
| 734 | 756 | |
| 735 | 757 | xgene_enet_free_irq(ndev); |
| 736 | 758 | xgene_enet_napi_disable(pdata); |
| 737 | − xgene_enet_process_ring(pdata->rx_ring, -1); | |
| 759 | + for (i = 0; i < pdata->rxq_cnt; i++) | |
| 760 | + xgene_enet_process_ring(pdata->rx_ring[i], -1); | |
| 738 | 761 | |
| 739 | 762 | return 0; |
| 740 | 763 | } |
| @@ -754,18 +777,26 @@ static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring) · 13 unmodified lines | ||
| 754 | 777 | static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata) |
| 755 | 778 | { |
| 756 | 779 | struct xgene_enet_desc_ring *buf_pool; |
| 780 | + struct xgene_enet_desc_ring *ring; | |
| 781 | + int i; | |
| 757 | 782 | |
| 758 | − if (pdata->tx_ring) { | |
| 759 | − xgene_enet_delete_ring(pdata->tx_ring); | |
| 760 | − pdata->tx_ring = NULL; | |
| 783 | + for (i = 0; i < pdata->txq_cnt; i++) { | |
| 784 | + ring = pdata->tx_ring[i]; | |
| 785 | + if (ring) { | |
| 786 | + xgene_enet_delete_ring(ring); | |
| 787 | + pdata->tx_ring[i] = NULL; | |
| 788 | + } | |
| 761 | 789 | } |
| 762 | 790 | |
| 763 | − if (pdata->rx_ring) { | |
| 764 | − buf_pool = pdata->rx_ring->buf_pool; | |
| 765 | − xgene_enet_delete_bufpool(buf_pool); | |
| 766 | − xgene_enet_delete_ring(buf_pool); | |
| 767 | − xgene_enet_delete_ring(pdata->rx_ring); | |
| 768 | − pdata->rx_ring = NULL; | |
| 791 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 792 | + ring = pdata->rx_ring[i]; | |
| 793 | + if (ring) { | |
| 794 | + buf_pool = ring->buf_pool; | |
| 795 | + xgene_enet_delete_bufpool(buf_pool); | |
| 796 | + xgene_enet_delete_ring(buf_pool); | |
| 797 | + xgene_enet_delete_ring(ring); | |
| 798 | + pdata->rx_ring[i] = NULL; | |
| 799 | + } | |
| 769 | 800 | } |
| 770 | 801 | } |
| 771 | 802 | |
| @@ -820,24 +851,29 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata) · 48 unmodified lines | ||
| 820 | 851 | { |
| 821 | 852 | struct device *dev = &pdata->pdev->dev; |
| 822 | 853 | struct xgene_enet_desc_ring *ring; |
| 854 | + int i; | |
| 855 | + | |
| 856 | + for (i = 0; i < pdata->txq_cnt; i++) { | |
| 857 | + ring = pdata->tx_ring[i]; | |
| 858 | + if (ring) { | |
| 859 | + if (ring->cp_ring && ring->cp_ring->cp_skb) | |
| 860 | + devm_kfree(dev, ring->cp_ring->cp_skb); | |
| 861 | + if (ring->cp_ring && pdata->cq_cnt) | |
| 862 | + xgene_enet_free_desc_ring(ring->cp_ring); | |
| 863 | + xgene_enet_free_desc_ring(ring); | |
| 864 | + } | |
| 865 | + } | |
| 823 | 866 | |
| 824 | − ring = pdata->tx_ring; | |
| 825 | − if (ring) { | |
| 826 | − if (ring->cp_ring && ring->cp_ring->cp_skb) | |
| 827 | − devm_kfree(dev, ring->cp_ring->cp_skb); | |
| 828 | − if (ring->cp_ring && pdata->cq_cnt) | |
| 829 | − xgene_enet_free_desc_ring(ring->cp_ring); | |
| 830 | − xgene_enet_free_desc_ring(ring); | |
| 831 | − } | |
| 832 | − | |
| 833 | − ring = pdata->rx_ring; | |
| 834 | − if (ring) { | |
| 835 | − if (ring->buf_pool) { | |
| 836 | − if (ring->buf_pool->rx_skb) | |
| 837 | − devm_kfree(dev, ring->buf_pool->rx_skb); | |
| 838 | − xgene_enet_free_desc_ring(ring->buf_pool); | |
| 867 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 868 | + ring = pdata->rx_ring[i]; | |
| 869 | + if (ring) { | |
| 870 | + if (ring->buf_pool) { | |
| 871 | + if (ring->buf_pool->rx_skb) | |
| 872 | + devm_kfree(dev, ring->buf_pool->rx_skb); | |
| 873 | + xgene_enet_free_desc_ring(ring->buf_pool); | |
| 874 | + } | |
| 875 | + xgene_enet_free_desc_ring(ring); | |
| 839 | 876 | } |
| 840 | − xgene_enet_free_desc_ring(ring); | |
| 841 | 877 | } |
| 842 | 878 | } |
| 843 | 879 | |
| @@ -950,104 +986,120 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) · 106 unmodified lines | ||
| 950 | 986 | u8 bp_bufnum = pdata->bp_bufnum; |
| 951 | 987 | u16 ring_num = pdata->ring_num; |
| 952 | 988 | u16 ring_id; |
| 953 | − int ret, size; | |
| 954 | − | |
| 955 | − /* allocate rx descriptor ring */ | |
| 956 | − owner = xgene_derive_ring_owner(pdata); | |
| 957 | − ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++); | |
| 958 | − rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 959 | − RING_CFGSIZE_16KB, ring_id); | |
| 960 | − if (!rx_ring) { | |
| 961 | − ret = -ENOMEM; | |
| 962 | − goto err; | |
| 963 | − } | |
| 989 | + int i, ret, size; | |
| 964 | 990 | |
| 965 | − /* allocate buffer pool for receiving packets */ | |
| 966 | − owner = xgene_derive_ring_owner(pdata); | |
| 967 | − ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++); | |
| 968 | − buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 969 | − RING_CFGSIZE_2KB, ring_id); | |
| 970 | − if (!buf_pool) { | |
| 971 | − ret = -ENOMEM; | |
| 972 | − goto err; | |
| 973 | − } | |
| 974 | − | |
| 975 | − rx_ring->nbufpool = NUM_BUFPOOL; | |
| 976 | − rx_ring->buf_pool = buf_pool; | |
| 977 | − rx_ring->irq = pdata->rx_irq; | |
| 978 | − if (!pdata->cq_cnt) { | |
| 979 | − snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc", | |
| 980 | − ndev->name); | |
| 981 | − } else { | |
| 982 | − snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx", ndev->name); | |
| 983 | − } | |
| 984 | − buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots, | |
| 985 | − sizeof(struct sk_buff *), GFP_KERNEL); | |
| 986 | − if (!buf_pool->rx_skb) { | |
| 987 | − ret = -ENOMEM; | |
| 988 | − goto err; | |
| 989 | − } | |
| 990 | − | |
| 991 | − buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool); | |
| 992 | − rx_ring->buf_pool = buf_pool; | |
| 993 | − pdata->rx_ring = rx_ring; | |
| 991 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 992 | + /* allocate rx descriptor ring */ | |
| 993 | + owner = xgene_derive_ring_owner(pdata); | |
| 994 | + ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++); | |
| 995 | + rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 996 | + RING_CFGSIZE_16KB, | |
| 997 | + ring_id); | |
| 998 | + if (!rx_ring) { | |
| 999 | + ret = -ENOMEM; | |
| 1000 | + goto err; | |
| 1001 | + } | |
| 994 | 1002 | |
| 995 | − /* allocate tx descriptor ring */ | |
| 996 | − owner = xgene_derive_ring_owner(pdata); | |
| 997 | − ring_id = xgene_enet_get_ring_id(owner, eth_bufnum++); | |
| 998 | − tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 999 | − RING_CFGSIZE_16KB, ring_id); | |
| 1000 | − if (!tx_ring) { | |
| 1001 | − ret = -ENOMEM; | |
| 1002 | − goto err; | |
| 1003 | − } | |
| 1003 | + /* allocate buffer pool for receiving packets */ | |
| 1004 | + owner = xgene_derive_ring_owner(pdata); | |
| 1005 | + ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++); | |
| 1006 | + buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 1007 | + RING_CFGSIZE_2KB, | |
| 1008 | + ring_id); | |
| 1009 | + if (!buf_pool) { | |
| 1010 | + ret = -ENOMEM; | |
| 1011 | + goto err; | |
| 1012 | + } | |
| 1004 | 1013 | |
| 1005 | − size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS; | |
| 1006 | − tx_ring->exp_bufs = dma_zalloc_coherent(dev, size, &dma_exp_bufs, | |
| 1014 | + rx_ring->nbufpool = NUM_BUFPOOL; | |
| 1015 | + rx_ring->buf_pool = buf_pool; | |
| 1016 | + rx_ring->irq = pdata->irqs[i]; | |
| 1017 | + if (!pdata->cq_cnt) { | |
| 1018 | + snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc", | |
| 1019 | + ndev->name); | |
| 1020 | + } else { | |
| 1021 | + snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx%d", | |
| 1022 | + ndev->name, i); | |
| 1023 | + } | |
| 1024 | + buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots, | |
| 1025 | + sizeof(struct sk_buff *), | |
| 1007 | 1026 | GFP_KERNEL); |
| 1008 | − if (!tx_ring->exp_bufs) { | |
| 1009 | − ret = -ENOMEM; | |
| 1010 | − goto err; | |
| 1011 | − } | |
| 1027 | + if (!buf_pool->rx_skb) { | |
| 1028 | + ret = -ENOMEM; | |
| 1029 | + goto err; | |
| 1030 | + } | |
| 1012 | 1031 | |
| 1013 | − pdata->tx_ring = tx_ring; | |
| 1032 | + buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool); | |
| 1033 | + rx_ring->buf_pool = buf_pool; | |
| 1034 | + pdata->rx_ring[i] = rx_ring; | |
| 1035 | + } | |
| 1014 | 1036 | |
| 1015 | − if (!pdata->cq_cnt) { | |
| 1016 | − cp_ring = pdata->rx_ring; | |
| 1017 | − } else { | |
| 1018 | − /* allocate tx completion descriptor ring */ | |
| 1019 | − ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++); | |
| 1020 | − cp_ring = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 1037 | + for (i = 0; i < pdata->txq_cnt; i++) { | |
| 1038 | + /* allocate tx descriptor ring */ | |
| 1039 | + owner = xgene_derive_ring_owner(pdata); | |
| 1040 | + ring_id = xgene_enet_get_ring_id(owner, eth_bufnum++); | |
| 1041 | + tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 1021 | 1042 | RING_CFGSIZE_16KB, |
| 1022 | 1043 | ring_id); |
| 1023 | − if (!cp_ring) { | |
| 1044 | + if (!tx_ring) { | |
| 1024 | 1045 | ret = -ENOMEM; |
| 1025 | 1046 | goto err; |
| 1026 | 1047 | } |
| 1027 | − cp_ring->irq = pdata->txc_irq; | |
| 1028 | − snprintf(cp_ring->irq_name, IRQ_ID_SIZE, "%s-txc", ndev->name); | |
| 1029 | − } | |
| 1030 | 1048 | |
| 1031 | − cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots, | |
| 1032 | − sizeof(struct sk_buff *), GFP_KERNEL); | |
| 1033 | − if (!cp_ring->cp_skb) { | |
| 1034 | − ret = -ENOMEM; | |
| 1035 | − goto err; | |
| 1036 | − } | |
| 1049 | + size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS; | |
| 1050 | + tx_ring->exp_bufs = dma_zalloc_coherent(dev, size, | |
| 1051 | + &dma_exp_bufs, | |
| 1052 | + GFP_KERNEL); | |
| 1053 | + if (!tx_ring->exp_bufs) { | |
| 1054 | + ret = -ENOMEM; | |
| 1055 | + goto err; | |
| 1056 | + } | |
| 1037 | 1057 | |
| 1038 | − size = sizeof(dma_addr_t) * MAX_SKB_FRAGS; | |
| 1039 | − cp_ring->frag_dma_addr = devm_kcalloc(dev, tx_ring->slots, | |
| 1040 | − size, GFP_KERNEL); | |
| 1041 | − if (!cp_ring->frag_dma_addr) { | |
| 1042 | − devm_kfree(dev, cp_ring->cp_skb); | |
| 1043 | − ret = -ENOMEM; | |
| 1044 | − goto err; | |
| 1045 | − } | |
| 1058 | + pdata->tx_ring[i] = tx_ring; | |
| 1046 | 1059 | |
| 1047 | − pdata->tx_ring->cp_ring = cp_ring; | |
| 1048 | − pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring); | |
| 1060 | + if (!pdata->cq_cnt) { | |
| 1061 | + cp_ring = pdata->rx_ring[i]; | |
| 1062 | + } else { | |
| 1063 | + /* allocate tx completion descriptor ring */ | |
| 1064 | + ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, | |
| 1065 | + cpu_bufnum++); | |
| 1066 | + cp_ring = xgene_enet_create_desc_ring(ndev, ring_num++, | |
| 1067 | + RING_CFGSIZE_16KB, | |
| 1068 | + ring_id); | |
| 1069 | + if (!cp_ring) { | |
| 1070 | + ret = -ENOMEM; | |
| 1071 | + goto err; | |
| 1072 | + } | |
| 1049 | 1073 | |
| 1050 | − pdata->tx_qcnt_hi = pdata->tx_ring->slots - 128; | |
| 1074 | + cp_ring->irq = pdata->irqs[pdata->rxq_cnt + i]; | |
| 1075 | + cp_ring->index = i; | |
| 1076 | + snprintf(cp_ring->irq_name, IRQ_ID_SIZE, "%s-txc%d", | |
| 1077 | + ndev->name, i); | |
| 1078 | + } | |
| 1079 | + | |
| 1080 | + cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots, | |
| 1081 | + sizeof(struct sk_buff *), | |
| 1082 | + GFP_KERNEL); | |
| 1083 | + if (!cp_ring->cp_skb) { | |
| 1084 | + ret = -ENOMEM; | |
| 1085 | + goto err; | |
| 1086 | + } | |
| 1087 | + | |
| 1088 | + size = sizeof(dma_addr_t) * MAX_SKB_FRAGS; | |
| 1089 | + cp_ring->frag_dma_addr = devm_kcalloc(dev, tx_ring->slots, | |
| 1090 | + size, GFP_KERNEL); | |
| 1091 | + if (!cp_ring->frag_dma_addr) { | |
| 1092 | + devm_kfree(dev, cp_ring->cp_skb); | |
| 1093 | + ret = -ENOMEM; | |
| 1094 | + goto err; | |
| 1095 | + } | |
| 1096 | + | |
| 1097 | + tx_ring->cp_ring = cp_ring; | |
| 1098 | + tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring); | |
| 1099 | + } | |
| 1100 | + | |
| 1101 | + pdata->ring_ops->coalesce(pdata->tx_ring[0]); | |
| 1102 | + pdata->tx_qcnt_hi = pdata->tx_ring[0]->slots - 128; | |
| 1051 | 1103 | |
| 1052 | 1104 | return 0; |
| 1053 | 1105 | |
| @@ -1166,6 +1218,32 @@ static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata) · 112 unmodified lines | ||
| 1166 | 1218 | return 0; |
| 1167 | 1219 | } |
| 1168 | 1220 | |
| 1221 | +static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata) | |
| 1222 | +{ | |
| 1223 | + struct platform_device *pdev = pdata->pdev; | |
| 1224 | + struct device *dev = &pdev->dev; | |
| 1225 | + int i, ret, max_irqs; | |
| 1226 | + | |
| 1227 | + if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) | |
| 1228 | + max_irqs = 1; | |
| 1229 | + else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) | |
| 1230 | + max_irqs = 2; | |
| 1231 | + else | |
| 1232 | + max_irqs = XGENE_MAX_ENET_IRQ; | |
| 1233 | + | |
| 1234 | + for (i = 0; i < max_irqs; i++) { | |
| 1235 | + ret = platform_get_irq(pdev, i); | |
| 1236 | + if (ret <= 0) { | |
| 1237 | + dev_err(dev, "Unable to get ENET IRQ\n"); | |
| 1238 | + ret = ret ? : -ENXIO; | |
| 1239 | + return ret; | |
| 1240 | + } | |
| 1241 | + pdata->irqs[i] = ret; | |
| 1242 | + } | |
| 1243 | + | |
| 1244 | + return 0; | |
| 1245 | +} | |
| 1246 | + | |
| 1169 | 1247 | static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) |
| 1170 | 1248 | { |
| 1171 | 1249 | struct platform_device *pdev; |
| @@ -1247,25 +1325,9 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) · 75 unmodified lines | ||
| 1247 | 1325 | if (ret) |
| 1248 | 1326 | return ret; |
| 1249 | 1327 | |
| 1250 | − ret = platform_get_irq(pdev, 0); | |
| 1251 | − if (ret <= 0) { | |
| 1252 | − dev_err(dev, "Unable to get ENET Rx IRQ\n"); | |
| 1253 | − ret = ret ? : -ENXIO; | |
| 1328 | + ret = xgene_enet_get_irqs(pdata); | |
| 1329 | + if (ret) | |
| 1254 | 1330 | return ret; |
| 1255 | − } | |
| 1256 | − pdata->rx_irq = ret; | |
| 1257 | − | |
| 1258 | − if (pdata->phy_mode != PHY_INTERFACE_MODE_RGMII) { | |
| 1259 | − ret = platform_get_irq(pdev, 1); | |
| 1260 | − if (ret <= 0) { | |
| 1261 | − pdata->cq_cnt = 0; | |
| 1262 | − dev_info(dev, "Unable to get Tx completion IRQ," | |
| 1263 | − "using Rx IRQ instead\n"); | |
| 1264 | − } else { | |
| 1265 | − pdata->cq_cnt = XGENE_MAX_TXC_RINGS; | |
| 1266 | − pdata->txc_irq = ret; | |
| 1267 | − } | |
| 1268 | − } | |
| 1269 | 1331 | |
| 1270 | 1332 | pdata->clk = devm_clk_get(&pdev->dev, NULL); |
| 1271 | 1333 | if (IS_ERR(pdata->clk)) { |
| @@ -1278,6 +1340,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) · 6 unmodified lines | ||
| 1278 | 1340 | else |
| 1279 | 1341 | base_addr = pdata->base_addr; |
| 1280 | 1342 | pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET; |
| 1343 | + pdata->cle.base = base_addr + BLOCK_ETH_CLE_CSR_OFFSET; | |
| 1281 | 1344 | pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET; |
| 1282 | 1345 | pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET; |
| 1283 | 1346 | if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII || |
| @@ -1298,10 +1361,11 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) · 14 unmodified lines | ||
| 1298 | 1361 | |
| 1299 | 1362 | static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata) |
| 1300 | 1363 | { |
| 1364 | + struct xgene_enet_cle *enet_cle = &pdata->cle; | |
| 1301 | 1365 | struct net_device *ndev = pdata->ndev; |
| 1302 | 1366 | struct xgene_enet_desc_ring *buf_pool; |
| 1303 | 1367 | u16 dst_ring_num; |
| 1304 | − int ret; | |
| 1368 | + int i, ret; | |
| 1305 | 1369 | |
| 1306 | 1370 | ret = pdata->port_ops->reset(pdata); |
| 1307 | 1371 | if (ret) |
| @@ -1314,16 +1378,36 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata) · 6 unmodified lines | ||
| 1314 | 1378 | } |
| 1315 | 1379 | |
| 1316 | 1380 | /* setup buffer pool */ |
| 1317 | − buf_pool = pdata->rx_ring->buf_pool; | |
| 1318 | − xgene_enet_init_bufpool(buf_pool); | |
| 1319 | − ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt); | |
| 1320 | − if (ret) { | |
| 1321 | − xgene_enet_delete_desc_rings(pdata); | |
| 1322 | − return ret; | |
| 1381 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 1382 | + buf_pool = pdata->rx_ring[i]->buf_pool; | |
| 1383 | + xgene_enet_init_bufpool(buf_pool); | |
| 1384 | + ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt); | |
| 1385 | + if (ret) { | |
| 1386 | + xgene_enet_delete_desc_rings(pdata); | |
| 1387 | + return ret; | |
| 1388 | + } | |
| 1389 | + } | |
| 1390 | + | |
| 1391 | + dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]); | |
| 1392 | + buf_pool = pdata->rx_ring[0]->buf_pool; | |
| 1393 | + if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { | |
| 1394 | + /* Initialize and Enable PreClassifier Tree */ | |
| 1395 | + enet_cle->max_nodes = 512; | |
| 1396 | + enet_cle->max_dbptrs = 1024; | |
| 1397 | + enet_cle->parsers = 3; | |
| 1398 | + enet_cle->active_parser = PARSER_ALL; | |
| 1399 | + enet_cle->ptree.start_node = 0; | |
| 1400 | + enet_cle->ptree.start_dbptr = 0; | |
| 1401 | + enet_cle->jump_bytes = 8; | |
| 1402 | + ret = pdata->cle_ops->cle_init(pdata); | |
| 1403 | + if (ret) { | |
| 1404 | + netdev_err(ndev, "Preclass Tree init error\n"); | |
| 1405 | + return ret; | |
| 1406 | + } | |
| 1407 | + } else { | |
| 1408 | + pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id); | |
| 1323 | 1409 | } |
| 1324 | 1410 | |
| 1325 | − dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring); | |
| 1326 | − pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id); | |
| 1327 | 1411 | pdata->mac_ops->init(pdata); |
| 1328 | 1412 | |
| 1329 | 1413 | return ret; |
| @@ -1336,16 +1420,26 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata) · 6 unmodified lines | ||
| 1336 | 1420 | pdata->mac_ops = &xgene_gmac_ops; |
| 1337 | 1421 | pdata->port_ops = &xgene_gport_ops; |
| 1338 | 1422 | pdata->rm = RM3; |
| 1423 | + pdata->rxq_cnt = 1; | |
| 1424 | + pdata->txq_cnt = 1; | |
| 1425 | + pdata->cq_cnt = 0; | |
| 1339 | 1426 | break; |
| 1340 | 1427 | case PHY_INTERFACE_MODE_SGMII: |
| 1341 | 1428 | pdata->mac_ops = &xgene_sgmac_ops; |
| 1342 | 1429 | pdata->port_ops = &xgene_sgport_ops; |
| 1343 | 1430 | pdata->rm = RM1; |
| 1431 | + pdata->rxq_cnt = 1; | |
| 1432 | + pdata->txq_cnt = 1; | |
| 1433 | + pdata->cq_cnt = 1; | |
| 1344 | 1434 | break; |
| 1345 | 1435 | default: |
| 1346 | 1436 | pdata->mac_ops = &xgene_xgmac_ops; |
| 1347 | 1437 | pdata->port_ops = &xgene_xgport_ops; |
| 1438 | + pdata->cle_ops = &xgene_cle3in_ops; | |
| 1348 | 1439 | pdata->rm = RM0; |
| 1440 | + pdata->rxq_cnt = XGENE_NUM_RX_RING; | |
| 1441 | + pdata->txq_cnt = XGENE_NUM_TX_RING; | |
| 1442 | + pdata->cq_cnt = XGENE_NUM_TXC_RING; | |
| 1349 | 1443 | break; |
| 1350 | 1444 | } |
| 1351 | 1445 | |
| @@ -1399,12 +1493,16 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata) · 47 unmodified lines | ||
| 1399 | 1493 | static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata) |
| 1400 | 1494 | { |
| 1401 | 1495 | struct napi_struct *napi; |
| 1496 | + int i; | |
| 1402 | 1497 | |
| 1403 | − napi = &pdata->rx_ring->napi; | |
| 1404 | − netif_napi_add(pdata->ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT); | |
| 1498 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 1499 | + napi = &pdata->rx_ring[i]->napi; | |
| 1500 | + netif_napi_add(pdata->ndev, napi, xgene_enet_napi, | |
| 1501 | + NAPI_POLL_WEIGHT); | |
| 1502 | + } | |
| 1405 | 1503 | |
| 1406 | − if (pdata->cq_cnt) { | |
| 1407 | − napi = &pdata->tx_ring->cp_ring->napi; | |
| 1504 | + for (i = 0; i < pdata->cq_cnt; i++) { | |
| 1505 | + napi = &pdata->tx_ring[i]->cp_ring->napi; | |
| 1408 | 1506 | netif_napi_add(pdata->ndev, napi, xgene_enet_napi, |
| 1409 | 1507 | NAPI_POLL_WEIGHT); |
| 1410 | 1508 | } |
| @@ -1413,12 +1511,15 @@ static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata) · 2 unmodified lines | ||
| 1413 | 1511 | static void xgene_enet_napi_del(struct xgene_enet_pdata *pdata) |
| 1414 | 1512 | { |
| 1415 | 1513 | struct napi_struct *napi; |
| 1514 | + int i; | |
| 1416 | 1515 | |
| 1417 | − napi = &pdata->rx_ring->napi; | |
| 1418 | − netif_napi_del(napi); | |
| 1516 | + for (i = 0; i < pdata->rxq_cnt; i++) { | |
| 1517 | + napi = &pdata->rx_ring[i]->napi; | |
| 1518 | + netif_napi_del(napi); | |
| 1519 | + } | |
| 1419 | 1520 | |
| 1420 | − if (pdata->cq_cnt) { | |
| 1421 | − napi = &pdata->tx_ring->cp_ring->napi; | |
| 1521 | + for (i = 0; i < pdata->cq_cnt; i++) { | |
| 1522 | + napi = &pdata->tx_ring[i]->cp_ring->napi; | |
| 1422 | 1523 | netif_napi_del(napi); |
| 1423 | 1524 | } |
| 1424 | 1525 | } |
| @@ -1432,7 +1533,8 @@ static int xgene_enet_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 1432 | 1533 | const struct of_device_id *of_id; |
| 1433 | 1534 | int ret; |
| 1434 | 1535 | |
| 1435 | − ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata)); | |
| 1536 | + ndev = alloc_etherdev_mqs(sizeof(struct xgene_enet_pdata), | |
| 1537 | + XGENE_NUM_RX_RING, XGENE_NUM_TX_RING); | |
| 1436 | 1538 | if (!ndev) |
| 1437 | 1539 | return -ENOMEM; |
| 1438 | 1540 | |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | #include <linux/if_vlan.h> |
| 37 | 37 | #include <linux/phy.h> |
| 38 | 38 | #include "xgene_enet_hw.h" |
| 39 | +#include "xgene_enet_cle.h" | |
| 39 | 40 | #include "xgene_enet_ring2.h" |
| 40 | 41 | |
| 41 | 42 | #define XGENE_DRV_VERSION "v1.0" |
| @@ -48,6 +49,11 @@ · 6 unmodified lines | ||
| 48 | 49 | #define XGENE_ENET_MSS 1448 |
| 49 | 50 | #define XGENE_MIN_ENET_FRAME_SIZE 60 |
| 50 | 51 | |
| 52 | +#define XGENE_MAX_ENET_IRQ 8 | |
| 53 | +#define XGENE_NUM_RX_RING 4 | |
| 54 | +#define XGENE_NUM_TX_RING 4 | |
| 55 | +#define XGENE_NUM_TXC_RING 4 | |
| 56 | + | |
| 51 | 57 | #define START_CPU_BUFNUM_0 0 |
| 52 | 58 | #define START_ETH_BUFNUM_0 2 |
| 53 | 59 | #define START_BP_BUFNUM_0 0x22 |
| @@ -72,7 +78,6 @@ · 18 unmodified lines | ||
| 72 | 78 | #define X2_START_RING_NUM_1 256 |
| 73 | 79 | |
| 74 | 80 | #define IRQ_ID_SIZE 16 |
| 75 | −#define XGENE_MAX_TXC_RINGS 1 | |
| 76 | 81 | |
| 77 | 82 | #define PHY_POLL_LINK_ON (10 * HZ) |
| 78 | 83 | #define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5) |
| @@ -102,6 +107,7 @@ struct xgene_enet_desc_ring { · 23 unmodified lines | ||
| 102 | 107 | void *irq_mbox_addr; |
| 103 | 108 | u16 dst_ring_num; |
| 104 | 109 | u8 nbufpool; |
| 110 | + u8 index; | |
| 105 | 111 | struct sk_buff *(*rx_skb); |
| 106 | 112 | struct sk_buff *(*cp_skb); |
| 107 | 113 | dma_addr_t *frag_dma_addr; |
| @@ -143,6 +149,11 @@ struct xgene_ring_ops { · 35 unmodified lines | ||
| 143 | 149 | void (*clear)(struct xgene_enet_desc_ring *); |
| 144 | 150 | void (*wr_cmd)(struct xgene_enet_desc_ring *, int); |
| 145 | 151 | u32 (*len)(struct xgene_enet_desc_ring *); |
| 152 | + void (*coalesce)(struct xgene_enet_desc_ring *); | |
| 153 | +}; | |
| 154 | + | |
| 155 | +struct xgene_cle_ops { | |
| 156 | + int (*cle_init)(struct xgene_enet_pdata *pdata); | |
| 146 | 157 | }; |
| 147 | 158 | |
| 148 | 159 | /* ethernet private data */ |
| @@ -154,15 +165,16 @@ struct xgene_enet_pdata { · 5 unmodified lines | ||
| 154 | 165 | struct clk *clk; |
| 155 | 166 | struct platform_device *pdev; |
| 156 | 167 | enum xgene_enet_id enet_id; |
| 157 | − struct xgene_enet_desc_ring *tx_ring; | |
| 158 | − struct xgene_enet_desc_ring *rx_ring; | |
| 159 | − u16 tx_level; | |
| 160 | − u16 txc_level; | |
| 168 | + struct xgene_enet_desc_ring *tx_ring[XGENE_NUM_TX_RING]; | |
| 169 | + struct xgene_enet_desc_ring *rx_ring[XGENE_NUM_RX_RING]; | |
| 170 | + u16 tx_level[XGENE_NUM_TX_RING]; | |
| 171 | + u16 txc_level[XGENE_NUM_TX_RING]; | |
| 161 | 172 | char *dev_name; |
| 162 | 173 | u32 rx_buff_cnt; |
| 163 | 174 | u32 tx_qcnt_hi; |
| 164 | − u32 rx_irq; | |
| 165 | − u32 txc_irq; | |
| 175 | + u32 irqs[XGENE_MAX_ENET_IRQ]; | |
| 176 | + u8 rxq_cnt; | |
| 177 | + u8 txq_cnt; | |
| 166 | 178 | u8 cq_cnt; |
| 167 | 179 | void __iomem *eth_csr_addr; |
| 168 | 180 | void __iomem *eth_ring_if_addr; |
| @@ -174,10 +186,12 @@ struct xgene_enet_pdata { · 5 unmodified lines | ||
| 174 | 186 | void __iomem *ring_cmd_addr; |
| 175 | 187 | int phy_mode; |
| 176 | 188 | enum xgene_enet_rm rm; |
| 189 | + struct xgene_enet_cle cle; | |
| 177 | 190 | struct rtnl_link_stats64 stats; |
| 178 | 191 | const struct xgene_mac_ops *mac_ops; |
| 179 | 192 | const struct xgene_port_ops *port_ops; |
| 180 | 193 | struct xgene_ring_ops *ring_ops; |
| 194 | + struct xgene_cle_ops *cle_ops; | |
| 181 | 195 | struct delayed_work link_work; |
| 182 | 196 | u32 port_id; |
| 183 | 197 | u8 cpu_bufnum; |
| @@ -229,6 +243,13 @@ static inline struct device *ndev_to_dev(struct net_device *ndev) · 45 unmodified lines | ||
| 229 | 243 | return ndev->dev.parent; |
| 230 | 244 | } |
| 231 | 245 | |
| 246 | +static inline u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring) | |
| 247 | +{ | |
| 248 | + struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); | |
| 249 | + | |
| 250 | + return ((u16)pdata->rm << 10) | ring->num; | |
| 251 | +} | |
| 252 | + | |
| 232 | 253 | void xgene_enet_set_ethtool_ops(struct net_device *netdev); |
| 233 | 254 | |
| 234 | 255 | #endif /* __XGENE_ENET_MAIN_H__ */ |
| @@ -190,6 +190,17 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring) · 189 unmodified lines | ||
| 190 | 190 | return num_msgs; |
| 191 | 191 | } |
| 192 | 192 | |
| 193 | +static void xgene_enet_setup_coalescing(struct xgene_enet_desc_ring *ring) | |
| 194 | +{ | |
| 195 | + u32 data = 0x7777; | |
| 196 | + | |
| 197 | + xgene_enet_ring_wr32(ring, CSR_PBM_COAL, 0x8e); | |
| 198 | + xgene_enet_ring_wr32(ring, CSR_PBM_CTICK1, data); | |
| 199 | + xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data << 16); | |
| 200 | + xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x40); | |
| 201 | + xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x80); | |
| 202 | +} | |
| 203 | + | |
| 193 | 204 | struct xgene_ring_ops xgene_ring2_ops = { |
| 194 | 205 | .num_ring_config = X2_NUM_RING_CONFIG, |
| 195 | 206 | .num_ring_id_shift = 13, |
| @@ -197,4 +208,5 @@ struct xgene_ring_ops xgene_ring2_ops = { · 1 unmodified line | ||
| 197 | 208 | .clear = xgene_enet_clear_ring, |
| 198 | 209 | .wr_cmd = xgene_enet_wr_cmd, |
| 199 | 210 | .len = xgene_enet_ring_len, |
| 211 | + .coalesce = xgene_enet_setup_coalescing, | |
| 200 | 212 | }; |
| @@ -14,36 +14,36 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/clk.h> |
| 15 | 15 | |
| 16 | 16 | /* STATUS and ENABLE Register bit masks */ |
| 17 | −#define TXINT_MASK (1<<0) /* Transmit interrupt */ | |
| 18 | −#define RXINT_MASK (1<<1) /* Receive interrupt */ | |
| 19 | −#define ERR_MASK (1<<2) /* Error interrupt */ | |
| 20 | −#define TXCH_MASK (1<<3) /* Transmit chaining error interrupt */ | |
| 21 | −#define MSER_MASK (1<<4) /* Missed packet counter error */ | |
| 22 | −#define RXCR_MASK (1<<8) /* RXCRCERR counter rolled over */ | |
| 23 | −#define RXFR_MASK (1<<9) /* RXFRAMEERR counter rolled over */ | |
| 24 | −#define RXFL_MASK (1<<10) /* RXOFLOWERR counter rolled over */ | |
| 25 | −#define MDIO_MASK (1<<12) /* MDIO complete interrupt */ | |
| 26 | −#define TXPL_MASK (1<<31) /* Force polling of BD by EMAC */ | |
| 17 | +#define TXINT_MASK (1 << 0) /* Transmit interrupt */ | |
| 18 | +#define RXINT_MASK (1 << 1) /* Receive interrupt */ | |
| 19 | +#define ERR_MASK (1 << 2) /* Error interrupt */ | |
| 20 | +#define TXCH_MASK (1 << 3) /* Transmit chaining error interrupt */ | |
| 21 | +#define MSER_MASK (1 << 4) /* Missed packet counter error */ | |
| 22 | +#define RXCR_MASK (1 << 8) /* RXCRCERR counter rolled over */ | |
| 23 | +#define RXFR_MASK (1 << 9) /* RXFRAMEERR counter rolled over */ | |
| 24 | +#define RXFL_MASK (1 << 10) /* RXOFLOWERR counter rolled over */ | |
| 25 | +#define MDIO_MASK (1 << 12) /* MDIO complete interrupt */ | |
| 26 | +#define TXPL_MASK (1 << 31) /* Force polling of BD by EMAC */ | |
| 27 | 27 | |
| 28 | 28 | /* CONTROL Register bit masks */ |
| 29 | −#define EN_MASK (1<<0) /* VMAC enable */ | |
| 30 | −#define TXRN_MASK (1<<3) /* TX enable */ | |
| 31 | −#define RXRN_MASK (1<<4) /* RX enable */ | |
| 32 | −#define DSBC_MASK (1<<8) /* Disable receive broadcast */ | |
| 33 | −#define ENFL_MASK (1<<10) /* Enable Full-duplex */ | |
| 34 | −#define PROM_MASK (1<<11) /* Promiscuous mode */ | |
| 29 | +#define EN_MASK (1 << 0) /* VMAC enable */ | |
| 30 | +#define TXRN_MASK (1 << 3) /* TX enable */ | |
| 31 | +#define RXRN_MASK (1 << 4) /* RX enable */ | |
| 32 | +#define DSBC_MASK (1 << 8) /* Disable receive broadcast */ | |
| 33 | +#define ENFL_MASK (1 << 10) /* Enable Full-duplex */ | |
| 34 | +#define PROM_MASK (1 << 11) /* Promiscuous mode */ | |
| 35 | 35 | |
| 36 | 36 | /* Buffer descriptor INFO bit masks */ |
| 37 | −#define OWN_MASK (1<<31) /* 0-CPU owns buffer, 1-EMAC owns buffer */ | |
| 38 | −#define FIRST_MASK (1<<16) /* First buffer in chain */ | |
| 39 | −#define LAST_MASK (1<<17) /* Last buffer in chain */ | |
| 37 | +#define OWN_MASK (1 << 31) /* 0-CPU or 1-EMAC owns buffer */ | |
| 38 | +#define FIRST_MASK (1 << 16) /* First buffer in chain */ | |
| 39 | +#define LAST_MASK (1 << 17) /* Last buffer in chain */ | |
| 40 | 40 | #define LEN_MASK 0x000007FF /* last 11 bits */ |
| 41 | −#define CRLS (1<<21) | |
| 42 | −#define DEFR (1<<22) | |
| 43 | −#define DROP (1<<23) | |
| 44 | −#define RTRY (1<<24) | |
| 45 | −#define LTCL (1<<28) | |
| 46 | −#define UFLO (1<<29) | |
| 41 | +#define CRLS (1 << 21) | |
| 42 | +#define DEFR (1 << 22) | |
| 43 | +#define DROP (1 << 23) | |
| 44 | +#define RTRY (1 << 24) | |
| 45 | +#define LTCL (1 << 28) | |
| 46 | +#define UFLO (1 << 29) | |
| 47 | 47 | |
| 48 | 48 | #define FOR_EMAC OWN_MASK |
| 49 | 49 | #define FOR_CPU 0 |
| @@ -66,7 +66,7 @@ enum { · 16 unmodified lines | ||
| 66 | 66 | R_MDIO, |
| 67 | 67 | }; |
| 68 | 68 | |
| 69 | −#define TX_TIMEOUT (400*HZ/1000) /* Transmission timeout */ | |
| 69 | +#define TX_TIMEOUT (400 * HZ / 1000) /* Transmission timeout */ | |
| 70 | 70 | |
| 71 | 71 | #define ARC_EMAC_NAPI_WEIGHT 40 /* Workload for NAPI */ |
| 72 | 72 | |
| @@ -102,6 +102,11 @@ struct buffer_state { · 29 unmodified lines | ||
| 102 | 102 | DEFINE_DMA_UNMAP_LEN(len); |
| 103 | 103 | }; |
| 104 | 104 | |
| 105 | +struct arc_emac_mdio_bus_data { | |
| 106 | + struct gpio_desc *reset_gpio; | |
| 107 | + int msec; | |
| 108 | +}; | |
| 109 | + | |
| 105 | 110 | /** |
| 106 | 111 | * struct arc_emac_priv - Storage of EMAC's private information. |
| 107 | 112 | * @dev: Pointer to the current device. |
| @@ -131,6 +136,7 @@ struct arc_emac_priv { · 23 unmodified lines | ||
| 131 | 136 | struct device *dev; |
| 132 | 137 | struct phy_device *phy_dev; |
| 133 | 138 | struct mii_bus *bus; |
| 139 | + struct arc_emac_mdio_bus_data bus_data; | |
| 134 | 140 | |
| 135 | 141 | void __iomem *regs; |
| 136 | 142 | struct clk *clk; |
| @@ -190,6 +196,7 @@ static inline unsigned int arc_reg_get(struct arc_emac_priv *priv, int reg) · 53 unmodified lines | ||
| 190 | 196 | static inline void arc_reg_or(struct arc_emac_priv *priv, int reg, int mask) |
| 191 | 197 | { |
| 192 | 198 | unsigned int value = arc_reg_get(priv, reg); |
| 199 | + | |
| 193 | 200 | arc_reg_set(priv, reg, value | mask); |
| 194 | 201 | } |
| 195 | 202 | |
| @@ -205,6 +212,7 @@ static inline void arc_reg_or(struct arc_emac_priv *priv, int reg, int mask) · 9 unmodified lines | ||
| 205 | 212 | static inline void arc_reg_clr(struct arc_emac_priv *priv, int reg, int mask) |
| 206 | 213 | { |
| 207 | 214 | unsigned int value = arc_reg_get(priv, reg); |
| 215 | + | |
| 208 | 216 | arc_reg_set(priv, reg, value & ~mask); |
| 209 | 217 | } |
| 210 | 218 | |
| @@ -26,7 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | |
| 27 | 27 | #include "emac.h" |
| 28 | 28 | |
| 29 | − | |
| 30 | 29 | /** |
| 31 | 30 | * arc_emac_tx_avail - Return the number of available slots in the tx ring. |
| 32 | 31 | * @priv: Pointer to ARC EMAC private data structure. |
| @@ -66,7 +65,7 @@ static void arc_emac_adjust_link(struct net_device *ndev) · 33 unmodified lines | ||
| 66 | 65 | if (priv->duplex != phy_dev->duplex) { |
| 67 | 66 | reg = arc_reg_get(priv, R_CTRL); |
| 68 | 67 | |
| 69 | − if (DUPLEX_FULL == phy_dev->duplex) | |
| 68 | + if (phy_dev->duplex == DUPLEX_FULL) | |
| 70 | 69 | reg |= ENFL_MASK; |
| 71 | 70 | else |
| 72 | 71 | reg &= ~ENFL_MASK; |
| @@ -466,9 +465,9 @@ static int arc_emac_open(struct net_device *ndev) · 393 unmodified lines | ||
| 466 | 465 | |
| 467 | 466 | /* Set CONTROL */ |
| 468 | 467 | arc_reg_set(priv, R_CTRL, |
| 469 | − (RX_BD_NUM << 24) | /* RX BD table length */ | |
| 470 | − (TX_BD_NUM << 16) | /* TX BD table length */ | |
| 471 | − TXRN_MASK | RXRN_MASK); | |
| 468 | + (RX_BD_NUM << 24) | /* RX BD table length */ | |
| 469 | + (TX_BD_NUM << 16) | /* TX BD table length */ | |
| 470 | + TXRN_MASK | RXRN_MASK); | |
| 472 | 471 | |
| 473 | 472 | napi_enable(&priv->napi); |
| 474 | 473 | |
| @@ -533,8 +532,10 @@ static void arc_free_tx_queue(struct net_device *ndev) · 58 unmodified lines | ||
| 533 | 532 | struct buffer_state *tx_buff = &priv->tx_buff[i]; |
| 534 | 533 | |
| 535 | 534 | if (tx_buff->skb) { |
| 536 | − dma_unmap_single(&ndev->dev, dma_unmap_addr(tx_buff, addr), | |
| 537 | − dma_unmap_len(tx_buff, len), DMA_TO_DEVICE); | |
| 535 | + dma_unmap_single(&ndev->dev, | |
| 536 | + dma_unmap_addr(tx_buff, addr), | |
| 537 | + dma_unmap_len(tx_buff, len), | |
| 538 | + DMA_TO_DEVICE); | |
| 538 | 539 | |
| 539 | 540 | /* return the sk_buff to system */ |
| 540 | 541 | dev_kfree_skb_irq(tx_buff->skb); |
| @@ -562,8 +563,10 @@ static void arc_free_rx_queue(struct net_device *ndev) · 21 unmodified lines | ||
| 562 | 563 | struct buffer_state *rx_buff = &priv->rx_buff[i]; |
| 563 | 564 | |
| 564 | 565 | if (rx_buff->skb) { |
| 565 | − dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr), | |
| 566 | − dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE); | |
| 566 | + dma_unmap_single(&ndev->dev, | |
| 567 | + dma_unmap_addr(rx_buff, addr), | |
| 568 | + dma_unmap_len(rx_buff, len), | |
| 569 | + DMA_FROM_DEVICE); | |
| 567 | 570 | |
| 568 | 571 | /* return the sk_buff to system */ |
| 569 | 572 | dev_kfree_skb_irq(rx_buff->skb); |
| @@ -717,8 +720,8 @@ static void arc_emac_set_address_internal(struct net_device *ndev) · 147 unmodified lines | ||
| 717 | 720 | struct arc_emac_priv *priv = netdev_priv(ndev); |
| 718 | 721 | unsigned int addr_low, addr_hi; |
| 719 | 722 | |
| 720 | − addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); | |
| 721 | − addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); | |
| 723 | + addr_low = le32_to_cpu(*(__le32 *)&ndev->dev_addr[0]); | |
| 724 | + addr_hi = le16_to_cpu(*(__le16 *)&ndev->dev_addr[4]); | |
| 722 | 725 | |
| 723 | 726 | arc_reg_set(priv, R_ADDRL, addr_low); |
| 724 | 727 | arc_reg_set(priv, R_ADDRH, addr_hi); |
| @@ -774,7 +777,6 @@ int arc_emac_probe(struct net_device *ndev, int interface) · 49 unmodified lines | ||
| 774 | 777 | unsigned int id, clock_frequency, irq; |
| 775 | 778 | int err; |
| 776 | 779 | |
| 777 | − | |
| 778 | 780 | /* Get PHY from device tree */ |
| 779 | 781 | phy_node = of_parse_phandle(dev->of_node, "phy", 0); |
| 780 | 782 | if (!phy_node) { |
| @@ -796,7 +798,6 @@ int arc_emac_probe(struct net_device *ndev, int interface) · 15 unmodified lines | ||
| 796 | 798 | return -ENODEV; |
| 797 | 799 | } |
| 798 | 800 | |
| 799 | − | |
| 800 | 801 | ndev->netdev_ops = &arc_emac_netdev_ops; |
| 801 | 802 | ndev->ethtool_ops = &arc_emac_ethtool_ops; |
| 802 | 803 | ndev->watchdog_timeo = TX_TIMEOUT; |
| @@ -807,9 +808,9 @@ int arc_emac_probe(struct net_device *ndev, int interface) · 4 unmodified lines | ||
| 807 | 808 | priv->dev = dev; |
| 808 | 809 | |
| 809 | 810 | priv->regs = devm_ioremap_resource(dev, &res_regs); |
| 810 | − if (IS_ERR(priv->regs)) { | |
| 811 | + if (IS_ERR(priv->regs)) | |
| 811 | 812 | return PTR_ERR(priv->regs); |
| 812 | − } | |
| 813 | + | |
| 813 | 814 | dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs); |
| 814 | 815 | |
| 815 | 816 | if (priv->clk) { |
| @@ -930,10 +931,8 @@ int arc_emac_remove(struct net_device *ndev) · 114 unmodified lines | ||
| 930 | 931 | unregister_netdev(ndev); |
| 931 | 932 | netif_napi_del(&priv->napi); |
| 932 | 933 | |
| 933 | − if (!IS_ERR(priv->clk)) { | |
| 934 | + if (!IS_ERR(priv->clk)) | |
| 934 | 935 | clk_disable_unprepare(priv->clk); |
| 935 | − } | |
| 936 | − | |
| 937 | 936 | |
| 938 | 937 | return 0; |
| 939 | 938 | } |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/delay.h> |
| 8 | 8 | #include <linux/of_mdio.h> |
| 9 | 9 | #include <linux/platform_device.h> |
| 10 | +#include <linux/gpio/consumer.h> | |
| 10 | 11 | |
| 11 | 12 | #include "emac.h" |
| 12 | 13 | |
| @@ -93,11 +94,30 @@ static int arc_mdio_write(struct mii_bus *bus, int phy_addr, · 80 unmodified lines | ||
| 93 | 94 | phy_addr, reg_num, value); |
| 94 | 95 | |
| 95 | 96 | arc_reg_set(priv, R_MDIO, |
| 96 | − 0x50020000 | (phy_addr << 23) | (reg_num << 18) | value); | |
| 97 | + 0x50020000 | (phy_addr << 23) | (reg_num << 18) | value); | |
| 97 | 98 | |
| 98 | 99 | return arc_mdio_complete_wait(priv); |
| 99 | 100 | } |
| 100 | 101 | |
| 102 | +/** | |
| 103 | + * arc_mdio_reset | |
| 104 | + * @bus: points to the mii_bus structure | |
| 105 | + * Description: reset the MII bus | |
| 106 | + */ | |
| 107 | +int arc_mdio_reset(struct mii_bus *bus) | |
| 108 | +{ | |
| 109 | + struct arc_emac_priv *priv = bus->priv; | |
| 110 | + struct arc_emac_mdio_bus_data *data = &priv->bus_data; | |
| 111 | + | |
| 112 | + if (data->reset_gpio) { | |
| 113 | + gpiod_set_value_cansleep(data->reset_gpio, 1); | |
| 114 | + msleep(data->msec); | |
| 115 | + gpiod_set_value_cansleep(data->reset_gpio, 0); | |
| 116 | + } | |
| 117 | + | |
| 118 | + return 0; | |
| 119 | +} | |
| 120 | + | |
| 101 | 121 | /** |
| 102 | 122 | * arc_mdio_probe - MDIO probe function. |
| 103 | 123 | * @priv: Pointer to ARC EMAC private data structure. |
| @@ -109,6 +129,8 @@ static int arc_mdio_write(struct mii_bus *bus, int phy_addr, · 5 unmodified lines | ||
| 109 | 129 | */ |
| 110 | 130 | int arc_mdio_probe(struct arc_emac_priv *priv) |
| 111 | 131 | { |
| 132 | + struct arc_emac_mdio_bus_data *data = &priv->bus_data; | |
| 133 | + struct device_node *np = priv->dev->of_node; | |
| 112 | 134 | struct mii_bus *bus; |
| 113 | 135 | int error; |
| 114 | 136 | |
| @@ -122,6 +144,21 @@ int arc_mdio_probe(struct arc_emac_priv *priv) · 7 unmodified lines | ||
| 122 | 144 | bus->name = "Synopsys MII Bus", |
| 123 | 145 | bus->read = &arc_mdio_read; |
| 124 | 146 | bus->write = &arc_mdio_write; |
| 147 | + bus->reset = &arc_mdio_reset; | |
| 148 | + | |
| 149 | + /* optional reset-related properties */ | |
| 150 | + data->reset_gpio = devm_gpiod_get_optional(priv->dev, "phy-reset", | |
| 151 | + GPIOD_OUT_LOW); | |
| 152 | + if (IS_ERR(data->reset_gpio)) { | |
| 153 | + error = PTR_ERR(data->reset_gpio); | |
| 154 | + dev_err(priv->dev, "Failed to request gpio: %d\n", error); | |
| 155 | + return error; | |
| 156 | + } | |
| 157 | + | |
| 158 | + of_property_read_u32(np, "phy-reset-duration", &data->msec); | |
| 159 | + /* A sane reset duration should not be longer than 1s */ | |
| 160 | + if (data->msec > 1000) | |
| 161 | + data->msec = 1; | |
| 125 | 162 | |
| 126 | 163 | snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name); |
| 127 | 164 | |
| @@ -50,7 +50,7 @@ static void emac_rockchip_set_mac_speed(void *priv, unsigned int speed) · 49 unmodified lines | ||
| 50 | 50 | u32 data; |
| 51 | 51 | int err = 0; |
| 52 | 52 | |
| 53 | − switch(speed) { | |
| 53 | + switch (speed) { | |
| 54 | 54 | case 10: |
| 55 | 55 | data = (1 << (speed_offset + 16)) | (0 << speed_offset); |
| 56 | 56 | break; |
| @@ -83,9 +83,18 @@ static const struct emac_rockchip_soc_data emac_rk3188_emac_data = { · 26 unmodified lines | ||
| 83 | 83 | }; |
| 84 | 84 | |
| 85 | 85 | static const struct of_device_id emac_rockchip_dt_ids[] = { |
| 86 | − { .compatible = "rockchip,rk3036-emac", .data = &emac_rk3036_emac_data }, | |
| 87 | − { .compatible = "rockchip,rk3066-emac", .data = &emac_rk3066_emac_data }, | |
| 88 | − { .compatible = "rockchip,rk3188-emac", .data = &emac_rk3188_emac_data }, | |
| 86 | + { | |
| 87 | + .compatible = "rockchip,rk3036-emac", | |
| 88 | + .data = &emac_rk3036_emac_data, | |
| 89 | + }, | |
| 90 | + { | |
| 91 | + .compatible = "rockchip,rk3066-emac", | |
| 92 | + .data = &emac_rk3066_emac_data, | |
| 93 | + }, | |
| 94 | + { | |
| 95 | + .compatible = "rockchip,rk3188-emac", | |
| 96 | + .data = &emac_rk3188_emac_data, | |
| 97 | + }, | |
| 89 | 98 | { /* Sentinel */ } |
| 90 | 99 | }; |
| 91 | 100 | |
| @@ -123,9 +132,11 @@ static int emac_rockchip_probe(struct platform_device *pdev) · 31 unmodified lines | ||
| 123 | 132 | goto out_netdev; |
| 124 | 133 | } |
| 125 | 134 | |
| 126 | − priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); | |
| 135 | + priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, | |
| 136 | + "rockchip,grf"); | |
| 127 | 137 | if (IS_ERR(priv->grf)) { |
| 128 | − dev_err(dev, "failed to retrieve global register file (%ld)\n", PTR_ERR(priv->grf)); | |
| 138 | + dev_err(dev, "failed to retrieve global register file (%ld)\n", | |
| 139 | + PTR_ERR(priv->grf)); | |
| 129 | 140 | err = PTR_ERR(priv->grf); |
| 130 | 141 | goto out_netdev; |
| 131 | 142 | } |
| @@ -135,14 +146,16 @@ static int emac_rockchip_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 135 | 146 | |
| 136 | 147 | priv->emac.clk = devm_clk_get(dev, "hclk"); |
| 137 | 148 | if (IS_ERR(priv->emac.clk)) { |
| 138 | − dev_err(dev, "failed to retrieve host clock (%ld)\n", PTR_ERR(priv->emac.clk)); | |
| 149 | + dev_err(dev, "failed to retrieve host clock (%ld)\n", | |
| 150 | + PTR_ERR(priv->emac.clk)); | |
| 139 | 151 | err = PTR_ERR(priv->emac.clk); |
| 140 | 152 | goto out_netdev; |
| 141 | 153 | } |
| 142 | 154 | |
| 143 | 155 | priv->refclk = devm_clk_get(dev, "macref"); |
| 144 | 156 | if (IS_ERR(priv->refclk)) { |
| 145 | − dev_err(dev, "failed to retrieve reference clock (%ld)\n", PTR_ERR(priv->refclk)); | |
| 157 | + dev_err(dev, "failed to retrieve reference clock (%ld)\n", | |
| 158 | + PTR_ERR(priv->refclk)); | |
| 146 | 159 | err = PTR_ERR(priv->refclk); |
| 147 | 160 | goto out_netdev; |
| 148 | 161 | } |
| @@ -179,19 +192,22 @@ static int emac_rockchip_probe(struct platform_device *pdev) · 30 unmodified lines | ||
| 179 | 192 | |
| 180 | 193 | err = regmap_write(priv->grf, priv->soc_data->grf_offset, data); |
| 181 | 194 | if (err) { |
| 182 | − dev_err(dev, "unable to apply initial settings to grf (%d)\n", err); | |
| 195 | + dev_err(dev, "unable to apply initial settings to grf (%d)\n", | |
| 196 | + err); | |
| 183 | 197 | goto out_regulator_disable; |
| 184 | 198 | } |
| 185 | 199 | |
| 186 | 200 | /* RMII interface needs always a rate of 50MHz */ |
| 187 | 201 | err = clk_set_rate(priv->refclk, 50000000); |
| 188 | 202 | if (err) |
| 189 | − dev_err(dev, "failed to change reference clock rate (%d)\n", err); | |
| 203 | + dev_err(dev, | |
| 204 | + "failed to change reference clock rate (%d)\n", err); | |
| 190 | 205 | |
| 191 | 206 | if (priv->soc_data->need_div_macclk) { |
| 192 | 207 | priv->macclk = devm_clk_get(dev, "macclk"); |
| 193 | 208 | if (IS_ERR(priv->macclk)) { |
| 194 | − dev_err(dev, "failed to retrieve mac clock (%ld)\n", PTR_ERR(priv->macclk)); | |
| 209 | + dev_err(dev, "failed to retrieve mac clock (%ld)\n", | |
| 210 | + PTR_ERR(priv->macclk)); | |
| 195 | 211 | err = PTR_ERR(priv->macclk); |
| 196 | 212 | goto out_regulator_disable; |
| 197 | 213 | } |
| @@ -205,7 +221,8 @@ static int emac_rockchip_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 205 | 221 | /* RMII TX/RX needs always a rate of 25MHz */ |
| 206 | 222 | err = clk_set_rate(priv->macclk, 25000000); |
| 207 | 223 | if (err) |
| 208 | − dev_err(dev, "failed to change mac clock rate (%d)\n", err); | |
| 224 | + dev_err(dev, | |
| 225 | + "failed to change mac clock rate (%d)\n", err); | |
| 209 | 226 | } |
| 210 | 227 | |
| 211 | 228 | err = arc_emac_probe(ndev, interface); |
| @@ -65,10 +65,6 @@ static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter); · 64 unmodified lines | ||
| 65 | 65 | static int atl1c_configure(struct atl1c_adapter *adapter); |
| 66 | 66 | static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter); |
| 67 | 67 | |
| 68 | −static const u16 atl1c_pay_load_size[] = { | |
| 69 | − 128, 256, 512, 1024, 2048, 4096, | |
| 70 | −}; | |
| 71 | − | |
| 72 | 68 | |
| 73 | 69 | static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | |
| 74 | 70 | NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; |
| @@ -149,6 +149,16 @@ config BNX2X_VXLAN · 148 unmodified lines | ||
| 149 | 149 | Say Y here if you want to enable hardware offload support for |
| 150 | 150 | Virtual eXtensible Local Area Network (VXLAN) in the driver. |
| 151 | 151 | |
| 152 | +config BNX2X_GENEVE | |
| 153 | + bool "Generic Network Virtualization Encapsulation (GENEVE) support" | |
| 154 | + depends on BNX2X && GENEVE && !(BNX2X=y && GENEVE=m) | |
| 155 | + ---help--- | |
| 156 | + This allows one to create GENEVE virtual interfaces that provide | |
| 157 | + Layer 2 Networks over Layer 3 Networks. GENEVE is often used | |
| 158 | + to tunnel virtual network infrastructure in virtualized environments. | |
| 159 | + Say Y here if you want to enable hardware offload support for | |
| 160 | + Generic Network Virtualization Encapsulation (GENEVE) in the driver. | |
| 161 | + | |
| 152 | 162 | config BGMAC |
| 153 | 163 | tristate "BCMA bus GBit core support" |
| 154 | 164 | depends on BCMA && BCMA_HOST_SOC |
| @@ -26,6 +26,18 @@ static const struct bcma_device_id bgmac_bcma_tbl[] = { · 25 unmodified lines | ||
| 26 | 26 | }; |
| 27 | 27 | MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); |
| 28 | 28 | |
| 29 | +static inline bool bgmac_is_bcm4707_family(struct bgmac *bgmac) | |
| 30 | +{ | |
| 31 | + switch (bgmac->core->bus->chipinfo.id) { | |
| 32 | + case BCMA_CHIP_ID_BCM4707: | |
| 33 | + case BCMA_CHIP_ID_BCM47094: | |
| 34 | + case BCMA_CHIP_ID_BCM53018: | |
| 35 | + return true; | |
| 36 | + default: | |
| 37 | + return false; | |
| 38 | + } | |
| 39 | +} | |
| 40 | + | |
| 29 | 41 | static bool bgmac_wait_value(struct bcma_device *core, u16 reg, u32 mask, |
| 30 | 42 | u32 value, int timeout) |
| 31 | 43 | { |
| @@ -987,11 +999,9 @@ static void bgmac_mac_speed(struct bgmac *bgmac) · 955 unmodified lines | ||
| 987 | 999 | static void bgmac_miiconfig(struct bgmac *bgmac) |
| 988 | 1000 | { |
| 989 | 1001 | struct bcma_device *core = bgmac->core; |
| 990 | − struct bcma_chipinfo *ci = &core->bus->chipinfo; | |
| 991 | 1002 | u8 imode; |
| 992 | 1003 | |
| 993 | − if (ci->id == BCMA_CHIP_ID_BCM4707 || | |
| 994 | − ci->id == BCMA_CHIP_ID_BCM53018) { | |
| 1004 | + if (bgmac_is_bcm4707_family(bgmac)) { | |
| 995 | 1005 | bcma_awrite32(core, BCMA_IOCTL, |
| 996 | 1006 | bcma_aread32(core, BCMA_IOCTL) | 0x40 | |
| 997 | 1007 | BGMAC_BCMA_IOCTL_SW_CLKEN); |
| @@ -1043,8 +1053,9 @@ static void bgmac_chip_reset(struct bgmac *bgmac) · 45 unmodified lines | ||
| 1043 | 1053 | (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) |
| 1044 | 1054 | iost &= ~BGMAC_BCMA_IOST_ATTACHED; |
| 1045 | 1055 | |
| 1046 | − /* 3GMAC: for BCM4707, only do core reset at bgmac_probe() */ | |
| 1047 | − if (ci->id != BCMA_CHIP_ID_BCM4707) { | |
| 1056 | + /* 3GMAC: for BCM4707 & BCM47094, only do core reset at bgmac_probe() */ | |
| 1057 | + if (ci->id != BCMA_CHIP_ID_BCM4707 && | |
| 1058 | + ci->id != BCMA_CHIP_ID_BCM47094) { | |
| 1048 | 1059 | flags = 0; |
| 1049 | 1060 | if (iost & BGMAC_BCMA_IOST_ATTACHED) { |
| 1050 | 1061 | flags = BGMAC_BCMA_IOCTL_SW_CLKEN; |
| @@ -1055,9 +1066,7 @@ static void bgmac_chip_reset(struct bgmac *bgmac) · 4 unmodified lines | ||
| 1055 | 1066 | } |
| 1056 | 1067 | |
| 1057 | 1068 | /* Request Misc PLL for corerev > 2 */ |
| 1058 | − if (core->id.rev > 2 && | |
| 1059 | − ci->id != BCMA_CHIP_ID_BCM4707 && | |
| 1060 | − ci->id != BCMA_CHIP_ID_BCM53018) { | |
| 1069 | + if (core->id.rev > 2 && !bgmac_is_bcm4707_family(bgmac)) { | |
| 1061 | 1070 | bgmac_set(bgmac, BCMA_CLKCTLST, |
| 1062 | 1071 | BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ); |
| 1063 | 1072 | bgmac_wait_value(bgmac->core, BCMA_CLKCTLST, |
| @@ -1193,8 +1202,7 @@ static void bgmac_enable(struct bgmac *bgmac) · 129 unmodified lines | ||
| 1193 | 1202 | break; |
| 1194 | 1203 | } |
| 1195 | 1204 | |
| 1196 | − if (ci->id != BCMA_CHIP_ID_BCM4707 && | |
| 1197 | − ci->id != BCMA_CHIP_ID_BCM53018) { | |
| 1205 | + if (!bgmac_is_bcm4707_family(bgmac)) { | |
| 1198 | 1206 | rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL); |
| 1199 | 1207 | rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK; |
| 1200 | 1208 | bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) / |
| @@ -1472,14 +1480,12 @@ static int bgmac_fixed_phy_register(struct bgmac *bgmac) · 271 unmodified lines | ||
| 1472 | 1480 | |
| 1473 | 1481 | static int bgmac_mii_register(struct bgmac *bgmac) |
| 1474 | 1482 | { |
| 1475 | − struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo; | |
| 1476 | 1483 | struct mii_bus *mii_bus; |
| 1477 | 1484 | struct phy_device *phy_dev; |
| 1478 | 1485 | char bus_id[MII_BUS_ID_SIZE + 3]; |
| 1479 | 1486 | int err = 0; |
| 1480 | 1487 | |
| 1481 | − if (ci->id == BCMA_CHIP_ID_BCM4707 || | |
| 1482 | − ci->id == BCMA_CHIP_ID_BCM53018) | |
| 1488 | + if (bgmac_is_bcm4707_family(bgmac)) | |
| 1483 | 1489 | return bgmac_fixed_phy_register(bgmac); |
| 1484 | 1490 | |
| 1485 | 1491 | mii_bus = mdiobus_alloc(); |
| @@ -1539,7 +1545,6 @@ static void bgmac_mii_unregister(struct bgmac *bgmac) · 53 unmodified lines | ||
| 1539 | 1545 | /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ |
| 1540 | 1546 | static int bgmac_probe(struct bcma_device *core) |
| 1541 | 1547 | { |
| 1542 | − struct bcma_chipinfo *ci = &core->bus->chipinfo; | |
| 1543 | 1548 | struct net_device *net_dev; |
| 1544 | 1549 | struct bgmac *bgmac; |
| 1545 | 1550 | struct ssb_sprom *sprom = &core->bus->sprom; |
| @@ -1620,8 +1625,7 @@ static int bgmac_probe(struct bcma_device *core) · 74 unmodified lines | ||
| 1620 | 1625 | bgmac_chip_reset(bgmac); |
| 1621 | 1626 | |
| 1622 | 1627 | /* For Northstar, we have to take all GMAC core out of reset */ |
| 1623 | − if (ci->id == BCMA_CHIP_ID_BCM4707 || | |
| 1624 | − ci->id == BCMA_CHIP_ID_BCM53018) { | |
| 1628 | + if (bgmac_is_bcm4707_family(bgmac)) { | |
| 1625 | 1629 | struct bcma_device *ns_core; |
| 1626 | 1630 | int ns_gmac; |
| 1627 | 1631 | |
| @@ -1277,8 +1277,7 @@ enum sp_rtnl_flag { · 1276 unmodified lines | ||
| 1277 | 1277 | BNX2X_SP_RTNL_HYPERVISOR_VLAN, |
| 1278 | 1278 | BNX2X_SP_RTNL_TX_STOP, |
| 1279 | 1279 | BNX2X_SP_RTNL_GET_DRV_VERSION, |
| 1280 | − BNX2X_SP_RTNL_ADD_VXLAN_PORT, | |
| 1281 | − BNX2X_SP_RTNL_DEL_VXLAN_PORT, | |
| 1280 | + BNX2X_SP_RTNL_CHANGE_UDP_PORT, | |
| 1282 | 1281 | }; |
| 1283 | 1282 | |
| 1284 | 1283 | enum bnx2x_iov_flag { |
| @@ -1327,6 +1326,17 @@ struct bnx2x_vlan_entry { · 42 unmodified lines | ||
| 1327 | 1326 | bool hw; |
| 1328 | 1327 | }; |
| 1329 | 1328 | |
| 1329 | +enum bnx2x_udp_port_type { | |
| 1330 | + BNX2X_UDP_PORT_VXLAN, | |
| 1331 | + BNX2X_UDP_PORT_GENEVE, | |
| 1332 | + BNX2X_UDP_PORT_MAX, | |
| 1333 | +}; | |
| 1334 | + | |
| 1335 | +struct bnx2x_udp_tunnel { | |
| 1336 | + u16 dst_port; | |
| 1337 | + u8 count; | |
| 1338 | +}; | |
| 1339 | + | |
| 1330 | 1340 | struct bnx2x { |
| 1331 | 1341 | /* Fields used in the tx and intr/napi performance paths |
| 1332 | 1342 | * are grouped together in the beginning of the structure |
| @@ -1830,9 +1840,10 @@ struct bnx2x { · 497 unmodified lines | ||
| 1830 | 1840 | struct list_head vlan_reg; |
| 1831 | 1841 | u16 vlan_cnt; |
| 1832 | 1842 | u16 vlan_credit; |
| 1833 | − u16 vxlan_dst_port; | |
| 1834 | − u8 vxlan_dst_port_count; | |
| 1835 | 1843 | bool accept_any_vlan; |
| 1844 | + | |
| 1845 | + /* Vxlan/Geneve related information */ | |
| 1846 | + struct bnx2x_udp_tunnel udp_tunnel_ports[BNX2X_UDP_PORT_MAX]; | |
| 1836 | 1847 | }; |
| 1837 | 1848 | |
| 1838 | 1849 | /* Tx queues may be less or equal to Rx queues */ |
| @@ -3042,8 +3042,12 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) · 3041 unmodified lines | ||
| 3042 | 3042 | bnx2x_save_statistics(bp); |
| 3043 | 3043 | } |
| 3044 | 3044 | |
| 3045 | − /* wait till consumers catch up with producers in all queues */ | |
| 3046 | − bnx2x_drain_tx_queues(bp); | |
| 3045 | + /* wait till consumers catch up with producers in all queues. | |
| 3046 | + * If we're recovering, FW can't write to host so no reason | |
| 3047 | + * to wait for the queues to complete all Tx. | |
| 3048 | + */ | |
| 3049 | + if (unload_mode != UNLOAD_RECOVERY) | |
| 3050 | + bnx2x_drain_tx_queues(bp); | |
| 3047 | 3051 | |
| 3048 | 3052 | /* if VF indicate to PF this function is going down (PF will delete sp |
| 3049 | 3053 | * elements and clear initializations |
| @@ -4272,6 +4276,14 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc) · 1222 unmodified lines | ||
| 4272 | 4276 | return 0; |
| 4273 | 4277 | } |
| 4274 | 4278 | |
| 4279 | +int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto, | |
| 4280 | + struct tc_to_netdev *tc) | |
| 4281 | +{ | |
| 4282 | + if (tc->type != TC_SETUP_MQPRIO) | |
| 4283 | + return -EINVAL; | |
| 4284 | + return bnx2x_setup_tc(dev, tc->tc); | |
| 4285 | +} | |
| 4286 | + | |
| 4275 | 4287 | /* called with rtnl_lock */ |
| 4276 | 4288 | int bnx2x_change_mac_addr(struct net_device *dev, void *p) |
| 4277 | 4289 | { |
| @@ -5086,4 +5098,3 @@ void bnx2x_schedule_sp_rtnl(struct bnx2x *bp, enum sp_rtnl_flag flag, · 808 unmodified lines | ||
| 5086 | 5098 | flag); |
| 5087 | 5099 | schedule_delayed_work(&bp->sp_rtnl_task, 0); |
| 5088 | 5100 | } |
| 5089 | −EXPORT_SYMBOL(bnx2x_schedule_sp_rtnl); | |
| @@ -486,6 +486,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev); · 485 unmodified lines | ||
| 486 | 486 | |
| 487 | 487 | /* setup_tc callback */ |
| 488 | 488 | int bnx2x_setup_tc(struct net_device *dev, u8 num_tc); |
| 489 | +int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto, | |
| 490 | + struct tc_to_netdev *tc); | |
| 489 | 491 | |
| 490 | 492 | int bnx2x_get_vf_config(struct net_device *dev, int vf, |
| 491 | 493 | struct ifla_vf_info *ivi); |
| @@ -923,6 +925,7 @@ static inline int bnx2x_func_start(struct bnx2x *bp) · 431 unmodified lines | ||
| 923 | 925 | struct bnx2x_func_state_params func_params = {NULL}; |
| 924 | 926 | struct bnx2x_func_start_params *start_params = |
| 925 | 927 | &func_params.params.start; |
| 928 | + u16 port; | |
| 926 | 929 | |
| 927 | 930 | /* Prepare parameters for function state transitions */ |
| 928 | 931 | __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); |
| @@ -959,8 +962,14 @@ static inline int bnx2x_func_start(struct bnx2x *bp) · 30 unmodified lines | ||
| 959 | 962 | start_params->network_cos_mode = STATIC_COS; |
| 960 | 963 | else /* CHIP_IS_E1X */ |
| 961 | 964 | start_params->network_cos_mode = FW_WRR; |
| 962 | − | |
| 963 | − start_params->vxlan_dst_port = bp->vxlan_dst_port; | |
| 965 | + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { | |
| 966 | + port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].dst_port; | |
| 967 | + start_params->vxlan_dst_port = port; | |
| 968 | + } | |
| 969 | + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { | |
| 970 | + port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].dst_port; | |
| 971 | + start_params->geneve_dst_port = port; | |
| 972 | + } | |
| 964 | 973 | |
| 965 | 974 | start_params->inner_rss = 1; |
| 966 | 975 | |
| @@ -195,6 +195,7 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp, · 194 unmodified lines | ||
| 195 | 195 | u32 error) { |
| 196 | 196 | u8 index; |
| 197 | 197 | u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority; |
| 198 | + u8 iscsi_pri_found = 0, fcoe_pri_found = 0; | |
| 198 | 199 | |
| 199 | 200 | if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) |
| 200 | 201 | DP(BNX2X_MSG_DCB, "DCBX_LOCAL_APP_ERROR\n"); |
| @@ -210,29 +211,57 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp, · 9 unmodified lines | ||
| 210 | 211 | |
| 211 | 212 | bp->dcbx_port_params.app.enabled = true; |
| 212 | 213 | |
| 214 | + /* Use 0 as the default application priority for all. */ | |
| 213 | 215 | for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++) |
| 214 | 216 | ttp[index] = 0; |
| 215 | 217 | |
| 216 | − if (app->default_pri < MAX_PFC_PRIORITIES) | |
| 217 | − ttp[LLFC_TRAFFIC_TYPE_NW] = app->default_pri; | |
| 218 | − | |
| 219 | 218 | for (index = 0 ; index < DCBX_MAX_APP_PROTOCOL; index++) { |
| 220 | 219 | struct dcbx_app_priority_entry *entry = |
| 221 | 220 | app->app_pri_tbl; |
| 221 | + enum traffic_type type = MAX_TRAFFIC_TYPE; | |
| 222 | 222 | |
| 223 | 223 | if (GET_FLAGS(entry[index].appBitfield, |
| 224 | − DCBX_APP_SF_ETH_TYPE) && | |
| 225 | − ETH_TYPE_FCOE == entry[index].app_id) | |
| 226 | − bnx2x_dcbx_get_ap_priority(bp, | |
| 227 | − entry[index].pri_bitmap, | |
| 228 | − LLFC_TRAFFIC_TYPE_FCOE); | |
| 224 | + DCBX_APP_SF_DEFAULT) && | |
| 225 | + GET_FLAGS(entry[index].appBitfield, | |
| 226 | + DCBX_APP_SF_ETH_TYPE)) { | |
| 227 | + type = LLFC_TRAFFIC_TYPE_NW; | |
| 228 | + } else if (GET_FLAGS(entry[index].appBitfield, | |
| 229 | + DCBX_APP_SF_PORT) && | |
| 230 | + TCP_PORT_ISCSI == entry[index].app_id) { | |
| 231 | + type = LLFC_TRAFFIC_TYPE_ISCSI; | |
| 232 | + iscsi_pri_found = 1; | |
| 233 | + } else if (GET_FLAGS(entry[index].appBitfield, | |
| 234 | + DCBX_APP_SF_ETH_TYPE) && | |
| 235 | + ETH_TYPE_FCOE == entry[index].app_id) { | |
| 236 | + type = LLFC_TRAFFIC_TYPE_FCOE; | |
| 237 | + fcoe_pri_found = 1; | |
| 238 | + } | |
| 229 | 239 | |
| 230 | − if (GET_FLAGS(entry[index].appBitfield, | |
| 231 | − DCBX_APP_SF_PORT) && | |
| 232 | − TCP_PORT_ISCSI == entry[index].app_id) | |
| 233 | − bnx2x_dcbx_get_ap_priority(bp, | |
| 234 | − entry[index].pri_bitmap, | |
| 235 | − LLFC_TRAFFIC_TYPE_ISCSI); | |
| 240 | + if (type == MAX_TRAFFIC_TYPE) | |
| 241 | + continue; | |
| 242 | + | |
| 243 | + bnx2x_dcbx_get_ap_priority(bp, | |
| 244 | + entry[index].pri_bitmap, | |
| 245 | + type); | |
| 246 | + } | |
| 247 | + | |
| 248 | + /* If we have received a non-zero default application | |
| 249 | + * priority, then use that for applications which are | |
| 250 | + * not configured with any priority. | |
| 251 | + */ | |
| 252 | + if (ttp[LLFC_TRAFFIC_TYPE_NW] != 0) { | |
| 253 | + if (!iscsi_pri_found) { | |
| 254 | + ttp[LLFC_TRAFFIC_TYPE_ISCSI] = | |
| 255 | + ttp[LLFC_TRAFFIC_TYPE_NW]; | |
| 256 | + DP(BNX2X_MSG_DCB, | |
| 257 | + "ISCSI is using default priority.\n"); | |
| 258 | + } | |
| 259 | + if (!fcoe_pri_found) { | |
| 260 | + ttp[LLFC_TRAFFIC_TYPE_FCOE] = | |
| 261 | + ttp[LLFC_TRAFFIC_TYPE_NW]; | |
| 262 | + DP(BNX2X_MSG_DCB, | |
| 263 | + "FCoE is using default priority.\n"); | |
| 264 | + } | |
| 236 | 265 | } |
| 237 | 266 | } else { |
| 238 | 267 | DP(BNX2X_MSG_DCB, "DCBX_LOCAL_APP_DISABLED\n"); |
| @@ -981,6 +981,11 @@ static void bnx2x_get_regs(struct net_device *dev, · 980 unmodified lines | ||
| 981 | 981 | memcpy(p, &dump_hdr, sizeof(struct dump_header)); |
| 982 | 982 | p += dump_hdr.header_size + 1; |
| 983 | 983 | |
| 984 | + /* This isn't really an error, but since attention handling is going | |
| 985 | + * to print the GRC timeouts using this macro, we use the same. | |
| 986 | + */ | |
| 987 | + BNX2X_ERR("Generating register dump. Might trigger harmless GRC timeouts\n"); | |
| 988 | + | |
| 984 | 989 | /* Actually read the registers */ |
| 985 | 990 | __bnx2x_get_regs(bp, p); |
| 986 | 991 | |
| @@ -1824,17 +1824,22 @@ struct dcbx_app_priority_entry { · 1823 unmodified lines | ||
| 1824 | 1824 | u8 pri_bitmap; |
| 1825 | 1825 | u8 appBitfield; |
| 1826 | 1826 | #define DCBX_APP_ENTRY_VALID 0x01 |
| 1827 | − #define DCBX_APP_ENTRY_SF_MASK 0x30 | |
| 1827 | + #define DCBX_APP_ENTRY_SF_MASK 0xF0 | |
| 1828 | 1828 | #define DCBX_APP_ENTRY_SF_SHIFT 4 |
| 1829 | 1829 | #define DCBX_APP_SF_ETH_TYPE 0x10 |
| 1830 | 1830 | #define DCBX_APP_SF_PORT 0x20 |
| 1831 | + #define DCBX_APP_SF_UDP 0x40 | |
| 1832 | + #define DCBX_APP_SF_DEFAULT 0x80 | |
| 1831 | 1833 | #elif defined(__LITTLE_ENDIAN) |
| 1832 | 1834 | u8 appBitfield; |
| 1833 | 1835 | #define DCBX_APP_ENTRY_VALID 0x01 |
| 1834 | − #define DCBX_APP_ENTRY_SF_MASK 0x30 | |
| 1836 | + #define DCBX_APP_ENTRY_SF_MASK 0xF0 | |
| 1835 | 1837 | #define DCBX_APP_ENTRY_SF_SHIFT 4 |
| 1838 | + #define DCBX_APP_ENTRY_VALID 0x01 | |
| 1836 | 1839 | #define DCBX_APP_SF_ETH_TYPE 0x10 |
| 1837 | 1840 | #define DCBX_APP_SF_PORT 0x20 |
| 1841 | + #define DCBX_APP_SF_UDP 0x40 | |
| 1842 | + #define DCBX_APP_SF_DEFAULT 0x80 | |
| 1838 | 1843 | u8 pri_bitmap; |
| 1839 | 1844 | u16 app_id; |
| 1840 | 1845 | #endif |
| @@ -59,7 +59,9 @@ · 58 unmodified lines | ||
| 59 | 59 | #include <linux/semaphore.h> |
| 60 | 60 | #include <linux/stringify.h> |
| 61 | 61 | #include <linux/vmalloc.h> |
| 62 | − | |
| 62 | +#if IS_ENABLED(CONFIG_BNX2X_GENEVE) | |
| 63 | +#include <net/geneve.h> | |
| 64 | +#endif | |
| 63 | 65 | #include "bnx2x.h" |
| 64 | 66 | #include "bnx2x_init.h" |
| 65 | 67 | #include "bnx2x_init_ops.h" |
| @@ -10074,11 +10076,13 @@ static void bnx2x_parity_recover(struct bnx2x *bp) · 10008 unmodified lines | ||
| 10074 | 10076 | } |
| 10075 | 10077 | } |
| 10076 | 10078 | |
| 10077 | −#ifdef CONFIG_BNX2X_VXLAN | |
| 10078 | −static int bnx2x_vxlan_port_update(struct bnx2x *bp, u16 port) | |
| 10079 | +#if defined(CONFIG_BNX2X_VXLAN) || IS_ENABLED(CONFIG_BNX2X_GENEVE) | |
| 10080 | +static int bnx2x_udp_port_update(struct bnx2x *bp) | |
| 10079 | 10081 | { |
| 10080 | 10082 | struct bnx2x_func_switch_update_params *switch_update_params; |
| 10081 | 10083 | struct bnx2x_func_state_params func_params = {NULL}; |
| 10084 | + struct bnx2x_udp_tunnel *udp_tunnel; | |
| 10085 | + u16 vxlan_port = 0, geneve_port = 0; | |
| 10082 | 10086 | int rc; |
| 10083 | 10087 | |
| 10084 | 10088 | switch_update_params = &func_params.params.switch_update; |
| @@ -10093,69 +10097,125 @@ static int bnx2x_vxlan_port_update(struct bnx2x *bp, u16 port) · 8 unmodified lines | ||
| 10093 | 10097 | /* Function parameters */ |
| 10094 | 10098 | __set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG, |
| 10095 | 10099 | &switch_update_params->changes); |
| 10096 | − switch_update_params->vxlan_dst_port = port; | |
| 10100 | + | |
| 10101 | + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { | |
| 10102 | + udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]; | |
| 10103 | + geneve_port = udp_tunnel->dst_port; | |
| 10104 | + switch_update_params->geneve_dst_port = geneve_port; | |
| 10105 | + } | |
| 10106 | + | |
| 10107 | + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { | |
| 10108 | + udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]; | |
| 10109 | + vxlan_port = udp_tunnel->dst_port; | |
| 10110 | + switch_update_params->vxlan_dst_port = vxlan_port; | |
| 10111 | + } | |
| 10112 | + | |
| 10113 | + /* Re-enable inner-rss for the offloaded UDP tunnels */ | |
| 10114 | + __set_bit(BNX2X_F_UPDATE_TUNNEL_INNER_RSS, | |
| 10115 | + &switch_update_params->changes); | |
| 10116 | + | |
| 10097 | 10117 | rc = bnx2x_func_state_change(bp, &func_params); |
| 10098 | 10118 | if (rc) |
| 10099 | − BNX2X_ERR("failed to change vxlan dst port to %d (rc = 0x%x)\n", | |
| 10100 | − port, rc); | |
| 10119 | + BNX2X_ERR("failed to set UDP dst port to %04x %04x (rc = 0x%x)\n", | |
| 10120 | + vxlan_port, geneve_port, rc); | |
| 10121 | + else | |
| 10122 | + DP(BNX2X_MSG_SP, | |
| 10123 | + "Configured UDP ports: Vxlan [%04x] Geneve [%04x]\n", | |
| 10124 | + vxlan_port, geneve_port); | |
| 10125 | + | |
| 10101 | 10126 | return rc; |
| 10102 | 10127 | } |
| 10103 | 10128 | |
| 10104 | −static void __bnx2x_add_vxlan_port(struct bnx2x *bp, u16 port) | |
| 10129 | +static void __bnx2x_add_udp_port(struct bnx2x *bp, u16 port, | |
| 10130 | + enum bnx2x_udp_port_type type) | |
| 10105 | 10131 | { |
| 10106 | − if (!netif_running(bp->dev)) | |
| 10132 | + struct bnx2x_udp_tunnel *udp_port = &bp->udp_tunnel_ports[type]; | |
| 10133 | + | |
| 10134 | + if (!netif_running(bp->dev) || !IS_PF(bp)) | |
| 10107 | 10135 | return; |
| 10108 | 10136 | |
| 10109 | − if (bp->vxlan_dst_port_count && bp->vxlan_dst_port == port) { | |
| 10110 | − bp->vxlan_dst_port_count++; | |
| 10137 | + if (udp_port->count && udp_port->dst_port == port) { | |
| 10138 | + udp_port->count++; | |
| 10111 | 10139 | return; |
| 10112 | 10140 | } |
| 10113 | 10141 | |
| 10114 | − if (bp->vxlan_dst_port_count || !IS_PF(bp)) { | |
| 10115 | − DP(BNX2X_MSG_SP, "Vxlan destination port limit reached\n"); | |
| 10142 | + if (udp_port->count) { | |
| 10143 | + DP(BNX2X_MSG_SP, | |
| 10144 | + "UDP tunnel [%d] - destination port limit reached\n", | |
| 10145 | + type); | |
| 10116 | 10146 | return; |
| 10117 | 10147 | } |
| 10118 | 10148 | |
| 10119 | − bp->vxlan_dst_port = port; | |
| 10120 | − bp->vxlan_dst_port_count = 1; | |
| 10121 | − bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_ADD_VXLAN_PORT, 0); | |
| 10149 | + udp_port->dst_port = port; | |
| 10150 | + udp_port->count = 1; | |
| 10151 | + bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_CHANGE_UDP_PORT, 0); | |
| 10122 | 10152 | } |
| 10123 | 10153 | |
| 10154 | +static void __bnx2x_del_udp_port(struct bnx2x *bp, u16 port, | |
| 10155 | + enum bnx2x_udp_port_type type) | |
| 10156 | +{ | |
| 10157 | + struct bnx2x_udp_tunnel *udp_port = &bp->udp_tunnel_ports[type]; | |
| 10158 | + | |
| 10159 | + if (!IS_PF(bp)) | |
| 10160 | + return; | |
| 10161 | + | |
| 10162 | + if (!udp_port->count || udp_port->dst_port != port) { | |
| 10163 | + DP(BNX2X_MSG_SP, "Invalid UDP tunnel [%d] port\n", | |
| 10164 | + type); | |
| 10165 | + return; | |
| 10166 | + } | |
| 10167 | + | |
| 10168 | + /* Remove reference, and make certain it's no longer in use */ | |
| 10169 | + udp_port->count--; | |
| 10170 | + if (udp_port->count) | |
| 10171 | + return; | |
| 10172 | + udp_port->dst_port = 0; | |
| 10173 | + | |
| 10174 | + if (netif_running(bp->dev)) | |
| 10175 | + bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_CHANGE_UDP_PORT, 0); | |
| 10176 | + else | |
| 10177 | + DP(BNX2X_MSG_SP, "Deleted UDP tunnel [%d] port %d\n", | |
| 10178 | + type, port); | |
| 10179 | +} | |
| 10180 | +#endif | |
| 10181 | + | |
| 10182 | +#ifdef CONFIG_BNX2X_VXLAN | |
| 10124 | 10183 | static void bnx2x_add_vxlan_port(struct net_device *netdev, |
| 10125 | 10184 | sa_family_t sa_family, __be16 port) |
| 10126 | 10185 | { |
| 10127 | 10186 | struct bnx2x *bp = netdev_priv(netdev); |
| 10128 | 10187 | u16 t_port = ntohs(port); |
| 10129 | 10188 | |
| 10130 | − __bnx2x_add_vxlan_port(bp, t_port); | |
| 10189 | + __bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_VXLAN); | |
| 10131 | 10190 | } |
| 10132 | 10191 | |
| 10133 | −static void __bnx2x_del_vxlan_port(struct bnx2x *bp, u16 port) | |
| 10192 | +static void bnx2x_del_vxlan_port(struct net_device *netdev, | |
| 10193 | + sa_family_t sa_family, __be16 port) | |
| 10134 | 10194 | { |
| 10135 | − if (!bp->vxlan_dst_port_count || bp->vxlan_dst_port != port || | |
| 10136 | − !IS_PF(bp)) { | |
| 10137 | − DP(BNX2X_MSG_SP, "Invalid vxlan port\n"); | |
| 10138 | − return; | |
| 10139 | − } | |
| 10140 | − bp->vxlan_dst_port_count--; | |
| 10141 | − if (bp->vxlan_dst_port_count) | |
| 10142 | − return; | |
| 10195 | + struct bnx2x *bp = netdev_priv(netdev); | |
| 10196 | + u16 t_port = ntohs(port); | |
| 10143 | 10197 | |
| 10144 | − if (netif_running(bp->dev)) { | |
| 10145 | − bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_DEL_VXLAN_PORT, 0); | |
| 10146 | − } else { | |
| 10147 | − bp->vxlan_dst_port = 0; | |
| 10148 | − netdev_info(bp->dev, "Deleted vxlan dest port %d", port); | |
| 10149 | − } | |
| 10198 | + __bnx2x_del_udp_port(bp, t_port, BNX2X_UDP_PORT_VXLAN); | |
| 10150 | 10199 | } |
| 10200 | +#endif | |
| 10151 | 10201 | |
| 10152 | −static void bnx2x_del_vxlan_port(struct net_device *netdev, | |
| 10153 | − sa_family_t sa_family, __be16 port) | |
| 10202 | +#if IS_ENABLED(CONFIG_BNX2X_GENEVE) | |
| 10203 | +static void bnx2x_add_geneve_port(struct net_device *netdev, | |
| 10204 | + sa_family_t sa_family, __be16 port) | |
| 10205 | +{ | |
| 10206 | + struct bnx2x *bp = netdev_priv(netdev); | |
| 10207 | + u16 t_port = ntohs(port); | |
| 10208 | + | |
| 10209 | + __bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_GENEVE); | |
| 10210 | +} | |
| 10211 | + | |
| 10212 | +static void bnx2x_del_geneve_port(struct net_device *netdev, | |
| 10213 | + sa_family_t sa_family, __be16 port) | |
| 10154 | 10214 | { |
| 10155 | 10215 | struct bnx2x *bp = netdev_priv(netdev); |
| 10156 | 10216 | u16 t_port = ntohs(port); |
| 10157 | 10217 | |
| 10158 | − __bnx2x_del_vxlan_port(bp, t_port); | |
| 10218 | + __bnx2x_del_udp_port(bp, t_port, BNX2X_UDP_PORT_GENEVE); | |
| 10159 | 10219 | } |
| 10160 | 10220 | #endif |
| 10161 | 10221 | |
| @@ -10167,9 +10227,6 @@ static int bnx2x_close(struct net_device *dev); · 5 unmodified lines | ||
| 10167 | 10227 | static void bnx2x_sp_rtnl_task(struct work_struct *work) |
| 10168 | 10228 | { |
| 10169 | 10229 | struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work); |
| 10170 | −#ifdef CONFIG_BNX2X_VXLAN | |
| 10171 | − u16 port; | |
| 10172 | −#endif | |
| 10173 | 10230 | |
| 10174 | 10231 | rtnl_lock(); |
| 10175 | 10232 | |
| @@ -10268,23 +10325,27 @@ sp_rtnl_not_reset: · 92 unmodified lines | ||
| 10268 | 10325 | &bp->sp_rtnl_state)) |
| 10269 | 10326 | bnx2x_update_mng_version(bp); |
| 10270 | 10327 | |
| 10271 | −#ifdef CONFIG_BNX2X_VXLAN | |
| 10272 | − port = bp->vxlan_dst_port; | |
| 10273 | − if (test_and_clear_bit(BNX2X_SP_RTNL_ADD_VXLAN_PORT, | |
| 10274 | − &bp->sp_rtnl_state)) { | |
| 10275 | − if (!bnx2x_vxlan_port_update(bp, port)) | |
| 10276 | − netdev_info(bp->dev, "Added vxlan dest port %d", port); | |
| 10277 | − else | |
| 10278 | − bp->vxlan_dst_port = 0; | |
| 10279 | − } | |
| 10280 | − | |
| 10281 | − if (test_and_clear_bit(BNX2X_SP_RTNL_DEL_VXLAN_PORT, | |
| 10328 | +#if defined(CONFIG_BNX2X_VXLAN) || IS_ENABLED(CONFIG_BNX2X_GENEVE) | |
| 10329 | + if (test_and_clear_bit(BNX2X_SP_RTNL_CHANGE_UDP_PORT, | |
| 10282 | 10330 | &bp->sp_rtnl_state)) { |
| 10283 | − if (!bnx2x_vxlan_port_update(bp, 0)) { | |
| 10284 | − netdev_info(bp->dev, | |
| 10285 | − "Deleted vxlan dest port %d", port); | |
| 10286 | − bp->vxlan_dst_port = 0; | |
| 10287 | − vxlan_get_rx_port(bp->dev); | |
| 10331 | + if (bnx2x_udp_port_update(bp)) { | |
| 10332 | + /* On error, forget configuration */ | |
| 10333 | + memset(bp->udp_tunnel_ports, 0, | |
| 10334 | + sizeof(struct bnx2x_udp_tunnel) * | |
| 10335 | + BNX2X_UDP_PORT_MAX); | |
| 10336 | + } else { | |
| 10337 | + /* Since we don't store additional port information, | |
| 10338 | + * if no port is configured for any feature ask for | |
| 10339 | + * information about currently configured ports. | |
| 10340 | + */ | |
| 10341 | +#ifdef CONFIG_BNX2X_VXLAN | |
| 10342 | + if (!bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) | |
| 10343 | + vxlan_get_rx_port(bp->dev); | |
| 10344 | +#endif | |
| 10345 | +#if IS_ENABLED(CONFIG_BNX2X_GENEVE) | |
| 10346 | + if (!bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) | |
| 10347 | + geneve_get_rx_port(bp->dev); | |
| 10348 | +#endif | |
| 10288 | 10349 | } |
| 10289 | 10350 | } |
| 10290 | 10351 | #endif |
| @@ -12366,8 +12427,10 @@ static int bnx2x_init_bp(struct bnx2x *bp) · 2075 unmodified lines | ||
| 12366 | 12427 | |
| 12367 | 12428 | if (SHMEM2_HAS(bp, dcbx_lldp_params_offset) && |
| 12368 | 12429 | SHMEM2_HAS(bp, dcbx_lldp_dcbx_stat_offset) && |
| 12430 | + SHMEM2_HAS(bp, dcbx_en) && | |
| 12369 | 12431 | SHMEM2_RD(bp, dcbx_lldp_params_offset) && |
| 12370 | − SHMEM2_RD(bp, dcbx_lldp_dcbx_stat_offset)) { | |
| 12432 | + SHMEM2_RD(bp, dcbx_lldp_dcbx_stat_offset) && | |
| 12433 | + SHMEM2_RD(bp, dcbx_en[BP_PORT(bp)])) { | |
| 12371 | 12434 | bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON); |
| 12372 | 12435 | bnx2x_dcbx_init_params(bp); |
| 12373 | 12436 | } else { |
| @@ -12492,6 +12555,10 @@ static int bnx2x_open(struct net_device *dev) · 118 unmodified lines | ||
| 12492 | 12555 | if (IS_PF(bp)) |
| 12493 | 12556 | vxlan_get_rx_port(dev); |
| 12494 | 12557 | #endif |
| 12558 | +#if IS_ENABLED(CONFIG_BNX2X_GENEVE) | |
| 12559 | + if (IS_PF(bp)) | |
| 12560 | + geneve_get_rx_port(dev); | |
| 12561 | +#endif | |
| 12495 | 12562 | |
| 12496 | 12563 | return 0; |
| 12497 | 12564 | } |
| @@ -12992,7 +13059,7 @@ static const struct net_device_ops bnx2x_netdev_ops = { · 494 unmodified lines | ||
| 12992 | 13059 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 12993 | 13060 | .ndo_poll_controller = poll_bnx2x, |
| 12994 | 13061 | #endif |
| 12995 | − .ndo_setup_tc = bnx2x_setup_tc, | |
| 13062 | + .ndo_setup_tc = __bnx2x_setup_tc, | |
| 12996 | 13063 | #ifdef CONFIG_BNX2X_SRIOV |
| 12997 | 13064 | .ndo_set_vf_mac = bnx2x_set_vf_mac, |
| 12998 | 13065 | .ndo_set_vf_vlan = bnx2x_set_vf_vlan, |
| @@ -13009,6 +13076,10 @@ static const struct net_device_ops bnx2x_netdev_ops = { · 10 unmodified lines | ||
| 13009 | 13076 | .ndo_add_vxlan_port = bnx2x_add_vxlan_port, |
| 13010 | 13077 | .ndo_del_vxlan_port = bnx2x_del_vxlan_port, |
| 13011 | 13078 | #endif |
| 13079 | +#if IS_ENABLED(CONFIG_BNX2X_GENEVE) | |
| 13080 | + .ndo_add_geneve_port = bnx2x_add_geneve_port, | |
| 13081 | + .ndo_del_geneve_port = bnx2x_del_geneve_port, | |
| 13082 | +#endif | |
| 13012 | 13083 | }; |
| 13013 | 13084 | |
| 13014 | 13085 | static int bnx2x_set_coherency_mask(struct bnx2x *bp) |
| @@ -14814,6 +14885,10 @@ static int bnx2x_get_fc_npiv(struct net_device *dev, · 1799 unmodified lines | ||
| 14814 | 14885 | } |
| 14815 | 14886 | |
| 14816 | 14887 | offset = SHMEM2_RD(bp, fc_npiv_nvram_tbl_addr[BP_PORT(bp)]); |
| 14888 | + if (!offset) { | |
| 14889 | + DP(BNX2X_MSG_MCP, "No FC-NPIV in NVRAM\n"); | |
| 14890 | + goto out; | |
| 14891 | + } | |
| 14817 | 14892 | DP(BNX2X_MSG_MCP, "Offset of FC-NPIV in NVRAM: %08x\n", offset); |
| 14818 | 14893 | |
| 14819 | 14894 | /* Read the table contents from nvram */ |
| @@ -1240,13 +1240,17 @@ static int bnxt_async_event_process(struct bnxt *bp, · 1239 unmodified lines | ||
| 1240 | 1240 | switch (event_id) { |
| 1241 | 1241 | case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: |
| 1242 | 1242 | set_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event); |
| 1243 | − schedule_work(&bp->sp_task); | |
| 1243 | + break; | |
| 1244 | + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD: | |
| 1245 | + set_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event); | |
| 1244 | 1246 | break; |
| 1245 | 1247 | default: |
| 1246 | 1248 | netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n", |
| 1247 | 1249 | event_id); |
| 1248 | − break; | |
| 1250 | + goto async_event_process_exit; | |
| 1249 | 1251 | } |
| 1252 | + schedule_work(&bp->sp_task); | |
| 1253 | +async_event_process_exit: | |
| 1250 | 1254 | return 0; |
| 1251 | 1255 | } |
| 1252 | 1256 | |
| @@ -2358,6 +2362,14 @@ static void bnxt_free_stats(struct bnxt *bp) · 1105 unmodified lines | ||
| 2358 | 2362 | u32 size, i; |
| 2359 | 2363 | struct pci_dev *pdev = bp->pdev; |
| 2360 | 2364 | |
| 2365 | + if (bp->hw_rx_port_stats) { | |
| 2366 | + dma_free_coherent(&pdev->dev, bp->hw_port_stats_size, | |
| 2367 | + bp->hw_rx_port_stats, | |
| 2368 | + bp->hw_rx_port_stats_map); | |
| 2369 | + bp->hw_rx_port_stats = NULL; | |
| 2370 | + bp->flags &= ~BNXT_FLAG_PORT_STATS; | |
| 2371 | + } | |
| 2372 | + | |
| 2361 | 2373 | if (!bp->bnapi) |
| 2362 | 2374 | return; |
| 2363 | 2375 | |
| @@ -2394,6 +2406,24 @@ static int bnxt_alloc_stats(struct bnxt *bp) · 30 unmodified lines | ||
| 2394 | 2406 | |
| 2395 | 2407 | cpr->hw_stats_ctx_id = INVALID_STATS_CTX_ID; |
| 2396 | 2408 | } |
| 2409 | + | |
| 2410 | + if (BNXT_PF(bp)) { | |
| 2411 | + bp->hw_port_stats_size = sizeof(struct rx_port_stats) + | |
| 2412 | + sizeof(struct tx_port_stats) + 1024; | |
| 2413 | + | |
| 2414 | + bp->hw_rx_port_stats = | |
| 2415 | + dma_alloc_coherent(&pdev->dev, bp->hw_port_stats_size, | |
| 2416 | + &bp->hw_rx_port_stats_map, | |
| 2417 | + GFP_KERNEL); | |
| 2418 | + if (!bp->hw_rx_port_stats) | |
| 2419 | + return -ENOMEM; | |
| 2420 | + | |
| 2421 | + bp->hw_tx_port_stats = (void *)(bp->hw_rx_port_stats + 1) + | |
| 2422 | + 512; | |
| 2423 | + bp->hw_tx_port_stats_map = bp->hw_rx_port_stats_map + | |
| 2424 | + sizeof(struct rx_port_stats) + 512; | |
| 2425 | + bp->flags |= BNXT_FLAG_PORT_STATS; | |
| 2426 | + } | |
| 2397 | 2427 | return 0; |
| 2398 | 2428 | } |
| 2399 | 2429 | |
| @@ -2597,28 +2627,27 @@ alloc_mem_err: · 197 unmodified lines | ||
| 2597 | 2627 | void bnxt_hwrm_cmd_hdr_init(struct bnxt *bp, void *request, u16 req_type, |
| 2598 | 2628 | u16 cmpl_ring, u16 target_id) |
| 2599 | 2629 | { |
| 2600 | − struct hwrm_cmd_req_hdr *req = request; | |
| 2630 | + struct input *req = request; | |
| 2601 | 2631 | |
| 2602 | − req->cmpl_ring_req_type = | |
| 2603 | − cpu_to_le32(req_type | (cmpl_ring << HWRM_CMPL_RING_SFT)); | |
| 2604 | − req->target_id_seq_id = cpu_to_le32(target_id << HWRM_TARGET_FID_SFT); | |
| 2632 | + req->req_type = cpu_to_le16(req_type); | |
| 2633 | + req->cmpl_ring = cpu_to_le16(cmpl_ring); | |
| 2634 | + req->target_id = cpu_to_le16(target_id); | |
| 2605 | 2635 | req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr); |
| 2606 | 2636 | } |
| 2607 | 2637 | |
| 2608 | −int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) | |
| 2638 | +static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, | |
| 2639 | + int timeout, bool silent) | |
| 2609 | 2640 | { |
| 2610 | 2641 | int i, intr_process, rc; |
| 2611 | − struct hwrm_cmd_req_hdr *req = msg; | |
| 2642 | + struct input *req = msg; | |
| 2612 | 2643 | u32 *data = msg; |
| 2613 | 2644 | __le32 *resp_len, *valid; |
| 2614 | 2645 | u16 cp_ring_id, len = 0; |
| 2615 | 2646 | struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr; |
| 2616 | 2647 | |
| 2617 | − req->target_id_seq_id |= cpu_to_le32(bp->hwrm_cmd_seq++); | |
| 2648 | + req->seq_id = cpu_to_le16(bp->hwrm_cmd_seq++); | |
| 2618 | 2649 | memset(resp, 0, PAGE_SIZE); |
| 2619 | − cp_ring_id = (le32_to_cpu(req->cmpl_ring_req_type) & | |
| 2620 | − HWRM_CMPL_RING_MASK) >> | |
| 2621 | − HWRM_CMPL_RING_SFT; | |
| 2650 | + cp_ring_id = le16_to_cpu(req->cmpl_ring); | |
| 2622 | 2651 | intr_process = (cp_ring_id == INVALID_HW_RING_ID) ? 0 : 1; |
| 2623 | 2652 | |
| 2624 | 2653 | /* Write request msg to hwrm channel */ |
| @@ -2629,12 +2658,14 @@ int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) · 4 unmodified lines | ||
| 2629 | 2658 | |
| 2630 | 2659 | /* currently supports only one outstanding message */ |
| 2631 | 2660 | if (intr_process) |
| 2632 | − bp->hwrm_intr_seq_id = le32_to_cpu(req->target_id_seq_id) & | |
| 2633 | − HWRM_SEQ_ID_MASK; | |
| 2661 | + bp->hwrm_intr_seq_id = le16_to_cpu(req->seq_id); | |
| 2634 | 2662 | |
| 2635 | 2663 | /* Ring channel doorbell */ |
| 2636 | 2664 | writel(1, bp->bar0 + 0x100); |
| 2637 | 2665 | |
| 2666 | + if (!timeout) | |
| 2667 | + timeout = DFLT_HWRM_CMD_TIMEOUT; | |
| 2668 | + | |
| 2638 | 2669 | i = 0; |
| 2639 | 2670 | if (intr_process) { |
| 2640 | 2671 | /* Wait until hwrm response cmpl interrupt is processed */ |
| @@ -2645,7 +2676,7 @@ int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) · 4 unmodified lines | ||
| 2645 | 2676 | |
| 2646 | 2677 | if (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID) { |
| 2647 | 2678 | netdev_err(bp->dev, "Resp cmpl intr err msg: 0x%x\n", |
| 2648 | − req->cmpl_ring_req_type); | |
| 2679 | + le16_to_cpu(req->req_type)); | |
| 2649 | 2680 | return -1; |
| 2650 | 2681 | } |
| 2651 | 2682 | } else { |
| @@ -2661,8 +2692,8 @@ int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) · 9 unmodified lines | ||
| 2661 | 2692 | |
| 2662 | 2693 | if (i >= timeout) { |
| 2663 | 2694 | netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n", |
| 2664 | − timeout, req->cmpl_ring_req_type, | |
| 2665 | − req->target_id_seq_id, *resp_len); | |
| 2695 | + timeout, le16_to_cpu(req->req_type), | |
| 2696 | + le16_to_cpu(req->seq_id), *resp_len); | |
| 2666 | 2697 | return -1; |
| 2667 | 2698 | } |
| 2668 | 2699 | |
| @@ -2676,20 +2707,23 @@ int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) · 7 unmodified lines | ||
| 2676 | 2707 | |
| 2677 | 2708 | if (i >= timeout) { |
| 2678 | 2709 | netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n", |
| 2679 | − timeout, req->cmpl_ring_req_type, | |
| 2680 | − req->target_id_seq_id, len, *valid); | |
| 2710 | + timeout, le16_to_cpu(req->req_type), | |
| 2711 | + le16_to_cpu(req->seq_id), len, *valid); | |
| 2681 | 2712 | return -1; |
| 2682 | 2713 | } |
| 2683 | 2714 | } |
| 2684 | 2715 | |
| 2685 | 2716 | rc = le16_to_cpu(resp->error_code); |
| 2686 | − if (rc) { | |
| 2717 | + if (rc && !silent) | |
| 2687 | 2718 | netdev_err(bp->dev, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n", |
| 2688 | 2719 | le16_to_cpu(resp->req_type), |
| 2689 | 2720 | le16_to_cpu(resp->seq_id), rc); |
| 2690 | − return rc; | |
| 2691 | − } | |
| 2692 | − return 0; | |
| 2721 | + return rc; | |
| 2722 | +} | |
| 2723 | + | |
| 2724 | +int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) | |
| 2725 | +{ | |
| 2726 | + return bnxt_hwrm_do_send_msg(bp, msg, msg_len, timeout, false); | |
| 2693 | 2727 | } |
| 2694 | 2728 | |
| 2695 | 2729 | int hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) |
| @@ -2702,6 +2736,17 @@ int hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) · 6 unmodified lines | ||
| 2702 | 2736 | return rc; |
| 2703 | 2737 | } |
| 2704 | 2738 | |
| 2739 | +int hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 msg_len, | |
| 2740 | + int timeout) | |
| 2741 | +{ | |
| 2742 | + int rc; | |
| 2743 | + | |
| 2744 | + mutex_lock(&bp->hwrm_cmd_lock); | |
| 2745 | + rc = bnxt_hwrm_do_send_msg(bp, msg, msg_len, timeout, true); | |
| 2746 | + mutex_unlock(&bp->hwrm_cmd_lock); | |
| 2747 | + return rc; | |
| 2748 | +} | |
| 2749 | + | |
| 2705 | 2750 | static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp) |
| 2706 | 2751 | { |
| 2707 | 2752 | struct hwrm_func_drv_rgtr_input req = {0}; |
| @@ -3518,47 +3563,82 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool close_path) · 810 unmodified lines | ||
| 3518 | 3563 | } |
| 3519 | 3564 | } |
| 3520 | 3565 | |
| 3566 | +static void bnxt_hwrm_set_coal_params(struct bnxt *bp, u32 max_bufs, | |
| 3567 | + u32 buf_tmrs, u16 flags, | |
| 3568 | + struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req) | |
| 3569 | +{ | |
| 3570 | + req->flags = cpu_to_le16(flags); | |
| 3571 | + req->num_cmpl_dma_aggr = cpu_to_le16((u16)max_bufs); | |
| 3572 | + req->num_cmpl_dma_aggr_during_int = cpu_to_le16(max_bufs >> 16); | |
| 3573 | + req->cmpl_aggr_dma_tmr = cpu_to_le16((u16)buf_tmrs); | |
| 3574 | + req->cmpl_aggr_dma_tmr_during_int = cpu_to_le16(buf_tmrs >> 16); | |
| 3575 | + /* Minimum time between 2 interrupts set to buf_tmr x 2 */ | |
| 3576 | + req->int_lat_tmr_min = cpu_to_le16((u16)buf_tmrs * 2); | |
| 3577 | + req->int_lat_tmr_max = cpu_to_le16((u16)buf_tmrs * 4); | |
| 3578 | + req->num_cmpl_aggr_int = cpu_to_le16((u16)max_bufs * 4); | |
| 3579 | +} | |
| 3580 | + | |
| 3521 | 3581 | int bnxt_hwrm_set_coal(struct bnxt *bp) |
| 3522 | 3582 | { |
| 3523 | 3583 | int i, rc = 0; |
| 3524 | − struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req = {0}; | |
| 3584 | + struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0}, | |
| 3585 | + req_tx = {0}, *req; | |
| 3525 | 3586 | u16 max_buf, max_buf_irq; |
| 3526 | 3587 | u16 buf_tmr, buf_tmr_irq; |
| 3527 | 3588 | u32 flags; |
| 3528 | 3589 | |
| 3529 | − bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS, | |
| 3530 | − -1, -1); | |
| 3590 | + bnxt_hwrm_cmd_hdr_init(bp, &req_rx, | |
| 3591 | + HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS, -1, -1); | |
| 3592 | + bnxt_hwrm_cmd_hdr_init(bp, &req_tx, | |
| 3593 | + HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS, -1, -1); | |
| 3531 | 3594 | |
| 3532 | − /* Each rx completion (2 records) should be DMAed immediately */ | |
| 3533 | − max_buf = min_t(u16, bp->coal_bufs / 4, 2); | |
| 3595 | + /* Each rx completion (2 records) should be DMAed immediately. | |
| 3596 | + * DMA 1/4 of the completion buffers at a time. | |
| 3597 | + */ | |
| 3598 | + max_buf = min_t(u16, bp->rx_coal_bufs / 4, 2); | |
| 3534 | 3599 | /* max_buf must not be zero */ |
| 3535 | 3600 | max_buf = clamp_t(u16, max_buf, 1, 63); |
| 3536 | − max_buf_irq = clamp_t(u16, bp->coal_bufs_irq, 1, 63); | |
| 3537 | − buf_tmr = max_t(u16, bp->coal_ticks / 4, 1); | |
| 3538 | − buf_tmr_irq = max_t(u16, bp->coal_ticks_irq, 1); | |
| 3601 | + max_buf_irq = clamp_t(u16, bp->rx_coal_bufs_irq, 1, 63); | |
| 3602 | + buf_tmr = BNXT_USEC_TO_COAL_TIMER(bp->rx_coal_ticks); | |
| 3603 | + /* buf timer set to 1/4 of interrupt timer */ | |
| 3604 | + buf_tmr = max_t(u16, buf_tmr / 4, 1); | |
| 3605 | + buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(bp->rx_coal_ticks_irq); | |
| 3606 | + buf_tmr_irq = max_t(u16, buf_tmr_irq, 1); | |
| 3539 | 3607 | |
| 3540 | 3608 | flags = RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_TIMER_RESET; |
| 3541 | 3609 | |
| 3542 | 3610 | /* RING_IDLE generates more IRQs for lower latency. Enable it only |
| 3543 | 3611 | * if coal_ticks is less than 25 us. |
| 3544 | 3612 | */ |
| 3545 | − if (BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks) < 25) | |
| 3613 | + if (bp->rx_coal_ticks < 25) | |
| 3546 | 3614 | flags |= RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_RING_IDLE; |
| 3547 | 3615 | |
| 3548 | − req.flags = cpu_to_le16(flags); | |
| 3549 | − req.num_cmpl_dma_aggr = cpu_to_le16(max_buf); | |
| 3550 | − req.num_cmpl_dma_aggr_during_int = cpu_to_le16(max_buf_irq); | |
| 3551 | − req.cmpl_aggr_dma_tmr = cpu_to_le16(buf_tmr); | |
| 3552 | − req.cmpl_aggr_dma_tmr_during_int = cpu_to_le16(buf_tmr_irq); | |
| 3553 | − req.int_lat_tmr_min = cpu_to_le16(buf_tmr); | |
| 3554 | − req.int_lat_tmr_max = cpu_to_le16(bp->coal_ticks); | |
| 3555 | − req.num_cmpl_aggr_int = cpu_to_le16(bp->coal_bufs); | |
| 3616 | + bnxt_hwrm_set_coal_params(bp, max_buf_irq << 16 | max_buf, | |
| 3617 | + buf_tmr_irq << 16 | buf_tmr, flags, &req_rx); | |
| 3618 | + | |
| 3619 | + /* max_buf must not be zero */ | |
| 3620 | + max_buf = clamp_t(u16, bp->tx_coal_bufs, 1, 63); | |
| 3621 | + max_buf_irq = clamp_t(u16, bp->tx_coal_bufs_irq, 1, 63); | |
| 3622 | + buf_tmr = BNXT_USEC_TO_COAL_TIMER(bp->tx_coal_ticks); | |
| 3623 | + /* buf timer set to 1/4 of interrupt timer */ | |
| 3624 | + buf_tmr = max_t(u16, buf_tmr / 4, 1); | |
| 3625 | + buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(bp->tx_coal_ticks_irq); | |
| 3626 | + buf_tmr_irq = max_t(u16, buf_tmr_irq, 1); | |
| 3627 | + | |
| 3628 | + flags = RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_TIMER_RESET; | |
| 3629 | + bnxt_hwrm_set_coal_params(bp, max_buf_irq << 16 | max_buf, | |
| 3630 | + buf_tmr_irq << 16 | buf_tmr, flags, &req_tx); | |
| 3556 | 3631 | |
| 3557 | 3632 | mutex_lock(&bp->hwrm_cmd_lock); |
| 3558 | 3633 | for (i = 0; i < bp->cp_nr_rings; i++) { |
| 3559 | − req.ring_id = cpu_to_le16(bp->grp_info[i].cp_fw_ring_id); | |
| 3634 | + struct bnxt_napi *bnapi = bp->bnapi[i]; | |
| 3560 | 3635 | |
| 3561 | − rc = _hwrm_send_message(bp, &req, sizeof(req), | |
| 3636 | + req = &req_rx; | |
| 3637 | + if (!bnapi->rx_ring) | |
| 3638 | + req = &req_tx; | |
| 3639 | + req->ring_id = cpu_to_le16(bp->grp_info[i].cp_fw_ring_id); | |
| 3640 | + | |
| 3641 | + rc = _hwrm_send_message(bp, req, sizeof(*req), | |
| 3562 | 3642 | HWRM_CMD_TIMEOUT); |
| 3563 | 3643 | if (rc) |
| 3564 | 3644 | break; |
| @@ -3767,15 +3847,36 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) · 202 unmodified lines | ||
| 3767 | 3847 | resp->hwrm_intf_upd); |
| 3768 | 3848 | netdev_warn(bp->dev, "Please update firmware with HWRM interface 1.0.0 or newer.\n"); |
| 3769 | 3849 | } |
| 3770 | − snprintf(bp->fw_ver_str, BC_HWRM_STR_LEN, "bc %d.%d.%d rm %d.%d.%d", | |
| 3850 | + snprintf(bp->fw_ver_str, BC_HWRM_STR_LEN, "%d.%d.%d/%d.%d.%d", | |
| 3771 | 3851 | resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld, |
| 3772 | 3852 | resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd); |
| 3773 | 3853 | |
| 3854 | + bp->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout); | |
| 3855 | + if (!bp->hwrm_cmd_timeout) | |
| 3856 | + bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT; | |
| 3857 | + | |
| 3774 | 3858 | hwrm_ver_get_exit: |
| 3775 | 3859 | mutex_unlock(&bp->hwrm_cmd_lock); |
| 3776 | 3860 | return rc; |
| 3777 | 3861 | } |
| 3778 | 3862 | |
| 3863 | +static int bnxt_hwrm_port_qstats(struct bnxt *bp) | |
| 3864 | +{ | |
| 3865 | + int rc; | |
| 3866 | + struct bnxt_pf_info *pf = &bp->pf; | |
| 3867 | + struct hwrm_port_qstats_input req = {0}; | |
| 3868 | + | |
| 3869 | + if (!(bp->flags & BNXT_FLAG_PORT_STATS)) | |
| 3870 | + return 0; | |
| 3871 | + | |
| 3872 | + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_QSTATS, -1, -1); | |
| 3873 | + req.port_id = cpu_to_le16(pf->port_id); | |
| 3874 | + req.tx_stat_host_addr = cpu_to_le64(bp->hw_tx_port_stats_map); | |
| 3875 | + req.rx_stat_host_addr = cpu_to_le64(bp->hw_rx_port_stats_map); | |
| 3876 | + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); | |
| 3877 | + return rc; | |
| 3878 | +} | |
| 3879 | + | |
| 3779 | 3880 | static void bnxt_hwrm_free_tunnel_ports(struct bnxt *bp) |
| 3780 | 3881 | { |
| 3781 | 3882 | if (bp->vxlan_port_cnt) { |
| @@ -4410,6 +4511,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) · 628 unmodified lines | ||
| 4410 | 4511 | link_info->pause = resp->pause; |
| 4411 | 4512 | link_info->auto_mode = resp->auto_mode; |
| 4412 | 4513 | link_info->auto_pause_setting = resp->auto_pause; |
| 4514 | + link_info->lp_pause = resp->link_partner_adv_pause; | |
| 4413 | 4515 | link_info->force_pause_setting = resp->force_pause; |
| 4414 | 4516 | link_info->duplex_setting = resp->duplex; |
| 4415 | 4517 | if (link_info->phy_link_status == BNXT_LINK_LINK) |
| @@ -4420,6 +4522,8 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) · 4 unmodified lines | ||
| 4420 | 4522 | link_info->auto_link_speed = le16_to_cpu(resp->auto_link_speed); |
| 4421 | 4523 | link_info->support_speeds = le16_to_cpu(resp->support_speeds); |
| 4422 | 4524 | link_info->auto_link_speeds = le16_to_cpu(resp->auto_link_speed_mask); |
| 4525 | + link_info->lp_auto_link_speeds = | |
| 4526 | + le16_to_cpu(resp->link_partner_adv_speeds); | |
| 4423 | 4527 | link_info->preemphasis = le32_to_cpu(resp->preemphasis); |
| 4424 | 4528 | link_info->phy_ver[0] = resp->phy_maj; |
| 4425 | 4529 | link_info->phy_ver[1] = resp->phy_min; |
| @@ -4831,6 +4935,22 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) · 405 unmodified lines | ||
| 4831 | 4935 | stats->tx_dropped += le64_to_cpu(hw_stats->tx_drop_pkts); |
| 4832 | 4936 | } |
| 4833 | 4937 | |
| 4938 | + if (bp->flags & BNXT_FLAG_PORT_STATS) { | |
| 4939 | + struct rx_port_stats *rx = bp->hw_rx_port_stats; | |
| 4940 | + struct tx_port_stats *tx = bp->hw_tx_port_stats; | |
| 4941 | + | |
| 4942 | + stats->rx_crc_errors = le64_to_cpu(rx->rx_fcs_err_frames); | |
| 4943 | + stats->rx_frame_errors = le64_to_cpu(rx->rx_align_err_frames); | |
| 4944 | + stats->rx_length_errors = le64_to_cpu(rx->rx_undrsz_frames) + | |
| 4945 | + le64_to_cpu(rx->rx_ovrsz_frames) + | |
| 4946 | + le64_to_cpu(rx->rx_runt_frames); | |
| 4947 | + stats->rx_errors = le64_to_cpu(rx->rx_false_carrier_frames) + | |
| 4948 | + le64_to_cpu(rx->rx_jbr_frames); | |
| 4949 | + stats->collisions = le64_to_cpu(tx->tx_total_collisions); | |
| 4950 | + stats->tx_fifo_errors = le64_to_cpu(tx->tx_fifo_underruns); | |
| 4951 | + stats->tx_errors = le64_to_cpu(tx->tx_err); | |
| 4952 | + } | |
| 4953 | + | |
| 4834 | 4954 | return stats; |
| 4835 | 4955 | } |
| 4836 | 4956 | |
| @@ -5171,6 +5291,10 @@ static void bnxt_timer(unsigned long data) · 334 unmodified lines | ||
| 5171 | 5291 | if (atomic_read(&bp->intr_sem) != 0) |
| 5172 | 5292 | goto bnxt_restart_timer; |
| 5173 | 5293 | |
| 5294 | + if (bp->link_info.link_up && (bp->flags & BNXT_FLAG_PORT_STATS)) { | |
| 5295 | + set_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event); | |
| 5296 | + schedule_work(&bp->sp_task); | |
| 5297 | + } | |
| 5174 | 5298 | bnxt_restart_timer: |
| 5175 | 5299 | mod_timer(&bp->timer, jiffies + bp->current_interval); |
| 5176 | 5300 | } |
| @@ -5222,6 +5346,9 @@ static void bnxt_sp_task(struct work_struct *work) · 45 unmodified lines | ||
| 5222 | 5346 | rtnl_unlock(); |
| 5223 | 5347 | } |
| 5224 | 5348 | |
| 5349 | + if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event)) | |
| 5350 | + bnxt_hwrm_port_qstats(bp); | |
| 5351 | + | |
| 5225 | 5352 | smp_mb__before_atomic(); |
| 5226 | 5353 | clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state); |
| 5227 | 5354 | } |
| @@ -5285,6 +5412,8 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) · 57 unmodified lines | ||
| 5285 | 5412 | goto init_err_release; |
| 5286 | 5413 | } |
| 5287 | 5414 | |
| 5415 | + pci_enable_pcie_error_reporting(pdev); | |
| 5416 | + | |
| 5288 | 5417 | INIT_WORK(&bp->sp_task, bnxt_sp_task); |
| 5289 | 5418 | |
| 5290 | 5419 | spin_lock_init(&bp->ntp_fltr_lock); |
| @@ -5292,10 +5421,16 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) · 1 unmodified line | ||
| 5292 | 5421 | bp->rx_ring_size = BNXT_DEFAULT_RX_RING_SIZE; |
| 5293 | 5422 | bp->tx_ring_size = BNXT_DEFAULT_TX_RING_SIZE; |
| 5294 | 5423 | |
| 5295 | − bp->coal_ticks = BNXT_USEC_TO_COAL_TIMER(4); | |
| 5296 | − bp->coal_bufs = 20; | |
| 5297 | − bp->coal_ticks_irq = BNXT_USEC_TO_COAL_TIMER(1); | |
| 5298 | − bp->coal_bufs_irq = 2; | |
| 5424 | + /* tick values in micro seconds */ | |
| 5425 | + bp->rx_coal_ticks = 12; | |
| 5426 | + bp->rx_coal_bufs = 30; | |
| 5427 | + bp->rx_coal_ticks_irq = 1; | |
| 5428 | + bp->rx_coal_bufs_irq = 2; | |
| 5429 | + | |
| 5430 | + bp->tx_coal_ticks = 25; | |
| 5431 | + bp->tx_coal_bufs = 30; | |
| 5432 | + bp->tx_coal_ticks_irq = 2; | |
| 5433 | + bp->tx_coal_bufs_irq = 2; | |
| 5299 | 5434 | |
| 5300 | 5435 | init_timer(&bp->timer); |
| 5301 | 5436 | bp->timer.data = (unsigned long)bp; |
| @@ -5378,9 +5513,16 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu) · 76 unmodified lines | ||
| 5378 | 5513 | return 0; |
| 5379 | 5514 | } |
| 5380 | 5515 | |
| 5381 | −static int bnxt_setup_tc(struct net_device *dev, u8 tc) | |
| 5516 | +static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto, | |
| 5517 | + struct tc_to_netdev *ntc) | |
| 5382 | 5518 | { |
| 5383 | 5519 | struct bnxt *bp = netdev_priv(dev); |
| 5520 | + u8 tc; | |
| 5521 | + | |
| 5522 | + if (ntc->type != TC_SETUP_MQPRIO) | |
| 5523 | + return -EINVAL; | |
| 5524 | + | |
| 5525 | + tc = ntc->tc; | |
| 5384 | 5526 | |
| 5385 | 5527 | if (tc > bp->max_tc) { |
| 5386 | 5528 | netdev_err(dev, "too many traffic classes requested: %d Max supported is %d\n", |
| @@ -5553,6 +5695,8 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp) · 166 unmodified lines | ||
| 5553 | 5695 | } |
| 5554 | 5696 | } |
| 5555 | 5697 | } |
| 5698 | + if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event)) | |
| 5699 | + netdev_info(bp->dev, "Receive PF driver unload event!"); | |
| 5556 | 5700 | } |
| 5557 | 5701 | |
| 5558 | 5702 | #else |
| @@ -5649,6 +5793,7 @@ static void bnxt_remove_one(struct pci_dev *pdev) · 90 unmodified lines | ||
| 5649 | 5793 | if (BNXT_PF(bp)) |
| 5650 | 5794 | bnxt_sriov_disable(bp); |
| 5651 | 5795 | |
| 5796 | + pci_disable_pcie_error_reporting(pdev); | |
| 5652 | 5797 | unregister_netdev(dev); |
| 5653 | 5798 | cancel_work_sync(&bp->sp_task); |
| 5654 | 5799 | bp->sp_event = 0; |
| @@ -5668,7 +5813,6 @@ static int bnxt_probe_phy(struct bnxt *bp) · 13 unmodified lines | ||
| 5668 | 5813 | { |
| 5669 | 5814 | int rc = 0; |
| 5670 | 5815 | struct bnxt_link_info *link_info = &bp->link_info; |
| 5671 | − char phy_ver[PHY_VER_STR_LEN]; | |
| 5672 | 5816 | |
| 5673 | 5817 | rc = bnxt_update_link(bp, false); |
| 5674 | 5818 | if (rc) { |
| @@ -5688,11 +5832,6 @@ static int bnxt_probe_phy(struct bnxt *bp) · 13 unmodified lines | ||
| 5688 | 5832 | link_info->req_duplex = link_info->duplex_setting; |
| 5689 | 5833 | link_info->req_flow_ctrl = link_info->force_pause_setting; |
| 5690 | 5834 | } |
| 5691 | − snprintf(phy_ver, PHY_VER_STR_LEN, " ph %d.%d.%d", | |
| 5692 | − link_info->phy_ver[0], | |
| 5693 | − link_info->phy_ver[1], | |
| 5694 | − link_info->phy_ver[2]); | |
| 5695 | − strcat(bp->fw_ver_str, phy_ver); | |
| 5696 | 5835 | return rc; |
| 5697 | 5836 | } |
| 5698 | 5837 | |
| @@ -5894,11 +6033,117 @@ init_err_free: · 195 unmodified lines | ||
| 5894 | 6033 | return rc; |
| 5895 | 6034 | } |
| 5896 | 6035 | |
| 6036 | +/** | |
| 6037 | + * bnxt_io_error_detected - called when PCI error is detected | |
| 6038 | + * @pdev: Pointer to PCI device | |
| 6039 | + * @state: The current pci connection state | |
| 6040 | + * | |
| 6041 | + * This function is called after a PCI bus error affecting | |
| 6042 | + * this device has been detected. | |
| 6043 | + */ | |
| 6044 | +static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev, | |
| 6045 | + pci_channel_state_t state) | |
| 6046 | +{ | |
| 6047 | + struct net_device *netdev = pci_get_drvdata(pdev); | |
| 6048 | + | |
| 6049 | + netdev_info(netdev, "PCI I/O error detected\n"); | |
| 6050 | + | |
| 6051 | + rtnl_lock(); | |
| 6052 | + netif_device_detach(netdev); | |
| 6053 | + | |
| 6054 | + if (state == pci_channel_io_perm_failure) { | |
| 6055 | + rtnl_unlock(); | |
| 6056 | + return PCI_ERS_RESULT_DISCONNECT; | |
| 6057 | + } | |
| 6058 | + | |
| 6059 | + if (netif_running(netdev)) | |
| 6060 | + bnxt_close(netdev); | |
| 6061 | + | |
| 6062 | + pci_disable_device(pdev); | |
| 6063 | + rtnl_unlock(); | |
| 6064 | + | |
| 6065 | + /* Request a slot slot reset. */ | |
| 6066 | + return PCI_ERS_RESULT_NEED_RESET; | |
| 6067 | +} | |
| 6068 | + | |
| 6069 | +/** | |
| 6070 | + * bnxt_io_slot_reset - called after the pci bus has been reset. | |
| 6071 | + * @pdev: Pointer to PCI device | |
| 6072 | + * | |
| 6073 | + * Restart the card from scratch, as if from a cold-boot. | |
| 6074 | + * At this point, the card has exprienced a hard reset, | |
| 6075 | + * followed by fixups by BIOS, and has its config space | |
| 6076 | + * set up identically to what it was at cold boot. | |
| 6077 | + */ | |
| 6078 | +static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev) | |
| 6079 | +{ | |
| 6080 | + struct net_device *netdev = pci_get_drvdata(pdev); | |
| 6081 | + struct bnxt *bp = netdev_priv(netdev); | |
| 6082 | + int err = 0; | |
| 6083 | + pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT; | |
| 6084 | + | |
| 6085 | + netdev_info(bp->dev, "PCI Slot Reset\n"); | |
| 6086 | + | |
| 6087 | + rtnl_lock(); | |
| 6088 | + | |
| 6089 | + if (pci_enable_device(pdev)) { | |
| 6090 | + dev_err(&pdev->dev, | |
| 6091 | + "Cannot re-enable PCI device after reset.\n"); | |
| 6092 | + } else { | |
| 6093 | + pci_set_master(pdev); | |
| 6094 | + | |
| 6095 | + if (netif_running(netdev)) | |
| 6096 | + err = bnxt_open(netdev); | |
| 6097 | + | |
| 6098 | + if (!err) | |
| 6099 | + result = PCI_ERS_RESULT_RECOVERED; | |
| 6100 | + } | |
| 6101 | + | |
| 6102 | + if (result != PCI_ERS_RESULT_RECOVERED && netif_running(netdev)) | |
| 6103 | + dev_close(netdev); | |
| 6104 | + | |
| 6105 | + rtnl_unlock(); | |
| 6106 | + | |
| 6107 | + err = pci_cleanup_aer_uncorrect_error_status(pdev); | |
| 6108 | + if (err) { | |
| 6109 | + dev_err(&pdev->dev, | |
| 6110 | + "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", | |
| 6111 | + err); /* non-fatal, continue */ | |
| 6112 | + } | |
| 6113 | + | |
| 6114 | + return PCI_ERS_RESULT_RECOVERED; | |
| 6115 | +} | |
| 6116 | + | |
| 6117 | +/** | |
| 6118 | + * bnxt_io_resume - called when traffic can start flowing again. | |
| 6119 | + * @pdev: Pointer to PCI device | |
| 6120 | + * | |
| 6121 | + * This callback is called when the error recovery driver tells | |
| 6122 | + * us that its OK to resume normal operation. | |
| 6123 | + */ | |
| 6124 | +static void bnxt_io_resume(struct pci_dev *pdev) | |
| 6125 | +{ | |
| 6126 | + struct net_device *netdev = pci_get_drvdata(pdev); | |
| 6127 | + | |
| 6128 | + rtnl_lock(); | |
| 6129 | + | |
| 6130 | + netif_device_attach(netdev); | |
| 6131 | + | |
| 6132 | + rtnl_unlock(); | |
| 6133 | +} | |
| 6134 | + | |
| 6135 | +static const struct pci_error_handlers bnxt_err_handler = { | |
| 6136 | + .error_detected = bnxt_io_error_detected, | |
| 6137 | + .slot_reset = bnxt_io_slot_reset, | |
| 6138 | + .resume = bnxt_io_resume | |
| 6139 | +}; | |
| 6140 | + | |
| 5897 | 6141 | static struct pci_driver bnxt_pci_driver = { |
| 5898 | 6142 | .name = DRV_MODULE_NAME, |
| 5899 | 6143 | .id_table = bnxt_pci_tbl, |
| 5900 | 6144 | .probe = bnxt_init_one, |
| 5901 | 6145 | .remove = bnxt_remove_one, |
| 6146 | + .err_handler = &bnxt_err_handler, | |
| 5902 | 6147 | #if defined(CONFIG_BNXT_SRIOV) |
| 5903 | 6148 | .sriov_configure = bnxt_sriov_configure, |
| 5904 | 6149 | #endif |
| @@ -477,12 +477,15 @@ struct rx_tpa_end_cmp_ext { · 476 unmodified lines | ||
| 477 | 477 | #define RING_CMP(idx) ((idx) & bp->cp_ring_mask) |
| 478 | 478 | #define NEXT_CMP(idx) RING_CMP(ADV_RAW_CMP(idx, 1)) |
| 479 | 479 | |
| 480 | −#define HWRM_CMD_TIMEOUT 500 | |
| 480 | +#define DFLT_HWRM_CMD_TIMEOUT 500 | |
| 481 | +#define HWRM_CMD_TIMEOUT (bp->hwrm_cmd_timeout) | |
| 481 | 482 | #define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4) |
| 482 | 483 | #define HWRM_RESP_ERR_CODE_MASK 0xffff |
| 484 | +#define HWRM_RESP_LEN_OFFSET 4 | |
| 483 | 485 | #define HWRM_RESP_LEN_MASK 0xffff0000 |
| 484 | 486 | #define HWRM_RESP_LEN_SFT 16 |
| 485 | 487 | #define HWRM_RESP_VALID_MASK 0xff000000 |
| 488 | +#define HWRM_SEQ_ID_INVALID -1 | |
| 486 | 489 | #define BNXT_HWRM_REQ_MAX_SIZE 128 |
| 487 | 490 | #define BNXT_HWRM_REQS_PER_PAGE (BNXT_PAGE_SIZE / \ |
| 488 | 491 | BNXT_HWRM_REQ_MAX_SIZE) |
| @@ -644,19 +647,6 @@ struct bnxt_irq { · 155 unmodified lines | ||
| 644 | 647 | |
| 645 | 648 | #define INVALID_STATS_CTX_ID -1 |
| 646 | 649 | |
| 647 | −struct hwrm_cmd_req_hdr { | |
| 648 | −#define HWRM_CMPL_RING_MASK 0xffff0000 | |
| 649 | −#define HWRM_CMPL_RING_SFT 16 | |
| 650 | − __le32 cmpl_ring_req_type; | |
| 651 | −#define HWRM_SEQ_ID_MASK 0xffff | |
| 652 | −#define HWRM_SEQ_ID_INVALID -1 | |
| 653 | −#define HWRM_RESP_LEN_OFFSET 4 | |
| 654 | −#define HWRM_TARGET_FID_MASK 0xffff0000 | |
| 655 | −#define HWRM_TARGET_FID_SFT 16 | |
| 656 | − __le32 target_id_seq_id; | |
| 657 | − __le64 resp_addr; | |
| 658 | −}; | |
| 659 | − | |
| 660 | 650 | struct bnxt_ring_grp_info { |
| 661 | 651 | u16 fw_stats_ctx; |
| 662 | 652 | u16 fw_grp_id; |
| @@ -767,10 +757,6 @@ struct bnxt_ntuple_filter { · 104 unmodified lines | ||
| 767 | 757 | #define BNXT_FLTR_UPDATE 1 |
| 768 | 758 | }; |
| 769 | 759 | |
| 770 | −#define BNXT_ALL_COPPER_ETHTOOL_SPEED \ | |
| 771 | − (ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full | \ | |
| 772 | − ADVERTISED_10000baseT_Full) | |
| 773 | − | |
| 774 | 760 | struct bnxt_link_info { |
| 775 | 761 | u8 media_type; |
| 776 | 762 | u8 transceiver; |
| @@ -790,6 +776,7 @@ struct bnxt_link_info { · 13 unmodified lines | ||
| 790 | 776 | #define BNXT_LINK_PAUSE_RX PORT_PHY_QCFG_RESP_PAUSE_RX |
| 791 | 777 | #define BNXT_LINK_PAUSE_BOTH (PORT_PHY_QCFG_RESP_PAUSE_RX | \ |
| 792 | 778 | PORT_PHY_QCFG_RESP_PAUSE_TX) |
| 779 | + u8 lp_pause; | |
| 793 | 780 | u8 auto_pause_setting; |
| 794 | 781 | u8 force_pause_setting; |
| 795 | 782 | u8 duplex_setting; |
| @@ -824,6 +811,7 @@ struct bnxt_link_info { · 28 unmodified lines | ||
| 824 | 811 | #define BNXT_LINK_SPEED_MSK_25GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_25GB |
| 825 | 812 | #define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB |
| 826 | 813 | #define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB |
| 814 | + u16 lp_auto_link_speeds; | |
| 827 | 815 | u16 auto_link_speed; |
| 828 | 816 | u16 force_link_speed; |
| 829 | 817 | u32 preemphasis; |
| @@ -885,6 +873,7 @@ struct bnxt { · 55 unmodified lines | ||
| 885 | 873 | #define BNXT_FLAG_MSIX_CAP 0x80 |
| 886 | 874 | #define BNXT_FLAG_RFS 0x100 |
| 887 | 875 | #define BNXT_FLAG_SHARED_RINGS 0x200 |
| 876 | + #define BNXT_FLAG_PORT_STATS 0x400 | |
| 888 | 877 | |
| 889 | 878 | #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \ |
| 890 | 879 | BNXT_FLAG_RFS | \ |
| @@ -937,7 +926,7 @@ struct bnxt { · 46 unmodified lines | ||
| 937 | 926 | struct bnxt_queue_info q_info[BNXT_MAX_QUEUE]; |
| 938 | 927 | |
| 939 | 928 | unsigned int current_interval; |
| 940 | −#define BNXT_TIMER_INTERVAL (HZ / 2) | |
| 929 | +#define BNXT_TIMER_INTERVAL HZ | |
| 941 | 930 | |
| 942 | 931 | struct timer_list timer; |
| 943 | 932 | |
| @@ -957,6 +946,14 @@ struct bnxt { · 13 unmodified lines | ||
| 957 | 946 | void *hwrm_dbg_resp_addr; |
| 958 | 947 | dma_addr_t hwrm_dbg_resp_dma_addr; |
| 959 | 948 | #define HWRM_DBG_REG_BUF_SIZE 128 |
| 949 | + | |
| 950 | + struct rx_port_stats *hw_rx_port_stats; | |
| 951 | + struct tx_port_stats *hw_tx_port_stats; | |
| 952 | + dma_addr_t hw_rx_port_stats_map; | |
| 953 | + dma_addr_t hw_tx_port_stats_map; | |
| 954 | + int hw_port_stats_size; | |
| 955 | + | |
| 956 | + int hwrm_cmd_timeout; | |
| 960 | 957 | struct mutex hwrm_cmd_lock; /* serialize hwrm messages */ |
| 961 | 958 | struct hwrm_ver_get_output ver_resp; |
| 962 | 959 | #define FW_VER_STR_LEN 32 |
| @@ -968,13 +965,17 @@ struct bnxt { · 5 unmodified lines | ||
| 968 | 965 | __le16 vxlan_fw_dst_port_id; |
| 969 | 966 | u8 nge_port_cnt; |
| 970 | 967 | __le16 nge_fw_dst_port_id; |
| 971 | − u16 coal_ticks; | |
| 972 | − u16 coal_ticks_irq; | |
| 973 | − u16 coal_bufs; | |
| 974 | − u16 coal_bufs_irq; | |
| 968 | + | |
| 969 | + u16 rx_coal_ticks; | |
| 970 | + u16 rx_coal_ticks_irq; | |
| 971 | + u16 rx_coal_bufs; | |
| 972 | + u16 rx_coal_bufs_irq; | |
| 973 | + u16 tx_coal_ticks; | |
| 974 | + u16 tx_coal_ticks_irq; | |
| 975 | + u16 tx_coal_bufs; | |
| 976 | + u16 tx_coal_bufs_irq; | |
| 975 | 977 | |
| 976 | 978 | #define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2) |
| 977 | −#define BNXT_COAL_TIMER_TO_USEC(x) ((x) * 2 / 25) | |
| 978 | 979 | |
| 979 | 980 | struct work_struct sp_task; |
| 980 | 981 | unsigned long sp_event; |
| @@ -986,6 +987,8 @@ struct bnxt { · 5 unmodified lines | ||
| 986 | 987 | #define BNXT_VXLAN_DEL_PORT_SP_EVENT 5 |
| 987 | 988 | #define BNXT_RESET_TASK_SP_EVENT 6 |
| 988 | 989 | #define BNXT_RST_RING_SP_EVENT 7 |
| 990 | +#define BNXT_HWRM_PF_UNLOAD_SP_EVENT 8 | |
| 991 | +#define BNXT_PERIODIC_STATS_SP_EVENT 9 | |
| 989 | 992 | |
| 990 | 993 | struct bnxt_pf_info pf; |
| 991 | 994 | #ifdef CONFIG_BNXT_SRIOV |
| @@ -1099,6 +1102,7 @@ void bnxt_set_ring_params(struct bnxt *); · 107 unmodified lines | ||
| 1099 | 1102 | void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16); |
| 1100 | 1103 | int _hwrm_send_message(struct bnxt *, void *, u32, int); |
| 1101 | 1104 | int hwrm_send_message(struct bnxt *, void *, u32, int); |
| 1105 | +int hwrm_send_message_silent(struct bnxt *, void *, u32, int); | |
| 1102 | 1106 | int bnxt_hwrm_set_coal(struct bnxt *); |
| 1103 | 1107 | int bnxt_hwrm_func_qcaps(struct bnxt *); |
| 1104 | 1108 | int bnxt_hwrm_set_pause(struct bnxt *); |
| @@ -7,6 +7,8 @@ · 6 unmodified lines | ||
| 7 | 7 | * the Free Software Foundation. |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | +#include <linux/ctype.h> | |
| 11 | +#include <linux/stringify.h> | |
| 10 | 12 | #include <linux/ethtool.h> |
| 11 | 13 | #include <linux/interrupt.h> |
| 12 | 14 | #include <linux/pci.h> |
| @@ -20,6 +22,8 @@ · 7 unmodified lines | ||
| 20 | 22 | #include "bnxt_fw_hdr.h" /* Firmware hdr constant and structure defs */ |
| 21 | 23 | #define FLASH_NVRAM_TIMEOUT ((HWRM_CMD_TIMEOUT) * 100) |
| 22 | 24 | |
| 25 | +static char *bnxt_get_pkgver(struct net_device *dev, char *buf, size_t buflen); | |
| 26 | + | |
| 23 | 27 | static u32 bnxt_get_msglevel(struct net_device *dev) |
| 24 | 28 | { |
| 25 | 29 | struct bnxt *bp = netdev_priv(dev); |
| @@ -41,12 +45,16 @@ static int bnxt_get_coalesce(struct net_device *dev, · 15 unmodified lines | ||
| 41 | 45 | |
| 42 | 46 | memset(coal, 0, sizeof(*coal)); |
| 43 | 47 | |
| 44 | − coal->rx_coalesce_usecs = | |
| 45 | − max_t(u16, BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks), 1); | |
| 46 | − coal->rx_max_coalesced_frames = bp->coal_bufs / 2; | |
| 47 | − coal->rx_coalesce_usecs_irq = | |
| 48 | − max_t(u16, BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks_irq), 1); | |
| 49 | − coal->rx_max_coalesced_frames_irq = bp->coal_bufs_irq / 2; | |
| 48 | + coal->rx_coalesce_usecs = bp->rx_coal_ticks; | |
| 49 | + /* 2 completion records per rx packet */ | |
| 50 | + coal->rx_max_coalesced_frames = bp->rx_coal_bufs / 2; | |
| 51 | + coal->rx_coalesce_usecs_irq = bp->rx_coal_ticks_irq; | |
| 52 | + coal->rx_max_coalesced_frames_irq = bp->rx_coal_bufs_irq / 2; | |
| 53 | + | |
| 54 | + coal->tx_coalesce_usecs = bp->tx_coal_ticks; | |
| 55 | + coal->tx_max_coalesced_frames = bp->tx_coal_bufs; | |
| 56 | + coal->tx_coalesce_usecs_irq = bp->tx_coal_ticks_irq; | |
| 57 | + coal->tx_max_coalesced_frames_irq = bp->tx_coal_bufs_irq; | |
| 50 | 58 | |
| 51 | 59 | return 0; |
| 52 | 60 | } |
| @@ -57,11 +65,16 @@ static int bnxt_set_coalesce(struct net_device *dev, · 4 unmodified lines | ||
| 57 | 65 | struct bnxt *bp = netdev_priv(dev); |
| 58 | 66 | int rc = 0; |
| 59 | 67 | |
| 60 | − bp->coal_ticks = BNXT_USEC_TO_COAL_TIMER(coal->rx_coalesce_usecs); | |
| 61 | − bp->coal_bufs = coal->rx_max_coalesced_frames * 2; | |
| 62 | − bp->coal_ticks_irq = | |
| 63 | − BNXT_USEC_TO_COAL_TIMER(coal->rx_coalesce_usecs_irq); | |
| 64 | − bp->coal_bufs_irq = coal->rx_max_coalesced_frames_irq * 2; | |
| 68 | + bp->rx_coal_ticks = coal->rx_coalesce_usecs; | |
| 69 | + /* 2 completion records per rx packet */ | |
| 70 | + bp->rx_coal_bufs = coal->rx_max_coalesced_frames * 2; | |
| 71 | + bp->rx_coal_ticks_irq = coal->rx_coalesce_usecs_irq; | |
| 72 | + bp->rx_coal_bufs_irq = coal->rx_max_coalesced_frames_irq * 2; | |
| 73 | + | |
| 74 | + bp->tx_coal_ticks = coal->tx_coalesce_usecs; | |
| 75 | + bp->tx_coal_bufs = coal->tx_max_coalesced_frames; | |
| 76 | + bp->tx_coal_ticks_irq = coal->tx_coalesce_usecs_irq; | |
| 77 | + bp->tx_coal_bufs_irq = coal->tx_max_coalesced_frames_irq; | |
| 65 | 78 | |
| 66 | 79 | if (netif_running(dev)) |
| 67 | 80 | rc = bnxt_hwrm_set_coal(bp); |
| @@ -71,13 +84,99 @@ static int bnxt_set_coalesce(struct net_device *dev, · 3 unmodified lines | ||
| 71 | 84 | |
| 72 | 85 | #define BNXT_NUM_STATS 21 |
| 73 | 86 | |
| 87 | +#define BNXT_RX_STATS_OFFSET(counter) \ | |
| 88 | + (offsetof(struct rx_port_stats, counter) / 8) | |
| 89 | + | |
| 90 | +#define BNXT_RX_STATS_ENTRY(counter) \ | |
| 91 | + { BNXT_RX_STATS_OFFSET(counter), __stringify(counter) } | |
| 92 | + | |
| 93 | +#define BNXT_TX_STATS_OFFSET(counter) \ | |
| 94 | + ((offsetof(struct tx_port_stats, counter) + \ | |
| 95 | + sizeof(struct rx_port_stats) + 512) / 8) | |
| 96 | + | |
| 97 | +#define BNXT_TX_STATS_ENTRY(counter) \ | |
| 98 | + { BNXT_TX_STATS_OFFSET(counter), __stringify(counter) } | |
| 99 | + | |
| 100 | +static const struct { | |
| 101 | + long offset; | |
| 102 | + char string[ETH_GSTRING_LEN]; | |
| 103 | +} bnxt_port_stats_arr[] = { | |
| 104 | + BNXT_RX_STATS_ENTRY(rx_64b_frames), | |
| 105 | + BNXT_RX_STATS_ENTRY(rx_65b_127b_frames), | |
| 106 | + BNXT_RX_STATS_ENTRY(rx_128b_255b_frames), | |
| 107 | + BNXT_RX_STATS_ENTRY(rx_256b_511b_frames), | |
| 108 | + BNXT_RX_STATS_ENTRY(rx_512b_1023b_frames), | |
| 109 | + BNXT_RX_STATS_ENTRY(rx_1024b_1518_frames), | |
| 110 | + BNXT_RX_STATS_ENTRY(rx_good_vlan_frames), | |
| 111 | + BNXT_RX_STATS_ENTRY(rx_1519b_2047b_frames), | |
| 112 | + BNXT_RX_STATS_ENTRY(rx_2048b_4095b_frames), | |
| 113 | + BNXT_RX_STATS_ENTRY(rx_4096b_9216b_frames), | |
| 114 | + BNXT_RX_STATS_ENTRY(rx_9217b_16383b_frames), | |
| 115 | + BNXT_RX_STATS_ENTRY(rx_total_frames), | |
| 116 | + BNXT_RX_STATS_ENTRY(rx_ucast_frames), | |
| 117 | + BNXT_RX_STATS_ENTRY(rx_mcast_frames), | |
| 118 | + BNXT_RX_STATS_ENTRY(rx_bcast_frames), | |
| 119 | + BNXT_RX_STATS_ENTRY(rx_fcs_err_frames), | |
| 120 | + BNXT_RX_STATS_ENTRY(rx_ctrl_frames), | |
| 121 | + BNXT_RX_STATS_ENTRY(rx_pause_frames), | |
| 122 | + BNXT_RX_STATS_ENTRY(rx_pfc_frames), | |
| 123 | + BNXT_RX_STATS_ENTRY(rx_align_err_frames), | |
| 124 | + BNXT_RX_STATS_ENTRY(rx_ovrsz_frames), | |
| 125 | + BNXT_RX_STATS_ENTRY(rx_jbr_frames), | |
| 126 | + BNXT_RX_STATS_ENTRY(rx_mtu_err_frames), | |
| 127 | + BNXT_RX_STATS_ENTRY(rx_tagged_frames), | |
| 128 | + BNXT_RX_STATS_ENTRY(rx_double_tagged_frames), | |
| 129 | + BNXT_RX_STATS_ENTRY(rx_good_frames), | |
| 130 | + BNXT_RX_STATS_ENTRY(rx_undrsz_frames), | |
| 131 | + BNXT_RX_STATS_ENTRY(rx_eee_lpi_events), | |
| 132 | + BNXT_RX_STATS_ENTRY(rx_eee_lpi_duration), | |
| 133 | + BNXT_RX_STATS_ENTRY(rx_bytes), | |
| 134 | + BNXT_RX_STATS_ENTRY(rx_runt_bytes), | |
| 135 | + BNXT_RX_STATS_ENTRY(rx_runt_frames), | |
| 136 | + | |
| 137 | + BNXT_TX_STATS_ENTRY(tx_64b_frames), | |
| 138 | + BNXT_TX_STATS_ENTRY(tx_65b_127b_frames), | |
| 139 | + BNXT_TX_STATS_ENTRY(tx_128b_255b_frames), | |
| 140 | + BNXT_TX_STATS_ENTRY(tx_256b_511b_frames), | |
| 141 | + BNXT_TX_STATS_ENTRY(tx_512b_1023b_frames), | |
| 142 | + BNXT_TX_STATS_ENTRY(tx_1024b_1518_frames), | |
| 143 | + BNXT_TX_STATS_ENTRY(tx_good_vlan_frames), | |
| 144 | + BNXT_TX_STATS_ENTRY(tx_1519b_2047_frames), | |
| 145 | + BNXT_TX_STATS_ENTRY(tx_2048b_4095b_frames), | |
| 146 | + BNXT_TX_STATS_ENTRY(tx_4096b_9216b_frames), | |
| 147 | + BNXT_TX_STATS_ENTRY(tx_9217b_16383b_frames), | |
| 148 | + BNXT_TX_STATS_ENTRY(tx_good_frames), | |
| 149 | + BNXT_TX_STATS_ENTRY(tx_total_frames), | |
| 150 | + BNXT_TX_STATS_ENTRY(tx_ucast_frames), | |
| 151 | + BNXT_TX_STATS_ENTRY(tx_mcast_frames), | |
| 152 | + BNXT_TX_STATS_ENTRY(tx_bcast_frames), | |
| 153 | + BNXT_TX_STATS_ENTRY(tx_pause_frames), | |
| 154 | + BNXT_TX_STATS_ENTRY(tx_pfc_frames), | |
| 155 | + BNXT_TX_STATS_ENTRY(tx_jabber_frames), | |
| 156 | + BNXT_TX_STATS_ENTRY(tx_fcs_err_frames), | |
| 157 | + BNXT_TX_STATS_ENTRY(tx_err), | |
| 158 | + BNXT_TX_STATS_ENTRY(tx_fifo_underruns), | |
| 159 | + BNXT_TX_STATS_ENTRY(tx_eee_lpi_events), | |
| 160 | + BNXT_TX_STATS_ENTRY(tx_eee_lpi_duration), | |
| 161 | + BNXT_TX_STATS_ENTRY(tx_total_collisions), | |
| 162 | + BNXT_TX_STATS_ENTRY(tx_bytes), | |
| 163 | +}; | |
| 164 | + | |
| 165 | +#define BNXT_NUM_PORT_STATS ARRAY_SIZE(bnxt_port_stats_arr) | |
| 166 | + | |
| 74 | 167 | static int bnxt_get_sset_count(struct net_device *dev, int sset) |
| 75 | 168 | { |
| 76 | 169 | struct bnxt *bp = netdev_priv(dev); |
| 77 | 170 | |
| 78 | 171 | switch (sset) { |
| 79 | − case ETH_SS_STATS: | |
| 80 | − return BNXT_NUM_STATS * bp->cp_nr_rings; | |
| 172 | + case ETH_SS_STATS: { | |
| 173 | + int num_stats = BNXT_NUM_STATS * bp->cp_nr_rings; | |
| 174 | + | |
| 175 | + if (bp->flags & BNXT_FLAG_PORT_STATS) | |
| 176 | + num_stats += BNXT_NUM_PORT_STATS; | |
| 177 | + | |
| 178 | + return num_stats; | |
| 179 | + } | |
| 81 | 180 | default: |
| 82 | 181 | return -EOPNOTSUPP; |
| 83 | 182 | } |
| @@ -106,6 +205,14 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, · 22 unmodified lines | ||
| 106 | 205 | buf[j] = le64_to_cpu(hw_stats[k]); |
| 107 | 206 | buf[j++] = cpr->rx_l4_csum_errors; |
| 108 | 207 | } |
| 208 | + if (bp->flags & BNXT_FLAG_PORT_STATS) { | |
| 209 | + __le64 *port_stats = (__le64 *)bp->hw_rx_port_stats; | |
| 210 | + | |
| 211 | + for (i = 0; i < BNXT_NUM_PORT_STATS; i++, j++) { | |
| 212 | + buf[j] = le64_to_cpu(*(port_stats + | |
| 213 | + bnxt_port_stats_arr[i].offset)); | |
| 214 | + } | |
| 215 | + } | |
| 109 | 216 | } |
| 110 | 217 | |
| 111 | 218 | static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) |
| @@ -160,6 +267,12 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) · 48 unmodified lines | ||
| 160 | 267 | sprintf(buf, "[%d]: rx_l4_csum_errors", i); |
| 161 | 268 | buf += ETH_GSTRING_LEN; |
| 162 | 269 | } |
| 270 | + if (bp->flags & BNXT_FLAG_PORT_STATS) { | |
| 271 | + for (i = 0; i < BNXT_NUM_PORT_STATS; i++) { | |
| 272 | + strcpy(buf, bnxt_port_stats_arr[i].string); | |
| 273 | + buf += ETH_GSTRING_LEN; | |
| 274 | + } | |
| 275 | + } | |
| 163 | 276 | break; |
| 164 | 277 | default: |
| 165 | 278 | netdev_err(bp->dev, "bnxt_get_strings invalid request %x\n", |
| @@ -460,10 +573,20 @@ static void bnxt_get_drvinfo(struct net_device *dev, · 294 unmodified lines | ||
| 460 | 573 | struct ethtool_drvinfo *info) |
| 461 | 574 | { |
| 462 | 575 | struct bnxt *bp = netdev_priv(dev); |
| 576 | + char *pkglog; | |
| 577 | + char *pkgver = NULL; | |
| 463 | 578 | |
| 579 | + pkglog = kmalloc(BNX_PKG_LOG_MAX_LENGTH, GFP_KERNEL); | |
| 580 | + if (pkglog) | |
| 581 | + pkgver = bnxt_get_pkgver(dev, pkglog, BNX_PKG_LOG_MAX_LENGTH); | |
| 464 | 582 | strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); |
| 465 | 583 | strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); |
| 466 | − strlcpy(info->fw_version, bp->fw_ver_str, sizeof(info->fw_version)); | |
| 584 | + if (pkgver && *pkgver != 0 && isdigit(*pkgver)) | |
| 585 | + snprintf(info->fw_version, sizeof(info->fw_version) - 1, | |
| 586 | + "%s pkg %s", bp->fw_ver_str, pkgver); | |
| 587 | + else | |
| 588 | + strlcpy(info->fw_version, bp->fw_ver_str, | |
| 589 | + sizeof(info->fw_version)); | |
| 467 | 590 | strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info)); |
| 468 | 591 | info->n_stats = BNXT_NUM_STATS * bp->cp_nr_rings; |
| 469 | 592 | info->testinfo_len = BNXT_NUM_TESTS(bp); |
| @@ -471,30 +594,11 @@ static void bnxt_get_drvinfo(struct net_device *dev, · 1 unmodified line | ||
| 471 | 594 | info->eedump_len = 0; |
| 472 | 595 | /* TODO CHIMP FW: reg dump details */ |
| 473 | 596 | info->regdump_len = 0; |
| 597 | + kfree(pkglog); | |
| 474 | 598 | } |
| 475 | 599 | |
| 476 | −static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info) | |
| 600 | +static u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause) | |
| 477 | 601 | { |
| 478 | − u16 fw_speeds = link_info->support_speeds; | |
| 479 | − u32 speed_mask = 0; | |
| 480 | − | |
| 481 | − if (fw_speeds & BNXT_LINK_SPEED_MSK_100MB) | |
| 482 | − speed_mask |= SUPPORTED_100baseT_Full; | |
| 483 | − if (fw_speeds & BNXT_LINK_SPEED_MSK_1GB) | |
| 484 | − speed_mask |= SUPPORTED_1000baseT_Full; | |
| 485 | − if (fw_speeds & BNXT_LINK_SPEED_MSK_2_5GB) | |
| 486 | − speed_mask |= SUPPORTED_2500baseX_Full; | |
| 487 | − if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB) | |
| 488 | − speed_mask |= SUPPORTED_10000baseT_Full; | |
| 489 | − if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) | |
| 490 | − speed_mask |= SUPPORTED_40000baseCR4_Full; | |
| 491 | − | |
| 492 | − return speed_mask; | |
| 493 | −} | |
| 494 | − | |
| 495 | −static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info) | |
| 496 | −{ | |
| 497 | − u16 fw_speeds = link_info->auto_link_speeds; | |
| 498 | 602 | u32 speed_mask = 0; |
| 499 | 603 | |
| 500 | 604 | /* TODO: support 25GB, 40GB, 50GB with different cable type */ |
| @@ -509,9 +613,48 @@ static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info) · 8 unmodified lines | ||
| 509 | 613 | speed_mask |= ADVERTISED_10000baseT_Full; |
| 510 | 614 | if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) |
| 511 | 615 | speed_mask |= ADVERTISED_40000baseCR4_Full; |
| 616 | + | |
| 617 | + if ((fw_pause & BNXT_LINK_PAUSE_BOTH) == BNXT_LINK_PAUSE_BOTH) | |
| 618 | + speed_mask |= ADVERTISED_Pause; | |
| 619 | + else if (fw_pause & BNXT_LINK_PAUSE_TX) | |
| 620 | + speed_mask |= ADVERTISED_Asym_Pause; | |
| 621 | + else if (fw_pause & BNXT_LINK_PAUSE_RX) | |
| 622 | + speed_mask |= ADVERTISED_Pause | ADVERTISED_Asym_Pause; | |
| 623 | + | |
| 512 | 624 | return speed_mask; |
| 513 | 625 | } |
| 514 | 626 | |
| 627 | +static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info) | |
| 628 | +{ | |
| 629 | + u16 fw_speeds = link_info->auto_link_speeds; | |
| 630 | + u8 fw_pause = 0; | |
| 631 | + | |
| 632 | + if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) | |
| 633 | + fw_pause = link_info->auto_pause_setting; | |
| 634 | + | |
| 635 | + return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause); | |
| 636 | +} | |
| 637 | + | |
| 638 | +static u32 bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info) | |
| 639 | +{ | |
| 640 | + u16 fw_speeds = link_info->lp_auto_link_speeds; | |
| 641 | + u8 fw_pause = 0; | |
| 642 | + | |
| 643 | + if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) | |
| 644 | + fw_pause = link_info->lp_pause; | |
| 645 | + | |
| 646 | + return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause); | |
| 647 | +} | |
| 648 | + | |
| 649 | +static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info) | |
| 650 | +{ | |
| 651 | + u16 fw_speeds = link_info->support_speeds; | |
| 652 | + u32 supported; | |
| 653 | + | |
| 654 | + supported = _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0); | |
| 655 | + return supported | SUPPORTED_Pause | SUPPORTED_Asym_Pause; | |
| 656 | +} | |
| 657 | + | |
| 515 | 658 | u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed) |
| 516 | 659 | { |
| 517 | 660 | switch (fw_link_speed) { |
| @@ -543,7 +686,6 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) · 25 unmodified lines | ||
| 543 | 686 | u16 ethtool_speed; |
| 544 | 687 | |
| 545 | 688 | cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info); |
| 546 | − cmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; | |
| 547 | 689 | |
| 548 | 690 | if (link_info->auto_link_speeds) |
| 549 | 691 | cmd->supported |= SUPPORTED_Autoneg; |
| @@ -553,21 +695,13 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) · 3 unmodified lines | ||
| 553 | 695 | bnxt_fw_to_ethtool_advertised_spds(link_info); |
| 554 | 696 | cmd->advertising |= ADVERTISED_Autoneg; |
| 555 | 697 | cmd->autoneg = AUTONEG_ENABLE; |
| 698 | + if (link_info->phy_link_status == BNXT_LINK_LINK) | |
| 699 | + cmd->lp_advertising = | |
| 700 | + bnxt_fw_to_ethtool_lp_adv(link_info); | |
| 556 | 701 | } else { |
| 557 | 702 | cmd->autoneg = AUTONEG_DISABLE; |
| 558 | 703 | cmd->advertising = 0; |
| 559 | 704 | } |
| 560 | − if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) { | |
| 561 | − if ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) == | |
| 562 | − BNXT_LINK_PAUSE_BOTH) { | |
| 563 | − cmd->advertising |= ADVERTISED_Pause; | |
| 564 | − } else { | |
| 565 | − cmd->advertising |= ADVERTISED_Asym_Pause; | |
| 566 | − if (link_info->auto_pause_setting & | |
| 567 | − BNXT_LINK_PAUSE_RX) | |
| 568 | − cmd->advertising |= ADVERTISED_Pause; | |
| 569 | − } | |
| 570 | − } | |
| 571 | 705 | |
| 572 | 706 | cmd->port = PORT_NONE; |
| 573 | 707 | if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { |
| @@ -663,16 +797,10 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) · 89 unmodified lines | ||
| 663 | 797 | return rc; |
| 664 | 798 | |
| 665 | 799 | if (cmd->autoneg == AUTONEG_ENABLE) { |
| 666 | − if (link_info->media_type != PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { | |
| 667 | − netdev_err(dev, "Media type doesn't support autoneg\n"); | |
| 668 | − rc = -EINVAL; | |
| 669 | − goto set_setting_exit; | |
| 670 | − } | |
| 671 | − if (cmd->advertising & ~(BNXT_ALL_COPPER_ETHTOOL_SPEED | | |
| 672 | − ADVERTISED_Autoneg | | |
| 673 | − ADVERTISED_TP | | |
| 674 | − ADVERTISED_Pause | | |
| 675 | − ADVERTISED_Asym_Pause)) { | |
| 800 | + u32 supported_spds = bnxt_fw_to_ethtool_support_spds(link_info); | |
| 801 | + | |
| 802 | + if (cmd->advertising & ~(supported_spds | ADVERTISED_Autoneg | | |
| 803 | + ADVERTISED_TP | ADVERTISED_FIBRE)) { | |
| 676 | 804 | netdev_err(dev, "Unsupported advertising mask (adv: 0x%x)\n", |
| 677 | 805 | cmd->advertising); |
| 678 | 806 | rc = -EINVAL; |
| @@ -727,8 +855,10 @@ static void bnxt_get_pauseparam(struct net_device *dev, · 48 unmodified lines | ||
| 727 | 855 | if (BNXT_VF(bp)) |
| 728 | 856 | return; |
| 729 | 857 | epause->autoneg = !!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL); |
| 730 | − epause->rx_pause = ((link_info->pause & BNXT_LINK_PAUSE_RX) != 0); | |
| 731 | − epause->tx_pause = ((link_info->pause & BNXT_LINK_PAUSE_TX) != 0); | |
| 858 | + epause->rx_pause = | |
| 859 | + ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_RX) != 0); | |
| 860 | + epause->tx_pause = | |
| 861 | + ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_TX) != 0); | |
| 732 | 862 | } |
| 733 | 863 | |
| 734 | 864 | static int bnxt_set_pauseparam(struct net_device *dev, |
| @@ -1102,6 +1232,85 @@ static int bnxt_get_nvram_item(struct net_device *dev, u32 index, u32 offset, · 367 unmodified lines | ||
| 1102 | 1232 | return rc; |
| 1103 | 1233 | } |
| 1104 | 1234 | |
| 1235 | +static int bnxt_find_nvram_item(struct net_device *dev, u16 type, u16 ordinal, | |
| 1236 | + u16 ext, u16 *index, u32 *item_length, | |
| 1237 | + u32 *data_length) | |
| 1238 | +{ | |
| 1239 | + struct bnxt *bp = netdev_priv(dev); | |
| 1240 | + int rc; | |
| 1241 | + struct hwrm_nvm_find_dir_entry_input req = {0}; | |
| 1242 | + struct hwrm_nvm_find_dir_entry_output *output = bp->hwrm_cmd_resp_addr; | |
| 1243 | + | |
| 1244 | + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_FIND_DIR_ENTRY, -1, -1); | |
| 1245 | + req.enables = 0; | |
| 1246 | + req.dir_idx = 0; | |
| 1247 | + req.dir_type = cpu_to_le16(type); | |
| 1248 | + req.dir_ordinal = cpu_to_le16(ordinal); | |
| 1249 | + req.dir_ext = cpu_to_le16(ext); | |
| 1250 | + req.opt_ordinal = NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_EQ; | |
| 1251 | + rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); | |
| 1252 | + if (rc == 0) { | |
| 1253 | + if (index) | |
| 1254 | + *index = le16_to_cpu(output->dir_idx); | |
| 1255 | + if (item_length) | |
| 1256 | + *item_length = le32_to_cpu(output->dir_item_length); | |
| 1257 | + if (data_length) | |
| 1258 | + *data_length = le32_to_cpu(output->dir_data_length); | |
| 1259 | + } | |
| 1260 | + return rc; | |
| 1261 | +} | |
| 1262 | + | |
| 1263 | +static char *bnxt_parse_pkglog(int desired_field, u8 *data, size_t datalen) | |
| 1264 | +{ | |
| 1265 | + char *retval = NULL; | |
| 1266 | + char *p; | |
| 1267 | + char *value; | |
| 1268 | + int field = 0; | |
| 1269 | + | |
| 1270 | + if (datalen < 1) | |
| 1271 | + return NULL; | |
| 1272 | + /* null-terminate the log data (removing last '\n'): */ | |
| 1273 | + data[datalen - 1] = 0; | |
| 1274 | + for (p = data; *p != 0; p++) { | |
| 1275 | + field = 0; | |
| 1276 | + retval = NULL; | |
| 1277 | + while (*p != 0 && *p != '\n') { | |
| 1278 | + value = p; | |
| 1279 | + while (*p != 0 && *p != '\t' && *p != '\n') | |
| 1280 | + p++; | |
| 1281 | + if (field == desired_field) | |
| 1282 | + retval = value; | |
| 1283 | + if (*p != '\t') | |
| 1284 | + break; | |
| 1285 | + *p = 0; | |
| 1286 | + field++; | |
| 1287 | + p++; | |
| 1288 | + } | |
| 1289 | + if (*p == 0) | |
| 1290 | + break; | |
| 1291 | + *p = 0; | |
| 1292 | + } | |
| 1293 | + return retval; | |
| 1294 | +} | |
| 1295 | + | |
| 1296 | +static char *bnxt_get_pkgver(struct net_device *dev, char *buf, size_t buflen) | |
| 1297 | +{ | |
| 1298 | + u16 index = 0; | |
| 1299 | + u32 datalen; | |
| 1300 | + | |
| 1301 | + if (bnxt_find_nvram_item(dev, BNX_DIR_TYPE_PKG_LOG, | |
| 1302 | + BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE, | |
| 1303 | + &index, NULL, &datalen) != 0) | |
| 1304 | + return NULL; | |
| 1305 | + | |
| 1306 | + memset(buf, 0, buflen); | |
| 1307 | + if (bnxt_get_nvram_item(dev, index, 0, datalen, buf) != 0) | |
| 1308 | + return NULL; | |
| 1309 | + | |
| 1310 | + return bnxt_parse_pkglog(BNX_PKG_LOG_FIELD_IDX_PKG_VERSION, buf, | |
| 1311 | + datalen); | |
| 1312 | +} | |
| 1313 | + | |
| 1105 | 1314 | static int bnxt_get_eeprom(struct net_device *dev, |
| 1106 | 1315 | struct ethtool_eeprom *eeprom, |
| 1107 | 1316 | u8 *data) |
| @@ -50,10 +50,24 @@ enum bnxt_nvm_directory_type { · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | #define BNX_DIR_ORDINAL_FIRST 0 |
| 52 | 52 | |
| 53 | +#define BNX_DIR_EXT_NONE 0 | |
| 53 | 54 | #define BNX_DIR_EXT_INACTIVE (1 << 0) |
| 54 | 55 | #define BNX_DIR_EXT_UPDATE (1 << 1) |
| 55 | 56 | |
| 57 | +#define BNX_DIR_ATTR_NONE 0 | |
| 56 | 58 | #define BNX_DIR_ATTR_NO_CHKSUM (1 << 0) |
| 57 | 59 | #define BNX_DIR_ATTR_PROP_STREAM (1 << 1) |
| 58 | 60 | |
| 61 | +#define BNX_PKG_LOG_MAX_LENGTH 4096 | |
| 62 | + | |
| 63 | +enum bnxnvm_pkglog_field_index { | |
| 64 | + BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0, | |
| 65 | + BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1, | |
| 66 | + BNX_PKG_LOG_FIELD_IDX_PKG_VERSION = 2, | |
| 67 | + BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3, | |
| 68 | + BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM = 4, | |
| 69 | + BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5, | |
| 70 | + BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6 | |
| 71 | +}; | |
| 72 | + | |
| 59 | 73 | #endif /* Don't add anything after this line */ |
| @@ -522,6 +522,46 @@ err_out1: · 521 unmodified lines | ||
| 522 | 522 | return rc; |
| 523 | 523 | } |
| 524 | 524 | |
| 525 | +static int bnxt_hwrm_fwd_async_event_cmpl(struct bnxt *bp, | |
| 526 | + struct bnxt_vf_info *vf, | |
| 527 | + u16 event_id) | |
| 528 | +{ | |
| 529 | + int rc = 0; | |
| 530 | + struct hwrm_fwd_async_event_cmpl_input req = {0}; | |
| 531 | + struct hwrm_fwd_async_event_cmpl_output *resp = bp->hwrm_cmd_resp_addr; | |
| 532 | + struct hwrm_async_event_cmpl *async_cmpl; | |
| 533 | + | |
| 534 | + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FWD_ASYNC_EVENT_CMPL, -1, -1); | |
| 535 | + if (vf) | |
| 536 | + req.encap_async_event_target_id = cpu_to_le16(vf->fw_fid); | |
| 537 | + else | |
| 538 | + /* broadcast this async event to all VFs */ | |
| 539 | + req.encap_async_event_target_id = cpu_to_le16(0xffff); | |
| 540 | + async_cmpl = (struct hwrm_async_event_cmpl *)req.encap_async_event_cmpl; | |
| 541 | + async_cmpl->type = | |
| 542 | + cpu_to_le16(HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT); | |
| 543 | + async_cmpl->event_id = cpu_to_le16(event_id); | |
| 544 | + | |
| 545 | + mutex_lock(&bp->hwrm_cmd_lock); | |
| 546 | + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); | |
| 547 | + | |
| 548 | + if (rc) { | |
| 549 | + netdev_err(bp->dev, "hwrm_fwd_async_event_cmpl failed. rc:%d\n", | |
| 550 | + rc); | |
| 551 | + goto fwd_async_event_cmpl_exit; | |
| 552 | + } | |
| 553 | + | |
| 554 | + if (resp->error_code) { | |
| 555 | + netdev_err(bp->dev, "hwrm_fwd_async_event_cmpl error %d\n", | |
| 556 | + resp->error_code); | |
| 557 | + rc = -1; | |
| 558 | + } | |
| 559 | + | |
| 560 | +fwd_async_event_cmpl_exit: | |
| 561 | + mutex_unlock(&bp->hwrm_cmd_lock); | |
| 562 | + return rc; | |
| 563 | +} | |
| 564 | + | |
| 525 | 565 | void bnxt_sriov_disable(struct bnxt *bp) |
| 526 | 566 | { |
| 527 | 567 | u16 num_vfs = pci_num_vf(bp->pdev); |
| @@ -530,6 +570,9 @@ void bnxt_sriov_disable(struct bnxt *bp) · 2 unmodified lines | ||
| 530 | 570 | return; |
| 531 | 571 | |
| 532 | 572 | if (pci_vfs_assigned(bp->pdev)) { |
| 573 | + bnxt_hwrm_fwd_async_event_cmpl( | |
| 574 | + bp, NULL, | |
| 575 | + HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD); | |
| 533 | 576 | netdev_warn(bp->dev, "Unable to free %d VFs because some are assigned to VMs.\n", |
| 534 | 577 | num_vfs); |
| 535 | 578 | } else { |
| @@ -758,8 +801,8 @@ static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf) · 222 unmodified lines | ||
| 758 | 801 | static int bnxt_vf_req_validate_snd(struct bnxt *bp, struct bnxt_vf_info *vf) |
| 759 | 802 | { |
| 760 | 803 | int rc = 0; |
| 761 | − struct hwrm_cmd_req_hdr *encap_req = vf->hwrm_cmd_req_addr; | |
| 762 | − u32 req_type = le32_to_cpu(encap_req->cmpl_ring_req_type) & 0xffff; | |
| 804 | + struct input *encap_req = vf->hwrm_cmd_req_addr; | |
| 805 | + u32 req_type = le16_to_cpu(encap_req->req_type); | |
| 763 | 806 | |
| 764 | 807 | switch (req_type) { |
| 765 | 808 | case HWRM_CFA_L2_FILTER_ALLOC: |
| @@ -809,13 +852,19 @@ void bnxt_update_vf_mac(struct bnxt *bp) · 43 unmodified lines | ||
| 809 | 852 | if (_hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT)) |
| 810 | 853 | goto update_vf_mac_exit; |
| 811 | 854 | |
| 812 | − if (!is_valid_ether_addr(resp->perm_mac_address)) | |
| 813 | − goto update_vf_mac_exit; | |
| 814 | − | |
| 855 | + /* Store MAC address from the firmware. There are 2 cases: | |
| 856 | + * 1. MAC address is valid. It is assigned from the PF and we | |
| 857 | + * need to override the current VF MAC address with it. | |
| 858 | + * 2. MAC address is zero. The VF will use a random MAC address by | |
| 859 | + * default but the stored zero MAC will allow the VF user to change | |
| 860 | + * the random MAC address using ndo_set_mac_address() if he wants. | |
| 861 | + */ | |
| 815 | 862 | if (!ether_addr_equal(resp->perm_mac_address, bp->vf.mac_addr)) |
| 816 | 863 | memcpy(bp->vf.mac_addr, resp->perm_mac_address, ETH_ALEN); |
| 817 | − /* overwrite netdev dev_adr with admin VF MAC */ | |
| 818 | − memcpy(bp->dev->dev_addr, bp->vf.mac_addr, ETH_ALEN); | |
| 864 | + | |
| 865 | + /* overwrite netdev dev_addr with admin VF MAC */ | |
| 866 | + if (is_valid_ether_addr(bp->vf.mac_addr)) | |
| 867 | + memcpy(bp->dev->dev_addr, bp->vf.mac_addr, ETH_ALEN); | |
| 819 | 868 | update_vf_mac_exit: |
| 820 | 869 | mutex_unlock(&bp->hwrm_cmd_lock); |
| 821 | 870 | } |
| @@ -1197,7 +1197,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, · 1196 unmodified lines | ||
| 1197 | 1197 | dev->stats.tx_bytes += tx_cb_ptr->skb->len; |
| 1198 | 1198 | dma_unmap_single(&dev->dev, |
| 1199 | 1199 | dma_unmap_addr(tx_cb_ptr, dma_addr), |
| 1200 | − tx_cb_ptr->skb->len, | |
| 1200 | + dma_unmap_len(tx_cb_ptr, dma_len), | |
| 1201 | 1201 | DMA_TO_DEVICE); |
| 1202 | 1202 | bcmgenet_free_cb(tx_cb_ptr); |
| 1203 | 1203 | } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) { |
| @@ -1308,7 +1308,7 @@ static int bcmgenet_xmit_single(struct net_device *dev, · 104 unmodified lines | ||
| 1308 | 1308 | } |
| 1309 | 1309 | |
| 1310 | 1310 | dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping); |
| 1311 | − dma_unmap_len_set(tx_cb_ptr, dma_len, skb->len); | |
| 1311 | + dma_unmap_len_set(tx_cb_ptr, dma_len, skb_len); | |
| 1312 | 1312 | length_status = (skb_len << DMA_BUFLENGTH_SHIFT) | dma_desc_flags | |
| 1313 | 1313 | (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT) | |
| 1314 | 1314 | DMA_TX_APPEND_CRC; |
| @@ -58,6 +58,9 @@ · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | #define GEM_MTU_MIN_SIZE 68 |
| 60 | 60 | |
| 61 | +#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) | |
| 62 | +#define MACB_WOL_ENABLED (0x1 << 1) | |
| 63 | + | |
| 61 | 64 | /* |
| 62 | 65 | * Graceful stop timeouts in us. We should allow up to |
| 63 | 66 | * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions) |
| @@ -2124,6 +2127,39 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs, · 2060 unmodified lines | ||
| 2124 | 2127 | } |
| 2125 | 2128 | } |
| 2126 | 2129 | |
| 2130 | +static void macb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |
| 2131 | +{ | |
| 2132 | + struct macb *bp = netdev_priv(netdev); | |
| 2133 | + | |
| 2134 | + wol->supported = 0; | |
| 2135 | + wol->wolopts = 0; | |
| 2136 | + | |
| 2137 | + if (bp->wol & MACB_WOL_HAS_MAGIC_PACKET) { | |
| 2138 | + wol->supported = WAKE_MAGIC; | |
| 2139 | + | |
| 2140 | + if (bp->wol & MACB_WOL_ENABLED) | |
| 2141 | + wol->wolopts |= WAKE_MAGIC; | |
| 2142 | + } | |
| 2143 | +} | |
| 2144 | + | |
| 2145 | +static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |
| 2146 | +{ | |
| 2147 | + struct macb *bp = netdev_priv(netdev); | |
| 2148 | + | |
| 2149 | + if (!(bp->wol & MACB_WOL_HAS_MAGIC_PACKET) || | |
| 2150 | + (wol->wolopts & ~WAKE_MAGIC)) | |
| 2151 | + return -EOPNOTSUPP; | |
| 2152 | + | |
| 2153 | + if (wol->wolopts & WAKE_MAGIC) | |
| 2154 | + bp->wol |= MACB_WOL_ENABLED; | |
| 2155 | + else | |
| 2156 | + bp->wol &= ~MACB_WOL_ENABLED; | |
| 2157 | + | |
| 2158 | + device_set_wakeup_enable(&bp->pdev->dev, bp->wol & MACB_WOL_ENABLED); | |
| 2159 | + | |
| 2160 | + return 0; | |
| 2161 | +} | |
| 2162 | + | |
| 2127 | 2163 | static const struct ethtool_ops macb_ethtool_ops = { |
| 2128 | 2164 | .get_settings = macb_get_settings, |
| 2129 | 2165 | .set_settings = macb_set_settings, |
| @@ -2131,6 +2167,8 @@ static const struct ethtool_ops macb_ethtool_ops = { · 1 unmodified line | ||
| 2131 | 2167 | .get_regs = macb_get_regs, |
| 2132 | 2168 | .get_link = ethtool_op_get_link, |
| 2133 | 2169 | .get_ts_info = ethtool_op_get_ts_info, |
| 2170 | + .get_wol = macb_get_wol, | |
| 2171 | + .set_wol = macb_set_wol, | |
| 2134 | 2172 | }; |
| 2135 | 2173 | |
| 2136 | 2174 | static const struct ethtool_ops gem_ethtool_ops = { |
| @@ -2402,9 +2440,9 @@ static int macb_init(struct platform_device *pdev) · 265 unmodified lines | ||
| 2402 | 2440 | if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII) |
| 2403 | 2441 | val = GEM_BIT(RGMII); |
| 2404 | 2442 | else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII && |
| 2405 | − (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII)) | |
| 2443 | + (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII)) | |
| 2406 | 2444 | val = MACB_BIT(RMII); |
| 2407 | − else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII)) | |
| 2445 | + else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII)) | |
| 2408 | 2446 | val = MACB_BIT(MII); |
| 2409 | 2447 | |
| 2410 | 2448 | if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN) |
| @@ -2736,7 +2774,7 @@ static int at91ether_init(struct platform_device *pdev) · 325 unmodified lines | ||
| 2736 | 2774 | } |
| 2737 | 2775 | |
| 2738 | 2776 | static const struct macb_config at91sam9260_config = { |
| 2739 | − .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII, | |
| 2777 | + .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, | |
| 2740 | 2778 | .clk_init = macb_clk_init, |
| 2741 | 2779 | .init = macb_init, |
| 2742 | 2780 | }; |
| @@ -2749,21 +2787,22 @@ static const struct macb_config pc302gem_config = { · 6 unmodified lines | ||
| 2749 | 2787 | }; |
| 2750 | 2788 | |
| 2751 | 2789 | static const struct macb_config sama5d2_config = { |
| 2752 | − .caps = 0, | |
| 2790 | + .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, | |
| 2753 | 2791 | .dma_burst_length = 16, |
| 2754 | 2792 | .clk_init = macb_clk_init, |
| 2755 | 2793 | .init = macb_init, |
| 2756 | 2794 | }; |
| 2757 | 2795 | |
| 2758 | 2796 | static const struct macb_config sama5d3_config = { |
| 2759 | − .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE, | |
| 2797 | + .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE | |
| 2798 | + | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, | |
| 2760 | 2799 | .dma_burst_length = 16, |
| 2761 | 2800 | .clk_init = macb_clk_init, |
| 2762 | 2801 | .init = macb_init, |
| 2763 | 2802 | }; |
| 2764 | 2803 | |
| 2765 | 2804 | static const struct macb_config sama5d4_config = { |
| 2766 | − .caps = 0, | |
| 2805 | + .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, | |
| 2767 | 2806 | .dma_burst_length = 4, |
| 2768 | 2807 | .clk_init = macb_clk_init, |
| 2769 | 2808 | .init = macb_init, |
| @@ -2890,6 +2929,11 @@ static int macb_probe(struct platform_device *pdev) · 120 unmodified lines | ||
| 2890 | 2929 | if (macb_config) |
| 2891 | 2930 | bp->jumbo_max_len = macb_config->jumbo_max_len; |
| 2892 | 2931 | |
| 2932 | + bp->wol = 0; | |
| 2933 | + if (of_get_property(np, "magic-packet", NULL)) | |
| 2934 | + bp->wol |= MACB_WOL_HAS_MAGIC_PACKET; | |
| 2935 | + device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET); | |
| 2936 | + | |
| 2893 | 2937 | spin_lock_init(&bp->lock); |
| 2894 | 2938 | |
| 2895 | 2939 | /* setup capabilities */ |
| @@ -3006,9 +3050,15 @@ static int __maybe_unused macb_suspend(struct device *dev) · 110 unmodified lines | ||
| 3006 | 3050 | netif_carrier_off(netdev); |
| 3007 | 3051 | netif_device_detach(netdev); |
| 3008 | 3052 | |
| 3009 | − clk_disable_unprepare(bp->tx_clk); | |
| 3010 | − clk_disable_unprepare(bp->hclk); | |
| 3011 | − clk_disable_unprepare(bp->pclk); | |
| 3053 | + if (bp->wol & MACB_WOL_ENABLED) { | |
| 3054 | + macb_writel(bp, IER, MACB_BIT(WOL)); | |
| 3055 | + macb_writel(bp, WOL, MACB_BIT(MAG)); | |
| 3056 | + enable_irq_wake(bp->queues[0].irq); | |
| 3057 | + } else { | |
| 3058 | + clk_disable_unprepare(bp->tx_clk); | |
| 3059 | + clk_disable_unprepare(bp->hclk); | |
| 3060 | + clk_disable_unprepare(bp->pclk); | |
| 3061 | + } | |
| 3012 | 3062 | |
| 3013 | 3063 | return 0; |
| 3014 | 3064 | } |
| @@ -3019,9 +3069,15 @@ static int __maybe_unused macb_resume(struct device *dev) · 4 unmodified lines | ||
| 3019 | 3069 | struct net_device *netdev = platform_get_drvdata(pdev); |
| 3020 | 3070 | struct macb *bp = netdev_priv(netdev); |
| 3021 | 3071 | |
| 3022 | − clk_prepare_enable(bp->pclk); | |
| 3023 | − clk_prepare_enable(bp->hclk); | |
| 3024 | − clk_prepare_enable(bp->tx_clk); | |
| 3072 | + if (bp->wol & MACB_WOL_ENABLED) { | |
| 3073 | + macb_writel(bp, IDR, MACB_BIT(WOL)); | |
| 3074 | + macb_writel(bp, WOL, 0); | |
| 3075 | + disable_irq_wake(bp->queues[0].irq); | |
| 3076 | + } else { | |
| 3077 | + clk_prepare_enable(bp->pclk); | |
| 3078 | + clk_prepare_enable(bp->hclk); | |
| 3079 | + clk_prepare_enable(bp->tx_clk); | |
| 3080 | + } | |
| 3025 | 3081 | |
| 3026 | 3082 | netif_device_attach(netdev); |
| 3027 | 3083 | |
| @@ -312,6 +312,8 @@ · 311 unmodified lines | ||
| 312 | 312 | #define MACB_PFR_SIZE 1 |
| 313 | 313 | #define MACB_PTZ_OFFSET 13 /* Enable pause time zero interrupt */ |
| 314 | 314 | #define MACB_PTZ_SIZE 1 |
| 315 | +#define MACB_WOL_OFFSET 14 /* Enable wake-on-lan interrupt */ | |
| 316 | +#define MACB_WOL_SIZE 1 | |
| 315 | 317 | |
| 316 | 318 | /* Bitfields in MAN */ |
| 317 | 319 | #define MACB_DATA_OFFSET 0 /* data */ |
| @@ -398,7 +400,7 @@ · 80 unmodified lines | ||
| 398 | 400 | /* Capability mask bits */ |
| 399 | 401 | #define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x00000001 |
| 400 | 402 | #define MACB_CAPS_USRIO_HAS_CLKEN 0x00000002 |
| 401 | −#define MACB_CAPS_USRIO_DEFAULT_IS_MII 0x00000004 | |
| 403 | +#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII 0x00000004 | |
| 402 | 404 | #define MACB_CAPS_NO_GIGABIT_HALF 0x00000008 |
| 403 | 405 | #define MACB_CAPS_USRIO_DISABLED 0x00000010 |
| 404 | 406 | #define MACB_CAPS_FIFO_MODE 0x10000000 |
| @@ -842,6 +844,8 @@ struct macb { · 437 unmodified lines | ||
| 842 | 844 | |
| 843 | 845 | unsigned int rx_frm_len_mask; |
| 844 | 846 | unsigned int jumbo_max_len; |
| 847 | + | |
| 848 | + u32 wol; | |
| 845 | 849 | }; |
| 846 | 850 | |
| 847 | 851 | static inline bool macb_is_gem(struct macb *bp) |
| @@ -35,7 +35,7 @@ config THUNDER_NIC_BGX · 34 unmodified lines | ||
| 35 | 35 | tristate "Thunder MAC interface driver (BGX)" |
| 36 | 36 | depends on 64BIT |
| 37 | 37 | select PHYLIB |
| 38 | − select MDIO_OCTEON | |
| 38 | + select MDIO_THUNDER | |
| 39 | 39 | ---help--- |
| 40 | 40 | This driver supports programming and controlling of MAC |
| 41 | 41 | interface from NIC physical function driver. |
| @@ -53,4 +53,15 @@ config LIQUIDIO · 11 unmodified lines | ||
| 53 | 53 | To compile this driver as a module, choose M here: the module |
| 54 | 54 | will be called liquidio. This is recommended. |
| 55 | 55 | |
| 56 | +config OCTEON_MGMT_ETHERNET | |
| 57 | + tristate "Octeon Management port ethernet driver (CN5XXX, CN6XXX)" | |
| 58 | + depends on CAVIUM_OCTEON_SOC | |
| 59 | + select PHYLIB | |
| 60 | + select MDIO_OCTEON | |
| 61 | + default y | |
| 62 | + help | |
| 63 | + Enable the ethernet driver for the management | |
| 64 | + port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX, | |
| 65 | + CN54XX, CN52XX, and CN6XXX chips. | |
| 66 | + | |
| 56 | 67 | endif # NET_VENDOR_CAVIUM |
| @@ -3,3 +3,4 @@ · 2 unmodified lines | ||
| 3 | 3 | # |
| 4 | 4 | obj-$(CONFIG_NET_VENDOR_CAVIUM) += thunder/ |
| 5 | 5 | obj-$(CONFIG_NET_VENDOR_CAVIUM) += liquidio/ |
| 6 | +obj-$(CONFIG_NET_VENDOR_CAVIUM) += octeon/ | |
File renamed without changes.
File renamed without changes.
| @@ -257,10 +257,13 @@ struct nicvf_drv_stats { · 256 unmodified lines | ||
| 257 | 257 | u64 rx_frames_jumbo; |
| 258 | 258 | u64 rx_drops; |
| 259 | 259 | |
| 260 | + u64 rcv_buffer_alloc_failures; | |
| 261 | + | |
| 260 | 262 | /* Tx */ |
| 261 | 263 | u64 tx_frames_ok; |
| 262 | 264 | u64 tx_drops; |
| 263 | 265 | u64 tx_tso; |
| 266 | + u64 tx_timeout; | |
| 264 | 267 | u64 txq_stop; |
| 265 | 268 | u64 txq_wake; |
| 266 | 269 | }; |
| @@ -269,45 +272,54 @@ struct nicvf { · 2 unmodified lines | ||
| 269 | 272 | struct nicvf *pnicvf; |
| 270 | 273 | struct net_device *netdev; |
| 271 | 274 | struct pci_dev *pdev; |
| 275 | + void __iomem *reg_base; | |
| 276 | + struct queue_set *qs; | |
| 277 | + struct nicvf_cq_poll *napi[8]; | |
| 272 | 278 | u8 vf_id; |
| 273 | − u8 node; | |
| 274 | − u8 tns_mode:1; | |
| 275 | − u8 sqs_mode:1; | |
| 276 | − u8 loopback_supported:1; | |
| 279 | + u8 sqs_id; | |
| 280 | + bool sqs_mode; | |
| 277 | 281 | bool hw_tso; |
| 278 | − u16 mtu; | |
| 279 | − struct queue_set *qs; | |
| 282 | + | |
| 283 | + /* Receive buffer alloc */ | |
| 284 | + u32 rb_page_offset; | |
| 285 | + u16 rb_pageref; | |
| 286 | + bool rb_alloc_fail; | |
| 287 | + bool rb_work_scheduled; | |
| 288 | + struct page *rb_page; | |
| 289 | + struct delayed_work rbdr_work; | |
| 290 | + struct tasklet_struct rbdr_task; | |
| 291 | + | |
| 292 | + /* Secondary Qset */ | |
| 293 | + u8 sqs_count; | |
| 280 | 294 | #define MAX_SQS_PER_VF_SINGLE_NODE 5 |
| 281 | 295 | #define MAX_SQS_PER_VF 11 |
| 282 | − u8 sqs_id; | |
| 283 | − u8 sqs_count; /* Secondary Qset count */ | |
| 284 | 296 | struct nicvf *snicvf[MAX_SQS_PER_VF]; |
| 297 | + | |
| 298 | + /* Queue count */ | |
| 285 | 299 | u8 rx_queues; |
| 286 | 300 | u8 tx_queues; |
| 287 | 301 | u8 max_queues; |
| 288 | − void __iomem *reg_base; | |
| 302 | + | |
| 303 | + u8 node; | |
| 304 | + u8 cpi_alg; | |
| 305 | + u16 mtu; | |
| 289 | 306 | bool link_up; |
| 290 | 307 | u8 duplex; |
| 291 | 308 | u32 speed; |
| 292 | − struct page *rb_page; | |
| 293 | − u32 rb_page_offset; | |
| 294 | − bool rb_alloc_fail; | |
| 295 | − bool rb_work_scheduled; | |
| 296 | − struct delayed_work rbdr_work; | |
| 297 | − struct tasklet_struct rbdr_task; | |
| 298 | − struct tasklet_struct qs_err_task; | |
| 299 | − struct tasklet_struct cq_task; | |
| 300 | − struct nicvf_cq_poll *napi[8]; | |
| 309 | + bool tns_mode; | |
| 310 | + bool loopback_supported; | |
| 301 | 311 | struct nicvf_rss_info rss_info; |
| 302 | − u8 cpi_alg; | |
| 312 | + struct tasklet_struct qs_err_task; | |
| 313 | + struct work_struct reset_task; | |
| 314 | + | |
| 303 | 315 | /* Interrupt coalescing settings */ |
| 304 | 316 | u32 cq_coalesce_usecs; |
| 305 | − | |
| 306 | 317 | u32 msg_enable; |
| 318 | + | |
| 319 | + /* Stats */ | |
| 307 | 320 | struct nicvf_hw_stats hw_stats; |
| 308 | 321 | struct nicvf_drv_stats drv_stats; |
| 309 | 322 | struct bgx_stats bgx_stats; |
| 310 | − struct work_struct reset_task; | |
| 311 | 323 | |
| 312 | 324 | /* MSI-X */ |
| 313 | 325 | bool msix_enabled; |
| @@ -315,6 +327,7 @@ struct nicvf { · 1 unmodified line | ||
| 315 | 327 | struct msix_entry msix_entries[NIC_VF_MSIX_VECTORS]; |
| 316 | 328 | char irq_name[NIC_VF_MSIX_VECTORS][20]; |
| 317 | 329 | bool irq_allocated[NIC_VF_MSIX_VECTORS]; |
| 330 | + cpumask_var_t affinity_mask[NIC_VF_MSIX_VECTORS]; | |
| 318 | 331 | |
| 319 | 332 | /* VF <-> PF mailbox communication */ |
| 320 | 333 | bool pf_acked; |
| @@ -89,9 +89,11 @@ static const struct nicvf_stat nicvf_drv_stats[] = { · 88 unmodified lines | ||
| 89 | 89 | NICVF_DRV_STAT(rx_frames_1518), |
| 90 | 90 | NICVF_DRV_STAT(rx_frames_jumbo), |
| 91 | 91 | NICVF_DRV_STAT(rx_drops), |
| 92 | + NICVF_DRV_STAT(rcv_buffer_alloc_failures), | |
| 92 | 93 | NICVF_DRV_STAT(tx_frames_ok), |
| 93 | 94 | NICVF_DRV_STAT(tx_tso), |
| 94 | 95 | NICVF_DRV_STAT(tx_drops), |
| 96 | + NICVF_DRV_STAT(tx_timeout), | |
| 95 | 97 | NICVF_DRV_STAT(txq_stop), |
| 96 | 98 | NICVF_DRV_STAT(txq_wake), |
| 97 | 99 | }; |
| @@ -826,7 +826,7 @@ static irqreturn_t nicvf_intr_handler(int irq, void *cq_irq) · 825 unmodified lines | ||
| 826 | 826 | nicvf_disable_intr(nic, NICVF_INTR_CQ, qidx); |
| 827 | 827 | |
| 828 | 828 | /* Schedule NAPI */ |
| 829 | − napi_schedule(&cq_poll->napi); | |
| 829 | + napi_schedule_irqoff(&cq_poll->napi); | |
| 830 | 830 | |
| 831 | 831 | /* Clear interrupt */ |
| 832 | 832 | nicvf_clear_intr(nic, NICVF_INTR_CQ, qidx); |
| @@ -897,6 +897,31 @@ static void nicvf_disable_msix(struct nicvf *nic) · 64 unmodified lines | ||
| 897 | 897 | } |
| 898 | 898 | } |
| 899 | 899 | |
| 900 | +static void nicvf_set_irq_affinity(struct nicvf *nic) | |
| 901 | +{ | |
| 902 | + int vec, cpu; | |
| 903 | + int irqnum; | |
| 904 | + | |
| 905 | + for (vec = 0; vec < nic->num_vec; vec++) { | |
| 906 | + if (!nic->irq_allocated[vec]) | |
| 907 | + continue; | |
| 908 | + | |
| 909 | + if (!zalloc_cpumask_var(&nic->affinity_mask[vec], GFP_KERNEL)) | |
| 910 | + return; | |
| 911 | + /* CQ interrupts */ | |
| 912 | + if (vec < NICVF_INTR_ID_SQ) | |
| 913 | + /* Leave CPU0 for RBDR and other interrupts */ | |
| 914 | + cpu = nicvf_netdev_qidx(nic, vec) + 1; | |
| 915 | + else | |
| 916 | + cpu = 0; | |
| 917 | + | |
| 918 | + cpumask_set_cpu(cpumask_local_spread(cpu, nic->node), | |
| 919 | + nic->affinity_mask[vec]); | |
| 920 | + irqnum = nic->msix_entries[vec].vector; | |
| 921 | + irq_set_affinity_hint(irqnum, nic->affinity_mask[vec]); | |
| 922 | + } | |
| 923 | +} | |
| 924 | + | |
| 900 | 925 | static int nicvf_register_interrupts(struct nicvf *nic) |
| 901 | 926 | { |
| 902 | 927 | int irq, ret = 0; |
| @@ -942,8 +967,13 @@ static int nicvf_register_interrupts(struct nicvf *nic) · 39 unmodified lines | ||
| 942 | 967 | ret = request_irq(nic->msix_entries[irq].vector, |
| 943 | 968 | nicvf_qs_err_intr_handler, |
| 944 | 969 | 0, nic->irq_name[irq], nic); |
| 945 | − if (!ret) | |
| 946 | − nic->irq_allocated[irq] = true; | |
| 970 | + if (ret) | |
| 971 | + goto err; | |
| 972 | + | |
| 973 | + nic->irq_allocated[irq] = true; | |
| 974 | + | |
| 975 | + /* Set IRQ affinities */ | |
| 976 | + nicvf_set_irq_affinity(nic); | |
| 947 | 977 | |
| 948 | 978 | err: |
| 949 | 979 | if (ret) |
| @@ -961,6 +991,9 @@ static void nicvf_unregister_interrupts(struct nicvf *nic) · 11 unmodified lines | ||
| 961 | 991 | if (!nic->irq_allocated[irq]) |
| 962 | 992 | continue; |
| 963 | 993 | |
| 994 | + irq_set_affinity_hint(nic->msix_entries[irq].vector, NULL); | |
| 995 | + free_cpumask_var(nic->affinity_mask[irq]); | |
| 996 | + | |
| 964 | 997 | if (irq < NICVF_INTR_ID_SQ) |
| 965 | 998 | free_irq(nic->msix_entries[irq].vector, nic->napi[irq]); |
| 966 | 999 | else |
| @@ -1394,6 +1427,7 @@ static void nicvf_tx_timeout(struct net_device *dev) · 427 unmodified lines | ||
| 1394 | 1427 | netdev_warn(dev, "%s: Transmit timed out, resetting\n", |
| 1395 | 1428 | dev->name); |
| 1396 | 1429 | |
| 1430 | + nic->drv_stats.tx_timeout++; | |
| 1397 | 1431 | schedule_work(&nic->reset_task); |
| 1398 | 1432 | } |
| 1399 | 1433 | |
| @@ -18,6 +18,15 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "q_struct.h" |
| 19 | 19 | #include "nicvf_queues.h" |
| 20 | 20 | |
| 21 | +static void nicvf_get_page(struct nicvf *nic) | |
| 22 | +{ | |
| 23 | + if (!nic->rb_pageref || !nic->rb_page) | |
| 24 | + return; | |
| 25 | + | |
| 26 | + atomic_add(nic->rb_pageref, &nic->rb_page->_count); | |
| 27 | + nic->rb_pageref = 0; | |
| 28 | +} | |
| 29 | + | |
| 21 | 30 | /* Poll a register for a specific value */ |
| 22 | 31 | static int nicvf_poll_reg(struct nicvf *nic, int qidx, |
| 23 | 32 | u64 reg, int bit_pos, int bits, int val) |
| @@ -78,32 +87,32 @@ static void nicvf_free_q_desc_mem(struct nicvf *nic, struct q_desc_mem *dmem) · 54 unmodified lines | ||
| 78 | 87 | static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp, |
| 79 | 88 | u32 buf_len, u64 **rbuf) |
| 80 | 89 | { |
| 81 | − int order = get_order(buf_len); | |
| 90 | + int order = (PAGE_SIZE <= 4096) ? PAGE_ALLOC_COSTLY_ORDER : 0; | |
| 82 | 91 | |
| 83 | 92 | /* Check if request can be accomodated in previous allocated page */ |
| 84 | − if (nic->rb_page) { | |
| 85 | − if ((nic->rb_page_offset + buf_len + buf_len) > | |
| 86 | − (PAGE_SIZE << order)) { | |
| 87 | − nic->rb_page = NULL; | |
| 88 | − } else { | |
| 89 | − nic->rb_page_offset += buf_len; | |
| 90 | − get_page(nic->rb_page); | |
| 91 | − } | |
| 93 | + if (nic->rb_page && | |
| 94 | + ((nic->rb_page_offset + buf_len) < (PAGE_SIZE << order))) { | |
| 95 | + nic->rb_pageref++; | |
| 96 | + goto ret; | |
| 92 | 97 | } |
| 93 | 98 | |
| 99 | + nicvf_get_page(nic); | |
| 100 | + nic->rb_page = NULL; | |
| 101 | + | |
| 94 | 102 | /* Allocate a new page */ |
| 95 | 103 | if (!nic->rb_page) { |
| 96 | 104 | nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN, |
| 97 | 105 | order); |
| 98 | 106 | if (!nic->rb_page) { |
| 99 | − netdev_err(nic->netdev, | |
| 100 | − "Failed to allocate new rcv buffer\n"); | |
| 107 | + nic->drv_stats.rcv_buffer_alloc_failures++; | |
| 101 | 108 | return -ENOMEM; |
| 102 | 109 | } |
| 103 | 110 | nic->rb_page_offset = 0; |
| 104 | 111 | } |
| 105 | 112 | |
| 113 | +ret: | |
| 106 | 114 | *rbuf = (u64 *)((u64)page_address(nic->rb_page) + nic->rb_page_offset); |
| 115 | + nic->rb_page_offset += buf_len; | |
| 107 | 116 | |
| 108 | 117 | return 0; |
| 109 | 118 | } |
| @@ -159,6 +168,9 @@ static int nicvf_init_rbdr(struct nicvf *nic, struct rbdr *rbdr, · 49 unmodified lines | ||
| 159 | 168 | desc = GET_RBDR_DESC(rbdr, idx); |
| 160 | 169 | desc->buf_addr = virt_to_phys(rbuf) >> NICVF_RCV_BUF_ALIGN; |
| 161 | 170 | } |
| 171 | + | |
| 172 | + nicvf_get_page(nic); | |
| 173 | + | |
| 162 | 174 | return 0; |
| 163 | 175 | } |
| 164 | 176 | |
| @@ -242,6 +254,8 @@ refill: · 77 unmodified lines | ||
| 242 | 254 | new_rb++; |
| 243 | 255 | } |
| 244 | 256 | |
| 257 | + nicvf_get_page(nic); | |
| 258 | + | |
| 245 | 259 | /* make sure all memory stores are done before ringing doorbell */ |
| 246 | 260 | smp_wmb(); |
| 247 | 261 | |
| @@ -886,7 +886,8 @@ static void bgx_get_qlm_mode(struct bgx *bgx) · 885 unmodified lines | ||
| 886 | 886 | |
| 887 | 887 | #ifdef CONFIG_ACPI |
| 888 | 888 | |
| 889 | −static int acpi_get_mac_address(struct acpi_device *adev, u8 *dst) | |
| 889 | +static int acpi_get_mac_address(struct device *dev, struct acpi_device *adev, | |
| 890 | + u8 *dst) | |
| 890 | 891 | { |
| 891 | 892 | u8 mac[ETH_ALEN]; |
| 892 | 893 | int ret; |
| @@ -897,10 +898,13 @@ static int acpi_get_mac_address(struct acpi_device *adev, u8 *dst) · 4 unmodified lines | ||
| 897 | 898 | goto out; |
| 898 | 899 | |
| 899 | 900 | if (!is_valid_ether_addr(mac)) { |
| 901 | + dev_err(dev, "MAC address invalid: %pM\n", mac); | |
| 900 | 902 | ret = -EINVAL; |
| 901 | 903 | goto out; |
| 902 | 904 | } |
| 903 | 905 | |
| 906 | + dev_info(dev, "MAC address set to: %pM\n", mac); | |
| 907 | + | |
| 904 | 908 | memcpy(dst, mac, ETH_ALEN); |
| 905 | 909 | out: |
| 906 | 910 | return ret; |
| @@ -911,14 +915,15 @@ static acpi_status bgx_acpi_register_phy(acpi_handle handle, · 4 unmodified lines | ||
| 911 | 915 | u32 lvl, void *context, void **rv) |
| 912 | 916 | { |
| 913 | 917 | struct bgx *bgx = context; |
| 918 | + struct device *dev = &bgx->pdev->dev; | |
| 914 | 919 | struct acpi_device *adev; |
| 915 | 920 | |
| 916 | 921 | if (acpi_bus_get_device(handle, &adev)) |
| 917 | 922 | goto out; |
| 918 | 923 | |
| 919 | − acpi_get_mac_address(adev, bgx->lmac[bgx->lmac_count].mac); | |
| 924 | + acpi_get_mac_address(dev, adev, bgx->lmac[bgx->lmac_count].mac); | |
| 920 | 925 | |
| 921 | − SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, &bgx->pdev->dev); | |
| 926 | + SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, dev); | |
| 922 | 927 | |
| 923 | 928 | bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count; |
| 924 | 929 | out: |
| @@ -968,38 +973,63 @@ static int bgx_init_acpi_phy(struct bgx *bgx) · 43 unmodified lines | ||
| 968 | 973 | |
| 969 | 974 | static int bgx_init_of_phy(struct bgx *bgx) |
| 970 | 975 | { |
| 971 | − struct device_node *np; | |
| 972 | − struct device_node *np_child; | |
| 976 | + struct fwnode_handle *fwn; | |
| 977 | + struct device_node *node = NULL; | |
| 973 | 978 | u8 lmac = 0; |
| 974 | − char bgx_sel[5]; | |
| 975 | − const char *mac; | |
| 976 | − | |
| 977 | − /* Get BGX node from DT */ | |
| 978 | − snprintf(bgx_sel, 5, "bgx%d", bgx->bgx_id); | |
| 979 | − np = of_find_node_by_name(NULL, bgx_sel); | |
| 980 | − if (!np) | |
| 981 | − return -ENODEV; | |
| 982 | − | |
| 983 | − for_each_child_of_node(np, np_child) { | |
| 984 | − struct device_node *phy_np = of_parse_phandle(np_child, | |
| 985 | − "phy-handle", 0); | |
| 986 | − if (!phy_np) | |
| 987 | − continue; | |
| 988 | − bgx->lmac[lmac].phydev = of_phy_find_device(phy_np); | |
| 989 | 979 | |
| 990 | − mac = of_get_mac_address(np_child); | |
| 980 | + device_for_each_child_node(&bgx->pdev->dev, fwn) { | |
| 981 | + struct phy_device *pd; | |
| 982 | + struct device_node *phy_np; | |
| 983 | + const char *mac; | |
| 984 | + | |
| 985 | + /* Should always be an OF node. But if it is not, we | |
| 986 | + * cannot handle it, so exit the loop. | |
| 987 | + */ | |
| 988 | + node = to_of_node(fwn); | |
| 989 | + if (!node) | |
| 990 | + break; | |
| 991 | + | |
| 992 | + mac = of_get_mac_address(node); | |
| 991 | 993 | if (mac) |
| 992 | 994 | ether_addr_copy(bgx->lmac[lmac].mac, mac); |
| 993 | 995 | |
| 994 | 996 | SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev); |
| 995 | 997 | bgx->lmac[lmac].lmacid = lmac; |
| 998 | + | |
| 999 | + phy_np = of_parse_phandle(node, "phy-handle", 0); | |
| 1000 | + /* If there is no phy or defective firmware presents | |
| 1001 | + * this cortina phy, for which there is no driver | |
| 1002 | + * support, ignore it. | |
| 1003 | + */ | |
| 1004 | + if (phy_np && | |
| 1005 | + !of_device_is_compatible(phy_np, "cortina,cs4223-slice")) { | |
| 1006 | + /* Wait until the phy drivers are available */ | |
| 1007 | + pd = of_phy_find_device(phy_np); | |
| 1008 | + if (!pd) | |
| 1009 | + goto defer; | |
| 1010 | + bgx->lmac[lmac].phydev = pd; | |
| 1011 | + } | |
| 1012 | + | |
| 996 | 1013 | lmac++; |
| 997 | − if (lmac == MAX_LMAC_PER_BGX) { | |
| 998 | − of_node_put(np_child); | |
| 1014 | + if (lmac == MAX_LMAC_PER_BGX) | |
| 999 | 1015 | break; |
| 1000 | − } | |
| 1001 | 1016 | } |
| 1017 | + of_node_put(node); | |
| 1002 | 1018 | return 0; |
| 1019 | + | |
| 1020 | +defer: | |
| 1021 | + /* We are bailing out, try not to leak device reference counts | |
| 1022 | + * for phy devices we may have already found. | |
| 1023 | + */ | |
| 1024 | + while (lmac) { | |
| 1025 | + if (bgx->lmac[lmac].phydev) { | |
| 1026 | + put_device(&bgx->lmac[lmac].phydev->mdio.dev); | |
| 1027 | + bgx->lmac[lmac].phydev = NULL; | |
| 1028 | + } | |
| 1029 | + lmac--; | |
| 1030 | + } | |
| 1031 | + of_node_put(node); | |
| 1032 | + return -EPROBE_DEFER; | |
| 1003 | 1033 | } |
| 1004 | 1034 | |
| 1005 | 1035 | #else |
| @@ -1026,9 +1056,6 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 20 unmodified lines | ||
| 1026 | 1056 | struct bgx *bgx = NULL; |
| 1027 | 1057 | u8 lmac; |
| 1028 | 1058 | |
| 1029 | − /* Load octeon mdio driver */ | |
| 1030 | − octeon_mdiobus_force_mod_depencency(); | |
| 1031 | − | |
| 1032 | 1059 | bgx = devm_kzalloc(dev, sizeof(*bgx), GFP_KERNEL); |
| 1033 | 1060 | if (!bgx) |
| 1034 | 1061 | return -ENOMEM; |
| @@ -702,6 +702,11 @@ struct doorbell_stats { · 701 unmodified lines | ||
| 702 | 702 | u32 db_full; |
| 703 | 703 | }; |
| 704 | 704 | |
| 705 | +struct hash_mac_addr { | |
| 706 | + struct list_head list; | |
| 707 | + u8 addr[ETH_ALEN]; | |
| 708 | +}; | |
| 709 | + | |
| 705 | 710 | struct adapter { |
| 706 | 711 | void __iomem *regs; |
| 707 | 712 | void __iomem *bar2; |
| @@ -740,6 +745,7 @@ struct adapter { · 32 unmodified lines | ||
| 740 | 745 | void *uld_handle[CXGB4_ULD_MAX]; |
| 741 | 746 | struct list_head list_node; |
| 742 | 747 | struct list_head rcu_node; |
| 748 | + struct list_head mac_hlist; /* list of MAC addresses in MPS Hash */ | |
| 743 | 749 | |
| 744 | 750 | struct tid_info tids; |
| 745 | 751 | void **tid_release_head; |
| @@ -1207,6 +1213,24 @@ static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd, · 461 unmodified lines | ||
| 1207 | 1213 | return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, false); |
| 1208 | 1214 | } |
| 1209 | 1215 | |
| 1216 | +/** | |
| 1217 | + * hash_mac_addr - return the hash value of a MAC address | |
| 1218 | + * @addr: the 48-bit Ethernet MAC address | |
| 1219 | + * | |
| 1220 | + * Hashes a MAC address according to the hash function used by HW inexact | |
| 1221 | + * (hash) address matching. | |
| 1222 | + */ | |
| 1223 | +static inline int hash_mac_addr(const u8 *addr) | |
| 1224 | +{ | |
| 1225 | + u32 a = ((u32)addr[0] << 16) | ((u32)addr[1] << 8) | addr[2]; | |
| 1226 | + u32 b = ((u32)addr[3] << 16) | ((u32)addr[4] << 8) | addr[5]; | |
| 1227 | + | |
| 1228 | + a ^= b; | |
| 1229 | + a ^= (a >> 12); | |
| 1230 | + a ^= (a >> 6); | |
| 1231 | + return a & 0x3f; | |
| 1232 | +} | |
| 1233 | + | |
| 1210 | 1234 | void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, |
| 1211 | 1235 | unsigned int data_reg, const u32 *vals, |
| 1212 | 1236 | unsigned int nregs, unsigned int start_idx); |
| @@ -1389,6 +1413,9 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, · 176 unmodified lines | ||
| 1389 | 1413 | int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox, |
| 1390 | 1414 | unsigned int viid, bool free, unsigned int naddr, |
| 1391 | 1415 | const u8 **addr, u16 *idx, u64 *hash, bool sleep_ok); |
| 1416 | +int t4_free_mac_filt(struct adapter *adap, unsigned int mbox, | |
| 1417 | + unsigned int viid, unsigned int naddr, | |
| 1418 | + const u8 **addr, bool sleep_ok); | |
| 1392 | 1419 | int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, |
| 1393 | 1420 | int idx, const u8 *addr, bool persist, bool add_smt); |
| 1394 | 1421 | int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid, |
| @@ -338,84 +338,108 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id) · 337 unmodified lines | ||
| 338 | 338 | netdev_info(dev, "%s module inserted\n", mod_str[pi->mod_type]); |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | +int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */ | |
| 342 | +module_param(dbfifo_int_thresh, int, 0644); | |
| 343 | +MODULE_PARM_DESC(dbfifo_int_thresh, "doorbell fifo interrupt threshold"); | |
| 344 | + | |
| 341 | 345 | /* |
| 342 | − * Configure the exact and hash address filters to handle a port's multicast | |
| 343 | − * and secondary unicast MAC addresses. | |
| 346 | + * usecs to sleep while draining the dbfifo | |
| 344 | 347 | */ |
| 345 | −static int set_addr_filters(const struct net_device *dev, bool sleep) | |
| 348 | +static int dbfifo_drain_delay = 1000; | |
| 349 | +module_param(dbfifo_drain_delay, int, 0644); | |
| 350 | +MODULE_PARM_DESC(dbfifo_drain_delay, | |
| 351 | + "usecs to sleep while draining the dbfifo"); | |
| 352 | + | |
| 353 | +static inline int cxgb4_set_addr_hash(struct port_info *pi) | |
| 346 | 354 | { |
| 355 | + struct adapter *adap = pi->adapter; | |
| 356 | + u64 vec = 0; | |
| 357 | + bool ucast = false; | |
| 358 | + struct hash_mac_addr *entry; | |
| 359 | + | |
| 360 | + /* Calculate the hash vector for the updated list and program it */ | |
| 361 | + list_for_each_entry(entry, &adap->mac_hlist, list) { | |
| 362 | + ucast |= is_unicast_ether_addr(entry->addr); | |
| 363 | + vec |= (1ULL << hash_mac_addr(entry->addr)); | |
| 364 | + } | |
| 365 | + return t4_set_addr_hash(adap, adap->mbox, pi->viid, ucast, | |
| 366 | + vec, false); | |
| 367 | +} | |
| 368 | + | |
| 369 | +static int cxgb4_mac_sync(struct net_device *netdev, const u8 *mac_addr) | |
| 370 | +{ | |
| 371 | + struct port_info *pi = netdev_priv(netdev); | |
| 372 | + struct adapter *adap = pi->adapter; | |
| 373 | + int ret; | |
| 347 | 374 | u64 mhash = 0; |
| 348 | 375 | u64 uhash = 0; |
| 349 | − bool free = true; | |
| 350 | − u16 filt_idx[7]; | |
| 351 | − const u8 *addr[7]; | |
| 352 | − int ret, naddr = 0; | |
| 353 | − const struct netdev_hw_addr *ha; | |
| 354 | − int uc_cnt = netdev_uc_count(dev); | |
| 355 | − int mc_cnt = netdev_mc_count(dev); | |
| 356 | − const struct port_info *pi = netdev_priv(dev); | |
| 357 | − unsigned int mb = pi->adapter->pf; | |
| 376 | + bool free = false; | |
| 377 | + bool ucast = is_unicast_ether_addr(mac_addr); | |
| 378 | + const u8 *maclist[1] = {mac_addr}; | |
| 379 | + struct hash_mac_addr *new_entry; | |
| 358 | 380 | |
| 359 | − /* first do the secondary unicast addresses */ | |
| 360 | − netdev_for_each_uc_addr(ha, dev) { | |
| 361 | − addr[naddr++] = ha->addr; | |
| 362 | − if (--uc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) { | |
| 363 | − ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free, | |
| 364 | − naddr, addr, filt_idx, &uhash, sleep); | |
| 365 | − if (ret < 0) | |
| 366 | − return ret; | |
| 367 | − | |
| 368 | − free = false; | |
| 369 | − naddr = 0; | |
| 370 | − } | |
| 381 | + ret = t4_alloc_mac_filt(adap, adap->mbox, pi->viid, free, 1, maclist, | |
| 382 | + NULL, ucast ? &uhash : &mhash, false); | |
| 383 | + if (ret < 0) | |
| 384 | + goto out; | |
| 385 | + /* if hash != 0, then add the addr to hash addr list | |
| 386 | + * so on the end we will calculate the hash for the | |
| 387 | + * list and program it | |
| 388 | + */ | |
| 389 | + if (uhash || mhash) { | |
| 390 | + new_entry = kzalloc(sizeof(*new_entry), GFP_ATOMIC); | |
| 391 | + if (!new_entry) | |
| 392 | + return -ENOMEM; | |
| 393 | + ether_addr_copy(new_entry->addr, mac_addr); | |
| 394 | + list_add_tail(&new_entry->list, &adap->mac_hlist); | |
| 395 | + ret = cxgb4_set_addr_hash(pi); | |
| 371 | 396 | } |
| 397 | +out: | |
| 398 | + return ret < 0 ? ret : 0; | |
| 399 | +} | |
| 372 | 400 | |
| 373 | − /* next set up the multicast addresses */ | |
| 374 | − netdev_for_each_mc_addr(ha, dev) { | |
| 375 | − addr[naddr++] = ha->addr; | |
| 376 | − if (--mc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) { | |
| 377 | − ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free, | |
| 378 | − naddr, addr, filt_idx, &mhash, sleep); | |
| 379 | − if (ret < 0) | |
| 380 | − return ret; | |
| 401 | +static int cxgb4_mac_unsync(struct net_device *netdev, const u8 *mac_addr) | |
| 402 | +{ | |
| 403 | + struct port_info *pi = netdev_priv(netdev); | |
| 404 | + struct adapter *adap = pi->adapter; | |
| 405 | + int ret; | |
| 406 | + const u8 *maclist[1] = {mac_addr}; | |
| 407 | + struct hash_mac_addr *entry, *tmp; | |
| 381 | 408 | |
| 382 | − free = false; | |
| 383 | − naddr = 0; | |
| 409 | + /* If the MAC address to be removed is in the hash addr | |
| 410 | + * list, delete it from the list and update hash vector | |
| 411 | + */ | |
| 412 | + list_for_each_entry_safe(entry, tmp, &adap->mac_hlist, list) { | |
| 413 | + if (ether_addr_equal(entry->addr, mac_addr)) { | |
| 414 | + list_del(&entry->list); | |
| 415 | + kfree(entry); | |
| 416 | + return cxgb4_set_addr_hash(pi); | |
| 384 | 417 | } |
| 385 | 418 | } |
| 386 | 419 | |
| 387 | − return t4_set_addr_hash(pi->adapter, mb, pi->viid, uhash != 0, | |
| 388 | − uhash | mhash, sleep); | |
| 420 | + ret = t4_free_mac_filt(adap, adap->mbox, pi->viid, 1, maclist, false); | |
| 421 | + return ret < 0 ? -EINVAL : 0; | |
| 389 | 422 | } |
| 390 | 423 | |
| 391 | −int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */ | |
| 392 | −module_param(dbfifo_int_thresh, int, 0644); | |
| 393 | −MODULE_PARM_DESC(dbfifo_int_thresh, "doorbell fifo interrupt threshold"); | |
| 394 | − | |
| 395 | −/* | |
| 396 | − * usecs to sleep while draining the dbfifo | |
| 397 | − */ | |
| 398 | −static int dbfifo_drain_delay = 1000; | |
| 399 | −module_param(dbfifo_drain_delay, int, 0644); | |
| 400 | −MODULE_PARM_DESC(dbfifo_drain_delay, | |
| 401 | − "usecs to sleep while draining the dbfifo"); | |
| 402 | − | |
| 403 | 424 | /* |
| 404 | 425 | * Set Rx properties of a port, such as promiscruity, address filters, and MTU. |
| 405 | 426 | * If @mtu is -1 it is left unchanged. |
| 406 | 427 | */ |
| 407 | 428 | static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok) |
| 408 | 429 | { |
| 409 | − int ret; | |
| 410 | 430 | struct port_info *pi = netdev_priv(dev); |
| 431 | + struct adapter *adapter = pi->adapter; | |
| 411 | 432 | |
| 412 | − ret = set_addr_filters(dev, sleep_ok); | |
| 413 | − if (ret == 0) | |
| 414 | − ret = t4_set_rxmode(pi->adapter, pi->adapter->pf, pi->viid, mtu, | |
| 415 | − (dev->flags & IFF_PROMISC) ? 1 : 0, | |
| 416 | − (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1, | |
| 417 | − sleep_ok); | |
| 418 | − return ret; | |
| 433 | + if (!(dev->flags & IFF_PROMISC)) { | |
| 434 | + __dev_uc_sync(dev, cxgb4_mac_sync, cxgb4_mac_unsync); | |
| 435 | + if (!(dev->flags & IFF_ALLMULTI)) | |
| 436 | + __dev_mc_sync(dev, cxgb4_mac_sync, cxgb4_mac_unsync); | |
| 437 | + } | |
| 438 | + | |
| 439 | + return t4_set_rxmode(adapter, adapter->mbox, pi->viid, mtu, | |
| 440 | + (dev->flags & IFF_PROMISC) ? 1 : 0, | |
| 441 | + (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1, | |
| 442 | + sleep_ok); | |
| 419 | 443 | } |
| 420 | 444 | |
| 421 | 445 | /** |
| @@ -2677,6 +2701,8 @@ static int cxgb_up(struct adapter *adap) · 2255 unmodified lines | ||
| 2677 | 2701 | #if IS_ENABLED(CONFIG_IPV6) |
| 2678 | 2702 | update_clip(adap); |
| 2679 | 2703 | #endif |
| 2704 | + /* Initialize hash mac addr list*/ | |
| 2705 | + INIT_LIST_HEAD(&adap->mac_hlist); | |
| 2680 | 2706 | out: |
| 2681 | 2707 | return err; |
| 2682 | 2708 | irq_err: |
| @@ -2226,7 +2226,7 @@ static int process_responses(struct sge_rspq *q, int budget) · 2225 unmodified lines | ||
| 2226 | 2226 | budget_left--; |
| 2227 | 2227 | } |
| 2228 | 2228 | |
| 2229 | − if (q->offset >= 0 && rxq->fl.size - rxq->fl.avail >= 16) | |
| 2229 | + if (q->offset >= 0 && fl_cap(&rxq->fl) - rxq->fl.avail >= 16) | |
| 2230 | 2230 | __refill_fl(q->adap, &rxq->fl); |
| 2231 | 2231 | return budget - budget_left; |
| 2232 | 2232 | } |
| @@ -2611,8 +2611,18 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, · 378 unmodified lines | ||
| 2611 | 2611 | htonl(FW_IQ_CMD_FL0CNGCHMAP_V(cong) | |
| 2612 | 2612 | FW_IQ_CMD_FL0CONGCIF_F | |
| 2613 | 2613 | FW_IQ_CMD_FL0CONGEN_F); |
| 2614 | + /* In T6, for egress queue type FL there is internal overhead | |
| 2615 | + * of 16B for header going into FLM module. Hence the maximum | |
| 2616 | + * allowed burst size is 448 bytes. For T4/T5, the hardware | |
| 2617 | + * doesn't coalesce fetch requests if more than 64 bytes of | |
| 2618 | + * Free List pointers are provided, so we use a 128-byte Fetch | |
| 2619 | + * Burst Minimum there (T6 implements coalescing so we can use | |
| 2620 | + * the smaller 64-byte value there). | |
| 2621 | + */ | |
| 2614 | 2622 | c.fl0dcaen_to_fl0cidxfthresh = |
| 2615 | − htons(FW_IQ_CMD_FL0FBMIN_V(FETCHBURSTMIN_64B_X) | | |
| 2623 | + htons(FW_IQ_CMD_FL0FBMIN_V(chip <= CHELSIO_T5 ? | |
| 2624 | + FETCHBURSTMIN_128B_X : | |
| 2625 | + FETCHBURSTMIN_64B_X) | | |
| 2616 | 2626 | FW_IQ_CMD_FL0FBMAX_V((chip <= CHELSIO_T5) ? |
| 2617 | 2627 | FETCHBURSTMAX_512B_X : |
| 2618 | 2628 | FETCHBURSTMAX_256B_X)); |
| @@ -4432,23 +4432,6 @@ void t4_intr_disable(struct adapter *adapter) · 4431 unmodified lines | ||
| 4432 | 4432 | t4_set_reg_field(adapter, PL_INT_MAP0_A, 1 << pf, 0); |
| 4433 | 4433 | } |
| 4434 | 4434 | |
| 4435 | −/** | |
| 4436 | − * hash_mac_addr - return the hash value of a MAC address | |
| 4437 | − * @addr: the 48-bit Ethernet MAC address | |
| 4438 | − * | |
| 4439 | − * Hashes a MAC address according to the hash function used by HW inexact | |
| 4440 | − * (hash) address matching. | |
| 4441 | − */ | |
| 4442 | −static int hash_mac_addr(const u8 *addr) | |
| 4443 | −{ | |
| 4444 | − u32 a = ((u32)addr[0] << 16) | ((u32)addr[1] << 8) | addr[2]; | |
| 4445 | − u32 b = ((u32)addr[3] << 16) | ((u32)addr[4] << 8) | addr[5]; | |
| 4446 | − a ^= b; | |
| 4447 | − a ^= (a >> 12); | |
| 4448 | − a ^= (a >> 6); | |
| 4449 | − return a & 0x3f; | |
| 4450 | −} | |
| 4451 | − | |
| 4452 | 4435 | /** |
| 4453 | 4436 | * t4_config_rss_range - configure a portion of the RSS mapping table |
| 4454 | 4437 | * @adapter: the adapter |
| @@ -6737,6 +6720,81 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox, · 2282 unmodified lines | ||
| 6737 | 6720 | return ret; |
| 6738 | 6721 | } |
| 6739 | 6722 | |
| 6723 | +/** | |
| 6724 | + * t4_free_mac_filt - frees exact-match filters of given MAC addresses | |
| 6725 | + * @adap: the adapter | |
| 6726 | + * @mbox: mailbox to use for the FW command | |
| 6727 | + * @viid: the VI id | |
| 6728 | + * @naddr: the number of MAC addresses to allocate filters for (up to 7) | |
| 6729 | + * @addr: the MAC address(es) | |
| 6730 | + * @sleep_ok: call is allowed to sleep | |
| 6731 | + * | |
| 6732 | + * Frees the exact-match filter for each of the supplied addresses | |
| 6733 | + * | |
| 6734 | + * Returns a negative error number or the number of filters freed. | |
| 6735 | + */ | |
| 6736 | +int t4_free_mac_filt(struct adapter *adap, unsigned int mbox, | |
| 6737 | + unsigned int viid, unsigned int naddr, | |
| 6738 | + const u8 **addr, bool sleep_ok) | |
| 6739 | +{ | |
| 6740 | + int offset, ret = 0; | |
| 6741 | + struct fw_vi_mac_cmd c; | |
| 6742 | + unsigned int nfilters = 0; | |
| 6743 | + unsigned int max_naddr = is_t4(adap->params.chip) ? | |
| 6744 | + NUM_MPS_CLS_SRAM_L_INSTANCES : | |
| 6745 | + NUM_MPS_T5_CLS_SRAM_L_INSTANCES; | |
| 6746 | + unsigned int rem = naddr; | |
| 6747 | + | |
| 6748 | + if (naddr > max_naddr) | |
| 6749 | + return -EINVAL; | |
| 6750 | + | |
| 6751 | + for (offset = 0; offset < (int)naddr ; /**/) { | |
| 6752 | + unsigned int fw_naddr = (rem < ARRAY_SIZE(c.u.exact) | |
| 6753 | + ? rem | |
| 6754 | + : ARRAY_SIZE(c.u.exact)); | |
| 6755 | + size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd, | |
| 6756 | + u.exact[fw_naddr]), 16); | |
| 6757 | + struct fw_vi_mac_exact *p; | |
| 6758 | + int i; | |
| 6759 | + | |
| 6760 | + memset(&c, 0, sizeof(c)); | |
| 6761 | + c.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_MAC_CMD) | | |
| 6762 | + FW_CMD_REQUEST_F | | |
| 6763 | + FW_CMD_WRITE_F | | |
| 6764 | + FW_CMD_EXEC_V(0) | | |
| 6765 | + FW_VI_MAC_CMD_VIID_V(viid)); | |
| 6766 | + c.freemacs_to_len16 = | |
| 6767 | + cpu_to_be32(FW_VI_MAC_CMD_FREEMACS_V(0) | | |
| 6768 | + FW_CMD_LEN16_V(len16)); | |
| 6769 | + | |
| 6770 | + for (i = 0, p = c.u.exact; i < (int)fw_naddr; i++, p++) { | |
| 6771 | + p->valid_to_idx = cpu_to_be16( | |
| 6772 | + FW_VI_MAC_CMD_VALID_F | | |
| 6773 | + FW_VI_MAC_CMD_IDX_V(FW_VI_MAC_MAC_BASED_FREE)); | |
| 6774 | + memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr)); | |
| 6775 | + } | |
| 6776 | + | |
| 6777 | + ret = t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), &c, sleep_ok); | |
| 6778 | + if (ret) | |
| 6779 | + break; | |
| 6780 | + | |
| 6781 | + for (i = 0, p = c.u.exact; i < fw_naddr; i++, p++) { | |
| 6782 | + u16 index = FW_VI_MAC_CMD_IDX_G( | |
| 6783 | + be16_to_cpu(p->valid_to_idx)); | |
| 6784 | + | |
| 6785 | + if (index < max_naddr) | |
| 6786 | + nfilters++; | |
| 6787 | + } | |
| 6788 | + | |
| 6789 | + offset += fw_naddr; | |
| 6790 | + rem -= fw_naddr; | |
| 6791 | + } | |
| 6792 | + | |
| 6793 | + if (ret == 0) | |
| 6794 | + ret = nfilters; | |
| 6795 | + return ret; | |
| 6796 | +} | |
| 6797 | + | |
| 6740 | 6798 | /** |
| 6741 | 6799 | * t4_change_mac - modifies the exact-match filter for a MAC address |
| 6742 | 6800 | * @adap: the adapter |
| @@ -65,6 +65,7 @@ · 64 unmodified lines | ||
| 65 | 65 | #define TIMERREG_COUNTER0_X 0 |
| 66 | 66 | |
| 67 | 67 | #define FETCHBURSTMIN_64B_X 2 |
| 68 | +#define FETCHBURSTMIN_128B_X 3 | |
| 68 | 69 | |
| 69 | 70 | #define FETCHBURSTMAX_256B_X 2 |
| 70 | 71 | #define FETCHBURSTMAX_512B_X 3 |
| @@ -348,6 +348,11 @@ struct sge { · 347 unmodified lines | ||
| 348 | 348 | #define for_each_ethrxq(sge, iter) \ |
| 349 | 349 | for (iter = 0; iter < (sge)->ethqsets; iter++) |
| 350 | 350 | |
| 351 | +struct hash_mac_addr { | |
| 352 | + struct list_head list; | |
| 353 | + u8 addr[ETH_ALEN]; | |
| 354 | +}; | |
| 355 | + | |
| 351 | 356 | /* |
| 352 | 357 | * Per-"adapter" (Virtual Function) information. |
| 353 | 358 | */ |
| @@ -381,6 +386,9 @@ struct adapter { · 27 unmodified lines | ||
| 381 | 386 | |
| 382 | 387 | /* various locks */ |
| 383 | 388 | spinlock_t stats_lock; |
| 389 | + | |
| 390 | + /* list of MAC addresses in MPS Hash */ | |
| 391 | + struct list_head mac_hlist; | |
| 384 | 392 | }; |
| 385 | 393 | |
| 386 | 394 | enum { /* adapter flags */ |
| @@ -741,6 +741,9 @@ static int adapter_up(struct adapter *adapter) · 740 unmodified lines | ||
| 741 | 741 | */ |
| 742 | 742 | enable_rx(adapter); |
| 743 | 743 | t4vf_sge_start(adapter); |
| 744 | + | |
| 745 | + /* Initialize hash mac addr list*/ | |
| 746 | + INIT_LIST_HEAD(&adapter->mac_hlist); | |
| 744 | 747 | return 0; |
| 745 | 748 | } |
| 746 | 749 | |
| @@ -787,10 +790,6 @@ static int cxgb4vf_open(struct net_device *dev) · 40 unmodified lines | ||
| 787 | 790 | /* |
| 788 | 791 | * Note that this interface is up and start everything up ... |
| 789 | 792 | */ |
| 790 | − netif_set_real_num_tx_queues(dev, pi->nqsets); | |
| 791 | − err = netif_set_real_num_rx_queues(dev, pi->nqsets); | |
| 792 | − if (err) | |
| 793 | − goto err_unwind; | |
| 794 | 793 | err = link_start(dev); |
| 795 | 794 | if (err) |
| 796 | 795 | goto err_unwind; |
| @@ -859,97 +858,74 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev) · 62 unmodified lines | ||
| 859 | 858 | return ns; |
| 860 | 859 | } |
| 861 | 860 | |
| 862 | −/* | |
| 863 | − * Collect up to maxaddrs worth of a netdevice's unicast addresses, starting | |
| 864 | − * at a specified offset within the list, into an array of addrss pointers and | |
| 865 | − * return the number collected. | |
| 866 | − */ | |
| 867 | −static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev, | |
| 868 | − const u8 **addr, | |
| 869 | − unsigned int offset, | |
| 870 | − unsigned int maxaddrs) | |
| 861 | +static inline int cxgb4vf_set_addr_hash(struct port_info *pi) | |
| 871 | 862 | { |
| 872 | − unsigned int index = 0; | |
| 873 | − unsigned int naddr = 0; | |
| 874 | − const struct netdev_hw_addr *ha; | |
| 875 | − | |
| 876 | − for_each_dev_addr(dev, ha) | |
| 877 | − if (index++ >= offset) { | |
| 878 | − addr[naddr++] = ha->addr; | |
| 879 | − if (naddr >= maxaddrs) | |
| 880 | − break; | |
| 881 | − } | |
| 882 | − return naddr; | |
| 883 | −} | |
| 884 | − | |
| 885 | −/* | |
| 886 | − * Collect up to maxaddrs worth of a netdevice's multicast addresses, starting | |
| 887 | − * at a specified offset within the list, into an array of addrss pointers and | |
| 888 | − * return the number collected. | |
| 889 | − */ | |
| 890 | −static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev, | |
| 891 | − const u8 **addr, | |
| 892 | − unsigned int offset, | |
| 893 | − unsigned int maxaddrs) | |
| 894 | −{ | |
| 895 | − unsigned int index = 0; | |
| 896 | − unsigned int naddr = 0; | |
| 897 | − const struct netdev_hw_addr *ha; | |
| 863 | + struct adapter *adapter = pi->adapter; | |
| 864 | + u64 vec = 0; | |
| 865 | + bool ucast = false; | |
| 866 | + struct hash_mac_addr *entry; | |
| 898 | 867 | |
| 899 | − netdev_for_each_mc_addr(ha, dev) | |
| 900 | − if (index++ >= offset) { | |
| 901 | − addr[naddr++] = ha->addr; | |
| 902 | − if (naddr >= maxaddrs) | |
| 903 | − break; | |
| 904 | − } | |
| 905 | − return naddr; | |
| 868 | + /* Calculate the hash vector for the updated list and program it */ | |
| 869 | + list_for_each_entry(entry, &adapter->mac_hlist, list) { | |
| 870 | + ucast |= is_unicast_ether_addr(entry->addr); | |
| 871 | + vec |= (1ULL << hash_mac_addr(entry->addr)); | |
| 872 | + } | |
| 873 | + return t4vf_set_addr_hash(adapter, pi->viid, ucast, vec, false); | |
| 906 | 874 | } |
| 907 | 875 | |
| 908 | −/* | |
| 909 | − * Configure the exact and hash address filters to handle a port's multicast | |
| 910 | − * and secondary unicast MAC addresses. | |
| 911 | − */ | |
| 912 | −static int set_addr_filters(const struct net_device *dev, bool sleep) | |
| 876 | +static int cxgb4vf_mac_sync(struct net_device *netdev, const u8 *mac_addr) | |
| 913 | 877 | { |
| 878 | + struct port_info *pi = netdev_priv(netdev); | |
| 879 | + struct adapter *adapter = pi->adapter; | |
| 880 | + int ret; | |
| 914 | 881 | u64 mhash = 0; |
| 915 | 882 | u64 uhash = 0; |
| 916 | − bool free = true; | |
| 917 | − unsigned int offset, naddr; | |
| 918 | − const u8 *addr[7]; | |
| 919 | − int ret; | |
| 920 | − const struct port_info *pi = netdev_priv(dev); | |
| 921 | − | |
| 922 | − /* first do the secondary unicast addresses */ | |
| 923 | − for (offset = 0; ; offset += naddr) { | |
| 924 | − naddr = collect_netdev_uc_list_addrs(dev, addr, offset, | |
| 925 | − ARRAY_SIZE(addr)); | |
| 926 | − if (naddr == 0) | |
| 927 | − break; | |
| 928 | − | |
| 929 | − ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free, | |
| 930 | − naddr, addr, NULL, &uhash, sleep); | |
| 931 | − if (ret < 0) | |
| 932 | − return ret; | |
| 883 | + bool free = false; | |
| 884 | + bool ucast = is_unicast_ether_addr(mac_addr); | |
| 885 | + const u8 *maclist[1] = {mac_addr}; | |
| 886 | + struct hash_mac_addr *new_entry; | |
| 933 | 887 | |
| 934 | − free = false; | |
| 888 | + ret = t4vf_alloc_mac_filt(adapter, pi->viid, free, 1, maclist, | |
| 889 | + NULL, ucast ? &uhash : &mhash, false); | |
| 890 | + if (ret < 0) | |
| 891 | + goto out; | |
| 892 | + /* if hash != 0, then add the addr to hash addr list | |
| 893 | + * so on the end we will calculate the hash for the | |
| 894 | + * list and program it | |
| 895 | + */ | |
| 896 | + if (uhash || mhash) { | |
| 897 | + new_entry = kzalloc(sizeof(*new_entry), GFP_ATOMIC); | |
| 898 | + if (!new_entry) | |
| 899 | + return -ENOMEM; | |
| 900 | + ether_addr_copy(new_entry->addr, mac_addr); | |
| 901 | + list_add_tail(&new_entry->list, &adapter->mac_hlist); | |
| 902 | + ret = cxgb4vf_set_addr_hash(pi); | |
| 935 | 903 | } |
| 904 | +out: | |
| 905 | + return ret < 0 ? ret : 0; | |
| 906 | +} | |
| 936 | 907 | |
| 937 | − /* next set up the multicast addresses */ | |
| 938 | − for (offset = 0; ; offset += naddr) { | |
| 939 | − naddr = collect_netdev_mc_list_addrs(dev, addr, offset, | |
| 940 | − ARRAY_SIZE(addr)); | |
| 941 | − if (naddr == 0) | |
| 942 | − break; | |
| 908 | +static int cxgb4vf_mac_unsync(struct net_device *netdev, const u8 *mac_addr) | |
| 909 | +{ | |
| 910 | + struct port_info *pi = netdev_priv(netdev); | |
| 911 | + struct adapter *adapter = pi->adapter; | |
| 912 | + int ret; | |
| 913 | + const u8 *maclist[1] = {mac_addr}; | |
| 914 | + struct hash_mac_addr *entry, *tmp; | |
| 943 | 915 | |
| 944 | − ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free, | |
| 945 | − naddr, addr, NULL, &mhash, sleep); | |
| 946 | − if (ret < 0) | |
| 947 | − return ret; | |
| 948 | − free = false; | |
| 916 | + /* If the MAC address to be removed is in the hash addr | |
| 917 | + * list, delete it from the list and update hash vector | |
| 918 | + */ | |
| 919 | + list_for_each_entry_safe(entry, tmp, &adapter->mac_hlist, list) { | |
| 920 | + if (ether_addr_equal(entry->addr, mac_addr)) { | |
| 921 | + list_del(&entry->list); | |
| 922 | + kfree(entry); | |
| 923 | + return cxgb4vf_set_addr_hash(pi); | |
| 924 | + } | |
| 949 | 925 | } |
| 950 | 926 | |
| 951 | − return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0, | |
| 952 | − uhash | mhash, sleep); | |
| 927 | + ret = t4vf_free_mac_filt(adapter, pi->viid, 1, maclist, false); | |
| 928 | + return ret < 0 ? -EINVAL : 0; | |
| 953 | 929 | } |
| 954 | 930 | |
| 955 | 931 | /* |
| @@ -958,16 +934,18 @@ static int set_addr_filters(const struct net_device *dev, bool sleep) · 2 unmodified lines | ||
| 958 | 934 | */ |
| 959 | 935 | static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok) |
| 960 | 936 | { |
| 961 | − int ret; | |
| 962 | 937 | struct port_info *pi = netdev_priv(dev); |
| 963 | 938 | |
| 964 | − ret = set_addr_filters(dev, sleep_ok); | |
| 965 | − if (ret == 0) | |
| 966 | − ret = t4vf_set_rxmode(pi->adapter, pi->viid, -1, | |
| 967 | − (dev->flags & IFF_PROMISC) != 0, | |
| 968 | − (dev->flags & IFF_ALLMULTI) != 0, | |
| 969 | − 1, -1, sleep_ok); | |
| 970 | − return ret; | |
| 939 | + if (!(dev->flags & IFF_PROMISC)) { | |
| 940 | + __dev_uc_sync(dev, cxgb4vf_mac_sync, cxgb4vf_mac_unsync); | |
| 941 | + if (!(dev->flags & IFF_ALLMULTI)) | |
| 942 | + __dev_mc_sync(dev, cxgb4vf_mac_sync, | |
| 943 | + cxgb4vf_mac_unsync); | |
| 944 | + } | |
| 945 | + return t4vf_set_rxmode(pi->adapter, pi->viid, -1, | |
| 946 | + (dev->flags & IFF_PROMISC) != 0, | |
| 947 | + (dev->flags & IFF_ALLMULTI) != 0, | |
| 948 | + 1, -1, sleep_ok); | |
| 971 | 949 | } |
| 972 | 950 | |
| 973 | 951 | /* |
| @@ -2194,6 +2172,73 @@ static void cleanup_debugfs(struct adapter *adapter) · 1220 unmodified lines | ||
| 2194 | 2172 | /* nothing to do */ |
| 2195 | 2173 | } |
| 2196 | 2174 | |
| 2175 | +/* Figure out how many Ports and Queue Sets we can support. This depends on | |
| 2176 | + * knowing our Virtual Function Resources and may be called a second time if | |
| 2177 | + * we fall back from MSI-X to MSI Interrupt Mode. | |
| 2178 | + */ | |
| 2179 | +static void size_nports_qsets(struct adapter *adapter) | |
| 2180 | +{ | |
| 2181 | + struct vf_resources *vfres = &adapter->params.vfres; | |
| 2182 | + unsigned int ethqsets, pmask_nports; | |
| 2183 | + | |
| 2184 | + /* The number of "ports" which we support is equal to the number of | |
| 2185 | + * Virtual Interfaces with which we've been provisioned. | |
| 2186 | + */ | |
| 2187 | + adapter->params.nports = vfres->nvi; | |
| 2188 | + if (adapter->params.nports > MAX_NPORTS) { | |
| 2189 | + dev_warn(adapter->pdev_dev, "only using %d of %d maximum" | |
| 2190 | + " allowed virtual interfaces\n", MAX_NPORTS, | |
| 2191 | + adapter->params.nports); | |
| 2192 | + adapter->params.nports = MAX_NPORTS; | |
| 2193 | + } | |
| 2194 | + | |
| 2195 | + /* We may have been provisioned with more VIs than the number of | |
| 2196 | + * ports we're allowed to access (our Port Access Rights Mask). | |
| 2197 | + * This is obviously a configuration conflict but we don't want to | |
| 2198 | + * crash the kernel or anything silly just because of that. | |
| 2199 | + */ | |
| 2200 | + pmask_nports = hweight32(adapter->params.vfres.pmask); | |
| 2201 | + if (pmask_nports < adapter->params.nports) { | |
| 2202 | + dev_warn(adapter->pdev_dev, "only using %d of %d provissioned" | |
| 2203 | + " virtual interfaces; limited by Port Access Rights" | |
| 2204 | + " mask %#x\n", pmask_nports, adapter->params.nports, | |
| 2205 | + adapter->params.vfres.pmask); | |
| 2206 | + adapter->params.nports = pmask_nports; | |
| 2207 | + } | |
| 2208 | + | |
| 2209 | + /* We need to reserve an Ingress Queue for the Asynchronous Firmware | |
| 2210 | + * Event Queue. And if we're using MSI Interrupts, we'll also need to | |
| 2211 | + * reserve an Ingress Queue for a Forwarded Interrupts. | |
| 2212 | + * | |
| 2213 | + * The rest of the FL/Intr-capable ingress queues will be matched up | |
| 2214 | + * one-for-one with Ethernet/Control egress queues in order to form | |
| 2215 | + * "Queue Sets" which will be aportioned between the "ports". For | |
| 2216 | + * each Queue Set, we'll need the ability to allocate two Egress | |
| 2217 | + * Contexts -- one for the Ingress Queue Free List and one for the TX | |
| 2218 | + * Ethernet Queue. | |
| 2219 | + * | |
| 2220 | + * Note that even if we're currently configured to use MSI-X | |
| 2221 | + * Interrupts (module variable msi == MSI_MSIX) we may get downgraded | |
| 2222 | + * to MSI Interrupts if we can't get enough MSI-X Interrupts. If that | |
| 2223 | + * happens we'll need to adjust things later. | |
| 2224 | + */ | |
| 2225 | + ethqsets = vfres->niqflint - 1 - (msi == MSI_MSI); | |
| 2226 | + if (vfres->nethctrl != ethqsets) | |
| 2227 | + ethqsets = min(vfres->nethctrl, ethqsets); | |
| 2228 | + if (vfres->neq < ethqsets*2) | |
| 2229 | + ethqsets = vfres->neq/2; | |
| 2230 | + if (ethqsets > MAX_ETH_QSETS) | |
| 2231 | + ethqsets = MAX_ETH_QSETS; | |
| 2232 | + adapter->sge.max_ethqsets = ethqsets; | |
| 2233 | + | |
| 2234 | + if (adapter->sge.max_ethqsets < adapter->params.nports) { | |
| 2235 | + dev_warn(adapter->pdev_dev, "only using %d of %d available" | |
| 2236 | + " virtual interfaces (too few Queue Sets)\n", | |
| 2237 | + adapter->sge.max_ethqsets, adapter->params.nports); | |
| 2238 | + adapter->params.nports = adapter->sge.max_ethqsets; | |
| 2239 | + } | |
| 2240 | +} | |
| 2241 | + | |
| 2197 | 2242 | /* |
| 2198 | 2243 | * Perform early "adapter" initialization. This is where we discover what |
| 2199 | 2244 | * adapter parameters we're going to be using and initialize basic adapter |
| @@ -2201,23 +2246,11 @@ static void cleanup_debugfs(struct adapter *adapter) · 1 unmodified line | ||
| 2201 | 2246 | */ |
| 2202 | 2247 | static int adap_init0(struct adapter *adapter) |
| 2203 | 2248 | { |
| 2204 | − struct vf_resources *vfres = &adapter->params.vfres; | |
| 2205 | 2249 | struct sge_params *sge_params = &adapter->params.sge; |
| 2206 | 2250 | struct sge *s = &adapter->sge; |
| 2207 | − unsigned int ethqsets; | |
| 2208 | 2251 | int err; |
| 2209 | 2252 | u32 param, val = 0; |
| 2210 | 2253 | |
| 2211 | − /* | |
| 2212 | − * Wait for the device to become ready before proceeding ... | |
| 2213 | − */ | |
| 2214 | − err = t4vf_wait_dev_ready(adapter); | |
| 2215 | − if (err) { | |
| 2216 | − dev_err(adapter->pdev_dev, "device didn't become ready:" | |
| 2217 | − " err=%d\n", err); | |
| 2218 | − return err; | |
| 2219 | − } | |
| 2220 | − | |
| 2221 | 2254 | /* |
| 2222 | 2255 | * Some environments do not properly handle PCIE FLRs -- e.g. in Linux |
| 2223 | 2256 | * 2.6.31 and later we can't call pci_reset_function() in order to |
| @@ -2323,69 +2356,23 @@ static int adap_init0(struct adapter *adapter) · 99 unmodified lines | ||
| 2323 | 2356 | return err; |
| 2324 | 2357 | } |
| 2325 | 2358 | |
| 2326 | − /* | |
| 2327 | − * The number of "ports" which we support is equal to the number of | |
| 2328 | − * Virtual Interfaces with which we've been provisioned. | |
| 2329 | − */ | |
| 2330 | − adapter->params.nports = vfres->nvi; | |
| 2331 | − if (adapter->params.nports > MAX_NPORTS) { | |
| 2332 | − dev_warn(adapter->pdev_dev, "only using %d of %d allowed" | |
| 2333 | − " virtual interfaces\n", MAX_NPORTS, | |
| 2334 | − adapter->params.nports); | |
| 2335 | − adapter->params.nports = MAX_NPORTS; | |
| 2336 | − } | |
| 2337 | − | |
| 2338 | − /* | |
| 2339 | − * We need to reserve a number of the ingress queues with Free List | |
| 2340 | − * and Interrupt capabilities for special interrupt purposes (like | |
| 2341 | − * asynchronous firmware messages, or forwarded interrupts if we're | |
| 2342 | − * using MSI). The rest of the FL/Intr-capable ingress queues will be | |
| 2343 | − * matched up one-for-one with Ethernet/Control egress queues in order | |
| 2344 | − * to form "Queue Sets" which will be aportioned between the "ports". | |
| 2345 | − * For each Queue Set, we'll need the ability to allocate two Egress | |
| 2346 | − * Contexts -- one for the Ingress Queue Free List and one for the TX | |
| 2347 | − * Ethernet Queue. | |
| 2348 | − */ | |
| 2349 | − ethqsets = vfres->niqflint - INGQ_EXTRAS; | |
| 2350 | − if (vfres->nethctrl != ethqsets) { | |
| 2351 | − dev_warn(adapter->pdev_dev, "unequal number of [available]" | |
| 2352 | − " ingress/egress queues (%d/%d); using minimum for" | |
| 2353 | − " number of Queue Sets\n", ethqsets, vfres->nethctrl); | |
| 2354 | − ethqsets = min(vfres->nethctrl, ethqsets); | |
| 2355 | − } | |
| 2356 | − if (vfres->neq < ethqsets*2) { | |
| 2357 | − dev_warn(adapter->pdev_dev, "Not enough Egress Contexts (%d)" | |
| 2358 | − " to support Queue Sets (%d); reducing allowed Queue" | |
| 2359 | − " Sets\n", vfres->neq, ethqsets); | |
| 2360 | − ethqsets = vfres->neq/2; | |
| 2361 | − } | |
| 2362 | − if (ethqsets > MAX_ETH_QSETS) { | |
| 2363 | − dev_warn(adapter->pdev_dev, "only using %d of %d allowed Queue" | |
| 2364 | − " Sets\n", MAX_ETH_QSETS, adapter->sge.max_ethqsets); | |
| 2365 | − ethqsets = MAX_ETH_QSETS; | |
| 2366 | − } | |
| 2367 | − if (vfres->niq != 0 || vfres->neq > ethqsets*2) { | |
| 2368 | − dev_warn(adapter->pdev_dev, "unused resources niq/neq (%d/%d)" | |
| 2369 | − " ignored\n", vfres->niq, vfres->neq - ethqsets*2); | |
| 2370 | − } | |
| 2371 | − adapter->sge.max_ethqsets = ethqsets; | |
| 2372 | − | |
| 2373 | − /* | |
| 2374 | − * Check for various parameter sanity issues. Most checks simply | |
| 2375 | − * result in us using fewer resources than our provissioning but we | |
| 2376 | − * do need at least one "port" with which to work ... | |
| 2377 | − */ | |
| 2378 | − if (adapter->sge.max_ethqsets < adapter->params.nports) { | |
| 2379 | − dev_warn(adapter->pdev_dev, "only using %d of %d available" | |
| 2380 | − " virtual interfaces (too few Queue Sets)\n", | |
| 2381 | − adapter->sge.max_ethqsets, adapter->params.nports); | |
| 2382 | − adapter->params.nports = adapter->sge.max_ethqsets; | |
| 2359 | + /* Check for various parameter sanity issues */ | |
| 2360 | + if (adapter->params.vfres.pmask == 0) { | |
| 2361 | + dev_err(adapter->pdev_dev, "no port access configured\n" | |
| 2362 | + "usable!\n"); | |
| 2363 | + return -EINVAL; | |
| 2383 | 2364 | } |
| 2384 | − if (adapter->params.nports == 0) { | |
| 2365 | + if (adapter->params.vfres.nvi == 0) { | |
| 2385 | 2366 | dev_err(adapter->pdev_dev, "no virtual interfaces configured/" |
| 2386 | 2367 | "usable!\n"); |
| 2387 | 2368 | return -EINVAL; |
| 2388 | 2369 | } |
| 2370 | + | |
| 2371 | + /* Initialize nports and max_ethqsets now that we have our Virtual | |
| 2372 | + * Function Resources. | |
| 2373 | + */ | |
| 2374 | + size_nports_qsets(adapter); | |
| 2375 | + | |
| 2389 | 2376 | return 0; |
| 2390 | 2377 | } |
| 2391 | 2378 | |
| @@ -2799,6 +2786,40 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, · 407 unmodified lines | ||
| 2799 | 2786 | } |
| 2800 | 2787 | } |
| 2801 | 2788 | |
| 2789 | + /* See what interrupts we'll be using. If we've been configured to | |
| 2790 | + * use MSI-X interrupts, try to enable them but fall back to using | |
| 2791 | + * MSI interrupts if we can't enable MSI-X interrupts. If we can't | |
| 2792 | + * get MSI interrupts we bail with the error. | |
| 2793 | + */ | |
| 2794 | + if (msi == MSI_MSIX && enable_msix(adapter) == 0) | |
| 2795 | + adapter->flags |= USING_MSIX; | |
| 2796 | + else { | |
| 2797 | + if (msi == MSI_MSIX) { | |
| 2798 | + dev_info(adapter->pdev_dev, | |
| 2799 | + "Unable to use MSI-X Interrupts; falling " | |
| 2800 | + "back to MSI Interrupts\n"); | |
| 2801 | + | |
| 2802 | + /* We're going to need a Forwarded Interrupt Queue so | |
| 2803 | + * that may cut into how many Queue Sets we can | |
| 2804 | + * support. | |
| 2805 | + */ | |
| 2806 | + msi = MSI_MSI; | |
| 2807 | + size_nports_qsets(adapter); | |
| 2808 | + } | |
| 2809 | + err = pci_enable_msi(pdev); | |
| 2810 | + if (err) { | |
| 2811 | + dev_err(&pdev->dev, "Unable to allocate MSI Interrupts;" | |
| 2812 | + " err=%d\n", err); | |
| 2813 | + goto err_free_dev; | |
| 2814 | + } | |
| 2815 | + adapter->flags |= USING_MSI; | |
| 2816 | + } | |
| 2817 | + | |
| 2818 | + /* Now that we know how many "ports" we have and what interrupt | |
| 2819 | + * mechanism we're going to use, we can configure our queue resources. | |
| 2820 | + */ | |
| 2821 | + cfg_queues(adapter); | |
| 2822 | + | |
| 2802 | 2823 | /* |
| 2803 | 2824 | * The "card" is now ready to go. If any errors occur during device |
| 2804 | 2825 | * registration we do not fail the whole "card" but rather proceed |
| @@ -2806,10 +2827,14 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, · 1 unmodified line | ||
| 2806 | 2827 | * must register at least one net device. |
| 2807 | 2828 | */ |
| 2808 | 2829 | for_each_port(adapter, pidx) { |
| 2830 | + struct port_info *pi = netdev_priv(adapter->port[pidx]); | |
| 2809 | 2831 | netdev = adapter->port[pidx]; |
| 2810 | 2832 | if (netdev == NULL) |
| 2811 | 2833 | continue; |
| 2812 | 2834 | |
| 2835 | + netif_set_real_num_tx_queues(netdev, pi->nqsets); | |
| 2836 | + netif_set_real_num_rx_queues(netdev, pi->nqsets); | |
| 2837 | + | |
| 2813 | 2838 | err = register_netdev(netdev); |
| 2814 | 2839 | if (err) { |
| 2815 | 2840 | dev_warn(&pdev->dev, "cannot register net device %s," |
| @@ -2821,7 +2846,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, · 5 unmodified lines | ||
| 2821 | 2846 | } |
| 2822 | 2847 | if (adapter->registered_device_map == 0) { |
| 2823 | 2848 | dev_err(&pdev->dev, "could not register any net devices\n"); |
| 2824 | − goto err_free_dev; | |
| 2849 | + goto err_disable_interrupts; | |
| 2825 | 2850 | } |
| 2826 | 2851 | |
| 2827 | 2852 | /* |
| @@ -2838,32 +2863,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, · 10 unmodified lines | ||
| 2838 | 2863 | setup_debugfs(adapter); |
| 2839 | 2864 | } |
| 2840 | 2865 | |
| 2841 | − /* | |
| 2842 | − * See what interrupts we'll be using. If we've been configured to | |
| 2843 | − * use MSI-X interrupts, try to enable them but fall back to using | |
| 2844 | − * MSI interrupts if we can't enable MSI-X interrupts. If we can't | |
| 2845 | − * get MSI interrupts we bail with the error. | |
| 2846 | − */ | |
| 2847 | − if (msi == MSI_MSIX && enable_msix(adapter) == 0) | |
| 2848 | − adapter->flags |= USING_MSIX; | |
| 2849 | − else { | |
| 2850 | − err = pci_enable_msi(pdev); | |
| 2851 | − if (err) { | |
| 2852 | − dev_err(&pdev->dev, "Unable to allocate %s interrupts;" | |
| 2853 | − " err=%d\n", | |
| 2854 | − msi == MSI_MSIX ? "MSI-X or MSI" : "MSI", err); | |
| 2855 | − goto err_free_debugfs; | |
| 2856 | − } | |
| 2857 | − adapter->flags |= USING_MSI; | |
| 2858 | − } | |
| 2859 | − | |
| 2860 | − /* | |
| 2861 | − * Now that we know how many "ports" we have and what their types are, | |
| 2862 | − * and how many Queue Sets we can support, we can configure our queue | |
| 2863 | − * resources. | |
| 2864 | − */ | |
| 2865 | − cfg_queues(adapter); | |
| 2866 | − | |
| 2867 | 2866 | /* |
| 2868 | 2867 | * Print a short notice on the existence and configuration of the new |
| 2869 | 2868 | * VF network device ... |
| @@ -2884,11 +2883,13 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, · 14 unmodified lines | ||
| 2884 | 2883 | * Error recovery and exit code. Unwind state that's been created |
| 2885 | 2884 | * so far and return the error. |
| 2886 | 2885 | */ |
| 2887 | − | |
| 2888 | −err_free_debugfs: | |
| 2889 | − if (!IS_ERR_OR_NULL(adapter->debugfs_root)) { | |
| 2890 | − cleanup_debugfs(adapter); | |
| 2891 | − debugfs_remove_recursive(adapter->debugfs_root); | |
| 2886 | +err_disable_interrupts: | |
| 2887 | + if (adapter->flags & USING_MSIX) { | |
| 2888 | + pci_disable_msix(adapter->pdev); | |
| 2889 | + adapter->flags &= ~USING_MSIX; | |
| 2890 | + } else if (adapter->flags & USING_MSI) { | |
| 2891 | + pci_disable_msi(adapter->pdev); | |
| 2892 | + adapter->flags &= ~USING_MSI; | |
| 2892 | 2893 | } |
| 2893 | 2894 | |
| 2894 | 2895 | err_free_dev: |
| @@ -1864,7 +1864,7 @@ static int process_responses(struct sge_rspq *rspq, int budget) · 1863 unmodified lines | ||
| 1864 | 1864 | * for new buffer pointers, refill the Free List. |
| 1865 | 1865 | */ |
| 1866 | 1866 | if (rspq->offset >= 0 && |
| 1867 | − rxq->fl.size - rxq->fl.avail >= 2*FL_PER_EQ_UNIT) | |
| 1867 | + fl_cap(&rxq->fl) - rxq->fl.avail >= 2*FL_PER_EQ_UNIT) | |
| 1868 | 1868 | __refill_fl(rspq->adapter, &rxq->fl); |
| 1869 | 1869 | return budget - budget_left; |
| 1870 | 1870 | } |
| @@ -2300,9 +2300,20 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, · 429 unmodified lines | ||
| 2300 | 2300 | FW_IQ_CMD_FL0HOSTFCMODE_V(SGE_HOSTFCMODE_NONE) | |
| 2301 | 2301 | FW_IQ_CMD_FL0PACKEN_F | |
| 2302 | 2302 | FW_IQ_CMD_FL0PADEN_F); |
| 2303 | + | |
| 2304 | + /* In T6, for egress queue type FL there is internal overhead | |
| 2305 | + * of 16B for header going into FLM module. Hence the maximum | |
| 2306 | + * allowed burst size is 448 bytes. For T4/T5, the hardware | |
| 2307 | + * doesn't coalesce fetch requests if more than 64 bytes of | |
| 2308 | + * Free List pointers are provided, so we use a 128-byte Fetch | |
| 2309 | + * Burst Minimum there (T6 implements coalescing so we can use | |
| 2310 | + * the smaller 64-byte value there). | |
| 2311 | + */ | |
| 2303 | 2312 | cmd.fl0dcaen_to_fl0cidxfthresh = |
| 2304 | 2313 | cpu_to_be16( |
| 2305 | − FW_IQ_CMD_FL0FBMIN_V(SGE_FETCHBURSTMIN_64B) | | |
| 2314 | + FW_IQ_CMD_FL0FBMIN_V(chip <= CHELSIO_T5 ? | |
| 2315 | + FETCHBURSTMIN_128B_X : | |
| 2316 | + FETCHBURSTMIN_64B_X) | | |
| 2306 | 2317 | FW_IQ_CMD_FL0FBMAX_V((chip <= CHELSIO_T5) ? |
| 2307 | 2318 | FETCHBURSTMAX_512B_X : |
| 2308 | 2319 | FETCHBURSTMAX_256B_X)); |
| @@ -2607,7 +2618,6 @@ int t4vf_sge_init(struct adapter *adapter) · 298 unmodified lines | ||
| 2607 | 2618 | u32 fl0 = sge_params->sge_fl_buffer_size[0]; |
| 2608 | 2619 | u32 fl1 = sge_params->sge_fl_buffer_size[1]; |
| 2609 | 2620 | struct sge *s = &adapter->sge; |
| 2610 | − unsigned int ingpadboundary, ingpackboundary, ingpad_shift; | |
| 2611 | 2621 | |
| 2612 | 2622 | /* |
| 2613 | 2623 | * Start by vetting the basic SGE parameters which have been set up by |
| @@ -2619,7 +2629,8 @@ int t4vf_sge_init(struct adapter *adapter) · 5 unmodified lines | ||
| 2619 | 2629 | fl0, fl1); |
| 2620 | 2630 | return -EINVAL; |
| 2621 | 2631 | } |
| 2622 | − if ((sge_params->sge_control & RXPKTCPLMODE_F) == 0) { | |
| 2632 | + if ((sge_params->sge_control & RXPKTCPLMODE_F) != | |
| 2633 | + RXPKTCPLMODE_V(RXPKTCPLMODE_SPLIT_X)) { | |
| 2623 | 2634 | dev_err(adapter->pdev_dev, "bad SGE CPL MODE\n"); |
| 2624 | 2635 | return -EINVAL; |
| 2625 | 2636 | } |
| @@ -2632,41 +2643,7 @@ int t4vf_sge_init(struct adapter *adapter) · 6 unmodified lines | ||
| 2632 | 2643 | s->stat_len = ((sge_params->sge_control & EGRSTATUSPAGESIZE_F) |
| 2633 | 2644 | ? 128 : 64); |
| 2634 | 2645 | s->pktshift = PKTSHIFT_G(sge_params->sge_control); |
| 2635 | − | |
| 2636 | − /* T4 uses a single control field to specify both the PCIe Padding and | |
| 2637 | − * Packing Boundary. T5 introduced the ability to specify these | |
| 2638 | − * separately. The actual Ingress Packet Data alignment boundary | |
| 2639 | − * within Packed Buffer Mode is the maximum of these two | |
| 2640 | − * specifications. (Note that it makes no real practical sense to | |
| 2641 | − * have the Pading Boudary be larger than the Packing Boundary but you | |
| 2642 | − * could set the chip up that way and, in fact, legacy T4 code would | |
| 2643 | − * end doing this because it would initialize the Padding Boundary and | |
| 2644 | − * leave the Packing Boundary initialized to 0 (16 bytes).) | |
| 2645 | − * Padding Boundary values in T6 starts from 8B, | |
| 2646 | − * where as it is 32B for T4 and T5. | |
| 2647 | − */ | |
| 2648 | − if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5) | |
| 2649 | − ingpad_shift = INGPADBOUNDARY_SHIFT_X; | |
| 2650 | − else | |
| 2651 | − ingpad_shift = T6_INGPADBOUNDARY_SHIFT_X; | |
| 2652 | − | |
| 2653 | − ingpadboundary = 1 << (INGPADBOUNDARY_G(sge_params->sge_control) + | |
| 2654 | − ingpad_shift); | |
| 2655 | − if (is_t4(adapter->params.chip)) { | |
| 2656 | − s->fl_align = ingpadboundary; | |
| 2657 | − } else { | |
| 2658 | − /* T5 has a different interpretation of one of the PCIe Packing | |
| 2659 | − * Boundary values. | |
| 2660 | − */ | |
| 2661 | − ingpackboundary = INGPACKBOUNDARY_G(sge_params->sge_control2); | |
| 2662 | − if (ingpackboundary == INGPACKBOUNDARY_16B_X) | |
| 2663 | − ingpackboundary = 16; | |
| 2664 | − else | |
| 2665 | − ingpackboundary = 1 << (ingpackboundary + | |
| 2666 | − INGPACKBOUNDARY_SHIFT_X); | |
| 2667 | − | |
| 2668 | − s->fl_align = max(ingpadboundary, ingpackboundary); | |
| 2669 | − } | |
| 2646 | + s->fl_align = t4vf_fl_pkt_align(adapter); | |
| 2670 | 2647 | |
| 2671 | 2648 | /* A FL with <= fl_starve_thres buffers is starving and a periodic |
| 2672 | 2649 | * timer will attempt to refill it. This needs to be larger than the |
| @@ -285,12 +285,31 @@ static inline int is_t4(enum chip_type chip) · 284 unmodified lines | ||
| 285 | 285 | return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4; |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | +/** | |
| 289 | + * hash_mac_addr - return the hash value of a MAC address | |
| 290 | + * @addr: the 48-bit Ethernet MAC address | |
| 291 | + * | |
| 292 | + * Hashes a MAC address according to the hash function used by hardware | |
| 293 | + * inexact (hash) address matching. | |
| 294 | + */ | |
| 295 | +static inline int hash_mac_addr(const u8 *addr) | |
| 296 | +{ | |
| 297 | + u32 a = ((u32)addr[0] << 16) | ((u32)addr[1] << 8) | addr[2]; | |
| 298 | + u32 b = ((u32)addr[3] << 16) | ((u32)addr[4] << 8) | addr[5]; | |
| 299 | + | |
| 300 | + a ^= b; | |
| 301 | + a ^= (a >> 12); | |
| 302 | + a ^= (a >> 6); | |
| 303 | + return a & 0x3f; | |
| 304 | +} | |
| 305 | + | |
| 288 | 306 | int t4vf_wait_dev_ready(struct adapter *); |
| 289 | 307 | int t4vf_port_init(struct adapter *, int); |
| 290 | 308 | |
| 291 | 309 | int t4vf_fw_reset(struct adapter *); |
| 292 | 310 | int t4vf_set_params(struct adapter *, unsigned int, const u32 *, const u32 *); |
| 293 | 311 | |
| 312 | +int t4vf_fl_pkt_align(struct adapter *adapter); | |
| 294 | 313 | enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS }; |
| 295 | 314 | int t4vf_bar2_sge_qregs(struct adapter *adapter, |
| 296 | 315 | unsigned int qid, |
| @@ -320,6 +339,8 @@ int t4vf_set_rxmode(struct adapter *, unsigned int, int, int, int, int, int, · 23 unmodified lines | ||
| 320 | 339 | bool); |
| 321 | 340 | int t4vf_alloc_mac_filt(struct adapter *, unsigned int, bool, unsigned int, |
| 322 | 341 | const u8 **, u16 *, u64 *, bool); |
| 342 | +int t4vf_free_mac_filt(struct adapter *, unsigned int, unsigned int naddr, | |
| 343 | + const u8 **, bool); | |
| 323 | 344 | int t4vf_change_mac(struct adapter *, unsigned int, int, const u8 *, bool); |
| 324 | 345 | int t4vf_set_addr_hash(struct adapter *, unsigned int, bool, u64, bool); |
| 325 | 346 | int t4vf_get_port_stats(struct adapter *, int, struct t4vf_port_stats *); |
| @@ -236,23 +236,6 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size, · 235 unmodified lines | ||
| 236 | 236 | return -ETIMEDOUT; |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | −/** | |
| 240 | − * hash_mac_addr - return the hash value of a MAC address | |
| 241 | − * @addr: the 48-bit Ethernet MAC address | |
| 242 | − * | |
| 243 | − * Hashes a MAC address according to the hash function used by hardware | |
| 244 | − * inexact (hash) address matching. | |
| 245 | − */ | |
| 246 | −static int hash_mac_addr(const u8 *addr) | |
| 247 | −{ | |
| 248 | − u32 a = ((u32)addr[0] << 16) | ((u32)addr[1] << 8) | addr[2]; | |
| 249 | − u32 b = ((u32)addr[3] << 16) | ((u32)addr[4] << 8) | addr[5]; | |
| 250 | − a ^= b; | |
| 251 | − a ^= (a >> 12); | |
| 252 | − a ^= (a >> 6); | |
| 253 | − return a & 0x3f; | |
| 254 | −} | |
| 255 | − | |
| 256 | 239 | #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ |
| 257 | 240 | FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \ |
| 258 | 241 | FW_PORT_CAP_SPEED_100G | FW_PORT_CAP_ANEG) |
| @@ -434,6 +417,61 @@ int t4vf_set_params(struct adapter *adapter, unsigned int nparams, · 175 unmodified lines | ||
| 434 | 417 | return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); |
| 435 | 418 | } |
| 436 | 419 | |
| 420 | +/** | |
| 421 | + * t4vf_fl_pkt_align - return the fl packet alignment | |
| 422 | + * @adapter: the adapter | |
| 423 | + * | |
| 424 | + * T4 has a single field to specify the packing and padding boundary. | |
| 425 | + * T5 onwards has separate fields for this and hence the alignment for | |
| 426 | + * next packet offset is maximum of these two. And T6 changes the | |
| 427 | + * Ingress Padding Boundary Shift, so it's all a mess and it's best | |
| 428 | + * if we put this in low-level Common Code ... | |
| 429 | + * | |
| 430 | + */ | |
| 431 | +int t4vf_fl_pkt_align(struct adapter *adapter) | |
| 432 | +{ | |
| 433 | + u32 sge_control, sge_control2; | |
| 434 | + unsigned int ingpadboundary, ingpackboundary, fl_align, ingpad_shift; | |
| 435 | + | |
| 436 | + sge_control = adapter->params.sge.sge_control; | |
| 437 | + | |
| 438 | + /* T4 uses a single control field to specify both the PCIe Padding and | |
| 439 | + * Packing Boundary. T5 introduced the ability to specify these | |
| 440 | + * separately. The actual Ingress Packet Data alignment boundary | |
| 441 | + * within Packed Buffer Mode is the maximum of these two | |
| 442 | + * specifications. (Note that it makes no real practical sense to | |
| 443 | + * have the Pading Boudary be larger than the Packing Boundary but you | |
| 444 | + * could set the chip up that way and, in fact, legacy T4 code would | |
| 445 | + * end doing this because it would initialize the Padding Boundary and | |
| 446 | + * leave the Packing Boundary initialized to 0 (16 bytes).) | |
| 447 | + * Padding Boundary values in T6 starts from 8B, | |
| 448 | + * where as it is 32B for T4 and T5. | |
| 449 | + */ | |
| 450 | + if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5) | |
| 451 | + ingpad_shift = INGPADBOUNDARY_SHIFT_X; | |
| 452 | + else | |
| 453 | + ingpad_shift = T6_INGPADBOUNDARY_SHIFT_X; | |
| 454 | + | |
| 455 | + ingpadboundary = 1 << (INGPADBOUNDARY_G(sge_control) + ingpad_shift); | |
| 456 | + | |
| 457 | + fl_align = ingpadboundary; | |
| 458 | + if (!is_t4(adapter->params.chip)) { | |
| 459 | + /* T5 has a different interpretation of one of the PCIe Packing | |
| 460 | + * Boundary values. | |
| 461 | + */ | |
| 462 | + sge_control2 = adapter->params.sge.sge_control2; | |
| 463 | + ingpackboundary = INGPACKBOUNDARY_G(sge_control2); | |
| 464 | + if (ingpackboundary == INGPACKBOUNDARY_16B_X) | |
| 465 | + ingpackboundary = 16; | |
| 466 | + else | |
| 467 | + ingpackboundary = 1 << (ingpackboundary + | |
| 468 | + INGPACKBOUNDARY_SHIFT_X); | |
| 469 | + | |
| 470 | + fl_align = max(ingpadboundary, ingpackboundary); | |
| 471 | + } | |
| 472 | + return fl_align; | |
| 473 | +} | |
| 474 | + | |
| 437 | 475 | /** |
| 438 | 476 | * t4vf_bar2_sge_qregs - return BAR2 SGE Queue register information |
| 439 | 477 | * @adapter: the adapter |
| @@ -1265,6 +1303,77 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free, · 825 unmodified lines | ||
| 1265 | 1303 | return ret; |
| 1266 | 1304 | } |
| 1267 | 1305 | |
| 1306 | +/** | |
| 1307 | + * t4vf_free_mac_filt - frees exact-match filters of given MAC addresses | |
| 1308 | + * @adapter: the adapter | |
| 1309 | + * @viid: the VI id | |
| 1310 | + * @naddr: the number of MAC addresses to allocate filters for (up to 7) | |
| 1311 | + * @addr: the MAC address(es) | |
| 1312 | + * @sleep_ok: call is allowed to sleep | |
| 1313 | + * | |
| 1314 | + * Frees the exact-match filter for each of the supplied addresses | |
| 1315 | + * | |
| 1316 | + * Returns a negative error number or the number of filters freed. | |
| 1317 | + */ | |
| 1318 | +int t4vf_free_mac_filt(struct adapter *adapter, unsigned int viid, | |
| 1319 | + unsigned int naddr, const u8 **addr, bool sleep_ok) | |
| 1320 | +{ | |
| 1321 | + int offset, ret = 0; | |
| 1322 | + struct fw_vi_mac_cmd cmd; | |
| 1323 | + unsigned int nfilters = 0; | |
| 1324 | + unsigned int max_naddr = adapter->params.arch.mps_tcam_size; | |
| 1325 | + unsigned int rem = naddr; | |
| 1326 | + | |
| 1327 | + if (naddr > max_naddr) | |
| 1328 | + return -EINVAL; | |
| 1329 | + | |
| 1330 | + for (offset = 0; offset < (int)naddr ; /**/) { | |
| 1331 | + unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact) ? | |
| 1332 | + rem : ARRAY_SIZE(cmd.u.exact)); | |
| 1333 | + size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd, | |
| 1334 | + u.exact[fw_naddr]), 16); | |
| 1335 | + struct fw_vi_mac_exact *p; | |
| 1336 | + int i; | |
| 1337 | + | |
| 1338 | + memset(&cmd, 0, sizeof(cmd)); | |
| 1339 | + cmd.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_MAC_CMD) | | |
| 1340 | + FW_CMD_REQUEST_F | | |
| 1341 | + FW_CMD_WRITE_F | | |
| 1342 | + FW_CMD_EXEC_V(0) | | |
| 1343 | + FW_VI_MAC_CMD_VIID_V(viid)); | |
| 1344 | + cmd.freemacs_to_len16 = | |
| 1345 | + cpu_to_be32(FW_VI_MAC_CMD_FREEMACS_V(0) | | |
| 1346 | + FW_CMD_LEN16_V(len16)); | |
| 1347 | + | |
| 1348 | + for (i = 0, p = cmd.u.exact; i < (int)fw_naddr; i++, p++) { | |
| 1349 | + p->valid_to_idx = cpu_to_be16( | |
| 1350 | + FW_VI_MAC_CMD_VALID_F | | |
| 1351 | + FW_VI_MAC_CMD_IDX_V(FW_VI_MAC_MAC_BASED_FREE)); | |
| 1352 | + memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr)); | |
| 1353 | + } | |
| 1354 | + | |
| 1355 | + ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &cmd, | |
| 1356 | + sleep_ok); | |
| 1357 | + if (ret) | |
| 1358 | + break; | |
| 1359 | + | |
| 1360 | + for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) { | |
| 1361 | + u16 index = FW_VI_MAC_CMD_IDX_G( | |
| 1362 | + be16_to_cpu(p->valid_to_idx)); | |
| 1363 | + | |
| 1364 | + if (index < max_naddr) | |
| 1365 | + nfilters++; | |
| 1366 | + } | |
| 1367 | + | |
| 1368 | + offset += fw_naddr; | |
| 1369 | + rem -= fw_naddr; | |
| 1370 | + } | |
| 1371 | + | |
| 1372 | + if (ret == 0) | |
| 1373 | + ret = nfilters; | |
| 1374 | + return ret; | |
| 1375 | +} | |
| 1376 | + | |
| 1268 | 1377 | /** |
| 1269 | 1378 | * t4vf_change_mac - modifies the exact-match filter for a MAC address |
| 1270 | 1379 | * @adapter: the adapter |
| @@ -201,16 +201,20 @@ static inline struct net_device *vnic_get_netdev(struct vnic_dev *vdev) · 200 unmodified lines | ||
| 201 | 201 | } |
| 202 | 202 | |
| 203 | 203 | /* wrappers function for kernel log |
| 204 | − * Make sure variable vdev of struct vnic_dev is available in the block where | |
| 205 | − * these macros are used | |
| 206 | 204 | */ |
| 207 | −#define vdev_info(args...) dev_info(&vdev->pdev->dev, args) | |
| 208 | −#define vdev_warn(args...) dev_warn(&vdev->pdev->dev, args) | |
| 209 | −#define vdev_err(args...) dev_err(&vdev->pdev->dev, args) | |
| 210 | − | |
| 211 | −#define vdev_netinfo(args...) netdev_info(vnic_get_netdev(vdev), args) | |
| 212 | −#define vdev_netwarn(args...) netdev_warn(vnic_get_netdev(vdev), args) | |
| 213 | −#define vdev_neterr(args...) netdev_err(vnic_get_netdev(vdev), args) | |
| 205 | +#define vdev_err(vdev, fmt, ...) \ | |
| 206 | + dev_err(&(vdev)->pdev->dev, fmt, ##__VA_ARGS__) | |
| 207 | +#define vdev_warn(vdev, fmt, ...) \ | |
| 208 | + dev_warn(&(vdev)->pdev->dev, fmt, ##__VA_ARGS__) | |
| 209 | +#define vdev_info(vdev, fmt, ...) \ | |
| 210 | + dev_info(&(vdev)->pdev->dev, fmt, ##__VA_ARGS__) | |
| 211 | + | |
| 212 | +#define vdev_neterr(vdev, fmt, ...) \ | |
| 213 | + netdev_err(vnic_get_netdev(vdev), fmt, ##__VA_ARGS__) | |
| 214 | +#define vdev_netwarn(vdev, fmt, ...) \ | |
| 215 | + netdev_warn(vnic_get_netdev(vdev), fmt, ##__VA_ARGS__) | |
| 216 | +#define vdev_netinfo(vdev, fmt, ...) \ | |
| 217 | + netdev_info(vnic_get_netdev(vdev), fmt, ##__VA_ARGS__) | |
| 214 | 218 | |
| 215 | 219 | static inline struct device *enic_get_dev(struct enic *enic) |
| 216 | 220 | { |
| @@ -43,7 +43,7 @@ int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index, · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | cq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_CQ, index); |
| 45 | 45 | if (!cq->ctrl) { |
| 46 | − vdev_err("Failed to hook CQ[%d] resource\n", index); | |
| 46 | + vdev_err(vdev, "Failed to hook CQ[%d] resource\n", index); | |
| 47 | 47 | return -EINVAL; |
| 48 | 48 | } |
| 49 | 49 | |
| @@ -53,14 +53,14 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, · 52 unmodified lines | ||
| 53 | 53 | return -EINVAL; |
| 54 | 54 | |
| 55 | 55 | if (bar->len < VNIC_MAX_RES_HDR_SIZE) { |
| 56 | − vdev_err("vNIC BAR0 res hdr length error\n"); | |
| 56 | + vdev_err(vdev, "vNIC BAR0 res hdr length error\n"); | |
| 57 | 57 | return -EINVAL; |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | rh = bar->vaddr; |
| 61 | 61 | mrh = bar->vaddr; |
| 62 | 62 | if (!rh) { |
| 63 | − vdev_err("vNIC BAR0 res hdr not mem-mapped\n"); | |
| 63 | + vdev_err(vdev, "vNIC BAR0 res hdr not mem-mapped\n"); | |
| 64 | 64 | return -EINVAL; |
| 65 | 65 | } |
| 66 | 66 | |
| @@ -69,7 +69,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, · 2 unmodified lines | ||
| 69 | 69 | (ioread32(&rh->version) != VNIC_RES_VERSION)) { |
| 70 | 70 | if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) || |
| 71 | 71 | (ioread32(&mrh->version) != MGMTVNIC_VERSION)) { |
| 72 | − vdev_err("vNIC BAR0 res magic/version error exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n", | |
| 72 | + vdev_err(vdev, "vNIC BAR0 res magic/version error exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n", | |
| 73 | 73 | VNIC_RES_MAGIC, VNIC_RES_VERSION, |
| 74 | 74 | MGMTVNIC_MAGIC, MGMTVNIC_VERSION, |
| 75 | 75 | ioread32(&rh->magic), ioread32(&rh->version)); |
| @@ -106,7 +106,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, · 30 unmodified lines | ||
| 106 | 106 | /* each count is stride bytes long */ |
| 107 | 107 | len = count * VNIC_RES_STRIDE; |
| 108 | 108 | if (len + bar_offset > bar[bar_num].len) { |
| 109 | − vdev_err("vNIC BAR0 resource %d out-of-bounds, offset 0x%x + size 0x%x > bar len 0x%lx\n", | |
| 109 | + vdev_err(vdev, "vNIC BAR0 resource %d out-of-bounds, offset 0x%x + size 0x%x > bar len 0x%lx\n", | |
| 110 | 110 | type, bar_offset, len, |
| 111 | 111 | bar[bar_num].len); |
| 112 | 112 | return -EINVAL; |
| @@ -198,7 +198,7 @@ int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring, · 85 unmodified lines | ||
| 198 | 198 | &ring->base_addr_unaligned); |
| 199 | 199 | |
| 200 | 200 | if (!ring->descs_unaligned) { |
| 201 | − vdev_err("Failed to allocate ring (size=%d), aborting\n", | |
| 201 | + vdev_err(vdev, "Failed to allocate ring (size=%d), aborting\n", | |
| 202 | 202 | (int)ring->size); |
| 203 | 203 | return -ENOMEM; |
| 204 | 204 | } |
| @@ -241,7 +241,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, · 36 unmodified lines | ||
| 241 | 241 | return -ENODEV; |
| 242 | 242 | } |
| 243 | 243 | if (status & STAT_BUSY) { |
| 244 | − vdev_neterr("Busy devcmd %d\n", _CMD_N(cmd)); | |
| 244 | + vdev_neterr(vdev, "Busy devcmd %d\n", _CMD_N(cmd)); | |
| 245 | 245 | return -EBUSY; |
| 246 | 246 | } |
| 247 | 247 | |
| @@ -275,7 +275,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, · 27 unmodified lines | ||
| 275 | 275 | return -err; |
| 276 | 276 | if (err != ERR_ECMDUNKNOWN || |
| 277 | 277 | cmd != CMD_CAPABILITY) |
| 278 | − vdev_neterr("Error %d devcmd %d\n", | |
| 278 | + vdev_neterr(vdev, "Error %d devcmd %d\n", | |
| 279 | 279 | err, _CMD_N(cmd)); |
| 280 | 280 | return -err; |
| 281 | 281 | } |
| @@ -290,7 +290,7 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, · 8 unmodified lines | ||
| 290 | 290 | } |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | − vdev_neterr("Timedout devcmd %d\n", _CMD_N(cmd)); | |
| 293 | + vdev_neterr(vdev, "Timedout devcmd %d\n", _CMD_N(cmd)); | |
| 294 | 294 | return -ETIMEDOUT; |
| 295 | 295 | } |
| 296 | 296 | |
| @@ -313,7 +313,7 @@ static int _vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, · 16 unmodified lines | ||
| 313 | 313 | new_posted = (posted + 1) % DEVCMD2_RING_SIZE; |
| 314 | 314 | |
| 315 | 315 | if (new_posted == fetch_index) { |
| 316 | − vdev_neterr("devcmd2 %d: wq is full. fetch index: %u, posted index: %u\n", | |
| 316 | + vdev_neterr(vdev, "devcmd2 %d: wq is full. fetch index: %u, posted index: %u\n", | |
| 317 | 317 | _CMD_N(cmd), fetch_index, posted); |
| 318 | 318 | return -EBUSY; |
| 319 | 319 | } |
| @@ -352,7 +352,7 @@ static int _vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, · 32 unmodified lines | ||
| 352 | 352 | err = result->error; |
| 353 | 353 | if (err != ERR_ECMDUNKNOWN || |
| 354 | 354 | cmd != CMD_CAPABILITY) |
| 355 | − vdev_neterr("Error %d devcmd %d\n", | |
| 355 | + vdev_neterr(vdev, "Error %d devcmd %d\n", | |
| 356 | 356 | err, _CMD_N(cmd)); |
| 357 | 357 | return -err; |
| 358 | 358 | } |
| @@ -365,7 +365,7 @@ static int _vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, · 6 unmodified lines | ||
| 365 | 365 | udelay(100); |
| 366 | 366 | } |
| 367 | 367 | |
| 368 | − vdev_neterr("devcmd %d timed out\n", _CMD_N(cmd)); | |
| 368 | + vdev_neterr(vdev, "devcmd %d timed out\n", _CMD_N(cmd)); | |
| 369 | 369 | |
| 370 | 370 | return -ETIMEDOUT; |
| 371 | 371 | } |
| @@ -401,7 +401,7 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev) · 29 unmodified lines | ||
| 401 | 401 | |
| 402 | 402 | fetch_index = ioread32(&vdev->devcmd2->wq.ctrl->fetch_index); |
| 403 | 403 | if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone */ |
| 404 | − vdev_err("Fatal error in devcmd2 init - hardware surprise removal"); | |
| 404 | + vdev_err(vdev, "Fatal error in devcmd2 init - hardware surprise removal\n"); | |
| 405 | 405 | |
| 406 | 406 | return -ENODEV; |
| 407 | 407 | } |
| @@ -474,8 +474,8 @@ static int vnic_dev_cmd_proxy(struct vnic_dev *vdev, · 66 unmodified lines | ||
| 474 | 474 | err = (int)vdev->args[1]; |
| 475 | 475 | if (err != ERR_ECMDUNKNOWN || |
| 476 | 476 | cmd != CMD_CAPABILITY) |
| 477 | − vdev_neterr("Error %d proxy devcmd %d\n", err, | |
| 478 | − _CMD_N(cmd)); | |
| 477 | + vdev_neterr(vdev, "Error %d proxy devcmd %d\n", | |
| 478 | + err, _CMD_N(cmd)); | |
| 479 | 479 | return err; |
| 480 | 480 | } |
| 481 | 481 | |
| @@ -768,7 +768,7 @@ int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, · 286 unmodified lines | ||
| 768 | 768 | |
| 769 | 769 | err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait); |
| 770 | 770 | if (err) |
| 771 | − vdev_neterr("Can't set packet filter\n"); | |
| 771 | + vdev_neterr(vdev, "Can't set packet filter\n"); | |
| 772 | 772 | |
| 773 | 773 | return err; |
| 774 | 774 | } |
| @@ -785,7 +785,7 @@ int vnic_dev_add_addr(struct vnic_dev *vdev, const u8 *addr) · 10 unmodified lines | ||
| 785 | 785 | |
| 786 | 786 | err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); |
| 787 | 787 | if (err) |
| 788 | − vdev_neterr("Can't add addr [%pM], %d\n", addr, err); | |
| 788 | + vdev_neterr(vdev, "Can't add addr [%pM], %d\n", addr, err); | |
| 789 | 789 | |
| 790 | 790 | return err; |
| 791 | 791 | } |
| @@ -802,7 +802,7 @@ int vnic_dev_del_addr(struct vnic_dev *vdev, const u8 *addr) · 10 unmodified lines | ||
| 802 | 802 | |
| 803 | 803 | err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); |
| 804 | 804 | if (err) |
| 805 | − vdev_neterr("Can't del addr [%pM], %d\n", addr, err); | |
| 805 | + vdev_neterr(vdev, "Can't del addr [%pM], %d\n", addr, err); | |
| 806 | 806 | |
| 807 | 807 | return err; |
| 808 | 808 | } |
| @@ -846,7 +846,8 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) · 37 unmodified lines | ||
| 846 | 846 | dma_addr_t notify_pa; |
| 847 | 847 | |
| 848 | 848 | if (vdev->notify || vdev->notify_pa) { |
| 849 | − vdev_neterr("notify block %p still allocated", vdev->notify); | |
| 849 | + vdev_neterr(vdev, "notify block %p still allocated\n", | |
| 850 | + vdev->notify); | |
| 850 | 851 | return -EINVAL; |
| 851 | 852 | } |
| 852 | 853 | |
| @@ -965,7 +966,7 @@ int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev) · 112 unmodified lines | ||
| 965 | 966 | */ |
| 966 | 967 | if ((err == ERR_ECMDUNKNOWN) || |
| 967 | 968 | (!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) { |
| 968 | − vdev_netwarn("Using default conversion factor for interrupt coalesce timer\n"); | |
| 969 | + vdev_netwarn(vdev, "Using default conversion factor for interrupt coalesce timer\n"); | |
| 969 | 970 | vnic_dev_intr_coal_timer_info_default(vdev); |
| 970 | 971 | return 0; |
| 971 | 972 | } |
| @@ -1103,16 +1104,16 @@ int vnic_devcmd_init(struct vnic_dev *vdev) · 131 unmodified lines | ||
| 1103 | 1104 | if (res) { |
| 1104 | 1105 | err = vnic_dev_init_devcmd2(vdev); |
| 1105 | 1106 | if (err) |
| 1106 | − vdev_warn("DEVCMD2 init failed: %d, Using DEVCMD1", | |
| 1107 | + vdev_warn(vdev, "DEVCMD2 init failed: %d, Using DEVCMD1\n", | |
| 1107 | 1108 | err); |
| 1108 | 1109 | else |
| 1109 | 1110 | return 0; |
| 1110 | 1111 | } else { |
| 1111 | − vdev_warn("DEVCMD2 resource not found (old firmware?) Using DEVCMD1\n"); | |
| 1112 | + vdev_warn(vdev, "DEVCMD2 resource not found (old firmware?) Using DEVCMD1\n"); | |
| 1112 | 1113 | } |
| 1113 | 1114 | err = vnic_dev_init_devcmd1(vdev); |
| 1114 | 1115 | if (err) |
| 1115 | − vdev_err("DEVCMD1 initialization failed: %d", err); | |
| 1116 | + vdev_err(vdev, "DEVCMD1 initialization failed: %d\n", err); | |
| 1116 | 1117 | |
| 1117 | 1118 | return err; |
| 1118 | 1119 | } |
| @@ -40,7 +40,8 @@ int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | intr->ctrl = vnic_dev_get_res(vdev, RES_TYPE_INTR_CTRL, index); |
| 42 | 42 | if (!intr->ctrl) { |
| 43 | − vdev_err("Failed to hook INTR[%d].ctrl resource\n", index); | |
| 43 | + vdev_err(vdev, "Failed to hook INTR[%d].ctrl resource\n", | |
| 44 | + index); | |
| 44 | 45 | return -EINVAL; |
| 45 | 46 | } |
| 46 | 47 | |
| @@ -92,7 +92,7 @@ int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, · 91 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | rq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_RQ, index); |
| 94 | 94 | if (!rq->ctrl) { |
| 95 | − vdev_err("Failed to hook RQ[%d] resource\n", index); | |
| 95 | + vdev_err(vdev, "Failed to hook RQ[%d] resource\n", index); | |
| 96 | 96 | return -EINVAL; |
| 97 | 97 | } |
| 98 | 98 | |
| @@ -179,7 +179,7 @@ int vnic_rq_disable(struct vnic_rq *rq) · 80 unmodified lines | ||
| 179 | 179 | udelay(10); |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | − vdev_neterr("Failed to disable RQ[%d]\n", rq->index); | |
| 182 | + vdev_neterr(vdev, "Failed to disable RQ[%d]\n", rq->index); | |
| 183 | 183 | |
| 184 | 184 | return -ETIMEDOUT; |
| 185 | 185 | } |
| @@ -95,7 +95,7 @@ int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, · 94 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | wq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_WQ, index); |
| 97 | 97 | if (!wq->ctrl) { |
| 98 | − vdev_err("Failed to hook WQ[%d] resource\n", index); | |
| 98 | + vdev_err(vdev, "Failed to hook WQ[%d] resource\n", index); | |
| 99 | 99 | return -EINVAL; |
| 100 | 100 | } |
| 101 | 101 | |
| @@ -187,7 +187,7 @@ int vnic_wq_disable(struct vnic_wq *wq) · 85 unmodified lines | ||
| 187 | 187 | udelay(10); |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | − vdev_neterr("Failed to disable WQ[%d]\n", wq->index); | |
| 190 | + vdev_neterr(vdev, "Failed to disable WQ[%d]\n", wq->index); | |
| 191 | 191 | |
| 192 | 192 | return -ETIMEDOUT; |
| 193 | 193 | } |
| @@ -505,9 +505,7 @@ media_picked: · 504 unmodified lines | ||
| 505 | 505 | tp->timer.expires = RUN_AT(next_tick); |
| 506 | 506 | add_timer(&tp->timer); |
| 507 | 507 | #ifdef CONFIG_TULIP_NAPI |
| 508 | − init_timer(&tp->oom_timer); | |
| 509 | − tp->oom_timer.data = (unsigned long)dev; | |
| 510 | − tp->oom_timer.function = oom_timer; | |
| 508 | + setup_timer(&tp->oom_timer, oom_timer, (unsigned long)dev); | |
| 511 | 509 | #endif |
| 512 | 510 | } |
| 513 | 511 | |
| @@ -782,9 +780,8 @@ static void tulip_down (struct net_device *dev) · 268 unmodified lines | ||
| 782 | 780 | |
| 783 | 781 | spin_unlock_irqrestore (&tp->lock, flags); |
| 784 | 782 | |
| 785 | − init_timer(&tp->timer); | |
| 786 | − tp->timer.data = (unsigned long)dev; | |
| 787 | − tp->timer.function = tulip_tbl[tp->chip_id].media_timer; | |
| 783 | + setup_timer(&tp->timer, tulip_tbl[tp->chip_id].media_timer, | |
| 784 | + (unsigned long)dev); | |
| 788 | 785 | |
| 789 | 786 | dev->if_port = tp->saved_if_port; |
| 790 | 787 | |
| @@ -1475,9 +1472,8 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) · 684 unmodified lines | ||
| 1475 | 1472 | tp->csr0 = csr0; |
| 1476 | 1473 | spin_lock_init(&tp->lock); |
| 1477 | 1474 | spin_lock_init(&tp->mii_lock); |
| 1478 | − init_timer(&tp->timer); | |
| 1479 | − tp->timer.data = (unsigned long)dev; | |
| 1480 | − tp->timer.function = tulip_tbl[tp->chip_id].media_timer; | |
| 1475 | + setup_timer(&tp->timer, tulip_tbl[tp->chip_id].media_timer, | |
| 1476 | + (unsigned long)dev); | |
| 1481 | 1477 | |
| 1482 | 1478 | INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task); |
| 1483 | 1479 | |
| @@ -72,6 +72,9 @@ · 71 unmodified lines | ||
| 72 | 72 | #define BE_MAX_MTU (BE_MAX_JUMBO_FRAME_SIZE - \ |
| 73 | 73 | (ETH_HLEN + ETH_FCS_LEN)) |
| 74 | 74 | |
| 75 | +/* Accommodate for QnQ configurations where VLAN insertion is enabled in HW */ | |
| 76 | +#define BE_MAX_GSO_SIZE (65535 - 2 * VLAN_HLEN) | |
| 77 | + | |
| 75 | 78 | #define BE_NUM_VLANS_SUPPORTED 64 |
| 76 | 79 | #define BE_MAX_EQD 128u |
| 77 | 80 | #define BE_MAX_TX_FRAG_COUNT 30 |
| @@ -89,6 +92,10 @@ · 11 unmodified lines | ||
| 89 | 92 | #define BE3_MAX_TX_QS 16 |
| 90 | 93 | #define BE3_MAX_EVT_QS 16 |
| 91 | 94 | #define BE3_SRIOV_MAX_EVT_QS 8 |
| 95 | +#define SH_VF_MAX_NIC_EQS 3 /* Skyhawk VFs can have a max of 4 EQs | |
| 96 | + * and at least 1 is granted to either | |
| 97 | + * SURF/DPDK | |
| 98 | + */ | |
| 92 | 99 | |
| 93 | 100 | #define MAX_RSS_IFACES 15 |
| 94 | 101 | #define MAX_RX_QS 32 |
| @@ -111,6 +118,8 @@ · 16 unmodified lines | ||
| 111 | 118 | #define RSS_INDIR_TABLE_LEN 128 |
| 112 | 119 | #define RSS_HASH_KEY_LEN 40 |
| 113 | 120 | |
| 121 | +#define BE_UNKNOWN_PHY_STATE 0xFF | |
| 122 | + | |
| 114 | 123 | struct be_dma_mem { |
| 115 | 124 | void *va; |
| 116 | 125 | dma_addr_t dma; |
| @@ -118,27 +127,27 @@ struct be_dma_mem { · 1 unmodified line | ||
| 118 | 127 | }; |
| 119 | 128 | |
| 120 | 129 | struct be_queue_info { |
| 130 | + u32 len; | |
| 131 | + u32 entry_size; /* Size of an element in the queue */ | |
| 132 | + u32 tail, head; | |
| 133 | + atomic_t used; /* Number of valid elements in the queue */ | |
| 134 | + u32 id; | |
| 121 | 135 | struct be_dma_mem dma_mem; |
| 122 | − u16 len; | |
| 123 | − u16 entry_size; /* Size of an element in the queue */ | |
| 124 | − u16 id; | |
| 125 | − u16 tail, head; | |
| 126 | 136 | bool created; |
| 127 | − atomic_t used; /* Number of valid elements in the queue */ | |
| 128 | 137 | }; |
| 129 | 138 | |
| 130 | −static inline u32 MODULO(u16 val, u16 limit) | |
| 139 | +static inline u32 MODULO(u32 val, u32 limit) | |
| 131 | 140 | { |
| 132 | 141 | BUG_ON(limit & (limit - 1)); |
| 133 | 142 | return val & (limit - 1); |
| 134 | 143 | } |
| 135 | 144 | |
| 136 | −static inline void index_adv(u16 *index, u16 val, u16 limit) | |
| 145 | +static inline void index_adv(u32 *index, u32 val, u32 limit) | |
| 137 | 146 | { |
| 138 | 147 | *index = MODULO((*index + val), limit); |
| 139 | 148 | } |
| 140 | 149 | |
| 141 | −static inline void index_inc(u16 *index, u16 limit) | |
| 150 | +static inline void index_inc(u32 *index, u32 limit) | |
| 142 | 151 | { |
| 143 | 152 | *index = MODULO((*index + 1), limit); |
| 144 | 153 | } |
| @@ -163,7 +172,7 @@ static inline void queue_head_inc(struct be_queue_info *q) · 18 unmodified lines | ||
| 163 | 172 | index_inc(&q->head, q->len); |
| 164 | 173 | } |
| 165 | 174 | |
| 166 | −static inline void index_dec(u16 *index, u16 limit) | |
| 175 | +static inline void index_dec(u32 *index, u32 limit) | |
| 167 | 176 | { |
| 168 | 177 | *index = MODULO((*index - 1), limit); |
| 169 | 178 | } |
| @@ -386,13 +395,17 @@ enum vf_state { · 216 unmodified lines | ||
| 386 | 395 | #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD BIT(7) |
| 387 | 396 | #define BE_FLAGS_VXLAN_OFFLOADS BIT(8) |
| 388 | 397 | #define BE_FLAGS_SETUP_DONE BIT(9) |
| 389 | −#define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10) | |
| 398 | +#define BE_FLAGS_PHY_MISCONFIGURED BIT(10) | |
| 390 | 399 | #define BE_FLAGS_ERR_DETECTION_SCHEDULED BIT(11) |
| 391 | 400 | #define BE_FLAGS_OS2BMC BIT(12) |
| 392 | 401 | |
| 393 | 402 | #define BE_UC_PMAC_COUNT 30 |
| 394 | 403 | #define BE_VF_UC_PMAC_COUNT 2 |
| 395 | 404 | |
| 405 | +#define MAX_ERR_RECOVERY_RETRY_COUNT 3 | |
| 406 | +#define ERR_DETECTION_DELAY 1000 | |
| 407 | +#define ERR_RECOVERY_RETRY_DELAY 30000 | |
| 408 | + | |
| 396 | 409 | /* Ethtool set_dump flags */ |
| 397 | 410 | #define LANCER_INITIATE_FW_DUMP 0x1 |
| 398 | 411 | #define LANCER_DELETE_FW_DUMP 0x2 |
| @@ -530,6 +543,7 @@ struct be_adapter { · 131 unmodified lines | ||
| 530 | 543 | u16 work_counter; |
| 531 | 544 | |
| 532 | 545 | struct delayed_work be_err_detection_work; |
| 546 | + u8 recovery_retries; | |
| 533 | 547 | u8 err_flags; |
| 534 | 548 | bool pcicfg_mapped; /* pcicfg obtained via pci_iomap() */ |
| 535 | 549 | u32 flags; |
| @@ -595,6 +609,7 @@ struct be_adapter { · 59 unmodified lines | ||
| 595 | 609 | u32 bmc_filt_mask; |
| 596 | 610 | u32 fat_dump_len; |
| 597 | 611 | u16 serial_num[CNTL_SERIAL_NUM_WORDS]; |
| 612 | + u8 phy_state; /* state of sfp optics (functional, faulted, etc.,) */ | |
| 598 | 613 | }; |
| 599 | 614 | |
| 600 | 615 | #define be_physfn(adapter) (!adapter->virtfn) |
| @@ -19,19 +19,25 @@ · 18 unmodified lines | ||
| 19 | 19 | #include "be.h" |
| 20 | 20 | #include "be_cmds.h" |
| 21 | 21 | |
| 22 | −static char *be_port_misconfig_evt_desc[] = { | |
| 23 | − "A valid SFP module detected", | |
| 24 | − "Optics faulted/ incorrectly installed/ not installed.", | |
| 25 | − "Optics of two types installed.", | |
| 26 | − "Incompatible optics.", | |
| 27 | − "Unknown port SFP status" | |
| 22 | +char *be_misconfig_evt_port_state[] = { | |
| 23 | + "Physical Link is functional", | |
| 24 | + "Optics faulted/incorrectly installed/not installed - Reseat optics. If issue not resolved, replace.", | |
| 25 | + "Optics of two types installed – Remove one optic or install matching pair of optics.", | |
| 26 | + "Incompatible optics – Replace with compatible optics for card to function.", | |
| 27 | + "Unqualified optics – Replace with Avago optics for Warranty and Technical Support.", | |
| 28 | + "Uncertified optics – Replace with Avago-certified optics to enable link operation." | |
| 28 | 29 | }; |
| 29 | 30 | |
| 30 | −static char *be_port_misconfig_remedy_desc[] = { | |
| 31 | − "", | |
| 32 | − "Reseat optics. If issue not resolved, replace", | |
| 33 | − "Remove one optic or install matching pair of optics", | |
| 34 | − "Replace with compatible optics for card to function", | |
| 31 | +static char *be_port_misconfig_evt_severity[] = { | |
| 32 | + "KERN_WARN", | |
| 33 | + "KERN_INFO", | |
| 34 | + "KERN_ERR", | |
| 35 | + "KERN_WARN" | |
| 36 | +}; | |
| 37 | + | |
| 38 | +static char *phy_state_oper_desc[] = { | |
| 39 | + "Link is non-operational", | |
| 40 | + "Link is operational", | |
| 35 | 41 | "" |
| 36 | 42 | }; |
| 37 | 43 | |
| @@ -65,7 +71,22 @@ static struct be_cmd_priv_map cmd_priv_map[] = { · 27 unmodified lines | ||
| 65 | 71 | CMD_SUBSYSTEM_COMMON, |
| 66 | 72 | BE_PRIV_LNKMGMT | BE_PRIV_VHADM | |
| 67 | 73 | BE_PRIV_DEVCFG | BE_PRIV_DEVSEC |
| 68 | − } | |
| 74 | + }, | |
| 75 | + { | |
| 76 | + OPCODE_LOWLEVEL_HOST_DDR_DMA, | |
| 77 | + CMD_SUBSYSTEM_LOWLEVEL, | |
| 78 | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC | |
| 79 | + }, | |
| 80 | + { | |
| 81 | + OPCODE_LOWLEVEL_LOOPBACK_TEST, | |
| 82 | + CMD_SUBSYSTEM_LOWLEVEL, | |
| 83 | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC | |
| 84 | + }, | |
| 85 | + { | |
| 86 | + OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, | |
| 87 | + CMD_SUBSYSTEM_LOWLEVEL, | |
| 88 | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC | |
| 89 | + }, | |
| 69 | 90 | }; |
| 70 | 91 | |
| 71 | 92 | static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem) |
| @@ -236,7 +257,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, · 164 unmodified lines | ||
| 236 | 257 | |
| 237 | 258 | if (base_status != MCC_STATUS_SUCCESS && |
| 238 | 259 | !be_skip_err_log(opcode, base_status, addl_status)) { |
| 239 | − if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { | |
| 260 | + if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST || | |
| 261 | + addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) { | |
| 240 | 262 | dev_warn(&adapter->pdev->dev, |
| 241 | 263 | "VF is not privileged to issue opcode %d-%d\n", |
| 242 | 264 | opcode, subsystem); |
| @@ -281,22 +303,56 @@ static void be_async_port_misconfig_event_process(struct be_adapter *adapter, · 38 unmodified lines | ||
| 281 | 303 | { |
| 282 | 304 | struct be_async_event_misconfig_port *evt = |
| 283 | 305 | (struct be_async_event_misconfig_port *)compl; |
| 284 | − u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1); | |
| 306 | + u32 sfp_misconfig_evt_word1 = le32_to_cpu(evt->event_data_word1); | |
| 307 | + u32 sfp_misconfig_evt_word2 = le32_to_cpu(evt->event_data_word2); | |
| 308 | + u8 phy_oper_state = PHY_STATE_OPER_MSG_NONE; | |
| 285 | 309 | struct device *dev = &adapter->pdev->dev; |
| 286 | − u8 port_misconfig_evt; | |
| 310 | + u8 msg_severity = DEFAULT_MSG_SEVERITY; | |
| 311 | + u8 phy_state_info; | |
| 312 | + u8 new_phy_state; | |
| 313 | + | |
| 314 | + new_phy_state = | |
| 315 | + (sfp_misconfig_evt_word1 >> (adapter->hba_port_num * 8)) & 0xff; | |
| 316 | + | |
| 317 | + if (new_phy_state == adapter->phy_state) | |
| 318 | + return; | |
| 319 | + | |
| 320 | + adapter->phy_state = new_phy_state; | |
| 321 | + | |
| 322 | + /* for older fw that doesn't populate link effect data */ | |
| 323 | + if (!sfp_misconfig_evt_word2) | |
| 324 | + goto log_message; | |
| 287 | 325 | |
| 288 | − port_misconfig_evt = | |
| 289 | − ((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff); | |
| 326 | + phy_state_info = | |
| 327 | + (sfp_misconfig_evt_word2 >> (adapter->hba_port_num * 8)) & 0xff; | |
| 290 | 328 | |
| 329 | + if (phy_state_info & PHY_STATE_INFO_VALID) { | |
| 330 | + msg_severity = (phy_state_info & PHY_STATE_MSG_SEVERITY) >> 1; | |
| 331 | + | |
| 332 | + if (be_phy_unqualified(new_phy_state)) | |
| 333 | + phy_oper_state = (phy_state_info & PHY_STATE_OPER); | |
| 334 | + } | |
| 335 | + | |
| 336 | +log_message: | |
| 291 | 337 | /* Log an error message that would allow a user to determine |
| 292 | 338 | * whether the SFPs have an issue |
| 293 | 339 | */ |
| 294 | − dev_info(dev, "Port %c: %s %s", adapter->port_name, | |
| 295 | − be_port_misconfig_evt_desc[port_misconfig_evt], | |
| 296 | − be_port_misconfig_remedy_desc[port_misconfig_evt]); | |
| 340 | + if (be_phy_state_unknown(new_phy_state)) | |
| 341 | + dev_printk(be_port_misconfig_evt_severity[msg_severity], dev, | |
| 342 | + "Port %c: Unrecognized Optics state: 0x%x. %s", | |
| 343 | + adapter->port_name, | |
| 344 | + new_phy_state, | |
| 345 | + phy_state_oper_desc[phy_oper_state]); | |
| 346 | + else | |
| 347 | + dev_printk(be_port_misconfig_evt_severity[msg_severity], dev, | |
| 348 | + "Port %c: %s %s", | |
| 349 | + adapter->port_name, | |
| 350 | + be_misconfig_evt_port_state[new_phy_state], | |
| 351 | + phy_state_oper_desc[phy_oper_state]); | |
| 297 | 352 | |
| 298 | − if (port_misconfig_evt == INCOMPATIBLE_SFP) | |
| 299 | − adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP; | |
| 353 | + /* Log Vendor name and part no. if a misconfigured SFP is detected */ | |
| 354 | + if (be_phy_misconfigured(new_phy_state)) | |
| 355 | + adapter->flags |= BE_FLAGS_PHY_MISCONFIGURED; | |
| 300 | 356 | } |
| 301 | 357 | |
| 302 | 358 | /* Grp5 CoS Priority evt */ |
| @@ -540,7 +596,7 @@ static int be_mcc_notify_wait(struct be_adapter *adapter) · 237 unmodified lines | ||
| 540 | 596 | int status; |
| 541 | 597 | struct be_mcc_wrb *wrb; |
| 542 | 598 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; |
| 543 | − u16 index = mcc_obj->q.head; | |
| 599 | + u32 index = mcc_obj->q.head; | |
| 544 | 600 | struct be_cmd_resp_hdr *resp; |
| 545 | 601 | |
| 546 | 602 | index_dec(&index, mcc_obj->q.len); |
| @@ -1497,34 +1553,25 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, · 950 unmodified lines | ||
| 1497 | 1553 | return status; |
| 1498 | 1554 | } |
| 1499 | 1555 | |
| 1500 | −/* Uses MCCQ */ | |
| 1556 | +/* Uses MCCQ if available else MBOX */ | |
| 1501 | 1557 | int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) |
| 1502 | 1558 | { |
| 1503 | − struct be_mcc_wrb *wrb; | |
| 1559 | + struct be_mcc_wrb wrb = {0}; | |
| 1504 | 1560 | struct be_cmd_req_if_destroy *req; |
| 1505 | 1561 | int status; |
| 1506 | 1562 | |
| 1507 | 1563 | if (interface_id == -1) |
| 1508 | 1564 | return 0; |
| 1509 | 1565 | |
| 1510 | − spin_lock_bh(&adapter->mcc_lock); | |
| 1511 | − | |
| 1512 | − wrb = wrb_from_mccq(adapter); | |
| 1513 | − if (!wrb) { | |
| 1514 | − status = -EBUSY; | |
| 1515 | − goto err; | |
| 1516 | − } | |
| 1517 | − req = embedded_payload(wrb); | |
| 1566 | + req = embedded_payload(&wrb); | |
| 1518 | 1567 | |
| 1519 | 1568 | be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
| 1520 | 1569 | OPCODE_COMMON_NTWK_INTERFACE_DESTROY, |
| 1521 | − sizeof(*req), wrb, NULL); | |
| 1570 | + sizeof(*req), &wrb, NULL); | |
| 1522 | 1571 | req->hdr.domain = domain; |
| 1523 | 1572 | req->interface_id = cpu_to_le32(interface_id); |
| 1524 | 1573 | |
| 1525 | − status = be_mcc_notify_wait(adapter); | |
| 1526 | −err: | |
| 1527 | − spin_unlock_bh(&adapter->mcc_lock); | |
| 1574 | + status = be_cmd_notify_wait(adapter, &wrb); | |
| 1528 | 1575 | return status; |
| 1529 | 1576 | } |
| 1530 | 1577 | |
| @@ -3168,6 +3215,10 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, · 1637 unmodified lines | ||
| 3168 | 3215 | struct be_cmd_req_set_lmode *req; |
| 3169 | 3216 | int status; |
| 3170 | 3217 | |
| 3218 | + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, | |
| 3219 | + CMD_SUBSYSTEM_LOWLEVEL)) | |
| 3220 | + return -EPERM; | |
| 3221 | + | |
| 3171 | 3222 | spin_lock_bh(&adapter->mcc_lock); |
| 3172 | 3223 | |
| 3173 | 3224 | wrb = wrb_from_mccq(adapter); |
| @@ -3213,6 +3264,10 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, · 39 unmodified lines | ||
| 3213 | 3264 | struct be_cmd_resp_loopback_test *resp; |
| 3214 | 3265 | int status; |
| 3215 | 3266 | |
| 3267 | + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_LOOPBACK_TEST, | |
| 3268 | + CMD_SUBSYSTEM_LOWLEVEL)) | |
| 3269 | + return -EPERM; | |
| 3270 | + | |
| 3216 | 3271 | spin_lock_bh(&adapter->mcc_lock); |
| 3217 | 3272 | |
| 3218 | 3273 | wrb = wrb_from_mccq(adapter); |
| @@ -3259,6 +3314,10 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, · 40 unmodified lines | ||
| 3259 | 3314 | int status; |
| 3260 | 3315 | int i, j = 0; |
| 3261 | 3316 | |
| 3317 | + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_HOST_DDR_DMA, | |
| 3318 | + CMD_SUBSYSTEM_LOWLEVEL)) | |
| 3319 | + return -EPERM; | |
| 3320 | + | |
| 3262 | 3321 | spin_lock_bh(&adapter->mcc_lock); |
| 3263 | 3322 | |
| 3264 | 3323 | wrb = wrb_from_mccq(adapter); |
| @@ -68,7 +68,8 @@ enum mcc_addl_status { · 67 unmodified lines | ||
| 68 | 68 | MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a, |
| 69 | 69 | MCC_ADDL_STATUS_INSUFFICIENT_VLANS = 0xab, |
| 70 | 70 | MCC_ADDL_STATUS_INVALID_SIGNATURE = 0x56, |
| 71 | − MCC_ADDL_STATUS_MISSING_SIGNATURE = 0x57 | |
| 71 | + MCC_ADDL_STATUS_MISSING_SIGNATURE = 0x57, | |
| 72 | + MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES = 0x60 | |
| 72 | 73 | }; |
| 73 | 74 | |
| 74 | 75 | #define CQE_BASE_STATUS_MASK 0xFFFF |
| @@ -175,10 +176,53 @@ struct be_async_event_qnq { · 100 unmodified lines | ||
| 175 | 176 | u32 flags; |
| 176 | 177 | } __packed; |
| 177 | 178 | |
| 178 | −#define INCOMPATIBLE_SFP 0x3 | |
| 179 | +enum { | |
| 180 | + BE_PHY_FUNCTIONAL = 0, | |
| 181 | + BE_PHY_NOT_PRESENT = 1, | |
| 182 | + BE_PHY_DIFF_MEDIA = 2, | |
| 183 | + BE_PHY_INCOMPATIBLE = 3, | |
| 184 | + BE_PHY_UNQUALIFIED = 4, | |
| 185 | + BE_PHY_UNCERTIFIED = 5 | |
| 186 | +}; | |
| 187 | + | |
| 188 | +#define PHY_STATE_MSG_SEVERITY 0x6 | |
| 189 | +#define PHY_STATE_OPER 0x1 | |
| 190 | +#define PHY_STATE_INFO_VALID 0x80 | |
| 191 | +#define PHY_STATE_OPER_MSG_NONE 0x2 | |
| 192 | +#define DEFAULT_MSG_SEVERITY 0x1 | |
| 193 | + | |
| 194 | +#define be_phy_state_unknown(phy_state) (phy_state > BE_PHY_UNCERTIFIED) | |
| 195 | +#define be_phy_unqualified(phy_state) \ | |
| 196 | + (phy_state == BE_PHY_UNQUALIFIED || \ | |
| 197 | + phy_state == BE_PHY_UNCERTIFIED) | |
| 198 | +#define be_phy_misconfigured(phy_state) \ | |
| 199 | + (phy_state == BE_PHY_INCOMPATIBLE || \ | |
| 200 | + phy_state == BE_PHY_UNQUALIFIED || \ | |
| 201 | + phy_state == BE_PHY_UNCERTIFIED) | |
| 202 | + | |
| 203 | +extern char *be_misconfig_evt_port_state[]; | |
| 204 | + | |
| 179 | 205 | /* async event indicating misconfigured port */ |
| 180 | 206 | struct be_async_event_misconfig_port { |
| 207 | + /* DATA_WORD1: | |
| 208 | + * phy state of port 0: bits 7 - 0 | |
| 209 | + * phy state of port 1: bits 15 - 8 | |
| 210 | + * phy state of port 2: bits 23 - 16 | |
| 211 | + * phy state of port 3: bits 31 - 24 | |
| 212 | + */ | |
| 181 | 213 | u32 event_data_word1; |
| 214 | + /* DATA_WORD2: | |
| 215 | + * phy state info of port 0: bits 7 - 0 | |
| 216 | + * phy state info of port 1: bits 15 - 8 | |
| 217 | + * phy state info of port 2: bits 23 - 16 | |
| 218 | + * phy state info of port 3: bits 31 - 24 | |
| 219 | + * | |
| 220 | + * PHY STATE INFO: | |
| 221 | + * Link operability :bit 0 | |
| 222 | + * Message severity :bit 2 - 1 | |
| 223 | + * Rsvd :bits 6 - 3 | |
| 224 | + * phy state info valid :bit 7 | |
| 225 | + */ | |
| 182 | 226 | u32 event_data_word2; |
| 183 | 227 | u32 rsvd0; |
| 184 | 228 | u32 flags; |
| @@ -720,29 +720,32 @@ static int be_set_phys_id(struct net_device *netdev, · 719 unmodified lines | ||
| 720 | 720 | enum ethtool_phys_id_state state) |
| 721 | 721 | { |
| 722 | 722 | struct be_adapter *adapter = netdev_priv(netdev); |
| 723 | + int status = 0; | |
| 723 | 724 | |
| 724 | 725 | switch (state) { |
| 725 | 726 | case ETHTOOL_ID_ACTIVE: |
| 726 | − be_cmd_get_beacon_state(adapter, adapter->hba_port_num, | |
| 727 | − &adapter->beacon_state); | |
| 728 | − return 1; /* cycle on/off once per second */ | |
| 727 | + status = be_cmd_get_beacon_state(adapter, adapter->hba_port_num, | |
| 728 | + &adapter->beacon_state); | |
| 729 | + if (status) | |
| 730 | + return be_cmd_status(status); | |
| 731 | + return 1; /* cycle on/off once per second */ | |
| 729 | 732 | |
| 730 | 733 | case ETHTOOL_ID_ON: |
| 731 | − be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, | |
| 732 | − BEACON_STATE_ENABLED); | |
| 734 | + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, | |
| 735 | + 0, 0, BEACON_STATE_ENABLED); | |
| 733 | 736 | break; |
| 734 | 737 | |
| 735 | 738 | case ETHTOOL_ID_OFF: |
| 736 | − be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, | |
| 737 | − BEACON_STATE_DISABLED); | |
| 739 | + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, | |
| 740 | + 0, 0, BEACON_STATE_DISABLED); | |
| 738 | 741 | break; |
| 739 | 742 | |
| 740 | 743 | case ETHTOOL_ID_INACTIVE: |
| 741 | − be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, | |
| 742 | − adapter->beacon_state); | |
| 744 | + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, | |
| 745 | + 0, 0, adapter->beacon_state); | |
| 743 | 746 | } |
| 744 | 747 | |
| 745 | − return 0; | |
| 748 | + return be_cmd_status(status); | |
| 746 | 749 | } |
| 747 | 750 | |
| 748 | 751 | static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump) |
| @@ -854,9 +854,9 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, · 853 unmodified lines | ||
| 854 | 854 | } |
| 855 | 855 | |
| 856 | 856 | /* Grab a WRB header for xmit */ |
| 857 | −static u16 be_tx_get_wrb_hdr(struct be_tx_obj *txo) | |
| 857 | +static u32 be_tx_get_wrb_hdr(struct be_tx_obj *txo) | |
| 858 | 858 | { |
| 859 | − u16 head = txo->q.head; | |
| 859 | + u32 head = txo->q.head; | |
| 860 | 860 | |
| 861 | 861 | queue_head_inc(&txo->q); |
| 862 | 862 | return head; |
| @@ -900,7 +900,7 @@ static void be_tx_setup_wrb_frag(struct be_tx_obj *txo, dma_addr_t busaddr, · 37 unmodified lines | ||
| 900 | 900 | * WRBs of the current packet are unmapped. Invoked to handle tx setup errors. |
| 901 | 901 | */ |
| 902 | 902 | static void be_xmit_restore(struct be_adapter *adapter, |
| 903 | − struct be_tx_obj *txo, u16 head, bool map_single, | |
| 903 | + struct be_tx_obj *txo, u32 head, bool map_single, | |
| 904 | 904 | u32 copied) |
| 905 | 905 | { |
| 906 | 906 | struct device *dev; |
| @@ -935,7 +935,7 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo, · 28 unmodified lines | ||
| 935 | 935 | struct device *dev = &adapter->pdev->dev; |
| 936 | 936 | struct be_queue_info *txq = &txo->q; |
| 937 | 937 | bool map_single = false; |
| 938 | − u16 head = txq->head; | |
| 938 | + u32 head = txq->head; | |
| 939 | 939 | dma_addr_t busaddr; |
| 940 | 940 | int len; |
| 941 | 941 | |
| @@ -1128,6 +1128,8 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, · 186 unmodified lines | ||
| 1128 | 1128 | struct sk_buff *skb, |
| 1129 | 1129 | struct be_wrb_params *wrb_params) |
| 1130 | 1130 | { |
| 1131 | + int err; | |
| 1132 | + | |
| 1131 | 1133 | /* Lancer, SH and BE3 in SRIOV mode have a bug wherein |
| 1132 | 1134 | * packets that are 32b or less may cause a transmit stall |
| 1133 | 1135 | * on that port. The workaround is to pad such packets |
| @@ -1144,6 +1146,13 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, · 10 unmodified lines | ||
| 1144 | 1146 | return NULL; |
| 1145 | 1147 | } |
| 1146 | 1148 | |
| 1149 | + /* The stack can send us skbs with length greater than | |
| 1150 | + * what the HW can handle. Trim the extra bytes. | |
| 1151 | + */ | |
| 1152 | + WARN_ON_ONCE(skb->len > BE_MAX_GSO_SIZE); | |
| 1153 | + err = pskb_trim(skb, BE_MAX_GSO_SIZE); | |
| 1154 | + WARN_ON(err); | |
| 1155 | + | |
| 1147 | 1156 | return skb; |
| 1148 | 1157 | } |
| 1149 | 1158 | |
| @@ -1468,6 +1477,9 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid) · 318 unmodified lines | ||
| 1468 | 1477 | if (lancer_chip(adapter) && vid == 0) |
| 1469 | 1478 | return 0; |
| 1470 | 1479 | |
| 1480 | + if (!test_bit(vid, adapter->vids)) | |
| 1481 | + return 0; | |
| 1482 | + | |
| 1471 | 1483 | clear_bit(vid, adapter->vids); |
| 1472 | 1484 | adapter->vlans_added--; |
| 1473 | 1485 | |
| @@ -1919,8 +1931,7 @@ static u32 be_get_eq_delay_mult_enc(struct be_eq_obj *eqo) · 445 unmodified lines | ||
| 1919 | 1931 | if (!aic->enable) |
| 1920 | 1932 | return 0; |
| 1921 | 1933 | |
| 1922 | − if (time_before_eq(now, aic->jiffies) || | |
| 1923 | − jiffies_to_msecs(now - aic->jiffies) < 1) | |
| 1934 | + if (jiffies_to_msecs(now - aic->jiffies) < 1) | |
| 1924 | 1935 | eqd = aic->prev_eqd; |
| 1925 | 1936 | else |
| 1926 | 1937 | eqd = be_get_new_eqd(eqo); |
| @@ -1993,7 +2004,7 @@ static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo) · 66 unmodified lines | ||
| 1993 | 2004 | struct be_adapter *adapter = rxo->adapter; |
| 1994 | 2005 | struct be_rx_page_info *rx_page_info; |
| 1995 | 2006 | struct be_queue_info *rxq = &rxo->q; |
| 1996 | − u16 frag_idx = rxq->tail; | |
| 2007 | + u32 frag_idx = rxq->tail; | |
| 1997 | 2008 | |
| 1998 | 2009 | rx_page_info = &rxo->page_info_tbl[frag_idx]; |
| 1999 | 2010 | BUG_ON(!rx_page_info->page); |
| @@ -2404,10 +2415,11 @@ static u16 be_tx_compl_process(struct be_adapter *adapter, · 404 unmodified lines | ||
| 2404 | 2415 | { |
| 2405 | 2416 | struct sk_buff **sent_skbs = txo->sent_skb_list; |
| 2406 | 2417 | struct be_queue_info *txq = &txo->q; |
| 2407 | − u16 frag_index, num_wrbs = 0; | |
| 2408 | 2418 | struct sk_buff *skb = NULL; |
| 2409 | 2419 | bool unmap_skb_hdr = false; |
| 2410 | 2420 | struct be_eth_wrb *wrb; |
| 2421 | + u16 num_wrbs = 0; | |
| 2422 | + u32 frag_index; | |
| 2411 | 2423 | |
| 2412 | 2424 | do { |
| 2413 | 2425 | if (sent_skbs[txq->tail]) { |
| @@ -2519,10 +2531,11 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) · 105 unmodified lines | ||
| 2519 | 2531 | |
| 2520 | 2532 | static void be_tx_compl_clean(struct be_adapter *adapter) |
| 2521 | 2533 | { |
| 2522 | − u16 end_idx, notified_idx, cmpl = 0, timeo = 0, num_wrbs = 0; | |
| 2523 | 2534 | struct device *dev = &adapter->pdev->dev; |
| 2535 | + u16 cmpl = 0, timeo = 0, num_wrbs = 0; | |
| 2524 | 2536 | struct be_tx_compl_info *txcp; |
| 2525 | 2537 | struct be_queue_info *txq; |
| 2538 | + u32 end_idx, notified_idx; | |
| 2526 | 2539 | struct be_tx_obj *txo; |
| 2527 | 2540 | int i, pending_txqs; |
| 2528 | 2541 | |
| @@ -3368,6 +3381,7 @@ done: · 839 unmodified lines | ||
| 3368 | 3381 | |
| 3369 | 3382 | static void be_rx_qs_destroy(struct be_adapter *adapter) |
| 3370 | 3383 | { |
| 3384 | + struct rss_info *rss = &adapter->rss_info; | |
| 3371 | 3385 | struct be_queue_info *q; |
| 3372 | 3386 | struct be_rx_obj *rxo; |
| 3373 | 3387 | int i; |
| @@ -3394,6 +3408,12 @@ static void be_rx_qs_destroy(struct be_adapter *adapter) · 20 unmodified lines | ||
| 3394 | 3408 | } |
| 3395 | 3409 | be_queue_free(adapter, q); |
| 3396 | 3410 | } |
| 3411 | + | |
| 3412 | + if (rss->rss_flags) { | |
| 3413 | + rss->rss_flags = RSS_ENABLE_NONE; | |
| 3414 | + be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, | |
| 3415 | + 128, rss->rss_hkey); | |
| 3416 | + } | |
| 3397 | 3417 | } |
| 3398 | 3418 | |
| 3399 | 3419 | static void be_disable_if_filters(struct be_adapter *adapter) |
| @@ -3514,20 +3534,21 @@ static int be_rx_qs_create(struct be_adapter *adapter) · 114 unmodified lines | ||
| 3514 | 3534 | if (!BEx_chip(adapter)) |
| 3515 | 3535 | rss->rss_flags |= RSS_ENABLE_UDP_IPV4 | |
| 3516 | 3536 | RSS_ENABLE_UDP_IPV6; |
| 3537 | + | |
| 3538 | + netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); | |
| 3539 | + rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, | |
| 3540 | + RSS_INDIR_TABLE_LEN, rss_key); | |
| 3541 | + if (rc) { | |
| 3542 | + rss->rss_flags = RSS_ENABLE_NONE; | |
| 3543 | + return rc; | |
| 3544 | + } | |
| 3545 | + | |
| 3546 | + memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); | |
| 3517 | 3547 | } else { |
| 3518 | 3548 | /* Disable RSS, if only default RX Q is created */ |
| 3519 | 3549 | rss->rss_flags = RSS_ENABLE_NONE; |
| 3520 | 3550 | } |
| 3521 | 3551 | |
| 3522 | − netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); | |
| 3523 | − rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, | |
| 3524 | − RSS_INDIR_TABLE_LEN, rss_key); | |
| 3525 | − if (rc) { | |
| 3526 | − rss->rss_flags = RSS_ENABLE_NONE; | |
| 3527 | − return rc; | |
| 3528 | − } | |
| 3529 | − | |
| 3530 | − memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); | |
| 3531 | 3552 | |
| 3532 | 3553 | /* Post 1 less than RXQ-len to avoid head being equal to tail, |
| 3533 | 3554 | * which is a queue empty condition |
| @@ -3794,18 +3815,15 @@ static u16 be_calculate_vf_qs(struct be_adapter *adapter, u16 num_vfs) · 260 unmodified lines | ||
| 3794 | 3815 | struct be_resources res = adapter->pool_res; |
| 3795 | 3816 | u16 num_vf_qs = 1; |
| 3796 | 3817 | |
| 3797 | − /* Distribute the queue resources equally among the PF and it's VFs | |
| 3818 | + /* Distribute the queue resources among the PF and it's VFs | |
| 3798 | 3819 | * Do not distribute queue resources in multi-channel configuration. |
| 3799 | 3820 | */ |
| 3800 | 3821 | if (num_vfs && !be_is_mc(adapter)) { |
| 3801 | − /* If number of VFs requested is 8 less than max supported, | |
| 3802 | − * assign 8 queue pairs to the PF and divide the remaining | |
| 3803 | − * resources evenly among the VFs | |
| 3804 | − */ | |
| 3805 | − if (num_vfs < (be_max_vfs(adapter) - 8)) | |
| 3806 | − num_vf_qs = (res.max_rss_qs - 8) / num_vfs; | |
| 3807 | − else | |
| 3808 | − num_vf_qs = res.max_rss_qs / num_vfs; | |
| 3822 | + /* Divide the qpairs evenly among the VFs and the PF, capped | |
| 3823 | + * at VF-EQ-count. Any remainder qpairs belong to the PF. | |
| 3824 | + */ | |
| 3825 | + num_vf_qs = min(SH_VF_MAX_NIC_EQS, | |
| 3826 | + res.max_rss_qs / (num_vfs + 1)); | |
| 3809 | 3827 | |
| 3810 | 3828 | /* Skyhawk-R chip supports only MAX_RSS_IFACES RSS capable |
| 3811 | 3829 | * interfaces per port. Provide RSS on VFs, only if number |
| @@ -4084,6 +4102,7 @@ static void be_setup_init(struct be_adapter *adapter) · 272 unmodified lines | ||
| 4084 | 4102 | adapter->if_handle = -1; |
| 4085 | 4103 | adapter->be3_native = false; |
| 4086 | 4104 | adapter->if_flags = 0; |
| 4105 | + adapter->phy_state = BE_UNKNOWN_PHY_STATE; | |
| 4087 | 4106 | if (be_physfn(adapter)) |
| 4088 | 4107 | adapter->cmd_privileges = MAX_PRIVILEGES; |
| 4089 | 4108 | else |
| @@ -4267,10 +4286,10 @@ static void be_schedule_worker(struct be_adapter *adapter) · 177 unmodified lines | ||
| 4267 | 4286 | adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; |
| 4268 | 4287 | } |
| 4269 | 4288 | |
| 4270 | −static void be_schedule_err_detection(struct be_adapter *adapter) | |
| 4289 | +static void be_schedule_err_detection(struct be_adapter *adapter, u32 delay) | |
| 4271 | 4290 | { |
| 4272 | 4291 | schedule_delayed_work(&adapter->be_err_detection_work, |
| 4273 | − msecs_to_jiffies(1000)); | |
| 4292 | + msecs_to_jiffies(delay)); | |
| 4274 | 4293 | adapter->flags |= BE_FLAGS_ERR_DETECTION_SCHEDULED; |
| 4275 | 4294 | } |
| 4276 | 4295 | |
| @@ -4309,6 +4328,23 @@ err: · 32 unmodified lines | ||
| 4309 | 4328 | return status; |
| 4310 | 4329 | } |
| 4311 | 4330 | |
| 4331 | +static int be_if_create(struct be_adapter *adapter) | |
| 4332 | +{ | |
| 4333 | + u32 en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS; | |
| 4334 | + u32 cap_flags = be_if_cap_flags(adapter); | |
| 4335 | + int status; | |
| 4336 | + | |
| 4337 | + if (adapter->cfg_num_qs == 1) | |
| 4338 | + cap_flags &= ~(BE_IF_FLAGS_DEFQ_RSS | BE_IF_FLAGS_RSS); | |
| 4339 | + | |
| 4340 | + en_flags &= cap_flags; | |
| 4341 | + /* will enable all the needed filter flags in be_open() */ | |
| 4342 | + status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags, | |
| 4343 | + &adapter->if_handle, 0); | |
| 4344 | + | |
| 4345 | + return status; | |
| 4346 | +} | |
| 4347 | + | |
| 4312 | 4348 | int be_update_queues(struct be_adapter *adapter) |
| 4313 | 4349 | { |
| 4314 | 4350 | struct net_device *netdev = adapter->netdev; |
| @@ -4326,6 +4362,9 @@ int be_update_queues(struct be_adapter *adapter) · 11 unmodified lines | ||
| 4326 | 4362 | be_msix_disable(adapter); |
| 4327 | 4363 | |
| 4328 | 4364 | be_clear_queues(adapter); |
| 4365 | + status = be_cmd_if_destroy(adapter, adapter->if_handle, 0); | |
| 4366 | + if (status) | |
| 4367 | + return status; | |
| 4329 | 4368 | |
| 4330 | 4369 | if (!msix_enabled(adapter)) { |
| 4331 | 4370 | status = be_msix_enable(adapter); |
| @@ -4333,6 +4372,10 @@ int be_update_queues(struct be_adapter *adapter) · 1 unmodified line | ||
| 4333 | 4372 | return status; |
| 4334 | 4373 | } |
| 4335 | 4374 | |
| 4375 | + status = be_if_create(adapter); | |
| 4376 | + if (status) | |
| 4377 | + return status; | |
| 4378 | + | |
| 4336 | 4379 | status = be_setup_queues(adapter); |
| 4337 | 4380 | if (status) |
| 4338 | 4381 | return status; |
| @@ -4397,7 +4440,6 @@ static int be_func_init(struct be_adapter *adapter) · 58 unmodified lines | ||
| 4397 | 4440 | static int be_setup(struct be_adapter *adapter) |
| 4398 | 4441 | { |
| 4399 | 4442 | struct device *dev = &adapter->pdev->dev; |
| 4400 | − u32 en_flags; | |
| 4401 | 4443 | int status; |
| 4402 | 4444 | |
| 4403 | 4445 | status = be_func_init(adapter); |
| @@ -4430,10 +4472,7 @@ static int be_setup(struct be_adapter *adapter) · 26 unmodified lines | ||
| 4430 | 4472 | goto err; |
| 4431 | 4473 | |
| 4432 | 4474 | /* will enable all the needed filter flags in be_open() */ |
| 4433 | − en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS; | |
| 4434 | − en_flags = en_flags & be_if_cap_flags(adapter); | |
| 4435 | − status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags, | |
| 4436 | − &adapter->if_handle, 0); | |
| 4475 | + status = be_if_create(adapter); | |
| 4437 | 4476 | if (status) |
| 4438 | 4477 | goto err; |
| 4439 | 4478 | |
| @@ -4591,6 +4630,9 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, · 151 unmodified lines | ||
| 4591 | 4630 | |
| 4592 | 4631 | /* BE and Lancer chips support VEB mode only */ |
| 4593 | 4632 | if (BEx_chip(adapter) || lancer_chip(adapter)) { |
| 4633 | + /* VEB is disabled in non-SR-IOV profiles on BE3/Lancer */ | |
| 4634 | + if (!pci_sriov_get_totalvfs(adapter->pdev)) | |
| 4635 | + return 0; | |
| 4594 | 4636 | hsw_mode = PORT_FWD_TYPE_VEB; |
| 4595 | 4637 | } else { |
| 4596 | 4638 | status = be_cmd_get_hsw_config(adapter, NULL, 0, |
| @@ -4806,7 +4848,7 @@ static void be_netdev_init(struct net_device *netdev) · 209 unmodified lines | ||
| 4806 | 4848 | netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | |
| 4807 | 4849 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | |
| 4808 | 4850 | NETIF_F_HW_VLAN_CTAG_TX; |
| 4809 | − if (be_multi_rxq(adapter)) | |
| 4851 | + if ((be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) | |
| 4810 | 4852 | netdev->hw_features |= NETIF_F_RXHASH; |
| 4811 | 4853 | |
| 4812 | 4854 | netdev->features |= netdev->hw_features | |
| @@ -4819,7 +4861,7 @@ static void be_netdev_init(struct net_device *netdev) · 6 unmodified lines | ||
| 4819 | 4861 | |
| 4820 | 4862 | netdev->flags |= IFF_MULTICAST; |
| 4821 | 4863 | |
| 4822 | − netif_set_gso_max_size(netdev, 65535 - ETH_HLEN); | |
| 4864 | + netif_set_gso_max_size(netdev, BE_MAX_GSO_SIZE - ETH_HLEN); | |
| 4823 | 4865 | |
| 4824 | 4866 | netdev->netdev_ops = &be_netdev_ops; |
| 4825 | 4867 | |
| @@ -4861,21 +4903,27 @@ static int be_resume(struct be_adapter *adapter) · 35 unmodified lines | ||
| 4861 | 4903 | |
| 4862 | 4904 | static int be_err_recover(struct be_adapter *adapter) |
| 4863 | 4905 | { |
| 4864 | − struct device *dev = &adapter->pdev->dev; | |
| 4865 | 4906 | int status; |
| 4866 | 4907 | |
| 4908 | + /* Error recovery is supported only Lancer as of now */ | |
| 4909 | + if (!lancer_chip(adapter)) | |
| 4910 | + return -EIO; | |
| 4911 | + | |
| 4912 | + /* Wait for adapter to reach quiescent state before | |
| 4913 | + * destroying queues | |
| 4914 | + */ | |
| 4915 | + status = be_fw_wait_ready(adapter); | |
| 4916 | + if (status) | |
| 4917 | + goto err; | |
| 4918 | + | |
| 4919 | + be_cleanup(adapter); | |
| 4920 | + | |
| 4867 | 4921 | status = be_resume(adapter); |
| 4868 | 4922 | if (status) |
| 4869 | 4923 | goto err; |
| 4870 | 4924 | |
| 4871 | − dev_info(dev, "Adapter recovery successful\n"); | |
| 4872 | 4925 | return 0; |
| 4873 | 4926 | err: |
| 4874 | − if (be_physfn(adapter)) | |
| 4875 | − dev_err(dev, "Adapter recovery failed\n"); | |
| 4876 | − else | |
| 4877 | − dev_err(dev, "Re-trying adapter recovery\n"); | |
| 4878 | − | |
| 4879 | 4927 | return status; |
| 4880 | 4928 | } |
| 4881 | 4929 | |
| @@ -4884,21 +4932,43 @@ static void be_err_detection_task(struct work_struct *work) · 2 unmodified lines | ||
| 4884 | 4932 | struct be_adapter *adapter = |
| 4885 | 4933 | container_of(work, struct be_adapter, |
| 4886 | 4934 | be_err_detection_work.work); |
| 4887 | − int status = 0; | |
| 4935 | + struct device *dev = &adapter->pdev->dev; | |
| 4936 | + int recovery_status; | |
| 4937 | + int delay = ERR_DETECTION_DELAY; | |
| 4888 | 4938 | |
| 4889 | 4939 | be_detect_error(adapter); |
| 4890 | 4940 | |
| 4891 | − if (be_check_error(adapter, BE_ERROR_HW)) { | |
| 4892 | − be_cleanup(adapter); | |
| 4893 | − | |
| 4894 | − /* As of now error recovery support is in Lancer only */ | |
| 4895 | − if (lancer_chip(adapter)) | |
| 4896 | − status = be_err_recover(adapter); | |
| 4941 | + if (be_check_error(adapter, BE_ERROR_HW)) | |
| 4942 | + recovery_status = be_err_recover(adapter); | |
| 4943 | + else | |
| 4944 | + goto reschedule_task; | |
| 4945 | + | |
| 4946 | + if (!recovery_status) { | |
| 4947 | + adapter->recovery_retries = 0; | |
| 4948 | + dev_info(dev, "Adapter recovery successful\n"); | |
| 4949 | + goto reschedule_task; | |
| 4950 | + } else if (be_virtfn(adapter)) { | |
| 4951 | + /* For VFs, check if PF have allocated resources | |
| 4952 | + * every second. | |
| 4953 | + */ | |
| 4954 | + dev_err(dev, "Re-trying adapter recovery\n"); | |
| 4955 | + goto reschedule_task; | |
| 4956 | + } else if (adapter->recovery_retries++ < | |
| 4957 | + MAX_ERR_RECOVERY_RETRY_COUNT) { | |
| 4958 | + /* In case of another error during recovery, it takes 30 sec | |
| 4959 | + * for adapter to come out of error. Retry error recovery after | |
| 4960 | + * this time interval. | |
| 4961 | + */ | |
| 4962 | + dev_err(&adapter->pdev->dev, "Re-trying adapter recovery\n"); | |
| 4963 | + delay = ERR_RECOVERY_RETRY_DELAY; | |
| 4964 | + goto reschedule_task; | |
| 4965 | + } else { | |
| 4966 | + dev_err(dev, "Adapter recovery failed\n"); | |
| 4897 | 4967 | } |
| 4898 | 4968 | |
| 4899 | − /* Always attempt recovery on VFs */ | |
| 4900 | − if (!status || be_virtfn(adapter)) | |
| 4901 | − be_schedule_err_detection(adapter); | |
| 4969 | + return; | |
| 4970 | +reschedule_task: | |
| 4971 | + be_schedule_err_detection(adapter, delay); | |
| 4902 | 4972 | } |
| 4903 | 4973 | |
| 4904 | 4974 | static void be_log_sfp_info(struct be_adapter *adapter) |
| @@ -4908,11 +4978,13 @@ static void be_log_sfp_info(struct be_adapter *adapter) · 3 unmodified lines | ||
| 4908 | 4978 | status = be_cmd_query_sfp_info(adapter); |
| 4909 | 4979 | if (!status) { |
| 4910 | 4980 | dev_err(&adapter->pdev->dev, |
| 4911 | − "Unqualified SFP+ detected on %c from %s part no: %s", | |
| 4912 | − adapter->port_name, adapter->phy.vendor_name, | |
| 4981 | + "Port %c: %s Vendor: %s part no: %s", | |
| 4982 | + adapter->port_name, | |
| 4983 | + be_misconfig_evt_port_state[adapter->phy_state], | |
| 4984 | + adapter->phy.vendor_name, | |
| 4913 | 4985 | adapter->phy.vendor_pn); |
| 4914 | 4986 | } |
| 4915 | − adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP; | |
| 4987 | + adapter->flags &= ~BE_FLAGS_PHY_MISCONFIGURED; | |
| 4916 | 4988 | } |
| 4917 | 4989 | |
| 4918 | 4990 | static void be_worker(struct work_struct *work) |
| @@ -4956,7 +5028,7 @@ static void be_worker(struct work_struct *work) · 37 unmodified lines | ||
| 4956 | 5028 | if (!skyhawk_chip(adapter)) |
| 4957 | 5029 | be_eqd_update(adapter, false); |
| 4958 | 5030 | |
| 4959 | − if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP) | |
| 5031 | + if (adapter->flags & BE_FLAGS_PHY_MISCONFIGURED) | |
| 4960 | 5032 | be_log_sfp_info(adapter); |
| 4961 | 5033 | |
| 4962 | 5034 | reschedule: |
| @@ -5298,7 +5370,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) · 335 unmodified lines | ||
| 5298 | 5370 | |
| 5299 | 5371 | be_roce_dev_add(adapter); |
| 5300 | 5372 | |
| 5301 | − be_schedule_err_detection(adapter); | |
| 5373 | + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); | |
| 5302 | 5374 | |
| 5303 | 5375 | /* On Die temperature not supported for VF. */ |
| 5304 | 5376 | if (be_physfn(adapter) && IS_ENABLED(CONFIG_BE2NET_HWMON)) { |
| @@ -5365,7 +5437,7 @@ static int be_pci_resume(struct pci_dev *pdev) · 60 unmodified lines | ||
| 5365 | 5437 | if (status) |
| 5366 | 5438 | return status; |
| 5367 | 5439 | |
| 5368 | − be_schedule_err_detection(adapter); | |
| 5440 | + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); | |
| 5369 | 5441 | |
| 5370 | 5442 | if (adapter->wol_en) |
| 5371 | 5443 | be_setup_wol(adapter, false); |
| @@ -5401,6 +5473,8 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, · 29 unmodified lines | ||
| 5401 | 5473 | |
| 5402 | 5474 | dev_err(&adapter->pdev->dev, "EEH error detected\n"); |
| 5403 | 5475 | |
| 5476 | + be_roce_dev_remove(adapter); | |
| 5477 | + | |
| 5404 | 5478 | if (!be_check_error(adapter, BE_ERROR_EEH)) { |
| 5405 | 5479 | be_set_error(adapter, BE_ERROR_EEH); |
| 5406 | 5480 | |
| @@ -5465,7 +5539,9 @@ static void be_eeh_resume(struct pci_dev *pdev) · 58 unmodified lines | ||
| 5465 | 5539 | if (status) |
| 5466 | 5540 | goto err; |
| 5467 | 5541 | |
| 5468 | − be_schedule_err_detection(adapter); | |
| 5542 | + be_roce_dev_add(adapter); | |
| 5543 | + | |
| 5544 | + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); | |
| 5469 | 5545 | return; |
| 5470 | 5546 | err: |
| 5471 | 5547 | dev_err(&adapter->pdev->dev, "EEH resume failed\n"); |
| @@ -43,20 +43,21 @@ static void nps_enet_read_rx_fifo(struct net_device *ndev, · 42 unmodified lines | ||
| 43 | 43 | bool dst_is_aligned = IS_ALIGNED((unsigned long)dst, sizeof(u32)); |
| 44 | 44 | |
| 45 | 45 | /* In case dst is not aligned we need an intermediate buffer */ |
| 46 | − if (dst_is_aligned) | |
| 47 | − for (i = 0; i < len; i++, reg++) | |
| 48 | − *reg = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); | |
| 46 | + if (dst_is_aligned) { | |
| 47 | + ioread32_rep(priv->regs_base + NPS_ENET_REG_RX_BUF, reg, len); | |
| 48 | + reg += len; | |
| 49 | + } | |
| 49 | 50 | else { /* !dst_is_aligned */ |
| 50 | 51 | for (i = 0; i < len; i++, reg++) { |
| 51 | 52 | u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); |
| 52 | − put_unaligned(buf, reg); | |
| 53 | + put_unaligned_be32(buf, reg); | |
| 53 | 54 | } |
| 54 | 55 | } |
| 55 | − | |
| 56 | 56 | /* copy last bytes (if any) */ |
| 57 | 57 | if (last) { |
| 58 | − u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); | |
| 59 | − memcpy((u8*)reg, &buf, last); | |
| 58 | + u32 buf; | |
| 59 | + ioread32_rep(priv->regs_base + NPS_ENET_REG_RX_BUF, &buf, 1); | |
| 60 | + memcpy((u8 *)reg, &buf, last); | |
| 60 | 61 | } |
| 61 | 62 | } |
| 62 | 63 | |
| @@ -66,26 +67,28 @@ static u32 nps_enet_rx_handler(struct net_device *ndev) · 3 unmodified lines | ||
| 66 | 67 | u32 work_done = 0; |
| 67 | 68 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 68 | 69 | struct sk_buff *skb; |
| 69 | − struct nps_enet_rx_ctl rx_ctrl; | |
| 70 | + u32 rx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); | |
| 71 | + u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT; | |
| 72 | + u32 rx_ctrl_er = (rx_ctrl_value & RX_CTL_ER_MASK) >> RX_CTL_ER_SHIFT; | |
| 73 | + u32 rx_ctrl_crc = (rx_ctrl_value & RX_CTL_CRC_MASK) >> RX_CTL_CRC_SHIFT; | |
| 70 | 74 | |
| 71 | − rx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); | |
| 72 | − frame_len = rx_ctrl.nr; | |
| 75 | + frame_len = (rx_ctrl_value & RX_CTL_NR_MASK) >> RX_CTL_NR_SHIFT; | |
| 73 | 76 | |
| 74 | 77 | /* Check if we got RX */ |
| 75 | − if (!rx_ctrl.cr) | |
| 78 | + if (!rx_ctrl_cr) | |
| 76 | 79 | return work_done; |
| 77 | 80 | |
| 78 | 81 | /* If we got here there is a work for us */ |
| 79 | 82 | work_done++; |
| 80 | 83 | |
| 81 | 84 | /* Check Rx error */ |
| 82 | − if (rx_ctrl.er) { | |
| 85 | + if (rx_ctrl_er) { | |
| 83 | 86 | ndev->stats.rx_errors++; |
| 84 | 87 | err = 1; |
| 85 | 88 | } |
| 86 | 89 | |
| 87 | 90 | /* Check Rx CRC error */ |
| 88 | − if (rx_ctrl.crc) { | |
| 91 | + if (rx_ctrl_crc) { | |
| 89 | 92 | ndev->stats.rx_crc_errors++; |
| 90 | 93 | ndev->stats.rx_dropped++; |
| 91 | 94 | err = 1; |
| @@ -136,23 +139,24 @@ rx_irq_frame_done: · 44 unmodified lines | ||
| 136 | 139 | static void nps_enet_tx_handler(struct net_device *ndev) |
| 137 | 140 | { |
| 138 | 141 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 139 | − struct nps_enet_tx_ctl tx_ctrl; | |
| 140 | − | |
| 141 | − tx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); | |
| 142 | + u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); | |
| 143 | + u32 tx_ctrl_ct = (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT; | |
| 144 | + u32 tx_ctrl_et = (tx_ctrl_value & TX_CTL_ET_MASK) >> TX_CTL_ET_SHIFT; | |
| 145 | + u32 tx_ctrl_nt = (tx_ctrl_value & TX_CTL_NT_MASK) >> TX_CTL_NT_SHIFT; | |
| 142 | 146 | |
| 143 | 147 | /* Check if we got TX */ |
| 144 | − if (!priv->tx_packet_sent || tx_ctrl.ct) | |
| 148 | + if (!priv->tx_packet_sent || tx_ctrl_ct) | |
| 145 | 149 | return; |
| 146 | 150 | |
| 147 | 151 | /* Ack Tx ctrl register */ |
| 148 | 152 | nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, 0); |
| 149 | 153 | |
| 150 | 154 | /* Check Tx transmit error */ |
| 151 | − if (unlikely(tx_ctrl.et)) { | |
| 155 | + if (unlikely(tx_ctrl_et)) { | |
| 152 | 156 | ndev->stats.tx_errors++; |
| 153 | 157 | } else { |
| 154 | 158 | ndev->stats.tx_packets++; |
| 155 | − ndev->stats.tx_bytes += tx_ctrl.nt; | |
| 159 | + ndev->stats.tx_bytes += tx_ctrl_nt; | |
| 156 | 160 | } |
| 157 | 161 | |
| 158 | 162 | dev_kfree_skb(priv->tx_skb); |
| @@ -178,13 +182,16 @@ static int nps_enet_poll(struct napi_struct *napi, int budget) · 19 unmodified lines | ||
| 178 | 182 | nps_enet_tx_handler(ndev); |
| 179 | 183 | work_done = nps_enet_rx_handler(ndev); |
| 180 | 184 | if (work_done < budget) { |
| 181 | − struct nps_enet_buf_int_enable buf_int_enable; | |
| 185 | + u32 buf_int_enable_value = 0; | |
| 182 | 186 | |
| 183 | 187 | napi_complete(napi); |
| 184 | − buf_int_enable.rx_rdy = NPS_ENET_ENABLE; | |
| 185 | − buf_int_enable.tx_done = NPS_ENET_ENABLE; | |
| 188 | + | |
| 189 | + /* set tx_done and rx_rdy bits */ | |
| 190 | + buf_int_enable_value |= NPS_ENET_ENABLE << RX_RDY_SHIFT; | |
| 191 | + buf_int_enable_value |= NPS_ENET_ENABLE << TX_DONE_SHIFT; | |
| 192 | + | |
| 186 | 193 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, |
| 187 | − buf_int_enable.value); | |
| 194 | + buf_int_enable_value); | |
| 188 | 195 | } |
| 189 | 196 | |
| 190 | 197 | return work_done; |
| @@ -205,13 +212,12 @@ static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance) · 14 unmodified lines | ||
| 205 | 212 | { |
| 206 | 213 | struct net_device *ndev = dev_instance; |
| 207 | 214 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 208 | − struct nps_enet_rx_ctl rx_ctrl; | |
| 209 | − struct nps_enet_tx_ctl tx_ctrl; | |
| 210 | − | |
| 211 | − rx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); | |
| 212 | − tx_ctrl.value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); | |
| 215 | + u32 rx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); | |
| 216 | + u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); | |
| 217 | + u32 tx_ctrl_ct = (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT; | |
| 218 | + u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT; | |
| 213 | 219 | |
| 214 | − if ((!tx_ctrl.ct && priv->tx_packet_sent) || rx_ctrl.cr) | |
| 220 | + if ((!tx_ctrl_ct && priv->tx_packet_sent) || rx_ctrl_cr) | |
| 215 | 221 | if (likely(napi_schedule_prep(&priv->napi))) { |
| 216 | 222 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0); |
| 217 | 223 | __napi_schedule(&priv->napi); |
| @@ -223,22 +229,24 @@ static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance) · 5 unmodified lines | ||
| 223 | 229 | static void nps_enet_set_hw_mac_address(struct net_device *ndev) |
| 224 | 230 | { |
| 225 | 231 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 226 | − struct nps_enet_ge_mac_cfg_1 ge_mac_cfg_1; | |
| 227 | − struct nps_enet_ge_mac_cfg_2 *ge_mac_cfg_2 = &priv->ge_mac_cfg_2; | |
| 232 | + u32 ge_mac_cfg_1_value = 0; | |
| 233 | + u32 *ge_mac_cfg_2_value = &priv->ge_mac_cfg_2_value; | |
| 228 | 234 | |
| 229 | 235 | /* set MAC address in HW */ |
| 230 | − ge_mac_cfg_1.octet_0 = ndev->dev_addr[0]; | |
| 231 | − ge_mac_cfg_1.octet_1 = ndev->dev_addr[1]; | |
| 232 | − ge_mac_cfg_1.octet_2 = ndev->dev_addr[2]; | |
| 233 | − ge_mac_cfg_1.octet_3 = ndev->dev_addr[3]; | |
| 234 | − ge_mac_cfg_2->octet_4 = ndev->dev_addr[4]; | |
| 235 | − ge_mac_cfg_2->octet_5 = ndev->dev_addr[5]; | |
| 236 | + ge_mac_cfg_1_value |= ndev->dev_addr[0] << CFG_1_OCTET_0_SHIFT; | |
| 237 | + ge_mac_cfg_1_value |= ndev->dev_addr[1] << CFG_1_OCTET_1_SHIFT; | |
| 238 | + ge_mac_cfg_1_value |= ndev->dev_addr[2] << CFG_1_OCTET_2_SHIFT; | |
| 239 | + ge_mac_cfg_1_value |= ndev->dev_addr[3] << CFG_1_OCTET_3_SHIFT; | |
| 240 | + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_OCTET_4_MASK) | |
| 241 | + | ndev->dev_addr[4] << CFG_2_OCTET_4_SHIFT; | |
| 242 | + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_OCTET_5_MASK) | |
| 243 | + | ndev->dev_addr[5] << CFG_2_OCTET_5_SHIFT; | |
| 236 | 244 | |
| 237 | 245 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_1, |
| 238 | − ge_mac_cfg_1.value); | |
| 246 | + ge_mac_cfg_1_value); | |
| 239 | 247 | |
| 240 | 248 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, |
| 241 | − ge_mac_cfg_2->value); | |
| 249 | + *ge_mac_cfg_2_value); | |
| 242 | 250 | } |
| 243 | 251 | |
| 244 | 252 | /** |
| @@ -254,93 +262,97 @@ static void nps_enet_set_hw_mac_address(struct net_device *ndev) · 9 unmodified lines | ||
| 254 | 262 | static void nps_enet_hw_reset(struct net_device *ndev) |
| 255 | 263 | { |
| 256 | 264 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 257 | − struct nps_enet_ge_rst ge_rst; | |
| 258 | − struct nps_enet_phase_fifo_ctl phase_fifo_ctl; | |
| 265 | + u32 ge_rst_value = 0, phase_fifo_ctl_value = 0; | |
| 259 | 266 | |
| 260 | − ge_rst.value = 0; | |
| 261 | − phase_fifo_ctl.value = 0; | |
| 262 | 267 | /* Pcs reset sequence*/ |
| 263 | − ge_rst.gmac_0 = NPS_ENET_ENABLE; | |
| 264 | − nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst.value); | |
| 268 | + ge_rst_value |= NPS_ENET_ENABLE << RST_GMAC_0_SHIFT; | |
| 269 | + nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst_value); | |
| 265 | 270 | usleep_range(10, 20); |
| 266 | − ge_rst.value = 0; | |
| 267 | − nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst.value); | |
| 271 | + nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, ge_rst_value); | |
| 268 | 272 | |
| 269 | 273 | /* Tx fifo reset sequence */ |
| 270 | − phase_fifo_ctl.rst = NPS_ENET_ENABLE; | |
| 271 | − phase_fifo_ctl.init = NPS_ENET_ENABLE; | |
| 274 | + phase_fifo_ctl_value |= NPS_ENET_ENABLE << PHASE_FIFO_CTL_RST_SHIFT; | |
| 275 | + phase_fifo_ctl_value |= NPS_ENET_ENABLE << PHASE_FIFO_CTL_INIT_SHIFT; | |
| 272 | 276 | nps_enet_reg_set(priv, NPS_ENET_REG_PHASE_FIFO_CTL, |
| 273 | − phase_fifo_ctl.value); | |
| 277 | + phase_fifo_ctl_value); | |
| 274 | 278 | usleep_range(10, 20); |
| 275 | − phase_fifo_ctl.value = 0; | |
| 279 | + phase_fifo_ctl_value = 0; | |
| 276 | 280 | nps_enet_reg_set(priv, NPS_ENET_REG_PHASE_FIFO_CTL, |
| 277 | − phase_fifo_ctl.value); | |
| 281 | + phase_fifo_ctl_value); | |
| 278 | 282 | } |
| 279 | 283 | |
| 280 | 284 | static void nps_enet_hw_enable_control(struct net_device *ndev) |
| 281 | 285 | { |
| 282 | 286 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 283 | − struct nps_enet_ge_mac_cfg_0 ge_mac_cfg_0; | |
| 284 | − struct nps_enet_buf_int_enable buf_int_enable; | |
| 285 | − struct nps_enet_ge_mac_cfg_2 *ge_mac_cfg_2 = &priv->ge_mac_cfg_2; | |
| 286 | − struct nps_enet_ge_mac_cfg_3 *ge_mac_cfg_3 = &priv->ge_mac_cfg_3; | |
| 287 | + u32 ge_mac_cfg_0_value = 0, buf_int_enable_value = 0; | |
| 288 | + u32 *ge_mac_cfg_2_value = &priv->ge_mac_cfg_2_value; | |
| 289 | + u32 *ge_mac_cfg_3_value = &priv->ge_mac_cfg_3_value; | |
| 287 | 290 | s32 max_frame_length; |
| 288 | 291 | |
| 289 | − ge_mac_cfg_0.value = 0; | |
| 290 | − buf_int_enable.value = 0; | |
| 291 | 292 | /* Enable Rx and Tx statistics */ |
| 292 | − ge_mac_cfg_2->stat_en = NPS_ENET_GE_MAC_CFG_2_STAT_EN; | |
| 293 | + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_STAT_EN_MASK) | |
| 294 | + | NPS_ENET_GE_MAC_CFG_2_STAT_EN << CFG_2_STAT_EN_SHIFT; | |
| 293 | 295 | |
| 294 | 296 | /* Discard packets with different MAC address */ |
| 295 | − ge_mac_cfg_2->disc_da = NPS_ENET_ENABLE; | |
| 297 | + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) | |
| 298 | + | NPS_ENET_ENABLE << CFG_2_DISK_DA_SHIFT; | |
| 296 | 299 | |
| 297 | 300 | /* Discard multicast packets */ |
| 298 | − ge_mac_cfg_2->disc_mc = NPS_ENET_ENABLE; | |
| 301 | + *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) | |
| 302 | + | NPS_ENET_ENABLE << CFG_2_DISK_MC_SHIFT; | |
| 299 | 303 | |
| 300 | 304 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, |
| 301 | − ge_mac_cfg_2->value); | |
| 305 | + *ge_mac_cfg_2_value); | |
| 302 | 306 | |
| 303 | 307 | /* Discard Packets bigger than max frame length */ |
| 304 | 308 | max_frame_length = ETH_HLEN + ndev->mtu + ETH_FCS_LEN; |
| 305 | − if (max_frame_length <= NPS_ENET_MAX_FRAME_LENGTH) | |
| 306 | − ge_mac_cfg_3->max_len = max_frame_length; | |
| 309 | + if (max_frame_length <= NPS_ENET_MAX_FRAME_LENGTH) { | |
| 310 | + *ge_mac_cfg_3_value = | |
| 311 | + (*ge_mac_cfg_3_value & ~CFG_3_MAX_LEN_MASK) | |
| 312 | + | max_frame_length << CFG_3_MAX_LEN_SHIFT; | |
| 313 | + } | |
| 307 | 314 | |
| 308 | 315 | /* Enable interrupts */ |
| 309 | − buf_int_enable.rx_rdy = NPS_ENET_ENABLE; | |
| 310 | − buf_int_enable.tx_done = NPS_ENET_ENABLE; | |
| 316 | + buf_int_enable_value |= NPS_ENET_ENABLE << RX_RDY_SHIFT; | |
| 317 | + buf_int_enable_value |= NPS_ENET_ENABLE << TX_DONE_SHIFT; | |
| 311 | 318 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, |
| 312 | − buf_int_enable.value); | |
| 319 | + buf_int_enable_value); | |
| 313 | 320 | |
| 314 | 321 | /* Write device MAC address to HW */ |
| 315 | 322 | nps_enet_set_hw_mac_address(ndev); |
| 316 | 323 | |
| 317 | 324 | /* Rx and Tx HW features */ |
| 318 | − ge_mac_cfg_0.tx_pad_en = NPS_ENET_ENABLE; | |
| 319 | − ge_mac_cfg_0.tx_crc_en = NPS_ENET_ENABLE; | |
| 320 | − ge_mac_cfg_0.rx_crc_strip = NPS_ENET_ENABLE; | |
| 325 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_PAD_EN_SHIFT; | |
| 326 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_CRC_EN_SHIFT; | |
| 327 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_CRC_STRIP_SHIFT; | |
| 321 | 328 | |
| 322 | 329 | /* IFG configuration */ |
| 323 | − ge_mac_cfg_0.rx_ifg = NPS_ENET_GE_MAC_CFG_0_RX_IFG; | |
| 324 | − ge_mac_cfg_0.tx_ifg = NPS_ENET_GE_MAC_CFG_0_TX_IFG; | |
| 330 | + ge_mac_cfg_0_value |= | |
| 331 | + NPS_ENET_GE_MAC_CFG_0_RX_IFG << CFG_0_RX_IFG_SHIFT; | |
| 332 | + ge_mac_cfg_0_value |= | |
| 333 | + NPS_ENET_GE_MAC_CFG_0_TX_IFG << CFG_0_TX_IFG_SHIFT; | |
| 325 | 334 | |
| 326 | 335 | /* preamble configuration */ |
| 327 | − ge_mac_cfg_0.rx_pr_check_en = NPS_ENET_ENABLE; | |
| 328 | − ge_mac_cfg_0.tx_pr_len = NPS_ENET_GE_MAC_CFG_0_TX_PR_LEN; | |
| 336 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_PR_CHECK_EN_SHIFT; | |
| 337 | + ge_mac_cfg_0_value |= | |
| 338 | + NPS_ENET_GE_MAC_CFG_0_TX_PR_LEN << CFG_0_TX_PR_LEN_SHIFT; | |
| 329 | 339 | |
| 330 | 340 | /* enable flow control frames */ |
| 331 | − ge_mac_cfg_0.tx_fc_en = NPS_ENET_ENABLE; | |
| 332 | − ge_mac_cfg_0.rx_fc_en = NPS_ENET_ENABLE; | |
| 333 | − ge_mac_cfg_0.tx_fc_retr = NPS_ENET_GE_MAC_CFG_0_TX_FC_RETR; | |
| 334 | − ge_mac_cfg_3->cf_drop = NPS_ENET_ENABLE; | |
| 341 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_FC_EN_SHIFT; | |
| 342 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_FC_EN_SHIFT; | |
| 343 | + ge_mac_cfg_0_value |= | |
| 344 | + NPS_ENET_GE_MAC_CFG_0_TX_FC_RETR << CFG_0_TX_FC_RETR_SHIFT; | |
| 345 | + *ge_mac_cfg_3_value = (*ge_mac_cfg_3_value & ~CFG_3_CF_DROP_MASK) | |
| 346 | + | NPS_ENET_ENABLE << CFG_3_CF_DROP_SHIFT; | |
| 335 | 347 | |
| 336 | 348 | /* Enable Rx and Tx */ |
| 337 | − ge_mac_cfg_0.rx_en = NPS_ENET_ENABLE; | |
| 338 | − ge_mac_cfg_0.tx_en = NPS_ENET_ENABLE; | |
| 349 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_EN_SHIFT; | |
| 350 | + ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_EN_SHIFT; | |
| 339 | 351 | |
| 340 | 352 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_3, |
| 341 | − ge_mac_cfg_3->value); | |
| 353 | + *ge_mac_cfg_3_value); | |
| 342 | 354 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_0, |
| 343 | − ge_mac_cfg_0.value); | |
| 355 | + ge_mac_cfg_0_value); | |
| 344 | 356 | } |
| 345 | 357 | |
| 346 | 358 | static void nps_enet_hw_disable_control(struct net_device *ndev) |
| @@ -358,31 +370,28 @@ static void nps_enet_send_frame(struct net_device *ndev, · 11 unmodified lines | ||
| 358 | 370 | struct sk_buff *skb) |
| 359 | 371 | { |
| 360 | 372 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 361 | − struct nps_enet_tx_ctl tx_ctrl; | |
| 373 | + u32 tx_ctrl_value = 0; | |
| 362 | 374 | short length = skb->len; |
| 363 | 375 | u32 i, len = DIV_ROUND_UP(length, sizeof(u32)); |
| 364 | 376 | u32 *src = (void *)skb->data; |
| 365 | 377 | bool src_is_aligned = IS_ALIGNED((unsigned long)src, sizeof(u32)); |
| 366 | 378 | |
| 367 | − tx_ctrl.value = 0; | |
| 368 | 379 | /* In case src is not aligned we need an intermediate buffer */ |
| 369 | 380 | if (src_is_aligned) |
| 370 | − for (i = 0; i < len; i++, src++) | |
| 371 | − nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, *src); | |
| 381 | + iowrite32_rep(priv->regs_base + NPS_ENET_REG_TX_BUF, src, len); | |
| 372 | 382 | else /* !src_is_aligned */ |
| 373 | 383 | for (i = 0; i < len; i++, src++) |
| 374 | 384 | nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, |
| 375 | − get_unaligned(src)); | |
| 385 | + get_unaligned_be32(src)); | |
| 376 | 386 | |
| 377 | 387 | /* Write the length of the Frame */ |
| 378 | − tx_ctrl.nt = length; | |
| 388 | + tx_ctrl_value |= length << TX_CTL_NT_SHIFT; | |
| 379 | 389 | |
| 380 | 390 | /* Indicate SW is done */ |
| 381 | 391 | priv->tx_packet_sent = true; |
| 382 | − tx_ctrl.ct = NPS_ENET_ENABLE; | |
| 383 | − | |
| 392 | + tx_ctrl_value |= NPS_ENET_ENABLE << TX_CTL_CT_SHIFT; | |
| 384 | 393 | /* Send Frame */ |
| 385 | − nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, tx_ctrl.value); | |
| 394 | + nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, tx_ctrl_value); | |
| 386 | 395 | } |
| 387 | 396 | |
| 388 | 397 | /** |
| @@ -422,19 +431,23 @@ static s32 nps_enet_set_mac_address(struct net_device *ndev, void *p) · 33 unmodified lines | ||
| 422 | 431 | static void nps_enet_set_rx_mode(struct net_device *ndev) |
| 423 | 432 | { |
| 424 | 433 | struct nps_enet_priv *priv = netdev_priv(ndev); |
| 425 | − struct nps_enet_ge_mac_cfg_2 ge_mac_cfg_2; | |
| 426 | − | |
| 427 | − ge_mac_cfg_2.value = priv->ge_mac_cfg_2.value; | |
| 434 | + u32 ge_mac_cfg_2_value = priv->ge_mac_cfg_2_value; | |
| 428 | 435 | |
| 429 | 436 | if (ndev->flags & IFF_PROMISC) { |
| 430 | − ge_mac_cfg_2.disc_da = NPS_ENET_DISABLE; | |
| 431 | − ge_mac_cfg_2.disc_mc = NPS_ENET_DISABLE; | |
| 437 | + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) | |
| 438 | + | NPS_ENET_DISABLE << CFG_2_DISK_DA_SHIFT; | |
| 439 | + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) | |
| 440 | + | NPS_ENET_DISABLE << CFG_2_DISK_MC_SHIFT; | |
| 441 | + | |
| 432 | 442 | } else { |
| 433 | − ge_mac_cfg_2.disc_da = NPS_ENET_ENABLE; | |
| 434 | − ge_mac_cfg_2.disc_mc = NPS_ENET_ENABLE; | |
| 443 | + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) | |
| 444 | + | NPS_ENET_ENABLE << CFG_2_DISK_DA_SHIFT; | |
| 445 | + ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) | |
| 446 | + | NPS_ENET_ENABLE << CFG_2_DISK_MC_SHIFT; | |
| 447 | + | |
| 435 | 448 | } |
| 436 | 449 | |
| 437 | − nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, ge_mac_cfg_2.value); | |
| 450 | + nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, ge_mac_cfg_2_value); | |
| 438 | 451 | } |
| 439 | 452 | |
| 440 | 453 | /** |
| @@ -453,12 +466,15 @@ static s32 nps_enet_open(struct net_device *ndev) · 12 unmodified lines | ||
| 453 | 466 | |
| 454 | 467 | /* Reset private variables */ |
| 455 | 468 | priv->tx_packet_sent = false; |
| 456 | − priv->ge_mac_cfg_2.value = 0; | |
| 457 | − priv->ge_mac_cfg_3.value = 0; | |
| 469 | + priv->ge_mac_cfg_2_value = 0; | |
| 470 | + priv->ge_mac_cfg_3_value = 0; | |
| 458 | 471 | |
| 459 | 472 | /* ge_mac_cfg_3 default values */ |
| 460 | − priv->ge_mac_cfg_3.rx_ifg_th = NPS_ENET_GE_MAC_CFG_3_RX_IFG_TH; | |
| 461 | − priv->ge_mac_cfg_3.max_len = NPS_ENET_GE_MAC_CFG_3_MAX_LEN; | |
| 473 | + priv->ge_mac_cfg_3_value |= | |
| 474 | + NPS_ENET_GE_MAC_CFG_3_RX_IFG_TH << CFG_3_RX_IFG_TH_SHIFT; | |
| 475 | + | |
| 476 | + priv->ge_mac_cfg_3_value |= | |
| 477 | + NPS_ENET_GE_MAC_CFG_3_MAX_LEN << CFG_3_MAX_LEN_SHIFT; | |
| 462 | 478 | |
| 463 | 479 | /* Disable HW device */ |
| 464 | 480 | nps_enet_hw_disable_control(ndev); |
| @@ -43,233 +43,123 @@ · 42 unmodified lines | ||
| 43 | 43 | #define NPS_ENET_REG_GE_RST 0x1400 |
| 44 | 44 | #define NPS_ENET_REG_PHASE_FIFO_CTL 0x1404 |
| 45 | 45 | |
| 46 | −/* Tx control register */ | |
| 47 | −struct nps_enet_tx_ctl { | |
| 48 | − union { | |
| 49 | − /* ct: SW sets to indicate frame ready in Tx buffer for | |
| 50 | − * transmission. HW resets to when transmission done | |
| 51 | − * et: Transmit error | |
| 52 | − * nt: Length in bytes of Tx frame loaded to Tx buffer | |
| 53 | − */ | |
| 54 | − struct { | |
| 55 | − u32 | |
| 56 | − __reserved_1:16, | |
| 57 | − ct:1, | |
| 58 | − et:1, | |
| 59 | − __reserved_2:3, | |
| 60 | − nt:11; | |
| 61 | − }; | |
| 62 | − | |
| 63 | − u32 value; | |
| 64 | − }; | |
| 65 | −}; | |
| 66 | − | |
| 67 | −/* Rx control register */ | |
| 68 | −struct nps_enet_rx_ctl { | |
| 69 | − union { | |
| 70 | − /* cr: HW sets to indicate frame ready in Rx buffer. | |
| 71 | − * SW resets to indicate host read received frame | |
| 72 | − * and new frames can be written to Rx buffer | |
| 73 | − * er: Rx error indication | |
| 74 | − * crc: Rx CRC error indication | |
| 75 | − * nr: Length in bytes of Rx frame loaded by MAC to Rx buffer | |
| 76 | − */ | |
| 77 | − struct { | |
| 78 | − u32 | |
| 79 | − __reserved_1:16, | |
| 80 | − cr:1, | |
| 81 | − er:1, | |
| 82 | − crc:1, | |
| 83 | − __reserved_2:2, | |
| 84 | − nr:11; | |
| 85 | − }; | |
| 86 | − | |
| 87 | − u32 value; | |
| 88 | − }; | |
| 89 | −}; | |
| 90 | − | |
| 91 | −/* Interrupt enable for data buffer events register */ | |
| 92 | −struct nps_enet_buf_int_enable { | |
| 93 | − union { | |
| 94 | − /* tx_done: Interrupt generation in the case when new frame | |
| 95 | − * is ready in Rx buffer | |
| 96 | − * rx_rdy: Interrupt generation in the case when current frame | |
| 97 | − * was read from TX buffer | |
| 98 | − */ | |
| 99 | − struct { | |
| 100 | − u32 | |
| 101 | − __reserved:30, | |
| 102 | − tx_done:1, | |
| 103 | − rx_rdy:1; | |
| 104 | − }; | |
| 105 | − | |
| 106 | − u32 value; | |
| 107 | − }; | |
| 108 | −}; | |
| 109 | − | |
| 110 | −/* Gbps Eth MAC Configuration 0 register */ | |
| 111 | −struct nps_enet_ge_mac_cfg_0 { | |
| 112 | − union { | |
| 113 | − /* tx_pr_len: Transmit preamble length in bytes | |
| 114 | − * tx_ifg_nib: Tx idle pattern | |
| 115 | − * nib_mode: Nibble (4-bit) Mode | |
| 116 | − * rx_pr_check_en: Receive preamble Check Enable | |
| 117 | − * tx_ifg: Transmit inter-Frame Gap | |
| 118 | − * rx_ifg: Receive inter-Frame Gap | |
| 119 | − * tx_fc_retr: Transmit Flow Control Retransmit Mode | |
| 120 | − * rx_length_check_en: Receive Length Check Enable | |
| 121 | − * rx_crc_ignore: Results of the CRC check are ignored | |
| 122 | − * rx_crc_strip: MAC strips the CRC from received frames | |
| 123 | − * rx_fc_en: Receive Flow Control Enable | |
| 124 | − * tx_crc_en: Transmit CRC Enabled | |
| 125 | − * tx_pad_en: Transmit Padding Enable | |
| 126 | − * tx_cf_en: Transmit Flow Control Enable | |
| 127 | − * tx_en: Transmit Enable | |
| 128 | − * rx_en: Receive Enable | |
| 129 | − */ | |
| 130 | − struct { | |
| 131 | − u32 | |
| 132 | − tx_pr_len:4, | |
| 133 | − tx_ifg_nib:4, | |
| 134 | − nib_mode:1, | |
| 135 | − rx_pr_check_en:1, | |
| 136 | − tx_ifg:6, | |
| 137 | − rx_ifg:4, | |
| 138 | − tx_fc_retr:3, | |
| 139 | − rx_length_check_en:1, | |
| 140 | − rx_crc_ignore:1, | |
| 141 | − rx_crc_strip:1, | |
| 142 | − rx_fc_en:1, | |
| 143 | − tx_crc_en:1, | |
| 144 | − tx_pad_en:1, | |
| 145 | − tx_fc_en:1, | |
| 146 | − tx_en:1, | |
| 147 | − rx_en:1; | |
| 148 | − }; | |
| 149 | − | |
| 150 | − u32 value; | |
| 151 | − }; | |
| 152 | −}; | |
| 153 | − | |
| 154 | −/* Gbps Eth MAC Configuration 1 register */ | |
| 155 | −struct nps_enet_ge_mac_cfg_1 { | |
| 156 | − union { | |
| 157 | − /* octet_3: MAC address octet 3 | |
| 158 | − * octet_2: MAC address octet 2 | |
| 159 | − * octet_1: MAC address octet 1 | |
| 160 | − * octet_0: MAC address octet 0 | |
| 161 | − */ | |
| 162 | − struct { | |
| 163 | − u32 | |
| 164 | − octet_3:8, | |
| 165 | − octet_2:8, | |
| 166 | − octet_1:8, | |
| 167 | − octet_0:8; | |
| 168 | − }; | |
| 169 | − | |
| 170 | − u32 value; | |
| 171 | − }; | |
| 172 | −}; | |
| 173 | − | |
| 174 | −/* Gbps Eth MAC Configuration 2 register */ | |
| 175 | −struct nps_enet_ge_mac_cfg_2 { | |
| 176 | − union { | |
| 177 | − /* transmit_flush_en: MAC flush enable | |
| 178 | − * stat_en: RMON statistics interface enable | |
| 179 | − * disc_da: Discard frames with DA different | |
| 180 | − * from MAC address | |
| 181 | − * disc_bc: Discard broadcast frames | |
| 182 | − * disc_mc: Discard multicast frames | |
| 183 | − * octet_5: MAC address octet 5 | |
| 184 | − * octet_4: MAC address octet 4 | |
| 185 | − */ | |
| 186 | − struct { | |
| 187 | − u32 | |
| 188 | − transmit_flush_en:1, | |
| 189 | − __reserved_1:5, | |
| 190 | − stat_en:2, | |
| 191 | − __reserved_2:1, | |
| 192 | − disc_da:1, | |
| 193 | − disc_bc:1, | |
| 194 | − disc_mc:1, | |
| 195 | − __reserved_3:4, | |
| 196 | − octet_5:8, | |
| 197 | − octet_4:8; | |
| 198 | − }; | |
| 199 | − | |
| 200 | − u32 value; | |
| 201 | − }; | |
| 202 | −}; | |
| 203 | − | |
| 204 | −/* Gbps Eth MAC Configuration 3 register */ | |
| 205 | −struct nps_enet_ge_mac_cfg_3 { | |
| 206 | − union { | |
| 207 | − /* ext_oob_cbfc_sel: Selects one of the 4 profiles for | |
| 208 | − * extended OOB in-flow-control indication | |
| 209 | − * max_len: Maximum receive frame length in bytes | |
| 210 | − * tx_cbfc_en: Enable transmission of class-based | |
| 211 | − * flow control packets | |
| 212 | − * rx_ifg_th: Threshold for IFG status reporting via OOB | |
| 213 | − * cf_timeout: Configurable time to decrement FC counters | |
| 214 | − * cf_drop: Drop control frames | |
| 215 | − * redirect_cbfc_sel: Selects one of CBFC redirect profiles | |
| 216 | − * rx_cbfc_redir_en: Enable Rx class-based flow | |
| 217 | − * control redirect | |
| 218 | − * rx_cbfc_en: Enable Rx class-based flow control | |
| 219 | − * tm_hd_mode: TM header mode | |
| 220 | − */ | |
| 221 | − struct { | |
| 222 | − u32 | |
| 223 | − ext_oob_cbfc_sel:2, | |
| 224 | − max_len:14, | |
| 225 | − tx_cbfc_en:1, | |
| 226 | − rx_ifg_th:5, | |
| 227 | − cf_timeout:4, | |
| 228 | − cf_drop:1, | |
| 229 | − redirect_cbfc_sel:2, | |
| 230 | − rx_cbfc_redir_en:1, | |
| 231 | − rx_cbfc_en:1, | |
| 232 | − tm_hd_mode:1; | |
| 233 | − }; | |
| 234 | − | |
| 235 | − u32 value; | |
| 236 | − }; | |
| 237 | −}; | |
| 238 | − | |
| 239 | −/* GE MAC, PCS reset control register */ | |
| 240 | −struct nps_enet_ge_rst { | |
| 241 | − union { | |
| 242 | − /* gmac_0: GE MAC reset | |
| 243 | − * spcs_0: SGMII PCS reset | |
| 244 | − */ | |
| 245 | − struct { | |
| 246 | − u32 | |
| 247 | − __reserved_1:23, | |
| 248 | − gmac_0:1, | |
| 249 | − __reserved_2:7, | |
| 250 | − spcs_0:1; | |
| 251 | − }; | |
| 252 | − | |
| 253 | − u32 value; | |
| 254 | − }; | |
| 255 | −}; | |
| 256 | − | |
| 257 | −/* Tx phase sync FIFO control register */ | |
| 258 | −struct nps_enet_phase_fifo_ctl { | |
| 259 | − union { | |
| 260 | − /* init: initialize serdes TX phase sync FIFO pointers | |
| 261 | − * rst: reset serdes TX phase sync FIFO | |
| 262 | − */ | |
| 263 | − struct { | |
| 264 | − u32 | |
| 265 | − __reserved:30, | |
| 266 | − init:1, | |
| 267 | − rst:1; | |
| 268 | − }; | |
| 269 | − | |
| 270 | − u32 value; | |
| 271 | − }; | |
| 272 | −}; | |
| 46 | +/* Tx control register masks and shifts */ | |
| 47 | +#define TX_CTL_NT_MASK 0x7FF | |
| 48 | +#define TX_CTL_NT_SHIFT 0 | |
| 49 | +#define TX_CTL_ET_MASK 0x4000 | |
| 50 | +#define TX_CTL_ET_SHIFT 14 | |
| 51 | +#define TX_CTL_CT_MASK 0x8000 | |
| 52 | +#define TX_CTL_CT_SHIFT 15 | |
| 53 | + | |
| 54 | +/* Rx control register masks and shifts */ | |
| 55 | +#define RX_CTL_NR_MASK 0x7FF | |
| 56 | +#define RX_CTL_NR_SHIFT 0 | |
| 57 | +#define RX_CTL_CRC_MASK 0x2000 | |
| 58 | +#define RX_CTL_CRC_SHIFT 13 | |
| 59 | +#define RX_CTL_ER_MASK 0x4000 | |
| 60 | +#define RX_CTL_ER_SHIFT 14 | |
| 61 | +#define RX_CTL_CR_MASK 0x8000 | |
| 62 | +#define RX_CTL_CR_SHIFT 15 | |
| 63 | + | |
| 64 | +/* Interrupt enable for data buffer events register masks and shifts */ | |
| 65 | +#define RX_RDY_MASK 0x1 | |
| 66 | +#define RX_RDY_SHIFT 0 | |
| 67 | +#define TX_DONE_MASK 0x2 | |
| 68 | +#define TX_DONE_SHIFT 1 | |
| 69 | + | |
| 70 | +/* Gbps Eth MAC Configuration 0 register masks and shifts */ | |
| 71 | +#define CFG_0_RX_EN_MASK 0x1 | |
| 72 | +#define CFG_0_RX_EN_SHIFT 0 | |
| 73 | +#define CFG_0_TX_EN_MASK 0x2 | |
| 74 | +#define CFG_0_TX_EN_SHIFT 1 | |
| 75 | +#define CFG_0_TX_FC_EN_MASK 0x4 | |
| 76 | +#define CFG_0_TX_FC_EN_SHIFT 2 | |
| 77 | +#define CFG_0_TX_PAD_EN_MASK 0x8 | |
| 78 | +#define CFG_0_TX_PAD_EN_SHIFT 3 | |
| 79 | +#define CFG_0_TX_CRC_EN_MASK 0x10 | |
| 80 | +#define CFG_0_TX_CRC_EN_SHIFT 4 | |
| 81 | +#define CFG_0_RX_FC_EN_MASK 0x20 | |
| 82 | +#define CFG_0_RX_FC_EN_SHIFT 5 | |
| 83 | +#define CFG_0_RX_CRC_STRIP_MASK 0x40 | |
| 84 | +#define CFG_0_RX_CRC_STRIP_SHIFT 6 | |
| 85 | +#define CFG_0_RX_CRC_IGNORE_MASK 0x80 | |
| 86 | +#define CFG_0_RX_CRC_IGNORE_SHIFT 7 | |
| 87 | +#define CFG_0_RX_LENGTH_CHECK_EN_MASK 0x100 | |
| 88 | +#define CFG_0_RX_LENGTH_CHECK_EN_SHIFT 8 | |
| 89 | +#define CFG_0_TX_FC_RETR_MASK 0xE00 | |
| 90 | +#define CFG_0_TX_FC_RETR_SHIFT 9 | |
| 91 | +#define CFG_0_RX_IFG_MASK 0xF000 | |
| 92 | +#define CFG_0_RX_IFG_SHIFT 12 | |
| 93 | +#define CFG_0_TX_IFG_MASK 0x3F0000 | |
| 94 | +#define CFG_0_TX_IFG_SHIFT 16 | |
| 95 | +#define CFG_0_RX_PR_CHECK_EN_MASK 0x400000 | |
| 96 | +#define CFG_0_RX_PR_CHECK_EN_SHIFT 22 | |
| 97 | +#define CFG_0_NIB_MODE_MASK 0x800000 | |
| 98 | +#define CFG_0_NIB_MODE_SHIFT 23 | |
| 99 | +#define CFG_0_TX_IFG_NIB_MASK 0xF000000 | |
| 100 | +#define CFG_0_TX_IFG_NIB_SHIFT 24 | |
| 101 | +#define CFG_0_TX_PR_LEN_MASK 0xF0000000 | |
| 102 | +#define CFG_0_TX_PR_LEN_SHIFT 28 | |
| 103 | + | |
| 104 | +/* Gbps Eth MAC Configuration 1 register masks and shifts */ | |
| 105 | +#define CFG_1_OCTET_0_MASK 0x000000FF | |
| 106 | +#define CFG_1_OCTET_0_SHIFT 0 | |
| 107 | +#define CFG_1_OCTET_1_MASK 0x0000FF00 | |
| 108 | +#define CFG_1_OCTET_1_SHIFT 8 | |
| 109 | +#define CFG_1_OCTET_2_MASK 0x00FF0000 | |
| 110 | +#define CFG_1_OCTET_2_SHIFT 16 | |
| 111 | +#define CFG_1_OCTET_3_MASK 0xFF000000 | |
| 112 | +#define CFG_1_OCTET_3_SHIFT 24 | |
| 113 | + | |
| 114 | +/* Gbps Eth MAC Configuration 2 register masks and shifts */ | |
| 115 | +#define CFG_2_OCTET_4_MASK 0x000000FF | |
| 116 | +#define CFG_2_OCTET_4_SHIFT 0 | |
| 117 | +#define CFG_2_OCTET_5_MASK 0x0000FF00 | |
| 118 | +#define CFG_2_OCTET_5_SHIFT 8 | |
| 119 | +#define CFG_2_DISK_MC_MASK 0x00100000 | |
| 120 | +#define CFG_2_DISK_MC_SHIFT 20 | |
| 121 | +#define CFG_2_DISK_BC_MASK 0x00200000 | |
| 122 | +#define CFG_2_DISK_BC_SHIFT 21 | |
| 123 | +#define CFG_2_DISK_DA_MASK 0x00400000 | |
| 124 | +#define CFG_2_DISK_DA_SHIFT 22 | |
| 125 | +#define CFG_2_STAT_EN_MASK 0x3000000 | |
| 126 | +#define CFG_2_STAT_EN_SHIFT 24 | |
| 127 | +#define CFG_2_TRANSMIT_FLUSH_EN_MASK 0x80000000 | |
| 128 | +#define CFG_2_TRANSMIT_FLUSH_EN_SHIFT 31 | |
| 129 | + | |
| 130 | +/* Gbps Eth MAC Configuration 3 register masks and shifts */ | |
| 131 | +#define CFG_3_TM_HD_MODE_MASK 0x1 | |
| 132 | +#define CFG_3_TM_HD_MODE_SHIFT 0 | |
| 133 | +#define CFG_3_RX_CBFC_EN_MASK 0x2 | |
| 134 | +#define CFG_3_RX_CBFC_EN_SHIFT 1 | |
| 135 | +#define CFG_3_RX_CBFC_REDIR_EN_MASK 0x4 | |
| 136 | +#define CFG_3_RX_CBFC_REDIR_EN_SHIFT 2 | |
| 137 | +#define CFG_3_REDIRECT_CBFC_SEL_MASK 0x18 | |
| 138 | +#define CFG_3_REDIRECT_CBFC_SEL_SHIFT 3 | |
| 139 | +#define CFG_3_CF_DROP_MASK 0x20 | |
| 140 | +#define CFG_3_CF_DROP_SHIFT 5 | |
| 141 | +#define CFG_3_CF_TIMEOUT_MASK 0x3C0 | |
| 142 | +#define CFG_3_CF_TIMEOUT_SHIFT 6 | |
| 143 | +#define CFG_3_RX_IFG_TH_MASK 0x7C00 | |
| 144 | +#define CFG_3_RX_IFG_TH_SHIFT 10 | |
| 145 | +#define CFG_3_TX_CBFC_EN_MASK 0x8000 | |
| 146 | +#define CFG_3_TX_CBFC_EN_SHIFT 15 | |
| 147 | +#define CFG_3_MAX_LEN_MASK 0x3FFF0000 | |
| 148 | +#define CFG_3_MAX_LEN_SHIFT 16 | |
| 149 | +#define CFG_3_EXT_OOB_CBFC_SEL_MASK 0xC0000000 | |
| 150 | +#define CFG_3_EXT_OOB_CBFC_SEL_SHIFT 30 | |
| 151 | + | |
| 152 | +/* GE MAC, PCS reset control register masks and shifts */ | |
| 153 | +#define RST_SPCS_MASK 0x1 | |
| 154 | +#define RST_SPCS_SHIFT 0 | |
| 155 | +#define RST_GMAC_0_MASK 0x100 | |
| 156 | +#define RST_GMAC_0_SHIFT 8 | |
| 157 | + | |
| 158 | +/* Tx phase sync FIFO control register masks and shifts */ | |
| 159 | +#define PHASE_FIFO_CTL_RST_MASK 0x1 | |
| 160 | +#define PHASE_FIFO_CTL_RST_SHIFT 0 | |
| 161 | +#define PHASE_FIFO_CTL_INIT_MASK 0x2 | |
| 162 | +#define PHASE_FIFO_CTL_INIT_SHIFT 1 | |
| 273 | 163 | |
| 274 | 164 | /** |
| 275 | 165 | * struct nps_enet_priv - Storage of ENET's private information. |
| @@ -285,8 +175,8 @@ struct nps_enet_priv { · 9 unmodified lines | ||
| 285 | 175 | bool tx_packet_sent; |
| 286 | 176 | struct sk_buff *tx_skb; |
| 287 | 177 | struct napi_struct napi; |
| 288 | − struct nps_enet_ge_mac_cfg_2 ge_mac_cfg_2; | |
| 289 | − struct nps_enet_ge_mac_cfg_3 ge_mac_cfg_3; | |
| 178 | + u32 ge_mac_cfg_2_value; | |
| 179 | + u32 ge_mac_cfg_3_value; | |
| 290 | 180 | }; |
| 291 | 181 | |
| 292 | 182 | /** |
| @@ -64,6 +64,7 @@ · 63 unmodified lines | ||
| 64 | 64 | #define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */ |
| 65 | 65 | #define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */ |
| 66 | 66 | #define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */ |
| 67 | +#define FEC_FTRL 0x1b0 /* Frame truncation receive length*/ | |
| 67 | 68 | #define FEC_RACC 0x1c4 /* Receive Accelerator function */ |
| 68 | 69 | #define FEC_RCMR_1 0x1c8 /* Receive classification match ring 1 */ |
| 69 | 70 | #define FEC_RCMR_2 0x1cc /* Receive classification match ring 2 */ |
| @@ -309,12 +310,6 @@ struct bufdesc_ex { · 239 unmodified lines | ||
| 309 | 310 | #define FEC_R_BUFF_SIZE(X) (((X) == 1) ? FEC_R_BUFF_SIZE_1 : \ |
| 310 | 311 | (((X) == 2) ? \ |
| 311 | 312 | FEC_R_BUFF_SIZE_2 : FEC_R_BUFF_SIZE_0)) |
| 312 | −#define FEC_R_DES_ACTIVE(X) (((X) == 1) ? FEC_R_DES_ACTIVE_1 : \ | |
| 313 | − (((X) == 2) ? \ | |
| 314 | − FEC_R_DES_ACTIVE_2 : FEC_R_DES_ACTIVE_0)) | |
| 315 | −#define FEC_X_DES_ACTIVE(X) (((X) == 1) ? FEC_X_DES_ACTIVE_1 : \ | |
| 316 | − (((X) == 2) ? \ | |
| 317 | − FEC_X_DES_ACTIVE_2 : FEC_X_DES_ACTIVE_0)) | |
| 318 | 313 | |
| 319 | 314 | #define FEC_DMA_CFG(X) (((X) == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1) |
| 320 | 315 | |
| @@ -380,6 +375,7 @@ struct bufdesc_ex { · 59 unmodified lines | ||
| 380 | 375 | #define FEC_ENET_TS_TIMER ((uint)0x00008000) |
| 381 | 376 | |
| 382 | 377 | #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER) |
| 378 | +#define FEC_NAPI_IMASK (FEC_ENET_MII | FEC_ENET_TS_TIMER) | |
| 383 | 379 | #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF)) |
| 384 | 380 | |
| 385 | 381 | /* ENET interrupt coalescing macro define */ |
| @@ -447,33 +443,35 @@ struct bufdesc_ex { · 61 unmodified lines | ||
| 447 | 443 | /* Controller supports RACC register */ |
| 448 | 444 | #define FEC_QUIRK_HAS_RACC (1 << 12) |
| 449 | 445 | |
| 446 | +struct bufdesc_prop { | |
| 447 | + int qid; | |
| 448 | + /* Address of Rx and Tx buffers */ | |
| 449 | + struct bufdesc *base; | |
| 450 | + struct bufdesc *last; | |
| 451 | + struct bufdesc *cur; | |
| 452 | + void __iomem *reg_desc_active; | |
| 453 | + dma_addr_t dma; | |
| 454 | + unsigned short ring_size; | |
| 455 | + unsigned char dsize; | |
| 456 | + unsigned char dsize_log2; | |
| 457 | +}; | |
| 458 | + | |
| 450 | 459 | struct fec_enet_priv_tx_q { |
| 451 | − int index; | |
| 460 | + struct bufdesc_prop bd; | |
| 452 | 461 | unsigned char *tx_bounce[TX_RING_SIZE]; |
| 453 | 462 | struct sk_buff *tx_skbuff[TX_RING_SIZE]; |
| 454 | 463 | |
| 455 | − dma_addr_t bd_dma; | |
| 456 | − struct bufdesc *tx_bd_base; | |
| 457 | − uint tx_ring_size; | |
| 458 | − | |
| 459 | 464 | unsigned short tx_stop_threshold; |
| 460 | 465 | unsigned short tx_wake_threshold; |
| 461 | 466 | |
| 462 | − struct bufdesc *cur_tx; | |
| 463 | 467 | struct bufdesc *dirty_tx; |
| 464 | 468 | char *tso_hdrs; |
| 465 | 469 | dma_addr_t tso_hdrs_dma; |
| 466 | 470 | }; |
| 467 | 471 | |
| 468 | 472 | struct fec_enet_priv_rx_q { |
| 469 | − int index; | |
| 473 | + struct bufdesc_prop bd; | |
| 470 | 474 | struct sk_buff *rx_skbuff[RX_RING_SIZE]; |
| 471 | − | |
| 472 | − dma_addr_t bd_dma; | |
| 473 | − struct bufdesc *rx_bd_base; | |
| 474 | − uint rx_ring_size; | |
| 475 | − | |
| 476 | − struct bufdesc *cur_rx; | |
| 477 | 475 | }; |
| 478 | 476 | |
| 479 | 477 | /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and |
| @@ -513,8 +511,6 @@ struct fec_enet_private { · 33 unmodified lines | ||
| 513 | 511 | unsigned long work_ts; |
| 514 | 512 | unsigned long work_mdio; |
| 515 | 513 | |
| 516 | − unsigned short bufdesc_size; | |
| 517 | − | |
| 518 | 514 | struct platform_device *pdev; |
| 519 | 515 | |
| 520 | 516 | int dev_id; |
| @@ -217,86 +217,38 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); · 216 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | #define IS_TSO_HEADER(txq, addr) \ |
| 219 | 219 | ((addr >= txq->tso_hdrs_dma) && \ |
| 220 | − (addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE)) | |
| 220 | + (addr < txq->tso_hdrs_dma + txq->bd.ring_size * TSO_HEADER_SIZE)) | |
| 221 | 221 | |
| 222 | 222 | static int mii_cnt; |
| 223 | 223 | |
| 224 | −static inline | |
| 225 | −struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, | |
| 226 | − struct fec_enet_private *fep, | |
| 227 | − int queue_id) | |
| 228 | −{ | |
| 229 | − struct bufdesc *new_bd = bdp + 1; | |
| 230 | − struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1; | |
| 231 | − struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id]; | |
| 232 | − struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id]; | |
| 233 | − struct bufdesc_ex *ex_base; | |
| 234 | − struct bufdesc *base; | |
| 235 | − int ring_size; | |
| 236 | − | |
| 237 | − if (bdp >= txq->tx_bd_base) { | |
| 238 | − base = txq->tx_bd_base; | |
| 239 | − ring_size = txq->tx_ring_size; | |
| 240 | − ex_base = (struct bufdesc_ex *)txq->tx_bd_base; | |
| 241 | − } else { | |
| 242 | − base = rxq->rx_bd_base; | |
| 243 | − ring_size = rxq->rx_ring_size; | |
| 244 | − ex_base = (struct bufdesc_ex *)rxq->rx_bd_base; | |
| 245 | − } | |
| 246 | − | |
| 247 | − if (fep->bufdesc_ex) | |
| 248 | − return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ? | |
| 249 | − ex_base : ex_new_bd); | |
| 250 | − else | |
| 251 | − return (new_bd >= (base + ring_size)) ? | |
| 252 | − base : new_bd; | |
| 253 | −} | |
| 254 | − | |
| 255 | −static inline | |
| 256 | −struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, | |
| 257 | − struct fec_enet_private *fep, | |
| 258 | − int queue_id) | |
| 259 | −{ | |
| 260 | − struct bufdesc *new_bd = bdp - 1; | |
| 261 | − struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1; | |
| 262 | − struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id]; | |
| 263 | − struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id]; | |
| 264 | − struct bufdesc_ex *ex_base; | |
| 265 | − struct bufdesc *base; | |
| 266 | − int ring_size; | |
| 267 | − | |
| 268 | − if (bdp >= txq->tx_bd_base) { | |
| 269 | − base = txq->tx_bd_base; | |
| 270 | − ring_size = txq->tx_ring_size; | |
| 271 | − ex_base = (struct bufdesc_ex *)txq->tx_bd_base; | |
| 272 | − } else { | |
| 273 | − base = rxq->rx_bd_base; | |
| 274 | − ring_size = rxq->rx_ring_size; | |
| 275 | − ex_base = (struct bufdesc_ex *)rxq->rx_bd_base; | |
| 276 | − } | |
| 224 | +static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, | |
| 225 | + struct bufdesc_prop *bd) | |
| 226 | +{ | |
| 227 | + return (bdp >= bd->last) ? bd->base | |
| 228 | + : (struct bufdesc *)(((unsigned)bdp) + bd->dsize); | |
| 229 | +} | |
| 277 | 230 | |
| 278 | − if (fep->bufdesc_ex) | |
| 279 | − return (struct bufdesc *)((ex_new_bd < ex_base) ? | |
| 280 | − (ex_new_bd + ring_size) : ex_new_bd); | |
| 281 | − else | |
| 282 | − return (new_bd < base) ? (new_bd + ring_size) : new_bd; | |
| 231 | +static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, | |
| 232 | + struct bufdesc_prop *bd) | |
| 233 | +{ | |
| 234 | + return (bdp <= bd->base) ? bd->last | |
| 235 | + : (struct bufdesc *)(((unsigned)bdp) - bd->dsize); | |
| 283 | 236 | } |
| 284 | 237 | |
| 285 | −static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp, | |
| 286 | − struct fec_enet_private *fep) | |
| 238 | +static int fec_enet_get_bd_index(struct bufdesc *bdp, | |
| 239 | + struct bufdesc_prop *bd) | |
| 287 | 240 | { |
| 288 | − return ((const char *)bdp - (const char *)base) / fep->bufdesc_size; | |
| 241 | + return ((const char *)bdp - (const char *)bd->base) >> bd->dsize_log2; | |
| 289 | 242 | } |
| 290 | 243 | |
| 291 | −static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep, | |
| 292 | − struct fec_enet_priv_tx_q *txq) | |
| 244 | +static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq) | |
| 293 | 245 | { |
| 294 | 246 | int entries; |
| 295 | 247 | |
| 296 | − entries = ((const char *)txq->dirty_tx - | |
| 297 | − (const char *)txq->cur_tx) / fep->bufdesc_size - 1; | |
| 248 | + entries = (((const char *)txq->dirty_tx - | |
| 249 | + (const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1; | |
| 298 | 250 | |
| 299 | − return entries > 0 ? entries : entries + txq->tx_ring_size; | |
| 251 | + return entries >= 0 ? entries : entries + txq->bd.ring_size; | |
| 300 | 252 | } |
| 301 | 253 | |
| 302 | 254 | static void swap_buffer(void *bufaddr, int len) |
| @@ -329,20 +281,20 @@ static void fec_dump(struct net_device *ndev) · 26 unmodified lines | ||
| 329 | 281 | pr_info("Nr SC addr len SKB\n"); |
| 330 | 282 | |
| 331 | 283 | txq = fep->tx_queue[0]; |
| 332 | − bdp = txq->tx_bd_base; | |
| 284 | + bdp = txq->bd.base; | |
| 333 | 285 | |
| 334 | 286 | do { |
| 335 | 287 | pr_info("%3u %c%c 0x%04x 0x%08x %4u %p\n", |
| 336 | 288 | index, |
| 337 | − bdp == txq->cur_tx ? 'S' : ' ', | |
| 289 | + bdp == txq->bd.cur ? 'S' : ' ', | |
| 338 | 290 | bdp == txq->dirty_tx ? 'H' : ' ', |
| 339 | 291 | fec16_to_cpu(bdp->cbd_sc), |
| 340 | 292 | fec32_to_cpu(bdp->cbd_bufaddr), |
| 341 | 293 | fec16_to_cpu(bdp->cbd_datlen), |
| 342 | 294 | txq->tx_skbuff[index]); |
| 343 | − bdp = fec_enet_get_nextdesc(bdp, fep, 0); | |
| 295 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 344 | 296 | index++; |
| 345 | − } while (bdp != txq->tx_bd_base); | |
| 297 | + } while (bdp != txq->bd.base); | |
| 346 | 298 | } |
| 347 | 299 | |
| 348 | 300 | static inline bool is_ipv4_pkt(struct sk_buff *skb) |
| @@ -373,10 +325,9 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, · 24 unmodified lines | ||
| 373 | 325 | struct net_device *ndev) |
| 374 | 326 | { |
| 375 | 327 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 376 | − struct bufdesc *bdp = txq->cur_tx; | |
| 328 | + struct bufdesc *bdp = txq->bd.cur; | |
| 377 | 329 | struct bufdesc_ex *ebdp; |
| 378 | 330 | int nr_frags = skb_shinfo(skb)->nr_frags; |
| 379 | − unsigned short queue = skb_get_queue_mapping(skb); | |
| 380 | 331 | int frag, frag_len; |
| 381 | 332 | unsigned short status; |
| 382 | 333 | unsigned int estatus = 0; |
| @@ -388,7 +339,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, · 5 unmodified lines | ||
| 388 | 339 | |
| 389 | 340 | for (frag = 0; frag < nr_frags; frag++) { |
| 390 | 341 | this_frag = &skb_shinfo(skb)->frags[frag]; |
| 391 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue); | |
| 342 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 392 | 343 | ebdp = (struct bufdesc_ex *)bdp; |
| 393 | 344 | |
| 394 | 345 | status = fec16_to_cpu(bdp->cbd_sc); |
| @@ -409,7 +360,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, · 14 unmodified lines | ||
| 409 | 360 | |
| 410 | 361 | if (fep->bufdesc_ex) { |
| 411 | 362 | if (fep->quirks & FEC_QUIRK_HAS_AVB) |
| 412 | − estatus |= FEC_TX_BD_FTYPE(queue); | |
| 363 | + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); | |
| 413 | 364 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
| 414 | 365 | estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; |
| 415 | 366 | ebdp->cbd_bdu = 0; |
| @@ -418,7 +369,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, · 2 unmodified lines | ||
| 418 | 369 | |
| 419 | 370 | bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; |
| 420 | 371 | |
| 421 | − index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); | |
| 372 | + index = fec_enet_get_bd_index(bdp, &txq->bd); | |
| 422 | 373 | if (((unsigned long) bufaddr) & fep->tx_align || |
| 423 | 374 | fep->quirks & FEC_QUIRK_SWAP_FRAME) { |
| 424 | 375 | memcpy(txq->tx_bounce[index], bufaddr, frag_len); |
| @@ -431,7 +382,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, · 6 unmodified lines | ||
| 431 | 382 | addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len, |
| 432 | 383 | DMA_TO_DEVICE); |
| 433 | 384 | if (dma_mapping_error(&fep->pdev->dev, addr)) { |
| 434 | − dev_kfree_skb_any(skb); | |
| 435 | 385 | if (net_ratelimit()) |
| 436 | 386 | netdev_err(ndev, "Tx DMA memory map failed\n"); |
| 437 | 387 | goto dma_mapping_error; |
| @@ -439,14 +389,18 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, · 1 unmodified line | ||
| 439 | 389 | |
| 440 | 390 | bdp->cbd_bufaddr = cpu_to_fec32(addr); |
| 441 | 391 | bdp->cbd_datlen = cpu_to_fec16(frag_len); |
| 392 | + /* Make sure the updates to rest of the descriptor are | |
| 393 | + * performed before transferring ownership. | |
| 394 | + */ | |
| 395 | + wmb(); | |
| 442 | 396 | bdp->cbd_sc = cpu_to_fec16(status); |
| 443 | 397 | } |
| 444 | 398 | |
| 445 | 399 | return bdp; |
| 446 | 400 | dma_mapping_error: |
| 447 | − bdp = txq->cur_tx; | |
| 401 | + bdp = txq->bd.cur; | |
| 448 | 402 | for (i = 0; i < frag; i++) { |
| 449 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue); | |
| 403 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 450 | 404 | dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr), |
| 451 | 405 | fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE); |
| 452 | 406 | } |
| @@ -463,12 +417,11 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 10 unmodified lines | ||
| 463 | 417 | dma_addr_t addr; |
| 464 | 418 | unsigned short status; |
| 465 | 419 | unsigned short buflen; |
| 466 | − unsigned short queue; | |
| 467 | 420 | unsigned int estatus = 0; |
| 468 | 421 | unsigned int index; |
| 469 | 422 | int entries_free; |
| 470 | 423 | |
| 471 | − entries_free = fec_enet_get_free_txdesc_num(fep, txq); | |
| 424 | + entries_free = fec_enet_get_free_txdesc_num(txq); | |
| 472 | 425 | if (entries_free < MAX_SKB_FRAGS + 1) { |
| 473 | 426 | dev_kfree_skb_any(skb); |
| 474 | 427 | if (net_ratelimit()) |
| @@ -483,7 +436,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 8 unmodified lines | ||
| 483 | 436 | } |
| 484 | 437 | |
| 485 | 438 | /* Fill in a Tx ring entry */ |
| 486 | − bdp = txq->cur_tx; | |
| 439 | + bdp = txq->bd.cur; | |
| 487 | 440 | last_bdp = bdp; |
| 488 | 441 | status = fec16_to_cpu(bdp->cbd_sc); |
| 489 | 442 | status &= ~BD_ENET_TX_STATS; |
| @@ -492,8 +445,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 2 unmodified lines | ||
| 492 | 445 | bufaddr = skb->data; |
| 493 | 446 | buflen = skb_headlen(skb); |
| 494 | 447 | |
| 495 | − queue = skb_get_queue_mapping(skb); | |
| 496 | − index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); | |
| 448 | + index = fec_enet_get_bd_index(bdp, &txq->bd); | |
| 497 | 449 | if (((unsigned long) bufaddr) & fep->tx_align || |
| 498 | 450 | fep->quirks & FEC_QUIRK_SWAP_FRAME) { |
| 499 | 451 | memcpy(txq->tx_bounce[index], skb->data, buflen); |
| @@ -514,8 +466,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 14 unmodified lines | ||
| 514 | 466 | |
| 515 | 467 | if (nr_frags) { |
| 516 | 468 | last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev); |
| 517 | − if (IS_ERR(last_bdp)) | |
| 469 | + if (IS_ERR(last_bdp)) { | |
| 470 | + dma_unmap_single(&fep->pdev->dev, addr, | |
| 471 | + buflen, DMA_TO_DEVICE); | |
| 472 | + dev_kfree_skb_any(skb); | |
| 518 | 473 | return NETDEV_TX_OK; |
| 474 | + } | |
| 519 | 475 | } else { |
| 520 | 476 | status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); |
| 521 | 477 | if (fep->bufdesc_ex) { |
| @@ -525,6 +481,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 3 unmodified lines | ||
| 525 | 481 | estatus |= BD_ENET_TX_TS; |
| 526 | 482 | } |
| 527 | 483 | } |
| 484 | + bdp->cbd_bufaddr = cpu_to_fec32(addr); | |
| 485 | + bdp->cbd_datlen = cpu_to_fec16(buflen); | |
| 528 | 486 | |
| 529 | 487 | if (fep->bufdesc_ex) { |
| 530 | 488 | |
| @@ -535,7 +493,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 4 unmodified lines | ||
| 535 | 493 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; |
| 536 | 494 | |
| 537 | 495 | if (fep->quirks & FEC_QUIRK_HAS_AVB) |
| 538 | − estatus |= FEC_TX_BD_FTYPE(queue); | |
| 496 | + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); | |
| 539 | 497 | |
| 540 | 498 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
| 541 | 499 | estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; |
| @@ -544,12 +502,14 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 2 unmodified lines | ||
| 544 | 502 | ebdp->cbd_esc = cpu_to_fec32(estatus); |
| 545 | 503 | } |
| 546 | 504 | |
| 547 | − index = fec_enet_get_bd_index(txq->tx_bd_base, last_bdp, fep); | |
| 505 | + index = fec_enet_get_bd_index(last_bdp, &txq->bd); | |
| 548 | 506 | /* Save skb pointer */ |
| 549 | 507 | txq->tx_skbuff[index] = skb; |
| 550 | 508 | |
| 551 | − bdp->cbd_datlen = cpu_to_fec16(buflen); | |
| 552 | − bdp->cbd_bufaddr = cpu_to_fec32(addr); | |
| 509 | + /* Make sure the updates to rest of the descriptor are performed before | |
| 510 | + * transferring ownership. | |
| 511 | + */ | |
| 512 | + wmb(); | |
| 553 | 513 | |
| 554 | 514 | /* Send it on its way. Tell FEC it's ready, interrupt when done, |
| 555 | 515 | * it's the last BD of the frame, and to put the CRC on the end. |
| @@ -558,18 +518,18 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, · 2 unmodified lines | ||
| 558 | 518 | bdp->cbd_sc = cpu_to_fec16(status); |
| 559 | 519 | |
| 560 | 520 | /* If this was the last BD in the ring, start at the beginning again. */ |
| 561 | − bdp = fec_enet_get_nextdesc(last_bdp, fep, queue); | |
| 521 | + bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd); | |
| 562 | 522 | |
| 563 | 523 | skb_tx_timestamp(skb); |
| 564 | 524 | |
| 565 | 525 | /* Make sure the update to bdp and tx_skbuff are performed before |
| 566 | − * cur_tx. | |
| 526 | + * txq->bd.cur. | |
| 567 | 527 | */ |
| 568 | 528 | wmb(); |
| 569 | − txq->cur_tx = bdp; | |
| 529 | + txq->bd.cur = bdp; | |
| 570 | 530 | |
| 571 | 531 | /* Trigger transmission start */ |
| 572 | − writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); | |
| 532 | + writel(0, txq->bd.reg_desc_active); | |
| 573 | 533 | |
| 574 | 534 | return 0; |
| 575 | 535 | } |
| @@ -582,7 +542,6 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, · 6 unmodified lines | ||
| 582 | 542 | { |
| 583 | 543 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 584 | 544 | struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); |
| 585 | − unsigned short queue = skb_get_queue_mapping(skb); | |
| 586 | 545 | unsigned short status; |
| 587 | 546 | unsigned int estatus = 0; |
| 588 | 547 | dma_addr_t addr; |
| @@ -614,7 +573,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, · 25 unmodified lines | ||
| 614 | 573 | |
| 615 | 574 | if (fep->bufdesc_ex) { |
| 616 | 575 | if (fep->quirks & FEC_QUIRK_HAS_AVB) |
| 617 | − estatus |= FEC_TX_BD_FTYPE(queue); | |
| 576 | + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); | |
| 618 | 577 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
| 619 | 578 | estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; |
| 620 | 579 | ebdp->cbd_bdu = 0; |
| @@ -643,7 +602,6 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, · 22 unmodified lines | ||
| 643 | 602 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 644 | 603 | int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); |
| 645 | 604 | struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); |
| 646 | − unsigned short queue = skb_get_queue_mapping(skb); | |
| 647 | 605 | void *bufaddr; |
| 648 | 606 | unsigned long dmabuf; |
| 649 | 607 | unsigned short status; |
| @@ -678,7 +636,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, · 28 unmodified lines | ||
| 678 | 636 | |
| 679 | 637 | if (fep->bufdesc_ex) { |
| 680 | 638 | if (fep->quirks & FEC_QUIRK_HAS_AVB) |
| 681 | − estatus |= FEC_TX_BD_FTYPE(queue); | |
| 639 | + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); | |
| 682 | 640 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
| 683 | 641 | estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; |
| 684 | 642 | ebdp->cbd_bdu = 0; |
| @@ -697,13 +655,12 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, · 12 unmodified lines | ||
| 697 | 655 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 698 | 656 | int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); |
| 699 | 657 | int total_len, data_left; |
| 700 | − struct bufdesc *bdp = txq->cur_tx; | |
| 701 | − unsigned short queue = skb_get_queue_mapping(skb); | |
| 658 | + struct bufdesc *bdp = txq->bd.cur; | |
| 702 | 659 | struct tso_t tso; |
| 703 | 660 | unsigned int index = 0; |
| 704 | 661 | int ret; |
| 705 | 662 | |
| 706 | − if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep, txq)) { | |
| 663 | + if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) { | |
| 707 | 664 | dev_kfree_skb_any(skb); |
| 708 | 665 | if (net_ratelimit()) |
| 709 | 666 | netdev_err(ndev, "NOT enough BD for TSO!\n"); |
| @@ -723,7 +680,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, · 13 unmodified lines | ||
| 723 | 680 | while (total_len > 0) { |
| 724 | 681 | char *hdr; |
| 725 | 682 | |
| 726 | − index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); | |
| 683 | + index = fec_enet_get_bd_index(bdp, &txq->bd); | |
| 727 | 684 | data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); |
| 728 | 685 | total_len -= data_left; |
| 729 | 686 | |
| @@ -738,9 +695,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, · 8 unmodified lines | ||
| 738 | 695 | int size; |
| 739 | 696 | |
| 740 | 697 | size = min_t(int, tso.size, data_left); |
| 741 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue); | |
| 742 | − index = fec_enet_get_bd_index(txq->tx_bd_base, | |
| 743 | − bdp, fep); | |
| 698 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 699 | + index = fec_enet_get_bd_index(bdp, &txq->bd); | |
| 744 | 700 | ret = fec_enet_txq_put_data_tso(txq, skb, ndev, |
| 745 | 701 | bdp, index, |
| 746 | 702 | tso.data, size, |
| @@ -753,22 +709,22 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, · 6 unmodified lines | ||
| 753 | 709 | tso_build_data(skb, &tso, size); |
| 754 | 710 | } |
| 755 | 711 | |
| 756 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue); | |
| 712 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 757 | 713 | } |
| 758 | 714 | |
| 759 | 715 | /* Save skb pointer */ |
| 760 | 716 | txq->tx_skbuff[index] = skb; |
| 761 | 717 | |
| 762 | 718 | skb_tx_timestamp(skb); |
| 763 | − txq->cur_tx = bdp; | |
| 719 | + txq->bd.cur = bdp; | |
| 764 | 720 | |
| 765 | 721 | /* Trigger transmission start */ |
| 766 | 722 | if (!(fep->quirks & FEC_QUIRK_ERR007885) || |
| 767 | − !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || | |
| 768 | − !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || | |
| 769 | − !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || | |
| 770 | − !readl(fep->hwp + FEC_X_DES_ACTIVE(queue))) | |
| 771 | − writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); | |
| 723 | + !readl(txq->bd.reg_desc_active) || | |
| 724 | + !readl(txq->bd.reg_desc_active) || | |
| 725 | + !readl(txq->bd.reg_desc_active) || | |
| 726 | + !readl(txq->bd.reg_desc_active)) | |
| 727 | + writel(0, txq->bd.reg_desc_active); | |
| 772 | 728 | |
| 773 | 729 | return 0; |
| 774 | 730 | |
| @@ -798,7 +754,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 23 unmodified lines | ||
| 798 | 754 | if (ret) |
| 799 | 755 | return ret; |
| 800 | 756 | |
| 801 | − entries_free = fec_enet_get_free_txdesc_num(fep, txq); | |
| 757 | + entries_free = fec_enet_get_free_txdesc_num(txq); | |
| 802 | 758 | if (entries_free <= txq->tx_stop_threshold) |
| 803 | 759 | netif_tx_stop_queue(nq); |
| 804 | 760 | |
| @@ -819,32 +775,32 @@ static void fec_enet_bd_init(struct net_device *dev) · 14 unmodified lines | ||
| 819 | 775 | for (q = 0; q < fep->num_rx_queues; q++) { |
| 820 | 776 | /* Initialize the receive buffer descriptors. */ |
| 821 | 777 | rxq = fep->rx_queue[q]; |
| 822 | − bdp = rxq->rx_bd_base; | |
| 778 | + bdp = rxq->bd.base; | |
| 823 | 779 | |
| 824 | − for (i = 0; i < rxq->rx_ring_size; i++) { | |
| 780 | + for (i = 0; i < rxq->bd.ring_size; i++) { | |
| 825 | 781 | |
| 826 | 782 | /* Initialize the BD for every fragment in the page. */ |
| 827 | 783 | if (bdp->cbd_bufaddr) |
| 828 | 784 | bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); |
| 829 | 785 | else |
| 830 | 786 | bdp->cbd_sc = cpu_to_fec16(0); |
| 831 | − bdp = fec_enet_get_nextdesc(bdp, fep, q); | |
| 787 | + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); | |
| 832 | 788 | } |
| 833 | 789 | |
| 834 | 790 | /* Set the last buffer to wrap */ |
| 835 | − bdp = fec_enet_get_prevdesc(bdp, fep, q); | |
| 791 | + bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); | |
| 836 | 792 | bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); |
| 837 | 793 | |
| 838 | − rxq->cur_rx = rxq->rx_bd_base; | |
| 794 | + rxq->bd.cur = rxq->bd.base; | |
| 839 | 795 | } |
| 840 | 796 | |
| 841 | 797 | for (q = 0; q < fep->num_tx_queues; q++) { |
| 842 | 798 | /* ...and the same for transmit */ |
| 843 | 799 | txq = fep->tx_queue[q]; |
| 844 | − bdp = txq->tx_bd_base; | |
| 845 | − txq->cur_tx = bdp; | |
| 800 | + bdp = txq->bd.base; | |
| 801 | + txq->bd.cur = bdp; | |
| 846 | 802 | |
| 847 | − for (i = 0; i < txq->tx_ring_size; i++) { | |
| 803 | + for (i = 0; i < txq->bd.ring_size; i++) { | |
| 848 | 804 | /* Initialize the BD for every fragment in the page. */ |
| 849 | 805 | bdp->cbd_sc = cpu_to_fec16(0); |
| 850 | 806 | if (txq->tx_skbuff[i]) { |
| @@ -852,11 +808,11 @@ static void fec_enet_bd_init(struct net_device *dev) · 1 unmodified line | ||
| 852 | 808 | txq->tx_skbuff[i] = NULL; |
| 853 | 809 | } |
| 854 | 810 | bdp->cbd_bufaddr = cpu_to_fec32(0); |
| 855 | − bdp = fec_enet_get_nextdesc(bdp, fep, q); | |
| 811 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 856 | 812 | } |
| 857 | 813 | |
| 858 | 814 | /* Set the last buffer to wrap */ |
| 859 | − bdp = fec_enet_get_prevdesc(bdp, fep, q); | |
| 815 | + bdp = fec_enet_get_prevdesc(bdp, &txq->bd); | |
| 860 | 816 | bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); |
| 861 | 817 | txq->dirty_tx = bdp; |
| 862 | 818 | } |
| @@ -868,7 +824,7 @@ static void fec_enet_active_rxring(struct net_device *ndev) · 5 unmodified lines | ||
| 868 | 824 | int i; |
| 869 | 825 | |
| 870 | 826 | for (i = 0; i < fep->num_rx_queues; i++) |
| 871 | − writel(0, fep->hwp + FEC_R_DES_ACTIVE(i)); | |
| 827 | + writel(0, fep->rx_queue[i]->bd.reg_desc_active); | |
| 872 | 828 | } |
| 873 | 829 | |
| 874 | 830 | static void fec_enet_enable_ring(struct net_device *ndev) |
| @@ -880,7 +836,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) · 5 unmodified lines | ||
| 880 | 836 | |
| 881 | 837 | for (i = 0; i < fep->num_rx_queues; i++) { |
| 882 | 838 | rxq = fep->rx_queue[i]; |
| 883 | − writel(rxq->bd_dma, fep->hwp + FEC_R_DES_START(i)); | |
| 839 | + writel(rxq->bd.dma, fep->hwp + FEC_R_DES_START(i)); | |
| 884 | 840 | writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i)); |
| 885 | 841 | |
| 886 | 842 | /* enable DMA1/2 */ |
| @@ -891,7 +847,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) · 4 unmodified lines | ||
| 891 | 847 | |
| 892 | 848 | for (i = 0; i < fep->num_tx_queues; i++) { |
| 893 | 849 | txq = fep->tx_queue[i]; |
| 894 | − writel(txq->bd_dma, fep->hwp + FEC_X_DES_START(i)); | |
| 850 | + writel(txq->bd.dma, fep->hwp + FEC_X_DES_START(i)); | |
| 895 | 851 | |
| 896 | 852 | /* enable DMA1/2 */ |
| 897 | 853 | if (i) |
| @@ -909,7 +865,7 @@ static void fec_enet_reset_skb(struct net_device *ndev) · 11 unmodified lines | ||
| 909 | 865 | for (i = 0; i < fep->num_tx_queues; i++) { |
| 910 | 866 | txq = fep->tx_queue[i]; |
| 911 | 867 | |
| 912 | − for (j = 0; j < txq->tx_ring_size; j++) { | |
| 868 | + for (j = 0; j < txq->bd.ring_size; j++) { | |
| 913 | 869 | if (txq->tx_skbuff[j]) { |
| 914 | 870 | dev_kfree_skb_any(txq->tx_skbuff[j]); |
| 915 | 871 | txq->tx_skbuff[j] = NULL; |
| @@ -988,6 +944,7 @@ fec_restart(struct net_device *ndev) · 72 unmodified lines | ||
| 988 | 944 | val &= ~FEC_RACC_OPTIONS; |
| 989 | 945 | writel(val, fep->hwp + FEC_RACC); |
| 990 | 946 | } |
| 947 | + writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); | |
| 991 | 948 | #endif |
| 992 | 949 | |
| 993 | 950 | /* |
| @@ -1221,16 +1178,16 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) · 227 unmodified lines | ||
| 1221 | 1178 | bdp = txq->dirty_tx; |
| 1222 | 1179 | |
| 1223 | 1180 | /* get next bdp of dirty_tx */ |
| 1224 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); | |
| 1181 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 1225 | 1182 | |
| 1226 | − while (bdp != READ_ONCE(txq->cur_tx)) { | |
| 1227 | − /* Order the load of cur_tx and cbd_sc */ | |
| 1183 | + while (bdp != READ_ONCE(txq->bd.cur)) { | |
| 1184 | + /* Order the load of bd.cur and cbd_sc */ | |
| 1228 | 1185 | rmb(); |
| 1229 | 1186 | status = fec16_to_cpu(READ_ONCE(bdp->cbd_sc)); |
| 1230 | 1187 | if (status & BD_ENET_TX_READY) |
| 1231 | 1188 | break; |
| 1232 | 1189 | |
| 1233 | − index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); | |
| 1190 | + index = fec_enet_get_bd_index(bdp, &txq->bd); | |
| 1234 | 1191 | |
| 1235 | 1192 | skb = txq->tx_skbuff[index]; |
| 1236 | 1193 | txq->tx_skbuff[index] = NULL; |
| @@ -1241,7 +1198,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) · 4 unmodified lines | ||
| 1241 | 1198 | DMA_TO_DEVICE); |
| 1242 | 1199 | bdp->cbd_bufaddr = cpu_to_fec32(0); |
| 1243 | 1200 | if (!skb) { |
| 1244 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); | |
| 1201 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 1245 | 1202 | continue; |
| 1246 | 1203 | } |
| 1247 | 1204 | |
| @@ -1290,21 +1247,21 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) · 42 unmodified lines | ||
| 1290 | 1247 | txq->dirty_tx = bdp; |
| 1291 | 1248 | |
| 1292 | 1249 | /* Update pointer to next buffer descriptor to be transmitted */ |
| 1293 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); | |
| 1250 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 1294 | 1251 | |
| 1295 | 1252 | /* Since we have freed up a buffer, the ring is no longer full |
| 1296 | 1253 | */ |
| 1297 | 1254 | if (netif_queue_stopped(ndev)) { |
| 1298 | − entries_free = fec_enet_get_free_txdesc_num(fep, txq); | |
| 1255 | + entries_free = fec_enet_get_free_txdesc_num(txq); | |
| 1299 | 1256 | if (entries_free >= txq->tx_wake_threshold) |
| 1300 | 1257 | netif_tx_wake_queue(nq); |
| 1301 | 1258 | } |
| 1302 | 1259 | } |
| 1303 | 1260 | |
| 1304 | 1261 | /* ERR006538: Keep the transmitter going */ |
| 1305 | − if (bdp != txq->cur_tx && | |
| 1306 | − readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0) | |
| 1307 | − writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id)); | |
| 1262 | + if (bdp != txq->bd.cur && | |
| 1263 | + readl(txq->bd.reg_desc_active) == 0) | |
| 1264 | + writel(0, txq->bd.reg_desc_active); | |
| 1308 | 1265 | } |
| 1309 | 1266 | |
| 1310 | 1267 | static void |
| @@ -1366,7 +1323,7 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb, · 55 unmodified lines | ||
| 1366 | 1323 | return true; |
| 1367 | 1324 | } |
| 1368 | 1325 | |
| 1369 | −/* During a receive, the cur_rx points to the current incoming buffer. | |
| 1326 | +/* During a receive, the bd_rx.cur points to the current incoming buffer. | |
| 1370 | 1327 | * When we update through the ring, if the next incoming buffer has |
| 1371 | 1328 | * not been given to the system, we just set the empty indicator, |
| 1372 | 1329 | * effectively tossing the packet. |
| @@ -1399,7 +1356,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) · 26 unmodified lines | ||
| 1399 | 1356 | /* First, grab all of the stats for the incoming packet. |
| 1400 | 1357 | * These get messed up if we get called due to a busy condition. |
| 1401 | 1358 | */ |
| 1402 | − bdp = rxq->cur_rx; | |
| 1359 | + bdp = rxq->bd.cur; | |
| 1403 | 1360 | |
| 1404 | 1361 | while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) { |
| 1405 | 1362 | |
| @@ -1407,37 +1364,31 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) · 1 unmodified line | ||
| 1407 | 1364 | break; |
| 1408 | 1365 | pkt_received++; |
| 1409 | 1366 | |
| 1410 | − /* Since we have allocated space to hold a complete frame, | |
| 1411 | − * the last indicator should be set. | |
| 1412 | − */ | |
| 1413 | − if ((status & BD_ENET_RX_LAST) == 0) | |
| 1414 | − netdev_err(ndev, "rcv is not +last\n"); | |
| 1415 | − | |
| 1416 | 1367 | writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); |
| 1417 | 1368 | |
| 1418 | 1369 | /* Check for errors. */ |
| 1370 | + status ^= BD_ENET_RX_LAST; | |
| 1419 | 1371 | if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | |
| 1420 | − BD_ENET_RX_CR | BD_ENET_RX_OV)) { | |
| 1372 | + BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST | | |
| 1373 | + BD_ENET_RX_CL)) { | |
| 1421 | 1374 | ndev->stats.rx_errors++; |
| 1422 | − if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { | |
| 1375 | + if (status & BD_ENET_RX_OV) { | |
| 1376 | + /* FIFO overrun */ | |
| 1377 | + ndev->stats.rx_fifo_errors++; | |
| 1378 | + goto rx_processing_done; | |
| 1379 | + } | |
| 1380 | + if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | |
| 1381 | + | BD_ENET_RX_LAST)) { | |
| 1423 | 1382 | /* Frame too long or too short. */ |
| 1424 | 1383 | ndev->stats.rx_length_errors++; |
| 1384 | + if (status & BD_ENET_RX_LAST) | |
| 1385 | + netdev_err(ndev, "rcv is not +last\n"); | |
| 1425 | 1386 | } |
| 1426 | − if (status & BD_ENET_RX_NO) /* Frame alignment */ | |
| 1427 | − ndev->stats.rx_frame_errors++; | |
| 1428 | 1387 | if (status & BD_ENET_RX_CR) /* CRC Error */ |
| 1429 | 1388 | ndev->stats.rx_crc_errors++; |
| 1430 | − if (status & BD_ENET_RX_OV) /* FIFO overrun */ | |
| 1431 | − ndev->stats.rx_fifo_errors++; | |
| 1432 | − } | |
| 1433 | − | |
| 1434 | − /* Report late collisions as a frame error. | |
| 1435 | − * On this error, the BD is closed, but we don't know what we | |
| 1436 | − * have in the buffer. So, just drop this frame on the floor. | |
| 1437 | − */ | |
| 1438 | − if (status & BD_ENET_RX_CL) { | |
| 1439 | − ndev->stats.rx_errors++; | |
| 1440 | − ndev->stats.rx_frame_errors++; | |
| 1389 | + /* Report late collisions as a frame error. */ | |
| 1390 | + if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL)) | |
| 1391 | + ndev->stats.rx_frame_errors++; | |
| 1441 | 1392 | goto rx_processing_done; |
| 1442 | 1393 | } |
| 1443 | 1394 | |
| @@ -1446,7 +1397,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) · 2 unmodified lines | ||
| 1446 | 1397 | pkt_len = fec16_to_cpu(bdp->cbd_datlen); |
| 1447 | 1398 | ndev->stats.rx_bytes += pkt_len; |
| 1448 | 1399 | |
| 1449 | − index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep); | |
| 1400 | + index = fec_enet_get_bd_index(bdp, &rxq->bd); | |
| 1450 | 1401 | skb = rxq->rx_skbuff[index]; |
| 1451 | 1402 | |
| 1452 | 1403 | /* The packet length includes FCS, but we don't want to |
| @@ -1535,7 +1486,6 @@ rx_processing_done: · 82 unmodified lines | ||
| 1535 | 1486 | |
| 1536 | 1487 | /* Mark the buffer empty */ |
| 1537 | 1488 | status |= BD_ENET_RX_EMPTY; |
| 1538 | − bdp->cbd_sc = cpu_to_fec16(status); | |
| 1539 | 1489 | |
| 1540 | 1490 | if (fep->bufdesc_ex) { |
| 1541 | 1491 | struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; |
| @@ -1544,17 +1494,22 @@ rx_processing_done: · 2 unmodified lines | ||
| 1544 | 1494 | ebdp->cbd_prot = 0; |
| 1545 | 1495 | ebdp->cbd_bdu = 0; |
| 1546 | 1496 | } |
| 1497 | + /* Make sure the updates to rest of the descriptor are | |
| 1498 | + * performed before transferring ownership. | |
| 1499 | + */ | |
| 1500 | + wmb(); | |
| 1501 | + bdp->cbd_sc = cpu_to_fec16(status); | |
| 1547 | 1502 | |
| 1548 | 1503 | /* Update BD pointer to next entry */ |
| 1549 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); | |
| 1504 | + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); | |
| 1550 | 1505 | |
| 1551 | 1506 | /* Doing this here will keep the FEC running while we process |
| 1552 | 1507 | * incoming frames. On a heavily loaded network, we should be |
| 1553 | 1508 | * able to keep up at the expense of system resources. |
| 1554 | 1509 | */ |
| 1555 | − writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id)); | |
| 1510 | + writel(0, rxq->bd.reg_desc_active); | |
| 1556 | 1511 | } |
| 1557 | − rxq->cur_rx = bdp; | |
| 1512 | + rxq->bd.cur = bdp; | |
| 1558 | 1513 | return pkt_received; |
| 1559 | 1514 | } |
| 1560 | 1515 | |
| @@ -1613,7 +1568,7 @@ fec_enet_interrupt(int irq, void *dev_id) · 52 unmodified lines | ||
| 1613 | 1568 | |
| 1614 | 1569 | if (napi_schedule_prep(&fep->napi)) { |
| 1615 | 1570 | /* Disable the NAPI interrupts */ |
| 1616 | − writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); | |
| 1571 | + writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK); | |
| 1617 | 1572 | __napi_schedule(&fep->napi); |
| 1618 | 1573 | } |
| 1619 | 1574 | } |
| @@ -2663,8 +2618,8 @@ static void fec_enet_free_buffers(struct net_device *ndev) · 1043 unmodified lines | ||
| 2663 | 2618 | |
| 2664 | 2619 | for (q = 0; q < fep->num_rx_queues; q++) { |
| 2665 | 2620 | rxq = fep->rx_queue[q]; |
| 2666 | − bdp = rxq->rx_bd_base; | |
| 2667 | − for (i = 0; i < rxq->rx_ring_size; i++) { | |
| 2621 | + bdp = rxq->bd.base; | |
| 2622 | + for (i = 0; i < rxq->bd.ring_size; i++) { | |
| 2668 | 2623 | skb = rxq->rx_skbuff[i]; |
| 2669 | 2624 | rxq->rx_skbuff[i] = NULL; |
| 2670 | 2625 | if (skb) { |
| @@ -2674,14 +2629,14 @@ static void fec_enet_free_buffers(struct net_device *ndev) · 3 unmodified lines | ||
| 2674 | 2629 | DMA_FROM_DEVICE); |
| 2675 | 2630 | dev_kfree_skb(skb); |
| 2676 | 2631 | } |
| 2677 | − bdp = fec_enet_get_nextdesc(bdp, fep, q); | |
| 2632 | + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); | |
| 2678 | 2633 | } |
| 2679 | 2634 | } |
| 2680 | 2635 | |
| 2681 | 2636 | for (q = 0; q < fep->num_tx_queues; q++) { |
| 2682 | 2637 | txq = fep->tx_queue[q]; |
| 2683 | − bdp = txq->tx_bd_base; | |
| 2684 | − for (i = 0; i < txq->tx_ring_size; i++) { | |
| 2638 | + bdp = txq->bd.base; | |
| 2639 | + for (i = 0; i < txq->bd.ring_size; i++) { | |
| 2685 | 2640 | kfree(txq->tx_bounce[i]); |
| 2686 | 2641 | txq->tx_bounce[i] = NULL; |
| 2687 | 2642 | skb = txq->tx_skbuff[i]; |
| @@ -2701,7 +2656,7 @@ static void fec_enet_free_queue(struct net_device *ndev) · 13 unmodified lines | ||
| 2701 | 2656 | if (fep->tx_queue[i] && fep->tx_queue[i]->tso_hdrs) { |
| 2702 | 2657 | txq = fep->tx_queue[i]; |
| 2703 | 2658 | dma_free_coherent(NULL, |
| 2704 | − txq->tx_ring_size * TSO_HEADER_SIZE, | |
| 2659 | + txq->bd.ring_size * TSO_HEADER_SIZE, | |
| 2705 | 2660 | txq->tso_hdrs, |
| 2706 | 2661 | txq->tso_hdrs_dma); |
| 2707 | 2662 | } |
| @@ -2727,15 +2682,15 @@ static int fec_enet_alloc_queue(struct net_device *ndev) · 19 unmodified lines | ||
| 2727 | 2682 | } |
| 2728 | 2683 | |
| 2729 | 2684 | fep->tx_queue[i] = txq; |
| 2730 | − txq->tx_ring_size = TX_RING_SIZE; | |
| 2731 | − fep->total_tx_ring_size += fep->tx_queue[i]->tx_ring_size; | |
| 2685 | + txq->bd.ring_size = TX_RING_SIZE; | |
| 2686 | + fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size; | |
| 2732 | 2687 | |
| 2733 | 2688 | txq->tx_stop_threshold = FEC_MAX_SKB_DESCS; |
| 2734 | 2689 | txq->tx_wake_threshold = |
| 2735 | − (txq->tx_ring_size - txq->tx_stop_threshold) / 2; | |
| 2690 | + (txq->bd.ring_size - txq->tx_stop_threshold) / 2; | |
| 2736 | 2691 | |
| 2737 | 2692 | txq->tso_hdrs = dma_alloc_coherent(NULL, |
| 2738 | − txq->tx_ring_size * TSO_HEADER_SIZE, | |
| 2693 | + txq->bd.ring_size * TSO_HEADER_SIZE, | |
| 2739 | 2694 | &txq->tso_hdrs_dma, |
| 2740 | 2695 | GFP_KERNEL); |
| 2741 | 2696 | if (!txq->tso_hdrs) { |
| @@ -2752,8 +2707,8 @@ static int fec_enet_alloc_queue(struct net_device *ndev) · 10 unmodified lines | ||
| 2752 | 2707 | goto alloc_failed; |
| 2753 | 2708 | } |
| 2754 | 2709 | |
| 2755 | − fep->rx_queue[i]->rx_ring_size = RX_RING_SIZE; | |
| 2756 | − fep->total_rx_ring_size += fep->rx_queue[i]->rx_ring_size; | |
| 2710 | + fep->rx_queue[i]->bd.ring_size = RX_RING_SIZE; | |
| 2711 | + fep->total_rx_ring_size += fep->rx_queue[i]->bd.ring_size; | |
| 2757 | 2712 | } |
| 2758 | 2713 | return ret; |
| 2759 | 2714 | |
| @@ -2772,8 +2727,8 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) · 12 unmodified lines | ||
| 2772 | 2727 | struct fec_enet_priv_rx_q *rxq; |
| 2773 | 2728 | |
| 2774 | 2729 | rxq = fep->rx_queue[queue]; |
| 2775 | − bdp = rxq->rx_bd_base; | |
| 2776 | − for (i = 0; i < rxq->rx_ring_size; i++) { | |
| 2730 | + bdp = rxq->bd.base; | |
| 2731 | + for (i = 0; i < rxq->bd.ring_size; i++) { | |
| 2777 | 2732 | skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); |
| 2778 | 2733 | if (!skb) |
| 2779 | 2734 | goto err_alloc; |
| @@ -2791,11 +2746,11 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) · 11 unmodified lines | ||
| 2791 | 2746 | ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); |
| 2792 | 2747 | } |
| 2793 | 2748 | |
| 2794 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue); | |
| 2749 | + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); | |
| 2795 | 2750 | } |
| 2796 | 2751 | |
| 2797 | 2752 | /* Set the last buffer to wrap. */ |
| 2798 | − bdp = fec_enet_get_prevdesc(bdp, fep, queue); | |
| 2753 | + bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); | |
| 2799 | 2754 | bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); |
| 2800 | 2755 | return 0; |
| 2801 | 2756 | |
| @@ -2813,8 +2768,8 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) · 11 unmodified lines | ||
| 2813 | 2768 | struct fec_enet_priv_tx_q *txq; |
| 2814 | 2769 | |
| 2815 | 2770 | txq = fep->tx_queue[queue]; |
| 2816 | − bdp = txq->tx_bd_base; | |
| 2817 | − for (i = 0; i < txq->tx_ring_size; i++) { | |
| 2771 | + bdp = txq->bd.base; | |
| 2772 | + for (i = 0; i < txq->bd.ring_size; i++) { | |
| 2818 | 2773 | txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); |
| 2819 | 2774 | if (!txq->tx_bounce[i]) |
| 2820 | 2775 | goto err_alloc; |
| @@ -2827,11 +2782,11 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) · 6 unmodified lines | ||
| 2827 | 2782 | ebdp->cbd_esc = cpu_to_fec32(BD_ENET_TX_INT); |
| 2828 | 2783 | } |
| 2829 | 2784 | |
| 2830 | − bdp = fec_enet_get_nextdesc(bdp, fep, queue); | |
| 2785 | + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); | |
| 2831 | 2786 | } |
| 2832 | 2787 | |
| 2833 | 2788 | /* Set the last buffer to wrap. */ |
| 2834 | − bdp = fec_enet_get_prevdesc(bdp, fep, queue); | |
| 2789 | + bdp = fec_enet_get_prevdesc(bdp, &txq->bd); | |
| 2835 | 2790 | bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); |
| 2836 | 2791 | |
| 2837 | 2792 | return 0; |
| @@ -3115,6 +3070,14 @@ static const struct net_device_ops fec_netdev_ops = { · 277 unmodified lines | ||
| 3115 | 3070 | .ndo_set_features = fec_set_features, |
| 3116 | 3071 | }; |
| 3117 | 3072 | |
| 3073 | +static const unsigned short offset_des_active_rxq[] = { | |
| 3074 | + FEC_R_DES_ACTIVE_0, FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2 | |
| 3075 | +}; | |
| 3076 | + | |
| 3077 | +static const unsigned short offset_des_active_txq[] = { | |
| 3078 | + FEC_X_DES_ACTIVE_0, FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2 | |
| 3079 | +}; | |
| 3080 | + | |
| 3118 | 3081 | /* |
| 3119 | 3082 | * XXX: We need to clean up on failure exits here. |
| 3120 | 3083 | * |
| @@ -3122,13 +3085,15 @@ static const struct net_device_ops fec_netdev_ops = { · 1 unmodified line | ||
| 3122 | 3085 | static int fec_enet_init(struct net_device *ndev) |
| 3123 | 3086 | { |
| 3124 | 3087 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 3125 | − struct fec_enet_priv_tx_q *txq; | |
| 3126 | − struct fec_enet_priv_rx_q *rxq; | |
| 3127 | 3088 | struct bufdesc *cbd_base; |
| 3128 | 3089 | dma_addr_t bd_dma; |
| 3129 | 3090 | int bd_size; |
| 3130 | 3091 | unsigned int i; |
| 3092 | + unsigned dsize = fep->bufdesc_ex ? sizeof(struct bufdesc_ex) : | |
| 3093 | + sizeof(struct bufdesc); | |
| 3094 | + unsigned dsize_log2 = __fls(dsize); | |
| 3131 | 3095 | |
| 3096 | + WARN_ON(dsize != (1 << dsize_log2)); | |
| 3132 | 3097 | #if defined(CONFIG_ARM) |
| 3133 | 3098 | fep->rx_align = 0xf; |
| 3134 | 3099 | fep->tx_align = 0xf; |
| @@ -3139,12 +3104,7 @@ static int fec_enet_init(struct net_device *ndev) · 4 unmodified lines | ||
| 3139 | 3104 | |
| 3140 | 3105 | fec_enet_alloc_queue(ndev); |
| 3141 | 3106 | |
| 3142 | − if (fep->bufdesc_ex) | |
| 3143 | − fep->bufdesc_size = sizeof(struct bufdesc_ex); | |
| 3144 | − else | |
| 3145 | − fep->bufdesc_size = sizeof(struct bufdesc); | |
| 3146 | − bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * | |
| 3147 | − fep->bufdesc_size; | |
| 3107 | + bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize; | |
| 3148 | 3108 | |
| 3149 | 3109 | /* Allocate memory for buffer descriptors. */ |
| 3150 | 3110 | cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma, |
| @@ -3162,33 +3122,35 @@ static int fec_enet_init(struct net_device *ndev) · 11 unmodified lines | ||
| 3162 | 3122 | |
| 3163 | 3123 | /* Set receive and transmit descriptor base. */ |
| 3164 | 3124 | for (i = 0; i < fep->num_rx_queues; i++) { |
| 3165 | − rxq = fep->rx_queue[i]; | |
| 3166 | − rxq->index = i; | |
| 3167 | − rxq->rx_bd_base = (struct bufdesc *)cbd_base; | |
| 3168 | − rxq->bd_dma = bd_dma; | |
| 3169 | − if (fep->bufdesc_ex) { | |
| 3170 | − bd_dma += sizeof(struct bufdesc_ex) * rxq->rx_ring_size; | |
| 3171 | − cbd_base = (struct bufdesc *) | |
| 3172 | − (((struct bufdesc_ex *)cbd_base) + rxq->rx_ring_size); | |
| 3173 | − } else { | |
| 3174 | − bd_dma += sizeof(struct bufdesc) * rxq->rx_ring_size; | |
| 3175 | − cbd_base += rxq->rx_ring_size; | |
| 3176 | − } | |
| 3125 | + struct fec_enet_priv_rx_q *rxq = fep->rx_queue[i]; | |
| 3126 | + unsigned size = dsize * rxq->bd.ring_size; | |
| 3127 | + | |
| 3128 | + rxq->bd.qid = i; | |
| 3129 | + rxq->bd.base = cbd_base; | |
| 3130 | + rxq->bd.cur = cbd_base; | |
| 3131 | + rxq->bd.dma = bd_dma; | |
| 3132 | + rxq->bd.dsize = dsize; | |
| 3133 | + rxq->bd.dsize_log2 = dsize_log2; | |
| 3134 | + rxq->bd.reg_desc_active = fep->hwp + offset_des_active_rxq[i]; | |
| 3135 | + bd_dma += size; | |
| 3136 | + cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); | |
| 3137 | + rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); | |
| 3177 | 3138 | } |
| 3178 | 3139 | |
| 3179 | 3140 | for (i = 0; i < fep->num_tx_queues; i++) { |
| 3180 | − txq = fep->tx_queue[i]; | |
| 3181 | − txq->index = i; | |
| 3182 | − txq->tx_bd_base = (struct bufdesc *)cbd_base; | |
| 3183 | − txq->bd_dma = bd_dma; | |
| 3184 | − if (fep->bufdesc_ex) { | |
| 3185 | − bd_dma += sizeof(struct bufdesc_ex) * txq->tx_ring_size; | |
| 3186 | − cbd_base = (struct bufdesc *) | |
| 3187 | − (((struct bufdesc_ex *)cbd_base) + txq->tx_ring_size); | |
| 3188 | − } else { | |
| 3189 | − bd_dma += sizeof(struct bufdesc) * txq->tx_ring_size; | |
| 3190 | − cbd_base += txq->tx_ring_size; | |
| 3191 | − } | |
| 3141 | + struct fec_enet_priv_tx_q *txq = fep->tx_queue[i]; | |
| 3142 | + unsigned size = dsize * txq->bd.ring_size; | |
| 3143 | + | |
| 3144 | + txq->bd.qid = i; | |
| 3145 | + txq->bd.base = cbd_base; | |
| 3146 | + txq->bd.cur = cbd_base; | |
| 3147 | + txq->bd.dma = bd_dma; | |
| 3148 | + txq->bd.dsize = dsize; | |
| 3149 | + txq->bd.dsize_log2 = dsize_log2; | |
| 3150 | + txq->bd.reg_desc_active = fep->hwp + offset_des_active_txq[i]; | |
| 3151 | + bd_dma += size; | |
| 3152 | + cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); | |
| 3153 | + txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); | |
| 3192 | 3154 | } |
| 3193 | 3155 | |
| 3194 | 3156 | |
| @@ -3229,6 +3191,7 @@ static int fec_enet_init(struct net_device *ndev) · 34 unmodified lines | ||
| 3229 | 3191 | static void fec_reset_phy(struct platform_device *pdev) |
| 3230 | 3192 | { |
| 3231 | 3193 | int err, phy_reset; |
| 3194 | + bool active_high = false; | |
| 3232 | 3195 | int msec = 1; |
| 3233 | 3196 | struct device_node *np = pdev->dev.of_node; |
| 3234 | 3197 | |
| @@ -3244,14 +3207,17 @@ static void fec_reset_phy(struct platform_device *pdev) · 9 unmodified lines | ||
| 3244 | 3207 | if (!gpio_is_valid(phy_reset)) |
| 3245 | 3208 | return; |
| 3246 | 3209 | |
| 3210 | + active_high = of_property_read_bool(np, "phy-reset-active-high"); | |
| 3211 | + | |
| 3247 | 3212 | err = devm_gpio_request_one(&pdev->dev, phy_reset, |
| 3248 | − GPIOF_OUT_INIT_LOW, "phy-reset"); | |
| 3213 | + active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, | |
| 3214 | + "phy-reset"); | |
| 3249 | 3215 | if (err) { |
| 3250 | 3216 | dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err); |
| 3251 | 3217 | return; |
| 3252 | 3218 | } |
| 3253 | 3219 | msleep(msec); |
| 3254 | − gpio_set_value_cansleep(phy_reset, 1); | |
| 3220 | + gpio_set_value_cansleep(phy_reset, !active_high); | |
| 3255 | 3221 | } |
| 3256 | 3222 | #else /* CONFIG_OF */ |
| 3257 | 3223 | static void fec_reset_phy(struct platform_device *pdev) |
| @@ -932,15 +932,14 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, · 931 unmodified lines | ||
| 932 | 932 | if (!is_init_done(dtsec->dtsec_drv_param)) |
| 933 | 933 | return -EINVAL; |
| 934 | 934 | |
| 935 | − /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ | |
| 936 | − if (dtsec->fm_rev_info.major == 2) | |
| 937 | − if (pause_time <= 320) { | |
| 935 | + if (pause_time) { | |
| 936 | + /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ | |
| 937 | + if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) { | |
| 938 | 938 | pr_warn("pause-time: %d illegal.Should be > 320\n", |
| 939 | 939 | pause_time); |
| 940 | 940 | return -EINVAL; |
| 941 | 941 | } |
| 942 | 942 | |
| 943 | − if (pause_time) { | |
| 944 | 943 | ptv = ioread32be(®s->ptv); |
| 945 | 944 | ptv &= PTV_PTE_MASK; |
| 946 | 945 | ptv |= pause_time & PTV_PT_MASK; |
| @@ -2324,6 +2324,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) · 2323 unmodified lines | ||
| 2324 | 2324 | struct txfcb *fcb = NULL; |
| 2325 | 2325 | struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL; |
| 2326 | 2326 | u32 lstatus; |
| 2327 | + skb_frag_t *frag; | |
| 2327 | 2328 | int i, rq = 0; |
| 2328 | 2329 | int do_tstamp, do_csum, do_vlan; |
| 2329 | 2330 | u32 bufaddr; |
| @@ -2391,52 +2392,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) · 61 unmodified lines | ||
| 2391 | 2392 | txbdp = txbdp_start = tx_queue->cur_tx; |
| 2392 | 2393 | lstatus = be32_to_cpu(txbdp->lstatus); |
| 2393 | 2394 | |
| 2394 | − /* Time stamp insertion requires one additional TxBD */ | |
| 2395 | − if (unlikely(do_tstamp)) | |
| 2396 | − txbdp_tstamp = txbdp = next_txbd(txbdp, base, | |
| 2397 | − tx_queue->tx_ring_size); | |
| 2398 | − | |
| 2399 | − if (nr_frags == 0) { | |
| 2400 | − if (unlikely(do_tstamp)) { | |
| 2401 | − u32 lstatus_ts = be32_to_cpu(txbdp_tstamp->lstatus); | |
| 2402 | − | |
| 2403 | − lstatus_ts |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); | |
| 2404 | − txbdp_tstamp->lstatus = cpu_to_be32(lstatus_ts); | |
| 2405 | − } else { | |
| 2406 | − lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); | |
| 2407 | − } | |
| 2408 | − } else { | |
| 2409 | − /* Place the fragment addresses and lengths into the TxBDs */ | |
| 2410 | − for (i = 0; i < nr_frags; i++) { | |
| 2411 | − unsigned int frag_len; | |
| 2412 | − /* Point at the next BD, wrapping as needed */ | |
| 2413 | − txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size); | |
| 2414 | − | |
| 2415 | − frag_len = skb_shinfo(skb)->frags[i].size; | |
| 2416 | − | |
| 2417 | − lstatus = be32_to_cpu(txbdp->lstatus) | frag_len | | |
| 2418 | − BD_LFLAG(TXBD_READY); | |
| 2419 | − | |
| 2420 | − /* Handle the last BD specially */ | |
| 2421 | − if (i == nr_frags - 1) | |
| 2422 | − lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); | |
| 2423 | − | |
| 2424 | − bufaddr = skb_frag_dma_map(priv->dev, | |
| 2425 | − &skb_shinfo(skb)->frags[i], | |
| 2426 | − 0, | |
| 2427 | − frag_len, | |
| 2428 | − DMA_TO_DEVICE); | |
| 2429 | − if (unlikely(dma_mapping_error(priv->dev, bufaddr))) | |
| 2430 | − goto dma_map_err; | |
| 2431 | − | |
| 2432 | − /* set the TxBD length and buffer pointer */ | |
| 2433 | − txbdp->bufPtr = cpu_to_be32(bufaddr); | |
| 2434 | − txbdp->lstatus = cpu_to_be32(lstatus); | |
| 2435 | − } | |
| 2436 | − | |
| 2437 | − lstatus = be32_to_cpu(txbdp_start->lstatus); | |
| 2438 | − } | |
| 2439 | − | |
| 2440 | 2395 | /* Add TxPAL between FCB and frame if required */ |
| 2441 | 2396 | if (unlikely(do_tstamp)) { |
| 2442 | 2397 | skb_push(skb, GMAC_TXPAL_LEN); |
| @@ -2471,12 +2426,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) · 28 unmodified lines | ||
| 2471 | 2426 | if (do_vlan) |
| 2472 | 2427 | gfar_tx_vlan(skb, fcb); |
| 2473 | 2428 | |
| 2474 | − /* Setup tx hardware time stamping if requested */ | |
| 2475 | − if (unlikely(do_tstamp)) { | |
| 2476 | − skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | |
| 2477 | − fcb->ptp = 1; | |
| 2478 | − } | |
| 2479 | − | |
| 2480 | 2429 | bufaddr = dma_map_single(priv->dev, skb->data, skb_headlen(skb), |
| 2481 | 2430 | DMA_TO_DEVICE); |
| 2482 | 2431 | if (unlikely(dma_mapping_error(priv->dev, bufaddr))) |
| @@ -2484,6 +2433,46 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) · 1 unmodified line | ||
| 2484 | 2433 | |
| 2485 | 2434 | txbdp_start->bufPtr = cpu_to_be32(bufaddr); |
| 2486 | 2435 | |
| 2436 | + /* Time stamp insertion requires one additional TxBD */ | |
| 2437 | + if (unlikely(do_tstamp)) | |
| 2438 | + txbdp_tstamp = txbdp = next_txbd(txbdp, base, | |
| 2439 | + tx_queue->tx_ring_size); | |
| 2440 | + | |
| 2441 | + if (likely(!nr_frags)) { | |
| 2442 | + lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); | |
| 2443 | + } else { | |
| 2444 | + u32 lstatus_start = lstatus; | |
| 2445 | + | |
| 2446 | + /* Place the fragment addresses and lengths into the TxBDs */ | |
| 2447 | + frag = &skb_shinfo(skb)->frags[0]; | |
| 2448 | + for (i = 0; i < nr_frags; i++, frag++) { | |
| 2449 | + unsigned int size; | |
| 2450 | + | |
| 2451 | + /* Point at the next BD, wrapping as needed */ | |
| 2452 | + txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size); | |
| 2453 | + | |
| 2454 | + size = skb_frag_size(frag); | |
| 2455 | + | |
| 2456 | + lstatus = be32_to_cpu(txbdp->lstatus) | size | | |
| 2457 | + BD_LFLAG(TXBD_READY); | |
| 2458 | + | |
| 2459 | + /* Handle the last BD specially */ | |
| 2460 | + if (i == nr_frags - 1) | |
| 2461 | + lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); | |
| 2462 | + | |
| 2463 | + bufaddr = skb_frag_dma_map(priv->dev, frag, 0, | |
| 2464 | + size, DMA_TO_DEVICE); | |
| 2465 | + if (unlikely(dma_mapping_error(priv->dev, bufaddr))) | |
| 2466 | + goto dma_map_err; | |
| 2467 | + | |
| 2468 | + /* set the TxBD length and buffer pointer */ | |
| 2469 | + txbdp->bufPtr = cpu_to_be32(bufaddr); | |
| 2470 | + txbdp->lstatus = cpu_to_be32(lstatus); | |
| 2471 | + } | |
| 2472 | + | |
| 2473 | + lstatus = lstatus_start; | |
| 2474 | + } | |
| 2475 | + | |
| 2487 | 2476 | /* If time stamping is requested one additional TxBD must be set up. The |
| 2488 | 2477 | * first TxBD points to the FCB and must have a data length of |
| 2489 | 2478 | * GMAC_FCB_LEN. The second TxBD points to the actual frame data with |
| @@ -2494,12 +2483,19 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) · 4 unmodified lines | ||
| 2494 | 2483 | |
| 2495 | 2484 | bufaddr = be32_to_cpu(txbdp_start->bufPtr); |
| 2496 | 2485 | bufaddr += fcb_len; |
| 2486 | + | |
| 2497 | 2487 | lstatus_ts |= BD_LFLAG(TXBD_READY) | |
| 2498 | 2488 | (skb_headlen(skb) - fcb_len); |
| 2489 | + if (!nr_frags) | |
| 2490 | + lstatus_ts |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); | |
| 2499 | 2491 | |
| 2500 | 2492 | txbdp_tstamp->bufPtr = cpu_to_be32(bufaddr); |
| 2501 | 2493 | txbdp_tstamp->lstatus = cpu_to_be32(lstatus_ts); |
| 2502 | 2494 | lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; |
| 2495 | + | |
| 2496 | + /* Setup tx hardware time stamping */ | |
| 2497 | + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | |
| 2498 | + fcb->ptp = 1; | |
| 2503 | 2499 | } else { |
| 2504 | 2500 | lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); |
| 2505 | 2501 | } |
| @@ -2712,7 +2708,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) · 206 unmodified lines | ||
| 2712 | 2708 | ~0x7UL); |
| 2713 | 2709 | |
| 2714 | 2710 | memset(&shhwtstamps, 0, sizeof(shhwtstamps)); |
| 2715 | − shhwtstamps.hwtstamp = ns_to_ktime(*ns); | |
| 2711 | + shhwtstamps.hwtstamp = ns_to_ktime(be64_to_cpu(*ns)); | |
| 2716 | 2712 | skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN); |
| 2717 | 2713 | skb_tstamp_tx(skb, &shhwtstamps); |
| 2718 | 2714 | gfar_clear_txbd_status(bdp); |
| @@ -3041,7 +3037,7 @@ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb) · 322 unmodified lines | ||
| 3041 | 3037 | u64 *ns = (u64 *) skb->data; |
| 3042 | 3038 | |
| 3043 | 3039 | memset(shhwtstamps, 0, sizeof(*shhwtstamps)); |
| 3044 | − shhwtstamps->hwtstamp = ns_to_ktime(*ns); | |
| 3040 | + shhwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(*ns)); | |
| 3045 | 3041 | } |
| 3046 | 3042 | |
| 3047 | 3043 | if (priv->padding) |
| @@ -422,19 +422,6 @@ static struct ptp_clock_info ptp_gianfar_caps = { · 421 unmodified lines | ||
| 422 | 422 | .enable = ptp_gianfar_enable, |
| 423 | 423 | }; |
| 424 | 424 | |
| 425 | −/* OF device tree */ | |
| 426 | − | |
| 427 | −static int get_of_u32(struct device_node *node, char *str, u32 *val) | |
| 428 | −{ | |
| 429 | − int plen; | |
| 430 | − const u32 *prop = of_get_property(node, str, &plen); | |
| 431 | − | |
| 432 | − if (!prop || plen != sizeof(*prop)) | |
| 433 | − return -1; | |
| 434 | − *val = *prop; | |
| 435 | − return 0; | |
| 436 | −} | |
| 437 | − | |
| 438 | 425 | static int gianfar_ptp_probe(struct platform_device *dev) |
| 439 | 426 | { |
| 440 | 427 | struct device_node *node = dev->dev.of_node; |
| @@ -452,15 +439,21 @@ static int gianfar_ptp_probe(struct platform_device *dev) · 11 unmodified lines | ||
| 452 | 439 | |
| 453 | 440 | etsects->caps = ptp_gianfar_caps; |
| 454 | 441 | |
| 455 | − if (get_of_u32(node, "fsl,cksel", &etsects->cksel)) | |
| 442 | + if (of_property_read_u32(node, "fsl,cksel", &etsects->cksel)) | |
| 456 | 443 | etsects->cksel = DEFAULT_CKSEL; |
| 457 | 444 | |
| 458 | − if (get_of_u32(node, "fsl,tclk-period", &etsects->tclk_period) || | |
| 459 | − get_of_u32(node, "fsl,tmr-prsc", &etsects->tmr_prsc) || | |
| 460 | − get_of_u32(node, "fsl,tmr-add", &etsects->tmr_add) || | |
| 461 | − get_of_u32(node, "fsl,tmr-fiper1", &etsects->tmr_fiper1) || | |
| 462 | − get_of_u32(node, "fsl,tmr-fiper2", &etsects->tmr_fiper2) || | |
| 463 | − get_of_u32(node, "fsl,max-adj", &etsects->caps.max_adj)) { | |
| 445 | + if (of_property_read_u32(node, | |
| 446 | + "fsl,tclk-period", &etsects->tclk_period) || | |
| 447 | + of_property_read_u32(node, | |
| 448 | + "fsl,tmr-prsc", &etsects->tmr_prsc) || | |
| 449 | + of_property_read_u32(node, | |
| 450 | + "fsl,tmr-add", &etsects->tmr_add) || | |
| 451 | + of_property_read_u32(node, | |
| 452 | + "fsl,tmr-fiper1", &etsects->tmr_fiper1) || | |
| 453 | + of_property_read_u32(node, | |
| 454 | + "fsl,tmr-fiper2", &etsects->tmr_fiper2) || | |
| 455 | + of_property_read_u32(node, | |
| 456 | + "fsl,max-adj", &etsects->caps.max_adj)) { | |
| 464 | 457 | pr_err("device tree node missing required elements\n"); |
| 465 | 458 | goto no_node; |
| 466 | 459 | } |
| @@ -92,6 +92,10 @@ struct e1000_hw; · 91 unmodified lines | ||
| 92 | 92 | #define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* SPT-H PCH */ |
| 93 | 93 | #define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* SPT-H PCH */ |
| 94 | 94 | #define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LBG PCH */ |
| 95 | +#define E1000_DEV_ID_PCH_SPT_I219_LM4 0x15D7 | |
| 96 | +#define E1000_DEV_ID_PCH_SPT_I219_V4 0x15D8 | |
| 97 | +#define E1000_DEV_ID_PCH_SPT_I219_LM5 0x15E3 | |
| 98 | +#define E1000_DEV_ID_PCH_SPT_I219_V5 0x15D6 | |
| 95 | 99 | |
| 96 | 100 | #define E1000_REVISION_4 4 |
| 97 | 101 | |
| @@ -1252,9 +1252,9 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) · 1251 unmodified lines | ||
| 1252 | 1252 | ew32(H2ME, mac_reg); |
| 1253 | 1253 | } |
| 1254 | 1254 | |
| 1255 | − /* Poll up to 100msec for ME to clear ULP_CFG_DONE */ | |
| 1255 | + /* Poll up to 300msec for ME to clear ULP_CFG_DONE. */ | |
| 1256 | 1256 | while (er32(FWSM) & E1000_FWSM_ULP_CFG_DONE) { |
| 1257 | − if (i++ == 10) { | |
| 1257 | + if (i++ == 30) { | |
| 1258 | 1258 | ret_val = -E1000_ERR_PHY; |
| 1259 | 1259 | goto out; |
| 1260 | 1260 | } |
| @@ -1328,6 +1328,8 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) · 67 unmodified lines | ||
| 1328 | 1328 | I218_ULP_CONFIG1_RESET_TO_SMBUS | |
| 1329 | 1329 | I218_ULP_CONFIG1_WOL_HOST | |
| 1330 | 1330 | I218_ULP_CONFIG1_INBAND_EXIT | |
| 1331 | + I218_ULP_CONFIG1_EN_ULP_LANPHYPC | | |
| 1332 | + I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST | | |
| 1331 | 1333 | I218_ULP_CONFIG1_DISABLE_SMB_PERST); |
| 1332 | 1334 | e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); |
| 1333 | 1335 | |
| @@ -1433,6 +1435,18 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) · 99 unmodified lines | ||
| 1433 | 1435 | emi_addr = I217_RX_CONFIG; |
| 1434 | 1436 | ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val); |
| 1435 | 1437 | |
| 1438 | + if (hw->mac.type == e1000_pch_lpt || | |
| 1439 | + hw->mac.type == e1000_pch_spt) { | |
| 1440 | + u16 phy_reg; | |
| 1441 | + | |
| 1442 | + e1e_rphy_locked(hw, I217_PLL_CLOCK_GATE_REG, &phy_reg); | |
| 1443 | + phy_reg &= ~I217_PLL_CLOCK_GATE_MASK; | |
| 1444 | + if (speed == SPEED_100 || speed == SPEED_10) | |
| 1445 | + phy_reg |= 0x3E8; | |
| 1446 | + else | |
| 1447 | + phy_reg |= 0xFA; | |
| 1448 | + e1e_wphy_locked(hw, I217_PLL_CLOCK_GATE_REG, phy_reg); | |
| 1449 | + } | |
| 1436 | 1450 | hw->phy.ops.release(hw); |
| 1437 | 1451 | |
| 1438 | 1452 | if (ret_val) |
| @@ -1467,6 +1481,18 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) · 28 unmodified lines | ||
| 1467 | 1481 | hw->phy.ops.release(hw); |
| 1468 | 1482 | if (ret_val) |
| 1469 | 1483 | return ret_val; |
| 1484 | + } else { | |
| 1485 | + ret_val = hw->phy.ops.acquire(hw); | |
| 1486 | + if (ret_val) | |
| 1487 | + return ret_val; | |
| 1488 | + | |
| 1489 | + ret_val = e1e_wphy_locked(hw, | |
| 1490 | + PHY_REG(776, 20), | |
| 1491 | + 0xC023); | |
| 1492 | + hw->phy.ops.release(hw); | |
| 1493 | + if (ret_val) | |
| 1494 | + return ret_val; | |
| 1495 | + | |
| 1470 | 1496 | } |
| 1471 | 1497 | } |
| 1472 | 1498 | } |
| @@ -188,6 +188,10 @@ · 187 unmodified lines | ||
| 188 | 188 | #define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */ |
| 189 | 189 | #define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */ |
| 190 | 190 | #define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */ |
| 191 | +/* enable ULP even if when phy powered down via lanphypc */ | |
| 192 | +#define I218_ULP_CONFIG1_EN_ULP_LANPHYPC 0x0400 | |
| 193 | +/* disable clear of sticky ULP on PERST */ | |
| 194 | +#define I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST 0x0800 | |
| 191 | 195 | #define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */ |
| 192 | 196 | |
| 193 | 197 | /* SMBus Address Phy Register */ |
| @@ -226,6 +230,9 @@ · 32 unmodified lines | ||
| 226 | 230 | #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 |
| 227 | 231 | #define HV_PM_CTRL_K1_ENABLE 0x4000 |
| 228 | 232 | |
| 233 | +#define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) | |
| 234 | +#define I217_PLL_CLOCK_GATE_MASK 0x07FF | |
| 235 | + | |
| 229 | 236 | #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ |
| 230 | 237 | |
| 231 | 238 | /* Inband Control */ |
| @@ -7452,6 +7452,10 @@ static const struct pci_device_id e1000_pci_tbl[] = { · 7451 unmodified lines | ||
| 7452 | 7452 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM2), board_pch_spt }, |
| 7453 | 7453 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V2), board_pch_spt }, |
| 7454 | 7454 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LBG_I219_LM3), board_pch_spt }, |
| 7455 | + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM4), board_pch_spt }, | |
| 7456 | + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V4), board_pch_spt }, | |
| 7457 | + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM5), board_pch_spt }, | |
| 7458 | + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V5), board_pch_spt }, | |
| 7455 | 7459 | |
| 7456 | 7460 | { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ |
| 7457 | 7461 | }; |
| @@ -1937,8 +1937,10 @@ static void fm10k_init_reta(struct fm10k_intfc *interface) · 1936 unmodified lines | ||
| 1937 | 1937 | u16 i, rss_i = interface->ring_feature[RING_F_RSS].indices; |
| 1938 | 1938 | u32 reta, base; |
| 1939 | 1939 | |
| 1940 | − /* If the netdev is initialized we have to maintain table if possible */ | |
| 1941 | − if (interface->netdev->reg_state != NETREG_UNINITIALIZED) { | |
| 1940 | + /* If the Rx flow indirection table has been configured manually, we | |
| 1941 | + * need to maintain it when possible. | |
| 1942 | + */ | |
| 1943 | + if (netif_is_rxfh_configured(interface->netdev)) { | |
| 1942 | 1944 | for (i = FM10K_RETA_SIZE; i--;) { |
| 1943 | 1945 | reta = interface->reta[i]; |
| 1944 | 1946 | if ((((reta << 24) >> 24) < rss_i) && |
| @@ -1946,6 +1948,10 @@ static void fm10k_init_reta(struct fm10k_intfc *interface) · 1 unmodified line | ||
| 1946 | 1948 | (((reta << 8) >> 24) < rss_i) && |
| 1947 | 1949 | (((reta) >> 24) < rss_i)) |
| 1948 | 1950 | continue; |
| 1951 | + | |
| 1952 | + /* this should never happen */ | |
| 1953 | + dev_err(&interface->pdev->dev, | |
| 1954 | + "RSS indirection table assigned flows out of queue bounds. Reconfiguring.\n"); | |
| 1949 | 1955 | goto repopulate_reta; |
| 1950 | 1956 | } |
| 1951 | 1957 | |
| @@ -1204,6 +1204,15 @@ err_queueing_scheme: · 1203 unmodified lines | ||
| 1204 | 1204 | return err; |
| 1205 | 1205 | } |
| 1206 | 1206 | |
| 1207 | +static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto, | |
| 1208 | + struct tc_to_netdev *tc) | |
| 1209 | +{ | |
| 1210 | + if (tc->type != TC_SETUP_MQPRIO) | |
| 1211 | + return -EINVAL; | |
| 1212 | + | |
| 1213 | + return fm10k_setup_tc(dev, tc->tc); | |
| 1214 | +} | |
| 1215 | + | |
| 1207 | 1216 | static int fm10k_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) |
| 1208 | 1217 | { |
| 1209 | 1218 | switch (cmd) { |
| @@ -1386,7 +1395,7 @@ static const struct net_device_ops fm10k_netdev_ops = { · 176 unmodified lines | ||
| 1386 | 1395 | .ndo_vlan_rx_kill_vid = fm10k_vlan_rx_kill_vid, |
| 1387 | 1396 | .ndo_set_rx_mode = fm10k_set_rx_mode, |
| 1388 | 1397 | .ndo_get_stats64 = fm10k_get_stats64, |
| 1389 | − .ndo_setup_tc = fm10k_setup_tc, | |
| 1398 | + .ndo_setup_tc = __fm10k_setup_tc, | |
| 1390 | 1399 | .ndo_set_vf_mac = fm10k_ndo_set_vf_mac, |
| 1391 | 1400 | .ndo_set_vf_vlan = fm10k_ndo_set_vf_vlan, |
| 1392 | 1401 | .ndo_set_vf_rate = fm10k_ndo_set_vf_bw, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /******************************************************************************* |
| 2 | 2 | * |
| 3 | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | − * Copyright(c) 2013 - 2015 Intel Corporation. | |
| 4 | + * Copyright(c) 2013 - 2016 Intel Corporation. | |
| 5 | 5 | * |
| 6 | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -64,9 +64,6 @@ · 56 unmodified lines | ||
| 64 | 64 | #include "i40e_dcb.h" |
| 65 | 65 | |
| 66 | 66 | /* Useful i40e defaults */ |
| 67 | −#define I40E_BASE_PF_SEID 16 | |
| 68 | −#define I40E_BASE_VSI_SEID 512 | |
| 69 | −#define I40E_BASE_VEB_SEID 288 | |
| 70 | 67 | #define I40E_MAX_VEB 16 |
| 71 | 68 | |
| 72 | 69 | #define I40E_MAX_NUM_DESCRIPTORS 4096 |
| @@ -104,6 +101,7 @@ · 31 unmodified lines | ||
| 104 | 101 | #define I40E_PRIV_FLAGS_FD_ATR BIT(2) |
| 105 | 102 | #define I40E_PRIV_FLAGS_VEB_STATS BIT(3) |
| 106 | 103 | #define I40E_PRIV_FLAGS_PS BIT(4) |
| 104 | +#define I40E_PRIV_FLAGS_HW_ATR_EVICT BIT(5) | |
| 107 | 105 | |
| 108 | 106 | #define I40E_NVM_VERSION_LO_SHIFT 0 |
| 109 | 107 | #define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) |
| @@ -113,6 +111,7 @@ · 3 unmodified lines | ||
| 113 | 111 | #define I40E_OEM_VER_PATCH_MASK 0xff |
| 114 | 112 | #define I40E_OEM_VER_BUILD_SHIFT 8 |
| 115 | 113 | #define I40E_OEM_VER_SHIFT 24 |
| 114 | +#define I40E_PHY_DEBUG_PORT BIT(4) | |
| 116 | 115 | |
| 117 | 116 | /* The values in here are decimal coded as hex as is the case in the NVM map*/ |
| 118 | 117 | #define I40E_CURRENT_NVM_VERSION_HI 0x2 |
| @@ -137,6 +136,19 @@ · 18 unmodified lines | ||
| 137 | 136 | /* default to trying for four seconds */ |
| 138 | 137 | #define I40E_TRY_LINK_TIMEOUT (4 * HZ) |
| 139 | 138 | |
| 139 | +/** | |
| 140 | + * i40e_is_mac_710 - Return true if MAC is X710/XL710 | |
| 141 | + * @hw: ptr to the hardware info | |
| 142 | + **/ | |
| 143 | +static inline bool i40e_is_mac_710(struct i40e_hw *hw) | |
| 144 | +{ | |
| 145 | + if ((hw->mac.type == I40E_MAC_X710) || | |
| 146 | + (hw->mac.type == I40E_MAC_XL710)) | |
| 147 | + return true; | |
| 148 | + | |
| 149 | + return false; | |
| 150 | +} | |
| 151 | + | |
| 140 | 152 | /* driver state flags */ |
| 141 | 153 | enum i40e_state_t { |
| 142 | 154 | __I40E_TESTING, |
| @@ -339,6 +351,12 @@ struct i40e_pf { · 196 unmodified lines | ||
| 339 | 351 | #define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(40) |
| 340 | 352 | #define I40E_FLAG_GENEVE_OFFLOAD_CAPABLE BIT_ULL(41) |
| 341 | 353 | #define I40E_FLAG_NO_PCI_LINK_CHECK BIT_ULL(42) |
| 354 | +#define I40E_FLAG_100M_SGMII_CAPABLE BIT_ULL(43) | |
| 355 | +#define I40E_FLAG_RESTART_AUTONEG BIT_ULL(44) | |
| 356 | +#define I40E_FLAG_NO_DCB_SUPPORT BIT_ULL(45) | |
| 357 | +#define I40E_FLAG_USE_SET_LLDP_MIB BIT_ULL(46) | |
| 358 | +#define I40E_FLAG_STOP_FW_LLDP BIT_ULL(47) | |
| 359 | +#define I40E_FLAG_HAVE_10GBASET_PHY BIT_ULL(48) | |
| 342 | 360 | #define I40E_FLAG_PF_MAC BIT_ULL(50) |
| 343 | 361 | |
| 344 | 362 | /* tracks features that get auto disabled by errors */ |
| @@ -391,6 +409,7 @@ struct i40e_pf { · 46 unmodified lines | ||
| 391 | 409 | struct i40e_vf *vf; |
| 392 | 410 | int num_alloc_vfs; /* actual number of VFs allocated */ |
| 393 | 411 | u32 vf_aq_requests; |
| 412 | + u32 arq_overflows; /* Not fatal, possibly indicative of problems */ | |
| 394 | 413 | |
| 395 | 414 | /* DCBx/DCBNL capability for PF that indicates |
| 396 | 415 | * whether DCBx is managed by firmware or host |
| @@ -423,6 +442,7 @@ struct i40e_pf { · 26 unmodified lines | ||
| 423 | 442 | |
| 424 | 443 | u32 ioremap_len; |
| 425 | 444 | u32 fd_inv; |
| 445 | + u16 phy_led_val; | |
| 426 | 446 | }; |
| 427 | 447 | |
| 428 | 448 | struct i40e_mac_filter { |
| @@ -492,6 +512,7 @@ struct i40e_vsi { · 63 unmodified lines | ||
| 492 | 512 | u32 tx_busy; |
| 493 | 513 | u64 tx_linearize; |
| 494 | 514 | u64 tx_force_wb; |
| 515 | + u64 tx_lost_interrupt; | |
| 495 | 516 | u32 rx_buf_failed; |
| 496 | 517 | u32 rx_page_failed; |
| 497 | 518 | |
| @@ -500,13 +521,6 @@ struct i40e_vsi { · 2 unmodified lines | ||
| 500 | 521 | struct i40e_ring **tx_rings; |
| 501 | 522 | |
| 502 | 523 | u16 work_limit; |
| 503 | − /* high bit set means dynamic, use accessor routines to read/write. | |
| 504 | − * hardware only supports 2us resolution for the ITR registers. | |
| 505 | − * these values always store the USER setting, and must be converted | |
| 506 | − * before programming to a register. | |
| 507 | − */ | |
| 508 | − u16 rx_itr_setting; | |
| 509 | − u16 tx_itr_setting; | |
| 510 | 524 | u16 int_rate_limit; /* value in usecs */ |
| 511 | 525 | |
| 512 | 526 | u16 rss_table_size; /* HW RSS table size */ |
| @@ -747,6 +761,9 @@ static inline void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) · 234 unmodified lines | ||
| 747 | 761 | struct i40e_hw *hw = &pf->hw; |
| 748 | 762 | u32 val; |
| 749 | 763 | |
| 764 | + /* definitely clear the PBA here, as this function is meant to | |
| 765 | + * clean out all previous interrupts AND enable the interrupt | |
| 766 | + */ | |
| 750 | 767 | val = I40E_PFINT_DYN_CTLN_INTENA_MASK | |
| 751 | 768 | I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | |
| 752 | 769 | (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT); |
| @@ -754,9 +771,8 @@ static inline void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) · 1 unmodified line | ||
| 754 | 771 | /* skip the flush */ |
| 755 | 772 | } |
| 756 | 773 | |
| 757 | −void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector); | |
| 758 | 774 | void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf); |
| 759 | −void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf); | |
| 775 | +void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf, bool clearpba); | |
| 760 | 776 | #ifdef I40E_FCOE |
| 761 | 777 | struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( |
| 762 | 778 | struct net_device *netdev, |
| @@ -786,7 +802,8 @@ struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr, · 23 unmodified lines | ||
| 786 | 802 | bool is_vf, bool is_netdev); |
| 787 | 803 | #ifdef I40E_FCOE |
| 788 | 804 | int i40e_close(struct net_device *netdev); |
| 789 | −int i40e_setup_tc(struct net_device *netdev, u8 tc); | |
| 805 | +int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto, | |
| 806 | + struct tc_to_netdev *tc); | |
| 790 | 807 | void i40e_netpoll(struct net_device *netdev); |
| 791 | 808 | int i40e_fcoe_enable(struct net_device *netdev); |
| 792 | 809 | int i40e_fcoe_disable(struct net_device *netdev); |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /******************************************************************************* |
| 2 | 2 | * |
| 3 | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | − * Copyright(c) 2013 - 2014 Intel Corporation. | |
| 4 | + * Copyright(c) 2013 - 2016 Intel Corporation. | |
| 5 | 5 | * |
| 6 | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -953,6 +953,9 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, · 945 unmodified lines | ||
| 953 | 953 | u16 flags; |
| 954 | 954 | u16 ntu; |
| 955 | 955 | |
| 956 | + /* pre-clean the event info */ | |
| 957 | + memset(&e->desc, 0, sizeof(e->desc)); | |
| 958 | + | |
| 956 | 959 | /* take the lock before we start messing with the ring */ |
| 957 | 960 | mutex_lock(&hw->aq.arq_mutex); |
| 958 | 961 | |
| @@ -1020,14 +1023,6 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, · 61 unmodified lines | ||
| 1020 | 1023 | hw->aq.arq.next_to_clean = ntc; |
| 1021 | 1024 | hw->aq.arq.next_to_use = ntu; |
| 1022 | 1025 | |
| 1023 | −clean_arq_element_out: | |
| 1024 | − /* Set pending if needed, unlock and return */ | |
| 1025 | − if (pending != NULL) | |
| 1026 | − *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc); | |
| 1027 | − | |
| 1028 | −clean_arq_element_err: | |
| 1029 | − mutex_unlock(&hw->aq.arq_mutex); | |
| 1030 | − | |
| 1031 | 1026 | if (i40e_is_nvm_update_op(&e->desc)) { |
| 1032 | 1027 | if (hw->aq.nvm_release_on_done) { |
| 1033 | 1028 | i40e_release_nvm(hw); |
| @@ -1048,6 +1043,13 @@ clean_arq_element_err: · 14 unmodified lines | ||
| 1048 | 1043 | } |
| 1049 | 1044 | } |
| 1050 | 1045 | |
| 1046 | +clean_arq_element_out: | |
| 1047 | + /* Set pending if needed, unlock and return */ | |
| 1048 | + if (pending) | |
| 1049 | + *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc); | |
| 1050 | +clean_arq_element_err: | |
| 1051 | + mutex_unlock(&hw->aq.arq_mutex); | |
| 1052 | + | |
| 1051 | 1053 | return ret_code; |
| 1052 | 1054 | } |
| 1053 | 1055 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /******************************************************************************* |
| 2 | 2 | * |
| 3 | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | − * Copyright(c) 2013 - 2014 Intel Corporation. | |
| 4 | + * Copyright(c) 2013 - 2016 Intel Corporation. | |
| 5 | 5 | * |
| 6 | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -34,7 +34,7 @@ · 26 unmodified lines | ||
| 34 | 34 | */ |
| 35 | 35 | |
| 36 | 36 | #define I40E_FW_API_VERSION_MAJOR 0x0001 |
| 37 | −#define I40E_FW_API_VERSION_MINOR 0x0004 | |
| 37 | +#define I40E_FW_API_VERSION_MINOR 0x0005 | |
| 38 | 38 | |
| 39 | 39 | struct i40e_aq_desc { |
| 40 | 40 | __le16 flags; |
| @@ -145,6 +145,9 @@ enum i40e_admin_queue_opc { · 104 unmodified lines | ||
| 145 | 145 | i40e_aqc_opc_remove_statistics = 0x0202, |
| 146 | 146 | i40e_aqc_opc_set_port_parameters = 0x0203, |
| 147 | 147 | i40e_aqc_opc_get_switch_resource_alloc = 0x0204, |
| 148 | + i40e_aqc_opc_set_switch_config = 0x0205, | |
| 149 | + i40e_aqc_opc_rx_ctl_reg_read = 0x0206, | |
| 150 | + i40e_aqc_opc_rx_ctl_reg_write = 0x0207, | |
| 148 | 151 | |
| 149 | 152 | i40e_aqc_opc_add_vsi = 0x0210, |
| 150 | 153 | i40e_aqc_opc_update_vsi_parameters = 0x0211, |
| @@ -220,6 +223,7 @@ enum i40e_admin_queue_opc { · 69 unmodified lines | ||
| 220 | 223 | i40e_aqc_opc_get_phy_wol_caps = 0x0621, |
| 221 | 224 | i40e_aqc_opc_set_phy_debug = 0x0622, |
| 222 | 225 | i40e_aqc_opc_upload_ext_phy_fm = 0x0625, |
| 226 | + i40e_aqc_opc_run_phy_activity = 0x0626, | |
| 223 | 227 | |
| 224 | 228 | /* NVM commands */ |
| 225 | 229 | i40e_aqc_opc_nvm_read = 0x0701, |
| @@ -228,6 +232,7 @@ enum i40e_admin_queue_opc { · 2 unmodified lines | ||
| 228 | 232 | i40e_aqc_opc_nvm_config_read = 0x0704, |
| 229 | 233 | i40e_aqc_opc_nvm_config_write = 0x0705, |
| 230 | 234 | i40e_aqc_opc_oem_post_update = 0x0720, |
| 235 | + i40e_aqc_opc_thermal_sensor = 0x0721, | |
| 231 | 236 | |
| 232 | 237 | /* virtualization commands */ |
| 233 | 238 | i40e_aqc_opc_send_msg_to_pf = 0x0801, |
| @@ -402,6 +407,7 @@ struct i40e_aqc_list_capabilities_element_resp { · 168 unmodified lines | ||
| 402 | 407 | #define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 |
| 403 | 408 | #define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 |
| 404 | 409 | #define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 |
| 410 | +#define I40E_AQ_CAP_ID_WOL_AND_PROXY 0x0008 | |
| 405 | 411 | #define I40E_AQ_CAP_ID_SRIOV 0x0012 |
| 406 | 412 | #define I40E_AQ_CAP_ID_VF 0x0013 |
| 407 | 413 | #define I40E_AQ_CAP_ID_VMDQ 0x0014 |
| @@ -422,6 +428,7 @@ struct i40e_aqc_list_capabilities_element_resp { · 14 unmodified lines | ||
| 422 | 428 | #define I40E_AQ_CAP_ID_LED 0x0061 |
| 423 | 429 | #define I40E_AQ_CAP_ID_SDP 0x0062 |
| 424 | 430 | #define I40E_AQ_CAP_ID_MDIO 0x0063 |
| 431 | +#define I40E_AQ_CAP_ID_WSR_PROT 0x0064 | |
| 425 | 432 | #define I40E_AQ_CAP_ID_FLEX10 0x00F1 |
| 426 | 433 | #define I40E_AQ_CAP_ID_CEM 0x00F2 |
| 427 | 434 | |
| @@ -680,6 +687,31 @@ struct i40e_aqc_switch_resource_alloc_element_resp { · 252 unmodified lines | ||
| 680 | 687 | |
| 681 | 688 | I40E_CHECK_STRUCT_LEN(0x10, i40e_aqc_switch_resource_alloc_element_resp); |
| 682 | 689 | |
| 690 | +/* Set Switch Configuration (direct 0x0205) */ | |
| 691 | +struct i40e_aqc_set_switch_config { | |
| 692 | + __le16 flags; | |
| 693 | +#define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001 | |
| 694 | +#define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002 | |
| 695 | + __le16 valid_flags; | |
| 696 | + u8 reserved[12]; | |
| 697 | +}; | |
| 698 | + | |
| 699 | +I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config); | |
| 700 | + | |
| 701 | +/* Read Receive control registers (direct 0x0206) | |
| 702 | + * Write Receive control registers (direct 0x0207) | |
| 703 | + * used for accessing Rx control registers that can be | |
| 704 | + * slow and need special handling when under high Rx load | |
| 705 | + */ | |
| 706 | +struct i40e_aqc_rx_ctl_reg_read_write { | |
| 707 | + __le32 reserved1; | |
| 708 | + __le32 address; | |
| 709 | + __le32 reserved2; | |
| 710 | + __le32 value; | |
| 711 | +}; | |
| 712 | + | |
| 713 | +I40E_CHECK_CMD_LENGTH(i40e_aqc_rx_ctl_reg_read_write); | |
| 714 | + | |
| 683 | 715 | /* Add VSI (indirect 0x0210) |
| 684 | 716 | * this indirect command uses struct i40e_aqc_vsi_properties_data |
| 685 | 717 | * as the indirect buffer (128 bytes) |
| @@ -906,7 +938,8 @@ struct i40e_aqc_add_veb { · 220 unmodified lines | ||
| 906 | 938 | I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT) |
| 907 | 939 | #define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2 |
| 908 | 940 | #define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4 |
| 909 | −#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 | |
| 941 | +#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 /* deprecated */ | |
| 942 | +#define I40E_AQC_ADD_VEB_ENABLE_DISABLE_STATS 0x10 | |
| 910 | 943 | u8 enable_tcs; |
| 911 | 944 | u8 reserved[9]; |
| 912 | 945 | }; |
| @@ -973,6 +1006,7 @@ struct i40e_aqc_add_macvlan_element_data { · 60 unmodified lines | ||
| 973 | 1006 | #define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002 |
| 974 | 1007 | #define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004 |
| 975 | 1008 | #define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008 |
| 1009 | +#define I40E_AQC_MACVLAN_ADD_USE_SHARED_MAC 0x0010 | |
| 976 | 1010 | __le16 queue_number; |
| 977 | 1011 | #define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0 |
| 978 | 1012 | #define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \ |
| @@ -1069,6 +1103,7 @@ struct i40e_aqc_set_vsi_promiscuous_modes { · 90 unmodified lines | ||
| 1069 | 1103 | #define I40E_AQC_SET_VSI_PROMISC_BROADCAST 0x04 |
| 1070 | 1104 | #define I40E_AQC_SET_VSI_DEFAULT 0x08 |
| 1071 | 1105 | #define I40E_AQC_SET_VSI_PROMISC_VLAN 0x10 |
| 1106 | +#define I40E_AQC_SET_VSI_PROMISC_TX 0x8000 | |
| 1072 | 1107 | __le16 seid; |
| 1073 | 1108 | #define I40E_AQC_VSI_PROM_CMD_SEID_MASK 0x3FF |
| 1074 | 1109 | __le16 vlan_tag; |
| @@ -1257,10 +1292,16 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { · 182 unmodified lines | ||
| 1257 | 1292 | |
| 1258 | 1293 | #define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 |
| 1259 | 1294 | #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 |
| 1260 | −#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 | |
| 1295 | +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN 0 | |
| 1261 | 1296 | #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 |
| 1262 | −#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 | |
| 1297 | +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE 2 | |
| 1263 | 1298 | #define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 |
| 1299 | +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_RESERVED 4 | |
| 1300 | +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN_GPE 5 | |
| 1301 | + | |
| 1302 | +#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_OUTER_MAC 0x2000 | |
| 1303 | +#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_INNER_MAC 0x4000 | |
| 1304 | +#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_OUTER_IP 0x8000 | |
| 1264 | 1305 | |
| 1265 | 1306 | __le32 tenant_id; |
| 1266 | 1307 | u8 reserved[4]; |
| @@ -1755,7 +1796,12 @@ struct i40e_aqc_get_link_status { · 488 unmodified lines | ||
| 1755 | 1796 | u8 config; |
| 1756 | 1797 | #define I40E_AQ_CONFIG_CRC_ENA 0x04 |
| 1757 | 1798 | #define I40E_AQ_CONFIG_PACING_MASK 0x78 |
| 1758 | − u8 reserved[5]; | |
| 1799 | + u8 external_power_ability; | |
| 1800 | +#define I40E_AQ_LINK_POWER_CLASS_1 0x00 | |
| 1801 | +#define I40E_AQ_LINK_POWER_CLASS_2 0x01 | |
| 1802 | +#define I40E_AQ_LINK_POWER_CLASS_3 0x02 | |
| 1803 | +#define I40E_AQ_LINK_POWER_CLASS_4 0x03 | |
| 1804 | + u8 reserved[4]; | |
| 1759 | 1805 | }; |
| 1760 | 1806 | |
| 1761 | 1807 | I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); |
| @@ -1823,6 +1869,18 @@ enum i40e_aq_phy_reg_type { · 61 unmodified lines | ||
| 1823 | 1869 | I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 |
| 1824 | 1870 | }; |
| 1825 | 1871 | |
| 1872 | +/* Run PHY Activity (0x0626) */ | |
| 1873 | +struct i40e_aqc_run_phy_activity { | |
| 1874 | + __le16 activity_id; | |
| 1875 | + u8 flags; | |
| 1876 | + u8 reserved1; | |
| 1877 | + __le32 control; | |
| 1878 | + __le32 data; | |
| 1879 | + u8 reserved2[4]; | |
| 1880 | +}; | |
| 1881 | + | |
| 1882 | +I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity); | |
| 1883 | + | |
| 1826 | 1884 | /* NVM Read command (indirect 0x0701) |
| 1827 | 1885 | * NVM Erase commands (direct 0x0702) |
| 1828 | 1886 | * NVM Update commands (indirect 0x0703) |
| @@ -1912,6 +1970,22 @@ struct i40e_aqc_nvm_oem_post_update_buffer { · 83 unmodified lines | ||
| 1912 | 1970 | |
| 1913 | 1971 | I40E_CHECK_STRUCT_LEN(0x28, i40e_aqc_nvm_oem_post_update_buffer); |
| 1914 | 1972 | |
| 1973 | +/* Thermal Sensor (indirect 0x0721) | |
| 1974 | + * read or set thermal sensor configs and values | |
| 1975 | + * takes a sensor and command specific data buffer, not detailed here | |
| 1976 | + */ | |
| 1977 | +struct i40e_aqc_thermal_sensor { | |
| 1978 | + u8 sensor_action; | |
| 1979 | +#define I40E_AQ_THERMAL_SENSOR_READ_CONFIG 0 | |
| 1980 | +#define I40E_AQ_THERMAL_SENSOR_SET_CONFIG 1 | |
| 1981 | +#define I40E_AQ_THERMAL_SENSOR_READ_TEMP 2 | |
| 1982 | + u8 reserved[7]; | |
| 1983 | + __le32 addr_high; | |
| 1984 | + __le32 addr_low; | |
| 1985 | +}; | |
| 1986 | + | |
| 1987 | +I40E_CHECK_CMD_LENGTH(i40e_aqc_thermal_sensor); | |
| 1988 | + | |
| 1915 | 1989 | /* Send to PF command (indirect 0x0801) id is only used by PF |
| 1916 | 1990 | * Send to VF command (indirect 0x0802) id is only used by PF |
| 1917 | 1991 | * Send to Peer PF command (indirect 0x0803) |
| @@ -2191,6 +2265,7 @@ struct i40e_aqc_add_udp_tunnel { · 273 unmodified lines | ||
| 2191 | 2265 | #define I40E_AQC_TUNNEL_TYPE_VXLAN 0x00 |
| 2192 | 2266 | #define I40E_AQC_TUNNEL_TYPE_NGE 0x01 |
| 2193 | 2267 | #define I40E_AQC_TUNNEL_TYPE_TEREDO 0x10 |
| 2268 | +#define I40E_AQC_TUNNEL_TYPE_VXLAN_GPE 0x11 | |
| 2194 | 2269 | u8 reserved1[10]; |
| 2195 | 2270 | }; |
| 2196 | 2271 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /******************************************************************************* |
| 2 | 2 | * |
| 3 | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | − * Copyright(c) 2013 - 2015 Intel Corporation. | |
| 4 | + * Copyright(c) 2013 - 2016 Intel Corporation. | |
| 5 | 5 | * |
| 6 | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -55,19 +55,13 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) · 47 unmodified lines | ||
| 55 | 55 | case I40E_DEV_ID_20G_KR2_A: |
| 56 | 56 | hw->mac.type = I40E_MAC_XL710; |
| 57 | 57 | break; |
| 58 | + case I40E_DEV_ID_KX_X722: | |
| 59 | + case I40E_DEV_ID_QSFP_X722: | |
| 58 | 60 | case I40E_DEV_ID_SFP_X722: |
| 59 | 61 | case I40E_DEV_ID_1G_BASE_T_X722: |
| 60 | 62 | case I40E_DEV_ID_10G_BASE_T_X722: |
| 61 | 63 | hw->mac.type = I40E_MAC_X722; |
| 62 | 64 | break; |
| 63 | − case I40E_DEV_ID_X722_VF: | |
| 64 | − case I40E_DEV_ID_X722_VF_HV: | |
| 65 | − hw->mac.type = I40E_MAC_X722_VF; | |
| 66 | − break; | |
| 67 | − case I40E_DEV_ID_VF: | |
| 68 | − case I40E_DEV_ID_VF_HV: | |
| 69 | − hw->mac.type = I40E_MAC_VF; | |
| 70 | − break; | |
| 71 | 65 | default: |
| 72 | 66 | hw->mac.type = I40E_MAC_GENERIC; |
| 73 | 67 | break; |
| @@ -1245,7 +1239,13 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw) · 1171 unmodified lines | ||
| 1245 | 1239 | grst_del = (rd32(hw, I40E_GLGEN_RSTCTL) & |
| 1246 | 1240 | I40E_GLGEN_RSTCTL_GRSTDEL_MASK) >> |
| 1247 | 1241 | I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT; |
| 1248 | − for (cnt = 0; cnt < grst_del + 10; cnt++) { | |
| 1242 | + | |
| 1243 | + /* It can take upto 15 secs for GRST steady state. | |
| 1244 | + * Bump it to 16 secs max to be safe. | |
| 1245 | + */ | |
| 1246 | + grst_del = grst_del * 20; | |
| 1247 | + | |
| 1248 | + for (cnt = 0; cnt < grst_del; cnt++) { | |
| 1249 | 1249 | reg = rd32(hw, I40E_GLGEN_RSTAT); |
| 1250 | 1250 | if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK)) |
| 1251 | 1251 | break; |
| @@ -1893,6 +1893,32 @@ i40e_status i40e_aq_set_phy_int_mask(struct i40e_hw *hw, · 641 unmodified lines | ||
| 1893 | 1893 | return status; |
| 1894 | 1894 | } |
| 1895 | 1895 | |
| 1896 | +/** | |
| 1897 | + * i40e_aq_set_phy_debug | |
| 1898 | + * @hw: pointer to the hw struct | |
| 1899 | + * @cmd_flags: debug command flags | |
| 1900 | + * @cmd_details: pointer to command details structure or NULL | |
| 1901 | + * | |
| 1902 | + * Reset the external PHY. | |
| 1903 | + **/ | |
| 1904 | +enum i40e_status_code i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags, | |
| 1905 | + struct i40e_asq_cmd_details *cmd_details) | |
| 1906 | +{ | |
| 1907 | + struct i40e_aq_desc desc; | |
| 1908 | + struct i40e_aqc_set_phy_debug *cmd = | |
| 1909 | + (struct i40e_aqc_set_phy_debug *)&desc.params.raw; | |
| 1910 | + enum i40e_status_code status; | |
| 1911 | + | |
| 1912 | + i40e_fill_default_direct_cmd_desc(&desc, | |
| 1913 | + i40e_aqc_opc_set_phy_debug); | |
| 1914 | + | |
| 1915 | + cmd->command_flags = cmd_flags; | |
| 1916 | + | |
| 1917 | + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); | |
| 1918 | + | |
| 1919 | + return status; | |
| 1920 | +} | |
| 1921 | + | |
| 1896 | 1922 | /** |
| 1897 | 1923 | * i40e_aq_add_vsi |
| 1898 | 1924 | * @hw: pointer to the hw struct |
| @@ -1958,12 +1984,19 @@ i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, · 59 unmodified lines | ||
| 1958 | 1984 | i40e_fill_default_direct_cmd_desc(&desc, |
| 1959 | 1985 | i40e_aqc_opc_set_vsi_promiscuous_modes); |
| 1960 | 1986 | |
| 1961 | − if (set) | |
| 1987 | + if (set) { | |
| 1962 | 1988 | flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST; |
| 1989 | + if (((hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver >= 5)) || | |
| 1990 | + (hw->aq.api_maj_ver > 1)) | |
| 1991 | + flags |= I40E_AQC_SET_VSI_PROMISC_TX; | |
| 1992 | + } | |
| 1963 | 1993 | |
| 1964 | 1994 | cmd->promiscuous_flags = cpu_to_le16(flags); |
| 1965 | 1995 | |
| 1966 | 1996 | cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_UNICAST); |
| 1997 | + if (((hw->aq.api_maj_ver >= 1) && (hw->aq.api_min_ver >= 5)) || | |
| 1998 | + (hw->aq.api_maj_ver > 1)) | |
| 1999 | + cmd->valid_flags |= cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_TX); | |
| 1967 | 2000 | |
| 1968 | 2001 | cmd->seid = cpu_to_le16(seid); |
| 1969 | 2002 | status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); |
| @@ -2038,6 +2071,37 @@ i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw, · 68 unmodified lines | ||
| 2038 | 2071 | return status; |
| 2039 | 2072 | } |
| 2040 | 2073 | |
| 2074 | +/** | |
| 2075 | + * i40e_aq_set_vsi_vlan_promisc - control the VLAN promiscuous setting | |
| 2076 | + * @hw: pointer to the hw struct | |
| 2077 | + * @seid: vsi number | |
| 2078 | + * @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN | |
| 2079 | + * @cmd_details: pointer to command details structure or NULL | |
| 2080 | + **/ | |
| 2081 | +i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw, | |
| 2082 | + u16 seid, bool enable, | |
| 2083 | + struct i40e_asq_cmd_details *cmd_details) | |
| 2084 | +{ | |
| 2085 | + struct i40e_aq_desc desc; | |
| 2086 | + struct i40e_aqc_set_vsi_promiscuous_modes *cmd = | |
| 2087 | + (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw; | |
| 2088 | + i40e_status status; | |
| 2089 | + u16 flags = 0; | |
| 2090 | + | |
| 2091 | + i40e_fill_default_direct_cmd_desc(&desc, | |
| 2092 | + i40e_aqc_opc_set_vsi_promiscuous_modes); | |
| 2093 | + if (enable) | |
| 2094 | + flags |= I40E_AQC_SET_VSI_PROMISC_VLAN; | |
| 2095 | + | |
| 2096 | + cmd->promiscuous_flags = cpu_to_le16(flags); | |
| 2097 | + cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_VLAN); | |
| 2098 | + cmd->seid = cpu_to_le16(seid); | |
| 2099 | + | |
| 2100 | + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); | |
| 2101 | + | |
| 2102 | + return status; | |
| 2103 | +} | |
| 2104 | + | |
| 2041 | 2105 | /** |
| 2042 | 2106 | * i40e_get_vsi_params - get VSI configuration info |
| 2043 | 2107 | * @hw: pointer to the hw struct |
| @@ -2283,8 +2347,8 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw) · 239 unmodified lines | ||
| 2283 | 2347 | * @downlink_seid: the VSI SEID |
| 2284 | 2348 | * @enabled_tc: bitmap of TCs to be enabled |
| 2285 | 2349 | * @default_port: true for default port VSI, false for control port |
| 2286 | − * @enable_l2_filtering: true to add L2 filter table rules to regular forwarding rules for cloud support | |
| 2287 | 2350 | * @veb_seid: pointer to where to put the resulting VEB SEID |
| 2351 | + * @enable_stats: true to turn on VEB stats | |
| 2288 | 2352 | * @cmd_details: pointer to command details structure or NULL |
| 2289 | 2353 | * |
| 2290 | 2354 | * This asks the FW to add a VEB between the uplink and downlink |
| @@ -2292,8 +2356,8 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw) · 1 unmodified line | ||
| 2292 | 2356 | **/ |
| 2293 | 2357 | i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, |
| 2294 | 2358 | u16 downlink_seid, u8 enabled_tc, |
| 2295 | − bool default_port, bool enable_l2_filtering, | |
| 2296 | − u16 *veb_seid, | |
| 2359 | + bool default_port, u16 *veb_seid, | |
| 2360 | + bool enable_stats, | |
| 2297 | 2361 | struct i40e_asq_cmd_details *cmd_details) |
| 2298 | 2362 | { |
| 2299 | 2363 | struct i40e_aq_desc desc; |
| @@ -2320,8 +2384,9 @@ i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, · 20 unmodified lines | ||
| 2320 | 2384 | else |
| 2321 | 2385 | veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DATA; |
| 2322 | 2386 | |
| 2323 | − if (enable_l2_filtering) | |
| 2324 | − veb_flags |= I40E_AQC_ADD_VEB_ENABLE_L2_FILTER; | |
| 2387 | + /* reverse logic here: set the bitflag to disable the stats */ | |
| 2388 | + if (!enable_stats) | |
| 2389 | + veb_flags |= I40E_AQC_ADD_VEB_ENABLE_DISABLE_STATS; | |
| 2325 | 2390 | |
| 2326 | 2391 | cmd->veb_flags = cpu_to_le16(veb_flags); |
| 2327 | 2392 | |
| @@ -2410,6 +2475,7 @@ i40e_status i40e_aq_add_macvlan(struct i40e_hw *hw, u16 seid, · 82 unmodified lines | ||
| 2410 | 2475 | (struct i40e_aqc_macvlan *)&desc.params.raw; |
| 2411 | 2476 | i40e_status status; |
| 2412 | 2477 | u16 buf_size; |
| 2478 | + int i; | |
| 2413 | 2479 | |
| 2414 | 2480 | if (count == 0 || !mv_list || !hw) |
| 2415 | 2481 | return I40E_ERR_PARAM; |
| @@ -2423,12 +2489,17 @@ i40e_status i40e_aq_add_macvlan(struct i40e_hw *hw, u16 seid, · 7 unmodified lines | ||
| 2423 | 2489 | cmd->seid[1] = 0; |
| 2424 | 2490 | cmd->seid[2] = 0; |
| 2425 | 2491 | |
| 2492 | + for (i = 0; i < count; i++) | |
| 2493 | + if (is_multicast_ether_addr(mv_list[i].mac_addr)) | |
| 2494 | + mv_list[i].flags |= | |
| 2495 | + cpu_to_le16(I40E_AQC_MACVLAN_ADD_USE_SHARED_MAC); | |
| 2496 | + | |
| 2426 | 2497 | desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); |
| 2427 | 2498 | if (buf_size > I40E_AQ_LARGE_BUF) |
| 2428 | 2499 | desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB); |
| 2429 | 2500 | |
| 2430 | 2501 | status = i40e_asq_send_command(hw, &desc, mv_list, buf_size, |
| 2431 | − cmd_details); | |
| 2502 | + cmd_details); | |
| 2432 | 2503 | |
| 2433 | 2504 | return status; |
| 2434 | 2505 | } |
| @@ -2475,6 +2546,137 @@ i40e_status i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 seid, · 40 unmodified lines | ||
| 2475 | 2546 | return status; |
| 2476 | 2547 | } |
| 2477 | 2548 | |
| 2549 | +/** | |
| 2550 | + * i40e_mirrorrule_op - Internal helper function to add/delete mirror rule | |
| 2551 | + * @hw: pointer to the hw struct | |
| 2552 | + * @opcode: AQ opcode for add or delete mirror rule | |
| 2553 | + * @sw_seid: Switch SEID (to which rule refers) | |
| 2554 | + * @rule_type: Rule Type (ingress/egress/VLAN) | |
| 2555 | + * @id: Destination VSI SEID or Rule ID | |
| 2556 | + * @count: length of the list | |
| 2557 | + * @mr_list: list of mirrored VSI SEIDs or VLAN IDs | |
| 2558 | + * @cmd_details: pointer to command details structure or NULL | |
| 2559 | + * @rule_id: Rule ID returned from FW | |
| 2560 | + * @rule_used: Number of rules used in internal switch | |
| 2561 | + * @rule_free: Number of rules free in internal switch | |
| 2562 | + * | |
| 2563 | + * Add/Delete a mirror rule to a specific switch. Mirror rules are supported for | |
| 2564 | + * VEBs/VEPA elements only | |
| 2565 | + **/ | |
| 2566 | +static i40e_status i40e_mirrorrule_op(struct i40e_hw *hw, | |
| 2567 | + u16 opcode, u16 sw_seid, u16 rule_type, u16 id, | |
| 2568 | + u16 count, __le16 *mr_list, | |
| 2569 | + struct i40e_asq_cmd_details *cmd_details, | |
| 2570 | + u16 *rule_id, u16 *rules_used, u16 *rules_free) | |
| 2571 | +{ | |
| 2572 | + struct i40e_aq_desc desc; | |
| 2573 | + struct i40e_aqc_add_delete_mirror_rule *cmd = | |
| 2574 | + (struct i40e_aqc_add_delete_mirror_rule *)&desc.params.raw; | |
| 2575 | + struct i40e_aqc_add_delete_mirror_rule_completion *resp = | |
| 2576 | + (struct i40e_aqc_add_delete_mirror_rule_completion *)&desc.params.raw; | |
| 2577 | + i40e_status status; | |
| 2578 | + u16 buf_size; | |
| 2579 | + | |
| 2580 | + buf_size = count * sizeof(*mr_list); | |
| 2581 | + | |
| 2582 | + /* prep the rest of the request */ | |
| 2583 | + i40e_fill_default_direct_cmd_desc(&desc, opcode); | |
| 2584 | + cmd->seid = cpu_to_le16(sw_seid); | |
| 2585 | + cmd->rule_type = cpu_to_le16(rule_type & | |
| 2586 | + I40E_AQC_MIRROR_RULE_TYPE_MASK); | |
| 2587 | + cmd->num_entries = cpu_to_le16(count); | |
| 2588 | + /* Dest VSI for add, rule_id for delete */ | |
| 2589 | + cmd->destination = cpu_to_le16(id); | |
| 2590 | + if (mr_list) { | |
| 2591 | + desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | | |
| 2592 | + I40E_AQ_FLAG_RD)); | |
| 2593 | + if (buf_size > I40E_AQ_LARGE_BUF) | |
| 2594 | + desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB); | |
| 2595 | + } | |
| 2596 | + | |
| 2597 | + status = i40e_asq_send_command(hw, &desc, mr_list, buf_size, | |
| 2598 | + cmd_details); | |
| 2599 | + if (!status || | |
| 2600 | + hw->aq.asq_last_status == I40E_AQ_RC_ENOSPC) { | |
| 2601 | + if (rule_id) | |
| 2602 | + *rule_id = le16_to_cpu(resp->rule_id); | |
| 2603 | + if (rules_used) | |
| 2604 | + *rules_used = le16_to_cpu(resp->mirror_rules_used); | |
| 2605 | + if (rules_free) | |
| 2606 | + *rules_free = le16_to_cpu(resp->mirror_rules_free); | |
| 2607 | + } | |
| 2608 | + return status; | |
| 2609 | +} | |
| 2610 | + | |
| 2611 | +/** | |
| 2612 | + * i40e_aq_add_mirrorrule - add a mirror rule | |
| 2613 | + * @hw: pointer to the hw struct | |
| 2614 | + * @sw_seid: Switch SEID (to which rule refers) | |
| 2615 | + * @rule_type: Rule Type (ingress/egress/VLAN) | |
| 2616 | + * @dest_vsi: SEID of VSI to which packets will be mirrored | |
| 2617 | + * @count: length of the list | |
| 2618 | + * @mr_list: list of mirrored VSI SEIDs or VLAN IDs | |
| 2619 | + * @cmd_details: pointer to command details structure or NULL | |
| 2620 | + * @rule_id: Rule ID returned from FW | |
| 2621 | + * @rule_used: Number of rules used in internal switch | |
| 2622 | + * @rule_free: Number of rules free in internal switch | |
| 2623 | + * | |
| 2624 | + * Add mirror rule. Mirror rules are supported for VEBs or VEPA elements only | |
| 2625 | + **/ | |
| 2626 | +i40e_status i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid, | |
| 2627 | + u16 rule_type, u16 dest_vsi, u16 count, __le16 *mr_list, | |
| 2628 | + struct i40e_asq_cmd_details *cmd_details, | |
| 2629 | + u16 *rule_id, u16 *rules_used, u16 *rules_free) | |
| 2630 | +{ | |
| 2631 | + if (!(rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS || | |
| 2632 | + rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS)) { | |
| 2633 | + if (count == 0 || !mr_list) | |
| 2634 | + return I40E_ERR_PARAM; | |
| 2635 | + } | |
| 2636 | + | |
| 2637 | + return i40e_mirrorrule_op(hw, i40e_aqc_opc_add_mirror_rule, sw_seid, | |
| 2638 | + rule_type, dest_vsi, count, mr_list, | |
| 2639 | + cmd_details, rule_id, rules_used, rules_free); | |
| 2640 | +} | |
| 2641 | + | |
| 2642 | +/** | |
| 2643 | + * i40e_aq_delete_mirrorrule - delete a mirror rule | |
| 2644 | + * @hw: pointer to the hw struct | |
| 2645 | + * @sw_seid: Switch SEID (to which rule refers) | |
| 2646 | + * @rule_type: Rule Type (ingress/egress/VLAN) | |
| 2647 | + * @count: length of the list | |
| 2648 | + * @rule_id: Rule ID that is returned in the receive desc as part of | |
| 2649 | + * add_mirrorrule. | |
| 2650 | + * @mr_list: list of mirrored VLAN IDs to be removed | |
| 2651 | + * @cmd_details: pointer to command details structure or NULL | |
| 2652 | + * @rule_used: Number of rules used in internal switch | |
| 2653 | + * @rule_free: Number of rules free in internal switch | |
| 2654 | + * | |
| 2655 | + * Delete a mirror rule. Mirror rules are supported for VEBs/VEPA elements only | |
| 2656 | + **/ | |
| 2657 | +i40e_status i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid, | |
| 2658 | + u16 rule_type, u16 rule_id, u16 count, __le16 *mr_list, | |
| 2659 | + struct i40e_asq_cmd_details *cmd_details, | |
| 2660 | + u16 *rules_used, u16 *rules_free) | |
| 2661 | +{ | |
| 2662 | + /* Rule ID has to be valid except rule_type: INGRESS VLAN mirroring */ | |
| 2663 | + if (rule_type != I40E_AQC_MIRROR_RULE_TYPE_VLAN) { | |
| 2664 | + if (!rule_id) | |
| 2665 | + return I40E_ERR_PARAM; | |
| 2666 | + } else { | |
| 2667 | + /* count and mr_list shall be valid for rule_type INGRESS VLAN | |
| 2668 | + * mirroring. For other rule_type, count and rule_type should | |
| 2669 | + * not matter. | |
| 2670 | + */ | |
| 2671 | + if (count == 0 || !mr_list) | |
| 2672 | + return I40E_ERR_PARAM; | |
| 2673 | + } | |
| 2674 | + | |
| 2675 | + return i40e_mirrorrule_op(hw, i40e_aqc_opc_delete_mirror_rule, sw_seid, | |
| 2676 | + rule_type, rule_id, count, mr_list, | |
| 2677 | + cmd_details, NULL, rules_used, rules_free); | |
| 2678 | +} | |
| 2679 | + | |
| 2478 | 2680 | /** |
| 2479 | 2681 | * i40e_aq_send_msg_to_vf |
| 2480 | 2682 | * @hw: pointer to the hardware structure |
| @@ -2765,35 +2967,6 @@ i40e_aq_erase_nvm_exit: · 284 unmodified lines | ||
| 2765 | 2967 | return status; |
| 2766 | 2968 | } |
| 2767 | 2969 | |
| 2768 | −#define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01 | |
| 2769 | −#define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02 | |
| 2770 | −#define I40E_DEV_FUNC_CAP_NPAR 0x03 | |
| 2771 | −#define I40E_DEV_FUNC_CAP_OS2BMC 0x04 | |
| 2772 | −#define I40E_DEV_FUNC_CAP_VALID_FUNC 0x05 | |
| 2773 | −#define I40E_DEV_FUNC_CAP_SRIOV_1_1 0x12 | |
| 2774 | −#define I40E_DEV_FUNC_CAP_VF 0x13 | |
| 2775 | −#define I40E_DEV_FUNC_CAP_VMDQ 0x14 | |
| 2776 | −#define I40E_DEV_FUNC_CAP_802_1_QBG 0x15 | |
| 2777 | −#define I40E_DEV_FUNC_CAP_802_1_QBH 0x16 | |
| 2778 | −#define I40E_DEV_FUNC_CAP_VSI 0x17 | |
| 2779 | −#define I40E_DEV_FUNC_CAP_DCB 0x18 | |
| 2780 | −#define I40E_DEV_FUNC_CAP_FCOE 0x21 | |
| 2781 | −#define I40E_DEV_FUNC_CAP_ISCSI 0x22 | |
| 2782 | −#define I40E_DEV_FUNC_CAP_RSS 0x40 | |
| 2783 | −#define I40E_DEV_FUNC_CAP_RX_QUEUES 0x41 | |
| 2784 | −#define I40E_DEV_FUNC_CAP_TX_QUEUES 0x42 | |
| 2785 | −#define I40E_DEV_FUNC_CAP_MSIX 0x43 | |
| 2786 | −#define I40E_DEV_FUNC_CAP_MSIX_VF 0x44 | |
| 2787 | −#define I40E_DEV_FUNC_CAP_FLOW_DIRECTOR 0x45 | |
| 2788 | −#define I40E_DEV_FUNC_CAP_IEEE_1588 0x46 | |
| 2789 | −#define I40E_DEV_FUNC_CAP_FLEX10 0xF1 | |
| 2790 | −#define I40E_DEV_FUNC_CAP_CEM 0xF2 | |
| 2791 | −#define I40E_DEV_FUNC_CAP_IWARP 0x51 | |
| 2792 | −#define I40E_DEV_FUNC_CAP_LED 0x61 | |
| 2793 | −#define I40E_DEV_FUNC_CAP_SDP 0x62 | |
| 2794 | −#define I40E_DEV_FUNC_CAP_MDIO 0x63 | |
| 2795 | −#define I40E_DEV_FUNC_CAP_WR_CSR_PROT 0x64 | |
| 2796 | − | |
| 2797 | 2970 | /** |
| 2798 | 2971 | * i40e_parse_discover_capabilities |
| 2799 | 2972 | * @hw: pointer to the hw struct |
| @@ -2832,79 +3005,79 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, · 32 unmodified lines | ||
| 2832 | 3005 | major_rev = cap->major_rev; |
| 2833 | 3006 | |
| 2834 | 3007 | switch (id) { |
| 2835 | − case I40E_DEV_FUNC_CAP_SWITCH_MODE: | |
| 3008 | + case I40E_AQ_CAP_ID_SWITCH_MODE: | |
| 2836 | 3009 | p->switch_mode = number; |
| 2837 | 3010 | break; |
| 2838 | − case I40E_DEV_FUNC_CAP_MGMT_MODE: | |
| 3011 | + case I40E_AQ_CAP_ID_MNG_MODE: | |
| 2839 | 3012 | p->management_mode = number; |
| 2840 | 3013 | break; |
| 2841 | − case I40E_DEV_FUNC_CAP_NPAR: | |
| 3014 | + case I40E_AQ_CAP_ID_NPAR_ACTIVE: | |
| 2842 | 3015 | p->npar_enable = number; |
| 2843 | 3016 | break; |
| 2844 | − case I40E_DEV_FUNC_CAP_OS2BMC: | |
| 3017 | + case I40E_AQ_CAP_ID_OS2BMC_CAP: | |
| 2845 | 3018 | p->os2bmc = number; |
| 2846 | 3019 | break; |
| 2847 | − case I40E_DEV_FUNC_CAP_VALID_FUNC: | |
| 3020 | + case I40E_AQ_CAP_ID_FUNCTIONS_VALID: | |
| 2848 | 3021 | p->valid_functions = number; |
| 2849 | 3022 | break; |
| 2850 | − case I40E_DEV_FUNC_CAP_SRIOV_1_1: | |
| 3023 | + case I40E_AQ_CAP_ID_SRIOV: | |
| 2851 | 3024 | if (number == 1) |
| 2852 | 3025 | p->sr_iov_1_1 = true; |
| 2853 | 3026 | break; |
| 2854 | − case I40E_DEV_FUNC_CAP_VF: | |
| 3027 | + case I40E_AQ_CAP_ID_VF: | |
| 2855 | 3028 | p->num_vfs = number; |
| 2856 | 3029 | p->vf_base_id = logical_id; |
| 2857 | 3030 | break; |
| 2858 | − case I40E_DEV_FUNC_CAP_VMDQ: | |
| 3031 | + case I40E_AQ_CAP_ID_VMDQ: | |
| 2859 | 3032 | if (number == 1) |
| 2860 | 3033 | p->vmdq = true; |
| 2861 | 3034 | break; |
| 2862 | − case I40E_DEV_FUNC_CAP_802_1_QBG: | |
| 3035 | + case I40E_AQ_CAP_ID_8021QBG: | |
| 2863 | 3036 | if (number == 1) |
| 2864 | 3037 | p->evb_802_1_qbg = true; |
| 2865 | 3038 | break; |
| 2866 | − case I40E_DEV_FUNC_CAP_802_1_QBH: | |
| 3039 | + case I40E_AQ_CAP_ID_8021QBR: | |
| 2867 | 3040 | if (number == 1) |
| 2868 | 3041 | p->evb_802_1_qbh = true; |
| 2869 | 3042 | break; |
| 2870 | − case I40E_DEV_FUNC_CAP_VSI: | |
| 3043 | + case I40E_AQ_CAP_ID_VSI: | |
| 2871 | 3044 | p->num_vsis = number; |
| 2872 | 3045 | break; |
| 2873 | − case I40E_DEV_FUNC_CAP_DCB: | |
| 3046 | + case I40E_AQ_CAP_ID_DCB: | |
| 2874 | 3047 | if (number == 1) { |
| 2875 | 3048 | p->dcb = true; |
| 2876 | 3049 | p->enabled_tcmap = logical_id; |
| 2877 | 3050 | p->maxtc = phys_id; |
| 2878 | 3051 | } |
| 2879 | 3052 | break; |
| 2880 | − case I40E_DEV_FUNC_CAP_FCOE: | |
| 3053 | + case I40E_AQ_CAP_ID_FCOE: | |
| 2881 | 3054 | if (number == 1) |
| 2882 | 3055 | p->fcoe = true; |
| 2883 | 3056 | break; |
| 2884 | − case I40E_DEV_FUNC_CAP_ISCSI: | |
| 3057 | + case I40E_AQ_CAP_ID_ISCSI: | |
| 2885 | 3058 | if (number == 1) |
| 2886 | 3059 | p->iscsi = true; |
| 2887 | 3060 | break; |
| 2888 | − case I40E_DEV_FUNC_CAP_RSS: | |
| 3061 | + case I40E_AQ_CAP_ID_RSS: | |
| 2889 | 3062 | p->rss = true; |
| 2890 | 3063 | p->rss_table_size = number; |
| 2891 | 3064 | p->rss_table_entry_width = logical_id; |
| 2892 | 3065 | break; |
| 2893 | − case I40E_DEV_FUNC_CAP_RX_QUEUES: | |
| 3066 | + case I40E_AQ_CAP_ID_RXQ: | |
| 2894 | 3067 | p->num_rx_qp = number; |
| 2895 | 3068 | p->base_queue = phys_id; |
| 2896 | 3069 | break; |
| 2897 | − case I40E_DEV_FUNC_CAP_TX_QUEUES: | |
| 3070 | + case I40E_AQ_CAP_ID_TXQ: | |
| 2898 | 3071 | p->num_tx_qp = number; |
| 2899 | 3072 | p->base_queue = phys_id; |
| 2900 | 3073 | break; |
| 2901 | − case I40E_DEV_FUNC_CAP_MSIX: | |
| 3074 | + case I40E_AQ_CAP_ID_MSIX: | |
| 2902 | 3075 | p->num_msix_vectors = number; |
| 2903 | 3076 | break; |
| 2904 | − case I40E_DEV_FUNC_CAP_MSIX_VF: | |
| 3077 | + case I40E_AQ_CAP_ID_VF_MSIX: | |
| 2905 | 3078 | p->num_msix_vectors_vf = number; |
| 2906 | 3079 | break; |
| 2907 | − case I40E_DEV_FUNC_CAP_FLEX10: | |
| 3080 | + case I40E_AQ_CAP_ID_FLEX10: | |
| 2908 | 3081 | if (major_rev == 1) { |
| 2909 | 3082 | if (number == 1) { |
| 2910 | 3083 | p->flex10_enable = true; |
| @@ -2920,38 +3093,38 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, · 9 unmodified lines | ||
| 2920 | 3093 | p->flex10_mode = logical_id; |
| 2921 | 3094 | p->flex10_status = phys_id; |
| 2922 | 3095 | break; |
| 2923 | − case I40E_DEV_FUNC_CAP_CEM: | |
| 3096 | + case I40E_AQ_CAP_ID_CEM: | |
| 2924 | 3097 | if (number == 1) |
| 2925 | 3098 | p->mgmt_cem = true; |
| 2926 | 3099 | break; |
| 2927 | − case I40E_DEV_FUNC_CAP_IWARP: | |
| 3100 | + case I40E_AQ_CAP_ID_IWARP: | |
| 2928 | 3101 | if (number == 1) |
| 2929 | 3102 | p->iwarp = true; |
| 2930 | 3103 | break; |
| 2931 | − case I40E_DEV_FUNC_CAP_LED: | |
| 3104 | + case I40E_AQ_CAP_ID_LED: | |
| 2932 | 3105 | if (phys_id < I40E_HW_CAP_MAX_GPIO) |
| 2933 | 3106 | p->led[phys_id] = true; |
| 2934 | 3107 | break; |
| 2935 | − case I40E_DEV_FUNC_CAP_SDP: | |
| 3108 | + case I40E_AQ_CAP_ID_SDP: | |
| 2936 | 3109 | if (phys_id < I40E_HW_CAP_MAX_GPIO) |
| 2937 | 3110 | p->sdp[phys_id] = true; |
| 2938 | 3111 | break; |
| 2939 | − case I40E_DEV_FUNC_CAP_MDIO: | |
| 3112 | + case I40E_AQ_CAP_ID_MDIO: | |
| 2940 | 3113 | if (number == 1) { |
| 2941 | 3114 | p->mdio_port_num = phys_id; |
| 2942 | 3115 | p->mdio_port_mode = logical_id; |
| 2943 | 3116 | } |
| 2944 | 3117 | break; |
| 2945 | − case I40E_DEV_FUNC_CAP_IEEE_1588: | |
| 3118 | + case I40E_AQ_CAP_ID_1588: | |
| 2946 | 3119 | if (number == 1) |
| 2947 | 3120 | p->ieee_1588 = true; |
| 2948 | 3121 | break; |
| 2949 | − case I40E_DEV_FUNC_CAP_FLOW_DIRECTOR: | |
| 3122 | + case I40E_AQ_CAP_ID_FLOW_DIRECTOR: | |
| 2950 | 3123 | p->fd = true; |
| 2951 | 3124 | p->fd_filters_guaranteed = number; |
| 2952 | 3125 | p->fd_filters_best_effort = logical_id; |
| 2953 | 3126 | break; |
| 2954 | − case I40E_DEV_FUNC_CAP_WR_CSR_PROT: | |
| 3127 | + case I40E_AQ_CAP_ID_WSR_PROT: | |
| 2955 | 3128 | p->wr_csr_prot = (u64)number; |
| 2956 | 3129 | p->wr_csr_prot |= (u64)logical_id << 32; |
| 2957 | 3130 | break; |
| @@ -3709,7 +3882,7 @@ i40e_status i40e_set_filter_control(struct i40e_hw *hw, · 751 unmodified lines | ||
| 3709 | 3882 | return ret; |
| 3710 | 3883 | |
| 3711 | 3884 | /* Read the PF Queue Filter control register */ |
| 3712 | − val = rd32(hw, I40E_PFQF_CTL_0); | |
| 3885 | + val = i40e_read_rx_ctl(hw, I40E_PFQF_CTL_0); | |
| 3713 | 3886 | |
| 3714 | 3887 | /* Program required PE hash buckets for the PF */ |
| 3715 | 3888 | val &= ~I40E_PFQF_CTL_0_PEHSIZE_MASK; |
| @@ -3746,7 +3919,7 @@ i40e_status i40e_set_filter_control(struct i40e_hw *hw, · 30 unmodified lines | ||
| 3746 | 3919 | if (settings->enable_macvlan) |
| 3747 | 3920 | val |= I40E_PFQF_CTL_0_MACVLAN_ENA_MASK; |
| 3748 | 3921 | |
| 3749 | − wr32(hw, I40E_PFQF_CTL_0, val); | |
| 3922 | + i40e_write_rx_ctl(hw, I40E_PFQF_CTL_0, val); | |
| 3750 | 3923 | |
| 3751 | 3924 | return 0; |
| 3752 | 3925 | } |
| @@ -4073,3 +4246,454 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw, · 320 unmodified lines | ||
| 4073 | 4246 | |
| 4074 | 4247 | return status; |
| 4075 | 4248 | } |
| 4249 | + | |
| 4250 | +/** | |
| 4251 | + * i40e_read_phy_register | |
| 4252 | + * @hw: pointer to the HW structure | |
| 4253 | + * @page: registers page number | |
| 4254 | + * @reg: register address in the page | |
| 4255 | + * @phy_adr: PHY address on MDIO interface | |
| 4256 | + * @value: PHY register value | |
| 4257 | + * | |
| 4258 | + * Reads specified PHY register value | |
| 4259 | + **/ | |
| 4260 | +i40e_status i40e_read_phy_register(struct i40e_hw *hw, | |
| 4261 | + u8 page, u16 reg, u8 phy_addr, | |
| 4262 | + u16 *value) | |
| 4263 | +{ | |
| 4264 | + i40e_status status = I40E_ERR_TIMEOUT; | |
| 4265 | + u32 command = 0; | |
| 4266 | + u16 retry = 1000; | |
| 4267 | + u8 port_num = hw->func_caps.mdio_port_num; | |
| 4268 | + | |
| 4269 | + command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) | | |
| 4270 | + (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | | |
| 4271 | + (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | | |
| 4272 | + (I40E_MDIO_OPCODE_ADDRESS) | | |
| 4273 | + (I40E_MDIO_STCODE) | | |
| 4274 | + (I40E_GLGEN_MSCA_MDICMD_MASK) | | |
| 4275 | + (I40E_GLGEN_MSCA_MDIINPROGEN_MASK); | |
| 4276 | + wr32(hw, I40E_GLGEN_MSCA(port_num), command); | |
| 4277 | + do { | |
| 4278 | + command = rd32(hw, I40E_GLGEN_MSCA(port_num)); | |
| 4279 | + if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) { | |
| 4280 | + status = 0; | |
| 4281 | + break; | |
| 4282 | + } | |
| 4283 | + usleep_range(10, 20); | |
| 4284 | + retry--; | |
| 4285 | + } while (retry); | |
| 4286 | + | |
| 4287 | + if (status) { | |
| 4288 | + i40e_debug(hw, I40E_DEBUG_PHY, | |
| 4289 | + "PHY: Can't write command to external PHY.\n"); | |
| 4290 | + goto phy_read_end; | |
| 4291 | + } | |
| 4292 | + | |
| 4293 | + command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | | |
| 4294 | + (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | | |
| 4295 | + (I40E_MDIO_OPCODE_READ) | | |
| 4296 | + (I40E_MDIO_STCODE) | | |
| 4297 | + (I40E_GLGEN_MSCA_MDICMD_MASK) | | |
| 4298 | + (I40E_GLGEN_MSCA_MDIINPROGEN_MASK); | |
| 4299 | + status = I40E_ERR_TIMEOUT; | |
| 4300 | + retry = 1000; | |
| 4301 | + wr32(hw, I40E_GLGEN_MSCA(port_num), command); | |
| 4302 | + do { | |
| 4303 | + command = rd32(hw, I40E_GLGEN_MSCA(port_num)); | |
| 4304 | + if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) { | |
| 4305 | + status = 0; | |
| 4306 | + break; | |
| 4307 | + } | |
| 4308 | + usleep_range(10, 20); | |
| 4309 | + retry--; | |
| 4310 | + } while (retry); | |
| 4311 | + | |
| 4312 | + if (!status) { | |
| 4313 | + command = rd32(hw, I40E_GLGEN_MSRWD(port_num)); | |
| 4314 | + *value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >> | |
| 4315 | + I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT; | |
| 4316 | + } else { | |
| 4317 | + i40e_debug(hw, I40E_DEBUG_PHY, | |
| 4318 | + "PHY: Can't read register value from external PHY.\n"); | |
| 4319 | + } | |
| 4320 | + | |
| 4321 | +phy_read_end: | |
| 4322 | + return status; | |
| 4323 | +} | |
| 4324 | + | |
| 4325 | +/** | |
| 4326 | + * i40e_write_phy_register | |
| 4327 | + * @hw: pointer to the HW structure | |
| 4328 | + * @page: registers page number | |
| 4329 | + * @reg: register address in the page | |
| 4330 | + * @phy_adr: PHY address on MDIO interface | |
| 4331 | + * @value: PHY register value | |
| 4332 | + * | |
| 4333 | + * Writes value to specified PHY register | |
| 4334 | + **/ | |
| 4335 | +i40e_status i40e_write_phy_register(struct i40e_hw *hw, | |
| 4336 | + u8 page, u16 reg, u8 phy_addr, | |
| 4337 | + u16 value) | |
| 4338 | +{ | |
| 4339 | + i40e_status status = I40E_ERR_TIMEOUT; | |
| 4340 | + u32 command = 0; | |
| 4341 | + u16 retry = 1000; | |
| 4342 | + u8 port_num = hw->func_caps.mdio_port_num; | |
| 4343 | + | |
| 4344 | + command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) | | |
| 4345 | + (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | | |
| 4346 | + (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | | |
| 4347 | + (I40E_MDIO_OPCODE_ADDRESS) | | |
| 4348 | + (I40E_MDIO_STCODE) | | |
| 4349 | + (I40E_GLGEN_MSCA_MDICMD_MASK) | | |
| 4350 | + (I40E_GLGEN_MSCA_MDIINPROGEN_MASK); | |
| 4351 | + wr32(hw, I40E_GLGEN_MSCA(port_num), command); | |
| 4352 | + do { | |
| 4353 | + command = rd32(hw, I40E_GLGEN_MSCA(port_num)); | |
| 4354 | + if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) { | |
| 4355 | + status = 0; | |
| 4356 | + break; | |
| 4357 | + } | |
| 4358 | + usleep_range(10, 20); | |
| 4359 | + retry--; | |
| 4360 | + } while (retry); | |
| 4361 | + if (status) { | |
| 4362 | + i40e_debug(hw, I40E_DEBUG_PHY, | |
| 4363 | + "PHY: Can't write command to external PHY.\n"); | |
| 4364 | + goto phy_write_end; | |
| 4365 | + } | |
| 4366 | + | |
| 4367 | + command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT; | |
| 4368 | + wr32(hw, I40E_GLGEN_MSRWD(port_num), command); | |
| 4369 | + | |
| 4370 | + command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | | |
| 4371 | + (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | | |
| 4372 | + (I40E_MDIO_OPCODE_WRITE) | | |
| 4373 | + (I40E_MDIO_STCODE) | | |
| 4374 | + (I40E_GLGEN_MSCA_MDICMD_MASK) | | |
| 4375 | + (I40E_GLGEN_MSCA_MDIINPROGEN_MASK); | |
| 4376 | + status = I40E_ERR_TIMEOUT; | |
| 4377 | + retry = 1000; | |
| 4378 | + wr32(hw, I40E_GLGEN_MSCA(port_num), command); | |
| 4379 | + do { | |
| 4380 | + command = rd32(hw, I40E_GLGEN_MSCA(port_num)); | |
| 4381 | + if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) { | |
| 4382 | + status = 0; | |
| 4383 | + break; | |
| 4384 | + } | |
| 4385 | + usleep_range(10, 20); | |
| 4386 | + retry--; | |
| 4387 | + } while (retry); | |
| 4388 | + | |
| 4389 | +phy_write_end: | |
| 4390 | + return status; | |
| 4391 | +} | |
| 4392 | + | |
| 4393 | +/** | |
| 4394 | + * i40e_get_phy_address | |
| 4395 | + * @hw: pointer to the HW structure | |
| 4396 | + * @dev_num: PHY port num that address we want | |
| 4397 | + * @phy_addr: Returned PHY address | |
| 4398 | + * | |
| 4399 | + * Gets PHY address for current port | |
| 4400 | + **/ | |
| 4401 | +u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num) | |
| 4402 | +{ | |
| 4403 | + u8 port_num = hw->func_caps.mdio_port_num; | |
| 4404 | + u32 reg_val = rd32(hw, I40E_GLGEN_MDIO_I2C_SEL(port_num)); | |
| 4405 | + | |
| 4406 | + return (u8)(reg_val >> ((dev_num + 1) * 5)) & 0x1f; | |
| 4407 | +} | |
| 4408 | + | |
| 4409 | +/** | |
| 4410 | + * i40e_blink_phy_led | |
| 4411 | + * @hw: pointer to the HW structure | |
| 4412 | + * @time: time how long led will blinks in secs | |
| 4413 | + * @interval: gap between LED on and off in msecs | |
| 4414 | + * | |
| 4415 | + * Blinks PHY link LED | |
| 4416 | + **/ | |
| 4417 | +i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, | |
| 4418 | + u32 time, u32 interval) | |
| 4419 | +{ | |
| 4420 | + i40e_status status = 0; | |
| 4421 | + u32 i; | |
| 4422 | + u16 led_ctl; | |
| 4423 | + u16 gpio_led_port; | |
| 4424 | + u16 led_reg; | |
| 4425 | + u16 led_addr = I40E_PHY_LED_PROV_REG_1; | |
| 4426 | + u8 phy_addr = 0; | |
| 4427 | + u8 port_num; | |
| 4428 | + | |
| 4429 | + i = rd32(hw, I40E_PFGEN_PORTNUM); | |
| 4430 | + port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK); | |
| 4431 | + phy_addr = i40e_get_phy_address(hw, port_num); | |
| 4432 | + | |
| 4433 | + for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++, | |
| 4434 | + led_addr++) { | |
| 4435 | + status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, | |
| 4436 | + led_addr, phy_addr, &led_reg); | |
| 4437 | + if (status) | |
| 4438 | + goto phy_blinking_end; | |
| 4439 | + led_ctl = led_reg; | |
| 4440 | + if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) { | |
| 4441 | + led_reg = 0; | |
| 4442 | + status = i40e_write_phy_register(hw, | |
| 4443 | + I40E_PHY_COM_REG_PAGE, | |
| 4444 | + led_addr, phy_addr, | |
| 4445 | + led_reg); | |
| 4446 | + if (status) | |
| 4447 | + goto phy_blinking_end; | |
| 4448 | + break; | |
| 4449 | + } | |
| 4450 | + } | |
| 4451 | + | |
| 4452 | + if (time > 0 && interval > 0) { | |
| 4453 | + for (i = 0; i < time * 1000; i += interval) { | |
| 4454 | + status = i40e_read_phy_register(hw, | |
| 4455 | + I40E_PHY_COM_REG_PAGE, | |
| 4456 | + led_addr, phy_addr, | |
| 4457 | + &led_reg); | |
| 4458 | + if (status) | |
| 4459 | + goto restore_config; | |
| 4460 | + if (led_reg & I40E_PHY_LED_MANUAL_ON) | |
| 4461 | + led_reg = 0; | |
| 4462 | + else | |
| 4463 | + led_reg = I40E_PHY_LED_MANUAL_ON; | |
| 4464 | + status = i40e_write_phy_register(hw, | |
| 4465 | + I40E_PHY_COM_REG_PAGE, | |
| 4466 | + led_addr, phy_addr, | |
| 4467 | + led_reg); | |
| 4468 | + if (status) | |
| 4469 | + goto restore_config; | |
| 4470 | + msleep(interval); | |
| 4471 | + } | |
| 4472 | + } | |
| 4473 | + | |
| 4474 | +restore_config: | |
| 4475 | + status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, | |
| 4476 | + phy_addr, led_ctl); | |
| 4477 | + | |
| 4478 | +phy_blinking_end: | |
| 4479 | + return status; | |
| 4480 | +} | |
| 4481 | + | |
| 4482 | +/** | |
| 4483 | + * i40e_led_get_phy - return current on/off mode | |
| 4484 | + * @hw: pointer to the hw struct | |
| 4485 | + * @led_addr: address of led register to use | |
| 4486 | + * @val: original value of register to use | |
| 4487 | + * | |
| 4488 | + **/ | |
| 4489 | +i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr, | |
| 4490 | + u16 *val) | |
| 4491 | +{ | |
| 4492 | + i40e_status status = 0; | |
| 4493 | + u16 gpio_led_port; | |
| 4494 | + u8 phy_addr = 0; | |
| 4495 | + u16 reg_val; | |
| 4496 | + u16 temp_addr; | |
| 4497 | + u8 port_num; | |
| 4498 | + u32 i; | |
| 4499 | + | |
| 4500 | + temp_addr = I40E_PHY_LED_PROV_REG_1; | |
| 4501 | + i = rd32(hw, I40E_PFGEN_PORTNUM); | |
| 4502 | + port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK); | |
| 4503 | + phy_addr = i40e_get_phy_address(hw, port_num); | |
| 4504 | + | |
| 4505 | + for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++, | |
| 4506 | + temp_addr++) { | |
| 4507 | + status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, | |
| 4508 | + temp_addr, phy_addr, ®_val); | |
| 4509 | + if (status) | |
| 4510 | + return status; | |
| 4511 | + *val = reg_val; | |
| 4512 | + if (reg_val & I40E_PHY_LED_LINK_MODE_MASK) { | |
| 4513 | + *led_addr = temp_addr; | |
| 4514 | + break; | |
| 4515 | + } | |
| 4516 | + } | |
| 4517 | + return status; | |
| 4518 | +} | |
| 4519 | + | |
| 4520 | +/** | |
| 4521 | + * i40e_led_set_phy | |
| 4522 | + * @hw: pointer to the HW structure | |
| 4523 | + * @on: true or false | |
| 4524 | + * @mode: original val plus bit for set or ignore | |
| 4525 | + * Set led's on or off when controlled by the PHY | |
| 4526 | + * | |
| 4527 | + **/ | |
| 4528 | +i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on, | |
| 4529 | + u16 led_addr, u32 mode) | |
| 4530 | +{ | |
| 4531 | + i40e_status status = 0; | |
| 4532 | + u16 led_ctl = 0; | |
| 4533 | + u16 led_reg = 0; | |
| 4534 | + u8 phy_addr = 0; | |
| 4535 | + u8 port_num; | |
| 4536 | + u32 i; | |
| 4537 | + | |
| 4538 | + i = rd32(hw, I40E_PFGEN_PORTNUM); | |
| 4539 | + port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK); | |
| 4540 | + phy_addr = i40e_get_phy_address(hw, port_num); | |
| 4541 | + | |
| 4542 | + status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, | |
| 4543 | + phy_addr, &led_reg); | |
| 4544 | + if (status) | |
| 4545 | + return status; | |
| 4546 | + led_ctl = led_reg; | |
| 4547 | + if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) { | |
| 4548 | + led_reg = 0; | |
| 4549 | + status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, | |
| 4550 | + led_addr, phy_addr, led_reg); | |
| 4551 | + if (status) | |
| 4552 | + return status; | |
| 4553 | + } | |
| 4554 | + status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, | |
| 4555 | + led_addr, phy_addr, &led_reg); | |
| 4556 | + if (status) | |
| 4557 | + goto restore_config; | |
| 4558 | + if (on) | |
| 4559 | + led_reg = I40E_PHY_LED_MANUAL_ON; | |
| 4560 | + else | |
| 4561 | + led_reg = 0; | |
| 4562 | + status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, | |
| 4563 | + led_addr, phy_addr, led_reg); | |
| 4564 | + if (status) | |
| 4565 | + goto restore_config; | |
| 4566 | + if (mode & I40E_PHY_LED_MODE_ORIG) { | |
| 4567 | + led_ctl = (mode & I40E_PHY_LED_MODE_MASK); | |
| 4568 | + status = i40e_write_phy_register(hw, | |
| 4569 | + I40E_PHY_COM_REG_PAGE, | |
| 4570 | + led_addr, phy_addr, led_ctl); | |
| 4571 | + } | |
| 4572 | + return status; | |
| 4573 | +restore_config: | |
| 4574 | + status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, | |
| 4575 | + phy_addr, led_ctl); | |
| 4576 | + return status; | |
| 4577 | +} | |
| 4578 | + | |
| 4579 | +/** | |
| 4580 | + * i40e_aq_rx_ctl_read_register - use FW to read from an Rx control register | |
| 4581 | + * @hw: pointer to the hw struct | |
| 4582 | + * @reg_addr: register address | |
| 4583 | + * @reg_val: ptr to register value | |
| 4584 | + * @cmd_details: pointer to command details structure or NULL | |
| 4585 | + * | |
| 4586 | + * Use the firmware to read the Rx control register, | |
| 4587 | + * especially useful if the Rx unit is under heavy pressure | |
| 4588 | + **/ | |
| 4589 | +i40e_status i40e_aq_rx_ctl_read_register(struct i40e_hw *hw, | |
| 4590 | + u32 reg_addr, u32 *reg_val, | |
| 4591 | + struct i40e_asq_cmd_details *cmd_details) | |
| 4592 | +{ | |
| 4593 | + struct i40e_aq_desc desc; | |
| 4594 | + struct i40e_aqc_rx_ctl_reg_read_write *cmd_resp = | |
| 4595 | + (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw; | |
| 4596 | + i40e_status status; | |
| 4597 | + | |
| 4598 | + if (!reg_val) | |
| 4599 | + return I40E_ERR_PARAM; | |
| 4600 | + | |
| 4601 | + i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_rx_ctl_reg_read); | |
| 4602 | + | |
| 4603 | + cmd_resp->address = cpu_to_le32(reg_addr); | |
| 4604 | + | |
| 4605 | + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); | |
| 4606 | + | |
| 4607 | + if (status == 0) | |
| 4608 | + *reg_val = le32_to_cpu(cmd_resp->value); | |
| 4609 | + | |
| 4610 | + return status; | |
| 4611 | +} | |
| 4612 | + | |
| 4613 | +/** | |
| 4614 | + * i40e_read_rx_ctl - read from an Rx control register | |
| 4615 | + * @hw: pointer to the hw struct | |
| 4616 | + * @reg_addr: register address | |
| 4617 | + **/ | |
| 4618 | +u32 i40e_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr) | |
| 4619 | +{ | |
| 4620 | + i40e_status status = 0; | |
| 4621 | + bool use_register; | |
| 4622 | + int retry = 5; | |
| 4623 | + u32 val = 0; | |
| 4624 | + | |
| 4625 | + use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5); | |
| 4626 | + if (!use_register) { | |
| 4627 | +do_retry: | |
| 4628 | + status = i40e_aq_rx_ctl_read_register(hw, reg_addr, &val, NULL); | |
| 4629 | + if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) { | |
| 4630 | + usleep_range(1000, 2000); | |
| 4631 | + retry--; | |
| 4632 | + goto do_retry; | |
| 4633 | + } | |
| 4634 | + } | |
| 4635 | + | |
| 4636 | + /* if the AQ access failed, try the old-fashioned way */ | |
| 4637 | + if (status || use_register) | |
| 4638 | + val = rd32(hw, reg_addr); | |
| 4639 | + | |
| 4640 | + return val; | |
| 4641 | +} | |
| 4642 | + | |
| 4643 | +/** | |
| 4644 | + * i40e_aq_rx_ctl_write_register | |
| 4645 | + * @hw: pointer to the hw struct | |
| 4646 | + * @reg_addr: register address | |
| 4647 | + * @reg_val: register value | |
| 4648 | + * @cmd_details: pointer to command details structure or NULL | |
| 4649 | + * | |
| 4650 | + * Use the firmware to write to an Rx control register, | |
| 4651 | + * especially useful if the Rx unit is under heavy pressure | |
| 4652 | + **/ | |
| 4653 | +i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw, | |
| 4654 | + u32 reg_addr, u32 reg_val, | |
| 4655 | + struct i40e_asq_cmd_details *cmd_details) | |
| 4656 | +{ | |
| 4657 | + struct i40e_aq_desc desc; | |
| 4658 | + struct i40e_aqc_rx_ctl_reg_read_write *cmd = | |
| 4659 | + (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw; | |
| 4660 | + i40e_status status; | |
| 4661 | + | |
| 4662 | + i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_rx_ctl_reg_write); | |
| 4663 | + | |
| 4664 | + cmd->address = cpu_to_le32(reg_addr); | |
| 4665 | + cmd->value = cpu_to_le32(reg_val); | |
| 4666 | + | |
| 4667 | + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); | |
| 4668 | + | |
| 4669 | + return status; | |
| 4670 | +} | |
| 4671 | + | |
| 4672 | +/** | |
| 4673 | + * i40e_write_rx_ctl - write to an Rx control register | |
| 4674 | + * @hw: pointer to the hw struct | |
| 4675 | + * @reg_addr: register address | |
| 4676 | + * @reg_val: register value | |
| 4677 | + **/ | |
| 4678 | +void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val) | |
| 4679 | +{ | |
| 4680 | + i40e_status status = 0; | |
| 4681 | + bool use_register; | |
| 4682 | + int retry = 5; | |
| 4683 | + | |
| 4684 | + use_register = (hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver < 5); | |
| 4685 | + if (!use_register) { | |
| 4686 | +do_retry: | |
| 4687 | + status = i40e_aq_rx_ctl_write_register(hw, reg_addr, | |
| 4688 | + reg_val, NULL); | |
| 4689 | + if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) { | |
| 4690 | + usleep_range(1000, 2000); | |
| 4691 | + retry--; | |
| 4692 | + goto do_retry; | |
| 4693 | + } | |
| 4694 | + } | |
| 4695 | + | |
| 4696 | + /* if the AQ access failed, try the old-fashioned way */ | |
| 4697 | + if (status || use_register) | |
| 4698 | + wr32(hw, reg_addr, reg_val); | |
| 4699 | +} | |
| @@ -380,17 +380,20 @@ static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, · 379 unmodified lines | ||
| 380 | 380 | { |
| 381 | 381 | u16 length, typelength, offset = 0; |
| 382 | 382 | struct i40e_cee_app_prio *app; |
| 383 | − u8 i, up, selector; | |
| 383 | + u8 i; | |
| 384 | 384 | |
| 385 | 385 | typelength = ntohs(tlv->hdr.typelen); |
| 386 | 386 | length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> |
| 387 | 387 | I40E_LLDP_TLV_LEN_SHIFT); |
| 388 | 388 | |
| 389 | 389 | dcbcfg->numapps = length / sizeof(*app); |
| 390 | + | |
| 390 | 391 | if (!dcbcfg->numapps) |
| 391 | 392 | return; |
| 392 | 393 | |
| 393 | 394 | for (i = 0; i < dcbcfg->numapps; i++) { |
| 395 | + u8 up, selector; | |
| 396 | + | |
| 394 | 397 | app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset); |
| 395 | 398 | for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) { |
| 396 | 399 | if (app->prio_map & BIT(up)) |
| @@ -400,13 +403,17 @@ static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, · 3 unmodified lines | ||
| 400 | 403 | |
| 401 | 404 | /* Get Selector from lower 2 bits, and convert to IEEE */ |
| 402 | 405 | selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK); |
| 403 | − if (selector == I40E_CEE_APP_SEL_ETHTYPE) | |
| 406 | + switch (selector) { | |
| 407 | + case I40E_CEE_APP_SEL_ETHTYPE: | |
| 404 | 408 | dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; |
| 405 | − else if (selector == I40E_CEE_APP_SEL_TCPIP) | |
| 409 | + break; | |
| 410 | + case I40E_CEE_APP_SEL_TCPIP: | |
| 406 | 411 | dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP; |
| 407 | − else | |
| 412 | + break; | |
| 413 | + default: | |
| 408 | 414 | /* Keep selector as it is for unknown types */ |
| 409 | 415 | dcbcfg->app[i].selector = selector; |
| 416 | + } | |
| 410 | 417 | |
| 411 | 418 | dcbcfg->app[i].protocolid = ntohs(app->protocol); |
| 412 | 419 | /* Move to next app */ |
| @@ -814,13 +821,15 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw) · 401 unmodified lines | ||
| 814 | 821 | struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg; |
| 815 | 822 | struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg; |
| 816 | 823 | |
| 817 | − /* If Firmware version < v4.33 IEEE only */ | |
| 818 | − if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || | |
| 819 | − (hw->aq.fw_maj_ver < 4)) | |
| 824 | + /* If Firmware version < v4.33 on X710/XL710, IEEE only */ | |
| 825 | + if ((hw->mac.type == I40E_MAC_XL710) && | |
| 826 | + (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || | |
| 827 | + (hw->aq.fw_maj_ver < 4))) | |
| 820 | 828 | return i40e_get_ieee_dcb_config(hw); |
| 821 | 829 | |
| 822 | − /* If Firmware version == v4.33 use old CEE struct */ | |
| 823 | − if ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33)) { | |
| 830 | + /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */ | |
| 831 | + if ((hw->mac.type == I40E_MAC_XL710) && | |
| 832 | + ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) { | |
| 824 | 833 | ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg, |
| 825 | 834 | sizeof(cee_v1_cfg), NULL); |
| 826 | 835 | if (!ret) { |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /******************************************************************************* |
| 2 | 2 | * |
| 3 | 3 | * Intel Ethernet Controller XL710 Family Linux Driver |
| 4 | − * Copyright(c) 2013 - 2014 Intel Corporation. | |
| 4 | + * Copyright(c) 2013 - 2016 Intel Corporation. | |
| 5 | 5 | * |
| 6 | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -61,256 +61,12 @@ static struct i40e_veb *i40e_dbg_find_veb(struct i40e_pf *pf, int seid) · 53 unmodified lines | ||
| 61 | 61 | { |
| 62 | 62 | int i; |
| 63 | 63 | |
| 64 | − if ((seid < I40E_BASE_VEB_SEID) || | |
| 65 | − (seid > (I40E_BASE_VEB_SEID + I40E_MAX_VEB))) | |
| 66 | − dev_info(&pf->pdev->dev, "%d: bad seid\n", seid); | |
| 67 | − else | |
| 68 | − for (i = 0; i < I40E_MAX_VEB; i++) | |
| 69 | − if (pf->veb[i] && pf->veb[i]->seid == seid) | |
| 70 | − return pf->veb[i]; | |
| 64 | + for (i = 0; i < I40E_MAX_VEB; i++) | |
| 65 | + if (pf->veb[i] && pf->veb[i]->seid == seid) | |
| 66 | + return pf->veb[i]; | |
| 71 | 67 | return NULL; |
| 72 | 68 | } |
| 73 | 69 | |
| 74 | −/************************************************************** | |
| 75 | − * dump | |
| 76 | − * The dump entry in debugfs is for getting a data snapshow of | |
| 77 | − * the driver's current configuration and runtime details. | |
| 78 | − * When the filesystem entry is written, a snapshot is taken. | |
| 79 | − * When the entry is read, the most recent snapshot data is dumped. | |
| 80 | − **************************************************************/ | |
| 81 | −static char *i40e_dbg_dump_buf; | |
| 82 | −static ssize_t i40e_dbg_dump_data_len; | |
| 83 | −static ssize_t i40e_dbg_dump_buffer_len; | |
| 84 | − | |
| 85 | −/** | |
| 86 | − * i40e_dbg_dump_read - read the dump data | |
| 87 | − * @filp: the opened file | |
| 88 | − * @buffer: where to write the data for the user to read | |
| 89 | − * @count: the size of the user's buffer | |
| 90 | − * @ppos: file position offset | |
| 91 | − **/ | |
| 92 | −static ssize_t i40e_dbg_dump_read(struct file *filp, char __user *buffer, | |
| 93 | − size_t count, loff_t *ppos) | |
| 94 | −{ | |
| 95 | − int bytes_not_copied; | |
| 96 | − int len; | |
| 97 | − | |
| 98 | − /* is *ppos bigger than the available data? */ | |
| 99 | − if (*ppos >= i40e_dbg_dump_data_len || !i40e_dbg_dump_buf) | |
| 100 | − return 0; | |
| 101 | − | |
| 102 | − /* be sure to not read beyond the end of available data */ | |
| 103 | − len = min_t(int, count, (i40e_dbg_dump_data_len - *ppos)); | |
| 104 | − | |
| 105 | − bytes_not_copied = copy_to_user(buffer, &i40e_dbg_dump_buf[*ppos], len); | |
| 106 | − if (bytes_not_copied) | |
| 107 | − return -EFAULT; | |
| 108 | − | |
| 109 | − *ppos += len; | |
| 110 | − return len; | |
| 111 | −} | |
| 112 | − | |
| 113 | −/** | |
| 114 | − * i40e_dbg_prep_dump_buf | |
| 115 | − * @pf: the PF we're working with | |
| 116 | − * @buflen: the desired buffer length | |
| 117 | − * | |
| 118 | − * Return positive if success, 0 if failed | |
| 119 | − **/ | |
| 120 | −static int i40e_dbg_prep_dump_buf(struct i40e_pf *pf, int buflen) | |
| 121 | −{ | |
| 122 | − /* if not already big enough, prep for re alloc */ | |
| 123 | − if (i40e_dbg_dump_buffer_len && i40e_dbg_dump_buffer_len < buflen) { | |
| 124 | − kfree(i40e_dbg_dump_buf); | |
| 125 | − i40e_dbg_dump_buffer_len = 0; | |
| 126 | − i40e_dbg_dump_buf = NULL; | |
| 127 | − } | |
| 128 | − | |
| 129 | − /* get a new buffer if needed */ | |
| 130 | − if (!i40e_dbg_dump_buf) { | |
| 131 | − i40e_dbg_dump_buf = kzalloc(buflen, GFP_KERNEL); | |
| 132 | − if (i40e_dbg_dump_buf != NULL) | |
| 133 | − i40e_dbg_dump_buffer_len = buflen; | |
| 134 | − } | |
| 135 | − | |
| 136 | − return i40e_dbg_dump_buffer_len; | |
| 137 | −} | |
| 138 | − | |
| 139 | −/** | |
| 140 | − * i40e_dbg_dump_write - trigger a datadump snapshot | |
| 141 | − * @filp: the opened file | |
| 142 | − * @buffer: where to find the user's data | |
| 143 | − * @count: the length of the user's data | |
| 144 | − * @ppos: file position offset | |
| 145 | − * | |
| 146 | − * Any write clears the stats | |
| 147 | − **/ | |
| 148 | −static ssize_t i40e_dbg_dump_write(struct file *filp, | |
| 149 | − const char __user *buffer, | |
| 150 | − size_t count, loff_t *ppos) | |
| 151 | −{ | |
| 152 | − struct i40e_pf *pf = filp->private_data; | |
| 153 | − bool seid_found = false; | |
| 154 | − long seid = -1; | |
| 155 | − int buflen = 0; | |
| 156 | − int i, ret; | |
| 157 | − int len; | |
| 158 | − u8 *p; | |
| 159 | − | |
| 160 | − /* don't allow partial writes */ | |
| 161 | − if (*ppos != 0) | |
| 162 | − return 0; | |
| 163 | − | |
| 164 | − /* decode the SEID given to be dumped */ | |
| 165 | − ret = kstrtol_from_user(buffer, count, 0, &seid); | |
| 166 | − | |
| 167 | − if (ret) { | |
| 168 | − dev_info(&pf->pdev->dev, "bad seid value\n"); | |
| 169 | − } else if (seid == 0) { | |
| 170 | − seid_found = true; | |
| 171 | − | |
| 172 | − kfree(i40e_dbg_dump_buf); | |
| 173 | − i40e_dbg_dump_buffer_len = 0; | |
| 174 | − i40e_dbg_dump_data_len = 0; | |
| 175 | − i40e_dbg_dump_buf = NULL; | |
| 176 | − dev_info(&pf->pdev->dev, "debug buffer freed\n"); | |
| 177 | − | |
| 178 | − } else if (seid == pf->pf_seid || seid == 1) { | |
| 179 | − seid_found = true; | |
| 180 | − | |
| 181 | − buflen = sizeof(struct i40e_pf); | |
| 182 | − buflen += (sizeof(struct i40e_aq_desc) | |
| 183 | − * (pf->hw.aq.num_arq_entries + pf->hw.aq.num_asq_entries)); | |
| 184 | − | |
| 185 | − if (i40e_dbg_prep_dump_buf(pf, buflen)) { | |
| 186 | − p = i40e_dbg_dump_buf; | |
| 187 | − | |
| 188 | − len = sizeof(struct i40e_pf); | |
| 189 | − memcpy(p, pf, len); | |
| 190 | − p += len; | |
| 191 | − | |
| 192 | − len = (sizeof(struct i40e_aq_desc) | |
| 193 | − * pf->hw.aq.num_asq_entries); | |
| 194 | − memcpy(p, pf->hw.aq.asq.desc_buf.va, len); | |
| 195 | − p += len; | |
| 196 | − | |
| 197 | − len = (sizeof(struct i40e_aq_desc) | |
| 198 | − * pf->hw.aq.num_arq_entries); | |
| 199 | − memcpy(p, pf->hw.aq.arq.desc_buf.va, len); | |
| 200 | − p += len; | |
| 201 | − | |
| 202 | − i40e_dbg_dump_data_len = buflen; | |
| 203 | − dev_info(&pf->pdev->dev, | |
| 204 | − "PF seid %ld dumped %d bytes\n", | |
| 205 | − seid, (int)i40e_dbg_dump_data_len); | |
| 206 | − } | |
| 207 | − } else if (seid >= I40E_BASE_VSI_SEID) { | |
| 208 | − struct i40e_vsi *vsi = NULL; | |
| 209 | − struct i40e_mac_filter *f; | |
| 210 | − int filter_count = 0; | |
| 211 | − | |
| 212 | − mutex_lock(&pf->switch_mutex); | |
| 213 | − vsi = i40e_dbg_find_vsi(pf, seid); | |
| 214 | − if (!vsi) { | |
| 215 | − mutex_unlock(&pf->switch_mutex); | |
| 216 | − goto write_exit; | |
| 217 | − } | |
| 218 | − | |
| 219 | − buflen = sizeof(struct i40e_vsi); | |
| 220 | − buflen += sizeof(struct i40e_q_vector) * vsi->num_q_vectors; | |
| 221 | − buflen += sizeof(struct i40e_ring) * 2 * vsi->num_queue_pairs; | |
| 222 | − buflen += sizeof(struct i40e_tx_buffer) * vsi->num_queue_pairs; | |
| 223 | − buflen += sizeof(struct i40e_rx_buffer) * vsi->num_queue_pairs; | |
| 224 | − list_for_each_entry(f, &vsi->mac_filter_list, list) | |
| 225 | − filter_count++; | |
| 226 | − buflen += sizeof(struct i40e_mac_filter) * filter_count; | |
| 227 | − | |
| 228 | − if (i40e_dbg_prep_dump_buf(pf, buflen)) { | |
| 229 | − p = i40e_dbg_dump_buf; | |
| 230 | − seid_found = true; | |
| 231 | − | |
| 232 | − len = sizeof(struct i40e_vsi); | |
| 233 | − memcpy(p, vsi, len); | |
| 234 | − p += len; | |
| 235 | − | |
| 236 | − if (vsi->num_q_vectors) { | |
| 237 | − len = (sizeof(struct i40e_q_vector) | |
| 238 | − * vsi->num_q_vectors); | |
| 239 | − memcpy(p, vsi->q_vectors, len); | |
| 240 | − p += len; | |
| 241 | − } | |
| 242 | − | |
| 243 | − if (vsi->num_queue_pairs) { | |
| 244 | − len = (sizeof(struct i40e_ring) * | |
| 245 | − vsi->num_queue_pairs); | |
| 246 | − memcpy(p, vsi->tx_rings, len); | |
| 247 | − p += len; | |
| 248 | − memcpy(p, vsi->rx_rings, len); | |
| 249 | − p += len; | |
| 250 | − } | |
| 251 | − | |
| 252 | − if (vsi->tx_rings[0]) { | |
| 253 | − len = sizeof(struct i40e_tx_buffer); | |
| 254 | − for (i = 0; i < vsi->num_queue_pairs; i++) { | |
| 255 | − memcpy(p, vsi->tx_rings[i]->tx_bi, len); | |
| 256 | − p += len; | |
| 257 | − } | |
| 258 | − len = sizeof(struct i40e_rx_buffer); | |
| 259 | − for (i = 0; i < vsi->num_queue_pairs; i++) { | |
| 260 | − memcpy(p, vsi->rx_rings[i]->rx_bi, len); | |
| 261 | − p += len; | |
| 262 | − } | |
| 263 | − } | |
| 264 | − | |
| 265 | − /* macvlan filter list */ | |
| 266 | − len = sizeof(struct i40e_mac_filter); | |
| 267 | − list_for_each_entry(f, &vsi->mac_filter_list, list) { | |
| 268 | − memcpy(p, f, len); | |
| 269 | − p += len; | |
| 270 | − } | |
| 271 | − | |
| 272 | − i40e_dbg_dump_data_len = buflen; | |
| 273 | − dev_info(&pf->pdev->dev, | |
| 274 | − "VSI seid %ld dumped %d bytes\n", | |
| 275 | − seid, (int)i40e_dbg_dump_data_len); | |
| 276 | − } | |
| 277 | − mutex_unlock(&pf->switch_mutex); | |
| 278 | − } else if (seid >= I40E_BASE_VEB_SEID) { | |
| 279 | − struct i40e_veb *veb = NULL; | |
| 280 | − | |
| 281 | − mutex_lock(&pf->switch_mutex); | |
| 282 | − veb = i40e_dbg_find_veb(pf, seid); | |
| 283 | − if (!veb) { | |
| 284 | − mutex_unlock(&pf->switch_mutex); | |
| 285 | − goto write_exit; | |
| 286 | − } | |
| 287 | − | |
| 288 | − buflen = sizeof(struct i40e_veb); | |
| 289 | − if (i40e_dbg_prep_dump_buf(pf, buflen)) { | |
| 290 | − seid_found = true; | |
| 291 | − memcpy(i40e_dbg_dump_buf, veb, buflen); | |
| 292 | − i40e_dbg_dump_data_len = buflen; | |
| 293 | − dev_info(&pf->pdev->dev, | |
| 294 | − "VEB seid %ld dumped %d bytes\n", | |
| 295 | − seid, (int)i40e_dbg_dump_data_len); | |
| 296 | − } | |
| 297 | − mutex_unlock(&pf->switch_mutex); | |
| 298 | − } | |
| 299 | − | |
| 300 | −write_exit: | |
| 301 | − if (!seid_found) | |
| 302 | − dev_info(&pf->pdev->dev, "unknown seid %ld\n", seid); | |
| 303 | − | |
| 304 | − return count; | |
| 305 | −} | |
194 more lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 507 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 1033 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 1375 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 1239 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 205 lines aren’t shown here.
This diff is large: its 281 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 251 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 1403 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 359 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 844 lines aren’t shown here.
This diff is large: its 488 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 1809 lines aren’t shown here.
This diff is large: its 422 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 496 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 263 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 237 lines aren’t shown here.
This diff is large: its 303 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 593 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 430 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 232 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 405 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 767 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 3133 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 2424 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 880 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 493 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 1308 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 205 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 317 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 5496 lines aren’t shown here.
This diff is large: its 596 lines aren’t shown here.
This diff is large: its 468 lines aren’t shown here.
This diff is large: its 2910 lines aren’t shown here.
This diff is large: its 2959 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 202 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 232 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 354 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 149 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 441 lines aren’t shown here.
This diff is large: its 300 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 957 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 469 lines aren’t shown here.
This diff is large: its 1891 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 1733 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 574 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 123 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 3298 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 154 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 353 lines aren’t shown here.
This diff is large: its 155 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 450 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 632 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 1271 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 934 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 142 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 227 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 194 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 163 lines aren’t shown here.
This diff is large: its 465 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 285 lines aren’t shown here.
This diff is large: its 177 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 181 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 240 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 301 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 233 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 1057 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 281 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 175 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 419 lines aren’t shown here.
This diff is large: its 258 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 236 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 148 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 235 lines aren’t shown here.
This diff is large: its 285 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 484 lines aren’t shown here.
This diff is large: its 233 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 249 lines aren’t shown here.
This diff is large: its 163 lines aren’t shown here.
This diff is large: its 240 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 621 lines aren’t shown here.
This diff is large: its 369 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 245 lines aren’t shown here.
This diff is large: its 292 lines aren’t shown here.
This diff is large: its 1200 lines aren’t shown here.
This diff is large: its 663 lines aren’t shown here.
This diff is large: its 150 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 414 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 536 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 345 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 4602 lines aren’t shown here.
This diff is large: its 862 lines aren’t shown here.
This diff is large: its 375 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 237 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 139 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 220 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 186 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 227 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 431 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 534 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 162 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 946 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 248 lines aren’t shown here.
This diff is large: its 629 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 291 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 359 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 267 lines aren’t shown here.
This diff is large: its 556 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 394 lines aren’t shown here.
This diff is large: its 348 lines aren’t shown here.
This diff is large: its 516 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 834 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 760 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 340 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 354 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 200 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 347 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 174 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 534 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 769 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 142 lines aren’t shown here.
This diff is large: its 343 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 233 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 284 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 987 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 402 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 250 lines aren’t shown here.
This diff is large: its 231 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 739 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 169 lines aren’t shown here.
This diff is large: its 747 lines aren’t shown here.
This diff is large: its 544 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 277 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 305 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 157 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 325 lines aren’t shown here.
This diff is large: its 348 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 339 lines aren’t shown here.
This diff is large: its 375 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 139 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 310 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 500 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 170 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 370 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 306 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 4 lines aren’t shown here.
This diff is large: its 427 lines aren’t shown here.
This diff is large: its 2410 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 165 lines aren’t shown here.
This diff is large: its 281 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 186 lines aren’t shown here.
This diff is large: its 187 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 905 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 861 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 273 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 702 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 249 lines aren’t shown here.
This diff is large: its 377 lines aren’t shown here.
This diff is large: its 149 lines aren’t shown here.
This diff is large: its 638 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 313 lines aren’t shown here.
This diff is large: its 399 lines aren’t shown here.
This diff is large: its 770 lines aren’t shown here.
This diff is large: its 838 lines aren’t shown here.
This diff is large: its 905 lines aren’t shown here.
This diff is large: its 170 lines aren’t shown here.
This diff is large: its 982 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 203 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 322 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 164 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 639 lines aren’t shown here.
This diff is large: its 232 lines aren’t shown here.
This diff is large: its 274 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 278 lines aren’t shown here.
This diff is large: its 417 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 181 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 364 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 324 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 871 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 231 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 273 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 368 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 217 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 399 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 285 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 259 lines aren’t shown here.