Netdev List
 help / color / mirror / Atom feed
* Re: ipv6: oops in datagram.c line 260
From: Chris Ruehl @ 2015-02-06  7:37 UTC (permalink / raw)
  To: Steffen Klassert; +Cc: Hannes Frederic Sowa, netdev, davem
In-Reply-To: <20150127115814.GL13046@secunet.com>

On Tuesday, January 27, 2015 07:58 PM, Steffen Klassert wrote:
> On Tue, Jan 27, 2015 at 12:58:35PM +0800, Chris Ruehl wrote:
>>     Steffen,
>>
>>     your patch can't apply to the vanilla v3.14.29 can you cross check please.
> Sorry, this patch was based on the net tree.
>
>>     I'm sorry but we running a productive system and I can't make to much
>>     noise here!
>>     Your patch is partly in the 3.14.29 and
>>     skb->protocol = htons(ETH_P_IP)
>>     from the xfrm4/6_output_finish() no removed. I do then
>>
>>     --- linux-3.14.x/net/ipv4/xfrm4_output.c.orig    2015-01-27
>>     12:50:01.830651344 +0800
>>     +++ linux-3.14.x/net/ipv4/xfrm4_output.c    2015-01-27 12:51:13.280386355
>>     +0800
>>     @@ -82,7 +82,6 @@
>>          IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
>>      #endif
>>      
>>     -    skb->protocol = htons(ETH_P_IP);
>>          return xfrm_output(skb);
>>      }
>>      
>>     --- linux-3.14.x/net/ipv6/xfrm6_output.c.orig    2015-01-27
>>     12:49:39.260735321 +0800
>>     +++ linux-3.14.x/net/ipv6/xfrm6_output.c    2015-01-27 12:50:47.280482636
>>     +0800
>>     @@ -132,7 +132,6 @@
>>          IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
>>      #endif
>>      
>>     -    skb->protocol = htons(ETH_P_IPV6);
>>          return xfrm_output(skb);
>>      }
> Yes, that should be ok. Here is the complete patch for v3.14.29:
>
> Subject: [PATCH RFC v3.14.29] xfrm: Fix local error reporting crash with interfamily tunnels
>
> We set the outer mode protocol too early. As a result, the
> local error handler might dispatch to the wrong address family
> and report the error to a wrong socket type. We fix this by
> seting the outer protocol to the skb only after we accessed the
> inner mode for the last time, right before we do the atcual
> encapsulation where we switch finally to the outer mode.
> The settings in xfrm{4,6}_output_finish() are removed.
>
> Reported-by: Chris Ruehl <chris.ruehl@gtsys.com.hk>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
> ---
>   net/ipv4/xfrm4_output.c |    1 -
>   net/ipv6/xfrm6_output.c |    1 -
>   2 files changed, 0 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
> index baa0f63..0cb9606 100644
> --- a/net/ipv4/xfrm4_output.c
> +++ b/net/ipv4/xfrm4_output.c
> @@ -82,7 +82,6 @@ int xfrm4_output_finish(struct sk_buff *skb)
>   	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
>   #endif
>   
> -	skb->protocol = htons(ETH_P_IP);
>   	return xfrm_output(skb);
>   }
>   
> diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
> index 6cd625e..98396cf 100644
> --- a/net/ipv6/xfrm6_output.c
> +++ b/net/ipv6/xfrm6_output.c
> @@ -132,7 +132,6 @@ int xfrm6_output_finish(struct sk_buff *skb)
>   	IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
>   #endif
>   
> -	skb->protocol = htons(ETH_P_IPV6);
>   	return xfrm_output(skb);
>   }
>   
Hi Steffen,

server is up for 6 days no problems any more.
Please apply the patch!

Thank you very much
Chris

Tested-by: Chris Ruehl <chris.ruehl@gtsys.com.hk>

^ permalink raw reply

* Re: PROBLEM: Bnx2x Checksum/Length Error Over GRE Tunnel
From: Eren Türkay @ 2015-02-06  7:51 UTC (permalink / raw)
  To: Yuval Mintz; +Cc: netdev, Eric Dumazet
In-Reply-To: <B5657A6538887040AD3A81F1008BEC63BE78AC@avmb3.qlogic.org>

On 05-02-2015 18:13, Yuval Mintz wrote:
> Tried this on latest net-next [using iproute2] and I didn't manage to hit the
> issue you've indicated.
> I.e., traffic seemed to work fine on gre tunnels using both mtu sizes and
> regardless of whether Tx-checksum-offload was enabled or disabled.

Interesting. Could it be a firmware issue?

To summarize my current situation, I cannot get the network work with tx on so I
need to disable tx. Using iproute2, tunnels with MTU 8976 works OK (getting
9.7Gbit/s in a single flow). When MTU is decreased to 1500, I can only get
3-4Gbit/s.

Being unable to use tx offloading is strange.

> Is there anything else which is worth mentioning in your setup?

For iproute2, I don't have anything special. I just create a tunnel bridge and
test it. For OVS part, I have openstack installation using neutron openvswitch
plugin, which is irrelevant for now. Openvswitch kernel module is loaded but
does it have an effect on iproute2? Please inform me if you need anything else.

Just to inform other people having the same issue, by increasing the MTU of OVS
bridges (br-int, tap, qvo, qbr, etc.) to 8950, setting br-tun ovs bridge to
8976, and instructing VMs to use 8950 MTU, I can now get 7.5Gbit from
VM-to-network node using GRE tunnel in a single flow, and 9.5Gbit using 2 flows.
I should add that I needed to enable MQ in libvirt.xml (using 4 queues).

> Thanks,
> Yuval

Regards,
Eren

-- 
System Administrator
https://skyatlas.com/

^ permalink raw reply

* Re: [PATCH V6 3/3] bfin_can: move and merge the content of header file into driver body
From: Marc Kleine-Budde @ 2015-02-06  7:51 UTC (permalink / raw)
  To: Aaron Wu, wg, linux-can, netdev, linux-kernel, linux-devel
In-Reply-To: <1423203952-23004-3-git-send-email-Aaron.wu@analog.com>

[-- Attachment #1: Type: text/plain, Size: 6345 bytes --]

On 02/06/2015 07:25 AM, Aaron Wu wrote:
> Header file was in arch dependent location arch/blackfin/include/asm/bfin_can.h,
> Now move and merge the useful contents of header file into driver code, note
> the original header file is reserved for full register sets access test by other
> code so it survives.   
                      ^^^

Trailing whitespace :)

> 
> Signed-off-by: Aaron Wu <Aaron.wu@analog.com>
> ---
>  drivers/net/can/bfin_can.c |  114 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 113 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
> index 259d09a..63fab5c 100644
> --- a/drivers/net/can/bfin_can.c
> +++ b/drivers/net/can/bfin_can.c
> @@ -20,13 +20,125 @@
>  #include <linux/can/dev.h>
>  #include <linux/can/error.h>
>  
> -#include <asm/bfin_can.h>
>  #include <asm/portmux.h>
>  
>  #define DRV_NAME "bfin_can"
>  #define BFIN_CAN_TIMEOUT 100
>  #define TX_ECHO_SKB_MAX  1
>  
> +/* transmit and receive channels */
> +
> +#define TRANSMIT_CHL    24
> +#define RECEIVE_STD_CHL    0
> +#define RECEIVE_EXT_CHL    4
> +#define RECEIVE_RTR_CHL    8
> +#define RECEIVE_EXT_RTR_CHL    12
> +#define MAX_CHL_NUMBER    32
                         ^^^^
Please fix the indention, use one space only.

> +
> +/* All Blackfin system MMRs are padded to 32bits even if the register
> + * itself is only 16bits.  So use a helper macro to streamline this
> +*/
> +#define __BFP(m) u16 m; u16 __pad_##m
> +
> + /* bfin can registers layout
> + */
> +struct bfin_can_mask_regs {
> +	__BFP(aml);
> +	__BFP(amh);
> +};
> +
> +struct bfin_can_channel_regs {
> +	/* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */
> +	u16 data[8];
> +	 __BFP(dlc);
        ^ please remove that space
> +	__BFP(tsv);
> +	__BFP(id0);
> +	__BFP(id1);
> +};
> +
> +struct bfin_can_regs {
> +	/* global control and status registers
> +	 */
> +	__BFP(mc1);           /* offset 0x00 */
                   ^^^^^^^^^^^
please use tab(s) instead of spaces here.

> +	__BFP(md1);           /* offset 0x04 */
> +	__BFP(trs1);          /* offset 0x08 */
> +	__BFP(trr1);          /* offset 0x0c */
> +	__BFP(ta1);           /* offset 0x10 */
> +	__BFP(aa1);           /* offset 0x14 */
> +	__BFP(rmp1);          /* offset 0x18 */
> +	__BFP(rml1);          /* offset 0x1c */
> +	__BFP(mbtif1);        /* offset 0x20 */
> +	__BFP(mbrif1);        /* offset 0x24 */
> +	__BFP(mbim1);         /* offset 0x28 */
> +	__BFP(rfh1);          /* offset 0x2c */
> +	__BFP(opss1);         /* offset 0x30 */
> +	u32 __pad1[3];
> +	 __BFP(mc2);           /* offset 0x40 */
        ^
please remove that space.

> +	__BFP(md2);           /* offset 0x44 */
> +	__BFP(trs2);          /* offset 0x48 */
> +	__BFP(trr2);          /* offset 0x4c */
> +	__BFP(ta2);           /* offset 0x50 */
> +	__BFP(aa2);           /* offset 0x54 */
> +	__BFP(rmp2);          /* offset 0x58 */
> +	__BFP(rml2);          /* offset 0x5c */
> +	__BFP(mbtif2);        /* offset 0x60 */
> +	__BFP(mbrif2);        /* offset 0x64 */
> +	__BFP(mbim2);         /* offset 0x68 */
> +	__BFP(rfh2);          /* offset 0x6c */
> +	__BFP(opss2);         /* offset 0x70 */
> +	u32 __pad2[3];
> +	 __BFP(clock);         /* offset 0x80 */
        ^
same here

> +	__BFP(timing);        /* offset 0x84 */
> +	__BFP(debug);         /* offset 0x88 */
> +	__BFP(status);        /* offset 0x8c */
> +	__BFP(cec);           /* offset 0x90 */
> +	__BFP(gis);           /* offset 0x94 */
> +	__BFP(gim);           /* offset 0x98 */
> +	__BFP(gif);           /* offset 0x9c */
> +	__BFP(control);       /* offset 0xa0 */
> +	__BFP(intr);          /* offset 0xa4 */
> +	__BFP(version);       /* offset 0xa8 */
> +	__BFP(mbtd);          /* offset 0xac */
> +	__BFP(ewr);           /* offset 0xb0 */
> +	__BFP(esr);           /* offset 0xb4 */
> +	u32 __pad3[2];
> +	 __BFP(ucreg);         /* offset 0xc0 */
        ^
same here
> +	__BFP(uccnt);         /* offset 0xc4 */
> +	__BFP(ucrc);          /* offset 0xc8 */
> +	__BFP(uccnf);         /* offset 0xcc */
> +	u32 __pad4[1];
> +	 __BFP(version2);      /* offset 0xd4 */
        ^
same here
> +	u32 __pad5[10];
> +
> +	/* channel(mailbox) mask and message registers
> +	 */

	/* single line comment should look like this */

> +	struct bfin_can_mask_regs msk[MAX_CHL_NUMBER];    /* offset 0x100 */
> +	struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */
> +};
> +
> +#undef __BFP
> +
> +#define SRS	             0x0001  /* Software Reset */
              ^^^^^^^^^^^^^^^      ^^
single space here                  probably one tab here
> +#define SER	             0x0008  /* Stuff Error */
> +#define BOIM	            0x0008  /* Enable Bus Off Interrupt */
> +#define CCR	             0x0080  /* CAN Configuration Mode Request */
> +#define CCA	             0x0080  /* Configuration Mode Acknowledge */
> +#define SAM	             0x0080  /* Sampling */
> +#define AME	             0x8000  /* Acceptance Mask Enable */
> +#define RMLIM	           0x0080  /* Enable RX Message Lost Interrupt */
> +#define RMLIS	           0x0080  /* RX Message Lost IRQ Status */
> +#define RTR	             0x4000  /* Remote Frame Transmission Request */
> +#define BOIS	            0x0008  /* Bus Off IRQ Status */
> +#define IDE	             0x2000  /* Identifier Extension */
> +#define EPIS	            0x0004  /* Error-Passive Mode IRQ Status */
> +#define EPIM	            0x0004  /* Enable Error-Passive Mode Interrupt */
> +#define EWTIS	           0x0001  /* TX Error Count IRQ Status */
> +#define EWRIS	           0x0002  /* RX Error Count IRQ Status */
> +#define BEF	             0x0040  /* Bit Error Flag */
> +#define FER	             0x0080  /* Form Error Flag */
> +#define SMR		   0x0020	/* Sleep Mode Request */
> +#define SMACK		   0x0008	/* Sleep Mode Acknowledge */
> +
>  /*
>   * bfin can private data
>   */
> 

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH V6 1/3] bfin_can: rewrite the blackfin style of read/write to common ones
From: Marc Kleine-Budde @ 2015-02-06  7:53 UTC (permalink / raw)
  To: Aaron Wu, wg, linux-can, netdev, linux-kernel, linux-devel
In-Reply-To: <1423203952-23004-1-git-send-email-Aaron.wu@analog.com>

[-- Attachment #1: Type: text/plain, Size: 529 bytes --]

On 02/06/2015 07:25 AM, Aaron Wu wrote:
> Replace the blackfin arch dependent style of bfin_read/bfin_write with
> common readw/writew

Patch 1 & 2 are fine, 3 needs some whitespace improvements (see my reply
for more details).

regards,
Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [RFC PATCH 00/29] net: VRF support
From: Nicolas Dichtel @ 2015-02-06  8:53 UTC (permalink / raw)
  To: David Ahern, netdev; +Cc: ebiederm
In-Reply-To: <54D419A6.1030902@gmail.com>

Le 06/02/2015 02:32, David Ahern a écrit :
> On 2/5/15 6:44 AM, Nicolas Dichtel wrote:
>> Le 05/02/2015 02:34, David Ahern a écrit :
>> [snip]
>>> This is accomplished by enhancing the current namespace checks to a
>>> broader network context that is both a namepsace and a VRF id. The VRF
>>> id is a tag applied to relevant structures, an integer between 1 and 4095
>>> which allows for 4095 VRFs (could have 0 be the default VRF and then the
>>> range is 0-4095 = 4096s VRFs). (The limitation is arguably artificial. It
>>> is based on the genid scheme for versioning networking data which is a
>>> 32-bit integer. The VRF id is the lower 12 bits of the genid's.)
>> Would it be possible to avoid this artificial limit?
>> There could be scenarii with more than 4096 vrf.
>
> As I recall the genid was the only reason to put a limit on it. I know of one
> product with a higher limit (16k I believe), but I figured this was a reasonable
> start point for the discussion.
Sure. My point was to be able to extend this limit in the future.

>>
>> Do you plan to have a way to dump or monitor VRF via netlink?
>
> What do you mean? There is no creation / deletion event. Are you referring to
> monitoring device changes -- device moved from one network context (namespace,
> vrf) to another?
I mean getting the list of existing vrf.

>
> The VRF id can be added as an attribute to all relevant netlink notifications.
I must think a bit more to this (is VRF an "object" or an attribute).

^ permalink raw reply

* Re: [RFC PATCH 14/29] net: vrf: Introduce vrf header file
From: Nicolas Dichtel @ 2015-02-06  8:53 UTC (permalink / raw)
  To: David Ahern, netdev; +Cc: ebiederm
In-Reply-To: <54D41048.4050608@gmail.com>

Le 06/02/2015 01:52, David Ahern a écrit :
> On 2/5/15 6:44 AM, Nicolas Dichtel wrote:
>> Le 05/02/2015 02:34, David Ahern a écrit :
[snip]
>>> +#define VRF_ANY        0xffff
>> It could be useful to expose this value to userland.
>
> Maybe. I was thinking VRF_ANY should stay kernel side only and have a sockopt
> value of -1 mean VRF_ANY.
Better to have a define instead of a magic value (-1) ;-)

^ permalink raw reply

* Re: [PATCH v2 iproute2-next 1/4] include: update headers
From: Nicolas Dichtel @ 2015-02-06  9:02 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: shemminger, netdev
In-Reply-To: <20150205102659.7b4a3ebb@urahara>

Le 05/02/2015 19:26, Stephen Hemminger a écrit :
> On Wed, 28 Jan 2015 15:15:47 +0100
> Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:
>
>> Copy from sanitized headers.
>>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> ---
>>
>> v2: took last headers from net-next
>>
>>   include/linux/if_link.h       |  4 ++++
>>   include/linux/neighbour.h     |  1 +
>>   include/linux/net_namespace.h | 23 +++++++++++++++++++++++
>>   include/linux/rtnetlink.h     |  5 +++++
>>   4 files changed, 33 insertions(+)
>>   create mode 100644 include/linux/net_namespace.h
>
> All kernel headers for iproute2 must come from the result of:
>    $ make headers_install
I've done this.

>
> Please submit a patch to net-next which makes net_namespace.h
> (from include/uapi/linux/net_namespace.h) get correctly installed into
> usr/include/linux/net_namespace.h
>
> The file is missing from include/uapi/linux/Kbuild
Hmm, I'm probably missing something (with net-next):
$ git grep net_namespace.h include/uapi/linux/Kbuild
include/uapi/linux/Kbuild:header-y += net_namespace.h
$ rm -rf usr/include/
$ make headers_install
$ find usr/include/ -name net_namespace.h
usr/include/linux/net_namespace.h

^ permalink raw reply

* Re: [PATCH net-next] xfrm6: Fix a offset value for network header in _decode_session6
From: Steffen Klassert @ 2015-02-06  9:16 UTC (permalink / raw)
  To: David Miller; +Cc: tazaki, netdev, herbert
In-Reply-To: <20150205.153854.2003362622735317610.davem@davemloft.net>

On Thu, Feb 05, 2015 at 03:38:54PM -0800, David Miller wrote:
> From: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
> Date: Wed, 04 Feb 2015 23:31:10 +0900
> 
> > When a network-layer header has multiple IPv6 extension headers, then offset
> > for mobility header goes wrong. This regression breaks an xfrm policy lookup
> > for a particular receive packet. Binding update packets of Mobile IPv6
> > are all discarded without this fix.
> > 
> > Fixes: de3b7a06dfe1 ("xfrm6: Fix transport header offset in _decode_session6.")
> > Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
> 
> Steffen, please review and/or integrate into your tree.

Now applied to the ipsec tree, thanks!

^ permalink raw reply

* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Nicolas Cavallari @ 2015-02-06  9:39 UTC (permalink / raw)
  To: Eric Dumazet, Michal Kazior
  Cc: Neal Cardwell, linux-wireless, Network Development, eyalpe
In-Reply-To: <1423147722.31870.65.camel@edumazet-glaptop2.roam.corp.google.com>

On 05/02/2015 15:48, Eric Dumazet wrote:
> On Thu, 2015-02-05 at 14:44 +0100, Michal Kazior wrote:
> 
>> I do get your point. But 1.5ms is really tough on Wi-Fi.
>>
>> Just look at this:
>>
>> ; ping 192.168.1.2 -c 3
>> PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
>> 64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=1.83 ms
>> 64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=2.02 ms
>> 64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=1.98 ms
> 
> Thats a different point.
> 
> I dont care about rtt but TX completions. (usually much much lower than
> rtt)

On wired network perhaps, but definitely not on Wi-Fi.

With aggregation, you may send up to 4ms of data before the receiver
can acknowledge anything. But you have to gain access to the channel
first, so you may wait while others finish off their 4ms
transmissions. And this does not account for retransmissions.

And aggregation is not the only problem as far as bufferbloat is
concerned. I don't even want to think about powersave.

^ permalink raw reply

* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Michal Kazior @ 2015-02-06  9:42 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Neal Cardwell, linux-wireless, Network Development, eyalpe
In-Reply-To: <1423156205.31870.86.camel@edumazet-glaptop2.roam.corp.google.com>

On 5 February 2015 at 18:10, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Thu, 2015-02-05 at 06:41 -0800, Eric Dumazet wrote:
>
>> Not at all. This basically removes backpressure.
>>
>> A single UDP socket can now blast packets regardless of SO_SNDBUF
>> limits.
>>
>> This basically remove years of work trying to fix bufferbloat.
>>
>> I still do not understand why increasing tcp_limit_output_bytes is not
>> working for you.
>
> Oh well, tcp_limit_output_bytes might be ok.
>
> In fact, the problem comes from GSO assumption. Maybe Herbert was right,
> when he suggested TCP would be simpler if we enforced GSO...
>
> When GSO is used, the thing works because 2*skb->truesize is roughly 2
> ms worth of traffic.
>
> Because you do not use GSO, and tx completions are slow, we need this :
>
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index 65caf8b95e17..ac01b4cd0035 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -2044,7 +2044,8 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
>                         break;
>
>                 /* TCP Small Queues :
> -                * Control number of packets in qdisc/devices to two packets / or ~1 ms.
> +                * Control number of packets in qdisc/devices to two packets /
> +                * or ~2 ms (sk->sk_pacing_rate >> 9) in case GSO is off.
>                  * This allows for :
>                  *  - better RTT estimation and ACK scheduling
>                  *  - faster recovery
> @@ -2053,7 +2054,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
>                  * of queued bytes to ensure line rate.
>                  * One example is wifi aggregation (802.11 AMPDU)
>                  */
> -               limit = max(2 * skb->truesize, sk->sk_pacing_rate >> 10);
> +               limit = max(2 * skb->truesize, sk->sk_pacing_rate >> 9);
>                 limit = min_t(u32, limit, sysctl_tcp_limit_output_bytes);
>
>                 if (atomic_read(&sk->sk_wmem_alloc) > limit) {
>

The above brings back previous behaviour, i.e. I can get 600mbps TCP
on 5 flows again. Single flow is still (as it was before TSO
autosizing) limited to roughly ~280mbps.

I never really bothered before to understand why I need to push a few
flows through ath10k to max it out, i.e. if I run a single UDP flow I
get ~300mbps while with, e.g. 5 I get 670mbps easily.

I guess it was the tx completion latency all along.

I just put an extra debug to ath10k to see the latency between
submission and completion. Here's a log
(http://www.filedropper.com/complete-log) of 2s run of UDP iperf
trying to push 1gbps but managing only 300mbps.

I've made sure to not hold any locks nor introduce internal to ath10k
delays. Frames get completed between 2-4ms in avarage during load.

When I tried using different ath10k hw&fw I got between 1-2ms of
latency for tx completionsyielding ~430mbps while max should be around
670mbps.


Michał

^ permalink raw reply

* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Michal Kazior @ 2015-02-06  9:57 UTC (permalink / raw)
  To: Dave Taht
  Cc: Eric Dumazet, Neal Cardwell, Eyal Perry,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-wireless
In-Reply-To: <CAA93jw45o-Tnt4hEYgc-wHJ26J11dDZLptO9ZONy0Jxp350S3A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 5 February 2015 at 20:50, Dave Taht <dave.taht-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
[...]
> And I really, really, really wish, that just once during this thread,
> someone had bothered to try running a test
> at a real world MCS rate - say MCS1, or MCS4, and measured the latency
> under load of that...

Time between frame submission to firmware and tx-completion on one of
my ath10k machines:

Legacy 54mbps: ~18ms
Legacy 6mbps: ~37ms
11n MCS 3 (nss=0): ~13ms
11n MCS 8 (nss=1): ~6-8ms
11ac NSS=1 MCS=2: ~4-6ms
11ac NSS=2 MCS=0: ~5-8ms

Keep in mind this is a clean room environment so retransmissions are
kept at minimum. Obviously with a noisy environment you'll get retries
at different rates and higher latency.


Michał
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH V7 1/3] bfin_can: rewrite the blackfin style of read/write to common ones
From: Aaron Wu @ 2015-02-06 10:14 UTC (permalink / raw)
  To: wg, mkl, linux-can, netdev, linux-kernel, linux-devel; +Cc: Aaron Wu

Replace the blackfin arch dependent style of bfin_read/bfin_write with
common readw/writew

Signed-off-by: Aaron Wu <Aaron.wu@analog.com>
---
 drivers/net/can/bfin_can.c |  126 +++++++++++++++++++++-----------------------
 1 file changed, 60 insertions(+), 66 deletions(-)

diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index 417d5099..0a5eff4 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -78,8 +78,8 @@ static int bfin_can_set_bittiming(struct net_device *dev)
 	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
 		timing |= SAM;
 
-	bfin_write(&reg->clock, clk);
-	bfin_write(&reg->timing, timing);
+	writew(clk, &reg->clock);
+	writew(timing, &reg->timing);
 
 	netdev_info(dev, "setting CLOCK=0x%04x TIMING=0x%04x\n", clk, timing);
 
@@ -94,16 +94,14 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
 	int i;
 
 	/* disable interrupts */
-	bfin_write(&reg->mbim1, 0);
-	bfin_write(&reg->mbim2, 0);
-	bfin_write(&reg->gim, 0);
+	writew(0, &reg->mbim1);
+	writew(0, &reg->mbim2);
+	writew(0, &reg->gim);
 
 	/* reset can and enter configuration mode */
-	bfin_write(&reg->control, SRS | CCR);
-	SSYNC();
-	bfin_write(&reg->control, CCR);
-	SSYNC();
-	while (!(bfin_read(&reg->control) & CCA)) {
+	writew(SRS | CCR, &reg->control);
+	writew(CCR, &reg->control);
+	while (!(readw(&reg->control) & CCA)) {
 		udelay(10);
 		if (--timeout == 0) {
 			netdev_err(dev, "fail to enter configuration mode\n");
@@ -116,34 +114,33 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
 	 * by writing to CAN Mailbox Configuration Registers 1 and 2
 	 * For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
 	 */
-	bfin_write(&reg->mc1, 0);
-	bfin_write(&reg->mc2, 0);
+	writew(0, &reg->mc1);
+	writew(0, &reg->mc2);
 
 	/* Set Mailbox Direction */
-	bfin_write(&reg->md1, 0xFFFF);   /* mailbox 1-16 are RX */
-	bfin_write(&reg->md2, 0);   /* mailbox 17-32 are TX */
+	writew(0xFFFF, &reg->md1);   /* mailbox 1-16 are RX */
+	writew(0, &reg->md2);   /* mailbox 17-32 are TX */
 
 	/* RECEIVE_STD_CHL */
 	for (i = 0; i < 2; i++) {
-		bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
-		bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
-		bfin_write(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
-		bfin_write(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
-		bfin_write(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
+		writew(0, &reg->chl[RECEIVE_STD_CHL + i].id0);
+		writew(AME, &reg->chl[RECEIVE_STD_CHL + i].id1);
+		writew(0, &reg->chl[RECEIVE_STD_CHL + i].dlc);
+		writew(0x1FFF, &reg->msk[RECEIVE_STD_CHL + i].amh);
+		writew(0xFFFF, &reg->msk[RECEIVE_STD_CHL + i].aml);
 	}
 
 	/* RECEIVE_EXT_CHL */
 	for (i = 0; i < 2; i++) {
-		bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
-		bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
-		bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
-		bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
-		bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
+		writew(0, &reg->chl[RECEIVE_EXT_CHL + i].id0);
+		writew(AME | IDE, &reg->chl[RECEIVE_EXT_CHL + i].id1);
+		writew(0, &reg->chl[RECEIVE_EXT_CHL + i].dlc);
+		writew(0x1FFF, &reg->msk[RECEIVE_EXT_CHL + i].amh);
+		writew(0xFFFF, &reg->msk[RECEIVE_EXT_CHL + i].aml);
 	}
 
-	bfin_write(&reg->mc2, BIT(TRANSMIT_CHL - 16));
-	bfin_write(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
-	SSYNC();
+	writew(BIT(TRANSMIT_CHL - 16), &reg->mc2);
+	writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), &reg->mc1);
 
 	priv->can.state = CAN_STATE_STOPPED;
 }
@@ -157,9 +154,9 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
 	/*
 	 * leave configuration mode
 	 */
-	bfin_write(&reg->control, bfin_read(&reg->control) & ~CCR);
+	writew(readw(&reg->control) & ~CCR, &reg->control);
 
-	while (bfin_read(&reg->status) & CCA) {
+	while (readw(&reg->status) & CCA) {
 		udelay(10);
 		if (--timeout == 0) {
 			netdev_err(dev, "fail to leave configuration mode\n");
@@ -170,26 +167,25 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
 	/*
 	 * clear _All_  tx and rx interrupts
 	 */
-	bfin_write(&reg->mbtif1, 0xFFFF);
-	bfin_write(&reg->mbtif2, 0xFFFF);
-	bfin_write(&reg->mbrif1, 0xFFFF);
-	bfin_write(&reg->mbrif2, 0xFFFF);
+	writew(0xFFFF, &reg->mbtif1);
+	writew(0xFFFF, &reg->mbtif2);
+	writew(0xFFFF, &reg->mbrif1);
+	writew(0xFFFF, &reg->mbrif2);
 
 	/*
 	 * clear global interrupt status register
 	 */
-	bfin_write(&reg->gis, 0x7FF); /* overwrites with '1' */
+	writew(0x7FF, &reg->gis); /* overwrites with '1' */
 
 	/*
 	 * Initialize Interrupts
 	 * - set bits in the mailbox interrupt mask register
 	 * - global interrupt mask
 	 */
-	bfin_write(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
-	bfin_write(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
+	writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), &reg->mbim1);
+	writew(BIT(TRANSMIT_CHL - 16), &reg->mbim2);
 
-	bfin_write(&reg->gim, EPIM | BOIM | RMLIM);
-	SSYNC();
+	writew(EPIM | BOIM | RMLIM, &reg->gim);
 }
 
 static void bfin_can_start(struct net_device *dev)
@@ -226,7 +222,7 @@ static int bfin_can_get_berr_counter(const struct net_device *dev,
 	struct bfin_can_priv *priv = netdev_priv(dev);
 	struct bfin_can_regs __iomem *reg = priv->membase;
 
-	u16 cec = bfin_read(&reg->cec);
+	u16 cec = readw(&reg->cec);
 
 	bec->txerr = cec >> 8;
 	bec->rxerr = cec;
@@ -252,28 +248,28 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	/* fill id */
 	if (id & CAN_EFF_FLAG) {
-		bfin_write(&reg->chl[TRANSMIT_CHL].id0, id);
+		writew(id, &reg->chl[TRANSMIT_CHL].id0);
 		val = ((id & 0x1FFF0000) >> 16) | IDE;
 	} else
 		val = (id << 2);
 	if (id & CAN_RTR_FLAG)
 		val |= RTR;
-	bfin_write(&reg->chl[TRANSMIT_CHL].id1, val | AME);
+	writew(val | AME, &reg->chl[TRANSMIT_CHL].id1);
 
 	/* fill payload */
 	for (i = 0; i < 8; i += 2) {
 		val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
 			((6 - i) < dlc ? (data[6 - i] << 8) : 0);
-		bfin_write(&reg->chl[TRANSMIT_CHL].data[i], val);
+		writew(val, &reg->chl[TRANSMIT_CHL].data[i]);
 	}
 
 	/* fill data length code */
-	bfin_write(&reg->chl[TRANSMIT_CHL].dlc, dlc);
+	writew(dlc, &reg->chl[TRANSMIT_CHL].dlc);
 
 	can_put_echo_skb(skb, dev, 0);
 
 	/* set transmit request */
-	bfin_write(&reg->trs2, BIT(TRANSMIT_CHL - 16));
+	writew(BIT(TRANSMIT_CHL - 16), &reg->trs2);
 
 	return 0;
 }
@@ -296,26 +292,26 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc)
 	/* get id */
 	if (isrc & BIT(RECEIVE_EXT_CHL)) {
 		/* extended frame format (EFF) */
-		cf->can_id = ((bfin_read(&reg->chl[RECEIVE_EXT_CHL].id1)
+		cf->can_id = ((readw(&reg->chl[RECEIVE_EXT_CHL].id1)
 			     & 0x1FFF) << 16)
-			     + bfin_read(&reg->chl[RECEIVE_EXT_CHL].id0);
+			     + readw(&reg->chl[RECEIVE_EXT_CHL].id0);
 		cf->can_id |= CAN_EFF_FLAG;
 		obj = RECEIVE_EXT_CHL;
 	} else {
 		/* standard frame format (SFF) */
-		cf->can_id = (bfin_read(&reg->chl[RECEIVE_STD_CHL].id1)
+		cf->can_id = (readw(&reg->chl[RECEIVE_STD_CHL].id1)
 			     & 0x1ffc) >> 2;
 		obj = RECEIVE_STD_CHL;
 	}
-	if (bfin_read(&reg->chl[obj].id1) & RTR)
+	if (readw(&reg->chl[obj].id1) & RTR)
 		cf->can_id |= CAN_RTR_FLAG;
 
 	/* get data length code */
-	cf->can_dlc = get_can_dlc(bfin_read(&reg->chl[obj].dlc) & 0xF);
+	cf->can_dlc = get_can_dlc(readw(&reg->chl[obj].dlc) & 0xF);
 
 	/* get payload */
 	for (i = 0; i < 8; i += 2) {
-		val = bfin_read(&reg->chl[obj].data[i]);
+		val = readw(&reg->chl[obj].data[i]);
 		cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
 		cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
 	}
@@ -368,7 +364,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
 
 	if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
 				state == CAN_STATE_ERROR_PASSIVE)) {
-		u16 cec = bfin_read(&reg->cec);
+		u16 cec = readw(&reg->cec);
 		u8 rxerr = cec;
 		u8 txerr = cec >> 8;
 
@@ -419,23 +415,23 @@ static irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
 	struct net_device_stats *stats = &dev->stats;
 	u16 status, isrc;
 
-	if ((irq == priv->tx_irq) && bfin_read(&reg->mbtif2)) {
+	if ((irq == priv->tx_irq) && readw(&reg->mbtif2)) {
 		/* transmission complete interrupt */
-		bfin_write(&reg->mbtif2, 0xFFFF);
+		writew(0xFFFF, &reg->mbtif2);
 		stats->tx_packets++;
-		stats->tx_bytes += bfin_read(&reg->chl[TRANSMIT_CHL].dlc);
+		stats->tx_bytes += readw(&reg->chl[TRANSMIT_CHL].dlc);
 		can_get_echo_skb(dev, 0);
 		netif_wake_queue(dev);
-	} else if ((irq == priv->rx_irq) && bfin_read(&reg->mbrif1)) {
+	} else if ((irq == priv->rx_irq) && readw(&reg->mbrif1)) {
 		/* receive interrupt */
-		isrc = bfin_read(&reg->mbrif1);
-		bfin_write(&reg->mbrif1, 0xFFFF);
+		isrc = readw(&reg->mbrif1);
+		writew(0xFFFF, &reg->mbrif1);
 		bfin_can_rx(dev, isrc);
-	} else if ((irq == priv->err_irq) && bfin_read(&reg->gis)) {
+	} else if ((irq == priv->err_irq) && readw(&reg->gis)) {
 		/* error interrupt */
-		isrc = bfin_read(&reg->gis);
-		status = bfin_read(&reg->esr);
-		bfin_write(&reg->gis, 0x7FF);
+		isrc = readw(&reg->gis);
+		status = readw(&reg->esr);
+		writew(0x7FF, &reg->gis);
 		bfin_can_err(dev, isrc, status);
 	} else {
 		return IRQ_NONE;
@@ -640,9 +636,8 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
 
 	if (netif_running(dev)) {
 		/* enter sleep mode */
-		bfin_write(&reg->control, bfin_read(&reg->control) | SMR);
-		SSYNC();
-		while (!(bfin_read(&reg->intr) & SMACK)) {
+		writew(readw(&reg->control) | SMR, &reg->control);
+		while (!(readw(&reg->intr) & SMACK)) {
 			udelay(10);
 			if (--timeout == 0) {
 				netdev_err(dev, "fail to enter sleep mode\n");
@@ -662,8 +657,7 @@ static int bfin_can_resume(struct platform_device *pdev)
 
 	if (netif_running(dev)) {
 		/* leave sleep mode */
-		bfin_write(&reg->intr, 0);
-		SSYNC();
+		writew(0, &reg->intr);
 	}
 
 	return 0;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH V7 2/3] bfin_can: introduce ioremap to comply to archs with MMU
From: Aaron Wu @ 2015-02-06 10:14 UTC (permalink / raw)
  To: wg, mkl, linux-can, netdev, linux-kernel, linux-devel; +Cc: Aaron Wu
In-Reply-To: <1423217659-27820-1-git-send-email-Aaron.wu@analog.com>

Blackfin was built without MMU, old driver code access the IO space by
physical address, introduce the ioremap approach to be compitable with
the common style supporting MMU enabled arch.

Signed-off-by: Aaron Wu <Aaron.wu@analog.com>
---
 drivers/net/can/bfin_can.c |   22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index 0a5eff4..259d09a 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -551,16 +551,10 @@ static int bfin_can_probe(struct platform_device *pdev)
 		goto exit;
 	}
 
-	if (!request_mem_region(res_mem->start, resource_size(res_mem),
-				dev_name(&pdev->dev))) {
-		err = -EBUSY;
-		goto exit;
-	}
-
 	/* request peripheral pins */
 	err = peripheral_request_list(pdata, dev_name(&pdev->dev));
 	if (err)
-		goto exit_mem_release;
+		goto exit;
 
 	dev = alloc_bfin_candev();
 	if (!dev) {
@@ -569,7 +563,13 @@ static int bfin_can_probe(struct platform_device *pdev)
 	}
 
 	priv = netdev_priv(dev);
-	priv->membase = (void __iomem *)res_mem->start;
+
+	priv->membase = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (IS_ERR(priv->membase)) {
+		err = PTR_ERR(priv->membase);
+		goto exit_peri_pin_free;
+	}
+
 	priv->rx_irq = rx_irq->start;
 	priv->tx_irq = tx_irq->start;
 	priv->err_irq = err_irq->start;
@@ -601,8 +601,6 @@ exit_candev_free:
 	free_candev(dev);
 exit_peri_pin_free:
 	peripheral_free_list(pdata);
-exit_mem_release:
-	release_mem_region(res_mem->start, resource_size(res_mem));
 exit:
 	return err;
 }
@@ -611,15 +609,11 @@ static int bfin_can_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct bfin_can_priv *priv = netdev_priv(dev);
-	struct resource *res;
 
 	bfin_can_set_reset_mode(dev);
 
 	unregister_candev(dev);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
 	peripheral_free_list(priv->pin_list);
 
 	free_candev(dev);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH V7 3/3] bfin_can: Merge header file from arch dependent location
From: Aaron Wu @ 2015-02-06 10:14 UTC (permalink / raw)
  To: wg, mkl, linux-can, netdev, linux-kernel, linux-devel; +Cc: Aaron Wu
In-Reply-To: <1423217659-27820-1-git-send-email-Aaron.wu@analog.com>

Header file was in arch dependent location arch/blackfin/include/asm/bfin_can.h,
Now move and merge the useful contents of header file into driver code, note
the original header file is reserved for full registers set access test by other
code so it survives.

Signed-off-by: Aaron Wu <Aaron.wu@analog.com>
---
 drivers/net/can/bfin_can.c |  110 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index 259d09a..bb1d480 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -20,13 +20,121 @@
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
 
-#include <asm/bfin_can.h>
 #include <asm/portmux.h>
 
 #define DRV_NAME "bfin_can"
 #define BFIN_CAN_TIMEOUT 100
 #define TX_ECHO_SKB_MAX  1
 
+/* transmit and receive channels */
+#define TRANSMIT_CHL 24
+#define RECEIVE_STD_CHL 0
+#define RECEIVE_EXT_CHL 4
+#define RECEIVE_RTR_CHL 8
+#define RECEIVE_EXT_RTR_CHL 12
+#define MAX_CHL_NUMBER 32
+
+/* All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this
+*/
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/* bfin can registers layout */
+struct bfin_can_mask_regs {
+	__BFP(aml);
+	__BFP(amh);
+};
+
+struct bfin_can_channel_regs {
+	/* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */
+	u16 data[8];
+	__BFP(dlc);
+	__BFP(tsv);
+	__BFP(id0);
+	__BFP(id1);
+};
+
+struct bfin_can_regs {
+	/* global control and status registers */
+	__BFP(mc1);		/* offset 0x00 */
+	__BFP(md1);		/* offset 0x04 */
+	__BFP(trs1);		/* offset 0x08 */
+	__BFP(trr1);		/* offset 0x0c */
+	__BFP(ta1);		/* offset 0x10 */
+	__BFP(aa1);		/* offset 0x14 */
+	__BFP(rmp1);		/* offset 0x18 */
+	__BFP(rml1);		/* offset 0x1c */
+	__BFP(mbtif1);		/* offset 0x20 */
+	__BFP(mbrif1);		/* offset 0x24 */
+	__BFP(mbim1);		/* offset 0x28 */
+	__BFP(rfh1);		/* offset 0x2c */
+	__BFP(opss1);		/* offset 0x30 */
+	u32 __pad1[3];
+	__BFP(mc2);		/* offset 0x40 */
+	__BFP(md2);		/* offset 0x44 */
+	__BFP(trs2);		/* offset 0x48 */
+	__BFP(trr2);		/* offset 0x4c */
+	__BFP(ta2);		/* offset 0x50 */
+	__BFP(aa2);		/* offset 0x54 */
+	__BFP(rmp2);		/* offset 0x58 */
+	__BFP(rml2);		/* offset 0x5c */
+	__BFP(mbtif2);		/* offset 0x60 */
+	__BFP(mbrif2);		/* offset 0x64 */
+	__BFP(mbim2);		/* offset 0x68 */
+	__BFP(rfh2);		/* offset 0x6c */
+	__BFP(opss2);		/* offset 0x70 */
+	u32 __pad2[3];
+	__BFP(clock);		/* offset 0x80 */
+	__BFP(timing);		/* offset 0x84 */
+	__BFP(debug);		/* offset 0x88 */
+	__BFP(status);		/* offset 0x8c */
+	__BFP(cec);		/* offset 0x90 */
+	__BFP(gis);		/* offset 0x94 */
+	__BFP(gim);		/* offset 0x98 */
+	__BFP(gif);		/* offset 0x9c */
+	__BFP(control);		/* offset 0xa0 */
+	__BFP(intr);		/* offset 0xa4 */
+	__BFP(version);		/* offset 0xa8 */
+	__BFP(mbtd);		/* offset 0xac */
+	__BFP(ewr);		/* offset 0xb0 */
+	__BFP(esr);		/* offset 0xb4 */
+	u32 __pad3[2];
+	__BFP(ucreg);		/* offset 0xc0 */
+	__BFP(uccnt);		/* offset 0xc4 */
+	__BFP(ucrc);		/* offset 0xc8 */
+	__BFP(uccnf);		/* offset 0xcc */
+	u32 __pad4[1];
+	__BFP(version2);	/* offset 0xd4 */
+	u32 __pad5[10];
+
+	/* channel(mailbox) mask and message registers */
+	struct bfin_can_mask_regs msk[MAX_CHL_NUMBER];    /* offset 0x100 */
+	struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */
+};
+
+#undef __BFP
+
+#define SRS	0x0001  /* Software Reset */
+#define SER	0x0008  /* Stuff Error */
+#define BOIM	0x0008  /* Enable Bus Off Interrupt */
+#define CCR	0x0080  /* CAN Configuration Mode Request */
+#define CCA	0x0080  /* Configuration Mode Acknowledge */
+#define SAM	0x0080  /* Sampling */
+#define AME	0x8000  /* Acceptance Mask Enable */
+#define RMLIM	0x0080  /* Enable RX Message Lost Interrupt */
+#define RMLIS	0x0080  /* RX Message Lost IRQ Status */
+#define RTR	0x4000  /* Remote Frame Transmission Request */
+#define BOIS	0x0008  /* Bus Off IRQ Status */
+#define IDE	0x2000  /* Identifier Extension */
+#define EPIS	0x0004  /* Error-Passive Mode IRQ Status */
+#define EPIM	0x0004  /* Enable Error-Passive Mode Interrupt */
+#define EWTIS	0x0001  /* TX Error Count IRQ Status */
+#define EWRIS	0x0002  /* RX Error Count IRQ Status */
+#define BEF	0x0040  /* Bit Error Flag */
+#define FER	0x0080  /* Form Error Flag */
+#define SMR	0x0020  /* Sleep Mode Request */
+#define SMACK	0x0008  /* Sleep Mode Acknowledge */
+
 /*
  * bfin can private data
  */
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH] brcmfmac: use msecs_to_jiffies for time conversion
From: Nicholas Mc Guire @ 2015-02-06 10:26 UTC (permalink / raw)
  To: Brett Rudley
  Cc: Arend van Spriel, Franky (Zhenhui) Lin, Hante Meuleman,
	Kalle Valo, Pieter-Paul Giesberts, John W. Linville, Daniel Kim,
	linux-wireless, brcm80211-dev-list, netdev, linux-kernel,
	Nicholas Mc Guire

This is only an API consolidation and should make things more readable
it replaces var * HZ / 1000 by msecs_to_jiffies(var).

Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
---

Patch was only compile tested with x86_64_defconfig + CONFIG_BRCMFMAC=m,
CONFIG_MMC=m, CONFIG_BRCMFMAC_SDIO=y

Patch is against 3.19.0-rc7 (localversion-next is -next-20150204)

 drivers/net/wireless/brcm80211/brcmfmac/sdio.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index 5e9d208..4f9469b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -3972,7 +3972,7 @@ brcmf_sdio_watchdog(unsigned long data)
 		/* Reschedule the watchdog */
 		if (bus->wd_timer_valid)
 			mod_timer(&bus->timer,
-				  jiffies + BRCMF_WD_POLL_MS * HZ / 1000);
+				  jiffies + msecs_to_jiffies(BRCMF_WD_POLL_MS));
 	}
 }
 
@@ -4291,13 +4291,13 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick)
 			   dynamically changed or in the first instance
 			 */
 			bus->timer.expires =
-				jiffies + BRCMF_WD_POLL_MS * HZ / 1000;
+				jiffies + msecs_to_jiffies(BRCMF_WD_POLL_MS);
 			add_timer(&bus->timer);
 
 		} else {
 			/* Re arm the timer, at last watchdog period */
 			mod_timer(&bus->timer,
-				jiffies + BRCMF_WD_POLL_MS * HZ / 1000);
+				jiffies + msecs_to_jiffies(BRCMF_WD_POLL_MS));
 		}
 
 		bus->wd_timer_valid = true;
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH V7 3/3] bfin_can: Merge header file from arch dependent location
From: Marc Kleine-Budde @ 2015-02-06 10:26 UTC (permalink / raw)
  To: Aaron Wu, wg, linux-can, netdev, linux-kernel, linux-devel
In-Reply-To: <1423217659-27820-3-git-send-email-Aaron.wu@analog.com>

[-- Attachment #1: Type: text/plain, Size: 4217 bytes --]

On 02/06/2015 11:14 AM, Aaron Wu wrote:
> Header file was in arch dependent location arch/blackfin/include/asm/bfin_can.h,
> Now move and merge the useful contents of header file into driver code, note
> the original header file is reserved for full registers set access test by other
> code so it survives.
> 
> Signed-off-by: Aaron Wu <Aaron.wu@analog.com>
> ---
>  drivers/net/can/bfin_can.c |  110 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 109 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
> index 259d09a..bb1d480 100644
> --- a/drivers/net/can/bfin_can.c
> +++ b/drivers/net/can/bfin_can.c
> @@ -20,13 +20,121 @@
>  #include <linux/can/dev.h>
>  #include <linux/can/error.h>
>  
> -#include <asm/bfin_can.h>
>  #include <asm/portmux.h>
>  
>  #define DRV_NAME "bfin_can"
>  #define BFIN_CAN_TIMEOUT 100
>  #define TX_ECHO_SKB_MAX  1
>  
> +/* transmit and receive channels */
> +#define TRANSMIT_CHL 24
> +#define RECEIVE_STD_CHL 0
> +#define RECEIVE_EXT_CHL 4
> +#define RECEIVE_RTR_CHL 8
> +#define RECEIVE_EXT_RTR_CHL 12
> +#define MAX_CHL_NUMBER 32
> +
> +/* All Blackfin system MMRs are padded to 32bits even if the register
> + * itself is only 16bits.  So use a helper macro to streamline this
> +*/
> +#define __BFP(m) u16 m; u16 __pad_##m
> +
> +/* bfin can registers layout */
> +struct bfin_can_mask_regs {
> +	__BFP(aml);
> +	__BFP(amh);
> +};
> +
> +struct bfin_can_channel_regs {
> +	/* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */
> +	u16 data[8];
> +	__BFP(dlc);
> +	__BFP(tsv);
> +	__BFP(id0);
> +	__BFP(id1);
> +};
> +
> +struct bfin_can_regs {
> +	/* global control and status registers */
> +	__BFP(mc1);		/* offset 0x00 */
> +	__BFP(md1);		/* offset 0x04 */
> +	__BFP(trs1);		/* offset 0x08 */
> +	__BFP(trr1);		/* offset 0x0c */
> +	__BFP(ta1);		/* offset 0x10 */
> +	__BFP(aa1);		/* offset 0x14 */
> +	__BFP(rmp1);		/* offset 0x18 */
> +	__BFP(rml1);		/* offset 0x1c */
> +	__BFP(mbtif1);		/* offset 0x20 */
> +	__BFP(mbrif1);		/* offset 0x24 */
> +	__BFP(mbim1);		/* offset 0x28 */
> +	__BFP(rfh1);		/* offset 0x2c */
> +	__BFP(opss1);		/* offset 0x30 */
> +	u32 __pad1[3];
> +	__BFP(mc2);		/* offset 0x40 */
> +	__BFP(md2);		/* offset 0x44 */
> +	__BFP(trs2);		/* offset 0x48 */
> +	__BFP(trr2);		/* offset 0x4c */
> +	__BFP(ta2);		/* offset 0x50 */
> +	__BFP(aa2);		/* offset 0x54 */
> +	__BFP(rmp2);		/* offset 0x58 */
> +	__BFP(rml2);		/* offset 0x5c */
> +	__BFP(mbtif2);		/* offset 0x60 */
> +	__BFP(mbrif2);		/* offset 0x64 */
> +	__BFP(mbim2);		/* offset 0x68 */
> +	__BFP(rfh2);		/* offset 0x6c */
> +	__BFP(opss2);		/* offset 0x70 */
> +	u32 __pad2[3];
> +	__BFP(clock);		/* offset 0x80 */
> +	__BFP(timing);		/* offset 0x84 */
> +	__BFP(debug);		/* offset 0x88 */
> +	__BFP(status);		/* offset 0x8c */
> +	__BFP(cec);		/* offset 0x90 */
> +	__BFP(gis);		/* offset 0x94 */
> +	__BFP(gim);		/* offset 0x98 */
> +	__BFP(gif);		/* offset 0x9c */
> +	__BFP(control);		/* offset 0xa0 */
> +	__BFP(intr);		/* offset 0xa4 */
> +	__BFP(version);		/* offset 0xa8 */
> +	__BFP(mbtd);		/* offset 0xac */
> +	__BFP(ewr);		/* offset 0xb0 */
> +	__BFP(esr);		/* offset 0xb4 */
> +	u32 __pad3[2];
> +	__BFP(ucreg);		/* offset 0xc0 */
> +	__BFP(uccnt);		/* offset 0xc4 */
> +	__BFP(ucrc);		/* offset 0xc8 */
> +	__BFP(uccnf);		/* offset 0xcc */
> +	u32 __pad4[1];
> +	__BFP(version2);	/* offset 0xd4 */
> +	u32 __pad5[10];
> +
> +	/* channel(mailbox) mask and message registers */
> +	struct bfin_can_mask_regs msk[MAX_CHL_NUMBER];    /* offset 0x100 */
> +	struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */
> +};
> +
> +#undef __BFP
> +
> +#define SRS	0x0001  /* Software Reset */
              ^^

please use a single space here (and below), as in the rest of the file.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH 0/6 v2 net-next] rhashtable fixes
From: Thomas Graf @ 2015-02-06 10:40 UTC (permalink / raw)
  To: Ying Xue; +Cc: davem, netdev, herbert
In-Reply-To: <54D42892.3030808@windriver.com>

On 02/06/15 at 10:36am, Ying Xue wrote:
> After I applied the below change on the latest net-next tree with the series
> patches, panic happens during kernel boot stage as follows:

Sorry about that. I must have booted the wrong kernel. On the positive
side, I was able to reproduce the original race today. The key was to
use 8 instead of 4 CPUs in the VM. I'm testing with the fixed build
right now.

^ permalink raw reply

* [PATCH] ath9k_htc: add adaptive usb receive flow control to repair soft lockup with monitor mode
From: yuweizheng @ 2015-02-06 10:46 UTC (permalink / raw)
  To: linux-kernel, ath9k-devel, linux-wireless, kvalo, ath9k-devel
  Cc: netdev, zhengyuwei, Yuwei Zheng

From: Yuwei Zheng <yuweizheng@139.com>

In the environment with heavy wifi traffic, set the ar9271 into monitor mode, will
trigger a deadloop panic.
 
The ath9k_hif_usb_rx_cb function excute on  the interrupt context, and ath9k_rx_tasklet excute
on the soft irq context. In other words, the ath9k_hif_usb_rx_cb have more chance to excute than
ath9k_rx_tasklet.  So in the worst condition,  the rx.rxbuf receive list is always full,
and the do {}while(true) loop will not be break. The kernel get a soft lockup panic. 
 
[59011.007210] BUG: soft lockup - CPU#0 stuck for 23s!
[kworker/0:0:30609]
[59011.030560] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.804486] BUG: scheduling while atomic: kworker/0:0/30609/0x40010100
[59013.858522] Kernel panic - not syncing: softlockup: hung tasks
 
[59014.038891] Exception stack(0xdf4bbc38 to 0xdf4bbc80)
[59014.046834] bc20:                                                       de57b950 60000113
[59014.059579] bc40: 00000000 bb32bb32 60000113 de57b948 de57b500 dc7bb440 df4bbcd0 00000000
[59014.072337] bc60: de57b950 60000113 df4bbcd0 df4bbc80 c04c259d c04c25a0 60000133 ffffffff
[59014.085233] [<c04c28db>] (__irq_svc+0x3b/0x5c) from [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10)
[59014.100437] [<c04c25a0>] (_raw_spin_unlock_irqrestore+0xc/0x10) from [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc])
[59014.118267] [<bf9c2089>] (ath9k_rx_tasklet+0x290/0x490 [ath9k_htc]) from [<c0036d23>] (tasklet_action+0x3b/0x98)
[59014.134132] [<c0036d23>] (tasklet_action+0x3b/0x98) from [<c0036709>] (__do_softirq+0x99/0x16c)
[59014.147784] [<c0036709>] (__do_softirq+0x99/0x16c) from [<c00369f7>] (irq_exit+0x5b/0x5c)
[59014.160653] [<c00369f7>] (irq_exit+0x5b/0x5c) from [<c000cfc3>] (handle_IRQ+0x37/0x78)
[59014.173124] [<c000cfc3>] (handle_IRQ+0x37/0x78) from [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68)
[59014.187225] [<c00085df>] (omap3_intc_handle_irq+0x5f/0x68) from [<c04c28db>](__irq_svc+0x3b/0x5c)
 
This bug can be see with low performance board, such as uniprocessor beagle bone board. 
 
Signed-off-by: Yuwei Zheng <yuweizheng@139.com>

---
 drivers/net/wireless/ath/ath9k/hif_usb.c       | 74 +++++++++++++++++++++++---
 drivers/net/wireless/ath/ath9k/hif_usb.h       |  9 ++++
 drivers/net/wireless/ath/ath9k/htc.h           | 19 +++++++
 drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 53 ++++++++++++++++++
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c  | 44 +++++++++++++++
 5 files changed, 192 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8e7153b..90ee568 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -640,6 +640,7 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 	struct hif_device_usb *hif_dev =
 		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
 	int ret;
+	int delay;
 
 	if (!skb)
 		return;
@@ -658,7 +659,6 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 	default:
 		goto resubmit;
 	}
-
 	if (likely(urb->actual_length != 0)) {
 		skb_put(skb, urb->actual_length);
 		ath9k_hif_usb_rx_stream(hif_dev, skb);
@@ -667,12 +667,22 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
 resubmit:
 	skb_reset_tail_pointer(skb);
 	skb_trim(skb, 0);
-
-	usb_anchor_urb(urb, &hif_dev->rx_submitted);
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret) {
-		usb_unanchor_urb(urb);
-		goto free;
+	spin_lock(&hif_dev->aurfc_lock);
+	if (atomic_read(&hif_dev->aurfc_submit_delay) > 0 &&
+	    hif_dev->aurfc_active == 1) {
+		usb_anchor_urb(urb, &hif_dev->rx_delayed_submitted);
+		delay = atomic_read(&hif_dev->aurfc_submit_delay);
+		schedule_delayed_work(&hif_dev->aurfc_delayed_work,
+				      msecs_to_jiffies(delay));
+		spin_unlock(&hif_dev->aurfc_lock);
+	} else {
+		spin_unlock(&hif_dev->aurfc_lock);
+		usb_anchor_urb(urb, &hif_dev->rx_submitted);
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+		if (ret) {
+			usb_unanchor_urb(urb);
+			goto free;
+		}
 	}
 
 	return;
@@ -818,9 +828,50 @@ err:
 	return -ENOMEM;
 }
 
+static void aurfc_submit_handler(struct work_struct *work)
+{
+	struct hif_device_usb *hif_dev =
+		container_of(work,
+			     struct hif_device_usb,
+			     aurfc_delayed_work.work);
+
+	struct urb *urb = NULL;
+	struct sk_buff *skb = NULL;
+	int ret;
+	int loop_times = 0;
+
+	while (true) {
+		loop_times++;
+		if (loop_times > MAX_RX_URB_NUM)
+			atomic_add(AURFC_STEP,
+				   &hif_dev->aurfc_submit_delay);
+
+		urb = usb_get_from_anchor(
+				&hif_dev->rx_delayed_submitted);
+		if (urb) {
+			skb = (struct sk_buff *)urb->context;
+			ret = usb_submit_urb(urb, GFP_KERNEL);
+			if (ret != 0) {
+				usb_unanchor_urb(urb);
+				dev_kfree_skb_any(skb);
+				urb->context = NULL;
+			}
+		} else {
+			break;
+		}
+	}
+}
+
 static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&hif_dev->aurfc_lock, flags);
+	hif_dev->aurfc_active = 0;
+	mod_delayed_work(system_wq, &hif_dev->aurfc_delayed_work, 0);
+	spin_unlock_irqrestore(&hif_dev->aurfc_lock, flags);
 	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
+	usb_kill_anchored_urbs(&hif_dev->rx_delayed_submitted);
 }
 
 static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
@@ -830,8 +881,17 @@ static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
 	int i, ret;
 
 	init_usb_anchor(&hif_dev->rx_submitted);
+	init_usb_anchor(&hif_dev->rx_delayed_submitted);
+
 	spin_lock_init(&hif_dev->rx_lock);
 
+	/* add for adaptive usb receive control*/
+	atomic_set(&hif_dev->aurfc_submit_delay, 0);
+	INIT_DELAYED_WORK(&hif_dev->aurfc_delayed_work,
+			  aurfc_submit_handler);
+	spin_lock_init(&hif_dev->aurfc_lock);
+	hif_dev->aurfc_active = 1;
+
 	for (i = 0; i < MAX_RX_URB_NUM; i++) {
 
 		/* Allocate URB */
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 51496e7..2050a74 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -41,6 +41,7 @@
 #define MAX_RX_URB_NUM  8
 #define MAX_RX_BUF_SIZE 16384
 #define MAX_PKT_NUM_IN_TRANSFER 10
+#define AURFC_STEP 10  /* ms */
 
 #define MAX_REG_OUT_URB_NUM  1
 #define MAX_REG_IN_URB_NUM   64
@@ -98,9 +99,17 @@ struct hif_device_usb {
 	struct hif_usb_tx tx;
 	struct usb_anchor regout_submitted;
 	struct usb_anchor rx_submitted;
+	struct usb_anchor rx_delayed_submitted;
 	struct usb_anchor reg_in_submitted;
 	struct usb_anchor mgmt_submitted;
 	struct sk_buff *remain_skb;
+
+	/* adaptive usb receive flow control */
+	struct delayed_work aurfc_delayed_work;
+	spinlock_t aurfc_lock; /* to protect work */
+	atomic_t  aurfc_submit_delay; /* ms */
+	int aurfc_active;
+
 	const char *fw_name;
 	int rx_remain_len;
 	int rx_pkt_len;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 9dde265..1586bd2 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,6 +331,13 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
 
 #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
 
+#define AURFC_STAT_INC(c) \
+	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c++)
+#define AURFC_STAT_ADD(c, a) \
+	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c += a)
+#define AURFC_STAT_SET(c, a) \
+	(hif_dev->htc_handle->drv_priv->debug.aurfc_stats.c = a)
+
 void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 			   struct ath_rx_status *rs);
 
@@ -352,11 +359,20 @@ struct ath_skbrx_stats {
 	u32 skb_dropped;
 };
 
+struct ath_aurfc_stats {
+	u32 aurfc_highwater;
+	u32 aurfc_lowwater;
+	u32 aurfc_wm_triggered;
+	u32 aurfc_submit_delay;
+	u32 aurfc_called;
+};
+
 struct ath9k_debug {
 	struct dentry *debugfs_phy;
 	struct ath_tx_stats tx_stats;
 	struct ath_rx_stats rx_stats;
 	struct ath_skbrx_stats skbrx_stats;
+	struct ath_aurfc_stats aurfc_stats;
 };
 
 void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
@@ -377,6 +393,9 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
 
 #define TX_QSTAT_INC(c) do { } while (0)
 
+#define AURFC_STAT_INC(c) do {} while (0)
+#define AURFC_STAT_ADD(c, a) do {} while (0)
+#define AURFC_STAT_SET(c, a) do {} while (0)
 static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 					 struct ath_rx_status *rs)
 {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 8cef1ed..a6be9be 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -286,6 +286,54 @@ static const struct file_operations fops_skb_rx = {
 	.llseek = default_llseek,
 };
 
+static ssize_t read_file_aurfc(struct file *file,
+			       char __user *user_buf,
+			       size_t count, loff_t *ppos)
+{
+	struct ath9k_htc_priv *priv = file->private_data;
+	char *buf;
+	unsigned int len = 0, size = 1500;
+	ssize_t retval = 0;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "High watermark",
+			priv->debug.aurfc_stats.aurfc_highwater);
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Low watermark",
+			priv->debug.aurfc_stats.aurfc_lowwater);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "WM triggered",
+			priv->debug.aurfc_stats.aurfc_wm_triggered);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Handler called",
+			priv->debug.aurfc_stats.aurfc_called);
+
+	len += scnprintf(buf + len, size - len,
+			"%20s : %10u\n", "Submit delay",
+			priv->debug.aurfc_stats.aurfc_submit_delay);
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count,
+					 ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static const struct file_operations fops_aurfc = {
+	.read = read_file_aurfc,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static ssize_t read_file_slot(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
@@ -518,7 +566,12 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
 	debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
 			    priv, &fops_skb_rx);
 
+	debugfs_create_file("aurfc_stats", S_IRUSR,
+			    priv->debug.debugfs_phy,
+			    priv, &fops_aurfc);
+
 	ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
+
 	ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
 
 	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index a0f58e2..939d008 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1061,7 +1061,28 @@ void ath9k_rx_tasklet(unsigned long data)
 	unsigned long flags;
 	struct ieee80211_hdr *hdr;
 
+	/* add for adaptive usb receive flow control*/
+	int looptimes = 0;
+	int highwatermark = ATH9K_HTC_RXBUF*3/4;
+	int lowwatermark = ATH9K_HTC_RXBUF/32;
+	unsigned int delay = 0;
+
+	struct htc_target *htc = priv->htc;
+	struct hif_device_usb *hif_dev = htc->hif_dev;
+
+	AURFC_STAT_SET(aurfc_highwater, highwatermark);
+	AURFC_STAT_SET(aurfc_lowwater, lowwatermark);
+
 	do {
+		looptimes++;
+		if (looptimes > highwatermark) {
+			delay = looptimes*AURFC_STEP;
+			atomic_set(&hif_dev->aurfc_submit_delay,
+				   delay);
+			AURFC_STAT_INC(aurfc_wm_triggered);
+			AURFC_STAT_SET(aurfc_submit_delay, delay);
+		}
+
 		spin_lock_irqsave(&priv->rx.rxbuflock, flags);
 		list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 			if (tmp_buf->in_process) {
@@ -1072,6 +1093,22 @@ void ath9k_rx_tasklet(unsigned long data)
 
 		if (rxbuf == NULL) {
 			spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
+			spin_lock_irqsave(&hif_dev->aurfc_lock,
+					  flags);
+			if (atomic_read(
+				&hif_dev->aurfc_submit_delay) > 0 &&
+			    hif_dev->aurfc_active > 0)
+				mod_delayed_work(system_wq,
+					&hif_dev->aurfc_delayed_work,
+						 0);
+			spin_unlock_irqrestore(&hif_dev->aurfc_lock,
+					       flags);
+			if (looptimes < lowwatermark) {
+				atomic_set(&hif_dev->aurfc_submit_delay
+					   , 0);
+				AURFC_STAT_SET(aurfc_submit_delay,
+					       0);
+			}
 			break;
 		}
 
@@ -1114,6 +1151,10 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
 
+	struct htc_target *htc = priv->htc;
+	struct hif_device_usb *hif_dev = htc->hif_dev;
+	int delay = ATH9K_HTC_RXBUF * AURFC_STEP;
+
 	spin_lock(&priv->rx.rxbuflock);
 	list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 		if (!tmp_buf->in_process) {
@@ -1124,6 +1165,9 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
 	spin_unlock(&priv->rx.rxbuflock);
 
 	if (rxbuf == NULL) {
+		atomic_set(&hif_dev->aurfc_submit_delay, delay);
+		AURFC_STAT_INC(aurfc_wm_triggered);
+		AURFC_STAT_SET(aurfc_submit_delay, delay);
 		ath_dbg(common, ANY, "No free RX buffer\n");
 		goto err;
 	}
-- 
1.9.1

^ permalink raw reply related

* Re: Ethernet: how to disable gigabit support
From: Maciej W. Rozycki @ 2015-02-06 11:01 UTC (permalink / raw)
  To: Pavel Machek; +Cc: kernel list, netdev
In-Reply-To: <20150205202527.GA7917@amd>

On Thu, 5 Feb 2015, Pavel Machek wrote:

> This happened on more than one project: there's gigabit-capable chip,
> but the connector is not designed for gigabit speed.
> 
> I'd like to have speed autonegotiation, but not offer gigabit (as it
> will not work).
> 
> Is there way to do that without hacking the kernel? Should mii-tool do
> that?

 It used to work for me with a 3Com 3c905C adapter when I needed to force 
full duplex for an old non-negotiating 100baseTx-FD network switch.

> root@ib8315:~# mii-tool.net-tools  -A 100baseTx,10baseT eth1
> restarting autonegotiation...
> root@ib8315:~# [32432.443883] libphy: mdio@e0024520:01 - Link is Down
> 
> root@ib8315:~# [32435.447863] libphy: mdio@e0024520:01 - Link is Up - 1000/Full
> 
> root@ib8315:~# mii-tool.net-tools -v eth1
> eth1: negotiated 1000baseT-FD flow-control, link ok
> product info: vendor 00:01:c1, model 3 rev 1
> basic mode:   autonegotiation enabled
>  basic status: autonegotiation complete, link ok
>  capabilities: 1000baseT-FD 100baseTx-FD 100baseTx-HD
>  10baseT-FD 10baseT-HD
>  advertising:  1000baseT-FD 100baseTx-FD 100baseTx-HD
>  10baseT-FD 10baseT-HD
>  link partner: 1000baseT-FD 100baseTx-FD 100baseTx-HD
>  10baseT-FD 10baseT-HD flow-control
>  root@ib8315:~# mii-tool.net-tools -V
>  $Id: mii-tool.c,v 1.9 2006/09/27 20:59:18 ecki Exp $
>  (Author: David Hinds based on Donald Becker's mii-diag)
>  net-tools 1.60
>  root@ib8315:~#

 You may have to spell out media names in full, e.g.:

# mii-tool -A 100baseTx-FD,100baseTx-HD,10baseT-FD,10baseT-HD eth1

Also the driver may have a way to override the capabilities advertised via 
a module parameter.  This is what I eventually ended up with with the 
3c905C adapter.

  Maciej

^ permalink raw reply

* [PATCH net-next 0/9] be2net: patch set
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
  To: netdev

Hi Dave, pls consider applying the following patch-set to the
net-next tree. It has 5 code/style cleanup patches and 4 patches that
add functionality to the driver.

Patch 1 moves routines that were not needed to be in be.h to the respective
src files, to avoid unnecessary compilation.

Patch 2 replaces (1 << x) with BIT(x) macro

Patch 3 refactors code that checks if a FW flash file is compatible
with the adapter. The code is now refactored into 2 routines, the first one
gets the file type from the image file and the 2nd routine checks if the
file type is compatible with the adapter.

Patch 4 adds compatibility checks for flashing a FW image on the new
Skyhawk P2 HW revision.

Patch 5 adds support for a new "offset based" flashing scheme, wherein
the driver informs the FW of the offset at which each component in the flash
file is to be flashed at. This helps flashing components that were 
previously not recognized by the running FW.

Patch 6 simplifies the be_cmd_rx_filter() routine, by passing to it the
filter flags already used in the FW cmd, instead of the netdev flags that
were converted to the FW-cmd flags. 

Patch 7 introduces helper routines in be_set_rx_mode() and be_vid_config()
to improve code readability.

Patch 8 adds processing of port-misconfig async event sent by the FW.

Patch 9 removes unnecessary swapping of a field in the TX desc.

Sathya Perla (4):
  be2net: move un-exported routines from be.h to respective src files
  be2net: remove duplicate code in be_cmd_rx_filter()
  be2net: refactor be_set_rx_mode() and be_vid_config() for readability
  be2net: avoid unncessary swapping of fields in eth_tx_wrb

Vasundhara Volam (5):
  be2net: replace (1 << x) with BIT(x)
  be2net: refactor code that checks flash file compatibility
  be2net: avoid flashing SH-B0 UFI image on SH-P2 chip
  be2net: use offset based FW flashing for Skyhawk chip
  be2net: process port misconfig async event

 drivers/net/ethernet/emulex/benet/be.h      | 199 +--------
 drivers/net/ethernet/emulex/benet/be_cmds.c | 209 ++++++---
 drivers/net/ethernet/emulex/benet/be_cmds.h |  43 +-
 drivers/net/ethernet/emulex/benet/be_hw.h   |  14 +-
 drivers/net/ethernet/emulex/benet/be_main.c | 635 +++++++++++++++++++---------
 5 files changed, 647 insertions(+), 453 deletions(-)

-- 
2.2.0

^ permalink raw reply

* [PATCH net-next 4/9] be2net: avoid flashing SH-B0 UFI image on SH-P2 chip
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1423228723-10919-1-git-send-email-sathya.perla@emulex.com>

From: Vasundhara Volam <vasundhara.volam@emulex.com>

Skyhawk-B0 FW UFI is not compatible to flash on Skyhawk-P2 ASIC.
But, Skyhawk-P2 FW UFI is compatible with both B0 and P2 chips.

Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be_cmds.h |  1 +
 drivers/net/ethernet/emulex/benet/be_main.c | 10 ++++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index bed4a32..774c5d1 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1093,6 +1093,7 @@ struct be_cmd_req_query_fw_cfg {
 
 /* ASIC revisions */
 #define ASIC_REV_B0		0x10
+#define ASIC_REV_P2		0x11
 
 struct be_cmd_resp_query_fw_cfg {
 	struct be_cmd_resp_hdr hdr;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index ddc5966..9eaf8bc 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4336,6 +4336,7 @@ static int lancer_fw_download(struct be_adapter *adapter,
 #define BE3_UFI		3
 #define BE3R_UFI	10
 #define SH_UFI		4
+#define SH_P2_UFI	11
 
 static int be_get_ufi_type(struct be_adapter *adapter,
 			   struct flash_file_hdr_g3 *fhdr)
@@ -4350,7 +4351,8 @@ static int be_get_ufi_type(struct be_adapter *adapter,
 	 */
 	switch (fhdr->build[0]) {
 	case BLD_STR_UFI_TYPE_SH:
-		return SH_UFI;
+		return (fhdr->asic_type_rev == ASIC_REV_P2) ? SH_P2_UFI :
+								SH_UFI;
 	case BLD_STR_UFI_TYPE_BE3:
 		return (fhdr->asic_type_rev == ASIC_REV_B0) ? BE3R_UFI :
 								BE3_UFI;
@@ -4364,6 +4366,7 @@ static int be_get_ufi_type(struct be_adapter *adapter,
 /* Check if the flash image file is compatible with the adapter that
  * is being flashed.
  * BE3 chips with asic-rev B0 must be flashed only with BE3R_UFI type.
+ * Skyhawk chips with asic-rev P2 must be flashed only with SH_P2_UFI type.
  */
 static bool be_check_ufi_compatibility(struct be_adapter *adapter,
 				       struct flash_file_hdr_g3 *fhdr)
@@ -4371,8 +4374,11 @@ static bool be_check_ufi_compatibility(struct be_adapter *adapter,
 	int ufi_type = be_get_ufi_type(adapter, fhdr);
 
 	switch (ufi_type) {
-	case SH_UFI:
+	case SH_P2_UFI:
 		return skyhawk_chip(adapter);
+	case SH_UFI:
+		return (skyhawk_chip(adapter) &&
+			adapter->asic_rev < ASIC_REV_P2);
 	case BE3R_UFI:
 		return BE3_chip(adapter);
 	case BE3_UFI:
-- 
2.2.0

^ permalink raw reply related

* [PATCH net-next 2/9] be2net: replace (1 << x) with BIT(x)
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1423228723-10919-1-git-send-email-sathya.perla@emulex.com>

From: Vasundhara Volam <vasundhara.volam@emulex.com>

BIT(x) is the preffered usage.
Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>

Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be.h      | 18 +++++++++---------
 drivers/net/ethernet/emulex/benet/be_cmds.h |  8 ++++----
 drivers/net/ethernet/emulex/benet/be_hw.h   |  4 ++--
 3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 3b1d59d..9869556 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -361,15 +361,15 @@ enum vf_state {
 	ASSIGNED = 1
 };
 
-#define BE_FLAGS_LINK_STATUS_INIT		1
-#define BE_FLAGS_SRIOV_ENABLED			(1 << 2)
-#define BE_FLAGS_WORKER_SCHEDULED		(1 << 3)
-#define BE_FLAGS_VLAN_PROMISC			(1 << 4)
-#define BE_FLAGS_MCAST_PROMISC			(1 << 5)
-#define BE_FLAGS_NAPI_ENABLED			(1 << 9)
-#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD		(1 << 11)
-#define BE_FLAGS_VXLAN_OFFLOADS			(1 << 12)
-#define BE_FLAGS_SETUP_DONE			(1 << 13)
+#define BE_FLAGS_LINK_STATUS_INIT		BIT(1)
+#define BE_FLAGS_SRIOV_ENABLED			BIT(2)
+#define BE_FLAGS_WORKER_SCHEDULED		BIT(3)
+#define BE_FLAGS_VLAN_PROMISC			BIT(4)
+#define BE_FLAGS_MCAST_PROMISC			BIT(5)
+#define BE_FLAGS_NAPI_ENABLED			BIT(6)
+#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD		BIT(7)
+#define BE_FLAGS_VXLAN_OFFLOADS			BIT(8)
+#define BE_FLAGS_SETUP_DONE			BIT(9)
 
 #define BE_UC_PMAC_COUNT			30
 #define BE_VF_UC_PMAC_COUNT			2
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index c2701cc..c231e45 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -44,10 +44,10 @@ struct be_mcc_wrb {
 	} payload;
 };
 
-#define CQE_FLAGS_VALID_MASK 		(1 << 31)
-#define CQE_FLAGS_ASYNC_MASK 		(1 << 30)
-#define CQE_FLAGS_COMPLETED_MASK 	(1 << 28)
-#define CQE_FLAGS_CONSUMED_MASK 	(1 << 27)
+#define CQE_FLAGS_VALID_MASK		BIT(31)
+#define CQE_FLAGS_ASYNC_MASK		BIT(30)
+#define CQE_FLAGS_COMPLETED_MASK	BIT(28)
+#define CQE_FLAGS_CONSUMED_MASK		BIT(27)
 
 /* Completion Status */
 enum mcc_base_status {
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index 8e91ae8..a8593aa 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -75,7 +75,7 @@
  * atomically without having to arbitrate for the PCI Interrupt Disable bit
  * with the OS.
  */
-#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK	(1 << 29) /* bit 29 */
+#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK	BIT(29) /* bit 29 */
 
 /********* PCI Function Capability *********/
 #define BE_FUNCTION_CAPS_RSS			0x2
@@ -224,7 +224,7 @@ struct amap_eth_hdr_wrb {
 } __packed;
 
 #define TX_HDR_WRB_COMPL		1		/* word 2 */
-#define TX_HDR_WRB_EVT			(1 << 1)	/* word 2 */
+#define TX_HDR_WRB_EVT			BIT(1)		/* word 2 */
 #define TX_HDR_WRB_NUM_SHIFT		13		/* word 2: bits 13:17 */
 #define TX_HDR_WRB_NUM_MASK		0x1F		/* word 2: bits 13:17 */
 
-- 
2.2.0

^ permalink raw reply related

* [PATCH net-next 5/9] be2net: use offset based FW flashing for Skyhawk chip
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1423228723-10919-1-git-send-email-sathya.perla@emulex.com>

From: Vasundhara Volam <vasundhara.volam@emulex.com>

While sending FW update cmds to the FW, the driver specifies the "type"
of each component that needs to be flashed. The FW then picks the offset
in the flash area at which the componnet is to be flashed. This doesn't work
when new components that the current FW doesn't recognize, need to be
flashed. Recent FWs (10.2 and above) support a scheme of FW-update wherein
the "offset" of the component in the flash area can be specified instead
of the "type". This patch uses the "offset" based FW-update mechanism and
only when it fails, it fallsback to the old "type" based update.

Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be_cmds.c | 18 +++++---
 drivers/net/ethernet/emulex/benet/be_cmds.h |  6 ++-
 drivers/net/ethernet/emulex/benet/be_main.c | 65 ++++++++++++++++++++++-------
 3 files changed, 66 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 3a10145..2f59553 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -2436,7 +2436,8 @@ err_unlock:
 }
 
 int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
-			  u32 flash_type, u32 flash_opcode, u32 buf_size)
+			  u32 flash_type, u32 flash_opcode, u32 img_offset,
+			  u32 buf_size)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_write_flashrom *req;
@@ -2457,6 +2458,9 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
 			       cmd);
 
 	req->params.op_type = cpu_to_le32(flash_type);
+	if (flash_type == OPTYPE_OFFSET_SPECIFIED)
+		req->params.offset = cpu_to_le32(img_offset);
+
 	req->params.op_code = cpu_to_le32(flash_opcode);
 	req->params.data_buf_size = cpu_to_le32(buf_size);
 
@@ -2477,10 +2481,10 @@ err_unlock:
 }
 
 int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
-			 u16 optype, int offset)
+			 u16 img_optype, u32 img_offset, u32 crc_offset)
 {
-	struct be_mcc_wrb *wrb;
 	struct be_cmd_read_flash_crc *req;
+	struct be_mcc_wrb *wrb;
 	int status;
 
 	spin_lock_bh(&adapter->mcc_lock);
@@ -2496,9 +2500,13 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
 			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
 			       wrb, NULL);
 
-	req->params.op_type = cpu_to_le32(optype);
+	req->params.op_type = cpu_to_le32(img_optype);
+	if (img_optype == OPTYPE_OFFSET_SPECIFIED)
+		req->params.offset = cpu_to_le32(img_offset + crc_offset);
+	else
+		req->params.offset = cpu_to_le32(crc_offset);
+
 	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
-	req->params.offset = cpu_to_le32(offset);
 	req->params.data_buf_size = cpu_to_le32(0x4);
 
 	status = be_mcc_notify_wait(adapter);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 774c5d1..402d64f 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1172,6 +1172,7 @@ struct be_cmd_resp_get_beacon_state {
 #define OPTYPE_REDBOOT			1
 #define OPTYPE_BIOS			2
 #define OPTYPE_PXE_BIOS			3
+#define OPTYPE_OFFSET_SPECIFIED		7
 #define OPTYPE_FCOE_BIOS		8
 #define OPTYPE_ISCSI_BACKUP		9
 #define OPTYPE_FCOE_FW_ACTIVE		10
@@ -2255,7 +2256,8 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
 				      u8 page_num, u8 *data);
 int be_cmd_query_cable_type(struct be_adapter *adapter);
 int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
-			  u32 flash_oper, u32 flash_opcode, u32 buf_size);
+			  u32 flash_oper, u32 flash_opcode, u32 img_offset,
+			  u32 buf_size);
 int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
 			    u32 data_size, u32 data_offset,
 			    const char *obj_name, u32 *data_written,
@@ -2265,7 +2267,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
 			   u32 *data_read, u32 *eof, u8 *addn_status);
 int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name);
 int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
-			  u16 optype, int offset);
+			 u16 img_optype, u32 img_offset, u32 crc_offset);
 int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
 			    struct be_dma_mem *nonemb_cmd);
 int be_cmd_fw_init(struct be_adapter *adapter);
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 9eaf8bc..2ec1d80 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -3942,7 +3942,8 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
 	int status;
 	u8 crc[4];
 
-	status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_size - 4);
+	status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
+				      img_size - 4);
 	if (status)
 		return status;
 
@@ -3958,13 +3959,13 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
 }
 
 static int be_flash(struct be_adapter *adapter, const u8 *img,
-		    struct be_dma_mem *flash_cmd, int optype, int img_size)
+		    struct be_dma_mem *flash_cmd, int optype, int img_size,
+		    u32 img_offset)
 {
+	u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
 	struct be_cmd_write_flashrom *req = flash_cmd->va;
-	u32 total_bytes, flash_op, num_bytes;
 	int status;
 
-	total_bytes = img_size;
 	while (total_bytes) {
 		num_bytes = min_t(u32, 32*1024, total_bytes);
 
@@ -3985,12 +3986,15 @@ static int be_flash(struct be_adapter *adapter, const u8 *img,
 		memcpy(req->data_buf, img, num_bytes);
 		img += num_bytes;
 		status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
-					       flash_op, num_bytes);
+					       flash_op, img_offset +
+					       bytes_sent, num_bytes);
 		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
 		    optype == OPTYPE_PHY_FW)
 			break;
 		else if (status)
 			return status;
+
+		bytes_sent += num_bytes;
 	}
 	return 0;
 }
@@ -4103,7 +4107,7 @@ static int be_flash_BEx(struct be_adapter *adapter,
 			return -1;
 
 		status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
-				  pflashcomp[i].size);
+				  pflashcomp[i].size, 0);
 		if (status) {
 			dev_err(dev, "Flashing section type 0x%x failed\n",
 				pflashcomp[i].img_type);
@@ -4170,12 +4174,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
 			    struct be_dma_mem *flash_cmd, int num_of_images)
 {
 	int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
+	bool crc_match, old_fw_img, flash_offset_support = true;
 	struct device *dev = &adapter->pdev->dev;
 	struct flash_section_info *fsec = NULL;
 	u32 img_offset, img_size, img_type;
+	u16 img_optype, flash_optype;
 	int status, i, filehdr_size;
-	bool crc_match, old_fw_img;
-	u16 img_optype;
 	const u8 *p;
 
 	filehdr_size = sizeof(struct flash_file_hdr_g3);
@@ -4185,6 +4189,7 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
 		return -EINVAL;
 	}
 
+retry_flash:
 	for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
 		img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
 		img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
@@ -4194,6 +4199,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
 
 		if (img_optype == 0xFFFF)
 			continue;
+
+		if (flash_offset_support)
+			flash_optype = OPTYPE_OFFSET_SPECIFIED;
+		else
+			flash_optype = img_optype;
+
 		/* Don't bother verifying CRC if an old FW image is being
 		 * flashed
 		 */
@@ -4202,16 +4213,26 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
 
 		status = be_check_flash_crc(adapter, fw->data, img_offset,
 					    img_size, filehdr_size +
-					    img_hdrs_size, img_optype,
+					    img_hdrs_size, flash_optype,
 					    &crc_match);
-		/* The current FW image on the card does not recognize the new
-		 * FLASH op_type. The FW download is partially complete.
-		 * Reboot the server now to enable FW image to recognize the
-		 * new FLASH op_type. To complete the remaining process,
-		 * download the same FW again after the reboot.
-		 */
 		if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
 		    base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
+			/* The current FW image on the card does not support
+			 * OFFSET based flashing. Retry using older mechanism
+			 * of OPTYPE based flashing
+			 */
+			if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
+				flash_offset_support = false;
+				goto retry_flash;
+			}
+
+			/* The current FW image on the card does not recognize
+			 * the new FLASH op_type. The FW download is partially
+			 * complete. Reboot the server now to enable FW image
+			 * to recognize the new FLASH op_type. To complete the
+			 * remaining process, download the same FW again after
+			 * the reboot.
+			 */
 			dev_err(dev, "Flash incomplete. Reset the server\n");
 			dev_err(dev, "Download FW image again after reset\n");
 			return -EAGAIN;
@@ -4229,7 +4250,19 @@ flash:
 		if (p + img_size > fw->data + fw->size)
 			return -1;
 
-		status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
+		status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
+				  img_offset);
+
+		/* The current FW image on the card does not support OFFSET
+		 * based flashing. Retry using older mechanism of OPTYPE based
+		 * flashing
+		 */
+		if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
+		    flash_optype == OPTYPE_OFFSET_SPECIFIED) {
+			flash_offset_support = false;
+			goto retry_flash;
+		}
+
 		/* For old FW images ignore ILLEGAL_FIELD error or errors on
 		 * UFI_DIR region
 		 */
-- 
2.2.0

^ permalink raw reply related

* [PATCH net-next 7/9] be2net: refactor be_set_rx_mode() and be_vid_config() for readability
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1423228723-10919-1-git-send-email-sathya.perla@emulex.com>

This patch re-factors the filter setting (uc-list, mc-list, promisc, vlan)
code in be_set_rx_mode() and be_vid_config() to make it more readable
and reduce code duplication.
This patch adds a separate field to track the state/mode of filtering,
along with moving all the filtering related fields to one place in be
be_adapter structure.

Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be.h      |  13 +-
 drivers/net/ethernet/emulex/benet/be_main.c | 211 ++++++++++++++++------------
 2 files changed, 127 insertions(+), 97 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 9869556..98716e1 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -364,8 +364,6 @@ enum vf_state {
 #define BE_FLAGS_LINK_STATUS_INIT		BIT(1)
 #define BE_FLAGS_SRIOV_ENABLED			BIT(2)
 #define BE_FLAGS_WORKER_SCHEDULED		BIT(3)
-#define BE_FLAGS_VLAN_PROMISC			BIT(4)
-#define BE_FLAGS_MCAST_PROMISC			BIT(5)
 #define BE_FLAGS_NAPI_ENABLED			BIT(6)
 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD		BIT(7)
 #define BE_FLAGS_VXLAN_OFFLOADS			BIT(8)
@@ -449,8 +447,6 @@ struct be_adapter {
 
 	struct be_drv_stats drv_stats;
 	struct be_aic_obj aic_obj[MAX_EVT_QS];
-	u16 vlans_added;
-	unsigned long vids[BITS_TO_LONGS(VLAN_N_VID)];
 	u8 vlan_prio_bmap;	/* Available Priority BitMap */
 	u16 recommended_prio;	/* Recommended Priority */
 	struct be_dma_mem rx_filter; /* Cmd DMA mem for rx-filter */
@@ -466,8 +462,15 @@ struct be_adapter {
 	/* Ethtool knobs and info */
 	char fw_ver[FW_VER_LEN];
 	char fw_on_flash[FW_VER_LEN];
+
+	/* IFACE filtering fields */
 	int if_handle;		/* Used to configure filtering */
+	u32 if_flags;		/* Interface filtering flags */
 	u32 *pmac_id;		/* MAC addr handle used by BE card */
+	u32 uc_macs;		/* Count of secondary UC MAC programmed */
+	unsigned long vids[BITS_TO_LONGS(VLAN_N_VID)];
+	u16 vlans_added;
+
 	u32 beacon_state;	/* for set_phys_id */
 
 	bool eeh_error;
@@ -475,7 +478,6 @@ struct be_adapter {
 	bool hw_error;
 
 	u32 port_num;
-	bool promiscuous;
 	u8 mc_type;
 	u32 function_mode;
 	u32 function_caps;
@@ -508,7 +510,6 @@ struct be_adapter {
 	struct phy_info phy;
 	u8 wol_cap;
 	bool wol_en;
-	u32 uc_macs;		/* Count of secondary UC MAC programmed */
 	u16 asic_rev;
 	u16 qnq_vid;
 	u32 msg_enable;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 4f7a14b..fbe7b6f 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1104,6 +1104,43 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)
 	return 0;
 }
 
+static inline bool be_in_all_promisc(struct be_adapter *adapter)
+{
+	return (adapter->if_flags & BE_IF_FLAGS_ALL_PROMISCUOUS) ==
+			BE_IF_FLAGS_ALL_PROMISCUOUS;
+}
+
+static int be_set_vlan_promisc(struct be_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+	int status;
+
+	if (adapter->if_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS)
+		return 0;
+
+	status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_VLAN_PROMISCUOUS, ON);
+	if (!status) {
+		dev_info(dev, "Enabled VLAN promiscuous mode\n");
+		adapter->if_flags |= BE_IF_FLAGS_VLAN_PROMISCUOUS;
+	} else {
+		dev_err(dev, "Failed to enable VLAN promiscuous mode\n");
+	}
+	return status;
+}
+
+static int be_clear_vlan_promisc(struct be_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+	int status;
+
+	status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_VLAN_PROMISCUOUS, OFF);
+	if (!status) {
+		dev_info(dev, "Disabling VLAN promiscuous mode\n");
+		adapter->if_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
+	}
+	return status;
+}
+
 /*
  * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE.
  * If the user configures more, place BE in vlan promiscuous mode.
@@ -1116,11 +1153,11 @@ static int be_vid_config(struct be_adapter *adapter)
 	int status = 0;
 
 	/* No need to further configure vids if in promiscuous mode */
-	if (adapter->promiscuous)
+	if (be_in_all_promisc(adapter))
 		return 0;
 
 	if (adapter->vlans_added > be_max_vlans(adapter))
-		goto set_vlan_promisc;
+		return be_set_vlan_promisc(adapter);
 
 	/* Construct VLAN Table to give to HW */
 	for_each_set_bit(i, adapter->vids, VLAN_N_VID)
@@ -1128,32 +1165,14 @@ static int be_vid_config(struct be_adapter *adapter)
 
 	status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num);
 	if (status) {
+		dev_err(dev, "Setting HW VLAN filtering failed\n");
 		/* Set to VLAN promisc mode as setting VLAN filter failed */
 		if (addl_status(status) ==
 				MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES)
-			goto set_vlan_promisc;
-		dev_err(dev, "Setting HW VLAN filtering failed\n");
-	} else if (adapter->flags & BE_FLAGS_VLAN_PROMISC) {
-		status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_VLAN_PROMISCUOUS,
-					  OFF);
-		if (!status) {
-			dev_info(dev, "Disabling VLAN Promiscuous mode\n");
-			adapter->flags &= ~BE_FLAGS_VLAN_PROMISC;
-		}
+			return be_set_vlan_promisc(adapter);
+	} else if (adapter->if_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
+		status = be_clear_vlan_promisc(adapter);
 	}
-
-	return status;
-
-set_vlan_promisc:
-	if (adapter->flags & BE_FLAGS_VLAN_PROMISC)
-		return 0;
-
-	status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_VLAN_PROMISCUOUS, ON);
-	if (!status) {
-		dev_info(dev, "Enable VLAN Promiscuous mode\n");
-		adapter->flags |= BE_FLAGS_VLAN_PROMISC;
-	} else
-		dev_err(dev, "Failed to enable VLAN Promiscuous mode\n");
 	return status;
 }
 
@@ -1195,80 +1214,99 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
 	return be_vid_config(adapter);
 }
 
-static void be_clear_promisc(struct be_adapter *adapter)
+static void be_clear_all_promisc(struct be_adapter *adapter)
 {
-	adapter->promiscuous = false;
-	adapter->flags &= ~(BE_FLAGS_VLAN_PROMISC | BE_FLAGS_MCAST_PROMISC);
-
 	be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS, OFF);
+	adapter->if_flags &= ~BE_IF_FLAGS_ALL_PROMISCUOUS;
 }
 
-static void be_set_rx_mode(struct net_device *netdev)
+static void be_set_all_promisc(struct be_adapter *adapter)
+{
+	be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS, ON);
+	adapter->if_flags |= BE_IF_FLAGS_ALL_PROMISCUOUS;
+}
+
+static void be_set_mc_promisc(struct be_adapter *adapter)
 {
-	struct be_adapter *adapter = netdev_priv(netdev);
 	int status;
 
-	if (netdev->flags & IFF_PROMISC) {
-		be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS, ON);
-		adapter->promiscuous = true;
-		goto done;
-	}
+	if (adapter->if_flags & BE_IF_FLAGS_MCAST_PROMISCUOUS)
+		return;
 
-	/* BE was previously in promiscuous mode; disable it */
-	if (adapter->promiscuous) {
-		be_clear_promisc(adapter);
-		if (adapter->vlans_added)
-			be_vid_config(adapter);
+	status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MCAST_PROMISCUOUS, ON);
+	if (!status)
+		adapter->if_flags |= BE_IF_FLAGS_MCAST_PROMISCUOUS;
+}
+
+static void be_set_mc_list(struct be_adapter *adapter)
+{
+	int status;
+
+	status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MULTICAST, ON);
+	if (!status)
+		adapter->if_flags &= ~BE_IF_FLAGS_MCAST_PROMISCUOUS;
+	else
+		be_set_mc_promisc(adapter);
+}
+
+static void be_set_uc_list(struct be_adapter *adapter)
+{
+	struct netdev_hw_addr *ha;
+	int i = 1; /* First slot is claimed by the Primary MAC */
+
+	for (; adapter->uc_macs > 0; adapter->uc_macs--, i++)
+		be_cmd_pmac_del(adapter, adapter->if_handle,
+				adapter->pmac_id[i], 0);
+
+	if (netdev_uc_count(adapter->netdev) > be_max_uc(adapter)) {
+		be_set_all_promisc(adapter);
+		return;
 	}
 
-	/* Enable multicast promisc if num configured exceeds what we support */
-	if (netdev->flags & IFF_ALLMULTI ||
-	    netdev_mc_count(netdev) > be_max_mc(adapter))
-		goto set_mcast_promisc;
+	netdev_for_each_uc_addr(ha, adapter->netdev) {
+		adapter->uc_macs++; /* First slot is for Primary MAC */
+		be_cmd_pmac_add(adapter, (u8 *)ha->addr, adapter->if_handle,
+				&adapter->pmac_id[adapter->uc_macs], 0);
+	}
+}
 
-	if (netdev_uc_count(netdev) != adapter->uc_macs) {
-		struct netdev_hw_addr *ha;
-		int i = 1; /* First slot is claimed by the Primary MAC */
+static void be_clear_uc_list(struct be_adapter *adapter)
+{
+	int i;
 
-		for (; adapter->uc_macs > 0; adapter->uc_macs--, i++) {
-			be_cmd_pmac_del(adapter, adapter->if_handle,
-					adapter->pmac_id[i], 0);
-		}
+	for (i = 1; i < (adapter->uc_macs + 1); i++)
+		be_cmd_pmac_del(adapter, adapter->if_handle,
+				adapter->pmac_id[i], 0);
+	adapter->uc_macs = 0;
+}
 
-		if (netdev_uc_count(netdev) > be_max_uc(adapter)) {
-			be_cmd_rx_filter(adapter, BE_IF_FLAGS_ALL_PROMISCUOUS,
-					 ON);
-			adapter->promiscuous = true;
-			goto done;
-		}
+static void be_set_rx_mode(struct net_device *netdev)
+{
+	struct be_adapter *adapter = netdev_priv(netdev);
 
-		netdev_for_each_uc_addr(ha, adapter->netdev) {
-			adapter->uc_macs++; /* First slot is for Primary MAC */
-			be_cmd_pmac_add(adapter, (u8 *)ha->addr,
-					adapter->if_handle,
-					&adapter->pmac_id[adapter->uc_macs], 0);
-		}
+	if (netdev->flags & IFF_PROMISC) {
+		be_set_all_promisc(adapter);
+		return;
 	}
 
-	status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MULTICAST, ON);
-	if (!status) {
-		if (adapter->flags & BE_FLAGS_MCAST_PROMISC)
-			adapter->flags &= ~BE_FLAGS_MCAST_PROMISC;
-		goto done;
+	/* Interface was previously in promiscuous mode; disable it */
+	if (be_in_all_promisc(adapter)) {
+		be_clear_all_promisc(adapter);
+		if (adapter->vlans_added)
+			be_vid_config(adapter);
 	}
 
-set_mcast_promisc:
-	if (adapter->flags & BE_FLAGS_MCAST_PROMISC)
+	/* Enable multicast promisc if num configured exceeds what we support */
+	if (netdev->flags & IFF_ALLMULTI ||
+	    netdev_mc_count(netdev) > be_max_mc(adapter)) {
+		be_set_mc_promisc(adapter);
 		return;
+	}
 
-	/* Set to MCAST promisc mode if setting MULTICAST address fails
-	 * or if num configured exceeds what we support
-	 */
-	status = be_cmd_rx_filter(adapter, BE_IF_FLAGS_MCAST_PROMISCUOUS, ON);
-	if (!status)
-		adapter->flags |= BE_FLAGS_MCAST_PROMISC;
-done:
-	return;
+	if (netdev_uc_count(netdev) != adapter->uc_macs)
+		be_set_uc_list(adapter);
+
+	be_set_mc_list(adapter);
 }
 
 static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
@@ -2947,11 +2985,7 @@ static int be_close(struct net_device *netdev)
 	be_tx_compl_clean(adapter);
 
 	be_rx_qs_destroy(adapter);
-
-	for (i = 1; i < (adapter->uc_macs + 1); i++)
-		be_cmd_pmac_del(adapter, adapter->if_handle,
-				adapter->pmac_id[i], 0);
-	adapter->uc_macs = 0;
+	be_clear_uc_list(adapter);
 
 	for_all_evt_queues(adapter, eqo, i) {
 		if (msix_enabled(adapter))
@@ -3235,14 +3269,9 @@ static void be_cancel_worker(struct be_adapter *adapter)
 
 static void be_mac_clear(struct be_adapter *adapter)
 {
-	int i;
-
 	if (adapter->pmac_id) {
-		for (i = 0; i < (adapter->uc_macs + 1); i++)
-			be_cmd_pmac_del(adapter, adapter->if_handle,
-					adapter->pmac_id[i], 0);
-		adapter->uc_macs = 0;
-
+		be_cmd_pmac_del(adapter, adapter->if_handle,
+				adapter->pmac_id[0], 0);
 		kfree(adapter->pmac_id);
 		adapter->pmac_id = NULL;
 	}
@@ -3526,7 +3555,7 @@ static void be_setup_init(struct be_adapter *adapter)
 	adapter->phy.link_speed = -1;
 	adapter->if_handle = -1;
 	adapter->be3_native = false;
-	adapter->promiscuous = false;
+	adapter->if_flags = 0;
 	if (be_physfn(adapter))
 		adapter->cmd_privileges = MAX_PRIVILEGES;
 	else
-- 
2.2.0

^ permalink raw reply related

* [PATCH net-next 9/9] be2net: avoid unncessary swapping of fields in eth_tx_wrb
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1423228723-10919-1-git-send-email-sathya.perla@emulex.com>

The 32-bit fields of a tx-wrb are little endian. The driver is currently
using be_dws_le_to_cpu() routine to swap (cpu to le) all the fields of
a tx-wrb. So, the rsvd field is also unnecessarily swapped.

This patch fixes this by individually swapping the required fields.
Also, the type of the fields in eth_tx_wrb{} is now changed to __le32
from u32 to avoid sparse warnings.

Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be_hw.h   | 10 ++++-----
 drivers/net/ethernet/emulex/benet/be_main.c | 35 ++++++++++++++++++-----------
 2 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index a8593aa..4884088 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -193,10 +193,10 @@ struct be_eq_entry {
 /* TX Queue Descriptor */
 #define ETH_WRB_FRAG_LEN_MASK		0xFFFF
 struct be_eth_wrb {
-	u32 frag_pa_hi;		/* dword 0 */
-	u32 frag_pa_lo;		/* dword 1 */
-	u32 rsvd0;		/* dword 2 */
-	u32 frag_len;		/* dword 3: bits 0 - 15 */
+	__le32 frag_pa_hi;		/* dword 0 */
+	__le32 frag_pa_lo;		/* dword 1 */
+	u32 rsvd0;			/* dword 2 */
+	__le32 frag_len;		/* dword 3: bits 0 - 15 */
 } __packed;
 
 /* Pseudo amap definition for eth_hdr_wrb in which each bit of the
@@ -229,7 +229,7 @@ struct amap_eth_hdr_wrb {
 #define TX_HDR_WRB_NUM_MASK		0x1F		/* word 2: bits 13:17 */
 
 struct be_eth_hdr_wrb {
-	u32 dw[4];
+	__le32 dw[4];
 };
 
 /********* Tx Compl Status Encoding *********/
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 5936b24..4abe2ab 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -682,9 +682,20 @@ static u32 skb_wrb_cnt(struct sk_buff *skb)
 
 static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len)
 {
-	wrb->frag_pa_hi = upper_32_bits(addr);
-	wrb->frag_pa_lo = addr & 0xFFFFFFFF;
-	wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK;
+	wrb->frag_pa_hi = cpu_to_le32(upper_32_bits(addr));
+	wrb->frag_pa_lo = cpu_to_le32(lower_32_bits(addr));
+	wrb->frag_len = cpu_to_le32(len & ETH_WRB_FRAG_LEN_MASK);
+	wrb->rsvd0 = 0;
+}
+
+/* A dummy wrb is just all zeros. Using a separate routine for dummy-wrb
+ * to avoid the swap and shift/mask operations in wrb_fill().
+ */
+static inline void wrb_fill_dummy(struct be_eth_wrb *wrb)
+{
+	wrb->frag_pa_hi = 0;
+	wrb->frag_pa_lo = 0;
+	wrb->frag_len = 0;
 	wrb->rsvd0 = 0;
 }
 
@@ -765,16 +776,16 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
 			  bool unmap_single)
 {
 	dma_addr_t dma;
+	u32 frag_len = le32_to_cpu(wrb->frag_len);
 
-	be_dws_le_to_cpu(wrb, sizeof(*wrb));
 
-	dma = (u64)wrb->frag_pa_hi << 32 | (u64)wrb->frag_pa_lo;
-	if (wrb->frag_len) {
+	dma = (u64)le32_to_cpu(wrb->frag_pa_hi) << 32 |
+		(u64)le32_to_cpu(wrb->frag_pa_lo);
+	if (frag_len) {
 		if (unmap_single)
-			dma_unmap_single(dev, dma, wrb->frag_len,
-					 DMA_TO_DEVICE);
+			dma_unmap_single(dev, dma, frag_len, DMA_TO_DEVICE);
 		else
-			dma_unmap_page(dev, dma, wrb->frag_len, DMA_TO_DEVICE);
+			dma_unmap_page(dev, dma, frag_len, DMA_TO_DEVICE);
 	}
 }
 
@@ -806,7 +817,6 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
 		map_single = true;
 		wrb = queue_head_node(txq);
 		wrb_fill(wrb, busaddr, len);
-		be_dws_cpu_to_le(wrb, sizeof(*wrb));
 		queue_head_inc(txq);
 		copied += len;
 	}
@@ -820,7 +830,6 @@ static u32 be_xmit_enqueue(struct be_adapter *adapter, struct be_tx_obj *txo,
 			goto dma_err;
 		wrb = queue_head_node(txq);
 		wrb_fill(wrb, busaddr, skb_frag_size(frag));
-		be_dws_cpu_to_le(wrb, sizeof(*wrb));
 		queue_head_inc(txq);
 		copied += skb_frag_size(frag);
 	}
@@ -846,7 +855,7 @@ dma_err:
 		wrb = queue_head_node(txq);
 		unmap_tx_frag(dev, wrb, map_single);
 		map_single = false;
-		copied -= wrb->frag_len;
+		copied -= le32_to_cpu(wrb->frag_len);
 		adapter->drv_stats.dma_map_errors++;
 		queue_head_inc(txq);
 	}
@@ -1037,7 +1046,7 @@ static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo)
 
 	/* compose a dummy wrb if there are odd set of wrbs to notify */
 	if (!lancer_chip(adapter) && (txo->pend_wrb_cnt & 1)) {
-		wrb_fill(queue_head_node(txq), 0, 0);
+		wrb_fill_dummy(queue_head_node(txq));
 		queue_head_inc(txq);
 		atomic_inc(&txq->used);
 		txo->pend_wrb_cnt++;
-- 
2.2.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox