diff options
author | Praneeth Bajjuri | 2021-01-05 14:15:31 -0600 |
---|---|---|
committer | Praneeth Bajjuri | 2021-01-05 14:15:31 -0600 |
commit | b6cc3b3206a67cfa96eb76c223d5f629908e11b1 (patch) | |
tree | cad1d6f264954dde9f9dc46bfcbd13cb9f1022e4 | |
parent | 2fcb7aeeee3091e0e8c905e26dbcd75f98f98374 (diff) | |
parent | 41c32273d7f5666a5637a109ec004fd746d5efac (diff) | |
download | kernel-b6cc3b3206a67cfa96eb76c223d5f629908e11b1.tar.gz kernel-b6cc3b3206a67cfa96eb76c223d5f629908e11b1.tar.xz kernel-b6cc3b3206a67cfa96eb76c223d5f629908e11b1.zip |
Merge branch 'ti-linux-5.4.y' of git://git.ti.com/ti-linux-kernel/ti-linux-kernel into android-feature-ti-linux-5.4.y
* 'ti-linux-5.4.y' of git://git.ti.com/ti-linux-kernel/ti-linux-kernel: (26 commits)
can: m_can: Set device to software init mode before closing
arm64: dts: ti: k3-j7200-common-proc-board: add mcu cpsw nuss pinmux and phy defs
arm64: dts: ti: k3-j7200-mcu: add mcu cpsw nuss node
arm64: dts: ti: j7200-main: add timesync_router node
arm64: dts: ti: j7200-main: add main navss cpts node
arm64: dts: ti: k3-j7200: add DMA support
dmaengine: ti: k3-psil: add map for j7200
soc: ti: k3-socinfo: Add entry for J7200
ARM: dts: am57xx-idk: Add hsr ptp tx interrupts
ARM: dts: am57xx-idk: Add emac ptp tx interrupts
net: ti: prueth: Add support for getting timestamping capabilitues from ethtool
net: ti: prueth: Add support for setting and getting hwtimestamp configuration
net: ti: prueth: Add support for reading timestamps from rx packets
net: ti: prueth: hsr: Add support for timestamping tx packets
dt-bindings: net: ti-prueth: Add ptp tx interrupt for hsr
net: ti: prueth: dual_emac: Add support for timestamping tx packets
dt-bindings: net: ti-prueth: Add ptp tx interrupt for dual emac
net: socket: forward extra timestamp of received skb to user space
net: socket: accept redundant network info in control message
net: socket: pass on redundant net info to sock_recv_errqueue
...
Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
27 files changed, 1271 insertions, 39 deletions
diff --git a/Documentation/devicetree/bindings/net/ti-prueth.txt b/Documentation/devicetree/bindings/net/ti-prueth.txt index 8d511fcba728..846712bff953 100644 --- a/Documentation/devicetree/bindings/net/ti-prueth.txt +++ b/Documentation/devicetree/bindings/net/ti-prueth.txt | |||
@@ -48,8 +48,10 @@ Optional properties for children: | |||
48 | for small size frames. So use it only if | 48 | for small size frames. So use it only if |
49 | specific application uses mostly MTU or near | 49 | specific application uses mostly MTU or near |
50 | MTU size frames. | 50 | MTU size frames. |
51 | - interrupts : Add interrupt sources for Tx if | 51 | add "emac_ptp_tx" when ptp is needed with Dual EMAC |
52 | interrupt-names "tx" used. | 52 | add "hsr_ptp_tx" when ptp is needed with hsr/prp. |
53 | - interrupts : should contain an array of PRUSS system event | ||
54 | numbers for each entry in interrupt-names. | ||
53 | 55 | ||
54 | Example (am572x-idk board, dual-emac): | 56 | Example (am572x-idk board, dual-emac): |
55 | ====================================== | 57 | ====================================== |
@@ -64,8 +66,8 @@ Example (am572x-idk board, dual-emac): | |||
64 | pruss2_emac0: ethernet-mii0 { | 66 | pruss2_emac0: ethernet-mii0 { |
65 | phy-handle = <&pruss2_eth0_phy>; | 67 | phy-handle = <&pruss2_eth0_phy>; |
66 | phy-mode = "mii"; | 68 | phy-mode = "mii"; |
67 | interrupts = <20>, <22>; | 69 | interrupts = <20>, <22>, <26>, <23>; |
68 | interrupt-names = "rx", "tx"; | 70 | interrupt-names = "rx", "tx", "emac_ptp_tx", "hsr_ptp_tx"; |
69 | /* Filled in by bootloader */ | 71 | /* Filled in by bootloader */ |
70 | local-mac-address = [00 00 00 00 00 00]; | 72 | local-mac-address = [00 00 00 00 00 00]; |
71 | }; | 73 | }; |
@@ -73,8 +75,8 @@ Example (am572x-idk board, dual-emac): | |||
73 | pruss2_emac1: ethernet-mii1 { | 75 | pruss2_emac1: ethernet-mii1 { |
74 | phy-handle = <&pruss2_eth1_phy>; | 76 | phy-handle = <&pruss2_eth1_phy>; |
75 | phy-mode = "mii"; | 77 | phy-mode = "mii"; |
76 | interrupts = <21>, <23>; | 78 | interrupts = <21>, <23>, <27>, <24>; |
77 | interrupt-names = "rx", "tx"; | 79 | interrupt-names = "rx", "tx", "emac_ptp_tx", "hsr_ptp_tx"; |
78 | /* Filled in by bootloader */ | 80 | /* Filled in by bootloader */ |
79 | local-mac-address = [00 00 00 00 00 00]; | 81 | local-mac-address = [00 00 00 00 00 00]; |
80 | }; | 82 | }; |
@@ -93,8 +95,8 @@ Example (am572x-idk board, single-emac): | |||
93 | pruss2_emac1: ethernet-mii1 { | 95 | pruss2_emac1: ethernet-mii1 { |
94 | phy-handle = <&pruss2_eth1_phy>; | 96 | phy-handle = <&pruss2_eth1_phy>; |
95 | phy-mode = "mii"; | 97 | phy-mode = "mii"; |
96 | interrupts = <21>, <23>; | 98 | interrupts = <21>, <23>, <27>, <24>; |
97 | interrupt-names = "rx", "tx"; | 99 | interrupt-names = "rx", "tx", "emac_ptp_tx", "hsr_ptp_tx"; |
98 | /* Filled in by bootloader */ | 100 | /* Filled in by bootloader */ |
99 | local-mac-address = [00 00 00 00 00 00]; | 101 | local-mac-address = [00 00 00 00 00 00]; |
100 | }; | 102 | }; |
diff --git a/arch/arm/boot/dts/am571x-idk.dts b/arch/arm/boot/dts/am571x-idk.dts index f7a97f61b9e8..d50c3f99b4b4 100644 --- a/arch/arm/boot/dts/am571x-idk.dts +++ b/arch/arm/boot/dts/am571x-idk.dts | |||
@@ -188,8 +188,8 @@ | |||
188 | ethernet-mii0 { | 188 | ethernet-mii0 { |
189 | phy-handle = <&pruss1_eth0_phy>; | 189 | phy-handle = <&pruss1_eth0_phy>; |
190 | phy-mode = "mii"; | 190 | phy-mode = "mii"; |
191 | interrupts = <20>; | 191 | interrupts = <20>, <26>, <23>; |
192 | interrupt-names = "rx"; | 192 | interrupt-names = "rx", "emac_ptp_tx", "hsr_ptp_tx"; |
193 | ti,no-half-duplex; | 193 | ti,no-half-duplex; |
194 | /* Filled in by bootloader */ | 194 | /* Filled in by bootloader */ |
195 | local-mac-address = [00 00 00 00 00 00]; | 195 | local-mac-address = [00 00 00 00 00 00]; |
@@ -198,8 +198,8 @@ | |||
198 | ethernet-mii1 { | 198 | ethernet-mii1 { |
199 | phy-handle = <&pruss1_eth1_phy>; | 199 | phy-handle = <&pruss1_eth1_phy>; |
200 | phy-mode = "mii"; | 200 | phy-mode = "mii"; |
201 | interrupts = <21>; | 201 | interrupts = <21>, <27>, <24>; |
202 | interrupt-names = "rx"; | 202 | interrupt-names = "rx", "emac_ptp_tx", "hsr_ptp_tx"; |
203 | ti,no-half-duplex; | 203 | ti,no-half-duplex; |
204 | /* Filled in by bootloader */ | 204 | /* Filled in by bootloader */ |
205 | local-mac-address = [00 00 00 00 00 00]; | 205 | local-mac-address = [00 00 00 00 00 00]; |
diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi index 0d9c3e02092e..5b9a9e127634 100644 --- a/arch/arm/boot/dts/am57xx-idk-common.dtsi +++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi | |||
@@ -172,8 +172,8 @@ | |||
172 | pruss2_emac0: ethernet-mii0 { | 172 | pruss2_emac0: ethernet-mii0 { |
173 | phy-handle = <&pruss2_eth0_phy>; | 173 | phy-handle = <&pruss2_eth0_phy>; |
174 | phy-mode = "mii"; | 174 | phy-mode = "mii"; |
175 | interrupts = <20>; | 175 | interrupts = <20>, <26>, <23>; |
176 | interrupt-names = "rx"; | 176 | interrupt-names = "rx", "emac_ptp_tx", "hsr_ptp_tx"; |
177 | ti,no-half-duplex; | 177 | ti,no-half-duplex; |
178 | /* Filled in by bootloader */ | 178 | /* Filled in by bootloader */ |
179 | local-mac-address = [00 00 00 00 00 00]; | 179 | local-mac-address = [00 00 00 00 00 00]; |
@@ -182,8 +182,8 @@ | |||
182 | pruss2_emac1: ethernet-mii1 { | 182 | pruss2_emac1: ethernet-mii1 { |
183 | phy-handle = <&pruss2_eth1_phy>; | 183 | phy-handle = <&pruss2_eth1_phy>; |
184 | phy-mode = "mii"; | 184 | phy-mode = "mii"; |
185 | interrupts = <21>; | 185 | interrupts = <21>, <27>, <24>; |
186 | interrupt-names = "rx"; | 186 | interrupt-names = "rx", "emac_ptp_tx", "hsr_ptp_tx"; |
187 | ti,no-half-duplex; | 187 | ti,no-half-duplex; |
188 | /* Filled in by bootloader */ | 188 | /* Filled in by bootloader */ |
189 | local-mac-address = [00 00 00 00 00 00]; | 189 | local-mac-address = [00 00 00 00 00 00]; |
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts index e27069317c4e..12c800b187f1 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts | |||
@@ -6,6 +6,7 @@ | |||
6 | /dts-v1/; | 6 | /dts-v1/; |
7 | 7 | ||
8 | #include "k3-j7200-som-p0.dtsi" | 8 | #include "k3-j7200-som-p0.dtsi" |
9 | #include <dt-bindings/net/ti-dp83867.h> | ||
9 | 10 | ||
10 | / { | 11 | / { |
11 | chosen { | 12 | chosen { |
@@ -14,6 +15,32 @@ | |||
14 | }; | 15 | }; |
15 | }; | 16 | }; |
16 | 17 | ||
18 | &wkup_pmx0 { | ||
19 | mcu_cpsw_pins_default: mcu_cpsw_pins_default { | ||
20 | pinctrl-single,pins = < | ||
21 | J721E_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */ | ||
22 | J721E_WKUP_IOPAD(0x006c, PIN_INPUT, 0) /* MCU_RGMII1_RX_CTL */ | ||
23 | J721E_WKUP_IOPAD(0x0070, PIN_OUTPUT, 0) /* MCU_RGMII1_TD3 */ | ||
24 | J721E_WKUP_IOPAD(0x0074, PIN_OUTPUT, 0) /* MCU_RGMII1_TD2 */ | ||
25 | J721E_WKUP_IOPAD(0x0078, PIN_OUTPUT, 0) /* MCU_RGMII1_TD1 */ | ||
26 | J721E_WKUP_IOPAD(0x007c, PIN_OUTPUT, 0) /* MCU_RGMII1_TD0 */ | ||
27 | J721E_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* MCU_RGMII1_RD3 */ | ||
28 | J721E_WKUP_IOPAD(0x008c, PIN_INPUT, 0) /* MCU_RGMII1_RD2 */ | ||
29 | J721E_WKUP_IOPAD(0x0090, PIN_INPUT, 0) /* MCU_RGMII1_RD1 */ | ||
30 | J721E_WKUP_IOPAD(0x0094, PIN_INPUT, 0) /* MCU_RGMII1_RD0 */ | ||
31 | J721E_WKUP_IOPAD(0x0080, PIN_INPUT, 0) /* MCU_RGMII1_TXC */ | ||
32 | J721E_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* MCU_RGMII1_RXC */ | ||
33 | >; | ||
34 | }; | ||
35 | |||
36 | mcu_mdio_pins_default: mcu_mdio1_pins_default { | ||
37 | pinctrl-single,pins = < | ||
38 | J721E_WKUP_IOPAD(0x009c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */ | ||
39 | J721E_WKUP_IOPAD(0x0098, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */ | ||
40 | >; | ||
41 | }; | ||
42 | }; | ||
43 | |||
17 | &wkup_uart0 { | 44 | &wkup_uart0 { |
18 | /* Wakeup UART is used by System firmware */ | 45 | /* Wakeup UART is used by System firmware */ |
19 | status = "disabled"; | 46 | status = "disabled"; |
@@ -62,3 +89,39 @@ | |||
62 | /* UART not brought out */ | 89 | /* UART not brought out */ |
63 | status = "disabled"; | 90 | status = "disabled"; |
64 | }; | 91 | }; |
92 | |||
93 | &mcu_cpsw { | ||
94 | pinctrl-names = "default"; | ||
95 | pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>; | ||
96 | |||
97 | cpts { | ||
98 | ti,pps = <3 1>; | ||
99 | }; | ||
100 | }; | ||
101 | |||
102 | &davinci_mdio { | ||
103 | phy0: ethernet-phy@0 { | ||
104 | reg = <0>; | ||
105 | ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; | ||
106 | ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; | ||
107 | }; | ||
108 | }; | ||
109 | |||
110 | &cpsw_port1 { | ||
111 | phy-mode = "rgmii-rxid"; | ||
112 | phy-handle = <&phy0>; | ||
113 | }; | ||
114 | |||
115 | #define TS_OFFSET(pa, val) (0x4 + (pa) * 4) (0x10000 | val) | ||
116 | |||
117 | ×ync_router { | ||
118 | pinctrl-names = "default"; | ||
119 | pinctrl-0 = <&mcu_cpts>; | ||
120 | |||
121 | mcu_cpts: mcu_cpts { | ||
122 | pinctrl-single,pins = < | ||
123 | /* pps [cpts genf1] in17 -> out25 [cpts hw4_push] */ | ||
124 | TS_OFFSET(25, 17) | ||
125 | >; | ||
126 | }; | ||
127 | }; | ||
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi index 70c8f7e941fb..0109f5cad461 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | |||
@@ -45,6 +45,31 @@ | |||
45 | #address-cells = <2>; | 45 | #address-cells = <2>; |
46 | #size-cells = <2>; | 46 | #size-cells = <2>; |
47 | ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>; | 47 | ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>; |
48 | ti,sci-dev-id = <199>; | ||
49 | |||
50 | main_navss_intr: interrupt-controller1 { | ||
51 | compatible = "ti,sci-intr"; | ||
52 | ti,intr-trigger-type = <4>; | ||
53 | interrupt-controller; | ||
54 | interrupt-parent = <&gic500>; | ||
55 | #interrupt-cells = <1>; | ||
56 | ti,sci = <&dmsc>; | ||
57 | ti,sci-dev-id = <213>; | ||
58 | ti,interrupt-ranges = <0 64 64>, | ||
59 | <64 448 64>, | ||
60 | <128 672 64>; | ||
61 | }; | ||
62 | |||
63 | main_udmass_inta: interrupt-controller@33d00000 { | ||
64 | compatible = "ti,sci-inta"; | ||
65 | reg = <0x0 0x33d00000 0x0 0x100000>; | ||
66 | interrupt-controller; | ||
67 | interrupt-parent = <&main_navss_intr>; | ||
68 | msi-controller; | ||
69 | ti,sci = <&dmsc>; | ||
70 | ti,sci-dev-id = <209>; | ||
71 | ti,interrupt-ranges = <0 0 256>; | ||
72 | }; | ||
48 | 73 | ||
49 | secure_proxy_main: mailbox@32c00000 { | 74 | secure_proxy_main: mailbox@32c00000 { |
50 | compatible = "ti,am654-secure-proxy"; | 75 | compatible = "ti,am654-secure-proxy"; |
@@ -56,6 +81,54 @@ | |||
56 | interrupt-names = "rx_011"; | 81 | interrupt-names = "rx_011"; |
57 | interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; | 82 | interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; |
58 | }; | 83 | }; |
84 | |||
85 | main_ringacc: ringacc@3c000000 { | ||
86 | compatible = "ti,am654-navss-ringacc"; | ||
87 | reg = <0x0 0x3c000000 0x0 0x400000>, | ||
88 | <0x0 0x38000000 0x0 0x400000>, | ||
89 | <0x0 0x31120000 0x0 0x100>, | ||
90 | <0x0 0x33000000 0x0 0x40000>; | ||
91 | reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target"; | ||
92 | ti,num-rings = <1024>; | ||
93 | ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */ | ||
94 | ti,sci = <&dmsc>; | ||
95 | ti,sci-dev-id = <211>; | ||
96 | msi-parent = <&main_udmass_inta>; | ||
97 | }; | ||
98 | |||
99 | main_udmap: dma-controller@31150000 { | ||
100 | compatible = "ti,j721e-navss-main-udmap"; | ||
101 | reg = <0x0 0x31150000 0x0 0x100>, | ||
102 | <0x0 0x34000000 0x0 0x100000>, | ||
103 | <0x0 0x35000000 0x0 0x100000>; | ||
104 | reg-names = "gcfg", "rchanrt", "tchanrt"; | ||
105 | msi-parent = <&main_udmass_inta>; | ||
106 | #dma-cells = <1>; | ||
107 | |||
108 | ti,sci = <&dmsc>; | ||
109 | ti,sci-dev-id = <212>; | ||
110 | ti,ringacc = <&main_ringacc>; | ||
111 | |||
112 | ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */ | ||
113 | <0x0f>, /* TX_HCHAN */ | ||
114 | <0x10>; /* TX_UHCHAN */ | ||
115 | ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */ | ||
116 | <0x0b>, /* RX_HCHAN */ | ||
117 | <0x0c>; /* RX_UHCHAN */ | ||
118 | ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */ | ||
119 | }; | ||
120 | |||
121 | cpts@310d0000 { | ||
122 | compatible = "ti,j721e-cpts"; | ||
123 | reg = <0x0 0x310d0000 0x0 0x400>; | ||
124 | reg-names = "cpts"; | ||
125 | clocks = <&k3_clks 201 1>; | ||
126 | clock-names = "cpts"; | ||
127 | interrupts-extended = <&main_navss_intr 391>; | ||
128 | interrupt-names = "cpts"; | ||
129 | ti,cpts-periodic-outputs = <6>; | ||
130 | ti,cpts-ext-ts-inputs = <8>; | ||
131 | }; | ||
59 | }; | 132 | }; |
60 | 133 | ||
61 | main_pmx0: pinmux@11c000 { | 134 | main_pmx0: pinmux@11c000 { |
@@ -196,4 +269,14 @@ | |||
196 | clocks = <&k3_clks 286 2>; | 269 | clocks = <&k3_clks 286 2>; |
197 | clock-names = "fclk"; | 270 | clock-names = "fclk"; |
198 | }; | 271 | }; |
272 | |||
273 | timesync_router: timesync_router@a40000 { | ||
274 | compatible = "pinctrl-single"; | ||
275 | reg = <0x0 0xa40000 0x0 0x800>; | ||
276 | #address-cells = <1>; | ||
277 | #size-cells = <0>; | ||
278 | #pinctrl-cells = <1>; | ||
279 | pinctrl-single,register-width = <32>; | ||
280 | pinctrl-single,function-mask = <0x000107ff>; | ||
281 | }; | ||
199 | }; | 282 | }; |
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi index 670e4c7cd9fe..9b6d2ac98edb 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi | |||
@@ -34,6 +34,20 @@ | |||
34 | }; | 34 | }; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | mcu_conf: syscon@40f00000 { | ||
38 | compatible = "syscon", "simple-mfd"; | ||
39 | reg = <0x0 0x40f00000 0x0 0x20000>; | ||
40 | #address-cells = <1>; | ||
41 | #size-cells = <1>; | ||
42 | ranges = <0x0 0x0 0x40f00000 0x20000>; | ||
43 | |||
44 | phy_gmii_sel: phy@4040 { | ||
45 | compatible = "ti,am654-phy-gmii-sel"; | ||
46 | reg = <0x4040 0x4>; | ||
47 | #phy-cells = <1>; | ||
48 | }; | ||
49 | }; | ||
50 | |||
37 | chipid@43000014 { | 51 | chipid@43000014 { |
38 | compatible = "ti,am654-chipid"; | 52 | compatible = "ti,am654-chipid"; |
39 | reg = <0x0 0x43000014 0x0 0x4>; | 53 | reg = <0x0 0x43000014 0x0 0x4>; |
@@ -81,4 +95,109 @@ | |||
81 | clocks = <&k3_clks 149 2>; | 95 | clocks = <&k3_clks 149 2>; |
82 | clock-names = "fclk"; | 96 | clock-names = "fclk"; |
83 | }; | 97 | }; |
98 | |||
99 | cbass_mcu_navss: navss@28380000 { | ||
100 | compatible = "simple-mfd"; | ||
101 | #address-cells = <2>; | ||
102 | #size-cells = <2>; | ||
103 | ranges; | ||
104 | dma-coherent; | ||
105 | dma-ranges; | ||
106 | |||
107 | ti,sci-dev-id = <232>; | ||
108 | |||
109 | mcu_ringacc: ringacc@2b800000 { | ||
110 | compatible = "ti,am654-navss-ringacc"; | ||
111 | reg = <0x0 0x2b800000 0x0 0x400000>, | ||
112 | <0x0 0x2b000000 0x0 0x400000>, | ||
113 | <0x0 0x28590000 0x0 0x100>, | ||
114 | <0x0 0x2a500000 0x0 0x40000>; | ||
115 | reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target"; | ||
116 | ti,num-rings = <286>; | ||
117 | ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */ | ||
118 | ti,sci = <&dmsc>; | ||
119 | ti,sci-dev-id = <235>; | ||
120 | msi-parent = <&main_udmass_inta>; | ||
121 | }; | ||
122 | |||
123 | mcu_udmap: dma-controller@285c0000 { | ||
124 | compatible = "ti,j721e-navss-mcu-udmap"; | ||
125 | reg = <0x0 0x285c0000 0x0 0x100>, | ||
126 | <0x0 0x2a800000 0x0 0x40000>, | ||
127 | <0x0 0x2aa00000 0x0 0x40000>; | ||
128 | reg-names = "gcfg", "rchanrt", "tchanrt"; | ||
129 | msi-parent = <&main_udmass_inta>; | ||
130 | #dma-cells = <1>; | ||
131 | |||
132 | ti,sci = <&dmsc>; | ||
133 | ti,sci-dev-id = <236>; | ||
134 | ti,ringacc = <&mcu_ringacc>; | ||
135 | |||
136 | ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */ | ||
137 | <0x0f>; /* TX_HCHAN */ | ||
138 | ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */ | ||
139 | <0x0b>; /* RX_HCHAN */ | ||
140 | ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */ | ||
141 | }; | ||
142 | }; | ||
143 | |||
144 | mcu_cpsw: ethernet@46000000 { | ||
145 | compatible = "ti,j721e-cpsw-nuss"; | ||
146 | #address-cells = <2>; | ||
147 | #size-cells = <2>; | ||
148 | reg = <0x0 0x46000000 0x0 0x200000>; | ||
149 | reg-names = "cpsw_nuss"; | ||
150 | ranges = <0x0 0x0 0x0 0x46000000 0x0 0x200000>; | ||
151 | dma-coherent; | ||
152 | clocks = <&k3_clks 18 21>; | ||
153 | clock-names = "fck"; | ||
154 | power-domains = <&k3_pds 18 TI_SCI_PD_EXCLUSIVE>; | ||
155 | |||
156 | dmas = <&mcu_udmap 0xf000>, | ||
157 | <&mcu_udmap 0xf001>, | ||
158 | <&mcu_udmap 0xf002>, | ||
159 | <&mcu_udmap 0xf003>, | ||
160 | <&mcu_udmap 0xf004>, | ||
161 | <&mcu_udmap 0xf005>, | ||
162 | <&mcu_udmap 0xf006>, | ||
163 | <&mcu_udmap 0xf007>, | ||
164 | <&mcu_udmap 0x7000>; | ||
165 | dma-names = "tx0", "tx1", "tx2", "tx3", | ||
166 | "tx4", "tx5", "tx6", "tx7", | ||
167 | "rx"; | ||
168 | |||
169 | ethernet-ports { | ||
170 | #address-cells = <1>; | ||
171 | #size-cells = <0>; | ||
172 | |||
173 | cpsw_port1: port@1 { | ||
174 | reg = <1>; | ||
175 | ti,mac-only; | ||
176 | label = "port1"; | ||
177 | ti,syscon-efuse = <&mcu_conf 0x200>; | ||
178 | phys = <&phy_gmii_sel 1>; | ||
179 | }; | ||
180 | }; | ||
181 | |||
182 | davinci_mdio: mdio@f00 { | ||
183 | compatible = "ti,cpsw-mdio","ti,davinci_mdio"; | ||
184 | reg = <0x0 0xf00 0x0 0x100>; | ||
185 | #address-cells = <1>; | ||
186 | #size-cells = <0>; | ||
187 | clocks = <&k3_clks 18 21>; | ||
188 | clock-names = "fck"; | ||
189 | bus_freq = <1000000>; | ||
190 | }; | ||
191 | |||
192 | cpts@3d000 { | ||
193 | compatible = "ti,am65-cpts"; | ||
194 | reg = <0x0 0x3d000 0x0 0x400>; | ||
195 | clocks = <&k3_clks 18 2>; | ||
196 | clock-names = "cpts"; | ||
197 | interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>; | ||
198 | interrupt-names = "cpts"; | ||
199 | ti,cpts-ext-ts-inputs = <4>; | ||
200 | ti,cpts-periodic-outputs = <2>; | ||
201 | }; | ||
202 | }; | ||
84 | }; | 203 | }; |
diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile index 9a29a107e374..0c67254caee6 100644 --- a/drivers/dma/ti/Makefile +++ b/drivers/dma/ti/Makefile | |||
@@ -4,5 +4,8 @@ obj-$(CONFIG_TI_EDMA) += edma.o | |||
4 | obj-$(CONFIG_DMA_OMAP) += omap-dma.o | 4 | obj-$(CONFIG_DMA_OMAP) += omap-dma.o |
5 | obj-$(CONFIG_TI_K3_UDMA) += k3-udma.o | 5 | obj-$(CONFIG_TI_K3_UDMA) += k3-udma.o |
6 | obj-$(CONFIG_TI_K3_UDMA_GLUE_LAYER) += k3-udma-glue.o | 6 | obj-$(CONFIG_TI_K3_UDMA_GLUE_LAYER) += k3-udma-glue.o |
7 | obj-$(CONFIG_TI_K3_PSIL) += k3-psil.o k3-psil-am654.o k3-psil-j721e.o | 7 | obj-$(CONFIG_TI_K3_PSIL) += k3-psil.o \ |
8 | k3-psil-am654.o \ | ||
9 | k3-psil-j721e.o \ | ||
10 | k3-psil-j7200.o | ||
8 | obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o | 11 | obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o |
diff --git a/drivers/dma/ti/k3-psil-j7200.c b/drivers/dma/ti/k3-psil-j7200.c new file mode 100644 index 000000000000..19a71bd2be61 --- /dev/null +++ b/drivers/dma/ti/k3-psil-j7200.c | |||
@@ -0,0 +1,172 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com | ||
4 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | |||
9 | #include "k3-psil-priv.h" | ||
10 | |||
11 | #define PSIL_PDMA_XY_TR(x) \ | ||
12 | { \ | ||
13 | .thread_id = x, \ | ||
14 | .ep_config = { \ | ||
15 | .ep_type = PSIL_EP_PDMA_XY, \ | ||
16 | }, \ | ||
17 | } | ||
18 | |||
19 | #define PSIL_PDMA_XY_PKT(x) \ | ||
20 | { \ | ||
21 | .thread_id = x, \ | ||
22 | .ep_config = { \ | ||
23 | .ep_type = PSIL_EP_PDMA_XY, \ | ||
24 | .pkt_mode = 1, \ | ||
25 | }, \ | ||
26 | } | ||
27 | |||
28 | #define PSIL_PDMA_MCASP(x) \ | ||
29 | { \ | ||
30 | .thread_id = x, \ | ||
31 | .ep_config = { \ | ||
32 | .ep_type = PSIL_EP_PDMA_XY, \ | ||
33 | .pdma_acc32 = 1, \ | ||
34 | .pdma_burst = 1, \ | ||
35 | }, \ | ||
36 | } | ||
37 | |||
38 | #define PSIL_ETHERNET(x) \ | ||
39 | { \ | ||
40 | .thread_id = x, \ | ||
41 | .ep_config = { \ | ||
42 | .ep_type = PSIL_EP_NATIVE, \ | ||
43 | .pkt_mode = 1, \ | ||
44 | .needs_epib = 1, \ | ||
45 | .psd_size = 16, \ | ||
46 | }, \ | ||
47 | } | ||
48 | |||
49 | #define PSIL_SA2UL(x, tx) \ | ||
50 | { \ | ||
51 | .thread_id = x, \ | ||
52 | .ep_config = { \ | ||
53 | .ep_type = PSIL_EP_NATIVE, \ | ||
54 | .pkt_mode = 1, \ | ||
55 | .needs_epib = 1, \ | ||
56 | .psd_size = 64, \ | ||
57 | .notdpkt = tx, \ | ||
58 | }, \ | ||
59 | } | ||
60 | |||
61 | /* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ | ||
62 | static struct psil_ep j7200_src_ep_map[] = { | ||
63 | /* PDMA_MCASP - McASP0-2 */ | ||
64 | PSIL_PDMA_MCASP(0x4400), | ||
65 | PSIL_PDMA_MCASP(0x4401), | ||
66 | PSIL_PDMA_MCASP(0x4402), | ||
67 | /* PDMA_SPI_G0 - SPI0-3 */ | ||
68 | PSIL_PDMA_XY_PKT(0x4600), | ||
69 | PSIL_PDMA_XY_PKT(0x4601), | ||
70 | PSIL_PDMA_XY_PKT(0x4602), | ||
71 | PSIL_PDMA_XY_PKT(0x4603), | ||
72 | PSIL_PDMA_XY_PKT(0x4604), | ||
73 | PSIL_PDMA_XY_PKT(0x4605), | ||
74 | PSIL_PDMA_XY_PKT(0x4606), | ||
75 | PSIL_PDMA_XY_PKT(0x4607), | ||
76 | PSIL_PDMA_XY_PKT(0x4608), | ||
77 | PSIL_PDMA_XY_PKT(0x4609), | ||
78 | PSIL_PDMA_XY_PKT(0x460a), | ||
79 | PSIL_PDMA_XY_PKT(0x460b), | ||
80 | PSIL_PDMA_XY_PKT(0x460c), | ||
81 | PSIL_PDMA_XY_PKT(0x460d), | ||
82 | PSIL_PDMA_XY_PKT(0x460e), | ||
83 | PSIL_PDMA_XY_PKT(0x460f), | ||
84 | /* PDMA_SPI_G1 - SPI4-7 */ | ||
85 | PSIL_PDMA_XY_PKT(0x4610), | ||
86 | PSIL_PDMA_XY_PKT(0x4611), | ||
87 | PSIL_PDMA_XY_PKT(0x4612), | ||
88 | PSIL_PDMA_XY_PKT(0x4613), | ||
89 | PSIL_PDMA_XY_PKT(0x4614), | ||
90 | PSIL_PDMA_XY_PKT(0x4615), | ||
91 | PSIL_PDMA_XY_PKT(0x4616), | ||
92 | PSIL_PDMA_XY_PKT(0x4617), | ||
93 | PSIL_PDMA_XY_PKT(0x4618), | ||
94 | PSIL_PDMA_XY_PKT(0x4619), | ||
95 | PSIL_PDMA_XY_PKT(0x461a), | ||
96 | PSIL_PDMA_XY_PKT(0x461b), | ||
97 | PSIL_PDMA_XY_PKT(0x461c), | ||
98 | PSIL_PDMA_XY_PKT(0x461d), | ||
99 | PSIL_PDMA_XY_PKT(0x461e), | ||
100 | PSIL_PDMA_XY_PKT(0x461f), | ||
101 | /* PDMA_USART_G0 - UART0-1 */ | ||
102 | PSIL_PDMA_XY_PKT(0x4700), | ||
103 | PSIL_PDMA_XY_PKT(0x4701), | ||
104 | /* PDMA_USART_G1 - UART2-3 */ | ||
105 | PSIL_PDMA_XY_PKT(0x4702), | ||
106 | PSIL_PDMA_XY_PKT(0x4703), | ||
107 | /* PDMA_USART_G2 - UART4-9 */ | ||
108 | PSIL_PDMA_XY_PKT(0x4704), | ||
109 | PSIL_PDMA_XY_PKT(0x4705), | ||
110 | PSIL_PDMA_XY_PKT(0x4706), | ||
111 | PSIL_PDMA_XY_PKT(0x4707), | ||
112 | PSIL_PDMA_XY_PKT(0x4708), | ||
113 | PSIL_PDMA_XY_PKT(0x4709), | ||
114 | /* CPSW5 */ | ||
115 | PSIL_ETHERNET(0x4a00), | ||
116 | /* CPSW0 */ | ||
117 | PSIL_ETHERNET(0x7000), | ||
118 | /* MCU_PDMA_MISC_G0 - SPI0 */ | ||
119 | PSIL_PDMA_XY_PKT(0x7100), | ||
120 | PSIL_PDMA_XY_PKT(0x7101), | ||
121 | PSIL_PDMA_XY_PKT(0x7102), | ||
122 | PSIL_PDMA_XY_PKT(0x7103), | ||
123 | /* MCU_PDMA_MISC_G1 - SPI1-2 */ | ||
124 | PSIL_PDMA_XY_PKT(0x7200), | ||
125 | PSIL_PDMA_XY_PKT(0x7201), | ||
126 | PSIL_PDMA_XY_PKT(0x7202), | ||
127 | PSIL_PDMA_XY_PKT(0x7203), | ||
128 | PSIL_PDMA_XY_PKT(0x7204), | ||
129 | PSIL_PDMA_XY_PKT(0x7205), | ||
130 | PSIL_PDMA_XY_PKT(0x7206), | ||
131 | PSIL_PDMA_XY_PKT(0x7207), | ||
132 | /* MCU_PDMA_MISC_G2 - UART0 */ | ||
133 | PSIL_PDMA_XY_PKT(0x7300), | ||
134 | /* MCU_PDMA_ADC - ADC0-1 */ | ||
135 | PSIL_PDMA_XY_TR(0x7400), | ||
136 | PSIL_PDMA_XY_TR(0x7401), | ||
137 | /* SA2UL */ | ||
138 | PSIL_SA2UL(0x7500, 0), | ||
139 | PSIL_SA2UL(0x7501, 0), | ||
140 | }; | ||
141 | |||
142 | /* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ | ||
143 | static struct psil_ep j7200_dst_ep_map[] = { | ||
144 | /* CPSW5 */ | ||
145 | PSIL_ETHERNET(0xca00), | ||
146 | PSIL_ETHERNET(0xca01), | ||
147 | PSIL_ETHERNET(0xca02), | ||
148 | PSIL_ETHERNET(0xca03), | ||
149 | PSIL_ETHERNET(0xca04), | ||
150 | PSIL_ETHERNET(0xca05), | ||
151 | PSIL_ETHERNET(0xca06), | ||
152 | PSIL_ETHERNET(0xca07), | ||
153 | /* CPSW0 */ | ||
154 | PSIL_ETHERNET(0xf000), | ||
155 | PSIL_ETHERNET(0xf001), | ||
156 | PSIL_ETHERNET(0xf002), | ||
157 | PSIL_ETHERNET(0xf003), | ||
158 | PSIL_ETHERNET(0xf004), | ||
159 | PSIL_ETHERNET(0xf005), | ||
160 | PSIL_ETHERNET(0xf006), | ||
161 | PSIL_ETHERNET(0xf007), | ||
162 | /* SA2UL */ | ||
163 | PSIL_SA2UL(0xf500, 1), | ||
164 | }; | ||
165 | |||
166 | struct psil_ep_map j7200_ep_map = { | ||
167 | .name = "j7200", | ||
168 | .src = j7200_src_ep_map, | ||
169 | .src_count = ARRAY_SIZE(j7200_src_ep_map), | ||
170 | .dst = j7200_dst_ep_map, | ||
171 | .dst_count = ARRAY_SIZE(j7200_dst_ep_map), | ||
172 | }; | ||
diff --git a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h index a1f389ca371e..b4b0fb359eff 100644 --- a/drivers/dma/ti/k3-psil-priv.h +++ b/drivers/dma/ti/k3-psil-priv.h | |||
@@ -39,5 +39,6 @@ struct psil_endpoint_config *psil_get_ep_config(u32 thread_id); | |||
39 | /* SoC PSI-L endpoint maps */ | 39 | /* SoC PSI-L endpoint maps */ |
40 | extern struct psil_ep_map am654_ep_map; | 40 | extern struct psil_ep_map am654_ep_map; |
41 | extern struct psil_ep_map j721e_ep_map; | 41 | extern struct psil_ep_map j721e_ep_map; |
42 | extern struct psil_ep_map j7200_ep_map; | ||
42 | 43 | ||
43 | #endif /* K3_PSIL_PRIV_H_ */ | 44 | #endif /* K3_PSIL_PRIV_H_ */ |
diff --git a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c index 860a999b2aec..b687f0f96097 100644 --- a/drivers/dma/ti/k3-psil.c +++ b/drivers/dma/ti/k3-psil.c | |||
@@ -19,6 +19,7 @@ static const struct psil_ep_map *soc_ep_map; | |||
19 | static const struct soc_device_attribute k3_soc_devices[] = { | 19 | static const struct soc_device_attribute k3_soc_devices[] = { |
20 | { .family = "AM65X", .data = &am654_ep_map }, | 20 | { .family = "AM65X", .data = &am654_ep_map }, |
21 | { .family = "J721E", .data = &j721e_ep_map }, | 21 | { .family = "J721E", .data = &j721e_ep_map }, |
22 | { .family = "J7200", .data = &j7200_ep_map }, | ||
22 | { /* sentinel */ } | 23 | { /* sentinel */ } |
23 | }; | 24 | }; |
24 | 25 | ||
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 562c8317e3aa..eeac2547d5e5 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c | |||
@@ -1366,6 +1366,9 @@ static void m_can_stop(struct net_device *dev) | |||
1366 | /* disable all interrupts */ | 1366 | /* disable all interrupts */ |
1367 | m_can_disable_all_interrupts(cdev); | 1367 | m_can_disable_all_interrupts(cdev); |
1368 | 1368 | ||
1369 | /* Set init mode to disengage from the network */ | ||
1370 | m_can_config_endisable(cdev, true); | ||
1371 | |||
1369 | /* set the state as STOPPED */ | 1372 | /* set the state as STOPPED */ |
1370 | cdev->can.state = CAN_STATE_STOPPED; | 1373 | cdev->can.state = CAN_STATE_STOPPED; |
1371 | } | 1374 | } |
diff --git a/drivers/net/ethernet/ti/icss_switch.h b/drivers/net/ethernet/ti/icss_switch.h index 6b0ffe9895d8..173d710869a2 100644 --- a/drivers/net/ethernet/ti/icss_switch.h +++ b/drivers/net/ethernet/ti/icss_switch.h | |||
@@ -89,6 +89,9 @@ | |||
89 | #define PRUETH_BD_SHADOW_MASK BIT(14) | 89 | #define PRUETH_BD_SHADOW_MASK BIT(14) |
90 | #define PRUETH_BD_SHADOW_SHIFT 14 | 90 | #define PRUETH_BD_SHADOW_SHIFT 14 |
91 | 91 | ||
92 | #define PRUETH_BD_TIMESTAMP_MASK BIT(15) | ||
93 | #define PRUETH_BD_TIMESTAMP_SHIT 15 | ||
94 | |||
92 | #define PRUETH_BD_PORT_MASK GENMASK(17, 16) | 95 | #define PRUETH_BD_PORT_MASK GENMASK(17, 16) |
93 | #define PRUETH_BD_PORT_SHIFT 16 | 96 | #define PRUETH_BD_PORT_SHIFT 16 |
94 | 97 | ||
diff --git a/drivers/net/ethernet/ti/prueth.h b/drivers/net/ethernet/ti/prueth.h index a345f172ac52..ab6fcfe769cb 100644 --- a/drivers/net/ethernet/ti/prueth.h +++ b/drivers/net/ethernet/ti/prueth.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <net/lredev.h> | 14 | #include <net/lredev.h> |
15 | 15 | ||
16 | #include "icss_switch.h" | 16 | #include "icss_switch.h" |
17 | #include "prueth_ptp.h" | ||
17 | 18 | ||
18 | #define PRUETH_NUMQUEUES 5 | 19 | #define PRUETH_NUMQUEUES 5 |
19 | 20 | ||
@@ -103,6 +104,7 @@ struct prueth_queue_info { | |||
103 | * @sv_frame: indicate if the frame is a SV frame for HSR/PRP | 104 | * @sv_frame: indicate if the frame is a SV frame for HSR/PRP |
104 | * @lookup_success: src mac found in FDB | 105 | * @lookup_success: src mac found in FDB |
105 | * @flood: packet is to be flooded | 106 | * @flood: packet is to be flooded |
107 | * @timstamp: Specifies if timestamp is appended to the packet | ||
106 | */ | 108 | */ |
107 | struct prueth_packet_info { | 109 | struct prueth_packet_info { |
108 | bool start_offset; | 110 | bool start_offset; |
@@ -114,6 +116,7 @@ struct prueth_packet_info { | |||
114 | bool sv_frame; | 116 | bool sv_frame; |
115 | bool lookup_success; | 117 | bool lookup_success; |
116 | bool flood; | 118 | bool flood; |
119 | bool timestamp; | ||
117 | }; | 120 | }; |
118 | 121 | ||
119 | /** | 122 | /** |
@@ -377,6 +380,13 @@ struct prueth_emac { | |||
377 | bool nsp_enabled; | 380 | bool nsp_enabled; |
378 | 381 | ||
379 | int offload_fwd_mark; | 382 | int offload_fwd_mark; |
383 | |||
384 | struct sk_buff *ptp_skb[PRUETH_PTP_TS_EVENTS]; | ||
385 | spinlock_t ptp_skb_lock; /* serialize access */ | ||
386 | int emac_ptp_tx_irq; | ||
387 | int hsr_ptp_tx_irq; | ||
388 | bool ptp_tx_enable; | ||
389 | bool ptp_rx_enable; | ||
380 | }; | 390 | }; |
381 | 391 | ||
382 | struct prueth_ndev_priority { | 392 | struct prueth_ndev_priority { |
@@ -482,6 +492,8 @@ int emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, | |||
482 | const struct prueth_queue_info *rxqueue); | 492 | const struct prueth_queue_info *rxqueue); |
483 | int emac_add_del_vid(struct prueth_emac *emac, | 493 | int emac_add_del_vid(struct prueth_emac *emac, |
484 | bool add, __be16 proto, u16 vid); | 494 | bool add, __be16 proto, u16 vid); |
495 | irqreturn_t prueth_ptp_tx_irq_handle(int irq, void *dev); | ||
496 | irqreturn_t prueth_ptp_tx_irq_work(int irq, void *dev); | ||
485 | 497 | ||
486 | extern const struct prueth_queue_desc queue_descs[][NUM_QUEUES]; | 498 | extern const struct prueth_queue_desc queue_descs[][NUM_QUEUES]; |
487 | 499 | ||
diff --git a/drivers/net/ethernet/ti/prueth_core.c b/drivers/net/ethernet/ti/prueth_core.c index c3576155e93a..2a0176ea6101 100644 --- a/drivers/net/ethernet/ti/prueth_core.c +++ b/drivers/net/ethernet/ti/prueth_core.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/mfd/syscon.h> | 16 | #include <linux/mfd/syscon.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/net_tstamp.h> | ||
18 | #include <linux/of.h> | 19 | #include <linux/of.h> |
19 | #include <linux/of_irq.h> | 20 | #include <linux/of_irq.h> |
20 | #include <linux/of_mdio.h> | 21 | #include <linux/of_mdio.h> |
@@ -22,6 +23,7 @@ | |||
22 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
23 | #include <linux/phy.h> | 24 | #include <linux/phy.h> |
24 | #include <linux/pruss.h> | 25 | #include <linux/pruss.h> |
26 | #include <linux/ptp_classify.h> | ||
25 | #include <linux/regmap.h> | 27 | #include <linux/regmap.h> |
26 | #include <linux/remoteproc.h> | 28 | #include <linux/remoteproc.h> |
27 | #include <net/pkt_cls.h> | 29 | #include <net/pkt_cls.h> |
@@ -151,6 +153,39 @@ static inline void prueth_write_reg(struct prueth *prueth, | |||
151 | writel_relaxed(val, prueth->mem[region].va + reg); | 153 | writel_relaxed(val, prueth->mem[region].va + reg); |
152 | } | 154 | } |
153 | 155 | ||
156 | static inline void prueth_ptp_ts_enable(struct prueth_emac *emac) | ||
157 | { | ||
158 | void __iomem *sram = emac->prueth->mem[PRUETH_MEM_SHARED_RAM].va; | ||
159 | u8 val = 0; | ||
160 | |||
161 | if (emac->ptp_tx_enable) | ||
162 | val = TIMESYNC_CTRL_FORCED_2STEP | TIMESYNC_CTRL_BG_ENABLE; | ||
163 | |||
164 | writeb(val, sram + TIMESYNC_CTRL_VAR_OFFSET); | ||
165 | } | ||
166 | |||
167 | static inline void prueth_ptp_tx_ts_enable(struct prueth_emac *emac, bool enable) | ||
168 | { | ||
169 | emac->ptp_tx_enable = enable; | ||
170 | prueth_ptp_ts_enable(emac); | ||
171 | } | ||
172 | |||
173 | static inline bool prueth_ptp_tx_ts_is_enabled(struct prueth_emac *emac) | ||
174 | { | ||
175 | return !!emac->ptp_tx_enable; | ||
176 | } | ||
177 | |||
178 | static inline void prueth_ptp_rx_ts_enable(struct prueth_emac *emac, bool enable) | ||
179 | { | ||
180 | emac->ptp_rx_enable = enable; | ||
181 | prueth_ptp_ts_enable(emac); | ||
182 | } | ||
183 | |||
184 | static inline bool prueth_ptp_rx_ts_is_enabled(struct prueth_emac *emac) | ||
185 | { | ||
186 | return !!emac->ptp_rx_enable; | ||
187 | } | ||
188 | |||
154 | static inline | 189 | static inline |
155 | void prueth_set_reg(struct prueth *prueth, enum prueth_mem region, | 190 | void prueth_set_reg(struct prueth *prueth, enum prueth_mem region, |
156 | unsigned int reg, u32 mask, u32 set) | 191 | unsigned int reg, u32 mask, u32 set) |
@@ -715,6 +750,205 @@ static irqreturn_t emac_rx_hardirq(int irq, void *dev_id) | |||
715 | return IRQ_HANDLED; | 750 | return IRQ_HANDLED; |
716 | } | 751 | } |
717 | 752 | ||
753 | static u8 prueth_ptp_ts_event_type(struct sk_buff *skb) | ||
754 | { | ||
755 | u8 *msgtype, *data, event_type, changed = 0; | ||
756 | unsigned int offset = 0, ptp_class; | ||
757 | u16 *seqid; | ||
758 | |||
759 | if (eth_hdr(skb)->h_proto == htons(ETH_P_HSR)) { | ||
760 | /* This 6-byte shift is just a trick to skip | ||
761 | * the size of a hsr tag so that the same | ||
762 | * pruptp_ts_msgtype can be re-used to parse | ||
763 | * hsr tagged skbs | ||
764 | */ | ||
765 | skb->data += 6; | ||
766 | changed = 6; | ||
767 | } | ||
768 | |||
769 | ptp_class = ptp_classify_raw(skb); | ||
770 | data = skb->data; | ||
771 | if (ptp_class == PTP_CLASS_NONE) { | ||
772 | event_type = PRUETH_PTP_TS_EVENTS; | ||
773 | goto exit; | ||
774 | } | ||
775 | |||
776 | if (ptp_class & PTP_CLASS_VLAN) | ||
777 | offset += VLAN_HLEN; | ||
778 | |||
779 | switch (ptp_class & PTP_CLASS_PMASK) { | ||
780 | case PTP_CLASS_IPV4: | ||
781 | offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN; | ||
782 | break; | ||
783 | case PTP_CLASS_IPV6: | ||
784 | offset += ETH_HLEN + IP6_HLEN + UDP_HLEN; | ||
785 | break; | ||
786 | case PTP_CLASS_L2: | ||
787 | offset += ETH_HLEN; | ||
788 | break; | ||
789 | default: | ||
790 | return PRUETH_PTP_TS_EVENTS; | ||
791 | } | ||
792 | |||
793 | if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid)) { | ||
794 | event_type = PRUETH_PTP_TS_EVENTS; | ||
795 | goto exit; | ||
796 | } | ||
797 | |||
798 | if (unlikely(ptp_class & PTP_CLASS_V1)) | ||
799 | msgtype = data + offset + OFF_PTP_CONTROL; | ||
800 | else | ||
801 | msgtype = data + offset; | ||
802 | |||
803 | /* | ||
804 | * Treat E2E Delay Req/Resp messages sane as P2P peer delay req/resp | ||
805 | * in driver here since firmware stores timestamps in the same memory | ||
806 | * location for either (since they cannot operate simultaneously | ||
807 | * anyway) | ||
808 | */ | ||
809 | switch (*msgtype & 0xf) { | ||
810 | case PTP_SYNC_MSG_ID: | ||
811 | event_type = PRUETH_PTP_SYNC; | ||
812 | break; | ||
813 | case PTP_DLY_REQ_MSG_ID: | ||
814 | case PTP_PDLY_REQ_MSG_ID: | ||
815 | event_type = PRUETH_PTP_DLY_REQ; | ||
816 | break; | ||
817 | case PTP_DLY_RESP_MSG_ID: | ||
818 | case PTP_PDLY_RSP_MSG_ID: | ||
819 | event_type = PRUETH_PTP_DLY_RESP; | ||
820 | break; | ||
821 | default: | ||
822 | event_type = PRUETH_PTP_TS_EVENTS; | ||
823 | } | ||
824 | |||
825 | exit: | ||
826 | skb->data -= changed; | ||
827 | |||
828 | return event_type; | ||
829 | } | ||
830 | |||
831 | static void prueth_ptp_tx_ts_reset(struct prueth_emac *emac, u8 event) | ||
832 | { | ||
833 | void __iomem *sram = emac->prueth->mem[PRUETH_MEM_SHARED_RAM].va; | ||
834 | u32 ts_notify_offs, ts_offs; | ||
835 | |||
836 | ts_offs = prueth_tx_ts_offs_get(emac->port_id - 1, event); | ||
837 | ts_notify_offs = prueth_tx_ts_notify_offs_get(emac->port_id - 1, event); | ||
838 | |||
839 | writeb(0, sram + ts_notify_offs); | ||
840 | memset_io(sram + ts_offs, 0, sizeof(u64)); | ||
841 | } | ||
842 | |||
843 | static int prueth_ptp_tx_ts_enqueue(struct prueth_emac *emac, struct sk_buff *skb) | ||
844 | { | ||
845 | unsigned long flags; | ||
846 | u8 event; | ||
847 | |||
848 | event = prueth_ptp_ts_event_type(skb); | ||
849 | if (event == PRUETH_PTP_TS_EVENTS) { | ||
850 | netdev_err(emac->ndev, "invalid PTP event\n"); | ||
851 | return -EINVAL; | ||
852 | } | ||
853 | |||
854 | spin_lock_irqsave(&emac->ptp_skb_lock, flags); | ||
855 | if (emac->ptp_skb[event]) { | ||
856 | dev_consume_skb_any(emac->ptp_skb[event]); | ||
857 | prueth_ptp_tx_ts_reset(emac, event); | ||
858 | netdev_warn(emac->ndev, "Dropped event waiting for tx ts.\n"); | ||
859 | } | ||
860 | |||
861 | skb_get(skb); | ||
862 | emac->ptp_skb[event] = skb; | ||
863 | spin_unlock_irqrestore(&emac->ptp_skb_lock, flags); | ||
864 | |||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | irqreturn_t prueth_ptp_tx_irq_handle(int irq, void *dev) | ||
869 | { | ||
870 | struct net_device *ndev = (struct net_device *)dev; | ||
871 | struct prueth_emac *emac = netdev_priv(ndev); | ||
872 | |||
873 | if (unlikely(netif_queue_stopped(ndev))) | ||
874 | netif_wake_queue(ndev); | ||
875 | |||
876 | if (prueth_ptp_tx_ts_is_enabled(emac)) | ||
877 | return IRQ_WAKE_THREAD; | ||
878 | |||
879 | return IRQ_HANDLED; | ||
880 | } | ||
881 | |||
882 | static u64 prueth_ptp_ts_get(struct prueth_emac *emac, u32 ts_offs) | ||
883 | { | ||
884 | void __iomem *sram = emac->prueth->mem[PRUETH_MEM_SHARED_RAM].va; | ||
885 | u64 cycles; | ||
886 | |||
887 | memcpy_fromio(&cycles, sram + ts_offs, sizeof(cycles)); | ||
888 | memset_io(sram + ts_offs, 0, sizeof(cycles)); | ||
889 | |||
890 | return cycles; | ||
891 | } | ||
892 | |||
893 | static void prueth_ptp_tx_ts_get(struct prueth_emac *emac, u8 event) | ||
894 | { | ||
895 | struct skb_shared_hwtstamps ssh; | ||
896 | struct sk_buff *skb; | ||
897 | unsigned long flags; | ||
898 | u64 ns; | ||
899 | |||
900 | /* get the msg from list */ | ||
901 | spin_lock_irqsave(&emac->ptp_skb_lock, flags); | ||
902 | skb = emac->ptp_skb[event]; | ||
903 | emac->ptp_skb[event] = NULL; | ||
904 | spin_unlock_irqrestore(&emac->ptp_skb_lock, flags); | ||
905 | if (!skb) { | ||
906 | /* In case of HSR, tx timestamp may be generated by | ||
907 | * cut-through packets such as SYNC, which does not | ||
908 | * have a corresponding queued tx packet. Such a tx | ||
909 | * timestamp is consumed by the rx port when processing | ||
910 | * the rx timestamp. | ||
911 | */ | ||
912 | if (PRUETH_IS_LRE(emac->prueth)) | ||
913 | return; | ||
914 | |||
915 | netdev_err(emac->ndev, "no tx msg %u found waiting for ts\n", | ||
916 | event); | ||
917 | return; | ||
918 | } | ||
919 | |||
920 | /* get timestamp */ | ||
921 | ns = prueth_ptp_ts_get(emac, | ||
922 | prueth_tx_ts_offs_get(emac->port_id - 1, event)); | ||
923 | memset(&ssh, 0, sizeof(ssh)); | ||
924 | ssh.hwtstamp = ns_to_ktime(ns); | ||
925 | skb_tstamp_tx(skb, &ssh); | ||
926 | |||
927 | dev_consume_skb_any(skb); | ||
928 | } | ||
929 | |||
930 | irqreturn_t prueth_ptp_tx_irq_work(int irq, void *dev) | ||
931 | { | ||
932 | struct prueth_emac *emac = netdev_priv(dev); | ||
933 | u32 ts_notify_offs, ts_notify_mask, i; | ||
934 | void __iomem *sram; | ||
935 | |||
936 | /* get and reset the ts notifications */ | ||
937 | sram = emac->prueth->mem[PRUETH_MEM_SHARED_RAM].va; | ||
938 | for (i = 0; i < PRUETH_PTP_TS_EVENTS; i++) { | ||
939 | ts_notify_offs = prueth_tx_ts_notify_offs_get(emac->port_id - 1, | ||
940 | i); | ||
941 | memcpy_fromio(&ts_notify_mask, sram + ts_notify_offs, | ||
942 | PRUETH_PTP_TS_NOTIFY_SIZE); | ||
943 | memset_io(sram + ts_notify_offs, 0, PRUETH_PTP_TS_NOTIFY_SIZE); | ||
944 | |||
945 | if (ts_notify_mask & PRUETH_PTP_TS_NOTIFY_MASK) | ||
946 | prueth_ptp_tx_ts_get(emac, i); | ||
947 | } | ||
948 | |||
949 | return IRQ_HANDLED; | ||
950 | } | ||
951 | |||
718 | /** | 952 | /** |
719 | * prueth_tx_enqueue - queue a packet to firmware for transmission | 953 | * prueth_tx_enqueue - queue a packet to firmware for transmission |
720 | * | 954 | * |
@@ -829,6 +1063,12 @@ static int prueth_tx_enqueue(struct prueth_emac *emac, struct sk_buff *skb, | |||
829 | memcpy(dst_addr, src_addr, pktlen); | 1063 | memcpy(dst_addr, src_addr, pktlen); |
830 | } | 1064 | } |
831 | 1065 | ||
1066 | if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && | ||
1067 | prueth_ptp_tx_ts_is_enabled(emac)) { | ||
1068 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | ||
1069 | prueth_ptp_tx_ts_enqueue(emac, skb); | ||
1070 | } | ||
1071 | |||
832 | /* update first buffer descriptor */ | 1072 | /* update first buffer descriptor */ |
833 | wr_buf_desc = (pktlen << PRUETH_BD_LENGTH_SHIFT) & PRUETH_BD_LENGTH_MASK; | 1073 | wr_buf_desc = (pktlen << PRUETH_BD_LENGTH_SHIFT) & PRUETH_BD_LENGTH_MASK; |
834 | if (PRUETH_IS_HSR(prueth)) | 1074 | if (PRUETH_IS_HSR(prueth)) |
@@ -882,6 +1122,7 @@ void parse_packet_info(struct prueth *prueth, u32 buffer_descriptor, | |||
882 | pkt_info->lookup_success = !!(buffer_descriptor & | 1122 | pkt_info->lookup_success = !!(buffer_descriptor & |
883 | PRUETH_BD_LOOKUP_SUCCESS_MASK); | 1123 | PRUETH_BD_LOOKUP_SUCCESS_MASK); |
884 | pkt_info->flood = !!(buffer_descriptor & PRUETH_BD_SW_FLOOD_MASK); | 1124 | pkt_info->flood = !!(buffer_descriptor & PRUETH_BD_SW_FLOOD_MASK); |
1125 | pkt_info->timestamp = !!(buffer_descriptor & PRUETH_BD_TIMESTAMP_MASK); | ||
885 | } | 1126 | } |
886 | 1127 | ||
887 | /* get packet from queue | 1128 | /* get packet from queue |
@@ -904,9 +1145,11 @@ int emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, | |||
904 | u8 macid[6]; | 1145 | u8 macid[6]; |
905 | /* OCMC RAM is not cached and read order is not important */ | 1146 | /* OCMC RAM is not cached and read order is not important */ |
906 | void *ocmc_ram = (__force void *)emac->prueth->mem[PRUETH_MEM_OCMC].va; | 1147 | void *ocmc_ram = (__force void *)emac->prueth->mem[PRUETH_MEM_OCMC].va; |
1148 | struct skb_shared_hwtstamps *ssh; | ||
907 | unsigned int actual_pkt_len; | 1149 | unsigned int actual_pkt_len; |
908 | u16 start_offset = 0, type; | 1150 | u16 start_offset = 0, type; |
909 | u8 offset = 0, *ptr; | 1151 | u8 offset = 0, *ptr; |
1152 | u64 ts; | ||
910 | 1153 | ||
911 | if (PRUETH_IS_HSR(prueth)) | 1154 | if (PRUETH_IS_HSR(prueth)) |
912 | start_offset = (pkt_info.start_offset ? | 1155 | start_offset = (pkt_info.start_offset ? |
@@ -989,8 +1232,16 @@ int emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, | |||
989 | else | 1232 | else |
990 | src_addr = ocmc_ram + rxqueue->buffer_offset; | 1233 | src_addr = ocmc_ram + rxqueue->buffer_offset; |
991 | memcpy(dst_addr, src_addr, remaining); | 1234 | memcpy(dst_addr, src_addr, remaining); |
1235 | src_addr += remaining; | ||
992 | } else { | 1236 | } else { |
993 | memcpy(dst_addr, src_addr, actual_pkt_len); | 1237 | memcpy(dst_addr, src_addr, actual_pkt_len); |
1238 | src_addr += actual_pkt_len; | ||
1239 | } | ||
1240 | |||
1241 | if (pkt_info.timestamp) { | ||
1242 | src_addr = (void *)roundup((uintptr_t)src_addr, ICSS_BLOCK_SIZE); | ||
1243 | dst_addr = &ts; | ||
1244 | memcpy(dst_addr, src_addr, sizeof(ts)); | ||
994 | } | 1245 | } |
995 | 1246 | ||
996 | /* Check if VLAN tag is present since SV payload location will change | 1247 | /* Check if VLAN tag is present since SV payload location will change |
@@ -1000,6 +1251,7 @@ int emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, | |||
1000 | ptr = nt_dst_addr + PRUETH_ETH_TYPE_OFFSET; | 1251 | ptr = nt_dst_addr + PRUETH_ETH_TYPE_OFFSET; |
1001 | type = (*ptr++) << PRUETH_ETH_TYPE_UPPER_SHIFT; | 1252 | type = (*ptr++) << PRUETH_ETH_TYPE_UPPER_SHIFT; |
1002 | type |= *ptr++; | 1253 | type |= *ptr++; |
1254 | eth_hdr(skb)->h_proto = htons(type); | ||
1003 | if (type == ETH_P_8021Q) | 1255 | if (type == ETH_P_8021Q) |
1004 | offset = 4; | 1256 | offset = 4; |
1005 | } | 1257 | } |
@@ -1047,6 +1299,12 @@ int emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr, | |||
1047 | prueth_sw_learn_fdb(emac, skb->data + ETH_ALEN); | 1299 | prueth_sw_learn_fdb(emac, skb->data + ETH_ALEN); |
1048 | } | 1300 | } |
1049 | 1301 | ||
1302 | if (prueth_ptp_rx_ts_is_enabled(emac)) { | ||
1303 | ssh = skb_hwtstamps(skb); | ||
1304 | memset(ssh, 0, sizeof(*ssh)); | ||
1305 | ssh->hwtstamp = ns_to_ktime(ts); | ||
1306 | } | ||
1307 | |||
1050 | /* send packet up the stack */ | 1308 | /* send packet up the stack */ |
1051 | skb->protocol = eth_type_trans(skb, ndev); | 1309 | skb->protocol = eth_type_trans(skb, ndev); |
1052 | netif_receive_skb(skb); | 1310 | netif_receive_skb(skb); |
@@ -1266,6 +1524,30 @@ static int emac_request_irqs(struct prueth_emac *emac) | |||
1266 | return ret; | 1524 | return ret; |
1267 | } | 1525 | } |
1268 | 1526 | ||
1527 | if (PRUETH_IS_EMAC(emac->prueth) && emac->tx_irq > 0) { | ||
1528 | ret = request_irq(emac->tx_irq, emac_tx_hardirq, | ||
1529 | IRQF_TRIGGER_HIGH, ndev->name, ndev); | ||
1530 | if (ret) { | ||
1531 | netdev_err(ndev, "unable to request TX IRQ\n"); | ||
1532 | free_irq(emac->rx_irq, ndev); | ||
1533 | return ret; | ||
1534 | } | ||
1535 | } | ||
1536 | |||
1537 | if (emac->emac_ptp_tx_irq) { | ||
1538 | ret = request_threaded_irq(emac->emac_ptp_tx_irq, | ||
1539 | prueth_ptp_tx_irq_handle, | ||
1540 | prueth_ptp_tx_irq_work, | ||
1541 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
1542 | ndev->name, ndev); | ||
1543 | if (ret) { | ||
1544 | netdev_err(ndev, "unable to request PTP TX IRQ\n"); | ||
1545 | free_irq(emac->rx_irq, ndev); | ||
1546 | free_irq(emac->tx_irq, ndev); | ||
1547 | } | ||
1548 | |||
1549 | } | ||
1550 | |||
1269 | return ret; | 1551 | return ret; |
1270 | } | 1552 | } |
1271 | 1553 | ||
@@ -1395,15 +1677,6 @@ static int emac_ndo_open(struct net_device *ndev) | |||
1395 | } | 1677 | } |
1396 | } | 1678 | } |
1397 | 1679 | ||
1398 | if (PRUETH_IS_EMAC(prueth) && emac->tx_irq > 0) { | ||
1399 | ret = request_irq(emac->tx_irq, emac_tx_hardirq, | ||
1400 | IRQF_TRIGGER_HIGH, ndev->name, ndev); | ||
1401 | if (ret) { | ||
1402 | netdev_err(ndev, "unable to request TX IRQ\n"); | ||
1403 | goto free_rx_irq; | ||
1404 | } | ||
1405 | } | ||
1406 | |||
1407 | /* start PHY */ | 1680 | /* start PHY */ |
1408 | phy_start(emac->phydev); | 1681 | phy_start(emac->phydev); |
1409 | 1682 | ||
@@ -1425,8 +1698,6 @@ static int emac_ndo_open(struct net_device *ndev) | |||
1425 | 1698 | ||
1426 | return 0; | 1699 | return 0; |
1427 | 1700 | ||
1428 | free_rx_irq: | ||
1429 | free_irq(emac->rx_irq, ndev); | ||
1430 | rproc_shutdown: | 1701 | rproc_shutdown: |
1431 | if (!PRUETH_IS_EMAC(prueth)) | 1702 | if (!PRUETH_IS_EMAC(prueth)) |
1432 | prueth_sw_shutdown_prus(emac, ndev); | 1703 | prueth_sw_shutdown_prus(emac, ndev); |
@@ -1452,6 +1723,7 @@ static int emac_ndo_stop(struct net_device *ndev) | |||
1452 | { | 1723 | { |
1453 | struct prueth_emac *emac = netdev_priv(ndev); | 1724 | struct prueth_emac *emac = netdev_priv(ndev); |
1454 | struct prueth *prueth = emac->prueth; | 1725 | struct prueth *prueth = emac->prueth; |
1726 | int i; | ||
1455 | 1727 | ||
1456 | mutex_lock(&prueth->mlock); | 1728 | mutex_lock(&prueth->mlock); |
1457 | prueth->emac_configured &= ~BIT(emac->port_id); | 1729 | prueth->emac_configured &= ~BIT(emac->port_id); |
@@ -1499,6 +1771,16 @@ static int emac_ndo_stop(struct net_device *ndev) | |||
1499 | */ | 1771 | */ |
1500 | if (PRUETH_IS_EMAC(emac->prueth) || PRUETH_IS_SWITCH(prueth)) { | 1772 | if (PRUETH_IS_EMAC(emac->prueth) || PRUETH_IS_SWITCH(prueth)) { |
1501 | free_irq(emac->rx_irq, ndev); | 1773 | free_irq(emac->rx_irq, ndev); |
1774 | free_irq(emac->emac_ptp_tx_irq, ndev); | ||
1775 | prueth_ptp_tx_ts_enable(emac, 0); | ||
1776 | prueth_ptp_rx_ts_enable(emac, 0); | ||
1777 | for (i = 0; i < PRUETH_PTP_TS_EVENTS; i++) { | ||
1778 | if (emac->ptp_skb[i]) { | ||
1779 | prueth_ptp_tx_ts_reset(emac, i); | ||
1780 | dev_consume_skb_any(emac->ptp_skb[i]); | ||
1781 | emac->ptp_skb[i] = NULL; | ||
1782 | } | ||
1783 | } | ||
1502 | } else { | 1784 | } else { |
1503 | /* Free interrupts on last port */ | 1785 | /* Free interrupts on last port */ |
1504 | prueth_lre_free_irqs(emac); | 1786 | prueth_lre_free_irqs(emac); |
@@ -1900,10 +2182,74 @@ unlock: | |||
1900 | spin_unlock_irqrestore(&emac->addr_lock, flags); | 2182 | spin_unlock_irqrestore(&emac->addr_lock, flags); |
1901 | } | 2183 | } |
1902 | 2184 | ||
2185 | static int emac_hwtstamp_config_set(struct net_device *ndev, struct ifreq *ifr) | ||
2186 | { | ||
2187 | struct prueth_emac *emac = netdev_priv(ndev); | ||
2188 | struct hwtstamp_config cfg; | ||
2189 | |||
2190 | if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) | ||
2191 | return -EFAULT; | ||
2192 | |||
2193 | /* reserved for future extensions */ | ||
2194 | if (cfg.flags) | ||
2195 | return -EINVAL; | ||
2196 | |||
2197 | if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON) | ||
2198 | return -ERANGE; | ||
2199 | |||
2200 | switch (cfg.rx_filter) { | ||
2201 | case HWTSTAMP_FILTER_NONE: | ||
2202 | prueth_ptp_rx_ts_enable(emac, 0); | ||
2203 | break; | ||
2204 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||
2205 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||
2206 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: | ||
2207 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | ||
2208 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: | ||
2209 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: | ||
2210 | case HWTSTAMP_FILTER_PTP_V2_EVENT: | ||
2211 | case HWTSTAMP_FILTER_PTP_V2_SYNC: | ||
2212 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: | ||
2213 | prueth_ptp_rx_ts_enable(emac, 1); | ||
2214 | cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; | ||
2215 | break; | ||
2216 | case HWTSTAMP_FILTER_ALL: | ||
2217 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: | ||
2218 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
2219 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
2220 | default: | ||
2221 | return -ERANGE; | ||
2222 | } | ||
2223 | |||
2224 | prueth_ptp_tx_ts_enable(emac, cfg.tx_type == HWTSTAMP_TX_ON); | ||
2225 | |||
2226 | return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; | ||
2227 | } | ||
2228 | static int emac_hwtstamp_config_get(struct net_device *ndev, struct ifreq *ifr) | ||
2229 | { | ||
2230 | struct prueth_emac *emac = netdev_priv(ndev); | ||
2231 | struct hwtstamp_config cfg; | ||
2232 | |||
2233 | cfg.flags = 0; | ||
2234 | cfg.tx_type = prueth_ptp_tx_ts_is_enabled(emac) ? | ||
2235 | HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; | ||
2236 | cfg.rx_filter = prueth_ptp_rx_ts_is_enabled(emac) ? | ||
2237 | HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE; | ||
2238 | |||
2239 | return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; | ||
2240 | } | ||
2241 | |||
1903 | static int emac_ndo_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) | 2242 | static int emac_ndo_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) |
1904 | { | 2243 | { |
1905 | struct prueth_emac *emac = netdev_priv(ndev); | 2244 | struct prueth_emac *emac = netdev_priv(ndev); |
1906 | 2245 | ||
2246 | switch (cmd) { | ||
2247 | case SIOCSHWTSTAMP: | ||
2248 | return emac_hwtstamp_config_set(ndev, ifr); | ||
2249 | case SIOCGHWTSTAMP: | ||
2250 | return emac_hwtstamp_config_get(ndev, ifr); | ||
2251 | } | ||
2252 | |||
1907 | return phy_mii_ioctl(emac->phydev, ifr, cmd); | 2253 | return phy_mii_ioctl(emac->phydev, ifr, cmd); |
1908 | } | 2254 | } |
1909 | 2255 | ||
@@ -2304,13 +2650,37 @@ static void emac_get_regs(struct net_device *ndev, struct ethtool_regs *regs, | |||
2304 | } | 2650 | } |
2305 | } | 2651 | } |
2306 | 2652 | ||
2653 | static int emac_get_ts_info(struct net_device *ndev, | ||
2654 | struct ethtool_ts_info *info) | ||
2655 | { | ||
2656 | struct prueth_emac *emac = netdev_priv(ndev); | ||
2657 | |||
2658 | if ((PRUETH_IS_EMAC(emac->prueth) && !emac->emac_ptp_tx_irq) || | ||
2659 | (PRUETH_IS_LRE(emac->prueth) && !emac->hsr_ptp_tx_irq)) | ||
2660 | return ethtool_op_get_ts_info(ndev, info); | ||
2661 | |||
2662 | info->so_timestamping = | ||
2663 | SOF_TIMESTAMPING_TX_HARDWARE | | ||
2664 | SOF_TIMESTAMPING_TX_SOFTWARE | | ||
2665 | SOF_TIMESTAMPING_RX_HARDWARE | | ||
2666 | SOF_TIMESTAMPING_RX_SOFTWARE | | ||
2667 | SOF_TIMESTAMPING_SOFTWARE | | ||
2668 | SOF_TIMESTAMPING_RAW_HARDWARE; | ||
2669 | |||
2670 | info->phc_index = ptp_clock_index(icss_iep_get_ptp_clock(emac->prueth->iep)); | ||
2671 | info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); | ||
2672 | info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); | ||
2673 | |||
2674 | return 0; | ||
2675 | } | ||
2676 | |||
2307 | /* Ethtool support for EMAC adapter */ | 2677 | /* Ethtool support for EMAC adapter */ |
2308 | static const struct ethtool_ops emac_ethtool_ops = { | 2678 | static const struct ethtool_ops emac_ethtool_ops = { |
2309 | .get_drvinfo = emac_get_drvinfo, | 2679 | .get_drvinfo = emac_get_drvinfo, |
2310 | .get_link_ksettings = emac_get_link_ksettings, | 2680 | .get_link_ksettings = emac_get_link_ksettings, |
2311 | .set_link_ksettings = emac_set_link_ksettings, | 2681 | .set_link_ksettings = emac_set_link_ksettings, |
2312 | .get_link = ethtool_op_get_link, | 2682 | .get_link = ethtool_op_get_link, |
2313 | .get_ts_info = ethtool_op_get_ts_info, | 2683 | .get_ts_info = emac_get_ts_info, |
2314 | .get_sset_count = emac_get_sset_count, | 2684 | .get_sset_count = emac_get_sset_count, |
2315 | .get_strings = emac_get_strings, | 2685 | .get_strings = emac_get_strings, |
2316 | .get_ethtool_stats = emac_get_ethtool_stats, | 2686 | .get_ethtool_stats = emac_get_ethtool_stats, |
@@ -2410,10 +2780,23 @@ static int prueth_netdev_init(struct prueth *prueth, | |||
2410 | dev_dbg(prueth->dev, "tx irq not configured\n"); | 2780 | dev_dbg(prueth->dev, "tx irq not configured\n"); |
2411 | } | 2781 | } |
2412 | 2782 | ||
2783 | emac->emac_ptp_tx_irq = of_irq_get_byname(eth_node, "emac_ptp_tx"); | ||
2784 | if (emac->emac_ptp_tx_irq < 0) { | ||
2785 | emac->emac_ptp_tx_irq = 0; | ||
2786 | dev_err(prueth->dev, "could not get ptp tx irq. Skipping PTP support\n"); | ||
2787 | } | ||
2788 | |||
2789 | emac->hsr_ptp_tx_irq = of_irq_get_byname(eth_node, "hsr_ptp_tx"); | ||
2790 | if (emac->hsr_ptp_tx_irq < 0) { | ||
2791 | emac->hsr_ptp_tx_irq = 0; | ||
2792 | dev_err(prueth->dev, "could not get hsr ptp tx irq. Skipping PTP support\n"); | ||
2793 | } | ||
2794 | |||
2413 | emac->msg_enable = netif_msg_init(debug_level, PRUETH_EMAC_DEBUG); | 2795 | emac->msg_enable = netif_msg_init(debug_level, PRUETH_EMAC_DEBUG); |
2414 | spin_lock_init(&emac->lock); | 2796 | spin_lock_init(&emac->lock); |
2415 | spin_lock_init(&emac->nsp_lock); | 2797 | spin_lock_init(&emac->nsp_lock); |
2416 | spin_lock_init(&emac->addr_lock); | 2798 | spin_lock_init(&emac->addr_lock); |
2799 | spin_lock_init(&emac->ptp_skb_lock); | ||
2417 | 2800 | ||
2418 | /* get mac address from DT and set private and netdev addr */ | 2801 | /* get mac address from DT and set private and netdev addr */ |
2419 | mac_addr = of_get_mac_address(eth_node); | 2802 | mac_addr = of_get_mac_address(eth_node); |
diff --git a/drivers/net/ethernet/ti/prueth_lre.c b/drivers/net/ethernet/ti/prueth_lre.c index 15ab6b9e2141..275138c09a93 100644 --- a/drivers/net/ethernet/ti/prueth_lre.c +++ b/drivers/net/ethernet/ti/prueth_lre.c | |||
@@ -858,6 +858,19 @@ int prueth_lre_request_irqs(struct prueth_emac *emac) | |||
858 | struct prueth *prueth = emac->prueth; | 858 | struct prueth *prueth = emac->prueth; |
859 | int ret; | 859 | int ret; |
860 | 860 | ||
861 | if (emac->hsr_ptp_tx_irq) { | ||
862 | ret = request_threaded_irq(emac->hsr_ptp_tx_irq, | ||
863 | prueth_ptp_tx_irq_handle, | ||
864 | prueth_ptp_tx_irq_work, | ||
865 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
866 | emac->ndev->name, emac->ndev); | ||
867 | if (ret) { | ||
868 | netdev_err(emac->ndev, "unable to request PTP TX IRQ\n"); | ||
869 | return ret; | ||
870 | } | ||
871 | |||
872 | } | ||
873 | |||
861 | /* HSR/PRP. Request irq when first port is initialized */ | 874 | /* HSR/PRP. Request irq when first port is initialized */ |
862 | if (prueth->emac_configured) | 875 | if (prueth->emac_configured) |
863 | return 0; | 876 | return 0; |
@@ -866,17 +879,24 @@ int prueth_lre_request_irqs(struct prueth_emac *emac) | |||
866 | IRQF_TRIGGER_HIGH, "eth_hp_int", prueth->hp); | 879 | IRQF_TRIGGER_HIGH, "eth_hp_int", prueth->hp); |
867 | if (ret) { | 880 | if (ret) { |
868 | netdev_err(emac->ndev, "unable to request RX HPQ IRQ\n"); | 881 | netdev_err(emac->ndev, "unable to request RX HPQ IRQ\n"); |
869 | return ret; | 882 | goto free_ptp_irq; |
870 | } | 883 | } |
871 | 884 | ||
872 | ret = request_irq(prueth->rx_lpq_irq, prueth_lre_emac_rx_hardirq, | 885 | ret = request_irq(prueth->rx_lpq_irq, prueth_lre_emac_rx_hardirq, |
873 | IRQF_TRIGGER_HIGH, "eth_lp_int", prueth->lp); | 886 | IRQF_TRIGGER_HIGH, "eth_lp_int", prueth->lp); |
874 | if (ret) { | 887 | if (ret) { |
875 | netdev_err(emac->ndev, "unable to request RX LPQ IRQ\n"); | 888 | netdev_err(emac->ndev, "unable to request RX LPQ IRQ\n"); |
876 | free_irq(prueth->rx_hpq_irq, prueth->hp); | 889 | goto free_rx_hpq_irq; |
877 | return ret; | ||
878 | } | 890 | } |
879 | 891 | ||
892 | return 0; | ||
893 | |||
894 | free_rx_hpq_irq: | ||
895 | free_irq(prueth->rx_hpq_irq, prueth->hp); | ||
896 | free_ptp_irq: | ||
897 | if (emac->hsr_ptp_tx_irq) | ||
898 | free_irq(emac->hsr_ptp_tx_irq, emac->ndev); | ||
899 | |||
880 | return ret; | 900 | return ret; |
881 | } | 901 | } |
882 | 902 | ||
diff --git a/drivers/net/ethernet/ti/prueth_ptp.h b/drivers/net/ethernet/ti/prueth_ptp.h new file mode 100644 index 000000000000..03c84ff5dad9 --- /dev/null +++ b/drivers/net/ethernet/ti/prueth_ptp.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com | ||
4 | */ | ||
5 | #ifndef PRUETH_PTP_H | ||
6 | #define PRUETH_PTP_H | ||
7 | |||
8 | #define RX_SYNC_TIMESTAMP_OFFSET_P1 0x8 /* 8 bytes */ | ||
9 | #define RX_PDELAY_REQ_TIMESTAMP_OFFSET_P1 0x14 /* 12 bytes */ | ||
10 | #define RX_PDELAY_RESP_TIMESTAMP_OFFSET_P1 0x20 /* 12 bytes */ | ||
11 | #define RX_SYNC_TIMESTAMP_OFFSET_P2 0x2c /* 12 bytes */ | ||
12 | #define RX_PDELAY_REQ_TIMESTAMP_OFFSET_P2 0x38 /* 12 bytes */ | ||
13 | #define RX_PDELAY_RESP_TIMESTAMP_OFFSET_P2 0x44 /* 12 bytes */ | ||
14 | #define TIMESYNC_DOMAIN_NUMBER_LIST 0x50 /* 2 bytes */ | ||
15 | #define P1_SMA_LINE_DELAY_OFFSET 0x52 /* 4 bytes */ | ||
16 | #define P2_SMA_LINE_DELAY_OFFSET 0x56 /* 4 bytes */ | ||
17 | #define TIMESYNC_SECONDS_COUNT_OFFSET 0x5a /* 6 bytes */ | ||
18 | #define TIMESYNC_TC_RCF_OFFSET 0x60 /* 4 bytes */ | ||
19 | #define DUT_IS_MASTER_OFFSET 0x64 /* 1 byte */ | ||
20 | #define MASTER_PORT_NUM_OFFSET 0x65 /* 1 byte */ | ||
21 | #define SYNC_MASTER_MAC_OFFSET 0x66 /* 6 bytes */ | ||
22 | #define TX_TS_NOTIFICATION_OFFSET_SYNC_P1 0x6c /* 1 byte */ | ||
23 | #define TX_TS_NOTIFICATION_OFFSET_PDEL_REQ_P1 0x6d /* 1 byte */ | ||
24 | #define TX_TS_NOTIFICATION_OFFSET_PDEL_RES_P1 0x6e /* 1 byte */ | ||
25 | #define TX_TS_NOTIFICATION_OFFSET_SYNC_P2 0x6f /* 1 byte */ | ||
26 | #define TX_TS_NOTIFICATION_OFFSET_PDEL_REQ_P2 0x70 /* 1 byte */ | ||
27 | #define TX_TS_NOTIFICATION_OFFSET_PDEL_RES_P2 0x71 /* 1 byte */ | ||
28 | #define TX_SYNC_TIMESTAMP_OFFSET_P1 0x72 /* 12 bytes */ | ||
29 | #define TX_PDELAY_REQ_TIMESTAMP_OFFSET_P1 0x7e /* 12 bytes */ | ||
30 | #define TX_PDELAY_RESP_TIMESTAMP_OFFSET_P1 0x8a /* 12 bytes */ | ||
31 | #define TX_SYNC_TIMESTAMP_OFFSET_P2 0x96 /* 12 bytes */ | ||
32 | #define TX_PDELAY_REQ_TIMESTAMP_OFFSET_P2 0xa2 /* 12 bytes */ | ||
33 | #define TX_PDELAY_RESP_TIMESTAMP_OFFSET_P2 0xae /* 12 bytes */ | ||
34 | #define TIMESYNC_CTRL_VAR_OFFSET 0xba /* 1 byte */ | ||
35 | #define DISABLE_SWITCH_SYNC_RELAY_OFFSET 0xbb /* 1 byte */ | ||
36 | #define MII_RX_CORRECTION_OFFSET 0xbc /* 2 bytes */ | ||
37 | #define MII_TX_CORRECTION_OFFSET 0xbe /* 2 bytes */ | ||
38 | #define TIMESYNC_CMP1_CMP_OFFSET 0xc1 /* 8 bytes */ | ||
39 | #define TIMESYNC_SYNC0_CMP_OFFSET 0xc9 /* 8 bytes */ | ||
40 | #define TIMESYNC_CMP1_PERIOD_OFFSET 0xd1 /* 4 bytes */ | ||
41 | #define TIMESYNC_SYNC0_WIDTH_OFFSET 0xd5 /* 4 bytes */ | ||
42 | #define SINGLE_STEP_IEP_OFFSET_P1 0xd9 /* 8 bytes */ | ||
43 | #define SINGLE_STEP_SECONDS_OFFSET_P1 0xe1 /* 8 bytes */ | ||
44 | #define SINGLE_STEP_IEP_OFFSET_P2 0xe9 /* 8 bytes */ | ||
45 | #define SINGLE_STEP_SECONDS_OFFSET_P2 0xf1 /* 8 bytes */ | ||
46 | #define LINK_LOCAL_FRAME_HAS_HSR_TAG 0xf9 /* 1 bytes */ | ||
47 | #define PTP_PREV_TX_TIMESTAMP_P1 0x101 /* 8 bytes */ | ||
48 | #define PTP_PREV_TX_TIMESTAMP_P2 0x109 /* 8 bytes */ | ||
49 | #define PTP_CLK_IDENTITY_OFFSET 0x111 /* 8 bytes */ | ||
50 | #define PTP_SCRATCH_MEM 0x119 /* 16 byte */ | ||
51 | #define PTP_IPV4_UDP_E2E_ENABLE 0x129 /* 1 byte */ | ||
52 | |||
53 | enum { | ||
54 | PRUETH_PTP_SYNC, | ||
55 | PRUETH_PTP_DLY_REQ, | ||
56 | PRUETH_PTP_DLY_RESP, | ||
57 | PRUETH_PTP_TS_EVENTS, | ||
58 | }; | ||
59 | |||
60 | #define PRUETH_PTP_TS_SIZE 12 | ||
61 | #define PRUETH_PTP_TS_NOTIFY_SIZE 1 | ||
62 | #define PRUETH_PTP_TS_NOTIFY_MASK 0xff | ||
63 | |||
64 | /* Bit definitions for TIMESYNC_CTRL */ | ||
65 | #define TIMESYNC_CTRL_BG_ENABLE BIT(0) | ||
66 | #define TIMESYNC_CTRL_FORCED_2STEP BIT(1) | ||
67 | |||
68 | static inline u32 prueth_tx_ts_offs_get(u8 port, u8 event) | ||
69 | { | ||
70 | return TX_SYNC_TIMESTAMP_OFFSET_P1 + port * | ||
71 | PRUETH_PTP_TS_EVENTS * PRUETH_PTP_TS_SIZE + | ||
72 | event * PRUETH_PTP_TS_SIZE; | ||
73 | } | ||
74 | |||
75 | static inline u32 prueth_tx_ts_notify_offs_get(u8 port, u8 event) | ||
76 | { | ||
77 | return TX_TS_NOTIFICATION_OFFSET_SYNC_P1 + | ||
78 | PRUETH_PTP_TS_EVENTS * PRUETH_PTP_TS_NOTIFY_SIZE * port + | ||
79 | event * PRUETH_PTP_TS_NOTIFY_SIZE; | ||
80 | } | ||
81 | |||
82 | #endif /* PRUETH_PTP_H */ | ||
diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c index eeb2b78eaffc..5d2745b84f81 100644 --- a/drivers/soc/ti/k3-socinfo.c +++ b/drivers/soc/ti/k3-socinfo.c | |||
@@ -40,6 +40,7 @@ static const struct k3_soc_id { | |||
40 | } k3_soc_ids[] = { | 40 | } k3_soc_ids[] = { |
41 | { 0xBB5A, "AM65X" }, | 41 | { 0xBB5A, "AM65X" }, |
42 | { 0xBB64, "J721E" }, | 42 | { 0xBB64, "J721E" }, |
43 | { 0xBB6D, "J7200" }, | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | int __init partno_to_names(unsigned int partno, | 46 | int __init partno_to_names(unsigned int partno, |
diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h index dd00fa41f7e7..dc9420cd4ed3 100644 --- a/include/linux/ptp_classify.h +++ b/include/linux/ptp_classify.h | |||
@@ -34,6 +34,18 @@ | |||
34 | #define PTP_EV_PORT 319 | 34 | #define PTP_EV_PORT 319 |
35 | #define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type */ | 35 | #define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type */ |
36 | 36 | ||
37 | /* PTP message types */ | ||
38 | #define PTP_SYNC_MSG_ID 0x0 | ||
39 | #define PTP_DLY_REQ_MSG_ID 0x1 | ||
40 | #define PTP_PDLY_REQ_MSG_ID 0x2 | ||
41 | #define PTP_PDLY_RSP_MSG_ID 0x3 | ||
42 | #define PTP_FOLLOW_UP_MSG_ID 0x8 | ||
43 | #define PTP_DLY_RESP_MSG_ID 0x9 | ||
44 | #define PTP_PDLY_RESP_FLW_UP_MSG_ID 0xa | ||
45 | #define PTP_ANNOUNCE_MSG_ID 0xb | ||
46 | #define PTP_SIGNAL_MSG_ID 0xc | ||
47 | #define PTP_MGMT_MSG_ID 0xd | ||
48 | |||
37 | #define OFF_PTP_SOURCE_UUID 22 /* PTPv1 only */ | 49 | #define OFF_PTP_SOURCE_UUID 22 /* PTPv1 only */ |
38 | #define OFF_PTP_SEQUENCE_ID 30 | 50 | #define OFF_PTP_SEQUENCE_ID 30 |
39 | #define OFF_PTP_CONTROL 32 /* PTPv1 only */ | 51 | #define OFF_PTP_CONTROL 32 /* PTPv1 only */ |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 542d881978ef..5857872fcd2b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -505,6 +505,27 @@ int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb, | |||
505 | struct msghdr *msg, int len, | 505 | struct msghdr *msg, int len, |
506 | struct ubuf_info *uarg); | 506 | struct ubuf_info *uarg); |
507 | 507 | ||
508 | /* Bit fields of redundant info io_port */ | ||
509 | #define PTP_MSG_IN (0x3 << 6) | ||
510 | #define PTP_EVT_OUT (0x2 << 6) | ||
511 | #define DIRECTED_TX (0x1 << 6) | ||
512 | #define PORT_B BIT(1) | ||
513 | #define PORT_A BIT(0) | ||
514 | |||
515 | struct skb_redundant_info { | ||
516 | __u8 io_port; /* tx/rx port of the skb */ | ||
517 | __u8 pathid; /* pathid in tag */ | ||
518 | __u16 ethertype; /* ethertype in tag */ | ||
519 | __u16 lsdu_size; /* lsdu size in tag */ | ||
520 | __u16 seqnr; /* seqnr in tag */ | ||
521 | }; | ||
522 | |||
523 | #define REDINFO_T(skb) (skb_redinfo(skb)->io_port & (0x3 << 6)) | ||
524 | #define REDINFO_PORTS(skb) (skb_redinfo(skb)->io_port & 0x3) | ||
525 | #define REDINFO_PATHID(skb) (skb_redinfo(skb)->pathid) | ||
526 | #define REDINFO_SEQNR(skb) (skb_redinfo(skb)->seqnr) | ||
527 | #define REDINFO_LSDU_SIZE(skb) (skb_redinfo(skb)->lsdu_size) | ||
528 | |||
508 | /* This data is invariant across clones and lives at | 529 | /* This data is invariant across clones and lives at |
509 | * the end of the header data, ie. at skb->end. | 530 | * the end of the header data, ie. at skb->end. |
510 | */ | 531 | */ |
@@ -519,6 +540,8 @@ struct skb_shared_info { | |||
519 | struct sk_buff *frag_list; | 540 | struct sk_buff *frag_list; |
520 | struct skb_shared_hwtstamps hwtstamps; | 541 | struct skb_shared_hwtstamps hwtstamps; |
521 | unsigned int gso_type; | 542 | unsigned int gso_type; |
543 | struct skb_shared_hwtstamps red_hwtstamps; | ||
544 | struct skb_redundant_info redinfo; | ||
522 | u32 tskey; | 545 | u32 tskey; |
523 | 546 | ||
524 | /* | 547 | /* |
@@ -1489,6 +1512,16 @@ static inline void skb_list_del_init(struct sk_buff *skb) | |||
1489 | __list_del_entry(&skb->list); | 1512 | __list_del_entry(&skb->list); |
1490 | skb_mark_not_on_list(skb); | 1513 | skb_mark_not_on_list(skb); |
1491 | } | 1514 | } |
1515 | static inline struct skb_redundant_info *skb_redinfo(struct sk_buff *skb) | ||
1516 | { | ||
1517 | return &skb_shinfo(skb)->redinfo; | ||
1518 | } | ||
1519 | |||
1520 | static inline struct skb_shared_hwtstamps * | ||
1521 | skb_redinfo_hwtstamps(struct sk_buff *skb) | ||
1522 | { | ||
1523 | return &skb_shinfo(skb)->red_hwtstamps; | ||
1524 | } | ||
1492 | 1525 | ||
1493 | /** | 1526 | /** |
1494 | * skb_queue_empty - check if a queue is empty | 1527 | * skb_queue_empty - check if a queue is empty |
diff --git a/include/net/sock.h b/include/net/sock.h index 338ecd0490d4..3f3ac13d7647 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1652,12 +1652,14 @@ struct sockcm_cookie { | |||
1652 | u64 transmit_time; | 1652 | u64 transmit_time; |
1653 | u32 mark; | 1653 | u32 mark; |
1654 | u16 tsflags; | 1654 | u16 tsflags; |
1655 | struct skb_redundant_info redinfo; | ||
1655 | }; | 1656 | }; |
1656 | 1657 | ||
1657 | static inline void sockcm_init(struct sockcm_cookie *sockc, | 1658 | static inline void sockcm_init(struct sockcm_cookie *sockc, |
1658 | const struct sock *sk) | 1659 | const struct sock *sk) |
1659 | { | 1660 | { |
1660 | *sockc = (struct sockcm_cookie) { .tsflags = sk->sk_tsflags }; | 1661 | *sockc = (struct sockcm_cookie) { .tsflags = sk->sk_tsflags }; |
1662 | memset(&sockc->redinfo, 0, sizeof(sockc->redinfo)); | ||
1661 | } | 1663 | } |
1662 | 1664 | ||
1663 | int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, | 1665 | int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, |
@@ -2375,6 +2377,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
2375 | struct sk_buff *skb); | 2377 | struct sk_buff *skb); |
2376 | void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, | 2378 | void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, |
2377 | struct sk_buff *skb); | 2379 | struct sk_buff *skb); |
2380 | void __sock_recv_redinfo_timestamp(struct msghdr *msg, struct sock *sk, | ||
2381 | struct sk_buff *skb); | ||
2378 | 2382 | ||
2379 | static inline void | 2383 | static inline void |
2380 | sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) | 2384 | sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) |
@@ -2457,6 +2461,31 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags) | |||
2457 | &skb_shinfo(skb)->tskey); | 2461 | &skb_shinfo(skb)->tskey); |
2458 | } | 2462 | } |
2459 | 2463 | ||
2464 | static inline void sock_recv_redundant_info(struct msghdr *msg, struct sock *sk, | ||
2465 | struct sk_buff *skb) | ||
2466 | { | ||
2467 | struct skb_redundant_info *sred; | ||
2468 | |||
2469 | sred = skb_redinfo(skb); | ||
2470 | if (sred->lsdu_size) | ||
2471 | put_cmsg(msg, SOL_SOCKET, SCM_REDUNDANT, sizeof(*sred), sred); | ||
2472 | |||
2473 | __sock_recv_redinfo_timestamp(msg, sk, skb); | ||
2474 | |||
2475 | } | ||
2476 | |||
2477 | static inline void sock_tx_redundant_info(const struct sock *sk, | ||
2478 | struct skb_redundant_info *redinfo, | ||
2479 | struct sk_buff *skb) | ||
2480 | { | ||
2481 | struct skb_redundant_info *sred; | ||
2482 | |||
2483 | if (redinfo->io_port) { | ||
2484 | sred = skb_redinfo(skb); | ||
2485 | memcpy(sred, redinfo, sizeof(*sred)); | ||
2486 | } | ||
2487 | } | ||
2488 | |||
2460 | /** | 2489 | /** |
2461 | * sk_eat_skb - Release a skb if it is no longer needed | 2490 | * sk_eat_skb - Release a skb if it is no longer needed |
2462 | * @sk: socket to eat this skb from | 2491 | * @sk: socket to eat this skb from |
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 77f7c1638eb1..990d9c9d7725 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h | |||
@@ -144,4 +144,10 @@ | |||
144 | 144 | ||
145 | #endif | 145 | #endif |
146 | 146 | ||
147 | #define SO_REDUNDANT 80 | ||
148 | #define SCM_REDUNDANT SO_REDUNDANT | ||
149 | |||
150 | #define SO_RED_TIMESTAMPING 81 | ||
151 | #define SCM_RED_TIMESTAMPING SO_RED_TIMESTAMPING | ||
152 | |||
147 | #endif /* __ASM_GENERIC_SOCKET_H */ | 153 | #endif /* __ASM_GENERIC_SOCKET_H */ |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 973a71f4bc89..c9a4a8ff84ad 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -4573,6 +4573,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, | |||
4573 | { | 4573 | { |
4574 | struct sk_buff *skb; | 4574 | struct sk_buff *skb; |
4575 | bool tsonly, opt_stats = false; | 4575 | bool tsonly, opt_stats = false; |
4576 | struct skb_redundant_info *sred, *orig_sred; | ||
4576 | 4577 | ||
4577 | if (!sk) | 4578 | if (!sk) |
4578 | return; | 4579 | return; |
@@ -4607,6 +4608,13 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, | |||
4607 | skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey; | 4608 | skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey; |
4608 | } | 4609 | } |
4609 | 4610 | ||
4611 | /* FIXME: should check sk flags */ | ||
4612 | orig_sred = skb_redinfo(orig_skb); | ||
4613 | if (orig_sred->lsdu_size) { | ||
4614 | sred = skb_redinfo(skb); | ||
4615 | memcpy(sred, orig_sred, sizeof(*sred)); | ||
4616 | } | ||
4617 | |||
4610 | if (hwtstamps) | 4618 | if (hwtstamps) |
4611 | *skb_hwtstamps(skb) = *hwtstamps; | 4619 | *skb_hwtstamps(skb) = *hwtstamps; |
4612 | else | 4620 | else |
diff --git a/net/core/sock.c b/net/core/sock.c index 69c02ac06c59..6eb478f11381 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -2270,6 +2270,7 @@ EXPORT_SYMBOL(sock_alloc_send_skb); | |||
2270 | int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, | 2270 | int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, |
2271 | struct sockcm_cookie *sockc) | 2271 | struct sockcm_cookie *sockc) |
2272 | { | 2272 | { |
2273 | struct skb_redundant_info *cred; | ||
2273 | u32 tsflags; | 2274 | u32 tsflags; |
2274 | 2275 | ||
2275 | switch (cmsg->cmsg_type) { | 2276 | switch (cmsg->cmsg_type) { |
@@ -2302,6 +2303,15 @@ int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, | |||
2302 | case SCM_RIGHTS: | 2303 | case SCM_RIGHTS: |
2303 | case SCM_CREDENTIALS: | 2304 | case SCM_CREDENTIALS: |
2304 | break; | 2305 | break; |
2306 | case SCM_REDUNDANT: | ||
2307 | if (cmsg->cmsg_len != | ||
2308 | CMSG_LEN(sizeof(struct skb_redundant_info))) | ||
2309 | return -EINVAL; | ||
2310 | |||
2311 | cred = (struct skb_redundant_info *)CMSG_DATA(cmsg); | ||
2312 | memcpy(&sockc->redinfo, cred, | ||
2313 | sizeof(struct skb_redundant_info)); | ||
2314 | break; | ||
2305 | default: | 2315 | default: |
2306 | return -EINVAL; | 2316 | return -EINVAL; |
2307 | } | 2317 | } |
@@ -3070,6 +3080,7 @@ int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, | |||
3070 | struct sock_exterr_skb *serr; | 3080 | struct sock_exterr_skb *serr; |
3071 | struct sk_buff *skb; | 3081 | struct sk_buff *skb; |
3072 | int copied, err; | 3082 | int copied, err; |
3083 | struct skb_redundant_info *sred; | ||
3073 | 3084 | ||
3074 | err = -EAGAIN; | 3085 | err = -EAGAIN; |
3075 | skb = sock_dequeue_err_skb(sk); | 3086 | skb = sock_dequeue_err_skb(sk); |
@@ -3087,6 +3098,9 @@ int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, | |||
3087 | 3098 | ||
3088 | sock_recv_timestamp(msg, sk, skb); | 3099 | sock_recv_timestamp(msg, sk, skb); |
3089 | 3100 | ||
3101 | sred = skb_redinfo(skb); | ||
3102 | put_cmsg(msg, SOL_SOCKET, SCM_REDUNDANT, sizeof(*sred), sred); | ||
3103 | |||
3090 | serr = SKB_EXT_ERR(skb); | 3104 | serr = SKB_EXT_ERR(skb); |
3091 | put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee); | 3105 | put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee); |
3092 | 3106 | ||
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 7716dc97733f..361d68842bb8 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c | |||
@@ -12,12 +12,19 @@ | |||
12 | #include <linux/etherdevice.h> | 12 | #include <linux/etherdevice.h> |
13 | #include <linux/rtnetlink.h> | 13 | #include <linux/rtnetlink.h> |
14 | #include <linux/pkt_sched.h> | 14 | #include <linux/pkt_sched.h> |
15 | #include <linux/net_tstamp.h> | ||
15 | #include "hsr_device.h" | 16 | #include "hsr_device.h" |
16 | #include "hsr_slave.h" | 17 | #include "hsr_slave.h" |
17 | #include "hsr_framereg.h" | 18 | #include "hsr_framereg.h" |
18 | #include "hsr_main.h" | 19 | #include "hsr_main.h" |
19 | #include "hsr_forward.h" | 20 | #include "hsr_forward.h" |
20 | 21 | ||
22 | static inline bool is_slave_port(struct hsr_port *p) | ||
23 | { | ||
24 | return (p->type == HSR_PT_SLAVE_A) || | ||
25 | (p->type == HSR_PT_SLAVE_B); | ||
26 | } | ||
27 | |||
21 | static bool is_admin_up(struct net_device *dev) | 28 | static bool is_admin_up(struct net_device *dev) |
22 | { | 29 | { |
23 | return dev && (dev->flags & IFF_UP); | 30 | return dev && (dev->flags & IFF_UP); |
@@ -687,6 +694,31 @@ err: | |||
687 | return ret; | 694 | return ret; |
688 | } | 695 | } |
689 | 696 | ||
697 | static int hsr_dev_ioctl(struct net_device *hsr_dev, struct ifreq *req, int cmd) | ||
698 | { | ||
699 | struct hsr_priv *priv = netdev_priv(hsr_dev); | ||
700 | const struct net_device_ops *ops; | ||
701 | struct hsr_port *port; | ||
702 | int ret = -ENOTSUPP; | ||
703 | |||
704 | if (cmd != SIOCSHWTSTAMP && cmd != SIOCGHWTSTAMP) | ||
705 | return ret; | ||
706 | |||
707 | hsr_for_each_port(priv, port) { | ||
708 | if (is_slave_port(port)) { | ||
709 | ops = port->dev->netdev_ops; | ||
710 | if (ops && ops->ndo_do_ioctl) { | ||
711 | ret = ops->ndo_do_ioctl(port->dev, req, cmd); | ||
712 | |||
713 | if (cmd == SIOCGHWTSTAMP || cmd < 0) | ||
714 | return ret; | ||
715 | } | ||
716 | } | ||
717 | } | ||
718 | |||
719 | return ret; | ||
720 | } | ||
721 | |||
690 | static int hsr_ndo_vlan_rx_kill_vid(struct net_device *dev, | 722 | static int hsr_ndo_vlan_rx_kill_vid(struct net_device *dev, |
691 | __be16 proto, u16 vid) | 723 | __be16 proto, u16 vid) |
692 | { | 724 | { |
@@ -724,6 +756,33 @@ static const struct net_device_ops hsr_device_ops = { | |||
724 | .ndo_set_rx_mode = hsr_ndo_set_rx_mode, | 756 | .ndo_set_rx_mode = hsr_ndo_set_rx_mode, |
725 | .ndo_vlan_rx_add_vid = hsr_ndo_vlan_rx_add_vid, | 757 | .ndo_vlan_rx_add_vid = hsr_ndo_vlan_rx_add_vid, |
726 | .ndo_vlan_rx_kill_vid = hsr_ndo_vlan_rx_kill_vid, | 758 | .ndo_vlan_rx_kill_vid = hsr_ndo_vlan_rx_kill_vid, |
759 | .ndo_do_ioctl = hsr_dev_ioctl, | ||
760 | }; | ||
761 | |||
762 | static int hsr_get_ts_info(struct net_device *dev, | ||
763 | struct ethtool_ts_info *info) | ||
764 | { | ||
765 | struct hsr_priv *priv = netdev_priv(dev); | ||
766 | struct hsr_port *port; | ||
767 | const struct ethtool_ops *ops; | ||
768 | int ret = -ENOTSUPP; | ||
769 | |||
770 | hsr_for_each_port(priv, port) { | ||
771 | if (is_slave_port(port)) { | ||
772 | ops = port->dev->ethtool_ops; | ||
773 | if (ops && ops->get_ts_info) { | ||
774 | ret = ops->get_ts_info(port->dev, info); | ||
775 | return ret; | ||
776 | } | ||
777 | } | ||
778 | } | ||
779 | |||
780 | return ret; | ||
781 | } | ||
782 | |||
783 | static const struct ethtool_ops hsr_ethtool_ops = { | ||
784 | .get_link = ethtool_op_get_link, | ||
785 | .get_ts_info = hsr_get_ts_info, | ||
727 | }; | 786 | }; |
728 | 787 | ||
729 | static struct device_type hsr_type = { | 788 | static struct device_type hsr_type = { |
@@ -738,6 +797,7 @@ void hsr_dev_setup(struct net_device *dev) | |||
738 | dev->min_mtu = 0; | 797 | dev->min_mtu = 0; |
739 | dev->header_ops = &hsr_header_ops; | 798 | dev->header_ops = &hsr_header_ops; |
740 | dev->netdev_ops = &hsr_device_ops; | 799 | dev->netdev_ops = &hsr_device_ops; |
800 | dev->ethtool_ops = &hsr_ethtool_ops; | ||
741 | SET_NETDEV_DEVTYPE(dev, &hsr_type); | 801 | SET_NETDEV_DEVTYPE(dev, &hsr_type); |
742 | dev->priv_flags |= IFF_NO_QUEUE; | 802 | dev->priv_flags |= IFF_NO_QUEUE; |
743 | 803 | ||
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index afe7bee853cc..d556f4a3d7a0 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c | |||
@@ -29,8 +29,19 @@ struct hsr_frame_info { | |||
29 | bool is_local_dest; | 29 | bool is_local_dest; |
30 | bool is_local_exclusive; | 30 | bool is_local_exclusive; |
31 | bool is_from_san; | 31 | bool is_from_san; |
32 | struct skb_redundant_info *sred; | ||
32 | }; | 33 | }; |
33 | 34 | ||
35 | static inline int is_hsr_l2ptp(struct sk_buff *skb) | ||
36 | { | ||
37 | struct hsr_ethhdr *hsr_ethhdr; | ||
38 | |||
39 | hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb); | ||
40 | |||
41 | return (hsr_ethhdr->ethhdr.h_proto == htons(ETH_P_HSR) && | ||
42 | hsr_ethhdr->hsr_tag.encap_proto == htons(ETH_P_1588)); | ||
43 | } | ||
44 | |||
34 | /* The uses I can see for these HSR supervision frames are: | 45 | /* The uses I can see for these HSR supervision frames are: |
35 | * 1) Use the frames that are sent after node initialization ("HSR_TLV.Type = | 46 | * 1) Use the frames that are sent after node initialization ("HSR_TLV.Type = |
36 | * 22") to reset any sequence_nr counters belonging to that node. Useful if | 47 | * 22") to reset any sequence_nr counters belonging to that node. Useful if |
@@ -274,7 +285,11 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, | |||
274 | else | 285 | else |
275 | hsr_ethhdr = (struct hsr_ethhdr *)pc; | 286 | hsr_ethhdr = (struct hsr_ethhdr *)pc; |
276 | 287 | ||
277 | hsr_set_path_id(hsr_ethhdr, port); | 288 | if (REDINFO_T(skb) == DIRECTED_TX) |
289 | set_hsr_tag_path(&hsr_ethhdr->hsr_tag, REDINFO_PATHID(skb)); | ||
290 | else | ||
291 | hsr_set_path_id(hsr_ethhdr, port); | ||
292 | |||
278 | set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); | 293 | set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); |
279 | hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr); | 294 | hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr); |
280 | hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; | 295 | hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; |
@@ -289,6 +304,9 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, | |||
289 | int movelen; | 304 | int movelen; |
290 | unsigned char *dst, *src; | 305 | unsigned char *dst, *src; |
291 | struct sk_buff *skb; | 306 | struct sk_buff *skb; |
307 | struct skb_redundant_info *sred; | ||
308 | struct hsr_ethhdr *hsr_ethhdr; | ||
309 | u16 s; | ||
292 | 310 | ||
293 | if (port->hsr->prot_version > HSR_V1) { | 311 | if (port->hsr->prot_version > HSR_V1) { |
294 | skb = skb_copy_expand(skb_o, skb_headroom(skb_o), | 312 | skb = skb_copy_expand(skb_o, skb_headroom(skb_o), |
@@ -321,6 +339,25 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, | |||
321 | 339 | ||
322 | hsr_fill_tag(skb, frame, port, port->hsr->prot_version); | 340 | hsr_fill_tag(skb, frame, port, port->hsr->prot_version); |
323 | 341 | ||
342 | if (REDINFO_T(skb) == DIRECTED_TX) | ||
343 | return skb; | ||
344 | |||
345 | skb_shinfo(skb)->tx_flags = skb_shinfo(skb_o)->tx_flags; | ||
346 | skb->sk = skb_o->sk; | ||
347 | |||
348 | /* TODO: should check socket option instead? */ | ||
349 | if (is_hsr_l2ptp(skb)) { | ||
350 | sred = skb_redinfo(skb); | ||
351 | /* assumes no vlan */ | ||
352 | hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb); | ||
353 | sred->io_port = (PTP_EVT_OUT | BIT(port->type - 1)); | ||
354 | sred->ethertype = ntohs(hsr_ethhdr->ethhdr.h_proto); | ||
355 | s = ntohs(hsr_ethhdr->hsr_tag.path_and_LSDU_size); | ||
356 | sred->lsdu_size = s & 0xfff; | ||
357 | sred->pathid = (s >> 12) & 0xf; | ||
358 | sred->seqnr = hsr_get_skb_sequence_nr(skb); | ||
359 | } | ||
360 | |||
324 | return skb; | 361 | return skb; |
325 | } | 362 | } |
326 | 363 | ||
@@ -418,6 +455,57 @@ static int hsr_xmit(struct sk_buff *skb, struct hsr_port *port, | |||
418 | return dev_queue_xmit(skb); | 455 | return dev_queue_xmit(skb); |
419 | } | 456 | } |
420 | 457 | ||
458 | static void stripped_skb_get_shared_info(struct sk_buff *skb_stripped, | ||
459 | struct hsr_frame_info *frame) | ||
460 | { | ||
461 | struct hsr_port *port_rcv = frame->port_rcv; | ||
462 | struct skb_redundant_info *sred; | ||
463 | struct sk_buff *skb_hsr, *skb; | ||
464 | struct hsr_ethhdr *hsr_ethhdr; | ||
465 | u16 s; | ||
466 | |||
467 | if (port_rcv->hsr->prot_version > HSR_V1) | ||
468 | return; | ||
469 | |||
470 | if (!frame->skb_hsr) | ||
471 | return; | ||
472 | |||
473 | skb_hsr = frame->skb_hsr; | ||
474 | skb = skb_stripped; | ||
475 | |||
476 | if (is_hsr_l2ptp(skb_hsr)) { | ||
477 | skb_hwtstamps(skb)->hwtstamp = skb_hwtstamps(skb_hsr)->hwtstamp; | ||
478 | skb_redinfo_hwtstamps(skb)->hwtstamp = | ||
479 | skb_redinfo_hwtstamps(skb_hsr)->hwtstamp; | ||
480 | |||
481 | sred = skb_redinfo(skb); | ||
482 | /* assumes no vlan */ | ||
483 | hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb_hsr); | ||
484 | sred->io_port = (PTP_MSG_IN | BIT(port_rcv->type - 1)); | ||
485 | sred->ethertype = ntohs(hsr_ethhdr->ethhdr.h_proto); | ||
486 | s = ntohs(hsr_ethhdr->hsr_tag.path_and_LSDU_size); | ||
487 | sred->lsdu_size = s & 0xfff; | ||
488 | sred->pathid = (s >> 12) & 0xf; | ||
489 | sred->seqnr = frame->sequence_nr; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | static unsigned int | ||
494 | hsr_directed_tx_ports(struct hsr_frame_info *frame) | ||
495 | { | ||
496 | struct sk_buff *skb; | ||
497 | |||
498 | if (frame->skb_std) | ||
499 | skb = frame->skb_std; | ||
500 | else | ||
501 | return 0; | ||
502 | |||
503 | if (REDINFO_T(skb) == DIRECTED_TX) | ||
504 | return REDINFO_PORTS(skb); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
421 | /* Forward the frame through all devices except: | 509 | /* Forward the frame through all devices except: |
422 | * - Back through the receiving device | 510 | * - Back through the receiving device |
423 | * - If it's a HSR frame: through a device where it has passed before | 511 | * - If it's a HSR frame: through a device where it has passed before |
@@ -434,6 +522,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame) | |||
434 | { | 522 | { |
435 | struct hsr_port *port; | 523 | struct hsr_port *port; |
436 | struct sk_buff *skb = NULL; | 524 | struct sk_buff *skb = NULL; |
525 | unsigned int dir_ports = 0; | ||
437 | 526 | ||
438 | hsr_for_each_port(frame->port_rcv->hsr, port) { | 527 | hsr_for_each_port(frame->port_rcv->hsr, port) { |
439 | /* Don't send frame back the way it came */ | 528 | /* Don't send frame back the way it came */ |
@@ -486,11 +575,18 @@ static void hsr_forward_do(struct hsr_frame_info *frame) | |||
486 | port->type == HSR_PT_SLAVE_A))) | 575 | port->type == HSR_PT_SLAVE_A))) |
487 | continue; | 576 | continue; |
488 | 577 | ||
489 | if (port->type != HSR_PT_MASTER) | 578 | dir_ports = hsr_directed_tx_ports(frame); |
579 | if (dir_ports && !(dir_ports & BIT(port->type - 1))) | ||
580 | continue; | ||
581 | |||
582 | if (port->type != HSR_PT_MASTER) { | ||
490 | skb = frame_get_tagged_skb(frame, port); | 583 | skb = frame_get_tagged_skb(frame, port); |
491 | else | 584 | } else { |
492 | skb = frame_get_stripped_skb(frame, port); | 585 | skb = frame_get_stripped_skb(frame, port); |
493 | 586 | ||
587 | stripped_skb_get_shared_info(skb, frame); | ||
588 | } | ||
589 | |||
494 | if (!skb) { | 590 | if (!skb) { |
495 | frame->port_rcv->dev->stats.rx_dropped++; | 591 | frame->port_rcv->dev->stats.rx_dropped++; |
496 | if (frame->port_rcv->type == HSR_PT_SLAVE_A || | 592 | if (frame->port_rcv->type == HSR_PT_SLAVE_A || |
@@ -573,10 +669,13 @@ static void fill_frame_info_non_prefixed(struct hsr_frame_info *frame, | |||
573 | if (port->type != HSR_PT_MASTER) { | 669 | if (port->type != HSR_PT_MASTER) { |
574 | frame->is_from_san = true; | 670 | frame->is_from_san = true; |
575 | } else { | 671 | } else { |
576 | if ((hsr->prot_version == HSR_V1 && | 672 | if ((REDINFO_T(skb) == DIRECTED_TX) && |
577 | hsr->hsr_mode != IEC62439_3_HSR_MODE_T) || | 673 | (REDINFO_LSDU_SIZE(skb))) { |
578 | hsr->prot_version == PRP_V1 || | 674 | frame->sequence_nr = REDINFO_SEQNR(skb); |
579 | hsr->prot_version == HSR_V0) { | 675 | } else if ((hsr->prot_version == HSR_V1 && |
676 | hsr->hsr_mode != IEC62439_3_HSR_MODE_T) || | ||
677 | hsr->prot_version == PRP_V1 || | ||
678 | hsr->prot_version == HSR_V0) { | ||
580 | /* Sequence nr for the master node */ | 679 | /* Sequence nr for the master node */ |
581 | spin_lock_irqsave(&hsr->seqnr_lock, | 680 | spin_lock_irqsave(&hsr->seqnr_lock, |
582 | irqflags); | 681 | irqflags); |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1d63ab3a878a..c74689da8ee7 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2950,6 +2950,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
2950 | 2950 | ||
2951 | skb_setup_tx_timestamp(skb, sockc.tsflags); | 2951 | skb_setup_tx_timestamp(skb, sockc.tsflags); |
2952 | 2952 | ||
2953 | sock_tx_redundant_info(sk, &sockc.redinfo, skb); | ||
2954 | |||
2953 | if (!vnet_hdr.gso_type && (len > dev->mtu + reserve + extra_len) && | 2955 | if (!vnet_hdr.gso_type && (len > dev->mtu + reserve + extra_len) && |
2954 | !packet_extra_vlan_len_allowed(dev, skb)) { | 2956 | !packet_extra_vlan_len_allowed(dev, skb)) { |
2955 | err = -EMSGSIZE; | 2957 | err = -EMSGSIZE; |
@@ -3389,6 +3391,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
3389 | 3391 | ||
3390 | sock_recv_ts_and_drops(msg, sk, skb); | 3392 | sock_recv_ts_and_drops(msg, sk, skb); |
3391 | 3393 | ||
3394 | sock_recv_redundant_info(msg, sk, skb); | ||
3395 | |||
3392 | if (msg->msg_name) { | 3396 | if (msg->msg_name) { |
3393 | int copy_len; | 3397 | int copy_len; |
3394 | 3398 | ||
diff --git a/net/socket.c b/net/socket.c index fb2b39647d01..a163b279d3d5 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -830,6 +830,25 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
830 | } | 830 | } |
831 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 831 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
832 | 832 | ||
833 | void __sock_recv_redinfo_timestamp(struct msghdr *msg, struct sock *sk, | ||
834 | struct sk_buff *skb) | ||
835 | { | ||
836 | struct scm_timestamping tss; | ||
837 | int empty = 1; | ||
838 | struct skb_shared_hwtstamps *red_shhwtstamps = | ||
839 | skb_redinfo_hwtstamps(skb); | ||
840 | |||
841 | if (red_shhwtstamps && | ||
842 | (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && | ||
843 | ktime_to_timespec_cond(red_shhwtstamps->hwtstamp, tss.ts + 2)) | ||
844 | empty = 0; | ||
845 | |||
846 | if (!empty) | ||
847 | put_cmsg(msg, SOL_SOCKET, | ||
848 | SCM_RED_TIMESTAMPING, sizeof(tss), &tss); | ||
849 | } | ||
850 | EXPORT_SYMBOL_GPL(__sock_recv_redinfo_timestamp); | ||
851 | |||
833 | void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, | 852 | void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, |
834 | struct sk_buff *skb) | 853 | struct sk_buff *skb) |
835 | { | 854 | { |