* [PATCH v2] net: mv643xx_eth: Fix highmem support in non-TSO egress path
From: Ezequiel Garcia @ 2015-01-22 12:14 UTC (permalink / raw)
To: David Miller, Russell King; +Cc: netdev, B38611, fabio.estevam, Ezequiel Garcia
Commit 69ad0dd7af22b61d9e0e68e56b6290121618b0fb
Author: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Date: Mon May 19 13:59:59 2014 -0300
net: mv643xx_eth: Use dma_map_single() to map the skb fragments
caused a nasty regression by removing the support for highmem skb
fragments. By using page_address() to get the address of a fragment's
page, we are assuming a lowmem page. However, such assumption is incorrect,
as fragments can be in highmem pages, resulting in very nasty issues.
This commit fixes this by using the skb_frag_dma_map() helper,
which takes care of mapping the skb fragment properly. Additionally,
the type of mapping is now tracked, so it can be unmapped using
dma_unmap_page or dma_unmap_single when appropriate.
Fixes: 69ad0dd7af22 ("net: mv643xx_eth: Use dma_map_single() to map the skb fragments")
Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
Changes from v1:
* Sending the mv643xx_eth fix for now.
* Fix DMA mapping type track, to use the correct unmap call.
drivers/net/ethernet/marvell/mv643xx_eth.c | 41 +++++++++++++++++++++++++-----
1 file changed, 34 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index a62fc38..e4c8461 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -192,6 +192,10 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define IS_TSO_HEADER(txq, addr) \
((addr >= txq->tso_hdrs_dma) && \
(addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE))
+
+#define DESC_DMA_MAP_SINGLE 0
+#define DESC_DMA_MAP_PAGE 1
+
/*
* RX/TX descriptors.
*/
@@ -362,6 +366,7 @@ struct tx_queue {
dma_addr_t tso_hdrs_dma;
struct tx_desc *tx_desc_area;
+ char *tx_desc_mapping; /* array to track the type of the dma mapping */
dma_addr_t tx_desc_dma;
int tx_desc_area_size;
@@ -750,6 +755,7 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
desc->l4i_chk = 0;
desc->byte_cnt = length;
@@ -879,14 +885,13 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
skb_frag_t *this_frag;
int tx_index;
struct tx_desc *desc;
- void *addr;
this_frag = &skb_shinfo(skb)->frags[frag];
- addr = page_address(this_frag->page.p) + this_frag->page_offset;
tx_index = txq->tx_curr_desc++;
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_PAGE;
/*
* The last fragment will generate an interrupt
@@ -902,8 +907,9 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
desc->l4i_chk = 0;
desc->byte_cnt = skb_frag_size(this_frag);
- desc->buf_ptr = dma_map_single(mp->dev->dev.parent, addr,
- desc->byte_cnt, DMA_TO_DEVICE);
+ desc->buf_ptr = skb_frag_dma_map(mp->dev->dev.parent,
+ this_frag, 0, desc->byte_cnt,
+ DMA_TO_DEVICE);
}
}
@@ -936,6 +942,7 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb,
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
if (nr_frags) {
txq_submit_frag_skb(txq, skb);
@@ -1047,9 +1054,12 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
int tx_index;
struct tx_desc *desc;
u32 cmd_sts;
+ char desc_dma_map;
tx_index = txq->tx_used_desc;
desc = &txq->tx_desc_area[tx_index];
+ desc_dma_map = txq->tx_desc_mapping[tx_index];
+
cmd_sts = desc->cmd_sts;
if (cmd_sts & BUFFER_OWNED_BY_DMA) {
@@ -1065,9 +1075,19 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
reclaimed++;
txq->tx_desc_count--;
- if (!IS_TSO_HEADER(txq, desc->buf_ptr))
- dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
- desc->byte_cnt, DMA_TO_DEVICE);
+ if (!IS_TSO_HEADER(txq, desc->buf_ptr)) {
+
+ if (desc_dma_map == DESC_DMA_MAP_PAGE)
+ dma_unmap_page(mp->dev->dev.parent,
+ desc->buf_ptr,
+ desc->byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_single(mp->dev->dev.parent,
+ desc->buf_ptr,
+ desc->byte_cnt,
+ DMA_TO_DEVICE);
+ }
if (cmd_sts & TX_ENABLE_INTERRUPT) {
struct sk_buff *skb = __skb_dequeue(&txq->tx_skb);
@@ -2048,6 +2068,11 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
nexti * sizeof(struct tx_desc);
}
+ txq->tx_desc_mapping = kcalloc(txq->tx_ring_size, sizeof(char),
+ GFP_KERNEL);
+ if (!txq->tx_desc_mapping)
+ return -ENOMEM;
+
/* Allocate DMA buffers for TSO MAC/IP/TCP headers */
txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent,
txq->tx_ring_size * TSO_HEADER_SIZE,
@@ -2077,6 +2102,8 @@ static void txq_deinit(struct tx_queue *txq)
else
dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,
txq->tx_desc_area, txq->tx_desc_dma);
+ kfree(txq->tx_desc_mapping);
+
if (txq->tso_hdrs)
dma_free_coherent(mp->dev->dev.parent,
txq->tx_ring_size * TSO_HEADER_SIZE,
--
2.2.1
^ permalink raw reply related
* Re: NULL pointer dereference at skb_queue_tail()
From: Tetsuo Handa @ 2015-01-22 12:18 UTC (permalink / raw)
To: eric.dumazet; +Cc: cwang, netdev
In-Reply-To: <1420818314.5947.77.camel@edumazet-glaptop2.roam.corp.google.com>
Eric Dumazet wrote:
> On Fri, 2015-01-09 at 22:20 +0900, Tetsuo Handa wrote:
>
> > Would you tell me which versions to test?
>
> Could you do a bisection ?
>
> I do not see obvious bugs in af_unix.c, so it might be a corruption from
> another part of the code, reusing a freed skb.
>
It looks like a bug in drm subsystem. Thank you.
http://lists.freedesktop.org/archives/dri-devel/2015-January/075922.html
^ permalink raw reply
* Re: [PATCH 2/2] net: mv643xx_eth: Fix highmem support in non-TSO egress path
From: Ezequiel Garcia @ 2015-01-22 12:17 UTC (permalink / raw)
To: Russell King - ARM Linux; +Cc: netdev, David Miller, B38611, fabio.estevam
In-Reply-To: <20150122001103.GY26493@n2100.arm.linux.org.uk>
On 01/21/2015 09:11 PM, Russell King - ARM Linux wrote:
> On Wed, Jan 21, 2015 at 08:34:30PM -0300, Ezequiel Garcia wrote:
>> I have just realised that the non-TSO and the TSO paths must work
>> simultaneously (we don't know which path an egress skb will take).
>>
>> So, with these patches, the unmapping is done using dma_unmap_page() which
>> is only correct if the skb took the non-TSO paths. In other words,
>> these fixes are wrong (although I have no idea the effect of
>> using dma_unmap_page on a mapping done with dma_map_single).
>>
>> And the problem is that in the TSO path, the linear and the non-linear
>> fragments use the same kind of descriptors, so we can't distinguish
>> them in the cleanup, and can't decide if _single or _page should be used.
>>
>> Any ideas?
>
> Or, maybe, if davem would reply, we might come to the conclusion (as
> I previously pointed out) that it's not a driver issue, but a netdev
> core issue:
>
> static netdev_features_t harmonize_features(struct sk_buff *skb,
> netdev_features_t features)
> {
> ...
> if (skb->ip_summed != CHECKSUM_NONE &&
> !can_checksum_protocol(features, type)) {
> features &= ~NETIF_F_ALL_CSUM;
> } else if (illegal_highdma(skb->dev, skb)) {
> features &= ~NETIF_F_SG;
> }
>
> The problem is when the first "if" is true (as is the case with IPv6 on
> mv643xx_eth.c), we clear NETIF_F_ALL_CSUM, but leave NETIF_F_SG set.
>
> Had that first if been false, we would've called illegal_highdma(), and
> found that the skb contains some highmem fragments, but the device does
> *not* have NETIF_F_HIGHDMA set, and so that second "if" would be true.
> The result of that is NETIF_F_SG is cleared.
>
> In this case, in validate_xmit_skb(), skb_needs_linearize() would be
> false for a skb with fragments, causing the skb to be linearised. I've
> not completely traced the GSO path, but I'd assume that does something
> similar (which I think skb_segment() handles.)
>
> So, I'm wondering whether the above should be:
>
> static netdev_features_t harmonize_features(struct sk_buff *skb,
> netdev_features_t features)
> {
> ...
> if (skb->ip_summed != CHECKSUM_NONE &&
> !can_checksum_protocol(features, type)) {
> features &= ~NETIF_F_ALL_CSUM;
> }
>
> if (illegal_highdma(skb->dev, skb)) {
> features &= ~NETIF_F_SG;
> }
>
> So that we get NETIF_F_SG turned off for all cases (irrespective of the
> NETIF_F_ALL_CSUM test) if we see a skb with highmem and we the device
> does not support highdma.
>
> Yes, the code above hasn't changed in functionality for a long time, but
> that doesn't mean it isn't buggy, and isn't the cause of our current bug.
>
Hm, that's interesting.
> However, it would be far better to have the drivers fixed for the sake
> of performance - it's only this dma_map_page() thing that is the real
> cause of the problem in these drivers.
>
Yes, I have just sent a v2 to fix the mv643xx_eth driver (non-TSO path).
If that works, I'll see about preparing a fix for mvneta, and for both
egress paths.
> Looking at TSO, it seems madness that it doesn't support highmem:
>
> void tso_start(struct sk_buff *skb, struct tso_t *tso)
> {
> ...
> tso->data = skb->data + hdr_len;
> ...
> tso->data = page_address(frag->page.p) + frag->page_offset;
>
> Of course, this would all be a lot easier for drivers if all drivers had
> to worry about was a struct page, offset and size, rather than having to
> track whether each individual mapping of a transmit packet was mapped
> with dma_map_single() or dma_map_page().
>
> That all said, what I really care about is the regression which basically
> makes 3.18 unusable on this hardware and seeing _some_ kind of resolution
> to that regression - I don't care if it doesn't quite perform, what I care
> about is that the network driver doesn't oops the kernel.
>
Thanks for all the info!
--
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply
* Re: pull-request: wireless-drivers-next 2015-01-22
From: Kalle Valo @ 2015-01-22 12:31 UTC (permalink / raw)
To: David Miller; +Cc: linux-wireless, netdev
In-Reply-To: <87h9vjnic4.fsf@kamboji.qca.qualcomm.com>
Kalle Valo <kvalo@codeaurora.org> writes:
> Hi Dave,
>
> now a bigger pull request for net-next. Rafal found a UTF-8 bug in
> patchwork[1] and because of that two commits (d0c102f70aec and
> d0f66df5392a) have his name corrupted:
>
> Acked-by: Rafa? Mi?ecki <zajec5@gmail.com>
>
> Somehow I failed to spot that when I commited the patches. As rebasing
> public git trees is bad, I thought we can live with these and decided
> not to rebase. But I'll pay close attention to this in the future to
> make sure that it won't happen again. Also we requested an update to
> patchwork.kernel.org, the latest patchwork doesn't seem to have this
> bug.
>
> Also please note this pull request also adds one DT binding doc, but
> this was reviewed in the device tree list:
>
> .../bindings/net/wireless/qcom,ath10k.txt | 30 +
>
> Please let me know if you have any issues.
I almost missed that there's actually a small conflict with net-next:
CONFLICT (content): Merge conflict in drivers/net/wireless/ath/wil6210/cfg80211.c
Please fix it like this in wil_cid_fill_sinfo():
if (test_bit(wil_status_fwconnected, wil->status)) {
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
sinfo->signal = reply.evt.sqi;
}
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH net v2] ipv4: try to cache dst_entries which would cause a redirect
From: Hannes Frederic Sowa @ 2015-01-22 12:34 UTC (permalink / raw)
To: Julian Anastasov; +Cc: netdev, Marcelo Leitner, Florian Westphal
In-Reply-To: <alpine.LFD.2.11.1501212144530.2701@ja.home.ssi.bg>
Hi,
On Mi, 2015-01-21 at 23:26 +0200, Julian Anastasov wrote:
> On Wed, 21 Jan 2015, Hannes Frederic Sowa wrote:
>
> > Not caching dst_entries which cause redirects could be exploited by hosts
> > on the same subnet, causing a severe DoS attack. This effect aggravated
> > since commit f88649721268999 ("ipv4: fix dst race in sk_dst_get()").
> >
> > Lookups causing redirects will be allocated with DST_NOCACHE set which
> > will force dst_release to free them via RCU. Unfortunately waiting for
> > RCU grace period just takes too long, we can end up with >1M dst_entries
> > waiting to be released and the system will run OOM. rcuos threads cannot
> > catch up under high softirq load.
> >
> > Attaching the flag to emit a redirect later on to the specific skb allows
> > us to cache those dst_entries thus reducing the pressure on allocation
> > and deallocation.
> >
> > This issue was discovered by Marcelo Leitner.
>
> After more thinking and after checking all
> ip_route_input places other issues popup :(
>
> Another place with non-trivial handling is
> icmp_route_lookup(), only called by icmp_send(). We do
> lookup and then revert it. ip_options_rcv_srr() too.
> In this case we even can replace initial route (which
> should be to local host, without redirect flag) with
> new route (which can be with IPSKB_DOREDIRECT).
> So, for this case we do not wrongly leave some
> IPSKB_DOREDIRECT flag.
>
> But in icmp_route_lookup() should we restore the
> original IPSKB_DOREDIRECT bit when_skb_refdst is restored?
> I.e. I'm not sure if some icmp_send() caller continues to
> use the skb. For now I see only one place where we continue
> to use skb after icmp_send: ip_rt_send_redirect(). But
> it is after our check for RTCF_DOREDIRECT. Other places
> free the skb.
>
> If we want to be pedantic, should we create some
> helper functions and structure to save old state? For now
> we are ok but using IPCB looks risky. For example:
I would try to not introduce this complexity. I am currently researching
if this change does improve things:
do_cache = res->fi && !itag;
- if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) &&
- (IN_DEV_SHARED_MEDIA(out_dev) ||
- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) {
- flags |= RTCF_DOREDIRECT;
- do_cache = false;
+ if (skb->protocol == htons(ETH_P_IP)) {
+ if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) &&
+ skb->protocol == htons(ETH_P_IP) &&
+ (IN_DEV_SHARED_MEDIA(out_dev) ||
+ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+ IPCB(skb)->flags |= IPSKB_DOREDIRECT;
+ else if (IPCB(skb)->flags & IPSKB_DOREDIRECT)
+ IPCB(skb)->flags &= ~IPSKB_DOREDIRECT;
}
So we do reset the IPSKB_DOREDIRECT flag on every lookup. This would
keep the ip_options_rcv_srr() lookup happy, as we only use the flag as
we would do before when keeping the last dst_entry.
icmp_route_lookup actually looks fine to me just because the skb will
never end up in ip_forward, thus the state of the flag does not matter.
What do you think?
The problem with NEIGHCB and IPCB is solved by the snippet above, too.
Thanks for the review,
Hannes
^ permalink raw reply
* [PATCH net 0/4] Fixes for sh_eth #2
From: Ben Hutchings @ 2015-01-22 12:38 UTC (permalink / raw)
To: David S.Miller
Cc: netdev, linux-kernel, Nobuhiro Iwamatsu, Mitsuhiro Kimura,
Hisashi Nakamura, Yoshihiro Kaneko
I'm continuing review and testing of Ethernet support on the R-Car H2
chip. This series fixes more of the issues I've found, but it won't be
the last set.
These are not tested on any of the other supported chips.
Ben.
Ben Hutchings (4):
sh_eth: Fix padding of short frames on TX
sh_eth: Detach net device when stopping queue to resize DMA rings
sh_eth: Fix crash or memory leak when resizing rings on device that
is down
sh_eth: Fix serialisation of interrupt disable with interrupt & NAPI
handlers
drivers/net/ethernet/renesas/sh_eth.c | 84 +++++++++++++++++++++------------
drivers/net/ethernet/renesas/sh_eth.h | 1 +
2 files changed, 55 insertions(+), 30 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [PATCH net 1/4] sh_eth: Fix padding of short frames on TX
From: Ben Hutchings @ 2015-01-22 12:40 UTC (permalink / raw)
To: David S.Miller
Cc: netdev, linux-kernel, Nobuhiro Iwamatsu, Mitsuhiro Kimura,
Hisashi Nakamura, Yoshihiro Kaneko
In-Reply-To: <1421930284.1222.285.camel@xylophone.i.decadent.org.uk>
If an skb to be transmitted is shorter than the minimum Ethernet frame
length, we currently set the DMA descriptor length to the minimum but
do not add zero-padding. This could result in leaking sensitive
data. We also pass different lengths to dma_map_single() and
dma_unmap_single().
Use skb_padto() to pad properly, before calling dma_map_single().
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
---
drivers/net/ethernet/renesas/sh_eth.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 28e3822..69f9fff 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2117,6 +2117,9 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
spin_unlock_irqrestore(&mdp->lock, flags);
+ if (skb_padto(skb, ETH_ZLEN))
+ return NETDEV_TX_OK;
+
entry = mdp->cur_tx % mdp->num_tx_ring;
mdp->tx_skbuff[entry] = skb;
txdesc = &mdp->tx_ring[entry];
@@ -2126,10 +2129,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
skb->len + 2);
txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
DMA_TO_DEVICE);
- if (skb->len < ETH_ZLEN)
- txdesc->buffer_length = ETH_ZLEN;
- else
- txdesc->buffer_length = skb->len;
+ txdesc->buffer_length = skb->len;
if (entry >= mdp->num_tx_ring - 1)
txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
--
1.7.10.4
^ permalink raw reply related
* [PATCH net 2/4] sh_eth: Detach net device when stopping queue to resize DMA rings
From: Ben Hutchings @ 2015-01-22 12:40 UTC (permalink / raw)
To: David S.Miller
Cc: netdev, linux-kernel, Nobuhiro Iwamatsu, Mitsuhiro Kimura,
Hisashi Nakamura, Yoshihiro Kaneko
In-Reply-To: <1421930284.1222.285.camel@xylophone.i.decadent.org.uk>
We must only ever stop TX queues when they are full or the net device
is not 'ready' so far as the net core, and specifically the watchdog,
is concerned. Otherwise, the watchdog may fire *immediately* if no
packets have been added to the queue in the last 5 seconds.
What's more, sh_eth_tx_timeout() will likely crash if called while
we're resizing the TX ring.
I could easily trigger this by running the loop:
while ethtool -G eth0 rx 128 && ethtool -G eth0 rx 64; do echo -n .; done
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
---
drivers/net/ethernet/renesas/sh_eth.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 69f9fff..0be16dd 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1968,6 +1968,7 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
return -EINVAL;
if (netif_running(ndev)) {
+ netif_device_detach(ndev);
netif_tx_disable(ndev);
/* Disable interrupts by clearing the interrupt mask. */
sh_eth_write(ndev, 0x0000, EESIPR);
@@ -2001,7 +2002,7 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
/* Setting the Rx mode will start the Rx process. */
sh_eth_write(ndev, EDRRR_R, EDRRR);
- netif_wake_queue(ndev);
+ netif_device_attach(ndev);
}
return 0;
--
1.7.10.4
^ permalink raw reply related
* RE: [PATCH v2] net: mv643xx_eth: Fix highmem support in non-TSO egress path
From: David Laight @ 2015-01-22 12:40 UTC (permalink / raw)
To: 'Ezequiel Garcia', David Miller, Russell King
Cc: netdev@vger.kernel.org, B38611@freescale.com,
fabio.estevam@freescale.com
In-Reply-To: <1421928859-17923-1-git-send-email-ezequiel.garcia@free-electrons.com>
From: Ezequiel Garcia
> Commit 69ad0dd7af22b61d9e0e68e56b6290121618b0fb
> Author: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> Date: Mon May 19 13:59:59 2014 -0300
>
> net: mv643xx_eth: Use dma_map_single() to map the skb fragments
>
> caused a nasty regression by removing the support for highmem skb
> fragments. By using page_address() to get the address of a fragment's
> page, we are assuming a lowmem page. However, such assumption is incorrect,
> as fragments can be in highmem pages, resulting in very nasty issues.
>
> This commit fixes this by using the skb_frag_dma_map() helper,
> which takes care of mapping the skb fragment properly. Additionally,
> the type of mapping is now tracked, so it can be unmapped using
> dma_unmap_page or dma_unmap_single when appropriate.
>
> Fixes: 69ad0dd7af22 ("net: mv643xx_eth: Use dma_map_single() to map the skb fragments")
> Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
...
> @@ -2048,6 +2068,11 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
> nexti * sizeof(struct tx_desc);
> }
>
> + txq->tx_desc_mapping = kcalloc(txq->tx_ring_size, sizeof(char),
> + GFP_KERNEL);
> + if (!txq->tx_desc_mapping)
> + return -ENOMEM;
> +
> /* Allocate DMA buffers for TSO MAC/IP/TCP headers */
> txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent,
> txq->tx_ring_size * TSO_HEADER_SIZE,
I'm guessing there is an error path for dma_alloc_coherent() failing.
You've not modified it to free tx_desc_mapping.
David
^ permalink raw reply
* [PATCH net 3/4] sh_eth: Fix crash or memory leak when resizing rings on device that is down
From: Ben Hutchings @ 2015-01-22 12:41 UTC (permalink / raw)
To: David S.Miller
Cc: netdev, linux-kernel, Nobuhiro Iwamatsu, Mitsuhiro Kimura,
Hisashi Nakamura, Yoshihiro Kaneko
In-Reply-To: <1421930284.1222.285.camel@xylophone.i.decadent.org.uk>
If the device is down then no packet buffers should be allocated.
We also must not touch its registers as it may be powered off.
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
---
drivers/net/ethernet/renesas/sh_eth.c | 34 +++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 0be16dd..be7aa43 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1976,29 +1976,31 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
sh_eth_write(ndev, 0, EDTRR);
sh_eth_write(ndev, 0, EDRRR);
synchronize_irq(ndev->irq);
- }
- /* Free all the skbuffs in the Rx queue. */
- sh_eth_ring_free(ndev);
- /* Free DMA buffer */
- sh_eth_free_dma_buffer(mdp);
+ /* Free all the skbuffs in the Rx queue. */
+ sh_eth_ring_free(ndev);
+ /* Free DMA buffer */
+ sh_eth_free_dma_buffer(mdp);
+ }
/* Set new parameters */
mdp->num_rx_ring = ring->rx_pending;
mdp->num_tx_ring = ring->tx_pending;
- ret = sh_eth_ring_init(ndev);
- if (ret < 0) {
- netdev_err(ndev, "%s: sh_eth_ring_init failed.\n", __func__);
- return ret;
- }
- ret = sh_eth_dev_init(ndev, false);
- if (ret < 0) {
- netdev_err(ndev, "%s: sh_eth_dev_init failed.\n", __func__);
- return ret;
- }
-
if (netif_running(ndev)) {
+ ret = sh_eth_ring_init(ndev);
+ if (ret < 0) {
+ netdev_err(ndev, "%s: sh_eth_ring_init failed.\n",
+ __func__);
+ return ret;
+ }
+ ret = sh_eth_dev_init(ndev, false);
+ if (ret < 0) {
+ netdev_err(ndev, "%s: sh_eth_dev_init failed.\n",
+ __func__);
+ return ret;
+ }
+
sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
/* Setting the Rx mode will start the Rx process. */
sh_eth_write(ndev, EDRRR_R, EDRRR);
--
1.7.10.4
^ permalink raw reply related
* [PATCH net 4/4] sh_eth: Fix serialisation of interrupt disable with interrupt & NAPI handlers
From: Ben Hutchings @ 2015-01-22 12:44 UTC (permalink / raw)
To: David S.Miller
Cc: netdev, linux-kernel, Nobuhiro Iwamatsu, Mitsuhiro Kimura,
Hisashi Nakamura, Yoshihiro Kaneko
In-Reply-To: <1421930284.1222.285.camel@xylophone.i.decadent.org.uk>
In order to stop the RX path accessing the RX ring while it's being
stopped or resized, we clear the interrupt mask (EESIPR) and then call
free_irq() or synchronise_irq(). This is insufficient because the
interrupt handler or NAPI poller may set EESIPR again after we clear
it. Also, in sh_eth_set_ringparam() we currently don't disable NAPI
polling at all.
I could easily trigger a crash by running the loop:
while ethtool -G eth0 rx 128 && ethtool -G eth0 rx 64; do echo -n .; done
and 'ping -f' toward the sh_eth port from another machine.
To fix this:
- Add a software flag (irq_enabled) to signal whether interrupts
should be enabled
- In the interrupt handler, if the flag is clear then clear EESIPR
and return
- In the NAPI poller, if the flag is clear then don't set EESIPR
- Set the flag before enabling interrupts in sh_eth_dev_init() and
sh_eth_set_ringparam()
- Clear the flag and serialise with the interrupt and NAPI
handlers before clearing EESIPR in sh_eth_close() and
sh_eth_set_ringparam()
After this, I could run the loop for 100,000 iterations successfully.
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
---
drivers/net/ethernet/renesas/sh_eth.c | 39 +++++++++++++++++++++++++--------
drivers/net/ethernet/renesas/sh_eth.h | 1 +
2 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index be7aa43..d475929 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1316,8 +1316,10 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
RFLR);
sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
- if (start)
+ if (start) {
+ mdp->irq_enabled = true;
sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
+ }
/* PAUSE Prohibition */
val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
@@ -1653,7 +1655,12 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check))
ret = IRQ_HANDLED;
else
- goto other_irq;
+ goto out;
+
+ if (!likely(mdp->irq_enabled)) {
+ sh_eth_write(ndev, 0, EESIPR);
+ goto out;
+ }
if (intr_status & EESR_RX_CHECK) {
if (napi_schedule_prep(&mdp->napi)) {
@@ -1684,7 +1691,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
sh_eth_error(ndev, intr_status);
}
-other_irq:
+out:
spin_unlock(&mdp->lock);
return ret;
@@ -1712,7 +1719,8 @@ static int sh_eth_poll(struct napi_struct *napi, int budget)
napi_complete(napi);
/* Reenable Rx interrupts */
- sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
+ if (mdp->irq_enabled)
+ sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
out:
return budget - quota;
}
@@ -1970,12 +1978,20 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
if (netif_running(ndev)) {
netif_device_detach(ndev);
netif_tx_disable(ndev);
- /* Disable interrupts by clearing the interrupt mask. */
+
+ /* Serialise with the interrupt handler and NAPI, then
+ * disable interrupts. We have to clear the
+ * irq_enabled flag first to ensure that interrupts
+ * won't be re-enabled.
+ */
+ mdp->irq_enabled = false;
+ synchronize_irq(ndev->irq);
+ napi_synchronize(&mdp->napi);
sh_eth_write(ndev, 0x0000, EESIPR);
+
/* Stop the chip's Tx and Rx processes. */
sh_eth_write(ndev, 0, EDTRR);
sh_eth_write(ndev, 0, EDRRR);
- synchronize_irq(ndev->irq);
/* Free all the skbuffs in the Rx queue. */
sh_eth_ring_free(ndev);
@@ -2001,6 +2017,7 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
return ret;
}
+ mdp->irq_enabled = true;
sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
/* Setting the Rx mode will start the Rx process. */
sh_eth_write(ndev, EDRRR_R, EDRRR);
@@ -2184,7 +2201,13 @@ static int sh_eth_close(struct net_device *ndev)
netif_stop_queue(ndev);
- /* Disable interrupts by clearing the interrupt mask. */
+ /* Serialise with the interrupt handler and NAPI, then disable
+ * interrupts. We have to clear the irq_enabled flag first to
+ * ensure that interrupts won't be re-enabled.
+ */
+ mdp->irq_enabled = false;
+ synchronize_irq(ndev->irq);
+ napi_disable(&mdp->napi);
sh_eth_write(ndev, 0x0000, EESIPR);
/* Stop the chip's Tx and Rx processes. */
@@ -2201,8 +2224,6 @@ static int sh_eth_close(struct net_device *ndev)
free_irq(ndev->irq, ndev);
- napi_disable(&mdp->napi);
-
/* Free all the skbuffs in the Rx queue. */
sh_eth_ring_free(ndev);
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 7bfaf1c..259d03f 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -513,6 +513,7 @@ struct sh_eth_private {
u32 rx_buf_sz; /* Based on MTU+slack. */
int edmac_endian;
struct napi_struct napi;
+ bool irq_enabled;
/* MII transceiver section. */
u32 phy_id; /* PHY ID */
struct mii_bus *mii_bus; /* MDIO bus control */
--
1.7.10.4
^ permalink raw reply related
* Payment
From: Finance Department @ 2015-01-22 11:37 UTC (permalink / raw)
Dear Recipient,
You have been awarded the sum of 8,000,000.00 (Eight Million Pounds sterling) with reference number 77100146 by office of the ministry of finance UK.Send us your personal details to deliver your funds.
Gloria Peter
^ permalink raw reply
* Re: [net-next PATCH v3 00/12] Flow API
From: Pablo Neira Ayuso @ 2015-01-22 12:52 UTC (permalink / raw)
To: John Fastabend
Cc: tgraf, simon.horman, sfeldma, netdev, jhs, davem, gerlitz.or,
andy, ast
In-Reply-To: <20150120202404.1741.8658.stgit@nitbit.x32>
Hi John,
On Tue, Jan 20, 2015 at 12:26:13PM -0800, John Fastabend wrote:
> I believe I addressed all the comments so far except for the integrate
> with 'tc'. I plan to work on the integration pieces next.
I think that postponing the integration with 'tc' means that we're
renouncing to provide some abstraction to represent the actions that
the device provides. After this patch we'll have a standard API that
exposes the vendor specific semantics, *so user configurations will
not be portable anymore*.
At least, we should come up with some abstraction / mapping as
interface, so the vendors can use them to represent their operations.
That interface will provide a trade-off: If the vendor offers an
operation that doesn't map to our abstraction, then sorry that
operation has to remain behind the curtain.
netdev is just two weeks ahead and this is an important change IMO.
I'd rather have the chance to meet you and other fellows there and
discuss if we can come up with some glue abstraction.
^ permalink raw reply
* Re: [PATCH v2] net: mv643xx_eth: Fix highmem support in non-TSO egress path
From: Ezequiel Garcia @ 2015-01-22 13:26 UTC (permalink / raw)
To: David Laight, David Miller, Russell King
Cc: netdev@vger.kernel.org, B38611@freescale.com,
fabio.estevam@freescale.com
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1CAD0E4F@AcuExch.aculab.com>
On 01/22/2015 09:40 AM, David Laight wrote:
> From: Ezequiel Garcia
>> Commit 69ad0dd7af22b61d9e0e68e56b6290121618b0fb
>> Author: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
>> Date: Mon May 19 13:59:59 2014 -0300
>>
>> net: mv643xx_eth: Use dma_map_single() to map the skb fragments
>>
>> caused a nasty regression by removing the support for highmem skb
>> fragments. By using page_address() to get the address of a fragment's
>> page, we are assuming a lowmem page. However, such assumption is incorrect,
>> as fragments can be in highmem pages, resulting in very nasty issues.
>>
>> This commit fixes this by using the skb_frag_dma_map() helper,
>> which takes care of mapping the skb fragment properly. Additionally,
>> the type of mapping is now tracked, so it can be unmapped using
>> dma_unmap_page or dma_unmap_single when appropriate.
>>
>> Fixes: 69ad0dd7af22 ("net: mv643xx_eth: Use dma_map_single() to map the skb fragments")
>> Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
>> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ...
>> @@ -2048,6 +2068,11 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
>> nexti * sizeof(struct tx_desc);
>> }
>>
>> + txq->tx_desc_mapping = kcalloc(txq->tx_ring_size, sizeof(char),
>> + GFP_KERNEL);
>> + if (!txq->tx_desc_mapping)
>> + return -ENOMEM;
>> +
>> /* Allocate DMA buffers for TSO MAC/IP/TCP headers */
>> txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent,
>> txq->tx_ring_size * TSO_HEADER_SIZE,
>
> I'm guessing there is an error path for dma_alloc_coherent() failing.
> You've not modified it to free tx_desc_mapping.
>
Yeah, you guess right.
--
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply
* [patch net-next RFC] tc: introduce OpenFlow classifier
From: Jiri Pirko @ 2015-01-22 13:37 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs
This patch introduces OpenFlow-based filter. So far, the very essential
packet fields are supported (according to OpenFlow v1.4 spec).
Known issues: skb_flow_dissect hashes out ipv6 addresses. That needs
to be changed to store them somewhere so they can be used later on.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
include/uapi/linux/pkt_cls.h | 33 +++
net/sched/Kconfig | 11 +
net/sched/Makefile | 1 +
net/sched/cls_openflow.c | 514 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 559 insertions(+)
create mode 100644 net/sched/cls_openflow.c
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 25731df..d4cef16 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -402,6 +402,39 @@ enum {
#define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
+/* OpenFlow classifier */
+
+enum {
+ TCA_OF_UNSPEC,
+ TCA_OF_CLASSID,
+ TCA_OF_POLICE,
+ TCA_OF_INDEV,
+ TCA_OF_ACT,
+ TCA_OF_KEY_ETH_DST, /* ETH_ALEN */
+ TCA_OF_KEY_ETH_DST_MASK, /* ETH_ALEN */
+ TCA_OF_KEY_ETH_SRC, /* ETH_ALEN */
+ TCA_OF_KEY_ETH_SRC_MASK, /* ETH_ALEN */
+ TCA_OF_KEY_ETH_TYPE, /* be16 */
+ TCA_OF_KEY_ETH_TYPE_MASK, /* be16 */
+ TCA_OF_KEY_IP_PROTO, /* u8 */
+ TCA_OF_KEY_IP_PROTO_MASK, /* u8 */
+ TCA_OF_KEY_IPV4_SRC, /* be32 */
+ TCA_OF_KEY_IPV4_SRC_MASK, /* be32 */
+ TCA_OF_KEY_IPV4_DST, /* be32 */
+ TCA_OF_KEY_IPV4_DST_MASK, /* be32 */
+ TCA_OF_KEY_IPV6_SRC, /* struct in6_addr */
+ TCA_OF_KEY_IPV6_SRC_MASK, /* struct in6_addr */
+ TCA_OF_KEY_IPV6_DST, /* struct in6_addr */
+ TCA_OF_KEY_IPV6_DST_MASK, /* struct in6_addr */
+ TCA_OF_KEY_TP_SRC, /* be16 */
+ TCA_OF_KEY_TP_SRC_MASK, /* be16 */
+ TCA_OF_KEY_TP_DST, /* be16 */
+ TCA_OF_KEY_TP_DST_MASK, /* be16 */
+ __TCA_OF_MAX,
+};
+
+#define TCA_OF_MAX (__TCA_OF_MAX - 1)
+
/* Extended Matches */
struct tcf_ematch_tree_hdr {
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 475e35e..9b01fae 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -477,6 +477,17 @@ config NET_CLS_BPF
To compile this code as a module, choose M here: the module will
be called cls_bpf.
+config NET_CLS_OPENFLOW
+ tristate "OpenFlow classifier"
+ select NET_CLS
+ ---help---
+ If you say Y here, you will be able to classify packets based on
+ a configurable combination of packet keys and masks accordint to
+ OpenFlow standard.
+
+ To compile this code as a module, choose M here: the module will
+ be called cls_openflow.
+
config NET_EMATCH
bool "Extended Matches"
select NET_CLS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 7ca7f4c..5faa9ca 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o
obj-$(CONFIG_NET_CLS_FLOW) += cls_flow.o
obj-$(CONFIG_NET_CLS_CGROUP) += cls_cgroup.o
obj-$(CONFIG_NET_CLS_BPF) += cls_bpf.o
+obj-$(CONFIG_NET_CLS_OPENFLOW) += cls_openflow.o
obj-$(CONFIG_NET_EMATCH) += ematch.o
obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o
obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
diff --git a/net/sched/cls_openflow.c b/net/sched/cls_openflow.c
new file mode 100644
index 0000000..1c261fa
--- /dev/null
+++ b/net/sched/cls_openflow.c
@@ -0,0 +1,514 @@
+/*
+ * net/sched/cls_openflow.c OpenFlow classifier
+ *
+ * Copyright (c) 2015 Jiri Pirko <jiri@resnulli.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <linux/if_ether.h>
+#include <linux/in6.h>
+
+#include <net/sch_generic.h>
+#include <net/pkt_cls.h>
+
+struct of_flow_key {
+ int indev_ifindex;
+ struct {
+ u8 src[ETH_ALEN];
+ u8 dst[ETH_ALEN];
+ __be16 type;
+ } eth;
+ struct {
+ u8 proto;
+ } ip;
+ union {
+ struct {
+ __be32 src;
+ __be32 dst;
+ } ipv4;
+ struct {
+ struct in6_addr src;
+ struct in6_addr dst;
+ } ipv6;
+ };
+ union {
+ struct {
+ __be16 src;
+ __be16 dst;
+ } tp;
+ };
+} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
+
+struct of_flow_match {
+ struct of_flow_key key;
+ struct of_flow_key mask;
+};
+
+struct cls_of_head {
+ struct list_head filters;
+ u32 hgen;
+ struct rcu_head rcu;
+};
+
+struct cls_of_filter {
+ struct list_head list;
+ u32 handle;
+ struct tcf_exts exts;
+ struct tcf_result res;
+ struct tcf_proto *tp;
+ struct of_flow_match match;
+ struct rcu_head rcu;
+};
+
+static void of_extract_key(struct sk_buff *skb, struct of_flow_key *skb_key)
+{
+ struct flow_keys flow_keys;
+ struct ethhdr *eth;
+
+ skb_key->indev_ifindex = skb->skb_iif;
+
+ eth = eth_hdr(skb);
+ ether_addr_copy(skb_key->eth.src, eth->h_source);
+ ether_addr_copy(skb_key->eth.dst, eth->h_dest);
+
+ skb_flow_dissect(skb, &flow_keys);
+ skb_key->eth.type = flow_keys.n_proto;
+ skb_key->ip.proto = flow_keys.ip_proto;
+ skb_key->ipv4.src = flow_keys.src;
+ skb_key->ipv4.dst = flow_keys.dst;
+ skb_key->tp.src = flow_keys.port16[0];
+ skb_key->tp.dst = flow_keys.port16[1];
+}
+
+static bool of_match(struct of_flow_key *skb_key, struct cls_of_filter *f)
+{
+ const long *lkey = (const long *) &f->match.key;
+ const long *lmask = (const long *) &f->match.mask;
+ const long *lskb_key = (const long *) skb_key;
+ int i;
+
+ for (i = 0; i < sizeof(struct of_flow_key); i += sizeof(const long)) {
+ if ((*lkey++ & *lmask) != (*lskb_key++ & *lmask))
+ return false;
+ lmask++;
+ }
+ return true;
+}
+
+static int of_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+ struct tcf_result *res)
+{
+ struct cls_of_head *head = rcu_dereference_bh(tp->root);
+ struct cls_of_filter *f;
+ struct of_flow_key skb_key;
+ int ret;
+
+ of_extract_key(skb, &skb_key);
+
+ list_for_each_entry_rcu(f, &head->filters, list) {
+ if (!of_match(&skb_key, f))
+ continue;
+
+ *res = f->res;
+
+ ret = tcf_exts_exec(skb, &f->exts, res);
+ if (ret < 0)
+ continue;
+
+ return ret;
+ }
+ return -1;
+}
+
+static int of_init(struct tcf_proto *tp)
+{
+ struct cls_of_head *head;
+
+ head = kzalloc(sizeof(*head), GFP_KERNEL);
+ if (!head)
+ return -ENOBUFS;
+
+ INIT_LIST_HEAD_RCU(&head->filters);
+ rcu_assign_pointer(tp->root, head);
+
+ return 0;
+}
+
+static void of_destroy_filter(struct rcu_head *head)
+{
+ struct cls_of_filter *f = container_of(head, struct cls_of_filter, rcu);
+
+ tcf_exts_destroy(&f->exts);
+ kfree(f);
+}
+
+static void of_destroy(struct tcf_proto *tp)
+{
+ struct cls_of_head *head = rtnl_dereference(tp->root);
+ struct cls_of_filter *f, *next;
+
+ list_for_each_entry_safe(f, next, &head->filters, list) {
+ list_del_rcu(&f->list);
+ call_rcu(&f->rcu, of_destroy_filter);
+ }
+ RCU_INIT_POINTER(tp->root, NULL);
+ kfree_rcu(head, rcu);
+}
+
+static unsigned long of_get(struct tcf_proto *tp, u32 handle)
+{
+ struct cls_of_head *head = rtnl_dereference(tp->root);
+ struct cls_of_filter *f;
+
+ list_for_each_entry(f, &head->filters, list)
+ if (f->handle == handle)
+ return (unsigned long) f;
+ return 0;
+}
+
+static const struct nla_policy of_policy[TCA_OF_MAX + 1] = {
+ [TCA_OF_UNSPEC] = { .type = NLA_UNSPEC },
+ [TCA_OF_CLASSID] = { .type = NLA_U32 },
+ [TCA_OF_INDEV] = { .type = NLA_STRING,
+ .len = IFNAMSIZ },
+ [TCA_OF_KEY_ETH_DST] = { .len = ETH_ALEN },
+ [TCA_OF_KEY_ETH_DST_MASK] = { .len = ETH_ALEN },
+ [TCA_OF_KEY_ETH_SRC] = { .len = ETH_ALEN },
+ [TCA_OF_KEY_ETH_SRC_MASK] = { .len = ETH_ALEN },
+ [TCA_OF_KEY_ETH_TYPE] = { .type = NLA_U16 },
+ [TCA_OF_KEY_ETH_TYPE_MASK] = { .type = NLA_U16 },
+ [TCA_OF_KEY_IP_PROTO] = { .type = NLA_U8 },
+ [TCA_OF_KEY_IP_PROTO_MASK] = { .type = NLA_U8 },
+ [TCA_OF_KEY_IPV4_SRC] = { .type = NLA_U32 },
+ [TCA_OF_KEY_IPV4_SRC_MASK] = { .type = NLA_U32 },
+ [TCA_OF_KEY_IPV4_DST] = { .type = NLA_U32 },
+ [TCA_OF_KEY_IPV4_DST_MASK] = { .type = NLA_U32 },
+ [TCA_OF_KEY_IPV6_SRC] = { .len = sizeof(struct in6_addr) },
+ [TCA_OF_KEY_IPV6_SRC_MASK] = { .len = sizeof(struct in6_addr) },
+ [TCA_OF_KEY_IPV6_DST] = { .len = sizeof(struct in6_addr) },
+ [TCA_OF_KEY_IPV6_DST_MASK] = { .len = sizeof(struct in6_addr) },
+ [TCA_OF_KEY_TP_SRC] = { .type = NLA_U16 },
+ [TCA_OF_KEY_TP_SRC_MASK] = { .type = NLA_U16 },
+ [TCA_OF_KEY_TP_DST] = { .type = NLA_U16 },
+ [TCA_OF_KEY_TP_DST_MASK] = { .type = NLA_U16 },
+};
+
+static void of_set_key_val(struct nlattr **tb,
+ void *val, int val_type,
+ void *mask, int mask_type, int len)
+{
+ if (!tb[val_type])
+ return;
+ memcpy(val, nla_data(tb[val_type]), len);
+ if (!tb[mask_type])
+ memset(mask, 0xff, len);
+ else
+ memcpy(mask, nla_data(tb[mask_type]), len);
+}
+
+static int of_set_parms(struct net *net, struct tcf_proto *tp,
+ struct cls_of_filter *f, unsigned long base,
+ struct nlattr **tb, struct nlattr *est, bool ovr)
+{
+ struct tcf_exts e;
+ struct of_flow_key *key, *mask;
+ int err;
+
+ tcf_exts_init(&e, TCA_OF_ACT, TCA_OF_POLICE);
+ err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_OF_CLASSID]) {
+ f->res.classid = nla_get_u32(tb[TCA_OF_CLASSID]);
+ tcf_bind_filter(tp, &f->res, base);
+ }
+
+ key = &f->match.key;
+ mask = &f->match.mask;
+
+ if (tb[TCA_OF_INDEV]) {
+ err = tcf_change_indev(net, tb[TCA_OF_INDEV]);
+ if (err < 0)
+ goto errout;
+ key->indev_ifindex = err;
+ mask->indev_ifindex = 0xffffffff;
+ }
+
+ of_set_key_val(tb, key->eth.dst, TCA_OF_KEY_ETH_DST,
+ mask->eth.dst, TCA_OF_KEY_ETH_DST_MASK,
+ sizeof(key->eth.dst));
+ of_set_key_val(tb, key->eth.src, TCA_OF_KEY_ETH_SRC,
+ mask->eth.src, TCA_OF_KEY_ETH_SRC_MASK,
+ sizeof(key->eth.src));
+ of_set_key_val(tb, &key->eth.type, TCA_OF_KEY_ETH_TYPE,
+ &mask->eth.type, TCA_OF_KEY_ETH_TYPE_MASK,
+ sizeof(key->eth.type));
+ of_set_key_val(tb, &key->ip.proto, TCA_OF_KEY_IP_PROTO,
+ &mask->ip.proto, TCA_OF_KEY_IP_PROTO_MASK,
+ sizeof(key->ip.proto));
+ of_set_key_val(tb, &key->ipv4.src, TCA_OF_KEY_IPV4_SRC,
+ &mask->ipv4.src, TCA_OF_KEY_IPV4_SRC_MASK,
+ sizeof(key->ipv4.src));
+ of_set_key_val(tb, &key->ipv4.dst, TCA_OF_KEY_IPV4_DST,
+ &mask->ipv4.dst, TCA_OF_KEY_IPV4_DST_MASK,
+ sizeof(key->ipv4.dst));
+ of_set_key_val(tb, &key->ipv6.src, TCA_OF_KEY_IPV6_SRC,
+ &mask->ipv6.src, TCA_OF_KEY_IPV6_SRC_MASK,
+ sizeof(key->ipv6.src));
+ of_set_key_val(tb, &key->ipv6.dst, TCA_OF_KEY_IPV6_DST,
+ &mask->ipv6.dst, TCA_OF_KEY_IPV6_DST_MASK,
+ sizeof(key->ipv6.dst));
+ of_set_key_val(tb, &key->tp.src, TCA_OF_KEY_TP_SRC,
+ &mask->tp.src, TCA_OF_KEY_TP_SRC_MASK,
+ sizeof(key->tp.src));
+ of_set_key_val(tb, &key->tp.dst, TCA_OF_KEY_TP_DST,
+ &mask->tp.dst, TCA_OF_KEY_TP_SRC_MASK,
+ sizeof(key->tp.dst));
+
+ tcf_exts_change(tp, &f->exts, &e);
+ f->tp = tp;
+
+ return 0;
+errout:
+ tcf_exts_destroy(&e);
+ return err;
+}
+
+static u32 of_grab_new_handle(struct tcf_proto *tp,
+ struct cls_of_head *head)
+{
+ unsigned int i = 0x80000000;
+ u32 handle;
+
+ do {
+ if (++head->hgen == 0x7FFFFFFF)
+ head->hgen = 1;
+ } while (--i > 0 && of_get(tp, head->hgen));
+
+ if (unlikely(i == 0)) {
+ pr_err("Insufficient number of handles\n");
+ handle = 0;
+ } else {
+ handle = head->hgen;
+ }
+
+ return handle;
+}
+
+static int of_change(struct net *net, struct sk_buff *in_skb,
+ struct tcf_proto *tp, unsigned long base,
+ u32 handle, struct nlattr **tca,
+ unsigned long *arg, bool ovr)
+{
+ struct cls_of_head *head = rtnl_dereference(tp->root);
+ struct cls_of_filter *fold = (struct cls_of_filter *) *arg;
+ struct cls_of_filter *fnew;
+ struct nlattr *tb[TCA_OF_MAX + 1];
+ int err;
+
+ if (!tca[TCA_OPTIONS])
+ return -EINVAL;
+
+ err = nla_parse_nested(tb, TCA_OF_MAX, tca[TCA_OPTIONS], of_policy);
+ if (err < 0)
+ return err;
+
+ if (fold && handle && fold->handle != handle)
+ return -EINVAL;
+
+ fnew = kzalloc(sizeof(*fnew), GFP_KERNEL);
+ if (!fnew)
+ return -ENOBUFS;
+
+ tcf_exts_init(&fnew->exts, TCA_OF_ACT, TCA_OF_POLICE);
+
+ if (!handle) {
+ handle = of_grab_new_handle(tp, head);
+ if (!handle) {
+ err = -EINVAL;
+ goto errout;
+ }
+ }
+ fnew->handle = handle;
+
+ err = of_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr);
+ if (err < 0)
+ goto errout;
+
+ *arg = (unsigned long) fnew;
+
+ if (fold) {
+ list_replace_rcu(&fnew->list, &fold->list);
+ tcf_unbind_filter(tp, &fold->res);
+ call_rcu(&fold->rcu, of_destroy_filter);
+ } else {
+ list_add_tail_rcu(&fnew->list, &head->filters);
+ }
+
+ return 0;
+
+errout:
+ kfree(fnew);
+ return err;
+}
+
+static int of_delete(struct tcf_proto *tp, unsigned long arg)
+{
+ struct cls_of_filter *f = (struct cls_of_filter *) arg;
+
+ list_del_rcu(&f->list);
+ tcf_unbind_filter(tp, &f->res);
+ call_rcu(&f->rcu, of_destroy_filter);
+ return 0;
+}
+
+static void of_walk(struct tcf_proto *tp, struct tcf_walker *arg)
+{
+ struct cls_of_head *head = rtnl_dereference(tp->root);
+ struct cls_of_filter *f;
+
+ list_for_each_entry_rcu(f, &head->filters, list) {
+ if (arg->count < arg->skip)
+ goto skip;
+ if (arg->fn(tp, (unsigned long) f, arg) < 0) {
+ arg->stop = 1;
+ break;
+ }
+skip:
+ arg->count++;
+ }
+}
+
+static int of_dump_key_val(struct sk_buff *skb,
+ void *val, int val_type,
+ void *mask, int mask_type, int len)
+{
+ int err;
+
+ if (!memchr_inv(mask, 0, len))
+ return 0;
+ err = nla_put(skb, val_type, len, val);
+ if (err)
+ return err;
+ err = nla_put(skb, mask_type, len, mask);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int of_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
+ struct sk_buff *skb, struct tcmsg *t)
+{
+ struct cls_of_filter *f = (struct cls_of_filter *) fh;
+ struct nlattr *nest;
+ struct of_flow_key *key, *mask;
+
+ if (!f)
+ return skb->len;
+
+ t->tcm_handle = f->handle;
+
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (!nest)
+ goto nla_put_failure;
+
+ if (f->res.classid &&
+ nla_put_u32(skb, TCA_BASIC_CLASSID, f->res.classid))
+ goto nla_put_failure;
+
+ key = &f->match.key;
+ mask = &f->match.mask;
+
+ if (mask->indev_ifindex) {
+ struct net_device *dev;
+
+ dev = __dev_get_by_index(net, key->indev_ifindex);
+ if (dev && nla_put_string(skb, TCA_OF_INDEV, dev->name))
+ goto nla_put_failure;
+ }
+
+ if (of_dump_key_val(skb, key->eth.dst, TCA_OF_KEY_ETH_DST,
+ mask->eth.dst, TCA_OF_KEY_ETH_DST_MASK,
+ sizeof(key->eth.dst)) ||
+ of_dump_key_val(skb, key->eth.src, TCA_OF_KEY_ETH_SRC,
+ mask->eth.src, TCA_OF_KEY_ETH_SRC_MASK,
+ sizeof(key->eth.src)) ||
+ of_dump_key_val(skb, &key->eth.type, TCA_OF_KEY_ETH_TYPE,
+ &mask->eth.type, TCA_OF_KEY_ETH_TYPE_MASK,
+ sizeof(key->eth.type)) ||
+ of_dump_key_val(skb, &key->ip.proto, TCA_OF_KEY_IP_PROTO,
+ &mask->ip.proto, TCA_OF_KEY_IP_PROTO_MASK,
+ sizeof(key->ip.proto)) ||
+ of_dump_key_val(skb, &key->ipv4.src, TCA_OF_KEY_IPV4_SRC,
+ &mask->ipv4.src, TCA_OF_KEY_IPV4_SRC_MASK,
+ sizeof(key->ipv4.src)) ||
+ of_dump_key_val(skb, &key->ipv4.dst, TCA_OF_KEY_IPV4_DST,
+ &mask->ipv4.dst, TCA_OF_KEY_IPV4_DST_MASK,
+ sizeof(key->ipv4.dst)) ||
+ of_dump_key_val(skb, &key->ipv6.src, TCA_OF_KEY_IPV6_SRC,
+ &mask->ipv6.src, TCA_OF_KEY_IPV6_SRC_MASK,
+ sizeof(key->ipv6.src)) ||
+ of_dump_key_val(skb, &key->ipv6.dst, TCA_OF_KEY_IPV6_DST,
+ &mask->ipv6.dst, TCA_OF_KEY_IPV6_DST_MASK,
+ sizeof(key->ipv6.dst)) ||
+ of_dump_key_val(skb, &key->tp.src, TCA_OF_KEY_TP_SRC,
+ &mask->tp.src, TCA_OF_KEY_TP_SRC_MASK,
+ sizeof(key->tp.src)) ||
+ of_dump_key_val(skb, &key->tp.dst, TCA_OF_KEY_TP_DST,
+ &mask->tp.dst, TCA_OF_KEY_TP_DST_MASK,
+ sizeof(key->tp.dst)))
+ goto nla_put_failure;
+
+ if (tcf_exts_dump(skb, &f->exts))
+ goto nla_put_failure;
+
+ nla_nest_end(skb, nest);
+
+ if (tcf_exts_dump_stats(skb, &f->exts) < 0)
+ goto nla_put_failure;
+
+ return skb->len;
+
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
+ return -1;
+}
+
+static struct tcf_proto_ops cls_of_ops __read_mostly = {
+ .kind = "openflow",
+ .classify = of_classify,
+ .init = of_init,
+ .destroy = of_destroy,
+ .get = of_get,
+ .change = of_change,
+ .delete = of_delete,
+ .walk = of_walk,
+ .dump = of_dump,
+ .owner = THIS_MODULE,
+};
+
+static int __init cls_of_init(void)
+{
+ return register_tcf_proto_ops(&cls_of_ops);
+}
+
+static void __exit cls_of_exit(void)
+{
+ unregister_tcf_proto_ops(&cls_of_ops);
+}
+
+module_init(cls_of_init);
+module_exit(cls_of_exit);
+
+MODULE_AUTHOR("Jiri Pirko <jiri@resnulli.us>");
+MODULE_DESCRIPTION("OpenFlow classifier");
+MODULE_LICENSE("GPL v2");
--
1.9.3
^ permalink raw reply related
* Re: [net-next PATCH v3 00/12] Flow API
From: Thomas Graf @ 2015-01-22 13:37 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: John Fastabend, simon.horman, sfeldma, netdev, jhs, davem,
gerlitz.or, andy, ast
In-Reply-To: <20150122125246.GA4486@salvia>
On 01/22/15 at 01:52pm, Pablo Neira Ayuso wrote:
> Hi John,
>
> On Tue, Jan 20, 2015 at 12:26:13PM -0800, John Fastabend wrote:
> > I believe I addressed all the comments so far except for the integrate
> > with 'tc'. I plan to work on the integration pieces next.
>
> I think that postponing the integration with 'tc' means that we're
> renouncing to provide some abstraction to represent the actions that
> the device provides. After this patch we'll have a standard API that
> exposes the vendor specific semantics, *so user configurations will
> not be portable anymore*.
>
> At least, we should come up with some abstraction / mapping as
> interface, so the vendors can use them to represent their operations.
> That interface will provide a trade-off: If the vendor offers an
> operation that doesn't map to our abstraction, then sorry that
> operation has to remain behind the curtain.
I thought this *is* the abstraction ;-) Can you elaborate on which
parts you consider vendor specific?
^ permalink raw reply
* Re: [bisected] no traffic on ssl vpn with 3.19rc1 - 3.19rc3
From: Billy Shuman @ 2015-01-22 13:43 UTC (permalink / raw)
To: Herbert Xu; +Cc: netdev
In-Reply-To: <CAHQNsodDfSOgmxoSk6++OQXfJ7SHo+M=bmojfUqN1KFJHtfemg@mail.gmail.com>
This patch from net-next ended up resolving my issue:
>From 957f094f221f81e457133b1f4c4d95ffa49ff731 Mon Sep 17 00:00:00 2001
From: Alex Gartrell <agartrell@fb.com>
Date: Thu, 25 Dec 2014 23:22:49 -0800
Subject: tun: return proper error code from tun_do_read
Instead of -1 with EAGAIN, read on a O_NONBLOCK tun fd will return 0. This
fixes this by properly returning the error code from __skb_recv_datagram.
On Fri, Jan 9, 2015 at 8:13 AM, Billy Shuman <wshuman3@gmail.com> wrote:
> Changeset 8c847d254146d32c86574a1b16923ff91bb784dd did not resolve the
> issue for me.
>
> Should I target any other specific changesets?
>
> Thanks,
> Billy
> William Shuman
> Tel: 260-316-9300
> Email: wshuman3@gmail.com
>
>
> On Thu, Jan 8, 2015 at 3:57 PM, Herbert Xu <herbert@gondor.apana.org.au> wrote:
>> Billy Shuman <wshuman3@gmail.com> wrote:
>>>
>>> Since 3.19rc1 I get 100% packet loss through SSL vpn. I bisected with
>>> the following result:
>>>
>>> 0b46d0ee9c240c7430a47e9b0365674d4a04522 is the first bad commit
>>> commit e0b46d0ee9c240c7430a47e9b0365674d4a04522
>>> Author: Herbert Xu <herbert@gondor.apana.org.au>
>>> Date: Fri Nov 7 21:22:23 2014 +0800
>>>
>>> tun: Use iovec iterators
>>>
>>> This patch removes the use of skb_copy_datagram_const_iovec in
>>> favour of the iovec iterator-based skb_copy_datagram_iter.
>>>
>>>
>>> https://bugzilla.kernel.org/show_bug.cgi?id=90901
>>
>> This changeset is known to be buggy. However it was fixed ages
>> ago by changeset 8c847d254146d32c86574a1b16923ff91bb784dd.
>>
>> So please test that changeset to see if it works for you. If it
>> does, then please do your bisection between that and the current
>> top of tree.
>>
>> Thanks,
>> --
>> Email: Herbert Xu <herbert@gondor.apana.org.au>
>> Home Page: http://gondor.apana.org.au/~herbert/
>> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* RE: [patch net-next RFC] tc: introduce OpenFlow classifier
From: Rosen, Rami @ 2015-01-22 13:48 UTC (permalink / raw)
To: Jiri Pirko, netdev@vger.kernel.org; +Cc: davem@davemloft.net, jhs@mojatatu.com
In-Reply-To: <1421933824-17916-1-git-send-email-jiri@resnulli.us>
+config NET_CLS_OPENFLOW
+ tristate "OpenFlow classifier"
+ select NET_CLS
+ ---help---
+ If you say Y here, you will be able to classify packets based on
+ a configurable combination of packet keys and masks accordint to
+ OpenFlow standard.
+
Should be: according to
Regards,
Rami Rosen
^ permalink raw reply
* Re: [PATCH] brcmfmac: avoid duplicated suspend/resume operation
From: Kalle Valo @ 2015-01-22 13:49 UTC (permalink / raw)
To: Fu, Zhonghui
Cc: brudley-dY08KVG/lbpWk0Htik3J/w, Arend van Spriel, Franky Lin,
meuleman-dY08KVG/lbpWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
pieterpg-dY08KVG/lbpWk0Htik3J/w, hdegoede-H+wXaHxf7aLQT0dZR+AlfA,
wens-jdAy2FN1RRM, linux-wireless-u79uwXL29TY76Z2rM5mHXA,
brcm80211-dev-list-dY08KVG/lbpWk0Htik3J/w,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-kernel@vger.kernel.org
In-Reply-To: <54BDCC06.8090107-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
"Fu, Zhonghui" <zhonghui.fu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> writes:
>>From 04d3fa673897ca4ccbea6c76836d0092dba2484a Mon Sep 17 00:00:00 2001
> From: Zhonghui Fu <zhonghui.fu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> Date: Tue, 20 Jan 2015 11:14:13 +0800
> Subject: [PATCH] brcmfmac: avoid duplicated suspend/resume operation
>
> WiFi chip has 2 SDIO functions, and PM core will trigger
> twice suspend/resume operations for one WiFi chip to do
> the same things. This patch avoid this case.
>
> Acked-by: Arend van Spriel <arend-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> Acked-by: Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
> Acked-by: Kalle Valo <kvalo-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Signed-off-by: Zhonghui Fu <zhonghui.fu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
I don't remember giving Acked-by to this (or for matter to anything for
a long time). What about Sergei or Arend?
Please do not add Acked-by, Signed-off-by or any other tags unless
explicitly specified by the person in question. I'm dropping this,
please resend with real Acked-by lines.
--
Kalle Valo
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net 4/4] sh_eth: Fix serialisation of interrupt disable with interrupt & NAPI handlers
From: Sergei Shtylyov @ 2015-01-22 13:50 UTC (permalink / raw)
To: Ben Hutchings, David S.Miller
Cc: netdev, linux-kernel, Nobuhiro Iwamatsu, Mitsuhiro Kimura,
Hisashi Nakamura, Yoshihiro Kaneko
In-Reply-To: <1421930648.1222.289.camel@xylophone.i.decadent.org.uk>
Hello.
On 1/22/2015 3:44 PM, Ben Hutchings wrote:
> In order to stop the RX path accessing the RX ring while it's being
> stopped or resized, we clear the interrupt mask (EESIPR) and then call
> free_irq() or synchronise_irq(). This is insufficient because the
> interrupt handler or NAPI poller may set EESIPR again after we clear
> it.
Hm, how come the interrupt handler gets called when we have disabled all
interrupts? Is it unmaskable EESR.ECI interrupt? BTW, I'm not seeing where the
interrupt handler enables interrupts again; only NAPI poller does that AFAIK.
> Also, in sh_eth_set_ringparam() we currently don't disable NAPI
> polling at all.
> I could easily trigger a crash by running the loop:
> while ethtool -G eth0 rx 128 && ethtool -G eth0 rx 64; do echo -n .; done
Oh, never done any 'ethtool' tests...
> and 'ping -f' toward the sh_eth port from another machine.
To fix this:
> - Add a software flag (irq_enabled) to signal whether interrupts
> should be enabled
> - In the interrupt handler, if the flag is clear then clear EESIPR
> and return
> - In the NAPI poller, if the flag is clear then don't set EESIPR
> - Set the flag before enabling interrupts in sh_eth_dev_init() and
> sh_eth_set_ringparam()
> - Clear the flag and serialise with the interrupt and NAPI
> handlers before clearing EESIPR in sh_eth_close() and
> sh_eth_set_ringparam()
> After this, I could run the loop for 100,000 iterations successfully.
> Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
[...]
> diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
> index 7bfaf1c..259d03f 100644
> --- a/drivers/net/ethernet/renesas/sh_eth.h
> +++ b/drivers/net/ethernet/renesas/sh_eth.h
> @@ -513,6 +513,7 @@ struct sh_eth_private {
> u32 rx_buf_sz; /* Based on MTU+slack. */
> int edmac_endian;
> struct napi_struct napi;
> + bool irq_enabled;
> /* MII transceiver section. */
> u32 phy_id; /* PHY ID */
> struct mii_bus *mii_bus; /* MDIO bus control */
In order to conserve space, I'd have added that field after
'vlan_num_ids', just before the 1-bit fields...
WBR, Sergei
^ permalink raw reply
* Re: [PATCH] brcmfmac: avoid duplicated suspend/resume operation
From: Sergei Shtylyov @ 2015-01-22 13:54 UTC (permalink / raw)
To: Kalle Valo, Fu, Zhonghui
Cc: brudley-dY08KVG/lbpWk0Htik3J/w, Arend van Spriel, Franky Lin,
meuleman-dY08KVG/lbpWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
pieterpg-dY08KVG/lbpWk0Htik3J/w, hdegoede-H+wXaHxf7aLQT0dZR+AlfA,
wens-jdAy2FN1RRM, linux-wireless-u79uwXL29TY76Z2rM5mHXA,
brcm80211-dev-list-dY08KVG/lbpWk0Htik3J/w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <87twzincvz.fsf-HodKDYzPHsUD5k0oWYwrnHL1okKdlPRT@public.gmane.org>
Hello.
On 1/22/2015 4:49 PM, Kalle Valo wrote:
>> >From 04d3fa673897ca4ccbea6c76836d0092dba2484a Mon Sep 17 00:00:00 2001
>> From: Zhonghui Fu <zhonghui.fu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
>> Date: Tue, 20 Jan 2015 11:14:13 +0800
>> Subject: [PATCH] brcmfmac: avoid duplicated suspend/resume operation
>> WiFi chip has 2 SDIO functions, and PM core will trigger
>> twice suspend/resume operations for one WiFi chip to do
>> the same things. This patch avoid this case.
>> Acked-by: Arend van Spriel <arend-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
>> Acked-by: Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
>> Acked-by: Kalle Valo <kvalo-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>> Signed-off-by: Zhonghui Fu <zhonghui.fu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> I don't remember giving Acked-by to this (or for matter to anything for
> a long time). What about Sergei or Arend?
I haven't ACK'ed this patch either.
WBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [net-next PATCH v3 00/12] Flow API
From: Pablo Neira Ayuso @ 2015-01-22 14:00 UTC (permalink / raw)
To: Thomas Graf
Cc: John Fastabend, simon.horman, sfeldma, netdev, jhs, davem,
gerlitz.or, andy, ast
In-Reply-To: <20150122133713.GA25797@casper.infradead.org>
On Thu, Jan 22, 2015 at 01:37:13PM +0000, Thomas Graf wrote:
> On 01/22/15 at 01:52pm, Pablo Neira Ayuso wrote:
> > Hi John,
> >
> > On Tue, Jan 20, 2015 at 12:26:13PM -0800, John Fastabend wrote:
> > > I believe I addressed all the comments so far except for the integrate
> > > with 'tc'. I plan to work on the integration pieces next.
> >
> > I think that postponing the integration with 'tc' means that we're
> > renouncing to provide some abstraction to represent the actions that
> > the device provides. After this patch we'll have a standard API that
> > exposes the vendor specific semantics, *so user configurations will
> > not be portable anymore*.
> >
> > At least, we should come up with some abstraction / mapping as
> > interface, so the vendors can use them to represent their operations.
> > That interface will provide a trade-off: If the vendor offers an
> > operation that doesn't map to our abstraction, then sorry that
> > operation has to remain behind the curtain.
>
> I thought this *is* the abstraction ;-) Can you elaborate on which
> parts you consider vendor specific?
+/* rocker specific action definitions */
+struct net_flow_action_arg rocker_set_group_id_args[] = {
+ {
+ .name = "group_id",
+ .type = NFL_ACTION_ARG_TYPE_U32,
+ .value_u32 = 0,
+ },
that is retrieved via ndo_flow_get_actions and fully exposed to
userspace.
^ permalink raw reply
* Re: [PATCH net-next 0/9] mlx4: Fix and enhance the device reset flow
From: Or Gerlitz @ 2015-01-22 14:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Matan Barak, Amir Vadai, Tal Alon, Roland Dreier
In-Reply-To: <1421851557-12084-1-git-send-email-ogerlitz@mellanox.com>
On 1/21/2015 4:45 PM, Or Gerlitz wrote:
> This series from Yishai Hadas fixes the device reset flow and adds SRIOV support.
>
> Reset flows are required whenever a device experiences errors, is unresponsive,
> or is not in a deterministic state. In such cases, the driver is expected to
> reset the HW and continue operation. When SRIOV is enabled, these requirements
> apply both to PF and VF devices.
So we spotted some problem in the SRIOV flow and prefer to fix it in a
V1, which will be sent next week, please don't take this one.
Or.
^ permalink raw reply
* [PATCH v3] net: mv643xx_eth: Fix highmem support in non-TSO egress path
From: Ezequiel Garcia @ 2015-01-22 14:33 UTC (permalink / raw)
To: David Miller, Russell King
Cc: netdev, B38611, fabio.estevam, David.Laight, Ezequiel Garcia
In-Reply-To: <1421928859-17923-1-git-send-email-ezequiel.garcia@free-electrons.com>
Commit 69ad0dd7af22b61d9e0e68e56b6290121618b0fb
Author: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Date: Mon May 19 13:59:59 2014 -0300
net: mv643xx_eth: Use dma_map_single() to map the skb fragments
caused a nasty regression by removing the support for highmem skb
fragments. By using page_address() to get the address of a fragment's
page, we are assuming a lowmem page. However, such assumption is incorrect,
as fragments can be in highmem pages, resulting in very nasty issues.
This commit fixes this by using the skb_frag_dma_map() helper,
which takes care of mapping the skb fragment properly. Additionally,
the type of mapping is now tracked, so it can be unmapped using
dma_unmap_page or dma_unmap_single when appropriate.
This commit also fixes the error path in txq_init() to release the
resources properly.
Fixes: 69ad0dd7af22 ("net: mv643xx_eth: Use dma_map_single() to map the skb fragments")
Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
Changes from v2:
* Add proper resource release in txq_init() error path
Changes from v1:
* Sending the mv643xx_eth fix for now.
* Fix DMA mapping type track, to use the correct unmap call.
---
drivers/net/ethernet/marvell/mv643xx_eth.c | 59 +++++++++++++++++++++++++-----
1 file changed, 49 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index a62fc38..1c75829 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -192,6 +192,10 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define IS_TSO_HEADER(txq, addr) \
((addr >= txq->tso_hdrs_dma) && \
(addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE))
+
+#define DESC_DMA_MAP_SINGLE 0
+#define DESC_DMA_MAP_PAGE 1
+
/*
* RX/TX descriptors.
*/
@@ -362,6 +366,7 @@ struct tx_queue {
dma_addr_t tso_hdrs_dma;
struct tx_desc *tx_desc_area;
+ char *tx_desc_mapping; /* array to track the type of the dma mapping */
dma_addr_t tx_desc_dma;
int tx_desc_area_size;
@@ -750,6 +755,7 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
desc->l4i_chk = 0;
desc->byte_cnt = length;
@@ -879,14 +885,13 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
skb_frag_t *this_frag;
int tx_index;
struct tx_desc *desc;
- void *addr;
this_frag = &skb_shinfo(skb)->frags[frag];
- addr = page_address(this_frag->page.p) + this_frag->page_offset;
tx_index = txq->tx_curr_desc++;
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_PAGE;
/*
* The last fragment will generate an interrupt
@@ -902,8 +907,9 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
desc->l4i_chk = 0;
desc->byte_cnt = skb_frag_size(this_frag);
- desc->buf_ptr = dma_map_single(mp->dev->dev.parent, addr,
- desc->byte_cnt, DMA_TO_DEVICE);
+ desc->buf_ptr = skb_frag_dma_map(mp->dev->dev.parent,
+ this_frag, 0, desc->byte_cnt,
+ DMA_TO_DEVICE);
}
}
@@ -936,6 +942,7 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb,
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
+ txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
if (nr_frags) {
txq_submit_frag_skb(txq, skb);
@@ -1047,9 +1054,12 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
int tx_index;
struct tx_desc *desc;
u32 cmd_sts;
+ char desc_dma_map;
tx_index = txq->tx_used_desc;
desc = &txq->tx_desc_area[tx_index];
+ desc_dma_map = txq->tx_desc_mapping[tx_index];
+
cmd_sts = desc->cmd_sts;
if (cmd_sts & BUFFER_OWNED_BY_DMA) {
@@ -1065,9 +1075,19 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
reclaimed++;
txq->tx_desc_count--;
- if (!IS_TSO_HEADER(txq, desc->buf_ptr))
- dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
- desc->byte_cnt, DMA_TO_DEVICE);
+ if (!IS_TSO_HEADER(txq, desc->buf_ptr)) {
+
+ if (desc_dma_map == DESC_DMA_MAP_PAGE)
+ dma_unmap_page(mp->dev->dev.parent,
+ desc->buf_ptr,
+ desc->byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_single(mp->dev->dev.parent,
+ desc->buf_ptr,
+ desc->byte_cnt,
+ DMA_TO_DEVICE);
+ }
if (cmd_sts & TX_ENABLE_INTERRUPT) {
struct sk_buff *skb = __skb_dequeue(&txq->tx_skb);
@@ -1996,6 +2016,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
struct tx_queue *txq = mp->txq + index;
struct tx_desc *tx_desc;
int size;
+ int ret;
int i;
txq->index = index;
@@ -2048,18 +2069,34 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
nexti * sizeof(struct tx_desc);
}
+ txq->tx_desc_mapping = kcalloc(txq->tx_ring_size, sizeof(char),
+ GFP_KERNEL);
+ if (!txq->tx_desc_mapping) {
+ ret = -ENOMEM;
+ goto err_free_desc_area;
+ }
+
/* Allocate DMA buffers for TSO MAC/IP/TCP headers */
txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent,
txq->tx_ring_size * TSO_HEADER_SIZE,
&txq->tso_hdrs_dma, GFP_KERNEL);
if (txq->tso_hdrs == NULL) {
- dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,
- txq->tx_desc_area, txq->tx_desc_dma);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_free_desc_mapping;
}
skb_queue_head_init(&txq->tx_skb);
return 0;
+
+err_free_desc_mapping:
+ kfree(txq->tx_desc_mapping);
+err_free_desc_area:
+ if (index == 0 && size <= mp->tx_desc_sram_size)
+ iounmap(txq->tx_desc_area);
+ else
+ dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,
+ txq->tx_desc_area, txq->tx_desc_dma);
+ return ret;
}
static void txq_deinit(struct tx_queue *txq)
@@ -2077,6 +2114,8 @@ static void txq_deinit(struct tx_queue *txq)
else
dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,
txq->tx_desc_area, txq->tx_desc_dma);
+ kfree(txq->tx_desc_mapping);
+
if (txq->tso_hdrs)
dma_free_coherent(mp->dev->dev.parent,
txq->tx_ring_size * TSO_HEADER_SIZE,
--
2.2.1
^ permalink raw reply related
* Re: [net-next PATCH v3 00/12] Flow API
From: Jamal Hadi Salim @ 2015-01-22 15:00 UTC (permalink / raw)
To: Pablo Neira Ayuso, Thomas Graf
Cc: John Fastabend, simon.horman, sfeldma, netdev, davem, gerlitz.or,
andy, ast, Jiri Pirko
In-Reply-To: <20150122140022.GA5674@salvia>
On 01/22/15 09:00, Pablo Neira Ayuso wrote:
>
> +/* rocker specific action definitions */
> +struct net_flow_action_arg rocker_set_group_id_args[] = {
> + {
> + .name = "group_id",
> + .type = NFL_ACTION_ARG_TYPE_U32,
> + .value_u32 = 0,
> + },
>
> that is retrieved via ndo_flow_get_actions and fully exposed to
> userspace.
>
My main concern is along similar lines (I did express it earlier and
I think Jiri chimed in as well).
The API exposes direct access to hardware. I am sure this was a result
of trying to replace the ethtool interface (which was primitive).
By providing vendors direct access to the hardware - they do not need
to use any traditional Linux tooling/APIs. I see this as a gaping hole
for vendor SDKs with their own definitions of their own hardware that
doesnt work with anyone else. i.e it seems to standardize proprietary
interfaces. Maybe thats what Pablo is alluding to.
Interfacing tc or nftables (or pick your favorite linux tool here) would
be preferable.
cheers,
jamal
^ 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