* Re: [PATCH v13 0/6] flexcan: Add support for powerpc flexcan (freescale p1010)
From: Robin Holt @ 2011-10-18 12:30 UTC (permalink / raw)
To: Kumar Gala
Cc: Grant Likely, netdev-u79uwXL29TY76Z2rM5mHXA, U Bhaskar-B22300,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
PPC list, David S. Miller, Wolfgang Grandegger
In-Reply-To: <D79CB818-C14E-4C8D-9A8D-42B39ADE20B2-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
On Tue, Oct 18, 2011 at 06:43:13AM -0500, Kumar Gala wrote:
>
> >> Robin,
> >>
> >> Do you remember why we went with just 'fsl,p1010-flexcan' as the device tree compatible? Do we feel the flex can on P1010 isn't the same as on MPC5xxx? or the ARM SoCs?
> >
> > The decision was due to the fact there is no true "generic" fsl.flexcan
> > chip free of any SOC implementation and therefore not something which
> > could be separately defined. That decision was made by Grant Likely.
> > I will inline that email below.
> >
> > Robin
>
>
> Thanks, I'll look into this internally at FSL. I think its confusing as hell to have "fsl,p1010-flexcan" in an ARM .dts and don't think any reasonable ARM customer of FSL would know to put a PPC SOC name in their .dts. I'll ask the HW guys what's going on so we can come up with a bit more generic name so we don't have to constantly change this. Even if its just:
Grants argument was that there should then be a fsl,zeba-flexcan which
would define each arm based soc. The match string could be there and
the devicetree binding would match on each equivalent.
Robin
>
> fsl,ppc-flexcan & fsl,arm-flexcan.
>
> > On Mon, Aug 15, 2011 at 09:13:50AM -0600, Grant Likely wrote:
> >> On Mon, Aug 15, 2011 at 9:03 AM, Robin Holt <holt-sJ/iWh9BUns@public.gmane.org> wrote:
> >>> Grant,
> >>>
> >>> Earlier, you had asked for a more specific name for the compatible
> >>> property of the Freescale flexcan device. I still have not gotten a
> >>> more specific answer. Hopefully Marc can give you more details about
> >>> the flexcan implementations.
> >>
> >> If there is no ip core version, then just stick with the
> >> fsl,<soc>-flexcan name and drop "fsl,flexcan". Marketing may say
> >> flexcan is flexcan, but hardware engineers like to change things.
> >> Trying to be too generic in compatible values will just lead to
> >> problems in the future.
> >
> > Thanks,
> > Robin
>
> - k
^ permalink raw reply
* Re: [net-next] stmmac: limit max_mtu in case of 4KiB and use __netdev_alloc_skb (V2)
From: Eric Dumazet @ 2011-10-18 12:26 UTC (permalink / raw)
To: Giuseppe CAVALLARO; +Cc: netdev, davem
In-Reply-To: <1318937995-14228-1-git-send-email-peppe.cavallaro@st.com>
Le mardi 18 octobre 2011 à 13:39 +0200, Giuseppe CAVALLARO a écrit :
> Problem using big mtu around 4096 bytes is you end allocating (4096
> +NET_SKB_PAD + NET_IP_ALIGN + sizeof(struct skb_shared_info) bytes ->
> 8192 bytes : order-1 pages
>
> It's better to limit the mtu to SKB_MAX_HEAD(NET_SKB_PAD),
> to have no more than one page per skb.
>
> Also the patch changes the netdev_alloc_skb_ip_align() done in
> init_dma_desc_rings() and uses a variant allowing GFP_KERNEL allocations
> allowing the driver to load even in case of memory pressure.
>
> Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
Seems good, thanks :)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* Re: BUG: All network processes hang (brcmsmac/wpa_supplicant)
From: Eric Dumazet @ 2011-10-18 12:24 UTC (permalink / raw)
To: Nico Schottelius; +Cc: LKML, netdev
In-Reply-To: <20111018111422.GA1979@schottelius.org>
Le mardi 18 octobre 2011 à 13:14 +0200, Nico Schottelius a écrit :
> Dear LKML,
>
> there is a rather nasty bug in all recent kernels (probably older as
> well):
>
> If wpa_supplicant looses the connection to an AP, all network calls
> hang, uninterruptle.
>
> This is a snippet of running fetchmail after the problem started:
>
> socket(PF_NETLINK, SOCK_RAW, 0) = 4
> bind(4, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
> getsockname(4, {sa_family=AF_NETLINK, pid=9734, groups=00000000}, [12]) = 0
> sendto(4, "\24\0\0\0\26\0\1\3\225\\\235N\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12
>
> [12:59] brief:linux-2.6% ps aux | grep fetchmail
> nico 9063 0.0 0.0 20652 1492 pts/3 D+ 12:55 0:00 fetchmail
> nico 9564 0.0 0.0 20652 1496 pts/15 D+ 13:01 0:00 fetchmail
> nico 9731 0.0 0.0 4288 724 pts/34 S+ 13:01 0:00 strace -fF fetchmail
> nico 9734 0.0 0.0 20652 1492 pts/34 D+ 13:01 0:00 fetchmail
>
> This is particular nasty, because even calling "sudo -i" does a sendto() call
> and thus hangs, as well as trying to send this mail with sendmail makes mutt hang.
>
> I've seen that on stock Archlinux kernel (linux 3.0.6-2),
> latest from Linus (v3.1-rc9-93-ga84a79e), merged trees from Keith and Jiri
> (3.1.0-rc6-gbee709a).
>
> Listing of hanging processes:
>
> [13:05] brief:linux-2.6% ps aux | grep D
> USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
> root 9056 0.2 0.0 0 0 ? D 12:54 0:02 [kworker/u:0]
> nico 9063 0.0 0.0 20652 1492 pts/3 D+ 12:55 0:00 fetchmail
> nico 9066 0.0 0.0 16548 1180 ? D 12:56 0:00 sendmail -oem -oi -f ME@inf.ethz.ch -- RECIPIENT
> root 9067 0.0 0.0 6060 320 pts/14 DN 12:56 0:00 ip r
> root 9124 0.0 0.0 6060 320 pts/14 DN 12:57 0:00 ip r add 192.168.42.1/24 dev lo
> root 9390 0.0 0.0 11996 784 pts/12 D+ 13:01 0:00 sudo -i
> nico 9564 0.0 0.0 20652 1496 pts/15 D+ 13:01 0:00 fetchmail
> nico 9734 0.0 0.0 20652 1492 pts/34 D+ 13:01 0:00 fetchmail
> root 12304 0.0 0.0 28624 2228 ? Ds 09:16 0:00 wpa_supplicant -B -P /run/wpa_supplicant_wlan0.pid -i wlan0 -D nl80211,wext -c /run/network//wpa.wlan0/wpa.conf
> [13:07] brief:linux-2.6%
>
> The hardware is again the (in)famous MacBook Air 4,2, so I imagine this may be
> related to brcmsmac.
>
> Attached are config, dmesg, lsmod.
Must be a mutex_unlock(some_mltex) missing somewhere.
Then later, a process holding RTNL is blocking on mutex_lock(some_mutex)
Try a "CONFIG_LOCKDEP=y" enabled build
^ permalink raw reply
* Re: [patch] pktgen: bug when calling ndelay in x86 architectures
From: Eric Dumazet @ 2011-10-18 11:56 UTC (permalink / raw)
To: Daniel Turull
Cc: David Miller, netdev, Robert Olsson, Voravit Tanyingyong,
Jens Laas
In-Reply-To: <4E9D5E1B.3080704@gmail.com>
Le mardi 18 octobre 2011 à 13:08 +0200, Daniel Turull a écrit :
> The value selected to delay the transmission in pktgen with the ndelay function should be lower.
> In Linux/arch/x86/include/asm/delay.h and Linux/arch/sh/include/asm/delay.h
> the maximal expected value for a constant is 20000 ns.
>
> Signed-off-by: Daniel Turull <daniel.turull@gmail.com>
> ---
> diff --git a/net/core/pktgen.c b/net/core/pktgen.c
> index 796044a..e17bd41 100644
> --- a/net/core/pktgen.c
> +++ b/net/core/pktgen.c
> @@ -2145,7 +2145,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
> }
>
> start_time = ktime_now();
> - if (remaining < 100000)
> + if (remaining < 20000)
> ndelay(remaining); /* really small just spin */
> else {
> /* see do_nanosleep */
But 'remaining' is not a constant.
If we want exactly 40.000 packets per second rate (25 us between
packets), your patch makes this not quite possible without
CONFIG_HIGH_RES_TIMERS and probable high jitter because of scheduler
effects.
pktgen is kind of special, we _want_ a cpu for our exclusive use.
^ permalink raw reply
* Re: PROBLEM: System call 'sendmsg' of process ospfd (quagga) causes kernel oops
From: Herbert Xu @ 2011-10-18 11:49 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Elmar Vonlanthen, linux-kernel, netdev, Timo Teräs
In-Reply-To: <1318937878.2657.50.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On Tue, Oct 18, 2011 at 01:37:58PM +0200, Eric Dumazet wrote:
>
> In the bug we try to fix, we have :
>
> skb = sock_alloc_send_skb(sk, ... + LL_ALLOCATED_SPACE(rt->dst.dev)
>
> ... < increase of dev->needed_headroom by another cpu/task >
>
> skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev));
OK, in that case one fix would be to replace LL_ALLOCATED_SPACE
with its two constiuents so that they may be stored in local
variables for later use.
hlen = LL_HEADROOM(skb);
tlen = LL_TAILROOM(skb);
skb_alloc_send_skb(sk, ... + LL_ALIGN(hlen + tlen));
skb_reserve(skb, LL_ALIGN(hlen));
Cheers,
--
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 v13 0/6] flexcan: Add support for powerpc flexcan (freescale p1010)
From: Marc Kleine-Budde @ 2011-10-18 11:48 UTC (permalink / raw)
To: Kumar Gala
Cc: Grant Likely, netdev-u79uwXL29TY76Z2rM5mHXA, U Bhaskar-B22300,
linux-can-u79uwXL29TY76Z2rM5mHXA,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w, PPC list, David S. Miller,
Wolfgang Grandegger
In-Reply-To: <D79CB818-C14E-4C8D-9A8D-42B39ADE20B2-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 857 bytes --]
On 10/18/2011 01:43 PM, Kumar Gala wrote:
> Thanks, I'll look into this internally at FSL. I think its confusing
> as hell to have "fsl,p1010-flexcan" in an ARM .dts and don't think
> any reasonable ARM customer of FSL would know to put a PPC SOC name
> in their .dts. I'll ask the HW guys what's going on so we can come
> up with a bit more generic name so we don't have to constantly change
> this. Even if its just:
>
> fsl,ppc-flexcan & fsl,arm-flexcan.
If you talk the HW guys ask them for a name for the coldfire flexcan
core, too please ;)
cheers, Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
[-- Attachment #2: Type: text/plain, Size: 188 bytes --]
_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core
^ permalink raw reply
* Re: [PATCH v13 0/6] flexcan: Add support for powerpc flexcan (freescale p1010)
From: Kumar Gala @ 2011-10-18 11:43 UTC (permalink / raw)
To: Robin Holt
Cc: Grant Likely, netdev-u79uwXL29TY76Z2rM5mHXA, U Bhaskar-B22300,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
PPC list, David S. Miller, Wolfgang Grandegger
In-Reply-To: <20111018094328.GC22814-sJ/iWh9BUns@public.gmane.org>
>> Robin,
>>
>> Do you remember why we went with just 'fsl,p1010-flexcan' as the device tree compatible? Do we feel the flex can on P1010 isn't the same as on MPC5xxx? or the ARM SoCs?
>
> The decision was due to the fact there is no true "generic" fsl.flexcan
> chip free of any SOC implementation and therefore not something which
> could be separately defined. That decision was made by Grant Likely.
> I will inline that email below.
>
> Robin
Thanks, I'll look into this internally at FSL. I think its confusing as hell to have "fsl,p1010-flexcan" in an ARM .dts and don't think any reasonable ARM customer of FSL would know to put a PPC SOC name in their .dts. I'll ask the HW guys what's going on so we can come up with a bit more generic name so we don't have to constantly change this. Even if its just:
fsl,ppc-flexcan & fsl,arm-flexcan.
> On Mon, Aug 15, 2011 at 09:13:50AM -0600, Grant Likely wrote:
>> On Mon, Aug 15, 2011 at 9:03 AM, Robin Holt <holt-sJ/iWh9BUns@public.gmane.org> wrote:
>>> Grant,
>>>
>>> Earlier, you had asked for a more specific name for the compatible
>>> property of the Freescale flexcan device. I still have not gotten a
>>> more specific answer. Hopefully Marc can give you more details about
>>> the flexcan implementations.
>>
>> If there is no ip core version, then just stick with the
>> fsl,<soc>-flexcan name and drop "fsl,flexcan". Marketing may say
>> flexcan is flexcan, but hardware engineers like to change things.
>> Trying to be too generic in compatible values will just lead to
>> problems in the future.
>
> Thanks,
> Robin
- k
^ permalink raw reply
* [net-next] stmmac: limit max_mtu in case of 4KiB and use __netdev_alloc_skb (V2)
From: Giuseppe CAVALLARO @ 2011-10-18 11:39 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, Giuseppe Cavallaro
In-Reply-To: <1318932085-14927-9-git-send-email-peppe.cavallaro@st.com>
Problem using big mtu around 4096 bytes is you end allocating (4096
+NET_SKB_PAD + NET_IP_ALIGN + sizeof(struct skb_shared_info) bytes ->
8192 bytes : order-1 pages
It's better to limit the mtu to SKB_MAX_HEAD(NET_SKB_PAD),
to have no more than one page per skb.
Also the patch changes the netdev_alloc_skb_ip_align() done in
init_dma_desc_rings() and uses a variant allowing GFP_KERNEL allocations
allowing the driver to load even in case of memory pressure.
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1848a16..6b8f455 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -474,11 +474,13 @@ static void init_dma_desc_rings(struct net_device *dev)
for (i = 0; i < rxsize; i++) {
struct dma_desc *p = priv->dma_rx + i;
- skb = netdev_alloc_skb_ip_align(dev, bfsize);
+ skb = __netdev_alloc_skb(dev, bfsize + NET_IP_ALIGN,
+ GFP_KERNEL);
if (unlikely(skb == NULL)) {
pr_err("%s: Rx init fails; skb is NULL\n", __func__);
break;
}
+ skb_reserve(skb, NET_IP_ALIGN);
priv->rx_skbuff[i] = skb;
priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
bfsize, DMA_FROM_DEVICE);
@@ -1401,7 +1403,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
if (priv->plat->enh_desc)
max_mtu = JUMBO_LEN;
else
- max_mtu = BUF_SIZE_4KiB;
+ max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
if ((new_mtu < 46) || (new_mtu > max_mtu)) {
pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
--
1.7.4.4
^ permalink raw reply related
* Re: [net-next 8/8] stmmac: limit max_mtu in case of 4KiB and use __netdev_alloc_skb.
From: Giuseppe CAVALLARO @ 2011-10-18 11:33 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, davem
In-Reply-To: <1318933110.2657.39.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On 10/18/2011 12:18 PM, Eric Dumazet wrote:
> Le mardi 18 octobre 2011 à 12:01 +0200, Giuseppe CAVALLARO a écrit :
>> Problem using big mtu around 4096 bytes is you end allocating (4096
>> +NET_SKB_PAD + NET_IP_ALIGN + sizeof(struct skb_shared_info) bytes ->
>> 8192 bytes : order-1 pages
>>
>> It's better to limit the mtu to SKB_MAX_HEAD(NET_SKB_PAD),
>> to have no more than one page per skb.
>>
>> Also the patch changes the netdev_alloc_skb_ip_align() done in
>> init_dma_desc_rings() and uses a variant allowing GFP_KERNEL allocations
>> allowing the driver to load even in case of memory pressure.
>>
>> Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
>> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>> ---
>> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++++----
>> 1 files changed, 9 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index 1848a16..f5ca3be 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -474,11 +474,13 @@ static void init_dma_desc_rings(struct net_device *dev)
>> for (i = 0; i < rxsize; i++) {
>> struct dma_desc *p = priv->dma_rx + i;
>>
>> - skb = netdev_alloc_skb_ip_align(dev, bfsize);
>> + skb = __netdev_alloc_skb(dev, bfsize + NET_IP_ALIGN,
>> + GFP_KERNEL);
>> if (unlikely(skb == NULL)) {
>> pr_err("%s: Rx init fails; skb is NULL\n", __func__);
>> break;
>> }
>> + skb_reserve(skb, NET_IP_ALIGN);
>> priv->rx_skbuff[i] = skb;
>> priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
>> bfsize, DMA_FROM_DEVICE);
>> @@ -1176,12 +1178,15 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
>>
>> skb = __skb_dequeue(&priv->rx_recycle);
>> if (skb == NULL)
>> - skb = netdev_alloc_skb_ip_align(priv->dev,
>> - bfsize);
>> + skb = __netdev_alloc_skb(priv->dev, bfsize +
>> + NET_IP_ALIGN,
>> + GFP_KERNEL);
>>
>
> No, you cant do that in softirq context. We cant sleep here and must use
> GFP_ATOMIC
> Only the init_dma_desc_rings() part is OK, we run in process context and
> are allowed to sleep in memory allocations (GFP_KERNEL)
>
>
>> if (unlikely(skb == NULL))
>> break;
>>
>> + skb_reserve(skb, NET_IP_ALIGN);
>> +
>> priv->rx_skbuff[entry] = skb;
>> priv->rx_skbuff_dma[entry] =
>> dma_map_single(priv->device, skb->data, bfsize,
>> @@ -1401,7 +1406,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
>> if (priv->plat->enh_desc)
>> max_mtu = JUMBO_LEN;
>> else
>> - max_mtu = BUF_SIZE_4KiB;
>> + max_mtu = SKB_MAX_HEAD(NET_SKB_PAD);
>>
>
> minor nit (since NET_IP_ALIGN is 0 anyway on modern x86)
> max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
>
>
>> if ((new_mtu < 46) || (new_mtu > max_mtu)) {
>> pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
>
>
>
Ok! I'm reworking and sending it again.
Thx
Peppe
^ permalink raw reply
* Re: PROBLEM: System call 'sendmsg' of process ospfd (quagga) causes kernel oops
From: Eric Dumazet @ 2011-10-18 11:37 UTC (permalink / raw)
To: Herbert Xu; +Cc: Elmar Vonlanthen, linux-kernel, netdev, Timo Teräs
In-Reply-To: <20111018104504.GA15913@gondor.apana.org.au>
Le mardi 18 octobre 2011 à 12:45 +0200, Herbert Xu a écrit :
> On Tue, Oct 18, 2011 at 12:23:43PM +0200, Eric Dumazet wrote:
> >
> > You're right, if reallocations are OK in all paths.
>
> If it wasn't OK then making needed_headroom constant won't work
> anyway.
>
> > We'll need to change LL_RESERVED_SPACE() / LL_RESERVED_SPACE_EXTRA() /
> > LL_ALLOCATED_SPACE() macros and provide the [read once] values, instead
> > of a [read once] pointer to values.
>
> I'm not sure what you mean here. I don't see any need to change
> these macros. All we need is to save the value in a local variable:
>
> hh_len = LL_RESERVED_SPACE(dev);
>
> skb = alloc_skb(hh_len + len);
> skb_reserve(skb, hh_len);
>
Not really Herbert. Please read again my patch changelog.
In the bug we try to fix, we have :
skb = sock_alloc_send_skb(sk, ... + LL_ALLOCATED_SPACE(rt->dst.dev)
... < increase of dev->needed_headroom by another cpu/task >
skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev));
skb_put() -> crash because we reserved too much space
So we really want LL_ALLOCATED_SPACE() and LL_RESERVED_SPACE() use the
same needed_headroom, or else you can have LL_RESERVED_SPACE() >
LL_ALLOCATED_SPACE().
There are several way to fix this, but this kind of code assumed the
dev->needed... values were consistent for the whole block.
^ permalink raw reply
* [patch] pktgen: bug when calling ndelay in x86 architectures
From: Daniel Turull @ 2011-10-18 11:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Robert Olsson, Voravit Tanyingyong, Jens Laas
The value selected to delay the transmission in pktgen with the ndelay function should be lower.
In Linux/arch/x86/include/asm/delay.h and Linux/arch/sh/include/asm/delay.h
the maximal expected value for a constant is 20000 ns.
Signed-off-by: Daniel Turull <daniel.turull@gmail.com>
---
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 796044a..e17bd41 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2145,7 +2145,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
}
start_time = ktime_now();
- if (remaining < 100000)
+ if (remaining < 20000)
ndelay(remaining); /* really small just spin */
else {
/* see do_nanosleep */
^ permalink raw reply related
* Re: [PATCH] Fix guest memory leak and panic
From: Ian Campbell @ 2011-10-18 10:50 UTC (permalink / raw)
To: Krishna Kumar2
Cc: davem@davemloft.net, linux-kernel@vger.kernel.org, mst@redhat.com,
netdev@vger.kernel.org, rusty@rustcorp.com.au,
virtualization@lists.linux-foundation.org
In-Reply-To: <OFB632D60B.6534A38B-ON6525792D.003A1B21-6525792D.003B0DB8@in.ibm.com>
On Tue, 2011-10-18 at 11:46 +0100, Krishna Kumar2 wrote:
> Ian Campbell <Ian.Campbell@citrix.com> wrote on 10/18/2011 03:17:11 PM:
>
> > > I think the best thing might be to remove the additional ref taking
> from
> > > the setter function and audit the previous changes to ensure they
> > > conform. I'll do that right away and post a fixup patch ASAP.
> >
> > Sigh, only one out of the ten callers of (__)skb_frag_set_page expects
> > skb_frag_set_page to take a new reference. I think that's pretty
> > comprehensive evidence that the current behaviour is unexpected and
> > wrong.
>
> Looks good!
Thanks.
> Does it make sense to commit both of these patches? The
> reason being - my patch becomes a cleanup of set_skb_frag()
> in virtio_net driver.
I think your patch remains a valid cleanup but I don't maintain that
code.
Ian.
^ permalink raw reply
* Re: [PATCH] Fix guest memory leak and panic
From: Krishna Kumar2 @ 2011-10-18 10:46 UTC (permalink / raw)
To: Ian Campbell
Cc: davem@davemloft.net, linux-kernel@vger.kernel.org, mst@redhat.com,
netdev@vger.kernel.org, rusty@rustcorp.com.au,
virtualization@lists.linux-foundation.org
In-Reply-To: <1318931232.16132.65.camel@zakaz.uk.xensource.com>
Ian Campbell <Ian.Campbell@citrix.com> wrote on 10/18/2011 03:17:11 PM:
> > I think the best thing might be to remove the additional ref taking
from
> > the setter function and audit the previous changes to ensure they
> > conform. I'll do that right away and post a fixup patch ASAP.
>
> Sigh, only one out of the ten callers of (__)skb_frag_set_page expects
> skb_frag_set_page to take a new reference. I think that's pretty
> comprehensive evidence that the current behaviour is unexpected and
> wrong.
Looks good!
Does it make sense to commit both of these patches? The
reason being - my patch becomes a cleanup of set_skb_frag()
in virtio_net driver.
thanks,
- KK
^ permalink raw reply
* Re: PROBLEM: System call 'sendmsg' of process ospfd (quagga) causes kernel oops
From: Herbert Xu @ 2011-10-18 10:45 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Elmar Vonlanthen, linux-kernel, netdev, Timo Teräs
In-Reply-To: <1318933423.2657.44.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On Tue, Oct 18, 2011 at 12:23:43PM +0200, Eric Dumazet wrote:
>
> You're right, if reallocations are OK in all paths.
If it wasn't OK then making needed_headroom constant won't work
anyway.
> We'll need to change LL_RESERVED_SPACE() / LL_RESERVED_SPACE_EXTRA() /
> LL_ALLOCATED_SPACE() macros and provide the [read once] values, instead
> of a [read once] pointer to values.
I'm not sure what you mean here. I don't see any need to change
these macros. All we need is to save the value in a local variable:
hh_len = LL_RESERVED_SPACE(dev);
skb = alloc_skb(hh_len + len);
skb_reserve(skb, hh_len);
Cheers,
--
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] Fix guest memory leak and panic
From: Krishna Kumar2 @ 2011-10-18 10:28 UTC (permalink / raw)
To: Ian Campbell
Cc: davem@davemloft.net, linux-kernel@vger.kernel.org, mst@redhat.com,
netdev@vger.kernel.org, rusty@rustcorp.com.au,
virtualization@lists.linux-foundation.org
In-Reply-To: <1318927016.16132.49.camel@zakaz.uk.xensource.com>
Ian Campbell <Ian.Campbell@citrix.com> wrote on 10/18/2011 02:06:56 PM:
Hi Ian,
> On Tue, 2011-10-18 at 09:05 +0100, Krishna Kumar wrote:
> > The extra reference to the fragment pages causes those pages to
> > not get freed in skb_release_data(). The following patch fixes
> > the bug. I have not checked if any other converted driver has
> > the same issue.
>
> Damn. You are completely correct and I appear to have made this same
> mistake several times. A quick look suggests that at least cxbg,
> myriage, vmxnet, cassini and bnx2 may potentially have a similar
> issue :-( (I stopped looking at that point, I'll obviously do a full
> audit).
>
> I considered quite carefully whether (__)skb_frag_set_page should take a
> reference or not and decided yes but I'm starting to reconsider whether
> I made the right choice. It seems that is just confusing and violates
> the principal of least surprise to have a function called "set" take a
> new reference. In reality all existing drivers expect that adding a page
> to an SKB frag will just take over the existing reference.
>
> I think the best thing might be to remove the additional ref taking from
> the setter function and audit the previous changes to ensure they
> conform. I'll do that right away and post a fixup patch ASAP.
>
> > Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
>
> This change is correct as things stand today, so:
>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
>
> but perhaps it would be better to hold off and let me fix all of these
> all at once.
Either way is fine with me. However, besides having a fix,
I would like to remove the manual initializations in
set_skb_frag(), and substitute with __skb_fill_page_desc,
like other drivers do.
thanks,
- KK
^ permalink raw reply
* Re: PROBLEM: System call 'sendmsg' of process ospfd (quagga) causes kernel oops
From: Eric Dumazet @ 2011-10-18 10:23 UTC (permalink / raw)
To: Herbert Xu; +Cc: Elmar Vonlanthen, linux-kernel, netdev, Timo Teräs
In-Reply-To: <20111018100527.GA15383@gondor.apana.org.au>
Le mardi 18 octobre 2011 à 12:05 +0200, Herbert Xu a écrit :
> On Tue, Oct 18, 2011 at 12:01:33PM +0200, Eric Dumazet wrote:
> >
> > Adding an RCU protected structure to hold hard_header_len /
> > needed_headroom / needed_tailroom should be possible, but this adds yet
> > another pointer dereference...
>
> I don't think we need RCU here since the problem is simply that
> we're using two different values for skb allocations and skb_reserve.
>
> As long as we use one and the same value it should work. The value
> will rarely be incorrect and when it is, automatic reallocation will
> occur.
>
You're right, if reallocations are OK in all paths.
We'll need to change LL_RESERVED_SPACE() / LL_RESERVED_SPACE_EXTRA() /
LL_ALLOCATED_SPACE() macros and provide the [read once] values, instead
of a [read once] pointer to values.
Thats a bit complex change, but doable.
^ permalink raw reply
* Re: [net-next 8/8] stmmac: limit max_mtu in case of 4KiB and use __netdev_alloc_skb.
From: Eric Dumazet @ 2011-10-18 10:18 UTC (permalink / raw)
To: Giuseppe CAVALLARO; +Cc: netdev, davem
In-Reply-To: <1318932085-14927-9-git-send-email-peppe.cavallaro@st.com>
Le mardi 18 octobre 2011 à 12:01 +0200, Giuseppe CAVALLARO a écrit :
> Problem using big mtu around 4096 bytes is you end allocating (4096
> +NET_SKB_PAD + NET_IP_ALIGN + sizeof(struct skb_shared_info) bytes ->
> 8192 bytes : order-1 pages
>
> It's better to limit the mtu to SKB_MAX_HEAD(NET_SKB_PAD),
> to have no more than one page per skb.
>
> Also the patch changes the netdev_alloc_skb_ip_align() done in
> init_dma_desc_rings() and uses a variant allowing GFP_KERNEL allocations
> allowing the driver to load even in case of memory pressure.
>
> Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++++----
> 1 files changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 1848a16..f5ca3be 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -474,11 +474,13 @@ static void init_dma_desc_rings(struct net_device *dev)
> for (i = 0; i < rxsize; i++) {
> struct dma_desc *p = priv->dma_rx + i;
>
> - skb = netdev_alloc_skb_ip_align(dev, bfsize);
> + skb = __netdev_alloc_skb(dev, bfsize + NET_IP_ALIGN,
> + GFP_KERNEL);
> if (unlikely(skb == NULL)) {
> pr_err("%s: Rx init fails; skb is NULL\n", __func__);
> break;
> }
> + skb_reserve(skb, NET_IP_ALIGN);
> priv->rx_skbuff[i] = skb;
> priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
> bfsize, DMA_FROM_DEVICE);
> @@ -1176,12 +1178,15 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
>
> skb = __skb_dequeue(&priv->rx_recycle);
> if (skb == NULL)
> - skb = netdev_alloc_skb_ip_align(priv->dev,
> - bfsize);
> + skb = __netdev_alloc_skb(priv->dev, bfsize +
> + NET_IP_ALIGN,
> + GFP_KERNEL);
>
No, you cant do that in softirq context. We cant sleep here and must use
GFP_ATOMIC
Only the init_dma_desc_rings() part is OK, we run in process context and
are allowed to sleep in memory allocations (GFP_KERNEL)
> if (unlikely(skb == NULL))
> break;
>
> + skb_reserve(skb, NET_IP_ALIGN);
> +
> priv->rx_skbuff[entry] = skb;
> priv->rx_skbuff_dma[entry] =
> dma_map_single(priv->device, skb->data, bfsize,
> @@ -1401,7 +1406,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
> if (priv->plat->enh_desc)
> max_mtu = JUMBO_LEN;
> else
> - max_mtu = BUF_SIZE_4KiB;
> + max_mtu = SKB_MAX_HEAD(NET_SKB_PAD);
>
minor nit (since NET_IP_ALIGN is 0 anyway on modern x86)
max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
> if ((new_mtu < 46) || (new_mtu > max_mtu)) {
> pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
^ permalink raw reply
* [PATCBN net-next] mlx4_en: fix skb truesize underestimation
From: Eric Dumazet @ 2011-10-18 10:13 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Yevgeny Petrilin
skb->truesize must account for allocated memory, not the used part of
it. Doing this work is important to avoid unexpected OOM situations.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
Note: To improve performance, this driver should avoid all the
get_page() done for every frag since it dirties page->_count and
conflict with previous skbs consumers (on a different cpu maybe)
Only at alloc_pages() time should we add to page->count the
(number_of_frags on this page) - 1
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 37cc9e5..c9aaf20 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -404,10 +404,11 @@ void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
struct skb_frag_struct *skb_frags,
- struct skb_frag_struct *skb_frags_rx,
+ struct sk_buff *skb,
struct mlx4_en_rx_alloc *page_alloc,
int length)
{
+ struct skb_frag_struct *skb_frags_rx = skb_shinfo(skb)->frags;
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_frag_info *frag_info;
int nr;
@@ -423,6 +424,7 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
skb_frags_rx[nr].page = skb_frags[nr].page;
skb_frags_rx[nr].size = skb_frags[nr].size;
skb_frags_rx[nr].page_offset = skb_frags[nr].page_offset;
+ skb->truesize += frag_info->frag_stride;
dma = be64_to_cpu(rx_desc->data[nr].addr);
/* Allocate a replacement page */
@@ -470,7 +472,6 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
skb->dev = priv->dev;
skb_reserve(skb, NET_IP_ALIGN);
skb->len = length;
- skb->truesize = length + sizeof(struct sk_buff);
/* Get pointer to first fragment so we could copy the headers into the
* (linear part of the) skb */
@@ -490,8 +491,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
/* Move relevant fragments to skb */
used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags,
- skb_shinfo(skb)->frags,
- page_alloc, length);
+ skb, page_alloc, length);
if (unlikely(!used_frags)) {
kfree_skb(skb);
return NULL;
@@ -600,7 +600,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
nr = mlx4_en_complete_rx_desc(
priv, rx_desc,
- skb_frags, skb_shinfo(gro_skb)->frags,
+ skb_frags, gro_skb,
ring->page_alloc, length);
if (!nr)
goto next;
@@ -608,7 +608,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
skb_shinfo(gro_skb)->nr_frags = nr;
gro_skb->len = length;
gro_skb->data_len = length;
- gro_skb->truesize += length;
gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
if (cqe->vlan_my_qpn &
^ permalink raw reply related
* Re: PROBLEM: System call 'sendmsg' of process ospfd (quagga) causes kernel oops
From: Herbert Xu @ 2011-10-18 10:05 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Elmar Vonlanthen, linux-kernel, netdev, Timo Teräs
In-Reply-To: <1318932093.2657.26.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On Tue, Oct 18, 2011 at 12:01:33PM +0200, Eric Dumazet wrote:
>
> Adding an RCU protected structure to hold hard_header_len /
> needed_headroom / needed_tailroom should be possible, but this adds yet
> another pointer dereference...
I don't think we need RCU here since the problem is simply that
we're using two different values for skb allocations and skb_reserve.
As long as we use one and the same value it should work. The value
will rarely be incorrect and when it is, automatic reallocation will
occur.
Cheers,
--
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
* [net-next 8/8] stmmac: limit max_mtu in case of 4KiB and use __netdev_alloc_skb.
From: Giuseppe CAVALLARO @ 2011-10-18 10:01 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, Giuseppe Cavallaro
In-Reply-To: <1318932085-14927-1-git-send-email-peppe.cavallaro@st.com>
Problem using big mtu around 4096 bytes is you end allocating (4096
+NET_SKB_PAD + NET_IP_ALIGN + sizeof(struct skb_shared_info) bytes ->
8192 bytes : order-1 pages
It's better to limit the mtu to SKB_MAX_HEAD(NET_SKB_PAD),
to have no more than one page per skb.
Also the patch changes the netdev_alloc_skb_ip_align() done in
init_dma_desc_rings() and uses a variant allowing GFP_KERNEL allocations
allowing the driver to load even in case of memory pressure.
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1848a16..f5ca3be 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -474,11 +474,13 @@ static void init_dma_desc_rings(struct net_device *dev)
for (i = 0; i < rxsize; i++) {
struct dma_desc *p = priv->dma_rx + i;
- skb = netdev_alloc_skb_ip_align(dev, bfsize);
+ skb = __netdev_alloc_skb(dev, bfsize + NET_IP_ALIGN,
+ GFP_KERNEL);
if (unlikely(skb == NULL)) {
pr_err("%s: Rx init fails; skb is NULL\n", __func__);
break;
}
+ skb_reserve(skb, NET_IP_ALIGN);
priv->rx_skbuff[i] = skb;
priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
bfsize, DMA_FROM_DEVICE);
@@ -1176,12 +1178,15 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
skb = __skb_dequeue(&priv->rx_recycle);
if (skb == NULL)
- skb = netdev_alloc_skb_ip_align(priv->dev,
- bfsize);
+ skb = __netdev_alloc_skb(priv->dev, bfsize +
+ NET_IP_ALIGN,
+ GFP_KERNEL);
if (unlikely(skb == NULL))
break;
+ skb_reserve(skb, NET_IP_ALIGN);
+
priv->rx_skbuff[entry] = skb;
priv->rx_skbuff_dma[entry] =
dma_map_single(priv->device, skb->data, bfsize,
@@ -1401,7 +1406,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
if (priv->plat->enh_desc)
max_mtu = JUMBO_LEN;
else
- max_mtu = BUF_SIZE_4KiB;
+ max_mtu = SKB_MAX_HEAD(NET_SKB_PAD);
if ((new_mtu < 46) || (new_mtu > max_mtu)) {
pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
--
1.7.4.4
^ permalink raw reply related
* [net-next 7/8] stmmac: add CHAINED descriptor mode support (V4)
From: Giuseppe CAVALLARO @ 2011-10-18 10:01 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, Giuseppe Cavallaro, Rayagond Kokatanur
In-Reply-To: <1318932085-14927-1-git-send-email-peppe.cavallaro@st.com>
This patch enhances the STMMAC driver to support CHAINED mode of
descriptor.
STMMAC supports DMA descriptor to operate both in dual buffer(RING)
and linked-list(CHAINED) mode. In RING mode (default) each descriptor
points to two data buffer pointers whereas in CHAINED mode they point
to only one data buffer pointer.
In CHAINED mode each descriptor will have pointer to next descriptor in
the list, hence creating the explicit chaining in the descriptor itself,
whereas such explicit chaining is not possible in RING mode.
First version of this work has been done by Rayagond.
Then the patch has been reworked avoiding ifdef inside the C code.
A new header file has been added to define all the functions needed for
managing enhanced and normal descriptors.
In fact, these have to be specialized according to the ring/chain usage.
Two new C files have been also added to implement the helper routines
needed to manage: jumbo frames, chain and ring setup (i.e. desc3).
Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 18 +++
drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +
drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 137 +++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/common.h | 13 ++
drivers/net/ethernet/stmicro/stmmac/descs_com.h | 126 +++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 22 ++--
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 20 +--
drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 126 +++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 130 ++++++++------------
10 files changed, 491 insertions(+), 105 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/chain_mode.c
create mode 100644 drivers/net/ethernet/stmicro/stmmac/descs_com.h
create mode 100644 drivers/net/ethernet/stmicro/stmmac/ring_mode.c
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 8cd9dde..ac6f190 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -63,4 +63,22 @@ config STMMAC_RTC_TIMER
endchoice
+choice
+ prompt "Select the DMA TX/RX descriptor operating modes"
+ depends on STMMAC_ETH
+ ---help---
+ This driver supports DMA descriptor to operate both in dual buffer
+ (RING) and linked-list(CHAINED) mode. In RING mode each descriptor
+ points to two data buffer pointers whereas in CHAINED mode they
+ points to only one data buffer pointer.
+
+config STMMAC_RING
+ bool "Enable Descriptor Ring Mode"
+
+config STMMAC_CHAINED
+ bool "Enable Descriptor Chained Mode"
+
+endchoice
+
+
endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 0f23d95..d7c4516 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,5 +1,7 @@
obj-$(CONFIG_STMMAC_ETH) += stmmac.o
stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
+stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
+stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \
dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
new file mode 100644
index 0000000..0668659
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ Specialised functions for managing Chained mode
+
+ Copyright(C) 2011 STMicroelectronics Ltd
+
+ It defines all the functions used to handle the normal/enhanced
+ descriptors in case of the DMA is configured to work in chained or
+ in ring mode.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include "stmmac.h"
+
+unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+{
+ struct stmmac_priv *priv = (struct stmmac_priv *) p;
+ unsigned int txsize = priv->dma_tx_size;
+ unsigned int entry = priv->cur_tx % txsize;
+ struct dma_desc *desc = priv->dma_tx + entry;
+ unsigned int nopaged_len = skb_headlen(skb);
+ unsigned int bmax;
+ unsigned int i = 1, len;
+
+ if (priv->plat->enh_desc)
+ bmax = BUF_SIZE_8KiB;
+ else
+ bmax = BUF_SIZE_2KiB;
+
+ len = nopaged_len - bmax;
+
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ bmax, DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum);
+
+ while (len != 0) {
+ entry = (++priv->cur_tx) % txsize;
+ desc = priv->dma_tx + entry;
+
+ if (len > bmax) {
+ desc->des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i),
+ bmax, DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 0, bmax,
+ csum);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ len -= bmax;
+ i++;
+ } else {
+ desc->des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i), len,
+ DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 0, len,
+ csum);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ len = 0;
+ }
+ }
+ return entry;
+}
+
+static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
+{
+ unsigned int ret = 0;
+
+ if ((enh_desc && (len > BUF_SIZE_8KiB)) ||
+ (!enh_desc && (len > BUF_SIZE_2KiB))) {
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+{
+}
+
+static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
+{
+}
+
+static void stmmac_clean_desc3(struct dma_desc *p)
+{
+}
+
+static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size)
+{
+ /*
+ * In chained mode the des3 points to the next element in the ring.
+ * The latest element has to point to the head.
+ */
+ int i;
+ struct dma_desc *p = des;
+ dma_addr_t dma_phy = phy_addr;
+
+ for (i = 0; i < (size - 1); i++) {
+ dma_phy += sizeof(struct dma_desc);
+ p->des3 = (unsigned int)dma_phy;
+ p++;
+ }
+ p->des3 = (unsigned int)phy_addr;
+}
+
+static int stmmac_set_16kib_bfsize(int mtu)
+{
+ /* Not supported */
+ return 0;
+}
+
+const struct stmmac_ring_mode_ops ring_mode_ops = {
+ .is_jumbo_frm = stmmac_is_jumbo_frm,
+ .jumbo_frm = stmmac_jumbo_frm,
+ .refill_desc3 = stmmac_refill_desc3,
+ .init_desc3 = stmmac_init_desc3,
+ .init_dma_chain = stmmac_init_dma_chain,
+ .clean_desc3 = stmmac_clean_desc3,
+ .set_16kib_bfsize = stmmac_set_16kib_bfsize,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index ffba014..9100c10 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -287,10 +287,22 @@ struct mii_regs {
unsigned int data; /* MII Data */
};
+struct stmmac_ring_mode_ops {
+ unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
+ unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
+ void (*refill_desc3) (int bfsize, struct dma_desc *p);
+ void (*init_desc3) (int des3_as_data_buf, struct dma_desc *p);
+ void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size);
+ void (*clean_desc3) (struct dma_desc *p);
+ int (*set_16kib_bfsize) (int mtu);
+};
+
struct mac_device_info {
const struct stmmac_ops *mac;
const struct stmmac_desc_ops *desc;
const struct stmmac_dma_ops *dma;
+ const struct stmmac_ring_mode_ops *ring;
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
unsigned int synopsys_uid;
@@ -304,3 +316,4 @@ extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int high, unsigned int low);
extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
+extern const struct stmmac_ring_mode_ops ring_mode_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
new file mode 100644
index 0000000..dd8d6e1
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ Header File to describe Normal/enhanced descriptor functions used for RING
+ and CHAINED modes.
+
+ Copyright(C) 2011 STMicroelectronics Ltd
+
+ It defines all the functions used to handle the normal/enhanced
+ descriptors in case of the DMA is configured to work in chained or
+ in ring mode.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#if defined(CONFIG_STMMAC_RING)
+static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
+ if (end)
+ p->des01.erx.end_ring = 1;
+}
+
+static inline void ehn_desc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ if (end)
+ p->des01.etx.end_ring = 1;
+}
+
+static inline void enh_desc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.etx.end_ring = ter;
+}
+
+static inline void enh_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ if (unlikely(len > BUF_SIZE_4KiB)) {
+ p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
+ p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
+ } else
+ p->des01.etx.buffer1_size = len;
+}
+
+static inline void ndesc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.rx.buffer2_size = BUF_SIZE_2KiB - 1;
+ if (end)
+ p->des01.rx.end_ring = 1;
+}
+
+static inline void ndesc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ if (end)
+ p->des01.tx.end_ring = 1;
+}
+
+static inline void ndesc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.tx.end_ring = ter;
+}
+
+static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ if (unlikely(len > BUF_SIZE_2KiB)) {
+ p->des01.etx.buffer1_size = BUF_SIZE_2KiB - 1;
+ p->des01.etx.buffer2_size = len - p->des01.etx.buffer1_size;
+ } else
+ p->des01.tx.buffer1_size = len;
+}
+
+#else
+
+static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.erx.second_address_chained = 1;
+}
+
+static inline void ehn_desc_tx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.etx.second_address_chained = 1;
+}
+
+static inline void enh_desc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.etx.second_address_chained = 1;
+}
+
+static inline void enh_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ p->des01.etx.buffer1_size = len;
+}
+
+static inline void ndesc_rx_set_on_ring_chain(struct dma_desc *p, int end)
+{
+ p->des01.rx.second_address_chained = 1;
+}
+
+static inline void ndesc_tx_set_on_ring_chain(struct dma_desc *p, int ring_size)
+{
+ p->des01.tx.second_address_chained = 1;
+}
+
+static inline void ndesc_end_tx_desc(struct dma_desc *p, int ter)
+{
+ p->des01.tx.second_address_chained = 1;
+}
+
+static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
+{
+ p->des01.tx.buffer1_size = len;
+}
+#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index e5dfb6a..d879763 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -23,6 +23,7 @@
*******************************************************************************/
#include "common.h"
+#include "descs_com.h"
static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p, void __iomem *ioaddr)
@@ -233,10 +234,9 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
for (i = 0; i < ring_size; i++) {
p->des01.erx.own = 1;
p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
- /* To support jumbo frames */
- p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
- if (i == ring_size - 1)
- p->des01.erx.end_ring = 1;
+
+ ehn_desc_rx_set_on_ring_chain(p, (i == ring_size - 1));
+
if (disable_rx_ic)
p->des01.erx.disable_ic = 1;
p++;
@@ -249,8 +249,7 @@ static void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
for (i = 0; i < ring_size; i++) {
p->des01.etx.own = 0;
- if (i == ring_size - 1)
- p->des01.etx.end_ring = 1;
+ ehn_desc_tx_set_on_ring_chain(p, (i == ring_size - 1));
p++;
}
}
@@ -285,19 +284,16 @@ static void enh_desc_release_tx_desc(struct dma_desc *p)
int ter = p->des01.etx.end_ring;
memset(p, 0, offsetof(struct dma_desc, des2));
- p->des01.etx.end_ring = ter;
+ enh_desc_end_tx_desc(p, ter);
}
static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
int csum_flag)
{
p->des01.etx.first_segment = is_fs;
- if (unlikely(len > BUF_SIZE_4KiB)) {
- p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
- p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
- } else {
- p->des01.etx.buffer1_size = len;
- }
+
+ enh_set_tx_desc_len(p, len);
+
if (likely(csum_flag))
p->des01.etx.checksum_insertion = cic_full;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index e13226b..f7e8ba7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -23,6 +23,7 @@
*******************************************************************************/
#include "common.h"
+#include "descs_com.h"
static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
struct dma_desc *p, void __iomem *ioaddr)
@@ -126,9 +127,9 @@ static void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
for (i = 0; i < ring_size; i++) {
p->des01.rx.own = 1;
p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
- p->des01.rx.buffer2_size = BUF_SIZE_2KiB - 1;
- if (i == ring_size - 1)
- p->des01.rx.end_ring = 1;
+
+ ndesc_rx_set_on_ring_chain(p, (i == ring_size - 1));
+
if (disable_rx_ic)
p->des01.rx.disable_ic = 1;
p++;
@@ -140,8 +141,7 @@ static void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
int i;
for (i = 0; i < ring_size; i++) {
p->des01.tx.own = 0;
- if (i == ring_size - 1)
- p->des01.tx.end_ring = 1;
+ ndesc_tx_set_on_ring_chain(p, (i == (ring_size - 1)));
p++;
}
}
@@ -176,20 +176,14 @@ static void ndesc_release_tx_desc(struct dma_desc *p)
int ter = p->des01.tx.end_ring;
memset(p, 0, offsetof(struct dma_desc, des2));
- /* set termination field */
- p->des01.tx.end_ring = ter;
+ ndesc_end_tx_desc(p, ter);
}
static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
int csum_flag)
{
p->des01.tx.first_segment = is_fs;
-
- if (unlikely(len > BUF_SIZE_2KiB)) {
- p->des01.etx.buffer1_size = BUF_SIZE_2KiB - 1;
- p->des01.etx.buffer2_size = len - p->des01.etx.buffer1_size;
- } else
- p->des01.tx.buffer1_size = len;
+ norm_set_tx_desc_len(p, len);
}
static void ndesc_clear_tx_ic(struct dma_desc *p)
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
new file mode 100644
index 0000000..fb8377d
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ Specialised functions for managing Ring mode
+
+ Copyright(C) 2011 STMicroelectronics Ltd
+
+ It defines all the functions used to handle the normal/enhanced
+ descriptors in case of the DMA is configured to work in chained or
+ in ring mode.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include "stmmac.h"
+
+static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+{
+ struct stmmac_priv *priv = (struct stmmac_priv *) p;
+ unsigned int txsize = priv->dma_tx_size;
+ unsigned int entry = priv->cur_tx % txsize;
+ struct dma_desc *desc = priv->dma_tx + entry;
+ unsigned int nopaged_len = skb_headlen(skb);
+ unsigned int bmax, len;
+
+ if (priv->plat->enh_desc)
+ bmax = BUF_SIZE_8KiB;
+ else
+ bmax = BUF_SIZE_2KiB;
+
+ len = nopaged_len - bmax;
+
+ if (nopaged_len > BUF_SIZE_8KiB) {
+
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ bmax, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 1, bmax,
+ csum);
+
+ entry = (++priv->cur_tx) % txsize;
+ desc = priv->dma_tx + entry;
+
+ desc->des2 = dma_map_single(priv->device, skb->data + bmax,
+ len, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 0, len, csum);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ } else {
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ nopaged_len, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum);
+ }
+
+ return entry;
+}
+
+static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
+{
+ unsigned int ret = 0;
+
+ if (len >= BUF_SIZE_4KiB)
+ ret = 1;
+
+ return ret;
+}
+
+static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+{
+ /* Fill DES3 in case of RING mode */
+ if (bfsize >= BUF_SIZE_8KiB)
+ p->des3 = p->des2 + BUF_SIZE_8KiB;
+}
+
+/* In ring mode we need to fill the desc3 because it is used
+ * as buffer */
+static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
+{
+ if (unlikely(des3_as_data_buf))
+ p->des3 = p->des2 + BUF_SIZE_8KiB;
+}
+
+static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size)
+{
+}
+
+static void stmmac_clean_desc3(struct dma_desc *p)
+{
+ if (unlikely(p->des3))
+ p->des3 = 0;
+}
+
+static int stmmac_set_16kib_bfsize(int mtu)
+{
+ int ret = 0;
+ if (unlikely(mtu >= BUF_SIZE_8KiB))
+ ret = BUF_SIZE_16KiB;
+ return ret;
+}
+
+const struct stmmac_ring_mode_ops ring_mode_ops = {
+ .is_jumbo_frm = stmmac_is_jumbo_frm,
+ .jumbo_frm = stmmac_jumbo_frm,
+ .refill_desc3 = stmmac_refill_desc3,
+ .init_desc3 = stmmac_init_desc3,
+ .init_dma_chain = stmmac_init_dma_chain,
+ .clean_desc3 = stmmac_clean_desc3,
+ .set_16kib_bfsize = stmmac_set_16kib_bfsize,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 49a4af3..9bafa6c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -22,7 +22,7 @@
#define DRV_MODULE_VERSION "Oct_2011"
#include <linux/stmmac.h>
-
+#include <linux/phy.h>
#include "common.h"
#ifdef CONFIG_STMMAC_TIMER
#include "stmmac_timer.h"
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 7325256..1848a16 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2,7 +2,7 @@
This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers.
ST Ethernet IPs are built around a Synopsys IP Core.
- Copyright (C) 2007-2009 STMicroelectronics Ltd
+ Copyright(C) 2007-2011 STMicroelectronics Ltd
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -41,17 +41,16 @@
#include <linux/if_ether.h>
#include <linux/crc32.h>
#include <linux/mii.h>
-#include <linux/phy.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
-#include "stmmac.h"
#ifdef CONFIG_STMMAC_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#endif
+#include "stmmac.h"
#define STMMAC_RESOURCE_NAME "stmmaceth"
@@ -388,11 +387,28 @@ static void display_ring(struct dma_desc *p, int size)
}
}
+static int stmmac_set_bfsize(int mtu, int bufsize)
+{
+ int ret = bufsize;
+
+ if (mtu >= BUF_SIZE_4KiB)
+ ret = BUF_SIZE_8KiB;
+ else if (mtu >= BUF_SIZE_2KiB)
+ ret = BUF_SIZE_4KiB;
+ else if (mtu >= DMA_BUFFER_SIZE)
+ ret = BUF_SIZE_2KiB;
+ else
+ ret = DMA_BUFFER_SIZE;
+
+ return ret;
+}
+
/**
* init_dma_desc_rings - init the RX/TX descriptor rings
* @dev: net device structure
* Description: this function initializes the DMA RX/TX descriptors
- * and allocates the socket buffers.
+ * and allocates the socket buffers. It suppors the chained and ring
+ * modes.
*/
static void init_dma_desc_rings(struct net_device *dev)
{
@@ -401,31 +417,24 @@ static void init_dma_desc_rings(struct net_device *dev)
struct sk_buff *skb;
unsigned int txsize = priv->dma_tx_size;
unsigned int rxsize = priv->dma_rx_size;
- unsigned int bfsize = priv->dma_buf_sz;
- int buff2_needed = 0, dis_ic = 0;
+ unsigned int bfsize;
+ int dis_ic = 0;
+ int des3_as_data_buf = 0;
- /* Set the Buffer size according to the MTU;
- * indeed, in case of jumbo we need to bump-up the buffer sizes.
- */
- if (unlikely(dev->mtu >= BUF_SIZE_8KiB))
- bfsize = BUF_SIZE_16KiB;
- else if (unlikely(dev->mtu >= BUF_SIZE_4KiB))
- bfsize = BUF_SIZE_8KiB;
- else if (unlikely(dev->mtu >= BUF_SIZE_2KiB))
- bfsize = BUF_SIZE_4KiB;
- else if (unlikely(dev->mtu >= DMA_BUFFER_SIZE))
- bfsize = BUF_SIZE_2KiB;
+ /* Set the max buffer size according to the DESC mode
+ * and the MTU. Note that RING mode allows 16KiB bsize. */
+ bfsize = priv->hw->ring->set_16kib_bfsize(dev->mtu);
+
+ if (bfsize == BUF_SIZE_16KiB)
+ des3_as_data_buf = 1;
else
- bfsize = DMA_BUFFER_SIZE;
+ bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
#ifdef CONFIG_STMMAC_TIMER
/* Disable interrupts on completion for the reception if timer is on */
if (likely(priv->tm->enable))
dis_ic = 1;
#endif
- /* If the MTU exceeds 8k so use the second buffer in the chain */
- if (bfsize >= BUF_SIZE_8KiB)
- buff2_needed = 1;
DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
txsize, rxsize, bfsize);
@@ -453,7 +462,7 @@ static void init_dma_desc_rings(struct net_device *dev)
return;
}
- DBG(probe, INFO, "stmmac (%s) DMA desc rings: virt addr (Rx %p, "
+ DBG(probe, INFO, "stmmac (%s) DMA desc: virt addr (Rx %p, "
"Tx %p)\n\tDMA phy addr (Rx 0x%08x, Tx 0x%08x)\n",
dev->name, priv->dma_rx, priv->dma_tx,
(unsigned int)priv->dma_rx_phy, (unsigned int)priv->dma_tx_phy);
@@ -475,8 +484,9 @@ static void init_dma_desc_rings(struct net_device *dev)
bfsize, DMA_FROM_DEVICE);
p->des2 = priv->rx_skbuff_dma[i];
- if (unlikely(buff2_needed))
- p->des3 = p->des2 + BUF_SIZE_8KiB;
+
+ priv->hw->ring->init_desc3(des3_as_data_buf, p);
+
DBG(probe, INFO, "[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
priv->rx_skbuff[i]->data, priv->rx_skbuff_dma[i]);
}
@@ -490,6 +500,12 @@ static void init_dma_desc_rings(struct net_device *dev)
priv->tx_skbuff[i] = NULL;
priv->dma_tx[i].des2 = 0;
}
+
+ /* In case of Chained mode this sets the des3 to the next
+ * element in the chain */
+ priv->hw->ring->init_dma_chain(priv->dma_rx, priv->dma_rx_phy, rxsize);
+ priv->hw->ring->init_dma_chain(priv->dma_tx, priv->dma_tx_phy, txsize);
+
priv->dirty_tx = 0;
priv->cur_tx = 0;
@@ -620,8 +636,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
dma_unmap_single(priv->device, p->des2,
priv->hw->desc->get_tx_len(p),
DMA_TO_DEVICE);
- if (unlikely(p->des3))
- p->des3 = 0;
+ priv->hw->ring->clean_desc3(p);
if (likely(skb != NULL)) {
/*
@@ -728,7 +743,6 @@ static void stmmac_no_timer_stopped(void)
*/
static void stmmac_tx_err(struct stmmac_priv *priv)
{
-
netif_stop_queue(priv->dev);
priv->hw->dma->stop_tx(priv->ioaddr);
@@ -1028,47 +1042,6 @@ static int stmmac_release(struct net_device *dev)
return 0;
}
-static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb,
- struct net_device *dev,
- int csum_insertion)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
- unsigned int nopaged_len = skb_headlen(skb);
- unsigned int txsize = priv->dma_tx_size;
- unsigned int entry = priv->cur_tx % txsize;
- struct dma_desc *desc = priv->dma_tx + entry;
-
- if (nopaged_len > BUF_SIZE_8KiB) {
-
- int buf2_size = nopaged_len - BUF_SIZE_8KiB;
-
- desc->des2 = dma_map_single(priv->device, skb->data,
- BUF_SIZE_8KiB, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 1, BUF_SIZE_8KiB,
- csum_insertion);
-
- entry = (++priv->cur_tx) % txsize;
- desc = priv->dma_tx + entry;
-
- desc->des2 = dma_map_single(priv->device,
- skb->data + BUF_SIZE_8KiB,
- buf2_size, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 0, buf2_size,
- csum_insertion);
- priv->hw->desc->set_tx_owner(desc);
- priv->tx_skbuff[entry] = NULL;
- } else {
- desc->des2 = dma_map_single(priv->device, skb->data,
- nopaged_len, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
- csum_insertion);
- }
- return entry;
-}
-
/**
* stmmac_xmit:
* @skb : the socket buffer
@@ -1083,6 +1056,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
int i, csum_insertion = 0;
int nfrags = skb_shinfo(skb)->nr_frags;
struct dma_desc *desc, *first;
+ unsigned int nopaged_len = skb_headlen(skb);
if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
if (!netif_queue_stopped(dev)) {
@@ -1103,7 +1077,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
pr_info("stmmac xmit:\n"
"\tskb addr %p - len: %d - nopaged_len: %d\n"
"\tn_frags: %d - ip_summed: %d - %s gso\n",
- skb, skb->len, skb_headlen(skb), nfrags, skb->ip_summed,
+ skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
!skb_is_gso(skb) ? "isn't" : "is");
#endif
@@ -1116,14 +1090,14 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN))
pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n"
"\t\tn_frags: %d, ip_summed: %d\n",
- skb->len, skb_headlen(skb), nfrags, skb->ip_summed);
+ skb->len, nopaged_len, nfrags, skb->ip_summed);
#endif
priv->tx_skbuff[entry] = skb;
- if (unlikely(skb->len >= BUF_SIZE_4KiB)) {
- entry = stmmac_handle_jumbo_frames(skb, dev, csum_insertion);
+
+ if (priv->hw->ring->is_jumbo_frm(skb->len, priv->plat->enh_desc)) {
+ entry = priv->hw->ring->jumbo_frm(priv, skb, csum_insertion);
desc = priv->dma_tx + entry;
} else {
- unsigned int nopaged_len = skb_headlen(skb);
desc->des2 = dma_map_single(priv->device, skb->data,
nopaged_len, DMA_TO_DEVICE);
priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
@@ -1214,11 +1188,10 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
DMA_FROM_DEVICE);
(p + entry)->des2 = priv->rx_skbuff_dma[entry];
- if (unlikely(priv->plat->has_gmac)) {
- if (bfsize >= BUF_SIZE_8KiB)
- (p + entry)->des3 =
- (p + entry)->des2 + BUF_SIZE_8KiB;
- }
+
+ if (unlikely(priv->plat->has_gmac))
+ priv->hw->ring->refill_desc3(bfsize, p + entry);
+
RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
}
wmb();
@@ -1795,6 +1768,7 @@ static int stmmac_mac_device_setup(struct net_device *dev)
device->desc = &ndesc_ops;
priv->hw = device;
+ priv->hw->ring = &ring_mode_ops;
if (device_can_wakeup(priv->device)) {
priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
--
1.7.4.4
^ permalink raw reply related
* [net-next 6/8] stmmac: allow mmc usage only if feature actually available (V4)
From: Giuseppe CAVALLARO @ 2011-10-18 10:01 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, Giuseppe Cavallaro, Rayagond Kokatanur
In-Reply-To: <1318932085-14927-1-git-send-email-peppe.cavallaro@st.com>
Enable the MMC support if it is actually available from the
HW capability register.
Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 24 +++++++++++--------
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +-
2 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index aedff9a..406404f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -96,7 +96,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
{ #m, FIELD_SIZEOF(struct stmmac_counters, m), \
offsetof(struct stmmac_priv, mmc.m)}
-static const struct stmmac_stats stmmac_gstr_mmc[] = {
+static const struct stmmac_stats stmmac_mmc[] = {
STMMAC_MMC_STAT(mmc_tx_octetcount_gb),
STMMAC_MMC_STAT(mmc_tx_framecount_gb),
STMMAC_MMC_STAT(mmc_tx_broadcastframe_g),
@@ -177,7 +177,7 @@ static const struct stmmac_stats stmmac_gstr_mmc[] = {
STMMAC_MMC_STAT(mmc_rx_icmp_gd_octets),
STMMAC_MMC_STAT(mmc_rx_icmp_err_octets),
};
-#define STMMAC_MMC_STATS_LEN ARRAY_SIZE(stmmac_gstr_mmc)
+#define STMMAC_MMC_STATS_LEN ARRAY_SIZE(stmmac_mmc)
static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
@@ -348,13 +348,17 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
priv->ioaddr);
else {
/* If supported, for new GMAC chips expose the MMC counters */
- dwmac_mmc_read(priv->ioaddr, &priv->mmc);
+ if (priv->dma_cap.rmon) {
+ dwmac_mmc_read(priv->ioaddr, &priv->mmc);
- for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
- char *p = (char *)priv + stmmac_gstr_mmc[i].stat_offset;
+ for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
+ char *p;
+ p = (char *)priv + stmmac_mmc[i].stat_offset;
- data[j++] = (stmmac_gstr_mmc[i].sizeof_stat ==
- sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
+ data[j++] = (stmmac_mmc[i].sizeof_stat ==
+ sizeof(u64)) ? (*(u64 *)p) :
+ (*(u32 *)p);
+ }
}
}
for (i = 0; i < STMMAC_STATS_LEN; i++) {
@@ -373,7 +377,7 @@ static int stmmac_get_sset_count(struct net_device *netdev, int sset)
case ETH_SS_STATS:
len = STMMAC_STATS_LEN;
- if (priv->plat->has_gmac)
+ if (priv->dma_cap.rmon)
len += STMMAC_MMC_STATS_LEN;
return len;
@@ -390,9 +394,9 @@ static void stmmac_get_strings(struct net_device *dev, u32 stringset, u8 *data)
switch (stringset) {
case ETH_SS_STATS:
- if (priv->plat->has_gmac)
+ if (priv->dma_cap.rmon)
for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
- memcpy(p, stmmac_gstr_mmc[i].stat_string,
+ memcpy(p, stmmac_mmc[i].stat_string,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 125a177..7325256 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -946,7 +946,8 @@ static int stmmac_open(struct net_device *dev)
memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
priv->xstats.threshold = tc;
- stmmac_mmc_setup(priv);
+ if (priv->dma_cap.rmon)
+ stmmac_mmc_setup(priv);
/* Start the ball rolling... */
DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
--
1.7.4.4
^ permalink raw reply related
* [net-next 5/8] stmmac: use predefined macros for HW cap register fields (V4)
From: Giuseppe CAVALLARO @ 2011-10-18 10:01 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, Rayagond Kokatanur, Giuseppe Cavallaro
In-Reply-To: <1318932085-14927-1-git-send-email-peppe.cavallaro@st.com>
From: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 30 +++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 54 +++++++++++++--------
2 files changed, 63 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 22c61b2..ffba014 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -103,6 +103,36 @@ struct stmmac_extra_stats {
#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
+/* DAM HW feature register fields */
+#define DMA_HW_FEAT_MIISEL 0x00000001 /* 10/100 Mbps Support */
+#define DMA_HW_FEAT_GMIISEL 0x00000002 /* 1000 Mbps Support */
+#define DMA_HW_FEAT_HDSEL 0x00000004 /* Half-Duplex Support */
+#define DMA_HW_FEAT_EXTHASHEN 0x00000008 /* Expanded DA Hash Filter */
+#define DMA_HW_FEAT_HASHSEL 0x00000010 /* HASH Filter */
+#define DMA_HW_FEAT_ADDMACADRSEL 0x00000020 /* Multiple MAC Addr Reg */
+#define DMA_HW_FEAT_PCSSEL 0x00000040 /* PCS registers */
+#define DMA_HW_FEAT_L3L4FLTREN 0x00000080 /* Layer 3 & Layer 4 Feature */
+#define DMA_HW_FEAT_SMASEL 0x00000100 /* SMA(MDIO) Interface */
+#define DMA_HW_FEAT_RWKSEL 0x00000200 /* PMT Remote Wakeup */
+#define DMA_HW_FEAT_MGKSEL 0x00000400 /* PMT Magic Packet */
+#define DMA_HW_FEAT_MMCSEL 0x00000800 /* RMON Module */
+#define DMA_HW_FEAT_TSVER1SEL 0x00001000 /* Only IEEE 1588-2002 Timestamp */
+#define DMA_HW_FEAT_TSVER2SEL 0x00002000 /* IEEE 1588-2008 Adv Timestamp */
+#define DMA_HW_FEAT_EEESEL 0x00004000 /* Energy Efficient Ethernet */
+#define DMA_HW_FEAT_AVSEL 0x00008000 /* AV Feature */
+#define DMA_HW_FEAT_TXCOESEL 0x00010000 /* Checksum Offload in Tx */
+#define DMA_HW_FEAT_RXTYP1COE 0x00020000 /* IP csum Offload(Type 1) in Rx */
+#define DMA_HW_FEAT_RXTYP2COE 0x00040000 /* IP csum Offload(Type 2) in Rx */
+#define DMA_HW_FEAT_RXFIFOSIZE 0x00080000 /* Rx FIFO > 2048 Bytes */
+#define DMA_HW_FEAT_RXCHCNT 0x00300000 /* No. of additional Rx Channels */
+#define DMA_HW_FEAT_TXCHCNT 0x00c00000 /* No. of additional Tx Channels */
+#define DMA_HW_FEAT_ENHDESSEL 0x01000000 /* Alternate (Enhanced Descriptor) */
+#define DMA_HW_FEAT_INTTSEN 0x02000000 /* Timestamping with Internal
+ System Time */
+#define DMA_HW_FEAT_FLEXIPPSEN 0x04000000 /* Flexible PPS Output */
+#define DMA_HW_FEAT_SAVLANINS 0x08000000 /* Source Addr or VLAN Insertion */
+#define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY interface */
+
enum rx_frame_status { /* IPC status */
good_frame = 0,
discard_frame = 1,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 622b7ac..125a177 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -799,33 +799,45 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
u32 hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
if (likely(hw_cap)) {
- priv->dma_cap.mbps_10_100 = (hw_cap & 0x1);
- priv->dma_cap.mbps_1000 = (hw_cap & 0x2) >> 1;
- priv->dma_cap.half_duplex = (hw_cap & 0x4) >> 2;
- priv->dma_cap.hash_filter = (hw_cap & 0x10) >> 4;
- priv->dma_cap.multi_addr = (hw_cap & 0x20) >> 5;
- priv->dma_cap.pcs = (hw_cap & 0x40) >> 6;
- priv->dma_cap.sma_mdio = (hw_cap & 0x100) >> 8;
- priv->dma_cap.pmt_remote_wake_up = (hw_cap & 0x200) >> 9;
- priv->dma_cap.pmt_magic_frame = (hw_cap & 0x400) >> 10;
- priv->dma_cap.rmon = (hw_cap & 0x800) >> 11; /* MMC */
+ priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
+ priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
+ priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
+ priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
+ priv->dma_cap.multi_addr =
+ (hw_cap & DMA_HW_FEAT_ADDMACADRSEL) >> 5;
+ priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
+ priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
+ priv->dma_cap.pmt_remote_wake_up =
+ (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
+ priv->dma_cap.pmt_magic_frame =
+ (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
+ /*MMC*/
+ priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
/* IEEE 1588-2002*/
- priv->dma_cap.time_stamp = (hw_cap & 0x1000) >> 12;
+ priv->dma_cap.time_stamp =
+ (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
/* IEEE 1588-2008*/
- priv->dma_cap.atime_stamp = (hw_cap & 0x2000) >> 13;
+ priv->dma_cap.atime_stamp =
+ (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
/* 802.3az - Energy-Efficient Ethernet (EEE) */
- priv->dma_cap.eee = (hw_cap & 0x4000) >> 14;
- priv->dma_cap.av = (hw_cap & 0x8000) >> 15;
+ priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
+ priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
/* TX and RX csum */
- priv->dma_cap.tx_coe = (hw_cap & 0x10000) >> 16;
- priv->dma_cap.rx_coe_type1 = (hw_cap & 0x20000) >> 17;
- priv->dma_cap.rx_coe_type2 = (hw_cap & 0x40000) >> 18;
- priv->dma_cap.rxfifo_over_2048 = (hw_cap & 0x80000) >> 19;
+ priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
+ priv->dma_cap.rx_coe_type1 =
+ (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
+ priv->dma_cap.rx_coe_type2 =
+ (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
+ priv->dma_cap.rxfifo_over_2048 =
+ (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
/* TX and RX number of channels */
- priv->dma_cap.number_rx_channel = (hw_cap & 0x300000) >> 20;
- priv->dma_cap.number_tx_channel = (hw_cap & 0xc00000) >> 22;
+ priv->dma_cap.number_rx_channel =
+ (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
+ priv->dma_cap.number_tx_channel =
+ (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
/* Alternate (enhanced) DESC mode*/
- priv->dma_cap.enh_desc = (hw_cap & 0x1000000) >> 24;
+ priv->dma_cap.enh_desc =
+ (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
} else
pr_debug("\tNo HW DMA feature register supported");
--
1.7.4.4
^ permalink raw reply related
* [net-next 4/8] stmmac: allow mtu bigger than 1500 in case of normal desc (V4)
From: Giuseppe CAVALLARO @ 2011-10-18 10:01 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, Giuseppe Cavallaro, Deepak SIKRI
In-Reply-To: <1318932085-14927-1-git-send-email-peppe.cavallaro@st.com>
This patch allows to set the mtu bigger than 1500
in case of normal descriptors.
This is helping some SPEAr customers.
Signed-off-by: Deepak SIKRI <deepak.sikri@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 8 +++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 029c2a2..e13226b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -126,6 +126,7 @@ static void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
for (i = 0; i < ring_size; i++) {
p->des01.rx.own = 1;
p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
+ p->des01.rx.buffer2_size = BUF_SIZE_2KiB - 1;
if (i == ring_size - 1)
p->des01.rx.end_ring = 1;
if (disable_rx_ic)
@@ -183,7 +184,12 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
int csum_flag)
{
p->des01.tx.first_segment = is_fs;
- p->des01.tx.buffer1_size = len;
+
+ if (unlikely(len > BUF_SIZE_2KiB)) {
+ p->des01.etx.buffer1_size = BUF_SIZE_2KiB - 1;
+ p->des01.etx.buffer2_size = len - p->des01.etx.buffer1_size;
+ } else
+ p->des01.tx.buffer1_size = len;
}
static void ndesc_clear_tx_ic(struct dma_desc *p)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d0af002..622b7ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1412,10 +1412,10 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
return -EBUSY;
}
- if (priv->plat->has_gmac)
+ if (priv->plat->enh_desc)
max_mtu = JUMBO_LEN;
else
- max_mtu = ETH_DATA_LEN;
+ max_mtu = BUF_SIZE_4KiB;
if ((new_mtu < 46) || (new_mtu > max_mtu)) {
pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
--
1.7.4.4
^ permalink raw reply related
* [net-next 3/8] stmmac: update the driver version and doc (V4)
From: Giuseppe CAVALLARO @ 2011-10-18 10:01 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, Giuseppe Cavallaro
In-Reply-To: <1318932085-14927-1-git-send-email-peppe.cavallaro@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
Documentation/networking/stmmac.txt | 11 ++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 40ec92c..8d67980 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -76,7 +76,16 @@ core.
4.5) DMA descriptors
Driver handles both normal and enhanced descriptors. The latter has been only
-tested on DWC Ether MAC 10/100/1000 Universal version 3.41a.
+tested on DWC Ether MAC 10/100/1000 Universal version 3.41a and later.
+
+STMMAC supports DMA descriptor to operate both in dual buffer (RING)
+and linked-list(CHAINED) mode. In RING each descriptor points to two
+data buffer pointers whereas in CHAINED mode they point to only one data
+buffer pointer. RING mode is the default.
+
+In CHAINED mode each descriptor will have pointer to next descriptor in
+the list, hence creating the explicit chaining in the descriptor itself,
+whereas such explicit chaining is not possible in RING mode.
4.6) Ethtool support
Ethtool is supported. Driver statistics and internal errors can be taken using:
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 50e95d8..49a4af3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -20,7 +20,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
-#define DRV_MODULE_VERSION "Aug_2011"
+#define DRV_MODULE_VERSION "Oct_2011"
#include <linux/stmmac.h>
#include "common.h"
--
1.7.4.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox