Netdev List
 help / color / mirror / Atom feed
* RE: AP firmware for TI wl1251 wifi chip (wl1251-fw-ap.bin)
From: Machani, Yaniv @ 2016-04-11 11:49 UTC (permalink / raw)
  To: Pali Rohár, Pavel Machek
  Cc: Chalmers, Kevin, Kalle Valo, Davis, Andrew, Mishol, Guy,
	Arik Nemtsov, Gery Kahn, Felipe Balbi, David Woodhouse,
	Aaro Koskinen, Ben Hutchings, David Gnedt, Ivaylo Dimitrov,
	Sebastian Reichel, Tony Lindgren, Menon, Nishanth,
	linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <20160411114118.GT8413@pali>

On Mon, Apr 11, 2016 at 14:41:18, Pali Rohár wrote:
> Mishol, Guy; Arik Nemtsov; Gery Kahn; Felipe Balbi; David Woodhouse; 
> Aaro Koskinen; Ben Hutchings; David Gnedt; Ivaylo Dimitrov; Sebastian 
> Reichel; Tony Lindgren; Menon, Nishanth; 
> linux-wireless@vger.kernel.org; netdev@vger.kernel.org; 
> linux-kernel@vger.kernel.org
> Subject: Re: AP firmware for TI wl1251 wifi chip (wl1251-fw-ap.bin)
> 
> On Sunday 10 April 2016 13:51:41 Pavel Machek wrote:
> > Is it "hardware can't do AP", "firmware can't do AP" or "current 
> > drivers do not support AP"?
> 

As both Firmware and HW are not in a stage where they can be modified, there is no support for AP mode in both.

Regards,
Yaniv Machani



^ permalink raw reply

* Re: AP firmware for TI wl1251 wifi chip (wl1251-fw-ap.bin)
From: Pali Rohár @ 2016-04-11 11:41 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Machani, Yaniv, Chalmers, Kevin, Kalle Valo, Davis, Andrew,
	Mishol, Guy, Arik Nemtsov, Gery Kahn, Felipe Balbi,
	David Woodhouse, Aaro Koskinen, Ben Hutchings, David Gnedt,
	Ivaylo Dimitrov, Sebastian Reichel, Tony Lindgren,
	Menon, Nishanth, linux-wireless@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20160410115141.GD30188@xo-6d-61-c0.localdomain>

On Sunday 10 April 2016 13:51:41 Pavel Machek wrote:
> Is it "hardware can't do AP", "firmware can't do AP" or "current drivers 
> do not support AP"?

We know that current linux TI wl1251.ko driver does not support AP. And
I'm still do not know if "hardware can do AP" or not. Also I'm not sure...
maybe current firmware can be "forced" for implementing AP mode.

David Gnedt implemented packet injection for wl1251.ko via JOIN firmware
command. And he wrote me that aircrack utils contains one application
which implementing full AP station in userspace just via packet
injection radiotap (which is supported by wl1251).

So maybe using other firmware (filter) commands together with current
packet injection implementation could be possible to create AP mode
(usable for standard hostapd daemon)? Just thinking...

Anyway, other TI wilink devices have different firmware for AP mode...

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply

* Re: [PATCH v1] net: cdc_ncm: update datagram size after changing mtu
From: Robert Dobrowolski @ 2016-04-11 12:00 UTC (permalink / raw)
  To: Bjørn Mork
  Cc: Robert Dobrowolski, linux-usb, rafal.f.redzimski, stable, oliver,
	netdev, linux-kernel
In-Reply-To: <87h9fex0ql.fsf@nemi.mork.no>

> Robert Dobrowolski <robert.dobrowolski@linux.intel.com> writes:
>
>> From: Rafal Redzimski <rafal.f.redzimski@intel.com>
>>
>> Current implementation updates the mtu size and notify cdc_ncm
>> device using USB_CDC_SET_MAX_DATAGRAM_SIZE request about datagram
>> size change instead of changing rx_urb_size.
>>
>> Whenever mtu is being changed, datagram size should also be
>> updated.
>
> Definitely!  Thanks for this.  But looking at the code I believe you
> need to fix the calculation of maxmtu too.  It is currently:
>
>   int maxmtu = ctx->max_datagram_size - cdc_ncm_eth_hlen(dev);
>
> And cdc_ncm_set_dgram_size() updates ctx->max_datagram_size with the new
> mtu, meaning that you can only reduce the mtu.  We should probably use
> cdc_ncm_max_dgram_size() instead here.
>
> And cdc_ncm_set_dgram_size() takes the datagram size with header as
> input (ref the above maxmtu calucalution), so it probably needs to
> called as
>
>   cdc_ncm_set_dgram_size(dev, new_mtu + cdc_ncm_eth_hlen(dev));
>
> to get it right.  I think.  None of this is tested on an actual device
> yet...  Care to test if I'm right, and do a v2 if necessry?
>
>> Cc: <stable@vger.kernel.org>
>
> This should be dropped for net.  Ask David to queue it for stable
> instead.  I usually do that by using a subject prefix like
>
>  [PATCH net,stable v1] ...
>
>
>
>
> Bjørn
>

ok, thanks for feedback I will send v2 patch

^ permalink raw reply

* veth produces martians after pushing veth into ns
From: Shaun Crampton @ 2016-04-11 10:46 UTC (permalink / raw)
  To: netdev@vger.kernel.org

Hi,

I'd appreciate if you could CC me on any responses.

I'm trying to push a veth into a namespace and then give it an IP address
and a default route.  The procedure that I have works fine at low scale,
but once I have ~100 veths on a moderately-loaded system, I start seeing
1s delays before processes in a namespace with a new veth can send
traffic.  The delays correspond with martian packet logs in the kernel log
so it's like the IP or route update hasn't taken effect yet and it's
trying to send packets with the wrong source.

My procedure looks like this:

# Outside the container, create a veth.
ip link add <vethname> type veth
ip link set <vethname> up
sleep 1  # This bypasses the (probably unrelated) 1s link-status timer in
the kernel.

# Push veth into container.
ip link set <vethname> netns <nsname>

# Inside the container, rename the veth, add IP addr and default route.
ip netns exec <nsname> ip link set <vethname> eth0
ip netns exec <nsname> ip link set <vethname> up
ip netns exec <nsname> ip addr add <ipaddr>
ip netns exec <nsname> ip route replace <hostaddr> dev eth0
ip netns exec <nsname> ip route replace default via <hostaddr> dev eth0

# Actually start the target program in the namespace.
ip netns exec <nsname> <executable to run>





Process tries to send UDP packets to a remote IP, first packet is dropped
with a martian warning on the host.  The source address for the martian is
the host's IP address so it appears that there's a window where the
namespace thinks it has the wrong IP, even though the ip route commands
completed before I exec the test program in the namespace.  After
(exactly) 1s, packets start flowing with correct source address.

Given that this only happens under load, I suspect that there's some async
processing going on that hasn't finished when the "ip route" commands
return.   Or, perhaps the veth has a routing or ARP cache that I need to
clear when I push it into the namespace.

I tried adding these calls after the "ip route replace"s:

ip netns exec <nsname> ip addr
ip netns exec <nsname> ip route


They both show the expected new IP/routes.  Adding those commands seems to
improve the success rate  (presumably because it effectively adds a small
sleep before the exec).

Can anyone suggest a good way to make sure that my script blocks until the
IPs and routes really are in place and active (or any caches I should be
clearing to avoid this issue)?

I'm running this kernel:

Linux smc-host-0015 3.19.0-28-generic #30-Ubuntu SMP Mon Aug 31 15:52:51
UTC 2015 x86_64 x86_64 x86_64 GNU/Linux


Thanks,

-Shaun

^ permalink raw reply

* Re: [RFC v5 0/5] Add virtio transport for AF_VSOCK
From: Stefan Hajnoczi @ 2016-04-11 10:45 UTC (permalink / raw)
  To: Ian Campbell
  Cc: marius vlad, Stefan Hajnoczi, kvm, Michael S. Tsirkin, netdev,
	virtualization, Claudio Imbrenda, Matt Benjamin, Greg Kurz,
	Christoffer Dall
In-Reply-To: <1460129705.1749.25.camel@docker.com>


[-- Attachment #1.1: Type: text/plain, Size: 2801 bytes --]

On Fri, Apr 08, 2016 at 04:35:05PM +0100, Ian Campbell wrote:
> On Fri, 2016-04-01 at 15:23 +0100, Stefan Hajnoczi wrote:
> > This series is based on Michael Tsirkin's vhost branch (v4.5-rc6).
> > 
> > I'm about to process Claudio Imbrenda's locking fixes for virtio-vsock but
> > first I want to share the latest version of the code.  Several people are
> > playing with vsock now so sharing the latest code should avoid duplicate work.
> 
> Thanks for this, I've been using it in my project and it mostly seems
> fine.
> 
> One wrinkle I came across, which I'm not sure if it is by design or a
> problem is that I can see this sequence coming from the guest (with
> other activity in between):
> 
>     1) OP_SHUTDOWN w/ flags == SHUTDOWN_RX
>     2) OP_SHUTDOWN w/ flags == SHUTDOWN_TX
>     3) OP_SHUTDOWN w/ flags == SHUTDOWN_TX|SHUTDOWN_RX
> 
> I orignally had my backend close things down at #2, however this meant
> that when #3 arrived it was for a non-existent socket (or, worse, an
> active one if the ports got reused). I checked v5 of the spec
> proposal[0] which says:
>     If these bits are set and there are no more virtqueue buffers
>     pending the socket is disconnected.
> 
> but I'm not entirely sure if this behaviour contradicts this or not
> (the bits have both been set at #2, but not at the same time).
> 
> BTW, how does one tell if there are no more virtqueue buffers pending
> or not while processing the op?

#2 is odd.  The shutdown bits are sticky so they cannot be cleared once
set.  I would have expected just #1 and #3.  The behavior you observe
look like a bug.

The spec text does not convey the meaning of OP_SHUTDOWN well.
OP_SHUTDOWN SHUTDOWN_TX|SHUTDOWN_RX means no further rx/tx is possible
for this connection.  "there are no more virtqueue buffers pending the
socket" really means that this isn't an immediate close from the
perspective of the application.  If the application still has unread rx
buffers then the socket stays readable until the rx data has been fully
read.

> Another thing I noticed, which is really more to do with the generic
> AF_VSOCK bits than anything to do with your patches is that there is no
> limitations on which vsock ports a non-privileged user can bind to and
> relatedly that there is no netns support so e.g. users in unproivileged
> containers can bind to any vsock port and talk to the host, which might
> be undesirable. For my use for now I just went with the big hammer
> approach of denying access from anything other than init_net
> namespace[1] while I consider what the right answer is.

From the vhost point of view each netns should have its own AF_VSOCK
namespace.  This way two containers could act as "the host" (CID 2) for
their respective guests.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* [PATCH] net: fjes: Use resource_size
From: Vaishali Thakkar @ 2016-04-11 10:28 UTC (permalink / raw)
  To: izumi.taku; +Cc: davem, netdev, linux-kernel, Vaishali Thakkar

Use the function resource_size instead of explicit computation.

Problem found using Coccinelle.

Signed-off-by: Vaishali Thakkar <vaishali.thakkar@oracle.com>
---
 drivers/net/fjes/fjes_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 0ddb54f..061b4af 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -1129,7 +1129,7 @@ static int fjes_probe(struct platform_device *plat_dev)
 
 	res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
 	hw->hw_res.start = res->start;
-	hw->hw_res.size = res->end - res->start + 1;
+	hw->hw_res.size = resource_size(res);
 	hw->hw_res.irq = platform_get_irq(plat_dev, 0);
 	err = fjes_hw_init(&adapter->hw);
 	if (err)
-- 
2.1.4

^ permalink raw reply related

* Re: Inconsistent use of size argument in kzalloc and memcpy in 'drivers/net/ethernet/toshiba/ps3_gelic_wireless.c'
From: Dan Carpenter @ 2016-04-11 10:26 UTC (permalink / raw)
  To: Christophe JAILLET; +Cc: geoff, netdev, linuxppc-dev, kernel-janitors
In-Reply-To: <570B75A4.5070904@wanadoo.fr>

On Mon, Apr 11, 2016 at 12:00:04PM +0200, Christophe JAILLET wrote:
> Hi,
> 
> while looking at potential clean-up, I ended on the following code
> which looks spurious to me.
> 
> We allocate 'be16_to_cpu(scan_info->size)' bytes, but then copy
> 'scan_info->size'.
> This is not consistent.
> 

Good catch.  be16_to_cpu(scan_info->size) is correct.  It's surprising
that this bug wasn't caught in testing...

regards,
dan carpenter


^ permalink raw reply

* Re: Inconsistent use of size argument in kzalloc and memcpy in 'drivers/net/ethernet/toshiba/ps3_gelic_wireless.c'
From: walter harms @ 2016-04-11 10:04 UTC (permalink / raw)
  To: Christophe JAILLET; +Cc: geoff, netdev, linuxppc-dev, kernel-janitors
In-Reply-To: <570B75A4.5070904@wanadoo.fr>

this is a case for kmemdup().

target->hwinfo=kmemdup(scan_info,be16_to_cpu(scan_info->size), GFP_KERNEL);


re,
 wh


Am 11.04.2016 12:00, schrieb Christophe JAILLET:
> Hi,
> 
> while looking at potential clean-up, I ended on the following code which
> looks spurious to me.
> 
> We allocate 'be16_to_cpu(scan_info->size)' bytes, but then copy
> 'scan_info->size'.
> This is not consistent.
> 
> 
> I don't know which one is the correct one.
> 
> 
> CJ
> 
> --- drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
> +++ /tmp/cocci-output-24201-0dddbd-ps3_gelic_wireless.c
> @@ -1616,13 +1616,10 @@ static void gelic_wl_scan_complete_event
>          target->valid = 1;
>          target->eurus_index = i;
>          kfree(target->hwinfo);
> -        target->hwinfo = kzalloc(be16_to_cpu(scan_info->size),
> -                     GFP_KERNEL);
>          if (!target->hwinfo)
>              continue;
> 
>          /* copy hw scan info */
> -        memcpy(target->hwinfo, scan_info, scan_info->size);
>          target->essid_len = strnlen(scan_info->essid,
>                          sizeof(scan_info->essid));
>          target->rate_len = 0;
> 
> -- 
> To unsubscribe from this list: send the line "unsubscribe
> kernel-janitors" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Inconsistent use of size argument in kzalloc and memcpy in 'drivers/net/ethernet/toshiba/ps3_gelic_wireless.c'
From: Christophe JAILLET @ 2016-04-11 10:00 UTC (permalink / raw)
  To: geoff, netdev, linuxppc-dev, kernel-janitors

Hi,

while looking at potential clean-up, I ended on the following code which 
looks spurious to me.

We allocate 'be16_to_cpu(scan_info->size)' bytes, but then copy 
'scan_info->size'.
This is not consistent.


I don't know which one is the correct one.


CJ

--- drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ /tmp/cocci-output-24201-0dddbd-ps3_gelic_wireless.c
@@ -1616,13 +1616,10 @@ static void gelic_wl_scan_complete_event
          target->valid = 1;
          target->eurus_index = i;
          kfree(target->hwinfo);
-        target->hwinfo = kzalloc(be16_to_cpu(scan_info->size),
-                     GFP_KERNEL);
          if (!target->hwinfo)
              continue;

          /* copy hw scan info */
-        memcpy(target->hwinfo, scan_info, scan_info->size);
          target->essid_len = strnlen(scan_info->essid,
                          sizeof(scan_info->essid));
          target->rate_len = 0;


^ permalink raw reply

* Re: [PATCH net] packet: fix heap info leak in PACKET_DIAG_MCLIST sock_diag interface
From: Pavel Emelyanov @ 2016-04-11  8:58 UTC (permalink / raw)
  To: Mathias Krause, David S. Miller; +Cc: netdev, Eric W. Biederman
In-Reply-To: <1460285548-832-1-git-send-email-minipli@googlemail.com>

On 04/10/2016 01:52 PM, Mathias Krause wrote:
> Because we miss to wipe the remainder of i->addr[] in packet_mc_add(),
> pdiag_put_mclist() leaks uninitialized heap bytes via the
> PACKET_DIAG_MCLIST netlink attribute.
> 
> Fix this by explicitly memset(0)ing the remaining bytes in i->addr[].
> 
> Fixes: eea68e2f1a00 ("packet: Report socket mclist info via diag module")
> Signed-off-by: Mathias Krause <minipli@googlemail.com>
> Cc: Eric W. Biederman <ebiederm@xmission.com>
> Cc: Pavel Emelyanov <xemul@parallels.com>

Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>

^ permalink raw reply

* Re: [Lsf-pc] [LSF/MM TOPIC] Generic page-pool recycle facility?
From: Mel Gorman @ 2016-04-11  8:58 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: lsf, linux-mm, netdev@vger.kernel.org, Brenden Blanco,
	James Bottomley, Tom Herbert, lsf-pc, Alexei Starovoitov
In-Reply-To: <20160407161715.52635cac@redhat.com>

On Thu, Apr 07, 2016 at 04:17:15PM +0200, Jesper Dangaard Brouer wrote:
> (Topic proposal for MM-summit)
> 
> Network Interface Cards (NIC) drivers, and increasing speeds stress
> the page-allocator (and DMA APIs).  A number of driver specific
> open-coded approaches exists that work-around these bottlenecks in the
> page allocator and DMA APIs. E.g. open-coded recycle mechanisms, and
> allocating larger pages and handing-out page "fragments".
> 
> I'm proposing a generic page-pool recycle facility, that can cover the
> driver use-cases, increase performance and open up for zero-copy RX.
> 

Which bottleneck dominates -- the page allocator or the DMA API when
setting up coherent pages?

I'm wary of another page allocator API being introduced if it's for
performance reasons. In response to this thread, I spent two days on
a series that boosts performance of the allocator in the fast paths by
11-18% to illustrate that there was low-hanging fruit for optimising. If
the one-LRU-per-node series was applied on top, there would be a further
boost to performance on the allocation side. It could be further boosted
if debugging checks and statistic updates were conditionally disabled by
the caller.

The main reason another allocator concerns me is that those pages
are effectively pinned and cannot be reclaimed by the VM in low memory
situations. It ends up needing its own API for tuning the size and hoping
all the drivers get it right without causing OOM situations. It becomes
a slippery slope of introducing shrinkers, locking and complexity. Then
callers start getting concerned about NUMA locality and having to deal
with multiple lists to maintain performance. Ultimately, it ends up being
as slow as the page allocator and back to square 1 except now with more code.

If it's the DMA API that dominates then something may be required but it
should rely on the existing page allocator to alloc/free from. It would
also need something like drain_all_pages to force free everything in there
in low memory situations. Remember that multiple instances private to
drivers or tasks will require shrinker implementations and the complexity
may get unwieldly.

-- 
Mel Gorman
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH 0/2] drivers: net: cpsw: fix ale calls and drop host_port field from cpsw_priv
From: Mugunthan V N @ 2016-04-11  8:36 UTC (permalink / raw)
  To: Grygorii Strashko, David S. Miller, netdev
  Cc: Sekhar Nori, linux-kernel, linux-omap
In-Reply-To: <1460031404-28594-1-git-send-email-grygorii.strashko@ti.com>

On Thursday 07 April 2016 05:46 PM, Grygorii Strashko wrote:
> This clean up series intended to:
>  - fix port_mask parameters in ale calls and drop unnecessary shifts
>  - drop host_port field from struct cpsw_priv
> 
> Nothing critical. Tested on am437x-idk-evm in dual mac and switch modes.
> 
> Grygorii Strashko (2):
>   drivers: net: cpsw: fix port_mask parameters in ale calls
>   drivers: net: cpsw: drop host_port field from struct cpsw_priv
> 
>  drivers/net/ethernet/ti/cpsw.c | 52 +++++++++++++++++-------------------------
>  1 file changed, 21 insertions(+), 31 deletions(-)
> 

Reviewed-by: Mugunthan V N <mugunthanvnm@ti.com>

Regards
Mugunthan V N

^ permalink raw reply

* Re: [PATCH] can: mcp251x: Replace create_freezable_workqueue with alloc_workqueue
From: Marc Kleine-Budde @ 2016-04-11  8:35 UTC (permalink / raw)
  To: Amitoj Kaur Chawla, wg, linux-can, netdev, linux-kernel; +Cc: tj
In-Reply-To: <20160408153210.GA15068@amitoj-Inspiron-3542>


[-- Attachment #1.1: Type: text/plain, Size: 983 bytes --]

On 04/08/2016 05:32 PM, Amitoj Kaur Chawla wrote:
> Replace scheduled to be removed create_freezable_workqueue with
> alloc_workqueue.
> 
> priv->wq should be explicitly set as freezable to ensure it is frozen
> in the suspend sequence and work items are drained so that no new work
> item starts execution until thawed. Thus, use of WQ_FREEZABLE flag
> here is required.
> 
> WQ_MEM_RECLAIM flag has been set here to ensure forward progress
> regardless of memory pressure.
> 
> The order of execution is not important so set @max_active as 0.
> 
> Signed-off-by: Amitoj Kaur Chawla <amitoj1606@gmail.com>
> Acked-by: Tejun Heo <tj@kernel.org>

Applied to can-next/master.

Tnx,
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: 455 bytes --]

^ permalink raw reply

* [PATCH net-next 11/11] fjes: Update fjes driver version : 1.1
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 22bd175..bfd58cc 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -30,7 +30,7 @@
 #include "fjes_ioctl.h"
 
 #define MAJ 1
-#define MIN 0
+#define MIN 1
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
 #define DRV_NAME	"fjes"
 char fjes_driver_name[] = DRV_NAME;
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 10/11] fjes: Introduce spinlock for rx_status
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch introduces spinlock of rx_status for
proper excusive control.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_hw.c   | 22 ++++++++++++++++-
 drivers/net/fjes/fjes_hw.h   |  2 ++
 drivers/net/fjes/fjes_main.c | 57 +++++++++++++++++++++++++++++++++++++-------
 3 files changed, 72 insertions(+), 9 deletions(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 4861e36..79599d0 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -216,6 +216,7 @@ static int fjes_hw_setup(struct fjes_hw *hw)
 	u8 mac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	struct fjes_device_command_param param;
 	struct ep_share_mem_info *buf_pair;
+	unsigned long flags;
 	size_t mem_size;
 	int result;
 	int epidx;
@@ -264,10 +265,12 @@ static int fjes_hw_setup(struct fjes_hw *hw)
 			if (result)
 				return result;
 
+			spin_lock_irqsave(&hw->rx_status_lock, flags);
 			fjes_hw_setup_epbuf(&buf_pair->tx, mac,
 					    fjes_support_mtu[0]);
 			fjes_hw_setup_epbuf(&buf_pair->rx, mac,
 					    fjes_support_mtu[0]);
+			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 		}
 	}
 
@@ -329,6 +332,7 @@ int fjes_hw_init(struct fjes_hw *hw)
 	INIT_WORK(&hw->epstop_task, fjes_hw_epstop_task);
 
 	mutex_init(&hw->hw_info.lock);
+	spin_lock_init(&hw->rx_status_lock);
 
 	hw->max_epid = fjes_hw_get_max_epid(hw);
 	hw->my_epid = fjes_hw_get_my_epid(hw);
@@ -736,6 +740,7 @@ fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
 void fjes_hw_raise_epstop(struct fjes_hw *hw)
 {
 	enum ep_partner_status status;
+	unsigned long flags;
 	int epidx;
 
 	for (epidx = 0; epidx < hw->max_epid; epidx++) {
@@ -756,8 +761,10 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw)
 		set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
 		set_bit(epidx, &hw->txrx_stop_req_bit);
 
+		spin_lock_irqsave(&hw->rx_status_lock, flags);
 		hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
 				FJES_RX_STOP_REQ_REQUEST;
+		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 	}
 }
 
@@ -939,6 +946,7 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 
 	struct fjes_adapter *adapter;
 	struct net_device *netdev;
+	unsigned long flags;
 
 	ulong unshare_bit = 0;
 	ulong share_bit = 0;
@@ -1031,8 +1039,10 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 			continue;
 
 		if (test_bit(epidx, &share_bit)) {
+			spin_lock_irqsave(&hw->rx_status_lock, flags);
 			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
 					    netdev->dev_addr, netdev->mtu);
+			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 
 			mutex_lock(&hw->hw_info.lock);
 
@@ -1082,10 +1092,14 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 			hw->ep_shm_info[epidx].ep_stats
 					      .command_unregister_buffer_executed += 1;
 
-			if (ret == 0)
+			if (ret == 0) {
+				spin_lock_irqsave(&hw->rx_status_lock, flags);
 				fjes_hw_setup_epbuf(
 					&hw->ep_shm_info[epidx].tx,
 					netdev->dev_addr, netdev->mtu);
+				spin_unlock_irqrestore(&hw->rx_status_lock,
+						       flags);
+			}
 		}
 
 		if (test_bit(epidx, &irq_bit)) {
@@ -1095,9 +1109,11 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 					      .send_interrupts_unshare += 1;
 
 			set_bit(epidx, &hw->txrx_stop_req_bit);
+			spin_lock_irqsave(&hw->rx_status_lock, flags);
 			hw->ep_shm_info[epidx].tx.
 				info->v1i.rx_status |=
 					FJES_RX_STOP_REQ_REQUEST;
+			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 			set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit);
 		}
 	}
@@ -1113,6 +1129,7 @@ static void fjes_hw_epstop_task(struct work_struct *work)
 {
 	struct fjes_hw *hw = container_of(work, struct fjes_hw, epstop_task);
 	struct fjes_adapter *adapter = (struct fjes_adapter *)hw->back;
+	unsigned long flags;
 
 	ulong remain_bit;
 	int epid_bit;
@@ -1120,9 +1137,12 @@ static void fjes_hw_epstop_task(struct work_struct *work)
 	while ((remain_bit = hw->epstop_req_bit)) {
 		for (epid_bit = 0; remain_bit; remain_bit >>= 1, epid_bit++) {
 			if (remain_bit & 1) {
+				spin_lock_irqsave(&hw->rx_status_lock, flags);
 				hw->ep_shm_info[epid_bit].
 					tx.info->v1i.rx_status |=
 						FJES_RX_STOP_REQ_DONE;
+				spin_unlock_irqrestore(&hw->rx_status_lock,
+						       flags);
 
 				clear_bit(epid_bit, &hw->epstop_req_bit);
 				set_bit(epid_bit,
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 66cefd1..ca72474 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -329,6 +329,8 @@ struct fjes_hw {
 
 	bool trace_started;
 	u32 trace_mode;
+
+	spinlock_t rx_status_lock; /* spinlock for rx_status */
 };
 
 int fjes_hw_init(struct fjes_hw *);
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 8ab0523..22bd175 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -293,6 +293,7 @@ static int fjes_close(struct net_device *netdev)
 {
 	struct fjes_adapter *adapter = netdev_priv(netdev);
 	struct fjes_hw *hw = &adapter->hw;
+	unsigned long flags;
 	int epidx;
 
 	netif_tx_stop_all_queues(netdev);
@@ -302,13 +303,18 @@ static int fjes_close(struct net_device *netdev)
 
 	napi_disable(&adapter->napi);
 
+	spin_lock_irqsave(&hw->rx_status_lock, flags);
 	for (epidx = 0; epidx < hw->max_epid; epidx++) {
 		if (epidx == hw->my_epid)
 			continue;
 
-		adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &=
-			~FJES_RX_POLL_WORK;
+		if (fjes_hw_get_partner_ep_status(hw, epidx) ==
+		    EP_PARTNER_SHARED)
+			adapter->hw.ep_shm_info[epidx]
+				   .tx.info->v1i.rx_status &=
+				~FJES_RX_POLL_WORK;
 	}
+	spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 
 	fjes_free_irq(adapter);
 
@@ -333,6 +339,7 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	struct ep_share_mem_info *buf_pair;
 	struct fjes_hw *hw = &adapter->hw;
+	unsigned long flags;
 	int result;
 	int epidx;
 
@@ -376,8 +383,10 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
 
 		buf_pair = &hw->ep_shm_info[epidx];
 
+		spin_lock_irqsave(&hw->rx_status_lock, flags);
 		fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
 				    netdev->mtu);
+		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 
 		if (fjes_hw_epid_is_same_zone(hw, epidx)) {
 			mutex_lock(&hw->hw_info.lock);
@@ -410,6 +419,7 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
 	struct ep_share_mem_info *buf_pair;
 	struct fjes_hw *hw = &adapter->hw;
 	bool reset_flag = false;
+	unsigned long flags;
 	int result;
 	int epidx;
 
@@ -429,8 +439,10 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
 
 		buf_pair = &hw->ep_shm_info[epidx];
 
+		spin_lock_irqsave(&hw->rx_status_lock, flags);
 		fjes_hw_setup_epbuf(&buf_pair->tx,
 				    netdev->dev_addr, netdev->mtu);
+		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 
 		clear_bit(epidx, &hw->txrx_stop_req_bit);
 	}
@@ -789,6 +801,7 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
 	struct fjes_adapter *adapter = netdev_priv(netdev);
 	bool running = netif_running(netdev);
 	struct fjes_hw *hw = &adapter->hw;
+	unsigned long flags;
 	int ret = -EINVAL;
 	int idx, epidx;
 
@@ -807,12 +820,15 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
 		return ret;
 
 	if (running) {
+		spin_lock_irqsave(&hw->rx_status_lock, flags);
 		for (epidx = 0; epidx < hw->max_epid; epidx++) {
 			if (epidx == hw->my_epid)
 				continue;
 			hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
 				~FJES_RX_MTU_CHANGING_DONE;
 		}
+		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
+
 		netif_tx_stop_all_queues(netdev);
 		netif_carrier_off(netdev);
 		cancel_work_sync(&adapter->tx_stall_task);
@@ -826,23 +842,25 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
 	netdev->mtu = new_mtu;
 
 	if (running) {
+		spin_lock_irqsave(&hw->rx_status_lock, flags);
 		for (epidx = 0; epidx < hw->max_epid; epidx++) {
 			if (epidx == hw->my_epid)
 				continue;
 
-			local_irq_disable();
+			spin_lock_irqsave(&hw->rx_status_lock, flags);
 			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
 					    netdev->dev_addr,
 					    netdev->mtu);
-			local_irq_enable();
 
 			hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
 				FJES_RX_MTU_CHANGING_DONE;
+			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 		}
 
 		netif_tx_wake_all_queues(netdev);
 		netif_carrier_on(netdev);
 		napi_enable(&adapter->napi);
+		napi_schedule(&adapter->napi);
 	}
 
 	return ret;
@@ -1096,6 +1114,7 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
 {
 	struct fjes_hw *hw = &adapter->hw;
 	enum ep_partner_status status;
+	unsigned long flags;
 
 	status = fjes_hw_get_partner_ep_status(hw, src_epid);
 	switch (status) {
@@ -1105,8 +1124,10 @@ static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
 		break;
 	case EP_PARTNER_WAITING:
 		if (src_epid < hw->my_epid) {
+			spin_lock_irqsave(&hw->rx_status_lock, flags);
 			hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
 				FJES_RX_STOP_REQ_DONE;
+			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 
 			clear_bit(src_epid, &hw->txrx_stop_req_bit);
 			set_bit(src_epid, &adapter->unshare_watch_bitmask);
@@ -1132,14 +1153,17 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
 {
 	struct fjes_hw *hw = &adapter->hw;
 	enum ep_partner_status status;
+	unsigned long flags;
 
 	set_bit(src_epid, &hw->hw_info.buffer_unshare_reserve_bit);
 
 	status = fjes_hw_get_partner_ep_status(hw, src_epid);
 	switch (status) {
 	case EP_PARTNER_WAITING:
+		spin_lock_irqsave(&hw->rx_status_lock, flags);
 		hw->ep_shm_info[src_epid].tx.info->v1i.rx_status |=
 				FJES_RX_STOP_REQ_DONE;
+		spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 		clear_bit(src_epid, &hw->txrx_stop_req_bit);
 		/* fall through */
 	case EP_PARTNER_UNSHARE:
@@ -1284,13 +1308,17 @@ static int fjes_poll(struct napi_struct *napi, int budget)
 	size_t frame_len;
 	void *frame;
 
+	spin_lock(&hw->rx_status_lock);
 	for (epidx = 0; epidx < hw->max_epid; epidx++) {
 		if (epidx == hw->my_epid)
 			continue;
 
-		adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status |=
-			FJES_RX_POLL_WORK;
+		if (fjes_hw_get_partner_ep_status(hw, epidx) ==
+		    EP_PARTNER_SHARED)
+			adapter->hw.ep_shm_info[epidx]
+				   .tx.info->v1i.rx_status |= FJES_RX_POLL_WORK;
 	}
+	spin_unlock(&hw->rx_status_lock);
 
 	while (work_done < budget) {
 		prefetch(&adapter->hw);
@@ -1348,13 +1376,17 @@ static int fjes_poll(struct napi_struct *napi, int budget)
 		if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) {
 			napi_reschedule(napi);
 		} else {
+			spin_lock(&hw->rx_status_lock);
 			for (epidx = 0; epidx < hw->max_epid; epidx++) {
 				if (epidx == hw->my_epid)
 					continue;
-				adapter->hw.ep_shm_info[epidx]
-					   .tx.info->v1i.rx_status &=
+				if (fjes_hw_get_partner_ep_status(hw, epidx) ==
+				    EP_PARTNER_SHARED)
+					adapter->hw.ep_shm_info[epidx].tx
+						   .info->v1i.rx_status &=
 						~FJES_RX_POLL_WORK;
 			}
+			spin_unlock(&hw->rx_status_lock);
 
 			fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false);
 		}
@@ -1527,6 +1559,7 @@ static void fjes_watch_unshare_task(struct work_struct *work)
 	int max_epid, my_epid, epidx;
 	int stop_req, stop_req_done;
 	ulong unshare_watch_bitmask;
+	unsigned long flags;
 	int wait_time = 0;
 	int is_shared;
 	int ret;
@@ -1582,8 +1615,10 @@ static void fjes_watch_unshare_task(struct work_struct *work)
 			hw->ep_shm_info[epidx].ep_stats
 					      .command_unregister_buffer_executed += 1;
 
+			spin_lock_irqsave(&hw->rx_status_lock, flags);
 			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
 					    netdev->dev_addr, netdev->mtu);
+			spin_unlock_irqrestore(&hw->rx_status_lock, flags);
 
 			clear_bit(epidx, &hw->txrx_stop_req_bit);
 			clear_bit(epidx, &unshare_watch_bitmask);
@@ -1624,9 +1659,12 @@ static void fjes_watch_unshare_task(struct work_struct *work)
 				hw->ep_shm_info[epidx].ep_stats
 						      .command_unregister_buffer_executed += 1;
 
+				spin_lock_irqsave(&hw->rx_status_lock, flags);
 				fjes_hw_setup_epbuf(
 					&hw->ep_shm_info[epidx].tx,
 					netdev->dev_addr, netdev->mtu);
+				spin_unlock_irqrestore(&hw->rx_status_lock,
+						       flags);
 
 				clear_bit(epidx, &hw->txrx_stop_req_bit);
 				clear_bit(epidx, &unshare_watch_bitmask);
@@ -1634,8 +1672,11 @@ static void fjes_watch_unshare_task(struct work_struct *work)
 			}
 
 			if (test_bit(epidx, &unshare_watch_bitmask)) {
+				spin_lock_irqsave(&hw->rx_status_lock, flags);
 				hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
 						~FJES_RX_STOP_REQ_DONE;
+				spin_unlock_irqrestore(&hw->rx_status_lock,
+						       flags);
 			}
 		}
 	}
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 08/11] fjes: fix bitwise check bug in fjes_raise_intr_rxdata_task
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

In fjes_raise_intr_rxdata_task(), there's a bug of bitwise
check because of missing "& FJES_RX_POLL_WORK".
This patch fixes this bug.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index e785d89..8c7a8b0 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -560,7 +560,8 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work)
 		if ((hw->ep_shm_info[epid].tx_status_work ==
 		     FJES_TX_DELAY_SEND_PENDING) &&
 		    (pstatus == EP_PARTNER_SHARED) &&
-		    !(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) {
+		    !(hw->ep_shm_info[epid].rx.info->v1i.rx_status &
+		      FJES_RX_POLL_WORK)) {
 			fjes_hw_raise_interrupt(hw, epid,
 						REG_ICTL_MASK_RX_DATA);
 			hw->ep_shm_info[epid].ep_stats.send_interrupts_rx += 1;
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 09/11] fjes: Enhance changing MTU related work
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch enhances the fjes_change_mtu() method
by introducing new flag named FJES_RX_MTU_CHANGING_DONE
in rx_status. At the same time, default MTU value is
changed into 65510 bytes.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_hw.c   |  8 +++++-
 drivers/net/fjes/fjes_hw.h   |  1 +
 drivers/net/fjes/fjes_main.c | 60 ++++++++++++++++++++++++++++++++++++--------
 3 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index b2b11c3..4861e36 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -179,6 +179,8 @@ void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
 
 	for (i = 0; i < EP_BUFFER_SUPPORT_VLAN_MAX; i++)
 		info->v1i.vlan_id[i] = vlan_id[i];
+
+	info->v1i.rx_status |= FJES_RX_MTU_CHANGING_DONE;
 }
 
 void
@@ -811,7 +813,8 @@ bool fjes_hw_check_mtu(struct epbuf_handler *epbh, u32 mtu)
 {
 	union ep_buffer_info *info = epbh->info;
 
-	return (info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu));
+	return ((info->v1i.frame_max == FJES_MTU_TO_FRAME_SIZE(mtu)) &&
+		info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE);
 }
 
 bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
@@ -864,6 +867,9 @@ bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
 {
 	union ep_buffer_info *info = epbh->info;
 
+	if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
+		return true;
+
 	if (info->v1i.count_max == 0)
 		return true;
 
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index a1c3d65..66cefd1 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -58,6 +58,7 @@ struct fjes_hw;
 #define FJES_RX_STOP_REQ_DONE		(0x1)
 #define FJES_RX_STOP_REQ_REQUEST	(0x2)
 #define FJES_RX_POLL_WORK		(0x4)
+#define FJES_RX_MTU_CHANGING_DONE	(0x8)
 
 #define EP_BUFFER_SIZE \
 	(((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 8c7a8b0..8ab0523 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -492,6 +492,9 @@ static void fjes_tx_stall_task(struct work_struct *work)
 
 			info = adapter->hw.ep_shm_info[epid].tx.info;
 
+			if (!(info->v1i.rx_status & FJES_RX_MTU_CHANGING_DONE))
+				return;
+
 			if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
 					 info->v1i.count_max)) {
 				all_queue_available = 0;
@@ -783,9 +786,11 @@ fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
 
 static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
 {
+	struct fjes_adapter *adapter = netdev_priv(netdev);
 	bool running = netif_running(netdev);
-	int ret = 0;
-	int idx;
+	struct fjes_hw *hw = &adapter->hw;
+	int ret = -EINVAL;
+	int idx, epidx;
 
 	for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
 		if (new_mtu <= fjes_support_mtu[idx]) {
@@ -793,19 +798,54 @@ static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
 			if (new_mtu == netdev->mtu)
 				return 0;
 
-			if (running)
-				fjes_close(netdev);
+			ret = 0;
+			break;
+		}
+	}
+
+	if (ret)
+		return ret;
 
-			netdev->mtu = new_mtu;
+	if (running) {
+		for (epidx = 0; epidx < hw->max_epid; epidx++) {
+			if (epidx == hw->my_epid)
+				continue;
+			hw->ep_shm_info[epidx].tx.info->v1i.rx_status &=
+				~FJES_RX_MTU_CHANGING_DONE;
+		}
+		netif_tx_stop_all_queues(netdev);
+		netif_carrier_off(netdev);
+		cancel_work_sync(&adapter->tx_stall_task);
+		napi_disable(&adapter->napi);
 
-			if (running)
-				ret = fjes_open(netdev);
+		msleep(1000);
 
-			return ret;
+		netif_tx_stop_all_queues(netdev);
+	}
+
+	netdev->mtu = new_mtu;
+
+	if (running) {
+		for (epidx = 0; epidx < hw->max_epid; epidx++) {
+			if (epidx == hw->my_epid)
+				continue;
+
+			local_irq_disable();
+			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
+					    netdev->dev_addr,
+					    netdev->mtu);
+			local_irq_enable();
+
+			hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
+				FJES_RX_MTU_CHANGING_DONE;
 		}
+
+		netif_tx_wake_all_queues(netdev);
+		netif_carrier_on(netdev);
+		napi_enable(&adapter->napi);
 	}
 
-	return -EINVAL;
+	return ret;
 }
 
 static int fjes_vlan_rx_add_vid(struct net_device *netdev,
@@ -1450,7 +1490,7 @@ static void fjes_netdev_setup(struct net_device *netdev)
 	netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
 	netdev->netdev_ops = &fjes_netdev_ops;
 	fjes_set_ethtool_ops(netdev);
-	netdev->mtu = fjes_support_mtu[0];
+	netdev->mtu = fjes_support_mtu[3];
 	netdev->flags |= IFF_BROADCAST;
 	netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
 }
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 06/11] fjes: optimize timeout value
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch optimizes the following timeout value.
  - FJES_DEVICE_RESET_TIMEOUT
  - FJES_COMMAND_REQ_TIMEOUT
  - FJES_COMMAND_REQ_BUFF_TIMEOUT

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_hw.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 41fe418..a1c3d65 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -34,9 +34,9 @@ struct fjes_hw;
 #define EP_BUFFER_INFO_SIZE 4096
 #define EP_TRACE_PAGE_SIZE 4096
 
-#define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3) /* sec */
-#define FJES_COMMAND_REQ_TIMEOUT  (5 + 1) /* sec */
-#define FJES_COMMAND_REQ_BUFF_TIMEOUT	(8 * 3) /* sec */
+#define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3 * 8) /* sec */
+#define FJES_COMMAND_REQ_TIMEOUT  ((5 + 1) * 3 * 8) /* sec */
+#define FJES_COMMAND_REQ_BUFF_TIMEOUT	(60 * 3) /* sec */
 #define FJES_COMMAND_EPSTOP_WAIT_TIMEOUT	(1) /* sec */
 
 #define FJES_CMD_REQ_ERR_INFO_PARAM  (0x0001)
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 07/11] fjes: fix incorrect statistics information in fjes_xmit_frame()
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

There are bugs of acounting statistics in fjes_xmit_frame().
Accounting self stats is wrong. accounting stats of other
EPs to be transmitted  is right.
This patch fixes this bug.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_main.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index f2327d8..e785d89 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -668,7 +668,7 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 				&adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
 			/* version is NOT 0 */
 			adapter->stats64.tx_carrier_errors += 1;
-			hw->ep_shm_info[my_epid].net_stats
+			hw->ep_shm_info[dest_epid].net_stats
 						.tx_carrier_errors += 1;
 			hw->ep_shm_info[dest_epid].ep_stats
 						  .tx_dropped_version_mismatch += 1;
@@ -678,9 +678,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 				&adapter->hw.ep_shm_info[dest_epid].rx,
 				netdev->mtu)) {
 			adapter->stats64.tx_dropped += 1;
-			hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1;
+			hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1;
 			adapter->stats64.tx_errors += 1;
-			hw->ep_shm_info[my_epid].net_stats.tx_errors += 1;
+			hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1;
 			hw->ep_shm_info[dest_epid].ep_stats
 						  .tx_dropped_buffer_size_discrepancy += 1;
 
@@ -715,10 +715,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 					    (long)adapter->tx_start_jiffies) >=
 					    FJES_TX_RETRY_TIMEOUT) {
 					adapter->stats64.tx_fifo_errors += 1;
-					hw->ep_shm_info[my_epid].net_stats
+					hw->ep_shm_info[dest_epid].net_stats
 								.tx_fifo_errors += 1;
 					adapter->stats64.tx_errors += 1;
-					hw->ep_shm_info[my_epid].net_stats
+					hw->ep_shm_info[dest_epid].net_stats
 								.tx_errors += 1;
 
 					ret = NETDEV_TX_OK;
@@ -737,10 +737,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 			} else {
 				if (!is_multi) {
 					adapter->stats64.tx_packets += 1;
-					hw->ep_shm_info[my_epid].net_stats
+					hw->ep_shm_info[dest_epid].net_stats
 								.tx_packets += 1;
 					adapter->stats64.tx_bytes += len;
-					hw->ep_shm_info[my_epid].net_stats
+					hw->ep_shm_info[dest_epid].net_stats
 								.tx_bytes += len;
 				}
 
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 05/11] fjes: show EP stats at statistics file in debugfs
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch enriches information in
/sys/kernel/debug/fjes/fjes.N/statistics file.
By applying this patch, each EP's stats information
are displayed in this file.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_debugfs.c | 27 ++++++++++++++++++++++++
 drivers/net/fjes/fjes_hw.c      |  9 ++++++++
 drivers/net/fjes/fjes_hw.h      | 18 ++++++++++++++++
 drivers/net/fjes/fjes_main.c    | 46 +++++++++++++++++++++++++++++++++++++----
 4 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/drivers/net/fjes/fjes_debugfs.c b/drivers/net/fjes/fjes_debugfs.c
index b0807c2..fc6cfa6 100644
--- a/drivers/net/fjes/fjes_debugfs.c
+++ b/drivers/net/fjes/fjes_debugfs.c
@@ -81,6 +81,33 @@ static int fjes_dbg_stats_show(struct seq_file *m, void *v)
 	FJES_DEBUGFS_NET_STATS_ENTRY(rx_compressed);
 	FJES_DEBUGFS_NET_STATS_ENTRY(tx_compressed);
 
+#define FJES_DEBUGFS_EP_STATS_ENTRY(X) do {				\
+	seq_printf(m, "%-41s", #X);					\
+	for (epidx = 0; epidx < max_epid; epidx++) {			\
+		if (epidx == my_epid)					\
+			seq_printf(m, "          -");			\
+		else							\
+			seq_printf(m, " %10llu",			\
+				   hw->ep_shm_info[epidx].ep_stats.X);	\
+	}								\
+	seq_printf(m, "\n");						\
+} while (0)
+
+	FJES_DEBUGFS_EP_STATS_ENTRY(command_register_buffer_executed);
+	FJES_DEBUGFS_EP_STATS_ENTRY(command_unregister_buffer_executed);
+	FJES_DEBUGFS_EP_STATS_ENTRY(send_interrupts_rx);
+	FJES_DEBUGFS_EP_STATS_ENTRY(send_interrupts_unshare);
+	FJES_DEBUGFS_EP_STATS_ENTRY(send_interrupts_zoneupdate);
+	FJES_DEBUGFS_EP_STATS_ENTRY(receive_interrupts_rx);
+	FJES_DEBUGFS_EP_STATS_ENTRY(receive_interrupts_unshare);
+	FJES_DEBUGFS_EP_STATS_ENTRY(receive_interrupts_stop);
+	FJES_DEBUGFS_EP_STATS_ENTRY(receive_interrupts_zoneupdate);
+	FJES_DEBUGFS_EP_STATS_ENTRY(tx_buffer_full);
+	FJES_DEBUGFS_EP_STATS_ENTRY(tx_dropped_not_shared);
+	FJES_DEBUGFS_EP_STATS_ENTRY(tx_dropped_version_mismatch);
+	FJES_DEBUGFS_EP_STATS_ENTRY(tx_dropped_buffer_size_discrepancy);
+	FJES_DEBUGFS_EP_STATS_ENTRY(tx_dropped_vlan_id_mismatch);
+
 	return 0;
 }
 
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 0b0795e..b2b11c3 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -745,6 +745,7 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw)
 		case EP_PARTNER_SHARED:
 			fjes_hw_raise_interrupt(hw, epidx,
 						REG_ICTL_MASK_TXRX_STOP_REQ);
+			hw->ep_shm_info[epidx].ep_stats.send_interrupts_unshare += 1;
 			break;
 		default:
 			break;
@@ -1046,6 +1047,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 				break;
 			}
 			mutex_unlock(&hw->hw_info.lock);
+
+			hw->ep_shm_info[epidx].ep_stats
+					      .command_register_buffer_executed += 1;
 		}
 
 		if (test_bit(epidx, &unshare_bit)) {
@@ -1069,6 +1073,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 
 			mutex_unlock(&hw->hw_info.lock);
 
+			hw->ep_shm_info[epidx].ep_stats
+					      .command_unregister_buffer_executed += 1;
+
 			if (ret == 0)
 				fjes_hw_setup_epbuf(
 					&hw->ep_shm_info[epidx].tx,
@@ -1078,6 +1085,8 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
 		if (test_bit(epidx, &irq_bit)) {
 			fjes_hw_raise_interrupt(hw, epidx,
 						REG_ICTL_MASK_TXRX_STOP_REQ);
+			hw->ep_shm_info[epidx].ep_stats
+					      .send_interrupts_unshare += 1;
 
 			set_bit(epidx, &hw->txrx_stop_req_bit);
 			hw->ep_shm_info[epidx].tx.
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 38be7d9..41fe418 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -235,6 +235,23 @@ union ep_buffer_info {
 
 };
 
+struct fjes_drv_ep_stats {
+	u64 command_register_buffer_executed;
+	u64 command_unregister_buffer_executed;
+	u64 send_interrupts_rx;
+	u64 send_interrupts_unshare;
+	u64 send_interrupts_zoneupdate;
+	u64 receive_interrupts_rx;
+	u64 receive_interrupts_unshare;
+	u64 receive_interrupts_stop;
+	u64 receive_interrupts_zoneupdate;
+	u64 tx_buffer_full;
+	u64 tx_dropped_not_shared;
+	u64 tx_dropped_version_mismatch;
+	u64 tx_dropped_buffer_size_discrepancy;
+	u64 tx_dropped_vlan_id_mismatch;
+};
+
 /* buffer pair for Extended Partition */
 struct ep_share_mem_info {
 	struct epbuf_handler {
@@ -245,6 +262,7 @@ struct ep_share_mem_info {
 	} tx, rx;
 
 	struct rtnl_link_stats64 net_stats;
+	struct fjes_drv_ep_stats ep_stats;
 
 	u16 tx_status_work;
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 7595415..f2327d8 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -363,6 +363,8 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
 		     FJES_ZONING_STATUS_ENABLE)) {
 			fjes_hw_raise_interrupt(hw, epidx,
 						REG_ICTL_MASK_INFO_UPDATE);
+			hw->ep_shm_info[epidx].ep_stats
+					      .send_interrupts_zoneupdate += 1;
 		}
 	}
 
@@ -392,6 +394,9 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
 				adapter->force_reset = true;
 				return result;
 			}
+
+			hw->ep_shm_info[epidx].ep_stats
+					      .command_register_buffer_executed += 1;
 		}
 	}
 
@@ -419,6 +424,9 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
 		if (result)
 			reset_flag = true;
 
+		hw->ep_shm_info[epidx].ep_stats
+				      .command_unregister_buffer_executed += 1;
+
 		buf_pair = &hw->ep_shm_info[epidx];
 
 		fjes_hw_setup_epbuf(&buf_pair->tx,
@@ -555,6 +563,7 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work)
 		    !(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) {
 			fjes_hw_raise_interrupt(hw, epid,
 						REG_ICTL_MASK_RX_DATA);
+			hw->ep_shm_info[epid].ep_stats.send_interrupts_rx += 1;
 		}
 	}
 
@@ -651,6 +660,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
 		pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
 		if (pstatus != EP_PARTNER_SHARED) {
+			if (!is_multi)
+				hw->ep_shm_info[dest_epid].ep_stats
+							  .tx_dropped_not_shared += 1;
 			ret = NETDEV_TX_OK;
 		} else if (!fjes_hw_check_epbuf_version(
 				&adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
@@ -658,6 +670,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 			adapter->stats64.tx_carrier_errors += 1;
 			hw->ep_shm_info[my_epid].net_stats
 						.tx_carrier_errors += 1;
+			hw->ep_shm_info[dest_epid].ep_stats
+						  .tx_dropped_version_mismatch += 1;
 
 			ret = NETDEV_TX_OK;
 		} else if (!fjes_hw_check_mtu(
@@ -667,12 +681,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 			hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1;
 			adapter->stats64.tx_errors += 1;
 			hw->ep_shm_info[my_epid].net_stats.tx_errors += 1;
+			hw->ep_shm_info[dest_epid].ep_stats
+						  .tx_dropped_buffer_size_discrepancy += 1;
 
 			ret = NETDEV_TX_OK;
 		} else if (vlan &&
 			   !fjes_hw_check_vlan_id(
 				&adapter->hw.ep_shm_info[dest_epid].rx,
 				vlan_id)) {
+			hw->ep_shm_info[dest_epid].ep_stats
+						  .tx_dropped_vlan_id_mismatch += 1;
 			ret = NETDEV_TX_OK;
 		} else {
 			if (len < VLAN_ETH_HLEN) {
@@ -706,6 +724,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 					ret = NETDEV_TX_OK;
 				} else {
 					netdev->trans_start = jiffies;
+					hw->ep_shm_info[dest_epid].ep_stats
+								  .tx_buffer_full += 1;
 					netif_tx_stop_queue(cur_queue);
 
 					if (!work_pending(&adapter->tx_stall_task))
@@ -1117,21 +1137,33 @@ static irqreturn_t fjes_intr(int irq, void *data)
 	icr = fjes_hw_capture_interrupt_status(hw);
 
 	if (icr & REG_IS_MASK_IS_ASSERT) {
-		if (icr & REG_ICTL_MASK_RX_DATA)
+		if (icr & REG_ICTL_MASK_RX_DATA) {
 			fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
+			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats.
+				receive_interrupts_rx += 1;
+		}
 
-		if (icr & REG_ICTL_MASK_DEV_STOP_REQ)
+		if (icr & REG_ICTL_MASK_DEV_STOP_REQ) {
 			fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
+			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats.
+				receive_interrupts_stop += 1;
+		}
 
-		if (icr & REG_ICTL_MASK_TXRX_STOP_REQ)
+		if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) {
 			fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
+			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats.
+				receive_interrupts_unshare += 1;
+		}
 
 		if (icr & REG_ICTL_MASK_TXRX_STOP_DONE)
 			fjes_hw_set_irqmask(hw,
 					    REG_ICTL_MASK_TXRX_STOP_DONE, true);
 
-		if (icr & REG_ICTL_MASK_INFO_UPDATE)
+		if (icr & REG_ICTL_MASK_INFO_UPDATE) {
 			fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID);
+			hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats.
+				receive_interrupts_zoneupdate += 1;
+		}
 
 		ret = IRQ_HANDLED;
 	} else {
@@ -1506,6 +1538,9 @@ static void fjes_watch_unshare_task(struct work_struct *work)
 			}
 			mutex_unlock(&hw->hw_info.lock);
 
+			hw->ep_shm_info[epidx].ep_stats
+					      .command_unregister_buffer_executed += 1;
+
 			fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
 					    netdev->dev_addr, netdev->mtu);
 
@@ -1545,6 +1580,9 @@ static void fjes_watch_unshare_task(struct work_struct *work)
 				}
 				mutex_unlock(&hw->hw_info.lock);
 
+				hw->ep_shm_info[epidx].ep_stats
+						      .command_unregister_buffer_executed += 1;
+
 				fjes_hw_setup_epbuf(
 					&hw->ep_shm_info[epidx].tx,
 					netdev->dev_addr, netdev->mtu);
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 04/11] fjes: Add debugfs entry for statistics
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch introduces debugfs entry named "statistics"
for statistics information.
You can get net_stats information by reading
/sys/kernel/debug/fjes/fjes.N/statistics file.
This is useful for debugging.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_debugfs.c | 72 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/drivers/net/fjes/fjes_debugfs.c b/drivers/net/fjes/fjes_debugfs.c
index d2fd892..b0807c2 100644
--- a/drivers/net/fjes/fjes_debugfs.c
+++ b/drivers/net/fjes/fjes_debugfs.c
@@ -31,6 +31,72 @@
 
 static struct dentry *fjes_debug_root;
 
+static int fjes_dbg_stats_show(struct seq_file *m, void *v)
+{
+	struct fjes_adapter *adapter = m->private;
+	struct fjes_hw *hw = &adapter->hw;
+	int max_epid = hw->max_epid;
+	int my_epid = hw->my_epid;
+	int epidx;
+
+	seq_printf(m, "%41s", " ");
+	for (epidx = 0; epidx < max_epid; epidx++)
+		seq_printf(m, "%10s%d",
+			   my_epid == epidx ? "(self)EP#" : "EP#", epidx);
+	seq_printf(m, "\n");
+
+#define FJES_DEBUGFS_NET_STATS_ENTRY(X) do {				\
+	seq_printf(m, "%-41s", #X);					\
+	for (epidx = 0; epidx < max_epid; epidx++) {			\
+		if (epidx == my_epid)					\
+			seq_printf(m, "          -");			\
+		else							\
+			seq_printf(m, " %10llu",			\
+				   hw->ep_shm_info[epidx].net_stats.X); \
+	}								\
+	seq_printf(m, "\n");						\
+} while (0)
+
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_packets);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_packets);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_bytes);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_bytes);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_dropped);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_dropped);
+	FJES_DEBUGFS_NET_STATS_ENTRY(multicast);
+	FJES_DEBUGFS_NET_STATS_ENTRY(collisions);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_length_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_over_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_crc_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_frame_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_fifo_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_missed_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_aborted_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_carrier_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_fifo_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_heartbeat_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_window_errors);
+	FJES_DEBUGFS_NET_STATS_ENTRY(rx_compressed);
+	FJES_DEBUGFS_NET_STATS_ENTRY(tx_compressed);
+
+	return 0;
+}
+
+static int fjes_dbg_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, fjes_dbg_stats_show, inode->i_private);
+}
+
+static const struct file_operations fjes_dbg_stats_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fjes_dbg_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static int fjes_dbg_status_show(struct seq_file *m, void *v)
 {
 	struct fjes_adapter *adapter = m->private;
@@ -89,6 +155,12 @@ void fjes_dbg_adapter_init(struct fjes_adapter *adapter)
 	if (!pfile)
 		dev_err(&adapter->plat_dev->dev,
 			"debugfs status for %s failed\n", name);
+
+	pfile = debugfs_create_file("statistics", 0444, adapter->dbg_adapter,
+				    adapter, &fjes_dbg_stats_fops);
+	if (!pfile)
+		dev_err(&adapter->plat_dev->dev,
+			"debugfs status for %s failed\n", name);
 }
 
 void fjes_dbg_adapter_exit(struct fjes_adapter *adapter)
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 03/11] fjes: Add debugs facility for fjes module
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch introduces debugfs facility for fjes module.
You can get EP status information by reading
/sys/kernel/debug/fjes/fjes.N/status file.
This is useful for debugging.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/Makefile       |   2 +-
 drivers/net/fjes/fjes.h         |  16 ++++++
 drivers/net/fjes/fjes_debugfs.c | 113 ++++++++++++++++++++++++++++++++++++++++
 drivers/net/fjes/fjes_main.c    |  12 ++++-
 4 files changed, 141 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_debugfs.c

diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 523e3d7..51c20ce 100644
--- a/drivers/net/fjes/Makefile
+++ b/drivers/net/fjes/Makefile
@@ -27,4 +27,4 @@
 
 obj-$(CONFIG_FUJITSU_ES) += fjes.o
 
-fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o
+fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_debugfs.o
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index a592fe2..a528f75 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -66,6 +66,10 @@ struct fjes_adapter {
 	bool interrupt_watch_enable;
 
 	struct fjes_hw hw;
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *dbg_adapter;
+#endif /* CONFIG_DEBUG_FS */
 };
 
 extern char fjes_driver_name[];
@@ -74,4 +78,16 @@ extern const u32 fjes_support_mtu[];
 
 void fjes_set_ethtool_ops(struct net_device *);
 
+#ifdef CONFIG_DEBUG_FS
+void fjes_dbg_adapter_init(struct fjes_adapter *adapter);
+void fjes_dbg_adapter_exit(struct fjes_adapter *adapter);
+void fjes_dbg_init(void);
+void fjes_dbg_exit(void);
+#else
+static inline void fjes_dbg_adapter_init(struct fjes_adapter *adapter) {}
+static inline void fjes_dbg_adapter_exit(struct fjes_adapter *adapter) {}
+static inline void fjes_dbg_init(void) {}
+static inline void fjes_dbg_exit(void) {}
+#endif /* CONFIG_DEBUF_FS */
+
 #endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_debugfs.c b/drivers/net/fjes/fjes_debugfs.c
new file mode 100644
index 0000000..d2fd892
--- /dev/null
+++ b/drivers/net/fjes/fjes_debugfs.c
@@ -0,0 +1,113 @@
+/*
+ *  FUJITSU Extended Socket Network Device driver
+ *  Copyright (c) 2015 FUJITSU LIMITED
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+/* debugfs support for fjes */
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+
+#include "fjes.h"
+
+static struct dentry *fjes_debug_root;
+
+static int fjes_dbg_status_show(struct seq_file *m, void *v)
+{
+	struct fjes_adapter *adapter = m->private;
+	struct fjes_hw *hw = &adapter->hw;
+	int max_epid = hw->max_epid;
+	int my_epid = hw->my_epid;
+	int epidx;
+
+	seq_printf(m,
+		   "status debug EP ID(n) n is partner status: UNSHARE(%d), SHARED(%d), WAITING(%d), COMPLETE(%d)\n",
+		   EP_PARTNER_UNSHARE, EP_PARTNER_SHARED, EP_PARTNER_WAITING,
+		   EP_PARTNER_COMPLETE);
+	seq_printf(m, "EP ID          SAME ZONE        CONNECTED\n");
+	for (epidx = 0; epidx < max_epid; epidx++) {
+		seq_printf(m, "%d", epidx);
+		if (epidx == my_epid)
+			seq_printf(m, "(self)        %c                %c\n",
+				   '-', '-');
+		else
+			seq_printf(m, "(%d)           %c                %c\n",
+				   fjes_hw_get_partner_ep_status(hw, epidx),
+				   fjes_hw_epid_is_same_zone(hw, epidx) ? 'Y' : 'N',
+				   fjes_hw_epid_is_shared(hw->hw_info.share, epidx) ? 'Y' : 'N');
+	}
+
+	return 0;
+}
+
+static int fjes_dbg_status_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, fjes_dbg_status_show, inode->i_private);
+}
+
+static const struct file_operations fjes_dbg_status_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fjes_dbg_status_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+void fjes_dbg_adapter_init(struct fjes_adapter *adapter)
+{
+	const char *name = dev_name(&adapter->plat_dev->dev);
+	struct dentry *pfile;
+
+	adapter->dbg_adapter = debugfs_create_dir(name, fjes_debug_root);
+	if (!adapter->dbg_adapter) {
+		dev_err(&adapter->plat_dev->dev,
+			"debugfs entry for %s failed\n", name);
+		return;
+	}
+
+	pfile = debugfs_create_file("status", 0444, adapter->dbg_adapter,
+				    adapter, &fjes_dbg_status_fops);
+	if (!pfile)
+		dev_err(&adapter->plat_dev->dev,
+			"debugfs status for %s failed\n", name);
+}
+
+void fjes_dbg_adapter_exit(struct fjes_adapter *adapter)
+{
+	debugfs_remove_recursive(adapter->dbg_adapter);
+	adapter->dbg_adapter = NULL;
+}
+
+void fjes_dbg_init(void)
+{
+	fjes_debug_root = debugfs_create_dir(fjes_driver_name, NULL);
+	if (!fjes_debug_root)
+		pr_info("init of debugfs failed\n");
+}
+
+void fjes_dbg_exit(void)
+{
+	debugfs_remove_recursive(fjes_debug_root);
+	fjes_debug_root = NULL;
+}
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 40cf65d..7595415 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -1359,6 +1359,8 @@ static int fjes_probe(struct platform_device *plat_dev)
 
 	netif_carrier_off(netdev);
 
+	fjes_dbg_adapter_init(adapter);
+
 	return 0;
 
 err_hw_exit:
@@ -1376,6 +1378,8 @@ static int fjes_remove(struct platform_device *plat_dev)
 	struct fjes_adapter *adapter = netdev_priv(netdev);
 	struct fjes_hw *hw = &adapter->hw;
 
+	fjes_dbg_adapter_exit(adapter);
+
 	cancel_delayed_work_sync(&adapter->interrupt_watch_task);
 	cancel_work_sync(&adapter->unshare_watch_task);
 	cancel_work_sync(&adapter->raise_intr_rxdata_task);
@@ -1566,9 +1570,13 @@ static int __init fjes_init_module(void)
 	pr_info("%s - version %s - %s\n",
 		fjes_driver_string, fjes_driver_version, fjes_copyright);
 
+	fjes_dbg_init();
+
 	result = platform_driver_register(&fjes_driver);
-	if (result < 0)
+	if (result < 0) {
+		fjes_dbg_exit();
 		return result;
+	}
 
 	result = acpi_bus_register_driver(&fjes_acpi_driver);
 	if (result < 0)
@@ -1578,6 +1586,7 @@ static int __init fjes_init_module(void)
 
 fail_acpi_driver:
 	platform_driver_unregister(&fjes_driver);
+	fjes_dbg_exit();
 	return result;
 }
 
@@ -1588,6 +1597,7 @@ static void __exit fjes_exit_module(void)
 {
 	acpi_bus_unregister_driver(&fjes_acpi_driver);
 	platform_driver_unregister(&fjes_driver);
+	fjes_dbg_exit();
 }
 
 module_exit(fjes_exit_module);
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 01/11] fjes: Add trace-gathering facility
From: Taku Izumi @ 2016-04-11  8:09 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch introduces trace-gathering facility via ioctl.
This data is useful for debugging this module and firmware.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_hw.c    | 140 ++++++++++++++++++++++++++++++++++
 drivers/net/fjes/fjes_hw.h    |  16 ++++
 drivers/net/fjes/fjes_ioctl.h |  86 +++++++++++++++++++++
 drivers/net/fjes/fjes_main.c  | 171 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 413 insertions(+)
 create mode 100644 drivers/net/fjes/fjes_ioctl.h

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index b103adb..0b0795e 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -1121,3 +1121,143 @@ static void fjes_hw_epstop_task(struct work_struct *work)
 		}
 	}
 }
+
+int fjes_hw_alloc_trace_buf(struct fjes_hw *hw, u64 trace_size, u32 mode)
+{
+	if (trace_size % EP_TRACE_PAGE_SIZE)
+		return -EINVAL;
+
+	if (FJES_DEV_COMMAND_START_TRACE_REQ_LEN(trace_size) >
+	    hw->hw_info.req_buf_size)
+		return -EINVAL;
+
+	hw->hw_info.trace = vmalloc(trace_size);
+	if (!hw->hw_info.trace)
+		return -ENOMEM;
+
+	hw->hw_info.trace_size = trace_size;
+	hw->trace_mode = mode;
+
+	return 0;
+}
+
+void fjes_hw_free_trace_buf(struct fjes_hw *hw)
+{
+	vfree(hw->hw_info.trace);
+	hw->hw_info.trace = NULL;
+	hw->hw_info.trace_size = 0;
+	hw->trace_mode = 0;
+}
+
+bool fjes_hw_trace_is_started(struct fjes_hw *hw)
+{
+	return hw->trace_started;
+}
+
+int fjes_hw_start_trace(struct fjes_hw *hw)
+{
+	union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
+	union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
+	enum fjes_dev_command_response_e ret;
+	int page_count;
+	int result = 0;
+	void *addr;
+	int i;
+
+	memset(req_buf, 0, hw->hw_info.req_buf_size);
+	memset(res_buf, 0, hw->hw_info.res_buf_size);
+
+	req_buf->start_trace.length =
+		FJES_DEV_COMMAND_START_TRACE_REQ_LEN(hw->hw_info.trace_size);
+	req_buf->start_trace.mode = hw->trace_mode;
+	req_buf->start_trace.buffer_len = hw->hw_info.trace_size;
+	page_count = hw->hw_info.trace_size / EP_TRACE_PAGE_SIZE;
+
+	for (i = 0; i < page_count; i++) {
+		addr = ((u8 *)hw->hw_info.trace) + i * EP_TRACE_PAGE_SIZE;
+		req_buf->start_trace.buffer[i] =
+			(__le64)(page_to_phys(vmalloc_to_page(addr)) +
+			offset_in_page(addr));
+	}
+	res_buf->start_trace.length = 0;
+	res_buf->start_trace.code = 0;
+
+	ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_START_TRACE);
+
+	if (res_buf->start_trace.length !=
+	    FJES_DEV_COMMAND_START_TRACE_RES_LEN)
+		result = -ENOMSG;
+	else if (ret == FJES_CMD_STATUS_NORMAL) {
+		switch (res_buf->start_trace.code) {
+		case FJES_CMD_REQ_RES_CODE_NORMAL:
+			result = 0;
+			hw->trace_started = true;
+			break;
+		default:
+			result = -EPERM;
+			break;
+		}
+	} else {
+		switch (ret) {
+		case FJES_CMD_STATUS_UNKNOWN:
+			result = -EPERM;
+			break;
+		case FJES_CMD_STATUS_TIMEOUT:
+			result = -EBUSY;
+			break;
+		case FJES_CMD_STATUS_ERROR_PARAM:
+		case FJES_CMD_STATUS_ERROR_STATUS:
+		default:
+			result = -EPERM;
+			break;
+		}
+	}
+
+	return result;
+}
+
+int fjes_hw_stop_trace(struct fjes_hw *hw)
+{
+	union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
+	union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
+	enum fjes_dev_command_response_e ret;
+	int result = 0;
+
+	memset(req_buf, 0, hw->hw_info.req_buf_size);
+	memset(res_buf, 0, hw->hw_info.res_buf_size);
+	req_buf->stop_trace.length = FJES_DEV_COMMAND_STOP_TRACE_RES_LEN;
+	res_buf->stop_trace.length = 0;
+	res_buf->stop_trace.code = 0;
+
+	ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_STOP_TRACE);
+
+	if (res_buf->stop_trace.length != FJES_DEV_COMMAND_STOP_TRACE_RES_LEN) {
+		result = -ENOMSG;
+	} else if (ret == FJES_CMD_STATUS_NORMAL) {
+		switch (res_buf->stop_trace.code) {
+		case FJES_CMD_REQ_RES_CODE_NORMAL:
+			result = 0;
+			hw->trace_started = false;
+			break;
+		default:
+			result = -EPERM;
+			break;
+		}
+	} else {
+		switch (ret) {
+		case FJES_CMD_STATUS_UNKNOWN:
+			result = -EPERM;
+			break;
+		case FJES_CMD_STATUS_TIMEOUT:
+			result = -EBUSY;
+			break;
+		case FJES_CMD_STATUS_ERROR_PARAM:
+		case FJES_CMD_STATUS_ERROR_STATUS:
+		default:
+			result = -EPERM;
+			break;
+		}
+	}
+
+	return result;
+}
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 6d57b89..38be7d9 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -32,6 +32,7 @@ struct fjes_hw;
 
 #define EP_BUFFER_SUPPORT_VLAN_MAX 4
 #define EP_BUFFER_INFO_SIZE 4096
+#define EP_TRACE_PAGE_SIZE 4096
 
 #define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3) /* sec */
 #define FJES_COMMAND_REQ_TIMEOUT  (5 + 1) /* sec */
@@ -93,6 +94,11 @@ struct fjes_hw;
 #define FJES_DEV_RES_BUF_SIZE(maxep) \
 	FJES_DEV_COMMAND_INFO_RES_LEN(maxep)
 
+#define FJES_DEV_COMMAND_START_TRACE_REQ_LEN(byte) (16 + (8 * (byte) / EP_TRACE_PAGE_SIZE))
+#define FJES_DEV_COMMAND_START_TRACE_RES_LEN (8)
+#define FJES_DEV_COMMAND_STOP_TRACE_REQ_LEN (4)
+#define FJES_DEV_COMMAND_STOP_TRACE_RES_LEN (8)
+
 /* Frame & MTU */
 struct esmem_frame {
 	__le32 frame_size;
@@ -172,6 +178,8 @@ enum fjes_dev_command_request_type {
 	FJES_CMD_REQ_INFO		= 0x0001,
 	FJES_CMD_REQ_SHARE_BUFFER	= 0x0002,
 	FJES_CMD_REQ_UNSHARE_BUFFER	= 0x0004,
+	FJES_CMD_REQ_START_TRACE        = 0x0100,
+	FJES_CMD_REQ_STOP_TRACE         = 0x0200,
 };
 
 /* parameter for command control */
@@ -299,6 +307,9 @@ struct fjes_hw {
 	u8 *base;
 
 	struct fjes_hw_info hw_info;
+
+	bool trace_started;
+	u32 trace_mode;
 };
 
 int fjes_hw_init(struct fjes_hw *);
@@ -331,4 +342,9 @@ void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
 void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
 int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);
 
+int fjes_hw_alloc_trace_buf(struct fjes_hw *, u64, u32);
+void fjes_hw_free_trace_buf(struct fjes_hw *);
+bool fjes_hw_trace_is_started(struct fjes_hw *);
+int fjes_hw_start_trace(struct fjes_hw *);
+int fjes_hw_stop_trace(struct fjes_hw *);
 #endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_ioctl.h b/drivers/net/fjes/fjes_ioctl.h
new file mode 100644
index 0000000..35adfda
--- /dev/null
+++ b/drivers/net/fjes/fjes_ioctl.h
@@ -0,0 +1,86 @@
+/*
+ *  FUJITSU Extended Socket Network Device driver
+ *  Copyright (c) 2015 FUJITSU LIMITED
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+#ifndef FJES_IOCTL_H_
+#define FJES_IOCTL_H_
+
+#define FJES_IOCTL_TRACE_START		(SIOCDEVPRIVATE + 1)
+#define FJES_IOCTL_TRACE_STOP		(SIOCDEVPRIVATE + 2)
+#define FJES_IOCTL_TRACE_GETCFG		(SIOCDEVPRIVATE + 3)
+
+struct fjes_ioctl_trace_start_req_val {
+	u32	mode;
+	u32	reserved;
+	u64	trace_size;
+};
+
+struct fjes_ioctl_trace_stop_req_val {
+	u64	trace_buff_size;
+};
+
+union fjes_ioctl_trace_req_val {
+	struct fjes_ioctl_trace_start_req_val	start;
+	struct fjes_ioctl_trace_stop_req_val	stop;
+};
+
+struct fjes_ioctl_trace_start_res_val {
+	u32	err_code;
+	u32	reserved;
+};
+
+struct fjes_ioctl_trace_getcfg_res_val {
+	u32	err_code;
+	u32	mode;
+	u64	trace_size;
+};
+
+struct fjes_ioctl_trace_stop_res_val {
+	u32	err_code;
+	u32	reserve;
+	u64	written_size;
+	u16	trace_data_buff[];
+};
+
+union fjes_ioctl_trace_res_val {
+	struct fjes_ioctl_trace_start_res_val	start;
+	struct fjes_ioctl_trace_getcfg_res_val	getcfg;
+	struct fjes_ioctl_trace_stop_res_val	stop;
+};
+
+struct fjes_ioctl_trace_param {
+	union fjes_ioctl_trace_req_val	req;
+	union fjes_ioctl_trace_res_val	res;
+};
+
+#define FJES_IOCTL_TRACE_START_ERR_NORMAL		(0x0000)
+#define FJES_IOCTL_TRACE_START_ERR_BUSY			(0x0001)
+#define FJES_IOCTL_TRACE_START_ERR_PARAM		(0x0100)
+#define FJES_IOCTL_TRACE_START_ERR_ALREADY_STARTED	(0x0200)
+#define FJES_IOCTL_TRACE_START_ERR_MEMORY		(0x0400)
+
+#define FJES_IOCTL_TRACE_STOP_ERR_NORMAL		(0x0000)
+#define FJES_IOCTL_TRACE_STOP_ERR_BUSY			(0x0001)
+#define FJES_IOCTL_TRACE_STOP_ERR_BEFORE_START		(0x0300)
+
+#define FJES_IOCTL_TRACE_GETCFG_ERR_NORMAL		(0x0000)
+#define FJES_IOCTL_TRACE_GETCFG_ERR_BEFORE_START	(0x0300)
+
+#endif /* FJES_IOCTL_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 0ddb54f..bc6e31d 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 
 #include "fjes.h"
+#include "fjes_ioctl.h"
 
 #define MAJ 1
 #define MIN 0
@@ -61,6 +62,7 @@ fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
 static int fjes_change_mtu(struct net_device *, int);
 static int fjes_vlan_rx_add_vid(struct net_device *, __be16 proto, u16);
 static int fjes_vlan_rx_kill_vid(struct net_device *, __be16 proto, u16);
+static int fjes_ioctl(struct net_device *, struct ifreq *, int cmd);
 static void fjes_tx_retry(struct net_device *);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -242,6 +244,7 @@ static const struct net_device_ops fjes_netdev_ops = {
 	.ndo_tx_timeout		= fjes_tx_retry,
 	.ndo_vlan_rx_add_vid	= fjes_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid = fjes_vlan_rx_kill_vid,
+	.ndo_do_ioctl		= fjes_ioctl,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -820,6 +823,174 @@ static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
 	return 0;
 }
 
+static int fjes_ioctl_trace_start(struct net_device *netdev, struct ifreq *rq)
+{
+	struct fjes_adapter *adapter = netdev_priv(netdev);
+	struct fjes_ioctl_trace_param param;
+	struct fjes_hw *hw = &adapter->hw;
+	u64 trace_size;
+	int ret = 0;
+	u32 mode;
+
+	if (copy_from_user(&param, rq->ifr_data, sizeof(param)))
+		return -EFAULT;
+
+	if (fjes_hw_trace_is_started(hw)) {
+		param.res.start.err_code =
+			FJES_IOCTL_TRACE_START_ERR_ALREADY_STARTED;
+	}
+
+	trace_size = param.req.start.trace_size;
+	mode = param.req.start.mode;
+
+	ret = fjes_hw_alloc_trace_buf(hw, trace_size, mode);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		param.res.start.err_code = FJES_IOCTL_TRACE_START_ERR_PARAM;
+		goto out;
+	case -ENOMEM:
+		param.res.start.err_code = FJES_IOCTL_TRACE_START_ERR_MEMORY;
+		goto out;
+	default:
+		break;
+	}
+
+	mutex_lock(&hw->hw_info.lock);
+	ret = fjes_hw_start_trace(hw);
+	mutex_unlock(&hw->hw_info.lock);
+
+	switch (ret) {
+	case 0:
+		param.res.start.err_code = FJES_IOCTL_TRACE_START_ERR_NORMAL;
+		break;
+	case -ENOMSG:
+	case -EBUSY:
+		param.res.start.err_code = FJES_IOCTL_TRACE_START_ERR_BUSY;
+		break;
+	default:
+		param.res.start.err_code =
+			hw->hw_info.res_buf->start_trace.code;
+		break;
+	}
+
+out:
+	if (copy_to_user(rq->ifr_data, &param, sizeof(param)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int fjes_ioctl_trace_stop(struct net_device *netdev, struct ifreq *rq)
+{
+	struct fjes_adapter *adapter = netdev_priv(netdev);
+	struct fjes_ioctl_trace_param param;
+	struct fjes_hw *hw = &adapter->hw;
+	struct es_device_trace *trace;
+	u32 start_trace_buff_size;
+	u32 stop_trace_buff_size;
+	bool trace_done = false;
+	u32 buff_size;
+	int ret;
+
+	if (copy_from_user(&param, rq->ifr_data, sizeof(param)))
+		return -EFAULT;
+
+	if (!fjes_hw_trace_is_started(hw)) {
+		param.res.stop.err_code =
+			FJES_IOCTL_TRACE_STOP_ERR_BEFORE_START;
+		goto out;
+	}
+
+	mutex_lock(&hw->hw_info.lock);
+	ret = fjes_hw_stop_trace(hw);
+	mutex_unlock(&hw->hw_info.lock);
+
+	switch (ret) {
+	case 0:
+		param.res.stop.err_code = FJES_IOCTL_TRACE_STOP_ERR_NORMAL;
+		trace_done = true;
+		break;
+	case -ENOMSG:
+	case -EBUSY:
+		param.res.stop.err_code = FJES_IOCTL_TRACE_STOP_ERR_BUSY;
+		break;
+	default:
+		param.res.stop.err_code = hw->hw_info.res_buf->stop_trace.code;
+		break;
+	}
+
+out:
+	if (copy_to_user(rq->ifr_data, &param, sizeof(param))) {
+		if (trace_done)
+			fjes_hw_free_trace_buf(hw);
+		return -EFAULT;
+	}
+
+	if (!trace_done)
+		return 0;
+
+	start_trace_buff_size = hw->hw_info.trace_size;
+	stop_trace_buff_size = param.req.stop.trace_buff_size;
+
+	trace = hw->hw_info.trace;
+	buff_size = min(start_trace_buff_size, stop_trace_buff_size);
+
+	param.res.stop.written_size = buff_size;
+	ret = copy_to_user(rq->ifr_data, &param,
+			   sizeof(union fjes_ioctl_trace_req_val) +
+			   sizeof(struct fjes_ioctl_trace_stop_res_val));
+
+	ret = copy_to_user((rq->ifr_data +
+			    sizeof(union fjes_ioctl_trace_req_val) +
+			    sizeof(struct fjes_ioctl_trace_stop_res_val)),
+			   trace,
+			   buff_size);
+
+	fjes_hw_free_trace_buf(hw);
+
+	return ret;
+}
+
+static int fjes_ioctl_trace_getcfg(struct net_device *netdev, struct ifreq *rq)
+{
+	struct fjes_adapter *adapter = netdev_priv(netdev);
+	struct fjes_ioctl_trace_param param;
+	struct fjes_hw *hw = &adapter->hw;
+
+	if (copy_from_user(&param, rq->ifr_data, sizeof(param)))
+		return -EFAULT;
+
+	if (fjes_hw_trace_is_started(hw)) {
+		param.res.getcfg.err_code = FJES_IOCTL_TRACE_GETCFG_ERR_NORMAL;
+		param.res.getcfg.mode = hw->trace_mode;
+		param.res.getcfg.trace_size = hw->hw_info.trace_size;
+	} else {
+		param.res.getcfg.err_code =
+			FJES_IOCTL_TRACE_GETCFG_ERR_BEFORE_START;
+	}
+
+	if (copy_to_user(rq->ifr_data, &param, sizeof(param)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int fjes_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+	switch (cmd) {
+	case FJES_IOCTL_TRACE_START:
+		return fjes_ioctl_trace_start(netdev, rq);
+	case FJES_IOCTL_TRACE_STOP:
+		return fjes_ioctl_trace_stop(netdev, rq);
+	case FJES_IOCTL_TRACE_GETCFG:
+		return fjes_ioctl_trace_getcfg(netdev, rq);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
 				   int src_epid)
 {
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 02/11] fjes: Add setting/getting register value feature via ioctl
From: Taku Izumi @ 2016-04-11  8:10 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi
In-Reply-To: <1460362136-14968-1-git-send-email-izumi.taku@jp.fujitsu.com>

This patch introduces setting/getting register value feature
via ioctl. This feature is useful for debugging.

Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_ioctl.h |  7 +++++++
 drivers/net/fjes/fjes_main.c  | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/drivers/net/fjes/fjes_ioctl.h b/drivers/net/fjes/fjes_ioctl.h
index 35adfda..61619f7 100644
--- a/drivers/net/fjes/fjes_ioctl.h
+++ b/drivers/net/fjes/fjes_ioctl.h
@@ -25,6 +25,8 @@
 #define FJES_IOCTL_TRACE_START		(SIOCDEVPRIVATE + 1)
 #define FJES_IOCTL_TRACE_STOP		(SIOCDEVPRIVATE + 2)
 #define FJES_IOCTL_TRACE_GETCFG		(SIOCDEVPRIVATE + 3)
+#define FJES_IOCTL_DEV_GETREG		(SIOCDEVPRIVATE + 4)
+#define FJES_IOCTL_DEV_SETREG		(SIOCDEVPRIVATE + 5)
 
 struct fjes_ioctl_trace_start_req_val {
 	u32	mode;
@@ -70,6 +72,11 @@ struct fjes_ioctl_trace_param {
 	union fjes_ioctl_trace_res_val	res;
 };
 
+struct fjes_ioctl_dev_reg_param {
+	u32	offset;
+	u32	val;
+};
+
 #define FJES_IOCTL_TRACE_START_ERR_NORMAL		(0x0000)
 #define FJES_IOCTL_TRACE_START_ERR_BUSY			(0x0001)
 #define FJES_IOCTL_TRACE_START_ERR_PARAM		(0x0100)
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index bc6e31d..40cf65d 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -977,6 +977,40 @@ static int fjes_ioctl_trace_getcfg(struct net_device *netdev, struct ifreq *rq)
 	return 0;
 }
 
+static int fjes_ioctl_reg_read(struct net_device *netdev, struct ifreq *rq)
+{
+	struct fjes_adapter *adapter = netdev_priv(netdev);
+	struct fjes_ioctl_dev_reg_param reg;
+	struct fjes_hw *hw = &adapter->hw;
+
+	if (copy_from_user(&reg, rq->ifr_data, sizeof(reg)))
+		return -EFAULT;
+
+	reg.val = rd32(reg.offset);
+
+	if (copy_to_user(rq->ifr_data, &reg, sizeof(reg)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int fjes_ioctl_reg_write(struct net_device *netdev, struct ifreq *rq)
+{
+	struct fjes_adapter *adapter = netdev_priv(netdev);
+	struct fjes_ioctl_dev_reg_param reg;
+	struct fjes_hw *hw = &adapter->hw;
+
+	if (copy_from_user(&reg, rq->ifr_data, sizeof(reg)))
+		return -EFAULT;
+
+	wr32(reg.offset, reg.val);
+
+	if (copy_to_user(rq->ifr_data, &reg, sizeof(reg)))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int fjes_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 {
 	switch (cmd) {
@@ -986,7 +1020,12 @@ static int fjes_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 		return fjes_ioctl_trace_stop(netdev, rq);
 	case FJES_IOCTL_TRACE_GETCFG:
 		return fjes_ioctl_trace_getcfg(netdev, rq);
+	case FJES_IOCTL_DEV_GETREG:
+		return fjes_ioctl_reg_read(netdev, rq);
+	case FJES_IOCTL_DEV_SETREG:
+		return fjes_ioctl_reg_write(netdev, rq);
 	default:
+
 		return -EOPNOTSUPP;
 	}
 }
-- 
2.4.3

^ permalink raw reply related

* [PATCH net-next 00/11] FUJITSU Extended Socket driver version 1.1
From: Taku Izumi @ 2016-04-11  8:08 UTC (permalink / raw)
  To: davem, netdev; +Cc: Taku Izumi

This patchsets update FUJITSU Extended Socket network driver into version 1.1.
This mainly includes debugging feature and some minor bugfix. 


Taku Izumi (11):
  fjes: Add trace-gathering facility
  fjes: Add setting/getting register value feature via ioctl
  fjes: Add debugs facility for fjes module
  fjes: Add debugfs entry for statistics
  fjes: show EP stats at statistics file in debugfs
  fjes: optimize timeout value
  fjes: fix incorrect statistics information in fjes_xmit_frame()
  fjes: fix bitwise check bug in fjes_raise_intr_rxdata_task
  fjes: Enhance changing MTU related work
  fjes: Introduce spinlock for rx_status
  fjes: Update fjes driver version : 1.1

 drivers/net/fjes/Makefile       |   2 +-
 drivers/net/fjes/fjes.h         |  16 ++
 drivers/net/fjes/fjes_debugfs.c | 212 +++++++++++++++++++++
 drivers/net/fjes/fjes_hw.c      | 179 +++++++++++++++++-
 drivers/net/fjes/fjes_hw.h      |  43 ++++-
 drivers/net/fjes/fjes_ioctl.h   |  93 ++++++++++
 drivers/net/fjes/fjes_main.c    | 400 +++++++++++++++++++++++++++++++++++++---
 7 files changed, 909 insertions(+), 36 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_debugfs.c
 create mode 100644 drivers/net/fjes/fjes_ioctl.h

-- 
2.4.3

^ permalink raw reply


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