* Re: [PATCH v2 net-next 2/6] vlan: add __vlan_find_dev_next()
From: Veaceslav Falico @ 2013-08-14 15:28 UTC (permalink / raw)
To: Nikolay Aleksandrov; +Cc: netdev, Patrick McHardy, David S. Miller
In-Reply-To: <5204CD73.9010309@redhat.com>
On Fri, Aug 09, 2013 at 01:07:31PM +0200, Nikolay Aleksandrov wrote:
...snip...
>We already discussed privately my comments about this new function, I'll leave
>them here just for the sake of having them documented:
As an almost top-posting - I'm currently on my vacation, so just a few
comments, without real code/patches. I'll come up with v3 at the next week,
hopefully.
>My proposition is to drop these changes altogether (the new function, and the
>vlan.h macro change) and instead add something like the following (I haven't
>tested it, it's only to illustrate the idea) in if_vlan.h so it'll be accessible
>to everyone:
>
>Version 1 (circular so you can simplify the bonding ALB code, I haven't left
>spaces because of auto-wrapping):
>
>#define dev_for_each_vlan_from(dev, vlandev, proto, from, i)
> for (i=from+1, vlandev=__vlan_find_dev_deep(dev, proto, from); \
> i!=from; \
> i=(i+1)%VLAN_N_VID, vlandev=__vlan_find_dev_deep(dev, proto, i)) \
> if (vlandev)
>
>#define dev_for_each_vlan(dev, vlandev, proto, i)
> dev_for_each_vlan_from(dev, vlandev, proto, 0, i)
I like this idea, however it's an overkill in some places (and calling
8k times __vlan_find_dev_deep()->rcu_dereference, verify for vlan_info,
re-call itself 8k times if it's really a slave etc... not really good).
That was one of the main thoughts when I've chosen the other way -
while (vlan = vlan_next(vlan))
They're also quite ugly (huge for, and an if () inside of a nested define)
- but that's more an IMO.
But, again, I like the dev_for_each_vlan() idea, and will look at it again,
trying to omit the __vlan_find_dev_deep() somehow and without that
monstrous for() :).
>
>Version 2 is the same but a little shorter, without the circular part.
>This way you reuse the already provided function __vlan_find_dev_deep and the
>churn is smaller, also __vlan_find_dev_deep takes care of the master issue (that
>is if dev doesn't have a vlan_info, then its master's vlan_info will be used).
Great ideas, thank you.
>Also the code will look much nicer IMO changing this:
>while ((vlan_dev = __vlan_find_dev_next))
>
>to
>
>dev_for_each_vlan(dev, vlan_dev, proto, i)
Yep, I agree, dev_for_each_vlan() looks a lot more readable. Maybe the
proto and i args can also be dropped somehow, I'll take a look...
>
>There're also 2 nice side-effects, first you'll only walk over 4096 entries (for
>the specified vlan proto only)
Not a big one, tbh, cause the current code looks for at most
vlan_id..8192(+0..vlan_id), so 8192. But the proto is indeed a good
side-effect. Another point - we're not working with QinQ at all...
>and the bonding ALB code will simplify from the
>ambiguous looking:
> vlan_id = bond->alb_info.current_alb_vlan;
> vlan_dev = __vlan_find_dev_deep(bond->dev,
> htons(ETH_P_8021Q),
> vlan_id);
>
> /* search for the next one, if not found - for any */
> if (vlan_dev)
> vlan_dev = __vlan_find_dev_next(bond->dev,
> vlan_dev);
> if (!vlan_dev)
> vlan_dev = __vlan_find_dev_next(bond->dev,
> NULL);
>
> if (vlan_dev) {
> vlan_id = vlan_dev_vlan_id(vlan_dev);
> bond->alb_info.current_alb_vlan = vlan_id;
> } else {
> bond->alb_info.current_alb_vlan = 0;
> rcu_read_unlock();
> kfree_skb(skb);
> continue;
> }
>
>to something like (again untested, sorry for the style - line wrapping):
Yep, that's why I really like the idea with dev_for_each_vlan(), with one
minor comment (which is fixable, I guess).
>
> vlan_id = bond->alb_info.current_alb_vlan+1;
> /* since from here is current+1, if there aren't any
> * vlans up to current, it'll get current again if it's
> * available
> */
> dev_for_each_vlan_from(bond->dev, vlan_dev, htons(ETH_P_8021Q), vlan_id, i)
> break;
^^^^^ THIS. It makes a big "WHAT?" in my head. :)
>
> if (vlan_dev) {
> vlan_id = vlan_dev_vlan_id(vlan_dev);
> bond->alb_info.current_alb_vlan = vlan_id;
> } else {
> bond->alb_info.current_alb_vlan = 0;
> rcu_read_unlock();
> kfree_skb(skb);
> continue;
> }
>
>Cheers,
> Nik
Thanks a lot for the feedback, really appreciated :).
^ permalink raw reply
* Re: Configuring and using RIPngd
From: Phil Oester @ 2013-08-14 15:24 UTC (permalink / raw)
To: Ale Lampro; +Cc: netdev
In-Reply-To: <CAABrkZnM90XTS1jZt-ZMDZTAG5mFeu2T0_++K+3Xxx8USQa6jQ@mail.gmail.com>
On Wed, Aug 14, 2013 at 12:02:35PM +0200, Ale Lampro wrote:
> Hi,
>
> I am new to the list and I am trying to achieve something that I think
> should be relatively easy with RIPngd and Quagga, but I am new to all
> this so I have some issues.
Best to ask this question on the Quagga mailing list.
Phil
^ permalink raw reply
* Re: question about netif_rx
From: Julia Lawall @ 2013-08-14 15:18 UTC (permalink / raw)
To: Rami Rosen
Cc: Francois Romieu, David Shwatrz, Julia Lawall, grant.likely,
rob.herring, Netdev, linux-kernel@vger.kernel.org, devicetree
In-Reply-To: <CAKoUAr==Ex=XAJe4=4R+BY5QaNXKMjM4EsHYbppbXOyROi2NAw@mail.gmail.com>
On Wed, 14 Aug 2013, Rami Rosen wrote:
> Hi,
> BTW, this is not the only NAPI issue here. When looking into cleanup
> of resources in this driver, a call to netif_napi_del() is missing
> (though there is a call to napi_disable(), which is not enough for
> proper cleanup).
Actually, netif_napi_del seems to be quite underused. At least
approximately, I would assume that every file that uses netif_napi_add
should use netif_napi_del at least once, and possible more times. But I
find 118 .c files that use netif_napi_add, and only 35 that use
netif_napi_del.
Are there some cases where it might not be needed?
julia
^ permalink raw reply
* Re: [PATCH stable] ipv6: restrict neighbor entry creation to output flow
From: Hannes Frederic Sowa @ 2013-08-14 15:00 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: netdev, jiri, dbanerje, yoshfuji, davem
In-Reply-To: <abab9dc5af4b61da70672b99ad80175b94b4ec68.1376488215.git.mleitner@redhat.com>
On Wed, Aug 14, 2013 at 10:53:27AM -0300, Marcelo Ricardo Leitner wrote:
> This patch is based on 3.2.y branch, the one used by reported. Please let me
> know if it should be different. Thanks.
>
> ---8<---
>
> Commit 0d6a77079c475033cb622c07c5a880b392ef664e introduced a regression on
> which routes to local delivery would not work anymore. Like this:
>
> $ ip -6 route add local 2001::/64 dev lo
> $ ping6 -c1 2001::9
> PING 2001::9(2001::9) 56 data bytes
> ping: sendmsg: Invalid argument
>
> As this is a local delivery, that commit would not allow the creation of a
> neighbor entry and thus the packet cannot be sent.
>
> But as TPROXY scenario actually needs to avoid the neighbor entry creation only
> for input flow, this patch now limits previous patch to input flow, keeping
> output as before that patch.
>
> Reported-by: Debabrata Banerjee <dbavatar@gmail.com>
> Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
> CC: Hannes Frederic Sowa <hannes@stressinduktion.org>
Looks good, thanks Marcelo!
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
David, this patch is for all stable kernels except the 3.10 series.
It does not apply cleanly throughout the whole longterm kernels but the
changes should not be too difficult to adapt. Do you take care of this
or can we do something to ease this process?
Thanks!
^ permalink raw reply
* Re: [PATCH] phy: micrel: Add definitions for common Micrel PHY registers
From: Dinh Nguyen @ 2013-08-14 14:58 UTC (permalink / raw)
To: Shawn Guo
Cc: David Miller, dinh.linux, nicolas.ferre, linux, plagnioj, netdev,
linux-arm-kernel
In-Reply-To: <20130814084508.GD31141@S2101-09.ap.freescale.net>
On Wed, 2013-08-14 at 16:45 +0800, Shawn Guo wrote:
> On Wed, Aug 14, 2013 at 12:51:54AM -0700, David Miller wrote:
> > From: Shawn Guo <shawn.guo@linaro.org>
> > Date: Wed, 14 Aug 2013 13:17:46 +0800
> >
> > > On Tue, Aug 13, 2013 at 09:58:59AM -0500, dinguyen@altera.com wrote:
> > >> From: Dinh Nguyen <dinguyen@altera.com>
> > >>
> > >> Hi Shawn,
> > >>
> > >> Can you apply this patch to your tree for 3.12?
> > >>
> > >
> > > I need David's Ack to send the patch through IMX tree.
> >
> > Acked-by: David S. Miller <davem@davemloft.net>
>
> Okay, applied with David's ACK.
Thanks,
Dinh
>
> Shawn
>
^ permalink raw reply
* [PATCH] net/mlx5_core: Support MANAGE_PAGES and QUERY_PAGES firmware command changes
From: Moshe Lazer @ 2013-08-14 14:46 UTC (permalink / raw)
To: davem; +Cc: netdev, roland, ogerlitz, Moshe Lazer, Eli Cohen
In the previous QUERY_PAGES command version we used one command to get the
required amount of boot, init and post init pages. The new version uses the
op_mod field to specify whether the query is for the required amount of boot,
init or post init pages. In addition the output field size for the required
amount of pages increased from 16 to 32 bits.
In MANAGE_PAGES command the input_num_entries and output_num_entries fields
sizes changed from 16 to 32 bits and the PAS tables offset changed to 0x10.
In the pages request event the num_pages field also changed to 32 bits.
In the HCA-capabilities-layout the size and location of max_qp_mcg field has
been changed to support 24 bits.
This patch isn't compatible with firmware versions < 5; however, it turns out that the
first GA firmware we will publish will not support previous versions so this should be OK.
Signed-off-by: Moshe Lazer <moshel@mellanox.com>
Signed-off-by: Eli Cohen <eli@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/fw.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/pagealloc.c | 58 +++++++++-----------
include/linux/mlx5/device.h | 22 ++++----
include/linux/mlx5/driver.h | 4 +-
6 files changed, 41 insertions(+), 49 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index c571de8..5472cbd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -46,7 +46,7 @@
#include "mlx5_core.h"
enum {
- CMD_IF_REV = 4,
+ CMD_IF_REV = 5,
};
enum {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index c02cbcf..443cc4d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -268,7 +268,7 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
case MLX5_EVENT_TYPE_PAGE_REQUEST:
{
u16 func_id = be16_to_cpu(eqe->data.req_pages.func_id);
- s16 npages = be16_to_cpu(eqe->data.req_pages.num_pages);
+ s32 npages = be32_to_cpu(eqe->data.req_pages.num_pages);
mlx5_core_dbg(dev, "page request for func 0x%x, napges %d\n", func_id, npages);
mlx5_core_req_pages_handler(dev, func_id, npages);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
index 72a5222..f012658 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
@@ -113,7 +113,7 @@ int mlx5_cmd_query_hca_cap(struct mlx5_core_dev *dev,
caps->log_max_srq = out->hca_cap.log_max_srqs & 0x1f;
caps->local_ca_ack_delay = out->hca_cap.local_ca_ack_delay & 0x1f;
caps->log_max_mcg = out->hca_cap.log_max_mcg;
- caps->max_qp_mcg = be16_to_cpu(out->hca_cap.max_qp_mcg);
+ caps->max_qp_mcg = be32_to_cpu(out->hca_cap.max_qp_mcg) & 0xffffff;
caps->max_ra_res_qp = 1 << (out->hca_cap.log_max_ra_res_qp & 0x3f);
caps->max_ra_req_qp = 1 << (out->hca_cap.log_max_ra_req_qp & 0x3f);
caps->max_srq_wqes = 1 << out->hca_cap.log_max_srq_sz;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
index 4a3e137..3a2408d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -43,10 +43,16 @@ enum {
MLX5_PAGES_TAKE = 2
};
+enum {
+ MLX5_BOOT_PAGES = 1,
+ MLX5_INIT_PAGES = 2,
+ MLX5_POST_INIT_PAGES = 3
+};
+
struct mlx5_pages_req {
struct mlx5_core_dev *dev;
u32 func_id;
- s16 npages;
+ s32 npages;
struct work_struct work;
};
@@ -64,27 +70,23 @@ struct mlx5_query_pages_inbox {
struct mlx5_query_pages_outbox {
struct mlx5_outbox_hdr hdr;
- __be16 num_boot_pages;
+ __be16 rsvd;
__be16 func_id;
- __be16 init_pages;
- __be16 num_pages;
+ __be32 num_pages;
};
struct mlx5_manage_pages_inbox {
struct mlx5_inbox_hdr hdr;
- __be16 rsvd0;
+ __be16 rsvd;
__be16 func_id;
- __be16 rsvd1;
- __be16 num_entries;
- u8 rsvd2[16];
+ __be32 num_entries;
__be64 pas[0];
};
struct mlx5_manage_pages_outbox {
struct mlx5_outbox_hdr hdr;
- u8 rsvd0[2];
- __be16 num_entries;
- u8 rsvd1[20];
+ __be32 num_entries;
+ u8 rsvd[4];
__be64 pas[0];
};
@@ -146,7 +148,7 @@ static struct page *remove_page(struct mlx5_core_dev *dev, u64 addr)
}
static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
- s16 *pages, s16 *init_pages, u16 *boot_pages)
+ s32 *npages, int boot)
{
struct mlx5_query_pages_inbox in;
struct mlx5_query_pages_outbox out;
@@ -155,6 +157,8 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
memset(&in, 0, sizeof(in));
memset(&out, 0, sizeof(out));
in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_PAGES);
+ in.hdr.opmod = boot ? cpu_to_be16(MLX5_BOOT_PAGES) : cpu_to_be16(MLX5_INIT_PAGES);
+
err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
if (err)
return err;
@@ -162,15 +166,7 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
if (out.hdr.status)
return mlx5_cmd_status_to_err(&out.hdr);
- if (pages)
- *pages = be16_to_cpu(out.num_pages);
-
- if (init_pages)
- *init_pages = be16_to_cpu(out.init_pages);
-
- if (boot_pages)
- *boot_pages = be16_to_cpu(out.num_boot_pages);
-
+ *npages = be32_to_cpu(out.num_pages);
*func_id = be16_to_cpu(out.func_id);
return err;
@@ -224,7 +220,7 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES);
in->hdr.opmod = cpu_to_be16(MLX5_PAGES_GIVE);
in->func_id = cpu_to_be16(func_id);
- in->num_entries = cpu_to_be16(npages);
+ in->num_entries = cpu_to_be32(npages);
err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out));
mlx5_core_dbg(dev, "err %d\n", err);
if (err) {
@@ -292,7 +288,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES);
in.hdr.opmod = cpu_to_be16(MLX5_PAGES_TAKE);
in.func_id = cpu_to_be16(func_id);
- in.num_entries = cpu_to_be16(npages);
+ in.num_entries = cpu_to_be32(npages);
mlx5_core_dbg(dev, "npages %d, outlen %d\n", npages, outlen);
err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen);
if (err) {
@@ -306,7 +302,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages,
goto out_free;
}
- num_claimed = be16_to_cpu(out->num_entries);
+ num_claimed = be32_to_cpu(out->num_entries);
if (nclaimed)
*nclaimed = num_claimed;
@@ -345,7 +341,7 @@ static void pages_work_handler(struct work_struct *work)
}
void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
- s16 npages)
+ s32 npages)
{
struct mlx5_pages_req *req;
@@ -364,20 +360,18 @@ void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot)
{
- u16 uninitialized_var(boot_pages);
- s16 uninitialized_var(init_pages);
u16 uninitialized_var(func_id);
+ s32 uninitialized_var(npages);
int err;
- err = mlx5_cmd_query_pages(dev, &func_id, NULL, &init_pages,
- &boot_pages);
+ err = mlx5_cmd_query_pages(dev, &func_id, &npages, boot);
if (err)
return err;
+ mlx5_core_dbg(dev, "requested %d %s pages for func_id 0x%x\n",
+ npages, boot ? "boot" : "init", func_id);
- mlx5_core_dbg(dev, "requested %d init pages and %d boot pages for func_id 0x%x\n",
- init_pages, boot_pages, func_id);
- return give_pages(dev, func_id, boot ? boot_pages : init_pages, 0);
+ return give_pages(dev, func_id, npages, 0);
}
static int optimal_reclaimed_pages(void)
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 737685e..68029b3 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -309,21 +309,20 @@ struct mlx5_hca_cap {
__be16 max_desc_sz_rq;
u8 rsvd21[2];
__be16 max_desc_sz_sq_dc;
- u8 rsvd22[4];
- __be16 max_qp_mcg;
- u8 rsvd23;
+ __be32 max_qp_mcg;
+ u8 rsvd22[3];
u8 log_max_mcg;
- u8 rsvd24;
+ u8 rsvd23;
u8 log_max_pd;
- u8 rsvd25;
+ u8 rsvd24;
u8 log_max_xrcd;
- u8 rsvd26[42];
+ u8 rsvd25[42];
__be16 log_uar_page_sz;
- u8 rsvd27[28];
+ u8 rsvd26[28];
u8 log_msx_atomic_size_qp;
- u8 rsvd28[2];
+ u8 rsvd27[2];
u8 log_msx_atomic_size_dc;
- u8 rsvd29[76];
+ u8 rsvd28[76];
};
@@ -472,9 +471,8 @@ struct mlx5_eqe_cmd {
struct mlx5_eqe_page_req {
u8 rsvd0[2];
__be16 func_id;
- u8 rsvd1[2];
- __be16 num_pages;
- __be32 rsvd2[5];
+ __be32 num_pages;
+ __be32 rsvd1[5];
};
union ev_data {
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 2aa258b..e7f552c 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -358,7 +358,7 @@ struct mlx5_caps {
u32 reserved_lkey;
u8 local_ca_ack_delay;
u8 log_max_mcg;
- u16 max_qp_mcg;
+ u32 max_qp_mcg;
int min_page_sz;
};
@@ -691,7 +691,7 @@ void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev);
int mlx5_pagealloc_start(struct mlx5_core_dev *dev);
void mlx5_pagealloc_stop(struct mlx5_core_dev *dev);
void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
- s16 npages);
+ s32 npages);
int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot);
int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev);
void mlx5_register_debugfs(void);
--
1.7.1
^ permalink raw reply related
* [PATCH] drivers/net/ethernet/via/via-velocity.c: update napi implementation
From: Julia Lawall @ 2013-08-14 14:26 UTC (permalink / raw)
To: Francois Romieu, roszenrami, dshwatrz
Cc: kernel-janitors, netdev, linux-kernel, grant.likely, rob.herring
From: Julia Lawall <Julia.Lawall@lip6.fr>
Drivers supporting NAPI should use a NAPI-specific function for receiving
packets. Hence netif_rx is changed to netif_receive_skb.
Furthermore netif_napi_del should be used in the probe and remove function
to clean up the NAPI resource information.
Thanks to Francois Romieu, David Shwatrz and Rami Rosen for their help on
this patch.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
I still don't understand the reason for choosing netif_receive_skb,
specifically. This patch is not tested.
drivers/net/ethernet/via/via-velocity.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index ef77631..d022bf9 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -2100,7 +2100,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
}
- netif_rx(skb);
+ netif_receive_skb(skb);
stats->rx_bytes += pkt_len;
stats->rx_packets++;
@@ -2904,6 +2904,7 @@ out:
return ret;
err_iounmap:
+ netif_napi_del(&vptr->napi);
iounmap(regs);
err_free_dev:
free_netdev(netdev);
@@ -2924,6 +2925,7 @@ static int velocity_remove(struct device *dev)
struct velocity_info *vptr = netdev_priv(netdev);
unregister_netdev(netdev);
+ netif_napi_del(&vptr->napi);
iounmap(vptr->mac_regs);
free_netdev(netdev);
velocity_nics--;
^ permalink raw reply related
* Re: Query: Regarding 8211E Phy module support in drivers/net/phy
From: Giuseppe CAVALLARO @ 2013-08-14 14:07 UTC (permalink / raw)
To: Sharma Bhupesh-B45370; +Cc: 'netdev@vger.kernel.org'
In-Reply-To: <A1A6EA40F8503D48BB002B42BD65974E0A0E6C8C@039-SN2MPN1-012.039d.mgd.msft.net>
On 8/2/2013 8:50 PM, Sharma Bhupesh-B45370 wrote:
> Hi Peppe,
>
> This regarding the patch prepared by you for adding RTL8211E support in
> drivers/net/phy/realtek.c
>
> commit ef3d90491a15f0d5cf1ec39a38a45dac6968fb2a
> Author: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
> Date: Wed Jan 23 00:30:03 2013 +0000
>
> net: phy: realtek: add rtl8211e driver
>
> This patch adds the minimal driver to manage the
> Realtek RTL8211E 10/100/1000 Transceivers.
>
> I see a macro specific to 8211E:
> +#define RTL8211E_INER_LINK_STAT 0x10
>
> I was having a look at the RTL8211E(G) datasheet and could see
> the following bit positions for INER register (Address 0x12):
>
> [7:1] as Reserved
> [0] as Jabber Interrupt
>
> If I am not wrong a value 0x10 written to the INER register tries to set bit [4] which seems
> Reserved.
Hello Sharma
you are right RTL8211E_INER_LINK_STAT should be 0x400
I will test it again (just to find the hw) and prepare/send a new patch.
Many thanks
peppe
>
> Or am I missing something here.
> Please let me know your views on the same.
>
> Thanks,
> Bhupesh
>
>
>
^ permalink raw reply
* Re: [PATCH] macvtap: Correctly set tap features when IFF_VNET_HDR is disabled.
From: Vlad Yasevich @ 2013-08-14 14:07 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: netdev
In-Reply-To: <20130814121043.GH5430@redhat.com>
On 08/14/2013 08:10 AM, Michael S. Tsirkin wrote:
> On Tue, Aug 13, 2013 at 01:55:58PM -0400, Vlad Yasevich wrote:
>> When the user turns off IFF_VNET_HDR flag, attempts to change
>> offload features via TUNSETOFFLOAD do not work. This could cause
>> GSO packets to be delivered to the user when the user is
>> not prepared to handle them.
>>
>> To solve, allow processing of TUNSETOFFLOAD when IFF_VNET_HDR is
>> disabled and make sure to turn off all offloads in this case.
>> Also, when IFF_VNET_HDR is disabled, run throught the offload change
>> as well to make sure that the functionality is not dependent on
>> the order of the ioclt() calls.
>>
>> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
>
> Hmm, this seems to make it even messier.
> So
> set TUNSETOFFLOAD
> clear IFF_VNET_HDR
> set IFF_VNET_HDR
>
> offloads are now clear?
>
> I'm also not sure userspace that sets offloads but clears
> vnet hdr knows what it's doing.
>
> How about we fail attempts to clear vnet hdr
> unless offloads are disabled?
>
OK. That makes it simpler...
-vlad
>
>
>
>> ---
>> drivers/net/macvtap.c | 27 +++++++++++++++++++--------
>> 1 file changed, 19 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
>> index a98fb0e..076b9e7 100644
>> --- a/drivers/net/macvtap.c
>> +++ b/drivers/net/macvtap.c
>> @@ -1019,6 +1019,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
>> struct macvlan_dev *vlan;
>> netdev_features_t features;
>> netdev_features_t feature_mask = 0;
>> + netdev_features_t tap_mask = TUN_OFFLOADS;
>>
>> vlan = rtnl_dereference(q->vlan);
>> if (!vlan)
>> @@ -1026,7 +1027,12 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
>>
>> features = vlan->dev->features;
>>
>> - if (arg & TUN_F_CSUM) {
>> + if (!(q->flags & IFF_VNET_HDR)) {
>> + /* Turn off all checsum offloading also if user does
>> + * not user vnet_hdr.
>
> Does not set?
>
>> + */
>> + tap_mask |= NETIF_F_ALL_CSUM;
>> + } else if (arg & TUN_F_CSUM) {
>> feature_mask = NETIF_F_HW_CSUM;
>>
>> if (arg & (TUN_F_TSO4 | TUN_F_TSO6)) {
>> @@ -1058,8 +1064,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
>> /* tap_features are the same as features on tun/tap and
>> * reflect user expectations.
>> */
>> - vlan->tap_features = vlan->dev->features &
>> - (feature_mask | ~TUN_OFFLOADS);
>> + vlan->tap_features = vlan->dev->features & (feature_mask | ~tap_mask);
>> vlan->set_features = features;
>> netdev_update_features(vlan->dev);
>>
>> @@ -1092,8 +1097,18 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
>> if ((u & ~(IFF_VNET_HDR | IFF_MULTI_QUEUE)) !=
>> (IFF_NO_PI | IFF_TAP))
>> ret = -EINVAL;
>> - else
>> + else {
>> + if ((q->flags ^ u) & IFF_VNET_HDR) {
>> + /* vnet_hdr support impacts the offloads,
>> + * so we need to run throught the offload
>
> throught ?
>
>> + * change.
>> + */
>> + rtnl_lock();
>> + ret = set_offload(q, 0);
>> + rtnl_unlock();
>> + }
>> q->flags = u;
>> + }
>>
>> return ret;
>>
>> @@ -1155,10 +1170,6 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
>> TUN_F_TSO_ECN | TUN_F_UFO))
>> return -EINVAL;
>>
>> - /* TODO: only accept frames with the features that
>> - got enabled for forwarded frames */
>> - if (!(q->flags & IFF_VNET_HDR))
>> - return -EINVAL;
>> rtnl_lock();
>> ret = set_offload(q, arg);
>> rtnl_unlock();
>> --
>> 1.8.1.4
^ permalink raw reply
* Re: How to debug a driver which hangs (niu)?
From: Jesper Dangaard Brouer @ 2013-08-14 13:30 UTC (permalink / raw)
To: Andrew Brooks; +Cc: Linux Net-Dev Mailing List, Jesper Brouer
In-Reply-To: <CAHOfOo0kYpa3OtJ2w5xzdi=V6ccm9PKNJ8Pzj+7avNPmZDr9Gg@mail.gmail.com>
On Mon, 12 Aug 2013, Andrew Brooks wrote:
> I'm using a network driver (niu) which regularly locks-up after
> printing the message "transmit timed out"
> (i.e. nothing else can be sent/received over that interface after the event).
What kernel version are you using?
I seem to remember to have fixed an issue with NIU driver, long time ago.
> Does anyone have any tips for helping me to debug this?
First thing you could do is to increase the message level in the driver (I
remeber NIU uses these msglvl settings).
By command:
ethtool -s eth0 msglvl $((0x7fff))
View the message level by command:
ethtool eth0
Cheers,
Jesper Brouer
--
-------------------------------------------------------------------
MSc. Master of Computer Science
Dept. of Computer Science, University of Copenhagen
Author of http://www.adsl-optimizer.dk
-------------------------------------------------------------------
^ permalink raw reply
* [PATCH stable] ipv6: restrict neighbor entry creation to output flow
From: Marcelo Ricardo Leitner @ 2013-08-14 13:53 UTC (permalink / raw)
To: netdev; +Cc: hannes, jiri, dbanerje, yoshfuji
This patch is based on 3.2.y branch, the one used by reported. Please let me
know if it should be different. Thanks.
---8<---
Commit 0d6a77079c475033cb622c07c5a880b392ef664e introduced a regression on
which routes to local delivery would not work anymore. Like this:
$ ip -6 route add local 2001::/64 dev lo
$ ping6 -c1 2001::9
PING 2001::9(2001::9) 56 data bytes
ping: sendmsg: Invalid argument
As this is a local delivery, that commit would not allow the creation of a
neighbor entry and thus the packet cannot be sent.
But as TPROXY scenario actually needs to avoid the neighbor entry creation only
for input flow, this patch now limits previous patch to input flow, keeping
output as before that patch.
Reported-by: Debabrata Banerjee <dbavatar@gmail.com>
Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
CC: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
net/ipv6/route.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 18ea73c..bc9103d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -791,7 +791,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
}
static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
- struct flowi6 *fl6, int flags)
+ struct flowi6 *fl6, int flags, bool input)
{
struct fib6_node *fn;
struct rt6_info *rt, *nrt;
@@ -799,8 +799,11 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
int attempts = 3;
int err;
int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
+ int local = RTF_NONEXTHOP;
strict |= flags & RT6_LOOKUP_F_IFACE;
+ if (input)
+ local |= RTF_LOCAL;
relookup:
read_lock_bh(&table->tb6_lock);
@@ -820,7 +823,7 @@ restart:
read_unlock_bh(&table->tb6_lock);
if (!dst_get_neighbour_raw(&rt->dst)
- && !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL)))
+ && !(rt->rt6i_flags & local))
nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
else if (!(rt->dst.flags & DST_HOST))
nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -864,7 +867,7 @@ out2:
static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
struct flowi6 *fl6, int flags)
{
- return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
+ return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags, true);
}
void ip6_route_input(struct sk_buff *skb)
@@ -890,7 +893,7 @@ void ip6_route_input(struct sk_buff *skb)
static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
struct flowi6 *fl6, int flags)
{
- return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
+ return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags, false);
}
struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk,
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH] r8169: fix invalid register dump
From: Peter Wu @ 2013-08-14 13:12 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, nic_swsd
In-Reply-To: <20130813222038.GC5635@electric-eye.fr.zoreil.com>
On Wednesday 14 August 2013 00:20:38 Francois Romieu wrote:
> > - memcpy_fromio(p, tp->mmio_addr, regs->len);
> > + for (i = 0; i < regs->len - 4; i += 4)
> > + memcpy_fromio(bytes + i, tp->mmio_addr + i, 4);
>
> regs->len is u32. regs->len - 4 should not underflow on normal situation but
> it's a bit sloppy.
Heh, I forgot about that case. Fixed it in the below patch. By the way,
have you observed similar behavior on other hardware?
Thanks,
Peter
--
From: Peter Wu <lekensteyn@gmail.com>
For some reason, my PCIe RTL8111E onboard NIC on a GA-Z68X-UD3H-B3
motherboard reads as FFs when reading from MMIO with a block size
larger than 7. Therefore change to reading blocks of four bytes.
Signed-off-by: Peter Wu <lekensteyn@gmail.com>
---
drivers/net/ethernet/realtek/r8169.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index b5eb419..d367763 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -1897,12 +1897,19 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
{
struct rtl8169_private *tp = netdev_priv(dev);
+ char *bytes = p;
+ int i;
if (regs->len > R8169_REGS_SIZE)
regs->len = R8169_REGS_SIZE;
rtl_lock_work(tp);
- memcpy_fromio(p, tp->mmio_addr, regs->len);
+ if (regs->len >= 4) {
+ for (i = 0; i < regs->len - 4; i += 4)
+ memcpy_fromio(bytes + i, tp->mmio_addr + i, 4);
+ }
+ if (i < regs->len)
+ memcpy_fromio(bytes + i, tp->mmio_addr + i, regs->len - i);
rtl_unlock_work(tp);
}
--
1.8.3.4
^ permalink raw reply related
* Re: [PATCH] r8169: remember WOL preferences on driver load
From: Peter Wu @ 2013-08-14 12:56 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, nic_swsd, Hayes Wang
In-Reply-To: <20130813212843.GB5635@electric-eye.fr.zoreil.com>
On Tuesday 13 August 2013 23:28:43 Francois Romieu wrote:
> > The r8168 vendor driver used to write to both Config1 and Config5, but
> > in recent versions, this is commented out. Here we keep writing PMEnable
> > to Config1 because there may be older chips where PMEnable is not sticky.
>
> <sneak regression paranoia>
> Please include the bits you want to keep in the "&" mask.
> </sneak regression paranoia>
I previously tried:
RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus));
but then I realized that the Realtek r8168 vendor driver does not touch this
register on load. The bits not included in the above mask are 2, 3 and 7. On
most datasheets for recent hardware, these are marked reserved.
For RTL8100C(L) (datasheet 1.3 from 2007), RTL8139D(L) (datasheet 1.3 from
2005) and RTL8101L (1.6 from 2008)
- bit 2 is Link Down Power Saving mode (1=disable, 0=enable; loaded from
EEPROM on RTL8139D(L))
- bit 3 is FIFOAddrPtr (internal use for testing FIFO SRAM, default 0)
- bit 7 is reserved
I'll let Hayes judge which approach is more appropriate.
Regards,
Peter
^ permalink raw reply
* [PATCH net-next v2 3/3] net/usb/r8152: enable interrupt transfer
From: Hayes Wang @ 2013-08-14 12:54 UTC (permalink / raw)
To: netdev; +Cc: nic_swsd, linux-kernel, linux-usb, Hayes Wang
In-Reply-To: <1376484880-741-1-git-send-email-hayeswang@realtek.com>
Use the interrupt transfer to replace polling link status.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
drivers/net/usb/r8152.c | 140 ++++++++++++++++++++++++++++++++++++++----------
1 file changed, 113 insertions(+), 27 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 4d938a7..ef2498c 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -272,6 +272,9 @@ enum rtl_register_content {
#define RTL8152_MAX_TX 10
#define RTL8152_MAX_RX 10
+#define INTBUFSIZE 2
+
+#define INTR_LINK 0x0004
#define RTL8152_REQT_READ 0xc0
#define RTL8152_REQT_WRITE 0x40
@@ -292,7 +295,8 @@ enum rtl_register_content {
enum rtl8152_flags {
RTL8152_UNPLUG = 0,
RTL8152_SET_RX_MODE,
- WORK_ENABLE
+ WORK_ENABLE,
+ RTL8152_LINK_CHG,
};
/* Define these values to match your device */
@@ -347,7 +351,9 @@ struct r8152 {
unsigned long flags;
struct usb_device *udev;
struct tasklet_struct tl;
+ struct usb_interface *intf;
struct net_device *netdev;
+ struct urb *intr_urb;
struct tx_agg tx_info[RTL8152_MAX_TX];
struct rx_agg rx_info[RTL8152_MAX_RX];
struct list_head rx_done, tx_free;
@@ -355,8 +361,10 @@ struct r8152 {
spinlock_t rx_lock, tx_lock;
struct delayed_work schedule;
struct mii_if_info mii;
+ int intr_interval;
u32 msg_enable;
u16 ocp_base;
+ u8 *intr_buff;
u8 version;
u8 speed;
};
@@ -860,6 +868,62 @@ static void write_bulk_callback(struct urb *urb)
tasklet_schedule(&tp->tl);
}
+static void intr_callback(struct urb *urb)
+{
+ struct r8152 *tp;
+ __u16 *d;
+ int status = urb->status;
+ int res;
+
+ tp = urb->context;
+ if (!tp)
+ return;
+
+ if (!test_bit(WORK_ENABLE, &tp->flags))
+ return;
+
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ switch (status) {
+ case 0: /* success */
+ break;
+ case -ECONNRESET: /* unlink */
+ case -ESHUTDOWN:
+ netif_device_detach(tp->netdev);
+ case -ENOENT:
+ return;
+ case -EOVERFLOW:
+ netif_info(tp, intr, tp->netdev, "intr status -EOVERFLOW\n");
+ goto resubmit;
+ /* -EPIPE: should clear the halt */
+ default:
+ netif_info(tp, intr, tp->netdev, "intr status %d\n", status);
+ goto resubmit;
+ }
+
+ d = urb->transfer_buffer;
+ if (INTR_LINK & __le16_to_cpu(d[0])) {
+ if (!(tp->speed & LINK_STATUS)) {
+ set_bit(RTL8152_LINK_CHG, &tp->flags);
+ schedule_delayed_work(&tp->schedule, 0);
+ }
+ } else {
+ if (tp->speed & LINK_STATUS) {
+ set_bit(RTL8152_LINK_CHG, &tp->flags);
+ schedule_delayed_work(&tp->schedule, 0);
+ }
+ }
+
+resubmit:
+ res = usb_submit_urb(urb, GFP_ATOMIC);
+ if (res == -ENODEV)
+ netif_device_detach(tp->netdev);
+ else if (res)
+ netif_err(tp, intr, tp->netdev,
+ "can't resubmit intr, status %d\n", res);
+}
+
static inline void *rx_agg_align(void *data)
{
return (void *)ALIGN((uintptr_t)data, 8);
@@ -899,11 +963,24 @@ static void free_all_mem(struct r8152 *tp)
tp->tx_info[i].head = NULL;
}
}
+
+ if (tp->intr_urb) {
+ usb_free_urb(tp->intr_urb);
+ tp->intr_urb = NULL;
+ }
+
+ if (tp->intr_buff) {
+ kfree(tp->intr_buff);
+ tp->intr_buff = NULL;
+ }
}
static int alloc_all_mem(struct r8152 *tp)
{
struct net_device *netdev = tp->netdev;
+ struct usb_interface *intf = tp->intf;
+ struct usb_host_interface *alt = intf->cur_altsetting;
+ struct usb_host_endpoint *ep_intr = alt->endpoint + 2;
struct urb *urb;
int node, i;
u8 *buf;
@@ -968,6 +1045,19 @@ static int alloc_all_mem(struct r8152 *tp)
list_add_tail(&tp->tx_info[i].list, &tp->tx_free);
}
+ tp->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!tp->intr_urb)
+ goto err1;
+
+ tp->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL);
+ if (!tp->intr_buff)
+ goto err1;
+
+ tp->intr_interval = (int)ep_intr->desc.bInterval;
+ usb_fill_int_urb(tp->intr_urb, tp->udev, usb_rcvintpipe(tp->udev, 3),
+ tp->intr_buff, INTBUFSIZE, intr_callback,
+ tp, tp->intr_interval);
+
return 0;
err1:
@@ -1228,8 +1318,10 @@ static void rtl8152_set_rx_mode(struct net_device *netdev)
{
struct r8152 *tp = netdev_priv(netdev);
- if (tp->speed & LINK_STATUS)
+ if (tp->speed & LINK_STATUS) {
set_bit(RTL8152_SET_RX_MODE, &tp->flags);
+ schedule_delayed_work(&tp->schedule, 0);
+ }
}
static void _rtl8152_set_rx_mode(struct net_device *netdev)
@@ -1648,7 +1740,6 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
r8152_mdio_write(tp, MII_BMCR, bmcr);
out:
- schedule_delayed_work(&tp->schedule, 5 * HZ);
return ret;
}
@@ -1671,6 +1762,7 @@ static void set_carrier(struct r8152 *tp)
struct net_device *netdev = tp->netdev;
u8 speed;
+ clear_bit(RTL8152_LINK_CHG, &tp->flags);
speed = rtl8152_get_speed(tp);
if (speed & LINK_STATUS) {
@@ -1700,13 +1792,12 @@ static void rtl_work_func_t(struct work_struct *work)
if (test_bit(RTL8152_UNPLUG, &tp->flags))
goto out1;
- set_carrier(tp);
+ if (test_bit(RTL8152_LINK_CHG, &tp->flags))
+ set_carrier(tp);
if (test_bit(RTL8152_SET_RX_MODE, &tp->flags))
_rtl8152_set_rx_mode(tp->netdev);
- schedule_delayed_work(&tp->schedule, HZ);
-
out1:
return;
}
@@ -1716,28 +1807,20 @@ static int rtl8152_open(struct net_device *netdev)
struct r8152 *tp = netdev_priv(netdev);
int res = 0;
- tp->speed = rtl8152_get_speed(tp);
- if (tp->speed & LINK_STATUS) {
- res = rtl8152_enable(tp);
- if (res) {
- if (res == -ENODEV)
- netif_device_detach(tp->netdev);
-
- netif_err(tp, ifup, netdev,
- "rtl8152_open failed: %d\n", res);
- return res;
- }
-
- netif_carrier_on(netdev);
- } else {
- netif_stop_queue(netdev);
- netif_carrier_off(netdev);
+ res = usb_submit_urb(tp->intr_urb, GFP_KERNEL);
+ if (res) {
+ if (res == -ENODEV)
+ netif_device_detach(tp->netdev);
+ netif_warn(tp, ifup, netdev,
+ "intr_urb submit failed: %d\n", res);
+ return res;
}
rtl8152_set_speed(tp, AUTONEG_ENABLE, SPEED_100, DUPLEX_FULL);
+ tp->speed = 0;
+ netif_carrier_off(netdev);
netif_start_queue(netdev);
set_bit(WORK_ENABLE, &tp->flags);
- schedule_delayed_work(&tp->schedule, 0);
return res;
}
@@ -1747,6 +1830,7 @@ static int rtl8152_close(struct net_device *netdev)
struct r8152 *tp = netdev_priv(netdev);
int res = 0;
+ usb_kill_urb(tp->intr_urb);
clear_bit(WORK_ENABLE, &tp->flags);
cancel_delayed_work_sync(&tp->schedule);
netif_stop_queue(netdev);
@@ -1872,6 +1956,7 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
if (netif_running(tp->netdev)) {
clear_bit(WORK_ENABLE, &tp->flags);
+ usb_kill_urb(tp->intr_urb);
cancel_delayed_work_sync(&tp->schedule);
tasklet_disable(&tp->tl);
}
@@ -1888,10 +1973,11 @@ static int rtl8152_resume(struct usb_interface *intf)
r8152b_init(tp);
netif_device_attach(tp->netdev);
if (netif_running(tp->netdev)) {
- rtl8152_enable(tp);
+ rtl8152_set_speed(tp, AUTONEG_ENABLE, SPEED_100, DUPLEX_FULL);
+ tp->speed = 0;
+ netif_carrier_off(tp->netdev);
set_bit(WORK_ENABLE, &tp->flags);
- set_bit(RTL8152_SET_RX_MODE, &tp->flags);
- schedule_delayed_work(&tp->schedule, 0);
+ usb_submit_urb(tp->intr_urb, GFP_KERNEL);
tasklet_enable(&tp->tl);
}
@@ -2027,13 +2113,13 @@ static int rtl8152_probe(struct usb_interface *intf,
tp->udev = udev;
tp->netdev = netdev;
+ tp->intf = intf;
netdev->netdev_ops = &rtl8152_netdev_ops;
netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
netdev->features |= NETIF_F_IP_CSUM;
netdev->hw_features = NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev, &ops);
- tp->speed = 0;
tp->mii.dev = netdev;
tp->mii.mdio_read = read_mii_word;
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v2 2/3] net/usb/r8152: enable tx checksum
From: Hayes Wang @ 2013-08-14 12:54 UTC (permalink / raw)
To: netdev; +Cc: nic_swsd, linux-kernel, linux-usb, Hayes Wang
In-Reply-To: <1376484880-741-1-git-send-email-hayeswang@realtek.com>
Enable tx checksum.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
drivers/net/usb/r8152.c | 64 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 59 insertions(+), 5 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index abb0b9f..4d938a7 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -20,6 +20,8 @@
#include <linux/if_vlan.h>
#include <linux/uaccess.h>
#include <linux/list.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
/* Version Information */
#define DRIVER_VERSION "v1.01.0 (2013/08/12)"
@@ -314,8 +316,13 @@ struct tx_desc {
u32 opts1;
#define TX_FS (1 << 31) /* First segment of a packet */
#define TX_LS (1 << 30) /* Final segment of a packet */
-#define TX_LEN_MASK 0xffff
+#define TX_LEN_MASK 0x3ffff
+
u32 opts2;
+#define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */
+#define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */
+#define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */
+#define IPV6_CS (1 << 28) /* Calculate IPv6 checksum */
};
struct rx_agg {
@@ -968,6 +975,52 @@ err1:
return -ENOMEM;
}
+static void
+r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb)
+{
+ memset(desc, 0, sizeof(*desc));
+
+ desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS);
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ __be16 protocol;
+ u8 ip_protocol;
+ u32 opts2 = 0;
+
+ if (skb->protocol == htons(ETH_P_8021Q))
+ protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+ else
+ protocol = skb->protocol;
+
+ switch (protocol) {
+ case htons(ETH_P_IP):
+ opts2 |= IPV4_CS;
+ ip_protocol = ip_hdr(skb)->protocol;
+ break;
+
+ case htons(ETH_P_IPV6):
+ opts2 |= IPV6_CS;
+ ip_protocol = ipv6_hdr(skb)->nexthdr;
+ break;
+
+ default:
+ ip_protocol = IPPROTO_RAW;
+ break;
+ }
+
+ if (ip_protocol == IPPROTO_TCP) {
+ opts2 |= TCP_CS;
+ opts2 |= (skb_transport_offset(skb) & 0x7fff) << 17;
+ } else if (ip_protocol == IPPROTO_UDP) {
+ opts2 |= UDP_CS;
+ } else {
+ WARN_ON_ONCE(1);
+ }
+
+ desc->opts2 = cpu_to_le32(opts2);
+ }
+}
+
static void rx_bottom(struct r8152 *tp)
{
struct net_device_stats *stats;
@@ -1097,8 +1150,7 @@ next_agg:
tx_desc = (struct tx_desc *)tx_data;
tx_data += sizeof(*tx_desc);
- tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS |
- TX_LS);
+ r8152_tx_csum(tp, tx_desc, skb);
memcpy(tx_data, skb->data, len);
agg->skb_num++;
agg->skb_len += len;
@@ -1256,7 +1308,7 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
agg->skb_num = agg->skb_len = 0;
len = skb->len;
- tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS);
+ r8152_tx_csum(tp, tx_desc, skb);
memcpy(tx_data, skb->data, len);
dev_kfree_skb_any(skb);
agg->skb_num++;
@@ -1977,7 +2029,9 @@ static int rtl8152_probe(struct usb_interface *intf,
tp->netdev = netdev;
netdev->netdev_ops = &rtl8152_netdev_ops;
netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
- netdev->features &= ~NETIF_F_IP_CSUM;
+
+ netdev->features |= NETIF_F_IP_CSUM;
+ netdev->hw_features = NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev, &ops);
tp->speed = 0;
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v2 1/3] net/usb/r8152: support aggregation
From: Hayes Wang @ 2013-08-14 12:54 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: nic_swsd-Rasf1IRRPZFBDgjK7y7TUQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA, Hayes Wang
In-Reply-To: <1376378913-879-1-git-send-email-hayeswang-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>
Enable the tx/rx aggregation which could contain one or more packets
for each bulk in/out. This could reduce the loading of the host
controller by sending less bulk transfer.
The rx packets in the bulk in buffer should be 8-byte aligned, and
the tx packets in the bulk out buffer should be 4-byte aligned.
Signed-off-by: Hayes Wang <hayeswang-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>
---
drivers/net/usb/r8152.c | 647 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 486 insertions(+), 161 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 11c51f2..abb0b9f 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -19,9 +19,10 @@
#include <linux/crc32.h>
#include <linux/if_vlan.h>
#include <linux/uaccess.h>
+#include <linux/list.h>
/* Version Information */
-#define DRIVER_VERSION "v1.0.0 (2013/05/03)"
+#define DRIVER_VERSION "v1.01.0 (2013/08/12)"
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd-Rasf1IRRPZFBDgjK7y7TUQ@public.gmane.org>"
#define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters"
#define MODULENAME "r8152"
@@ -267,6 +268,9 @@ enum rtl_register_content {
FULL_DUP = 0x01,
};
+#define RTL8152_MAX_TX 10
+#define RTL8152_MAX_RX 10
+
#define RTL8152_REQT_READ 0xc0
#define RTL8152_REQT_WRITE 0x40
#define RTL8152_REQ_GET_REGS 0x05
@@ -285,7 +289,6 @@ enum rtl_register_content {
/* rtl8152 flags */
enum rtl8152_flags {
RTL8152_UNPLUG = 0,
- RX_URB_FAIL,
RTL8152_SET_RX_MODE,
WORK_ENABLE
};
@@ -315,13 +318,34 @@ struct tx_desc {
u32 opts2;
};
+struct rx_agg {
+ struct list_head list;
+ struct urb *urb;
+ void *context;
+ void *buffer;
+ void *head;
+};
+
+struct tx_agg {
+ struct list_head list;
+ struct urb *urb;
+ void *context;
+ void *buffer;
+ void *head;
+ u32 skb_num;
+ u32 skb_len;
+};
+
struct r8152 {
unsigned long flags;
struct usb_device *udev;
struct tasklet_struct tl;
struct net_device *netdev;
- struct urb *rx_urb, *tx_urb;
- struct sk_buff *tx_skb, *rx_skb;
+ struct tx_agg tx_info[RTL8152_MAX_TX];
+ struct rx_agg rx_info[RTL8152_MAX_RX];
+ struct list_head rx_done, tx_free;
+ struct sk_buff_head tx_queue;
+ spinlock_t rx_lock, tx_lock;
struct delayed_work schedule;
struct mii_if_info mii;
u32 msg_enable;
@@ -340,6 +364,7 @@ enum rtl_version {
* The RTL chips use a 64 element hash table based on the Ethernet CRC.
*/
static const int multicast_filter_limit = 32;
+static unsigned int rx_buf_sz = 16384;
static
int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
@@ -686,6 +711,9 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
}
+static
+int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags);
+
static inline void set_ethernet_addr(struct r8152 *tp)
{
struct net_device *dev = tp->netdev;
@@ -716,26 +744,6 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
return 0;
}
-static int alloc_all_urbs(struct r8152 *tp)
-{
- tp->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!tp->rx_urb)
- return 0;
- tp->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!tp->tx_urb) {
- usb_free_urb(tp->rx_urb);
- return 0;
- }
-
- return 1;
-}
-
-static void free_all_urbs(struct r8152 *tp)
-{
- usb_free_urb(tp->rx_urb);
- usb_free_urb(tp->tx_urb);
-}
-
static struct net_device_stats *rtl8152_get_stats(struct net_device *dev)
{
return &dev->stats;
@@ -743,129 +751,425 @@ static struct net_device_stats *rtl8152_get_stats(struct net_device *dev)
static void read_bulk_callback(struct urb *urb)
{
- struct r8152 *tp;
- unsigned pkt_len;
- struct sk_buff *skb;
struct net_device *netdev;
- struct net_device_stats *stats;
+ unsigned long lockflags;
int status = urb->status;
+ struct rx_agg *agg;
+ struct r8152 *tp;
int result;
- struct rx_desc *rx_desc;
- tp = urb->context;
+ agg = urb->context;
+ if (!agg)
+ return;
+
+ tp = agg->context;
if (!tp)
return;
+
if (test_bit(RTL8152_UNPLUG, &tp->flags))
return;
+
+ if (!test_bit(WORK_ENABLE, &tp->flags))
+ return;
+
netdev = tp->netdev;
- if (!netif_device_present(netdev))
+ if (!netif_carrier_ok(netdev))
return;
- stats = rtl8152_get_stats(netdev);
switch (status) {
case 0:
- break;
+ if (urb->actual_length < ETH_ZLEN)
+ break;
+
+ spin_lock_irqsave(&tp->rx_lock, lockflags);
+ list_add_tail(&agg->list, &tp->rx_done);
+ spin_unlock_irqrestore(&tp->rx_lock, lockflags);
+ tasklet_schedule(&tp->tl);
+ return;
case -ESHUTDOWN:
set_bit(RTL8152_UNPLUG, &tp->flags);
netif_device_detach(tp->netdev);
+ return;
case -ENOENT:
return; /* the urb is in unlink state */
case -ETIME:
pr_warn_ratelimited("may be reset is needed?..\n");
- goto goon;
+ break;
default:
pr_warn_ratelimited("Rx status %d\n", status);
- goto goon;
+ break;
}
- /* protect against short packets (tell me why we got some?!?) */
- if (urb->actual_length < sizeof(*rx_desc))
- goto goon;
-
-
- rx_desc = (struct rx_desc *)urb->transfer_buffer;
- pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
- if (urb->actual_length < sizeof(struct rx_desc) + pkt_len)
- goto goon;
-
- skb = netdev_alloc_skb_ip_align(netdev, pkt_len);
- if (!skb)
- goto goon;
-
- memcpy(skb->data, tp->rx_skb->data + sizeof(struct rx_desc), pkt_len);
- skb_put(skb, pkt_len);
- skb->protocol = eth_type_trans(skb, netdev);
- netif_rx(skb);
- stats->rx_packets++;
- stats->rx_bytes += pkt_len;
-goon:
- usb_fill_bulk_urb(tp->rx_urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1),
- tp->rx_skb->data, RTL8152_RMS + sizeof(struct rx_desc),
- (usb_complete_t)read_bulk_callback, tp);
- result = usb_submit_urb(tp->rx_urb, GFP_ATOMIC);
+ result = r8152_submit_rx(tp, agg, GFP_ATOMIC);
if (result == -ENODEV) {
netif_device_detach(tp->netdev);
} else if (result) {
- set_bit(RX_URB_FAIL, &tp->flags);
- goto resched;
- } else {
- clear_bit(RX_URB_FAIL, &tp->flags);
+ spin_lock_irqsave(&tp->rx_lock, lockflags);
+ list_add_tail(&agg->list, &tp->rx_done);
+ spin_unlock_irqrestore(&tp->rx_lock, lockflags);
+ tasklet_schedule(&tp->tl);
}
-
- return;
-resched:
- tasklet_schedule(&tp->tl);
}
-static void rx_fixup(unsigned long data)
+static void write_bulk_callback(struct urb *urb)
{
+ struct net_device_stats *stats;
+ unsigned long lockflags;
+ struct tx_agg *agg;
struct r8152 *tp;
- int status;
+ int status = urb->status;
- tp = (struct r8152 *)data;
- if (!test_bit(WORK_ENABLE, &tp->flags))
+ agg = urb->context;
+ if (!agg)
return;
- status = usb_submit_urb(tp->rx_urb, GFP_ATOMIC);
- if (status == -ENODEV) {
- netif_device_detach(tp->netdev);
- } else if (status) {
- set_bit(RX_URB_FAIL, &tp->flags);
- goto tlsched;
+ tp = agg->context;
+ if (!tp)
+ return;
+
+ stats = rtl8152_get_stats(tp->netdev);
+ if (status) {
+ pr_warn_ratelimited("Tx status %d\n", status);
+ stats->tx_errors += agg->skb_num;
} else {
- clear_bit(RX_URB_FAIL, &tp->flags);
+ stats->tx_packets += agg->skb_num;
+ stats->tx_bytes += agg->skb_len;
}
- return;
-tlsched:
- tasklet_schedule(&tp->tl);
+ spin_lock_irqsave(&tp->tx_lock, lockflags);
+ list_add_tail(&agg->list, &tp->tx_free);
+ spin_unlock_irqrestore(&tp->tx_lock, lockflags);
+
+ if (!netif_carrier_ok(tp->netdev))
+ return;
+
+ if (!test_bit(WORK_ENABLE, &tp->flags))
+ return;
+
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ if (!skb_queue_empty(&tp->tx_queue))
+ tasklet_schedule(&tp->tl);
}
-static void write_bulk_callback(struct urb *urb)
+static inline void *rx_agg_align(void *data)
+{
+ return (void *)ALIGN((uintptr_t)data, 8);
+}
+
+static inline void *tx_agg_align(void *data)
+{
+ return (void *)ALIGN((uintptr_t)data, 4);
+}
+
+static void free_all_mem(struct r8152 *tp)
+{
+ int i;
+
+ for (i = 0; i < RTL8152_MAX_RX; i++) {
+ if (tp->rx_info[i].urb) {
+ usb_free_urb(tp->rx_info[i].urb);
+ tp->rx_info[i].urb = NULL;
+ }
+
+ if (tp->rx_info[i].buffer) {
+ kfree(tp->rx_info[i].buffer);
+ tp->rx_info[i].buffer = NULL;
+ tp->rx_info[i].head = NULL;
+ }
+ }
+
+ for (i = 0; i < RTL8152_MAX_TX; i++) {
+ if (tp->tx_info[i].urb) {
+ usb_free_urb(tp->tx_info[i].urb);
+ tp->tx_info[i].urb = NULL;
+ }
+
+ if (tp->tx_info[i].buffer) {
+ kfree(tp->tx_info[i].buffer);
+ tp->tx_info[i].buffer = NULL;
+ tp->tx_info[i].head = NULL;
+ }
+ }
+}
+
+static int alloc_all_mem(struct r8152 *tp)
+{
+ struct net_device *netdev = tp->netdev;
+ struct urb *urb;
+ int node, i;
+ u8 *buf;
+
+ node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1;
+
+ spin_lock_init(&tp->rx_lock);
+ spin_lock_init(&tp->tx_lock);
+ INIT_LIST_HEAD(&tp->rx_done);
+ INIT_LIST_HEAD(&tp->tx_free);
+ skb_queue_head_init(&tp->tx_queue);
+
+ for (i = 0; i < RTL8152_MAX_RX; i++) {
+ buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
+ if (!buf)
+ goto err1;
+
+ if (buf != rx_agg_align(buf)) {
+ kfree(buf);
+ buf = kmalloc_node(rx_buf_sz + 8, GFP_KERNEL, node);
+ if (!buf)
+ goto err1;
+ }
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ kfree(buf);
+ goto err1;
+ }
+
+ INIT_LIST_HEAD(&tp->rx_info[i].list);
+ tp->rx_info[i].context = tp;
+ tp->rx_info[i].urb = urb;
+ tp->rx_info[i].buffer = buf;
+ tp->rx_info[i].head = rx_agg_align(buf);
+ }
+
+ for (i = 0; i < RTL8152_MAX_TX; i++) {
+ buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
+ if (!buf)
+ goto err1;
+
+ if (buf != tx_agg_align(buf)) {
+ kfree(buf);
+ buf = kmalloc_node(rx_buf_sz + 4, GFP_KERNEL, node);
+ if (!buf)
+ goto err1;
+ }
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ kfree(buf);
+ goto err1;
+ }
+
+ INIT_LIST_HEAD(&tp->tx_info[i].list);
+ tp->tx_info[i].context = tp;
+ tp->tx_info[i].urb = urb;
+ tp->tx_info[i].buffer = buf;
+ tp->tx_info[i].head = tx_agg_align(buf);
+
+ list_add_tail(&tp->tx_info[i].list, &tp->tx_free);
+ }
+
+ return 0;
+
+err1:
+ free_all_mem(tp);
+ return -ENOMEM;
+}
+
+static void rx_bottom(struct r8152 *tp)
+{
+ struct net_device_stats *stats;
+ struct net_device *netdev;
+ struct rx_agg *agg;
+ struct rx_desc *rx_desc;
+ unsigned long lockflags;
+ struct list_head *cursor, *next;
+ struct sk_buff *skb;
+ struct urb *urb;
+ unsigned pkt_len;
+ int len_used;
+ u8 *rx_data;
+ int ret;
+
+ netdev = tp->netdev;
+
+ stats = rtl8152_get_stats(netdev);
+
+ spin_lock_irqsave(&tp->rx_lock, lockflags);
+ list_for_each_safe(cursor, next, &tp->rx_done) {
+ list_del_init(cursor);
+ spin_unlock_irqrestore(&tp->rx_lock, lockflags);
+
+ agg = list_entry(cursor, struct rx_agg, list);
+ urb = agg->urb;
+ if (urb->actual_length < ETH_ZLEN) {
+ ret = r8152_submit_rx(tp, agg, GFP_ATOMIC);
+ spin_lock_irqsave(&tp->rx_lock, lockflags);
+ if (ret && ret != -ENODEV) {
+ list_add_tail(&agg->list, next);
+ tasklet_schedule(&tp->tl);
+ }
+ continue;
+ }
+
+ len_used = 0;
+ rx_desc = agg->head;
+ rx_data = agg->head;
+ pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
+ len_used += sizeof(struct rx_desc) + pkt_len;
+
+ while (urb->actual_length >= len_used) {
+ if (pkt_len < ETH_ZLEN)
+ break;
+
+ pkt_len -= 4; /* CRC */
+ rx_data += sizeof(struct rx_desc);
+
+ skb = netdev_alloc_skb_ip_align(netdev, pkt_len);
+ if (!skb) {
+ stats->rx_dropped++;
+ break;
+ }
+ memcpy(skb->data, rx_data, pkt_len);
+ skb_put(skb, pkt_len);
+ skb->protocol = eth_type_trans(skb, netdev);
+ netif_rx(skb);
+ stats->rx_packets++;
+ stats->rx_bytes += pkt_len;
+
+ rx_data = rx_agg_align(rx_data + pkt_len + 4);
+ rx_desc = (struct rx_desc *)rx_data;
+ pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
+ len_used = (int)(rx_data - (u8 *)agg->head);
+ len_used += sizeof(struct rx_desc) + pkt_len;
+ }
+
+ ret = r8152_submit_rx(tp, agg, GFP_ATOMIC);
+ spin_lock_irqsave(&tp->rx_lock, lockflags);
+ if (ret && ret != -ENODEV) {
+ list_add_tail(&agg->list, next);
+ tasklet_schedule(&tp->tl);
+ }
+ }
+ spin_unlock_irqrestore(&tp->rx_lock, lockflags);
+}
+
+static void tx_bottom(struct r8152 *tp)
+{
+ struct net_device_stats *stats;
+ struct net_device *netdev;
+ struct tx_agg *agg;
+ unsigned long lockflags;
+ u32 remain, total;
+ u8 *tx_data;
+ int res;
+
+ netdev = tp->netdev;
+
+next_agg:
+ agg = NULL;
+ spin_lock_irqsave(&tp->tx_lock, lockflags);
+ if (!skb_queue_empty(&tp->tx_queue) && !list_empty(&tp->tx_free)) {
+ struct list_head *cursor;
+
+ cursor = tp->tx_free.next;
+ list_del_init(cursor);
+ agg = list_entry(cursor, struct tx_agg, list);
+ }
+ spin_unlock_irqrestore(&tp->tx_lock, lockflags);
+
+ if (!agg)
+ return;
+
+ tx_data = agg->head;
+ agg->skb_num = agg->skb_len = 0;
+ remain = rx_buf_sz - sizeof(struct tx_desc);
+ total = 0;
+
+ while (remain >= ETH_ZLEN) {
+ struct tx_desc *tx_desc;
+ struct sk_buff *skb;
+ unsigned int len;
+
+ skb = skb_dequeue(&tp->tx_queue);
+ if (!skb)
+ break;
+
+ len = skb->len;
+ if (remain < len) {
+ skb_queue_head(&tp->tx_queue, skb);
+ break;
+ }
+
+ tx_data = tx_agg_align(tx_data);
+ tx_desc = (struct tx_desc *)tx_data;
+ tx_data += sizeof(*tx_desc);
+
+ tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS |
+ TX_LS);
+ memcpy(tx_data, skb->data, len);
+ agg->skb_num++;
+ agg->skb_len += len;
+ dev_kfree_skb_any(skb);
+
+ tx_data += len;
+ remain = rx_buf_sz - sizeof(*tx_desc) -
+ (u32)(tx_agg_align(tx_data) - agg->head);
+ }
+
+ usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
+ agg->head, (int)(tx_data - (u8 *)agg->head),
+ (usb_complete_t)write_bulk_callback, agg);
+ res = usb_submit_urb(agg->urb, GFP_ATOMIC);
+
+ stats = rtl8152_get_stats(netdev);
+
+ if (res) {
+ /* Can we get/handle EPIPE here? */
+ if (res == -ENODEV) {
+ netif_device_detach(netdev);
+ } else {
+ netif_warn(tp, tx_err, netdev,
+ "failed tx_urb %d\n", res);
+ stats->tx_dropped += agg->skb_num;
+ spin_lock_irqsave(&tp->tx_lock, lockflags);
+ list_add_tail(&agg->list, &tp->tx_free);
+ spin_unlock_irqrestore(&tp->tx_lock, lockflags);
+ }
+ return;
+ }
+ goto next_agg;
+}
+
+static void bottom_half(unsigned long data)
{
struct r8152 *tp;
- int status = urb->status;
- tp = urb->context;
- if (!tp)
+ tp = (struct r8152 *)data;
+
+ if (test_bit(RTL8152_UNPLUG, &tp->flags))
+ return;
+
+ if (!test_bit(WORK_ENABLE, &tp->flags))
return;
- dev_kfree_skb_irq(tp->tx_skb);
- if (!netif_device_present(tp->netdev))
+
+ if (!netif_carrier_ok(tp->netdev))
return;
- if (status)
- dev_info(&urb->dev->dev, "%s: Tx status %d\n",
- tp->netdev->name, status);
- tp->netdev->trans_start = jiffies;
- netif_wake_queue(tp->netdev);
+
+ rx_bottom(tp);
+ tx_bottom(tp);
+}
+
+static
+int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags)
+{
+ usb_fill_bulk_urb(agg->urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1),
+ agg->head, rx_buf_sz,
+ (usb_complete_t)read_bulk_callback, agg);
+
+ return usb_submit_urb(agg->urb, mem_flags);
}
static void rtl8152_tx_timeout(struct net_device *netdev)
{
struct r8152 *tp = netdev_priv(netdev);
- struct net_device_stats *stats = rtl8152_get_stats(netdev);
+ int i;
+
netif_warn(tp, tx_err, netdev, "Tx timeout.\n");
- usb_unlink_urb(tp->tx_urb);
- stats->tx_errors++;
+ for (i = 0; i < RTL8152_MAX_TX; i++)
+ usb_unlink_urb(tp->tx_info[i].urb);
}
static void rtl8152_set_rx_mode(struct net_device *netdev)
@@ -923,33 +1227,44 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
{
struct r8152 *tp = netdev_priv(netdev);
struct net_device_stats *stats = rtl8152_get_stats(netdev);
+ unsigned long lockflags;
+ struct tx_agg *agg = NULL;
struct tx_desc *tx_desc;
unsigned int len;
+ u8 *tx_data;
int res;
- netif_stop_queue(netdev);
- len = skb->len;
- if (skb_header_cloned(skb) || skb_headroom(skb) < sizeof(*tx_desc)) {
- struct sk_buff *tx_skb;
+ skb_tx_timestamp(skb);
- tx_skb = skb_copy_expand(skb, sizeof(*tx_desc), 0, GFP_ATOMIC);
- dev_kfree_skb_any(skb);
- if (!tx_skb) {
- stats->tx_dropped++;
- netif_wake_queue(netdev);
- return NETDEV_TX_OK;
- }
- skb = tx_skb;
+ spin_lock_irqsave(&tp->tx_lock, lockflags);
+ if (!list_empty(&tp->tx_free) && skb_queue_empty(&tp->tx_queue)) {
+ struct list_head *cursor;
+
+ cursor = tp->tx_free.next;
+ list_del_init(cursor);
+ agg = list_entry(cursor, struct tx_agg, list);
}
- tx_desc = (struct tx_desc *)skb_push(skb, sizeof(*tx_desc));
- memset(tx_desc, 0, sizeof(*tx_desc));
- tx_desc->opts1 = cpu_to_le32((len & TX_LEN_MASK) | TX_FS | TX_LS);
- tp->tx_skb = skb;
- skb_tx_timestamp(skb);
- usb_fill_bulk_urb(tp->tx_urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
- skb->data, skb->len,
- (usb_complete_t)write_bulk_callback, tp);
- res = usb_submit_urb(tp->tx_urb, GFP_ATOMIC);
+ spin_unlock_irqrestore(&tp->tx_lock, lockflags);
+
+ if (!agg) {
+ skb_queue_tail(&tp->tx_queue, skb);
+ return NETDEV_TX_OK;
+ }
+
+ tx_desc = (struct tx_desc *)agg->head;
+ tx_data = agg->head + sizeof(*tx_desc);
+ agg->skb_num = agg->skb_len = 0;
+
+ len = skb->len;
+ tx_desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS);
+ memcpy(tx_data, skb->data, len);
+ dev_kfree_skb_any(skb);
+ agg->skb_num++;
+ agg->skb_len += len;
+ usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
+ agg->head, len + sizeof(*tx_desc),
+ (usb_complete_t)write_bulk_callback, agg);
+ res = usb_submit_urb(agg->urb, GFP_ATOMIC);
if (res) {
/* Can we get/handle EPIPE here? */
if (res == -ENODEV) {
@@ -957,12 +1272,11 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
} else {
netif_warn(tp, tx_err, netdev,
"failed tx_urb %d\n", res);
- stats->tx_errors++;
- netif_start_queue(netdev);
+ stats->tx_dropped++;
+ spin_lock_irqsave(&tp->tx_lock, lockflags);
+ list_add_tail(&agg->list, &tp->tx_free);
+ spin_unlock_irqrestore(&tp->tx_lock, lockflags);
}
- } else {
- stats->tx_packets++;
- stats->tx_bytes += skb->len;
}
return NETDEV_TX_OK;
@@ -999,17 +1313,18 @@ static inline u8 rtl8152_get_speed(struct r8152 *tp)
static int rtl8152_enable(struct r8152 *tp)
{
- u32 ocp_data;
+ u32 ocp_data;
+ int i, ret;
u8 speed;
speed = rtl8152_get_speed(tp);
- if (speed & _100bps) {
+ if (speed & _10bps) {
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
- ocp_data &= ~EEEP_CR_EEEP_TX;
+ ocp_data |= EEEP_CR_EEEP_TX;
ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
} else {
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
- ocp_data |= EEEP_CR_EEEP_TX;
+ ocp_data &= ~EEEP_CR_EEEP_TX;
ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
}
@@ -1023,23 +1338,34 @@ static int rtl8152_enable(struct r8152 *tp)
ocp_data &= ~RXDY_GATED_EN;
ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
- usb_fill_bulk_urb(tp->rx_urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1),
- tp->rx_skb->data, RTL8152_RMS + sizeof(struct rx_desc),
- (usb_complete_t)read_bulk_callback, tp);
+ INIT_LIST_HEAD(&tp->rx_done);
+ ret = 0;
+ for (i = 0; i < RTL8152_MAX_RX; i++) {
+ INIT_LIST_HEAD(&tp->rx_info[i].list);
+ ret |= r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL);
+ }
- return usb_submit_urb(tp->rx_urb, GFP_KERNEL);
+ return ret;
}
static void rtl8152_disable(struct r8152 *tp)
{
- u32 ocp_data;
- int i;
+ struct net_device_stats *stats = rtl8152_get_stats(tp->netdev);
+ struct sk_buff *skb;
+ u32 ocp_data;
+ int i;
ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
ocp_data &= ~RCR_ACPT_ALL;
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
- usb_kill_urb(tp->tx_urb);
+ while ((skb = skb_dequeue(&tp->tx_queue))) {
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+ }
+
+ for (i = 0; i < RTL8152_MAX_TX; i++)
+ usb_kill_urb(tp->tx_info[i].urb);
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
ocp_data |= RXDY_GATED_EN;
@@ -1058,7 +1384,8 @@ static void rtl8152_disable(struct r8152 *tp)
mdelay(1);
}
- usb_kill_urb(tp->rx_urb);
+ for (i = 0; i < RTL8152_MAX_RX; i++)
+ usb_kill_urb(tp->rx_info[i].urb);
rtl8152_nic_reset(tp);
}
@@ -1303,7 +1630,9 @@ static void set_carrier(struct r8152 *tp)
} else {
if (tp->speed & LINK_STATUS) {
netif_carrier_off(netdev);
+ tasklet_disable(&tp->tl);
rtl8152_disable(tp);
+ tasklet_enable(&tp->tl);
}
}
tp->speed = speed;
@@ -1369,7 +1698,9 @@ static int rtl8152_close(struct net_device *netdev)
clear_bit(WORK_ENABLE, &tp->flags);
cancel_delayed_work_sync(&tp->schedule);
netif_stop_queue(netdev);
+ tasklet_disable(&tp->tl);
rtl8152_disable(tp);
+ tasklet_enable(&tp->tl);
return res;
}
@@ -1429,8 +1760,8 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp)
static void r8152b_init(struct r8152 *tp)
{
- u32 ocp_data;
- int i;
+ u32 ocp_data;
+ int i;
rtl_clear_bp(tp);
@@ -1475,9 +1806,9 @@ static void r8152b_init(struct r8152 *tp)
break;
}
- /* disable rx aggregation */
+ /* enable rx aggregation */
ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
- ocp_data |= RX_AGG_DISABLE;
+ ocp_data &= ~RX_AGG_DISABLE;
ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
}
@@ -1490,6 +1821,7 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
if (netif_running(tp->netdev)) {
clear_bit(WORK_ENABLE, &tp->flags);
cancel_delayed_work_sync(&tp->schedule);
+ tasklet_disable(&tp->tl);
}
rtl8152_down(tp);
@@ -1508,6 +1840,7 @@ static int rtl8152_resume(struct usb_interface *intf)
set_bit(WORK_ENABLE, &tp->flags);
set_bit(RTL8152_SET_RX_MODE, &tp->flags);
schedule_delayed_work(&tp->schedule, 0);
+ tasklet_enable(&tp->tl);
}
return 0;
@@ -1619,6 +1952,7 @@ static int rtl8152_probe(struct usb_interface *intf,
struct usb_device *udev = interface_to_usbdev(intf);
struct r8152 *tp;
struct net_device *netdev;
+ int ret;
if (udev->actconfig->desc.bConfigurationValue != 1) {
usb_driver_set_configuration(udev, 1);
@@ -1631,10 +1965,12 @@ static int rtl8152_probe(struct usb_interface *intf,
return -ENOMEM;
}
+ SET_NETDEV_DEV(netdev, &intf->dev);
tp = netdev_priv(netdev);
+ memset(tp, 0, sizeof(*tp));
tp->msg_enable = 0x7FFF;
- tasklet_init(&tp->tl, rx_fixup, (unsigned long)tp);
+ tasklet_init(&tp->tl, bottom_half, (unsigned long)tp);
INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
tp->udev = udev;
@@ -1657,37 +1993,27 @@ static int rtl8152_probe(struct usb_interface *intf,
r8152b_init(tp);
set_ethernet_addr(tp);
- if (!alloc_all_urbs(tp)) {
- netif_err(tp, probe, netdev, "out of memory");
+ ret = alloc_all_mem(tp);
+ if (ret)
goto out;
- }
-
- tp->rx_skb = netdev_alloc_skb(netdev,
- RTL8152_RMS + sizeof(struct rx_desc));
- if (!tp->rx_skb)
- goto out1;
usb_set_intfdata(intf, tp);
- SET_NETDEV_DEV(netdev, &intf->dev);
-
- if (register_netdev(netdev) != 0) {
+ ret = register_netdev(netdev);
+ if (ret != 0) {
netif_err(tp, probe, netdev, "couldn't register the device");
- goto out2;
+ goto out1;
}
netif_info(tp, probe, netdev, "%s", DRIVER_VERSION);
return 0;
-out2:
- usb_set_intfdata(intf, NULL);
- dev_kfree_skb(tp->rx_skb);
out1:
- free_all_urbs(tp);
+ usb_set_intfdata(intf, NULL);
out:
free_netdev(netdev);
- return -EIO;
+ return ret;
}
static void rtl8152_unload(struct r8152 *tp)
@@ -1715,9 +2041,7 @@ static void rtl8152_disconnect(struct usb_interface *intf)
tasklet_kill(&tp->tl);
unregister_netdev(tp->netdev);
rtl8152_unload(tp);
- free_all_urbs(tp);
- if (tp->rx_skb)
- dev_kfree_skb(tp->rx_skb);
+ free_all_mem(tp);
free_netdev(tp->netdev);
}
}
@@ -1732,11 +2056,12 @@ MODULE_DEVICE_TABLE(usb, rtl8152_table);
static struct usb_driver rtl8152_driver = {
.name = MODULENAME,
+ .id_table = rtl8152_table,
.probe = rtl8152_probe,
.disconnect = rtl8152_disconnect,
- .id_table = rtl8152_table,
.suspend = rtl8152_suspend,
- .resume = rtl8152_resume
+ .resume = rtl8152_resume,
+ .reset_resume = rtl8152_resume,
};
module_usb_driver(rtl8152_driver);
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH net-next 3/6] 6lowpan: introduce lowpan_fetch_skb function
From: Alexander Aring @ 2013-08-14 12:54 UTC (permalink / raw)
To: Alexander Smirnov, dbaryshkov, davem, linux-zigbee-devel, netdev
In-Reply-To: <20130814124754.GA2723@order.stressinduktion.org>
Hi Hannes,
On Wed, Aug 14, 2013 at 02:47:54PM +0200, Hannes Frederic Sowa wrote:
> On Wed, Aug 14, 2013 at 02:45:47PM +0200, Alexander Aring wrote:
> > This was the old behaviour, we decide it to make it like this:
> >
> > fail = ...
> > fail |= ....
> >
> > if (fail)
> > ...
> >
> > We discussed that already at the linux-zigbee-devel mailinglist.
> > I don't know what I should do now, on linux-zigbee-devel we decide it to
> > this way, now we decide it in a other way...
>
> Oh, I didn't know. Please just take my mail as a suggestion. If there
> already was a discussion and you had a consensus about that please just
> ignore my mails. :)
>
This discussion was only with two persons.
So I am happy to hear some other opinions. :-)
Regards
Alex
^ permalink raw reply
* Re: [PATCH net-next 3/6] 6lowpan: introduce lowpan_fetch_skb function
From: Hannes Frederic Sowa @ 2013-08-14 12:47 UTC (permalink / raw)
To: Alexander Aring
Cc: Alexander Smirnov, dbaryshkov, davem, linux-zigbee-devel, netdev
In-Reply-To: <20130814124545.GB4303@x61s.8.8.8.8>
On Wed, Aug 14, 2013 at 02:45:47PM +0200, Alexander Aring wrote:
> This was the old behaviour, we decide it to make it like this:
>
> fail = ...
> fail |= ....
>
> if (fail)
> ...
>
> We discussed that already at the linux-zigbee-devel mailinglist.
> I don't know what I should do now, on linux-zigbee-devel we decide it to
> this way, now we decide it in a other way...
Oh, I didn't know. Please just take my mail as a suggestion. If there
already was a discussion and you had a consensus about that please just
ignore my mails. :)
Thanks,
Hannes
^ permalink raw reply
* Re: [PATCH net-next 3/6] 6lowpan: introduce lowpan_fetch_skb function
From: Alexander Aring @ 2013-08-14 12:45 UTC (permalink / raw)
To: Alexander Smirnov; +Cc: dbaryshkov, davem, linux-zigbee-devel, netdev
In-Reply-To: <520B7029.3070903@gmail.com>
Hi Alex,
On Wed, Aug 14, 2013 at 03:55:21PM +0400, Alexander Smirnov wrote:
> On 08/14/2013 03:49 PM, Hannes Frederic Sowa wrote:
> >On Wed, Aug 14, 2013 at 01:01:45PM +0200, Alexander Aring wrote:
> >>This patch adds a helper function to parse the ipv6 header to a
> >>6lowpan header in stream.
> >>
> >>This function checks first if we can pull data with a specific
> >>length from a skb. If this seems to be okay, we copy skb data to
> >>a destination pointer and run skb_pull.
> >>
> >>Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> >>Reviewed-by: Werner Almesberger <werner@almesberger.net>
> >>---
> >> net/ieee802154/6lowpan.h | 12 ++++++++++++
> >> 1 file changed, 12 insertions(+)
> >>
> >>diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
> >>index 61f0ce9..e3348ec 100644
> >>--- a/net/ieee802154/6lowpan.h
> >>+++ b/net/ieee802154/6lowpan.h
> >>@@ -233,4 +233,16 @@
> >> dest = 16 bit inline */
> >> #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
> >>
> >>+static inline bool lowpan_fetch_skb(struct sk_buff *skb,
> >>+ void *data, const unsigned int len)
> >>+{
> >>+ if (unlikely(!pskb_may_pull(skb, len)))
> >>+ return true;
> >>+
> >>+ skb_copy_from_linear_data(skb, data, len);
> >>+ skb_pull(skb, len);
> >>+
> >>+ return false;
> >>+}
> >
> >Isn't the return value inverted here?
>
> Nope, everything is right here, but I spent several minutes to get it...
> Probably using of standard intergers will be better here: return
> -EINVAL and return 0;
>
This was the old behaviour, we decide it to make it like this:
fail = ...
fail |= ....
if (fail)
...
We discussed that already at the linux-zigbee-devel mailinglist.
I don't know what I should do now, on linux-zigbee-devel we decide it to
this way, now we decide it in a other way...
Regards
Alex
^ permalink raw reply
* Re: [PATCHv2 net-next 0/6] 6lowpan: uncompress of addresses fix
From: Alexander Aring @ 2013-08-14 12:41 UTC (permalink / raw)
To: Alexander Smirnov; +Cc: dbaryshkov, davem, linux-zigbee-devel, netdev
In-Reply-To: <520B68C4.7030602@gmail.com>
Hi Alex,
On Wed, Aug 14, 2013 at 03:23:48PM +0400, Alexander Smirnov wrote:
> On 08/14/2013 03:01 PM, Alexander Aring wrote:
> >The current implementation to uncompress addresses in a 6lowpan header
> >is completely broken.
> >
> >This patch series fixes the parsing of addresses in a 6lowpan header.
> >It contains a major rewrite of the uncompress address function to parse
> >the address in a correct way.
> >
>
> Could you please describe in a few words how have you tested the changes?
>
I test this with a ravenusbstick and the jackdaw firmware.
This is a usb stick with a contiki stack which offers a ipv6 interface
under linux. It still uses the 6LoWPAN contiki stack.
On the other side I have a beaglebone device with the current net-next
6LoWPAN stack.
I add several addresses to this linux device to catch all cases (except
short address) in the uncompression function.
With a ping6 $ADDRESS and wireshark on the usb stick I see the
outcomming 6lowpan packets. If I get a correct reply with the used
address it seems that the uncompression works.
I am thinking to implement some test cases to test all uncompression of
all address-cases. This patch series was tested manually.
A wireshark on the beaglebone doesn't work at the moment. I get a
nullpointer dereference in the 6LoWPAN stack. I suppose this is why the
6LoWPAN Stack copies sk_buffs and free the old one. This is a wrong
behaviour because the caller of a function has the old sk_buff which is
freed.
I need some time to drop the skb_clone functions.... and then I will
check wireshark.
If wireshark works I don't see the 6LoWPAN Header anyway, but I can see
if the ipv6 header is reconstructed correctly.
> Small cosmetic hint: lowpan_raw_dump_inline() already has an
> argument to print debug message, so there is no need to add extra
> pr_debug calls before it to print static text.
>
ok, I will change it.
Regards
Alex
^ permalink raw reply
* Re: [PATCH net] xfrm: introduce helper for safe determination of mtu
From: Steffen Klassert @ 2013-08-14 12:23 UTC (permalink / raw)
To: Hannes Frederic Sowa, netdev
In-Reply-To: <20130813023558.GD27385@order.stressinduktion.org>
On Tue, Aug 13, 2013 at 04:35:58AM +0200, Hannes Frederic Sowa wrote:
> skb->sk socket can be of AF_INET or AF_INET6 address family. Thus we
> always have to make sure we a referring to the correct interpretation
> of skb->sk.
>
> We only depend on header defines to query the mtu, so we don't introduce
> a new dependency to ipv6 by this change.
>
> Cc: Steffen Klassert <steffen.klassert@secunet.com>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Also applied to ipsec, thanks!
^ permalink raw reply
* Re: [PATCH net v3] xfrm: make local error reporting more robust
From: Steffen Klassert @ 2013-08-14 12:22 UTC (permalink / raw)
To: Hannes Frederic Sowa, netdev
In-Reply-To: <20130814110523.GG16264@order.stressinduktion.org>
On Wed, Aug 14, 2013 at 01:05:23PM +0200, Hannes Frederic Sowa wrote:
> In xfrm4 and xfrm6 we need to take care about sockets of the other
> address family. This could happen because a 6in4 or 4in6 tunnel could
> get protected by ipsec.
>
> Because we don't want to have a run-time dependency on ipv6 when only
> using ipv4 xfrm we have to embed a pointer to the correct local_error
> function in xfrm_state_afinet and look it up when returning an error
> depending on the socket address family.
>
> Thanks to vi0ss for the great bug report:
> <https://bugzilla.kernel.org/show_bug.cgi?id=58691>
>
> v2:
> a) fix two more unsafe interpretations of skb->sk as ipv6 socket
> (xfrm6_local_dontfrag and __xfrm6_output)
> v3:
> a) add an EXPORT_SYMBOL_GPL(xfrm_local_error) to fix a link error when
> building ipv6 as a module (thanks to Steffen Klassert)
>
> Reported-by: <vi0oss@gmail.com>
> Cc: Steffen Klassert <steffen.klassert@secunet.com>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Applied to ipsec, thanks a lot Hannes!
^ permalink raw reply
* Re: [PATCH] macvtap: Correctly set tap features when IFF_VNET_HDR is disabled.
From: Michael S. Tsirkin @ 2013-08-14 12:10 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev
In-Reply-To: <1376416558-25015-1-git-send-email-vyasevic@redhat.com>
On Tue, Aug 13, 2013 at 01:55:58PM -0400, Vlad Yasevich wrote:
> When the user turns off IFF_VNET_HDR flag, attempts to change
> offload features via TUNSETOFFLOAD do not work. This could cause
> GSO packets to be delivered to the user when the user is
> not prepared to handle them.
>
> To solve, allow processing of TUNSETOFFLOAD when IFF_VNET_HDR is
> disabled and make sure to turn off all offloads in this case.
> Also, when IFF_VNET_HDR is disabled, run throught the offload change
> as well to make sure that the functionality is not dependent on
> the order of the ioclt() calls.
>
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Hmm, this seems to make it even messier.
So
set TUNSETOFFLOAD
clear IFF_VNET_HDR
set IFF_VNET_HDR
offloads are now clear?
I'm also not sure userspace that sets offloads but clears
vnet hdr knows what it's doing.
How about we fail attempts to clear vnet hdr
unless offloads are disabled?
> ---
> drivers/net/macvtap.c | 27 +++++++++++++++++++--------
> 1 file changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
> index a98fb0e..076b9e7 100644
> --- a/drivers/net/macvtap.c
> +++ b/drivers/net/macvtap.c
> @@ -1019,6 +1019,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
> struct macvlan_dev *vlan;
> netdev_features_t features;
> netdev_features_t feature_mask = 0;
> + netdev_features_t tap_mask = TUN_OFFLOADS;
>
> vlan = rtnl_dereference(q->vlan);
> if (!vlan)
> @@ -1026,7 +1027,12 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
>
> features = vlan->dev->features;
>
> - if (arg & TUN_F_CSUM) {
> + if (!(q->flags & IFF_VNET_HDR)) {
> + /* Turn off all checsum offloading also if user does
> + * not user vnet_hdr.
Does not set?
> + */
> + tap_mask |= NETIF_F_ALL_CSUM;
> + } else if (arg & TUN_F_CSUM) {
> feature_mask = NETIF_F_HW_CSUM;
>
> if (arg & (TUN_F_TSO4 | TUN_F_TSO6)) {
> @@ -1058,8 +1064,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
> /* tap_features are the same as features on tun/tap and
> * reflect user expectations.
> */
> - vlan->tap_features = vlan->dev->features &
> - (feature_mask | ~TUN_OFFLOADS);
> + vlan->tap_features = vlan->dev->features & (feature_mask | ~tap_mask);
> vlan->set_features = features;
> netdev_update_features(vlan->dev);
>
> @@ -1092,8 +1097,18 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
> if ((u & ~(IFF_VNET_HDR | IFF_MULTI_QUEUE)) !=
> (IFF_NO_PI | IFF_TAP))
> ret = -EINVAL;
> - else
> + else {
> + if ((q->flags ^ u) & IFF_VNET_HDR) {
> + /* vnet_hdr support impacts the offloads,
> + * so we need to run throught the offload
throught ?
> + * change.
> + */
> + rtnl_lock();
> + ret = set_offload(q, 0);
> + rtnl_unlock();
> + }
> q->flags = u;
> + }
>
> return ret;
>
> @@ -1155,10 +1170,6 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
> TUN_F_TSO_ECN | TUN_F_UFO))
> return -EINVAL;
>
> - /* TODO: only accept frames with the features that
> - got enabled for forwarded frames */
> - if (!(q->flags & IFF_VNET_HDR))
> - return -EINVAL;
> rtnl_lock();
> ret = set_offload(q, arg);
> rtnl_unlock();
> --
> 1.8.1.4
^ permalink raw reply
* Re: [PATCH net-next 3/6] 6lowpan: introduce lowpan_fetch_skb function
From: Hannes Frederic Sowa @ 2013-08-14 12:06 UTC (permalink / raw)
To: Alexander Smirnov
Cc: Alexander Aring, dbaryshkov, davem, linux-zigbee-devel, netdev
In-Reply-To: <520B7029.3070903@gmail.com>
On Wed, Aug 14, 2013 at 03:55:21PM +0400, Alexander Smirnov wrote:
> On 08/14/2013 03:49 PM, Hannes Frederic Sowa wrote:
> >On Wed, Aug 14, 2013 at 01:01:45PM +0200, Alexander Aring wrote:
> >>This patch adds a helper function to parse the ipv6 header to a
> >>6lowpan header in stream.
> >>
> >>This function checks first if we can pull data with a specific
> >>length from a skb. If this seems to be okay, we copy skb data to
> >>a destination pointer and run skb_pull.
> >>
> >>Signed-off-by: Alexander Aring <alex.aring@gmail.com>
> >>Reviewed-by: Werner Almesberger <werner@almesberger.net>
> >>---
> >> net/ieee802154/6lowpan.h | 12 ++++++++++++
> >> 1 file changed, 12 insertions(+)
> >>
> >>diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
> >>index 61f0ce9..e3348ec 100644
> >>--- a/net/ieee802154/6lowpan.h
> >>+++ b/net/ieee802154/6lowpan.h
> >>@@ -233,4 +233,16 @@
> >> dest = 16 bit inline */
> >> #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit
> >> inline */
> >>
> >>+static inline bool lowpan_fetch_skb(struct sk_buff *skb,
> >>+ void *data, const unsigned int len)
> >>+{
> >>+ if (unlikely(!pskb_may_pull(skb, len)))
> >>+ return true;
> >>+
> >>+ skb_copy_from_linear_data(skb, data, len);
> >>+ skb_pull(skb, len);
> >>+
> >>+ return false;
> >>+}
> >
> >Isn't the return value inverted here?
>
> Nope, everything is right here, but I spent several minutes to get it...
> Probably using of standard intergers will be better here: return -EINVAL
> and return 0;
Ah, yes, I saw it in your next patch. You could also use false for failure and
true for success. Either way, this seemd a bit unnatural for me.
Thanks,
Hannes
^ permalink raw reply
* Re: [PATCH v3 1/6] ARM: davinci: da8xx: fix clock lookup for mdio device
From: Sekhar Nori @ 2013-08-14 12:04 UTC (permalink / raw)
To: Prabhakar Lad
Cc: DLOS, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, LKML, Heiko Schocher,
LAK
In-Reply-To: <1371999607-6483-2-git-send-email-prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Hi Prabhakar,
On 6/23/2013 8:30 PM, Prabhakar Lad wrote:
> From: "Lad, Prabhakar" <prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> This patch removes the clock alias for mdio device and adds a entry
> in clock lookup table, this entry can now be used by both DT and NON
> DT case.
>
> Signed-off-by: Lad, Prabhakar <prabhakar.csengg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: davinci-linux-open-source-VycZQUHpC/PFrsHnngEfi1aTQe2KTcn/@public.gmane.org
> Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Cc: Sekhar Nori <nsekhar-l0cyMroinI0@public.gmane.org>
> Cc: Heiko Schocher <hs-ynQEQJNshbs@public.gmane.org>
This patch looks good, except you can do the same thing on all DaVinci
devices not just on DA8XX. Apart from this patches 1-5 in this series
look good. If you can spin this fix in short time I can queue 1-5 for
v3.12 while we wait for you to fix 6/6
Thanks,
Sekhar
^ 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