* [PATCH net] netlink: don't send unknown nsid
From: Nicolas Dichtel @ 2017-06-01 8:00 UTC (permalink / raw)
To: davem; +Cc: netdev, fbl, Nicolas Dichtel
In-Reply-To: <4942f9fe-625b-bb97-7b45-4a1e8bf69b1b@6wind.com>
The NETLINK_F_LISTEN_ALL_NSID otion enables to listen all netns that have a
nsid assigned into the netns where the netlink socket is opened.
The nsid is sent as metadata to userland, but the existence of this nsid is
checked only for netns that are different from the socket netns. Thus, if
no nsid is assigned to the socket netns, NETNSA_NSID_NOT_ASSIGNED is
reported to the userland. This value is confusing and useless.
After this patch, only valid nsid are sent to userland.
Reported-by: Flavio Leitner <fbl@sysclose.org>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/netlink/af_netlink.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index ee841f00a6ec..7586d446d7dc 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -62,6 +62,7 @@
#include <asm/cacheflush.h>
#include <linux/hash.h>
#include <linux/genetlink.h>
+#include <linux/net_namespace.h>
#include <net/net_namespace.h>
#include <net/sock.h>
@@ -1415,7 +1416,8 @@ static void do_one_broadcast(struct sock *sk,
goto out;
}
NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
- NETLINK_CB(p->skb2).nsid_is_set = true;
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
val = netlink_broadcast_deliver(sk, p->skb2);
if (val < 0) {
netlink_overrun(sk);
--
2.8.1
^ permalink raw reply related
* [PATCH] qlcnic: Fix a sleep-in-atomic bug in qlcnic_82xx_hw_write_wx_2M and qlcnic_82xx_hw_read_wx_2M
From: Jia-Ju Bai @ 2017-06-01 8:18 UTC (permalink / raw)
To: harish.patil, manish.chopra, Dept-GELinuxNICDev
Cc: netdev, linux-kernel, Jia-Ju Bai
The driver may sleep under a write spin lock, and the function
call path is:
qlcnic_82xx_hw_write_wx_2M (acquire the lock by write_lock_irqsave)
crb_win_lock
qlcnic_pcie_sem_lock
usleep_range
qlcnic_82xx_hw_read_wx_2M (acquire the lock by write_lock_irqsave)
crb_win_lock
qlcnic_pcie_sem_lock
usleep_range
To fix it, the usleep_range is replaced with udelay.
Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 838cc0c..7848cf0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -341,7 +341,7 @@ static void qlcnic_write_window_reg(u32 addr, void __iomem *bar0, u32 data)
}
return -EIO;
}
- usleep_range(1000, 1500);
+ udelay(1200);
}
if (id_reg)
--
1.7.9.5
^ permalink raw reply related
* [net] vxlan: fix use-after-free on deletion
From: Mark Bloch @ 2017-06-01 8:43 UTC (permalink / raw)
To: jbenc, roopa; +Cc: netdev
Adding a vxlan interface to a socket isn't symmetrical, while adding
is done in vxlan_open() the deletion is done in vxlan_dellink().
This can cause a use-after-free error when we close the vxlan
interface before deleting it.
We add vxlan_vs_del_dev() to match vxlan_vs_add_dev() and call
it from vxlan_stop() to match the call from vxlan_open().
Signed-off-by: Mark Bloch <markb@mellanox.com>
---
drivers/net/vxlan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 328b471..f6a4310 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -59,6 +59,8 @@
static int vxlan_sock_add(struct vxlan_dev *vxlan);
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan);
+
/* per-network namespace private data for this module */
struct vxlan_net {
struct list_head vxlan_list;
@@ -1067,6 +1069,8 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
rcu_assign_pointer(vxlan->vn4_sock, NULL);
synchronize_net();
+ vxlan_vs_del_dev(vxlan);
+
if (__vxlan_sock_release_prep(sock4)) {
udp_tunnel_sock_release(sock4->sock);
kfree(sock4);
@@ -2342,6 +2346,15 @@ static void vxlan_cleanup(unsigned long arg)
mod_timer(&vxlan->age_timer, next_timer);
}
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
+{
+ struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+
+ spin_lock(&vn->sock_lock);
+ hlist_del_init_rcu(&vxlan->hlist);
+ spin_unlock(&vn->sock_lock);
+}
+
static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
{
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
@@ -3286,15 +3299,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
static void vxlan_dellink(struct net_device *dev, struct list_head *head)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
vxlan_flush(vxlan, true);
- spin_lock(&vn->sock_lock);
- if (!hlist_unhashed(&vxlan->hlist))
- hlist_del_rcu(&vxlan->hlist);
- spin_unlock(&vn->sock_lock);
-
gro_cells_destroy(&vxlan->gro_cells);
list_del(&vxlan->next);
unregister_netdevice_queue(dev, head);
--
1.8.4.3
^ permalink raw reply related
* Re: [net] vxlan: fix use-after-free on deletion
From: Jiri Benc @ 2017-06-01 8:53 UTC (permalink / raw)
To: Mark Bloch; +Cc: roopa, netdev
In-Reply-To: <1496306615-770-1-git-send-email-markb@mellanox.com>
On Thu, 1 Jun 2017 11:43:35 +0300, Mark Bloch wrote:
> Adding a vxlan interface to a socket isn't symmetrical, while adding
> is done in vxlan_open() the deletion is done in vxlan_dellink().
> This can cause a use-after-free error when we close the vxlan
> interface before deleting it.
>
> We add vxlan_vs_del_dev() to match vxlan_vs_add_dev() and call
> it from vxlan_stop() to match the call from vxlan_open().
>
> Signed-off-by: Mark Bloch <markb@mellanox.com>
Acked-by: Jiri Benc <jbenc@redhat.com>
^ permalink raw reply
* Re: [PATCH nf-next] netns: add and use net_ns_barrier
From: Florian Westphal @ 2017-06-01 8:52 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Florian Westphal, netfilter-devel, netdev
In-Reply-To: <87y3tcj3n7.fsf@xmission.com>
Eric W. Biederman <ebiederm@xmission.com> wrote:
> Florian Westphal <fw@strlen.de> writes:
>
> > Quoting Joe Stringer:
> > If a user loads nf_conntrack_ftp, sends FTP traffic through a network
> > namespace, destroys that namespace then unloads the FTP helper module,
> > then the kernel will crash.
> >
> > Events that lead to the crash:
> > 1. conntrack is created with ftp helper in netns x
> > 2. This netns is destroyed
> > 3. netns destruction is scheduled
> > 4. netns destruction wq starts, removes netns from global list
> > 5. ftp helper is unloaded, which resets all helpers of the conntracks
> > via for_each_net()
> >
> > but because netns is already gone from list the for_each_net() loop
> > doesn't include it, therefore all of these conntracks are unaffected.
> >
> > 6. helper module unload finishes
> > 7. netns wq invokes destructor for rmmod'ed helper
> >
> > CC: "Eric W. Biederman" <ebiederm@xmission.com>
> > Reported-by: Joe Stringer <joe@ovn.org>
> > Signed-off-by: Florian Westphal <fw@strlen.de>
> > ---
> > Eric, I'd like an explicit (n)ack from you for this one.
>
> This doesn't look too scary but I have the impression we have addressed
> this elsewhere with a different solution.
>
> Looking...
>
> Ok. unregister_pernet_operations takes the net_mutex and thus
> gives you this barrier automatically.
>
> Hmm. Why isn't this working for conntrack, looking...
>
> nf_conntrack_ftp doesn't use unregister_pernet_operations...
> nf_conntract_ftp does use nf_conntrack_helpers_unregister
>
> I think I almost see the problem.
>
> What is the per net code that stops dealing with the nf_conntract_ftp?
>
> I am trying to figure out if your netns_barrier is reasonable or if
> it treating the symptom. I am having trouble seeing enough of what
> conntrack is doing to judge.
>
> Am I correct in understanding that the root problem is there is
> something pointing to ftp_exp_policy at the time of module unload?
Joe described it nicely, problem is that after unload we may have
conntracks that still have a nf_conn_help extension attached that
has a pointer to a structure that resided in the (unloaded) module.
Normally these references should have been NULL'd out by
nf_ct_iterate_destroy(), however, there is a small chance that
its for_each_net() misses namespaces already removed-from-list by
concurrent netns workqueue cleanup.
I guess another solution to fix this would be to add dummy pernet
ops to all conntrack helpers so they block on unregister_pernet_subsys().
But thats rather ugly IMO since they don't have any notion of a net
namespace in first place.
^ permalink raw reply
* [PATCH net V3] net/mlx4: Fix the check in attaching steering rules
From: Tariq Toukan @ 2017-06-01 9:16 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Eran Ben Elisha, Or Gerlitz, Talat Batheesh, Tariq Toukan
From: Talat Batheesh <talatb@mellanox.com>
Our previous patch (cited below) introduced a regression
for RAW Eth QPs.
Fix it by checking if the QP number provided by user-space
exists, hence allowing steering rules to be added for valid
QPs only.
Fixes: 89c557687a32 ("net/mlx4_en: Avoid adding steering rules with ...")
Reported-by: Or Gerlitz <gerlitz.or@gmail.com>
Signed-off-by: Talat Batheesh <talatb@mellanox.com>
Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Acked-by: Or Gerlitz <ogerlitz@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
---
v3:
* Moved qpn check into core function, it will indicate any errors to the EN driver.
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 5 -----
drivers/net/ethernet/mellanox/mlx4/mcg.c | 15 +++++++++++----
drivers/net/ethernet/mellanox/mlx4/qp.c | 13 +++++++++++++
include/linux/mlx4/qp.h | 1 +
4 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index ae5fdc2df654..ffbcb27c05e5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -1562,11 +1562,6 @@ static int mlx4_en_flow_replace(struct net_device *dev,
qpn = priv->drop_qp.qpn;
else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {
qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1);
- if (qpn < priv->rss_map.base_qpn ||
- qpn >= priv->rss_map.base_qpn + priv->rx_ring_num) {
- en_warn(priv, "rxnfc: QP (0x%x) doesn't exist\n", qpn);
- return -EINVAL;
- }
} else {
if (cmd->fs.ring_cookie >= priv->rx_ring_num) {
en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist\n",
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index 1a670b681555..0710b3677464 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -35,6 +35,7 @@
#include <linux/etherdevice.h>
#include <linux/mlx4/cmd.h>
+#include <linux/mlx4/qp.h>
#include <linux/export.h>
#include "mlx4.h"
@@ -985,16 +986,21 @@ int mlx4_flow_attach(struct mlx4_dev *dev,
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
+ if (!mlx4_qp_lookup(dev, rule->qpn)) {
+ mlx4_err_rule(dev, "QP doesn't exist\n", rule);
+ ret = -EINVAL;
+ goto out;
+ }
+
trans_rule_ctrl_to_hw(rule, mailbox->buf);
size += sizeof(struct mlx4_net_trans_rule_hw_ctrl);
list_for_each_entry(cur, &rule->list, list) {
ret = parse_trans_rule(dev, cur, mailbox->buf + size);
- if (ret < 0) {
- mlx4_free_cmd_mailbox(dev, mailbox);
- return ret;
- }
+ if (ret < 0)
+ goto out;
+
size += ret;
}
@@ -1021,6 +1027,7 @@ int mlx4_flow_attach(struct mlx4_dev *dev,
}
}
+out:
mlx4_free_cmd_mailbox(dev, mailbox);
return ret;
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index 2d6abd4662b1..ad92d2311478 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -384,6 +384,19 @@ static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
__mlx4_qp_free_icm(dev, qpn);
}
+struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn)
+{
+ struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
+ struct mlx4_qp *qp;
+
+ spin_lock(&qp_table->lock);
+
+ qp = __mlx4_qp_lookup(dev, qpn);
+
+ spin_unlock(&qp_table->lock);
+ return qp;
+}
+
int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, gfp_t gfp)
{
struct mlx4_priv *priv = mlx4_priv(dev);
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index b4ee8f62ce8d..8e2828d48d7f 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -470,6 +470,7 @@ struct mlx4_update_qp_params {
u16 rate_val;
};
+struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn);
int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
enum mlx4_update_qp_attr attr,
struct mlx4_update_qp_params *params);
--
1.8.3.1
^ permalink raw reply related
* Re: [net-next 09/15] ixgbevf: Resolve truncation warning for q_vector->name
From: Sergei Shtylyov @ 2017-06-01 9:30 UTC (permalink / raw)
To: Jeff Kirsher, davem; +Cc: Tony Nguyen, netdev, nhorman, sassmann, jogreene
In-Reply-To: <20170531211936.63417-10-jeffrey.t.kirsher@intel.com>
Hello!
On 6/1/2017 12:19 AM, Jeff Kirsher wrote:
> From: Tony Nguyen <anthony.l.nguyen@intel.com>
>
> The following warning is now shown as a result of new checks added for
> gcc 7:
>
> drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c: In function ‘ixgbevf_open’:
> drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:1363:13: warning: ‘%d’ directive output may be truncated writing between 1 and 10 bytes into a region of size between 3 and 18 [-Wformat-truncation=]
> "%s-%s-%d", netdev->name, "TxRx", ri++);
> ^~
> drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:1363:6: note: directive argument in the range [0, 2147483647]
> "%s-%s-%d", netdev->name, "TxRx", ri++);
> ^~~~~~~~~~
> drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c:1362:4: note: ‘snprintf’ output between 8 and 32 bytes into a destination of size 24
> snprintf(q_vector->name, sizeof(q_vector->name) - 1,
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> "%s-%s-%d", netdev->name, "TxRx", ri++);
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> Resolve this warning by making a couple of changes.
> - Don't reserve space for the null terminator. Since snprintf adds the
> null terminator automatically, there is no need for us to reserve a byte
> for it.
>
> - Change a couple variables that can never be negative from int to
> unsigned int.
>
> While we're making changes to the format string, move the constant strings
> into the format string instead of providing them as specifiers.
I suspect that trick saved some data space due to using the identical (and
so merged) format strings...
> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
> Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
[...]
MBR, Sergei
^ permalink raw reply
* Re: BRCMFMAC OOB interrupt problem
From: Arend van Spriel @ 2017-06-01 9:38 UTC (permalink / raw)
To: Hegr, Jiri, franky.lin@broadcom.com, hante.meuleman@broadcom.com
Cc: kvalo@codeaurora.org, linux-wireless@vger.kernel.org,
brcm80211-dev-list.pdl@broadcom.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <BY2PR07MB15534619EB5D533B633CDAF5CEF60@BY2PR07MB1553.namprd07.prod.outlook.com>
On 01-06-17 09:44, Hegr, Jiri wrote:
> Dears,
> We use small WiFi evaluation board WM-BN-BM-04_EVB_V1.2 with BCM43362 chip (Broadcom).
> This board is connected to OMAP-L138 via SDIO interface with Linux 4.9.10 containing WiFi driver brcmfmac.
> Our problem is in OOB interrupt. The driver (and the WiFi chip) works fine if the interrupt is not set in a device tree (SDIO interface is used instead).
> But if the host-wake interrupt is used, the initialization phase does not pass. We are sure that the OOB interrupt is triggered. We found out that it waits for a control frame (probably) but it gets some event frame only. After about 2.5 seconds the timeout occurs and the initialization fails.
> Could you help us to solve the problem?
> There is our device tree settings and terminal output bellow (the "DBG" lines are our own).
>
> There is also problem with WARN_ON(nents > sdiodev->max_segment_count); in bcmsdh.c file, but it seems that it does not influence the driver work because the problem occurs without OOB interrupt setting also and everything works fine.
>
> Regards,
>
> Jiri Hegr
>
> mmc1: mmc@21b000 {
> #address-cells = <1>;
> #size-cells = <0>;
> max-frequency = <25000000>;
> bus-width = <4>;
> pinctrl-names = "default";
> pinctrl-0 = <&mmc1_pins>;
> status = "okay";
> non-removable;
>
> brcmf: bcrmf@1 {
> reg = <1>;
> compatible = "brcm,bcm4329-fmac";
> interrupt-parent = <&gpio>;
> interrupts = <95 0x02>;
> interrupt-names = "host-wake";
> };
> };
>
> [ 24.314527] brcmfmac: *** DBG: starting datawork worker thread...
> [ 24.354778] brcmfmac: *** DBG: brcmf_sdio_readframes...
> [ 24.360088] brcmfmac: *** DBG: rd->len check: 0
> [ 24.404232] brcmfmac: *** DBG: rd->channel check: 1
> [ 24.435047] brcmfmac: *** DBG: rd->len check: 0
> [ 24.454977] brcmfmac: *** DBG: brcmf_sdio_readframes - loop break
> [ 27.013900] brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout
> [ 27.019813] brcmfmac: brcmf_c_preinit_dcmds: Retreiving cur_etheraddr failed, -110
> [ 27.031282] brcmfmac: brcmf_bus_start: failed: -110
> [ 27.046164] brcmfmac: brcmf_sdio_firmware_callback: dongle is not responding
Can you build the driver with CONFIG_BRCMDBG and load the driver with
debugging:
$ sudo insmod brcmfmac.ko debug=0x31516
Regards,
Arend
> Honeywell *
> Jiri Hegr - R&D Scientist III.
>
> Honeywell International s.r.o. - Aerospace Advanced Techonologies
> V Parku 2325/16
> Praha 148 00, Czech Republic
> Office: Turanka 100
> 627 00 Brno, Czech Republic
>
> Tel: +420 532 115 564
> E-mail: jiri.hegr2@honeywell.com<mailto:jiri.hegr2@honeywell.com>
>
>
^ permalink raw reply
* Re: cw1200: Fix a sleep-in-atomic bug in cw1200_tx_confirm_cb and cw1200_cqm_bssloss_sm
From: Kalle Valo @ 2017-06-01 9:48 UTC (permalink / raw)
To: Jia-Ju Bai; +Cc: pizza, linux-wireless, netdev, linux-kernel, Jia-Ju Bai
In-Reply-To: <1496284574-11056-1-git-send-email-baijiaju1990@163.com>
Jia-Ju Bai <baijiaju1990@163.com> wrote:
> The driver may sleep under a spin lock, and the function call path is:
> cw1200_tx_confirm_cb (acquire the lock by spin_lock)
> __cw1200_cqm_bssloss_sm
> cancel_work_sync --> may sleep
>
> cw1200_cqm_bssloss_sm
> __cw1200_cqm_bssloss_sm
> cancel_work_sync --> may sleep
>
> To fix it, the lock is released before cancel_work_sync, and the lock
> is acquired again after this function.
>
> Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
I assume that you haven't tested this on a real device and only compile tested.
You should mention that in the commit log.
Releasing a lock held by calling function is evil. Did you do any lock analysis
or are you just blindly releasing locks to fix a warning in your tool?
Also I would like to have an ack from a reviewer before I can take patches like
this.
Patch set to Changes Requested.
--
https://patchwork.kernel.org/patch/9758613/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [net-next] qtnfmac: remove duplicated assignment to mac
From: Kalle Valo @ 2017-06-01 9:50 UTC (permalink / raw)
To: Colin Ian King
Cc: Avinash Patil, Sergey Matyukevich, Huizhao Wang, Kamlesh Rath,
linux-wireless, netdev, kernel-janitors, linux-kernel
In-Reply-To: <20170525134503.12106-1-colin.king@canonical.com>
Colin Ian King <colin.king@canonical.com> wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> mac is being assigned twice, remove redundant 2nd assignment.
>
> Detected by CoverityScan, CID#1437554 ("Incorrect expression")
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> Acked-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Patch applied to wireless-drivers-next.git, thanks.
4f8e25458cb6 qtnfmac: remove duplicated assignment to mac
--
https://patchwork.kernel.org/patch/9748407/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: mwifiex: simplify the code around ra_list
From: Kalle Valo @ 2017-06-01 9:50 UTC (permalink / raw)
To: Shawn Lin; +Cc: Amitkumar Karwar, Xinming Hu, linux-wireless, netdev, Shawn Lin
In-Reply-To: <1495762909-46795-1-git-send-email-shawn.lin@rock-chips.com>
Shawn Lin <shawn.lin@rock-chips.com> wrote:
> We don't need to check if the list is empty separately
> as we could use list_first_entry_or_null to cover it.
>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> Reviewed-by: Brian Norris <briannorris@chromium.org>
Patch applied to wireless-drivers-next.git, thanks.
01926202b34b mwifiex: simplify the code around ra_list
--
https://patchwork.kernel.org/patch/9749573/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
From: Yan, Zheng @ 2017-06-01 9:56 UTC (permalink / raw)
To: Deepa Dinamani
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
tglx-hfZtesqFncYOwBW4kG4KsQ, Al Viro,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
andreas.dilger-ral2JQCrhuEAvxtiuMwx3w, Arnd Bergmann,
bfields-uC3wQj2KruNg9hUCZPvPmw, clm-b10kYP2dOMg,
davem-fT/PcQaiUtIeIZ0/mPfg9Q, dsterba-IBi9RG/b67k,
dushistov-JGs/UdohzUI, eparis-H+wXaHxf7aLQT0dZR+AlfA,
jaegeuk-DgEjT+Ai2ygdnm+yROfE0A, jbacik-b10kYP2dOMg,
jlayton-vpEMnDpepFuMZCB2o+C8xQ,
john.stultz-QSEj5FYQhm4dnm+yROfE0A,
jsimmons-wEGCiKHe2LqWVfeAwA7xHQ, mingo-H+wXaHxf7aLQT0dZR+AlfA,
oleg.drokin-ral2JQCrhuEAvxtiuMwx3w, paul-r2n+y4ga6xFZroRs9YW3xA,
rostedt-nx8X9YLhiw1AfugRpC6u6w, yuchao0-hv44wF8Li93QT0dZR+AlfA,
ceph-devel, devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
linux-audit-H+wXaHxf7aLQT0dZR+AlfA,
linux-btrfs-u79uwXL29TY76Z2rM5mHXA,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-f2fs-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-securit
In-Reply-To: <1491613030-11599-5-git-send-email-deepa.kernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Sat, Apr 8, 2017 at 8:57 AM, Deepa Dinamani <deepa.kernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> CURRENT_TIME is not y2038 safe.
> The macro will be deleted and all the references to it
> will be replaced by ktime_get_* apis.
>
> struct timespec is also not y2038 safe.
> Retain timespec for timestamp representation here as ceph
> uses it internally everywhere.
> These references will be changed to use struct timespec64
> in a separate patch.
>
> The current_fs_time() api is being changed to use vfs
> struct inode* as an argument instead of struct super_block*.
>
> Set the new mds client request r_stamp field using
> ktime_get_real_ts() instead of using current_fs_time().
>
> Also, since r_stamp is used as mtime on the server, use
> timespec_trunc() to truncate the timestamp, using the right
> granularity from the superblock.
>
> This api will be transitioned to be y2038 safe along
> with vfs.
>
> Signed-off-by: Deepa Dinamani <deepa.kernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Reviewed-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> ---
> drivers/block/rbd.c | 2 +-
> fs/ceph/mds_client.c | 4 +++-
> net/ceph/messenger.c | 6 ++++--
> net/ceph/osd_client.c | 4 ++--
> 4 files changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
> index 517838b..77204da 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
> {
> struct ceph_osd_request *osd_req = obj_request->osd_req;
>
> - osd_req->r_mtime = CURRENT_TIME;
> + ktime_get_real_ts(&osd_req->r_mtime);
> osd_req->r_data_offset = obj_request->offset;
> }
>
> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> index c681762..1d3fa90 100644
> --- a/fs/ceph/mds_client.c
> +++ b/fs/ceph/mds_client.c
> @@ -1666,6 +1666,7 @@ struct ceph_mds_request *
> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
> {
> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
> + struct timespec ts;
>
> if (!req)
> return ERR_PTR(-ENOMEM);
> @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
> init_completion(&req->r_safe_completion);
> INIT_LIST_HEAD(&req->r_unsafe_item);
>
> - req->r_stamp = current_fs_time(mdsc->fsc->sb);
> + ktime_get_real_ts(&ts);
> + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
This change causes our kernel_untar_tar test case to fail (inode's
ctime goes back). The reason is that there is time drift between the
time stamps got by ktime_get_real_ts() and current_time(). We need to
revert this change until current_time() uses ktime_get_real_ts()
internally.
Regards
Yan, Zheng
>
> req->r_op = op;
> req->r_direct_mode = mode;
> diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
> index f76bb33..5766a6c 100644
> --- a/net/ceph/messenger.c
> +++ b/net/ceph/messenger.c
> @@ -1386,8 +1386,9 @@ static void prepare_write_keepalive(struct ceph_connection *con)
> dout("prepare_write_keepalive %p\n", con);
> con_out_kvec_reset(con);
> if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) {
> - struct timespec now = CURRENT_TIME;
> + struct timespec now;
>
> + ktime_get_real_ts(&now);
> con_out_kvec_add(con, sizeof(tag_keepalive2), &tag_keepalive2);
> ceph_encode_timespec(&con->out_temp_keepalive2, &now);
> con_out_kvec_add(con, sizeof(con->out_temp_keepalive2),
> @@ -3176,8 +3177,9 @@ bool ceph_con_keepalive_expired(struct ceph_connection *con,
> {
> if (interval > 0 &&
> (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2)) {
> - struct timespec now = CURRENT_TIME;
> + struct timespec now;
> struct timespec ts;
> + ktime_get_real_ts(&now);
> jiffies_to_timespec(interval, &ts);
> ts = timespec_add(con->last_keepalive_ack, ts);
> return timespec_compare(&now, &ts) >= 0;
> diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
> index e15ea9e..242d7c0 100644
> --- a/net/ceph/osd_client.c
> +++ b/net/ceph/osd_client.c
> @@ -3574,7 +3574,7 @@ ceph_osdc_watch(struct ceph_osd_client *osdc,
> ceph_oid_copy(&lreq->t.base_oid, oid);
> ceph_oloc_copy(&lreq->t.base_oloc, oloc);
> lreq->t.flags = CEPH_OSD_FLAG_WRITE;
> - lreq->mtime = CURRENT_TIME;
> + ktime_get_real_ts(&lreq->mtime);
>
> lreq->reg_req = alloc_linger_request(lreq);
> if (!lreq->reg_req) {
> @@ -3632,7 +3632,7 @@ int ceph_osdc_unwatch(struct ceph_osd_client *osdc,
> ceph_oid_copy(&req->r_base_oid, &lreq->t.base_oid);
> ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc);
> req->r_flags = CEPH_OSD_FLAG_WRITE;
> - req->r_mtime = CURRENT_TIME;
> + ktime_get_real_ts(&req->r_mtime);
> osd_req_op_watch_init(req, 0, lreq->linger_id,
> CEPH_OSD_WATCH_OP_UNWATCH);
>
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH net-next] ppp: remove unnecessary bh disable in xmit path
From: gfree.wind @ 2017-06-01 9:58 UTC (permalink / raw)
To: paulus, linux-ppp, g.nault, netdev; +Cc: Gao Feng
From: Gao Feng <gfree.wind@vip.163.com>
Since the commit 55454a565836 ("ppp: avoid dealock on recursive xmit"),
the PPP xmit path is protected by wrapper functions which disable the
bh already. So it is unnecessary to disable the bh again in the real
xmit path.
Signed-off-by: Gao Feng <gfree.wind@vip.163.com>
---
drivers/net/ppp/ppp_generic.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index f9c0e62..bbded33 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1618,7 +1618,7 @@ static void ppp_xmit_process(struct ppp *ppp)
list = list->next;
pch = list_entry(list, struct channel, clist);
- spin_lock_bh(&pch->downl);
+ spin_lock(&pch->downl);
if (pch->chan) {
if (pch->chan->ops->start_xmit(pch->chan, skb))
ppp->xmit_pending = NULL;
@@ -1627,7 +1627,7 @@ static void ppp_xmit_process(struct ppp *ppp)
kfree_skb(skb);
ppp->xmit_pending = NULL;
}
- spin_unlock_bh(&pch->downl);
+ spin_unlock(&pch->downl);
return;
}
@@ -1757,7 +1757,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
}
/* check the channel's mtu and whether it is still attached. */
- spin_lock_bh(&pch->downl);
+ spin_lock(&pch->downl);
if (pch->chan == NULL) {
/* can't use this channel, it's being deregistered */
if (pch->speed == 0)
@@ -1765,7 +1765,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
else
totspeed -= pch->speed;
- spin_unlock_bh(&pch->downl);
+ spin_unlock(&pch->downl);
pch->avail = 0;
totlen = len;
totfree--;
@@ -1816,7 +1816,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
*/
if (flen <= 0) {
pch->avail = 2;
- spin_unlock_bh(&pch->downl);
+ spin_unlock(&pch->downl);
continue;
}
@@ -1861,14 +1861,14 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
len -= flen;
++ppp->nxseq;
bits = 0;
- spin_unlock_bh(&pch->downl);
+ spin_unlock(&pch->downl);
}
ppp->nxchan = i;
return 1;
noskb:
- spin_unlock_bh(&pch->downl);
+ spin_unlock(&pch->downl);
if (ppp->debug & 1)
netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
++ppp->dev->stats.tx_errors;
@@ -1883,7 +1883,7 @@ static void __ppp_channel_push(struct channel *pch)
struct sk_buff *skb;
struct ppp *ppp;
- spin_lock_bh(&pch->downl);
+ spin_lock(&pch->downl);
if (pch->chan) {
while (!skb_queue_empty(&pch->file.xq)) {
skb = skb_dequeue(&pch->file.xq);
@@ -1897,14 +1897,14 @@ static void __ppp_channel_push(struct channel *pch)
/* channel got deregistered */
skb_queue_purge(&pch->file.xq);
}
- spin_unlock_bh(&pch->downl);
+ spin_unlock(&pch->downl);
/* see if there is anything from the attached unit to be sent */
if (skb_queue_empty(&pch->file.xq)) {
- read_lock_bh(&pch->upl);
+ read_lock(&pch->upl);
ppp = pch->ppp;
if (ppp)
__ppp_xmit_process(ppp);
- read_unlock_bh(&pch->upl);
+ read_unlock(&pch->upl);
}
}
--
1.9.1
^ permalink raw reply related
* Re: [i40e] regression on TCP stream and TCP maerts, kernel-4.12.0-0.rc2
From: Adrian Tomasov @ 2017-06-01 10:14 UTC (permalink / raw)
To: Alexander Duyck
Cc: Adam Okuliar, Mitch Williams, intel-wired-lan, Netdev,
Jeff Kirsher, Otto Sabart, Jirka Hladky
In-Reply-To: <CAKgT0Ucg9wHrKDBjQXKH6gziuinwcK9MO-jRC=0q60Lm-8vFqA@mail.gmail.com>
On Wed, 2017-05-31 at 14:42 -0700, Alexander Duyck wrote:
> On Wed, May 31, 2017 at 6:48 AM, Adrian Tomasov <atomasov@redhat.com>
> wrote:
> >
> > On Tue, 2017-05-30 at 18:27 -0700, Alexander Duyck wrote:
> > >
> > > On Tue, May 30, 2017 at 8:41 AM, Alexander Duyck
> > > <alexander.duyck@gmail.com> wrote:
> > > >
> > > >
> > > > On Tue, May 30, 2017 at 6:43 AM, Adam Okuliar <aokuliar@redhat.
> > > > com>
> > > > wrote:
> > > > >
> > > > >
> > > > > Hello,
> > > > >
> > > > > we found regression on intel card(XL710) with i40e driver.
> > > > > Regression is
> > > > > about ~45%
> > > > > on TCP_STREAM and TCP_MAERTS test for IPv4 and IPv6.
> > > > > Regression
> > > > > was first
> > > > > visible in kernel-4.12.0-0.rc1.
> > > > >
> > > > > More details about results you can see in uploaded images in
> > > > > bugzilla. [0]
> > > > >
> > > > >
> > > > > [0] https://bugzilla.kernel.org/show_bug.cgi?id=195923
> > > > >
> > > > >
> > > > > Best regards, / S pozdravom,
> > > > >
> > > > > Adrián Tomašov
> > > > > Kernel Performance QE
> > > > > atomasov@redhat.com
> > > >
> > > > I have added the i40e driver maintainer and the intel-wired-lan
> > > > mailing list so that we can make are developers aware of the
> > > > issue.
> > > >
> > > > Thanks.
> > > >
> > > > - Alex
> > >
> > > Adam,
> > >
> > > We are having some issues trying to reproduce what you reported.
> > >
> > > Can you provide some additional data. Specifically we would be
> > > looking
> > > for an "ethtool -i", and an "ethtool -S" for the port before and
> > > after
> > > the test. If you can attach it to the bugzilla that would be
> > > appreciated.
> > >
> > > Thanks.
> > >
> > > - Alex
> >
> > Hello Alex,
> >
> > requested files are updated in bugzilla.
> >
> > If you have any questions about testing feel free to ask.
> >
> >
> > Best regards,
> >
> > Adrian
>
> So looking at the data I wonder if we don't have an MTU mismatch in
> the network config. I notice the "after" has rx_length_errors being
> reported. Recent changes made it so that i40e doesn't support jumbo
> frames by default, whereas before we could. You might want to check
> for that as that could cause the kind of performance issues you are
> seeing.
>
> - Alex
There isn't MTU mismatch. Traffic path is : server -> switch ->
server.
Output from switch:
> show interfaces et-0/0/18
Physical interface: et-0/0/18, Enabled, Physical link is Up
Interface index: 644, SNMP ifIndex: 538
Link-level type: Ethernet, MTU: 1514, Speed: 40Gbps, BPDU Error:
None, MAC-REWRITE Error: None, Loopback: Disabled, Source filtering:
Disabled, Flow control: Disabled, Media type: Fiber
Device flags : Present Running
Interface flags: SNMP-Traps Internal: 0x4000
Link flags : None
CoS queues : 12 supported, 12 maximum usable queues
Current address: d4:04:ff:90:5a:4b, Hardware address:
d4:04:ff:90:5a:4b
Last flapped : 2017-06-01 10:09:32 CEST (01:21:29 ago)
Input rate : 432 bps (0 pps)
Output rate : 8336 bps (11 pps)
Active alarms : None
Active defects : None
Interface transmit statistics: Disabled
Logical interface et-0/0/18.0 (Index 552) (SNMP ifIndex 539)
Flags: SNMP-Traps 0x24024000 Encapsulation: Ethernet-Bridge
Input packets : 464041
Output packets: 209210
Protocol eth-switch, MTU: 1514
Flags: Is-Primary, Trunk-Mode
MTU is same for all et-0/0/x interfaces.
- Adrian
^ permalink raw reply
* Re: [net] vxlan: fix use-after-free on deletion
From: Or Gerlitz @ 2017-06-01 10:17 UTC (permalink / raw)
To: Mark Bloch; +Cc: Jiri Benc, Roopa Prabhu, Linux Netdev List
In-Reply-To: <1496306615-770-1-git-send-email-markb@mellanox.com>
On Thu, Jun 1, 2017 at 11:43 AM, Mark Bloch <markb@mellanox.com> wrote:
> Adding a vxlan interface to a socket isn't symmetrical, while adding
> is done in vxlan_open() the deletion is done in vxlan_dellink().
> This can cause a use-after-free error when we close the vxlan
> interface before deleting it.
>
> We add vxlan_vs_del_dev() to match vxlan_vs_add_dev() and call
> it from vxlan_stop() to match the call from vxlan_open().
>
If you are fixing a specific commit, best to put a proper Fixes that here
> Signed-off-by: Mark Bloch <markb@mellanox.com>
^ permalink raw reply
* Re: [PATCH 04/12] fs: ceph: CURRENT_TIME with ktime_get_real_ts()
From: Arnd Bergmann @ 2017-06-01 10:22 UTC (permalink / raw)
To: Yan, Zheng
Cc: yuchao0-hv44wF8Li93QT0dZR+AlfA, J. Bruce Fields, Chris Mason,
linux-mtd, Deepa Dinamani, Evgeniy Dushistov, Jeff Layton,
ceph-devel, devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
linux-cifs-u79uwXL29TY76Z2rM5mHXA, Paul Moore, y2038 Mailman List,
Ingo Molnar, Steven Rostedt, Drokin, Oleg, John Stultz, Al Viro,
David Sterba, Jaegeuk Kim, Thomas Gleixner, Josef Bacik, gregkh,
samba-technical-w/Ol4Ecudpl8XjKLYN78aQ, Linux Kernel Mailing List,
Eric
In-Reply-To: <CAAM7YAmp=cZKqGHa8UqDnrQLCe+6TKx+7w9SDZv4cW5fr4dfvA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Thu, Jun 1, 2017 at 11:56 AM, Yan, Zheng <ukernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Sat, Apr 8, 2017 at 8:57 AM, Deepa Dinamani <deepa.kernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
>> index 517838b..77204da 100644
>> --- a/drivers/block/rbd.c
>> +++ b/drivers/block/rbd.c
>> @@ -1922,7 +1922,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
>> {
>> struct ceph_osd_request *osd_req = obj_request->osd_req;
>>
>> - osd_req->r_mtime = CURRENT_TIME;
>> + ktime_get_real_ts(&osd_req->r_mtime);
>> osd_req->r_data_offset = obj_request->offset;
>> }
>>
>> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
>> index c681762..1d3fa90 100644
>> --- a/fs/ceph/mds_client.c
>> +++ b/fs/ceph/mds_client.c
>> @@ -1666,6 +1666,7 @@ struct ceph_mds_request *
>> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>> {
>> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
>> + struct timespec ts;
>>
>> if (!req)
>> return ERR_PTR(-ENOMEM);
>> @@ -1684,7 +1685,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
>> init_completion(&req->r_safe_completion);
>> INIT_LIST_HEAD(&req->r_unsafe_item);
>>
>> - req->r_stamp = current_fs_time(mdsc->fsc->sb);
>> + ktime_get_real_ts(&ts);
>> + req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
>
> This change causes our kernel_untar_tar test case to fail (inode's
> ctime goes back). The reason is that there is time drift between the
> time stamps got by ktime_get_real_ts() and current_time(). We need to
> revert this change until current_time() uses ktime_get_real_ts()
> internally.
Hmm, the change was not supposed to have a user-visible effect, so
something has gone wrong, but I don't immediately see how it
relates to what you observe.
ktime_get_real_ts() and current_time() use the same time base, there
is no drift, but there is a difference in resolution, as the latter uses
the time stamp of the last jiffies update, which may be up to one jiffy
(10ms) behind the exact time we put in the request stamps here.
Do you still see problems if you use current_kernel_time() instead of
ktime_get_real_ts()?
Arnd
^ permalink raw reply
* [PATCH 0/5] Add phylib support for MV88X3310 10G phy
From: Russell King - ARM Linux @ 2017-06-01 10:23 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli
Cc: devicetree, Mark Rutland, netdev, Rob Herring
Hi,
This patch series adds support for the Marvell 88x3310 PHY found on
the SolidRun Macchiatobin board.
The first patch introduces a set of generic Clause 45 PHY helpers that
C45 PHY drivers can make use of if they wish.
Patch 2 fixes the aneg restart to be compatible with C45 PHYs - it can
currently only cope with C22 PHYs.
Patch 3 moves the "gen10g" driver into the Clause 45 code, grouping all
core clause 45 code together.
Patch 4 adds the phy_interface_t types for XAUI and 10GBase-KR links.
As 10GBase-KR appears to be compatible with XFI and SFI, XFI and SFI,
I currently see no reason to add XFI and SFI interface modes. There
seems to be vendor code out there using these, but they all alias back
to the same hardware settings.
Patch 5 adds support for the MV88X3310 PHY, which supports both the
copper and fiber interfaces. It should be noted that the MV88X3310
automatically switches its MAC facing interface between 10GBase-KR
and SGMII depending on the negotiated speed. This was discussed with
Florian, and we agreed to update the phy interface mode depending on
the properties of the actual link mode to the PHY.
Documentation/devicetree/bindings/net/ethernet.txt | 2 +
MAINTAINERS | 6 +
drivers/net/phy/Makefile | 4 +-
drivers/net/phy/marvell10g.c | 364 +++++++++++++++++++++
drivers/net/phy/phy-c45.c | 295 +++++++++++++++++
drivers/net/phy/phy.c | 23 +-
drivers/net/phy/phy_device.c | 113 ++-----
include/linux/phy.h | 20 ++
8 files changed, 729 insertions(+), 98 deletions(-)
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH 1/5] net: phy: add 802.3 clause 45 support to phylib
From: Russell King @ 2017-06-01 10:26 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
In-Reply-To: <20170601102327.GF27796@n2100.armlinux.org.uk>
Add generic helpers for 802.3 clause 45 PHYs for >= 10Gbps support.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/Makefile | 2 +-
drivers/net/phy/phy-c45.c | 231 +++++++++++++++++++++++++++++++++++++++++++
drivers/net/phy/phy_device.c | 20 ++--
include/linux/phy.h | 12 +++
4 files changed, 250 insertions(+), 15 deletions(-)
create mode 100644 drivers/net/phy/phy-c45.c
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e36db9a2ba38..19eddf758c88 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,6 +1,6 @@
# Makefile for Linux PHY drivers and MDIO bus drivers
-libphy-y := phy.o phy-core.o phy_device.o
+libphy-y := phy.o phy-c45.o phy-core.o phy_device.o
mdio-bus-y += mdio_bus.o mdio_device.o
ifdef CONFIG_MDIO_DEVICE
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
new file mode 100644
index 000000000000..252e49864215
--- /dev/null
+++ b/drivers/net/phy/phy-c45.c
@@ -0,0 +1,231 @@
+/*
+ * Clause 45 PHY support
+ */
+#include <linux/ethtool.h>
+#include <linux/export.h>
+#include <linux/mdio.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+/**
+ * genphy_c45_setup_forced - configures a forced speed
+ * @phydev: target phy_device struct
+ */
+int genphy_c45_pma_setup_forced(struct phy_device *phydev)
+{
+ int ctrl1, ctrl2, ret;
+
+ /* Half duplex is not supported */
+ if (phydev->duplex != DUPLEX_FULL)
+ return -EINVAL;
+
+ ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
+ if (ctrl1 < 0)
+ return ctrl1;
+
+ ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
+ if (ctrl2 < 0)
+ return ctrl2;
+
+ ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
+ /* PMA/PMD type selection is 1.7.5:0 not 1.7.3:0. See 45.2.1.6.1. */
+ ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
+
+ switch (phydev->speed) {
+ case SPEED_10:
+ ctrl2 |= MDIO_PMA_CTRL2_10BT;
+ break;
+ case SPEED_100:
+ ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
+ ctrl2 |= MDIO_PMA_CTRL2_100BTX;
+ break;
+ case SPEED_1000:
+ ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
+ /* Assume 1000base-T */
+ ctrl2 |= MDIO_PMA_CTRL2_1000BT;
+ break;
+ case SPEED_10000:
+ ctrl1 |= MDIO_CTRL1_SPEED10G;
+ /* Assume 10Gbase-T */
+ ctrl2 |= MDIO_PMA_CTRL2_10GBT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
+ if (ret < 0)
+ return ret;
+
+ return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
+
+/**
+ * genphy_c45_an_disable_aneg - disable auto-negotiation
+ * @phydev: target phy_device struct
+ *
+ * Disable auto-negotiation in the Clause 45 PHY. The link parameters
+ * parameters are controlled through the PMA/PMD MMD registers.
+ *
+ * Returns zero on success, negative errno code on failure.
+ */
+int genphy_c45_an_disable_aneg(struct phy_device *phydev)
+{
+ int val;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+ if (val < 0)
+ return val;
+
+ val &= ~(MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
+
+ return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
+
+/**
+ * genphy_c45_restart_aneg - Enable and restart auto-negotiation
+ * @phydev: target phy_device struct
+ *
+ * This assumes that the auto-negotiation MMD is present.
+ *
+ * Enable and restart auto-negotiation.
+ */
+int genphy_c45_restart_aneg(struct phy_device *phydev)
+{
+ int val;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+ if (val < 0)
+ return val;
+
+ val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
+
+ return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
+
+/**
+ * genphy_c45_aneg_done - return auto-negotiation complete status
+ * @phydev: target phy_device struct
+ *
+ * This assumes that the auto-negotiation MMD is present.
+ *
+ * Reads the status register from the auto-negotiation MMD, returning:
+ * - positive if auto-negotiation is complete
+ * - negative errno code on error
+ * - zero otherwise
+ */
+int genphy_c45_aneg_done(struct phy_device *phydev)
+{
+ int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
+
+ return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
+
+/**
+ * genphy_c45_read_link - read the overall link status from the MMDs
+ * @phydev: target phy_device struct
+ * @mmd_mask: MMDs to read status from
+ *
+ * Read the link status from the specified MMDs, and if they all indicate
+ * that the link is up, return positive. If an error is encountered,
+ * a negative errno will be returned, otherwise zero.
+ */
+int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask)
+{
+ int val, devad;
+ bool link = true;
+
+ while (mmd_mask) {
+ devad = __ffs(mmd_mask);
+ mmd_mask &= ~BIT(devad);
+
+ /* The link state is latched low so that momentary link
+ * drops can be detected. Do not double-read the status
+ * register if the link is down.
+ */
+ val = phy_read_mmd(phydev, devad, MDIO_STAT1);
+ if (val < 0)
+ return val;
+
+ if (!(val & MDIO_STAT1_LSTATUS))
+ link = false;
+ }
+
+ return link;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_read_link);
+
+/**
+ * genphy_c45_read_lpa - read the link partner advertisment and pause
+ * @phydev: target phy_device struct
+ *
+ * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
+ * filling in the link partner advertisment, pause and asym_pause members
+ * in @phydev. This assumes that the auto-negotiation MMD is present, and
+ * the backplane bit (7.48.0) is clear. Clause 45 PHY drivers are expected
+ * to fill in the remainder of the link partner advert from vendor registers.
+ */
+int genphy_c45_read_lpa(struct phy_device *phydev)
+{
+ int val;
+
+ /* Read the link partner's base page advertisment */
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
+ if (val < 0)
+ return val;
+
+ phydev->lp_advertising = mii_lpa_to_ethtool_lpa_t(val);
+ phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
+ phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
+
+ /* Read the link partner's 10G advertisment */
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
+ if (val < 0)
+ return val;
+
+ if (val & MDIO_AN_10GBT_STAT_LP10G)
+ phydev->lp_advertising |= ADVERTISED_10000baseT_Full;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
+
+/**
+ * genphy_c45_read_pma - read link speed etc from PMA
+ * @phydev: target phy_device struct
+ */
+int genphy_c45_read_pma(struct phy_device *phydev)
+{
+ int val;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
+ if (val < 0)
+ return val;
+
+ switch (val & MDIO_CTRL1_SPEEDSEL) {
+ case 0:
+ phydev->speed = SPEED_10;
+ break;
+ case MDIO_PMA_CTRL1_SPEED100:
+ phydev->speed = SPEED_100;
+ break;
+ case MDIO_PMA_CTRL1_SPEED1000:
+ phydev->speed = SPEED_1000;
+ break;
+ case MDIO_CTRL1_SPEED10G:
+ phydev->speed = SPEED_10000;
+ break;
+ default:
+ phydev->speed = SPEED_UNKNOWN;
+ break;
+ }
+
+ phydev->duplex = DUPLEX_FULL;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 1219eeab69d1..040575dba98c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1483,27 +1483,19 @@ EXPORT_SYMBOL(genphy_read_status);
static int gen10g_read_status(struct phy_device *phydev)
{
- int devad, reg;
u32 mmd_mask = phydev->c45_ids.devices_in_package;
-
- phydev->link = 1;
+ int ret;
/* For now just lie and say it's 10G all the time */
phydev->speed = SPEED_10000;
phydev->duplex = DUPLEX_FULL;
- for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) {
- if (!(mmd_mask & 1))
- continue;
+ /* Avoid reading the vendor MMDs */
+ mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
- /* Read twice because link state is latched and a
- * read moves the current state into the register
- */
- phy_read_mmd(phydev, devad, MDIO_STAT1);
- reg = phy_read_mmd(phydev, devad, MDIO_STAT1);
- if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
- phydev->link = 0;
- }
+ ret = genphy_c45_read_link(phydev, mmd_mask);
+
+ phydev->link = ret > 0 ? 1 : 0;
return 0;
}
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e76e4adbc7c7..735ff1f98db3 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -816,6 +816,8 @@ static inline const char *phydev_name(const struct phy_device *phydev)
void phy_attached_print(struct phy_device *phydev, const char *fmt, ...)
__printf(2, 3);
void phy_attached_info(struct phy_device *phydev);
+
+/* Clause 22 PHY */
int genphy_config_init(struct phy_device *phydev);
int genphy_setup_forced(struct phy_device *phydev);
int genphy_restart_aneg(struct phy_device *phydev);
@@ -830,6 +832,16 @@ static inline int genphy_no_soft_reset(struct phy_device *phydev)
{
return 0;
}
+
+/* Clause 45 PHY */
+int genphy_c45_restart_aneg(struct phy_device *phydev);
+int genphy_c45_aneg_done(struct phy_device *phydev);
+int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask);
+int genphy_c45_read_lpa(struct phy_device *phydev);
+int genphy_c45_read_pma(struct phy_device *phydev);
+int genphy_c45_pma_setup_forced(struct phy_device *phydev);
+int genphy_c45_an_disable_aneg(struct phy_device *phydev);
+
void phy_driver_unregister(struct phy_driver *drv);
void phy_drivers_unregister(struct phy_driver *drv, int n);
int phy_driver_register(struct phy_driver *new_driver, struct module *owner);
--
2.7.4
^ permalink raw reply related
* [PATCH 2/5] net: phy: hook up clause 45 autonegotiation restart
From: Russell King @ 2017-06-01 10:26 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
In-Reply-To: <20170601102327.GF27796@n2100.armlinux.org.uk>
genphy_restart_aneg() can only restart autonegotiation on clause 22
PHYs. Add a phy_restart_aneg() function which selects between the
clause 22 and clause 45 restart functionality depending on the PHY
type.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phy.c | 23 +++++++++++++++++++++--
include/linux/phy.h | 1 +
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 82ab8fb82587..25b24789a409 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -149,6 +149,25 @@ static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
return 0;
}
+/**
+ * phy_restart_aneg - restart auto-negotiation
+ * @phydev: target phy_device struct
+ *
+ * Restart the autonegotiation on @phydev. Returns >= 0 on success or
+ * negative errno on error.
+ */
+int phy_restart_aneg(struct phy_device *phydev)
+{
+ int ret;
+
+ if (phydev->is_c45)
+ ret = genphy_c45_restart_aneg(phydev);
+ else
+ ret = genphy_restart_aneg(phydev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_restart_aneg);
/**
* phy_aneg_done - return auto-negotiation status
@@ -1415,7 +1434,7 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
/* Restart autonegotiation so the new modes get sent to the
* link partner.
*/
- ret = genphy_restart_aneg(phydev);
+ ret = phy_restart_aneg(phydev);
if (ret < 0)
return ret;
}
@@ -1474,6 +1493,6 @@ int phy_ethtool_nway_reset(struct net_device *ndev)
if (!phydev->drv)
return -EIO;
- return genphy_restart_aneg(phydev);
+ return phy_restart_aneg(phydev);
}
EXPORT_SYMBOL(phy_ethtool_nway_reset);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 735ff1f98db3..45dfe1b2b003 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -793,6 +793,7 @@ int phy_start_aneg(struct phy_device *phydev);
int phy_aneg_done(struct phy_device *phydev);
int phy_stop_interrupts(struct phy_device *phydev);
+int phy_restart_aneg(struct phy_device *phydev);
static inline int phy_read_status(struct phy_device *phydev)
{
--
2.7.4
^ permalink raw reply related
* [PATCH 4/5] net: phy: add XAUI and 10GBASE-KR PHY connection types
From: Russell King @ 2017-06-01 10:26 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli
Cc: Rob Herring, Mark Rutland, netdev, devicetree
In-Reply-To: <20170601102327.GF27796@n2100.armlinux.org.uk>
XAUI allows XGMII to reach an extended distance by using a XGXS layer at
each end of the MAC to PHY link, operating over four Serdes lanes.
10GBASE-KR is a single lane Serdes backplane ethernet connection method
with autonegotiation on the link. Some PHYs use this to connect to the
ethernet interface at 10G speeds, switching to other connection types
when utilising slower speeds.
10GBASE-KR is also used for XFI and SFI to connect to XFP and SFP fiber
modules.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
Documentation/devicetree/bindings/net/ethernet.txt | 2 ++
include/linux/phy.h | 7 +++++++
2 files changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt
index 3a6916909d90..d4abe9a98109 100644
--- a/Documentation/devicetree/bindings/net/ethernet.txt
+++ b/Documentation/devicetree/bindings/net/ethernet.txt
@@ -32,6 +32,8 @@
* "2000base-x",
* "2500base-x",
* "rxaui"
+ * "xaui"
+ * "10gbase-kr" (10GBASE-KR, XFI, SFI)
- phy-connection-type: the same as "phy-mode" property but described in ePAPR;
- phy-handle: phandle, specifies a reference to a node representing a PHY
device; this property is described in ePAPR and so preferred;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 45dfe1b2b003..45728d0a0d0e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -84,6 +84,9 @@ typedef enum {
PHY_INTERFACE_MODE_1000BASEX,
PHY_INTERFACE_MODE_2500BASEX,
PHY_INTERFACE_MODE_RXAUI,
+ PHY_INTERFACE_MODE_XAUI,
+ /* 10GBASE-KR, XFI, SFI - single lane 10G Serdes */
+ PHY_INTERFACE_MODE_10GKR,
PHY_INTERFACE_MODE_MAX,
} phy_interface_t;
@@ -150,6 +153,10 @@ static inline const char *phy_modes(phy_interface_t interface)
return "2500base-x";
case PHY_INTERFACE_MODE_RXAUI:
return "rxaui";
+ case PHY_INTERFACE_MODE_XAUI:
+ return "xaui";
+ case PHY_INTERFACE_MODE_10GKR:
+ return "10gbase-kr";
default:
return "unknown";
}
--
2.7.4
^ permalink raw reply related
* [PATCH 3/5] net: phy: split out 10G genphy support
From: Russell King @ 2017-06-01 10:26 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
In-Reply-To: <20170601102327.GF27796@n2100.armlinux.org.uk>
Move the old 10G genphy support to sit beside the new clause 45 library
functions, so all the 10G phy code is together.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phy-c45.c | 64 ++++++++++++++++++++++++++
drivers/net/phy/phy_device.c | 105 ++++++++-----------------------------------
2 files changed, 83 insertions(+), 86 deletions(-)
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 252e49864215..ed77b1cb61de 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -229,3 +229,67 @@ int genphy_c45_read_pma(struct phy_device *phydev)
return 0;
}
EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
+
+/* The gen10g_* functions are the old Clause 45 stub */
+
+static int gen10g_config_aneg(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int gen10g_read_status(struct phy_device *phydev)
+{
+ u32 mmd_mask = phydev->c45_ids.devices_in_package;
+ int ret;
+
+ /* For now just lie and say it's 10G all the time */
+ phydev->speed = SPEED_10000;
+ phydev->duplex = DUPLEX_FULL;
+
+ /* Avoid reading the vendor MMDs */
+ mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
+
+ ret = genphy_c45_read_link(phydev, mmd_mask);
+
+ phydev->link = ret > 0 ? 1 : 0;
+
+ return 0;
+}
+
+static int gen10g_soft_reset(struct phy_device *phydev)
+{
+ /* Do nothing for now */
+ return 0;
+}
+
+static int gen10g_config_init(struct phy_device *phydev)
+{
+ /* Temporarily just say we support everything */
+ phydev->supported = SUPPORTED_10000baseT_Full;
+ phydev->advertising = SUPPORTED_10000baseT_Full;
+
+ return 0;
+}
+
+static int gen10g_suspend(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int gen10g_resume(struct phy_device *phydev)
+{
+ return 0;
+}
+
+struct phy_driver genphy_10g_driver = {
+ .phy_id = 0xffffffff,
+ .phy_id_mask = 0xffffffff,
+ .name = "Generic 10G PHY",
+ .soft_reset = gen10g_soft_reset,
+ .config_init = gen10g_config_init,
+ .features = 0,
+ .config_aneg = gen10g_config_aneg,
+ .read_status = gen10g_read_status,
+ .suspend = gen10g_suspend,
+ .resume = gen10g_resume,
+};
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 040575dba98c..cedd1fd91626 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -69,13 +69,8 @@ static void phy_mdio_device_remove(struct mdio_device *mdiodev)
phy_device_remove(phydev);
}
-enum genphy_driver {
- GENPHY_DRV_1G,
- GENPHY_DRV_10G,
- GENPHY_DRV_MAX
-};
-
-static struct phy_driver genphy_driver[GENPHY_DRV_MAX];
+static struct phy_driver genphy_driver;
+extern struct phy_driver genphy_10g_driver;
static LIST_HEAD(phy_fixup_list);
static DEFINE_MUTEX(phy_fixup_lock);
@@ -928,11 +923,9 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
*/
if (!d->driver) {
if (phydev->is_c45)
- d->driver =
- &genphy_driver[GENPHY_DRV_10G].mdiodrv.driver;
+ d->driver = &genphy_10g_driver.mdiodrv.driver;
else
- d->driver =
- &genphy_driver[GENPHY_DRV_1G].mdiodrv.driver;
+ d->driver = &genphy_driver.mdiodrv.driver;
using_genphy = true;
}
@@ -1048,7 +1041,6 @@ void phy_detach(struct phy_device *phydev)
struct net_device *dev = phydev->attached_dev;
struct module *ndev_owner = dev->dev.parent->driver->owner;
struct mii_bus *bus;
- int i;
phydev->attached_dev->phydev = NULL;
phydev->attached_dev = NULL;
@@ -1063,13 +1055,9 @@ void phy_detach(struct phy_device *phydev)
* from the generic driver so that there's a chance a
* real driver could be loaded
*/
- for (i = 0; i < ARRAY_SIZE(genphy_driver); i++) {
- if (phydev->mdio.dev.driver ==
- &genphy_driver[i].mdiodrv.driver) {
- device_release_driver(&phydev->mdio.dev);
- break;
- }
- }
+ if (phydev->mdio.dev.driver == &genphy_10g_driver.mdiodrv.driver ||
+ phydev->mdio.dev.driver == &genphy_driver.mdiodrv.driver)
+ device_release_driver(&phydev->mdio.dev);
/*
* The phydev might go away on the put_device() below, so avoid
@@ -1343,11 +1331,6 @@ int genphy_aneg_done(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_aneg_done);
-static int gen10g_config_aneg(struct phy_device *phydev)
-{
- return 0;
-}
-
/**
* genphy_update_link - update link status in @phydev
* @phydev: target phy_device struct
@@ -1481,25 +1464,6 @@ int genphy_read_status(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_read_status);
-static int gen10g_read_status(struct phy_device *phydev)
-{
- u32 mmd_mask = phydev->c45_ids.devices_in_package;
- int ret;
-
- /* For now just lie and say it's 10G all the time */
- phydev->speed = SPEED_10000;
- phydev->duplex = DUPLEX_FULL;
-
- /* Avoid reading the vendor MMDs */
- mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
-
- ret = genphy_c45_read_link(phydev, mmd_mask);
-
- phydev->link = ret > 0 ? 1 : 0;
-
- return 0;
-}
-
/**
* genphy_soft_reset - software reset the PHY via BMCR_RESET bit
* @phydev: target phy_device struct
@@ -1563,23 +1527,8 @@ int genphy_config_init(struct phy_device *phydev)
return 0;
}
-
-static int gen10g_soft_reset(struct phy_device *phydev)
-{
- /* Do nothing for now */
- return 0;
-}
EXPORT_SYMBOL(genphy_config_init);
-static int gen10g_config_init(struct phy_device *phydev)
-{
- /* Temporarily just say we support everything */
- phydev->supported = SUPPORTED_10000baseT_Full;
- phydev->advertising = SUPPORTED_10000baseT_Full;
-
- return 0;
-}
-
int genphy_suspend(struct phy_device *phydev)
{
int value;
@@ -1595,11 +1544,6 @@ int genphy_suspend(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_suspend);
-static int gen10g_suspend(struct phy_device *phydev)
-{
- return 0;
-}
-
int genphy_resume(struct phy_device *phydev)
{
int value;
@@ -1615,11 +1559,6 @@ int genphy_resume(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_resume);
-static int gen10g_resume(struct phy_device *phydev)
-{
- return 0;
-}
-
static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
{
/* The default values for phydev->supported are provided by the PHY
@@ -1851,8 +1790,7 @@ void phy_drivers_unregister(struct phy_driver *drv, int n)
}
EXPORT_SYMBOL(phy_drivers_unregister);
-static struct phy_driver genphy_driver[] = {
-{
+static struct phy_driver genphy_driver = {
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
.name = "Generic PHY",
@@ -1866,18 +1804,7 @@ static struct phy_driver genphy_driver[] = {
.read_status = genphy_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
-}, {
- .phy_id = 0xffffffff,
- .phy_id_mask = 0xffffffff,
- .name = "Generic 10G PHY",
- .soft_reset = gen10g_soft_reset,
- .config_init = gen10g_config_init,
- .features = 0,
- .config_aneg = gen10g_config_aneg,
- .read_status = gen10g_read_status,
- .suspend = gen10g_suspend,
- .resume = gen10g_resume,
-} };
+};
static int __init phy_init(void)
{
@@ -1887,18 +1814,24 @@ static int __init phy_init(void)
if (rc)
return rc;
- rc = phy_drivers_register(genphy_driver,
- ARRAY_SIZE(genphy_driver), THIS_MODULE);
+ rc = phy_driver_register(&genphy_10g_driver, THIS_MODULE);
if (rc)
+ goto err_10g;
+
+ rc = phy_driver_register(&genphy_driver, THIS_MODULE);
+ if (rc) {
+ phy_driver_unregister(&genphy_10g_driver);
+err_10g:
mdio_bus_exit();
+ }
return rc;
}
static void __exit phy_exit(void)
{
- phy_drivers_unregister(genphy_driver,
- ARRAY_SIZE(genphy_driver));
+ phy_driver_unregister(&genphy_10g_driver);
+ phy_driver_unregister(&genphy_driver);
mdio_bus_exit();
}
--
2.7.4
^ permalink raw reply related
* [PATCH 5/5] net: phy: add Marvell Alaska X 88X3310 10Gigabit PHY support
From: Russell King @ 2017-06-01 10:26 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
In-Reply-To: <20170601102327.GF27796@n2100.armlinux.org.uk>
Add phylib support for the Marvell Alaska X 10 Gigabit PHY (MV88X3310).
This phy is able to operate at 10G, 1G, 100M and 10M speeds, and only
supports Clause 45 accesses.
The PHY appears (based on the vendor IDs) to be two different vendors
IP, with each devad containing several instances.
This PHY driver has only been tested with the RJ45 copper port, fiber
port and a Marvell Armada 8040-based ethernet interface.
It should be noted that to use the full range of speeds, MAC drivers
need to also reconfigure the link mode as per phydev->interface, since
the PHY automatically changes its interface mode depending on the
negotiated speed.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
MAINTAINERS | 6 +
drivers/net/phy/Makefile | 2 +-
drivers/net/phy/marvell10g.c | 364 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 371 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/phy/marvell10g.c
diff --git a/MAINTAINERS b/MAINTAINERS
index f7d568b8f133..9b6c3347d6d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7971,6 +7971,12 @@ S: Maintained
F: drivers/net/ethernet/marvell/mv643xx_eth.*
F: include/linux/mv643xx.h
+MARVELL MV88X3310 PHY DRIVER
+M: Russell King <rmk@armlinux.org.uk>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/phy/marvell10g.c
+
MARVELL MVNETA ETHERNET DRIVER
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
L: netdev@vger.kernel.org
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 19eddf758c88..905990fece28 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -55,7 +55,7 @@ obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
obj-$(CONFIG_LXT_PHY) += lxt.o
-obj-$(CONFIG_MARVELL_PHY) += marvell.o
+obj-$(CONFIG_MARVELL_PHY) += marvell.o marvell10g.o
obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
new file mode 100644
index 000000000000..f43e03dada6a
--- /dev/null
+++ b/drivers/net/phy/marvell10g.c
@@ -0,0 +1,364 @@
+/*
+ * Marvell 10G 88x3310 PHY driver
+ *
+ * Based upon the ID registers, this PHY appears to be a mixture of IPs
+ * from two different companies.
+ *
+ * There appears to be several different data paths through the PHY which
+ * are automatically managed by the PHY. The following has been determined
+ * via observation and experimentation:
+ *
+ * SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
+ * 10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
+ * 10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
+ *
+ * If both the fiber and copper ports are connected, the first to gain
+ * link takes priority and the other port is completely locked out.
+ */
+#include <linux/phy.h>
+
+enum {
+ MV_PCS_BASE_T = 0x0000,
+ MV_PCS_BASE_R = 0x1000,
+ MV_PCS_1000BASEX = 0x2000,
+
+ /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
+ * registers appear to set themselves to the 0x800X when AN is
+ * restarted, but status registers appear readable from either.
+ */
+ MV_AN_CTRL1000 = 0x8000, /* 1000base-T control register */
+ MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */
+
+ /* This register appears to reflect the copper status */
+ MV_AN_RESULT = 0xa016,
+ MV_AN_RESULT_SPD_10 = BIT(12),
+ MV_AN_RESULT_SPD_100 = BIT(13),
+ MV_AN_RESULT_SPD_1000 = BIT(14),
+ MV_AN_RESULT_SPD_10000 = BIT(15),
+};
+
+static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
+ u16 mask, u16 bits)
+{
+ int old, val, ret;
+
+ old = phy_read_mmd(phydev, devad, reg);
+ if (old < 0)
+ return old;
+
+ val = (old & ~mask) | (bits & mask);
+ if (val == old)
+ return 0;
+
+ ret = phy_write_mmd(phydev, devad, reg, val);
+
+ return ret < 0 ? ret : 1;
+}
+
+static int mv3310_probe(struct phy_device *phydev)
+{
+ u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
+
+ if (!phydev->is_c45 ||
+ (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int mv3310_soft_reset(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int mv3310_config_init(struct phy_device *phydev)
+{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
+ u32 mask;
+ int val;
+
+ /* Check that the PHY interface type is compatible */
+ if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
+ phydev->interface != PHY_INTERFACE_MODE_XGMII &&
+ phydev->interface != PHY_INTERFACE_MODE_XAUI &&
+ phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
+ phydev->interface != PHY_INTERFACE_MODE_10GKR)
+ return -ENODEV;
+
+ __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
+ __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
+
+ if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
+ if (val < 0)
+ return val;
+
+ if (val & MDIO_AN_STAT1_ABLE)
+ __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
+ }
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
+ if (val < 0)
+ return val;
+
+ /* Ethtool does not support the WAN mode bits */
+ if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
+ MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
+ MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
+ MDIO_PMA_STAT2_10GBEW))
+ __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
+ if (val & MDIO_PMA_STAT2_10GBSR)
+ __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
+ if (val & MDIO_PMA_STAT2_10GBLR)
+ __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
+ if (val & MDIO_PMA_STAT2_10GBER)
+ __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
+
+ if (val & MDIO_PMA_STAT2_EXTABLE) {
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
+ if (val < 0)
+ return val;
+
+ if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
+ MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
+ __set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
+ if (val & MDIO_PMA_EXTABLE_10GBLRM)
+ __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
+ if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
+ MDIO_PMA_EXTABLE_1000BKX))
+ __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
+ if (val & MDIO_PMA_EXTABLE_10GBLRM)
+ __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+ supported);
+ if (val & MDIO_PMA_EXTABLE_10GBT)
+ __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ supported);
+ if (val & MDIO_PMA_EXTABLE_10GBKX4)
+ __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+ supported);
+ if (val & MDIO_PMA_EXTABLE_10GBKR)
+ __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ supported);
+ if (val & MDIO_PMA_EXTABLE_1000BT)
+ __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ supported);
+ if (val & MDIO_PMA_EXTABLE_1000BKX)
+ __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ supported);
+ if (val & MDIO_PMA_EXTABLE_100BTX)
+ __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ supported);
+ if (val & MDIO_PMA_EXTABLE_10BT)
+ __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+ supported);
+ }
+
+ if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
+ dev_warn(&phydev->mdio.dev,
+ "PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS, supported);
+
+ phydev->supported &= mask;
+ phydev->advertising &= phydev->supported;
+
+ return 0;
+}
+
+static int mv3310_config_aneg(struct phy_device *phydev)
+{
+ bool changed = false;
+ u32 advertising;
+ int ret;
+
+ if (phydev->autoneg == AUTONEG_DISABLE) {
+ ret = genphy_c45_pma_setup_forced(phydev);
+ if (ret < 0)
+ return ret;
+
+ return genphy_c45_an_disable_aneg(phydev);
+ }
+
+ phydev->advertising &= phydev->supported;
+ advertising = phydev->advertising;
+
+ ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_100BASE4 |
+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
+ ethtool_adv_to_mii_adv_t(advertising));
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
+ ADVERTISE_1000FULL | ADVERTISE_1000HALF,
+ ethtool_adv_to_mii_ctrl1000_t(advertising));
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ /* 10G control register */
+ ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADV10G,
+ advertising & ADVERTISED_10000baseT_Full ?
+ MDIO_AN_10GBT_CTRL_ADV10G : 0);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = true;
+
+ if (changed)
+ ret = genphy_c45_restart_aneg(phydev);
+
+ return ret;
+}
+
+static int mv3310_aneg_done(struct phy_device *phydev)
+{
+ int val;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
+ if (val < 0)
+ return val;
+
+ if (val & MDIO_STAT1_LSTATUS)
+ return 1;
+
+ return genphy_c45_aneg_done(phydev);
+}
+
+/* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
+static int mv3310_read_10gbr_status(struct phy_device *phydev)
+{
+ phydev->link = 1;
+ phydev->speed = SPEED_10000;
+ phydev->duplex = DUPLEX_FULL;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
+ phydev->interface = PHY_INTERFACE_MODE_10GKR;
+
+ return 0;
+}
+
+static int mv3310_read_status(struct phy_device *phydev)
+{
+ u32 mmd_mask = phydev->c45_ids.devices_in_package;
+ int val;
+
+ /* The vendor devads do not report link status. Avoid the PHYXS
+ * instance as there are three, and its status depends on the MAC
+ * being appropriately configured for the negotiated speed.
+ */
+ mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) |
+ BIT(MDIO_MMD_PHYXS));
+
+ phydev->speed = SPEED_UNKNOWN;
+ phydev->duplex = DUPLEX_UNKNOWN;
+ phydev->lp_advertising = 0;
+ phydev->link = 0;
+ phydev->pause = 0;
+ phydev->asym_pause = 0;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
+ if (val < 0)
+ return val;
+
+ if (val & MDIO_STAT1_LSTATUS)
+ return mv3310_read_10gbr_status(phydev);
+
+ val = genphy_c45_read_link(phydev, mmd_mask);
+ if (val < 0)
+ return val;
+
+ phydev->link = val > 0 ? 1 : 0;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
+ if (val < 0)
+ return val;
+
+ if (val & MDIO_AN_STAT1_COMPLETE) {
+ val = genphy_c45_read_lpa(phydev);
+ if (val < 0)
+ return val;
+
+ /* Read the link partner's 1G advertisment */
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
+ if (val < 0)
+ return val;
+
+ phydev->lp_advertising |= mii_stat1000_to_ethtool_lpa_t(val);
+
+ if (phydev->autoneg == AUTONEG_ENABLE) {
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_RESULT);
+ if (val < 0)
+ return val;
+
+ if (val & MV_AN_RESULT_SPD_10000)
+ phydev->speed = SPEED_10000;
+ else if (val & MV_AN_RESULT_SPD_1000)
+ phydev->speed = SPEED_1000;
+ else if (val & MV_AN_RESULT_SPD_100)
+ phydev->speed = SPEED_100;
+ else if (val & MV_AN_RESULT_SPD_10)
+ phydev->speed = SPEED_10;
+
+ phydev->duplex = DUPLEX_FULL;
+ }
+ }
+
+ if (phydev->autoneg != AUTONEG_ENABLE) {
+ val = genphy_c45_read_pma(phydev);
+ if (val < 0)
+ return val;
+ }
+
+ if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
+ phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
+ /* The PHY automatically switches its serdes interface (and
+ * active PHYXS instance) between Cisco SGMII and 10GBase-KR
+ * modes according to the speed. Florian suggests setting
+ * phydev->interface to communicate this to the MAC. Only do
+ * this if we are already in either SGMII or 10GBase-KR mode.
+ */
+ if (phydev->speed == SPEED_10000)
+ phydev->interface = PHY_INTERFACE_MODE_10GKR;
+ else if (phydev->speed >= SPEED_10 &&
+ phydev->speed < SPEED_10000)
+ phydev->interface = PHY_INTERFACE_MODE_SGMII;
+ }
+
+ return 0;
+}
+
+static struct phy_driver mv3310_drivers[] = {
+ {
+ .phy_id = 0x002b09aa,
+ .phy_id_mask = 0xffffffff,
+ .name = "mv88x3310",
+ .features = SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_TP |
+ SUPPORTED_FIBRE |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_Backplane,
+ .probe = mv3310_probe,
+ .soft_reset = mv3310_soft_reset,
+ .config_init = mv3310_config_init,
+ .config_aneg = mv3310_config_aneg,
+ .aneg_done = mv3310_aneg_done,
+ .read_status = mv3310_read_status,
+ },
+};
+
+module_phy_driver(mv3310_drivers);
+
+static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
+ { 0x002b09aa, 0xffffffff },
+ { },
+};
+MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
+MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
+MODULE_LICENSE("GPL");
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next 2/3] udp: avoid a cache miss on dequeue
From: Paolo Abeni @ 2017-06-01 10:39 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, David S. Miller, Eric Dumazet
In-Reply-To: <1496250043.27480.6.camel@edumazet-glaptop3.roam.corp.google.com>
On Wed, 2017-05-31 at 10:00 -0700, Eric Dumazet wrote:
> On Mon, 2017-05-29 at 17:27 +0200, Paolo Abeni wrote:
> > Since UDP no more uses sk->destructor, we can clear completely
> > the skb head state before enqueuing.
>
> ...
>
> > @@ -1739,6 +1740,9 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
> > sk_mark_napi_id_once(sk, skb);
> > }
> >
> > + /* drop all pending head states; dst, nf and sk are dropped by caller */
> > + secpath_reset(skb);
> > +
>
> I wonder if using skb_release_head_state() would be more appropriate ?
>
> Surely more descriptive and probably not more expensive since all
> cache lines should be already hot at this point.
Thank you for reviewing this.
I would prefer not adding more code to the core, but I think we would
need something new, like:
skb_reset_head_state()
{
skb_dst_drop(skb);
secpath_reset(skb);
nf_reset(skb);
skb_orphan(skb);
}
because elsewhere the skb could be in inconsistent state: skb->sp !=
NULL but with its refcount is already decremented. WDYT?
Paolo
^ permalink raw reply
* Re: [PATCH net-next] ppp: remove unnecessary bh disable in xmit path
From: Guillaume Nault @ 2017-06-01 10:43 UTC (permalink / raw)
To: gfree.wind; +Cc: paulus, linux-ppp, netdev
In-Reply-To: <1496311119-59204-1-git-send-email-gfree.wind@vip.163.com>
On Thu, Jun 01, 2017 at 05:58:39PM +0800, gfree.wind@vip.163.com wrote:
> From: Gao Feng <gfree.wind@vip.163.com>
>
> Since the commit 55454a565836 ("ppp: avoid dealock on recursive xmit"),
> the PPP xmit path is protected by wrapper functions which disable the
> bh already. So it is unnecessary to disable the bh again in the real
> xmit path.
>
Thanks!
Acked-by: Guillaume Nault <g.nault@alphalink.fr>
^ permalink raw reply
* Re: [PATCH net-next 3/3] udp: try to avoid 2 cache miss on dequeue
From: Paolo Abeni @ 2017-06-01 10:46 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, David S. Miller, Eric Dumazet
In-Reply-To: <1496250276.27480.9.camel@edumazet-glaptop3.roam.corp.google.com>
On Wed, 2017-05-31 at 10:04 -0700, Eric Dumazet wrote:
> On Mon, 2017-05-29 at 17:27 +0200, Paolo Abeni wrote:
> > when udp_recvmsg() is executed, on x86_64 and other archs, most skb
> > fields are on cold cachelines.
> > If the skb are linear and the kernel don't need to compute the udp
> > csum, only a handful of skb fields are required by udp_recvmsg().
> > Since we already use skb->dev_scratch to cache hot data, and
> > there are 32 bits unused on 64 bit archs, use such field to cache
> > as much data as we can, and try to prefetch on dequeue the relevant
> > fields that are left out.
> >
> > This can save up to 2 cache miss per packet.
>
> okay ;)
>
> >
> > Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> > ---
> > net/ipv4/udp.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++------
> > 1 file changed, 103 insertions(+), 11 deletions(-)
> >
> > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> > index 53fa48d..616132e 100644
> > --- a/net/ipv4/udp.c
> > +++ b/net/ipv4/udp.c
> > @@ -1163,6 +1163,83 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
> > return ret;
> > }
> >
> > +/* Copy as much information as possible into skb->dev_scratch to avoid
> > + * possibly multiple cache miss on dequeue();
> > + */
> > +#if BITS_PER_LONG == 64
> > +
> > +/* we can store multiple info here: truesize, len and the bit needed to
> > + * compute skb_csum_unnecessary will be on cold cache lines at recvmsg
> > + * time.
> > + * skb->len can be stored on 16 bits since the udp header has been already
> > + * validated and pulled.
> > + */
> > +struct udp_dev_scratch {
> > + __u32 truesize;
> > + __u16 len;
> > + __u16 is_linear:1;
> > + __u16 csum_unnecessary:1;
>
> What about
> u32 truesize;
> u16 len;
> bool is_linear;
> bool csum_unnecessary;
>
> I do not believe the __ prefix is necessary for a local structure (not
> uapi)
>
> Also a plain bool or u8 is faster than a bit field (shorter
> instructions)
Thank you! I like the above! I'll go for 'bool' usage in v2,
Paolo
p.s. I used the bitfield because I initially had an additional, very
ugly, patch saving another cache miss and requiring one more bit there,
but said patch hurted so much the sight that I had to drop it.
^ permalink raw reply
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