* Re: [PATCH v2 net-next 4/6] udp: flow dissector offload
From: Paolo Abeni @ 2017-08-30 10:36 UTC (permalink / raw)
To: Tom Herbert, davem; +Cc: netdev
In-Reply-To: <20170829232711.1465-5-tom@quantonium.net>
On Tue, 2017-08-29 at 16:27 -0700, Tom Herbert wrote:
> Add support to perform UDP specific flow dissection. This is
> primarily intended for dissecting encapsulated packets in UDP
> encapsulation.
>
> This patch adds a flow_dissect offload for UDP4 and UDP6. The backend
> function performs a socket lookup and calls the flow_dissect function
> if a socket is found.
>
> Signed-off-by: Tom Herbert <tom@quantonium.net>
> ---
> include/linux/udp.h | 8 ++++++++
> include/net/udp.h | 8 ++++++++
> include/net/udp_tunnel.h | 8 ++++++++
> net/ipv4/udp_offload.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> net/ipv4/udp_tunnel.c | 1 +
> net/ipv6/udp_offload.c | 13 +++++++++++++
> 6 files changed, 83 insertions(+)
>
> diff --git a/include/linux/udp.h b/include/linux/udp.h
> index eaea63bc79bb..2e90b189ef6a 100644
> --- a/include/linux/udp.h
> +++ b/include/linux/udp.h
> @@ -79,6 +79,14 @@ struct udp_sock {
> int (*gro_complete)(struct sock *sk,
> struct sk_buff *skb,
> int nhoff);
> + /* Flow dissector function for a UDP socket */
> + enum flow_dissect_ret (*flow_dissect)(struct sock *sk,
> + const struct sk_buff *skb,
> + struct flow_dissector_key_control *key_control,
> + struct flow_dissector *flow_dissector,
> + void *target_container, void *data,
> + __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
> + int *p_hlen, unsigned int flags);
>
> /* udp_recvmsg try to use this before splicing sk_receive_queue */
> struct sk_buff_head reader_queue ____cacheline_aligned_in_smp;
> diff --git a/include/net/udp.h b/include/net/udp.h
> index f3d1de6f0983..499e4faf8b14 100644
> --- a/include/net/udp.h
> +++ b/include/net/udp.h
> @@ -174,6 +174,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
> struct udphdr *uh, udp_lookup_t lookup);
> int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup);
>
> +enum flow_dissect_ret udp_flow_dissect(const struct sk_buff *skb,
> + udp_lookup_t lookup,
> + struct flow_dissector_key_control *key_control,
> + struct flow_dissector *flow_dissector,
> + void *target_container, void *data,
> + __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
> + int *p_hlen, unsigned int flags);
> +
> static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)
> {
> struct udphdr *uh;
> diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
> index 10cce0dd4450..b7102e0f41a9 100644
> --- a/include/net/udp_tunnel.h
> +++ b/include/net/udp_tunnel.h
> @@ -69,6 +69,13 @@ typedef struct sk_buff **(*udp_tunnel_gro_receive_t)(struct sock *sk,
> struct sk_buff *skb);
> typedef int (*udp_tunnel_gro_complete_t)(struct sock *sk, struct sk_buff *skb,
> int nhoff);
> +typedef enum flow_dissect_ret (*udp_tunnel_flow_dissect_t)(struct sock *sk,
> + const struct sk_buff *skb,
> + struct flow_dissector_key_control *key_control,
> + struct flow_dissector *flow_dissector,
> + void *target_container, void *data,
> + __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
> + int *p_hlen, unsigned int flags);
>
> struct udp_tunnel_sock_cfg {
> void *sk_user_data; /* user data used by encap_rcv call back */
> @@ -78,6 +85,7 @@ struct udp_tunnel_sock_cfg {
> udp_tunnel_encap_destroy_t encap_destroy;
> udp_tunnel_gro_receive_t gro_receive;
> udp_tunnel_gro_complete_t gro_complete;
> + udp_tunnel_flow_dissect_t flow_dissect;
> };
>
> /* Setup the given (UDP) sock to receive UDP encapsulated packets */
> diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
> index 97658bfc1b58..7f0a7ed4a6f7 100644
> --- a/net/ipv4/udp_offload.c
> +++ b/net/ipv4/udp_offload.c
> @@ -328,11 +328,56 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
> return udp_gro_complete(skb, nhoff, udp4_lib_lookup_skb);
> }
>
> +enum flow_dissect_ret udp_flow_dissect(const struct sk_buff *skb,
> + udp_lookup_t lookup,
> + struct flow_dissector_key_control *key_control,
> + struct flow_dissector *flow_dissector,
> + void *target_container, void *data,
> + __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
> + int *p_hlen, unsigned int flags)
> +{
> + enum flow_dissect_ret ret = FLOW_DISSECT_RET_CONTINUE;
> + struct udphdr *uh, _uh;
> + struct sock *sk;
> +
> + uh = __skb_header_pointer(skb, *p_nhoff, sizeof(_uh), data,
> + *p_hlen, &_uh);
> + if (!uh)
> + return FLOW_DISSECT_RET_OUT_BAD;
> +
> + rcu_read_lock();
> +
> + sk = (*lookup)(skb, uh->source, uh->dest);
> +
> + if (sk && udp_sk(sk)->flow_dissect)
> + ret = udp_sk(sk)->flow_dissect(sk, skb, key_control,
> + flow_dissector, target_container,
> + data, p_proto, p_ip_proto,
> + p_nhoff, p_hlen, flags);
> + rcu_read_unlock();
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(udp_flow_dissect);
If I read the above correctly, this is going to add another full UDP
lookup per UDP packet, can we avoid it with some static key enabled by
vxlan/fou/etc. ?
Thanks,
Paolo
^ permalink raw reply
* Re: Question about ip_defrag
From: Jesper Dangaard Brouer @ 2017-08-30 10:58 UTC (permalink / raw)
To: Florian Westphal
Cc: liujian (CE), davem@davemloft.net, edumazet@google.com,
netdev@vger.kernel.org, Wangkefeng (Kevin), weiyongjun (A),
brouer
In-Reply-To: <20170829075315.GA9993@breakpoint.cc>
(trimmed CC list a bit)
On Tue, 29 Aug 2017 09:53:15 +0200 Florian Westphal <fw@strlen.de> wrote:
> Jesper Dangaard Brouer <brouer@redhat.com> wrote:
> > On Mon, 28 Aug 2017 16:00:32 +0200
> > Florian Westphal <fw@strlen.de> wrote:
> >
> > > liujian (CE) <liujian56@huawei.com> wrote:
> > > > Hi
> > > >
> > > > I checked our 3.10 kernel, we had backported all percpu_counter
> > > > bug fix in lib/percpu_counter.c and include/linux/percpu_counter.h.
> > > > And I check 4.13-rc6, also has the issue if NIC's rx cpu num big enough.
> > > >
> > > > > > > > the issue:
> > > > > > > > Ip_defrag fail caused by frag_mem_limit reached 4M(frags.high_thresh).
> > > > > > > > At this moment,sum_frag_mem_limit is about 10K.
> > > >
> > > > So should we change ipfrag high/low thresh to a reasonable value ?
> > > > And if it is, is there a standard to change the value?
> > >
> > > Each cpu can have frag_percpu_counter_batch bytes rest doesn't know
> > > about so with 64 cpus that is ~8 mbyte.
> > >
> > > possible solutions:
> > > 1. reduce frag_percpu_counter_batch to 16k or so
> > > 2. make both low and high thresh depend on NR_CPUS
>
> I take 2) back. Its wrong to do this, for large NR_CPU values it
> would even overflow.
Alternatively solution 3:
Why do we want to maintain a (4MBytes) memory limit, across all CPUs?
Couldn't we just allow each CPU to have a memory limit?
> > To me it looks like we/I have been using the wrong API for comparing
> > against percpu_counters. I guess we should have used __percpu_counter_compare().
>
> Are you sure? For liujian use case (64 cores) it looks like we would
> always fall through to percpu_counter_sum() so we eat spinlock_irqsave
> cost for all compares.
>
> Before we entertain this we should consider reducing frag_percpu_counter_batch
> to a smaller value.
Yes, I agree, we really need to lower/reduce the frag_percpu_counter_batch.
As you say, else the __percpu_counter_compare() call will be useless
(around systems with >= 32 CPUs).
I think the bug is in frag_mem_limit(). It just reads the global
counter (fbc->count), without considering other CPUs can have upto 130K
that haven't been subtracted yet (due to 3M low limit, become dangerous
at >=24 CPUs). The __percpu_counter_compare() does the right thing,
and takes into account the number of (online) CPUs and batch size, to
account for this.
If we choose 16K (16384), and use __percpu_counter_compare(), then we
can scale to systems with 256 CPUs (4*1024*1024/16384=256), before this
memory accounting becomes more expensive (than not using percpu_counters).
But Liujian, reports he have a 384 CPU system, so he would still need
to increase the lower+high threshold.
$ grep -H . /proc/sys/net/ipv*/ip*frag_*_thresh /proc/sys/net/netfilter/nf_conntrack_frag6_*_thresh
/proc/sys/net/ipv4/ipfrag_high_thresh:4194304
/proc/sys/net/ipv4/ipfrag_low_thresh:3145728
/proc/sys/net/ipv6/ip6frag_high_thresh:4194304
/proc/sys/net/ipv6/ip6frag_low_thresh:3145728
/proc/sys/net/netfilter/nf_conntrack_frag6_high_thresh:4194304
/proc/sys/net/netfilter/nf_conntrack_frag6_low_thresh:3145728
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH v2 2/3] dt-binding: net: sfp binding documentation
From: Sergei Shtylyov @ 2017-08-30 11:04 UTC (permalink / raw)
To: Baruch Siach, Rob Herring, Mark Rutland, Andrew Lunn,
Florian Fainelli, David S. Miller, Russell King
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <7ae5d883fd038cf518949b0aa9cbe5369e2a1851.1504086672.git.baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
Hello!
On 8/30/2017 12:51 PM, Baruch Siach wrote:
> Add device-tree binding documentation SFP transceivers. Support for SFP
> transceivers has been recently introduced (drivers/net/phy/sfp.c).
>
> Signed-off-by: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
> ---
> v2:
> Rename -gpio properties to -gpios
> Rename the rate-select-gpio property to rate-select0-gpios
> Add the rate-select1-gpios property
> Add examples
> ---
> Documentation/devicetree/bindings/net/sff,sfp.txt | 74 +++++++++++++++++++++++
> 1 file changed, 74 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/sff,sfp.txt
>
> diff --git a/Documentation/devicetree/bindings/net/sff,sfp.txt b/Documentation/devicetree/bindings/net/sff,sfp.txt
> new file mode 100644
> index 000000000000..1d9c786d6287
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/sff,sfp.txt
> @@ -0,0 +1,74 @@
> +Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
> +Transceiver
> +
> +Required properties:
> +
> +- compatible : must be "sff,sfp"
> +
> +Optional Properties:
> +
> +- i2c-bus : phandle of an I2C bus controller for the SFP two wire serial
> + interface
> +
> +- moddef0-gpios : phandle of the MOD-DEF0 (AKA Mod_ABS) module presence input
> + gpio signal
Your example shows there's GPIO phandle *and* specifier.
> +
> +- los-gpios : phandle of the Receiver Loss of Signal Indication input gpio
> + signal
Ditto.
> +
> +- tx-fault-gpios : phandle of the Module Transmitter Fault input gpio signal
Ditto.
> +
> +- tx-disable-gpios : phandle of the Transmitter Disable output gpio signal
Ditto.
> +
> +- rate-select0-gpios : phandle of the Rx Signaling Rate Select (AKA RS0) output
> + gpio
> +
> +- rate-select1-gpios : phandle of the Tx Signaling Rate Select (AKA RS1) output
> + gpio (SFP+ only)
> +
> +Example #1: Direct serdes to SFP connection
> +
> +sfp_eth3: sfp-eth3 {
> + compatible = "sff,sfp";
> + i2c-bus = <&sfp_1g_i2c>;
> + los-gpios = <&cpm_gpio2 22 GPIO_ACTIVE_HIGH>;
> + moddef0-gpios = <&cpm_gpio2 21 GPIO_ACTIVE_LOW>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&cpm_sfp_1g_pins &cps_sfp_1g_pins>;
> + tx-disable-gpios = <&cps_gpio1 24 GPIO_ACTIVE_HIGH>;
> + tx-fault-gpios = <&cpm_gpio2 19 GPIO_ACTIVE_HIGH>;
> +};
[...]
> +Example #2: Serdes to PHY to SFP connection
> +
> +sfp_eth0: sfp-eth0 {
> + compatible = "sff,sfp+";
> + i2c-bus = <&sfpp0_i2c>;
> + los-gpio = <&cps_gpio1 28 GPIO_ACTIVE_HIGH>;
You describe "los-gpios" above , not "los-gpio" (which is a deprecated form).
> + moddef0-gpio = <&cps_gpio1 27 GPIO_ACTIVE_LOW>;
Ditto.
> + pinctrl-names = "default";
> + pinctrl-0 = <&cps_sfpp0_pins>;
> + tx-disable-gpio = <&cps_gpio1 29 GPIO_ACTIVE_HIGH>;
Ditto.
> + tx-fault-gpio = <&cps_gpio1 26 GPIO_ACTIVE_HIGH>;
Ditto.
[...]
MBR, Sergei
--
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
* [PATCH net-next] net: hns3: Fixes the wrong IS_ERR check on the returned phydev value
From: Salil Mehta @ 2017-08-30 11:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, mehta.salil.lnk, netdev, linux-kernel,
linuxarm
This patch removes the wrong check being done for the phy device being
returned by the mdiobus_get_phy() function. This function never returns
the error pointers.
Fixes: 256727da7395 ("net: hns3: Add MDIO support to HNS3 Ethernet
Driver for hip08 SoC")
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
index a2add8b..f32d719 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -150,7 +150,7 @@ int hclge_mac_mdio_config(struct hclge_dev *hdev)
}
phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr);
- if (!phydev || IS_ERR(phydev)) {
+ if (!phydev) {
dev_err(mdio_bus->parent, "Failed to get phy device\n");
mdiobus_unregister(mdio_bus);
return -EIO;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2 2/3] dt-binding: net: sfp binding documentation
From: Baruch Siach @ 2017-08-30 11:11 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Rob Herring, Mark Rutland, Andrew Lunn, Florian Fainelli,
David S. Miller, Russell King, netdev, devicetree
In-Reply-To: <89261369-d97c-a78c-5a21-a269b2c7e513@cogentembedded.com>
Hi Sergei,
Thanks for reviewing.
On Wed, Aug 30, 2017 at 02:04:11PM +0300, Sergei Shtylyov wrote:
> On 8/30/2017 12:51 PM, Baruch Siach wrote:
>
> > Add device-tree binding documentation SFP transceivers. Support for SFP
> > transceivers has been recently introduced (drivers/net/phy/sfp.c).
> >
> > Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> > ---
> > v2:
> > Rename -gpio properties to -gpios
> > Rename the rate-select-gpio property to rate-select0-gpios
> > Add the rate-select1-gpios property
> > Add examples
> > ---
> > Documentation/devicetree/bindings/net/sff,sfp.txt | 74 +++++++++++++++++++++++
> > 1 file changed, 74 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/net/sff,sfp.txt
> >
> > diff --git a/Documentation/devicetree/bindings/net/sff,sfp.txt b/Documentation/devicetree/bindings/net/sff,sfp.txt
> > new file mode 100644
> > index 000000000000..1d9c786d6287
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/net/sff,sfp.txt
> > @@ -0,0 +1,74 @@
> > +Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
> > +Transceiver
> > +
> > +Required properties:
> > +
> > +- compatible : must be "sff,sfp"
> > +
> > +Optional Properties:
> > +
> > +- i2c-bus : phandle of an I2C bus controller for the SFP two wire serial
> > + interface
> > +
> > +- moddef0-gpios : phandle of the MOD-DEF0 (AKA Mod_ABS) module presence input
> > + gpio signal
>
> Your example shows there's GPIO phandle *and* specifier.
Would "GPIO specifier" be enough here?
[...]
> > +Example #2: Serdes to PHY to SFP connection
> > +
> > +sfp_eth0: sfp-eth0 {
> > + compatible = "sff,sfp+";
> > + i2c-bus = <&sfpp0_i2c>;
> > + los-gpio = <&cps_gpio1 28 GPIO_ACTIVE_HIGH>;
>
> You describe "los-gpios" above , not "los-gpio" (which is a deprecated form).
Will fix.
baruch
--
http://baruch.siach.name/blog/ ~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch@tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -
^ permalink raw reply
* Re: [PATCH v2 2/3] dt-binding: net: sfp binding documentation
From: Sergei Shtylyov @ 2017-08-30 11:15 UTC (permalink / raw)
To: Baruch Siach
Cc: Rob Herring, Mark Rutland, Andrew Lunn, Florian Fainelli,
David S. Miller, Russell King, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170830111118.wy62va6sjzsxrgoo@tarshish>
On 8/30/2017 2:11 PM, Baruch Siach wrote:
> On Wed, Aug 30, 2017 at 02:04:11PM +0300, Sergei Shtylyov wrote:
>> On 8/30/2017 12:51 PM, Baruch Siach wrote:
>>
>>> Add device-tree binding documentation SFP transceivers. Support for SFP
>>> transceivers has been recently introduced (drivers/net/phy/sfp.c).
>>>
>>> Signed-off-by: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
>>> ---
>>> v2:
>>> Rename -gpio properties to -gpios
>>> Rename the rate-select-gpio property to rate-select0-gpios
>>> Add the rate-select1-gpios property
>>> Add examples
>>> ---
>>> Documentation/devicetree/bindings/net/sff,sfp.txt | 74 +++++++++++++++++++++++
>>> 1 file changed, 74 insertions(+)
>>> create mode 100644 Documentation/devicetree/bindings/net/sff,sfp.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/net/sff,sfp.txt b/Documentation/devicetree/bindings/net/sff,sfp.txt
>>> new file mode 100644
>>> index 000000000000..1d9c786d6287
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/net/sff,sfp.txt
>>> @@ -0,0 +1,74 @@
>>> +Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
>>> +Transceiver
>>> +
>>> +Required properties:
>>> +
>>> +- compatible : must be "sff,sfp"
>>> +
>>> +Optional Properties:
>>> +
>>> +- i2c-bus : phandle of an I2C bus controller for the SFP two wire serial
>>> + interface
>>> +
>>> +- moddef0-gpios : phandle of the MOD-DEF0 (AKA Mod_ABS) module presence input
>>> + gpio signal
>>
>> Your example shows there's GPIO phandle *and* specifier.
>
> Would "GPIO specifier" be enough here?
No, specifier is the cells following GPIO (or any other) phandle.
> [...]
MBR, Sergei
--
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
* [PATCH v3 net-next] staging: irda: fix init level for irda core
From: Greg KH @ 2017-08-30 11:16 UTC (permalink / raw)
To: David Miller
Cc: devel, netdev, samuel, linux-kernel, kernel test robot,
Geert Uytterhoeven
In-Reply-To: <20170829174622.GA25926@kroah.com>
When moving the IRDA code out of net/ into drivers/staging/irda/net, the
link order changes when IRDA is built into the kernel. That causes a
kernel crash at boot time as netfilter isn't initialized yet.
To fix this, move the init call level of the irda core to be
device_initcall() as the link order keeps this being initialized at the
correct time.
Reported-by: kernel test robot <fengguang.wu@intel.com>
Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
v3 - just change the initcall level, works so much simpler, thanks to
DaveM for the idea.
v2 - don't force irda to be a module, make the Makefiles put irda back
where it was before in the link order.
drivers/staging/irda/net/irmod.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/irda/net/irmod.c b/drivers/staging/irda/net/irmod.c
index c5e35b85c477..4319f4ff66b0 100644
--- a/drivers/staging/irda/net/irmod.c
+++ b/drivers/staging/irda/net/irmod.c
@@ -190,7 +190,7 @@ static void __exit irda_cleanup(void)
*
* Jean II
*/
-subsys_initcall(irda_init);
+device_initcall(irda_init);
module_exit(irda_cleanup);
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no> & Jean Tourrilhes <jt@hpl.hp.com>");
--
2.14.1
^ permalink raw reply related
* Re: [PATCH v2 2/3] dt-binding: net: sfp binding documentation
From: Baruch Siach @ 2017-08-30 11:25 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Rob Herring, Mark Rutland, Andrew Lunn, Florian Fainelli,
David S. Miller, Russell King, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <c3e8af44-bf58-81d7-bd51-d2538dcd41d9-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
Hi Sergei,
On Wed, Aug 30, 2017 at 02:15:32PM +0300, Sergei Shtylyov wrote:
> On 8/30/2017 2:11 PM, Baruch Siach wrote:
>
> > On Wed, Aug 30, 2017 at 02:04:11PM +0300, Sergei Shtylyov wrote:
> > > On 8/30/2017 12:51 PM, Baruch Siach wrote:
> > >
> > > > Add device-tree binding documentation SFP transceivers. Support for SFP
> > > > transceivers has been recently introduced (drivers/net/phy/sfp.c).
> > > >
> > > > Signed-off-by: Baruch Siach <baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org>
> > > > ---
> > > > v2:
> > > > Rename -gpio properties to -gpios
> > > > Rename the rate-select-gpio property to rate-select0-gpios
> > > > Add the rate-select1-gpios property
> > > > Add examples
> > > > ---
> > > > Documentation/devicetree/bindings/net/sff,sfp.txt | 74 +++++++++++++++++++++++
> > > > 1 file changed, 74 insertions(+)
> > > > create mode 100644 Documentation/devicetree/bindings/net/sff,sfp.txt
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/net/sff,sfp.txt b/Documentation/devicetree/bindings/net/sff,sfp.txt
> > > > new file mode 100644
> > > > index 000000000000..1d9c786d6287
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/net/sff,sfp.txt
> > > > @@ -0,0 +1,74 @@
> > > > +Small Form Factor (SFF) Committee Small Form-factor Pluggable (SFP)
> > > > +Transceiver
> > > > +
> > > > +Required properties:
> > > > +
> > > > +- compatible : must be "sff,sfp"
> > > > +
> > > > +Optional Properties:
> > > > +
> > > > +- i2c-bus : phandle of an I2C bus controller for the SFP two wire serial
> > > > + interface
> > > > +
> > > > +- moddef0-gpios : phandle of the MOD-DEF0 (AKA Mod_ABS) module presence input
> > > > + gpio signal
> > >
> > > Your example shows there's GPIO phandle *and* specifier.
> >
> > Would "GPIO specifier" be enough here?
>
> No, specifier is the cells following GPIO (or any other) phandle.
So this should be "GPIO phandle and specifier of ...", is that correct?
I have found very few (< 4) occurrences of this language in (lots of) '-gpios'
property descriptions under Documentation/devicetree/bindings/. Is this a new
requirement?
baruch
--
http://baruch.siach.name/blog/ ~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org - tel: +972.52.368.4656, http://www.tkos.co.il -
--
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
* Re: [PATCH net-next v4 02/13] phy: add the mvebu cp110 comphy driver
From: Kishon Vijay Abraham I @ 2017-08-30 11:32 UTC (permalink / raw)
To: Antoine Tenart, davem, andrew, jason, sebastian.hesselbarth,
gregory.clement
Cc: thomas.petazzoni, nadavh, linux, linux-kernel, mw, stefanc,
miquel.raynal, netdev
In-Reply-To: <20170830082924.3180-3-antoine.tenart@free-electrons.com>
On Wednesday 30 August 2017 01:59 PM, Antoine Tenart wrote:
> On the CP110 unit, which can be found on various Marvell platforms such
> as the 7k and 8k (currently), a comphy (common PHYs) hardware block can
> be found. This block provides a number of PHYs which can be used in
> various modes by other controllers (network, SATA ...). These common
> PHYs must be configured for the controllers using them to work correctly
> either at boot time, or when the system runs to switch the mode used.
> This patch adds a driver for this comphy hardware block, providing
> callbacks for the its PHYs so that consumers can configure the modes
> used.
>
> As of this commit, two modes are supported by the comphy driver: sgmii
> and 10gkr.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
> drivers/phy/marvell/Kconfig | 11 +
> drivers/phy/marvell/Makefile | 1 +
> drivers/phy/marvell/phy-mvebu-cp110-comphy.c | 644 +++++++++++++++++++++++++++
> 3 files changed, 656 insertions(+)
> create mode 100644 drivers/phy/marvell/phy-mvebu-cp110-comphy.c
>
> diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
> index 048d8893bc2e..68e321225400 100644
> --- a/drivers/phy/marvell/Kconfig
> +++ b/drivers/phy/marvell/Kconfig
> @@ -21,6 +21,17 @@ config PHY_BERLIN_USB
> help
> Enable this to support the USB PHY on Marvell Berlin SoCs.
>
> +config PHY_MVEBU_CP110_COMPHY
> + tristate "Marvell CP110 comphy driver"
> + depends on ARCH_MVEBU || COMPILE_TEST
> + depends on OF
> + select GENERIC_PHY
> + help
> + This driver allows to control the comphy, an hardware block providing
> + shared serdes PHYs on Marvell Armada 7k/8k (in the CP110). Its serdes
> + lanes can be used by various controllers (Ethernet, sata, usb,
> + PCIe...).
> +
> config PHY_MVEBU_SATA
> def_bool y
> depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
> diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
> index 3fc188f59118..0cf6a7cbaf9f 100644
> --- a/drivers/phy/marvell/Makefile
> +++ b/drivers/phy/marvell/Makefile
> @@ -1,6 +1,7 @@
> obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
> obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
> obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
> +obj-$(CONFIG_PHY_MVEBU_CP110_COMPHY) += phy-mvebu-cp110-comphy.o
> obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
> obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
> obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
> diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> new file mode 100644
> index 000000000000..73ebad6634a7
> --- /dev/null
> +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> @@ -0,0 +1,644 @@
> +/*
> + * Copyright (C) 2017 Marvell
> + *
> + * Antoine Tenart <antoine.tenart@free-electrons.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +/* Relative to priv->base */
> +#define MVEBU_COMPHY_SERDES_CFG0(n) (0x0 + (n) * 0x1000)
> +#define MVEBU_COMPHY_SERDES_CFG0_PU_PLL BIT(1)
> +#define MVEBU_COMPHY_SERDES_CFG0_GEN_RX(n) ((n) << 3)
> +#define MVEBU_COMPHY_SERDES_CFG0_GEN_TX(n) ((n) << 7)
> +#define MVEBU_COMPHY_SERDES_CFG0_PU_RX BIT(11)
> +#define MVEBU_COMPHY_SERDES_CFG0_PU_TX BIT(12)
> +#define MVEBU_COMPHY_SERDES_CFG0_HALF_BUS BIT(14)
> +#define MVEBU_COMPHY_SERDES_CFG1(n) (0x4 + (n) * 0x1000)
> +#define MVEBU_COMPHY_SERDES_CFG1_RESET BIT(3)
> +#define MVEBU_COMPHY_SERDES_CFG1_RX_INIT BIT(4)
> +#define MVEBU_COMPHY_SERDES_CFG1_CORE_RESET BIT(5)
> +#define MVEBU_COMPHY_SERDES_CFG1_RF_RESET BIT(6)
> +#define MVEBU_COMPHY_SERDES_CFG2(n) (0x8 + (n) * 0x1000)
> +#define MVEBU_COMPHY_SERDES_CFG2_DFE_EN BIT(4)
> +#define MVEBU_COMPHY_SERDES_STATUS0(n) (0x18 + (n) * 0x1000)
> +#define MVEBU_COMPHY_SERDES_STATUS0_TX_PLL_RDY BIT(2)
> +#define MVEBU_COMPHY_SERDES_STATUS0_RX_PLL_RDY BIT(3)
> +#define MVEBU_COMPHY_SERDES_STATUS0_RX_INIT BIT(4)
> +#define MVEBU_COMPHY_PWRPLL_CTRL(n) (0x804 + (n) * 0x1000)
> +#define MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(n) ((n) << 0)
> +#define MVEBU_COMPHY_PWRPLL_PHY_MODE(n) ((n) << 5)
> +#define MVEBU_COMPHY_IMP_CAL(n) (0x80c + (n) * 0x1000)
> +#define MVEBU_COMPHY_IMP_CAL_TX_EXT(n) ((n) << 10)
> +#define MVEBU_COMPHY_IMP_CAL_TX_EXT_EN BIT(15)
> +#define MVEBU_COMPHY_DFE_RES(n) (0x81c + (n) * 0x1000)
> +#define MVEBU_COMPHY_DFE_RES_FORCE_GEN_TBL BIT(15)
> +#define MVEBU_COMPHY_COEF(n) (0x828 + (n) * 0x1000)
> +#define MVEBU_COMPHY_COEF_DFE_EN BIT(14)
> +#define MVEBU_COMPHY_COEF_DFE_CTRL BIT(15)
> +#define MVEBU_COMPHY_GEN1_S0(n) (0x834 + (n) * 0x1000)
> +#define MVEBU_COMPHY_GEN1_S0_TX_AMP(n) ((n) << 1)
> +#define MVEBU_COMPHY_GEN1_S0_TX_EMPH(n) ((n) << 7)
> +#define MVEBU_COMPHY_GEN1_S1(n) (0x838 + (n) * 0x1000)
> +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(n) ((n) << 0)
> +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(n) ((n) << 3)
> +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_FI(n) ((n) << 6)
> +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(n) ((n) << 8)
> +#define MVEBU_COMPHY_GEN1_S1_RX_DFE_EN BIT(10)
> +#define MVEBU_COMPHY_GEN1_S1_RX_DIV(n) ((n) << 11)
> +#define MVEBU_COMPHY_GEN1_S2(n) (0x8f4 + (n) * 0x1000)
> +#define MVEBU_COMPHY_GEN1_S2_TX_EMPH(n) ((n) << 0)
> +#define MVEBU_COMPHY_GEN1_S2_TX_EMPH_EN BIT(4)
> +#define MVEBU_COMPHY_LOOPBACK(n) (0x88c + (n) * 0x1000)
> +#define MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(n) ((n) << 1)
> +#define MVEBU_COMPHY_VDD_CAL0(n) (0x908 + (n) * 0x1000)
> +#define MVEBU_COMPHY_VDD_CAL0_CONT_MODE BIT(15)
> +#define MVEBU_COMPHY_EXT_SELV(n) (0x914 + (n) * 0x1000)
> +#define MVEBU_COMPHY_EXT_SELV_RX_SAMPL(n) ((n) << 5)
> +#define MVEBU_COMPHY_MISC_CTRL0(n) (0x93c + (n) * 0x1000)
> +#define MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE BIT(5)
> +#define MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL BIT(10)
> +#define MVEBU_COMPHY_RX_CTRL1(n) (0x940 + (n) * 0x1000)
> +#define MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL BIT(11)
> +#define MVEBU_COMPHY_RX_CTRL1_CLK8T_EN BIT(12)
> +#define MVEBU_COMPHY_SPEED_DIV(n) (0x954 + (n) * 0x1000)
> +#define MVEBU_COMPHY_SPEED_DIV_TX_FORCE BIT(7)
> +#define MVEBU_SP_CALIB(n) (0x96c + (n) * 0x1000)
> +#define MVEBU_SP_CALIB_SAMPLER(n) ((n) << 8)
> +#define MVEBU_SP_CALIB_SAMPLER_EN BIT(12)
> +#define MVEBU_COMPHY_TX_SLEW_RATE(n) (0x974 + (n) * 0x1000)
> +#define MVEBU_COMPHY_TX_SLEW_RATE_EMPH(n) ((n) << 5)
> +#define MVEBU_COMPHY_TX_SLEW_RATE_SLC(n) ((n) << 10)
> +#define MVEBU_COMPHY_DLT_CTRL(n) (0x984 + (n) * 0x1000)
> +#define MVEBU_COMPHY_DLT_CTRL_DTL_FLOOP_EN BIT(2)
> +#define MVEBU_COMPHY_FRAME_DETECT0(n) (0xa14 + (n) * 0x1000)
> +#define MVEBU_COMPHY_FRAME_DETECT0_PATN(n) ((n) << 7)
> +#define MVEBU_COMPHY_FRAME_DETECT3(n) (0xa20 + (n) * 0x1000)
> +#define MVEBU_COMPHY_FRAME_DETECT3_LOST_TIMEOUT_EN BIT(12)
> +#define MVEBU_COMPHY_DME(n) (0xa28 + (n) * 0x1000)
> +#define MVEBU_COMPHY_DME_ETH_MODE BIT(7)
> +#define MVEBU_COMPHY_TRAINING0(n) (0xa68 + (n) * 0x1000)
> +#define MVEBU_COMPHY_TRAINING0_P2P_HOLD BIT(15)
> +#define MVEBU_COMPHY_TRAINING5(n) (0xaa4 + (n) * 0x1000)
> +#define MVEBU_COMPHY_TRAINING5_RX_TIMER(n) ((n) << 0)
> +#define MVEBU_COMPHY_TX_TRAIN_PRESET(n) (0xb1c + (n) * 0x1000)
> +#define MVEBU_COMPHY_TX_TRAIN_PRESET_16B_AUTO_EN BIT(8)
> +#define MVEBU_COMPHY_TX_TRAIN_PRESET_PRBS11 BIT(9)
> +#define MVEBU_COMPHY_GEN1_S3(n) (0xc40 + (n) * 0x1000)
> +#define MVEBU_COMPHY_GEN1_S3_FBCK_SEL BIT(9)
> +#define MVEBU_COMPHY_GEN1_S4(n) (0xc44 + (n) * 0x1000)
> +#define MVEBU_COMPHY_GEN1_S4_DFE_RES(n) ((n) << 8)
> +#define MVEBU_COMPHY_TX_PRESET(n) (0xc68 + (n) * 0x1000)
> +#define MVEBU_COMPHY_TX_PRESET_INDEX(n) ((n) << 0)
> +#define MVEBU_COMPHY_GEN1_S5(n) (0xd38 + (n) * 0x1000)
> +#define MVEBU_COMPHY_GEN1_S5_ICP(n) ((n) << 0)
> +
> +/* Relative to priv->regmap */
> +#define MVEBU_COMPHY_CONF1(n) (0x1000 + (n) * 0x28)
> +#define MVEBU_COMPHY_CONF1_PWRUP BIT(1)
> +#define MVEBU_COMPHY_CONF1_USB_PCIE BIT(2) /* 0: Ethernet/SATA */
> +#define MVEBU_COMPHY_CONF6(n) (0x1014 + (n) * 0x28)
> +#define MVEBU_COMPHY_CONF6_40B BIT(18)
> +#define MVEBU_COMPHY_SELECTOR 0x1140
> +#define MVEBU_COMPHY_SELECTOR_PHY(n) ((n) * 0x4)
> +
> +#define MVEBU_COMPHY_LANES 6
> +#define MVEBU_COMPHY_PORTS 3
> +
> +struct mvebu_comhy_conf {
> + enum phy_mode mode;
> + unsigned lane;
> + unsigned port;
> + u32 mux;
> +};
> +
> +#define MVEBU_COMPHY_CONF(_lane, _port, _mode, _mux) \
> + { \
> + .lane = _lane, \
> + .port = _port, \
> + .mode = _mode, \
> + .mux = _mux, \
> + }
> +
> +static const struct mvebu_comhy_conf mvebu_comphy_cp110_modes[] = {
> + /* lane 0 */
> + MVEBU_COMPHY_CONF(0, 1, PHY_MODE_SGMII, 0x1),
> + /* lane 1 */
> + MVEBU_COMPHY_CONF(1, 2, PHY_MODE_SGMII, 0x1),
> + /* lane 2 */
> + MVEBU_COMPHY_CONF(2, 0, PHY_MODE_SGMII, 0x1),
> + MVEBU_COMPHY_CONF(2, 0, PHY_MODE_10GKR, 0x1),
> + /* lane 3 */
> + MVEBU_COMPHY_CONF(3, 1, PHY_MODE_SGMII, 0x2),
> + /* lane 4 */
> + MVEBU_COMPHY_CONF(4, 0, PHY_MODE_SGMII, 0x2),
> + MVEBU_COMPHY_CONF(4, 0, PHY_MODE_10GKR, 0x2),
> + MVEBU_COMPHY_CONF(4, 1, PHY_MODE_SGMII, 0x1),
> + /* lane 5 */
> + MVEBU_COMPHY_CONF(5, 2, PHY_MODE_SGMII, 0x1),
> +};
> +
> +struct mvebu_comphy_priv {
> + void __iomem *base;
> + struct regmap *regmap;
> + struct device *dev;
> + int modes[MVEBU_COMPHY_LANES];
> +};
> +
> +struct mvebu_comphy_lane {
> + struct mvebu_comphy_priv *priv;
> + unsigned id;
> + enum phy_mode mode;
> + int port;
> +};
> +
> +static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode)
> +{
> + int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes);
> +
> + /* Unused PHY mux value is 0x0 */
> + if (mode == PHY_MODE_INVALID)
> + return 0;
> +
> + for (i = 0; i < n; i++) {
> + if (mvebu_comphy_cp110_modes[i].lane == lane &&
> + mvebu_comphy_cp110_modes[i].port == port &&
> + mvebu_comphy_cp110_modes[i].mode == mode)
> + break;
> + }
> +
> + if (i == n)
> + return -EINVAL;
> +
> + return mvebu_comphy_cp110_modes[i].mux;
> +}
> +
> +static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane,
> + enum phy_mode mode)
> +{
> + struct mvebu_comphy_priv *priv = lane->priv;
> + u32 val;
> +
> + regmap_read(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), &val);
> + val &= ~MVEBU_COMPHY_CONF1_USB_PCIE;
> + val |= MVEBU_COMPHY_CONF1_PWRUP;
> + regmap_write(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), val);
> +
> + /* Select baud rates and PLLs */
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> + val &= ~(MVEBU_COMPHY_SERDES_CFG0_PU_PLL |
> + MVEBU_COMPHY_SERDES_CFG0_PU_RX |
> + MVEBU_COMPHY_SERDES_CFG0_PU_TX |
> + MVEBU_COMPHY_SERDES_CFG0_HALF_BUS |
> + MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) |
> + MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf));
> + if (mode == PHY_MODE_10GKR)
> + val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) |
> + MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe);
> + else if (mode == PHY_MODE_SGMII)
> + val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) |
> + MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) |
> + MVEBU_COMPHY_SERDES_CFG0_HALF_BUS;
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> +
> + /* reset */
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> + val &= ~(MVEBU_COMPHY_SERDES_CFG1_RESET |
> + MVEBU_COMPHY_SERDES_CFG1_CORE_RESET |
> + MVEBU_COMPHY_SERDES_CFG1_RF_RESET);
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> +
> + /* de-assert reset */
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> + val |= MVEBU_COMPHY_SERDES_CFG1_RESET |
> + MVEBU_COMPHY_SERDES_CFG1_CORE_RESET;
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> +
> + /* wait until clocks are ready */
> + mdelay(1);
> +
> + /* exlicitly disable 40B, the bits isn't clear on reset */
> + regmap_read(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), &val);
> + val &= ~MVEBU_COMPHY_CONF6_40B;
> + regmap_write(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), val);
> +
> + /* refclk selection */
> + val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
> + val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL;
> + if (mode == PHY_MODE_10GKR)
> + val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE;
> + writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
> +
> + /* power and pll selection */
> + val = readl(priv->base + MVEBU_COMPHY_PWRPLL_CTRL(lane->id));
> + val &= ~(MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(0x1f) |
> + MVEBU_COMPHY_PWRPLL_PHY_MODE(0x7));
> + val |= MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(0x1) |
> + MVEBU_COMPHY_PWRPLL_PHY_MODE(0x4);
> + writel(val, priv->base + MVEBU_COMPHY_PWRPLL_CTRL(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_LOOPBACK(lane->id));
> + val &= ~MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(0x7);
> + val |= MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(0x1);
> + writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id));
> +}
> +
> +static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane,
> + enum phy_mode mode)
> +{
> + struct mvebu_comphy_priv *priv = lane->priv;
> + u32 val;
> +
> + /* SERDES external config */
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> + val |= MVEBU_COMPHY_SERDES_CFG0_PU_PLL |
> + MVEBU_COMPHY_SERDES_CFG0_PU_RX |
> + MVEBU_COMPHY_SERDES_CFG0_PU_TX;
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> +
> + /* check rx/tx pll */
> + readl_poll_timeout(priv->base + MVEBU_COMPHY_SERDES_STATUS0(lane->id),
> + val,
> + val & (MVEBU_COMPHY_SERDES_STATUS0_RX_PLL_RDY |
> + MVEBU_COMPHY_SERDES_STATUS0_TX_PLL_RDY),
> + 1000, 150000);
> + if (!(val & (MVEBU_COMPHY_SERDES_STATUS0_RX_PLL_RDY |
> + MVEBU_COMPHY_SERDES_STATUS0_TX_PLL_RDY)))
> + return -ETIMEDOUT;
> +
> + /* rx init */
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> + val |= MVEBU_COMPHY_SERDES_CFG1_RX_INIT;
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> +
> + /* check rx */
> + readl_poll_timeout(priv->base + MVEBU_COMPHY_SERDES_STATUS0(lane->id),
> + val, val & MVEBU_COMPHY_SERDES_STATUS0_RX_INIT,
> + 1000, 10000);
> + if (!(val & MVEBU_COMPHY_SERDES_STATUS0_RX_INIT))
> + return -ETIMEDOUT;
> +
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> + val &= ~MVEBU_COMPHY_SERDES_CFG1_RX_INIT;
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> +
> + return 0;
> +}
> +
> +static int mvebu_comphy_set_mode_sgmii(struct phy *phy)
> +{
> + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> + struct mvebu_comphy_priv *priv = lane->priv;
> + u32 val;
> +
> + mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_SGMII);
> +
> + val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> + val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
> + val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL;
> + writel(val, priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> + val &= ~MVEBU_COMPHY_DLT_CTRL_DTL_FLOOP_EN;
> + writel(val, priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> +
> + regmap_read(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), &val);
> + val &= ~MVEBU_COMPHY_CONF1_USB_PCIE;
> + val |= MVEBU_COMPHY_CONF1_PWRUP;
> + regmap_write(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), val);
> +
> + val = readl(priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> + val &= ~MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xf);
> + val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1);
> + writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> +
> + return mvebu_comphy_init_plls(lane, PHY_MODE_SGMII);
> +}
> +
> +static int mvebu_comphy_set_mode_10gkr(struct phy *phy)
> +{
> + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> + struct mvebu_comphy_priv *priv = lane->priv;
> + u32 val;
> +
> + mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_10GKR);
> +
> + val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> + val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL |
> + MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
> + writel(val, priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> + val |= MVEBU_COMPHY_DLT_CTRL_DTL_FLOOP_EN;
> + writel(val, priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> +
> + /* Speed divider */
> + val = readl(priv->base + MVEBU_COMPHY_SPEED_DIV(lane->id));
> + val |= MVEBU_COMPHY_SPEED_DIV_TX_FORCE;
> + writel(val, priv->base + MVEBU_COMPHY_SPEED_DIV(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
> + val |= MVEBU_COMPHY_SERDES_CFG2_DFE_EN;
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
> +
> + /* DFE resolution */
> + val = readl(priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
> + val |= MVEBU_COMPHY_DFE_RES_FORCE_GEN_TBL;
> + writel(val, priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> + val &= ~(MVEBU_COMPHY_GEN1_S0_TX_AMP(0x1f) |
> + MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xf));
> + val |= MVEBU_COMPHY_GEN1_S0_TX_AMP(0x1c) |
> + MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xe);
> + writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_GEN1_S2(lane->id));
> + val &= ~MVEBU_COMPHY_GEN1_S2_TX_EMPH(0xf);
> + val |= MVEBU_COMPHY_GEN1_S2_TX_EMPH_EN;
> + writel(val, priv->base + MVEBU_COMPHY_GEN1_S2(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_TX_SLEW_RATE(lane->id));
> + val |= MVEBU_COMPHY_TX_SLEW_RATE_EMPH(0x3) |
> + MVEBU_COMPHY_TX_SLEW_RATE_SLC(0x3f);
> + writel(val, priv->base + MVEBU_COMPHY_TX_SLEW_RATE(lane->id));
> +
> + /* Impedance calibration */
> + val = readl(priv->base + MVEBU_COMPHY_IMP_CAL(lane->id));
> + val &= ~MVEBU_COMPHY_IMP_CAL_TX_EXT(0x1f);
> + val |= MVEBU_COMPHY_IMP_CAL_TX_EXT(0xe) |
> + MVEBU_COMPHY_IMP_CAL_TX_EXT_EN;
> + writel(val, priv->base + MVEBU_COMPHY_IMP_CAL(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_GEN1_S5(lane->id));
> + val &= ~MVEBU_COMPHY_GEN1_S5_ICP(0xf);
> + writel(val, priv->base + MVEBU_COMPHY_GEN1_S5(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
> + val &= ~(MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x7) |
> + MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x7) |
> + MVEBU_COMPHY_GEN1_S1_RX_MUL_FI(0x3) |
> + MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(0x3));
> + val |= MVEBU_COMPHY_GEN1_S1_RX_DFE_EN |
> + MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x2) |
> + MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x2) |
> + MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(0x1) |
> + MVEBU_COMPHY_GEN1_S1_RX_DIV(0x3);
> + writel(val, priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_COEF(lane->id));
> + val &= ~(MVEBU_COMPHY_COEF_DFE_EN | MVEBU_COMPHY_COEF_DFE_CTRL);
> + writel(val, priv->base + MVEBU_COMPHY_COEF(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
> + val &= ~MVEBU_COMPHY_GEN1_S4_DFE_RES(0x3);
> + val |= MVEBU_COMPHY_GEN1_S4_DFE_RES(0x1);
> + writel(val, priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_GEN1_S3(lane->id));
> + val |= MVEBU_COMPHY_GEN1_S3_FBCK_SEL;
> + writel(val, priv->base + MVEBU_COMPHY_GEN1_S3(lane->id));
> +
> + /* rx training timer */
> + val = readl(priv->base + MVEBU_COMPHY_TRAINING5(lane->id));
> + val &= ~MVEBU_COMPHY_TRAINING5_RX_TIMER(0x3ff);
> + val |= MVEBU_COMPHY_TRAINING5_RX_TIMER(0x13);
> + writel(val, priv->base + MVEBU_COMPHY_TRAINING5(lane->id));
> +
> + /* tx train peak to peak hold */
> + val = readl(priv->base + MVEBU_COMPHY_TRAINING0(lane->id));
> + val |= MVEBU_COMPHY_TRAINING0_P2P_HOLD;
> + writel(val, priv->base + MVEBU_COMPHY_TRAINING0(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_TX_PRESET(lane->id));
> + val &= ~MVEBU_COMPHY_TX_PRESET_INDEX(0xf);
> + val |= MVEBU_COMPHY_TX_PRESET_INDEX(0x2); /* preset coeff */
> + writel(val, priv->base + MVEBU_COMPHY_TX_PRESET(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_FRAME_DETECT3(lane->id));
> + val &= ~MVEBU_COMPHY_FRAME_DETECT3_LOST_TIMEOUT_EN;
> + writel(val, priv->base + MVEBU_COMPHY_FRAME_DETECT3(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_TX_TRAIN_PRESET(lane->id));
> + val |= MVEBU_COMPHY_TX_TRAIN_PRESET_16B_AUTO_EN |
> + MVEBU_COMPHY_TX_TRAIN_PRESET_PRBS11;
> + writel(val, priv->base + MVEBU_COMPHY_TX_TRAIN_PRESET(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_FRAME_DETECT0(lane->id));
> + val &= ~MVEBU_COMPHY_FRAME_DETECT0_PATN(0x1ff);
> + val |= MVEBU_COMPHY_FRAME_DETECT0_PATN(0x88);
> + writel(val, priv->base + MVEBU_COMPHY_FRAME_DETECT0(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_DME(lane->id));
> + val |= MVEBU_COMPHY_DME_ETH_MODE;
> + writel(val, priv->base + MVEBU_COMPHY_DME(lane->id));
> +
> + val = readl(priv->base + MVEBU_COMPHY_VDD_CAL0(lane->id));
> + val |= MVEBU_COMPHY_VDD_CAL0_CONT_MODE;
> + writel(val, priv->base + MVEBU_COMPHY_VDD_CAL0(lane->id));
> +
> + val = readl(priv->base + MVEBU_SP_CALIB(lane->id));
> + val &= ~MVEBU_SP_CALIB_SAMPLER(0x3);
> + val |= MVEBU_SP_CALIB_SAMPLER(0x3) |
> + MVEBU_SP_CALIB_SAMPLER_EN;
> + writel(val, priv->base + MVEBU_SP_CALIB(lane->id));
> + val &= ~MVEBU_SP_CALIB_SAMPLER_EN;
> + writel(val, priv->base + MVEBU_SP_CALIB(lane->id));
> +
> + /* External rx regulator */
> + val = readl(priv->base + MVEBU_COMPHY_EXT_SELV(lane->id));
> + val &= ~MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1f);
> + val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a);
> + writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id));
> +
> + return mvebu_comphy_init_plls(lane, PHY_MODE_10GKR);
> +}
> +
> +static int mvebu_comphy_power_on(struct phy *phy)
> +{
> + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> + struct mvebu_comphy_priv *priv = lane->priv;
> + int ret;
> + u32 mux, val;
> +
> + mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode);
> + if (mux < 0)
> + return -ENOTSUPP;
> +
> + regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val);
> + val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
> + val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id);
> + regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val);
> +
> + switch (lane->mode) {
> + case PHY_MODE_SGMII:
> + ret = mvebu_comphy_set_mode_sgmii(phy);
> + break;
> + case PHY_MODE_10GKR:
> + ret = mvebu_comphy_set_mode_10gkr(phy);
> + break;
> + default:
> + return -ENOTSUPP;
> + }
> +
> + /* digital reset */
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> + val |= MVEBU_COMPHY_SERDES_CFG1_RF_RESET;
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> +
> + return ret;
> +}
> +
> +static int mvebu_comphy_set_mode(struct phy *phy, enum phy_mode mode)
> +{
> + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> +
> + if (mvebu_comphy_get_mux(lane->id, lane->port, mode) < 0)
> + return -EINVAL;
> +
> + lane->mode = mode;
> + return 0;
> +}
> +
> +static int mvebu_comphy_power_off(struct phy *phy)
> +{
> + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> + struct mvebu_comphy_priv *priv = lane->priv;
> + u32 val;
> +
> + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> + val &= ~(MVEBU_COMPHY_SERDES_CFG1_RESET |
> + MVEBU_COMPHY_SERDES_CFG1_CORE_RESET |
> + MVEBU_COMPHY_SERDES_CFG1_RF_RESET);
> + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> +
> + regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val);
> + val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
> + regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val);
> +
> + return 0;
> +}
> +
> +static const struct phy_ops mvebu_comphy_ops = {
> + .power_on = mvebu_comphy_power_on,
> + .power_off = mvebu_comphy_power_off,
> + .set_mode = mvebu_comphy_set_mode,
> + .owner = THIS_MODULE,
> +};
> +
> +static struct phy *mvebu_comphy_xlate(struct device *dev,
> + struct of_phandle_args *args)
> +{
> + struct mvebu_comphy_lane *lane;
> + struct phy *phy;
> +
> + if (WARN_ON(args->args[0] >= MVEBU_COMPHY_PORTS))
> + return ERR_PTR(-EINVAL);
> +
> + phy = of_phy_simple_xlate(dev, args);
> + if (IS_ERR(phy))
> + return phy;
> +
> + lane = phy_get_drvdata(phy);
> + if (lane->port >= 0)
> + return ERR_PTR(-EBUSY);
> + lane->port = args->args[0];
> +
> + return phy;
> +}
> +
> +static int mvebu_comphy_probe(struct platform_device *pdev)
> +{
> + struct mvebu_comphy_priv *priv;
> + struct phy_provider *provider;
> + struct device_node *child;
> + struct resource *res;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->dev = &pdev->dev;
> + priv->regmap =
> + syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> + "marvell,system-controller");
> + if (IS_ERR(priv->regmap))
> + return PTR_ERR(priv->regmap);
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + priv->base = devm_ioremap_resource(&pdev->dev, res);
> + if (!priv->base)
> + return -ENOMEM;
> +
> + for_each_available_child_of_node(pdev->dev.of_node, child) {
> + struct mvebu_comphy_lane *lane;
> + struct phy *phy;
> + int ret;
> + u32 val;
> +
> + ret = of_property_read_u32(child, "reg", &val);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "missing 'reg' property (%d)\n",
> + ret);
> + continue;
> + }
> +
> + if (val >= MVEBU_COMPHY_LANES) {
> + dev_err(&pdev->dev, "invalid 'reg' property\n");
> + continue;
> + }
> +
> + lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL);
> + if (!lane)
> + return -ENOMEM;
> +
> + phy = devm_phy_create(&pdev->dev, child, &mvebu_comphy_ops);
> + if (IS_ERR(phy))
> + return PTR_ERR(phy);
> +
> + lane->priv = priv;
> + lane->mode = PHY_MODE_INVALID;
> + lane->id = val;
> + lane->port = -1;
> + phy_set_drvdata(phy, lane);
> +
> + /*
> + * Once all modes are supported in this driver we should call
> + * mvebu_comphy_power_off(phy) here to avoid relying on the
> + * bootloader/firmware configuration.
> + */
> + }
> +
> + dev_set_drvdata(&pdev->dev, priv);
> + provider = devm_of_phy_provider_register(&pdev->dev,
> + mvebu_comphy_xlate);
> + return PTR_ERR_OR_ZERO(provider);
> +}
> +
> +static const struct of_device_id mvebu_comphy_of_match_table[] = {
> + { .compatible = "marvell,comphy-cp110" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, mvebu_comphy_of_match_table);
> +
> +static struct platform_driver mvebu_comphy_driver = {
> + .probe = mvebu_comphy_probe,
> + .driver = {
> + .name = "mvebu-comphy",
> + .of_match_table = mvebu_comphy_of_match_table,
> + },
> +};
> +module_platform_driver(mvebu_comphy_driver);
> +
> +MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
> +MODULE_DESCRIPTION("Common PHY driver for mvebu SoCs");
> +MODULE_LICENSE("GPL v2");
>
^ permalink raw reply
* Re: [PATCH net-next v6 3/3] openvswitch: enable NSH support
From: Mooney, Sean K @ 2017-08-30 11:36 UTC (permalink / raw)
To: Hannes Frederic Sowa, Yang, Yi Y
Cc: dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, e@erig.me,
jbenc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org
In-Reply-To: <87wp5l7560.fsf-tFNcAqjVMyqKXQKiL6tip0B+6BGkLq7r@public.gmane.org>
> -----Original Message-----
> From: ovs-dev-bounces-yBygre7rU0TnMu66kgdUjQ@public.gmane.org [mailto:ovs-dev-
> bounces-yBygre7rU0TnMu66kgdUjQ@public.gmane.org] On Behalf Of Hannes Frederic Sowa
> Sent: Wednesday, August 30, 2017 10:53 AM
> To: Yang, Yi Y <yi.y.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Cc: dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org; netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; jbenc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org;
> e@erig.me
> Subject: Re: [ovs-dev] [PATCH net-next v6 3/3] openvswitch: enable NSH
> support
>
> Hello,
>
> Yi Yang <yi.y.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> writes:
>
> [...]
>
> > +struct ovs_key_nsh {
> > + u8 flags;
> > + u8 ttl;
> > + u8 mdtype;
> > + u8 np;
> > + __be32 path_hdr;
> > + __be32 context[NSH_MD1_CONTEXT_SIZE]; };
> > +
> > struct sw_flow_key {
> > u8 tun_opts[IP_TUNNEL_OPTS_MAX];
> > u8 tun_opts_len;
> > @@ -144,6 +154,7 @@ struct sw_flow_key {
> > };
> > } ipv6;
> > };
> > + struct ovs_key_nsh nsh; /* network service header */
> > struct {
> > /* Connection tracking fields not packed above. */
> > struct {
>
> Does it makes sense to keep the context headers as part of the flow?
> What is the reasoning behind it? With mdtype 2 headers this might
> either not work very well or will increase sw_flow_key size causing
> slowdowns for all protocols.
[Mooney, Sean K]
Having the nsh context headers in the flow is quite useful
It would allow loadblancing on values stored in the context headers
Or other use. I belive odl previously used context header 4 to store a
Flow id so this could potentialy be used with the multipath action to have ovs
Choose between several possible next hops in the chain.
Another example of where this is usefull is branching chains.
if I assume that both the classifier and
Service function forwarder are collocated in ovs on the host, and is send
A packet to a firewall service function which tags the packet as suspicious
Via setting a context header metadata field to 1, I as the sdn controller can
Install a high priority rule that will reclassify the packet as part of as separate
Service function chain the will prefer dpi on the packet before returning it to
The original chain if demand not a threat.
So while a sff dose not in general have to be able to match on the context header
If I assume I want to use ovs to implenet a classifier or service function(e.g. loadblancer)
The its desirable to be able to both match on the context headers in md type1 and also be able
To set them(this is something classifies and service fuction are allowed to do).
>
> [...]
> _______________________________________________
> dev mailing list
> dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
^ permalink raw reply
* Re: [PATCH net-next v4 02/13] phy: add the mvebu cp110 comphy driver
From: Antoine Tenart @ 2017-08-30 11:39 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Antoine Tenart, davem, andrew, jason, sebastian.hesselbarth,
gregory.clement, thomas.petazzoni, nadavh, linux, linux-kernel,
mw, stefanc, miquel.raynal, netdev
In-Reply-To: <088b395c-35cd-9af7-5171-2d0fdd31d144@ti.com>
[-- Attachment #1: Type: text/plain, Size: 29743 bytes --]
Hi Kishon,
On Wed, Aug 30, 2017 at 05:02:55PM +0530, Kishon Vijay Abraham I wrote:
> On Wednesday 30 August 2017 01:59 PM, Antoine Tenart wrote:
> > On the CP110 unit, which can be found on various Marvell platforms such
> > as the 7k and 8k (currently), a comphy (common PHYs) hardware block can
> > be found. This block provides a number of PHYs which can be used in
> > various modes by other controllers (network, SATA ...). These common
> > PHYs must be configured for the controllers using them to work correctly
> > either at boot time, or when the system runs to switch the mode used.
> > This patch adds a driver for this comphy hardware block, providing
> > callbacks for the its PHYs so that consumers can configure the modes
> > used.
> >
> > As of this commit, two modes are supported by the comphy driver: sgmii
> > and 10gkr.
> >
> > Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
>
> Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
Thanks for the review!
@Dave: As stated by Kishon in the previous version of the series, the
two generic PHY patches can go through the net-next tree.
Thanks,
Antoine
> > ---
> > drivers/phy/marvell/Kconfig | 11 +
> > drivers/phy/marvell/Makefile | 1 +
> > drivers/phy/marvell/phy-mvebu-cp110-comphy.c | 644 +++++++++++++++++++++++++++
> > 3 files changed, 656 insertions(+)
> > create mode 100644 drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> >
> > diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
> > index 048d8893bc2e..68e321225400 100644
> > --- a/drivers/phy/marvell/Kconfig
> > +++ b/drivers/phy/marvell/Kconfig
> > @@ -21,6 +21,17 @@ config PHY_BERLIN_USB
> > help
> > Enable this to support the USB PHY on Marvell Berlin SoCs.
> >
> > +config PHY_MVEBU_CP110_COMPHY
> > + tristate "Marvell CP110 comphy driver"
> > + depends on ARCH_MVEBU || COMPILE_TEST
> > + depends on OF
> > + select GENERIC_PHY
> > + help
> > + This driver allows to control the comphy, an hardware block providing
> > + shared serdes PHYs on Marvell Armada 7k/8k (in the CP110). Its serdes
> > + lanes can be used by various controllers (Ethernet, sata, usb,
> > + PCIe...).
> > +
> > config PHY_MVEBU_SATA
> > def_bool y
> > depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
> > diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
> > index 3fc188f59118..0cf6a7cbaf9f 100644
> > --- a/drivers/phy/marvell/Makefile
> > +++ b/drivers/phy/marvell/Makefile
> > @@ -1,6 +1,7 @@
> > obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
> > obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
> > obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
> > +obj-$(CONFIG_PHY_MVEBU_CP110_COMPHY) += phy-mvebu-cp110-comphy.o
> > obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
> > obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
> > obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
> > diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> > new file mode 100644
> > index 000000000000..73ebad6634a7
> > --- /dev/null
> > +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
> > @@ -0,0 +1,644 @@
> > +/*
> > + * Copyright (C) 2017 Marvell
> > + *
> > + * Antoine Tenart <antoine.tenart@free-electrons.com>
> > + *
> > + * This file is licensed under the terms of the GNU General Public
> > + * License version 2. This program is licensed "as is" without any
> > + * warranty of any kind, whether express or implied.
> > + */
> > +
> > +#include <linux/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/module.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +/* Relative to priv->base */
> > +#define MVEBU_COMPHY_SERDES_CFG0(n) (0x0 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_SERDES_CFG0_PU_PLL BIT(1)
> > +#define MVEBU_COMPHY_SERDES_CFG0_GEN_RX(n) ((n) << 3)
> > +#define MVEBU_COMPHY_SERDES_CFG0_GEN_TX(n) ((n) << 7)
> > +#define MVEBU_COMPHY_SERDES_CFG0_PU_RX BIT(11)
> > +#define MVEBU_COMPHY_SERDES_CFG0_PU_TX BIT(12)
> > +#define MVEBU_COMPHY_SERDES_CFG0_HALF_BUS BIT(14)
> > +#define MVEBU_COMPHY_SERDES_CFG1(n) (0x4 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_SERDES_CFG1_RESET BIT(3)
> > +#define MVEBU_COMPHY_SERDES_CFG1_RX_INIT BIT(4)
> > +#define MVEBU_COMPHY_SERDES_CFG1_CORE_RESET BIT(5)
> > +#define MVEBU_COMPHY_SERDES_CFG1_RF_RESET BIT(6)
> > +#define MVEBU_COMPHY_SERDES_CFG2(n) (0x8 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_SERDES_CFG2_DFE_EN BIT(4)
> > +#define MVEBU_COMPHY_SERDES_STATUS0(n) (0x18 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_SERDES_STATUS0_TX_PLL_RDY BIT(2)
> > +#define MVEBU_COMPHY_SERDES_STATUS0_RX_PLL_RDY BIT(3)
> > +#define MVEBU_COMPHY_SERDES_STATUS0_RX_INIT BIT(4)
> > +#define MVEBU_COMPHY_PWRPLL_CTRL(n) (0x804 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(n) ((n) << 0)
> > +#define MVEBU_COMPHY_PWRPLL_PHY_MODE(n) ((n) << 5)
> > +#define MVEBU_COMPHY_IMP_CAL(n) (0x80c + (n) * 0x1000)
> > +#define MVEBU_COMPHY_IMP_CAL_TX_EXT(n) ((n) << 10)
> > +#define MVEBU_COMPHY_IMP_CAL_TX_EXT_EN BIT(15)
> > +#define MVEBU_COMPHY_DFE_RES(n) (0x81c + (n) * 0x1000)
> > +#define MVEBU_COMPHY_DFE_RES_FORCE_GEN_TBL BIT(15)
> > +#define MVEBU_COMPHY_COEF(n) (0x828 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_COEF_DFE_EN BIT(14)
> > +#define MVEBU_COMPHY_COEF_DFE_CTRL BIT(15)
> > +#define MVEBU_COMPHY_GEN1_S0(n) (0x834 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_GEN1_S0_TX_AMP(n) ((n) << 1)
> > +#define MVEBU_COMPHY_GEN1_S0_TX_EMPH(n) ((n) << 7)
> > +#define MVEBU_COMPHY_GEN1_S1(n) (0x838 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(n) ((n) << 0)
> > +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(n) ((n) << 3)
> > +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_FI(n) ((n) << 6)
> > +#define MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(n) ((n) << 8)
> > +#define MVEBU_COMPHY_GEN1_S1_RX_DFE_EN BIT(10)
> > +#define MVEBU_COMPHY_GEN1_S1_RX_DIV(n) ((n) << 11)
> > +#define MVEBU_COMPHY_GEN1_S2(n) (0x8f4 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_GEN1_S2_TX_EMPH(n) ((n) << 0)
> > +#define MVEBU_COMPHY_GEN1_S2_TX_EMPH_EN BIT(4)
> > +#define MVEBU_COMPHY_LOOPBACK(n) (0x88c + (n) * 0x1000)
> > +#define MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(n) ((n) << 1)
> > +#define MVEBU_COMPHY_VDD_CAL0(n) (0x908 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_VDD_CAL0_CONT_MODE BIT(15)
> > +#define MVEBU_COMPHY_EXT_SELV(n) (0x914 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_EXT_SELV_RX_SAMPL(n) ((n) << 5)
> > +#define MVEBU_COMPHY_MISC_CTRL0(n) (0x93c + (n) * 0x1000)
> > +#define MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE BIT(5)
> > +#define MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL BIT(10)
> > +#define MVEBU_COMPHY_RX_CTRL1(n) (0x940 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL BIT(11)
> > +#define MVEBU_COMPHY_RX_CTRL1_CLK8T_EN BIT(12)
> > +#define MVEBU_COMPHY_SPEED_DIV(n) (0x954 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_SPEED_DIV_TX_FORCE BIT(7)
> > +#define MVEBU_SP_CALIB(n) (0x96c + (n) * 0x1000)
> > +#define MVEBU_SP_CALIB_SAMPLER(n) ((n) << 8)
> > +#define MVEBU_SP_CALIB_SAMPLER_EN BIT(12)
> > +#define MVEBU_COMPHY_TX_SLEW_RATE(n) (0x974 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_TX_SLEW_RATE_EMPH(n) ((n) << 5)
> > +#define MVEBU_COMPHY_TX_SLEW_RATE_SLC(n) ((n) << 10)
> > +#define MVEBU_COMPHY_DLT_CTRL(n) (0x984 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_DLT_CTRL_DTL_FLOOP_EN BIT(2)
> > +#define MVEBU_COMPHY_FRAME_DETECT0(n) (0xa14 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_FRAME_DETECT0_PATN(n) ((n) << 7)
> > +#define MVEBU_COMPHY_FRAME_DETECT3(n) (0xa20 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_FRAME_DETECT3_LOST_TIMEOUT_EN BIT(12)
> > +#define MVEBU_COMPHY_DME(n) (0xa28 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_DME_ETH_MODE BIT(7)
> > +#define MVEBU_COMPHY_TRAINING0(n) (0xa68 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_TRAINING0_P2P_HOLD BIT(15)
> > +#define MVEBU_COMPHY_TRAINING5(n) (0xaa4 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_TRAINING5_RX_TIMER(n) ((n) << 0)
> > +#define MVEBU_COMPHY_TX_TRAIN_PRESET(n) (0xb1c + (n) * 0x1000)
> > +#define MVEBU_COMPHY_TX_TRAIN_PRESET_16B_AUTO_EN BIT(8)
> > +#define MVEBU_COMPHY_TX_TRAIN_PRESET_PRBS11 BIT(9)
> > +#define MVEBU_COMPHY_GEN1_S3(n) (0xc40 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_GEN1_S3_FBCK_SEL BIT(9)
> > +#define MVEBU_COMPHY_GEN1_S4(n) (0xc44 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_GEN1_S4_DFE_RES(n) ((n) << 8)
> > +#define MVEBU_COMPHY_TX_PRESET(n) (0xc68 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_TX_PRESET_INDEX(n) ((n) << 0)
> > +#define MVEBU_COMPHY_GEN1_S5(n) (0xd38 + (n) * 0x1000)
> > +#define MVEBU_COMPHY_GEN1_S5_ICP(n) ((n) << 0)
> > +
> > +/* Relative to priv->regmap */
> > +#define MVEBU_COMPHY_CONF1(n) (0x1000 + (n) * 0x28)
> > +#define MVEBU_COMPHY_CONF1_PWRUP BIT(1)
> > +#define MVEBU_COMPHY_CONF1_USB_PCIE BIT(2) /* 0: Ethernet/SATA */
> > +#define MVEBU_COMPHY_CONF6(n) (0x1014 + (n) * 0x28)
> > +#define MVEBU_COMPHY_CONF6_40B BIT(18)
> > +#define MVEBU_COMPHY_SELECTOR 0x1140
> > +#define MVEBU_COMPHY_SELECTOR_PHY(n) ((n) * 0x4)
> > +
> > +#define MVEBU_COMPHY_LANES 6
> > +#define MVEBU_COMPHY_PORTS 3
> > +
> > +struct mvebu_comhy_conf {
> > + enum phy_mode mode;
> > + unsigned lane;
> > + unsigned port;
> > + u32 mux;
> > +};
> > +
> > +#define MVEBU_COMPHY_CONF(_lane, _port, _mode, _mux) \
> > + { \
> > + .lane = _lane, \
> > + .port = _port, \
> > + .mode = _mode, \
> > + .mux = _mux, \
> > + }
> > +
> > +static const struct mvebu_comhy_conf mvebu_comphy_cp110_modes[] = {
> > + /* lane 0 */
> > + MVEBU_COMPHY_CONF(0, 1, PHY_MODE_SGMII, 0x1),
> > + /* lane 1 */
> > + MVEBU_COMPHY_CONF(1, 2, PHY_MODE_SGMII, 0x1),
> > + /* lane 2 */
> > + MVEBU_COMPHY_CONF(2, 0, PHY_MODE_SGMII, 0x1),
> > + MVEBU_COMPHY_CONF(2, 0, PHY_MODE_10GKR, 0x1),
> > + /* lane 3 */
> > + MVEBU_COMPHY_CONF(3, 1, PHY_MODE_SGMII, 0x2),
> > + /* lane 4 */
> > + MVEBU_COMPHY_CONF(4, 0, PHY_MODE_SGMII, 0x2),
> > + MVEBU_COMPHY_CONF(4, 0, PHY_MODE_10GKR, 0x2),
> > + MVEBU_COMPHY_CONF(4, 1, PHY_MODE_SGMII, 0x1),
> > + /* lane 5 */
> > + MVEBU_COMPHY_CONF(5, 2, PHY_MODE_SGMII, 0x1),
> > +};
> > +
> > +struct mvebu_comphy_priv {
> > + void __iomem *base;
> > + struct regmap *regmap;
> > + struct device *dev;
> > + int modes[MVEBU_COMPHY_LANES];
> > +};
> > +
> > +struct mvebu_comphy_lane {
> > + struct mvebu_comphy_priv *priv;
> > + unsigned id;
> > + enum phy_mode mode;
> > + int port;
> > +};
> > +
> > +static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode)
> > +{
> > + int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes);
> > +
> > + /* Unused PHY mux value is 0x0 */
> > + if (mode == PHY_MODE_INVALID)
> > + return 0;
> > +
> > + for (i = 0; i < n; i++) {
> > + if (mvebu_comphy_cp110_modes[i].lane == lane &&
> > + mvebu_comphy_cp110_modes[i].port == port &&
> > + mvebu_comphy_cp110_modes[i].mode == mode)
> > + break;
> > + }
> > +
> > + if (i == n)
> > + return -EINVAL;
> > +
> > + return mvebu_comphy_cp110_modes[i].mux;
> > +}
> > +
> > +static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane,
> > + enum phy_mode mode)
> > +{
> > + struct mvebu_comphy_priv *priv = lane->priv;
> > + u32 val;
> > +
> > + regmap_read(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), &val);
> > + val &= ~MVEBU_COMPHY_CONF1_USB_PCIE;
> > + val |= MVEBU_COMPHY_CONF1_PWRUP;
> > + regmap_write(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), val);
> > +
> > + /* Select baud rates and PLLs */
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> > + val &= ~(MVEBU_COMPHY_SERDES_CFG0_PU_PLL |
> > + MVEBU_COMPHY_SERDES_CFG0_PU_RX |
> > + MVEBU_COMPHY_SERDES_CFG0_PU_TX |
> > + MVEBU_COMPHY_SERDES_CFG0_HALF_BUS |
> > + MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) |
> > + MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf));
> > + if (mode == PHY_MODE_10GKR)
> > + val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) |
> > + MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe);
> > + else if (mode == PHY_MODE_SGMII)
> > + val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) |
> > + MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) |
> > + MVEBU_COMPHY_SERDES_CFG0_HALF_BUS;
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> > +
> > + /* reset */
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > + val &= ~(MVEBU_COMPHY_SERDES_CFG1_RESET |
> > + MVEBU_COMPHY_SERDES_CFG1_CORE_RESET |
> > + MVEBU_COMPHY_SERDES_CFG1_RF_RESET);
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > +
> > + /* de-assert reset */
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > + val |= MVEBU_COMPHY_SERDES_CFG1_RESET |
> > + MVEBU_COMPHY_SERDES_CFG1_CORE_RESET;
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > +
> > + /* wait until clocks are ready */
> > + mdelay(1);
> > +
> > + /* exlicitly disable 40B, the bits isn't clear on reset */
> > + regmap_read(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), &val);
> > + val &= ~MVEBU_COMPHY_CONF6_40B;
> > + regmap_write(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), val);
> > +
> > + /* refclk selection */
> > + val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
> > + val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL;
> > + if (mode == PHY_MODE_10GKR)
> > + val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE;
> > + writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id));
> > +
> > + /* power and pll selection */
> > + val = readl(priv->base + MVEBU_COMPHY_PWRPLL_CTRL(lane->id));
> > + val &= ~(MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(0x1f) |
> > + MVEBU_COMPHY_PWRPLL_PHY_MODE(0x7));
> > + val |= MVEBU_COMPHY_PWRPLL_CTRL_RFREQ(0x1) |
> > + MVEBU_COMPHY_PWRPLL_PHY_MODE(0x4);
> > + writel(val, priv->base + MVEBU_COMPHY_PWRPLL_CTRL(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_LOOPBACK(lane->id));
> > + val &= ~MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(0x7);
> > + val |= MVEBU_COMPHY_LOOPBACK_DBUS_WIDTH(0x1);
> > + writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id));
> > +}
> > +
> > +static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane,
> > + enum phy_mode mode)
> > +{
> > + struct mvebu_comphy_priv *priv = lane->priv;
> > + u32 val;
> > +
> > + /* SERDES external config */
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> > + val |= MVEBU_COMPHY_SERDES_CFG0_PU_PLL |
> > + MVEBU_COMPHY_SERDES_CFG0_PU_RX |
> > + MVEBU_COMPHY_SERDES_CFG0_PU_TX;
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG0(lane->id));
> > +
> > + /* check rx/tx pll */
> > + readl_poll_timeout(priv->base + MVEBU_COMPHY_SERDES_STATUS0(lane->id),
> > + val,
> > + val & (MVEBU_COMPHY_SERDES_STATUS0_RX_PLL_RDY |
> > + MVEBU_COMPHY_SERDES_STATUS0_TX_PLL_RDY),
> > + 1000, 150000);
> > + if (!(val & (MVEBU_COMPHY_SERDES_STATUS0_RX_PLL_RDY |
> > + MVEBU_COMPHY_SERDES_STATUS0_TX_PLL_RDY)))
> > + return -ETIMEDOUT;
> > +
> > + /* rx init */
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > + val |= MVEBU_COMPHY_SERDES_CFG1_RX_INIT;
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > +
> > + /* check rx */
> > + readl_poll_timeout(priv->base + MVEBU_COMPHY_SERDES_STATUS0(lane->id),
> > + val, val & MVEBU_COMPHY_SERDES_STATUS0_RX_INIT,
> > + 1000, 10000);
> > + if (!(val & MVEBU_COMPHY_SERDES_STATUS0_RX_INIT))
> > + return -ETIMEDOUT;
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > + val &= ~MVEBU_COMPHY_SERDES_CFG1_RX_INIT;
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > +
> > + return 0;
> > +}
> > +
> > +static int mvebu_comphy_set_mode_sgmii(struct phy *phy)
> > +{
> > + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> > + struct mvebu_comphy_priv *priv = lane->priv;
> > + u32 val;
> > +
> > + mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_SGMII);
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> > + val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
> > + val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL;
> > + writel(val, priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> > + val &= ~MVEBU_COMPHY_DLT_CTRL_DTL_FLOOP_EN;
> > + writel(val, priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> > +
> > + regmap_read(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), &val);
> > + val &= ~MVEBU_COMPHY_CONF1_USB_PCIE;
> > + val |= MVEBU_COMPHY_CONF1_PWRUP;
> > + regmap_write(priv->regmap, MVEBU_COMPHY_CONF1(lane->id), val);
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> > + val &= ~MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xf);
> > + val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1);
> > + writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> > +
> > + return mvebu_comphy_init_plls(lane, PHY_MODE_SGMII);
> > +}
> > +
> > +static int mvebu_comphy_set_mode_10gkr(struct phy *phy)
> > +{
> > + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> > + struct mvebu_comphy_priv *priv = lane->priv;
> > + u32 val;
> > +
> > + mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_10GKR);
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> > + val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL |
> > + MVEBU_COMPHY_RX_CTRL1_CLK8T_EN;
> > + writel(val, priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> > + val |= MVEBU_COMPHY_DLT_CTRL_DTL_FLOOP_EN;
> > + writel(val, priv->base + MVEBU_COMPHY_DLT_CTRL(lane->id));
> > +
> > + /* Speed divider */
> > + val = readl(priv->base + MVEBU_COMPHY_SPEED_DIV(lane->id));
> > + val |= MVEBU_COMPHY_SPEED_DIV_TX_FORCE;
> > + writel(val, priv->base + MVEBU_COMPHY_SPEED_DIV(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
> > + val |= MVEBU_COMPHY_SERDES_CFG2_DFE_EN;
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG2(lane->id));
> > +
> > + /* DFE resolution */
> > + val = readl(priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
> > + val |= MVEBU_COMPHY_DFE_RES_FORCE_GEN_TBL;
> > + writel(val, priv->base + MVEBU_COMPHY_DFE_RES(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> > + val &= ~(MVEBU_COMPHY_GEN1_S0_TX_AMP(0x1f) |
> > + MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xf));
> > + val |= MVEBU_COMPHY_GEN1_S0_TX_AMP(0x1c) |
> > + MVEBU_COMPHY_GEN1_S0_TX_EMPH(0xe);
> > + writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_GEN1_S2(lane->id));
> > + val &= ~MVEBU_COMPHY_GEN1_S2_TX_EMPH(0xf);
> > + val |= MVEBU_COMPHY_GEN1_S2_TX_EMPH_EN;
> > + writel(val, priv->base + MVEBU_COMPHY_GEN1_S2(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_TX_SLEW_RATE(lane->id));
> > + val |= MVEBU_COMPHY_TX_SLEW_RATE_EMPH(0x3) |
> > + MVEBU_COMPHY_TX_SLEW_RATE_SLC(0x3f);
> > + writel(val, priv->base + MVEBU_COMPHY_TX_SLEW_RATE(lane->id));
> > +
> > + /* Impedance calibration */
> > + val = readl(priv->base + MVEBU_COMPHY_IMP_CAL(lane->id));
> > + val &= ~MVEBU_COMPHY_IMP_CAL_TX_EXT(0x1f);
> > + val |= MVEBU_COMPHY_IMP_CAL_TX_EXT(0xe) |
> > + MVEBU_COMPHY_IMP_CAL_TX_EXT_EN;
> > + writel(val, priv->base + MVEBU_COMPHY_IMP_CAL(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_GEN1_S5(lane->id));
> > + val &= ~MVEBU_COMPHY_GEN1_S5_ICP(0xf);
> > + writel(val, priv->base + MVEBU_COMPHY_GEN1_S5(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
> > + val &= ~(MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x7) |
> > + MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x7) |
> > + MVEBU_COMPHY_GEN1_S1_RX_MUL_FI(0x3) |
> > + MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(0x3));
> > + val |= MVEBU_COMPHY_GEN1_S1_RX_DFE_EN |
> > + MVEBU_COMPHY_GEN1_S1_RX_MUL_PI(0x2) |
> > + MVEBU_COMPHY_GEN1_S1_RX_MUL_PF(0x2) |
> > + MVEBU_COMPHY_GEN1_S1_RX_MUL_FF(0x1) |
> > + MVEBU_COMPHY_GEN1_S1_RX_DIV(0x3);
> > + writel(val, priv->base + MVEBU_COMPHY_GEN1_S1(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_COEF(lane->id));
> > + val &= ~(MVEBU_COMPHY_COEF_DFE_EN | MVEBU_COMPHY_COEF_DFE_CTRL);
> > + writel(val, priv->base + MVEBU_COMPHY_COEF(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
> > + val &= ~MVEBU_COMPHY_GEN1_S4_DFE_RES(0x3);
> > + val |= MVEBU_COMPHY_GEN1_S4_DFE_RES(0x1);
> > + writel(val, priv->base + MVEBU_COMPHY_GEN1_S4(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_GEN1_S3(lane->id));
> > + val |= MVEBU_COMPHY_GEN1_S3_FBCK_SEL;
> > + writel(val, priv->base + MVEBU_COMPHY_GEN1_S3(lane->id));
> > +
> > + /* rx training timer */
> > + val = readl(priv->base + MVEBU_COMPHY_TRAINING5(lane->id));
> > + val &= ~MVEBU_COMPHY_TRAINING5_RX_TIMER(0x3ff);
> > + val |= MVEBU_COMPHY_TRAINING5_RX_TIMER(0x13);
> > + writel(val, priv->base + MVEBU_COMPHY_TRAINING5(lane->id));
> > +
> > + /* tx train peak to peak hold */
> > + val = readl(priv->base + MVEBU_COMPHY_TRAINING0(lane->id));
> > + val |= MVEBU_COMPHY_TRAINING0_P2P_HOLD;
> > + writel(val, priv->base + MVEBU_COMPHY_TRAINING0(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_TX_PRESET(lane->id));
> > + val &= ~MVEBU_COMPHY_TX_PRESET_INDEX(0xf);
> > + val |= MVEBU_COMPHY_TX_PRESET_INDEX(0x2); /* preset coeff */
> > + writel(val, priv->base + MVEBU_COMPHY_TX_PRESET(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_FRAME_DETECT3(lane->id));
> > + val &= ~MVEBU_COMPHY_FRAME_DETECT3_LOST_TIMEOUT_EN;
> > + writel(val, priv->base + MVEBU_COMPHY_FRAME_DETECT3(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_TX_TRAIN_PRESET(lane->id));
> > + val |= MVEBU_COMPHY_TX_TRAIN_PRESET_16B_AUTO_EN |
> > + MVEBU_COMPHY_TX_TRAIN_PRESET_PRBS11;
> > + writel(val, priv->base + MVEBU_COMPHY_TX_TRAIN_PRESET(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_FRAME_DETECT0(lane->id));
> > + val &= ~MVEBU_COMPHY_FRAME_DETECT0_PATN(0x1ff);
> > + val |= MVEBU_COMPHY_FRAME_DETECT0_PATN(0x88);
> > + writel(val, priv->base + MVEBU_COMPHY_FRAME_DETECT0(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_DME(lane->id));
> > + val |= MVEBU_COMPHY_DME_ETH_MODE;
> > + writel(val, priv->base + MVEBU_COMPHY_DME(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_VDD_CAL0(lane->id));
> > + val |= MVEBU_COMPHY_VDD_CAL0_CONT_MODE;
> > + writel(val, priv->base + MVEBU_COMPHY_VDD_CAL0(lane->id));
> > +
> > + val = readl(priv->base + MVEBU_SP_CALIB(lane->id));
> > + val &= ~MVEBU_SP_CALIB_SAMPLER(0x3);
> > + val |= MVEBU_SP_CALIB_SAMPLER(0x3) |
> > + MVEBU_SP_CALIB_SAMPLER_EN;
> > + writel(val, priv->base + MVEBU_SP_CALIB(lane->id));
> > + val &= ~MVEBU_SP_CALIB_SAMPLER_EN;
> > + writel(val, priv->base + MVEBU_SP_CALIB(lane->id));
> > +
> > + /* External rx regulator */
> > + val = readl(priv->base + MVEBU_COMPHY_EXT_SELV(lane->id));
> > + val &= ~MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1f);
> > + val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a);
> > + writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id));
> > +
> > + return mvebu_comphy_init_plls(lane, PHY_MODE_10GKR);
> > +}
> > +
> > +static int mvebu_comphy_power_on(struct phy *phy)
> > +{
> > + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> > + struct mvebu_comphy_priv *priv = lane->priv;
> > + int ret;
> > + u32 mux, val;
> > +
> > + mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode);
> > + if (mux < 0)
> > + return -ENOTSUPP;
> > +
> > + regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val);
> > + val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
> > + val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id);
> > + regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val);
> > +
> > + switch (lane->mode) {
> > + case PHY_MODE_SGMII:
> > + ret = mvebu_comphy_set_mode_sgmii(phy);
> > + break;
> > + case PHY_MODE_10GKR:
> > + ret = mvebu_comphy_set_mode_10gkr(phy);
> > + break;
> > + default:
> > + return -ENOTSUPP;
> > + }
> > +
> > + /* digital reset */
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > + val |= MVEBU_COMPHY_SERDES_CFG1_RF_RESET;
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > +
> > + return ret;
> > +}
> > +
> > +static int mvebu_comphy_set_mode(struct phy *phy, enum phy_mode mode)
> > +{
> > + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> > +
> > + if (mvebu_comphy_get_mux(lane->id, lane->port, mode) < 0)
> > + return -EINVAL;
> > +
> > + lane->mode = mode;
> > + return 0;
> > +}
> > +
> > +static int mvebu_comphy_power_off(struct phy *phy)
> > +{
> > + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy);
> > + struct mvebu_comphy_priv *priv = lane->priv;
> > + u32 val;
> > +
> > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > + val &= ~(MVEBU_COMPHY_SERDES_CFG1_RESET |
> > + MVEBU_COMPHY_SERDES_CFG1_CORE_RESET |
> > + MVEBU_COMPHY_SERDES_CFG1_RF_RESET);
> > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id));
> > +
> > + regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val);
> > + val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id));
> > + regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct phy_ops mvebu_comphy_ops = {
> > + .power_on = mvebu_comphy_power_on,
> > + .power_off = mvebu_comphy_power_off,
> > + .set_mode = mvebu_comphy_set_mode,
> > + .owner = THIS_MODULE,
> > +};
> > +
> > +static struct phy *mvebu_comphy_xlate(struct device *dev,
> > + struct of_phandle_args *args)
> > +{
> > + struct mvebu_comphy_lane *lane;
> > + struct phy *phy;
> > +
> > + if (WARN_ON(args->args[0] >= MVEBU_COMPHY_PORTS))
> > + return ERR_PTR(-EINVAL);
> > +
> > + phy = of_phy_simple_xlate(dev, args);
> > + if (IS_ERR(phy))
> > + return phy;
> > +
> > + lane = phy_get_drvdata(phy);
> > + if (lane->port >= 0)
> > + return ERR_PTR(-EBUSY);
> > + lane->port = args->args[0];
> > +
> > + return phy;
> > +}
> > +
> > +static int mvebu_comphy_probe(struct platform_device *pdev)
> > +{
> > + struct mvebu_comphy_priv *priv;
> > + struct phy_provider *provider;
> > + struct device_node *child;
> > + struct resource *res;
> > +
> > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + return -ENOMEM;
> > +
> > + priv->dev = &pdev->dev;
> > + priv->regmap =
> > + syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> > + "marvell,system-controller");
> > + if (IS_ERR(priv->regmap))
> > + return PTR_ERR(priv->regmap);
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + priv->base = devm_ioremap_resource(&pdev->dev, res);
> > + if (!priv->base)
> > + return -ENOMEM;
> > +
> > + for_each_available_child_of_node(pdev->dev.of_node, child) {
> > + struct mvebu_comphy_lane *lane;
> > + struct phy *phy;
> > + int ret;
> > + u32 val;
> > +
> > + ret = of_property_read_u32(child, "reg", &val);
> > + if (ret < 0) {
> > + dev_err(&pdev->dev, "missing 'reg' property (%d)\n",
> > + ret);
> > + continue;
> > + }
> > +
> > + if (val >= MVEBU_COMPHY_LANES) {
> > + dev_err(&pdev->dev, "invalid 'reg' property\n");
> > + continue;
> > + }
> > +
> > + lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL);
> > + if (!lane)
> > + return -ENOMEM;
> > +
> > + phy = devm_phy_create(&pdev->dev, child, &mvebu_comphy_ops);
> > + if (IS_ERR(phy))
> > + return PTR_ERR(phy);
> > +
> > + lane->priv = priv;
> > + lane->mode = PHY_MODE_INVALID;
> > + lane->id = val;
> > + lane->port = -1;
> > + phy_set_drvdata(phy, lane);
> > +
> > + /*
> > + * Once all modes are supported in this driver we should call
> > + * mvebu_comphy_power_off(phy) here to avoid relying on the
> > + * bootloader/firmware configuration.
> > + */
> > + }
> > +
> > + dev_set_drvdata(&pdev->dev, priv);
> > + provider = devm_of_phy_provider_register(&pdev->dev,
> > + mvebu_comphy_xlate);
> > + return PTR_ERR_OR_ZERO(provider);
> > +}
> > +
> > +static const struct of_device_id mvebu_comphy_of_match_table[] = {
> > + { .compatible = "marvell,comphy-cp110" },
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(of, mvebu_comphy_of_match_table);
> > +
> > +static struct platform_driver mvebu_comphy_driver = {
> > + .probe = mvebu_comphy_probe,
> > + .driver = {
> > + .name = "mvebu-comphy",
> > + .of_match_table = mvebu_comphy_of_match_table,
> > + },
> > +};
> > +module_platform_driver(mvebu_comphy_driver);
> > +
> > +MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
> > +MODULE_DESCRIPTION("Common PHY driver for mvebu SoCs");
> > +MODULE_LICENSE("GPL v2");
> >
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* RE: [PATCH net-next v2] net: bcmgenet: Use correct I/O accessors
From: David Laight @ 2017-08-30 11:39 UTC (permalink / raw)
To: 'Florian Fainelli', netdev@vger.kernel.org
Cc: davem@davemloft.net, opendmb@gmail.com, jaedon.shin@gmail.com
In-Reply-To: <1504034731-31613-1-git-send-email-f.fainelli@gmail.com>
From: Florian Fainelli
> Sent: 29 August 2017 20:26
> The GENET driver currently uses __raw_{read,write}l which means
> native I/O endian. This works correctly for an ARM LE kernel (default)
> but fails miserably on an ARM BE (BE8) kernel where registers are kept
> little endian, so replace uses with {read,write}l_relaxed here which is
> what we want because this is all performance sensitive code.
...
> + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
> + __raw_writel(value, offset);
> + else
> + writel_relaxed(value, offset);
How do you know that all BE MIPS that might have this driver have
the BE registers of your card?
(Or that all ARM BE systems have LE registers.)
If nothing else the driver code should be predicated on a
condition set by the kernel config that depends on the cpu build
rather than embedding that condition in a lot of drivers
David
^ permalink raw reply
* [PATCH][next] qed: fix spelling mistake: "calescing" -> "coalescing"
From: Colin King @ 2017-08-30 11:40 UTC (permalink / raw)
To: Yuval Mintz, Ariel Elior, everest-linux-l2, netdev; +Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to spelling mistake in DP_NOTICE message
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 9a1645852015..085338990f49 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -2805,7 +2805,7 @@ static int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle)
p_hwfn = p_cid->p_owner;
rc = qed_get_queue_coalesce(p_hwfn, coal, handle);
if (rc)
- DP_NOTICE(p_hwfn, "Unable to read queue calescing\n");
+ DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n");
return rc;
}
--
2.14.1
^ permalink raw reply related
* [PATCH][next] bpf: test_maps: fix typo "conenct" -> "connext"
From: Colin King @ 2017-08-30 11:47 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Shuah Khan, netdev,
linux-kselftest
Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to typo in printf error message
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
tools/testing/selftests/bpf/test_maps.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 7059bb315a10..8fdaf2e21c8a 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -525,7 +525,7 @@ static void test_sockmap(int tasks, void *data)
addr.sin_port = htons(ports[i - 2]);
err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
if (err) {
- printf("failed to conenct\n");
+ printf("failed to connect\n");
goto out;
}
}
--
2.14.1
^ permalink raw reply related
* [PATCH][next][V2] bpf: test_maps: fix typo "conenct" -> "connect"
From: Colin King @ 2017-08-30 11:47 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Shuah Khan, netdev,
linux-kselftest
Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Trivial fix to typo in printf error message
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
tools/testing/selftests/bpf/test_maps.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index 7059bb315a10..8fdaf2e21c8a 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -525,7 +525,7 @@ static void test_sockmap(int tasks, void *data)
addr.sin_port = htons(ports[i - 2]);
err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
if (err) {
- printf("failed to conenct\n");
+ printf("failed to connect\n");
goto out;
}
}
--
2.14.1
^ permalink raw reply related
* [PATCH] netfilter: nat: constify rhashtable_params
From: Arvind Yadav @ 2017-08-30 11:48 UTC (permalink / raw)
To: davem, fw, kadlec, pablo; +Cc: linux-kernel, netdev, coreteam, netfilter-devel
rhashtable_params are not supposed to change at runtime. All
Functions rhashtable_* working with const rhashtable_params
provided by <linux/rhashtable.h>. So mark the non-const structs
as const.
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
---
net/netfilter/nf_nat_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index eb54178..d1f355e 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -198,7 +198,7 @@ static int nf_nat_bysource_cmp(struct rhashtable_compare_arg *arg,
return 0;
}
-static struct rhashtable_params nf_nat_bysource_params = {
+static const struct rhashtable_params nf_nat_bysource_params = {
.head_offset = offsetof(struct nf_conn, nat_bysource),
.obj_hashfn = nf_nat_bysource_hash,
.obj_cmpfn = nf_nat_bysource_cmp,
--
1.9.1
^ permalink raw reply related
* [PATCH] RDS: constify rhashtable_params
From: Arvind Yadav @ 2017-08-30 11:49 UTC (permalink / raw)
To: davem, santosh.shilimkar; +Cc: linux-kernel, rds-devel, linux-rdma, netdev
rhashtable_params are not supposed to change at runtime. All
Functions rhashtable_* working with const rhashtable_params
provided by <linux/rhashtable.h>. So mark the non-const structs
as const.
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
---
net/rds/bind.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 3a915be..75d43dc 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -40,7 +40,7 @@
static struct rhashtable bind_hash_table;
-static struct rhashtable_params ht_parms = {
+static const struct rhashtable_params ht_parms = {
.nelem_hint = 768,
.key_len = sizeof(u64),
.key_offset = offsetof(struct rds_sock, rs_bound_key),
--
1.9.1
^ permalink raw reply related
* Re: Question about ip_defrag
From: Florian Westphal @ 2017-08-30 11:58 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Florian Westphal, liujian (CE), davem@davemloft.net,
edumazet@google.com, netdev@vger.kernel.org, Wangkefeng (Kevin),
weiyongjun (A)
In-Reply-To: <20170830125843.250c91c1@redhat.com>
Jesper Dangaard Brouer <brouer@redhat.com> wrote:
> > I take 2) back. Its wrong to do this, for large NR_CPU values it
> > would even overflow.
>
> Alternatively solution 3:
> Why do we want to maintain a (4MBytes) memory limit, across all CPUs?
> Couldn't we just allow each CPU to have a memory limit?
Consider ipv4, ipv6, nf ipv6 defrag, 6lowpan, and 8k cpus... This will
render any limit useless.
> > > To me it looks like we/I have been using the wrong API for comparing
> > > against percpu_counters. I guess we should have used __percpu_counter_compare().
> >
> > Are you sure? For liujian use case (64 cores) it looks like we would
> > always fall through to percpu_counter_sum() so we eat spinlock_irqsave
> > cost for all compares.
> >
> > Before we entertain this we should consider reducing frag_percpu_counter_batch
> > to a smaller value.
>
> Yes, I agree, we really need to lower/reduce the frag_percpu_counter_batch.
> As you say, else the __percpu_counter_compare() call will be useless
> (around systems with >= 32 CPUs).
>
> I think the bug is in frag_mem_limit(). It just reads the global
> counter (fbc->count), without considering other CPUs can have upto 130K
> that haven't been subtracted yet (due to 3M low limit, become dangerous
> at >=24 CPUs). The __percpu_counter_compare() does the right thing,
> and takes into account the number of (online) CPUs and batch size, to
> account for this.
Right, I think we should at very least use __percpu_counter_compare
before denying a new frag queue allocation request.
I'll create a patch.
^ permalink raw reply
* [patch net-next 0/8] mlxsw: Add IPv6 host dpipe table
From: Jiri Pirko @ 2017-08-30 12:02 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
From: Jiri Pirko <jiri@mellanox.com>
Arkadi says:
This patchset adds IPv6 host dpipe table support. This will provide the
ability to observe the hardware offloaded IPv6 neighbors.
Arkadi Sharshevsky (8):
devlink: Add IPv6 header for dpipe
mlxsw: spectrum_router: Export IPv6 link local address check helper
mlxsw: spectrum_dpipe: Add IPv6 host table initial support
mlxsw: spectrum_router: Add IPv6 neighbor access helper
mlxsw: spectrum_dpipe: Make host entry fill handler more generic
mlxsw: spectrum_dpipe: Add support for IPv6 host table dump
mlxsw: spectrum_router: Add support for setting counters on IPv6
neighbors
mlxsw: spectrum_dpipe: Add support for controlling IPv6 neighbor
counters
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 182 ++++++++++++++++++---
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.h | 1 +
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 37 ++++-
.../net/ethernet/mellanox/mlxsw/spectrum_router.h | 3 +
include/net/devlink.h | 1 +
include/uapi/linux/devlink.h | 5 +
net/core/devlink.c | 17 ++
7 files changed, 219 insertions(+), 27 deletions(-)
--
2.9.3
^ permalink raw reply
* [patch net-next 1/8] devlink: Add IPv6 header for dpipe
From: Jiri Pirko @ 2017-08-30 12:02 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
This will be used by the IPv6 host table which will be introduced in the
following patches. The fields in the header are added per-use. This header
is global and can be reused by many drivers.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/devlink.h | 1 +
include/uapi/linux/devlink.h | 5 +++++
net/core/devlink.c | 17 +++++++++++++++++
3 files changed, 23 insertions(+)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index aaf7178..b9654e1 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -330,6 +330,7 @@ int devlink_dpipe_match_put(struct sk_buff *skb,
struct devlink_dpipe_match *match);
extern struct devlink_dpipe_header devlink_dpipe_header_ethernet;
extern struct devlink_dpipe_header devlink_dpipe_header_ipv4;
+extern struct devlink_dpipe_header devlink_dpipe_header_ipv6;
#else
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 6c17254..0cbca96 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -234,9 +234,14 @@ enum devlink_dpipe_field_ipv4_id {
DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
};
+enum devlink_dpipe_field_ipv6_id {
+ DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
+};
+
enum devlink_dpipe_header_id {
DEVLINK_DPIPE_HEADER_ETHERNET,
DEVLINK_DPIPE_HEADER_IPV4,
+ DEVLINK_DPIPE_HEADER_IPV6,
};
#endif /* _UAPI_LINUX_DEVLINK_H_ */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 194708a..47931a2 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -63,6 +63,23 @@ struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
};
EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
+static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
+ {
+ .name = "destination ip",
+ .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
+ .bitwidth = 128,
+ },
+};
+
+struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
+ .name = "ipv6",
+ .id = DEVLINK_DPIPE_HEADER_IPV6,
+ .fields = devlink_dpipe_fields_ipv6,
+ .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
+ .global = true,
+};
+EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
+
EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
static LIST_HEAD(devlink_list);
--
2.9.3
^ permalink raw reply related
* [patch net-next 2/8] mlxsw: spectrum_router: Export IPv6 link local address check helper
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Neighbors with link local addresses are not offloaded to the host table,
yet, the are maintained in the driver for adjacency table usage. When
dumping the IPv6 host neighbors this link local neighbors should be
ignored. This patch exports this helper for dpipe usage.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 6 ++++--
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 377d85c..1f41bcd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -1396,8 +1396,10 @@ mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
}
-static bool mlxsw_sp_neigh_ipv6_ignore(struct neighbour *n)
+bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry)
{
+ struct neighbour *n = neigh_entry->key.n;
+
/* Packets with a link-local destination address are trapped
* after LPM lookup and never reach the neighbour table, so
* there is no need to program such neighbours to the device.
@@ -1420,7 +1422,7 @@ mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
mlxsw_sp_rauht_op(adding));
} else if (neigh_entry->key.n->tbl->family == AF_INET6) {
- if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry->key.n))
+ if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
return;
mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry,
mlxsw_sp_rauht_op(adding));
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index fb0f971..5b68616 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -76,5 +76,6 @@ void
mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry,
bool adding);
+bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry);
#endif /* _MLXSW_ROUTER_H_*/
--
2.9.3
^ permalink raw reply related
* [patch net-next 3/8] mlxsw: spectrum_dpipe: Add IPv6 host table initial support
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add IPv6 host table initial support. The action behavior for both IPv4/6
tables is the same, thus the same action dump op is used. Neighbors with
link local address are ignored.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 76 ++++++++++++++++++++--
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.h | 1 +
2 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 3ea1314..93ba6a6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -76,6 +76,7 @@ static struct devlink_dpipe_header *mlxsw_dpipe_headers[] = {
&mlxsw_sp_dpipe_header_metadata,
&devlink_dpipe_header_ethernet,
&devlink_dpipe_header_ipv4,
+ &devlink_dpipe_header_ipv6,
};
static struct devlink_dpipe_headers mlxsw_sp_dpipe_headers = {
@@ -328,9 +329,21 @@ static int mlxsw_sp_dpipe_table_host_matches_dump(struct sk_buff *skb, int type)
if (err)
return err;
- match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
- match.header = &devlink_dpipe_header_ipv4;
- match.field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ switch (type) {
+ case AF_INET:
+ match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
+ match.header = &devlink_dpipe_header_ipv4;
+ match.field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ break;
+ case AF_INET6:
+ match.type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
+ match.header = &devlink_dpipe_header_ipv6;
+ match.field_id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
return devlink_dpipe_match_put(skb, &match);
}
@@ -342,7 +355,7 @@ mlxsw_sp_dpipe_table_host4_matches_dump(void *priv, struct sk_buff *skb)
}
static int
-mlxsw_sp_dpipe_table_host4_actions_dump(void *priv, struct sk_buff *skb)
+mlxsw_sp_dpipe_table_host_actions_dump(void *priv, struct sk_buff *skb)
{
struct devlink_dpipe_action action = {0};
@@ -648,8 +661,15 @@ mlxsw_sp_dpipe_table_host_size_get(struct mlxsw_sp *mlxsw_sp, int type)
if (!rif)
continue;
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
- if (mlxsw_sp_neigh_entry_type(neigh_entry) != type)
+ int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
+
+ if (neigh_type != type)
continue;
+
+ if (neigh_type == AF_INET6 &&
+ mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
+ continue;
+
size++;
}
}
@@ -667,7 +687,7 @@ static u64 mlxsw_sp_dpipe_table_host4_size_get(void *priv)
static struct devlink_dpipe_table_ops mlxsw_sp_host4_ops = {
.matches_dump = mlxsw_sp_dpipe_table_host4_matches_dump,
- .actions_dump = mlxsw_sp_dpipe_table_host4_actions_dump,
+ .actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
.entries_dump = mlxsw_sp_dpipe_table_host4_entries_dump,
.counters_set_update = mlxsw_sp_dpipe_table_host4_counters_update,
.size_get = mlxsw_sp_dpipe_table_host4_size_get,
@@ -691,6 +711,43 @@ static void mlxsw_sp_dpipe_host4_table_fini(struct mlxsw_sp *mlxsw_sp)
MLXSW_SP_DPIPE_TABLE_NAME_HOST4);
}
+static int
+mlxsw_sp_dpipe_table_host6_matches_dump(void *priv, struct sk_buff *skb)
+{
+ return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET6);
+}
+
+static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+
+ return mlxsw_sp_dpipe_table_host_size_get(mlxsw_sp, AF_INET6);
+}
+
+static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops = {
+ .matches_dump = mlxsw_sp_dpipe_table_host6_matches_dump,
+ .actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
+ .size_get = mlxsw_sp_dpipe_table_host6_size_get,
+};
+
+static int mlxsw_sp_dpipe_host6_table_init(struct mlxsw_sp *mlxsw_sp)
+{
+ struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
+
+ return devlink_dpipe_table_register(devlink,
+ MLXSW_SP_DPIPE_TABLE_NAME_HOST6,
+ &mlxsw_sp_host6_ops,
+ mlxsw_sp, false);
+}
+
+static void mlxsw_sp_dpipe_host6_table_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
+
+ devlink_dpipe_table_unregister(devlink,
+ MLXSW_SP_DPIPE_TABLE_NAME_HOST6);
+}
+
int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)
{
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
@@ -707,8 +764,14 @@ int mlxsw_sp_dpipe_init(struct mlxsw_sp *mlxsw_sp)
err = mlxsw_sp_dpipe_host4_table_init(mlxsw_sp);
if (err)
goto err_host4_table_init;
+
+ err = mlxsw_sp_dpipe_host6_table_init(mlxsw_sp);
+ if (err)
+ goto err_host6_table_init;
return 0;
+err_host6_table_init:
+ mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);
err_host4_table_init:
mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
err_erif_table_init:
@@ -720,6 +783,7 @@ void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp)
{
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
+ mlxsw_sp_dpipe_host6_table_fini(mlxsw_sp);
mlxsw_sp_dpipe_host4_table_fini(mlxsw_sp);
mlxsw_sp_dpipe_erif_table_fini(mlxsw_sp);
devlink_dpipe_headers_unregister(devlink);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h
index c56a3d9..283fde4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.h
@@ -55,5 +55,6 @@ static inline void mlxsw_sp_dpipe_fini(struct mlxsw_sp *mlxsw_sp)
#define MLXSW_SP_DPIPE_TABLE_NAME_ERIF "mlxsw_erif"
#define MLXSW_SP_DPIPE_TABLE_NAME_HOST4 "mlxsw_host4"
+#define MLXSW_SP_DPIPE_TABLE_NAME_HOST6 "mlxsw_host6"
#endif /* _MLXSW_PIPELINE_H_*/
--
2.9.3
^ permalink raw reply related
* [patch net-next 4/8] mlxsw: spectrum_router: Add IPv6 neighbor access helper
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add helper for accessing destination IP in case of IPv6 neighbor.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 9 +++++++++
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h | 2 ++
2 files changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 1f41bcd..db57c0c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -947,6 +947,15 @@ u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
return ntohl(*((__be32 *) n->primary_key));
}
+struct in6_addr *
+mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
+{
+ struct neighbour *n;
+
+ n = neigh_entry->key.n;
+ return (struct in6_addr *) &n->primary_key;
+}
+
int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_neigh_entry *neigh_entry,
u64 *p_counter)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index 5b68616..87a04af 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -65,6 +65,8 @@ int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry);
unsigned char *
mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry);
u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry);
+struct in6_addr *
+mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry);
#define mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) \
for (neigh_entry = mlxsw_sp_rif_neigh_next(rif, NULL); neigh_entry; \
--
2.9.3
^ permalink raw reply related
* [patch net-next 5/8] mlxsw: spectrum_dpipe: Make host entry fill handler more generic
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Change the host entry filler helper to be applicable for both IPv4/6
addresses.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 93ba6a6..5924e97 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -439,13 +439,12 @@ mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry *entry,
}
static void
-__mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
- struct mlxsw_sp_rif *rif,
- unsigned char *ha, u32 dip)
+__mlxsw_sp_dpipe_table_host_entry_fill(struct devlink_dpipe_entry *entry,
+ struct mlxsw_sp_rif *rif,
+ unsigned char *ha, void *dip)
{
struct devlink_dpipe_value *value;
u32 *rif_value;
- u32 *dip_value;
u8 *ha_value;
/* Set Match RIF index */
@@ -458,9 +457,7 @@ __mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
/* Set Match DIP */
value = &entry->match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
-
- dip_value = value->value;
- *dip_value = dip;
+ memcpy(value->value, dip, value->value_size);
/* Set Action DMAC */
value = entry->action_values;
@@ -478,7 +475,7 @@ mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
ha = mlxsw_sp_neigh_entry_ha(neigh_entry);
dip = mlxsw_sp_neigh4_entry_dip(neigh_entry);
- __mlxsw_sp_dpipe_table_host4_entry_fill(entry, rif, ha, dip);
+ __mlxsw_sp_dpipe_table_host_entry_fill(entry, rif, ha, &dip);
}
static void
--
2.9.3
^ permalink raw reply related
* [patch net-next 6/8] mlxsw: spectrum_dpipe: Add support for IPv6 host table dump
From: Jiri Pirko @ 2017-08-30 12:03 UTC (permalink / raw)
To: netdev; +Cc: davem, arkadis, idosch, mlxsw
In-Reply-To: <20170830120306.6128-1-jiri@resnulli.us>
From: Arkadi Sharshevsky <arkadis@mellanox.com>
Add support for IPv6 host table dump.
Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 75 ++++++++++++++++++++--
1 file changed, 70 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 5924e97..75da2ef 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -386,8 +386,19 @@ mlxsw_sp_dpipe_table_host_match_action_prepare(struct devlink_dpipe_match *match
match = &matches[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
match->type = DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT;
- match->header = &devlink_dpipe_header_ipv4;
- match->field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ switch (type) {
+ case AF_INET:
+ match->header = &devlink_dpipe_header_ipv4;
+ match->field_id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP;
+ break;
+ case AF_INET6:
+ match->header = &devlink_dpipe_header_ipv6;
+ match->field_id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP;
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
action->type = DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY;
action->header = &devlink_dpipe_header_ethernet;
@@ -424,7 +435,18 @@ mlxsw_sp_dpipe_table_host_entry_prepare(struct devlink_dpipe_entry *entry,
match_value = &match_values[MLXSW_SP_DPIPE_TABLE_HOST_MATCH_DIP];
match_value->match = match;
- match_value->value_size = sizeof(u32);
+ switch (type) {
+ case AF_INET:
+ match_value->value_size = sizeof(u32);
+ break;
+ case AF_INET6:
+ match_value->value_size = sizeof(struct in6_addr);
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
match_value->value = kmalloc(match_value->value_size, GFP_KERNEL);
if (!match_value->value)
return -ENOMEM;
@@ -479,6 +501,20 @@ mlxsw_sp_dpipe_table_host4_entry_fill(struct devlink_dpipe_entry *entry,
}
static void
+mlxsw_sp_dpipe_table_host6_entry_fill(struct devlink_dpipe_entry *entry,
+ struct mlxsw_sp_neigh_entry *neigh_entry,
+ struct mlxsw_sp_rif *rif)
+{
+ struct in6_addr *dip;
+ unsigned char *ha;
+
+ ha = mlxsw_sp_neigh_entry_ha(neigh_entry);
+ dip = mlxsw_sp_neigh6_entry_dip(neigh_entry);
+
+ __mlxsw_sp_dpipe_table_host_entry_fill(entry, rif, ha, dip);
+}
+
+static void
mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp *mlxsw_sp,
struct devlink_dpipe_entry *entry,
struct mlxsw_sp_neigh_entry *neigh_entry,
@@ -487,7 +523,18 @@ mlxsw_sp_dpipe_table_host_entry_fill(struct mlxsw_sp *mlxsw_sp,
{
int err;
- mlxsw_sp_dpipe_table_host4_entry_fill(entry, neigh_entry, rif);
+ switch (type) {
+ case AF_INET:
+ mlxsw_sp_dpipe_table_host4_entry_fill(entry, neigh_entry, rif);
+ break;
+ case AF_INET6:
+ mlxsw_sp_dpipe_table_host6_entry_fill(entry, neigh_entry, rif);
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+
err = mlxsw_sp_neigh_counter_get(mlxsw_sp, neigh_entry,
&entry->counter);
if (!err)
@@ -526,7 +573,13 @@ mlxsw_sp_dpipe_table_host_entries_get(struct mlxsw_sp *mlxsw_sp,
rif_neigh_count = 0;
mlxsw_sp_rif_neigh_for_each(neigh_entry, rif) {
- if (mlxsw_sp_neigh_entry_type(neigh_entry) != type)
+ int neigh_type = mlxsw_sp_neigh_entry_type(neigh_entry);
+
+ if (neigh_type != type)
+ continue;
+
+ if (neigh_type == AF_INET6 &&
+ mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
continue;
if (rif_neigh_count < rif_neigh_skip)
@@ -714,6 +767,17 @@ mlxsw_sp_dpipe_table_host6_matches_dump(void *priv, struct sk_buff *skb)
return mlxsw_sp_dpipe_table_host_matches_dump(skb, AF_INET6);
}
+static int
+mlxsw_sp_dpipe_table_host6_entries_dump(void *priv, bool counters_enabled,
+ struct devlink_dpipe_dump_ctx *dump_ctx)
+{
+ struct mlxsw_sp *mlxsw_sp = priv;
+
+ return mlxsw_sp_dpipe_table_host_entries_dump(mlxsw_sp,
+ counters_enabled,
+ dump_ctx, AF_INET6);
+}
+
static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
{
struct mlxsw_sp *mlxsw_sp = priv;
@@ -724,6 +788,7 @@ static u64 mlxsw_sp_dpipe_table_host6_size_get(void *priv)
static struct devlink_dpipe_table_ops mlxsw_sp_host6_ops = {
.matches_dump = mlxsw_sp_dpipe_table_host6_matches_dump,
.actions_dump = mlxsw_sp_dpipe_table_host_actions_dump,
+ .entries_dump = mlxsw_sp_dpipe_table_host6_entries_dump,
.size_get = mlxsw_sp_dpipe_table_host6_size_get,
};
--
2.9.3
^ 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