* [PATCH v5 1/2] mpls: export mpls_forward()
From: Amine Kherbouche @ 2017-09-28 16:34 UTC (permalink / raw)
To: netdev, davem, xeb, roopa; +Cc: amine.kherbouche, equinox
In-Reply-To: <cover.1506616214.git.amine.kherbouche@6wind.com>
Exporting mpls_forward() function to be able to be called from elsewhere
such as MPLSoverGRE in the next commit.
Signed-off-by: Amine Kherbouche <amine.kherbouche@6wind.com>
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
include/linux/mpls.h | 4 ++++
net/mpls/af_mpls.c | 5 +++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/include/linux/mpls.h b/include/linux/mpls.h
index 384fb22..b0579ab 100644
--- a/include/linux/mpls.h
+++ b/include/linux/mpls.h
@@ -2,10 +2,14 @@
#define _LINUX_MPLS_H
#include <uapi/linux/mpls.h>
+#include <linux/netdevice.h>
#define MPLS_TTL_MASK (MPLS_LS_TTL_MASK >> MPLS_LS_TTL_SHIFT)
#define MPLS_BOS_MASK (MPLS_LS_S_MASK >> MPLS_LS_S_SHIFT)
#define MPLS_TC_MASK (MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)
#define MPLS_LABEL_MASK (MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)
+int mpls_forward(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev);
+
#endif /* _LINUX_MPLS_H */
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index c5b9ce4..36ea2ad 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -307,8 +307,8 @@ static bool mpls_egress(struct net *net, struct mpls_route *rt,
return success;
}
-static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev)
+int mpls_forward(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
{
struct net *net = dev_net(dev);
struct mpls_shim_hdr *hdr;
@@ -442,6 +442,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
kfree_skb(skb);
return NET_RX_DROP;
}
+EXPORT_SYMBOL(mpls_forward);
static struct packet_type mpls_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_MPLS_UC),
--
2.1.4
^ permalink raw reply related
* [PATCH v5 0/2] Introduce MPLS over GRE
From: Amine Kherbouche @ 2017-09-28 16:34 UTC (permalink / raw)
To: netdev, davem, xeb, roopa; +Cc: amine.kherbouche, equinox
This series introduces the MPLS over GRE encapsulation (RFC 4023).
Various applications of MPLS make use of label stacks with multiple
entries. In some cases, it is possible to replace the top label of
the stack with an IP-based encapsulation, thereby, it is possible for
two LSRs that are adjacent on an LSP to be separated by an IP network,
even if that IP network does not provide MPLS.
Changes in v5:
- Reword first commit title.
Changes in v4:
- Bring back mpls_forward() function exportation patch.
- Move back mpls_gre_rcv() to gre module file and wrap it under
ifdef.
Changes in v3:
- remove mpls_forward() function exportation patch.
- wrap efficiently mpls iptunnel add/del functions and dependent
function/structure.
- move mpls_gre_rcv to af_mpls.c file and export it.
- remove unnecessary functions.
Changes in v2:
- wrap ip tunnel functions under ifdef in mpls file.
- fix indentation.
- check return code.
An example of configuration:
node1 LER1 LER2 node2
+-----+ +------+ +------+ +-----+
| | | | | | | |
| | | |p3 GRE tunnel p4| | | |
| |p1 p2| +-------------------+ |p5 p6| |
| +-------------+ +-------------------+ +------------+| |
| |10.100.0.0/24| | | |10.200.0.0/24| |
| |fd00:100::/64| | 10.125.0.0/24 | |fd00:200::/64| |
| | | | fd00:125::/64 | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
+-----+ +------+ +------+ +-----+
### node1 ###
ip link set p1 up
ip addr add 10.100.0.1/24 dev p1
### LER1 ###
ip link set p2 up
ip addr add 10.100.0.2/24 dev p2
ip link set p3 up
ip addr add 10.125.0.1/24 dev p3
modprobe mpls_router
sysctl -w net.mpls.conf.p2.input=1
sysctl -w net.mpls.conf.p3.input=1
sysctl -w net.mpls.platform_labels=1000
ip link add gre1 type gre ttl 64 local 10.125.0.1 remote 10.125.0.2 dev p3
ip link set dev gre1 up
ip -M route add 111 as 222 dev gre1
ip -M route add 555 as 666 via inet 10.100.0.1 dev p2
### LER2 ###
ip link set p5 up
ip addr add 10.200.0.2/24 dev p5
ip link set p4 up
ip addr add 10.125.0.2/24 dev p4
modprobe mpls_router
sysctl -w net.mpls.conf.p4.input=1
sysctl -w net.mpls.conf.p5.input=1
sysctl -w net.mpls.platform_labels=1000
ip link add gre1 type gre ttl 64 local 10.125.0.2 remote 10.125.0.1 dev p4
ip link set dev gre1 up
ip -M route add 444 as 555 dev gre1
ip -M route add 222 as 333 via inet 10.200.0.1 dev p5
### node2 ###
ip link set p6 up
ip addr add 10.200.0.1/24 dev p6
Now using this scapy to forge and send packets from the port p1 of node1:
p = Ether(src='de:ed:01:0c:41:09', dst='de:ed:01:2f:3b:ba')
p /= MPLS(s=1, ttl=64, label=111)/Raw(load='\xde')
sendp(p, iface="p1", count=20, inter=0.1)
Amine Kherbouche (2):
mpls: export mpls_forward()
ip_tunnel: add mpls over gre encapsulation
include/linux/mpls.h | 4 ++++
include/net/gre.h | 1 +
include/uapi/linux/if_tunnel.h | 1 +
net/ipv4/gre_demux.c | 27 +++++++++++++++++++++++++++
net/ipv4/ip_gre.c | 3 +++
net/ipv6/ip6_gre.c | 3 +++
net/mpls/af_mpls.c | 41 +++++++++++++++++++++++++++++++++++++++--
7 files changed, 78 insertions(+), 2 deletions(-)
--
2.1.4
^ permalink raw reply
* Re: [PATCH net v2 0/3] net: mvpp2: various fixes
From: David Miller @ 2017-09-28 16:34 UTC (permalink / raw)
To: antoine.tenart
Cc: andrew, gregory.clement, thomas.petazzoni, miquel.raynal, nadavh,
linux, linux-kernel, mw, stefanc, netdev
In-Reply-To: <20170925125948.13507-1-antoine.tenart@free-electrons.com>
From: Antoine Tenart <antoine.tenart@free-electrons.com>
Date: Mon, 25 Sep 2017 14:59:45 +0200
> This series contains 3 fixes for the Marvell PPv2 driver.
Series applied, thanks.
^ permalink raw reply
* Re: [PATCH] isdn/eicon: do integrity check on cmd->adapter == a->controller early
From: David Miller @ 2017-09-28 16:32 UTC (permalink / raw)
To: mengxu.gatech; +Cc: mac, isdn, netdev, linux-kernel, meng.xu, sanidhya, taesoo
In-Reply-To: <1506266081-22895-1-git-send-email-mengxu.gatech@gmail.com>
From: Meng Xu <mengxu.gatech@gmail.com>
Date: Sun, 24 Sep 2017 11:14:41 -0400
> + /* do the integrity check early */
> + if(((diva_xdi_um_cfg_cmd_t *)data)->adapter != a->controller){
> + DBG_ERR(("A: A(%d) write, invalid controller=%d != %d",
> + ((diva_xdi_um_cfg_cmd_t *)data)->adapter, a->controller));
> +
DBG_ERR() has a trailing semicolon in it's definition, so if you add
another one when you invoke it there will be two ";;".
This whole code base is such a mess, I really think there is little
to no value in trying to make minor changes here.
So unless you are fixing some kind of exploitable hole, please drop
this.
Thank you.
^ permalink raw reply
* Re: [PATCH net-next RFC 1/9] net: dsa: mv88e6xxx: add accessors for PTP/TAI registers
From: Vivien Didelot @ 2017-09-28 16:29 UTC (permalink / raw)
To: Brandon Streiff, netdev
Cc: linux-kernel, David S. Miller, Florian Fainelli, Andrew Lunn,
Richard Cochran, Erik Hons, Brandon Streiff
In-Reply-To: <1506612341-18061-2-git-send-email-brandon.streiff@ni.com>
Hi Brandon,
Brandon Streiff <brandon.streiff@ni.com> writes:
> + .port_ptp_read = mv88e6352_port_ptp_read,
> + .port_ptp_write = mv88e6352_port_ptp_write,
> + .ptp_read = mv88e6352_ptp_read,
> + .ptp_write = mv88e6352_ptp_write,
> + .tai_read = mv88e6352_tai_read,
> + .tai_write = mv88e6352_tai_write,
> + .port_ptp_read = mv88e6390_port_ptp_read,
> + .port_ptp_write = mv88e6390_port_ptp_write,
> + .ptp_read = mv88e6390_ptp_read,
> + .ptp_write = mv88e6390_ptp_write,
> + .tai_read = mv88e6390_tai_read,
> + .tai_write = mv88e6390_tai_write,
Only nitpick: please keep the mv88e63{52,90}_g2_avb_ prefix here.
Otherwise thanks for respecting the code organization, very clear patch:
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Vivien
^ permalink raw reply
* Re: [PATCH net-next 0/3] support changing steering policies in tuntap
From: Willem de Bruijn @ 2017-09-28 16:09 UTC (permalink / raw)
To: Jason Wang; +Cc: Michael S. Tsirkin, Network Development, LKML
In-Reply-To: <26f01b12-396e-6319-0eed-c987930e0ed9@redhat.com>
On Thu, Sep 28, 2017 at 3:23 AM, Jason Wang <jasowang@redhat.com> wrote:
>
>
> On 2017年09月28日 07:25, Willem de Bruijn wrote:
>>>>
>>>> In the future, both simple and sophisticated policy like RSS or other
>>>> guest
>>>> driven steering policies could be done on top.
>>>
>>> IMHO there should be a more practical example before adding all this
>>> indirection. And it would be nice to understand why this queue selection
>>> needs to be tun specific.
>>
>> I was thinking the same and this reminds me of the various strategies
>> implemented in packet fanout. tun_cpu_select_queue is analogous to
>> fanout_demux_cpu though it is tun-specific in that it requires
>> tun->numqueues.
>
>
> Right, the main idea is to introduce a way to change flow steering policy
> for tun. I think fanout policy could be implemented through the API
> introduced in this series. (Current flow caches based automatic steering
> method is tun specific).
>
>>
>> Fanout accrued various strategies until it gained an eBPF variant. Just
>> supporting BPF is probably sufficient here, too.
>
>
> Technically yes, but for tun, it also serve for virt. We probably still need
> some hard coded policy which could be changed by guest until we can accept
> an BPF program from guest I think?
When would a guest choose the policy? As long as this is under control
of a host user, possibly unprivileged, allowing BPF here is moot, as any
user can run socket filter BPF already. Programming from the guest is
indeed different. I don't fully understand that use case.
^ permalink raw reply
* Re: [PATCH net-next] vhost_net: do not stall on zerocopy depletion
From: Willem de Bruijn @ 2017-09-28 16:05 UTC (permalink / raw)
To: Jason Wang
Cc: Network Development, David Miller, Michael S. Tsirkin,
Koichiro Den, virtualization, Willem de Bruijn
In-Reply-To: <a574875f-cea7-e769-ff41-c337c9720d7a@redhat.com>
On Thu, Sep 28, 2017 at 3:41 AM, Jason Wang <jasowang@redhat.com> wrote:
>
>
> On 2017年09月28日 08:25, Willem de Bruijn wrote:
>>
>> From: Willem de Bruijn <willemb@google.com>
>>
>> Vhost-net has a hard limit on the number of zerocopy skbs in flight.
>> When reached, transmission stalls. Stalls cause latency, as well as
>> head-of-line blocking of other flows that do not use zerocopy.
>>
>> Instead of stalling, revert to copy-based transmission.
>>
>> Tested by sending two udp flows from guest to host, one with payload
>> of VHOST_GOODCOPY_LEN, the other too small for zerocopy (1B). The
>> large flow is redirected to a netem instance with 1MBps rate limit
>> and deep 1000 entry queue.
>>
>> modprobe ifb
>> ip link set dev ifb0 up
>> tc qdisc add dev ifb0 root netem limit 1000 rate 1MBit
>>
>> tc qdisc add dev tap0 ingress
>> tc filter add dev tap0 parent ffff: protocol ip \
>> u32 match ip dport 8000 0xffff \
>> action mirred egress redirect dev ifb0
>>
>> Before the delay, both flows process around 80K pps. With the delay,
>> before this patch, both process around 400. After this patch, the
>> large flow is still rate limited, while the small reverts to its
>> original rate. See also discussion in the first link, below.
>>
>> The limit in vhost_exceeds_maxpend must be carefully chosen. When
>> vq->num >> 1, the flows remain correlated. This value happens to
>> correspond to VHOST_MAX_PENDING for vq->num == 256.
>
>
> Have you tested e.g vq->num = 512 or 1024?
I did test with 1024 previously, but let me run that again
with this patch applied.
>
>
>> Allow smaller
>> fractions and ensure correctness also for much smaller values of
>> vq->num, by testing the min() of both explicitly. See also the
>> discussion in the second link below.
>>
>>
>> Link:http://lkml.kernel.org/r/CAF=yD-+Wk9sc9dXMUq1+x_hh=3ThTXa6BnZkygP3tgVpjbp93g@mail.gmail.com
>> Link:http://lkml.kernel.org/r/20170819064129.27272-1-den@klaipeden.com
>> Signed-off-by: Willem de Bruijn <willemb@google.com>
>> ---
>> drivers/vhost/net.c | 14 ++++----------
>> 1 file changed, 4 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
>> index 58585ec8699e..50758602ae9d 100644
>> --- a/drivers/vhost/net.c
>> +++ b/drivers/vhost/net.c
>> @@ -436,8 +436,8 @@ static bool vhost_exceeds_maxpend(struct vhost_net
>> *net)
>> struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_TX];
>> struct vhost_virtqueue *vq = &nvq->vq;
>> - return (nvq->upend_idx + vq->num - VHOST_MAX_PEND) % UIO_MAXIOV
>> - == nvq->done_idx;
>> + return (nvq->upend_idx + UIO_MAXIOV - nvq->done_idx) % UIO_MAXIOV
>> >
>> + min(VHOST_MAX_PEND, vq->num >> 2);
>> }
>> /* Expects to be always run from workqueue - which acts as
>> @@ -480,12 +480,6 @@ static void handle_tx(struct vhost_net *net)
>> if (zcopy)
>> vhost_zerocopy_signal_used(net, vq);
>> - /* If more outstanding DMAs, queue the work.
>> - * Handle upend_idx wrap around
>> - */
>> - if (unlikely(vhost_exceeds_maxpend(net)))
>> - break;
>> -
>> head = vhost_net_tx_get_vq_desc(net, vq, vq->iov,
>> ARRAY_SIZE(vq->iov),
>> &out, &in);
>> @@ -509,6 +503,7 @@ static void handle_tx(struct vhost_net *net)
>> len = iov_length(vq->iov, out);
>> iov_iter_init(&msg.msg_iter, WRITE, vq->iov, out, len);
>> iov_iter_advance(&msg.msg_iter, hdr_size);
>> +
>
>
> Looks unnecessary. Other looks good.
Oops, indeed. Thanks.
^ permalink raw reply
* [PATCH net] ppp: fix __percpu annotation
From: Guillaume Nault @ 2017-09-28 15:57 UTC (permalink / raw)
To: netdev; +Cc: Gao Feng, Paul Mackerras
Move sparse annotation right after pointer type.
Fixes sparse warning:
drivers/net/ppp/ppp_generic.c:1422:13: warning: incorrect type in initializer (different address spaces)
drivers/net/ppp/ppp_generic.c:1422:13: expected void const [noderef] <asn:3>*__vpp_verify
drivers/net/ppp/ppp_generic.c:1422:13: got int *<noident>
...
Fixes: e5dadc65f9e0 ("ppp: Fix false xmit recursion detect with two ppp devices")
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
---
drivers/net/ppp/ppp_generic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index a404552555d4..c3f77e3b7819 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -120,7 +120,7 @@ struct ppp {
int n_channels; /* how many channels are attached 54 */
spinlock_t rlock; /* lock for receive side 58 */
spinlock_t wlock; /* lock for transmit side 5c */
- int *xmit_recursion __percpu; /* xmit recursion detect */
+ int __percpu *xmit_recursion; /* xmit recursion detect */
int mru; /* max receive unit 60 */
unsigned int flags; /* control bits 64 */
unsigned int xstate; /* transmit state bits 68 */
--
2.14.2
^ permalink raw reply related
* [PATCH 4/4] arm64: dts: renesas: ulcb: Add EthernetAVB PHY reset
From: Geert Uytterhoeven @ 2017-09-28 15:53 UTC (permalink / raw)
To: David S . Miller, Simon Horman, Magnus Damm
Cc: Sergei Shtylyov, Andrew Lunn, Florian Fainelli,
Niklas Söderlund, netdev, linux-renesas-soc, devicetree,
Geert Uytterhoeven
In-Reply-To: <1506614014-4398-1-git-send-email-geert+renesas@glider.be>
Describe the GPIO used to reset the Ethernet PHY for EthernetAVB.
This allows the driver to reset the PHY during probe and after system
resume.
On ULCB, the enable pin of the regulator providing PHY power is always
pulled high, but the driver may still need to reset the PHY if this
wasn't done by the bootloader before.
Inspired by patches in the BSP for the individual Salvator-X/XS boards
by Kazuya Mizuguchi.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Compile-tested only.
---
arch/arm64/boot/dts/renesas/ulcb.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi
index dfec9072718b8da1..49cf392fccfb3165 100644
--- a/arch/arm64/boot/dts/renesas/ulcb.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi
@@ -147,6 +147,7 @@
pinctrl-names = "default";
renesas,no-ether-link;
phy-handle = <&phy0>;
+ reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
status = "okay";
phy0: ethernet-phy@0 {
--
2.7.4
^ permalink raw reply related
* [PATCH 1/4] dt-bindings: net: ravb: Document optional reset-gpios property
From: Geert Uytterhoeven @ 2017-09-28 15:53 UTC (permalink / raw)
To: David S . Miller, Simon Horman, Magnus Damm
Cc: Sergei Shtylyov, Andrew Lunn, Florian Fainelli,
Niklas Söderlund, netdev, linux-renesas-soc, devicetree,
Geert Uytterhoeven
In-Reply-To: <1506614014-4398-1-git-send-email-geert+renesas@glider.be>
The optional "reset-gpios" property (part of the generic MDIO bus
properties) lets us describe the GPIO used for resetting the Ethernet
PHY.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Documentation/devicetree/bindings/net/renesas,ravb.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/renesas,ravb.txt b/Documentation/devicetree/bindings/net/renesas,ravb.txt
index c902261893b913f5..4a6ec1ba32d0bf16 100644
--- a/Documentation/devicetree/bindings/net/renesas,ravb.txt
+++ b/Documentation/devicetree/bindings/net/renesas,ravb.txt
@@ -52,6 +52,7 @@ Optional properties:
AVB_LINK signal.
- renesas,ether-link-active-low: boolean, specify when the AVB_LINK signal is
active-low instead of normal active-high.
+- reset-gpios: see mdio.txt in the same directory.
Example:
@@ -99,6 +100,7 @@ Example:
pinctrl-0 = <ðer_pins>;
pinctrl-names = "default";
renesas,no-ether-link;
+ reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
#address-cells = <1>;
#size-cells = <0>;
--
2.7.4
^ permalink raw reply related
* [PATCH 3/4] arm64: dts: renesas: salvator-common: Add EthernetAVB PHY reset
From: Geert Uytterhoeven @ 2017-09-28 15:53 UTC (permalink / raw)
To: David S . Miller, Simon Horman, Magnus Damm
Cc: Sergei Shtylyov, Andrew Lunn, Florian Fainelli,
Niklas Söderlund, netdev, linux-renesas-soc, devicetree,
Geert Uytterhoeven
In-Reply-To: <1506614014-4398-1-git-send-email-geert+renesas@glider.be>
Describe the GPIO used to reset the Ethernet PHY for EthernetAVB.
This allows the driver to reset the PHY during probe and after system
resume.
This fixes Ethernet operation after resume from s2ram on Salvator-XS,
where the enable pin of the regulator providing PHY power is connected
to PRESETn, and PSCI powers down the SoC during system suspend.
On Salvator-X, the enable pin is always pulled high, but the driver may
still need to reset the PHY if this wasn't done by the bootloader
before.
Inspired by patches in the BSP for the individual Salvator-X/XS boards
by Kazuya Mizuguchi.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
For proper PHY reset operation during system resume, this depends on
"ravb: Add missing PHY reset during system resume".
However, this patch can be applied independently.
---
arch/arm64/boot/dts/renesas/salvator-common.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
index ed4a8dfead3c2e58..db00e7c484f76eac 100644
--- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
@@ -296,6 +296,7 @@
pinctrl-names = "default";
renesas,no-ether-link;
phy-handle = <&phy0>;
+ reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
status = "okay";
phy0: ethernet-phy@0 {
--
2.7.4
^ permalink raw reply related
* [PATCH 2/4] ravb: Add optional PHY reset during system resume
From: Geert Uytterhoeven @ 2017-09-28 15:53 UTC (permalink / raw)
To: David S . Miller, Simon Horman, Magnus Damm
Cc: Sergei Shtylyov, Andrew Lunn, Florian Fainelli,
Niklas Söderlund, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven
In-Reply-To: <1506614014-4398-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
If the optional "reset-gpios" property is specified in DT, the generic
MDIO bus code takes care of resetting the PHY during device probe.
However, the PHY may still have to be reset explicitly after system
resume.
This allows to restore Ethernet operation after resume from s2ram on
Salvator-XS, where the enable pin of the regulator providing PHY power
is connected to PRESETn, and PSCI suspend powers down the SoC.
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
drivers/net/ethernet/renesas/ravb_main.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index fdf30bfa403bf416..96d1d48e302f8c9a 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -19,6 +19,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
+#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -2268,6 +2269,7 @@ static int __maybe_unused ravb_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct ravb_private *priv = netdev_priv(ndev);
+ struct mii_bus *bus = priv->mii_bus;
int ret = 0;
if (priv->wol_enabled) {
@@ -2302,6 +2304,13 @@ static int __maybe_unused ravb_resume(struct device *dev)
* reopen device if it was running before system suspended.
*/
+ /* PHY reset */
+ if (bus->reset_gpiod) {
+ gpiod_set_value_cansleep(bus->reset_gpiod, 1);
+ udelay(bus->reset_delay_us);
+ gpiod_set_value_cansleep(bus->reset_gpiod, 0);
+ }
+
/* Set AVB config mode */
ravb_set_config_mode(ndev);
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/4] ravb: Add PHY reset support
From: Geert Uytterhoeven @ 2017-09-28 15:53 UTC (permalink / raw)
To: David S . Miller, Simon Horman, Magnus Damm
Cc: Sergei Shtylyov, Andrew Lunn, Florian Fainelli,
Niklas Söderlund, netdev, linux-renesas-soc, devicetree,
Geert Uytterhoeven
Hi all,
This patch series adds optional PHY reset support during EthernetAVB driver
probe and system resume on the Renesas Salvator-X/XS development boards.
The rationale behind this is twofold:
1. On Salvator-XS, the enable pin of the regulator providing PHY power
is connected to PRESETn, and PSCI powers down the SoC during system
suspend. Hence a PHY reset is needed to restore network functionality
after resume.
2. Linux should not rely on the boot loader having reset the PHY, but
should reset the PHY during driver probe.
The first two patches are destined for David's net-next tree. They update
the EthernetAVB DT bindings, and add support for resetting the PHY during
system resume.
The last two patches are destined for Simon's renesas tree. They add
properties to describe the EthernetAVB PHY reset topology to the common
Salvator-X/XS and ULCB DTS files.
Thanks!
Geert Uytterhoeven (4):
dt-bindings: net: ravb: Document optional reset-gpios property
ravb: Add optional PHY reset during system resume
arm64: dts: renesas: salvator-common: Add EthernetAVB PHY reset
arm64: dts: renesas: ulcb: Add EthernetAVB PHY reset
Documentation/devicetree/bindings/net/renesas,ravb.txt | 2 ++
arch/arm64/boot/dts/renesas/salvator-common.dtsi | 1 +
arch/arm64/boot/dts/renesas/ulcb.dtsi | 1 +
drivers/net/ethernet/renesas/ravb_main.c | 9 +++++++++
4 files changed, 13 insertions(+)
--
2.7.4
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH net] net: mvpp2: Fix clock resource by adding an optional bus clock
From: Gregory CLEMENT @ 2017-09-28 15:52 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: Andrew Lunn, Yehuda Yitschak, Marcin Wojtas, Jason Cooper, netdev,
Antoine Tenart, Omri Itach, linux-kernel, Nadav Haklai,
Shadi Ammouri, Igal Liberman, Miquèl Raynal, Hanna Hawa,
David S. Miller, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20170928174654.630cfefd@windsurf.lan>
Hi Thomas,
On jeu., sept. 28 2017, Thomas Petazzoni <thomas.petazzoni@free-electrons.com> wrote:
>> /* List of pointers to port structures */
>> struct mvpp2_port **port_list;
>> @@ -7963,6 +7964,16 @@ static int mvpp2_probe(struct platform_device *pdev)
>> err = clk_prepare_enable(priv->mg_clk);
>> if (err < 0)
>> goto err_gop_clk;
>> +
>> + priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
>> + if (IS_ERR(priv->axi_clk)) {
>> + err = PTR_ERR(priv->axi_clk);
>> + priv->axi_clk = NULL;
>
> You should handle -EPROBE_DEFER here. Indeed, if we have -EPROBE_DEFER,
> we shouldn't treat it as "the clock doesn't exist, so let's skip it and
> continue", but rather as "the clock exists, but isn't ready to use yet,
> let's try later".
You're totally right, I will send a v2 (I will also fix the other issue
you spotted).
Thanks,
Gregory
>
> Thanks!
>
> Thomas
> --
> Thomas Petazzoni, CTO, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH net-next 2/2] tools: bpf: add bpftool
From: David Miller @ 2017-09-28 15:48 UTC (permalink / raw)
To: kubakici; +Cc: netdev, daniel, alexei.starovoitov, hannes, dsahern, oss-drivers
In-Reply-To: <20170928065912.00a9b6a1@cakuba>
From: Jakub Kicinski <kubakici@wp.pl>
Date: Thu, 28 Sep 2017 06:59:12 -0700
> On Tue, 26 Sep 2017 08:35:22 -0700, Jakub Kicinski wrote:
>> Add a simple tool for querying and updating BPF objects on the system.
>>
>> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
>> Reviewed-by: Simon Horman <simon.horman@netronome.com>
>
> Dave, I got some late review nitpicks internally which I think are
> worth addressing. Would you mind dropping this series? I will post v2
> with the cleanups and README included.
Sure.
^ permalink raw reply
* Re: [PATCH net] net: mvpp2: Fix clock resource by adding an optional bus clock
From: Thomas Petazzoni @ 2017-09-28 15:46 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: David S. Miller, linux-kernel, netdev, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, linux-arm-kernel, Antoine Tenart,
Miquèl Raynal, Nadav Haklai, Shadi Ammouri, Yehuda Yitschak,
Omri Itach, Hanna Hawa, Igal Liberman, Marcin Wojtas
In-Reply-To: <20170928153923.29003-1-gregory.clement@free-electrons.com>
Hello,
On Thu, 28 Sep 2017 17:39:23 +0200, Gregory CLEMENT wrote:
> diff --git a/Documentation/devicetree/bindings/net/marvell-pp2.txt b/Documentation/devicetree/bindings/net/marvell-pp2.txt
> index 7e2dad08a12e..49e1be6bb6ba 100644
> --- a/Documentation/devicetree/bindings/net/marvell-pp2.txt
> +++ b/Documentation/devicetree/bindings/net/marvell-pp2.txt
> @@ -21,8 +21,9 @@ Required properties:
> - main controller clock (for both armada-375-pp2 and armada-7k-pp2)
> - GOP clock (for both armada-375-pp2 and armada-7k-pp2)
> - MG clock (only for armada-7k-pp2)
> -- clock-names: names of used clocks, must be "pp_clk", "gop_clk" and
> - "mg_clk" (the latter only for armada-7k-pp2).
> + - AXI clock (only for armada-7k-pp2)
> +- clock-names: names of used clocks, must be "pp_clk", "gop_clk", "mg_clk"
> + and "axi"(the 2 latter only for armada-7k-pp2).
Should be "axi_clk" not "axi", otherwise your binding documentation
doesn't match the driver and example.
Also, missing space after "axi".
>
> The ethernet ports are represented by subnodes. At least one port is
> required.
> @@ -78,8 +79,9 @@ Example for marvell,armada-7k-pp2:
> cpm_ethernet: ethernet@0 {
> compatible = "marvell,armada-7k-pp22";
> reg = <0x0 0x100000>, <0x129000 0xb000>;
> - clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
> - clock-names = "pp_clk", "gop_clk", "gp_clk";
> + clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>,
> + <&cpm_syscon0 1 5>, <&cpm_syscon0 1 18>;
Please indent the second line with one more tab.
> + clock-names = "pp_clk", "gop_clk", "gp_clk", "axi_clk";
>
> eth0: eth0 {
> interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>,
> diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
> index dd0ee2691c86..33b6791df2bb 100644
> --- a/drivers/net/ethernet/marvell/mvpp2.c
> +++ b/drivers/net/ethernet/marvell/mvpp2.c
> @@ -792,6 +792,7 @@ struct mvpp2 {
> struct clk *pp_clk;
> struct clk *gop_clk;
> struct clk *mg_clk;
> + struct clk *axi_clk;
>
> /* List of pointers to port structures */
> struct mvpp2_port **port_list;
> @@ -7963,6 +7964,16 @@ static int mvpp2_probe(struct platform_device *pdev)
> err = clk_prepare_enable(priv->mg_clk);
> if (err < 0)
> goto err_gop_clk;
> +
> + priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
> + if (IS_ERR(priv->axi_clk)) {
> + err = PTR_ERR(priv->axi_clk);
> + priv->axi_clk = NULL;
You should handle -EPROBE_DEFER here. Indeed, if we have -EPROBE_DEFER,
we shouldn't treat it as "the clock doesn't exist, so let's skip it and
continue", but rather as "the clock exists, but isn't ready to use yet,
let's try later".
Thanks!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [Intel-wired-lan] [PATCH net v2] i40e: Fix limit imprecise of the number of MAC/VLAN that can be added for VFs
From: Alexander Duyck @ 2017-09-28 15:44 UTC (permalink / raw)
To: w00273186
Cc: David Miller, Jeff Kirsher, Sergei Shtylyov, Netdev, caihe,
intel-wired-lan
In-Reply-To: <1506564064-10740-1-git-send-email-wangyunjian@huawei.com>
On Wed, Sep 27, 2017 at 7:01 PM, w00273186 <wangyunjian@huawei.com> wrote:
> From: Yunjian Wang <wangyunjian@huawei.com>
>
> Now it doesn't limit the number of MAC/VLAN strictly. When there is more
> elements in the virtchnl MAC/VLAN list, it can still add successfully.
You could still add but should you. I'm not clear from this patch
description what this is supposed to be addressing. If you enable the
"trust" flag for a VF via the "ip link set dev <iface> vf <vfnum>
trust on" it can make use of any resources on the device, but without
that there is an upper limit that is supposed to be enforced to
prevent the VF from making use of an excessive amount of resources.
That is what is being enforced by the code you are moving out of the
way below.
> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 27 +++++++++++++---------
> 1 file changed, 16 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
> index 4d1e670..285b96a 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
> @@ -2065,11 +2065,6 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
> dev_err(&pf->pdev->dev,
> "VF attempting to override administratively set MAC address, reload the VF driver to resume normal operation\n");
> ret = -EPERM;
> - } else if ((vf->num_mac >= I40E_VC_MAX_MAC_ADDR_PER_VF) &&
> - !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
> - dev_err(&pf->pdev->dev,
> - "VF is not trusted, switch the VF to trusted to add more functionality\n");
> - ret = -EPERM;
> }
> return ret;
> }
> @@ -2128,6 +2123,15 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
> } else {
> vf->num_mac++;
> }
> +
> + if ((vf->num_mac >= I40E_VC_MAX_MAC_ADDR_PER_VF) &&
> + !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
> + dev_err(&pf->pdev->dev,
> + "VF is not trusted, switch the VF to trusted to add more functionality\n");
> + ret = -EPERM;
> + spin_unlock_bh(&vsi->mac_filter_hash_lock);
> + goto error_param;
> + }
> }
> spin_unlock_bh(&vsi->mac_filter_hash_lock);
>
This doesn't make any sense. You are doing the checks after you have
already added the MAC. The only part you aren't doing is sending the
message to the VF indicating that the request was successful.
> @@ -2221,12 +2225,6 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
> i40e_status aq_ret = 0;
> int i;
>
> - if ((vf->num_vlan >= I40E_VC_MAX_VLAN_PER_VF) &&
> - !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
> - dev_err(&pf->pdev->dev,
> - "VF is not trusted, switch the VF to trusted to add more VLAN addresses\n");
> - goto error_param;
> - }
> if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
> !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
> aq_ret = I40E_ERR_PARAM;
> @@ -2269,6 +2267,13 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
> dev_err(&pf->pdev->dev,
> "Unable to add VLAN filter %d for VF %d, error %d\n",
> vfl->vlan_id[i], vf->vf_id, ret);
> + if ((vf->num_vlan >= I40E_VC_MAX_VLAN_PER_VF) &&
> + !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
> + dev_err(&pf->pdev->dev,
> + "VF is not trusted, switch the VF to trusted to add more VLAN addresses\n");
> + aq_ret = -EPERM;
> + goto error_param;
> + }
> }
>
> error_param:
Same here. You are doing this after the call to i40e_vsi_add_vlan. The
code makes no sense here. This bit of code is supposed to be
preventing a VF from abusing resources if the VF is not privelaged.
^ permalink raw reply
* Re: [PATCH v4 1/2] expose stack entry function
From: David Miller @ 2017-09-28 15:43 UTC (permalink / raw)
To: amine.kherbouche; +Cc: netdev, xeb, roopa, equinox
In-Reply-To: <d34f8440be3e1d735c694c6899c5a8b14e9a70ea.1506590878.git.amine.kherbouche@6wind.com>
From: Amine Kherbouche <amine.kherbouche@6wind.com>
Date: Thu, 28 Sep 2017 11:34:19 +0200
> Exporting mpls_forward() function to be able to be called from elsewhere
> such as MPLSoverGRE in the next commit.
>
> Signed-off-by: Amine Kherbouche <amine.kherbouche@6wind.com>
> Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
You need to resubmit this series with this patch having a proper
subsystem prefix in the Subject line, as pointed out by another
reviewer.
Thanks.
^ permalink raw reply
* Re: [PATCH v3] tun: bail out from tun_get_user() if the skb is empty
From: David Miller @ 2017-09-28 15:42 UTC (permalink / raw)
To: glider; +Cc: edumazet, dvyukov, syzkaller, netdev, linux-kernel
In-Reply-To: <20170928093237.121450-1-glider@google.com>
From: Alexander Potapenko <glider@google.com>
Date: Thu, 28 Sep 2017 11:32:37 +0200
> KMSAN (https://github.com/google/kmsan) reported accessing uninitialized
> skb->data[0] in the case the skb is empty (i.e. skb->len is 0):
...
> Make sure tun_get_user() doesn't touch skb->data[0] unless there is
> actual data.
...
> Signed-off-by: Alexander Potapenko <glider@google.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* [PATCH net] net: mvpp2: Fix clock resource by adding an optional bus clock
From: Gregory CLEMENT @ 2017-09-28 15:39 UTC (permalink / raw)
To: David S. Miller, linux-kernel, netdev
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Gregory CLEMENT,
Thomas Petazzoni, linux-arm-kernel, Antoine Tenart,
Miquèl Raynal, Nadav Haklai, Shadi Ammouri, Yehuda Yitschak,
Omri Itach, Hanna Hawa, Igal Liberman, Marcin Wojtas
On Armada 7K/8K we need to explicitly enable the bus clock. The bus clock
is optional because not all the SoCs need them but at least for Armada
7K/8K it is actually mandatory.
The binding documentation is updating accordingly.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
Documentation/devicetree/bindings/net/marvell-pp2.txt | 10 ++++++----
drivers/net/ethernet/marvell/mvpp2.c | 15 +++++++++++++++
2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/marvell-pp2.txt b/Documentation/devicetree/bindings/net/marvell-pp2.txt
index 7e2dad08a12e..49e1be6bb6ba 100644
--- a/Documentation/devicetree/bindings/net/marvell-pp2.txt
+++ b/Documentation/devicetree/bindings/net/marvell-pp2.txt
@@ -21,8 +21,9 @@ Required properties:
- main controller clock (for both armada-375-pp2 and armada-7k-pp2)
- GOP clock (for both armada-375-pp2 and armada-7k-pp2)
- MG clock (only for armada-7k-pp2)
-- clock-names: names of used clocks, must be "pp_clk", "gop_clk" and
- "mg_clk" (the latter only for armada-7k-pp2).
+ - AXI clock (only for armada-7k-pp2)
+- clock-names: names of used clocks, must be "pp_clk", "gop_clk", "mg_clk"
+ and "axi"(the 2 latter only for armada-7k-pp2).
The ethernet ports are represented by subnodes. At least one port is
required.
@@ -78,8 +79,9 @@ Example for marvell,armada-7k-pp2:
cpm_ethernet: ethernet@0 {
compatible = "marvell,armada-7k-pp22";
reg = <0x0 0x100000>, <0x129000 0xb000>;
- clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
- clock-names = "pp_clk", "gop_clk", "gp_clk";
+ clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>,
+ <&cpm_syscon0 1 5>, <&cpm_syscon0 1 18>;
+ clock-names = "pp_clk", "gop_clk", "gp_clk", "axi_clk";
eth0: eth0 {
interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index dd0ee2691c86..33b6791df2bb 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -792,6 +792,7 @@ struct mvpp2 {
struct clk *pp_clk;
struct clk *gop_clk;
struct clk *mg_clk;
+ struct clk *axi_clk;
/* List of pointers to port structures */
struct mvpp2_port **port_list;
@@ -7963,6 +7964,16 @@ static int mvpp2_probe(struct platform_device *pdev)
err = clk_prepare_enable(priv->mg_clk);
if (err < 0)
goto err_gop_clk;
+
+ priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
+ if (IS_ERR(priv->axi_clk)) {
+ err = PTR_ERR(priv->axi_clk);
+ priv->axi_clk = NULL;
+ } else {
+ err = clk_prepare_enable(priv->axi_clk);
+ if (err < 0)
+ goto err_gop_clk;
+ }
}
/* Get system's tclk rate */
@@ -8015,6 +8026,8 @@ static int mvpp2_probe(struct platform_device *pdev)
return 0;
err_mg_clk:
+ if (priv->axi_clk)
+ clk_disable_unprepare(priv->axi_clk);
if (priv->hw_version == MVPP22)
clk_disable_unprepare(priv->mg_clk);
err_gop_clk:
@@ -8052,6 +8065,8 @@ static int mvpp2_remove(struct platform_device *pdev)
aggr_txq->descs_dma);
}
+ if (priv->axi_clk)
+ clk_disable_unprepare(priv->axi_clk);
clk_disable_unprepare(priv->mg_clk);
clk_disable_unprepare(priv->pp_clk);
clk_disable_unprepare(priv->gop_clk);
--
2.14.1
^ permalink raw reply related
* [PATCH net-next RFC 9/9] net: dsa: mv88e6xxx: add workaround for 6341 timestamping
From: Brandon Streiff @ 2017-09-28 15:25 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, David S. Miller, Florian Fainelli, Andrew Lunn,
Vivien Didelot, Richard Cochran, Erik Hons, Brandon Streiff
In-Reply-To: <1506612341-18061-1-git-send-email-brandon.streiff@ni.com>
88E6341 devices default to timestamping at the PHY, but due to a
hardware issue, timestamps via this component are unreliable. For
this family, configure the PTP hardware to force the timestamping
to occur at the MAC.
Signed-off-by: Brandon Streiff <brandon.streiff@ni.com>
---
drivers/net/dsa/mv88e6xxx/hwtstamp.c | 13 +++++++++++++
drivers/net/dsa/mv88e6xxx/hwtstamp.h | 9 +++++++++
2 files changed, 22 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.c b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
index 825d6f0..b6aee88 100644
--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.c
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
@@ -523,6 +523,19 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
return err;
}
+ /* 88E6341 devices default to timestamping at the PHY, but this has
+ * a hardware issue that results in unreliable timestamps. Force
+ * these devices to timestamp at the MAC.
+ */
+ if (chip->info->family == MV88E6XXX_FAMILY_6341) {
+ u16 val = MV88E6341_PTP_CFG_UPDATE |
+ MV88E6341_PTP_CFG_MODE_IDX |
+ MV88E6341_PTP_CFG_MODE_TS_AT_MAC;
+ err = mv88e6xxx_ptp_write(chip, MV88E6341_PTP_CFG, val);
+ if (err)
+ return err;
+ }
+
return 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.h b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
index 1d24220..550711a 100644
--- a/drivers/net/dsa/mv88e6xxx/hwtstamp.h
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
@@ -34,6 +34,15 @@
/* Offset 0x02: Timestamp Arrival Capture Pointers */
#define MV88E6XXX_PTP_TS_ARRIVAL_PTR 0x02
+/* Offset 0x07: PTP Global Configuration */
+#define MV88E6341_PTP_CFG 0x07
+#define MV88E6341_PTP_CFG_UPDATE 0x8000
+#define MV88E6341_PTP_CFG_IDX_MASK 0x7f00
+#define MV88E6341_PTP_CFG_DATA_MASK 0x00ff
+#define MV88E6341_PTP_CFG_MODE_IDX 0x0
+#define MV88E6341_PTP_CFG_MODE_TS_AT_PHY 0x00
+#define MV88E6341_PTP_CFG_MODE_TS_AT_MAC 0x80
+
/* Offset 0x08: PTP Interrupt Status */
#define MV88E6XXX_PTP_IRQ_STATUS 0x08
--
2.1.4
^ permalink raw reply related
* [PATCH net-next RFC 8/9] net: dsa: mv88e6xxx: add rx/tx timestamping support
From: Brandon Streiff @ 2017-09-28 15:25 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, David S. Miller, Florian Fainelli, Andrew Lunn,
Vivien Didelot, Richard Cochran, Erik Hons, Brandon Streiff
In-Reply-To: <1506612341-18061-1-git-send-email-brandon.streiff@ni.com>
This patch implements RX/TX timestamping support.
The Marvell PTP hardware supports RX timestamping individual message
types, but for simplicity we only support the EVENT receive filter since
few if any clients bother with the more specific filter types.
We also utilize a feature of the "generation 3" PTP hardware that lets
us to embed the timestamp value into one of the reserved fields in the
PTP header. This lets us extract the timestamp out of the header and
avoid an SMI access in the RX codepath. (This implementation does not
presently support the older generations.)
Signed-off-by: Brandon Streiff <brandon.streiff@ni.com>
---
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 16 +-
drivers/net/dsa/mv88e6xxx/chip.h | 26 ++
drivers/net/dsa/mv88e6xxx/hwtstamp.c | 535 +++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/hwtstamp.h | 162 +++++++++++
5 files changed, 738 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/dsa/mv88e6xxx/hwtstamp.c
create mode 100644 drivers/net/dsa/mv88e6xxx/hwtstamp.h
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
index 47eda30..9bd0175 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -4,6 +4,7 @@ mv88e6xxx-objs += global1.o
mv88e6xxx-objs += global1_atu.o
mv88e6xxx-objs += global1_vtu.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o
+mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o
mv88e6xxx-objs += phy.o
mv88e6xxx-objs += port.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 4a37b26..9a0ee56 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -36,6 +36,7 @@
#include "chip.h"
#include "global1.h"
#include "global2.h"
+#include "hwtstamp.h"
#include "phy.h"
#include "port.h"
#include "ptp.h"
@@ -2034,11 +2035,15 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
if (err)
goto unlock;
- /* Setup PTP Hardware Clock */
+ /* Setup PTP Hardware Clock and timestamping */
if (chip->info->ptp_support) {
err = mv88e6xxx_ptp_setup(chip);
if (err)
goto unlock;
+
+ err = mv88e6xxx_hwtstamp_setup(chip);
+ if (err)
+ goto unlock;
}
unlock:
@@ -3851,6 +3856,11 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.port_mdb_del = mv88e6xxx_port_mdb_del,
.crosschip_bridge_join = mv88e6xxx_crosschip_bridge_join,
.crosschip_bridge_leave = mv88e6xxx_crosschip_bridge_leave,
+ .port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set,
+ .port_hwtstamp_get = mv88e6xxx_port_hwtstamp_get,
+ .port_txtstamp = mv88e6xxx_port_txtstamp,
+ .port_rxtstamp = mv88e6xxx_port_rxtstamp,
+ .get_ts_info = mv88e6xxx_get_ts_info,
};
static struct dsa_switch_driver mv88e6xxx_switch_drv = {
@@ -3979,8 +3989,10 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
struct mv88e6xxx_chip *chip = ds->priv;
- if (chip->info->ptp_support)
+ if (chip->info->ptp_support) {
+ mv88e6xxx_hwtstamp_free(chip);
mv88e6xxx_ptp_free(chip);
+ }
mv88e6xxx_phy_destroy(chip);
mv88e6xxx_unregister_switch(chip);
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index b763778..52e449b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -163,6 +163,29 @@ struct mv88e6xxx_irq {
unsigned int nirqs;
};
+/* state flags for mv88e6xxx_port_hwtstamp::state */
+enum {
+ MV88E6XXX_HWTSTAMP_ENABLED,
+ MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS,
+};
+
+struct mv88e6xxx_port_hwtstamp {
+ /* Port index */
+ int port_id;
+
+ /* Timestamping state */
+ unsigned long state;
+
+ /* Resources for transmit timestamping */
+ struct work_struct tx_tstamp_work;
+ unsigned long tx_tstamp_start;
+ struct sk_buff *tx_skb;
+ u16 tx_seq_id;
+
+ /* Current timestamp configuration */
+ struct hwtstamp_config tstamp_config;
+};
+
struct mv88e6xxx_chip {
const struct mv88e6xxx_info *info;
@@ -231,6 +254,9 @@ struct mv88e6xxx_chip {
struct ptp_pin_desc pin_config[MV88E6XXX_MAX_GPIO];
u16 trig_config;
u16 evcap_config;
+
+ /* Per-port timestamping resources. */
+ struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
};
struct mv88e6xxx_bus_ops {
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.c b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
new file mode 100644
index 0000000..825d6f0
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.c
@@ -0,0 +1,535 @@
+/*
+ * Marvell 88E6xxx Switch hardware timestamping support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2017 National Instruments
+ * Erik Hons <erik.hons@ni.com>
+ * Brandon Streiff <brandon.streiff@ni.com>
+ * Dane Wagner <dane.wagner@ni.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "chip.h"
+#include "global2.h"
+#include "hwtstamp.h"
+#include <linux/ptp_classify.h>
+
+static int mv88e6xxx_port_ptp_read(struct mv88e6xxx_chip *chip, int port,
+ int addr, u16 *data, int len)
+{
+ if (!chip->info->ops->avb_ops->port_ptp_read)
+ return -EOPNOTSUPP;
+
+ return chip->info->ops->avb_ops->port_ptp_read(chip, port, addr,
+ data, len);
+}
+
+static int mv88e6xxx_port_ptp_write(struct mv88e6xxx_chip *chip, int port,
+ int addr, u16 data)
+{
+ if (!chip->info->ops->avb_ops->port_ptp_write)
+ return -EOPNOTSUPP;
+
+ return chip->info->ops->avb_ops->port_ptp_write(chip, port, addr,
+ data);
+}
+
+static int mv88e6xxx_ptp_write(struct mv88e6xxx_chip *chip, int addr,
+ u16 data)
+{
+ if (!chip->info->ops->avb_ops->ptp_write)
+ return -EOPNOTSUPP;
+
+ return chip->info->ops->avb_ops->ptp_write(chip, addr, data);
+}
+
+/* TX_TSTAMP_TIMEOUT: This limits the time spent polling for a TX
+ * timestamp. When working properly, hardware will produce a timestamp
+ * within 1ms. Software may enounter delays due to MDIO contention, so
+ * the timeout is set accordingly.
+ */
+#define TX_TSTAMP_TIMEOUT msecs_to_jiffies(20)
+
+int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
+ struct ethtool_ts_info *info)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+
+ if (!chip->info->ptp_support)
+ return -EOPNOTSUPP;
+
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = ptp_clock_index(chip->ptp_clock);
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ);
+
+ return 0;
+}
+
+static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
+ struct hwtstamp_config *config)
+{
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
+ bool tstamp_enable = false;
+ u16 port_config0;
+ int err;
+
+ /* Prevent the TX/RX paths from trying to interact with the
+ * timestamp hardware while we reconfigure it.
+ */
+ clear_bit_unlock(MV88E6XXX_HWTSTAMP_ENABLED, &ps->state);
+
+ /* reserved for future extensions */
+ if (config->flags)
+ return -EINVAL;
+
+ switch (config->tx_type) {
+ case HWTSTAMP_TX_OFF:
+ tstamp_enable = false;
+ break;
+ case HWTSTAMP_TX_ON:
+ tstamp_enable = true;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ /* The switch supports timestamping both L2 and L4; one cannot be
+ * disabled independently of the other.
+ */
+ switch (config->rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ tstamp_enable = false;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ default:
+ config->rx_filter = HWTSTAMP_FILTER_NONE;
+ return -ERANGE;
+ }
+
+ if (tstamp_enable) {
+ /* Disable transportSpecific value matching, so that packets
+ * with either 1588 (0) and 802.1AS (1) will be timestamped.
+ */
+ port_config0 = MV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH;
+ } else {
+ /* Disable PTP. This disables both RX and TX timestamping. */
+ port_config0 = MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP;
+ }
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
+ port_config0);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err < 0)
+ return err;
+
+ /* Once hardware has been configured, enable timestamp checks
+ * in the RX/TX paths.
+ */
+ if (tstamp_enable)
+ set_bit(MV88E6XXX_HWTSTAMP_ENABLED, &ps->state);
+
+ return 0;
+}
+
+int mv88e6xxx_port_hwtstamp_set(struct dsa_switch *ds, int port,
+ struct ifreq *ifr)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
+ struct hwtstamp_config config;
+ int err;
+
+ if (!chip->info->ptp_support)
+ return -EOPNOTSUPP;
+
+ if (port < 0 || port >= mv88e6xxx_num_ports(chip))
+ return -EINVAL;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ err = mv88e6xxx_set_hwtstamp_config(chip, port, &config);
+ if (err)
+ return err;
+
+ /* Save the chosen configuration to be returned later. */
+ memcpy(&ps->tstamp_config, &config, sizeof(config));
+
+ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+ -EFAULT : 0;
+}
+
+int mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds, int port,
+ struct ifreq *ifr)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
+ struct hwtstamp_config *config = &ps->tstamp_config;
+
+ if (!chip->info->ptp_support)
+ return -EOPNOTSUPP;
+
+ if (port < 0 || port >= mv88e6xxx_num_ports(chip))
+ return -EINVAL;
+
+ return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
+ -EFAULT : 0;
+}
+
+/* Get the start of the PTP header in this skb */
+static u8 *_get_ptp_header(struct sk_buff *skb, unsigned int type)
+{
+ unsigned int offset = 0;
+ u8 *data = skb_mac_header(skb);
+
+ if (type & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ switch (type & PTP_CLASS_PMASK) {
+ case PTP_CLASS_IPV4:
+ offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+ break;
+ case PTP_CLASS_IPV6:
+ offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+ break;
+ case PTP_CLASS_L2:
+ offset += ETH_HLEN;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Ensure that the entire header is present in this packet. */
+ if (skb->len + ETH_HLEN < offset + 34)
+ return ERR_PTR(-EINVAL);
+
+ return data + offset;
+}
+
+static bool mv88e6xxx_should_tstamp(struct mv88e6xxx_chip *chip, int port,
+ struct sk_buff *skb, unsigned int type)
+{
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
+ u8 *ptp_hdr, *msgtype;
+ bool ret;
+
+ if (port < 0 || port >= mv88e6xxx_num_ports(chip))
+ return false;
+
+ ptp_hdr = _get_ptp_header(skb, type);
+ if (IS_ERR(ptp_hdr))
+ return false;
+
+ if (unlikely(type & PTP_CLASS_V1))
+ msgtype = ptp_hdr + OFF_PTP_CONTROL;
+ else
+ msgtype = ptp_hdr;
+
+ ret = test_bit(MV88E6XXX_HWTSTAMP_ENABLED, &ps->state);
+
+ dev_dbg(chip->dev,
+ "p%d: PTP message classification 0x%x type 0x%x, tstamp? %d",
+ port, type, *msgtype, (int)ret);
+
+ return ret;
+}
+
+/* rxtstamp will be called in interrupt context so we don't to do
+ * anything like read PTP registers over SMI.
+ */
+bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
+ struct sk_buff *skb, unsigned int type)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct skb_shared_hwtstamps *shhwtstamps;
+ __be32 *ptp_rx_ts;
+ u8 *ptp_hdr;
+ u32 raw_ts;
+ u64 ns;
+
+ if (!chip->info->ptp_support)
+ return false;
+
+ if (port < 0 || port >= mv88e6xxx_num_ports(chip))
+ return false;
+
+ if (!mv88e6xxx_should_tstamp(chip, port, skb, type))
+ return false;
+
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+ /* Because we configured the arrival timestamper to put the counter
+ * into the 32-bit "reserved" field of the PTP header, we can retrieve
+ * the value from the packet directly instead of having to retrieve it
+ * via SMI.
+ */
+ ptp_hdr = _get_ptp_header(skb, type);
+ if (IS_ERR(ptp_hdr))
+ return false;
+ ptp_rx_ts = (__be32 *)(ptp_hdr + OFF_PTP_RESERVED);
+ raw_ts = __be32_to_cpu(*ptp_rx_ts);
+ ns = timecounter_cyc2time(&chip->tstamp_tc, raw_ts);
+ shhwtstamps->hwtstamp = ns_to_ktime(ns);
+
+ dev_dbg(chip->dev, "p%d: rxtstamp %llx\n", port, ns);
+
+ return false;
+}
+
+static void mv88e6xxx_txtstamp_work(struct work_struct *ugly)
+{
+ struct mv88e6xxx_port_hwtstamp *ps = container_of(
+ ugly, struct mv88e6xxx_port_hwtstamp, tx_tstamp_work);
+ struct mv88e6xxx_chip *chip = container_of(
+ ps, struct mv88e6xxx_chip, port_hwtstamp[ps->port_id]);
+ struct sk_buff *tmp_skb;
+ unsigned long tmp_tstamp_start;
+ int err;
+ u16 departure_block[4];
+ u16 tmp_seq_id;
+
+ if (!test_bit(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS, &ps->state))
+ return;
+
+ tmp_skb = ps->tx_skb;
+ tmp_seq_id = ps->tx_seq_id;
+ tmp_tstamp_start = ps->tx_tstamp_start;
+
+ if (!tmp_skb)
+ return;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_port_ptp_read(chip, ps->port_id,
+ MV88E6XXX_PORT_PTP_DEP_STS,
+ departure_block,
+ ARRAY_SIZE(departure_block));
+ mutex_unlock(&chip->reg_lock);
+
+ if (err)
+ goto free_and_clear_skb;
+
+ if (departure_block[0] & MV88E6XXX_PTP_TS_VALID) {
+ struct skb_shared_hwtstamps shhwtstamps;
+ u64 ns;
+ u32 time_raw;
+ u16 status;
+
+ /* We have the timestamp; go ahead and clear valid now */
+ mutex_lock(&chip->reg_lock);
+ mv88e6xxx_port_ptp_write(chip, ps->port_id,
+ MV88E6XXX_PORT_PTP_DEP_STS, 0);
+ mutex_unlock(&chip->reg_lock);
+
+ status = departure_block[0] &
+ MV88E6XXX_PTP_TS_STATUS_MASK;
+ if (status != MV88E6XXX_PTP_TS_STATUS_NORMAL) {
+ dev_warn(chip->dev, "p%d: tx timestamp overrun\n",
+ ps->port_id);
+ goto free_and_clear_skb;
+ }
+
+ if (departure_block[3] != tmp_seq_id) {
+ dev_warn(chip->dev, "p%d: unexpected sequence id\n",
+ ps->port_id);
+ goto free_and_clear_skb;
+ }
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ time_raw = ((u32)departure_block[2] << 16) |
+ departure_block[1];
+ ns = timecounter_cyc2time(&chip->tstamp_tc, time_raw);
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+
+ dev_dbg(chip->dev,
+ "p%d: txtstamp %llx status 0x%04x skb ID 0x%04x hw ID 0x%04x\n",
+ ps->port_id, ktime_to_ns(shhwtstamps.hwtstamp),
+ departure_block[0], tmp_seq_id, departure_block[3]);
+
+ /* skb_complete_tx_timestamp() will free up the client to make
+ * another timestamp-able transmit. We have to be ready for it
+ * -- by clearing the ps->tx_skb "flag" -- beforehand.
+ */
+
+ ps->tx_skb = NULL;
+ clear_bit_unlock(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS, &ps->state);
+
+ skb_complete_tx_timestamp(tmp_skb, &shhwtstamps);
+
+ } else {
+ if (time_is_before_jiffies(
+ tmp_tstamp_start + TX_TSTAMP_TIMEOUT)) {
+ dev_warn(chip->dev, "p%d: clearing tx timestamp hang\n",
+ ps->port_id);
+ goto free_and_clear_skb;
+ }
+
+ /* The timestamp should be available quickly, while getting it
+ * is high priority and time bounded to only 10ms. A poll is
+ * warranted and this is the nicest way to realize it in a work
+ * item.
+ */
+
+ queue_work(system_highpri_wq, &ps->tx_tstamp_work);
+ }
+
+ return;
+
+free_and_clear_skb:
+ ps->tx_skb = NULL;
+ clear_bit_unlock(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS, &ps->state);
+
+ dev_kfree_skb_any(tmp_skb);
+}
+
+void mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
+ struct sk_buff *clone, unsigned int type)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
+
+ if (!chip->info->ptp_support)
+ return;
+
+ if (port < 0 || port >= mv88e6xxx_num_ports(chip))
+ goto out;
+
+ if (unlikely(skb_shinfo(clone)->tx_flags & SKBTX_HW_TSTAMP) &&
+ mv88e6xxx_should_tstamp(chip, port, clone, type)) {
+ __be16 *seq_ptr = (__be16 *)(_get_ptp_header(clone, type) +
+ OFF_PTP_SEQUENCE_ID);
+
+ if (!test_and_set_bit_lock(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS,
+ &ps->state)) {
+ ps->tx_skb = clone;
+ ps->tx_tstamp_start = jiffies;
+ ps->tx_seq_id = be16_to_cpup(seq_ptr);
+
+ /* Fetching the timestamp is high-priority work because
+ * 802.1AS bounds the time for a response.
+ *
+ * No need to check result of queue_work(). ps->tx_skb
+ * check ensures work item is not pending (it may be
+ * waiting to exit)
+ */
+ queue_work(system_highpri_wq, &ps->tx_tstamp_work);
+ return;
+ }
+
+ /* Otherwise we're already in progress... */
+ dev_dbg(chip->dev,
+ "p%d: tx timestamp already in progress, discarding",
+ port);
+ }
+
+out:
+ /* We don't need it after all. */
+ kfree_skb(clone);
+}
+
+static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)
+{
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
+
+ ps->port_id = port;
+ INIT_WORK(&ps->tx_tstamp_work, mv88e6xxx_txtstamp_work);
+
+ return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
+ MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP);
+}
+
+static void mv88e6xxx_hwtstamp_port_free(struct mv88e6xxx_chip *chip, int port)
+{
+ struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
+
+ cancel_work_sync(&ps->tx_tstamp_work);
+}
+
+int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
+{
+ int i;
+ int err;
+
+ /* Disable timestamping on all ports. */
+ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
+ err = mv88e6xxx_hwtstamp_port_setup(chip, i);
+ if (err)
+ return err;
+ }
+
+ /* MV88E6XXX_PTP_MSG_TYPE is a mask of PTP message types to
+ * timestamp. This affects all ports that have timestamping enabled,
+ * but the timestamp config is per-port; thus we configure all events
+ * here and only support the HWTSTAMP_FILTER_*_EVENT filter types.
+ */
+ err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_MSGTYPE,
+ MV88E6XXX_PTP_MSGTYPE_ALL_EVENT);
+ if (err)
+ return err;
+
+ /* Each event type will be timestamped using ARRIVAL0. */
+ err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_TS_ARRIVAL_PTR, 0x0);
+ if (err)
+ return err;
+
+ /* Configure the switch to embed the (32-bit) arrival timestamps in
+ * the packets, in the "reserved" field of the PTP header at octet 16
+ * (OFF_PTP_RESERVED), and disable interrupts. When we do the per-port
+ * configuration later, we will also allow overwrites (by not setting
+ * the DISABLE_OVERWRITE bit). This combination lets us handle
+ * back-to-back RX packets easily, because we don't have to do an SMI
+ * access to retrieve the timestamp.
+ */
+ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
+ u16 val = MV88E6XXX_PORT_PTP_CFG2_EMBED_ARRIVAL;
+
+ err = mv88e6xxx_port_ptp_write(chip, i,
+ MV88E6XXX_PORT_PTP_CFG2, val);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip)
+{
+ int i;
+
+ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
+ mv88e6xxx_hwtstamp_port_free(chip, i);
+}
diff --git a/drivers/net/dsa/mv88e6xxx/hwtstamp.h b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
new file mode 100644
index 0000000..1d24220
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/hwtstamp.h
@@ -0,0 +1,162 @@
+/*
+ * Marvell 88E6xxx Switch hardware timestamping support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2017 National Instruments
+ * Erik Hons <erik.hons@ni.com>
+ * Brandon Streiff <brandon.streiff@ni.com>
+ * Dane Wagner <dane.wagner@ni.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _MV88E6XXX_HWTSTAMP_H
+#define _MV88E6XXX_HWTSTAMP_H
+
+#include "chip.h"
+
+/* Global PTP registers */
+/* Offset 0x00: PTP EtherType */
+#define MV88E6XXX_PTP_ETHERTYPE 0x00
+
+/* Offset 0x01: Message Type Timestamp Enables */
+#define MV88E6XXX_PTP_MSGTYPE 0x01
+#define MV88E6XXX_PTP_MSGTYPE_SYNC 0x0001
+#define MV88E6XXX_PTP_MSGTYPE_DELAY_REQ 0x0002
+#define MV88E6XXX_PTP_MSGTYPE_PDLAY_REQ 0x0004
+#define MV88E6XXX_PTP_MSGTYPE_PDLAY_RES 0x0008
+#define MV88E6XXX_PTP_MSGTYPE_ALL_EVENT 0x000f
+
+/* Offset 0x02: Timestamp Arrival Capture Pointers */
+#define MV88E6XXX_PTP_TS_ARRIVAL_PTR 0x02
+
+/* Offset 0x08: PTP Interrupt Status */
+#define MV88E6XXX_PTP_IRQ_STATUS 0x08
+
+/* Per-Port PTP Registers */
+/* Offset 0x00: PTP Configuration 0 */
+#define MV88E6XXX_PORT_PTP_CFG0 0x00
+#define MV88E6XXX_PORT_PTP_CFG0_TSPEC_SHIFT 12
+#define MV88E6XXX_PORT_PTP_CFG0_TSPEC_MASK 0xf000
+#define MV88E6XXX_PORT_PTP_CFG0_TSPEC_1588 0x0000
+#define MV88E6XXX_PORT_PTP_CFG0_TSPEC_8021AS 0x1000
+#define MV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH 0x0800
+#define MV88E6XXX_PORT_PTP_CFG0_DISABLE_OVERWRITE 0x0002
+#define MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP 0x0001
+
+/* Offset 0x01: PTP Configuration 1 */
+#define MV88E6XXX_PORT_PTP_CFG1 0x01
+
+/* Offset 0x02: PTP Configuration 2 */
+#define MV88E6XXX_PORT_PTP_CFG2 0x02
+#define MV88E6XXX_PORT_PTP_CFG2_EMBED_ARRIVAL 0x1000
+#define MV88E6XXX_PORT_PTP_CFG2_DEP_IRQ_EN 0x0002
+#define MV88E6XXX_PORT_PTP_CFG2_ARR_IRQ_EN 0x0001
+
+/* Offset 0x03: PTP LED Configuration */
+#define MV88E6XXX_PORT_PTP_LED_CFG 0x03
+
+/* Offset 0x08: PTP Arrival 0 Status */
+#define MV88E6XXX_PORT_PTP_ARR0_STS 0x08
+
+/* Offset 0x09/0x0A: PTP Arrival 0 Time */
+#define MV88E6XXX_PORT_PTP_ARR0_TIME_LO 0x09
+#define MV88E6XXX_PORT_PTP_ARR0_TIME_HI 0x0a
+
+/* Offset 0x0B: PTP Arrival 0 Sequence ID */
+#define MV88E6XXX_PORT_PTP_ARR0_SEQID 0x0b
+
+/* Offset 0x0C: PTP Arrival 1 Status */
+#define MV88E6XXX_PORT_PTP_ARR1_STS 0x0c
+
+/* Offset 0x0D/0x0E: PTP Arrival 1 Time */
+#define MV88E6XXX_PORT_PTP_ARR1_TIME_LO 0x0d
+#define MV88E6XXX_PORT_PTP_ARR1_TIME_HI 0x0e
+
+/* Offset 0x0F: PTP Arrival 1 Sequence ID */
+#define MV88E6XXX_PORT_PTP_ARR1_SEQID 0x0f
+
+/* Offset 0x10: PTP Departure Status */
+#define MV88E6XXX_PORT_PTP_DEP_STS 0x10
+
+/* Offset 0x11/0x12: PTP Deperture Time */
+#define MV88E6XXX_PORT_PTP_DEP_TIME_LO 0x11
+#define MV88E6XXX_PORT_PTP_DEP_TIME_HI 0x12
+
+/* Offset 0x13: PTP Departure Sequence ID */
+#define MV88E6XXX_PORT_PTP_DEP_SEQID 0x13
+
+/* Status fields for arrival and depature timestamp status registers */
+#define MV88E6XXX_PTP_TS_STATUS_MASK 0x0006
+#define MV88E6XXX_PTP_TS_STATUS_NORMAL 0x0000
+#define MV88E6XXX_PTP_TS_STATUS_OVERWITTEN 0x0002
+#define MV88E6XXX_PTP_TS_STATUS_DISCARDED 0x0004
+#define MV88E6XXX_PTP_TS_VALID 0x0001
+
+#ifdef CONFIG_NET_DSA_MV88E6XXX_PTP
+
+int mv88e6xxx_port_hwtstamp_set(struct dsa_switch *ds, int port,
+ struct ifreq *ifr);
+int mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds, int port,
+ struct ifreq *ifr);
+
+bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
+ struct sk_buff *clone, unsigned int type);
+void mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
+ struct sk_buff *clone, unsigned int type);
+
+int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
+ struct ethtool_ts_info *info);
+
+int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip);
+
+#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
+
+static inline int mv88e6xxx_port_hwtstamp_set(struct dsa_switch *ds,
+ int port, struct ifreq *ifr)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds,
+ int port, struct ifreq *ifr)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
+ struct sk_buff *clone,
+ unsigned int type)
+{
+ return false;
+}
+
+static inline void mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
+ struct sk_buff *clone,
+ unsigned int type)
+{
+}
+
+static inline int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
+ struct ethtool_ts_info *info);
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip)
+{
+}
+
+#endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */
+
+#endif /* _MV88E6XXX_HWTSTAMP_H */
--
2.1.4
^ permalink raw reply related
* [PATCH net-next RFC 7/9] ptp: add offset for reserved field to header
From: Brandon Streiff @ 2017-09-28 15:25 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, David S. Miller, Florian Fainelli, Andrew Lunn,
Vivien Didelot, Richard Cochran, Erik Hons, Brandon Streiff
In-Reply-To: <1506612341-18061-1-git-send-email-brandon.streiff@ni.com>
There is a four-byte "reserved" field at octet 16 in PTPv2.
Signed-off-by: Brandon Streiff <brandon.streiff@ni.com>
---
include/linux/ptp_classify.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h
index a079656..b9b0073 100644
--- a/include/linux/ptp_classify.h
+++ b/include/linux/ptp_classify.h
@@ -47,6 +47,7 @@
#define PTP_EV_PORT 319
#define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type */
+#define OFF_PTP_RESERVED 16 /* PTPv2 only */
#define OFF_PTP_SOURCE_UUID 22 /* PTPv1 only */
#define OFF_PTP_SEQUENCE_ID 30
#define OFF_PTP_CONTROL 32 /* PTPv1 only */
--
2.1.4
^ permalink raw reply related
* [PATCH net-next RFC 6/9] net: dsa: forward timestamping callbacks to switch drivers
From: Brandon Streiff @ 2017-09-28 15:25 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, David S. Miller, Florian Fainelli, Andrew Lunn,
Vivien Didelot, Richard Cochran, Erik Hons, Brandon Streiff
In-Reply-To: <1506612341-18061-1-git-send-email-brandon.streiff@ni.com>
Forward the rx/tx timestamp machinery from the dsa infrastructure to the
switch driver.
On the rx side, defer delivery of skbs until we have an rx timestamp.
This mimicks the behavior of skb_defer_rx_timestamp. The implementation
does have to thread through the tagging protocol handlers because
it is where that we know which switch and port the skb goes to.
On the tx side, identify PTP packets, clone them, and pass them to the
underlying switch driver before we transmit. This mimicks the behavior
of skb_tx_timestamp.
Signed-off-by: Brandon Streiff <brandon.streiff@ni.com>
---
include/net/dsa.h | 13 +++++++++++--
net/dsa/dsa.c | 39 ++++++++++++++++++++++++++++++++++++++-
net/dsa/slave.c | 25 +++++++++++++++++++++++++
net/dsa/tag_brcm.c | 6 +++++-
net/dsa/tag_dsa.c | 6 +++++-
net/dsa/tag_edsa.c | 6 +++++-
net/dsa/tag_ksz.c | 6 +++++-
net/dsa/tag_lan9303.c | 6 +++++-
net/dsa/tag_mtk.c | 6 +++++-
net/dsa/tag_qca.c | 6 +++++-
net/dsa/tag_trailer.c | 6 +++++-
11 files changed, 114 insertions(+), 11 deletions(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 1163af1..4daf7f7 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -101,11 +101,14 @@ struct dsa_platform_data {
};
struct packet_type;
+struct dsa_switch;
struct dsa_device_ops {
struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt);
+ struct packet_type *pt,
+ struct dsa_switch **src_dev,
+ int *src_port);
int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
int *offset);
};
@@ -134,7 +137,9 @@ struct dsa_switch_tree {
/* Copy of tag_ops->rcv for faster access in hot path */
struct sk_buff * (*rcv)(struct sk_buff *skb,
struct net_device *dev,
- struct packet_type *pt);
+ struct packet_type *pt,
+ struct dsa_switch **src_dev,
+ int *src_port);
/*
* The switch port to which the CPU is attached.
@@ -449,6 +454,10 @@ struct dsa_switch_ops {
struct ifreq *ifr);
int (*port_hwtstamp_set)(struct dsa_switch *ds, int port,
struct ifreq *ifr);
+ void (*port_txtstamp)(struct dsa_switch *ds, int port,
+ struct sk_buff *clone, unsigned int type);
+ bool (*port_rxtstamp)(struct dsa_switch *ds, int port,
+ struct sk_buff *skb, unsigned int type);
};
struct dsa_switch_driver {
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 81c852e..42e7286 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -22,6 +22,7 @@
#include <linux/netdevice.h>
#include <linux/sysfs.h>
#include <linux/phy_fixed.h>
+#include <linux/ptp_classify.h>
#include <linux/gpio/consumer.h>
#include <linux/etherdevice.h>
@@ -157,6 +158,37 @@ struct net_device *dsa_dev_to_net_device(struct device *dev)
}
EXPORT_SYMBOL_GPL(dsa_dev_to_net_device);
+/* Determine if we should defer delivery of skb until we have a rx timestamp.
+ *
+ * Called from dsa_switch_rcv. For now, this will only work if tagging is
+ * enabled on the switch. Normally the MAC driver would retrieve the hardware
+ * timestamp when it reads the packet out of the hardware. However in a DSA
+ * switch, the DSA driver owning the interface to which the packet is
+ * delivered is never notified unless we do so here.
+ */
+static bool dsa_skb_defer_rx_timestamp(struct dsa_switch *ds, int port,
+ struct sk_buff *skb)
+{
+ unsigned int type;
+
+ if (skb_headroom(skb) < ETH_HLEN)
+ return false;
+
+ __skb_push(skb, ETH_HLEN);
+
+ type = ptp_classify_raw(skb);
+
+ __skb_pull(skb, ETH_HLEN);
+
+ if (type == PTP_CLASS_NONE)
+ return false;
+
+ if (likely(ds->ops->port_rxtstamp))
+ return ds->ops->port_rxtstamp(ds, port, skb, type);
+
+ return false;
+}
+
static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *unused)
{
@@ -164,6 +196,8 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
struct sk_buff *nskb = NULL;
struct pcpu_sw_netstats *s;
struct dsa_slave_priv *p;
+ struct dsa_switch *ds = NULL;
+ int source_port;
if (unlikely(dst == NULL)) {
kfree_skb(skb);
@@ -174,7 +208,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
if (!skb)
return 0;
- nskb = dst->rcv(skb, dev, pt);
+ nskb = dst->rcv(skb, dev, pt, &ds, &source_port);
if (!nskb) {
kfree_skb(skb);
return 0;
@@ -192,6 +226,9 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
s->rx_bytes += skb->len;
u64_stats_update_end(&s->syncp);
+ if (dsa_skb_defer_rx_timestamp(ds, source_port, skb))
+ return 0;
+
netif_receive_skb(skb);
return 0;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 2cf6a83..a278335 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -22,6 +22,7 @@
#include <net/tc_act/tc_mirred.h>
#include <linux/if_bridge.h>
#include <linux/netpoll.h>
+#include <linux/ptp_classify.h>
#include "dsa_priv.h"
@@ -407,6 +408,25 @@ static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev,
return NETDEV_TX_OK;
}
+static void dsa_skb_tx_timestamp(struct dsa_slave_priv *p,
+ struct sk_buff *skb)
+{
+ struct dsa_switch *ds = p->dp->ds;
+ struct sk_buff *clone;
+ unsigned int type;
+
+ type = ptp_classify_raw(skb);
+ if (type == PTP_CLASS_NONE)
+ return;
+
+ if (ds->ops->port_txtstamp) {
+ clone = skb_clone_sk(skb);
+ if (!clone)
+ return;
+ ds->ops->port_txtstamp(ds, p->dp->index, clone, type);
+ }
+}
+
static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);
@@ -419,6 +439,11 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
s->tx_bytes += skb->len;
u64_stats_update_end(&s->syncp);
+ /* Identify PTP protocol packets, clone them, and pass them to the
+ * switch driver
+ */
+ dsa_skb_tx_timestamp(p, skb);
+
/* Transmit function may have to reallocate the original SKB,
* in which case it must have freed it. Only free it here on error.
*/
diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c
index dbb0164..1c8b1c9 100644
--- a/net/dsa/tag_brcm.c
+++ b/net/dsa/tag_brcm.c
@@ -90,7 +90,8 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev
}
static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
@@ -131,6 +132,9 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = ds->ports[source_port].netdev;
+ *src_dev = ds;
+ *src_port = source_port;
+
return skb;
}
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index fbf9ca9..2abcd01 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -65,7 +65,8 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
}
static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
@@ -155,6 +156,9 @@ static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = ds->ports[source_port].netdev;
+ *src_dev = ds;
+ *src_port = source_port;
+
return skb;
}
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index 76367ba..bc529e5 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -78,7 +78,8 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
}
static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
@@ -174,6 +175,9 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = ds->ports[source_port].netdev;
+ *src_dev = ds;
+ *src_port = source_port;
+
return skb;
}
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index 010ca0a..7760862 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -78,7 +78,8 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
}
static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
@@ -96,6 +97,9 @@ static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = ds->ports[source_port].netdev;
+ *src_dev = ds;
+ *src_port = source_port;
+
return skb;
}
diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c
index 0b98261..adabd48 100644
--- a/net/dsa/tag_lan9303.c
+++ b/net/dsa/tag_lan9303.c
@@ -68,7 +68,8 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
}
static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
u16 *lan9303_tag;
struct dsa_switch_tree *dst = dev->dsa_ptr;
@@ -123,6 +124,9 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
/* forward the packet to the dedicated interface */
skb->dev = ds->ports[source_port].netdev;
+ *src_dev = ds;
+ *src_port = source_port;
+
return skb;
}
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index ec8ee5f..321d1a6 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -44,7 +44,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
}
static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
@@ -83,6 +84,9 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = ds->ports[port].netdev;
+ *src_dev = ds;
+ *src_port = port;
+
return skb;
}
diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c
index 1d4c707..de51fe6e 100644
--- a/net/dsa/tag_qca.c
+++ b/net/dsa/tag_qca.c
@@ -63,7 +63,8 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
}
static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
@@ -107,6 +108,9 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
/* Update skb & forward the frame accordingly */
skb->dev = ds->ports[port].netdev;
+ *src_dev = ds;
+ *src_port = port;
+
return skb;
}
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index d2fd492..ca5960f 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -56,7 +56,8 @@ static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
}
static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt)
+ struct packet_type *pt,
+ struct dsa_switch **src_dev, int *src_port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
@@ -80,6 +81,9 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
skb->dev = ds->ports[source_port].netdev;
+ *src_dev = ds;
+ *src_port = source_port;
+
return skb;
}
--
2.1.4
^ permalink raw reply related
* [PATCH net-next RFC 5/9] net: dsa: forward hardware timestamping ioctls to switch driver
From: Brandon Streiff @ 2017-09-28 15:25 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, David S. Miller, Florian Fainelli, Andrew Lunn,
Vivien Didelot, Richard Cochran, Erik Hons, Brandon Streiff
In-Reply-To: <1506612341-18061-1-git-send-email-brandon.streiff@ni.com>
This patch adds support to the dsa slave network device so that
switch drivers can implement the SIOC[GS]HWTSTAMP ioctls and the
ethtool timestamp-info interface.
Signed-off-by: Brandon Streiff <brandon.streiff@ni.com>
---
include/net/dsa.h | 15 +++++++++++++++
net/dsa/slave.c | 39 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 8dee216..1163af1 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -19,6 +19,7 @@
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/ethtool.h>
+#include <linux/net_tstamp.h>
#include <net/devlink.h>
#include <net/switchdev.h>
@@ -329,6 +330,12 @@ struct dsa_switch_ops {
struct ethtool_wolinfo *w);
/*
+ * ethtool timestamp info
+ */
+ int (*get_ts_info)(struct dsa_switch *ds, int port,
+ struct ethtool_ts_info *ts);
+
+ /*
* Suspend and resume
*/
int (*suspend)(struct dsa_switch *ds);
@@ -434,6 +441,14 @@ struct dsa_switch_ops {
int port, struct net_device *br);
void (*crosschip_bridge_leave)(struct dsa_switch *ds, int sw_index,
int port, struct net_device *br);
+
+ /*
+ * PTP functionality
+ */
+ int (*port_hwtstamp_get)(struct dsa_switch *ds, int port,
+ struct ifreq *ifr);
+ int (*port_hwtstamp_set)(struct dsa_switch *ds, int port,
+ struct ifreq *ifr);
};
struct dsa_switch_driver {
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index bf8800d..2cf6a83 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -264,10 +264,34 @@ dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->dp->ds;
+ int port = p->dp->index;
+
if (!dev->phydev)
return -ENODEV;
- return phy_mii_ioctl(dev->phydev, ifr, cmd);
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ if (dev->phydev)
+ return phy_mii_ioctl(dev->phydev, ifr, cmd);
+ else
+ return -EOPNOTSUPP;
+ case SIOCGHWTSTAMP:
+ if (ds->ops->port_hwtstamp_get)
+ return ds->ops->port_hwtstamp_get(ds, port, ifr);
+ else
+ return -EOPNOTSUPP;
+ case SIOCSHWTSTAMP:
+ if (ds->ops->port_hwtstamp_set)
+ return ds->ops->port_hwtstamp_set(ds, port, ifr);
+ else
+ return -EOPNOTSUPP;
+ default:
+ return -EOPNOTSUPP;
+ }
}
static int dsa_slave_port_attr_set(struct net_device *dev,
@@ -876,6 +900,18 @@ static int dsa_slave_set_rxnfc(struct net_device *dev,
return ds->ops->set_rxnfc(ds, p->dp->index, nfc);
}
+static int dsa_slave_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *ts)
+{
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->dp->ds;
+
+ if (!ds->ops->get_ts_info)
+ return -EOPNOTSUPP;
+
+ return ds->ops->get_ts_info(ds, p->dp->index, ts);
+}
+
static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_drvinfo = dsa_slave_get_drvinfo,
.get_regs_len = dsa_slave_get_regs_len,
@@ -896,6 +932,7 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.set_link_ksettings = phy_ethtool_set_link_ksettings,
.get_rxnfc = dsa_slave_get_rxnfc,
.set_rxnfc = dsa_slave_set_rxnfc,
+ .get_ts_info = dsa_slave_get_ts_info,
};
static const struct net_device_ops dsa_slave_netdev_ops = {
--
2.1.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox