* Multicast packets receiving problem on linux since version 3.10.1
From: Andrey Dmitrov @ 2014-01-17 15:10 UTC (permalink / raw)
To: netdev; +Cc: Konstantin Ushakov, Alexandra N. Kossovsky, Yurij Plotnikov
[-- Attachment #1: Type: text/plain, Size: 3118 bytes --]
Greetings,
there is a problem with receiving multicast packets on linux-3.10.1 and
newer. It's reproducible with two hosts (host_A, host_B), with eth3@host_A
directly connected to eth3@host_B. Two VLANs and one multicast group are
used.
Each side opens two sockets and binds them to different VLAN interfaces.
host_A arranges both sockets to receive multicast packets of the group.
Then the first socket is removed from the group. After this the second
socket
can no longer receive multicast packets of the group, which sent by the
second host. See the example below.
host_A:
Two VLANs 999 and 1001 are added on eth3:
eth3.999 10.208.14.1
eth3.1001 10.208.15.1
1. socket(SOCK_DGRAM) -> 3
2. setsockopt(3, SOL_SOCKET, SO_REUSEADDR, 1) -> 0
3. setsockopt(3, IPPROTO_IP, MCAST_JOIN_GROUP, {229.17.88.168,
eth3.999}) -> 0
4. setsockopt(3, SOL_SOCKET, SO_BINDTODEVICE, eth3.999) -> 0
5. bind(3, 0.0.0.0:29214)->0
6. socket(SOCK_DGRAM) -> 4
7. setsockopt(4, SOL_SOCKET, SO_REUSEADDR, 1) -> 0
8. setsockopt(4, IPPROTO_IP, MCAST_JOIN_GROUP, {229.17.88.168,
eth3.1001}) -> 0
9. setsockopt(4, SOL_SOCKET, SO_BINDTODEVICE, eth3.1001) -> 0
10. bind(4, 0.0.0.0:29214) -> 0
11. poll({{3, POLLIN}, {4, POLLIN}}, 2, 30000) -> 2
12. recv(3, buf, 100) -> 100
13. recv(4, buf, 99) -> 99
14. setsockopt(3, IPPROTO_IP, MCAST_LEAVE_GROUP, {229.17.88.168,
eth3.999}) -> 0
15. poll({{3, POLLIN}, {4, POLLIN}}, 2, 30000) -> 0
Socket 4 does not receive the multicast packet on linux 3.10 and newer. But
it receives the packet with older linux versions. Probably the packet is
filtered by NIC, tcpdump does not see it.
host_B:
Two VLANs 999 and 1001 are added on eth3:
eth3.999 10.208.14.2
eth3.1001 10.208.15.2
16. socket(SOCK_DGRAM) -> 3
17. bind(3, 10.208.14.2:29219) -> 0
18. socket(SOCK_DGRAM) -> 4
19. bind(4, 10.208.15.2:29219) -> 0
20. sendto(3, 229.17.88.168:29214, buf, 100) -> 100
21. sendto(4, 229.17.88.168:29214, buf, 99) -> 99
Continue when socket 3 on host_A will leave the group (line 14).
22. sendto(3, 229.17.88.168:29214, buf, 100) -> 100
23. sendto(4, 229.17.88.168:29214, buf, 99) -> 99
Note, that if I replace step #14 with:
> setsockopt(4, IPPROTO_IP, MCAST_LEAVE_GROUP, {229.17.88.168,
eth3.1001}) -> 0
and remove the second socket from the group (instead of the first one) -
then
the first socket will receive it's packet.
Find client and server C programs that reproduce the problem attached.
The client
logs received packets. As stated above in good case it will log 3
packets and in
bad one - only 2. Use the following command lines to start the client
and server:
host_A:
sudo ip link add link eth3 name eth3.999 type vlan id 999
sudo ifconfig eth3.999 10.208.14.1/24
sudo ip link add link eth3 name eth3.1001 type vlan id 1001
sudo ifconfig eth3.1001 10.208.15.1/24
gcc mcast_client.c -o cl
sudo ./cl
host_B:
sudo ip link add link eth3 name eth3.999 type vlan id 999
sudo ifconfig eth3.999 10.208.14.2/24
sudo ip link add link eth3 name eth3.1001 type vlan id 1001
sudo ifconfig eth3.1001 10.208.15.2/24
gcc mcast_serv.c -o serv
./serv
Thanks in advance,
Andrey Dmitrov
[-- Attachment #2: mcast_client.c --]
[-- Type: text/x-csrc, Size: 4162 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#define ERROR(_line...) \
do { \
fprintf(stderr, _line); \
fprintf(stderr, "\n"); \
assert(0); \
} while (0)
#define ERROR_CL(_line...) \
do { \
close(sock); \
ERROR(_line); \
} while (0)
#define WARN(_line...) \
do { \
printf(_line); \
printf("\n"); \
} while (0)
#define MCAST_GROUP "229.17.88.168"
#define PORT 12345
#define VLAN1 "999"
#define VLAN2 "1001"
#define VLAN_IF_STR(_vlan) "eth3." _vlan
#define VLAN_IF1 VLAN_IF_STR(VLAN1)
#define VLAN_IF2 VLAN_IF_STR(VLAN2)
static int
init_socket(const char *ifname)
{
int sock;
int val = 1;
struct group_req req;
struct sockaddr_in addr;
struct ifreq ifr;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
ERROR("Can't open socket: %s", strerror(errno));
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != 0)
ERROR_CL("Can't set SO_REUSEADDR for socket: %s", strerror(errno));
memset(&req, 0, sizeof(req));
if ((req.gr_interface = if_nametoindex(ifname)) <= 0)
ERROR_CL("Wrong interface index: %s", strerror(errno));
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
if (inet_pton(AF_INET, MCAST_GROUP, &addr.sin_addr) != 1)
ERROR_CL("Can't convert mcast group address: %s", strerror(errno));
memcpy(&req.gr_group, &addr, sizeof(addr));
if (setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, &req,
sizeof(req)) != 0)
ERROR_CL("Can't set SO_REUSEADDR for socket: %s", strerror(errno));
memset(&ifr, 0, sizeof(struct ifreq));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
if (ioctl(sock, SIOCGIFINDEX, &ifr) != 0)
ERROR_CL("Can't get interface index with ioctl: %s", strerror(errno));
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(struct ifreq)) != 0)
ERROR_CL("SO_BINDTODEVICE failed: %s", strerror(errno));
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
ERROR_CL("bind failed: %s", strerror(errno));
return sock;
}
static int
leave_group(int sock, const char *ifname)
{
struct group_req req;
struct sockaddr_in addr;
memset(&req, 0, sizeof(req));
if ((req.gr_interface = if_nametoindex(ifname)) <= 0)
{
WARN("Wrong interface index: %s", strerror(errno));
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
if (inet_pton(AF_INET, MCAST_GROUP, &addr.sin_addr) != 1)
{
WARN("Can't convert mcast group address: %s", strerror(errno));
return -1;
}
memcpy(&req.gr_group, &addr, sizeof(addr));
if (setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, &req, sizeof(req)) != 0)
{
WARN("Can't set SO_REUSEADDR for socket: %s", strerror(errno));
return -1;
}
return 0;
}
int
main(void)
{
int sock1;
int sock2;
char buf[100];
int len;
int rc = EXIT_SUCCESS;
sock1 = init_socket(VLAN_IF1);
sock2 = init_socket(VLAN_IF2);
if ((len = recv(sock1, buf, sizeof(buf), 0)) < 0)
WARN("Failed to receive packets: %s", strerror(errno));
WARN("packet length %d", len);
if ((len = recv(sock2, buf, sizeof(buf), 0)) < 0)
WARN("Failed to receive packets: %s", strerror(errno));
WARN("packet length %d", len);
if (leave_group(sock1, VLAN_IF1) != 0)
{
WARN("Failed to leave group");
rc = EXIT_FAILURE;
goto cleanup;
}
if ((len = recv(sock2, buf, sizeof(buf), 0)) < 0)
WARN("Failed to receive packets: %s", strerror(errno));
WARN("packet length %d", len);
if ((len = recv(sock1, buf, sizeof(buf), 0)) < 0)
WARN("Failed to receive packets: %s", strerror(errno));
WARN("packet length %d", len);
cleanup:
close(sock1);
close(sock2);
return rc;
}
[-- Attachment #3: mcast_serv.c --]
[-- Type: text/x-csrc, Size: 2678 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#define ERROR(_line...) \
do { \
fprintf(stderr, _line); \
fprintf(stderr, "\n"); \
assert(0); \
} while (0)
#define ERROR_CL(_line...) \
do { \
close(sock); \
ERROR(_line); \
} while (0)
#define WARN(_line...) \
do { \
printf(_line); \
printf("\n"); \
} while (0)
#define MCAST_GROUP "229.17.88.168"
#define GROUP_PORT 12345
#define LOCAL_PORT 23456
#define LOCAL_ADDR1 "10.208.14.2"
#define LOCAL_ADDR2 "10.208.15.2"
#define VLAN1 "999"
#define VLAN2 "1001"
#define VLAN_IF_STR(_vlan) "eth3." _vlan
#define VLAN_IF1 VLAN_IF_STR(VLAN1)
#define VLAN_IF2 VLAN_IF_STR(VLAN2)
static int
init_socket_send(const char *ifname, const char *local_addr)
{
int sock;
struct sockaddr_in addr;
struct in_addr ifaddr;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
ERROR("Can't open socket: %s", strerror(errno));
WARN("if %s, addr %s", ifname, local_addr);
if (inet_aton(local_addr, &ifaddr) == 0)
ERROR_CL("inet_aton failed: %s", strerror(errno));
if (setsockopt(sock, SOL_IP, IP_MULTICAST_IF, &ifaddr, sizeof(ifaddr)) != 0)
ERROR_CL("IP_MULTICAST_IF failed: %s", strerror(errno));
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(LOCAL_PORT);
if (inet_pton(AF_INET, local_addr, &addr.sin_addr) != 1)
ERROR_CL("Can't convert mcast group address: %s", strerror(errno));
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
ERROR_CL("bind failed: %s", strerror(errno));
return sock;
}
int
main(void)
{
int sock1;
int sock2;
char buf[100];
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(GROUP_PORT);
if (inet_pton(AF_INET, MCAST_GROUP, &addr.sin_addr) != 1)
ERROR("Can't convert mcast group address: %s", strerror(errno));
sock1 = init_socket_send(VLAN_IF1, LOCAL_ADDR1);
sock2 = init_socket_send(VLAN_IF2, LOCAL_ADDR2);
if (sendto(sock1, buf, 99, 0, (struct sockaddr *)&addr, sizeof(addr)) != 99 ||
sendto(sock2, buf, 98, 0, (struct sockaddr *)&addr, sizeof(addr)) != 98)
WARN("send failed: %s", strerror(errno));
sleep(1);
if (sendto(sock1, buf, 97, 0, (struct sockaddr *)&addr, sizeof(addr)) != 97 ||
sendto(sock2, buf, 96, 0, (struct sockaddr *)&addr, sizeof(addr)) != 96)
WARN("send failed: %s", strerror(errno));
close(sock1);
close(sock2);
return EXIT_SUCCESS;
}
^ permalink raw reply
* RE: PROBLEM: usbnet / ax88179_178a: Panic in usb_hcd_map_urb_for_dma
From: David Laight @ 2014-01-17 14:46 UTC (permalink / raw)
To: 'Ming Lei'
Cc: Bjørn Mork, Thomas Kear, Ben Hutchings, netdev,
linux-usb@vger.kernel.org
In-Reply-To: <CACVXFVOGxWe5+o0hLROiPN43OCDekV2Ovz1yXr95H1m+yHGn4w@mail.gmail.com>
From: Ming Lei
> On Mon, Jan 13, 2014 at 9:26 PM, David Laight <David.Laight@aculab.com> wrote:
> >>
> >> I believe all processing use the urb->num_sgs field to limit the number
> >> of entries. Common interfaces like dma_map_sg() and for_each_sg() limit
> >> their processing to "nents" entries, and the USB code use the value of
> >> urb->num_sgs for this parameter.
> >
> > Which mostly means that the sg_xxx functions are doing a whole load
> > of unnecessary instructions and memory accesses...
> >
> > This probably has a lot to do with the significant difference in the
> > cpu use for the usb3 and 'normal' ethernet interfaces.
> >
> > While each bit doesn't seem significant, they soon add up.
>
> If you plan to remove the 'nents' parameter, I am wondering if it is
> a good idea, because sg_nents() should be more heavy. Not mention
> sometimes the callers just want to map/unmap part of entries.
I was thinking of using a simple address/length array without all
the extra fields and flags 'overpunched' in the low address bits.
I'm not even sure the current use is strictly correct.
The field names of the scatterlist have a page address and offset
but the buffers passed to xhci (at least by usbnet) can span multiple
pages - they are physically contiguous.
IIRC some traces of requests for USB disks show a separate SG entry
for each 4k page - even for both virtually and physically adjacent
pages.
David
^ permalink raw reply
* Re: [PATCH v2] sch_htb: let skb->priority refer to non-leaf class
From: Eric Dumazet @ 2014-01-17 14:35 UTC (permalink / raw)
To: Harry Mason; +Cc: Jamal Hadi Salim, linux-netdev
In-Reply-To: <1389953999.4698.18.camel@azathoth.dev.smoothwall.net>
On Fri, 2014-01-17 at 10:19 +0000, Harry Mason wrote:
> If the class in skb->priority is not a leaf, apply filters from the
> selected class, not the qdisc. This lets netfilter or user space
> partially classify the packet.
>
> Signed-off-by: Harry Mason <harry.mason@smoothwall.net>
> ---
>
> On Thu, 2014-01-16 at 08:25 -0800, Eric Dumazet wrote:
> > On Thu, 2014-01-16 at 14:45 +0000, Harry Mason wrote:
> >
> >> + /* Start with inner filter chain if a non-leaf class is selected */
> >> + if (cl)
> >> + tcf = cl->filter_list;
> >> + else
> >> + tcf = q->filter_list;
> >
> > Could this break some existing htb setups ?
>
> I think it is unlikely. Setting skb->priority to a non-leaf class would
> be equivalent to setting it to the base qdisc. In theory an application
> might rely on this if it expects the classes to be dynamic, but adding
> a filter could restore the old behaviour.
>
Problem is : Your patch is one patch among thousands of patches, and
people will install new kernels without knowing this could have an
impact on their setup and might discover the problems too late
(after some failure)
> To me this is intuitively how it should behave, and reproduces what would
> happen if a tc filter instead of netfilter had first assigned the
> non-leaf class.
This is definitely a patch for net-next, not net tree.
>
> > Also we test cl being NULL at line 222, it would be nice to not
> > test it again...
>
> Updated below.
>
> net/sched/sch_htb.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
> index 717b210..8073d92 100644
> --- a/net/sched/sch_htb.c
> +++ b/net/sched/sch_htb.c
> @@ -219,11 +219,15 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
> if (skb->priority == sch->handle)
> return HTB_DIRECT; /* X:0 (direct flow) selected */
> cl = htb_find(skb->priority, sch);
> - if (cl && cl->level == 0)
> - return cl;
> + if (cl) {
> + if (cl->level == 0)
> + return cl;
> + /* Start with inner filter chain if a non-leaf class is selected */
> + tcf = cl->filter_list;
> + } else
> + tcf = q->filter_list;
>
} else {
tcf = q->filter_list;
}
(Documentation/CodingStyle line 169)
> *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
> - tcf = q->filter_list;
> while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
> #ifdef CONFIG_NET_CLS_ACT
> switch (result) {
^ permalink raw reply
* Re: [PATCH net] net: core: orphan frags before queuing to slow qdisc
From: Eric Dumazet @ 2014-01-17 14:28 UTC (permalink / raw)
To: Jason Wang; +Cc: davem, netdev, linux-kernel, Michael S. Tsirkin
In-Reply-To: <1389951734-13234-1-git-send-email-jasowang@redhat.com>
On Fri, 2014-01-17 at 17:42 +0800, Jason Wang wrote:
> Many qdiscs can queue a packet for a long time, this will lead an issue
> with zerocopy skb. It means the frags will not be orphaned in an expected
> short time, this breaks the assumption that virtio-net will transmit the
> packet in time.
>
> So if guest packets were queued through such kind of qdisc and hit the
> limitation of the max pending packets for virtio/vhost. All packets that
> go to another destination from guest will also be blocked.
>
> A case for reproducing the issue:
>
> - Boot two VMs and connect them to the same bridge kvmbr.
> - Setup tbf with a very low rate/burst on eth0 which is a port of kvmbr.
> - Let VM1 send lots of packets thorugh eth0
> - After a while, VM1 is unable to send any packets out since the number of
> pending packets (queued to tbf) were exceeds the limitation of vhost/virito
So whats the problem ? If the limit is low, you cannot sent packets.
Solution : increase the limit, or tell the vm to lower its rate.
Oh wait, are you bitten because you did some prior skb_orphan() to allow
the vm to send unlimited number of skbs ???
>
> Solve this issue by orphaning the frags before queuing it to a slow qdisc (the
> one without TCQ_F_CAN_BYPASS).
Why orphaning the frags only solves the problem ? A skb without zerocopy
frags should also be blocked for a while.
Seriously, lets admit this zero copy stuff is utterly broken.
TCQ_F_CAN_BYPASS is not enough. Some NIC have separate queues with
strict priorities.
It seems to me that you are pushing to use FIFO (the only qdisc setting
TCQ_F_CAN_BYPASS), by adding yet another test in fast path (I do not
know how we can still call it a fast path), while we already have smart
qdisc to avoid the inherent HOL and unfairness problems of FIFO.
>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> net/core/dev.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 0ce469e..1209774 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2700,6 +2700,12 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
> contended = qdisc_is_running(q);
> if (unlikely(contended))
> spin_lock(&q->busylock);
> + if (!(q->flags & TCQ_F_CAN_BYPASS) &&
> + unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) {
> + kfree_skb(skb);
> + rc = NET_XMIT_DROP;
> + goto out;
> + }
Are you aware that copying stuff takes time ?
If yes, why is it done after taking the busylock spinlock ?
>
> spin_lock(root_lock);
> if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
> @@ -2739,6 +2745,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
> }
> }
> spin_unlock(root_lock);
> +out:
> if (unlikely(contended))
> spin_unlock(&q->busylock);
> return rc;
^ permalink raw reply
* Re: [PATCH v4 net-next 2/4] sh_eth: Add support for r7s72100
From: Sergei Shtylyov @ 2014-01-17 14:05 UTC (permalink / raw)
To: Simon Horman
Cc: David S. Miller, netdev, linux-sh, linux-arm-kernel, Magnus Damm
In-Reply-To: <20140117061301.GD16455@verge.net.au>
Hello.
On 17-01-2014 10:13, Simon Horman wrote:
>>>>>>> This is a fast ethernet controller.
>>>>>>> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
>>>>>> [...]
>>>>>>> diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
>>>>>>> index 4b38533..cc6d4af 100644
>>>>>>> --- a/drivers/net/ethernet/renesas/sh_eth.c
>>>>>>> +++ b/drivers/net/ethernet/renesas/sh_eth.c
>>>>>>> @@ -190,6 +190,59 @@ static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
>>>> [...]
>>>>>>> @@ -701,6 +762,35 @@ static struct sh_eth_cpu_data r8a7740_data = {
>>>>>>> .shift_rd0 = 1,
>>>>>>> };
>>>>>>>
>>>>>>> +/* R7S72100 */
>>>>>>> +static struct sh_eth_cpu_data r7s72100_data = {
>>>>>>> + .chip_reset = sh_eth_chip_reset,
>>>>>>> + .set_duplex = sh_eth_set_duplex,
>>>>>>> +
>>>>>>> + .register_type = SH_ETH_REG_FAST_RZ,
>>>>>>> +
>>>>>>> + .ecsr_value = ECSR_ICD,
>>>>>>> + .ecsipr_value = ECSIPR_ICDIP,
>>>>>>> + .eesipr_value = 0xff7f009f,
>>>>>>> +
>>>>>>> + .tx_check = EESR_TC1 | EESR_FTC,
>>>>>>> + .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
>>>>>>> + EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
>>>>>>> + EESR_TDE | EESR_ECI,
>>>>>>> + .fdr_value = 0x0000070f,
>>>>>>> + .rmcr_value = RMCR_RNC,
>>>>>>> +
>>>>>>> + .apr = 1,
>>>>>>> + .mpr = 1,
>>>>>>> + .tpauser = 1,
>>>>>>> + .hw_swap = 1,
>>>>>>> + .rpadir = 1,
>>>>>>> + .rpadir_value = 2 << 16,
>>>>>>> + .no_trimd = 1,
>>>>>>> + .tsu = 1,
>>>>>>> + .shift_rd0 = 1,
>>>>>> Perhaps this field should be renamed to something talking about
>>>>>> check summing support (since bits 0..15 of RD0 contain a frame check
>>>>>> sum for those SoCs). Or maybe it should be just merged with the
>>>>>> 'hw_crc' field...
>>>>> I have no feelings about that one way or another.
>>>> Do you happen to have R8A7740 manual by chance? If so, does it
>>>> talk about RX check summing support and using RD0 for that?
>>> Yes and yes.
>>> I have taken a quick look and the documentation for RX checksumming on the
>>> R8A7740 appears to be very similar if not the same as that of the R7S72100.
>>> In particular both refer to using the bottom 16 bits of RD0 as
>>> containing the packet checksum.
>> OK, now if you had SH7734 manual to completely confirm that check
>> sum is stored in the same place there... most probably it is, of
>> course, and we should merge 'hw_crc' and 'shift_rd0' into a single
>> field.
> Unfortunately I don't have access to that manual.
Anyway, we also need Gen2 manuals accepting the fact that checksumming is
also supported (they also set 'shift_rd0' field) and giving the mapping of CSMR...
WBR, Sergei
^ permalink raw reply
* Re: [Xen-devel] [PATCH net-next v2] xen-netfront: clean up code in xennet_release_rx_bufs
From: Wei Liu @ 2014-01-17 14:02 UTC (permalink / raw)
To: annie li
Cc: Wei Liu, David Vrabel, ian.campbell, netdev, xen-devel,
andrew.bennieston, davem
In-Reply-To: <52D922DD.2060407@oracle.com>
On Fri, Jan 17, 2014 at 08:32:29PM +0800, annie li wrote:
>
> On 2014-1-17 20:08, Wei Liu wrote:
> >On Fri, Jan 17, 2014 at 02:25:40PM +0800, annie li wrote:
> >>On 2014/1/16 19:10, David Vrabel wrote:
> >>>On 15/01/14 23:57, Annie Li wrote:
> >>>>This patch implements two things:
> >>>>
> >>>>* release grant reference and skb for rx path, this fixex resource leaking.
> >>>>* clean up grant transfer code kept from old netfront(2.6.18) which grants
> >>>>pages for access/map and transfer. But grant transfer is deprecated in current
> >>>>netfront, so remove corresponding release code for transfer.
> >>>>
> >>>>gnttab_end_foreign_access_ref may fail when the grant entry is currently used
> >>>>for reading or writing. But this patch does not cover this and improvement for
> >>>>this failure may be implemented in a separate patch.
> >>>I don't think replacing a resource leak with a security bug is a good idea.
> >>>
> >>>If you would prefer not to fix the gnttab_end_foreign_access() call, I
> >>>think you can fix this in netfront by taking a reference to the page
> >>>before calling gnttab_end_foreign_access(). This will ensure the page
> >>>isn't freed until the subsequent kfree_skb(), or the gref is released by
> >>>the foreign domain (whichever is later).
> >>Taking a reference to the page before calling
> >>gnttab_end_foreign_access() delays the free work until kfree_skb().
> >>Simply adding put_page before kfree_skb() does not make things
> >>different from gnttab_end_foreign_access_ref(), and the pages will
> >>be freed by kfree_skb(), problem will be hit in
> >>gnttab_handle_deferred() when freeing pages which already be freed.
> >>
> >I think David's idea is:
> >
> > get_page
> > gnttab_end_foreign_access
> > kfree_skb
> >
> >The get_page is to offset put_page in gnttab_end_foreign_access. You
> >don't need to put page before kfree_skb.
>
> Yes, this is what I described as following about David's patch.
>
> >>So put_page is required in gnttab_end_foreign_access(), this will
> >>ensure either free is taken by kfree_skb or gnttab_handle_deferred.
> >>This involves changes in blkfront/pcifront/tpmfront(just like your
> >>patch), this way ensure page is released when ref is end.
>
> But this would has some issue in netfront tx path. Netfront ends all
What issue with tx path? Your patch only touches rx skbs, doesn't it?
> grant reference of one skb first and then release this skb. If the
> gnttab_end_foreign_access_ref fails in gnttab_end_foreign_access(),
> this frag page and corresponding grant reference will be put in
> entry and release work will be done in the timer routine. If some
I understand up to this point.
> frag pages of one skb is free in this timer routine, then
> dev_kfree_skb_irq will free pages which have been freed.
Why is dev_kfree_skb_irq involved? It is used in tx path not rx path.
Even if we look at dev_kfree_skb_irq, it calls __kfree_skb for dropped
packet eventually, which should do the right thing if we don't mess up
ref counts.
Wei.
> So I prefer following way I mentioned, suggestions?
>
> >>Another solution I am thinking is calling
> >>gnttab_end_foreign_access() with page parameter as NULL, then
> >>gnttab_end_foreign_access will only do ending grant reference work
> >>and releasing page work is done by kfree_skb().
>
> Thanks
> Annie
^ permalink raw reply
* [PATCH net-next v3 8/8] net: stmmac: sunxi platform extensions for GMAC in Allwinner A20 SoC's
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
The Allwinner A20 has an ethernet controller that seems to be
an early version of Synopsys DesignWare MAC 10/100/1000 Universal,
which is supported by the stmmac driver.
Allwinner's GMAC requires setting additional registers in the SoC's
clock control unit.
The exact version of the DWMAC IP that Allwinner uses is unknown,
thus the exact feature set is unknown.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
.../bindings/net/allwinner,sun7i-a20-gmac.txt | 27 ++++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 141 +++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
6 files changed, 186 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
new file mode 100644
index 0000000..ea4d752
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
@@ -0,0 +1,27 @@
+* Allwinner GMAC ethernet controller
+
+This device is a platform glue layer for stmmac.
+Please see stmmac.txt for the other unchanged properties.
+
+Required properties:
+ - compatible: Should be "allwinner,sun7i-a20-gmac"
+ - clocks: Should contain the GMAC main clock, and tx clock
+ The tx clock type should be "allwinner,sun7i-a20-gmac-clk"
+ - clock-names: Should contain the clock names "stmmaceth",
+ and "allwinner_gmac_tx"
+
+Optional properties:
+- phy-supply: phandle to a regulator if the PHY needs one
+
+Examples:
+
+ gmac: ethernet@01c50000 {
+ compatible = "allwinner,sun7i-a20-gmac";
+ reg = <0x01c50000 0x10000>,
+ <0x01c20164 0x4>;
+ interrupts = <0 85 1>;
+ interrupt-names = "macirq";
+ clocks = <&ahb_gates 49>, <&gmac_tx>;
+ clock-names = "stmmaceth", "allwinner_gmac_tx";
+ phy-mode = "mii";
+ };
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index b59d1ef..e2f202e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -26,6 +26,17 @@ config STMMAC_PLATFORM
If unsure, say N.
+config DWMAC_SUNXI
+ bool "Allwinner GMAC support"
+ depends on STMMAC_PLATFORM && ARCH_SUNXI
+ default y
+ ---help---
+ Support for Allwinner A20/A31 GMAC ethernet controllers.
+
+ This selects Allwinner SoC glue layer support for the
+ stmmac device driver. This driver is used for A20/A31
+ GMAC ethernet controller.
+
config STMMAC_PCI
bool "STMMAC PCI bus support"
depends on STMMAC_ETH && PCI
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 356a9dd..ecadece 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_STMMAC_ETH) += stmmac.o
stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
+stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
chain_mode.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/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
new file mode 100644
index 0000000..dc4f8ae
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -0,0 +1,141 @@
+/**
+ * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer
+ *
+ * Copyright (C) 2013 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include <linux/stmmac.h>
+#include <linux/clk.h>
+#include <linux/phy.h>
+#include <linux/of_net.h>
+#include <linux/regulator/consumer.h>
+
+struct sunxi_priv_data {
+ int interface;
+ int clk_enabled;
+ struct clk *tx_clk;
+ struct regulator *regulator;
+};
+
+static void *sun7i_gmac_setup(struct platform_device *pdev)
+{
+ struct sunxi_priv_data *gmac;
+ struct device *dev = &pdev->dev;
+
+ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
+ if (!gmac)
+ return ERR_PTR(-ENOMEM);
+
+ gmac->interface = of_get_phy_mode(dev->of_node);
+
+ gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
+ if (IS_ERR(gmac->tx_clk)) {
+ dev_err(dev, "could not get tx clock\n");
+ return gmac->tx_clk;
+ }
+
+ /* Optional regulator for PHY */
+ gmac->regulator = devm_regulator_get_optional(dev, "phy");
+ if (IS_ERR(gmac->regulator)) {
+ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
+ return ERR_PTR(-EPROBE_DEFER);
+ dev_info(dev, "no regulator found\n");
+ gmac->regulator = NULL;
+ }
+
+ return gmac;
+}
+
+#define SUN7I_GMAC_GMII_RGMII_RATE 125000000
+#define SUN7I_GMAC_MII_RATE 25000000
+
+static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
+{
+ struct sunxi_priv_data *gmac = priv;
+ int ret;
+
+ if (gmac->regulator) {
+ ret = regulator_enable(gmac->regulator);
+ if (ret)
+ return ret;
+ }
+
+ /* Set GMAC interface port mode
+ *
+ * The GMAC TX clock lines are configured by setting the clock
+ * rate, which then uses the auto-reparenting feature of the
+ * clock driver, and enabling/disabling the clock.
+ */
+ if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
+ clk_prepare_enable(gmac->tx_clk);
+ gmac->clk_enabled = 1;
+ } else {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
+ clk_prepare(gmac->tx_clk);
+ }
+
+ return 0;
+}
+
+static void sun7i_gmac_exit(struct platform_device *pdev, void *priv)
+{
+ struct sunxi_priv_data *gmac = priv;
+
+ if (gmac->clk_enabled) {
+ clk_disable(gmac->tx_clk);
+ gmac->clk_enabled = 0;
+ }
+ clk_unprepare(gmac->tx_clk);
+
+ if (gmac->regulator)
+ regulator_disable(gmac->regulator);
+}
+
+static void sun7i_fix_speed(void *priv, unsigned int speed)
+{
+ struct sunxi_priv_data *gmac = priv;
+
+ /* only GMII mode requires us to reconfigure the clock lines */
+ if (gmac->interface != PHY_INTERFACE_MODE_GMII)
+ return;
+
+ if (gmac->clk_enabled) {
+ clk_disable(gmac->tx_clk);
+ gmac->clk_enabled = 0;
+ }
+ clk_unprepare(gmac->tx_clk);
+
+ if (speed == 1000) {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
+ clk_prepare_enable(gmac->tx_clk);
+ gmac->clk_enabled = 1;
+ } else {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
+ clk_prepare(gmac->tx_clk);
+ }
+}
+
+/* of_data specifying hardware features and callbacks.
+ * hardware features were copied from Allwinner drivers. */
+const struct stmmac_of_data sun7i_gmac_data = {
+ .has_gmac = 1,
+ .tx_coe = 1,
+ .fix_mac_speed = sun7i_fix_speed,
+ .setup = sun7i_gmac_setup,
+ .init = sun7i_gmac_init,
+ .exit = sun7i_gmac_exit,
+};
+
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index c1c141f..d9af26e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -130,6 +130,9 @@ void stmmac_disable_eee_mode(struct stmmac_priv *priv);
bool stmmac_eee_init(struct stmmac_priv *priv);
#ifdef CONFIG_STMMAC_PLATFORM
+#ifdef CONFIG_DWMAC_SUNXI
+extern const struct stmmac_of_data sun7i_gmac_data;
+#endif
extern struct platform_driver stmmac_pltfr_driver;
static inline int stmmac_register_platform(void)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index bf119db..9d4baa8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -30,6 +30,9 @@
#include "stmmac.h"
static const struct of_device_id stmmac_dt_ids[] = {
+#ifdef CONFIG_DWMAC_SUNXI
+ { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
+#endif
/* SoC specific glue layers should come before generic bindings */
{ .compatible = "st,spear600-gmac"},
{ .compatible = "snps,dwmac-3.610"},
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 7/8] net: stmmac: Use driver data and callbacks tied with compatible strings
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
The stmmac driver core allows passing feature flags and callbacks via
platform data. Add a similar stmmac_of_data to pass flags and callbacks
tied to compatible strings. This allows us to extend stmmac with glue
layers for different SoCs.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 +++++++++++++++++-----
include/linux/stmmac.h | 18 +++++++++
2 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 82110f1..bf119db 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -26,8 +26,20 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_net.h>
+#include <linux/of_device.h>
#include "stmmac.h"
+static const struct of_device_id stmmac_dt_ids[] = {
+ /* SoC specific glue layers should come before generic bindings */
+ { .compatible = "st,spear600-gmac"},
+ { .compatible = "snps,dwmac-3.610"},
+ { .compatible = "snps,dwmac-3.70a"},
+ { .compatible = "snps,dwmac-3.710"},
+ { .compatible = "snps,dwmac"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
+
#ifdef CONFIG_OF
static int stmmac_probe_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat,
@@ -35,10 +47,32 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
{
struct device_node *np = pdev->dev.of_node;
struct stmmac_dma_cfg *dma_cfg;
+ const struct of_device_id *device;
if (!np)
return -ENODEV;
+ device = of_match_device(stmmac_dt_ids, &pdev->dev);
+ if (!device)
+ return -ENODEV;
+
+ if (device->data) {
+ const struct stmmac_of_data *data = device->data;
+ plat->has_gmac = data->has_gmac;
+ plat->enh_desc = data->enh_desc;
+ plat->tx_coe = data->tx_coe;
+ plat->rx_coe = data->rx_coe;
+ plat->bugged_jumbo = data->bugged_jumbo;
+ plat->pmt = data->pmt;
+ plat->riwt_off = data->riwt_off;
+ plat->fix_mac_speed = data->fix_mac_speed;
+ plat->bus_setup = data->bus_setup;
+ plat->setup = data->setup;
+ plat->free = data->free;
+ plat->init = data->init;
+ plat->exit = data->exit;
+ }
+
*mac = of_get_mac_address(np);
plat->interface = of_get_phy_mode(np);
@@ -259,16 +293,6 @@ static int stmmac_pltfr_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
stmmac_pltfr_suspend, stmmac_pltfr_resume);
-static const struct of_device_id stmmac_dt_ids[] = {
- { .compatible = "st,spear600-gmac"},
- { .compatible = "snps,dwmac-3.610"},
- { .compatible = "snps,dwmac-3.70a"},
- { .compatible = "snps,dwmac-3.710"},
- { .compatible = "snps,dwmac"},
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
-
struct platform_driver stmmac_pltfr_driver = {
.probe = stmmac_pltfr_probe,
.remove = stmmac_pltfr_remove,
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 0a5a7ac..1367974 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -121,4 +121,22 @@ struct plat_stmmacenet_data {
void *custom_data;
void *bsp_priv;
};
+
+/* of_data for SoC glue layer device tree bindings */
+
+struct stmmac_of_data {
+ int has_gmac;
+ int enh_desc;
+ int tx_coe;
+ int rx_coe;
+ int bugged_jumbo;
+ int pmt;
+ int riwt_off;
+ void (*fix_mac_speed)(void *priv, unsigned int speed);
+ void (*bus_setup)(void __iomem *ioaddr);
+ void *(*setup)(struct platform_device *pdev);
+ void (*free)(struct platform_device *pdev, void *priv);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
+};
#endif
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 6/8] net: stmmac: Deprecate snps,phy-addr and auto-detect PHY address
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
The snps,phy-addr device tree property is non-standard, and should be
removed in favor of proper phy node support. Remove it from the binding
documents and warn if the property is still used.
Most PHYs respond to address 0, but a few don't, so auto-detect PHY
address by default, to make up for the lack of explicit address selection.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
Documentation/devicetree/bindings/net/stmmac.txt | 1 -
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 9 ++++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index d132513..aefb639 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -12,7 +12,6 @@ Required properties:
property
- phy-mode: String, operation mode of the PHY interface.
Supported values are: "mii", "rmii", "gmii", "rgmii".
-- snps,phy-addr phy address to connect to.
- snps,reset-gpio gpio number for phy reset.
- snps,reset-active-low boolean flag to indicate if phy reset is active low.
- snps,reset-delays-us is triplet of delays
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 634260e..82110f1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -50,7 +50,14 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
if (plat->bus_id < 0)
plat->bus_id = 0;
- of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr);
+ /* Default to phy auto-detection */
+ plat->phy_addr = -1;
+
+ /* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ * and warn of its use. Remove this when phy node support is added.
+ */
+ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
+ dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
sizeof(struct stmmac_mdio_bus_data),
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 5/8] net: stmmac: Honor DT parameter to force DMA store and forward mode
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
"snps,force_sf_dma_mode" is documented in stmmac device tree bindings,
but is never handled by the driver.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 704a5e0..634260e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -56,6 +56,8 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
sizeof(struct stmmac_mdio_bus_data),
GFP_KERNEL);
+ plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode");
+
/*
* Currently only the properties needed on SPEAr600
* are provided. All other properties should be added
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 4/8] blackfin: Update stmmac callback signatures
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
Mike Frysinger,
uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
stmmac callbacks have been extended for better separation.
Update them to avoid breakage.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
arch/blackfin/mach-bf609/boards/ezkit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c
index 82beedd..05194e9 100644
--- a/arch/blackfin/mach-bf609/boards/ezkit.c
+++ b/arch/blackfin/mach-bf609/boards/ezkit.c
@@ -117,7 +117,7 @@ static struct stmmac_dma_cfg eth_dma_cfg = {
.pbl = 2,
};
-int stmmac_ptp_clk_init(struct platform_device *pdev)
+int stmmac_ptp_clk_init(struct platform_device *pdev, void *priv)
{
bfin_write32(PADS0_EMAC_PTP_CLKSEL, 0);
return 0;
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 3/8] net: stmmac: Allocate and pass soc/board specific data to callbacks
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
The current .init and .exit callbacks requires access to driver
private data structures. This is not a good seperation and abstraction.
Instead, we add a new .setup callback for allocating private data, and
pass the returned pointer to the other callbacks.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
Documentation/networking/stmmac.txt | 12 ++++++++----
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 18 ++++++++++++++----
include/linux/stmmac.h | 6 ++++--
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index cdd916d..2090895 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -127,8 +127,9 @@ struct plat_stmmacenet_data {
int riwt_off;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
- int (*init)(struct platform_device *pdev);
- void (*exit)(struct platform_device *pdev);
+ void *(*setup)(struct platform_device *pdev);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
void *custom_cfg;
void *custom_data;
void *bsp_priv;
@@ -169,10 +170,13 @@ Where:
o bus_setup: perform HW setup of the bus. For example, on some ST platforms
this field is used to configure the AMBA bridge to generate more
efficient STBus traffic.
- o init/exit: callbacks used for calling a custom initialization;
+ o setup/init/exit: callbacks used for calling a custom initialization;
this is sometime necessary on some platforms (e.g. ST boxes)
where the HW needs to have set some PIO lines or system cfg
- registers.
+ registers. setup should return a pointer to private data,
+ which will be stored in bsp_priv, and then passed to init and
+ exit callbacks. init/exit callbacks should not use or modify
+ platform data.
o custom_cfg/custom_data: this is a custom configuration that can be passed
while initializing the resources.
o bsp_priv: another private pointer.
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index cc6b89a7..704a5e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -144,9 +144,16 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
}
}
+ /* Custom setup (if needed) */
+ if (plat_dat->setup) {
+ plat_dat->bsp_priv = plat_dat->setup(pdev);
+ if (IS_ERR(plat_dat->bsp_priv))
+ return PTR_ERR(plat_dat->bsp_priv);
+ }
+
/* Custom initialisation (if needed)*/
if (plat_dat->init) {
- ret = plat_dat->init(pdev);
+ ret = plat_dat->init(pdev, plat_dat->bsp_priv);
if (unlikely(ret))
return ret;
}
@@ -203,7 +210,10 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
int ret = stmmac_dvr_remove(ndev);
if (priv->plat->exit)
- priv->plat->exit(pdev);
+ priv->plat->exit(pdev, priv->plat->bsp_priv);
+
+ if (priv->plat->free)
+ priv->plat->free(pdev, priv->plat->bsp_priv);
return ret;
}
@@ -218,7 +228,7 @@ static int stmmac_pltfr_suspend(struct device *dev)
ret = stmmac_suspend(ndev);
if (priv->plat->exit)
- priv->plat->exit(pdev);
+ priv->plat->exit(pdev, priv->plat->bsp_priv);
return ret;
}
@@ -230,7 +240,7 @@ static int stmmac_pltfr_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
if (priv->plat->init)
- priv->plat->init(pdev);
+ priv->plat->init(pdev, priv->plat->bsp_priv);
return stmmac_resume(ndev);
}
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 33ace71..0a5a7ac 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -113,8 +113,10 @@ struct plat_stmmacenet_data {
int max_speed;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
- int (*init)(struct platform_device *pdev);
- void (*exit)(struct platform_device *pdev);
+ void *(*setup)(struct platform_device *pdev);
+ void (*free)(struct platform_device *pdev, void *priv);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
void *custom_cfg;
void *custom_data;
void *bsp_priv;
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 2/8] net: stmmac: Add support for optional reset control
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
The DWMAC has a reset assert line, which is used on some SoCs. Add an
optional reset control to stmmac driver core.
To support reset control deferred probing, this patch changes the driver
probe function to return the actual error, instead of just -EINVAL.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
Documentation/devicetree/bindings/net/stmmac.txt | 3 +++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 4 ++--
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++--
6 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index eba0e5e..d132513 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -30,6 +30,9 @@ Required properties:
Optional properties:
- mac-address: 6 bytes, mac address
+- resets: Should contain a phandle to the STMMAC reset signal, if any
+- reset-names: Should contain the reset signal name "stmmaceth", if a
+ reset phandle is given
Examples:
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 6e52c0f..b59d1ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -5,6 +5,7 @@ config STMMAC_ETH
select PHYLIB
select CRC32
select PTP_1588_CLOCK
+ select RESET_CONTROLLER
---help---
This is the driver for the Ethernet IPs are built around a
Synopsys IP Core and only tested on the STMicroelectronics
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 73709e9..c1c141f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -32,6 +32,7 @@
#include <linux/pci.h>
#include "common.h"
#include <linux/ptp_clock_kernel.h>
+#include <linux/reset.h>
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
@@ -91,6 +92,7 @@ struct stmmac_priv {
int wolopts;
int wol_irq;
struct clk *stmmac_clk;
+ struct reset_control *stmmac_rst;
int clk_csr;
struct timer_list eee_ctrl_timer;
int lpi_irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 0d2c4cb..0c5c120 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -51,6 +51,7 @@
#include <linux/net_tstamp.h>
#include "stmmac_ptp.h"
#include "stmmac.h"
+#include <linux/reset.h>
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
#define JUMBO_LEN 9000
@@ -2728,10 +2729,24 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if (IS_ERR(priv->stmmac_clk)) {
dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
__func__);
+ ret = PTR_ERR(priv->stmmac_clk);
goto error_clk_get;
}
clk_prepare_enable(priv->stmmac_clk);
+ priv->stmmac_rst = devm_reset_control_get(priv->device,
+ STMMAC_RESOURCE_NAME);
+ if (IS_ERR(priv->stmmac_rst)) {
+ if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto error_hw_init;
+ }
+ dev_info(priv->device, "no reset control found\n");
+ priv->stmmac_rst = NULL;
+ }
+ if (priv->stmmac_rst)
+ reset_control_deassert(priv->stmmac_rst);
+
/* Init MAC and get the capabilities */
ret = stmmac_hw_init(priv);
if (ret)
@@ -2808,7 +2823,7 @@ error_hw_init:
error_clk_get:
free_netdev(ndev);
- return NULL;
+ return ERR_PTR(ret);
}
/**
@@ -2832,6 +2847,8 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
+ if (priv->stmmac_rst)
+ reset_control_assert(priv->stmmac_rst);
clk_disable_unprepare(priv->stmmac_clk);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 37ba2e0..2916089 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -100,9 +100,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
stmmac_default_data();
priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
- if (!priv) {
+ if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
- ret = -ENODEV;
+ ret = PTR_ERR(priv);
goto err_out;
}
priv->dev->irq = pdev->irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 6d0bf22..cc6b89a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -152,9 +152,9 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
}
priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
- if (!priv) {
+ if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
- return -ENODEV;
+ return PTR_ERR(priv);
}
/* Get MAC address if available (DT) */
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 1/8] net: stmmac: Enable stmmac main clock when probing hardware
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1389965087-21971-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
The stmmac driver does not enable the main clock during the probe phase.
If the clock was not enabled by the boot loader or was disabled by the
kernel, hardware features and the MDIO bus would not be probed properly.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 +++++++++++------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index cddcf76..0d2c4cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1680,8 +1680,6 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
- clk_prepare_enable(priv->stmmac_clk);
-
stmmac_check_ether_addr(priv);
if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
@@ -1819,7 +1817,6 @@ static int stmmac_release(struct net_device *dev)
#ifdef CONFIG_STMMAC_DEBUG_FS
stmmac_exit_fs();
#endif
- clk_disable_unprepare(priv->stmmac_clk);
stmmac_release_ptp(priv);
@@ -2727,10 +2724,18 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if ((phyaddr >= 0) && (phyaddr <= 31))
priv->plat->phy_addr = phyaddr;
+ priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
+ if (IS_ERR(priv->stmmac_clk)) {
+ dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
+ __func__);
+ goto error_clk_get;
+ }
+ clk_prepare_enable(priv->stmmac_clk);
+
/* Init MAC and get the capabilities */
ret = stmmac_hw_init(priv);
if (ret)
- goto error_free_netdev;
+ goto error_hw_init;
ndev->netdev_ops = &stmmac_netdev_ops;
@@ -2768,12 +2773,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
goto error_netdev_register;
}
- priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);
- if (IS_ERR(priv->stmmac_clk)) {
- pr_warn("%s: warning: cannot get CSR clock\n", __func__);
- goto error_clk_get;
- }
-
/* If a specific clk_csr value is passed from the platform
* this means that the CSR Clock Range selection cannot be
* changed at run-time and it is fixed. Viceversa the driver'll try to
@@ -2801,12 +2800,12 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
return priv;
error_mdio_register:
- clk_put(priv->stmmac_clk);
-error_clk_get:
unregister_netdev(ndev);
error_netdev_register:
netif_napi_del(&priv->napi);
-error_free_netdev:
+error_hw_init:
+ clk_disable_unprepare(priv->stmmac_clk);
+error_clk_get:
free_netdev(ndev);
return NULL;
@@ -2833,6 +2832,7 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
+ clk_disable_unprepare(priv->stmmac_clk);
free_netdev(ndev);
return 0;
--
1.8.5.2
^ permalink raw reply related
* [PATCH net-next v3 0/8] net: stmmac: Add Allwinner A20 GMAC ethernet
From: Chen-Yu Tsai @ 2014-01-17 13:24 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: Chen-Yu Tsai, Giuseppe Cavallaro, Srinivas Kandagatla,
Mike Frysinger,
uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Hi,
This is v3 of the Allwinner A20 GMAC glue layer for stmmac.
I have split the series into stmmac driver changes for net-next,
and clock and DT patches for their respective trees.
The Allwinner A20 SoC integrates an early version of dwmac
IP from Synopsys. On top of that is a hardware glue layer.
This layer needs to be configured before the dwmac can be
used.
Part of the glue layer is a clock mux, which controls the
source and direction of the TX clock used by GMAC.
The glue layer is implemented with existing feature flags
and callbacks found in stmmac driver core. A new stmmac_of_data
structure, which is a subset of the original platform data,
has been added to tie these values with compatible strings.
The purpose of this is to avoid future glue layers assuming
they can pass other data or directly modify values used by
the driver core. This is found in patch #7.
The callbacks have also been extended to pass board specific
data. This is found in patch #3.
This version of dwmac IP requires store and forward DMA mode.
The relevant device tree property was documented, but not
implemented. Patch #6 adds this to stmmac platform driver.
Changes since v2:
* Dropped non CONFIG_RESET_CONTROLLER routines, make stmmac
select CONFIG_RESET_CONTROLLER
* Split out "Deprecate snps,phy-addr and auto-detect PHY address"
from "Use driver data and callbacks tied with compatible strings"
* Added comments on how sunxi glue layer uses GMAC clock
* Rebased onto net-next
* Corrected typo in blackfin commit message
Changes since v1:
* Added optional reset control to stmmac driver core
* Added non CONFIG_RESET_CONROLLER routines for the above change
* Extended callback API, as discussed with Srinivas
* Used new stmmac_of_data to pass features and callbacks,
instead of platform data, as discussed
* Seperated clock module glue layer into clock driver
Cheers,
ChenYu
Chen-Yu Tsai (8):
net: stmmac: Enable stmmac main clock when probing hardware
net: stmmac: Add support for optional reset control
net: stmmac: Allocate and pass soc/board specific data to callbacks
blackfin: Update stmmac callback signatures
net: stmmac: Honor DT parameter to force DMA store and forward mode
net: stmmac: Deprecate snps,phy-addr and auto-detect PHY address
net: stmmac: Use driver data and callbacks tied with compatible
strings
net: stmmac: sunxi platform extensions for GMAC in Allwinner A20 SoC's
.../bindings/net/allwinner,sun7i-a20-gmac.txt | 27 ++++
Documentation/devicetree/bindings/net/stmmac.txt | 4 +-
Documentation/networking/stmmac.txt | 12 +-
arch/blackfin/mach-bf609/boards/ezkit.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 ++
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 141 +++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 5 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 45 +++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 4 +-
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 80 +++++++++---
include/linux/stmmac.h | 24 +++-
12 files changed, 316 insertions(+), 41 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
--
1.8.5.2
^ permalink raw reply
* [PATCH v3] sch_htb: let skb->priority refer to non-leaf class
From: Harry Mason @ 2014-01-17 13:22 UTC (permalink / raw)
To: Sergei Shtylyov, Jamal Hadi Salim, Eric Dumazet; +Cc: linux-netdev
In-Reply-To: <52D927CD.4080403@cogentembedded.com>
If the class in skb->priority is not a leaf, apply filters from the
selected class, not the qdisc. This lets netfilter or user space
partially classify the packet.
Signed-off-by: Harry Mason <harry.mason@smoothwall.net>
---
On Fri, 2014-01-17 at 16:53 +0400, Sergei Shtylyov wrote:
> On 17-01-2014 14:19, Harry Mason wrote:
> > + if (cl) {
> > + if (cl->level == 0)
> > + return cl;
> > + /* Start with inner filter chain if a non-leaf class is selected */
> > + tcf = cl->filter_list;
> > + } else
> > + tcf = q->filter_list;
>
> There should be {} in the *else* arm, since it's in another arm of *if*
> already -- see Documentation/CodingStyle.
Thanks, updated.
net/sched/sch_htb.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 717b210..e9c8c08 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -219,11 +219,16 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
if (skb->priority == sch->handle)
return HTB_DIRECT; /* X:0 (direct flow) selected */
cl = htb_find(skb->priority, sch);
- if (cl && cl->level == 0)
- return cl;
+ if (cl) {
+ if (cl->level == 0)
+ return cl;
+ /* Start with inner filter chain if a non-leaf class is selected */
+ tcf = cl->filter_list;
+ } else {
+ tcf = q->filter_list;
+ }
*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
- tcf = q->filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
#ifdef CONFIG_NET_CLS_ACT
switch (result) {
--
1.7.10.4
^ permalink raw reply related
* [PATCH net-next 4/4] benet: Support for configurable RSS hash key.
From: Venkata Duvvuru @ 2014-01-17 13:03 UTC (permalink / raw)
To: netdev@vger.kernel.org
This be2net patch implements the get/set_rsshkey() ethtool hooks.
RSS_CONFIG device command is invoked to set the hashkey.
It also uses an initial random value for RSS hash key instead of a hard-coded value as hard-coded values for a hash-key are usually considered a security risk.
Signed-off-by: Venkat Duvvuru <VenkatKumar.Duvvuru@Emulex.com>
---
drivers/net/ethernet/emulex/benet/be.h | 12 ++++-
drivers/net/ethernet/emulex/benet/be_cmds.c | 9 +---
drivers/net/ethernet/emulex/benet/be_cmds.h | 4 +-
drivers/net/ethernet/emulex/benet/be_ethtool.c | 58 ++++++++++++++++++-----
drivers/net/ethernet/emulex/benet/be_main.c | 24 ++++++----
5 files changed, 74 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 8d09615..544361c 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or @@ -121,6 +121,8 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MAX_VFS 30 /* Max VFs supported by BE3 FW */
#define FW_VER_LEN 32
+#define RSS_HASH_KEY_LEN 40
+
struct be_dma_mem {
void *va;
dma_addr_t dma;
@@ -403,6 +405,12 @@ struct be_resources {
u32 if_cap_flags;
};
+struct rss_info {
+ u64 rss_flags;
+ u8 rsstable[128];
+ u8 rss_hkey[RSS_HASH_KEY_LEN];
+};
+
struct be_adapter {
struct pci_dev *pdev;
struct net_device *netdev;
@@ -499,7 +507,7 @@ struct be_adapter {
u32 msg_enable;
int be_get_temp_freq;
u8 pf_number;
- u64 rss_flags;
+ struct rss_info rss_info;
};
#define be_physfn(adapter) (!adapter->virtfn)
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 48076a6..7984252 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or @@ -2013,13 +2013,10 @@ int be_cmd_reset_function(struct be_adapter *adapter) }
int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
- u32 rss_hash_opts, u16 table_size)
+ u32 rss_hash_opts, u16 table_size, u8 *rss_hkey)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_rss_config *req;
- u32 myhash[10] = {0x15d43fa5, 0x2534685a, 0x5f87693a, 0x5668494e,
- 0x33cf6a53, 0x383334c6, 0x76ac4257, 0x59b242b2,
- 0x3ea83c02, 0x4a110304};
int status;
if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) @@ -2042,7 +2039,7 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
req->hdr.version = 1;
memcpy(req->cpu_table, rsstable, table_size);
- memcpy(req->hash, myhash, sizeof(myhash));
+ memcpy(req->hash, rss_hkey, RSS_HASH_KEY_LEN);
be_dws_cpu_to_le(req->hash, sizeof(req->hash));
status = be_mbox_notify_wait(adapter); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index fc4e076..630406d 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or @@ -2012,7 +2012,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
u32 *function_mode, u32 *function_caps, u16 *asic_rev); int be_cmd_reset_function(struct be_adapter *adapter); int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
- u32 rss_hash_opts, u16 table_size);
+ u32 rss_hash_opts, u16 table_size, u8 *rss_hkey);
int be_process_mcc(struct be_adapter *adapter); int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
u8 status, u8 state);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 05be007..7357a69 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or @@ -931,27 +931,27 @@ static u64 be_get_rss_hash_opts(struct be_adapter *adapter, u64 flow_type)
switch (flow_type) {
case TCP_V4_FLOW:
- if (adapter->rss_flags & RSS_ENABLE_IPV4)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV4)
data |= RXH_IP_DST | RXH_IP_SRC;
- if (adapter->rss_flags & RSS_ENABLE_TCP_IPV4)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_TCP_IPV4)
data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
case UDP_V4_FLOW:
- if (adapter->rss_flags & RSS_ENABLE_IPV4)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV4)
data |= RXH_IP_DST | RXH_IP_SRC;
- if (adapter->rss_flags & RSS_ENABLE_UDP_IPV4)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_UDP_IPV4)
data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
case TCP_V6_FLOW:
- if (adapter->rss_flags & RSS_ENABLE_IPV6)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV6)
data |= RXH_IP_DST | RXH_IP_SRC;
- if (adapter->rss_flags & RSS_ENABLE_TCP_IPV6)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_TCP_IPV6)
data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
case UDP_V6_FLOW:
- if (adapter->rss_flags & RSS_ENABLE_IPV6)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_IPV6)
data |= RXH_IP_DST | RXH_IP_SRC;
- if (adapter->rss_flags & RSS_ENABLE_UDP_IPV6)
+ if (adapter->rss_info.rss_flags & RSS_ENABLE_UDP_IPV6)
data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
}
@@ -990,7 +990,7 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter,
struct be_rx_obj *rxo;
int status = 0, i, j;
u8 rsstable[128];
- u32 rss_flags = adapter->rss_flags;
+ u32 rss_flags = adapter->rss_info.rss_flags;
if (cmd->data != L3_RSS_FLAGS &&
cmd->data != (L3_RSS_FLAGS | L4_RSS_FLAGS)) @@ -1037,7 +1037,7 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter,
return -EINVAL;
}
- if (rss_flags == adapter->rss_flags)
+ if (rss_flags == adapter->rss_info.rss_flags)
return status;
if (be_multi_rxq(adapter)) {
@@ -1049,9 +1049,11 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter,
}
}
}
- status = be_cmd_rss_config(adapter, rsstable, rss_flags, 128);
+
+ status = be_cmd_rss_config(adapter, adapter->rss_info.rsstable,
+ rss_flags, 128, adapter->rss_info.rss_hkey);
if (!status)
- adapter->rss_flags = rss_flags;
+ adapter->rss_info.rss_flags = rss_flags;
return status;
}
@@ -1101,6 +1103,34 @@ static int be_set_channels(struct net_device *netdev,
return be_update_queues(adapter);
}
+static int be_get_rss_hkey(struct net_device *netdev,
+ struct ethtool_rss_hkey *cmd)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ memcpy(cmd->data, adapter->rss_info.rss_hkey, RSS_HASH_KEY_LEN);
+ cmd->data_len = RSS_HASH_KEY_LEN;
+
+ return 0;
+}
+
+static int be_set_rss_hkey(struct net_device *netdev,
+ struct ethtool_rss_hkey *cmd)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+ int rc = 0;
+
+ rc = be_cmd_rss_config(adapter, adapter->rss_info.rsstable,
+ adapter->rss_info.rss_flags,
+ 128, cmd->data);
+ if (rc) {
+ adapter->rss_info.rss_flags = RSS_ENABLE_NONE;
+ return -EIO;
+ }
+ memcpy(adapter->rss_info.rss_hkey, cmd->data, RSS_HASH_KEY_LEN);
+ return rc;
+}
+
const struct ethtool_ops be_ethtool_ops = {
.get_settings = be_get_settings,
.get_drvinfo = be_get_drvinfo,
@@ -1127,6 +1157,8 @@ const struct ethtool_ops be_ethtool_ops = {
.self_test = be_self_test,
.get_rxnfc = be_get_rxnfc,
.set_rxnfc = be_set_rxnfc,
+ .get_rsshkey = be_get_rss_hkey,
+ .set_rsshkey = be_set_rss_hkey,
.get_channels = be_get_channels,
.set_channels = be_set_channels
};
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 6d22d6f..04f8a66 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or @@ -2695,7 +2695,7 @@ static int be_rx_qs_create(struct be_adapter *adapter) {
struct be_rx_obj *rxo;
int rc, i, j;
- u8 rsstable[128];
+ u8 rss_hkey[RSS_HASH_KEY_LEN];
for_all_rx_queues(adapter, rxo, i) {
rc = be_queue_alloc(adapter, &rxo->q, RX_Q_LEN, @@ -2724,27 +2724,31 @@ static int be_rx_qs_create(struct be_adapter *adapter)
for_all_rss_queues(adapter, rxo, i) {
if ((j + i) >= 128)
break;
- rsstable[j + i] = rxo->rss_id;
+ adapter->rss_info.rsstable[j + i] = rxo->rss_id;
}
}
- adapter->rss_flags = RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 |
- RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6;
+ adapter->rss_info.rss_flags = RSS_ENABLE_TCP_IPV4 |
+ RSS_ENABLE_IPV4 | RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6;
if (!BEx_chip(adapter))
- adapter->rss_flags |= RSS_ENABLE_UDP_IPV4 |
+ adapter->rss_info.rss_flags |= RSS_ENABLE_UDP_IPV4 |
RSS_ENABLE_UDP_IPV6;
} else {
/* Disable RSS, if only default RX Q is created */
- adapter->rss_flags = RSS_ENABLE_NONE;
+ adapter->rss_info.rss_flags = RSS_ENABLE_NONE;
}
- rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
- 128);
+ get_random_bytes(rss_hkey, RSS_HASH_KEY_LEN);
+ rc = be_cmd_rss_config(adapter, adapter->rss_info.rsstable,
+ adapter->rss_info.rss_flags,
+ 128, rss_hkey);
if (rc) {
- adapter->rss_flags = RSS_ENABLE_NONE;
+ adapter->rss_info.rss_flags = RSS_ENABLE_NONE;
return rc;
}
+ memcpy(adapter->rss_info.rss_hkey, rss_hkey, RSS_HASH_KEY_LEN);
+
/* First time posting */
for_all_rx_queues(adapter, rxo, i)
be_post_rx_frags(rxo, GFP_KERNEL);
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 3/4] ethtool: Support for configurable RSS hash key.
From: Venkata Duvvuru @ 2014-01-17 13:02 UTC (permalink / raw)
To: netdev@vger.kernel.org
This ethtool patch primarily copies the ioctl command data structures from/to the User space and invokes the driver hook.
Signed-off-by: Venkat Duvvuru <VenkatKumar.Duvvuru@Emulex.com>
---
include/linux/ethtool.h | 2 ++
include/uapi/linux/ethtool.h | 19 +++++++++++++++++++
net/core/ethtool.c | 40 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c8e3e7e..2c30fd1 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -227,6 +227,8 @@ struct ethtool_ops {
int (*get_rxnfc)(struct net_device *,
struct ethtool_rxnfc *, u32 *rule_locs);
int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
+ int (*set_rsshkey) (struct net_device *, struct ethtool_rss_hkey *);
+ int (*get_rsshkey) (struct net_device *, struct ethtool_rss_hkey *);
int (*flash_device)(struct net_device *, struct ethtool_flash *);
int (*reset)(struct net_device *, u32 *);
u32 (*get_rxfh_indir_size)(struct net_device *);
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 38dbafa..f39d82f 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -678,6 +678,22 @@ struct ethtool_rx_ntuple {
struct ethtool_rx_ntuple_flow_spec fs;
};
+
+/**
+ * struct ethtool_rss_hkey - command to set/get RSS hash key of the device.
+ * @cmd: Command number - %ETHTOOL_SET_RSS_HKEY/ETHTOOL_GET_RSS_HKEY
+ * @data: 40 or 16 byte rss hash key
+ * @data_len: rss hash key length
+ */
+
+#define RSS_HASH_KEY_LEN 40
+/* RSS Hash key */
+struct ethtool_rss_hkey {
+ __u32 cmd; /* ETHTOOL_SET/GET_RSS_HKEY */
+ __u8 data[RSS_HASH_KEY_LEN];
+ __u32 data_len;
+};
+
#define ETHTOOL_FLASH_MAX_FILENAME 128
enum ethtool_flash_op_type {
ETHTOOL_FLASH_ALL_REGIONS = 0,
@@ -901,6 +917,9 @@ enum ethtool_sfeatures_retval_bits {
#define ETHTOOL_GEEE 0x00000044 /* Get EEE settings */
#define ETHTOOL_SEEE 0x00000045 /* Set EEE settings */
+#define ETHTOOL_SET_RSS_HKEY 0x00000046 /* Set RSS hash key */
+#define ETHTOOL_GET_RSS_HKEY 0x00000047 /* Get RSS hash key */
+
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
#define SPARC_ETH_SSET ETHTOOL_SSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 30071de..70f68ff 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -501,6 +501,40 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
return 0;
}
+static noinline_for_stack int ethtool_get_rsshkey(struct net_device *dev,
+ void __user *useraddr)
+{
+ struct ethtool_rss_hkey info;
+ int rc;
+
+ if (!dev->ethtool_ops->get_rsshkey)
+ return -EOPNOTSUPP;
+
+ rc = dev->ethtool_ops->get_rsshkey(dev, &info);
+
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ rc = -EFAULT;
+
+ return rc;
+}
+
+static noinline_for_stack int ethtool_set_rsshkey(struct net_device *dev,
+ void __user *useraddr)
+{
+ struct ethtool_rss_hkey info;
+ int rc;
+
+ if (!dev->ethtool_ops->set_rsshkey)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&info, useraddr, sizeof(info)))
+ return -EFAULT;
+
+ rc = dev->ethtool_ops->set_rsshkey(dev, &info);
+
+ return rc;
+}
+
static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
u32 cmd, void __user *useraddr)
{
@@ -1612,6 +1646,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_SRXCLSRLINS:
rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);
break;
+ case ETHTOOL_GET_RSS_HKEY:
+ rc = ethtool_get_rsshkey(dev, useraddr);
+ break;
+ case ETHTOOL_SET_RSS_HKEY:
+ rc = ethtool_set_rsshkey(dev, useraddr);
+ break;
case ETHTOOL_FLASHDEV:
rc = ethtool_flash_device(dev, useraddr);
break;
--
1.7.1
^ permalink raw reply
* [PATCH 2/4 ethtool] ethtool: Support for configurable RSS hash key.
From: Venkata Duvvuru @ 2014-01-17 13:02 UTC (permalink / raw)
To: netdev@vger.kernel.org
This ethtool patch will primarily implement the parser for the options provided by the user for set and get hashkey before invoking the ioctl.
This patch also has Ethtool man page changes which describes the Usage of set and get hashkey options.
Signed-off-by: Venkat Duvvuru <VenkatKumar.Duvvuru@Emulex.com>
---
ethtool.8.in | 17 ++++++++
ethtool.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/ethtool.8.in b/ethtool.8.in index f587ec8..a228bf7 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -275,6 +275,13 @@ ethtool \- query or control network driver and hardware settings .br .BI delete \ N .HP
+.B ethtool \-\-show\-hashkey
+.I devname
+.HP
+.B ethtool \-\-hashkey
+.I devname
+.RB [ hkey \ \*(MA:\...]
+.HP
.B ethtool \-w|\-\-get\-dump
.I devname
.RB [ data
@@ -762,6 +769,16 @@ of the rule ordering process.
.BI delete \ N
Deletes the RX classification rule with the given ID.
.TP
+.B \-\-show\-hashkey
+Gets the configured rss hashkey of the specified network device.
+.TP
+.B \-\-hashkey hkey
+Changes rss hash key of the specified network device. RSS hash key should be of device supported length.
+40 bytes for IPv6.
+16 bytes for IPv4.
+Hash key format must be in xx:yy:zz:aa:bb:cc format meaning both the
+nibbles of a byte should be mentioned even if a nibble is zero.
+.TP
.B \-w \-\-get\-dump
Retrieves and prints firmware dump for the specified network device.
By default, it prints out the dump flag, version and length of the dump data.
diff --git a/ethtool.c b/ethtool.c
index b06dfa3..4b05b0c 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -471,6 +471,59 @@ static int rxflow_str_to_type(const char *str)
return flow_type;
}
+static inline int is_hkey_char_valid(const char rss_hkey_string) {
+ /* Are there any invalid characters in the string */
+ return ((rss_hkey_string >= '0' && rss_hkey_string <= '9') ||
+ (rss_hkey_string >= 'a' && rss_hkey_string <= 'f') ||
+ (rss_hkey_string >= 'A' && rss_hkey_string <= 'F')); }
+
+static int convert_string_to_hashkey(struct ethtool_rss_hkey *rss_hkey,
+ const char *rss_hkey_string)
+{
+ int i = 0;
+ int hex_byte;
+
+ do {
+ if (i > (RSS_HASH_KEY_LEN - 1)) {
+ fprintf(stderr,
+ "Invalid key: Device supports %d bytes key\n",
+ rss_hkey->data_len);
+ goto err;
+ }
+
+ if (!(is_hkey_char_valid(*rss_hkey_string) &&
+ is_hkey_char_valid(*(rss_hkey_string + 1)))) {
+ fprintf(stderr, "Invalid RSS Hash Key Format\n");
+ goto err;
+ }
+
+ sscanf(rss_hkey_string, "%2x", &hex_byte);
+ rss_hkey->data[i++] = hex_byte;
+
+ rss_hkey_string += 2;
+
+ if (*rss_hkey_string == ':') {
+ rss_hkey_string++;
+ } else if (*rss_hkey_string != '\0') {
+ fprintf(stderr, "Invalid RSS Hash Key Format\n");
+ goto err;
+ }
+
+ } while (*rss_hkey_string);
+
+ if (i != rss_hkey->data_len) {
+ fprintf(stderr, "Invalid key: Device supports %d bytes key\n",
+ rss_hkey->data_len);
+ goto err;
+ }
+
+ return 0;
+err:
+ exit_bad_args();
+}
+
static int do_version(struct cmd_context *ctx) {
fprintf(stdout,
@@ -2863,6 +2916,80 @@ static int do_phys_id(struct cmd_context *ctx)
return err;
}
+static int get_hashkey(struct cmd_context *ctx) {
+ struct ethtool_rss_hkey *rss_hkey;
+ int rc;
+ int i;
+
+ if (ctx->argc != 0)
+ exit_bad_args();
+
+ rss_hkey = calloc(1, sizeof(struct ethtool_rss_hkey));
+ if (!rss_hkey) {
+ perror("Cannot allocate enough memory for get hashkey data");
+ return -ENOMEM;
+ }
+
+ rss_hkey->cmd = ETHTOOL_GET_RSS_HKEY;
+
+ rc = send_ioctl(ctx, rss_hkey);
+ if (rc < 0) {
+ perror("Cannot get hash key");
+ goto done;
+ }
+
+ for (i = 0; i < RSS_HASH_KEY_LEN; i++) {
+ if (i == (RSS_HASH_KEY_LEN - 1))
+ printf("%02x\n", rss_hkey->data[i]);
+ else
+ printf("%02x:", rss_hkey->data[i]);
+ }
+
+done:
+ free(rss_hkey);
+ return rc;
+}
+
+static int set_hashkey(struct cmd_context *ctx) {
+ struct ethtool_rss_hkey *rss_hkey;
+ int err;
+
+ if (ctx->argc != 2)
+ exit_bad_args();
+
+ if (strcmp(ctx->argp[0], "hkey"))
+ exit_bad_args();
+
+ rss_hkey = calloc(1, sizeof(struct ethtool_rss_hkey));
+ if (!rss_hkey) {
+ perror("Cannot allocate enough memory for rss hkey data");
+ return -ENOMEM;
+ }
+ rss_hkey->cmd = ETHTOOL_GET_RSS_HKEY;
+
+ err = send_ioctl(ctx, rss_hkey);
+ if (err < 0) {
+ perror("Cannot get rss hash key");
+ goto done;
+ }
+
+ if (convert_string_to_hashkey(rss_hkey, ctx->argp[1]) < 0) {
+ err = -EINVAL;
+ goto done;
+ }
+
+ rss_hkey->cmd = ETHTOOL_SET_RSS_HKEY;
+
+ err = send_ioctl(ctx, rss_hkey);
+ if (err < 0)
+ perror("Cannot set rss hash key");
+done:
+ free(rss_hkey);
+ return err;
+}
+
static int do_gstats(struct cmd_context *ctx) {
struct ethtool_gstrings *strings;
@@ -3829,6 +3956,9 @@ static const struct option {
" [ action %d ]\n"
" [ loc %d]] |\n"
" delete %d\n" },
+ { "--show-hashkey", 1, get_hashkey, "Show RSS hash key " },
+ { "--hashkey", 1, set_hashkey, "Set RSS hash key",
+ " [ hkey %x:%x:%x:%x:%x:....:%x]\n" },
{ "-T|--show-time-stamping", 1, do_tsinfo,
"Show time stamping capabilities" },
{ "-x|--show-rxfh-indir", 1, do_grxfhindir,
--
1.7.1
^ permalink raw reply related
* [PATCH 1/4 ethtool] ethtool: Support for configurable RSS hash key.
From: Venkata Duvvuru @ 2014-01-17 13:02 UTC (permalink / raw)
To: netdev@vger.kernel.org
This patch adds new definitions related to set/get hashkey feature.
Kernel tree head was at commit abfce3ef58b6a6c95de389f9d20047a05b10e484
Date: Thu Jan 16 16:25:19 2014 +0800
Signed-off-by: Venkat Duvvuru <VenkatKumar.Duvvuru@Emulex.com>
---
ethtool-copy.h | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/ethtool-copy.h b/ethtool-copy.h index b5515c2..d8454e8 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -678,6 +678,22 @@ struct ethtool_rx_ntuple {
struct ethtool_rx_ntuple_flow_spec fs;
};
+
+/**
+ * struct ethtool_rss_hkey - command to set/get RSS hash key of the device.
+ * @cmd: Command number - %ETHTOOL_SET_RSS_HKEY/ETHTOOL_GET_RSS_HKEY
+ * @data: 40 or 16 byte rss hash key
+ * @data_len: rss hash key length
+ */
+
+#define RSS_HASH_KEY_LEN 40
+/* RSS Hash key */
+struct ethtool_rss_hkey {
+ __u32 cmd; /* ETHTOOL_SET/GET_RSS_HKEY */
+ __u8 data[RSS_HASH_KEY_LEN];
+ __u32 data_len;
+};
+
#define ETHTOOL_FLASH_MAX_FILENAME 128
enum ethtool_flash_op_type {
ETHTOOL_FLASH_ALL_REGIONS = 0,
@@ -901,6 +917,9 @@ enum ethtool_sfeatures_retval_bits {
#define ETHTOOL_GEEE 0x00000044 /* Get EEE settings */
#define ETHTOOL_SEEE 0x00000045 /* Set EEE settings */
+#define ETHTOOL_SET_RSS_HKEY 0x00000046 /* Set RSS hash key */
+#define ETHTOOL_GET_RSS_HKEY 0x00000047 /* Get RSS hash key */
+
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
#define SPARC_ETH_SSET ETHTOOL_SSET
@@ -993,8 +1012,8 @@ enum ethtool_sfeatures_retval_bits {
#define PORT_OTHER 0xff
/* Which transceiver to use. */
-#define XCVR_INTERNAL 0x00
-#define XCVR_EXTERNAL 0x01
+#define XCVR_INTERNAL 0x00 /* PHY and MAC are in the same package */
+#define XCVR_EXTERNAL 0x01 /* PHY and MAC are in different packages */
#define XCVR_DUMMY1 0x02
#define XCVR_DUMMY2 0x03
#define XCVR_DUMMY3 0x04
--
1.7.1
^ permalink raw reply
* [PATCH 0/4] Patchset - Support for configurable RSS hash key
From: Venkata Duvvuru @ 2014-01-17 13:02 UTC (permalink / raw)
To: netdev@vger.kernel.org
NIC drivers that support RSS use either a hard-coded value or a random value for the RSS hash key. Irrespective of the type of the key used, the user would want to change the hash key if he/she is not satisfied with the effectiveness of the default hash-key in spreading the incoming flows evenly across the RSS queues.
This patch set provides support for configuring the RSS hash-key via the ethtool interface.
The patch set consists of:
a) ethtool user-land patches
b) ethtool kernel patch
c) be2net patch that implements the ethtool hooks
^ permalink raw reply
* Re: [PATCH v2] sch_htb: let skb->priority refer to non-leaf class
From: Sergei Shtylyov @ 2014-01-17 12:53 UTC (permalink / raw)
To: Harry Mason, Eric Dumazet, Jamal Hadi Salim; +Cc: linux-netdev
In-Reply-To: <1389953999.4698.18.camel@azathoth.dev.smoothwall.net>
Hello.
On 17-01-2014 14:19, Harry Mason wrote:
> If the class in skb->priority is not a leaf, apply filters from the
> selected class, not the qdisc. This lets netfilter or user space
> partially classify the packet.
> Signed-off-by: Harry Mason <harry.mason@smoothwall.net>
> ---
> On Thu, 2014-01-16 at 08:25 -0800, Eric Dumazet wrote:
>> On Thu, 2014-01-16 at 14:45 +0000, Harry Mason wrote:
>>> + /* Start with inner filter chain if a non-leaf class is selected */
>>> + if (cl)
>>> + tcf = cl->filter_list;
>>> + else
>>> + tcf = q->filter_list;
>> Could this break some existing htb setups ?
> I think it is unlikely. Setting skb->priority to a non-leaf class would
> be equivalent to setting it to the base qdisc. In theory an application
> might rely on this if it expects the classes to be dynamic, but adding
> a filter could restore the old behaviour.
> To me this is intuitively how it should behave, and reproduces what would
> happen if a tc filter instead of netfilter had first assigned the
> non-leaf class.
>> Also we test cl being NULL at line 222, it would be nice to not
>> test it again...
> Updated below.
> net/sched/sch_htb.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
> diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
> index 717b210..8073d92 100644
> --- a/net/sched/sch_htb.c
> +++ b/net/sched/sch_htb.c
> @@ -219,11 +219,15 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
> if (skb->priority == sch->handle)
> return HTB_DIRECT; /* X:0 (direct flow) selected */
> cl = htb_find(skb->priority, sch);
> - if (cl && cl->level == 0)
> - return cl;
> + if (cl) {
> + if (cl->level == 0)
> + return cl;
> + /* Start with inner filter chain if a non-leaf class is selected */
> + tcf = cl->filter_list;
> + } else
> + tcf = q->filter_list;
There should be {} in the *else* arm, since it's in another arm of *if*
already -- see Documentation/CodingStyle.
WBR, Sergei
^ permalink raw reply
* Re: [PATCH] net: sk == 0xffffffff fix - not for commit
From: Andrzej Pietrasiewicz @ 2014-01-17 12:47 UTC (permalink / raw)
To: Eric Dumazet
Cc: linux-kernel, linux-usb, Kyungmin Park, Felipe Balbi,
Greg Kroah-Hartman, Marek Szyprowski, Michal Nazarewicz,
David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
In-Reply-To: <52D91FAF.8090109@samsung.com>
W dniu 17.01.2014 13:18, Andrzej Pietrasiewicz pisze:
> W dniu 16.01.2014 17:29, Eric Dumazet pisze:
>> On Thu, 2014-01-16 at 16:21 +0100, Andrzej Pietrasiewicz wrote:
>>> W dniu 10.12.2013 15:25, Eric Dumazet pisze:
>>>> On Tue, 2013-12-10 at 07:55 +0100, Andrzej Pietrasiewicz wrote:
>>>>> W dniu 09.12.2013 16:31, Eric Dumazet pisze:
>>>>>> On Mon, 2013-12-09 at 12:47 +0100, Andrzej Pietrasiewicz wrote:
>>>>>>> NOT FOR COMMITTING TO MAINLINE.
>>>>>>>
>>>>>>> With g_ether loaded the sk occasionally becomes 0xffffffff.
>>>>>>> It happens usually after transferring few hundreds of kilobytes to few
>>>>>>> tens of megabytes. If sk is 0xffffffff then dereferencing it causes
>>>>>>> kernel panic.
>>>>>>>
>>>>>>> This is a *workaround*. I don't know enough net code to understand the core
>>>>>>> of the problem. However, with this patch applied the problems are gone,
>>>>>>> or at least pushed farther away.
>>>>>>
>>>>>> Is it happening on SMP or UP ?
>>>>>
>>>>> UP build, S5PC110
>>>>
>>>> OK
>>>>
>>>> I believe you need additional debugging to track the exact moment
>>>> 0xffffffff is fed to 'sk'
>>>>
>>>> It looks like a very strange bug, involving a problem in some assembly
>>>> helper, register save/restore, compiler bug or stack corruption or
>>>> something.
>>>>
>>>
>>> I started with adding WARN_ON(sk == 0xffffffff); just before return in
>>> __inet_lookup_established(), and the problem was gone. So this looks
>>> very strange, like a toolchain problem.
>>
>> Or a timing issue. Adding a WARN_ON() adds extra instructions and might
>> really change the assembly output.
>>
>>>
>>> I used gcc-linaro-arm-linux-gnueabihf-4.8-2013.05.
>>>
>>> If I change the toolchain to
>>>
>>> gcc-linaro-arm-linux-gnueabihf-4.7-2013.04-20130415
>>>
>>> the problem seems to have gone away.
>>
>> Its totally possible some barrier was not properly handled by the
>> compiler. You could disassemble the function on both toolchains and
>> try to spot the issue.
>>
>
> So I gave it a try.
>
> Below is a part of assembly code (ARM) which corresponds to the last
> lines of the __inet_lookup_established():
>
> C source:
> =========
> found:
> rcu_read_unlock();
> return sk;
> }
>
> assembly for toolchain 4.7:
> ===========================
> c0333bb8: ebf4bb6e bl c0062978 <__rcu_read_unlock>
> c0333bbc: e51b0030 ldr r0, [fp, #-48] ; 0x30
> c0333bc0: e24bd028 sub sp, fp, #40 ; 0x28
> c0333bc4: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
> c0333bc8: e5132018 ldr r2, [r3, #-24]
>
>
> assembly for toolchain 4.8:
> ===========================
> c033ff5c: ebf4927e bl c006495c <__rcu_read_unlock>
> c033ff60: e24bd028 sub sp, fp, #40 ; 0x28
> c033ff64: e51b0030 ldr r0, [fp, #-48] ; 0x30
> c033ff68: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
> c033ff6c: e5113018 ldr r3, [r1, #-24]
>
> What can be seen is that the usage of registers is slightly different,
> and, what is more important, the _order_ of ldr/sub is different.
> Now, if I swap the instructions at offsets c033ff60 and c033ff64
> in the 4.8-generated vmlinux, the problem seems gone! Well, at least
> the binary behaves the same way as the 4.7-generated one.
>
> Here is a _hypothesis_ of what _might_ be happening:
>
> The function in question puts its return value in the register r0.
> In both cases the return value is fetched from a memory location
> relative #-48 to what the frame pointer points to. However,
> in the 4.7-generated binary the ldr executes in the branch delay slot,
> whereas in the 4.8-generated binary it is the sub which executes
> in the branch delay slot. That way, in the 4.7-generated binary the return
> value is fetched before __rcu_read_unlock begins, but in the
> 4.8-generated binary it is fetched some time later. Which might be
> enough for someone else to schedule in and break the data to be
> copied to r0 and returned from the function.
>
> As I said, this is just a hypothesis.
>
Please disregard what I have written.
There is no delay slot on ARM :O
A nice hypothesis, though ;)
AP
^ permalink raw reply
* Re: [Xen-devel] [PATCH net-next v2] xen-netfront: clean up code in xennet_release_rx_bufs
From: annie li @ 2014-01-17 12:32 UTC (permalink / raw)
To: Wei Liu
Cc: David Vrabel, ian.campbell, netdev, xen-devel, andrew.bennieston,
davem
In-Reply-To: <20140117120810.GA11681@zion.uk.xensource.com>
On 2014-1-17 20:08, Wei Liu wrote:
> On Fri, Jan 17, 2014 at 02:25:40PM +0800, annie li wrote:
>> On 2014/1/16 19:10, David Vrabel wrote:
>>> On 15/01/14 23:57, Annie Li wrote:
>>>> This patch implements two things:
>>>>
>>>> * release grant reference and skb for rx path, this fixex resource leaking.
>>>> * clean up grant transfer code kept from old netfront(2.6.18) which grants
>>>> pages for access/map and transfer. But grant transfer is deprecated in current
>>>> netfront, so remove corresponding release code for transfer.
>>>>
>>>> gnttab_end_foreign_access_ref may fail when the grant entry is currently used
>>>> for reading or writing. But this patch does not cover this and improvement for
>>>> this failure may be implemented in a separate patch.
>>> I don't think replacing a resource leak with a security bug is a good idea.
>>>
>>> If you would prefer not to fix the gnttab_end_foreign_access() call, I
>>> think you can fix this in netfront by taking a reference to the page
>>> before calling gnttab_end_foreign_access(). This will ensure the page
>>> isn't freed until the subsequent kfree_skb(), or the gref is released by
>>> the foreign domain (whichever is later).
>> Taking a reference to the page before calling
>> gnttab_end_foreign_access() delays the free work until kfree_skb().
>> Simply adding put_page before kfree_skb() does not make things
>> different from gnttab_end_foreign_access_ref(), and the pages will
>> be freed by kfree_skb(), problem will be hit in
>> gnttab_handle_deferred() when freeing pages which already be freed.
>>
> I think David's idea is:
>
> get_page
> gnttab_end_foreign_access
> kfree_skb
>
> The get_page is to offset put_page in gnttab_end_foreign_access. You
> don't need to put page before kfree_skb.
Yes, this is what I described as following about David's patch.
>> So put_page is required in gnttab_end_foreign_access(), this will
>> ensure either free is taken by kfree_skb or gnttab_handle_deferred.
>> This involves changes in blkfront/pcifront/tpmfront(just like your
>> patch), this way ensure page is released when ref is end.
But this would has some issue in netfront tx path. Netfront ends all
grant reference of one skb first and then release this skb. If the
gnttab_end_foreign_access_ref fails in gnttab_end_foreign_access(), this
frag page and corresponding grant reference will be put in entry and
release work will be done in the timer routine. If some frag pages of
one skb is free in this timer routine, then dev_kfree_skb_irq will free
pages which have been freed.
So I prefer following way I mentioned, suggestions?
>> Another solution I am thinking is calling
>> gnttab_end_foreign_access() with page parameter as NULL, then
>> gnttab_end_foreign_access will only do ending grant reference work
>> and releasing page work is done by kfree_skb().
Thanks
Annie
^ permalink raw reply
* Re: [PATCH] net: sk == 0xffffffff fix - not for commit
From: Andrzej Pietrasiewicz @ 2014-01-17 12:18 UTC (permalink / raw)
To: Eric Dumazet
Cc: linux-kernel, linux-usb, Kyungmin Park, Felipe Balbi,
Greg Kroah-Hartman, Marek Szyprowski, Michal Nazarewicz,
David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev
In-Reply-To: <1389889754.31367.406.camel@edumazet-glaptop2.roam.corp.google.com>
W dniu 16.01.2014 17:29, Eric Dumazet pisze:
> On Thu, 2014-01-16 at 16:21 +0100, Andrzej Pietrasiewicz wrote:
>> W dniu 10.12.2013 15:25, Eric Dumazet pisze:
>>> On Tue, 2013-12-10 at 07:55 +0100, Andrzej Pietrasiewicz wrote:
>>>> W dniu 09.12.2013 16:31, Eric Dumazet pisze:
>>>>> On Mon, 2013-12-09 at 12:47 +0100, Andrzej Pietrasiewicz wrote:
>>>>>> NOT FOR COMMITTING TO MAINLINE.
>>>>>>
>>>>>> With g_ether loaded the sk occasionally becomes 0xffffffff.
>>>>>> It happens usually after transferring few hundreds of kilobytes to few
>>>>>> tens of megabytes. If sk is 0xffffffff then dereferencing it causes
>>>>>> kernel panic.
>>>>>>
>>>>>> This is a *workaround*. I don't know enough net code to understand the core
>>>>>> of the problem. However, with this patch applied the problems are gone,
>>>>>> or at least pushed farther away.
>>>>>
>>>>> Is it happening on SMP or UP ?
>>>>
>>>> UP build, S5PC110
>>>
>>> OK
>>>
>>> I believe you need additional debugging to track the exact moment
>>> 0xffffffff is fed to 'sk'
>>>
>>> It looks like a very strange bug, involving a problem in some assembly
>>> helper, register save/restore, compiler bug or stack corruption or
>>> something.
>>>
>>
>> I started with adding WARN_ON(sk == 0xffffffff); just before return in
>> __inet_lookup_established(), and the problem was gone. So this looks
>> very strange, like a toolchain problem.
>
> Or a timing issue. Adding a WARN_ON() adds extra instructions and might
> really change the assembly output.
>
>>
>> I used gcc-linaro-arm-linux-gnueabihf-4.8-2013.05.
>>
>> If I change the toolchain to
>>
>> gcc-linaro-arm-linux-gnueabihf-4.7-2013.04-20130415
>>
>> the problem seems to have gone away.
>
> Its totally possible some barrier was not properly handled by the
> compiler. You could disassemble the function on both toolchains and
> try to spot the issue.
>
So I gave it a try.
Below is a part of assembly code (ARM) which corresponds to the last
lines of the __inet_lookup_established():
C source:
=========
found:
rcu_read_unlock();
return sk;
}
assembly for toolchain 4.7:
===========================
c0333bb8: ebf4bb6e bl c0062978 <__rcu_read_unlock>
c0333bbc: e51b0030 ldr r0, [fp, #-48] ; 0x30
c0333bc0: e24bd028 sub sp, fp, #40 ; 0x28
c0333bc4: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
c0333bc8: e5132018 ldr r2, [r3, #-24]
assembly for toolchain 4.8:
===========================
c033ff5c: ebf4927e bl c006495c <__rcu_read_unlock>
c033ff60: e24bd028 sub sp, fp, #40 ; 0x28
c033ff64: e51b0030 ldr r0, [fp, #-48] ; 0x30
c033ff68: e89daff0 ldm sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
c033ff6c: e5113018 ldr r3, [r1, #-24]
What can be seen is that the usage of registers is slightly different,
and, what is more important, the _order_ of ldr/sub is different.
Now, if I swap the instructions at offsets c033ff60 and c033ff64
in the 4.8-generated vmlinux, the problem seems gone! Well, at least
the binary behaves the same way as the 4.7-generated one.
Here is a _hypothesis_ of what _might_ be happening:
The function in question puts its return value in the register r0.
In both cases the return value is fetched from a memory location
relative #-48 to what the frame pointer points to. However,
in the 4.7-generated binary the ldr executes in the branch delay slot,
whereas in the 4.8-generated binary it is the sub which executes
in the branch delay slot. That way, in the 4.7-generated binary the return
value is fetched before __rcu_read_unlock begins, but in the
4.8-generated binary it is fetched some time later. Which might be
enough for someone else to schedule in and break the data to be
copied to r0 and returned from the function.
As I said, this is just a hypothesis.
AP
^ 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