* [PATCH net] xfrm: add NETDEV_UNREGISTER event process for xfrmi
From: Xin Long @ 2019-08-26 8:25 UTC (permalink / raw)
To: network dev; +Cc: davem, Steffen Klassert
When creating a xfrmi dev, it always holds the phydev. The xfrmi dev should
be deleted when the phydev is being unregistered, so that the phydev can be
put on time. Otherwise the phydev's deleting will get stuck:
# ip link add dummy10 type dummy
# ip link add xfrmi10 type xfrm dev dummy10
# ip link del dummy10
The last command blocks and dmesg shows:
unregister_netdevice: waiting for dummy10 to become free. Usage count = 1
This patch fixes it by adding NETDEV_UNREGISTER event process for xfrmi.
Fixes: f203b76d7809 ("xfrm: Add virtual xfrm interfaces")
Reported-by: Xiumei Mu <xmu@redhat.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/xfrm/xfrm_interface.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 74868f9..f3de1f5 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -877,6 +877,35 @@ static const struct xfrm_if_cb xfrm_if_cb = {
.decode_session = xfrmi_decode_session,
};
+static int xfrmi_event(struct notifier_block *this, unsigned long e, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct xfrmi_net *xfrmn = net_generic(dev_net(dev), xfrmi_net_id);
+ struct xfrm_if *xi;
+ LIST_HEAD(list);
+
+ if (e != NETDEV_UNREGISTER)
+ return NOTIFY_DONE;
+
+ rcu_read_lock();
+ for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
+ if (xi->phydev != dev)
+ continue;
+ unregister_netdevice_queue(xi->dev, &list);
+ }
+ rcu_read_unlock();
+
+ if (list_empty(&list))
+ return NOTIFY_DONE;
+
+ unregister_netdevice_many(&list);
+ return NOTIFY_OK;
+}
+
+static struct notifier_block xfrmi_notifier = {
+ .notifier_call = xfrmi_event,
+};
+
static int __init xfrmi_init(void)
{
const char *msg;
@@ -906,6 +935,7 @@ static int __init xfrmi_init(void)
goto rtnl_link_failed;
xfrm_if_register_cb(&xfrm_if_cb);
+ register_netdevice_notifier(&xfrmi_notifier);
return err;
@@ -922,6 +952,7 @@ static int __init xfrmi_init(void)
static void __exit xfrmi_fini(void)
{
+ unregister_netdevice_notifier(&xfrmi_notifier);
xfrm_if_unregister_cb();
rtnl_link_unregister(&xfrmi_link_ops);
xfrmi4_fini();
--
2.1.0
^ permalink raw reply related
* [PATCH net] xfrm: remove the unnecessary .net_exit for xfrmi
From: Xin Long @ 2019-08-26 8:25 UTC (permalink / raw)
To: network dev; +Cc: davem, Steffen Klassert
The xfrm_if(s) on each netns can be deleted when its xfrmi dev is
deleted. xfrmi dev's removal can happen when:
1. Its phydev is being deleted and NETDEV_UNREGISTER event is
processed in xfrmi_event() from my last patch.
2. netns is being removed and all xfrmi devs will be deleted.
3. rtnl_link_unregister(&xfrmi_link_ops) in xfrmi_fini() when
xfrm_interface.ko is being unloaded.
So there's no need to use xfrmi_exit_net() to clean any xfrm_if up.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/xfrm/xfrm_interface.c | 23 -----------------------
1 file changed, 23 deletions(-)
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index f3de1f5..3420c71 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -738,30 +738,7 @@ static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
.get_link_net = xfrmi_get_link_net,
};
-static void __net_exit xfrmi_destroy_interfaces(struct xfrmi_net *xfrmn)
-{
- struct xfrm_if *xi;
- LIST_HEAD(list);
-
- xi = rtnl_dereference(xfrmn->xfrmi[0]);
- if (!xi)
- return;
-
- unregister_netdevice_queue(xi->dev, &list);
- unregister_netdevice_many(&list);
-}
-
-static void __net_exit xfrmi_exit_net(struct net *net)
-{
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
-
- rtnl_lock();
- xfrmi_destroy_interfaces(xfrmn);
- rtnl_unlock();
-}
-
static struct pernet_operations xfrmi_net_ops = {
- .exit = xfrmi_exit_net,
.id = &xfrmi_net_id,
.size = sizeof(struct xfrmi_net),
};
--
2.1.0
^ permalink raw reply related
* [PATCH net-next 0/3] sctp: add SCTP_ECN_SUPPORTED sockopt
From: Xin Long @ 2019-08-26 8:30 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
This patchset is to make ecn flag per netns and endpoint and then
add SCTP_ECN_SUPPORTED sockopt, as does for other feature flags.
Xin Long (3):
sctp: make ecn flag per netns and endpoint
sctp: allow users to set netns ecn flag with sysctl
sctp: allow users to set ep ecn flag by sockopt
include/net/netns/sctp.h | 3 ++
include/net/sctp/structs.h | 3 +-
include/uapi/linux/sctp.h | 1 +
net/sctp/endpointola.c | 1 +
net/sctp/protocol.c | 3 ++
net/sctp/sm_make_chunk.c | 16 +++++++---
net/sctp/socket.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
net/sctp/sysctl.c | 7 +++++
8 files changed, 102 insertions(+), 5 deletions(-)
--
2.1.0
^ permalink raw reply
* [PATCH net-next 1/3] sctp: make ecn flag per netns and endpoint
From: Xin Long @ 2019-08-26 8:30 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1566807985.git.lucien.xin@gmail.com>
This patch is to add ecn flag for both netns_sctp and sctp_endpoint,
net->sctp.ecn_enable is set 1 by default, and ep->ecn_enable will
be initialized with net->sctp.ecn_enable.
asoc->peer.ecn_capable will be set during negotiation only when
ep->ecn_enable is set on both sides.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/net/netns/sctp.h | 3 +++
include/net/sctp/structs.h | 3 ++-
net/sctp/endpointola.c | 1 +
net/sctp/protocol.c | 3 +++
net/sctp/sm_make_chunk.c | 16 ++++++++++++----
5 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 0db7fb3..bdc0f27 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -128,6 +128,9 @@ struct netns_sctp {
/* Flag to indicate if stream interleave is enabled */
int intl_enable;
+ /* Flag to indicate if ecn is enabled */
+ int ecn_enable;
+
/*
* Policy to control SCTP IPv4 address scoping
* 0 - Disable IPv4 address scoping
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index daac1ef..503fbc3 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1322,7 +1322,8 @@ struct sctp_endpoint {
/* SCTP-AUTH: endpoint shared keys */
struct list_head endpoint_shared_keys;
__u16 active_key_id;
- __u8 auth_enable:1,
+ __u8 ecn_enable:1,
+ auth_enable:1,
intl_enable:1,
prsctp_enable:1,
asconf_enable:1,
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 75a407d..ea53049 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -106,6 +106,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
*/
ep->prsctp_enable = net->sctp.prsctp_enable;
ep->reconf_enable = net->sctp.reconf_enable;
+ ep->ecn_enable = net->sctp.ecn_enable;
/* Remember who we are attached to. */
ep->base.sk = sk;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2d47adc..b48ffe8 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1254,6 +1254,9 @@ static int __net_init sctp_defaults_init(struct net *net)
/* Disable AUTH by default. */
net->sctp.auth_enable = 0;
+ /* Enable ECN by default. */
+ net->sctp.ecn_enable = 1;
+
/* Set SCOPE policy to enabled */
net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 338278f..e41ed2e 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -244,7 +244,9 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
chunksize = sizeof(init) + addrs_len;
chunksize += SCTP_PAD4(SCTP_SAT_LEN(num_types));
- chunksize += sizeof(ecap_param);
+
+ if (asoc->ep->ecn_enable)
+ chunksize += sizeof(ecap_param);
if (asoc->ep->prsctp_enable)
chunksize += sizeof(prsctp_param);
@@ -335,7 +337,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
sctp_addto_chunk(retval, sizeof(sat), &sat);
sctp_addto_chunk(retval, num_types * sizeof(__u16), &types);
- sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
+ if (asoc->ep->ecn_enable)
+ sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
/* Add the supported extensions parameter. Be nice and add this
* fist before addiding the parameters for the extensions themselves
@@ -2597,8 +2600,13 @@ static int sctp_process_param(struct sctp_association *asoc,
break;
case SCTP_PARAM_ECN_CAPABLE:
- asoc->peer.ecn_capable = 1;
- break;
+ if (asoc->ep->ecn_enable) {
+ asoc->peer.ecn_capable = 1;
+ break;
+ }
+ /* Fall Through */
+ goto fall_through;
+
case SCTP_PARAM_ADAPTATION_LAYER_IND:
asoc->peer.adaptation_ind = ntohl(param.aind->adaptation_ind);
--
2.1.0
^ permalink raw reply related
* [PATCH net-next 2/3] sctp: allow users to set netns ecn flag with sysctl
From: Xin Long @ 2019-08-26 8:30 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1566807985.git.lucien.xin@gmail.com>
sysctl net.sctp.ecn_enable is added in this patch. It will allow
users to change the default sctp ecn flag, net.sctp.ecn_enable.
This feature was also required on this thread:
http://lkml.iu.edu/hypermail/linux/kernel/0812.1/01858.html
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/sysctl.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 1250751..238cf17 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -278,6 +278,13 @@ static struct ctl_table sctp_net_table[] = {
.proc_handler = proc_dointvec,
},
{
+ .procname = "ecn_enable",
+ .data = &init_net.sctp.ecn_enable,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
.procname = "addr_scope_policy",
.data = &init_net.sctp.scope_policy,
.maxlen = sizeof(int),
--
2.1.0
^ permalink raw reply related
* [PATCH net-next 3/3] sctp: allow users to set ep ecn flag by sockopt
From: Xin Long @ 2019-08-26 8:30 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
In-Reply-To: <cover.1566807985.git.lucien.xin@gmail.com>
SCTP_ECN_SUPPORTED sockopt will be added to allow users to change
ep ecn flag, and it's similar with other feature flags.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/uapi/linux/sctp.h | 1 +
net/sctp/socket.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 62527ac..6d5b164 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -136,6 +136,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_EVENT 127
#define SCTP_ASCONF_SUPPORTED 128
#define SCTP_AUTH_SUPPORTED 129
+#define SCTP_ECN_SUPPORTED 130
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 82bc252..3e50a97 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4560,6 +4560,34 @@ static int sctp_setsockopt_auth_supported(struct sock *sk,
return retval;
}
+static int sctp_setsockopt_ecn_supported(struct sock *sk,
+ char __user *optval,
+ unsigned int optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ int retval = -EINVAL;
+
+ if (optlen != sizeof(params))
+ goto out;
+
+ if (copy_from_user(¶ms, optval, optlen)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP))
+ goto out;
+
+ sctp_sk(sk)->ep->ecn_enable = !!params.assoc_value;
+ retval = 0;
+
+out:
+ return retval;
+}
+
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
@@ -4766,6 +4794,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_AUTH_SUPPORTED:
retval = sctp_setsockopt_auth_supported(sk, optval, optlen);
break;
+ case SCTP_ECN_SUPPORTED:
+ retval = sctp_setsockopt_ecn_supported(sk, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -7828,6 +7859,45 @@ static int sctp_getsockopt_auth_supported(struct sock *sk, int len,
return retval;
}
+static int sctp_getsockopt_ecn_supported(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ int retval = -EFAULT;
+
+ if (len < sizeof(params)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ len = sizeof(params);
+ if (copy_from_user(¶ms, optval, len))
+ goto out;
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ params.assoc_value = asoc ? asoc->peer.ecn_capable
+ : sctp_sk(sk)->ep->ecn_enable;
+
+ if (put_user(len, optlen))
+ goto out;
+
+ if (copy_to_user(optval, ¶ms, len))
+ goto out;
+
+ retval = 0;
+
+out:
+ return retval;
+}
+
static int sctp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -8037,6 +8107,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_auth_supported(sk, len, optval,
optlen);
break;
+ case SCTP_ECN_SUPPORTED:
+ retval = sctp_getsockopt_ecn_supported(sk, len, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
--
2.1.0
^ permalink raw reply related
* [PATCH net v2 2/2] r8152: remove calling netif_napi_del
From: Hayes Wang @ 2019-08-26 8:41 UTC (permalink / raw)
To: netdev; +Cc: nic_swsd, linux-kernel, jslaby, Hayes Wang
In-Reply-To: <1394712342-15778-317-Taiwan-albertk@realtek.com>
Remove unnecessary use of netif_napi_del. This also avoids to call
napi_disable() after netif_napi_del().
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
drivers/net/usb/r8152.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index ad3abe26b51b..04137ac373b0 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -5352,7 +5352,6 @@ static int rtl8152_probe(struct usb_interface *intf,
return 0;
out1:
- netif_napi_del(&tp->napi);
usb_set_intfdata(intf, NULL);
out:
free_netdev(netdev);
@@ -5367,7 +5366,6 @@ static void rtl8152_disconnect(struct usb_interface *intf)
if (tp) {
rtl_set_unplug(tp);
- netif_napi_del(&tp->napi);
unregister_netdev(tp->netdev);
cancel_delayed_work_sync(&tp->hw_phy_work);
tp->rtl_ops.unload(tp);
--
2.21.0
^ permalink raw reply related
* [PATCH net v2 0/2] r8152: fix side effect
From: Hayes Wang @ 2019-08-26 8:41 UTC (permalink / raw)
To: netdev; +Cc: nic_swsd, linux-kernel, jslaby, Hayes Wang
v2:
Replace patch #2 with "r8152: remove calling netif_napi_del".
v1:
The commit 0ee1f4734967 ("r8152: napi hangup fix after disconnect")
add a check to avoid using napi_disable after netif_napi_del. However,
the commit ffa9fec30ca0 ("r8152: set RTL8152_UNPLUG only for real
disconnection") let the check useless.
Therefore, I revert commit 0ee1f4734967 ("r8152: napi hangup fix
after disconnect") first, and add another patch to fix it.
Hayes Wang (2):
Revert "r8152: napi hangup fix after disconnect"
r8152: remove calling netif_napi_del
drivers/net/usb/r8152.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
--
2.21.0
^ permalink raw reply
* [PATCH net v2 1/2] Revert "r8152: napi hangup fix after disconnect"
From: Hayes Wang @ 2019-08-26 8:41 UTC (permalink / raw)
To: netdev; +Cc: nic_swsd, linux-kernel, jslaby, Hayes Wang
In-Reply-To: <1394712342-15778-317-Taiwan-albertk@realtek.com>
This reverts commit 0ee1f4734967af8321ecebaf9c74221ace34f2d5.
This conflicts with commit ffa9fec30ca0 ("r8152: set
RTL8152_UNPLUG only for real disconnection").
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
drivers/net/usb/r8152.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index eee0f5007ee3..ad3abe26b51b 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -4021,8 +4021,7 @@ static int rtl8152_close(struct net_device *netdev)
#ifdef CONFIG_PM_SLEEP
unregister_pm_notifier(&tp->pm_notifier);
#endif
- if (!test_bit(RTL8152_UNPLUG, &tp->flags))
- napi_disable(&tp->napi);
+ napi_disable(&tp->napi);
clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb);
cancel_delayed_work_sync(&tp->schedule);
--
2.21.0
^ permalink raw reply related
* Re: [PATCH net v2 1/2] Revert "r8152: napi hangup fix after disconnect"
From: Jiri Slaby @ 2019-08-26 8:55 UTC (permalink / raw)
To: Hayes Wang, netdev; +Cc: nic_swsd, linux-kernel
In-Reply-To: <1394712342-15778-318-Taiwan-albertk@realtek.com>
On 26. 08. 19, 10:41, Hayes Wang wrote:
> This reverts commit 0ee1f4734967af8321ecebaf9c74221ace34f2d5.
>
> This conflicts with commit ffa9fec30ca0 ("r8152: set
> RTL8152_UNPLUG only for real disconnection").
Could you clarify *why* it conflicts? And how is the problem fixed by
0ee1f473496 avoided now?
> Signed-off-by: Hayes Wang <hayeswang@realtek.com>
> ---
> drivers/net/usb/r8152.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index eee0f5007ee3..ad3abe26b51b 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c
> @@ -4021,8 +4021,7 @@ static int rtl8152_close(struct net_device *netdev)
> #ifdef CONFIG_PM_SLEEP
> unregister_pm_notifier(&tp->pm_notifier);
> #endif
> - if (!test_bit(RTL8152_UNPLUG, &tp->flags))
> - napi_disable(&tp->napi);
> + napi_disable(&tp->napi);
> clear_bit(WORK_ENABLE, &tp->flags);
> usb_kill_urb(tp->intr_urb);
> cancel_delayed_work_sync(&tp->schedule);
>
thanks,
--
js
suse labs
^ permalink raw reply
* Aw: [PATCH net-next v4 0/3] net: ethernet: mediatek: convert to PHYLINK
From: Frank Wunderlich @ 2019-08-26 9:24 UTC (permalink / raw)
To: "René van Dorst"
Cc: John Crispin, Sean Wang, Nelson Chang, David S . Miller,
Matthias Brugger, netdev, linux-arm-kernel, linux-mediatek,
linux-mips, Russell King, Stefan Roese,
"René van Dorst"
In-Reply-To: <20190825174341.20750-1-opensource@vdorst.com>
Tested on Bananapi-R2 (mt7623+mt7530) and Bananapi-R64 v0.1 (mt7622+rtl8367)
Tested-by: Frank Wunderlich <frank-w@public-files.de>
regards Frank
^ permalink raw reply
* [PATCH net] net/rds: Fix info leak in rds6_inc_info_copy()
From: Ka-Cheong Poon @ 2019-08-26 9:39 UTC (permalink / raw)
To: netdev; +Cc: santosh.shilimkar, davem, rds-devel
The rds6_inc_info_copy() function has a couple struct members which
are leaking stack information. The ->tos field should hold actual
information and the ->flags field needs to be zeroed out.
Fixes: 3eb450367d08 ("rds: add type of service(tos) infrastructure")
Fixes: b7ff8b1036f0 ("rds: Extend RDS API for IPv6 support")
Reported-by: 黄ID蝴蝶 <butterflyhuangxx@gmail.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
---
net/rds/recv.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 853de48..a42ba7f 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -811,6 +811,7 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence);
minfo6.len = be32_to_cpu(inc->i_hdr.h_len);
+ minfo6.tos = inc->i_conn->c_tos;
if (flip) {
minfo6.laddr = *daddr;
@@ -824,6 +825,8 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
minfo6.fport = inc->i_hdr.h_dport;
}
+ minfo6.flags = 0;
+
rds_info_copy(iter, &minfo6, sizeof(minfo6));
}
#endif
--
1.8.3.1
^ permalink raw reply related
* RE: [PATCH net v2 1/2] Revert "r8152: napi hangup fix after disconnect"
From: Hayes Wang @ 2019-08-26 9:43 UTC (permalink / raw)
To: Jiri Slaby, netdev@vger.kernel.org; +Cc: nic_swsd, linux-kernel@vger.kernel.org
In-Reply-To: <1f707377-7b61-4ba1-62bf-f275d0360749@suse.cz>
Jiri Slaby [mailto:jslaby@suse.cz]
> Sent: Monday, August 26, 2019 4:55 PM
[...]
> Could you clarify *why* it conflicts? And how is the problem fixed by
> 0ee1f473496 avoided now?
In rtl8152_disconnect(), the flow would be as following.
static void rtl8152_disconnect(struct usb_interface *intf)
{
...
- netif_napi_del(&tp->napi);
- unregister_netdev(tp->netdev);
- rtl8152_close
- napi_disable
Therefore you add a checking of RTL8152_UNPLUG to avoid
calling napi_disable() after netif_napi_del(). However,
after commit ffa9fec30ca0 ("r8152: set RTL8152_UNPLUG
only for real disconnection"), RTL8152_UNPLUG is not
always set when calling rtl8152_disconnect(). That is,
napi_disable() would be called after netif_napi_del(),
if RTL8152_UNPLUG is not set.
The best way is to avoid calling netif_napi_del() before
calling unregister_netdev(). And I has submitted such
patch following this one.
Best Regards,
Hayes
^ permalink raw reply
* Re: [PATCH] net: Adding parameter detection in __ethtool_get_link_ksettings.
From: Dongxu Liu @ 2019-08-26 9:47 UTC (permalink / raw)
To: eric.dumazet; +Cc: davem, linux-kernel, liudongxu3, netdev
In-Reply-To: <aa0a372e-a169-7d78-0782-505cbdab8f90@gmail.com>
> On 8/26/19 9:23 AM, Dongxu Liu wrote:
> The __ethtool_get_link_ksettings symbol will be exported,
> and external users may use an illegal address.
> We should check the parameters before using them,
> otherwise the system will crash.
>
> [ 8980.991134] BUG: unable to handle kernel NULL pointer dereference at (null)
> [ 8980.993049] IP: [<ffffffff8155aca7>] __ethtool_get_link_ksettings+0x27/0x140
> [ 8980.994285] PGD 0
> [ 8980.995013] Oops: 0000 [#1] SMP
> [ 8980.995896] Modules linked in: sch_ingress ...
> [ 8981.013220] CPU: 3 PID: 25174 Comm: kworker/3:3 Tainted: G O ----V------- 3.10.0-327.36.58.4.x86_64 #1
> [ 8981.017667] Workqueue: events linkwatch_event
> [ 8981.018652] task: ffff8800a8348000 ti: ffff8800b045c000 task.ti: ffff8800b045c000
> [ 8981.020418] RIP: 0010:[<ffffffff8155aca7>] [<ffffffff8155aca7>] __ethtool_get_link_ksettings+0x27/0x140
> [ 8981.022383] RSP: 0018:ffff8800b045fc88 EFLAGS: 00010202
> [ 8981.023453] RAX: 0000000000000000 RBX: ffff8800b045fcac RCX: 0000000000000000
> [ 8981.024726] RDX: ffff8800b658f600 RSI: ffff8800b045fcac RDI: ffff8802296e0000
> [ 8981.026000] RBP: ffff8800b045fc98 R08: 0000000000000000 R09: 0000000000000001
> [ 8981.027273] R10: 00000000000073e0 R11: 0000082b0cc8adea R12: ffff8802296e0000
> [ 8981.028561] R13: ffff8800b566e8c0 R14: ffff8800b658f600 R15: ffff8800b566e000
> [ 8981.029841] FS: 0000000000000000(0000) GS:ffff88023ed80000(0000) knlGS:0000000000000000
> [ 8981.031715] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 8981.032845] CR2: 0000000000000000 CR3: 00000000b39a9000 CR4: 00000000003407e0
> [ 8981.034137] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [ 8981.035427] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> [ 8981.036702] Stack:
> [ 8981.037406] ffff8800b658f600 0000000000009c40 ffff8800b045fce8 ffffffffa047a71d
> [ 8981.039238] 000000000000004d ffff8800b045fcc8 ffff8800b045fd28 ffffffff815cb198
> [ 8981.041070] ffff8800b045fcd8 ffffffff810807e6 00000000e8212951 0000000000000001
> [ 8981.042910] Call Trace:
> [ 8981.043660] [<ffffffffa047a71d>] bond_update_speed_duplex+0x3d/0x90 [bonding]
> [ 8981.045424] [<ffffffff815cb198>] ? inetdev_event+0x38/0x530
> [ 8981.046554] [<ffffffff810807e6>] ? put_online_cpus+0x56/0x80
> [ 8981.047688] [<ffffffffa0480d67>] bond_netdev_event+0x137/0x360 [bonding]
> ...
>
> Signed-off-by: Dongxu Liu <liudongxu3@huawei.com>
> ---
> net/core/ethtool.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/net/core/ethtool.c b/net/core/ethtool.c index
> 6288e69..9a50b64 100644
> --- a/net/core/ethtool.c
> +++ b/net/core/ethtool.c
> @@ -545,6 +545,8 @@ int __ethtool_get_link_ksettings(struct net_device
> *dev, {
> ASSERT_RTNL();
>
> + if (!dev || !dev->ethtool_ops)
> + return -EOPNOTSUPP;
> I do not believe dev can possibly be NULL at this point.
> if (!dev->ethtool_ops->get_link_ksettings)
> return -EOPNOTSUPP;
>
>
> I tried to find an appropriate Fixes: tag.
> It seems this particular bug was added either by
> Fixes: 9856909c2abb ("net: bonding: use __ethtool_get_ksettings")
> or generically in :
> Fixes: 3f1ac7a700d0 ("net: ethtool: add new ETHTOOL_xLINKSETTINGS API")
In fact, "dev->ethtool_ops" is a null pointer in my environment.
I didn't get the case where "dev" is a null pointer.
Maybe "if (!dev->ethtool_ops)" is more accurate for this bug.
I found this bug in version 3.10, the function name was __ethtool_get_settings.
After 3f1ac7a700d0 ("net: ethtool: add new ETHTOOL_xLINKSETTINGS API"),
This function evolved into __ethtool_get_link_ksettings.
^ permalink raw reply
* [PATCH] samples: bpf: add max_pckt_size option at xdp_adjust_tail
From: Daniel T. Lee @ 2019-08-26 9:57 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov; +Cc: netdev
Currently, at xdp_adjust_tail_kern.c, MAX_PCKT_SIZE is limited
to 600. To make this size flexible, a new map 'pcktsz' is added.
By updating new packet size to this map from the userland,
xdp_adjust_tail_kern.o will use this value as a new max_pckt_size.
If no '-P <MAX_PCKT_SIZE>' option is used, the size of maximum packet
will be 600 as a default.
Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com>
---
samples/bpf/xdp_adjust_tail_kern.c | 23 +++++++++++++++++++----
samples/bpf/xdp_adjust_tail_user.c | 21 +++++++++++++++++++--
2 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/samples/bpf/xdp_adjust_tail_kern.c b/samples/bpf/xdp_adjust_tail_kern.c
index 411fdb21f8bc..4d53af370b68 100644
--- a/samples/bpf/xdp_adjust_tail_kern.c
+++ b/samples/bpf/xdp_adjust_tail_kern.c
@@ -25,6 +25,13 @@
#define ICMP_TOOBIG_SIZE 98
#define ICMP_TOOBIG_PAYLOAD_SIZE 92
+struct bpf_map_def SEC("maps") pcktsz = {
+ .type = BPF_MAP_TYPE_ARRAY,
+ .key_size = sizeof(__u32),
+ .value_size = sizeof(__u32),
+ .max_entries = 1,
+};
+
struct bpf_map_def SEC("maps") icmpcnt = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(__u32),
@@ -64,7 +71,8 @@ static __always_inline void ipv4_csum(void *data_start, int data_size,
*csum = csum_fold_helper(*csum);
}
-static __always_inline int send_icmp4_too_big(struct xdp_md *xdp)
+static __always_inline int send_icmp4_too_big(struct xdp_md *xdp,
+ __u32 max_pckt_size)
{
int headroom = (int)sizeof(struct iphdr) + (int)sizeof(struct icmphdr);
@@ -92,7 +100,7 @@ static __always_inline int send_icmp4_too_big(struct xdp_md *xdp)
orig_iph = data + off;
icmp_hdr->type = ICMP_DEST_UNREACH;
icmp_hdr->code = ICMP_FRAG_NEEDED;
- icmp_hdr->un.frag.mtu = htons(MAX_PCKT_SIZE-sizeof(struct ethhdr));
+ icmp_hdr->un.frag.mtu = htons(max_pckt_size - sizeof(struct ethhdr));
icmp_hdr->checksum = 0;
ipv4_csum(icmp_hdr, ICMP_TOOBIG_PAYLOAD_SIZE, &csum);
icmp_hdr->checksum = csum;
@@ -118,14 +126,21 @@ static __always_inline int handle_ipv4(struct xdp_md *xdp)
{
void *data_end = (void *)(long)xdp->data_end;
void *data = (void *)(long)xdp->data;
+ __u32 max_pckt_size = MAX_PCKT_SIZE;
+ __u32 *pckt_sz;
+ __u32 key = 0;
int pckt_size = data_end - data;
int offset;
- if (pckt_size > MAX_PCKT_SIZE) {
+ pckt_sz = bpf_map_lookup_elem(&pcktsz, &key);
+ if (pckt_sz && *pckt_sz)
+ max_pckt_size = *pckt_sz;
+
+ if (pckt_size > max_pckt_size) {
offset = pckt_size - ICMP_TOOBIG_SIZE;
if (bpf_xdp_adjust_tail(xdp, 0 - offset))
return XDP_PASS;
- return send_icmp4_too_big(xdp);
+ return send_icmp4_too_big(xdp, max_pckt_size);
}
return XDP_PASS;
}
diff --git a/samples/bpf/xdp_adjust_tail_user.c b/samples/bpf/xdp_adjust_tail_user.c
index a3596b617c4c..dd3befa5e1fe 100644
--- a/samples/bpf/xdp_adjust_tail_user.c
+++ b/samples/bpf/xdp_adjust_tail_user.c
@@ -72,6 +72,7 @@ static void usage(const char *cmd)
printf("Usage: %s [...]\n", cmd);
printf(" -i <ifname|ifindex> Interface\n");
printf(" -T <stop-after-X-seconds> Default: 0 (forever)\n");
+ printf(" -P <MAX_PCKT_SIZE> Default: 600\n");
printf(" -S use skb-mode\n");
printf(" -N enforce native mode\n");
printf(" -F force loading prog\n");
@@ -85,9 +86,11 @@ int main(int argc, char **argv)
.prog_type = BPF_PROG_TYPE_XDP,
};
unsigned char opt_flags[256] = {};
- const char *optstr = "i:T:SNFh";
+ const char *optstr = "i:T:P:SNFh";
struct bpf_prog_info info = {};
__u32 info_len = sizeof(info);
+ __u32 max_pckt_size = 0;
+ __u32 key = 0;
unsigned int kill_after_s = 0;
int i, prog_fd, map_fd, opt;
struct bpf_object *obj;
@@ -110,6 +113,9 @@ int main(int argc, char **argv)
case 'T':
kill_after_s = atoi(optarg);
break;
+ case 'P':
+ max_pckt_size = atoi(optarg);
+ break;
case 'S':
xdp_flags |= XDP_FLAGS_SKB_MODE;
break;
@@ -150,9 +156,20 @@ int main(int argc, char **argv)
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
return 1;
+ /* update pcktsz map */
map = bpf_map__next(NULL, obj);
if (!map) {
- printf("finding a map in obj file failed\n");
+ printf("finding a pcktsz map in obj file failed\n");
+ return 1;
+ }
+ map_fd = bpf_map__fd(map);
+ if (max_pckt_size)
+ bpf_map_update_elem(map_fd, &key, &max_pckt_size, BPF_ANY);
+
+ /* fetch icmpcnt map */
+ map = bpf_map__next(map, obj);
+ if (!map) {
+ printf("finding a icmpcnt map in obj file failed\n");
return 1;
}
map_fd = bpf_map__fd(map);
--
2.20.1
^ permalink raw reply related
* Re: [PATCH 29/38] cls_flower: Convert handle_idr to XArray
From: Vlad Buslov @ 2019-08-26 10:11 UTC (permalink / raw)
To: Cong Wang; +Cc: Vlad Buslov, Matthew Wilcox, netdev@vger.kernel.org
In-Reply-To: <CAM_iQpXXKwKUhzU1wwXrXqwXSEq-OJ4diBhSuR04kitLKs=g0g@mail.gmail.com>
On Sun 25 Aug 2019 at 21:32, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Wed, Aug 21, 2019 at 11:27 AM Vlad Buslov <vladbu@mellanox.com> wrote:
>> At first I was confused why you bring up rtnl lock in commit message
>> (flower classifier has 'unlocked' flag set and can't rely on it anymore)
>> but looking at the code I see that we lost rcu read lock here in commit
>> d39d714969cd ("idr: introduce idr_for_each_entry_continue_ul()") and you
>> are correctly bringing it back. Adding Cong to advise if it is okay to
>> wait for this patch to be accepted or we need to proceed with fixing the
>> missing RCU lock as a standalone patch.
>
> Hmm? Isn't ->walk() still called with RTNL lock? tcf_chain_dump()
> calls __tcf_get_next_proto() which asserts RTNL.
>
> So why does it still need RCU read lock when having RTNL?
Individual filters can be deleted without obtaining rtnl lock. And
without rcu read lock, f can be deallocated in fl_walk() main loop
before refcount_inc_not_zero() obtains reference to it.
^ permalink raw reply
* Re: [PATCH v6 5/7] nfc: pn533: add UART phy driver
From: Claudiu.Beznea @ 2019-08-26 10:31 UTC (permalink / raw)
To: poeschel
Cc: gregkh, tglx, swinslow, allison, opensource, kstewart,
linux-kernel, netdev, johan
In-Reply-To: <20190823100611.GB14401@lem-wkst-02.lemonage>
Hi Lars,
On 23.08.2019 13:06, Lars Poeschel wrote:
> External E-Mail
>
>
> On Thu, Aug 22, 2019 at 10:09:09AM +0000, Claudiu.Beznea@microchip.com wrote:
>> Hi Lars,
>>
>> On 20.08.2019 15:03, Lars Poeschel wrote:
>>> This adds the UART phy interface for the pn533 driver.
>>> The pn533 driver can be used through UART interface this way.
>>> It is implemented as a serdev device.
>>>
>>> Cc: Johan Hovold <johan@kernel.org>
>>> Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
>>> ---
>>> Changes in v6:
>>> - Rebased the patch series on v5.3-rc5
>>>
>>> Changes in v5:
>>> - Use the splitted pn53x_common_init and pn53x_register_nfc
>>> and pn53x_common_clean and pn53x_unregister_nfc alike
>>>
>>> Changes in v4:
>>> - SPDX-License-Identifier: GPL-2.0+
>>> - Source code comments above refering items
>>> - Error check for serdev_device_write's
>>> - Change if (xxx == NULL) to if (!xxx)
>>> - Remove device name from a dev_err
>>> - move pn533_register in _probe a bit towards the end of _probe
>>> - make use of newly added dev_up / dev_down phy_ops
>>> - control send_wakeup variable from dev_up / dev_down
>>>
>>> Changes in v3:
>>> - depend on SERIAL_DEV_BUS in Kconfig
>>>
>>> Changes in v2:
>>> - switched from tty line discipline to serdev, resulting in many
>>> simplifications
>>> - SPDX License Identifier
>>>
>>> drivers/nfc/pn533/Kconfig | 11 ++
>>> drivers/nfc/pn533/Makefile | 2 +
>>> drivers/nfc/pn533/pn533.h | 8 +
>>> drivers/nfc/pn533/uart.c | 316 +++++++++++++++++++++++++++++++++++++
>>> 4 files changed, 337 insertions(+)
>>> create mode 100644 drivers/nfc/pn533/uart.c
>>>
>>> diff --git a/drivers/nfc/pn533/Kconfig b/drivers/nfc/pn533/Kconfig
>>> index f6d6b345ba0d..7fe1bbe26568 100644
>>> --- a/drivers/nfc/pn533/Kconfig
>>> +++ b/drivers/nfc/pn533/Kconfig
>>> @@ -26,3 +26,14 @@ config NFC_PN533_I2C
>>>
>>> If you choose to build a module, it'll be called pn533_i2c.
>>> Say N if unsure.
>>> +
>>> +config NFC_PN532_UART
>>> + tristate "NFC PN532 device support (UART)"
>>> + depends on SERIAL_DEV_BUS
>>> + select NFC_PN533
>>> + ---help---
>>> + This module adds support for the NXP pn532 UART interface.
>>> + Select this if your platform is using the UART bus.
>>> +
>>> + If you choose to build a module, it'll be called pn532_uart.
>>> + Say N if unsure.
>>> diff --git a/drivers/nfc/pn533/Makefile b/drivers/nfc/pn533/Makefile
>>> index 43c25b4f9466..b9648337576f 100644
>>> --- a/drivers/nfc/pn533/Makefile
>>> +++ b/drivers/nfc/pn533/Makefile
>>> @@ -4,7 +4,9 @@
>>> #
>>> pn533_usb-objs = usb.o
>>> pn533_i2c-objs = i2c.o
>>> +pn532_uart-objs = uart.o
>>>
>>> obj-$(CONFIG_NFC_PN533) += pn533.o
>>> obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o
>>> obj-$(CONFIG_NFC_PN533_I2C) += pn533_i2c.o
>>> +obj-$(CONFIG_NFC_PN532_UART) += pn532_uart.o
>>> diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h
>>> index 510ddebbd896..6541088fad73 100644
>>> --- a/drivers/nfc/pn533/pn533.h
>>> +++ b/drivers/nfc/pn533/pn533.h
>>> @@ -43,6 +43,11 @@
>>>
>>> /* Preamble (1), SoPC (2), ACK Code (2), Postamble (1) */
>>> #define PN533_STD_FRAME_ACK_SIZE 6
>>> +/*
>>> + * Preamble (1), SoPC (2), Packet Length (1), Packet Length Checksum (1),
>>> + * Specific Application Level Error Code (1) , Postamble (1)
>>> + */
>>> +#define PN533_STD_ERROR_FRAME_SIZE 8
>>> #define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
>>> #define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
>>> /* Half start code (3), LEN (4) should be 0xffff for extended frame */
>>> @@ -84,6 +89,9 @@
>>> #define PN533_CMD_MI_MASK 0x40
>>> #define PN533_CMD_RET_SUCCESS 0x00
>>>
>>> +#define PN533_FRAME_DATALEN_ACK 0x00
>>> +#define PN533_FRAME_DATALEN_ERROR 0x01
>>> +#define PN533_FRAME_DATALEN_EXTENDED 0xFF
>>>
>>> enum pn533_protocol_type {
>>> PN533_PROTO_REQ_ACK_RESP = 0,
>>> diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c
>>> new file mode 100644
>>> index 000000000000..f1cc2354a4fd
>>> --- /dev/null
>>> +++ b/drivers/nfc/pn533/uart.c
>>> @@ -0,0 +1,316 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Driver for NXP PN532 NFC Chip - UART transport layer
>>> + *
>>> + * Copyright (C) 2018 Lemonage Software GmbH
>>> + * Author: Lars Pöschel <poeschel@lemonage.de>
>>> + * All rights reserved.
>>> + */
>>> +
>>> +#include <linux/device.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/module.h>
>>> +#include <linux/nfc.h>
>>> +#include <linux/netdevice.h>
>>> +#include <linux/of.h>
>>> +#include <linux/serdev.h>
>>> +#include "pn533.h"
>>> +
>>> +#define PN532_UART_SKB_BUFF_LEN (PN533_CMD_DATAEXCH_DATA_MAXLEN * 2)
>>> +
>>> +enum send_wakeup {
>>> + PN532_SEND_NO_WAKEUP = 0,
>>> + PN532_SEND_WAKEUP,
>>> + PN532_SEND_LAST_WAKEUP,
>>> +};
>>> +
>>> +
>>> +struct pn532_uart_phy {
>>> + struct serdev_device *serdev;
>>> + struct sk_buff *recv_skb;
>>> + struct pn533 *priv;
>>> + enum send_wakeup send_wakeup;
>>
>> Could there be any concurrency issues w/ regards to accessing this
>> variable? I see it is accessed in pn532_uart_send_frame(), pn532_dev_up(),
>> pn532_dev_down() which may be called from the following wq:
>>
>> INIT_WORK(&priv->mi_tm_rx_work, pn533_wq_tm_mi_recv);
>>
>> INIT_WORK(&priv->mi_tm_tx_work, pn533_wq_tm_mi_send);
>>
>> INIT_DELAYED_WORK(&priv->poll_work, pn533_wq_poll);
>>
>>
>> and from net/nfc/core.c via dev_up()/dev_down().
>
> Well, I spend some minutes thinking about this. There should be no real
> problem. The code in pn533.c ensures, that commands are transmitted
> sequencially. And it always is command - response. So if a command is
> send, the driver waits for a response from the chip.
> So pn532_uart_send_frame should not be called multiple times without
> reaching at least serdev_device_write, but at this point the race is
> already over.
> There is one exception, this is the abort command. This command can be
> sent without receiving a previous response. So there is the possibility
> of a successful race.
> The send_wakeup variable is used to control if we need to send a
> wakeup request to the pn532 chip prior to the actual command we would
> like to send.
> Worst thing that I see could happen - if the race succeeds - is that we
> send a wakeup to the chip that is propably not needed as it is already
> awake. But this does not hurt as a wakeup send to the pn532 is
> essentially a no-op if the chip is awake already. I could have
> implemented it so, that a wakeup is sent in front of every command
> without thinking and the driver would work.
> The same is with pn532_dev_up. It could be that there is one wakeup sent
> to much, but it does not hurt.
> pn532_dev_down is not problematic I think.
>
> To sum it up: There is maybe a very little probability, but it does
> nothing bad. Question is now: Is it worth mutex'ing the send_wakeup
> variable or can we leave it as-is ?
Being so as you described above, I am for leaving it as is. Maybe, as you
wish, document this somewhere (e.g. a comment in the code), so that others
to be aware of this.
Thank you,
Claudiu Beznea
>
> Thank you for your review, Claudiu.
> Regards,
> Lars
>
>
^ permalink raw reply
* Re: [PATCH net-next 0/3] sctp: add SCTP_ECN_SUPPORTED sockopt
From: Neil Horman @ 2019-08-26 11:02 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, davem
In-Reply-To: <cover.1566807985.git.lucien.xin@gmail.com>
On Mon, Aug 26, 2019 at 04:30:01PM +0800, Xin Long wrote:
> This patchset is to make ecn flag per netns and endpoint and then
> add SCTP_ECN_SUPPORTED sockopt, as does for other feature flags.
>
> Xin Long (3):
> sctp: make ecn flag per netns and endpoint
> sctp: allow users to set netns ecn flag with sysctl
> sctp: allow users to set ep ecn flag by sockopt
>
> include/net/netns/sctp.h | 3 ++
> include/net/sctp/structs.h | 3 +-
> include/uapi/linux/sctp.h | 1 +
> net/sctp/endpointola.c | 1 +
> net/sctp/protocol.c | 3 ++
> net/sctp/sm_make_chunk.c | 16 +++++++---
> net/sctp/socket.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
> net/sctp/sysctl.c | 7 +++++
> 8 files changed, 102 insertions(+), 5 deletions(-)
>
> --
> 2.1.0
>
>
Series
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: [PATCH net-next v3 3/6] net: dsa: mv88e6xxx: create serdes_get_lane chip operation
From: Marek Behun @ 2019-08-26 12:21 UTC (permalink / raw)
To: Vivien Didelot; +Cc: netdev, Andrew Lunn, Florian Fainelli, Vladimir Oltean
In-Reply-To: <20190825121214.GJ6729@t480s.localdomain>
On Sun, 25 Aug 2019 12:12:14 -0400
Vivien Didelot <vivien.didelot@gmail.com> wrote:
> In fact you're also relying on -ENODEV, which is what you return here (and in
> other places) instead of 0. So I'm afraid you have to address my comment now...
Vivien, you are right. I returned -ENODEV for Peridot when no lane was
to be on port. It should return 0.
I am sending v4 now with this corrected, and tested on Turris Mox with
combinations Peridot, Topaz and Peridot + Topaz.
Marek
^ permalink raw reply
* [PATCH net-next v4 0/6] net: dsa: mv88e6xxx: Peridot/Topaz SERDES changes
From: Marek Behún @ 2019-08-26 12:21 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
Hello,
this is the fourth version of changes for the Topaz/Peridot family of
switches. The patches apply on net-next.
Changes since v3:
- there was a mistake in the serdes_get_lane implementations for
6390 (patch 3/6). These methods returned -ENODEV if no lane was
to be on port, but they should return 0. This is now fixed.
Tested on Turris Mox with Peridot, Topaz, and Peridot + Topaz.
Marek
Marek Behún (6):
net: dsa: mv88e6xxx: support 2500base-x in SGMII IRQ handler
net: dsa: mv88e6xxx: update code operating on hidden registers
net: dsa: mv88e6xxx: create serdes_get_lane chip operation
net: dsa: mv88e6xxx: simplify SERDES code for Topaz and Peridot
net: dsa: mv88e6xxx: rename port cmode macro
net: dsa: mv88e6xxx: fully support SERDES on Topaz family
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 88 +++-----
drivers/net/dsa/mv88e6xxx/chip.h | 3 +
drivers/net/dsa/mv88e6xxx/port.c | 98 ++++++---
drivers/net/dsa/mv88e6xxx/port.h | 30 ++-
drivers/net/dsa/mv88e6xxx/port_hidden.c | 70 ++++++
drivers/net/dsa/mv88e6xxx/serdes.c | 275 +++++++++++-------------
drivers/net/dsa/mv88e6xxx/serdes.h | 27 ++-
8 files changed, 333 insertions(+), 259 deletions(-)
create mode 100644 drivers/net/dsa/mv88e6xxx/port_hidden.c
--
2.21.0
^ permalink raw reply
* [PATCH net-next v4 6/6] net: dsa: mv88e6xxx: fully support SERDES on Topaz family
From: Marek Behún @ 2019-08-26 12:21 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190826122109.20660-1-marek.behun@nic.cz>
Currently we support SERDES on the Topaz family in a limited way: no
IRQs and the cmode is not writable, thus the mode is determined by
strapping pins.
Marvell's examples though show how to make cmode writable on port 5 and
support SGMII autonegotiation. It is done by writing hidden registers,
for which we already have code.
This patch adds support for making the cmode for the SERDES port
writable on the Topaz family, and enables cmode setting and SERDES IRQs.
Tested on Turris Mox.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/net/dsa/mv88e6xxx/chip.c | 6 +++
drivers/net/dsa/mv88e6xxx/port.c | 76 +++++++++++++++++++++++++-------
drivers/net/dsa/mv88e6xxx/port.h | 4 ++
3 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 202ccce65b1c..6525075f6bd3 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2913,6 +2913,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_set_cmode = mv88e6341_port_set_cmode,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
@@ -2929,6 +2930,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6341_serdes_get_lane,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_validate = mv88e6341_phylink_validate,
};
@@ -3608,6 +3611,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6352_port_link_state,
.port_get_cmode = mv88e6352_port_get_cmode,
+ .port_set_cmode = mv88e6341_port_set_cmode,
.port_setup_message_port = mv88e6xxx_setup_message_port,
.stats_snapshot = mv88e6390_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
@@ -3624,6 +3628,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
.serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6341_serdes_get_lane,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 7183c94a92ec..908b95434b4d 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -392,17 +392,37 @@ phy_interface_t mv88e6390x_port_max_speed_mode(int port)
return PHY_INTERFACE_MODE_NA;
}
-int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
- phy_interface_t mode)
+static int mv88e6341_port_force_writable_cmode(struct mv88e6xxx_chip *chip,
+ int port)
+{
+ int err, addr;
+ u16 reg, bits;
+
+ addr = chip->info->port_base_addr + port;
+
+ err = mv88e6xxx_port_hidden_read(chip, 0x7, addr, 0, ®);
+ if (err)
+ return err;
+
+ bits = MV88E6341_PORT_RESERVED_1A_FORCE_CMODE |
+ MV88E6341_PORT_RESERVED_1A_SGMII_AN;
+
+ if ((reg & bits) == bits)
+ return 0;
+
+ reg |= bits;
+ return mv88e6xxx_port_hidden_write(chip, 0x7, addr, 0, reg);
+}
+
+static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode, bool allow_over_2500,
+ bool make_cmode_writable)
{
s8 lane;
u16 cmode;
u16 reg;
int err;
- if (port != 9 && port != 10)
- return -EOPNOTSUPP;
-
/* Default to a slow mode, so freeing up SERDES interfaces for
* other ports which might use them for SFPs.
*/
@@ -421,9 +441,13 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
break;
case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_XAUI:
+ if (!allow_over_2500)
+ return -EINVAL;
cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
break;
case PHY_INTERFACE_MODE_RXAUI:
+ if (!allow_over_2500)
+ return -EINVAL;
cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
break;
default:
@@ -457,6 +481,12 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
if (err)
return err;
+ if (make_cmode_writable) {
+ err = mv88e6341_port_force_writable_cmode(chip, port);
+ if (err)
+ return err;
+ }
+
reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
reg |= cmode;
@@ -484,21 +514,37 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
return 0;
}
+int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ if (port != 9 && port != 10)
+ return -EOPNOTSUPP;
+
+ return mv88e6xxx_port_set_cmode(chip, port, mode, true, false);
+}
+
int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode)
{
- switch (mode) {
- case PHY_INTERFACE_MODE_NA:
+ if (port != 9 && port != 10)
+ return -EOPNOTSUPP;
+
+ if (mode == PHY_INTERFACE_MODE_NA)
+ return 0;
+
+ return mv88e6xxx_port_set_cmode(chip, port, mode, false, false);
+}
+
+int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode)
+{
+ if (port != 5)
+ return -EOPNOTSUPP;
+
+ if (mode == PHY_INTERFACE_MODE_NA)
return 0;
- case PHY_INTERFACE_MODE_XGMII:
- case PHY_INTERFACE_MODE_XAUI:
- case PHY_INTERFACE_MODE_RXAUI:
- return -EINVAL;
- default:
- break;
- }
- return mv88e6390x_port_set_cmode(chip, port, mode);
+ return mv88e6xxx_port_set_cmode(chip, port, mode, false, true);
}
int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 6d7a067da0f5..d4e9bea6e82f 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -269,6 +269,8 @@
#define MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT 10
#define MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT 0x04
#define MV88E6XXX_PORT_RESERVED_1A_DATA_PORT 0x05
+#define MV88E6341_PORT_RESERVED_1A_FORCE_CMODE 0x8000
+#define MV88E6341_PORT_RESERVED_1A_SGMII_AN 0x2000
int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
u16 *val);
@@ -334,6 +336,8 @@ int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
u8 out);
int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
u8 out);
+int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+ phy_interface_t mode);
int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
phy_interface_t mode);
int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v4 4/6] net: dsa: mv88e6xxx: simplify SERDES code for Topaz and Peridot
From: Marek Behún @ 2019-08-26 12:21 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190826122109.20660-1-marek.behun@nic.cz>
By adding an additional serdes_get_lane implementation (for Topaz), we
can merge the implementations of other SERDES functions (powering and
IRQs). We can skip checking port numbers, since the serdes_get_lane()
methods inform if there is no lane on a port or if the lane cannot be
used for given cmode.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/net/dsa/mv88e6xxx/chip.c | 18 ++---
drivers/net/dsa/mv88e6xxx/port.c | 4 +-
drivers/net/dsa/mv88e6xxx/serdes.c | 104 ++++++++---------------------
drivers/net/dsa/mv88e6xxx/serdes.h | 7 +-
4 files changed, 42 insertions(+), 91 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 5a3fff1971b9..202ccce65b1c 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2927,7 +2927,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
- .serdes_power = mv88e6341_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6341_serdes_get_lane,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_validate = mv88e6341_phylink_validate,
};
@@ -3301,10 +3302,10 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.rmu_disable = mv88e6390_g1_rmu_disable,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
- .serdes_power = mv88e6390x_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6390x_serdes_get_lane,
- .serdes_irq_setup = mv88e6390x_serdes_irq_setup,
- .serdes_irq_free = mv88e6390x_serdes_irq_free,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_validate = mv88e6390x_phylink_validate,
};
@@ -3621,7 +3622,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.reset = mv88e6352_g1_reset,
.vtu_getnext = mv88e6352_g1_vtu_getnext,
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
- .serdes_power = mv88e6341_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
+ .serdes_get_lane = mv88e6341_serdes_get_lane,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
@@ -3854,10 +3856,10 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.rmu_disable = mv88e6390_g1_rmu_disable,
.vtu_getnext = mv88e6390_g1_vtu_getnext,
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
- .serdes_power = mv88e6390x_serdes_power,
+ .serdes_power = mv88e6390_serdes_power,
.serdes_get_lane = mv88e6390x_serdes_get_lane,
- .serdes_irq_setup = mv88e6390x_serdes_irq_setup,
- .serdes_irq_free = mv88e6390x_serdes_irq_free,
+ .serdes_irq_setup = mv88e6390_serdes_irq_setup,
+ .serdes_irq_free = mv88e6390_serdes_irq_free,
.gpio_ops = &mv88e6352_gpio_ops,
.avb_ops = &mv88e6390_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 6a1fa5c72fdb..d20be5327640 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -445,7 +445,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
return err;
}
- err = mv88e6390x_serdes_power(chip, port, false);
+ err = mv88e6390_serdes_power(chip, port, false);
if (err)
return err;
}
@@ -470,7 +470,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
if (err)
return err;
- err = mv88e6390x_serdes_power(chip, port, true);
+ err = mv88e6390_serdes_power(chip, port, true);
if (err)
return err;
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 61ef7bf85829..d7aadda157d6 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -286,6 +286,23 @@ void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
chip->ports[port].serdes_irq = 0;
}
+int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
+{
+ u8 cmode = chip->ports[port].cmode;
+
+ *lane = -1;
+
+ if (port != 5)
+ return 0;
+
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
+ cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+ *lane = MV88E6341_PORT5_LANE;
+
+ return 0;
+}
+
int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
{
u8 cmode = chip->ports[port].cmode;
@@ -445,26 +462,9 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, s8 lane,
return err;
}
-static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port,
- s8 lane, bool on)
-{
- u8 cmode = chip->ports[port].cmode;
-
- switch (cmode) {
- case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
- case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
- return mv88e6390_serdes_power_sgmii(chip, lane, on);
- case MV88E6XXX_PORT_STS_CMODE_XAUI:
- case MV88E6XXX_PORT_STS_CMODE_RXAUI:
- return mv88e6390_serdes_power_10g(chip, lane, on);
- }
-
- return 0;
-}
-
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
{
+ u8 cmode = chip->ports[port].cmode;
s8 lane;
int err;
@@ -474,30 +474,14 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
if (lane < 0)
return 0;
- switch (port) {
- case 9 ... 10:
- return mv88e6390_serdes_power_lane(chip, port, lane, on);
- }
-
- return 0;
-}
-
-int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
-{
- s8 lane;
- int err;
-
- err = mv88e6xxx_serdes_get_lane(chip, port, &lane);
- if (err)
- return err;
- if (lane < 0)
- return 0;
-
- switch (port) {
- case 2 ... 4:
- case 5 ... 7:
- case 9 ... 10:
- return mv88e6390_serdes_power_lane(chip, port, lane, on);
+ switch (cmode) {
+ case MV88E6XXX_PORT_STS_CMODE_SGMII:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
+ return mv88e6390_serdes_power_sgmii(chip, lane, on);
+ case MV88E6XXX_PORT_STS_CMODE_XAUI:
+ case MV88E6XXX_PORT_STS_CMODE_RXAUI:
+ return mv88e6390_serdes_power_10g(chip, lane, on);
}
return 0;
@@ -662,7 +646,7 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
return ret;
}
-int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
+int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
{
int err;
s8 lane;
@@ -700,15 +684,7 @@ int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
return mv88e6390_serdes_irq_enable(chip, port, lane);
}
-int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
-{
- if (port < 9)
- return 0;
-
- return mv88e6390x_serdes_irq_setup(chip, port);
-}
-
-void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
+void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
{
int err;
s8 lane;
@@ -732,27 +708,3 @@ void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
chip->ports[port].serdes_irq = 0;
}
-
-void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
-{
- if (port < 9)
- return;
-
- mv88e6390x_serdes_irq_free(chip, port);
-}
-
-int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
-{
- u8 cmode = chip->ports[port].cmode;
-
- if (port != 5)
- return 0;
-
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
- cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
- cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- return mv88e6390_serdes_power_sgmii(chip, MV88E6341_ADDR_SERDES,
- on);
-
- return 0;
-}
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 1ddb8fb3aab9..7fded708b05d 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -28,7 +28,7 @@
#define MV88E6352_SERDES_INT_STATUS 0x13
-#define MV88E6341_ADDR_SERDES 0x15
+#define MV88E6341_PORT5_LANE 0x15
#define MV88E6390_PORT9_LANE0 0x09
#define MV88E6390_PORT9_LANE1 0x12
@@ -87,16 +87,13 @@ static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
return chip->info->ops->serdes_get_lane(chip, port, lane);
}
+int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane);
-int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
-int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
-int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port);
-void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
int port, uint8_t *data);
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v4 1/6] net: dsa: mv88e6xxx: support 2500base-x in SGMII IRQ handler
From: Marek Behún @ 2019-08-26 12:21 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190826122109.20660-1-marek.behun@nic.cz>
The mv88e6390_serdes_irq_link_sgmii IRQ handler reads the SERDES PHY
status register to determine speed, among other things. If cmode of the
port is set to 2500base-x, though, the PHY still reports 1000 Mbps (the
PHY register itself does not differentiate between 1000 Mbps and 2500
Mbps - it thinks it is running at 1000 Mbps, although clock is 2.5x
faster).
Look at the cmode and set SPEED_2500 if cmode is set to 2500base-x.
Also tell mv88e6xxx_port_setup_mac the PHY interface mode corresponding
to current cmode in terms of phy_interface_t.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Vladimir Oltean <olteanv@gmail.com>
Cc: Vivien Didelot <vivien.didelot@gmail.com>
---
drivers/net/dsa/mv88e6xxx/serdes.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 20c526c2a9ee..678aaba3d019 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -505,9 +505,11 @@ int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
int port, int lane)
{
+ u8 cmode = chip->ports[port].cmode;
struct dsa_switch *ds = chip->ds;
int duplex = DUPLEX_UNKNOWN;
int speed = SPEED_UNKNOWN;
+ phy_interface_t mode;
int link, err;
u16 status;
@@ -527,7 +529,10 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
- speed = SPEED_1000;
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
+ speed = SPEED_2500;
+ else
+ speed = SPEED_1000;
break;
case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
speed = SPEED_100;
@@ -541,8 +546,22 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
}
}
+ switch (cmode) {
+ case MV88E6XXX_PORT_STS_CMODE_SGMII:
+ mode = PHY_INTERFACE_MODE_SGMII;
+ break;
+ case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ mode = PHY_INTERFACE_MODE_1000BASEX;
+ break;
+ case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
+ mode = PHY_INTERFACE_MODE_2500BASEX;
+ break;
+ default:
+ mode = PHY_INTERFACE_MODE_NA;
+ }
+
err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
- PAUSE_OFF, PHY_INTERFACE_MODE_NA);
+ PAUSE_OFF, mode);
if (err)
dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
err);
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v4 5/6] net: dsa: mv88e6xxx: rename port cmode macro
From: Marek Behún @ 2019-08-26 12:21 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190826122109.20660-1-marek.behun@nic.cz>
This is a cosmetic update. We are removing the last underscore from
macros MV88E6XXX_PORT_STS_CMODE_100BASE_X and
MV88E6XXX_PORT_STS_CMODE_1000BASE_X. The 2500base-x version does not
have that underscore. Also PHY_INTERFACE_MODE_ macros do not have it
there.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx/port.c | 4 +--
drivers/net/dsa/mv88e6xxx/port.h | 4 +--
drivers/net/dsa/mv88e6xxx/serdes.c | 48 +++++++++++++++---------------
3 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index d20be5327640..7183c94a92ec 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -411,7 +411,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
switch (mode) {
case PHY_INTERFACE_MODE_1000BASEX:
- cmode = MV88E6XXX_PORT_STS_CMODE_1000BASE_X;
+ cmode = MV88E6XXX_PORT_STS_CMODE_1000BASEX;
break;
case PHY_INTERFACE_MODE_SGMII:
cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
@@ -618,7 +618,7 @@ int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
else
state->interface = PHY_INTERFACE_MODE_RGMII;
break;
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
state->interface = PHY_INTERFACE_MODE_1000BASEX;
break;
case MV88E6XXX_PORT_STS_CMODE_SGMII:
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 21d2d8f7c8f9..6d7a067da0f5 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -43,8 +43,8 @@
#define MV88E6XXX_PORT_STS_FLOW_CTL 0x0010
#define MV88E6XXX_PORT_STS_CMODE_MASK 0x000f
#define MV88E6XXX_PORT_STS_CMODE_RGMII 0x0007
-#define MV88E6XXX_PORT_STS_CMODE_100BASE_X 0x0008
-#define MV88E6XXX_PORT_STS_CMODE_1000BASE_X 0x0009
+#define MV88E6XXX_PORT_STS_CMODE_100BASEX 0x0008
+#define MV88E6XXX_PORT_STS_CMODE_1000BASEX 0x0009
#define MV88E6XXX_PORT_STS_CMODE_SGMII 0x000a
#define MV88E6XXX_PORT_STS_CMODE_2500BASEX 0x000b
#define MV88E6XXX_PORT_STS_CMODE_XAUI 0x000c
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index d7aadda157d6..e2439f86d351 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -73,8 +73,8 @@ static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
{
u8 cmode = chip->ports[port].cmode;
- if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) ||
- (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) ||
+ if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
+ (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
(cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
return true;
@@ -295,7 +295,7 @@ int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
if (port != 5)
return 0;
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
*lane = MV88E6341_PORT5_LANE;
@@ -311,13 +311,13 @@ int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
switch (port) {
case 9:
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
*lane = MV88E6390_PORT9_LANE0;
break;
case 10:
- if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
*lane = MV88E6390_PORT10_LANE0;
@@ -341,53 +341,53 @@ int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
switch (port) {
case 2:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT9_LANE1;
break;
case 3:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT9_LANE2;
break;
case 4:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT9_LANE3;
break;
case 5:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT10_LANE1;
break;
case 6:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT10_LANE2;
break;
case 7:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
- if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X)
+ if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
*lane = MV88E6390_PORT10_LANE3;
break;
case 9:
- if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
@@ -395,7 +395,7 @@ int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, s8 *lane)
*lane = MV88E6390_PORT9_LANE0;
break;
case 10:
- if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X ||
+ if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
@@ -476,7 +476,7 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
return mv88e6390_serdes_power_sgmii(chip, lane, on);
case MV88E6XXX_PORT_STS_CMODE_XAUI:
@@ -535,7 +535,7 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
case MV88E6XXX_PORT_STS_CMODE_SGMII:
mode = PHY_INTERFACE_MODE_SGMII;
break;
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
mode = PHY_INTERFACE_MODE_1000BASEX;
break;
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
@@ -578,7 +578,7 @@ int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
err = mv88e6390_serdes_irq_enable_sgmii(chip, lane);
}
@@ -594,7 +594,7 @@ int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
err = mv88e6390_serdes_irq_disable_sgmii(chip, lane);
}
@@ -629,7 +629,7 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id)
switch (cmode) {
case MV88E6XXX_PORT_STS_CMODE_SGMII:
- case MV88E6XXX_PORT_STS_CMODE_1000BASE_X:
+ case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
if (err)
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v4 2/6] net: dsa: mv88e6xxx: update code operating on hidden registers
From: Marek Behún @ 2019-08-26 12:21 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Vivien Didelot, Florian Fainelli, Vladimir Oltean,
Marek Behún
In-Reply-To: <20190826122109.20660-1-marek.behun@nic.cz>
This patch moves the functions operating on the hidden debug registers
into it's own file, port_hidden.c. The functions prefix is renamed from
mv88e6390_hidden_ to mv88e6xxx_port_hidden_, to be consistent with the
rest of this driver. The macros are prefixed with MV88E6XXX_ prefix, and
are changed not to use the BIT() macro nor bit shifts, since the rest of
the port.h file does not use it.
We also add the support for setting the Block Address field when
operating hidden registers. Marvell's mdio examples for SERDES settings
on Topaz use Block Address 0x7 when reading/writing hidden registers,
and although the specification says that block must be set to 0xf, those
settings are reachable only with Block Address 0x7.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 58 +-------------------
drivers/net/dsa/mv88e6xxx/port.h | 22 +++++---
drivers/net/dsa/mv88e6xxx/port_hidden.c | 70 +++++++++++++++++++++++++
4 files changed, 87 insertions(+), 64 deletions(-)
create mode 100644 drivers/net/dsa/mv88e6xxx/port_hidden.c
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
index e85755dde90b..aa645ff86f64 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -10,6 +10,7 @@ mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2_scratch.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o
mv88e6xxx-objs += phy.o
mv88e6xxx-objs += port.o
+mv88e6xxx-objs += port_hidden.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o
mv88e6xxx-objs += serdes.o
mv88e6xxx-objs += smi.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index d0bf98c10b2b..ec4274d71145 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2317,60 +2317,6 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
return mv88e6xxx_g1_stats_clear(chip);
}
-/* The mv88e6390 has some hidden registers used for debug and
- * development. The errata also makes use of them.
- */
-static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
- int reg, u16 val)
-{
- u16 ctrl;
- int err;
-
- err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
- PORT_RESERVED_1A, val);
- if (err)
- return err;
-
- ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
- PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
- reg;
-
- return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
- PORT_RESERVED_1A, ctrl);
-}
-
-static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
-{
- int bit = __bf_shf(PORT_RESERVED_1A_BUSY);
-
- return mv88e6xxx_wait_bit(chip, PORT_RESERVED_1A_CTRL_PORT,
- PORT_RESERVED_1A, bit, 0);
-}
-
-
-static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
- int reg, u16 *val)
-{
- u16 ctrl;
- int err;
-
- ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
- PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
- reg;
-
- err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
- PORT_RESERVED_1A, ctrl);
- if (err)
- return err;
-
- err = mv88e6390_hidden_wait(chip);
- if (err)
- return err;
-
- return mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
- PORT_RESERVED_1A, val);
-}
-
/* Check if the errata has already been applied. */
static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
{
@@ -2379,7 +2325,7 @@ static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
u16 val;
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
- err = mv88e6390_hidden_read(chip, port, 0, &val);
+ err = mv88e6xxx_port_hidden_read(chip, 0xf, port, 0, &val);
if (err) {
dev_err(chip->dev,
"Error reading hidden register: %d\n", err);
@@ -2412,7 +2358,7 @@ static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
}
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
- err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
+ err = mv88e6xxx_port_hidden_write(chip, 0xf, port, 0, 0x01c0);
if (err)
return err;
}
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 1abf5ea033e2..21d2d8f7c8f9 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -261,14 +261,14 @@
#define MV88E6095_PORT_IEEE_PRIO_REMAP_4567 0x19
/* Offset 0x1a: Magic undocumented errata register */
-#define PORT_RESERVED_1A 0x1a
-#define PORT_RESERVED_1A_BUSY BIT(15)
-#define PORT_RESERVED_1A_WRITE BIT(14)
-#define PORT_RESERVED_1A_READ 0
-#define PORT_RESERVED_1A_PORT_SHIFT 5
-#define PORT_RESERVED_1A_BLOCK (0xf << 10)
-#define PORT_RESERVED_1A_CTRL_PORT 4
-#define PORT_RESERVED_1A_DATA_PORT 5
+#define MV88E6XXX_PORT_RESERVED_1A 0x1a
+#define MV88E6XXX_PORT_RESERVED_1A_BUSY 0x8000
+#define MV88E6XXX_PORT_RESERVED_1A_WRITE 0x4000
+#define MV88E6XXX_PORT_RESERVED_1A_READ 0x0000
+#define MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT 5
+#define MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT 10
+#define MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT 0x04
+#define MV88E6XXX_PORT_RESERVED_1A_DATA_PORT 0x05
int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
u16 *val);
@@ -353,4 +353,10 @@ int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port);
int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port);
+int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
+ int port, int reg, u16 val);
+int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
+ int reg, u16 *val);
+
#endif /* _MV88E6XXX_PORT_H */
diff --git a/drivers/net/dsa/mv88e6xxx/port_hidden.c b/drivers/net/dsa/mv88e6xxx/port_hidden.c
new file mode 100644
index 000000000000..b49d05f0e117
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/port_hidden.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Marvell 88E6xxx Switch Hidden Registers support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch>
+ */
+
+#include <linux/bitfield.h>
+
+#include "chip.h"
+#include "port.h"
+
+/* The mv88e6390 and mv88e6341 have some hidden registers used for debug and
+ * development. The errata also makes use of them.
+ */
+int mv88e6xxx_port_hidden_write(struct mv88e6xxx_chip *chip, int block,
+ int port, int reg, u16 val)
+{
+ u16 ctrl;
+ int err;
+
+ err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, val);
+ if (err)
+ return err;
+
+ ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
+ MV88E6XXX_PORT_RESERVED_1A_WRITE |
+ block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
+ port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
+ reg;
+
+ return mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, ctrl);
+}
+
+int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip)
+{
+ int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY);
+
+ return mv88e6xxx_wait_bit(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, bit, 0);
+}
+
+int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port,
+ int reg, u16 *val)
+{
+ u16 ctrl;
+ int err;
+
+ ctrl = MV88E6XXX_PORT_RESERVED_1A_BUSY |
+ MV88E6XXX_PORT_RESERVED_1A_READ |
+ block << MV88E6XXX_PORT_RESERVED_1A_BLOCK_SHIFT |
+ port << MV88E6XXX_PORT_RESERVED_1A_PORT_SHIFT |
+ reg;
+
+ err = mv88e6xxx_port_write(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, ctrl);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_hidden_wait(chip);
+ if (err)
+ return err;
+
+ return mv88e6xxx_port_read(chip, MV88E6XXX_PORT_RESERVED_1A_DATA_PORT,
+ MV88E6XXX_PORT_RESERVED_1A, val);
+}
--
2.21.0
^ 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