[PATCH net] fjes: Fix wrong netdevice feature flags

2017-03-14 Thread Taku Izumi
This patch fixes netdev->features for Extended Socket network device.

Currently Extended Socket network device's netdev->feature claims
NETIF_F_HW_CSUM, however this is completely wrong. There's no feature
of checksum offloading.
That causes invalid TCP/UDP checksum and packet rjection when IP
forwarding from Extended Socket network device to other network device.

NETIF_F_HW_CSUM should be omitted.

Signed-off-by: Taku Izumi <izumi.t...@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 b75d9cd..c4b3c4b 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -1316,7 +1316,7 @@ static void fjes_netdev_setup(struct net_device *netdev)
netdev->min_mtu = fjes_support_mtu[0];
netdev->max_mtu = fjes_support_mtu[3];
netdev->flags |= IFF_BROADCAST;
-   netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
+   netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 }
 
 static void fjes_irq_watch_task(struct work_struct *work)
-- 
1.8.3.1



[PATCH resend] ethtool: add register dump support for fjes driver

2016-11-15 Thread Taku Izumi
This patch adds the register dump format for FUJITSU Extended
Network device like the following:

   # ethtool -d es0

0x: OWNER_EPID(Owner EPID)   0x0001
0x0004: MAX_EP(Maximum EP)   0x0008
0x0010: DCTL  (Device Control)   0x
0x0020: CR(Command request)  0x8002
0x0024: CS(Command status)   0x8002
0x0028: SHSTSAL   (Share status address Low) 0xE8215304
0x002C: SHSTSAH   (Share status address High)0x0007
0x0034: REQBL (Request Buffer length)0x8028
0x0038: REQBAL(Request Buffer Address Low)   0xEB0A
0x003C: REQBAH(Request Buffer Address High)  0x0007
0x0044: RESPBL(Response Buffer Length)   0x0018
0x0048: RESPBAL   (Response Buffer Address Low)  0xE41E1220
0x004C: RESPBAH   (Response Buffer Address High) 0x0007
0x0080: IS(Interrupt status) 0x
0x0084: IMS   (Interrupt mask set)   0x7FE0
0x0088: IMC   (Interrupt mask clear) 0x001F
0x008C: IG(Interrupt generator)  0x0001
0x0090: ICTL  (Interrupt control)0x

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 Makefile.am |  2 +-
 ethtool.c   |  1 +
 fjes.c  | 89 +
 internal.h  |  2 ++
 4 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 fjes.c

diff --git a/Makefile.am b/Makefile.am
index de2db2e..edbda57 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,7 +14,7 @@ ethtool_SOURCES += \
  pcnet32.c realtek.c tg3.c marvell.c vioc.c\
  smsc911x.c at76c50x-usb.c sfc.c stmmac.c  \
  sff-common.c sff-common.h sfpid.c sfpdiag.c   \
- ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h
+ ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h fjes.c
 endif
 
 TESTS = test-cmdline test-features
diff --git a/ethtool.c b/ethtool.c
index 49ac94e..75299c6 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1136,6 +1136,7 @@ static const struct {
{ "et131x", et131x_dump_regs },
{ "altera_tse", altera_tse_dump_regs },
{ "vmxnet3", vmxnet3_dump_regs },
+   { "fjes", fjes_dump_regs },
 #endif
 };
 
diff --git a/fjes.c b/fjes.c
new file mode 100644
index 000..52f7c28
--- /dev/null
+++ b/fjes.c
@@ -0,0 +1,89 @@
+/* Copyright (c) 2016 FUJITSU LIMITED */
+#include 
+#include "internal.h"
+
+int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+{
+   u32 *regs_buff = (u32 *)regs->data;
+
+   if (regs->version != 1)
+   return -1;
+
+   /* Information registers */
+   fprintf(stdout,
+   "0x: OWNER_EPID(Owner EPID)   
0x%08X\n",
+   regs_buff[0]);
+
+   fprintf(stdout,
+   "0x0004: MAX_EP(Maximum EP)   
0x%08X\n",
+   regs_buff[1]);
+
+   /* Device Control registers */
+   fprintf(stdout,
+   "0x0010: DCTL  (Device Control)   
0x%08X\n",
+   regs_buff[4]);
+
+   /* Command Control registers */
+   fprintf(stdout,
+   "0x0020: CR(Command request)  
0x%08X\n",
+   regs_buff[8]);
+
+   fprintf(stdout,
+   "0x0024: CS(Command status)   
0x%08X\n",
+   regs_buff[9]);
+
+   fprintf(stdout,
+   "0x0028: SHSTSAL   (Share status address Low) 
0x%08X\n",
+   regs_buff[10]);
+
+   fprintf(stdout,
+   "0x002C: SHSTSAH   (Share status address High)
0x%08X\n",
+   regs_buff[11]);
+
+   fprintf(stdout,
+   "0x0034: REQBL (Request Buffer length)
0x%08X\n",
+   regs_buff[13]);
+
+   fprintf(stdout,
+   "0x0038: REQBAL(Request Buffer Address Low)   
0x%08X\n",
+   regs_buff[14]);
+
+   fprintf(stdout,
+   "0x003C: REQBAH(Request Buffer Address High)  
0x%08X\n",
+   regs_buff[15]);
+
+   fprintf(stdout,
+   "0x0044: RESPBL(Response Buffer Length)   
0x%08X\n",
+   regs_buff[17]);
+
+   fprintf(stdout,
+   "0x0048: RESPBAL   (Response Buffer Address Low)  
0x%08X\n",
+   regs_buff[18]);
+
+   fprintf(stdout,
+   "0x004C: RESPBAH   (Response Buffer Address High) 
0x%08X\n",
+   regs_b

[PATCH] ethtool: add register dump support for fjes driver

2016-10-17 Thread Taku Izumi
From: Taku <izumi.t...@jp.fujitsu.com>

This patch adds the register dump format for FUJITSU Extended
Network device like the following:

   # ethtool -d es0

0x: OWNER_EPID(Owner EPID)   0x0001
0x0004: MAX_EP(Maximum EP)   0x0008
0x0010: DCTL  (Device Control)   0x
0x0020: CR(Command request)  0x8002
0x0024: CS(Command status)   0x8002
0x0028: SHSTSAL   (Share status address Low) 0xE8215304
0x002C: SHSTSAH   (Share status address High)0x0007
0x0034: REQBL (Request Buffer length)0x8028
0x0038: REQBAL(Request Buffer Address Low)   0xEB0A
0x003C: REQBAH(Request Buffer Address High)  0x0007
0x0044: RESPBL(Response Buffer Length)   0x0018
0x0048: RESPBAL   (Response Buffer Address Low)  0xE41E1220
0x004C: RESPBAH   (Response Buffer Address High) 0x0007
0x0080: IS(Interrupt status) 0x
0x0084: IMS   (Interrupt mask set)   0x7FE0
0x0088: IMC   (Interrupt mask clear) 0x001F
0x008C: IG(Interrupt generator)  0x0001
0x0090: ICTL  (Interrupt control)0x

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 Makefile.am |  2 +-
 ethtool.c   |  1 +
 fjes.c  | 89 +
 internal.h  |  2 ++
 4 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 fjes.c

diff --git a/Makefile.am b/Makefile.am
index de2db2e..edbda57 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,7 +14,7 @@ ethtool_SOURCES += \
  pcnet32.c realtek.c tg3.c marvell.c vioc.c\
  smsc911x.c at76c50x-usb.c sfc.c stmmac.c  \
  sff-common.c sff-common.h sfpid.c sfpdiag.c   \
- ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h
+ ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h fjes.c
 endif
 
 TESTS = test-cmdline test-features
diff --git a/ethtool.c b/ethtool.c
index 49ac94e..75299c6 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1136,6 +1136,7 @@ static const struct {
{ "et131x", et131x_dump_regs },
{ "altera_tse", altera_tse_dump_regs },
{ "vmxnet3", vmxnet3_dump_regs },
+   { "fjes", fjes_dump_regs },
 #endif
 };
 
diff --git a/fjes.c b/fjes.c
new file mode 100644
index 000..52f7c28
--- /dev/null
+++ b/fjes.c
@@ -0,0 +1,89 @@
+/* Copyright (c) 2016 FUJITSU LIMITED */
+#include 
+#include "internal.h"
+
+int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+{
+   u32 *regs_buff = (u32 *)regs->data;
+
+   if (regs->version != 1)
+   return -1;
+
+   /* Information registers */
+   fprintf(stdout,
+   "0x: OWNER_EPID(Owner EPID)   
0x%08X\n",
+   regs_buff[0]);
+
+   fprintf(stdout,
+   "0x0004: MAX_EP(Maximum EP)   
0x%08X\n",
+   regs_buff[1]);
+
+   /* Device Control registers */
+   fprintf(stdout,
+   "0x0010: DCTL  (Device Control)   
0x%08X\n",
+   regs_buff[4]);
+
+   /* Command Control registers */
+   fprintf(stdout,
+   "0x0020: CR(Command request)  
0x%08X\n",
+   regs_buff[8]);
+
+   fprintf(stdout,
+   "0x0024: CS(Command status)   
0x%08X\n",
+   regs_buff[9]);
+
+   fprintf(stdout,
+   "0x0028: SHSTSAL   (Share status address Low) 
0x%08X\n",
+   regs_buff[10]);
+
+   fprintf(stdout,
+   "0x002C: SHSTSAH   (Share status address High)
0x%08X\n",
+   regs_buff[11]);
+
+   fprintf(stdout,
+   "0x0034: REQBL (Request Buffer length)
0x%08X\n",
+   regs_buff[13]);
+
+   fprintf(stdout,
+   "0x0038: REQBAL(Request Buffer Address Low)   
0x%08X\n",
+   regs_buff[14]);
+
+   fprintf(stdout,
+   "0x003C: REQBAH(Request Buffer Address High)  
0x%08X\n",
+   regs_buff[15]);
+
+   fprintf(stdout,
+   "0x0044: RESPBL(Response Buffer Length)   
0x%08X\n",
+   regs_buff[17]);
+
+   fprintf(stdout,
+   "0x0048: RESPBAL   (Response Buffer Address Low)  
0x%08X\n",
+   regs_buff[18]);
+
+   fprintf(stdout,
+   "0x004C: RESPBAH   (Response 

[PATCH net-next v2 4/6] fjes: ethtool -w and -W support for fjes driver

2016-10-14 Thread Taku Izumi
This patch adds implementation of supporting
ethtool -w and -W for fjes driver.

You can enable and disable firmware debug mode by
using ethtool -W, and also retrieve firmware
activity information by using ethtool -w.

This is useful for debugging.

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_ethtool.c |  63 ++
 drivers/net/fjes/fjes_hw.c  | 137 
 drivers/net/fjes/fjes_hw.h  |  15 +
 drivers/net/fjes/fjes_trace.h   |  69 
 4 files changed, 284 insertions(+)

diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 68ef287..6575f88 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -235,6 +235,66 @@ static void fjes_get_regs(struct net_device *netdev,
regs_buff[36] = rd32(XSCT_ICTL);
 }
 
+static int fjes_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
+   int ret = 0;
+
+   if (dump->flag) {
+   if (hw->debug_mode)
+   return -EPERM;
+
+   hw->debug_mode = dump->flag;
+
+   /* enable debug mode */
+   mutex_lock(>hw_info.lock);
+   ret = fjes_hw_start_debug(hw);
+   mutex_unlock(>hw_info.lock);
+
+   if (ret)
+   hw->debug_mode = 0;
+   } else {
+   if (!hw->debug_mode)
+   return -EPERM;
+
+   /* disable debug mode */
+   mutex_lock(>hw_info.lock);
+   ret = fjes_hw_stop_debug(hw);
+   mutex_unlock(>hw_info.lock);
+   }
+
+   return ret;
+}
+
+static int fjes_get_dump_flag(struct net_device *netdev,
+ struct ethtool_dump *dump)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
+
+   dump->len = hw->hw_info.trace_size;
+   dump->version = 1;
+   dump->flag = hw->debug_mode;
+
+   return 0;
+}
+
+static int fjes_get_dump_data(struct net_device *netdev,
+ struct ethtool_dump *dump, void *buf)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
+   int ret = 0;
+
+   if (hw->hw_info.trace)
+   memcpy(buf, hw->hw_info.trace, hw->hw_info.trace_size);
+   else
+   ret = -EPERM;
+
+   return ret;
+}
+
 static const struct ethtool_ops fjes_ethtool_ops = {
.get_settings   = fjes_get_settings,
.get_drvinfo= fjes_get_drvinfo,
@@ -243,6 +303,9 @@ static const struct ethtool_ops fjes_ethtool_ops = {
.get_sset_count   = fjes_get_sset_count,
.get_regs   = fjes_get_regs,
.get_regs_len   = fjes_get_regs_len,
+   .set_dump   = fjes_set_dump,
+   .get_dump_flag  = fjes_get_dump_flag,
+   .get_dump_data  = fjes_get_dump_data,
 };
 
 void fjes_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index dba59dc..9c652c0 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -343,6 +343,9 @@ int fjes_hw_init(struct fjes_hw *hw)
 
ret = fjes_hw_setup(hw);
 
+   hw->hw_info.trace = vzalloc(FJES_DEBUG_BUFFER_SIZE);
+   hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
+
return ret;
 }
 
@@ -351,6 +354,18 @@ void fjes_hw_exit(struct fjes_hw *hw)
int ret;
 
if (hw->base) {
+
+   if (hw->debug_mode) {
+   /* disable debug mode */
+   mutex_lock(>hw_info.lock);
+   fjes_hw_stop_debug(hw);
+   mutex_unlock(>hw_info.lock);
+   }
+   vfree(hw->hw_info.trace);
+   hw->hw_info.trace = NULL;
+   hw->hw_info.trace_size = 0;
+   hw->debug_mode = 0;
+
ret = fjes_hw_reset(hw);
if (ret)
pr_err("%s: reset error", __func__);
@@ -1175,3 +1190,125 @@ static void fjes_hw_epstop_task(struct work_struct 
*work)
}
}
 }
+
+int fjes_hw_start_debug(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;
+
+   if (!hw->hw_info.trace)
+   return -EPERM;
+   memset(hw->hw_info.trace, 0, FJES_DEBUG_BUFFER_SIZE);
+
+   memset(req_buf, 

[PATCH net-next v2 2/6] fjes: Enhance ethtool -S for fjes driver

2016-10-14 Thread Taku Izumi
This patch enhances ethtool -S for fjes driver so that
EP related statistics can be retrieved.

The following statistics can be displayed via ethtool -S:

 ep%d_com_regist_buf_exec
 ep%d_com_unregist_buf_exec
 ep%d_send_intr_rx
 ep%d_send_intr_unshare
 ep%d_send_intr_zoneupdate
 ep%d_recv_intr_rx
 ep%d_recv_intr_unshare
 ep%d_recv_intr_stop
 ep%d_recv_intr_zoneupdate
 ep%d_tx_buffer_full
 ep%d_tx_dropped_not_shared
 ep%d_tx_dropped_ver_mismatch
 ep%d_tx_dropped_buf_size_mismatch
 ep%d_tx_dropped_vlanid_mismatch

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_ethtool.c | 70 -
 drivers/net/fjes/fjes_hw.c  |  9 ++
 drivers/net/fjes/fjes_hw.h  | 19 +++
 drivers/net/fjes/fjes_main.c| 44 +++---
 4 files changed, 137 insertions(+), 5 deletions(-)

diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 8397634..68ef287 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -49,10 +49,18 @@ static const struct fjes_stats fjes_gstrings_stats[] = {
FJES_STAT("tx_dropped", stats64.tx_dropped),
 };
 
+#define FJES_EP_STATS_LEN 14
+#define FJES_STATS_LEN \
+   (ARRAY_SIZE(fjes_gstrings_stats) + \
+((&((struct fjes_adapter *)netdev_priv(netdev))->hw)->max_epid - 1) * \
+FJES_EP_STATS_LEN)
+
 static void fjes_get_ethtool_stats(struct net_device *netdev,
   struct ethtool_stats *stats, u64 *data)
 {
struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
+   int epidx;
char *p;
int i;
 
@@ -61,11 +69,39 @@ static void fjes_get_ethtool_stats(struct net_device 
*netdev,
data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64))
? *(u64 *)p : *(u32 *)p;
}
+   for (epidx = 0; epidx < hw->max_epid; epidx++) {
+   if (epidx == hw->my_epid)
+   continue;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .com_regist_buf_exec;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .com_unregist_buf_exec;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_rx;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_unshare;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .send_intr_zoneupdate;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_rx;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_unshare;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_stop;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .recv_intr_zoneupdate;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.tx_buffer_full;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_not_shared;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_ver_mismatch;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_buf_size_mismatch;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_vlanid_mismatch;
+   }
 }
 
 static void fjes_get_strings(struct net_device *netdev,
 u32 stringset, u8 *data)
 {
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
u8 *p = data;
int i;
 
@@ -76,6 +112,38 @@ static void fjes_get_strings(struct net_device *netdev,
   ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+   for (i = 0; i < hw->max_epid; i++) {
+   if (i == hw->my_epid)
+   continue;
+   sprintf(p, "ep%u_com_regist_buf_exec", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_com_unregist_buf_exec", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_send_intr_rx", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_send_intr_unshare", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_send_intr_zoneupdate", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_recv_intr_rx", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_recv_intr_unshare&q

[PATCH net-next v2 6/6] fjes: Update fjes driver version : 1.2

2016-10-14 Thread Taku Izumi
Signed-off-by: Taku Izumi <izumi.t...@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 359e7a5..f36eb4a 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -30,7 +30,7 @@
 #include "fjes_trace.h"
 
 #define MAJ 1
-#define MIN 1
+#define MIN 2
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
 #define DRV_NAME   "fjes"
 char fjes_driver_name[] = DRV_NAME;
-- 
2.6.6



[PATCH net-next v2 5/6] fjes: Add debugfs entry for EP status information in fjes driver

2016-10-14 Thread Taku Izumi
This patch adds debugfs entry to show EP status information.
You can get each EP's status information like the following:

  # cat /sys/kernel/debug/fjes/fjes.0/status

EPIDSTATUS   SAME_ZONECONNECTED
ep0 shared   YY
ep1 ---
ep2 unshared NN
ep3 unshared NN
ep4 unshared NN
ep5 unshared NN
ep6 unshared NN
ep7 unshared NN

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/Makefile   |   2 +-
 drivers/net/fjes/fjes.h |  16 ++
 drivers/net/fjes/fjes_debugfs.c | 117 
 drivers/net/fjes/fjes_main.c|  12 -
 4 files changed, 145 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 6705d1b..bc47b35 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_trace.o
+fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_trace.o fjes_debugfs.o
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index a592fe2..0372be3 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
 };
 
 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_DEBUG_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 000..30052eb
--- /dev/null
+++ b/drivers/net/fjes/fjes_debugfs.c
@@ -0,0 +1,117 @@
+/*
+ *  FUJITSU Extended Socket Network Device driver
+ *  Copyright (c) 2015-2016 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 driver */
+
+#ifdef CONFIG_DEBUG_FS
+
+#include 
+#include 
+#include 
+
+#include "fjes.h"
+
+static struct dentry *fjes_debug_root;
+
+static const char * const ep_status_string[] = {
+   "unshared",
+   "shared",
+   "waiting",
+   "complete",
+};
+
+static int fjes_dbg_status_show(struct seq_file *m, void *v)
+{
+   struct fjes_adapter *adapter = m->private;
+   struct fjes_hw *hw = >hw;
+   int max_epid = hw->max_epid;
+   int my_epid = hw->my_epid;
+   int epidx;
+
+   seq_puts(m, "EPID\tSTATUS   SAME_ZONECONNECTED\n");
+   for (epidx = 0; epidx < max_epid; epidx++) {
+   if (epidx == my_epid) {
+   seq_printf(m, "ep%d\t%-16c %-16c %-16c\n",
+  epidx, '-', '-', '-');
+   } else {
+   seq_printf(m, "ep%d\t%-16s %-16c %-16c\n",
+  epidx,
+  
ep_status_string[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_MODU

[PATCH net-next v2 3/6] fjes: Add tracepoints in fjes driver

2016-10-14 Thread Taku Izumi
This patch adds tracepoints in fjes driver.
This is useful for debugging purpose.

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/Makefile |   2 +-
 drivers/net/fjes/fjes_hw.c|  25 +++-
 drivers/net/fjes/fjes_main.c  |   5 +
 drivers/net/fjes/fjes_trace.c |  30 
 drivers/net/fjes/fjes_trace.h | 311 ++
 5 files changed, 369 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_trace.c
 create mode 100644 drivers/net/fjes/fjes_trace.h

diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 523e3d7..6705d1b 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_trace.o
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 82b56e8..dba59dc 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -21,6 +21,7 @@
 
 #include "fjes_hw.h"
 #include "fjes.h"
+#include "fjes_trace.h"
 
 static void fjes_hw_update_zone_task(struct work_struct *);
 static void fjes_hw_epstop_task(struct work_struct *);
@@ -371,7 +372,7 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
union REG_CR cr;
union REG_CS cs;
-   int timeout;
+   int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
 
cr.reg = 0;
cr.bits.req_start = 1;
@@ -408,6 +409,8 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
}
}
 
+   trace_fjes_hw_issue_request_command(, , timeout, ret);
+
return ret;
 }
 
@@ -427,11 +430,13 @@ int fjes_hw_request_info(struct fjes_hw *hw)
res_buf->info.code = 0;
 
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
+   trace_fjes_hw_request_info(hw, res_buf);
 
result = 0;
 
if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
res_buf->info.length) {
+   trace_fjes_hw_request_info_err("Invalid res_buf");
result = -ENOMSG;
} else if (ret == FJES_CMD_STATUS_NORMAL) {
switch (res_buf->info.code) {
@@ -448,6 +453,7 @@ int fjes_hw_request_info(struct fjes_hw *hw)
result = -EPERM;
break;
case FJES_CMD_STATUS_TIMEOUT:
+   trace_fjes_hw_request_info_err("Timeout");
result = -EBUSY;
break;
case FJES_CMD_STATUS_ERROR_PARAM:
@@ -512,6 +518,8 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int 
dest_epid,
res_buf->share_buffer.length = 0;
res_buf->share_buffer.code = 0;
 
+   trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair);
+
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
 
timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -532,16 +540,20 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int 
dest_epid,
 
result = 0;
 
+   trace_fjes_hw_register_buff_addr(res_buf, timeout);
+
if (res_buf->share_buffer.length !=
-   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN)
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) {
+   trace_fjes_hw_register_buff_addr_err("Invalid res_buf");
result = -ENOMSG;
-   else if (ret == FJES_CMD_STATUS_NORMAL) {
+   } else if (ret == FJES_CMD_STATUS_NORMAL) {
switch (res_buf->share_buffer.code) {
case FJES_CMD_REQ_RES_CODE_NORMAL:
result = 0;
set_bit(dest_epid, >hw_info.buffer_share_bit);
break;
case FJES_CMD_REQ_RES_CODE_BUSY:
+   trace_fjes_hw_register_buff_addr_err("Busy Timeout");
result = -EBUSY;
break;
default:
@@ -554,6 +566,7 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int 
dest_epid,
result = -EPERM;
break;
case FJES_CMD_STATUS_TIMEOUT:
+   trace_fjes_hw_register_buff_addr_err("Timeout");
result = -EBUSY;
break;
case FJES_CMD_STATUS_ERROR_PARAM:
@@ -595,6 +608,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int 
dest_epid)
res_buf->unshare_buffer.length = 0;
res_buf->unshare_buffer.code = 0;
 
+   trace_fjes_hw_unregister_buff_addr_req(req_buf);
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
 
timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -616,8 +630,11 @@ int fjes_hw_unre

[PATCH net-next v2 1/6] fjes: ethtool -d support for fjes driver

2016-10-14 Thread Taku Izumi
This patch adds implementation of supporting
ethtool -d for fjes driver. By using ethtool -d,
you can get registers dump of Exetnded socket device.

  # ethtool -d es0

Offset  Values
--  --
0x: 01 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00
0x0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0020: 02 00 00 80 02 00 00 80 64 a6 58 08 07 00 00 00
0x0030: 00 00 00 00 28 80 00 00 00 00 f9 e3 06 00 00 00
0x0040: 00 00 00 00 18 00 00 00 80 a4 58 08 07 00 00 00
0x0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0080: 00 00 00 00 00 00 e0 7f 00 00 01 00 00 00 01 00
0x0090: 00 00 00 00

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

diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 9c218e1..8397634 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -121,12 +121,60 @@ static int fjes_get_settings(struct net_device *netdev,
return 0;
 }
 
+static int fjes_get_regs_len(struct net_device *netdev)
+{
+#define FJES_REGS_LEN  37
+   return FJES_REGS_LEN * sizeof(u32);
+}
+
+static void fjes_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
+   u32 *regs_buff = p;
+
+   memset(p, 0, FJES_REGS_LEN * sizeof(u32));
+
+   regs->version = 1;
+
+   /* Information registers */
+   regs_buff[0] = rd32(XSCT_OWNER_EPID);
+   regs_buff[1] = rd32(XSCT_MAX_EP);
+
+   /* Device Control registers */
+   regs_buff[4] = rd32(XSCT_DCTL);
+
+   /* Command Control registers */
+   regs_buff[8] = rd32(XSCT_CR);
+   regs_buff[9] = rd32(XSCT_CS);
+   regs_buff[10] = rd32(XSCT_SHSTSAL);
+   regs_buff[11] = rd32(XSCT_SHSTSAH);
+
+   regs_buff[13] = rd32(XSCT_REQBL);
+   regs_buff[14] = rd32(XSCT_REQBAL);
+   regs_buff[15] = rd32(XSCT_REQBAH);
+
+   regs_buff[17] = rd32(XSCT_RESPBL);
+   regs_buff[18] = rd32(XSCT_RESPBAL);
+   regs_buff[19] = rd32(XSCT_RESPBAH);
+
+   /* Interrupt Control registers */
+   regs_buff[32] = rd32(XSCT_IS);
+   regs_buff[33] = rd32(XSCT_IMS);
+   regs_buff[34] = rd32(XSCT_IMC);
+   regs_buff[35] = rd32(XSCT_IG);
+   regs_buff[36] = rd32(XSCT_ICTL);
+}
+
 static const struct ethtool_ops fjes_ethtool_ops = {
.get_settings   = fjes_get_settings,
.get_drvinfo= fjes_get_drvinfo,
.get_ethtool_stats = fjes_get_ethtool_stats,
.get_strings  = fjes_get_strings,
.get_sset_count   = fjes_get_sset_count,
+   .get_regs   = fjes_get_regs,
+   .get_regs_len   = fjes_get_regs_len,
 };
 
 void fjes_set_ethtool_ops(struct net_device *netdev)
-- 
2.6.6



[PATCH net-next v2 0/6] FUJITSU Extended Socket driver version 1.2

2016-10-14 Thread Taku Izumi
This patchset updates FUJITSU Extended Socket network driver into version 1.2.
This includes the following enhancements:
  - ethtool -d support
  - ethtool -S enhancement
  - ethtool -w/-W support
  - Add some debugging feature (tracepoints etc)

v1 -> v2:
  - Use u64 instead of phys_addr_t as TP_STRUCT__entry
  - Use ethtool facility to achieve debug mode instead of using debugfs


Taku Izumi (6):
  fjes: ethtool -d support for fjes driver
  fjes: Enhance ethtool -S for fjes driver
  fjes: Add tracepoints in fjes driver
  fjes: ethtool -w and -W support for fjes driver
  fjes: Add debugfs entry for EP status information in fjes driver
  fjes: Update fjes driver version : 1.2

 drivers/net/fjes/Makefile   |   2 +-
 drivers/net/fjes/fjes.h |  16 ++
 drivers/net/fjes/fjes_debugfs.c | 117 +
 drivers/net/fjes/fjes_ethtool.c | 181 ++-
 drivers/net/fjes/fjes_hw.c  | 171 +-
 drivers/net/fjes/fjes_hw.h  |  34 
 drivers/net/fjes/fjes_main.c|  63 ++-
 drivers/net/fjes/fjes_trace.c   |  30 
 drivers/net/fjes/fjes_trace.h   | 380 
 9 files changed, 983 insertions(+), 11 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_debugfs.c
 create mode 100644 drivers/net/fjes/fjes_trace.c
 create mode 100644 drivers/net/fjes/fjes_trace.h

-- 
2.6.6



[PATCH net-next 0/6] FUJITSU Extended Socket driver version 1.2

2016-10-11 Thread Taku Izumi
From: Taku <izumi.t...@jp.fujitsu.com>

This patchset updates FUJITSU Extended Socket network driver into version 1.2.
This includes the following enhancements:
  - ethtool -d support
  - ethtool -S enhancement
  - Add some debugging feature (tracepoints etc)

Taku Izumi (6):
  fjes: ethtool -d support for fjes driver
  fjes: Enhance ethtool -S for fjes driver
  fjes: Add tracepoints in fjes driver
  fjes: Implement debug mode for fjes driver
  fjes: Add debugfs entry for EP status information in fjes driver
  fjes: Update fjes driver version : 1.2

 drivers/net/fjes/Makefile   |   2 +-
 drivers/net/fjes/fjes.h |  18 ++
 drivers/net/fjes/fjes_debugfs.c | 220 +++
 drivers/net/fjes/fjes_ethtool.c | 118 -
 drivers/net/fjes/fjes_hw.c  | 156 +++-
 drivers/net/fjes/fjes_hw.h  |  34 
 drivers/net/fjes/fjes_main.c|  63 ++-
 drivers/net/fjes/fjes_trace.c   |  30 
 drivers/net/fjes/fjes_trace.h   | 381 
 9 files changed, 1011 insertions(+), 11 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_debugfs.c
 create mode 100644 drivers/net/fjes/fjes_trace.c
 create mode 100644 drivers/net/fjes/fjes_trace.h

-- 
2.6.6



[PATCH 1/6] fjes: ethtool -d support for fjes driver

2016-10-11 Thread Taku Izumi
This patch adds implementation of supporting
ethtool -d for fjes driver. By using ethtool -d,
you can get registers dump of Exetnded socket device.

  # ethtool -d es0

Offset  Values
--  --
0x: 01 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00
0x0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0020: 02 00 00 80 02 00 00 80 64 a6 58 08 07 00 00 00
0x0030: 00 00 00 00 28 80 00 00 00 00 f9 e3 06 00 00 00
0x0040: 00 00 00 00 18 00 00 00 80 a4 58 08 07 00 00 00
0x0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0080: 00 00 00 00 00 00 e0 7f 00 00 01 00 00 00 01 00
0x0090: 00 00 00 00

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

diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 9c218e1..8397634 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -121,12 +121,60 @@ static int fjes_get_settings(struct net_device *netdev,
return 0;
 }
 
+static int fjes_get_regs_len(struct net_device *netdev)
+{
+#define FJES_REGS_LEN  37
+   return FJES_REGS_LEN * sizeof(u32);
+}
+
+static void fjes_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
+   u32 *regs_buff = p;
+
+   memset(p, 0, FJES_REGS_LEN * sizeof(u32));
+
+   regs->version = 1;
+
+   /* Information registers */
+   regs_buff[0] = rd32(XSCT_OWNER_EPID);
+   regs_buff[1] = rd32(XSCT_MAX_EP);
+
+   /* Device Control registers */
+   regs_buff[4] = rd32(XSCT_DCTL);
+
+   /* Command Control registers */
+   regs_buff[8] = rd32(XSCT_CR);
+   regs_buff[9] = rd32(XSCT_CS);
+   regs_buff[10] = rd32(XSCT_SHSTSAL);
+   regs_buff[11] = rd32(XSCT_SHSTSAH);
+
+   regs_buff[13] = rd32(XSCT_REQBL);
+   regs_buff[14] = rd32(XSCT_REQBAL);
+   regs_buff[15] = rd32(XSCT_REQBAH);
+
+   regs_buff[17] = rd32(XSCT_RESPBL);
+   regs_buff[18] = rd32(XSCT_RESPBAL);
+   regs_buff[19] = rd32(XSCT_RESPBAH);
+
+   /* Interrupt Control registers */
+   regs_buff[32] = rd32(XSCT_IS);
+   regs_buff[33] = rd32(XSCT_IMS);
+   regs_buff[34] = rd32(XSCT_IMC);
+   regs_buff[35] = rd32(XSCT_IG);
+   regs_buff[36] = rd32(XSCT_ICTL);
+}
+
 static const struct ethtool_ops fjes_ethtool_ops = {
.get_settings   = fjes_get_settings,
.get_drvinfo= fjes_get_drvinfo,
.get_ethtool_stats = fjes_get_ethtool_stats,
.get_strings  = fjes_get_strings,
.get_sset_count   = fjes_get_sset_count,
+   .get_regs   = fjes_get_regs,
+   .get_regs_len   = fjes_get_regs_len,
 };
 
 void fjes_set_ethtool_ops(struct net_device *netdev)
-- 
2.6.6



[PATCH 3/6] fjes: Add tracepoints in fjes driver

2016-10-11 Thread Taku Izumi
This patch adds tracepoints in fjes driver.
This is useful for debugging purpose.

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/Makefile |   2 +-
 drivers/net/fjes/fjes_hw.c|  25 +++-
 drivers/net/fjes/fjes_main.c  |   5 +
 drivers/net/fjes/fjes_trace.c |  30 
 drivers/net/fjes/fjes_trace.h | 312 ++
 5 files changed, 370 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_trace.c
 create mode 100644 drivers/net/fjes/fjes_trace.h

diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 523e3d7..6705d1b 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_trace.o
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 82b56e8..dba59dc 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -21,6 +21,7 @@
 
 #include "fjes_hw.h"
 #include "fjes.h"
+#include "fjes_trace.h"
 
 static void fjes_hw_update_zone_task(struct work_struct *);
 static void fjes_hw_epstop_task(struct work_struct *);
@@ -371,7 +372,7 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
union REG_CR cr;
union REG_CS cs;
-   int timeout;
+   int timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
 
cr.reg = 0;
cr.bits.req_start = 1;
@@ -408,6 +409,8 @@ fjes_hw_issue_request_command(struct fjes_hw *hw,
}
}
 
+   trace_fjes_hw_issue_request_command(, , timeout, ret);
+
return ret;
 }
 
@@ -427,11 +430,13 @@ int fjes_hw_request_info(struct fjes_hw *hw)
res_buf->info.code = 0;
 
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
+   trace_fjes_hw_request_info(hw, res_buf);
 
result = 0;
 
if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
res_buf->info.length) {
+   trace_fjes_hw_request_info_err("Invalid res_buf");
result = -ENOMSG;
} else if (ret == FJES_CMD_STATUS_NORMAL) {
switch (res_buf->info.code) {
@@ -448,6 +453,7 @@ int fjes_hw_request_info(struct fjes_hw *hw)
result = -EPERM;
break;
case FJES_CMD_STATUS_TIMEOUT:
+   trace_fjes_hw_request_info_err("Timeout");
result = -EBUSY;
break;
case FJES_CMD_STATUS_ERROR_PARAM:
@@ -512,6 +518,8 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int 
dest_epid,
res_buf->share_buffer.length = 0;
res_buf->share_buffer.code = 0;
 
+   trace_fjes_hw_register_buff_addr_req(req_buf, buf_pair);
+
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
 
timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -532,16 +540,20 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int 
dest_epid,
 
result = 0;
 
+   trace_fjes_hw_register_buff_addr(res_buf, timeout);
+
if (res_buf->share_buffer.length !=
-   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN)
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) {
+   trace_fjes_hw_register_buff_addr_err("Invalid res_buf");
result = -ENOMSG;
-   else if (ret == FJES_CMD_STATUS_NORMAL) {
+   } else if (ret == FJES_CMD_STATUS_NORMAL) {
switch (res_buf->share_buffer.code) {
case FJES_CMD_REQ_RES_CODE_NORMAL:
result = 0;
set_bit(dest_epid, >hw_info.buffer_share_bit);
break;
case FJES_CMD_REQ_RES_CODE_BUSY:
+   trace_fjes_hw_register_buff_addr_err("Busy Timeout");
result = -EBUSY;
break;
default:
@@ -554,6 +566,7 @@ int fjes_hw_register_buff_addr(struct fjes_hw *hw, int 
dest_epid,
result = -EPERM;
break;
case FJES_CMD_STATUS_TIMEOUT:
+   trace_fjes_hw_register_buff_addr_err("Timeout");
result = -EBUSY;
break;
case FJES_CMD_STATUS_ERROR_PARAM:
@@ -595,6 +608,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int 
dest_epid)
res_buf->unshare_buffer.length = 0;
res_buf->unshare_buffer.code = 0;
 
+   trace_fjes_hw_unregister_buff_addr_req(req_buf);
ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_UNSHARE_BUFFER);
 
timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
@@ -616,8 +630,11 @@ int fjes_hw_unre

[PATCH 4/6] fjes: Implement debug mode for fjes driver

2016-10-11 Thread Taku Izumi
This patch implements debug mode for fjes driver.
You can get firmware activity information by enabling
debug mode. This is useful for debugging.

To enable debug mode, write value of debugging mode to
debug_mode file in debugfs:

  # echo 1 > /sys/kernel/debug/fjes/fjes.0/debug_mode

To disable debug mode, write 0 to debug_mode file in debugfs:

  # echo 0 > /sys/kernel/debug/fjes/fjes.0/debug_mode

Firmware activity information can be retrieved via
/sys/kernel/debug/fjes/fjes.0/debug_data file.

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/Makefile   |   2 +-
 drivers/net/fjes/fjes.h |  18 +
 drivers/net/fjes/fjes_debugfs.c | 169 
 drivers/net/fjes/fjes_hw.c  | 122 +
 drivers/net/fjes/fjes_hw.h  |  15 
 drivers/net/fjes/fjes_main.c|  12 ++-
 drivers/net/fjes/fjes_trace.h   |  69 
 7 files changed, 405 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 6705d1b..bc47b35 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_trace.o
+fjes-objs := fjes_main.o fjes_hw.o fjes_ethtool.o fjes_trace.o fjes_debugfs.o
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index a592fe2..3f4dc73 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -23,6 +23,7 @@
 #define FJES_H_
 
 #include 
+#include 
 
 #include "fjes_hw.h"
 
@@ -66,6 +67,11 @@ struct fjes_adapter {
bool interrupt_watch_enable;
 
struct fjes_hw hw;
+
+#ifdef CONFIG_DEBUG_FS
+   struct dentry *dbg_adapter;
+   struct debugfs_blob_wrapper blob;
+#endif /* CONFIG_DEBUG_FS */
 };
 
 extern char fjes_driver_name[];
@@ -74,4 +80,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_DEBUG_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 000..d868fe7
--- /dev/null
+++ b/drivers/net/fjes/fjes_debugfs.c
@@ -0,0 +1,169 @@
+/*
+ *  FUJITSU Extended Socket Network Device driver
+ *  Copyright (c) 2015-2016 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 driver */
+
+#ifdef CONFIG_DEBUG_FS
+
+#include 
+#include 
+#include 
+
+#include "fjes.h"
+
+static struct dentry *fjes_debug_root;
+
+static ssize_t fjes_dbg_dbg_mode_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+   struct fjes_adapter *adapter = file->private_data;
+   struct fjes_hw *hw = >hw;
+   char buf[64];
+   int size;
+
+   size = sprintf(buf, "%d\n", hw->debug_mode);
+
+   return simple_read_from_buffer(ubuf, count, ppos, buf, size);
+}
+
+static ssize_t fjes_dbg_dbg_mode_write(struct file *file,
+  const char __user *ubuf, size_t count,
+  loff_t *ppos)
+{
+   struct fjes_adapter *adapter = file->private_data;
+   struct fjes_hw *hw = >hw;
+   unsigned int value;
+   int ret;
+
+   ret = kstrtouint_from_user(ubuf, count, 10, );
+   if (ret)
+   return ret;
+
+   if (value) {
+   if (hw->debug_mode)
+   return -EPERM;
+
+   hw->debug_mode = value;
+
+   /* enable debug mode */
+   mutex_lock(>hw_info.lock);
+   ret = fjes_hw_start_debug(hw);
+   mutex_unlock(>hw_info.lock);
+
+   if (

[PATCH 2/6] fjes: Enhance ethtool -S for fjes driver

2016-10-11 Thread Taku Izumi
This patch enhances ethtool -S for fjes driver so that
EP related statistics can be retrieved.

The following statistics can be displayed via ethtool -S:

 ep%d_com_regist_buf_exec
 ep%d_com_unregist_buf_exec
 ep%d_send_intr_rx
 ep%d_send_intr_unshare
 ep%d_send_intr_zoneupdate
 ep%d_recv_intr_rx
 ep%d_recv_intr_unshare
 ep%d_recv_intr_stop
 ep%d_recv_intr_zoneupdate
 ep%d_tx_buffer_full
 ep%d_tx_dropped_not_shared
 ep%d_tx_dropped_ver_mismatch
 ep%d_tx_dropped_buf_size_mismatch
 ep%d_tx_dropped_vlanid_mismatch

Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_ethtool.c | 70 -
 drivers/net/fjes/fjes_hw.c  |  9 ++
 drivers/net/fjes/fjes_hw.h  | 19 +++
 drivers/net/fjes/fjes_main.c| 44 +++---
 4 files changed, 137 insertions(+), 5 deletions(-)

diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
index 8397634..68ef287 100644
--- a/drivers/net/fjes/fjes_ethtool.c
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -49,10 +49,18 @@ static const struct fjes_stats fjes_gstrings_stats[] = {
FJES_STAT("tx_dropped", stats64.tx_dropped),
 };
 
+#define FJES_EP_STATS_LEN 14
+#define FJES_STATS_LEN \
+   (ARRAY_SIZE(fjes_gstrings_stats) + \
+((&((struct fjes_adapter *)netdev_priv(netdev))->hw)->max_epid - 1) * \
+FJES_EP_STATS_LEN)
+
 static void fjes_get_ethtool_stats(struct net_device *netdev,
   struct ethtool_stats *stats, u64 *data)
 {
struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
+   int epidx;
char *p;
int i;
 
@@ -61,11 +69,39 @@ static void fjes_get_ethtool_stats(struct net_device 
*netdev,
data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64))
? *(u64 *)p : *(u32 *)p;
}
+   for (epidx = 0; epidx < hw->max_epid; epidx++) {
+   if (epidx == hw->my_epid)
+   continue;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .com_regist_buf_exec;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .com_unregist_buf_exec;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_rx;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.send_intr_unshare;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .send_intr_zoneupdate;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_rx;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_unshare;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.recv_intr_stop;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .recv_intr_zoneupdate;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats.tx_buffer_full;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_not_shared;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_ver_mismatch;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_buf_size_mismatch;
+   data[i++] = hw->ep_shm_info[epidx].ep_stats
+   .tx_dropped_vlanid_mismatch;
+   }
 }
 
 static void fjes_get_strings(struct net_device *netdev,
 u32 stringset, u8 *data)
 {
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = >hw;
u8 *p = data;
int i;
 
@@ -76,6 +112,38 @@ static void fjes_get_strings(struct net_device *netdev,
   ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+   for (i = 0; i < hw->max_epid; i++) {
+   if (i == hw->my_epid)
+   continue;
+   sprintf(p, "ep%u_com_regist_buf_exec", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_com_unregist_buf_exec", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_send_intr_rx", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_send_intr_unshare", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_send_intr_zoneupdate", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_recv_intr_rx", i);
+   p += ETH_GSTRING_LEN;
+   sprintf(p, "ep%u_recv_intr_unshare&q

[PATCH 5/6] fjes: Add debugfs entry for EP status information in fjes driver

2016-10-11 Thread Taku Izumi
This patch adds debugfs entry to show EP status information.
You can get each EP's status information like the following:

  # cat /sys/kernel/debug/fjes/fjes.0/status

EPIDSTATUS   SAME_ZONECONNECTED
ep0 shared   YY
ep1 ---
ep2 unshared NN
ep3 unshared NN
ep4 unshared NN
ep5 unshared NN
ep6 unshared NN
ep7 unshared NN

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

diff --git a/drivers/net/fjes/fjes_debugfs.c b/drivers/net/fjes/fjes_debugfs.c
index d868fe7..19528a5 100644
--- a/drivers/net/fjes/fjes_debugfs.c
+++ b/drivers/net/fjes/fjes_debugfs.c
@@ -97,6 +97,51 @@ static const struct file_operations fjes_dbg_dbg_mode_fops = 
{
.write  = fjes_dbg_dbg_mode_write,
 };
 
+static const char * const ep_status_string[] = {
+   "unshared",
+   "shared",
+   "waiting",
+   "complete",
+};
+
+static int fjes_dbg_status_show(struct seq_file *m, void *v)
+{
+   struct fjes_adapter *adapter = m->private;
+   struct fjes_hw *hw = >hw;
+   int max_epid = hw->max_epid;
+   int my_epid = hw->my_epid;
+   int epidx;
+
+   seq_puts(m, "EPID\tSTATUS   SAME_ZONECONNECTED\n");
+   for (epidx = 0; epidx < max_epid; epidx++) {
+   if (epidx == my_epid) {
+   seq_printf(m, "ep%d\t%-16c %-16c %-16c\n",
+  epidx, '-', '-', '-');
+   } else {
+   seq_printf(m, "ep%d\t%-16s %-16c %-16c\n",
+  epidx,
+  
ep_status_string[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(>plat_dev->dev);
@@ -132,6 +177,12 @@ void fjes_dbg_adapter_init(struct fjes_adapter *adapter)
hw->hw_info.trace = NULL;
hw->hw_info.trace_size = 0;
}
+
+   pfile = debugfs_create_file("status", 0444, adapter->dbg_adapter,
+   adapter, _dbg_status_fops);
+   if (!pfile)
+   dev_err(>plat_dev->dev,
+   "debugfs status for %s failed\n", name);
 }
 
 void fjes_dbg_adapter_exit(struct fjes_adapter *adapter)
-- 
2.6.6



[PATCH 6/6] fjes: Update fjes driver version : 1.2

2016-10-11 Thread Taku Izumi
From: Taku <izumi.t...@jp.fujitsu.com>

Signed-off-by: Taku Izumi <izumi.t...@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 359e7a5..f36eb4a 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -30,7 +30,7 @@
 #include "fjes_trace.h"
 
 #define MAJ 1
-#define MIN 1
+#define MIN 2
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
 #define DRV_NAME   "fjes"
 char fjes_driver_name[] = DRV_NAME;
-- 
2.6.6



[PATCH net-next] fjes: Fix unnecessary spinlock_irqsave

2016-05-09 Thread Taku Izumi
commit-bd5a256 introduces a deadlock bug in fjes_change_mtu().
This spin_lock_irqsave() is obviously unnecessary.

This patch eliminates unnecessary spin_lock_irqsave() in
fjes_change_mtu()

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

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index f4e6926..86c331b 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -819,7 +819,6 @@ static int fjes_change_mtu(struct net_device *netdev, int 
new_mtu)
netdev->mtu = new_mtu;
 
if (running) {
-   spin_lock_irqsave(>rx_status_lock, flags);
for (epidx = 0; epidx < hw->max_epid; epidx++) {
if (epidx == hw->my_epid)
continue;
-- 
1.9.1



[PATCH net-next v2 6/6] fjes: Update fjes driver version : 1.1

2016-04-14 Thread Taku Izumi
Signed-off-by: Taku Izumi <izumi.t...@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 87b2474..bb7e903 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -29,7 +29,7 @@
 #include "fjes.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



[PATCH net-next v2 3/6] fjes: fix bitwise check bug in fjes_raise_intr_rxdata_task

2016-04-14 Thread Taku Izumi
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.t...@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 05bdd8b..e22a869 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -549,7 +549,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);
}
-- 
2.4.3



[PATCH net-next v2 5/6] fjes: Introduce spinlock for rx_status

2016-04-14 Thread Taku Izumi
This patch introduces spinlock of rx_status for
proper excusive control.

Signed-off-by: Taku Izumi <izumi.t...@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 e9f494b..0dbafed 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(>rx_status_lock, flags);
fjes_hw_setup_epbuf(_pair->tx, mac,
fjes_support_mtu[0]);
fjes_hw_setup_epbuf(_pair->rx, mac,
fjes_support_mtu[0]);
+   spin_unlock_irqrestore(>rx_status_lock, flags);
}
}
 
@@ -329,6 +332,7 @@ int fjes_hw_init(struct fjes_hw *hw)
INIT_WORK(>epstop_task, fjes_hw_epstop_task);
 
mutex_init(>hw_info.lock);
+   spin_lock_init(>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++) {
@@ -755,8 +760,10 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw)
set_bit(epidx, >hw_info.buffer_unshare_reserve_bit);
set_bit(epidx, >txrx_stop_req_bit);
 
+   spin_lock_irqsave(>rx_status_lock, flags);
hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
FJES_RX_STOP_REQ_REQUEST;
+   spin_unlock_irqrestore(>rx_status_lock, flags);
}
 }
 
@@ -938,6 +945,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;
@@ -1030,8 +1038,10 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
continue;
 
if (test_bit(epidx, _bit)) {
+   spin_lock_irqsave(>rx_status_lock, flags);
fjes_hw_setup_epbuf(>ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu);
+   spin_unlock_irqrestore(>rx_status_lock, flags);
 
mutex_lock(>hw_info.lock);
 
@@ -1075,10 +1085,14 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
 
mutex_unlock(>hw_info.lock);
 
-   if (ret == 0)
+   if (ret == 0) {
+   spin_lock_irqsave(>rx_status_lock, flags);
fjes_hw_setup_epbuf(
>ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu);
+   spin_unlock_irqrestore(>rx_status_lock,
+  flags);
+   }
}
 
if (test_bit(epidx, _bit)) {
@@ -1086,9 +1100,11 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
REG_ICTL_MASK_TXRX_STOP_REQ);
 
set_bit(epidx, >txrx_stop_req_bit);
+   spin_lock_irqsave(>rx_status_lock, flags);
hw->ep_shm_info[epidx].tx.
info->v1i.rx_status |=
FJES_RX_STOP_REQ_REQUEST;
+   spin_unlock_irqrestore(>rx_status_lock, flags);
set_bit(epidx, >hw_info.buffer_unshare_reserve_bit);
}
}
@@ -1104,6 +1120,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;
@@ -,9 +11

[PATCH net-next v2 4/6] fjes: Enhance changing MTU related work

2016-04-14 Thread Taku Izumi
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.t...@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 b103adb..e9f494b 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
@@ -810,7 +812,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)
@@ -863,6 +866,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 baee7f5..f40cf07 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -57,6 +57,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 e22a869..3c0c120 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -481,6 +481,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;
@@ -760,9 +763,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 = >hw;
+   int ret = -EINVAL;
+   int idx, epidx;
 
for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
if (new_mtu <= fjes_support_mtu[idx]) {
@@ -770,19 +775,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;
+
+   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(>tx_stall_task);
+   napi_disable(>napi);
+
+   msleep(1000);
 
-   netdev->mtu = new_mtu;
+   netif_tx_stop_all_queues(netdev);
+   }
 
-   if (running)
-   ret = fjes_open(netdev);
+   netdev->mtu = new_mtu;
 
-   return ret;
+   if (running) {
+   for (epidx = 0; epidx < hw->max_epid; epidx++) {
+   if (epidx == hw->my_epid)
+   continue;
+
+   local_irq_disable();
+   fjes_hw_setup_epbuf(>ep_shm_info[epidx].tx,
+   netdev->dev_addr,
+   

[PATCH net-next v2 1/6] fjes: optimize timeout value

2016-04-14 Thread Taku Izumi
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.t...@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 6d57b89..baee7f5 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -33,9 +33,9 @@ struct fjes_hw;
 #define EP_BUFFER_SUPPORT_VLAN_MAX 4
 #define EP_BUFFER_INFO_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



[PATCH net-next v2 2/6] fjes: fix incorrect statistics information in fjes_xmit_frame()

2016-04-14 Thread Taku Izumi
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.t...@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 061b4af..05bdd8b 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -653,7 +653,7 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
>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;
 
ret = NETDEV_TX_OK;
@@ -661,9 +661,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
>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;
 
ret = NETDEV_TX_OK;
} else if (vlan &&
@@ -694,10 +694,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;
@@ -714,10 +714,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



[PATCH net-next v2 0/6] FUJITSU Extended Socket driver version 1.1

2016-04-14 Thread Taku Izumi
This patchsets update FUJITSU Extended Socket network driver into version 1.1.
This mainly includes some improvements and minor bugfix.

v1->v2:
  - Remove ioctl and debugfs facility according to David comment

Taku Izumi (6):
  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/fjes_hw.c   |  30 +-
 drivers/net/fjes/fjes_hw.h   |   9 ++-
 drivers/net/fjes/fjes_main.c | 132 +++
 3 files changed, 141 insertions(+), 30 deletions(-)

-- 
2.4.3



[PATCH net-next 09/11] fjes: Enhance changing MTU related work

2016-04-11 Thread Taku Izumi
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.t...@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 = >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(>tx_stall_task);
+   napi_disable(>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(>ep_shm_info[epidx].tx,
+   netdev->dev_addr,
+   

[PATCH net-next 03/11] fjes: Add debugs facility for fjes module

2016-04-11 Thread Taku Izumi
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.t...@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 000..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 
+#include 
+#include 
+
+#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 = >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 ZONECONNECTED\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(>plat_dev->dev);
+   struct dentry *pfile;
+
+   adapter->dbg_a

[PATCH net-next 01/11] fjes: Add trace-gathering facility

2016-04-11 Thread Taku Izumi
This patch introduces trace-gathering facility via ioctl.
This data is useful for debugging this module and firmware.

Signed-off-by: Taku Izumi <izumi.t...@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 =

[PATCH net-next 05/11] fjes: show EP stats at statistics file in debugfs

2016-04-11 Thread Taku Izumi
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.t...@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_info.lock);
+
+   hw->ep_shm_info[epidx].ep_stats
+ .command_register_buffer_executed 
+= 1;
}
 
if (test_bit(epidx, _bit)) {
@@ -1069,6 +1073,9 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
 
mutex_unlock(>hw_info.lock);
 
+   hw->ep_shm_info[epidx].ep_stats
+ 
.command_unregister_buffer_executed += 1;
+
if (ret == 0)
fjes_hw_setup_epbuf(
>ep_shm_info[epidx].tx,
@@ -1078,6 +1085,8 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
if (test_bit(epidx, _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, >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;
+   u

[PATCH net-next 10/11] fjes: Introduce spinlock for rx_status

2016-04-11 Thread Taku Izumi
This patch introduces spinlock of rx_status for
proper excusive control.

Signed-off-by: Taku Izumi <izumi.t...@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(>rx_status_lock, flags);
fjes_hw_setup_epbuf(_pair->tx, mac,
fjes_support_mtu[0]);
fjes_hw_setup_epbuf(_pair->rx, mac,
fjes_support_mtu[0]);
+   spin_unlock_irqrestore(>rx_status_lock, flags);
}
}
 
@@ -329,6 +332,7 @@ int fjes_hw_init(struct fjes_hw *hw)
INIT_WORK(>epstop_task, fjes_hw_epstop_task);
 
mutex_init(>hw_info.lock);
+   spin_lock_init(>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_info.buffer_unshare_reserve_bit);
set_bit(epidx, >txrx_stop_req_bit);
 
+   spin_lock_irqsave(>rx_status_lock, flags);
hw->ep_shm_info[epidx].tx.info->v1i.rx_status |=
FJES_RX_STOP_REQ_REQUEST;
+   spin_unlock_irqrestore(>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, _bit)) {
+   spin_lock_irqsave(>rx_status_lock, flags);
fjes_hw_setup_epbuf(>ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu);
+   spin_unlock_irqrestore(>rx_status_lock, flags);
 
mutex_lock(>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(>rx_status_lock, flags);
fjes_hw_setup_epbuf(
>ep_shm_info[epidx].tx,
netdev->dev_addr, netdev->mtu);
+   spin_unlock_irqrestore(>rx_status_lock,
+  flags);
+   }
}
 
if (test_bit(epidx, _bit)) {
@@ -1095,9 +1109,11 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
  .send_interrupts_unshare += 1;
 
set_bit(epidx, >txrx_stop_req_bit);
+   spin_lock_irqsave(>rx_status_lock, flags);
hw->ep_shm_info[epidx].tx.
info->v1i.rx_status |=
FJES_RX_STOP_REQ_REQUEST;
+   spin_unlock_irqrestore(>rx_status_lock, flags);
set_bit(epidx, >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 flag

[PATCH net-next 11/11] fjes: Update fjes driver version : 1.1

2016-04-11 Thread Taku Izumi
Signed-off-by: Taku Izumi <izumi.t...@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



[PATCH net-next 06/11] fjes: optimize timeout value

2016-04-11 Thread Taku Izumi
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.t...@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



[PATCH net-next 00/11] FUJITSU Extended Socket driver version 1.1

2016-04-11 Thread 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



[PATCH net-next 07/11] fjes: fix incorrect statistics information in fjes_xmit_frame()

2016-04-11 Thread Taku Izumi
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.t...@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)
>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)
>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



[PATCH net-next 02/11] fjes: Add setting/getting register value feature via ioctl

2016-04-11 Thread Taku Izumi
This patch introduces setting/getting register value feature
via ioctl. This feature is useful for debugging.

Signed-off-by: Taku Izumi <izumi.t...@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  (0x)
 #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 = >hw;
+
+   if (copy_from_user(, rq->ifr_data, sizeof(reg)))
+   return -EFAULT;
+
+   reg.val = rd32(reg.offset);
+
+   if (copy_to_user(rq->ifr_data, , 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 = >hw;
+
+   if (copy_from_user(, rq->ifr_data, sizeof(reg)))
+   return -EFAULT;
+
+   wr32(reg.offset, reg.val);
+
+   if (copy_to_user(rq->ifr_data, , 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



[PATCH net-next 04/11] fjes: Add debugfs entry for statistics

2016-04-11 Thread Taku Izumi
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.t...@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 = >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(>plat_dev->dev,
"debugfs status for %s failed\n", name);
+
+   pfile = debugfs_create_file("statistics", 0444, adapter->dbg_adapter,
+   adapter, _dbg_stats_fops);
+   if (!pfile)
+   dev_err(>plat_dev->dev,
+   "debugfs status for %s failed\n", name);
 }
 
 void fjes_dbg_adapter_exit(struct fjes_adapter *adapter)
-- 
2.4.3



[PATCH net-next 08/11] fjes: fix bitwise check bug in fjes_raise_intr_rxdata_task

2016-04-11 Thread Taku Izumi
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.t...@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



[PATCH net] fjes: fix off-by-one error at fjes_hw_update_zone_task()

2015-09-16 Thread Taku Izumi
Dan Carpenter reported off-by-one error of fjes at
http://www.mail-archive.com/netdev@vger.kernel.org/msg77520.html

Actually this is a bug.
ep_shm_info[epidx].{es_status, zone} should be update
inside for loop.

This patch fixes this bug.

Reported-by: Dan Carpenter <dan.carpen...@oracle.com>
Signed-off-by: Taku Izumi <izumi.t...@jp.fujitsu.com>
---
 drivers/net/fjes/fjes_hw.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index b5f4a78..2d3848c 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -1011,11 +1011,11 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
set_bit(epidx, _bit);
break;
}
-   }
-
-   hw->ep_shm_info[epidx].es_status = info[epidx].es_status;
-   hw->ep_shm_info[epidx].zone = info[epidx].zone;
 
+   hw->ep_shm_info[epidx].es_status =
+   info[epidx].es_status;
+   hw->ep_shm_info[epidx].zone = info[epidx].zone;
+   }
break;
}
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 19/22] fjes: update_zone_task

2015-08-21 Thread Taku Izumi
This patch adds update_zone_task.
Zoning information can be changed by user.
This task is used to monitor if zoning information is
changed or not.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 179 +++
 drivers/net/fjes/fjes_hw.h   |   1 +
 drivers/net/fjes/fjes_main.c |  14 
 3 files changed, 194 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 4a4b750..4525d36 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -22,6 +22,8 @@
 #include fjes_hw.h
 #include fjes.h
 
+static void fjes_hw_update_zone_task(struct work_struct *);
+
 /* supported MTU list */
 const u32 fjes_support_mtu[] = {
FJES_MTU_DEFINE(8 * 1024),
@@ -322,6 +324,8 @@ int fjes_hw_init(struct fjes_hw *hw)
 
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
+   INIT_WORK(hw-update_zone_task, fjes_hw_update_zone_task);
+
mutex_init(hw-hw_info.lock);
 
hw-max_epid = fjes_hw_get_max_epid(hw);
@@ -349,6 +353,8 @@ void fjes_hw_exit(struct fjes_hw *hw)
}
 
fjes_hw_cleanup(hw);
+
+   cancel_work_sync(hw-update_zone_task);
 }
 
 static enum fjes_dev_command_response_e
@@ -913,3 +919,176 @@ int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
 
return 0;
 }
+
+static void fjes_hw_update_zone_task(struct work_struct *work)
+{
+   struct fjes_hw *hw = container_of(work,
+   struct fjes_hw, update_zone_task);
+
+   struct my_s {u8 es_status; u8 zone; } *info;
+   union fjes_device_command_res *res_buf;
+   enum ep_partner_status pstatus;
+
+   struct fjes_adapter *adapter;
+   struct net_device *netdev;
+
+   ulong unshare_bit = 0;
+   ulong share_bit = 0;
+   ulong irq_bit = 0;
+
+   int epidx;
+   int ret;
+
+   adapter = (struct fjes_adapter *)hw-back;
+   netdev = adapter-netdev;
+   res_buf = hw-hw_info.res_buf;
+   info = (struct my_s *)res_buf-info.info;
+
+   mutex_lock(hw-hw_info.lock);
+
+   ret = fjes_hw_request_info(hw);
+   switch (ret) {
+   case -ENOMSG:
+   case -EBUSY:
+   default:
+   if (!work_pending(adapter-force_close_task)) {
+   adapter-force_reset = true;
+   schedule_work(adapter-force_close_task);
+   }
+   break;
+
+   case 0:
+
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid) {
+   hw-ep_shm_info[epidx].es_status =
+   info[epidx].es_status;
+   hw-ep_shm_info[epidx].zone =
+   info[epidx].zone;
+   continue;
+   }
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epidx);
+   switch (pstatus) {
+   case EP_PARTNER_UNSHARE:
+   default:
+   if ((info[epidx].zone !=
+   FJES_ZONING_ZONE_TYPE_NONE) 
+   (info[epidx].es_status ==
+   FJES_ZONING_STATUS_ENABLE) 
+   (info[epidx].zone ==
+   info[hw-my_epid].zone))
+   set_bit(epidx, share_bit);
+   else
+   set_bit(epidx, unshare_bit);
+   break;
+
+   case EP_PARTNER_COMPLETE:
+   case EP_PARTNER_WAITING:
+   if ((info[epidx].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE) ||
+   (info[epidx].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (info[epidx].zone !=
+   info[hw-my_epid].zone)) {
+   set_bit(epidx,
+   
adapter-unshare_watch_bitmask);
+   set_bit(epidx,
+   
hw-hw_info.buffer_unshare_reserve_bit);
+   }
+   break;
+
+   case EP_PARTNER_SHARED:
+   if ((info[epidx].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE) ||
+   (info[epidx].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (info[epidx].zone !=
+   info[hw-my_epid].zone))
+   set_bit(epidx

[PATCH v3 21/22] fjes: handle receive cancellation request interrupt

2015-08-21 Thread Taku Izumi
This patch adds implementation of handling IRQ
of other receiver's receive cancellation request.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 78 
 1 file changed, 78 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 5e77d0c..5f93e42 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -820,6 +820,74 @@ static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
return 0;
 }
 
+static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
+  int src_epid)
+{
+   struct fjes_hw *hw = adapter-hw;
+   enum ep_partner_status status;
+
+   status = fjes_hw_get_partner_ep_status(hw, src_epid);
+   switch (status) {
+   case EP_PARTNER_UNSHARE:
+   case EP_PARTNER_COMPLETE:
+   default:
+   break;
+   case EP_PARTNER_WAITING:
+   if (src_epid  hw-my_epid) {
+   hw-ep_shm_info[src_epid].tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_DONE;
+
+   clear_bit(src_epid, hw-txrx_stop_req_bit);
+   set_bit(src_epid, adapter-unshare_watch_bitmask);
+
+   if (!work_pending(adapter-unshare_watch_task))
+   queue_work(adapter-control_wq,
+  adapter-unshare_watch_task);
+   }
+   break;
+   case EP_PARTNER_SHARED:
+   if (hw-ep_shm_info[src_epid].rx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_REQUEST) {
+   set_bit(src_epid, hw-epstop_req_bit);
+   if (!work_pending(hw-epstop_task))
+   queue_work(adapter-control_wq,
+  hw-epstop_task);
+   }
+   break;
+   }
+}
+
+static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
+{
+   struct fjes_hw *hw = adapter-hw;
+   enum ep_partner_status status;
+
+   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:
+   hw-ep_shm_info[src_epid].tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_DONE;
+   clear_bit(src_epid, hw-txrx_stop_req_bit);
+   /* fall through */
+   case EP_PARTNER_UNSHARE:
+   case EP_PARTNER_COMPLETE:
+   default:
+   set_bit(src_epid, adapter-unshare_watch_bitmask);
+   if (!work_pending(adapter-unshare_watch_task))
+   queue_work(adapter-control_wq,
+  adapter-unshare_watch_task);
+   break;
+   case EP_PARTNER_SHARED:
+   set_bit(src_epid, hw-epstop_req_bit);
+
+   if (!work_pending(hw-epstop_task))
+   queue_work(adapter-control_wq, hw-epstop_task);
+   break;
+   }
+}
+
 static void fjes_update_zone_irq(struct fjes_adapter *adapter,
 int src_epid)
 {
@@ -842,6 +910,16 @@ static irqreturn_t fjes_intr(int irq, void *data)
if (icr  REG_ICTL_MASK_RX_DATA)
fjes_rx_irq(adapter, icr  REG_IS_MASK_EPID);
 
+   if (icr  REG_ICTL_MASK_DEV_STOP_REQ)
+   fjes_stop_req_irq(adapter, icr  REG_IS_MASK_EPID);
+
+   if (icr  REG_ICTL_MASK_TXRX_STOP_REQ)
+   fjes_txrx_stop_req_irq(adapter, icr  REG_IS_MASK_EPID);
+
+   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)
fjes_update_zone_irq(adapter, icr  REG_IS_MASK_EPID);
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 09/22] fjes: raise_intr_rxdata_task

2015-08-21 Thread Taku Izumi
This patch add raise_intr_rxdata_task.
Extended Socket Network Device is shared memory
based, so someone's transmission denotes other's
reception. In order to notify receivers, sender
has to raise interruption of receivers.
raise_intr_rxdata_task does this work.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  4 +++
 drivers/net/fjes/fjes_main.c | 63 
 2 files changed, 67 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 7af4304..8e9899e 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -50,6 +50,10 @@ struct fjes_adapter {
 
bool irq_registered;
 
+   struct workqueue_struct *txrx_wq;
+
+   struct work_struct raise_intr_rxdata_task;
+
struct fjes_hw hw;
 };
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 220ff3d..80e180f 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -52,6 +52,7 @@ static int fjes_close(struct net_device *);
 static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
+static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -276,6 +277,8 @@ static int fjes_close(struct net_device *netdev)
 
fjes_free_irq(adapter);
 
+   cancel_work_sync(adapter-raise_intr_rxdata_task);
+
fjes_hw_wait_epstop(hw);
 
fjes_free_resources(adapter);
@@ -404,6 +407,54 @@ static void fjes_free_resources(struct fjes_adapter 
*adapter)
}
 }
 
+static void fjes_raise_intr_rxdata_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, raise_intr_rxdata_task);
+   struct fjes_hw *hw = adapter-hw;
+   enum ep_partner_status pstatus;
+   int max_epid, my_epid, epid;
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   for (epid = 0; epid  max_epid; epid++)
+   hw-ep_shm_info[epid].tx_status_work = 0;
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (epid == my_epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   if (pstatus == EP_PARTNER_SHARED) {
+   hw-ep_shm_info[epid].tx_status_work =
+   hw-ep_shm_info[epid].tx.info-v1i.tx_status;
+
+   if (hw-ep_shm_info[epid].tx_status_work ==
+   FJES_TX_DELAY_SEND_PENDING) {
+   hw-ep_shm_info[epid].tx.info-v1i.tx_status =
+   FJES_TX_DELAY_SEND_NONE;
+   }
+   }
+   }
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (epid == my_epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   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)) {
+   fjes_hw_raise_interrupt(hw, epid,
+   REG_ICTL_MASK_RX_DATA);
+   }
+   }
+
+   usleep_range(500, 1000);
+}
+
 static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
void *data, size_t len)
 {
@@ -416,6 +467,9 @@ static int fjes_tx_send(struct fjes_adapter *adapter, int 
dest,
 
adapter-hw.ep_shm_info[dest].tx.info-v1i.tx_status =
FJES_TX_DELAY_SEND_PENDING;
+   if (!work_pending(adapter-raise_intr_rxdata_task))
+   queue_work(adapter-txrx_wq,
+  adapter-raise_intr_rxdata_task);
 
retval = 0;
return retval;
@@ -630,6 +684,11 @@ static int fjes_probe(struct platform_device *plat_dev)
adapter-force_reset = false;
adapter-open_guard = false;
 
+   adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
+
+   INIT_WORK(adapter-raise_intr_rxdata_task,
+ fjes_raise_intr_rxdata_task);
+
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
hw-hw_res.start = res-start;
hw-hw_res.size = res-end - res-start + 1;
@@ -669,6 +728,10 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = adapter-hw;
 
+   cancel_work_sync(adapter-raise_intr_rxdata_task);
+   if (adapter-txrx_wq)
+   destroy_workqueue(adapter-txrx_wq);
+
unregister_netdev(netdev);
 
fjes_hw_exit(hw);
-- 
1.8.3.1

--
To unsubscribe from this list: send the line

[PATCH v3 02/22] fjes: Hardware initialization routine

2015-08-21 Thread Taku Izumi
This patch adds hardware initialization routine to be
invoked at driver's .probe routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/Makefile|   2 +-
 drivers/net/fjes/fjes.h  |   1 +
 drivers/net/fjes/fjes_hw.c   | 295 +++
 drivers/net/fjes/fjes_hw.h   | 251 
 drivers/net/fjes/fjes_regs.h | 102 +++
 5 files changed, 650 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/fjes/fjes_hw.c
 create mode 100644 drivers/net/fjes/fjes_hw.h
 create mode 100644 drivers/net/fjes/fjes_regs.h

diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 34bccba..753d52f 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-objs := fjes_main.o fjes_hw.o
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 52eb60b..15ded96 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -28,5 +28,6 @@
 
 extern char fjes_driver_name[];
 extern char fjes_driver_version[];
+extern const u32 fjes_support_mtu[];
 
 #endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
new file mode 100644
index 000..ae26638
--- /dev/null
+++ b/drivers/net/fjes/fjes_hw.c
@@ -0,0 +1,295 @@
+/*
+ *  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.
+ *
+ */
+
+#include fjes_hw.h
+#include fjes.h
+
+/* supported MTU list */
+const u32 fjes_support_mtu[] = {
+   FJES_MTU_DEFINE(8 * 1024),
+   FJES_MTU_DEFINE(16 * 1024),
+   FJES_MTU_DEFINE(32 * 1024),
+   FJES_MTU_DEFINE(64 * 1024),
+   0
+};
+
+u32 fjes_hw_rd32(struct fjes_hw *hw, u32 reg)
+{
+   u8 *base = hw-base;
+   u32 value = 0;
+
+   value = readl(base[reg]);
+
+   return value;
+}
+
+static u8 *fjes_hw_iomap(struct fjes_hw *hw)
+{
+   u8 *base;
+
+   if (!request_mem_region(hw-hw_res.start, hw-hw_res.size,
+   fjes_driver_name)) {
+   pr_err(request_mem_region failed\n);
+   return NULL;
+   }
+
+   base = (u8 *)ioremap_nocache(hw-hw_res.start, hw-hw_res.size);
+
+   return base;
+}
+
+int fjes_hw_reset(struct fjes_hw *hw)
+{
+   union REG_DCTL dctl;
+   int timeout;
+
+   dctl.reg = 0;
+   dctl.bits.reset = 1;
+   wr32(XSCT_DCTL, dctl.reg);
+
+   timeout = FJES_DEVICE_RESET_TIMEOUT * 1000;
+   dctl.reg = rd32(XSCT_DCTL);
+   while ((dctl.bits.reset == 1)  (timeout  0)) {
+   msleep(1000);
+   dctl.reg = rd32(XSCT_DCTL);
+   timeout -= 1000;
+   }
+
+   return timeout  0 ? 0 : -EIO;
+}
+
+static int fjes_hw_get_max_epid(struct fjes_hw *hw)
+{
+   union REG_MAX_EP info;
+
+   info.reg = rd32(XSCT_MAX_EP);
+
+   return info.bits.maxep;
+}
+
+static int fjes_hw_get_my_epid(struct fjes_hw *hw)
+{
+   union REG_OWNER_EPID info;
+
+   info.reg = rd32(XSCT_OWNER_EPID);
+
+   return info.bits.epid;
+}
+
+static int fjes_hw_alloc_shared_status_region(struct fjes_hw *hw)
+{
+   size_t size;
+
+   size = sizeof(struct fjes_device_shared_info) +
+   (sizeof(u8) * hw-max_epid);
+   hw-hw_info.share = kzalloc(size, GFP_KERNEL);
+   if (!hw-hw_info.share)
+   return -ENOMEM;
+
+   hw-hw_info.share-epnum = hw-max_epid;
+
+   return 0;
+}
+
+static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
+{
+   void *mem;
+
+   mem = vzalloc(EP_BUFFER_SIZE);
+   if (!mem)
+   return -ENOMEM;
+
+   epbh-buffer = mem;
+   epbh-size = EP_BUFFER_SIZE;
+
+   epbh-info = (union ep_buffer_info *)mem;
+   epbh-ring = (u8 *)(mem + sizeof(union ep_buffer_info));
+
+   return 0;
+}
+
+void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
+{
+   union ep_buffer_info *info = epbh-info;
+   u16 vlan_id[EP_BUFFER_SUPPORT_VLAN_MAX];
+   int i;
+
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++)
+   vlan_id[i] = info-v1i.vlan_id[i];
+
+   memset(info, 0, sizeof(union ep_buffer_info));
+
+   info-v1i.version = 0;  /* version 0

[PATCH v3 08/22] fjes: net_device_ops.ndo_start_xmit

2015-08-21 Thread Taku Izumi
This patch adds net_device_ops.ndo_start_xmit callback,
which is called when sending packets.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   1 +
 drivers/net/fjes/fjes_hw.c   |  55 ++
 drivers/net/fjes/fjes_hw.h   |  12 +++
 drivers/net/fjes/fjes_main.c | 177 +++
 4 files changed, 245 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index f182ed3..7af4304 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -29,6 +29,7 @@
 #define FJES_ACPI_SYMBOL   Extended Socket
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
+#define FJES_TX_RETRY_TIMEOUT  (100)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 1935f48..487dbc6 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -791,3 +791,58 @@ int fjes_hw_wait_epstop(struct fjes_hw *hw)
return (wait_time  FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)
? 0 : -EBUSY;
 }
+
+bool fjes_hw_check_epbuf_version(struct epbuf_handler *epbh, u32 version)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   return (info-common.version == version);
+}
+
+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));
+}
+
+bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   bool ret = false;
+   int i;
+
+   if (vlan_id == 0) {
+   ret = true;
+   } else {
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (vlan_id == info-v1i.vlan_id[i]) {
+   ret = true;
+   break;
+   }
+   }
+   }
+   return ret;
+}
+
+int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
+ void *frame, size_t size)
+{
+   union ep_buffer_info *info = epbh-info;
+   struct esmem_frame *ring_frame;
+
+   if (EP_RING_FULL(info-v1i.head, info-v1i.tail, info-v1i.count_max))
+   return -ENOBUFS;
+
+   ring_frame = (struct esmem_frame *)(epbh-ring[EP_RING_INDEX
+(info-v1i.tail - 1,
+ info-v1i.count_max) *
+info-v1i.frame_max]);
+
+   ring_frame-frame_size = size;
+   memcpy((void *)(ring_frame-frame_data), (void *)frame, size);
+
+   EP_RING_INDEX_INC(epbh-info-v1i.tail, info-v1i.count_max);
+
+   return 0;
+}
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 9b8df55..07e1226 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -50,6 +50,9 @@ struct fjes_hw;
 
 #define FJES_ZONING_ZONE_TYPE_NONE (0xFF)
 
+#define FJES_TX_DELAY_SEND_NONE(0)
+#define FJES_TX_DELAY_SEND_PENDING (1)
+
 #define FJES_RX_STOP_REQ_NONE  (0x0)
 #define FJES_RX_STOP_REQ_DONE  (0x1)
 #define FJES_RX_STOP_REQ_REQUEST   (0x2)
@@ -61,6 +64,11 @@ struct fjes_hw;
 
 #define EP_RING_NUM(buffer_size, frame_size) \
(u32)((buffer_size) / (frame_size))
+#define EP_RING_INDEX(_num, _max) (((_num) + (_max)) % (_max))
+#define EP_RING_INDEX_INC(_num, _max) \
+   ((_num) = EP_RING_INDEX((_num) + 1, (_max)))
+#define EP_RING_FULL(_head, _tail, _max)   \
+   (0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
 
 #define FJES_MTU_TO_BUFFER_SIZE(mtu) \
(ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
@@ -309,5 +317,9 @@ enum ep_partner_status
 
 bool fjes_hw_epid_is_same_zone(struct fjes_hw *, int);
 int fjes_hw_epid_is_shared(struct fjes_device_shared_info *, int);
+bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
+bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
+bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);
 
 #endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index bd50cbd..220ff3d 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -51,6 +51,7 @@ static int fjes_open(struct net_device *);
 static int fjes_close(struct net_device *);
 static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
+static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -212,6 +213,7 @@ static void fjes_free_irq(struct fjes_adapter *adapter)
 static const struct net_device_ops

[PATCH v3 06/22] fjes: buffer address regist/unregistration routine

2015-08-21 Thread Taku Izumi
This patch adds buffer address regist/unregistration routine.

This function is mainly invoked when network device's
activation (open) and deactivation (close)
in order to retist/unregist shared buffer address.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c | 186 +
 drivers/net/fjes/fjes_hw.h |   9 ++-
 2 files changed, 194 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index c31be7f..1e807df 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -452,6 +452,192 @@ int fjes_hw_request_info(struct fjes_hw *hw)
return result;
 }
 
+int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
+  struct ep_share_mem_info *buf_pair)
+{
+   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 timeout;
+   int i, idx;
+   void *addr;
+   int result;
+
+   if (test_bit(dest_epid, hw-hw_info.buffer_share_bit))
+   return 0;
+
+   memset(req_buf, 0, hw-hw_info.req_buf_size);
+   memset(res_buf, 0, hw-hw_info.res_buf_size);
+
+   req_buf-share_buffer.length = FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(
+   buf_pair-tx.size,
+   buf_pair-rx.size);
+   req_buf-share_buffer.epid = dest_epid;
+
+   idx = 0;
+   req_buf-share_buffer.buffer[idx++] = buf_pair-tx.size;
+   page_count = buf_pair-tx.size / EP_BUFFER_INFO_SIZE;
+   for (i = 0; i  page_count; i++) {
+   addr = ((u8 *)(buf_pair-tx.buffer)) +
+   (i * EP_BUFFER_INFO_SIZE);
+   req_buf-share_buffer.buffer[idx++] =
+   (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+   offset_in_page(addr));
+   }
+
+   req_buf-share_buffer.buffer[idx++] = buf_pair-rx.size;
+   page_count = buf_pair-rx.size / EP_BUFFER_INFO_SIZE;
+   for (i = 0; i  page_count; i++) {
+   addr = ((u8 *)(buf_pair-rx.buffer)) +
+   (i * EP_BUFFER_INFO_SIZE);
+   req_buf-share_buffer.buffer[idx++] =
+   (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+   offset_in_page(addr));
+   }
+
+   res_buf-share_buffer.length = 0;
+   res_buf-share_buffer.code = 0;
+
+   ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
+
+   timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
+   while ((ret == FJES_CMD_STATUS_NORMAL) 
+  (res_buf-share_buffer.length ==
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) 
+  (res_buf-share_buffer.code == FJES_CMD_REQ_RES_CODE_BUSY) 
+  (timeout  0)) {
+   msleep(200 + hw-my_epid * 20);
+   timeout -= (200 + hw-my_epid * 20);
+
+   res_buf-share_buffer.length = 0;
+   res_buf-share_buffer.code = 0;
+
+   ret = fjes_hw_issue_request_command(
+   hw, FJES_CMD_REQ_SHARE_BUFFER);
+   }
+
+   result = 0;
+
+   if (res_buf-share_buffer.length !=
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN)
+   result = -ENOMSG;
+   else if (ret == FJES_CMD_STATUS_NORMAL) {
+   switch (res_buf-share_buffer.code) {
+   case FJES_CMD_REQ_RES_CODE_NORMAL:
+   result = 0;
+   set_bit(dest_epid, hw-hw_info.buffer_share_bit);
+   break;
+   case FJES_CMD_REQ_RES_CODE_BUSY:
+   result = -EBUSY;
+   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_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
+{
+   union fjes_device_command_req *req_buf = hw-hw_info.req_buf;
+   union fjes_device_command_res *res_buf = hw-hw_info.res_buf;
+   struct fjes_device_shared_info *share = hw-hw_info.share;
+   enum fjes_dev_command_response_e ret

[PATCH v3 22/22] fjes: ethtool support

2015-08-21 Thread Taku Izumi
This patch adds implementation for ethtool support.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/Makefile   |   2 +-
 drivers/net/fjes/fjes.h |   2 +
 drivers/net/fjes/fjes_ethtool.c | 137 
 drivers/net/fjes/fjes_main.c|   1 +
 4 files changed, 141 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/fjes/fjes_ethtool.c

diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 753d52f..523e3d7 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-objs := fjes_main.o fjes_hw.o fjes_ethtool.o
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 57feee8..a592fe2 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -72,4 +72,6 @@ extern char fjes_driver_name[];
 extern char fjes_driver_version[];
 extern const u32 fjes_support_mtu[];
 
+void fjes_set_ethtool_ops(struct net_device *);
+
 #endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c
new file mode 100644
index 000..0119dd1
--- /dev/null
+++ b/drivers/net/fjes/fjes_ethtool.c
@@ -0,0 +1,137 @@
+/*
+ *  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.
+ *
+ */
+
+/* ethtool support for fjes */
+
+#include linux/vmalloc.h
+#include linux/netdevice.h
+#include linux/ethtool.h
+#include linux/platform_device.h
+
+#include fjes.h
+
+struct fjes_stats {
+   char stat_string[ETH_GSTRING_LEN];
+   int sizeof_stat;
+   int stat_offset;
+};
+
+#define FJES_STAT(name, stat) { \
+   .stat_string = name, \
+   .sizeof_stat = FIELD_SIZEOF(struct fjes_adapter, stat), \
+   .stat_offset = offsetof(struct fjes_adapter, stat) \
+}
+
+static const struct fjes_stats fjes_gstrings_stats[] = {
+   FJES_STAT(rx_packets, stats64.rx_packets),
+   FJES_STAT(tx_packets, stats64.tx_packets),
+   FJES_STAT(rx_bytes, stats64.rx_bytes),
+   FJES_STAT(tx_bytes, stats64.rx_bytes),
+   FJES_STAT(rx_dropped, stats64.rx_dropped),
+   FJES_STAT(tx_dropped, stats64.tx_dropped),
+};
+
+static void fjes_get_ethtool_stats(struct net_device *netdev,
+  struct ethtool_stats *stats, u64 *data)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   char *p;
+   int i;
+
+   for (i = 0; i  ARRAY_SIZE(fjes_gstrings_stats); i++) {
+   p = (char *)adapter + fjes_gstrings_stats[i].stat_offset;
+   data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64))
+   ? *(u64 *)p : *(u32 *)p;
+   }
+}
+
+static void fjes_get_strings(struct net_device *netdev,
+u32 stringset, u8 *data)
+{
+   u8 *p = data;
+   int i;
+
+   switch (stringset) {
+   case ETH_SS_STATS:
+   for (i = 0; i  ARRAY_SIZE(fjes_gstrings_stats); i++) {
+   memcpy(p, fjes_gstrings_stats[i].stat_string,
+  ETH_GSTRING_LEN);
+   p += ETH_GSTRING_LEN;
+   }
+   break;
+   }
+}
+
+static int fjes_get_sset_count(struct net_device *netdev, int sset)
+{
+   switch (sset) {
+   case ETH_SS_STATS:
+   return ARRAY_SIZE(fjes_gstrings_stats);
+   default:
+   return -EOPNOTSUPP;
+   }
+}
+
+static void fjes_get_drvinfo(struct net_device *netdev,
+struct ethtool_drvinfo *drvinfo)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct platform_device *plat_dev;
+
+   plat_dev = adapter-plat_dev;
+
+   strlcpy(drvinfo-driver, fjes_driver_name, sizeof(drvinfo-driver));
+   strlcpy(drvinfo-version, fjes_driver_version,
+   sizeof(drvinfo-version));
+
+   strlcpy(drvinfo-fw_version, none, sizeof(drvinfo-fw_version));
+   snprintf(drvinfo-bus_info, sizeof(drvinfo-bus_info),
+platform:%s, plat_dev-name);
+   drvinfo-regdump_len = 0;
+   drvinfo-eedump_len = 0;
+}
+
+static int fjes_get_settings(struct net_device *netdev,
+struct ethtool_cmd *ecmd

[PATCH v3 15/22] fjes: net_device_ops.ndo_vlan_rx_add/kill_vid

2015-08-21 Thread Taku Izumi
This patch adds net_device_ops.ndo_vlan_rx_add_vid and
net_device_ops.ndo_vlan_rx_kill_vid callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 27 +++
 drivers/net/fjes/fjes_hw.h   |  2 ++
 drivers/net/fjes/fjes_main.c | 40 
 3 files changed, 69 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 3c96d06..4a4b750 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -825,6 +825,33 @@ bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 
vlan_id)
return ret;
 }
 
+bool fjes_hw_set_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (info-v1i.vlan_id[i] == 0) {
+   info-v1i.vlan_id[i] = vlan_id;
+   return true;
+   }
+   }
+   return false;
+}
+
+void fjes_hw_del_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+
+   if (0 != vlan_id) {
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (vlan_id == info-v1i.vlan_id[i])
+   info-v1i.vlan_id[i] = 0;
+   }
+   }
+}
+
 bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
 {
union ep_buffer_info *info = epbh-info;
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 3511db2..95e632b 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -322,6 +322,8 @@ int fjes_hw_epid_is_shared(struct fjes_device_shared_info 
*, int);
 bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
 bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
 bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+bool fjes_hw_set_vlan_id(struct epbuf_handler *, u16);
+void fjes_hw_del_vlan_id(struct epbuf_handler *, u16);
 bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
 void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
 void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 94ccc11..4a4ce81 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -58,6 +58,8 @@ static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 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 void fjes_tx_retry(struct net_device *);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -226,6 +228,8 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_get_stats64= fjes_get_stats64,
.ndo_change_mtu = fjes_change_mtu,
.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,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -751,6 +755,42 @@ static int fjes_change_mtu(struct net_device *netdev, int 
new_mtu)
return -EINVAL;
 }
 
+static int fjes_vlan_rx_add_vid(struct net_device *netdev,
+   __be16 proto, u16 vid)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   bool ret = true;
+   int epid;
+
+   for (epid = 0; epid  adapter-hw.max_epid; epid++) {
+   if (epid == adapter-hw.my_epid)
+   continue;
+
+   if (!fjes_hw_check_vlan_id(
+   adapter-hw.ep_shm_info[epid].tx, vid))
+   ret = fjes_hw_set_vlan_id(
+   adapter-hw.ep_shm_info[epid].tx, vid);
+   }
+
+   return ret ? 0 : -ENOSPC;
+}
+
+static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
+__be16 proto, u16 vid)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   int epid;
+
+   for (epid = 0; epid  adapter-hw.max_epid; epid++) {
+   if (epid == adapter-hw.my_epid)
+   continue;
+
+   fjes_hw_del_vlan_id(adapter-hw.ep_shm_info[epid].tx, vid);
+   }
+
+   return 0;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 14/22] fjes: net_device_ops.ndo_tx_timeout

2015-08-21 Thread Taku Izumi
This patch adds net_device_ops.ndo_tx_timeout callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 519976c..94ccc11 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -58,6 +58,7 @@ static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
 static int fjes_change_mtu(struct net_device *, int);
+static void fjes_tx_retry(struct net_device *);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -224,6 +225,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_start_xmit = fjes_xmit_frame,
.ndo_get_stats64= fjes_get_stats64,
.ndo_change_mtu = fjes_change_mtu,
+   .ndo_tx_timeout = fjes_tx_retry,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -705,6 +707,13 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
return ret;
 }
 
+static void fjes_tx_retry(struct net_device *netdev)
+{
+   struct netdev_queue *queue = netdev_get_tx_queue(netdev, 0);
+
+   netif_tx_wake_queue(queue);
+}
+
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
 {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 16/22] fjes: interrupt_watch_task

2015-08-21 Thread Taku Izumi
This patch adds interrupt_watch_task.
This task is used to prevent delay of interrupts.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  5 +
 drivers/net/fjes/fjes_main.c | 40 +++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index b04ea9d..1743dbb 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -32,6 +32,7 @@
 #define FJES_TX_RETRY_TIMEOUT  (100)
 #define FJES_TX_TX_STALL_TIMEOUT   (FJES_TX_RETRY_INTERVAL / 2)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
+#define FJES_IRQ_WATCH_DELAY   (HZ)
 
 /* board specific private data structure */
 struct fjes_adapter {
@@ -52,10 +53,14 @@ struct fjes_adapter {
bool irq_registered;
 
struct workqueue_struct *txrx_wq;
+   struct workqueue_struct *control_wq;
 
struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
+   struct delayed_work interrupt_watch_task;
+   bool interrupt_watch_enable;
+
struct fjes_hw hw;
 };
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 4a4ce81..5fce33d 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -71,7 +71,7 @@ static int fjes_remove(struct platform_device *);
 
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
-
+static void fjes_irq_watch_task(struct work_struct *);
 static void fjes_rx_irq(struct fjes_adapter *, int);
 static int fjes_poll(struct napi_struct *, int);
 
@@ -197,6 +197,13 @@ static int fjes_request_irq(struct fjes_adapter *adapter)
struct net_device *netdev = adapter-netdev;
int result = -1;
 
+   adapter-interrupt_watch_enable = true;
+   if (!delayed_work_pending(adapter-interrupt_watch_task)) {
+   queue_delayed_work(adapter-control_wq,
+  adapter-interrupt_watch_task,
+  FJES_IRQ_WATCH_DELAY);
+   }
+
if (!adapter-irq_registered) {
result = request_irq(adapter-hw.hw_res.irq, fjes_intr,
 IRQF_SHARED, netdev-name, adapter);
@@ -213,6 +220,9 @@ static void fjes_free_irq(struct fjes_adapter *adapter)
 {
struct fjes_hw *hw = adapter-hw;
 
+   adapter-interrupt_watch_enable = false;
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
+
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
if (adapter-irq_registered) {
@@ -297,6 +307,7 @@ static int fjes_close(struct net_device *netdev)
 
fjes_free_irq(adapter);
 
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
 
@@ -996,11 +1007,15 @@ static int fjes_probe(struct platform_device *plat_dev)
adapter-open_guard = false;
 
adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
+   adapter-control_wq = create_workqueue(DRV_NAME /control);
 
INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
 
+   INIT_DELAYED_WORK(adapter-interrupt_watch_task, fjes_irq_watch_task);
+   adapter-interrupt_watch_enable = false;
+
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
hw-hw_res.start = res-start;
hw-hw_res.size = res-end - res-start + 1;
@@ -1040,8 +1055,11 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = adapter-hw;
 
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
+   if (adapter-control_wq)
+   destroy_workqueue(adapter-control_wq);
if (adapter-txrx_wq)
destroy_workqueue(adapter-txrx_wq);
 
@@ -1077,6 +1095,26 @@ static void fjes_netdev_setup(struct net_device *netdev)
netdev-features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
 }
 
+static void fjes_irq_watch_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(to_delayed_work(work),
+   struct fjes_adapter, interrupt_watch_task);
+
+   local_irq_disable();
+   fjes_intr(adapter-hw.hw_res.irq, adapter);
+   local_irq_enable();
+
+   if (fjes_rxframe_search_exist(adapter, 0) = 0)
+   napi_schedule(adapter-napi);
+
+   if (adapter-interrupt_watch_enable) {
+   if (!delayed_work_pending(adapter-interrupt_watch_task))
+   queue_delayed_work(adapter-control_wq,
+  adapter-interrupt_watch_task

[PATCH v3 18/22] fjes: unshare_watch_task

2015-08-21 Thread Taku Izumi
This patch adds unshare_watch_task.
Shared buffer's status can be changed into unshared.
This task is used to monitor shared buffer's status.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   3 ++
 drivers/net/fjes/fjes_main.c | 126 +++
 2 files changed, 129 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index d31d4c3..57feee8 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -59,6 +59,9 @@ struct fjes_adapter {
struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
+   struct work_struct unshare_watch_task;
+   unsigned long unshare_watch_bitmask;
+
struct delayed_work interrupt_watch_task;
bool interrupt_watch_enable;
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index caecfb3..c47ecf3 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -73,6 +73,7 @@ static int fjes_remove(struct platform_device *);
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
 static void fjes_irq_watch_task(struct work_struct *);
+static void fjes_watch_unshare_task(struct work_struct *);
 static void fjes_rx_irq(struct fjes_adapter *, int);
 static int fjes_poll(struct napi_struct *, int);
 
@@ -309,6 +310,8 @@ static int fjes_close(struct net_device *netdev)
fjes_free_irq(adapter);
 
cancel_delayed_work_sync(adapter-interrupt_watch_task);
+   cancel_work_sync(adapter-unshare_watch_task);
+   adapter-unshare_watch_bitmask = 0;
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
 
@@ -1025,6 +1028,8 @@ static int fjes_probe(struct platform_device *plat_dev)
INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
+   INIT_WORK(adapter-unshare_watch_task, fjes_watch_unshare_task);
+   adapter-unshare_watch_bitmask = 0;
 
INIT_DELAYED_WORK(adapter-interrupt_watch_task, fjes_irq_watch_task);
adapter-interrupt_watch_enable = false;
@@ -1069,6 +1074,7 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_hw *hw = adapter-hw;
 
cancel_delayed_work_sync(adapter-interrupt_watch_task);
+   cancel_work_sync(adapter-unshare_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
if (adapter-control_wq)
@@ -1128,6 +1134,126 @@ static void fjes_irq_watch_task(struct work_struct 
*work)
}
 }
 
+static void fjes_watch_unshare_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter =
+   container_of(work, struct fjes_adapter, unshare_watch_task);
+
+   struct net_device *netdev = adapter-netdev;
+   struct fjes_hw *hw = adapter-hw;
+
+   int unshare_watch, unshare_reserve;
+   int max_epid, my_epid, epidx;
+   int stop_req, stop_req_done;
+   ulong unshare_watch_bitmask;
+   int wait_time = 0;
+   int is_shared;
+   int ret;
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   unshare_watch_bitmask = adapter-unshare_watch_bitmask;
+   adapter-unshare_watch_bitmask = 0;
+
+   while ((unshare_watch_bitmask || hw-txrx_stop_req_bit) 
+  (wait_time  3000)) {
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+
+   is_shared = fjes_hw_epid_is_shared(hw-hw_info.share,
+  epidx);
+
+   stop_req = test_bit(epidx, hw-txrx_stop_req_bit);
+
+   stop_req_done = 
hw-ep_shm_info[epidx].rx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_DONE;
+
+   unshare_watch = test_bit(epidx, unshare_watch_bitmask);
+
+   unshare_reserve = test_bit(epidx,
+  
hw-hw_info.buffer_unshare_reserve_bit);
+
+   if ((!stop_req ||
+(is_shared  (!is_shared || !stop_req_done))) 
+   (is_shared || !unshare_watch || !unshare_reserve))
+   continue;
+
+   mutex_lock(hw-hw_info.lock);
+   ret = fjes_hw_unregister_buff_addr(hw, epidx);
+   switch (ret) {
+   case 0:
+   break;
+   case -ENOMSG:
+   case -EBUSY:
+   default:
+   if (!work_pending(
+   adapter-force_close_task

[PATCH v3 04/22] fjes: platform_driver's .probe and .remove routine

2015-08-21 Thread Taku Izumi
This patch implements platform_driver's .probe and .remove
routine, and also adds board specific private data structure.

This driver registers net_device at platform_driver's .probe
routine and unregisters net_device at its .remove routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  | 25 
 drivers/net/fjes/fjes_main.c | 94 
 2 files changed, 119 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 15ded96..54bc189 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -24,7 +24,32 @@
 
 #include linux/acpi.h
 
+#include fjes_hw.h
+
 #define FJES_ACPI_SYMBOL   Extended Socket
+#define FJES_MAX_QUEUES1
+#define FJES_TX_RETRY_INTERVAL (20 * HZ)
+
+/* board specific private data structure */
+struct fjes_adapter {
+   struct net_device *netdev;
+   struct platform_device *plat_dev;
+
+   struct napi_struct napi;
+   struct rtnl_link_stats64 stats64;
+
+   unsigned int tx_retry_count;
+   unsigned long tx_start_jiffies;
+   unsigned long rx_last_jiffies;
+   bool unset_rx_last;
+
+   bool force_reset;
+   bool open_guard;
+
+   bool irq_registered;
+
+   struct fjes_hw hw;
+};
 
 extern char fjes_driver_name[];
 extern char fjes_driver_version[];
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 9517666..45a8b9c 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -23,6 +23,7 @@
 #include linux/types.h
 #include linux/nls.h
 #include linux/platform_device.h
+#include linux/netdevice.h
 
 #include fjes.h
 
@@ -49,6 +50,9 @@ static acpi_status fjes_get_acpi_resource(struct 
acpi_resource *, void*);
 static int fjes_probe(struct platform_device *);
 static int fjes_remove(struct platform_device *);
 
+static int fjes_sw_init(struct fjes_adapter *);
+static void fjes_netdev_setup(struct net_device *);
+
 static const struct acpi_device_id fjes_acpi_ids[] = {
{PNP0C02, 0},
{, 0},
@@ -166,18 +170,108 @@ fjes_get_acpi_resource(struct acpi_resource *acpi_res, 
void *data)
return AE_OK;
 }
 
+static const struct net_device_ops fjes_netdev_ops = {
+};
+
 /* fjes_probe - Device Initialization Routine */
 static int fjes_probe(struct platform_device *plat_dev)
 {
+   struct fjes_adapter *adapter;
+   struct net_device *netdev;
+   struct resource *res;
+   struct fjes_hw *hw;
+   int err;
+
+   err = -ENOMEM;
+   netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), es%d,
+NET_NAME_UNKNOWN, fjes_netdev_setup,
+FJES_MAX_QUEUES);
+
+   if (!netdev)
+   goto err_out;
+
+   SET_NETDEV_DEV(netdev, plat_dev-dev);
+
+   dev_set_drvdata(plat_dev-dev, netdev);
+   adapter = netdev_priv(netdev);
+   adapter-netdev = netdev;
+   adapter-plat_dev = plat_dev;
+   hw = adapter-hw;
+   hw-back = adapter;
+
+   /* setup the private structure */
+   err = fjes_sw_init(adapter);
+   if (err)
+   goto err_free_netdev;
+
+   adapter-force_reset = false;
+   adapter-open_guard = false;
+
+   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.irq = platform_get_irq(plat_dev, 0);
+   err = fjes_hw_init(adapter-hw);
+   if (err)
+   goto err_free_netdev;
+
+   /* setup MAC address (02:00:00:00:00:[epid])*/
+   netdev-dev_addr[0] = 2;
+   netdev-dev_addr[1] = 0;
+   netdev-dev_addr[2] = 0;
+   netdev-dev_addr[3] = 0;
+   netdev-dev_addr[4] = 0;
+   netdev-dev_addr[5] = hw-my_epid; /* EPID */
+
+   err = register_netdev(netdev);
+   if (err)
+   goto err_hw_exit;
+
+   netif_carrier_off(netdev);
+
return 0;
+
+err_hw_exit:
+   fjes_hw_exit(adapter-hw);
+err_free_netdev:
+   free_netdev(netdev);
+err_out:
+   return err;
 }
 
 /* fjes_remove - Device Removal Routine */
 static int fjes_remove(struct platform_device *plat_dev)
 {
+   struct net_device *netdev = dev_get_drvdata(plat_dev-dev);
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = adapter-hw;
+
+   unregister_netdev(netdev);
+
+   fjes_hw_exit(hw);
+
+   free_netdev(netdev);
+
return 0;
 }
 
+static int fjes_sw_init(struct fjes_adapter *adapter)
+{
+   return 0;
+}
+
+/* fjes_netdev_setup - netdevice initialization routine */
+static void fjes_netdev_setup(struct net_device *netdev)
+{
+   ether_setup(netdev);
+
+   netdev-watchdog_timeo = FJES_TX_RETRY_INTERVAL;
+   netdev-netdev_ops = fjes_netdev_ops;
+   netdev-mtu = fjes_support_mtu[0];
+   netdev-flags |= IFF_BROADCAST;
+   netdev-features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER

[PATCH v3 07/22] fjes: net_device_ops.ndo_open and .ndo_stop

2015-08-21 Thread Taku Izumi
This patch adds net_device_ops.ndo_open and .ndo_stop
callback. These function is called when network device
activation and deactivation.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   1 +
 drivers/net/fjes/fjes_hw.c   | 145 +
 drivers/net/fjes/fjes_hw.h   |  30 ++
 drivers/net/fjes/fjes_main.c | 246 +++
 drivers/net/fjes/fjes_regs.h |  17 +++
 5 files changed, 439 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 54bc189..f182ed3 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -29,6 +29,7 @@
 #define FJES_ACPI_SYMBOL   Extended Socket
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
+#define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
 struct fjes_adapter {
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 1e807df..1935f48 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -638,6 +638,25 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int 
dest_epid)
return result;
 }
 
+int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid,
+   enum REG_ICTL_MASK  mask)
+{
+   u32 ig = mask | dest_epid;
+
+   wr32(XSCT_IG, cpu_to_le32(ig));
+
+   return 0;
+}
+
+u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw)
+{
+   u32 cur_is;
+
+   cur_is = rd32(XSCT_IS);
+
+   return cur_is;
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
@@ -646,3 +665,129 @@ void fjes_hw_set_irqmask(struct fjes_hw *hw,
else
wr32(XSCT_IMC, intr_mask);
 }
+
+bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid)
+{
+   if (epid = hw-max_epid)
+   return false;
+
+   if ((hw-ep_shm_info[epid].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (hw-ep_shm_info[hw-my_epid].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE))
+   return false;
+   else
+   return (hw-ep_shm_info[epid].zone ==
+   hw-ep_shm_info[hw-my_epid].zone);
+}
+
+int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share,
+  int dest_epid)
+{
+   int value = false;
+
+   if (dest_epid  share-epnum)
+   value = share-ep_status[dest_epid];
+
+   return value;
+}
+
+static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid)
+{
+   return test_bit(src_epid, hw-txrx_stop_req_bit);
+}
+
+static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid)
+{
+   return (hw-ep_shm_info[src_epid].tx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_DONE);
+}
+
+enum ep_partner_status
+fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
+{
+   enum ep_partner_status status;
+
+   if (fjes_hw_epid_is_shared(hw-hw_info.share, epid)) {
+   if (fjes_hw_epid_is_stop_requested(hw, epid)) {
+   status = EP_PARTNER_WAITING;
+   } else {
+   if (fjes_hw_epid_is_stop_process_done(hw, epid))
+   status = EP_PARTNER_COMPLETE;
+   else
+   status = EP_PARTNER_SHARED;
+   }
+   } else {
+   status = EP_PARTNER_UNSHARE;
+   }
+
+   return status;
+}
+
+void fjes_hw_raise_epstop(struct fjes_hw *hw)
+{
+   enum ep_partner_status status;
+   int epidx;
+
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+
+   status = fjes_hw_get_partner_ep_status(hw, epidx);
+   switch (status) {
+   case EP_PARTNER_SHARED:
+   fjes_hw_raise_interrupt(hw, epidx,
+   REG_ICTL_MASK_TXRX_STOP_REQ);
+   break;
+   default:
+   break;
+   }
+
+   set_bit(epidx, hw-hw_info.buffer_unshare_reserve_bit);
+   set_bit(epidx, hw-txrx_stop_req_bit);
+
+   hw-ep_shm_info[epidx].tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_REQUEST;
+   }
+}
+
+int fjes_hw_wait_epstop(struct fjes_hw *hw)
+{
+   enum ep_partner_status status;
+   union ep_buffer_info *info;
+   int wait_time = 0;
+   int epidx;
+
+   while (hw-hw_info.buffer_unshare_reserve_bit 
+  (wait_time  FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) {
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+   status = fjes_hw_epid_is_shared(hw

[PATCH v3 03/22] fjes: Hardware cleanup routine

2015-08-21 Thread Taku Izumi
This patch adds hardware cleanup routine to be
invoked at driver's .remove routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c | 66 ++
 drivers/net/fjes/fjes_hw.h |  1 +
 2 files changed, 67 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index ae26638..757cece 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -56,6 +56,12 @@ static u8 *fjes_hw_iomap(struct fjes_hw *hw)
return base;
 }
 
+static void fjes_hw_iounmap(struct fjes_hw *hw)
+{
+   iounmap(hw-base);
+   release_mem_region(hw-hw_res.start, hw-hw_res.size);
+}
+
 int fjes_hw_reset(struct fjes_hw *hw)
 {
union REG_DCTL dctl;
@@ -109,6 +115,12 @@ static int fjes_hw_alloc_shared_status_region(struct 
fjes_hw *hw)
return 0;
 }
 
+static void fjes_hw_free_shared_status_region(struct fjes_hw *hw)
+{
+   kfree(hw-hw_info.share);
+   hw-hw_info.share = NULL;
+}
+
 static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
 {
void *mem;
@@ -126,6 +138,18 @@ static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
return 0;
 }
 
+static void fjes_hw_free_epbuf(struct epbuf_handler *epbh)
+{
+   if (epbh-buffer)
+   vfree(epbh-buffer);
+
+   epbh-buffer = NULL;
+   epbh-size = 0;
+
+   epbh-info = NULL;
+   epbh-ring = NULL;
+}
+
 void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
 {
union ep_buffer_info *info = epbh-info;
@@ -258,6 +282,32 @@ static int fjes_hw_setup(struct fjes_hw *hw)
return 0;
 }
 
+static void fjes_hw_cleanup(struct fjes_hw *hw)
+{
+   int epidx;
+
+   if (!hw-ep_shm_info)
+   return;
+
+   fjes_hw_free_shared_status_region(hw);
+
+   kfree(hw-hw_info.req_buf);
+   hw-hw_info.req_buf = NULL;
+
+   kfree(hw-hw_info.res_buf);
+   hw-hw_info.res_buf = NULL;
+
+   for (epidx = 0; epidx  hw-max_epid ; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+   fjes_hw_free_epbuf(hw-ep_shm_info[epidx].tx);
+   fjes_hw_free_epbuf(hw-ep_shm_info[epidx].rx);
+   }
+
+   kfree(hw-ep_shm_info);
+   hw-ep_shm_info = NULL;
+}
+
 int fjes_hw_init(struct fjes_hw *hw)
 {
int ret;
@@ -285,6 +335,22 @@ int fjes_hw_init(struct fjes_hw *hw)
return ret;
 }
 
+void fjes_hw_exit(struct fjes_hw *hw)
+{
+   int ret;
+
+   if (hw-base) {
+   ret = fjes_hw_reset(hw);
+   if (ret)
+   pr_err(%s: reset error, __func__);
+
+   fjes_hw_iounmap(hw);
+   hw-base = NULL;
+   }
+
+   fjes_hw_cleanup(hw);
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 836ebe2..1b3e9ca 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -241,6 +241,7 @@ struct fjes_hw {
 };
 
 int fjes_hw_init(struct fjes_hw *);
+void fjes_hw_exit(struct fjes_hw *);
 int fjes_hw_reset(struct fjes_hw *);
 
 void fjes_hw_init_command_registers(struct fjes_hw *,
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 20/22] fjes: epstop_task

2015-08-21 Thread Taku Izumi
This patch adds epstop_task.
This task is used to process other receiver's
cancellation request.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 31 +++
 drivers/net/fjes/fjes_hw.h   |  1 +
 drivers/net/fjes/fjes_main.c |  1 +
 3 files changed, 33 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 4525d36..b5f4a78 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -23,6 +23,7 @@
 #include fjes.h
 
 static void fjes_hw_update_zone_task(struct work_struct *);
+static void fjes_hw_epstop_task(struct work_struct *);
 
 /* supported MTU list */
 const u32 fjes_support_mtu[] = {
@@ -325,6 +326,7 @@ int fjes_hw_init(struct fjes_hw *hw)
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
INIT_WORK(hw-update_zone_task, fjes_hw_update_zone_task);
+   INIT_WORK(hw-epstop_task, fjes_hw_epstop_task);
 
mutex_init(hw-hw_info.lock);
 
@@ -355,6 +357,7 @@ void fjes_hw_exit(struct fjes_hw *hw)
fjes_hw_cleanup(hw);
 
cancel_work_sync(hw-update_zone_task);
+   cancel_work_sync(hw-epstop_task);
 }
 
 static enum fjes_dev_command_response_e
@@ -1092,3 +1095,31 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
   adapter-unshare_watch_task);
}
 }
+
+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;
+
+   ulong remain_bit;
+   int epid_bit;
+
+   while ((remain_bit = hw-epstop_req_bit)) {
+   for (epid_bit = 0; remain_bit; remain_bit = 1, epid_bit++) {
+   if (remain_bit  1) {
+   hw-ep_shm_info[epid_bit].
+   tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_DONE;
+
+   clear_bit(epid_bit, hw-epstop_req_bit);
+   set_bit(epid_bit,
+   adapter-unshare_watch_bitmask);
+
+   if (!work_pending(adapter-unshare_watch_task))
+   queue_work(
+   adapter-control_wq,
+   adapter-unshare_watch_task);
+   }
+   }
+   }
+}
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index e59b737..6d57b89 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -283,6 +283,7 @@ struct fjes_hw {
unsigned long txrx_stop_req_bit;
unsigned long epstop_req_bit;
struct work_struct update_zone_task;
+   struct work_struct epstop_task;
 
int my_epid;
int max_epid;
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 8e3a084..5e77d0c 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -316,6 +316,7 @@ static int fjes_close(struct net_device *netdev)
cancel_work_sync(adapter-tx_stall_task);
 
cancel_work_sync(hw-update_zone_task);
+   cancel_work_sync(hw-epstop_task);
 
fjes_hw_wait_epstop(hw);
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 01/22] fjes: Introduce FUJITSU Extended Socket Network Device driver

2015-08-21 Thread Taku Izumi
This patch adds the basic code of FUJITSU Extended Socket
Network Device driver.

When PNP0C02 is found in ACPI DSDT, it evaluates _STR
to check if PNP0C02 is for Extended Socket device driver
and retrieves ACPI resource information. Then creates
platform_device.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/Kconfig  |   7 ++
 drivers/net/Makefile |   2 +
 drivers/net/fjes/Makefile|  30 ++
 drivers/net/fjes/fjes.h  |  32 +++
 drivers/net/fjes/fjes_main.c | 213 +++
 5 files changed, 284 insertions(+)
 create mode 100644 drivers/net/fjes/Makefile
 create mode 100644 drivers/net/fjes/fjes.h
 create mode 100644 drivers/net/fjes/fjes_main.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c18f9e6..c78a81a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -407,6 +407,13 @@ config VMXNET3
  To compile this driver as a module, choose M here: the
  module will be called vmxnet3.
 
+config FUJITSU_ES
+   tristate FUJITSU Extended Socket Network Device driver
+   depends on ACPI
+   help
+ This driver provides support for Extended Socket network device
+  on Extended Partitioning of FUJITSU PRIMEQUEST 2000 E2 series.
+
 source drivers/net/hyperv/Kconfig
 
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c12cb22..677c7b4 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -67,3 +67,5 @@ obj-$(CONFIG_USB_NET_DRIVERS) += usb/
 
 obj-$(CONFIG_HYPERV_NET) += hyperv/
 obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
+
+obj-$(CONFIG_FUJITSU_ES) += fjes/
diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
new file mode 100644
index 000..34bccba
--- /dev/null
+++ b/drivers/net/fjes/Makefile
@@ -0,0 +1,30 @@
+
+#
+# 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.
+#
+
+
+
+#
+# Makefile for the FUJITSU Extended Socket network device driver
+#
+
+obj-$(CONFIG_FUJITSU_ES) += fjes.o
+
+fjes-objs := fjes_main.o
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
new file mode 100644
index 000..52eb60b
--- /dev/null
+++ b/drivers/net/fjes/fjes.h
@@ -0,0 +1,32 @@
+/*
+ *  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_H_
+#define FJES_H_
+
+#include linux/acpi.h
+
+#define FJES_ACPI_SYMBOL   Extended Socket
+
+extern char fjes_driver_name[];
+extern char fjes_driver_version[];
+
+#endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
new file mode 100644
index 000..9517666
--- /dev/null
+++ b/drivers/net/fjes/fjes_main.c
@@ -0,0 +1,213 @@
+/*
+ *  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

[PATCH v3 00/22] FUJITSU Extended Socket network device driver

2015-08-21 Thread Taku Izumi
This patchsets adds FUJITSU Extended Socket network device driver.
Extended Socket network device is a shared memory based high-speed
network interface between Extended Partitions of PRIMEQUEST 2000 E2
series.

You can get some information about Extended Partition and Extended
Socket by referring the following manual.

http://globalsp.ts.fujitsu.com/dmsp/Publications/public/CA92344-0537.pdf
3.2.1 Extended Partitioning
3.2.2 Extended Socke

v2.2 - v3:
   - Fix up according to David's comment (No functional change)


Taku Izumi (22):
  fjes: Introduce FUJITSU Extended Socket Network Device driver
  fjes: Hardware initialization routine
  fjes: Hardware cleanup routine
  fjes: platform_driver's .probe and .remove routine
  fjes: ES information acquisition routine
  fjes: buffer address regist/unregistration routine
  fjes: net_device_ops.ndo_open and .ndo_stop
  fjes: net_device_ops.ndo_start_xmit
  fjes: raise_intr_rxdata_task
  fjes: tx_stall_task
  fjes: NAPI polling function
  fjes: net_device_ops.ndo_get_stats64
  fjes: net_device_ops.ndo_change_mtu
  fjes: net_device_ops.ndo_tx_timeout
  fjes: net_device_ops.ndo_vlan_rx_add/kill_vid
  fjes: interrupt_watch_task
  fjes: force_close_task
  fjes: unshare_watch_task
  fjes: update_zone_task
  fjes: epstop_task
  fjes: handle receive cancellation request interrupt
  fjes: ethtool support

 drivers/net/Kconfig |7 +
 drivers/net/Makefile|2 +
 drivers/net/fjes/Makefile   |   30 +
 drivers/net/fjes/fjes.h |   77 +++
 drivers/net/fjes/fjes_ethtool.c |  137 
 drivers/net/fjes/fjes_hw.c  | 1125 +++
 drivers/net/fjes/fjes_hw.h  |  334 ++
 drivers/net/fjes/fjes_main.c| 1383 +++
 drivers/net/fjes/fjes_regs.h|  142 
 9 files changed, 3237 insertions(+)
 create mode 100644 drivers/net/fjes/Makefile
 create mode 100644 drivers/net/fjes/fjes.h
 create mode 100644 drivers/net/fjes/fjes_ethtool.c
 create mode 100644 drivers/net/fjes/fjes_hw.c
 create mode 100644 drivers/net/fjes/fjes_hw.h
 create mode 100644 drivers/net/fjes/fjes_main.c
 create mode 100644 drivers/net/fjes/fjes_regs.h

-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 11/22] fjes: NAPI polling function

2015-08-21 Thread Taku Izumi
This patch adds NAPI polling function and receive related work.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   |  40 ++
 drivers/net/fjes/fjes_hw.h   |   5 ++
 drivers/net/fjes/fjes_main.c | 171 ++-
 3 files changed, 214 insertions(+), 2 deletions(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 487dbc6..3c96d06 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -825,6 +825,46 @@ bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 
vlan_id)
return ret;
 }
 
+bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   if (info-v1i.count_max == 0)
+   return true;
+
+   return EP_RING_EMPTY(info-v1i.head, info-v1i.tail,
+info-v1i.count_max);
+}
+
+void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *epbh,
+  size_t *psize)
+{
+   union ep_buffer_info *info = epbh-info;
+   struct esmem_frame *ring_frame;
+   void *frame;
+
+   ring_frame = (struct esmem_frame *)(epbh-ring[EP_RING_INDEX
+(info-v1i.head,
+ info-v1i.count_max) *
+info-v1i.frame_max]);
+
+   *psize = (size_t)ring_frame-frame_size;
+
+   frame = ring_frame-frame_data;
+
+   return frame;
+}
+
+void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *epbh)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   if (fjes_hw_epbuf_rx_is_empty(epbh))
+   return;
+
+   EP_RING_INDEX_INC(epbh-info-v1i.head, info-v1i.count_max);
+}
+
 int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
  void *frame, size_t size)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 07e1226..3511db2 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -69,6 +69,8 @@ struct fjes_hw;
((_num) = EP_RING_INDEX((_num) + 1, (_max)))
 #define EP_RING_FULL(_head, _tail, _max)   \
(0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
+#define EP_RING_EMPTY(_head, _tail, _max) \
+   (1 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
 
 #define FJES_MTU_TO_BUFFER_SIZE(mtu) \
(ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
@@ -320,6 +322,9 @@ int fjes_hw_epid_is_shared(struct fjes_device_shared_info 
*, int);
 bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
 bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
 bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
+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);
 
 #endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index ac1e076..6194962 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -66,6 +66,9 @@ static int fjes_remove(struct platform_device *);
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
 
+static void fjes_rx_irq(struct fjes_adapter *, int);
+static int fjes_poll(struct napi_struct *, int);
+
 static const struct acpi_device_id fjes_acpi_ids[] = {
{PNP0C02, 0},
{, 0},
@@ -235,6 +238,8 @@ static int fjes_open(struct net_device *netdev)
hw-txrx_stop_req_bit = 0;
hw-epstop_req_bit = 0;
 
+   napi_enable(adapter-napi);
+
fjes_hw_capture_interrupt_status(hw);
 
result = fjes_request_irq(adapter);
@@ -250,6 +255,7 @@ static int fjes_open(struct net_device *netdev)
 
 err_req_irq:
fjes_free_irq(adapter);
+   napi_disable(adapter-napi);
 
 err_setup_res:
fjes_free_resources(adapter);
@@ -268,6 +274,8 @@ static int fjes_close(struct net_device *netdev)
 
fjes_hw_raise_epstop(hw);
 
+   napi_disable(adapter-napi);
+
for (epidx = 0; epidx  hw-max_epid; epidx++) {
if (epidx == hw-my_epid)
continue;
@@ -701,14 +709,167 @@ 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_IS_MASK_IS_ASSERT) {
+   if (icr  REG_ICTL_MASK_RX_DATA)
+   fjes_rx_irq(adapter, icr  REG_IS_MASK_EPID);
+
ret = IRQ_HANDLED;
-   else
+   } else {
ret = IRQ_NONE;
+   }
 
return ret;
 }
 
+static int fjes_rxframe_search_exist(struct fjes_adapter *adapter,
+int start_epid)
+{
+   struct fjes_hw *hw = adapter-hw;
+   enum

[PATCH v3 13/22] fjes: net_device_ops.ndo_change_mtu

2015-08-21 Thread Taku Izumi
This patch adds net_device_ops.ndo_change_mtu.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 20feb3e..519976c 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -57,6 +57,7 @@ static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
+static int fjes_change_mtu(struct net_device *, int);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -222,6 +223,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_stop   = fjes_close,
.ndo_start_xmit = fjes_xmit_frame,
.ndo_get_stats64= fjes_get_stats64,
+   .ndo_change_mtu = fjes_change_mtu,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -713,6 +715,33 @@ fjes_get_stats64(struct net_device *netdev, struct 
rtnl_link_stats64 *stats)
return stats;
 }
 
+static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
+{
+   bool running = netif_running(netdev);
+   int ret = 0;
+   int idx;
+
+   for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
+   if (new_mtu = fjes_support_mtu[idx]) {
+   new_mtu = fjes_support_mtu[idx];
+   if (new_mtu == netdev-mtu)
+   return 0;
+
+   if (running)
+   fjes_close(netdev);
+
+   netdev-mtu = new_mtu;
+
+   if (running)
+   ret = fjes_open(netdev);
+
+   return ret;
+   }
+   }
+
+   return -EINVAL;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 12/22] fjes: net_device_ops.ndo_get_stats64

2015-08-21 Thread Taku Izumi
This patch adds net_device_ops.ndo_get_stats64 callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 6194962..20feb3e 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -55,6 +55,8 @@ static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct 
net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
+static struct rtnl_link_stats64 *
+fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -219,6 +221,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_open   = fjes_open,
.ndo_stop   = fjes_close,
.ndo_start_xmit = fjes_xmit_frame,
+   .ndo_get_stats64= fjes_get_stats64,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -700,6 +703,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
return ret;
 }
 
+static struct rtnl_link_stats64 *
+fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+
+   memcpy(stats, adapter-stats64, sizeof(struct rtnl_link_stats64));
+
+   return stats;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 10/22] fjes: tx_stall_task

2015-08-21 Thread Taku Izumi
This patch adds tx_stall_task.
When receiver's buffer is full, sender stops
its tx queue. This task is used to monitor
receiver's status and when receiver's buffer
is avairable, it resumes tx queue.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  2 ++
 drivers/net/fjes/fjes_main.c | 61 
 2 files changed, 63 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 8e9899e..b04ea9d 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -30,6 +30,7 @@
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
 #define FJES_TX_RETRY_TIMEOUT  (100)
+#define FJES_TX_TX_STALL_TIMEOUT   (FJES_TX_RETRY_INTERVAL / 2)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
@@ -52,6 +53,7 @@ struct fjes_adapter {
 
struct workqueue_struct *txrx_wq;
 
+   struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
struct fjes_hw hw;
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 80e180f..ac1e076 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -53,6 +53,7 @@ static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
+static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -278,6 +279,7 @@ static int fjes_close(struct net_device *netdev)
fjes_free_irq(adapter);
 
cancel_work_sync(adapter-raise_intr_rxdata_task);
+   cancel_work_sync(adapter-tx_stall_task);
 
fjes_hw_wait_epstop(hw);
 
@@ -407,6 +409,59 @@ static void fjes_free_resources(struct fjes_adapter 
*adapter)
}
 }
 
+static void fjes_tx_stall_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, tx_stall_task);
+   struct net_device *netdev = adapter-netdev;
+   struct fjes_hw *hw = adapter-hw;
+   int all_queue_available, sendable;
+   enum ep_partner_status pstatus;
+   int max_epid, my_epid, epid;
+   union ep_buffer_info *info;
+   int i;
+
+   if (((long)jiffies -
+   (long)(netdev-trans_start))  FJES_TX_TX_STALL_TIMEOUT) {
+   netif_wake_queue(netdev);
+   return;
+   }
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   for (i = 0; i  5; i++) {
+   all_queue_available = 1;
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (my_epid == epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   sendable = (pstatus == EP_PARTNER_SHARED);
+   if (!sendable)
+   continue;
+
+   info = adapter-hw.ep_shm_info[epid].tx.info;
+
+   if (EP_RING_FULL(info-v1i.head, info-v1i.tail,
+info-v1i.count_max)) {
+   all_queue_available = 0;
+   break;
+   }
+   }
+
+   if (all_queue_available) {
+   netif_wake_queue(netdev);
+   return;
+   }
+   }
+
+   usleep_range(50, 100);
+
+   queue_work(adapter-txrx_wq, adapter-tx_stall_task);
+}
+
 static void fjes_raise_intr_rxdata_task(struct work_struct *work)
 {
struct fjes_adapter *adapter = container_of(work,
@@ -602,6 +657,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
netdev-trans_start = jiffies;
netif_tx_stop_queue(cur_queue);
 
+   if 
(!work_pending(adapter-tx_stall_task))
+   queue_work(adapter-txrx_wq,
+  
adapter-tx_stall_task);
+
ret = NETDEV_TX_BUSY;
}
} else {
@@ -686,6 +745,7 @@ static int fjes_probe(struct platform_device *plat_dev)
 
adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
 
+   INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
 
@@ -729,6 +789,7 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_hw *hw = adapter-hw;
 
cancel_work_sync(adapter-raise_intr_rxdata_task);
+   cancel_work_sync

[PATCH v3 05/22] fjes: ES information acquisition routine

2015-08-21 Thread Taku Izumi
This patch adds ES information acquisition routine.
ES information can be retrieved issuing information
request command. ES information includes which
receiver is same zone.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 101 +++
 drivers/net/fjes/fjes_hw.h   |  24 ++
 drivers/net/fjes/fjes_regs.h |  23 ++
 3 files changed, 148 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 757cece..c31be7f 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -351,6 +351,107 @@ void fjes_hw_exit(struct fjes_hw *hw)
fjes_hw_cleanup(hw);
 }
 
+static enum fjes_dev_command_response_e
+fjes_hw_issue_request_command(struct fjes_hw *hw,
+ enum fjes_dev_command_request_type type)
+{
+   enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
+   union REG_CR cr;
+   union REG_CS cs;
+   int timeout;
+
+   cr.reg = 0;
+   cr.bits.req_start = 1;
+   cr.bits.req_code = type;
+   wr32(XSCT_CR, cr.reg);
+   cr.reg = rd32(XSCT_CR);
+
+   if (cr.bits.error == 0) {
+   timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
+   cs.reg = rd32(XSCT_CS);
+
+   while ((cs.bits.complete != 1)  timeout  0) {
+   msleep(1000);
+   cs.reg = rd32(XSCT_CS);
+   timeout -= 1000;
+   }
+
+   if (cs.bits.complete == 1)
+   ret = FJES_CMD_STATUS_NORMAL;
+   else if (timeout = 0)
+   ret = FJES_CMD_STATUS_TIMEOUT;
+
+   } else {
+   switch (cr.bits.err_info) {
+   case FJES_CMD_REQ_ERR_INFO_PARAM:
+   ret = FJES_CMD_STATUS_ERROR_PARAM;
+   break;
+   case FJES_CMD_REQ_ERR_INFO_STATUS:
+   ret = FJES_CMD_STATUS_ERROR_STATUS;
+   break;
+   default:
+   ret = FJES_CMD_STATUS_UNKNOWN;
+   break;
+   }
+   }
+
+   return ret;
+}
+
+int fjes_hw_request_info(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;
+
+   memset(req_buf, 0, hw-hw_info.req_buf_size);
+   memset(res_buf, 0, hw-hw_info.res_buf_size);
+
+   req_buf-info.length = FJES_DEV_COMMAND_INFO_REQ_LEN;
+
+   res_buf-info.length = 0;
+   res_buf-info.code = 0;
+
+   ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
+
+   result = 0;
+
+   if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw-hw_info.max_epid)) !=
+   res_buf-info.length) {
+   result = -ENOMSG;
+   } else if (ret == FJES_CMD_STATUS_NORMAL) {
+   switch (res_buf-info.code) {
+   case FJES_CMD_REQ_RES_CODE_NORMAL:
+   result = 0;
+   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:
+   result = -EPERM;
+   break;
+   case FJES_CMD_STATUS_ERROR_STATUS:
+   result = -EPERM;
+   break;
+   default:
+   result = -EPERM;
+   break;
+   }
+   }
+
+   return result;
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 1b3e9ca..cc1ef21 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -34,6 +34,12 @@ struct fjes_hw;
 #define EP_BUFFER_INFO_SIZE 4096
 
 #define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3) /* sec */
+#define FJES_COMMAND_REQ_TIMEOUT  (5 + 1) /* sec */
+
+#define FJES_CMD_REQ_ERR_INFO_PARAM  (0x0001)
+#define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002)
+
+#define FJES_CMD_REQ_RES_CODE_NORMAL (0)
 
 #define EP_BUFFER_SIZE \
(((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
@@ -50,6 +56,7 @@ struct fjes_hw;
((size) - sizeof(struct esmem_frame) - \
(ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))
 
+#define FJES_DEV_COMMAND_INFO_REQ_LEN  (4)
 #define FJES_DEV_COMMAND_INFO_RES_LEN(epnum) (8 + 2 * (epnum))
 #define FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(txb, rxb) \
(24 + (8 * ((txb) / EP_BUFFER_INFO_SIZE + (rxb

[PATCH v2.2 21/22] fjes: handle receive cancellation request interrupt

2015-08-20 Thread Taku Izumi
This patch adds implementation of handling IRQ
of other receiver's receive cancellation request.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 78 
 1 file changed, 78 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index faaf2ed..ba7e607 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -822,6 +822,74 @@ static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
return 0;
 }
 
+static void fjes_txrx_stop_req_irq(struct fjes_adapter *adapter,
+  int src_epid)
+{
+   struct fjes_hw *hw = adapter-hw;
+   enum ep_partner_status status;
+
+   status = fjes_hw_get_partner_ep_status(hw, src_epid);
+   switch (status) {
+   case EP_PARTNER_UNSHARE:
+   case EP_PARTNER_COMPLETE:
+   default:
+   break;
+   case EP_PARTNER_WAITING:
+   if (src_epid  hw-my_epid) {
+   hw-ep_shm_info[src_epid].tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_DONE;
+
+   clear_bit(src_epid, hw-txrx_stop_req_bit);
+   set_bit(src_epid, adapter-unshare_watch_bitmask);
+
+   if (!work_pending(adapter-unshare_watch_task))
+   queue_work(adapter-control_wq,
+  adapter-unshare_watch_task);
+   }
+   break;
+   case EP_PARTNER_SHARED:
+   if (hw-ep_shm_info[src_epid].rx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_REQUEST) {
+   set_bit(src_epid, hw-epstop_req_bit);
+   if (!work_pending(hw-epstop_task))
+   queue_work(adapter-control_wq,
+  hw-epstop_task);
+   }
+   break;
+   }
+}
+
+static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid)
+{
+   struct fjes_hw *hw = adapter-hw;
+   enum ep_partner_status status;
+
+   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:
+   hw-ep_shm_info[src_epid].tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_DONE;
+   clear_bit(src_epid, hw-txrx_stop_req_bit);
+   /* fall through */
+   case EP_PARTNER_UNSHARE:
+   case EP_PARTNER_COMPLETE:
+   default:
+   set_bit(src_epid, adapter-unshare_watch_bitmask);
+   if (!work_pending(adapter-unshare_watch_task))
+   queue_work(adapter-control_wq,
+  adapter-unshare_watch_task);
+   break;
+   case EP_PARTNER_SHARED:
+   set_bit(src_epid, hw-epstop_req_bit);
+
+   if (!work_pending(hw-epstop_task))
+   queue_work(adapter-control_wq, hw-epstop_task);
+   break;
+   }
+}
+
 static void fjes_update_zone_irq(struct fjes_adapter *adapter,
 int src_epid)
 {
@@ -844,6 +912,16 @@ static irqreturn_t fjes_intr(int irq, void *data)
if (icr  REG_ICTL_MASK_RX_DATA)
fjes_rx_irq(adapter, icr  REG_IS_MASK_EPID);
 
+   if (icr  REG_ICTL_MASK_DEV_STOP_REQ)
+   fjes_stop_req_irq(adapter, icr  REG_IS_MASK_EPID);
+
+   if (icr  REG_ICTL_MASK_TXRX_STOP_REQ)
+   fjes_txrx_stop_req_irq(adapter, icr  REG_IS_MASK_EPID);
+
+   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)
fjes_update_zone_irq(adapter, icr  REG_IS_MASK_EPID);
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 06/22] fjes: buffer address regist/unregistration routine

2015-08-20 Thread Taku Izumi
This patch adds buffer address regist/unregistration routine.

This function is mainly invoked when network device's
activation (open) and deactivation (close)
in order to retist/unregist shared buffer address.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c | 186 +
 drivers/net/fjes/fjes_hw.h |   9 ++-
 2 files changed, 194 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 3fbe68e..5f43957 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -452,6 +452,192 @@ int fjes_hw_request_info(struct fjes_hw *hw)
return result;
 }
 
+int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
+  struct ep_share_mem_info *buf_pair)
+{
+   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 i, idx;
+   int page_count;
+   void *addr;
+   int timeout;
+   int result;
+
+   if (test_bit(dest_epid, hw-hw_info.buffer_share_bit))
+   return 0;
+
+   memset(req_buf, 0, hw-hw_info.req_buf_size);
+   memset(res_buf, 0, hw-hw_info.res_buf_size);
+
+   req_buf-share_buffer.length = FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(
+   buf_pair-tx.size,
+   buf_pair-rx.size);
+   req_buf-share_buffer.epid = dest_epid;
+
+   idx = 0;
+   req_buf-share_buffer.buffer[idx++] = buf_pair-tx.size;
+   page_count = buf_pair-tx.size / EP_BUFFER_INFO_SIZE;
+   for (i = 0; i  page_count; i++) {
+   addr = ((u8 *)(buf_pair-tx.buffer)) +
+   (i * EP_BUFFER_INFO_SIZE);
+   req_buf-share_buffer.buffer[idx++] =
+   (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+   offset_in_page(addr));
+   }
+
+   req_buf-share_buffer.buffer[idx++] = buf_pair-rx.size;
+   page_count = buf_pair-rx.size / EP_BUFFER_INFO_SIZE;
+   for (i = 0; i  page_count; i++) {
+   addr = ((u8 *)(buf_pair-rx.buffer)) +
+   (i * EP_BUFFER_INFO_SIZE);
+   req_buf-share_buffer.buffer[idx++] =
+   (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+   offset_in_page(addr));
+   }
+
+   res_buf-share_buffer.length = 0;
+   res_buf-share_buffer.code = 0;
+
+   ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
+
+   timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
+   while ((ret == FJES_CMD_STATUS_NORMAL) 
+  (res_buf-share_buffer.length ==
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) 
+  (res_buf-share_buffer.code == FJES_CMD_REQ_RES_CODE_BUSY) 
+  (timeout  0)) {
+   msleep(200 + hw-my_epid * 20);
+   timeout -= (200 + hw-my_epid * 20);
+
+   res_buf-share_buffer.length = 0;
+   res_buf-share_buffer.code = 0;
+
+   ret = fjes_hw_issue_request_command(
+   hw, FJES_CMD_REQ_SHARE_BUFFER);
+   }
+
+   result = 0;
+
+   if (res_buf-share_buffer.length !=
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN)
+   result = -ENOMSG;
+   else if (ret == FJES_CMD_STATUS_NORMAL) {
+   switch (res_buf-share_buffer.code) {
+   case FJES_CMD_REQ_RES_CODE_NORMAL:
+   result = 0;
+   set_bit(dest_epid, hw-hw_info.buffer_share_bit);
+   break;
+   case FJES_CMD_REQ_RES_CODE_BUSY:
+   result = -EBUSY;
+   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_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
+{
+   union fjes_device_command_req *req_buf = hw-hw_info.req_buf;
+   union fjes_device_command_res *res_buf = hw-hw_info.res_buf;
+   struct fjes_device_shared_info *share = hw-hw_info.share;
+   enum fjes_dev_command_response_e ret

[PATCH v2.2 01/22] fjes: Introduce FUJITSU Extended Socket Network Device driver

2015-08-20 Thread Taku Izumi
This patch adds the basic code of FUJITSU Extended Socket
Network Device driver.

When PNP0C02 is found in ACPI DSDT, it evaluates _STR
to check if PNP0C02 is for Extended Socket device driver
and retrieves ACPI resource information. Then creates
platform_device.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/Kconfig  |   7 ++
 drivers/net/Makefile |   2 +
 drivers/net/fjes/Makefile|  31 +++
 drivers/net/fjes/fjes.h  |  33 +++
 drivers/net/fjes/fjes_main.c | 214 +++
 5 files changed, 287 insertions(+)
 create mode 100644 drivers/net/fjes/Makefile
 create mode 100644 drivers/net/fjes/fjes.h
 create mode 100644 drivers/net/fjes/fjes_main.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c18f9e6..c78a81a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -407,6 +407,13 @@ config VMXNET3
  To compile this driver as a module, choose M here: the
  module will be called vmxnet3.
 
+config FUJITSU_ES
+   tristate FUJITSU Extended Socket Network Device driver
+   depends on ACPI
+   help
+ This driver provides support for Extended Socket network device
+  on Extended Partitioning of FUJITSU PRIMEQUEST 2000 E2 series.
+
 source drivers/net/hyperv/Kconfig
 
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c12cb22..677c7b4 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -67,3 +67,5 @@ obj-$(CONFIG_USB_NET_DRIVERS) += usb/
 
 obj-$(CONFIG_HYPERV_NET) += hyperv/
 obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
+
+obj-$(CONFIG_FUJITSU_ES) += fjes/
diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
new file mode 100644
index 000..98e59cb
--- /dev/null
+++ b/drivers/net/fjes/Makefile
@@ -0,0 +1,31 @@
+
+#
+# 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.
+#
+
+
+
+#
+# Makefile for the FUJITSU Extended Socket network device driver
+#
+
+obj-$(CONFIG_FUJITSU_ES) += fjes.o
+
+fjes-objs := fjes_main.o
+
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
new file mode 100644
index 000..4622da1
--- /dev/null
+++ b/drivers/net/fjes/fjes.h
@@ -0,0 +1,33 @@
+/*
+ *  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_H_
+#define FJES_H_
+
+#include linux/acpi.h
+
+#define FJES_ACPI_SYMBOL   Extended Socket
+
+extern char fjes_driver_name[];
+extern char fjes_driver_version[];
+extern u32 fjes_support_mtu[];
+
+#endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
new file mode 100644
index 000..ab4d20c
--- /dev/null
+++ b/drivers/net/fjes/fjes_main.c
@@ -0,0 +1,214 @@
+/*
+ *  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

[PATCH v2.2 20/22] fjes: epstop_task

2015-08-20 Thread Taku Izumi
This patch adds epstop_task.
This task is used to process other receiver's
cancellation request.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 30 ++
 drivers/net/fjes/fjes_hw.h   |  1 +
 drivers/net/fjes/fjes_main.c |  1 +
 3 files changed, 32 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 4588ef3..ada0b9e 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -23,6 +23,7 @@
 #include fjes.h
 
 static void fjes_hw_update_zone_task(struct work_struct *);
+static void fjes_hw_epstop_task(struct work_struct *);
 
 /* supported MTU list */
 const u32 fjes_support_mtu[] = {
@@ -325,6 +326,7 @@ int fjes_hw_init(struct fjes_hw *hw)
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
INIT_WORK(hw-update_zone_task, fjes_hw_update_zone_task);
+   INIT_WORK(hw-epstop_task, fjes_hw_epstop_task);
 
mutex_init(hw-hw_info.lock);
 
@@ -355,6 +357,7 @@ void fjes_hw_exit(struct fjes_hw *hw)
fjes_hw_cleanup(hw);
 
cancel_work_sync(hw-update_zone_task);
+   cancel_work_sync(hw-epstop_task);
 }
 
 static enum fjes_dev_command_response_e
@@ -1085,3 +1088,30 @@ static void fjes_hw_update_zone_task(struct work_struct 
*work)
}
 }
 
+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;
+   int epid_bit;
+   unsigned long remain_bit;
+
+   while ((remain_bit = hw-epstop_req_bit)) {
+   for (epid_bit = 0; remain_bit; remain_bit = 1, epid_bit++) {
+   if (remain_bit  1) {
+   hw-ep_shm_info[epid_bit].
+   tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_DONE;
+
+   clear_bit(epid_bit, hw-epstop_req_bit);
+   set_bit(epid_bit,
+   adapter-unshare_watch_bitmask);
+
+   if (!work_pending(adapter-unshare_watch_task))
+   queue_work(
+   adapter-control_wq,
+   adapter-unshare_watch_task);
+   }
+   }
+   }
+}
+
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index fe51041..4d3184a 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -283,6 +283,7 @@ struct fjes_hw {
unsigned long txrx_stop_req_bit;
unsigned long epstop_req_bit;
struct work_struct update_zone_task;
+   struct work_struct epstop_task;
 
int my_epid;
int max_epid;
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 615c1ef..faaf2ed 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -316,6 +316,7 @@ static int fjes_close(struct net_device *netdev)
cancel_work_sync(adapter-tx_stall_task);
 
cancel_work_sync(hw-update_zone_task);
+   cancel_work_sync(hw-epstop_task);
 
fjes_hw_wait_epstop(hw);
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 16/22] fjes: interrupt_watch_task

2015-08-20 Thread Taku Izumi
This patch adds interrupt_watch_task.
This task is used to prevent delay of interrupts.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  5 +
 drivers/net/fjes/fjes_main.c | 40 +++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index b04ea9d..1743dbb 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -32,6 +32,7 @@
 #define FJES_TX_RETRY_TIMEOUT  (100)
 #define FJES_TX_TX_STALL_TIMEOUT   (FJES_TX_RETRY_INTERVAL / 2)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
+#define FJES_IRQ_WATCH_DELAY   (HZ)
 
 /* board specific private data structure */
 struct fjes_adapter {
@@ -52,10 +53,14 @@ struct fjes_adapter {
bool irq_registered;
 
struct workqueue_struct *txrx_wq;
+   struct workqueue_struct *control_wq;
 
struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
+   struct delayed_work interrupt_watch_task;
+   bool interrupt_watch_enable;
+
struct fjes_hw hw;
 };
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 1bb9347..2bf9f71 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -71,7 +71,7 @@ static int fjes_remove(struct platform_device *);
 
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
-
+static void fjes_irq_watch_task(struct work_struct *);
 static void fjes_rx_irq(struct fjes_adapter *, int);
 static int fjes_poll(struct napi_struct *, int);
 
@@ -197,6 +197,13 @@ static int fjes_request_irq(struct fjes_adapter *adapter)
struct net_device *netdev = adapter-netdev;
int result = -1;
 
+   adapter-interrupt_watch_enable = true;
+   if (!delayed_work_pending(adapter-interrupt_watch_task)) {
+   queue_delayed_work(adapter-control_wq,
+  adapter-interrupt_watch_task,
+  FJES_IRQ_WATCH_DELAY);
+   }
+
if (!adapter-irq_registered) {
result = request_irq(adapter-hw.hw_res.irq, fjes_intr,
 IRQF_SHARED, netdev-name, adapter);
@@ -213,6 +220,9 @@ static void fjes_free_irq(struct fjes_adapter *adapter)
 {
struct fjes_hw *hw = adapter-hw;
 
+   adapter-interrupt_watch_enable = false;
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
+
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
if (adapter-irq_registered) {
@@ -297,6 +307,7 @@ static int fjes_close(struct net_device *netdev)
 
fjes_free_irq(adapter);
 
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
 
@@ -999,11 +1010,15 @@ static int fjes_probe(struct platform_device *plat_dev)
adapter-open_guard = false;
 
adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
+   adapter-control_wq = create_workqueue(DRV_NAME /control);
 
INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
 
+   INIT_DELAYED_WORK(adapter-interrupt_watch_task, fjes_irq_watch_task);
+   adapter-interrupt_watch_enable = false;
+
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
hw-hw_res.start = res-start;
hw-hw_res.size = res-end - res-start + 1;
@@ -1044,8 +1059,11 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = adapter-hw;
 
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
+   if (adapter-control_wq)
+   destroy_workqueue(adapter-control_wq);
if (adapter-txrx_wq)
destroy_workqueue(adapter-txrx_wq);
 
@@ -1081,6 +1099,26 @@ static void fjes_netdev_setup(struct net_device *netdev)
netdev-features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
 }
 
+static void fjes_irq_watch_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(to_delayed_work(work),
+   struct fjes_adapter, interrupt_watch_task);
+
+   local_irq_disable();
+   fjes_intr(adapter-hw.hw_res.irq, adapter);
+   local_irq_enable();
+
+   if (fjes_rxframe_search_exist(adapter, 0) = 0)
+   napi_schedule(adapter-napi);
+
+   if (adapter-interrupt_watch_enable) {
+   if (!delayed_work_pending(adapter-interrupt_watch_task))
+   queue_delayed_work(adapter-control_wq,
+  adapter-interrupt_watch_task

[PATCH v2.2 18/22] fjes: unshare_watch_task

2015-08-20 Thread Taku Izumi
This patch adds unshare_watch_task.
Shared buffer's status can be changed into unshared.
This task is used to monitor shared buffer's status.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   3 ++
 drivers/net/fjes/fjes_main.c | 126 +++
 2 files changed, 129 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index d31d4c3..57feee8 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -59,6 +59,9 @@ struct fjes_adapter {
struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
+   struct work_struct unshare_watch_task;
+   unsigned long unshare_watch_bitmask;
+
struct delayed_work interrupt_watch_task;
bool interrupt_watch_enable;
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 3a8cc5b..e31a229 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -73,6 +73,7 @@ static int fjes_remove(struct platform_device *);
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
 static void fjes_irq_watch_task(struct work_struct *);
+static void fjes_watch_unshare_task(struct work_struct *);
 static void fjes_rx_irq(struct fjes_adapter *, int);
 static int fjes_poll(struct napi_struct *, int);
 
@@ -309,6 +310,8 @@ static int fjes_close(struct net_device *netdev)
fjes_free_irq(adapter);
 
cancel_delayed_work_sync(adapter-interrupt_watch_task);
+   cancel_work_sync(adapter-unshare_watch_task);
+   adapter-unshare_watch_bitmask = 0;
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
 
@@ -1028,6 +1031,8 @@ static int fjes_probe(struct platform_device *plat_dev)
INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
+   INIT_WORK(adapter-unshare_watch_task, fjes_watch_unshare_task);
+   adapter-unshare_watch_bitmask = 0;
 
INIT_DELAYED_WORK(adapter-interrupt_watch_task, fjes_irq_watch_task);
adapter-interrupt_watch_enable = false;
@@ -1073,6 +1078,7 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_hw *hw = adapter-hw;
 
cancel_delayed_work_sync(adapter-interrupt_watch_task);
+   cancel_work_sync(adapter-unshare_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
if (adapter-control_wq)
@@ -1132,6 +1138,126 @@ static void fjes_irq_watch_task(struct work_struct 
*work)
}
 }
 
+static void fjes_watch_unshare_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter =
+   container_of(work, struct fjes_adapter, unshare_watch_task);
+
+   struct fjes_hw *hw = adapter-hw;
+   struct net_device *netdev = adapter-netdev;
+   int epidx;
+   int max_epid, my_epid;
+   unsigned long unshare_watch_bitmask;
+   int wait_time = 0;
+   int is_shared;
+   int stop_req, stop_req_done;
+   int unshare_watch, unshare_reserve;
+   int ret;
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   unshare_watch_bitmask = adapter-unshare_watch_bitmask;
+   adapter-unshare_watch_bitmask = 0;
+
+   while ((unshare_watch_bitmask || hw-txrx_stop_req_bit) 
+  (wait_time  3000)) {
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+
+   is_shared = fjes_hw_epid_is_shared(hw-hw_info.share,
+  epidx);
+
+   stop_req = test_bit(epidx, hw-txrx_stop_req_bit);
+
+   stop_req_done = 
hw-ep_shm_info[epidx].rx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_DONE;
+
+   unshare_watch = test_bit(epidx, unshare_watch_bitmask);
+
+   unshare_reserve = test_bit(epidx,
+  
hw-hw_info.buffer_unshare_reserve_bit);
+
+   if ((!stop_req ||
+(is_shared  (!is_shared || !stop_req_done))) 
+   (is_shared || !unshare_watch || !unshare_reserve))
+   continue;
+
+   mutex_lock(hw-hw_info.lock);
+   ret = fjes_hw_unregister_buff_addr(hw, epidx);
+   switch (ret) {
+   case 0:
+   break;
+   case -ENOMSG:
+   case -EBUSY:
+   default:
+   if (!work_pending(
+   adapter-force_close_task

[PATCH v2.2 19/22] fjes: update_zone_task

2015-08-20 Thread Taku Izumi
This patch adds update_zone_task.
Zoning information can be changed by user.
This task is used to monitor if zoning information is
changed or not.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 171 +++
 drivers/net/fjes/fjes_hw.h   |   1 +
 drivers/net/fjes/fjes_main.c |  14 
 3 files changed, 186 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 46e114c..4588ef3 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -22,6 +22,8 @@
 #include fjes_hw.h
 #include fjes.h
 
+static void fjes_hw_update_zone_task(struct work_struct *);
+
 /* supported MTU list */
 const u32 fjes_support_mtu[] = {
FJES_MTU_DEFINE(8 * 1024),
@@ -322,6 +324,8 @@ int fjes_hw_init(struct fjes_hw *hw)
 
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
+   INIT_WORK(hw-update_zone_task, fjes_hw_update_zone_task);
+
mutex_init(hw-hw_info.lock);
 
hw-max_epid = fjes_hw_get_max_epid(hw);
@@ -349,6 +353,8 @@ void fjes_hw_exit(struct fjes_hw *hw)
}
 
fjes_hw_cleanup(hw);
+
+   cancel_work_sync(hw-update_zone_task);
 }
 
 static enum fjes_dev_command_response_e
@@ -914,3 +920,168 @@ int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
return 0;
 }
 
+static void fjes_hw_update_zone_task(struct work_struct *work)
+{
+   struct fjes_hw *hw = container_of(work,
+   struct fjes_hw, update_zone_task);
+   struct fjes_adapter *adapter = (struct fjes_adapter *)hw-back;
+   struct net_device *netdev = adapter-netdev;
+   int ret;
+   int epidx;
+   enum ep_partner_status pstatus;
+   unsigned long share_bit = 0;
+   unsigned long unshare_bit = 0;
+   unsigned long irq_bit = 0;
+   union fjes_device_command_res *res_buf = hw-hw_info.res_buf;
+   struct my_s {u8 es_status; u8 zone; } *info =
+   (struct my_s *)res_buf-info.info;
+
+   mutex_lock(hw-hw_info.lock);
+
+   ret = fjes_hw_request_info(hw);
+   switch (ret) {
+   case -ENOMSG:
+   case -EBUSY:
+   default:
+   if (!work_pending(adapter-force_close_task)) {
+   adapter-force_reset = true;
+   schedule_work(adapter-force_close_task);
+   }
+   break;
+
+   case 0:
+
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid) {
+   hw-ep_shm_info[epidx].es_status =
+   info[epidx].es_status;
+   hw-ep_shm_info[epidx].zone =
+   info[epidx].zone;
+   continue;
+   }
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epidx);
+   switch (pstatus) {
+   case EP_PARTNER_UNSHARE:
+   default:
+   if ((info[epidx].zone !=
+   FJES_ZONING_ZONE_TYPE_NONE) 
+   (info[epidx].es_status ==
+   FJES_ZONING_STATUS_ENABLE) 
+   (info[epidx].zone ==
+   info[hw-my_epid].zone))
+   set_bit(epidx, share_bit);
+   else
+   set_bit(epidx, unshare_bit);
+   break;
+
+   case EP_PARTNER_COMPLETE:
+   case EP_PARTNER_WAITING:
+   if ((info[epidx].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE) ||
+   (info[epidx].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (info[epidx].zone !=
+   info[hw-my_epid].zone)) {
+   set_bit(epidx,
+   
adapter-unshare_watch_bitmask);
+   set_bit(epidx,
+   
hw-hw_info.buffer_unshare_reserve_bit);
+   }
+   break;
+
+   case EP_PARTNER_SHARED:
+   if ((info[epidx].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE) ||
+   (info[epidx].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (info[epidx].zone !=
+   info[hw-my_epid].zone))
+   set_bit(epidx, irq_bit

[PATCH v2.2 13/22] fjes: net_device_ops.ndo_change_mtu

2015-08-20 Thread Taku Izumi
This patch adds net_device_ops.ndo_change_mtu.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 842edbb..bb94890 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -57,6 +57,7 @@ static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
+static int fjes_change_mtu(struct net_device *, int);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -222,6 +223,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_stop   = fjes_close,
.ndo_start_xmit = fjes_xmit_frame,
.ndo_get_stats64= fjes_get_stats64,
+   .ndo_change_mtu = fjes_change_mtu,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -715,6 +717,33 @@ fjes_get_stats64(struct net_device *netdev, struct 
rtnl_link_stats64 *stats)
return stats;
 }
 
+static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
+{
+   int idx;
+   bool running = netif_running(netdev);
+   int ret = 0;
+
+   for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
+   if (new_mtu = fjes_support_mtu[idx]) {
+   new_mtu = fjes_support_mtu[idx];
+   if (new_mtu == netdev-mtu)
+   return 0;
+
+   if (running)
+   fjes_close(netdev);
+
+   netdev-mtu = new_mtu;
+
+   if (running)
+   ret = fjes_open(netdev);
+
+   return ret;
+   }
+   }
+
+   return -EINVAL;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 17/22] fjes: force_close_task

2015-08-20 Thread Taku Izumi
This patch adds force_close_task.
This task is used to close network device forcibly.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  1 +
 drivers/net/fjes/fjes_main.c | 13 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 1743dbb..d31d4c3 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -47,6 +47,7 @@ struct fjes_adapter {
unsigned long rx_last_jiffies;
bool unset_rx_last;
 
+   struct work_struct force_close_task;
bool force_reset;
bool open_guard;
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 2bf9f71..3a8cc5b 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -54,6 +54,7 @@ static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static void fjes_tx_stall_task(struct work_struct *);
+static void fjes_force_close_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
@@ -494,6 +495,17 @@ static void fjes_tx_stall_task(struct work_struct *work)
queue_work(adapter-txrx_wq, adapter-tx_stall_task);
 }
 
+static void fjes_force_close_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, force_close_task);
+   struct net_device *netdev = adapter-netdev;
+
+   rtnl_lock();
+   dev_close(netdev);
+   rtnl_unlock();
+}
+
 static void fjes_raise_intr_rxdata_task(struct work_struct *work)
 {
struct fjes_adapter *adapter = container_of(work,
@@ -1006,6 +1018,7 @@ static int fjes_probe(struct platform_device *plat_dev)
if (err)
goto err_sw_init;
 
+   INIT_WORK(adapter-force_close_task, fjes_force_close_task);
adapter-force_reset = false;
adapter-open_guard = false;
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 00/22] FUJITSU Extended Socket network device driver

2015-08-20 Thread Taku Izumi
This patchsets adds FUJITSU Extended Socket network device driver.
Extended Socket network device is a shared memory based high-speed network
interface between Extended Partitions of PRIMEQUEST 2000 E2 series.
 
You can get some information about Extended Partition and Extended
Socket by referring the following manual.
 
http://globalsp.ts.fujitsu.com/dmsp/Publications/public/CA92344-0537.pdf
3.2.1 Extended Partitioning
3.2.2 Extended Socke

v2.1 - v2.2:
   - minor fix patch 21/22 according to Sergei's comment


Taku Izumi (22):
  fjes: Introduce FUJITSU Extended Socket Network Device driver
  fjes: Hardware initialization routine
  fjes: Hardware cleanup routine
  fjes: platform_driver's .probe and .remove routine
  fjes: ES information acquisition routine
  fjes: buffer address regist/unregistration routine
  fjes: net_device_ops.ndo_open and .ndo_stop
  fjes: net_device_ops.ndo_start_xmit
  fjes: raise_intr_rxdata_task
  fjes: tx_stall_task
  fjes: NAPI polling function
  fjes: net_device_ops.ndo_get_stats64
  fjes: net_device_ops.ndo_change_mtu
  fjes: net_device_ops.ndo_tx_timeout
  fjes: net_device_ops.ndo_vlan_rx_add/kill_vid
  fjes: interrupt_watch_task
  fjes: force_close_task
  fjes: unshare_watch_task
  fjes: update_zone_task
  fjes: epstop_task
  fjes: handle receive cancellation request interrupt
  fjes: ethtool support

 drivers/net/Kconfig |7 +
 drivers/net/Makefile|2 +
 drivers/net/fjes/Makefile   |   31 +
 drivers/net/fjes/fjes.h |   77 +++
 drivers/net/fjes/fjes_ethtool.c |  135 
 drivers/net/fjes/fjes_hw.c  | 1117 +++
 drivers/net/fjes/fjes_hw.h  |  334 ++
 drivers/net/fjes/fjes_main.c| 1388 +++
 drivers/net/fjes/fjes_regs.h|  142 
 9 files changed, 3233 insertions(+)
 create mode 100644 drivers/net/fjes/Makefile
 create mode 100644 drivers/net/fjes/fjes.h
 create mode 100644 drivers/net/fjes/fjes_ethtool.c
 create mode 100644 drivers/net/fjes/fjes_hw.c
 create mode 100644 drivers/net/fjes/fjes_hw.h
 create mode 100644 drivers/net/fjes/fjes_main.c
 create mode 100644 drivers/net/fjes/fjes_regs.h

-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 03/22] fjes: Hardware cleanup routine

2015-08-20 Thread Taku Izumi
This patch adds hardware cleanup routine to be
invoked at driver's .remove routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c | 66 ++
 drivers/net/fjes/fjes_hw.h |  1 +
 2 files changed, 67 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index e94538f..abe583e 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -56,6 +56,12 @@ static u8 *fjes_hw_iomap(struct fjes_hw *hw)
return base;
 }
 
+static void fjes_hw_iounmap(struct fjes_hw *hw)
+{
+   iounmap(hw-base);
+   release_mem_region(hw-hw_res.start, hw-hw_res.size);
+}
+
 int fjes_hw_reset(struct fjes_hw *hw)
 {
int timeout;
@@ -109,6 +115,12 @@ static int fjes_hw_alloc_shared_status_region(struct 
fjes_hw *hw)
return 0;
 }
 
+static void fjes_hw_free_shared_status_region(struct fjes_hw *hw)
+{
+   kfree(hw-hw_info.share);
+   hw-hw_info.share = NULL;
+}
+
 static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
 {
void *mem;
@@ -126,6 +138,18 @@ static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
return 0;
 }
 
+static void fjes_hw_free_epbuf(struct epbuf_handler *epbh)
+{
+   if (epbh-buffer)
+   vfree(epbh-buffer);
+
+   epbh-buffer = NULL;
+   epbh-size = 0;
+
+   epbh-info = NULL;
+   epbh-ring = NULL;
+}
+
 void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
 {
union ep_buffer_info *info = epbh-info;
@@ -258,6 +282,32 @@ static int fjes_hw_setup(struct fjes_hw *hw)
return 0;
 }
 
+static void fjes_hw_cleanup(struct fjes_hw *hw)
+{
+   int epidx;
+
+   if (!hw-ep_shm_info)
+   return;
+
+   fjes_hw_free_shared_status_region(hw);
+
+   kfree(hw-hw_info.req_buf);
+   hw-hw_info.req_buf = NULL;
+
+   kfree(hw-hw_info.res_buf);
+   hw-hw_info.res_buf = NULL;
+
+   for (epidx = 0; epidx  hw-max_epid ; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+   fjes_hw_free_epbuf(hw-ep_shm_info[epidx].tx);
+   fjes_hw_free_epbuf(hw-ep_shm_info[epidx].rx);
+   }
+
+   kfree(hw-ep_shm_info);
+   hw-ep_shm_info = NULL;
+}
+
 int fjes_hw_init(struct fjes_hw *hw)
 {
int ret;
@@ -285,6 +335,22 @@ int fjes_hw_init(struct fjes_hw *hw)
return ret;
 }
 
+void fjes_hw_exit(struct fjes_hw *hw)
+{
+   int ret;
+
+   if (hw-base) {
+   ret = fjes_hw_reset(hw);
+   if (ret)
+   pr_err(%s: reset error, __func__);
+
+   fjes_hw_iounmap(hw);
+   hw-base = NULL;
+   }
+
+   fjes_hw_cleanup(hw);
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 836ebe2..1b3e9ca 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -241,6 +241,7 @@ struct fjes_hw {
 };
 
 int fjes_hw_init(struct fjes_hw *);
+void fjes_hw_exit(struct fjes_hw *);
 int fjes_hw_reset(struct fjes_hw *);
 
 void fjes_hw_init_command_registers(struct fjes_hw *,
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 04/22] fjes: platform_driver's .probe and .remove routine

2015-08-20 Thread Taku Izumi
This patch implements platform_driver's .probe and .remove
routine, and also adds board specific private data structure.

This driver registers net_device at platform_driver's .probe
routine and unregisters net_device at its .remove routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  | 25 
 drivers/net/fjes/fjes_main.c | 95 
 2 files changed, 120 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 15ded96..54bc189 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -24,7 +24,32 @@
 
 #include linux/acpi.h
 
+#include fjes_hw.h
+
 #define FJES_ACPI_SYMBOL   Extended Socket
+#define FJES_MAX_QUEUES1
+#define FJES_TX_RETRY_INTERVAL (20 * HZ)
+
+/* board specific private data structure */
+struct fjes_adapter {
+   struct net_device *netdev;
+   struct platform_device *plat_dev;
+
+   struct napi_struct napi;
+   struct rtnl_link_stats64 stats64;
+
+   unsigned int tx_retry_count;
+   unsigned long tx_start_jiffies;
+   unsigned long rx_last_jiffies;
+   bool unset_rx_last;
+
+   bool force_reset;
+   bool open_guard;
+
+   bool irq_registered;
+
+   struct fjes_hw hw;
+};
 
 extern char fjes_driver_name[];
 extern char fjes_driver_version[];
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index ab4d20c..7695b84 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -23,6 +23,7 @@
 #include linux/types.h
 #include linux/nls.h
 #include linux/platform_device.h
+#include linux/netdevice.h
 
 #include fjes.h
 
@@ -49,6 +50,9 @@ static acpi_status fjes_get_acpi_resource(struct 
acpi_resource *, void*);
 static int fjes_probe(struct platform_device *);
 static int fjes_remove(struct platform_device *);
 
+static int fjes_sw_init(struct fjes_adapter *);
+static void fjes_netdev_setup(struct net_device *);
+
 static const struct acpi_device_id fjes_acpi_ids[] = {
{PNP0C02, 0},
{, 0},
@@ -166,18 +170,109 @@ fjes_get_acpi_resource(struct acpi_resource *acpi_res, 
void *data)
return AE_OK;
 }
 
+static const struct net_device_ops fjes_netdev_ops = {
+};
+
 /* fjes_probe - Device Initialization Routine */
 static int fjes_probe(struct platform_device *plat_dev)
 {
+   struct net_device *netdev;
+   struct fjes_adapter *adapter;
+   struct fjes_hw *hw;
+   struct resource *res;
+   int err;
+
+   err = -ENOMEM;
+   netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), es%d,
+NET_NAME_UNKNOWN, fjes_netdev_setup,
+FJES_MAX_QUEUES);
+
+   if (!netdev)
+   goto err_alloc_netdev;
+
+   SET_NETDEV_DEV(netdev, plat_dev-dev);
+
+   dev_set_drvdata(plat_dev-dev, netdev);
+   adapter = netdev_priv(netdev);
+   adapter-netdev = netdev;
+   adapter-plat_dev = plat_dev;
+   hw = adapter-hw;
+   hw-back = adapter;
+
+   /* setup the private structure */
+   err = fjes_sw_init(adapter);
+   if (err)
+   goto err_sw_init;
+
+   adapter-force_reset = false;
+   adapter-open_guard = false;
+
+   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.irq = platform_get_irq(plat_dev, 0);
+   err = fjes_hw_init(adapter-hw);
+   if (err)
+   goto err_hw_init;
+
+   /* setup MAC address (02:00:00:00:00:[epid])*/
+   netdev-dev_addr[0] = 2;
+   netdev-dev_addr[1] = 0;
+   netdev-dev_addr[2] = 0;
+   netdev-dev_addr[3] = 0;
+   netdev-dev_addr[4] = 0;
+   netdev-dev_addr[5] = hw-my_epid; /* EPID */
+
+   err = register_netdev(netdev);
+   if (err)
+   goto err_register;
+
+   netif_carrier_off(netdev);
+
return 0;
+
+err_register:
+   fjes_hw_exit(adapter-hw);
+err_hw_init:
+err_sw_init:
+   free_netdev(netdev);
+err_alloc_netdev:
+   return err;
 }
 
 /* fjes_remove - Device Removal Routine */
 static int fjes_remove(struct platform_device *plat_dev)
 {
+   struct net_device *netdev = dev_get_drvdata(plat_dev-dev);
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = adapter-hw;
+
+   unregister_netdev(netdev);
+
+   fjes_hw_exit(hw);
+
+   free_netdev(netdev);
+
return 0;
 }
 
+static int fjes_sw_init(struct fjes_adapter *adapter)
+{
+   return 0;
+}
+
+/* fjes_netdev_setup - netdevice initialization routine */
+static void fjes_netdev_setup(struct net_device *netdev)
+{
+   ether_setup(netdev);
+
+   netdev-watchdog_timeo = FJES_TX_RETRY_INTERVAL;
+   netdev-netdev_ops = fjes_netdev_ops;
+   netdev-mtu = fjes_support_mtu[0];
+   netdev-flags |= IFF_BROADCAST;
+   netdev-features |= NETIF_F_HW_CSUM

[PATCH v2.2 14/22] fjes: net_device_ops.ndo_tx_timeout

2015-08-20 Thread Taku Izumi
This patch adds net_device_ops.ndo_tx_timeout callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index bb94890..c611c58 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -58,6 +58,7 @@ static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
 static int fjes_change_mtu(struct net_device *, int);
+static void fjes_tx_retry(struct net_device *);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -224,6 +225,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_start_xmit = fjes_xmit_frame,
.ndo_get_stats64= fjes_get_stats64,
.ndo_change_mtu = fjes_change_mtu,
+   .ndo_tx_timeout = fjes_tx_retry,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -707,6 +709,13 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
return ret;
 }
 
+static void fjes_tx_retry(struct net_device *netdev)
+{
+   struct netdev_queue *queue = netdev_get_tx_queue(netdev, 0);
+
+   netif_tx_wake_queue(queue);
+}
+
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
 {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 12/22] fjes: net_device_ops.ndo_get_stats64

2015-08-20 Thread Taku Izumi
This patch adds net_device_ops.ndo_get_stats64 callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 186197d..842edbb 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -55,6 +55,8 @@ static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct 
net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
+static struct rtnl_link_stats64 *
+fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -219,6 +221,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_open   = fjes_open,
.ndo_stop   = fjes_close,
.ndo_start_xmit = fjes_xmit_frame,
+   .ndo_get_stats64= fjes_get_stats64,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -702,6 +705,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
return ret;
 }
 
+static struct rtnl_link_stats64 *
+fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+
+   memcpy(stats, adapter-stats64, sizeof(struct rtnl_link_stats64));
+
+   return stats;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 11/22] fjes: NAPI polling function

2015-08-20 Thread Taku Izumi
This patch adds NAPI polling function and receive related work.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   |  40 ++
 drivers/net/fjes/fjes_hw.h   |   5 ++
 drivers/net/fjes/fjes_main.c | 172 ++-
 3 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 4965791..ae7b7cd 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -825,6 +825,46 @@ bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 
vlan_id)
return ret;
 }
 
+bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   if (info-v1i.count_max == 0)
+   return true;
+
+   return EP_RING_EMPTY(info-v1i.head, info-v1i.tail,
+info-v1i.count_max);
+}
+
+void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *epbh,
+  size_t *psize)
+{
+   union ep_buffer_info *info = epbh-info;
+   struct esmem_frame *ring_frame;
+   void *frame;
+
+   ring_frame = (struct esmem_frame *)(epbh-ring[EP_RING_INDEX
+(info-v1i.head,
+ info-v1i.count_max) *
+info-v1i.frame_max]);
+
+   *psize = (size_t)ring_frame-frame_size;
+
+   frame = ring_frame-frame_data;
+
+   return frame;
+}
+
+void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *epbh)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   if (fjes_hw_epbuf_rx_is_empty(epbh))
+   return;
+
+   EP_RING_INDEX_INC(epbh-info-v1i.head, info-v1i.count_max);
+}
+
 int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
  void *frame, size_t size)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 2b49421..0b43bc3 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -69,6 +69,8 @@ struct fjes_hw;
((_num) = EP_RING_INDEX((_num) + 1, (_max)))
 #define EP_RING_FULL(_head, _tail, _max)   \
(0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
+#define EP_RING_EMPTY(_head, _tail, _max) \
+   (1 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
 
 #define FJES_MTU_TO_BUFFER_SIZE(mtu) \
(ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
@@ -320,6 +322,9 @@ int fjes_hw_epid_is_shared(struct fjes_device_shared_info 
*, int);
 bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
 bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
 bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
+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);
 
 #endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 8cc687e..186197d 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -66,6 +66,9 @@ static int fjes_remove(struct platform_device *);
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
 
+static void fjes_rx_irq(struct fjes_adapter *, int);
+static int fjes_poll(struct napi_struct *, int);
+
 static const struct acpi_device_id fjes_acpi_ids[] = {
{PNP0C02, 0},
{, 0},
@@ -235,6 +238,8 @@ static int fjes_open(struct net_device *netdev)
hw-txrx_stop_req_bit = 0;
hw-epstop_req_bit = 0;
 
+   napi_enable(adapter-napi);
+
fjes_hw_capture_interrupt_status(hw);
 
result = fjes_request_irq(adapter);
@@ -250,6 +255,7 @@ static int fjes_open(struct net_device *netdev)
 
 err_req_irq:
fjes_free_irq(adapter);
+   napi_disable(adapter-napi);
 
 err_setup_res:
fjes_free_resources(adapter);
@@ -268,6 +274,8 @@ static int fjes_close(struct net_device *netdev)
 
fjes_hw_raise_epstop(hw);
 
+   napi_disable(adapter-napi);
+
for (epidx = 0; epidx  hw-max_epid; epidx++) {
if (epidx == hw-my_epid)
continue;
@@ -703,14 +711,168 @@ 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_IS_MASK_IS_ASSERT) {
+   if (icr  REG_ICTL_MASK_RX_DATA)
+   fjes_rx_irq(adapter, icr  REG_IS_MASK_EPID);
+
ret = IRQ_HANDLED;
-   else
+   } else {
ret = IRQ_NONE;
+   }
 
return ret;
 }
 
+static int fjes_rxframe_search_exist(struct fjes_adapter *adapter,
+int start_epid)
+{
+   struct fjes_hw *hw = adapter-hw;
+   int cur_epid

[PATCH v2.2 15/22] fjes: net_device_ops.ndo_vlan_rx_add/kill_vid

2015-08-20 Thread Taku Izumi
This patch adds net_device_ops.ndo_vlan_rx_add_vid and
net_device_ops.ndo_vlan_rx_kill_vid callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 27 +++
 drivers/net/fjes/fjes_hw.h   |  2 ++
 drivers/net/fjes/fjes_main.c | 40 
 3 files changed, 69 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index ae7b7cd..46e114c 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -825,6 +825,33 @@ bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 
vlan_id)
return ret;
 }
 
+bool fjes_hw_set_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (info-v1i.vlan_id[i] == 0) {
+   info-v1i.vlan_id[i] = vlan_id;
+   return true;
+   }
+   }
+   return false;
+}
+
+void fjes_hw_del_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+
+   if (0 != vlan_id) {
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (vlan_id == info-v1i.vlan_id[i])
+   info-v1i.vlan_id[i] = 0;
+   }
+   }
+}
+
 bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
 {
union ep_buffer_info *info = epbh-info;
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 0b43bc3..2fcbfeb 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -322,6 +322,8 @@ int fjes_hw_epid_is_shared(struct fjes_device_shared_info 
*, int);
 bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
 bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
 bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+bool fjes_hw_set_vlan_id(struct epbuf_handler *, u16);
+void fjes_hw_del_vlan_id(struct epbuf_handler *, u16);
 bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
 void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
 void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index c611c58..1bb9347 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -58,6 +58,8 @@ static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 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 void fjes_tx_retry(struct net_device *);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -226,6 +228,8 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_get_stats64= fjes_get_stats64,
.ndo_change_mtu = fjes_change_mtu,
.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,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -753,6 +757,42 @@ static int fjes_change_mtu(struct net_device *netdev, int 
new_mtu)
return -EINVAL;
 }
 
+static int fjes_vlan_rx_add_vid(struct net_device *netdev,
+   __be16 proto, u16 vid)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   bool ret = true;
+   int epid;
+
+   for (epid = 0; epid  adapter-hw.max_epid; epid++) {
+   if (epid == adapter-hw.my_epid)
+   continue;
+
+   if (!fjes_hw_check_vlan_id(
+   adapter-hw.ep_shm_info[epid].tx, vid))
+   ret = fjes_hw_set_vlan_id(
+   adapter-hw.ep_shm_info[epid].tx, vid);
+   }
+
+   return ret ? 0 : -ENOSPC;
+}
+
+static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
+__be16 proto, u16 vid)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   int epid;
+
+   for (epid = 0; epid  adapter-hw.max_epid; epid++) {
+   if (epid == adapter-hw.my_epid)
+   continue;
+
+   fjes_hw_del_vlan_id(adapter-hw.ep_shm_info[epid].tx, vid);
+   }
+
+   return 0;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.2 05/22] fjes: ES information acquisition routine

2015-08-20 Thread Taku Izumi
This patch adds ES information acquisition routine.
ES information can be retrieved issuing information
request command. ES information includes which
receiver is same zone.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 101 +++
 drivers/net/fjes/fjes_hw.h   |  24 ++
 drivers/net/fjes/fjes_regs.h |  23 ++
 3 files changed, 148 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index abe583e..3fbe68e 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -351,6 +351,107 @@ void fjes_hw_exit(struct fjes_hw *hw)
fjes_hw_cleanup(hw);
 }
 
+static enum fjes_dev_command_response_e
+fjes_hw_issue_request_command(struct fjes_hw *hw,
+ enum fjes_dev_command_request_type type)
+{
+   union REG_CR cr;
+   union REG_CS cs;
+   enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
+   int timeout;
+
+   cr.reg = 0;
+   cr.bits.req_start = 1;
+   cr.bits.req_code = type;
+   wr32(XSCT_CR, cr.reg);
+   cr.reg = rd32(XSCT_CR);
+
+   if (cr.bits.error == 0) {
+   timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
+   cs.reg = rd32(XSCT_CS);
+
+   while ((cs.bits.complete != 1)  timeout  0) {
+   msleep(1000);
+   cs.reg = rd32(XSCT_CS);
+   timeout -= 1000;
+   }
+
+   if (cs.bits.complete == 1)
+   ret = FJES_CMD_STATUS_NORMAL;
+   else if (timeout = 0)
+   ret = FJES_CMD_STATUS_TIMEOUT;
+
+   } else {
+   switch (cr.bits.err_info) {
+   case FJES_CMD_REQ_ERR_INFO_PARAM:
+   ret = FJES_CMD_STATUS_ERROR_PARAM;
+   break;
+   case FJES_CMD_REQ_ERR_INFO_STATUS:
+   ret = FJES_CMD_STATUS_ERROR_STATUS;
+   break;
+   default:
+   ret = FJES_CMD_STATUS_UNKNOWN;
+   break;
+   }
+   }
+
+   return ret;
+}
+
+int fjes_hw_request_info(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;
+
+   memset(req_buf, 0, hw-hw_info.req_buf_size);
+   memset(res_buf, 0, hw-hw_info.res_buf_size);
+
+   req_buf-info.length = FJES_DEV_COMMAND_INFO_REQ_LEN;
+
+   res_buf-info.length = 0;
+   res_buf-info.code = 0;
+
+   ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
+
+   result = 0;
+
+   if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw-hw_info.max_epid)) !=
+   res_buf-info.length) {
+   result = -ENOMSG;
+   } else if (ret == FJES_CMD_STATUS_NORMAL) {
+   switch (res_buf-info.code) {
+   case FJES_CMD_REQ_RES_CODE_NORMAL:
+   result = 0;
+   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:
+   result = -EPERM;
+   break;
+   case FJES_CMD_STATUS_ERROR_STATUS:
+   result = -EPERM;
+   break;
+   default:
+   result = -EPERM;
+   break;
+   }
+   }
+
+   return result;
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 1b3e9ca..df30d3d 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -34,6 +34,12 @@ struct fjes_hw;
 #define EP_BUFFER_INFO_SIZE 4096
 
 #define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3) /* sec */
+#define FJES_COMMAND_REQ_TIMEOUT  (5 + 1) /* sec */
+
+#define FJES_CMD_REQ_ERR_INFO_PARAM  (0x0001)
+#define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002)
+
+#define FJES_CMD_REQ_RES_CODE_NORMAL (0)
 
 #define EP_BUFFER_SIZE \
(((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
@@ -50,6 +56,7 @@ struct fjes_hw;
((size) - sizeof(struct esmem_frame) - \
(ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))
 
+#define FJES_DEV_COMMAND_INFO_REQ_LEN  (4)
 #define FJES_DEV_COMMAND_INFO_RES_LEN(epnum) (8 + 2 * (epnum))
 #define FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(txb, rxb) \
(24 + (8 * ((txb) / EP_BUFFER_INFO_SIZE + (rxb

[PATCH v2.2 10/22] fjes: tx_stall_task

2015-08-20 Thread Taku Izumi
This patch adds tx_stall_task.
When receiver's buffer is full, sender stops
its tx queue. This task is used to monitor
receiver's status and when receiver's buffer
is avairable, it resumes tx queue.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  2 ++
 drivers/net/fjes/fjes_main.c | 63 
 2 files changed, 65 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 8e9899e..b04ea9d 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -30,6 +30,7 @@
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
 #define FJES_TX_RETRY_TIMEOUT  (100)
+#define FJES_TX_TX_STALL_TIMEOUT   (FJES_TX_RETRY_INTERVAL / 2)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
@@ -52,6 +53,7 @@ struct fjes_adapter {
 
struct workqueue_struct *txrx_wq;
 
+   struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
struct fjes_hw hw;
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 8d67097..8cc687e 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -53,6 +53,7 @@ static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
+static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -278,6 +279,7 @@ static int fjes_close(struct net_device *netdev)
fjes_free_irq(adapter);
 
cancel_work_sync(adapter-raise_intr_rxdata_task);
+   cancel_work_sync(adapter-tx_stall_task);
 
fjes_hw_wait_epstop(hw);
 
@@ -407,6 +409,61 @@ static void fjes_free_resources(struct fjes_adapter 
*adapter)
}
 }
 
+static void fjes_tx_stall_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, tx_stall_task);
+   struct fjes_hw *hw = adapter-hw;
+   struct net_device *netdev = adapter-netdev;
+   enum ep_partner_status pstatus;
+   int epid;
+   int max_epid, my_epid;
+   union ep_buffer_info *info;
+   int all_queue_available;
+   int i;
+   int sendable;
+
+   if (((long)jiffies -
+   (long)(netdev-trans_start))  FJES_TX_TX_STALL_TIMEOUT) {
+   netif_wake_queue(netdev);
+   return;
+   }
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   for (i = 0; i  5; i++) {
+   all_queue_available = 1;
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (my_epid == epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   sendable = (pstatus == EP_PARTNER_SHARED);
+   if (!sendable)
+   continue;
+
+   info = adapter-hw.ep_shm_info[epid].tx.info;
+
+   if (EP_RING_FULL(info-v1i.head, info-v1i.tail,
+info-v1i.count_max)) {
+   all_queue_available = 0;
+   break;
+   }
+   }
+
+   if (all_queue_available) {
+   netif_wake_queue(netdev);
+   return;
+   }
+   }
+
+   usleep_range(50, 100);
+
+   queue_work(adapter-txrx_wq, adapter-tx_stall_task);
+}
+
 static void fjes_raise_intr_rxdata_task(struct work_struct *work)
 {
struct fjes_adapter *adapter = container_of(work,
@@ -602,6 +659,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
netdev-trans_start = jiffies;
netif_tx_stop_queue(cur_queue);
 
+   if 
(!work_pending(adapter-tx_stall_task))
+   queue_work(adapter-txrx_wq,
+  
adapter-tx_stall_task);
+
ret = NETDEV_TX_BUSY;
}
} else {
@@ -686,6 +747,7 @@ static int fjes_probe(struct platform_device *plat_dev)
 
adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
 
+   INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
 
@@ -730,6 +792,7 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_hw *hw = adapter-hw;
 
cancel_work_sync(adapter-raise_intr_rxdata_task

[PATCH v2.2 08/22] fjes: net_device_ops.ndo_start_xmit

2015-08-20 Thread Taku Izumi
This patch adds net_device_ops.ndo_start_xmit callback,
which is called when sending packets.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   1 +
 drivers/net/fjes/fjes_hw.c   |  56 ++
 drivers/net/fjes/fjes_hw.h   |  12 +++
 drivers/net/fjes/fjes_main.c | 176 +++
 4 files changed, 245 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index f182ed3..7af4304 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -29,6 +29,7 @@
 #define FJES_ACPI_SYMBOL   Extended Socket
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
+#define FJES_TX_RETRY_TIMEOUT  (100)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 042f684..4965791 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -791,3 +791,59 @@ int fjes_hw_wait_epstop(struct fjes_hw *hw)
return (wait_time  FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)
? 0 : -EBUSY;
 }
+
+bool fjes_hw_check_epbuf_version(struct epbuf_handler *epbh, u32 version)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   return (info-common.version == version);
+}
+
+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));
+}
+
+bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+   bool ret = false;
+
+   if (vlan_id == 0) {
+   ret = true;
+   } else {
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (vlan_id == info-v1i.vlan_id[i]) {
+   ret = true;
+   break;
+   }
+   }
+   }
+   return ret;
+}
+
+int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
+ void *frame, size_t size)
+{
+   union ep_buffer_info *info = epbh-info;
+   struct esmem_frame *ring_frame;
+
+   if (EP_RING_FULL(info-v1i.head, info-v1i.tail, info-v1i.count_max))
+   return -ENOBUFS;
+
+   ring_frame = (struct esmem_frame *)(epbh-ring[EP_RING_INDEX
+(info-v1i.tail - 1,
+ info-v1i.count_max) *
+info-v1i.frame_max]);
+
+   ring_frame-frame_size = size;
+   memcpy((void *)(ring_frame-frame_data), (void *)frame, size);
+
+   EP_RING_INDEX_INC(epbh-info-v1i.tail, info-v1i.count_max);
+
+   return 0;
+}
+
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index d53c508..2b49421 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -50,6 +50,9 @@ struct fjes_hw;
 
 #define FJES_ZONING_ZONE_TYPE_NONE (0xFF)
 
+#define FJES_TX_DELAY_SEND_NONE(0)
+#define FJES_TX_DELAY_SEND_PENDING (1)
+
 #define FJES_RX_STOP_REQ_NONE  (0x0)
 #define FJES_RX_STOP_REQ_DONE  (0x1)
 #define FJES_RX_STOP_REQ_REQUEST   (0x2)
@@ -61,6 +64,11 @@ struct fjes_hw;
 
 #define EP_RING_NUM(buffer_size, frame_size) \
(u32)((buffer_size) / (frame_size))
+#define EP_RING_INDEX(_num, _max) (((_num) + (_max)) % (_max))
+#define EP_RING_INDEX_INC(_num, _max) \
+   ((_num) = EP_RING_INDEX((_num) + 1, (_max)))
+#define EP_RING_FULL(_head, _tail, _max)   \
+   (0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
 
 #define FJES_MTU_TO_BUFFER_SIZE(mtu) \
(ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
@@ -309,5 +317,9 @@ enum ep_partner_status
 
 bool fjes_hw_epid_is_same_zone(struct fjes_hw *, int);
 int fjes_hw_epid_is_shared(struct fjes_device_shared_info *, int);
+bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
+bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
+bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);
 
 #endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 29bd7dc..be14e66 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -51,6 +51,7 @@ static int fjes_open(struct net_device *);
 static int fjes_close(struct net_device *);
 static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
+static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -212,6 +213,7 @@ static void fjes_free_irq(struct fjes_adapter *adapter)
 static const struct net_device_ops

[PATCH v2.2 09/22] fjes: raise_intr_rxdata_task

2015-08-20 Thread Taku Izumi
This patch add raise_intr_rxdata_task.
Extended Socket Network Device is shared memory
based, so someone's transmission denotes other's
reception. In order to notify receivers, sender
has to raise interruption of receivers.
raise_intr_rxdata_task does this work.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  4 +++
 drivers/net/fjes/fjes_main.c | 64 
 2 files changed, 68 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 7af4304..8e9899e 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -50,6 +50,10 @@ struct fjes_adapter {
 
bool irq_registered;
 
+   struct workqueue_struct *txrx_wq;
+
+   struct work_struct raise_intr_rxdata_task;
+
struct fjes_hw hw;
 };
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index be14e66..8d67097 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -52,6 +52,7 @@ static int fjes_close(struct net_device *);
 static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
+static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -276,6 +277,8 @@ static int fjes_close(struct net_device *netdev)
 
fjes_free_irq(adapter);
 
+   cancel_work_sync(adapter-raise_intr_rxdata_task);
+
fjes_hw_wait_epstop(hw);
 
fjes_free_resources(adapter);
@@ -404,6 +407,55 @@ static void fjes_free_resources(struct fjes_adapter 
*adapter)
}
 }
 
+static void fjes_raise_intr_rxdata_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, raise_intr_rxdata_task);
+   struct fjes_hw *hw = adapter-hw;
+   int epid;
+   int max_epid, my_epid;
+   enum ep_partner_status pstatus;
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   for (epid = 0; epid  max_epid; epid++)
+   hw-ep_shm_info[epid].tx_status_work = 0;
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (epid == my_epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   if (pstatus == EP_PARTNER_SHARED) {
+   hw-ep_shm_info[epid].tx_status_work =
+   hw-ep_shm_info[epid].tx.info-v1i.tx_status;
+
+   if (hw-ep_shm_info[epid].tx_status_work ==
+   FJES_TX_DELAY_SEND_PENDING) {
+   hw-ep_shm_info[epid].tx.info-v1i.tx_status =
+   FJES_TX_DELAY_SEND_NONE;
+   }
+   }
+   }
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (epid == my_epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   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)) {
+   fjes_hw_raise_interrupt(hw, epid,
+   REG_ICTL_MASK_RX_DATA);
+   }
+   }
+
+   usleep_range(500, 1000);
+}
+
 static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
void *data, size_t len)
 {
@@ -416,6 +468,9 @@ static int fjes_tx_send(struct fjes_adapter *adapter, int 
dest,
 
adapter-hw.ep_shm_info[dest].tx.info-v1i.tx_status =
FJES_TX_DELAY_SEND_PENDING;
+   if (!work_pending(adapter-raise_intr_rxdata_task))
+   queue_work(adapter-txrx_wq,
+  adapter-raise_intr_rxdata_task);
 
retval = 0;
return retval;
@@ -629,6 +684,11 @@ static int fjes_probe(struct platform_device *plat_dev)
adapter-force_reset = false;
adapter-open_guard = false;
 
+   adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
+
+   INIT_WORK(adapter-raise_intr_rxdata_task,
+ fjes_raise_intr_rxdata_task);
+
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
hw-hw_res.start = res-start;
hw-hw_res.size = res-end - res-start + 1;
@@ -669,6 +729,10 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = adapter-hw;
 
+   cancel_work_sync(adapter-raise_intr_rxdata_task);
+   if (adapter-txrx_wq)
+   destroy_workqueue(adapter-txrx_wq);
+
unregister_netdev(netdev);
 
fjes_hw_exit(hw);
-- 
1.8.3.1

--
To unsubscribe from this list: send

[PATCH v2.2 07/22] fjes: net_device_ops.ndo_open and .ndo_stop

2015-08-20 Thread Taku Izumi
This patch adds net_device_ops.ndo_open and .ndo_stop
callback. These function is called when network device
activation and deactivation.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   1 +
 drivers/net/fjes/fjes_hw.c   | 144 +
 drivers/net/fjes/fjes_hw.h   |  30 ++
 drivers/net/fjes/fjes_main.c | 246 +++
 drivers/net/fjes/fjes_regs.h |  17 +++
 5 files changed, 438 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 54bc189..f182ed3 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -29,6 +29,7 @@
 #define FJES_ACPI_SYMBOL   Extended Socket
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
+#define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
 struct fjes_adapter {
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 5f43957..042f684 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -638,6 +638,25 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int 
dest_epid)
return result;
 }
 
+int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid,
+   enum REG_ICTL_MASK  mask)
+{
+   u32 ig = mask | dest_epid;
+
+   wr32(XSCT_IG, cpu_to_le32(ig));
+
+   return 0;
+}
+
+u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw)
+{
+   u32 cur_is;
+
+   cur_is = rd32(XSCT_IS);
+
+   return cur_is;
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
@@ -647,3 +666,128 @@ void fjes_hw_set_irqmask(struct fjes_hw *hw,
wr32(XSCT_IMC, intr_mask);
 }
 
+bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid)
+{
+   if (epid = hw-max_epid)
+   return false;
+
+   if ((hw-ep_shm_info[epid].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (hw-ep_shm_info[hw-my_epid].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE))
+   return false;
+   else
+   return (hw-ep_shm_info[epid].zone ==
+   hw-ep_shm_info[hw-my_epid].zone);
+}
+
+int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share,
+  int dest_epid)
+{
+   int value = false;
+
+   if (dest_epid  share-epnum)
+   value = share-ep_status[dest_epid];
+
+   return value;
+}
+
+static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid)
+{
+   return test_bit(src_epid, hw-txrx_stop_req_bit);
+}
+
+static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid)
+{
+   return (hw-ep_shm_info[src_epid].tx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_DONE);
+}
+
+enum ep_partner_status
+fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
+{
+   enum ep_partner_status status;
+
+   if (fjes_hw_epid_is_shared(hw-hw_info.share, epid)) {
+   if (fjes_hw_epid_is_stop_requested(hw, epid)) {
+   status = EP_PARTNER_WAITING;
+   } else {
+   if (fjes_hw_epid_is_stop_process_done(hw, epid))
+   status = EP_PARTNER_COMPLETE;
+   else
+   status = EP_PARTNER_SHARED;
+   }
+   } else {
+   status = EP_PARTNER_UNSHARE;
+   }
+
+   return status;
+}
+
+void fjes_hw_raise_epstop(struct fjes_hw *hw)
+{
+   int epidx;
+   enum ep_partner_status status;
+
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+
+   status = fjes_hw_get_partner_ep_status(hw, epidx);
+   switch (status) {
+   case EP_PARTNER_SHARED:
+   fjes_hw_raise_interrupt(hw, epidx,
+   REG_ICTL_MASK_TXRX_STOP_REQ);
+   break;
+   default:
+   break;
+   }
+
+   set_bit(epidx, hw-hw_info.buffer_unshare_reserve_bit);
+   set_bit(epidx, hw-txrx_stop_req_bit);
+
+   hw-ep_shm_info[epidx].tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_REQUEST;
+   }
+}
+
+int fjes_hw_wait_epstop(struct fjes_hw *hw)
+{
+   int epidx;
+   int wait_time = 0;
+   enum ep_partner_status status;
+   union ep_buffer_info *info;
+
+   while (hw-hw_info.buffer_unshare_reserve_bit 
+  (wait_time  FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) {
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+   status = fjes_hw_epid_is_shared(hw

[PATCH v2.2 02/22] fjes: Hardware initialization routine

2015-08-20 Thread Taku Izumi
This patch adds hardware initialization routine to be
invoked at driver's .probe routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/Makefile|   2 +-
 drivers/net/fjes/fjes.h  |   2 +-
 drivers/net/fjes/fjes_hw.c   | 296 +++
 drivers/net/fjes/fjes_hw.h   | 251 
 drivers/net/fjes/fjes_regs.h | 102 +++
 5 files changed, 651 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_hw.c
 create mode 100644 drivers/net/fjes/fjes_hw.h
 create mode 100644 drivers/net/fjes/fjes_regs.h

diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 98e59cb..a67f65d8 100644
--- a/drivers/net/fjes/Makefile
+++ b/drivers/net/fjes/Makefile
@@ -27,5 +27,5 @@
 
 obj-$(CONFIG_FUJITSU_ES) += fjes.o
 
-fjes-objs := fjes_main.o
+fjes-objs := fjes_main.o fjes_hw.o
 
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 4622da1..15ded96 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -28,6 +28,6 @@
 
 extern char fjes_driver_name[];
 extern char fjes_driver_version[];
-extern u32 fjes_support_mtu[];
+extern const u32 fjes_support_mtu[];
 
 #endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
new file mode 100644
index 000..e94538f
--- /dev/null
+++ b/drivers/net/fjes/fjes_hw.c
@@ -0,0 +1,296 @@
+/*
+ *  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.
+ *
+ */
+
+#include fjes_hw.h
+#include fjes.h
+
+/* supported MTU list */
+const u32 fjes_support_mtu[] = {
+   FJES_MTU_DEFINE(8 * 1024),
+   FJES_MTU_DEFINE(16 * 1024),
+   FJES_MTU_DEFINE(32 * 1024),
+   FJES_MTU_DEFINE(64 * 1024),
+   0
+};
+
+u32 fjes_hw_rd32(struct fjes_hw *hw, u32 reg)
+{
+   u8 *base = hw-base;
+   u32 value = 0;
+
+   value = readl(base[reg]);
+
+   return value;
+}
+
+static u8 *fjes_hw_iomap(struct fjes_hw *hw)
+{
+   u8 *base;
+
+   if (!request_mem_region(hw-hw_res.start, hw-hw_res.size,
+   fjes_driver_name)) {
+   pr_err(request_mem_region failed\n);
+   return NULL;
+   }
+
+   base = (u8 *)ioremap_nocache(hw-hw_res.start, hw-hw_res.size);
+
+   return base;
+}
+
+int fjes_hw_reset(struct fjes_hw *hw)
+{
+   int timeout;
+   union REG_DCTL dctl;
+
+   dctl.reg = 0;
+   dctl.bits.reset = 1;
+   wr32(XSCT_DCTL, dctl.reg);
+
+   timeout = FJES_DEVICE_RESET_TIMEOUT * 1000;
+   dctl.reg = rd32(XSCT_DCTL);
+   while ((dctl.bits.reset == 1)  (timeout  0)) {
+   msleep(1000);
+   dctl.reg = rd32(XSCT_DCTL);
+   timeout -= 1000;
+   }
+
+   return timeout  0 ? 0 : -EIO;
+}
+
+static int fjes_hw_get_max_epid(struct fjes_hw *hw)
+{
+   union REG_MAX_EP info;
+
+   info.reg = rd32(XSCT_MAX_EP);
+
+   return info.bits.maxep;
+}
+
+static int fjes_hw_get_my_epid(struct fjes_hw *hw)
+{
+   union REG_OWNER_EPID info;
+
+   info.reg = rd32(XSCT_OWNER_EPID);
+
+   return info.bits.epid;
+}
+
+static int fjes_hw_alloc_shared_status_region(struct fjes_hw *hw)
+{
+   size_t size;
+
+   size = sizeof(struct fjes_device_shared_info) +
+   (sizeof(u8) * hw-max_epid);
+   hw-hw_info.share = kzalloc(size, GFP_KERNEL);
+   if (!hw-hw_info.share)
+   return -ENOMEM;
+
+   hw-hw_info.share-epnum = hw-max_epid;
+
+   return 0;
+}
+
+static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
+{
+   void *mem;
+
+   mem = vzalloc(EP_BUFFER_SIZE);
+   if (!mem)
+   return -ENOMEM;
+
+   epbh-buffer = mem;
+   epbh-size = EP_BUFFER_SIZE;
+
+   epbh-info = (union ep_buffer_info *)mem;
+   epbh-ring = (u8 *)(mem + sizeof(union ep_buffer_info));
+
+   return 0;
+}
+
+void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+   u16 vlan_id[EP_BUFFER_SUPPORT_VLAN_MAX];
+
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++)
+   vlan_id[i] = info-v1i.vlan_id[i];
+
+   memset(info, 0, sizeof(union ep_buffer_info

[PATCH v2.1 10/22] fjes: tx_stall_task

2015-07-22 Thread Taku Izumi
This patch adds tx_stall_task.
When receiver's buffer is full, sender stops
its tx queue. This task is used to monitor
receiver's status and when receiver's buffer
is avairable, it resumes tx queue.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  2 ++
 drivers/net/fjes/fjes_main.c | 63 
 2 files changed, 65 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 8e9899e..b04ea9d 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -30,6 +30,7 @@
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
 #define FJES_TX_RETRY_TIMEOUT  (100)
+#define FJES_TX_TX_STALL_TIMEOUT   (FJES_TX_RETRY_INTERVAL / 2)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
@@ -52,6 +53,7 @@ struct fjes_adapter {
 
struct workqueue_struct *txrx_wq;
 
+   struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
struct fjes_hw hw;
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 8d67097..8cc687e 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -53,6 +53,7 @@ static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
+static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -278,6 +279,7 @@ static int fjes_close(struct net_device *netdev)
fjes_free_irq(adapter);
 
cancel_work_sync(adapter-raise_intr_rxdata_task);
+   cancel_work_sync(adapter-tx_stall_task);
 
fjes_hw_wait_epstop(hw);
 
@@ -407,6 +409,61 @@ static void fjes_free_resources(struct fjes_adapter 
*adapter)
}
 }
 
+static void fjes_tx_stall_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, tx_stall_task);
+   struct fjes_hw *hw = adapter-hw;
+   struct net_device *netdev = adapter-netdev;
+   enum ep_partner_status pstatus;
+   int epid;
+   int max_epid, my_epid;
+   union ep_buffer_info *info;
+   int all_queue_available;
+   int i;
+   int sendable;
+
+   if (((long)jiffies -
+   (long)(netdev-trans_start))  FJES_TX_TX_STALL_TIMEOUT) {
+   netif_wake_queue(netdev);
+   return;
+   }
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   for (i = 0; i  5; i++) {
+   all_queue_available = 1;
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (my_epid == epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   sendable = (pstatus == EP_PARTNER_SHARED);
+   if (!sendable)
+   continue;
+
+   info = adapter-hw.ep_shm_info[epid].tx.info;
+
+   if (EP_RING_FULL(info-v1i.head, info-v1i.tail,
+info-v1i.count_max)) {
+   all_queue_available = 0;
+   break;
+   }
+   }
+
+   if (all_queue_available) {
+   netif_wake_queue(netdev);
+   return;
+   }
+   }
+
+   usleep_range(50, 100);
+
+   queue_work(adapter-txrx_wq, adapter-tx_stall_task);
+}
+
 static void fjes_raise_intr_rxdata_task(struct work_struct *work)
 {
struct fjes_adapter *adapter = container_of(work,
@@ -602,6 +659,10 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
netdev-trans_start = jiffies;
netif_tx_stop_queue(cur_queue);
 
+   if 
(!work_pending(adapter-tx_stall_task))
+   queue_work(adapter-txrx_wq,
+  
adapter-tx_stall_task);
+
ret = NETDEV_TX_BUSY;
}
} else {
@@ -686,6 +747,7 @@ static int fjes_probe(struct platform_device *plat_dev)
 
adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
 
+   INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
 
@@ -730,6 +792,7 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_hw *hw = adapter-hw;
 
cancel_work_sync(adapter-raise_intr_rxdata_task

[PATCH v2.1 07/22] fjes: net_device_ops.ndo_open and .ndo_stop

2015-07-22 Thread Taku Izumi
This patch adds net_device_ops.ndo_open and .ndo_stop
callback. These function is called when network device
activation and deactivation.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   1 +
 drivers/net/fjes/fjes_hw.c   | 144 +
 drivers/net/fjes/fjes_hw.h   |  30 ++
 drivers/net/fjes/fjes_main.c | 246 +++
 drivers/net/fjes/fjes_regs.h |  17 +++
 5 files changed, 438 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 54bc189..f182ed3 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -29,6 +29,7 @@
 #define FJES_ACPI_SYMBOL   Extended Socket
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
+#define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
 struct fjes_adapter {
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 5f43957..042f684 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -638,6 +638,25 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int 
dest_epid)
return result;
 }
 
+int fjes_hw_raise_interrupt(struct fjes_hw *hw, int dest_epid,
+   enum REG_ICTL_MASK  mask)
+{
+   u32 ig = mask | dest_epid;
+
+   wr32(XSCT_IG, cpu_to_le32(ig));
+
+   return 0;
+}
+
+u32 fjes_hw_capture_interrupt_status(struct fjes_hw *hw)
+{
+   u32 cur_is;
+
+   cur_is = rd32(XSCT_IS);
+
+   return cur_is;
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
@@ -647,3 +666,128 @@ void fjes_hw_set_irqmask(struct fjes_hw *hw,
wr32(XSCT_IMC, intr_mask);
 }
 
+bool fjes_hw_epid_is_same_zone(struct fjes_hw *hw, int epid)
+{
+   if (epid = hw-max_epid)
+   return false;
+
+   if ((hw-ep_shm_info[epid].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (hw-ep_shm_info[hw-my_epid].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE))
+   return false;
+   else
+   return (hw-ep_shm_info[epid].zone ==
+   hw-ep_shm_info[hw-my_epid].zone);
+}
+
+int fjes_hw_epid_is_shared(struct fjes_device_shared_info *share,
+  int dest_epid)
+{
+   int value = false;
+
+   if (dest_epid  share-epnum)
+   value = share-ep_status[dest_epid];
+
+   return value;
+}
+
+static bool fjes_hw_epid_is_stop_requested(struct fjes_hw *hw, int src_epid)
+{
+   return test_bit(src_epid, hw-txrx_stop_req_bit);
+}
+
+static bool fjes_hw_epid_is_stop_process_done(struct fjes_hw *hw, int src_epid)
+{
+   return (hw-ep_shm_info[src_epid].tx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_DONE);
+}
+
+enum ep_partner_status
+fjes_hw_get_partner_ep_status(struct fjes_hw *hw, int epid)
+{
+   enum ep_partner_status status;
+
+   if (fjes_hw_epid_is_shared(hw-hw_info.share, epid)) {
+   if (fjes_hw_epid_is_stop_requested(hw, epid)) {
+   status = EP_PARTNER_WAITING;
+   } else {
+   if (fjes_hw_epid_is_stop_process_done(hw, epid))
+   status = EP_PARTNER_COMPLETE;
+   else
+   status = EP_PARTNER_SHARED;
+   }
+   } else {
+   status = EP_PARTNER_UNSHARE;
+   }
+
+   return status;
+}
+
+void fjes_hw_raise_epstop(struct fjes_hw *hw)
+{
+   int epidx;
+   enum ep_partner_status status;
+
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+
+   status = fjes_hw_get_partner_ep_status(hw, epidx);
+   switch (status) {
+   case EP_PARTNER_SHARED:
+   fjes_hw_raise_interrupt(hw, epidx,
+   REG_ICTL_MASK_TXRX_STOP_REQ);
+   break;
+   default:
+   break;
+   }
+
+   set_bit(epidx, hw-hw_info.buffer_unshare_reserve_bit);
+   set_bit(epidx, hw-txrx_stop_req_bit);
+
+   hw-ep_shm_info[epidx].tx.info-v1i.rx_status |=
+   FJES_RX_STOP_REQ_REQUEST;
+   }
+}
+
+int fjes_hw_wait_epstop(struct fjes_hw *hw)
+{
+   int epidx;
+   int wait_time = 0;
+   enum ep_partner_status status;
+   union ep_buffer_info *info;
+
+   while (hw-hw_info.buffer_unshare_reserve_bit 
+  (wait_time  FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)) {
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+   status = fjes_hw_epid_is_shared(hw

[PATCH v2.1 06/22] fjes: buffer address regist/unregistration routine

2015-07-22 Thread Taku Izumi
This patch adds buffer address regist/unregistration routine.

This function is mainly invoked when network device's
activation (open) and deactivation (close)
in order to retist/unregist shared buffer address.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c | 186 +
 drivers/net/fjes/fjes_hw.h |   9 ++-
 2 files changed, 194 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 3fbe68e..5f43957 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -452,6 +452,192 @@ int fjes_hw_request_info(struct fjes_hw *hw)
return result;
 }
 
+int fjes_hw_register_buff_addr(struct fjes_hw *hw, int dest_epid,
+  struct ep_share_mem_info *buf_pair)
+{
+   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 i, idx;
+   int page_count;
+   void *addr;
+   int timeout;
+   int result;
+
+   if (test_bit(dest_epid, hw-hw_info.buffer_share_bit))
+   return 0;
+
+   memset(req_buf, 0, hw-hw_info.req_buf_size);
+   memset(res_buf, 0, hw-hw_info.res_buf_size);
+
+   req_buf-share_buffer.length = FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(
+   buf_pair-tx.size,
+   buf_pair-rx.size);
+   req_buf-share_buffer.epid = dest_epid;
+
+   idx = 0;
+   req_buf-share_buffer.buffer[idx++] = buf_pair-tx.size;
+   page_count = buf_pair-tx.size / EP_BUFFER_INFO_SIZE;
+   for (i = 0; i  page_count; i++) {
+   addr = ((u8 *)(buf_pair-tx.buffer)) +
+   (i * EP_BUFFER_INFO_SIZE);
+   req_buf-share_buffer.buffer[idx++] =
+   (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+   offset_in_page(addr));
+   }
+
+   req_buf-share_buffer.buffer[idx++] = buf_pair-rx.size;
+   page_count = buf_pair-rx.size / EP_BUFFER_INFO_SIZE;
+   for (i = 0; i  page_count; i++) {
+   addr = ((u8 *)(buf_pair-rx.buffer)) +
+   (i * EP_BUFFER_INFO_SIZE);
+   req_buf-share_buffer.buffer[idx++] =
+   (__le64)(page_to_phys(vmalloc_to_page(addr)) +
+   offset_in_page(addr));
+   }
+
+   res_buf-share_buffer.length = 0;
+   res_buf-share_buffer.code = 0;
+
+   ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_SHARE_BUFFER);
+
+   timeout = FJES_COMMAND_REQ_BUFF_TIMEOUT * 1000;
+   while ((ret == FJES_CMD_STATUS_NORMAL) 
+  (res_buf-share_buffer.length ==
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN) 
+  (res_buf-share_buffer.code == FJES_CMD_REQ_RES_CODE_BUSY) 
+  (timeout  0)) {
+   msleep(200 + hw-my_epid * 20);
+   timeout -= (200 + hw-my_epid * 20);
+
+   res_buf-share_buffer.length = 0;
+   res_buf-share_buffer.code = 0;
+
+   ret = fjes_hw_issue_request_command(
+   hw, FJES_CMD_REQ_SHARE_BUFFER);
+   }
+
+   result = 0;
+
+   if (res_buf-share_buffer.length !=
+   FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN)
+   result = -ENOMSG;
+   else if (ret == FJES_CMD_STATUS_NORMAL) {
+   switch (res_buf-share_buffer.code) {
+   case FJES_CMD_REQ_RES_CODE_NORMAL:
+   result = 0;
+   set_bit(dest_epid, hw-hw_info.buffer_share_bit);
+   break;
+   case FJES_CMD_REQ_RES_CODE_BUSY:
+   result = -EBUSY;
+   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_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
+{
+   union fjes_device_command_req *req_buf = hw-hw_info.req_buf;
+   union fjes_device_command_res *res_buf = hw-hw_info.res_buf;
+   struct fjes_device_shared_info *share = hw-hw_info.share;
+   enum fjes_dev_command_response_e ret

[PATCH v2.1 15/22] fjes: net_device_ops.ndo_vlan_rx_add/kill_vid

2015-07-22 Thread Taku Izumi
This patch adds net_device_ops.ndo_vlan_rx_add_vid and
net_device_ops.ndo_vlan_rx_kill_vid callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 27 +++
 drivers/net/fjes/fjes_hw.h   |  2 ++
 drivers/net/fjes/fjes_main.c | 40 
 3 files changed, 69 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index ae7b7cd..46e114c 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -825,6 +825,33 @@ bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 
vlan_id)
return ret;
 }
 
+bool fjes_hw_set_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (info-v1i.vlan_id[i] == 0) {
+   info-v1i.vlan_id[i] = vlan_id;
+   return true;
+   }
+   }
+   return false;
+}
+
+void fjes_hw_del_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+
+   if (0 != vlan_id) {
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (vlan_id == info-v1i.vlan_id[i])
+   info-v1i.vlan_id[i] = 0;
+   }
+   }
+}
+
 bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
 {
union ep_buffer_info *info = epbh-info;
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 0b43bc3..2fcbfeb 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -322,6 +322,8 @@ int fjes_hw_epid_is_shared(struct fjes_device_shared_info 
*, int);
 bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
 bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
 bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+bool fjes_hw_set_vlan_id(struct epbuf_handler *, u16);
+void fjes_hw_del_vlan_id(struct epbuf_handler *, u16);
 bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
 void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
 void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index c611c58..1bb9347 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -58,6 +58,8 @@ static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 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 void fjes_tx_retry(struct net_device *);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -226,6 +228,8 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_get_stats64= fjes_get_stats64,
.ndo_change_mtu = fjes_change_mtu,
.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,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -753,6 +757,42 @@ static int fjes_change_mtu(struct net_device *netdev, int 
new_mtu)
return -EINVAL;
 }
 
+static int fjes_vlan_rx_add_vid(struct net_device *netdev,
+   __be16 proto, u16 vid)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   bool ret = true;
+   int epid;
+
+   for (epid = 0; epid  adapter-hw.max_epid; epid++) {
+   if (epid == adapter-hw.my_epid)
+   continue;
+
+   if (!fjes_hw_check_vlan_id(
+   adapter-hw.ep_shm_info[epid].tx, vid))
+   ret = fjes_hw_set_vlan_id(
+   adapter-hw.ep_shm_info[epid].tx, vid);
+   }
+
+   return ret ? 0 : -ENOSPC;
+}
+
+static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
+__be16 proto, u16 vid)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   int epid;
+
+   for (epid = 0; epid  adapter-hw.max_epid; epid++) {
+   if (epid == adapter-hw.my_epid)
+   continue;
+
+   fjes_hw_del_vlan_id(adapter-hw.ep_shm_info[epid].tx, vid);
+   }
+
+   return 0;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.1 13/22] fjes: net_device_ops.ndo_change_mtu

2015-07-22 Thread Taku Izumi
This patch adds net_device_ops.ndo_change_mtu.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 842edbb..bb94890 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -57,6 +57,7 @@ static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
+static int fjes_change_mtu(struct net_device *, int);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -222,6 +223,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_stop   = fjes_close,
.ndo_start_xmit = fjes_xmit_frame,
.ndo_get_stats64= fjes_get_stats64,
+   .ndo_change_mtu = fjes_change_mtu,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -715,6 +717,33 @@ fjes_get_stats64(struct net_device *netdev, struct 
rtnl_link_stats64 *stats)
return stats;
 }
 
+static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
+{
+   int idx;
+   bool running = netif_running(netdev);
+   int ret = 0;
+
+   for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
+   if (new_mtu = fjes_support_mtu[idx]) {
+   new_mtu = fjes_support_mtu[idx];
+   if (new_mtu == netdev-mtu)
+   return 0;
+
+   if (running)
+   fjes_close(netdev);
+
+   netdev-mtu = new_mtu;
+
+   if (running)
+   ret = fjes_open(netdev);
+
+   return ret;
+   }
+   }
+
+   return -EINVAL;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.1 02/22] fjes: Hardware initialization routine

2015-07-22 Thread Taku Izumi
This patch adds hardware initialization routine to be
invoked at driver's .probe routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/Makefile|   2 +-
 drivers/net/fjes/fjes.h  |   2 +-
 drivers/net/fjes/fjes_hw.c   | 296 +++
 drivers/net/fjes/fjes_hw.h   | 251 
 drivers/net/fjes/fjes_regs.h | 102 +++
 5 files changed, 651 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/fjes/fjes_hw.c
 create mode 100644 drivers/net/fjes/fjes_hw.h
 create mode 100644 drivers/net/fjes/fjes_regs.h

diff --git a/drivers/net/fjes/Makefile b/drivers/net/fjes/Makefile
index 98e59cb..a67f65d8 100644
--- a/drivers/net/fjes/Makefile
+++ b/drivers/net/fjes/Makefile
@@ -27,5 +27,5 @@
 
 obj-$(CONFIG_FUJITSU_ES) += fjes.o
 
-fjes-objs := fjes_main.o
+fjes-objs := fjes_main.o fjes_hw.o
 
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 4622da1..15ded96 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -28,6 +28,6 @@
 
 extern char fjes_driver_name[];
 extern char fjes_driver_version[];
-extern u32 fjes_support_mtu[];
+extern const u32 fjes_support_mtu[];
 
 #endif /* FJES_H_ */
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
new file mode 100644
index 000..e94538f
--- /dev/null
+++ b/drivers/net/fjes/fjes_hw.c
@@ -0,0 +1,296 @@
+/*
+ *  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.
+ *
+ */
+
+#include fjes_hw.h
+#include fjes.h
+
+/* supported MTU list */
+const u32 fjes_support_mtu[] = {
+   FJES_MTU_DEFINE(8 * 1024),
+   FJES_MTU_DEFINE(16 * 1024),
+   FJES_MTU_DEFINE(32 * 1024),
+   FJES_MTU_DEFINE(64 * 1024),
+   0
+};
+
+u32 fjes_hw_rd32(struct fjes_hw *hw, u32 reg)
+{
+   u8 *base = hw-base;
+   u32 value = 0;
+
+   value = readl(base[reg]);
+
+   return value;
+}
+
+static u8 *fjes_hw_iomap(struct fjes_hw *hw)
+{
+   u8 *base;
+
+   if (!request_mem_region(hw-hw_res.start, hw-hw_res.size,
+   fjes_driver_name)) {
+   pr_err(request_mem_region failed\n);
+   return NULL;
+   }
+
+   base = (u8 *)ioremap_nocache(hw-hw_res.start, hw-hw_res.size);
+
+   return base;
+}
+
+int fjes_hw_reset(struct fjes_hw *hw)
+{
+   int timeout;
+   union REG_DCTL dctl;
+
+   dctl.reg = 0;
+   dctl.bits.reset = 1;
+   wr32(XSCT_DCTL, dctl.reg);
+
+   timeout = FJES_DEVICE_RESET_TIMEOUT * 1000;
+   dctl.reg = rd32(XSCT_DCTL);
+   while ((dctl.bits.reset == 1)  (timeout  0)) {
+   msleep(1000);
+   dctl.reg = rd32(XSCT_DCTL);
+   timeout -= 1000;
+   }
+
+   return timeout  0 ? 0 : -EIO;
+}
+
+static int fjes_hw_get_max_epid(struct fjes_hw *hw)
+{
+   union REG_MAX_EP info;
+
+   info.reg = rd32(XSCT_MAX_EP);
+
+   return info.bits.maxep;
+}
+
+static int fjes_hw_get_my_epid(struct fjes_hw *hw)
+{
+   union REG_OWNER_EPID info;
+
+   info.reg = rd32(XSCT_OWNER_EPID);
+
+   return info.bits.epid;
+}
+
+static int fjes_hw_alloc_shared_status_region(struct fjes_hw *hw)
+{
+   size_t size;
+
+   size = sizeof(struct fjes_device_shared_info) +
+   (sizeof(u8) * hw-max_epid);
+   hw-hw_info.share = kzalloc(size, GFP_KERNEL);
+   if (!hw-hw_info.share)
+   return -ENOMEM;
+
+   hw-hw_info.share-epnum = hw-max_epid;
+
+   return 0;
+}
+
+static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
+{
+   void *mem;
+
+   mem = vzalloc(EP_BUFFER_SIZE);
+   if (!mem)
+   return -ENOMEM;
+
+   epbh-buffer = mem;
+   epbh-size = EP_BUFFER_SIZE;
+
+   epbh-info = (union ep_buffer_info *)mem;
+   epbh-ring = (u8 *)(mem + sizeof(union ep_buffer_info));
+
+   return 0;
+}
+
+void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+   u16 vlan_id[EP_BUFFER_SUPPORT_VLAN_MAX];
+
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++)
+   vlan_id[i] = info-v1i.vlan_id[i];
+
+   memset(info, 0, sizeof(union ep_buffer_info

[PATCH v2.1 16/22] fjes: interrupt_watch_task

2015-07-22 Thread Taku Izumi
This patch adds interrupt_watch_task.
This task is used to prevent delay of interrupts.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  5 +
 drivers/net/fjes/fjes_main.c | 40 +++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index b04ea9d..1743dbb 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -32,6 +32,7 @@
 #define FJES_TX_RETRY_TIMEOUT  (100)
 #define FJES_TX_TX_STALL_TIMEOUT   (FJES_TX_RETRY_INTERVAL / 2)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
+#define FJES_IRQ_WATCH_DELAY   (HZ)
 
 /* board specific private data structure */
 struct fjes_adapter {
@@ -52,10 +53,14 @@ struct fjes_adapter {
bool irq_registered;
 
struct workqueue_struct *txrx_wq;
+   struct workqueue_struct *control_wq;
 
struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
+   struct delayed_work interrupt_watch_task;
+   bool interrupt_watch_enable;
+
struct fjes_hw hw;
 };
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 1bb9347..2bf9f71 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -71,7 +71,7 @@ static int fjes_remove(struct platform_device *);
 
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
-
+static void fjes_irq_watch_task(struct work_struct *);
 static void fjes_rx_irq(struct fjes_adapter *, int);
 static int fjes_poll(struct napi_struct *, int);
 
@@ -197,6 +197,13 @@ static int fjes_request_irq(struct fjes_adapter *adapter)
struct net_device *netdev = adapter-netdev;
int result = -1;
 
+   adapter-interrupt_watch_enable = true;
+   if (!delayed_work_pending(adapter-interrupt_watch_task)) {
+   queue_delayed_work(adapter-control_wq,
+  adapter-interrupt_watch_task,
+  FJES_IRQ_WATCH_DELAY);
+   }
+
if (!adapter-irq_registered) {
result = request_irq(adapter-hw.hw_res.irq, fjes_intr,
 IRQF_SHARED, netdev-name, adapter);
@@ -213,6 +220,9 @@ static void fjes_free_irq(struct fjes_adapter *adapter)
 {
struct fjes_hw *hw = adapter-hw;
 
+   adapter-interrupt_watch_enable = false;
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
+
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
if (adapter-irq_registered) {
@@ -297,6 +307,7 @@ static int fjes_close(struct net_device *netdev)
 
fjes_free_irq(adapter);
 
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
 
@@ -999,11 +1010,15 @@ static int fjes_probe(struct platform_device *plat_dev)
adapter-open_guard = false;
 
adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
+   adapter-control_wq = create_workqueue(DRV_NAME /control);
 
INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
 
+   INIT_DELAYED_WORK(adapter-interrupt_watch_task, fjes_irq_watch_task);
+   adapter-interrupt_watch_enable = false;
+
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
hw-hw_res.start = res-start;
hw-hw_res.size = res-end - res-start + 1;
@@ -1044,8 +1059,11 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = adapter-hw;
 
+   cancel_delayed_work_sync(adapter-interrupt_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
+   if (adapter-control_wq)
+   destroy_workqueue(adapter-control_wq);
if (adapter-txrx_wq)
destroy_workqueue(adapter-txrx_wq);
 
@@ -1081,6 +1099,26 @@ static void fjes_netdev_setup(struct net_device *netdev)
netdev-features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
 }
 
+static void fjes_irq_watch_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(to_delayed_work(work),
+   struct fjes_adapter, interrupt_watch_task);
+
+   local_irq_disable();
+   fjes_intr(adapter-hw.hw_res.irq, adapter);
+   local_irq_enable();
+
+   if (fjes_rxframe_search_exist(adapter, 0) = 0)
+   napi_schedule(adapter-napi);
+
+   if (adapter-interrupt_watch_enable) {
+   if (!delayed_work_pending(adapter-interrupt_watch_task))
+   queue_delayed_work(adapter-control_wq,
+  adapter-interrupt_watch_task

[PATCH v2.1 14/22] fjes: net_device_ops.ndo_tx_timeout

2015-07-22 Thread Taku Izumi
This patch adds net_device_ops.ndo_tx_timeout callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index bb94890..c611c58 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -58,6 +58,7 @@ static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
 static int fjes_change_mtu(struct net_device *, int);
+static void fjes_tx_retry(struct net_device *);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -224,6 +225,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_start_xmit = fjes_xmit_frame,
.ndo_get_stats64= fjes_get_stats64,
.ndo_change_mtu = fjes_change_mtu,
+   .ndo_tx_timeout = fjes_tx_retry,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -707,6 +709,13 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
return ret;
 }
 
+static void fjes_tx_retry(struct net_device *netdev)
+{
+   struct netdev_queue *queue = netdev_get_tx_queue(netdev, 0);
+
+   netif_tx_wake_queue(queue);
+}
+
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
 {
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.1 09/22] fjes: raise_intr_rxdata_task

2015-07-22 Thread Taku Izumi
This patch add raise_intr_rxdata_task.
Extended Socket Network Device is shared memory
based, so someone's transmission denotes other's
reception. In order to notify receivers, sender
has to raise interruption of receivers.
raise_intr_rxdata_task does this work.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  4 +++
 drivers/net/fjes/fjes_main.c | 64 
 2 files changed, 68 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 7af4304..8e9899e 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -50,6 +50,10 @@ struct fjes_adapter {
 
bool irq_registered;
 
+   struct workqueue_struct *txrx_wq;
+
+   struct work_struct raise_intr_rxdata_task;
+
struct fjes_hw hw;
 };
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index be14e66..8d67097 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -52,6 +52,7 @@ static int fjes_close(struct net_device *);
 static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
+static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -276,6 +277,8 @@ static int fjes_close(struct net_device *netdev)
 
fjes_free_irq(adapter);
 
+   cancel_work_sync(adapter-raise_intr_rxdata_task);
+
fjes_hw_wait_epstop(hw);
 
fjes_free_resources(adapter);
@@ -404,6 +407,55 @@ static void fjes_free_resources(struct fjes_adapter 
*adapter)
}
 }
 
+static void fjes_raise_intr_rxdata_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, raise_intr_rxdata_task);
+   struct fjes_hw *hw = adapter-hw;
+   int epid;
+   int max_epid, my_epid;
+   enum ep_partner_status pstatus;
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   for (epid = 0; epid  max_epid; epid++)
+   hw-ep_shm_info[epid].tx_status_work = 0;
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (epid == my_epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   if (pstatus == EP_PARTNER_SHARED) {
+   hw-ep_shm_info[epid].tx_status_work =
+   hw-ep_shm_info[epid].tx.info-v1i.tx_status;
+
+   if (hw-ep_shm_info[epid].tx_status_work ==
+   FJES_TX_DELAY_SEND_PENDING) {
+   hw-ep_shm_info[epid].tx.info-v1i.tx_status =
+   FJES_TX_DELAY_SEND_NONE;
+   }
+   }
+   }
+
+   for (epid = 0; epid  max_epid; epid++) {
+   if (epid == my_epid)
+   continue;
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epid);
+   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)) {
+   fjes_hw_raise_interrupt(hw, epid,
+   REG_ICTL_MASK_RX_DATA);
+   }
+   }
+
+   usleep_range(500, 1000);
+}
+
 static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
void *data, size_t len)
 {
@@ -416,6 +468,9 @@ static int fjes_tx_send(struct fjes_adapter *adapter, int 
dest,
 
adapter-hw.ep_shm_info[dest].tx.info-v1i.tx_status =
FJES_TX_DELAY_SEND_PENDING;
+   if (!work_pending(adapter-raise_intr_rxdata_task))
+   queue_work(adapter-txrx_wq,
+  adapter-raise_intr_rxdata_task);
 
retval = 0;
return retval;
@@ -629,6 +684,11 @@ static int fjes_probe(struct platform_device *plat_dev)
adapter-force_reset = false;
adapter-open_guard = false;
 
+   adapter-txrx_wq = create_workqueue(DRV_NAME /txrx);
+
+   INIT_WORK(adapter-raise_intr_rxdata_task,
+ fjes_raise_intr_rxdata_task);
+
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
hw-hw_res.start = res-start;
hw-hw_res.size = res-end - res-start + 1;
@@ -669,6 +729,10 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = adapter-hw;
 
+   cancel_work_sync(adapter-raise_intr_rxdata_task);
+   if (adapter-txrx_wq)
+   destroy_workqueue(adapter-txrx_wq);
+
unregister_netdev(netdev);
 
fjes_hw_exit(hw);
-- 
1.8.3.1

--
To unsubscribe from this list: send

[PATCH v2.1 11/22] fjes: NAPI polling function

2015-07-22 Thread Taku Izumi
This patch adds NAPI polling function and receive related work.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   |  40 ++
 drivers/net/fjes/fjes_hw.h   |   5 ++
 drivers/net/fjes/fjes_main.c | 172 ++-
 3 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 4965791..ae7b7cd 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -825,6 +825,46 @@ bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 
vlan_id)
return ret;
 }
 
+bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   if (info-v1i.count_max == 0)
+   return true;
+
+   return EP_RING_EMPTY(info-v1i.head, info-v1i.tail,
+info-v1i.count_max);
+}
+
+void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *epbh,
+  size_t *psize)
+{
+   union ep_buffer_info *info = epbh-info;
+   struct esmem_frame *ring_frame;
+   void *frame;
+
+   ring_frame = (struct esmem_frame *)(epbh-ring[EP_RING_INDEX
+(info-v1i.head,
+ info-v1i.count_max) *
+info-v1i.frame_max]);
+
+   *psize = (size_t)ring_frame-frame_size;
+
+   frame = ring_frame-frame_data;
+
+   return frame;
+}
+
+void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *epbh)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   if (fjes_hw_epbuf_rx_is_empty(epbh))
+   return;
+
+   EP_RING_INDEX_INC(epbh-info-v1i.head, info-v1i.count_max);
+}
+
 int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
  void *frame, size_t size)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 2b49421..0b43bc3 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -69,6 +69,8 @@ struct fjes_hw;
((_num) = EP_RING_INDEX((_num) + 1, (_max)))
 #define EP_RING_FULL(_head, _tail, _max)   \
(0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
+#define EP_RING_EMPTY(_head, _tail, _max) \
+   (1 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
 
 #define FJES_MTU_TO_BUFFER_SIZE(mtu) \
(ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
@@ -320,6 +322,9 @@ int fjes_hw_epid_is_shared(struct fjes_device_shared_info 
*, int);
 bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
 bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
 bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
+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);
 
 #endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 8cc687e..186197d 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -66,6 +66,9 @@ static int fjes_remove(struct platform_device *);
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
 
+static void fjes_rx_irq(struct fjes_adapter *, int);
+static int fjes_poll(struct napi_struct *, int);
+
 static const struct acpi_device_id fjes_acpi_ids[] = {
{PNP0C02, 0},
{, 0},
@@ -235,6 +238,8 @@ static int fjes_open(struct net_device *netdev)
hw-txrx_stop_req_bit = 0;
hw-epstop_req_bit = 0;
 
+   napi_enable(adapter-napi);
+
fjes_hw_capture_interrupt_status(hw);
 
result = fjes_request_irq(adapter);
@@ -250,6 +255,7 @@ static int fjes_open(struct net_device *netdev)
 
 err_req_irq:
fjes_free_irq(adapter);
+   napi_disable(adapter-napi);
 
 err_setup_res:
fjes_free_resources(adapter);
@@ -268,6 +274,8 @@ static int fjes_close(struct net_device *netdev)
 
fjes_hw_raise_epstop(hw);
 
+   napi_disable(adapter-napi);
+
for (epidx = 0; epidx  hw-max_epid; epidx++) {
if (epidx == hw-my_epid)
continue;
@@ -703,14 +711,168 @@ 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_IS_MASK_IS_ASSERT) {
+   if (icr  REG_ICTL_MASK_RX_DATA)
+   fjes_rx_irq(adapter, icr  REG_IS_MASK_EPID);
+
ret = IRQ_HANDLED;
-   else
+   } else {
ret = IRQ_NONE;
+   }
 
return ret;
 }
 
+static int fjes_rxframe_search_exist(struct fjes_adapter *adapter,
+int start_epid)
+{
+   struct fjes_hw *hw = adapter-hw;
+   int cur_epid

[PATCH v2.1 04/22] fjes: platform_driver's .probe and .remove routine

2015-07-22 Thread Taku Izumi
This patch implements platform_driver's .probe and .remove
routine, and also adds board specific private data structure.

This driver registers net_device at platform_driver's .probe
routine and unregisters net_device at its .remove routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  | 25 
 drivers/net/fjes/fjes_main.c | 95 
 2 files changed, 120 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 15ded96..54bc189 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -24,7 +24,32 @@
 
 #include linux/acpi.h
 
+#include fjes_hw.h
+
 #define FJES_ACPI_SYMBOL   Extended Socket
+#define FJES_MAX_QUEUES1
+#define FJES_TX_RETRY_INTERVAL (20 * HZ)
+
+/* board specific private data structure */
+struct fjes_adapter {
+   struct net_device *netdev;
+   struct platform_device *plat_dev;
+
+   struct napi_struct napi;
+   struct rtnl_link_stats64 stats64;
+
+   unsigned int tx_retry_count;
+   unsigned long tx_start_jiffies;
+   unsigned long rx_last_jiffies;
+   bool unset_rx_last;
+
+   bool force_reset;
+   bool open_guard;
+
+   bool irq_registered;
+
+   struct fjes_hw hw;
+};
 
 extern char fjes_driver_name[];
 extern char fjes_driver_version[];
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index ab4d20c..7695b84 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -23,6 +23,7 @@
 #include linux/types.h
 #include linux/nls.h
 #include linux/platform_device.h
+#include linux/netdevice.h
 
 #include fjes.h
 
@@ -49,6 +50,9 @@ static acpi_status fjes_get_acpi_resource(struct 
acpi_resource *, void*);
 static int fjes_probe(struct platform_device *);
 static int fjes_remove(struct platform_device *);
 
+static int fjes_sw_init(struct fjes_adapter *);
+static void fjes_netdev_setup(struct net_device *);
+
 static const struct acpi_device_id fjes_acpi_ids[] = {
{PNP0C02, 0},
{, 0},
@@ -166,18 +170,109 @@ fjes_get_acpi_resource(struct acpi_resource *acpi_res, 
void *data)
return AE_OK;
 }
 
+static const struct net_device_ops fjes_netdev_ops = {
+};
+
 /* fjes_probe - Device Initialization Routine */
 static int fjes_probe(struct platform_device *plat_dev)
 {
+   struct net_device *netdev;
+   struct fjes_adapter *adapter;
+   struct fjes_hw *hw;
+   struct resource *res;
+   int err;
+
+   err = -ENOMEM;
+   netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), es%d,
+NET_NAME_UNKNOWN, fjes_netdev_setup,
+FJES_MAX_QUEUES);
+
+   if (!netdev)
+   goto err_alloc_netdev;
+
+   SET_NETDEV_DEV(netdev, plat_dev-dev);
+
+   dev_set_drvdata(plat_dev-dev, netdev);
+   adapter = netdev_priv(netdev);
+   adapter-netdev = netdev;
+   adapter-plat_dev = plat_dev;
+   hw = adapter-hw;
+   hw-back = adapter;
+
+   /* setup the private structure */
+   err = fjes_sw_init(adapter);
+   if (err)
+   goto err_sw_init;
+
+   adapter-force_reset = false;
+   adapter-open_guard = false;
+
+   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.irq = platform_get_irq(plat_dev, 0);
+   err = fjes_hw_init(adapter-hw);
+   if (err)
+   goto err_hw_init;
+
+   /* setup MAC address (02:00:00:00:00:[epid])*/
+   netdev-dev_addr[0] = 2;
+   netdev-dev_addr[1] = 0;
+   netdev-dev_addr[2] = 0;
+   netdev-dev_addr[3] = 0;
+   netdev-dev_addr[4] = 0;
+   netdev-dev_addr[5] = hw-my_epid; /* EPID */
+
+   err = register_netdev(netdev);
+   if (err)
+   goto err_register;
+
+   netif_carrier_off(netdev);
+
return 0;
+
+err_register:
+   fjes_hw_exit(adapter-hw);
+err_hw_init:
+err_sw_init:
+   free_netdev(netdev);
+err_alloc_netdev:
+   return err;
 }
 
 /* fjes_remove - Device Removal Routine */
 static int fjes_remove(struct platform_device *plat_dev)
 {
+   struct net_device *netdev = dev_get_drvdata(plat_dev-dev);
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+   struct fjes_hw *hw = adapter-hw;
+
+   unregister_netdev(netdev);
+
+   fjes_hw_exit(hw);
+
+   free_netdev(netdev);
+
return 0;
 }
 
+static int fjes_sw_init(struct fjes_adapter *adapter)
+{
+   return 0;
+}
+
+/* fjes_netdev_setup - netdevice initialization routine */
+static void fjes_netdev_setup(struct net_device *netdev)
+{
+   ether_setup(netdev);
+
+   netdev-watchdog_timeo = FJES_TX_RETRY_INTERVAL;
+   netdev-netdev_ops = fjes_netdev_ops;
+   netdev-mtu = fjes_support_mtu[0];
+   netdev-flags |= IFF_BROADCAST;
+   netdev-features |= NETIF_F_HW_CSUM

[PATCH v2.1 08/22] fjes: net_device_ops.ndo_start_xmit

2015-07-22 Thread Taku Izumi
This patch adds net_device_ops.ndo_start_xmit callback,
which is called when sending packets.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   1 +
 drivers/net/fjes/fjes_hw.c   |  56 ++
 drivers/net/fjes/fjes_hw.h   |  12 +++
 drivers/net/fjes/fjes_main.c | 176 +++
 4 files changed, 245 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index f182ed3..7af4304 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -29,6 +29,7 @@
 #define FJES_ACPI_SYMBOL   Extended Socket
 #define FJES_MAX_QUEUES1
 #define FJES_TX_RETRY_INTERVAL (20 * HZ)
+#define FJES_TX_RETRY_TIMEOUT  (100)
 #define FJES_OPEN_ZONE_UPDATE_WAIT (300) /* msec */
 
 /* board specific private data structure */
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 042f684..4965791 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -791,3 +791,59 @@ int fjes_hw_wait_epstop(struct fjes_hw *hw)
return (wait_time  FJES_COMMAND_EPSTOP_WAIT_TIMEOUT * 1000)
? 0 : -EBUSY;
 }
+
+bool fjes_hw_check_epbuf_version(struct epbuf_handler *epbh, u32 version)
+{
+   union ep_buffer_info *info = epbh-info;
+
+   return (info-common.version == version);
+}
+
+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));
+}
+
+bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
+{
+   union ep_buffer_info *info = epbh-info;
+   int i;
+   bool ret = false;
+
+   if (vlan_id == 0) {
+   ret = true;
+   } else {
+   for (i = 0; i  EP_BUFFER_SUPPORT_VLAN_MAX; i++) {
+   if (vlan_id == info-v1i.vlan_id[i]) {
+   ret = true;
+   break;
+   }
+   }
+   }
+   return ret;
+}
+
+int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
+ void *frame, size_t size)
+{
+   union ep_buffer_info *info = epbh-info;
+   struct esmem_frame *ring_frame;
+
+   if (EP_RING_FULL(info-v1i.head, info-v1i.tail, info-v1i.count_max))
+   return -ENOBUFS;
+
+   ring_frame = (struct esmem_frame *)(epbh-ring[EP_RING_INDEX
+(info-v1i.tail - 1,
+ info-v1i.count_max) *
+info-v1i.frame_max]);
+
+   ring_frame-frame_size = size;
+   memcpy((void *)(ring_frame-frame_data), (void *)frame, size);
+
+   EP_RING_INDEX_INC(epbh-info-v1i.tail, info-v1i.count_max);
+
+   return 0;
+}
+
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index d53c508..2b49421 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -50,6 +50,9 @@ struct fjes_hw;
 
 #define FJES_ZONING_ZONE_TYPE_NONE (0xFF)
 
+#define FJES_TX_DELAY_SEND_NONE(0)
+#define FJES_TX_DELAY_SEND_PENDING (1)
+
 #define FJES_RX_STOP_REQ_NONE  (0x0)
 #define FJES_RX_STOP_REQ_DONE  (0x1)
 #define FJES_RX_STOP_REQ_REQUEST   (0x2)
@@ -61,6 +64,11 @@ struct fjes_hw;
 
 #define EP_RING_NUM(buffer_size, frame_size) \
(u32)((buffer_size) / (frame_size))
+#define EP_RING_INDEX(_num, _max) (((_num) + (_max)) % (_max))
+#define EP_RING_INDEX_INC(_num, _max) \
+   ((_num) = EP_RING_INDEX((_num) + 1, (_max)))
+#define EP_RING_FULL(_head, _tail, _max)   \
+   (0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
 
 #define FJES_MTU_TO_BUFFER_SIZE(mtu) \
(ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
@@ -309,5 +317,9 @@ enum ep_partner_status
 
 bool fjes_hw_epid_is_same_zone(struct fjes_hw *, int);
 int fjes_hw_epid_is_shared(struct fjes_device_shared_info *, int);
+bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
+bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
+bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
+int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);
 
 #endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 29bd7dc..be14e66 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -51,6 +51,7 @@ static int fjes_open(struct net_device *);
 static int fjes_close(struct net_device *);
 static int fjes_setup_resources(struct fjes_adapter *);
 static void fjes_free_resources(struct fjes_adapter *);
+static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static irqreturn_t fjes_intr(int, void*);
 
 static int fjes_acpi_add(struct acpi_device *);
@@ -212,6 +213,7 @@ static void fjes_free_irq(struct fjes_adapter *adapter)
 static const struct net_device_ops

[PATCH v2.1 12/22] fjes: net_device_ops.ndo_get_stats64

2015-07-22 Thread Taku Izumi
This patch adds net_device_ops.ndo_get_stats64 callback.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_main.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 186197d..842edbb 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -55,6 +55,8 @@ static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct 
net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static void fjes_tx_stall_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
+static struct rtnl_link_stats64 *
+fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
 
 static int fjes_acpi_add(struct acpi_device *);
 static int fjes_acpi_remove(struct acpi_device *);
@@ -219,6 +221,7 @@ static const struct net_device_ops fjes_netdev_ops = {
.ndo_open   = fjes_open,
.ndo_stop   = fjes_close,
.ndo_start_xmit = fjes_xmit_frame,
+   .ndo_get_stats64= fjes_get_stats64,
 };
 
 /* fjes_open - Called when a network interface is made active */
@@ -702,6 +705,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device 
*netdev)
return ret;
 }
 
+static struct rtnl_link_stats64 *
+fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+   struct fjes_adapter *adapter = netdev_priv(netdev);
+
+   memcpy(stats, adapter-stats64, sizeof(struct rtnl_link_stats64));
+
+   return stats;
+}
+
 static irqreturn_t fjes_intr(int irq, void *data)
 {
struct fjes_adapter *adapter = data;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.1 05/22] fjes: ES information acquisition routine

2015-07-22 Thread Taku Izumi
This patch adds ES information acquisition routine.
ES information can be retrieved issuing information
request command. ES information includes which
receiver is same zone.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 101 +++
 drivers/net/fjes/fjes_hw.h   |  24 ++
 drivers/net/fjes/fjes_regs.h |  23 ++
 3 files changed, 148 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index abe583e..3fbe68e 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -351,6 +351,107 @@ void fjes_hw_exit(struct fjes_hw *hw)
fjes_hw_cleanup(hw);
 }
 
+static enum fjes_dev_command_response_e
+fjes_hw_issue_request_command(struct fjes_hw *hw,
+ enum fjes_dev_command_request_type type)
+{
+   union REG_CR cr;
+   union REG_CS cs;
+   enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
+   int timeout;
+
+   cr.reg = 0;
+   cr.bits.req_start = 1;
+   cr.bits.req_code = type;
+   wr32(XSCT_CR, cr.reg);
+   cr.reg = rd32(XSCT_CR);
+
+   if (cr.bits.error == 0) {
+   timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
+   cs.reg = rd32(XSCT_CS);
+
+   while ((cs.bits.complete != 1)  timeout  0) {
+   msleep(1000);
+   cs.reg = rd32(XSCT_CS);
+   timeout -= 1000;
+   }
+
+   if (cs.bits.complete == 1)
+   ret = FJES_CMD_STATUS_NORMAL;
+   else if (timeout = 0)
+   ret = FJES_CMD_STATUS_TIMEOUT;
+
+   } else {
+   switch (cr.bits.err_info) {
+   case FJES_CMD_REQ_ERR_INFO_PARAM:
+   ret = FJES_CMD_STATUS_ERROR_PARAM;
+   break;
+   case FJES_CMD_REQ_ERR_INFO_STATUS:
+   ret = FJES_CMD_STATUS_ERROR_STATUS;
+   break;
+   default:
+   ret = FJES_CMD_STATUS_UNKNOWN;
+   break;
+   }
+   }
+
+   return ret;
+}
+
+int fjes_hw_request_info(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;
+
+   memset(req_buf, 0, hw-hw_info.req_buf_size);
+   memset(res_buf, 0, hw-hw_info.res_buf_size);
+
+   req_buf-info.length = FJES_DEV_COMMAND_INFO_REQ_LEN;
+
+   res_buf-info.length = 0;
+   res_buf-info.code = 0;
+
+   ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);
+
+   result = 0;
+
+   if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw-hw_info.max_epid)) !=
+   res_buf-info.length) {
+   result = -ENOMSG;
+   } else if (ret == FJES_CMD_STATUS_NORMAL) {
+   switch (res_buf-info.code) {
+   case FJES_CMD_REQ_RES_CODE_NORMAL:
+   result = 0;
+   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:
+   result = -EPERM;
+   break;
+   case FJES_CMD_STATUS_ERROR_STATUS:
+   result = -EPERM;
+   break;
+   default:
+   result = -EPERM;
+   break;
+   }
+   }
+
+   return result;
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 1b3e9ca..df30d3d 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -34,6 +34,12 @@ struct fjes_hw;
 #define EP_BUFFER_INFO_SIZE 4096
 
 #define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3) /* sec */
+#define FJES_COMMAND_REQ_TIMEOUT  (5 + 1) /* sec */
+
+#define FJES_CMD_REQ_ERR_INFO_PARAM  (0x0001)
+#define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002)
+
+#define FJES_CMD_REQ_RES_CODE_NORMAL (0)
 
 #define EP_BUFFER_SIZE \
(((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
@@ -50,6 +56,7 @@ struct fjes_hw;
((size) - sizeof(struct esmem_frame) - \
(ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))
 
+#define FJES_DEV_COMMAND_INFO_REQ_LEN  (4)
 #define FJES_DEV_COMMAND_INFO_RES_LEN(epnum) (8 + 2 * (epnum))
 #define FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(txb, rxb) \
(24 + (8 * ((txb) / EP_BUFFER_INFO_SIZE + (rxb

[PATCH v2.1 03/22] fjes: Hardware cleanup routine

2015-07-22 Thread Taku Izumi
This patch adds hardware cleanup routine to be
invoked at driver's .remove routine.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c | 66 ++
 drivers/net/fjes/fjes_hw.h |  1 +
 2 files changed, 67 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index e94538f..abe583e 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -56,6 +56,12 @@ static u8 *fjes_hw_iomap(struct fjes_hw *hw)
return base;
 }
 
+static void fjes_hw_iounmap(struct fjes_hw *hw)
+{
+   iounmap(hw-base);
+   release_mem_region(hw-hw_res.start, hw-hw_res.size);
+}
+
 int fjes_hw_reset(struct fjes_hw *hw)
 {
int timeout;
@@ -109,6 +115,12 @@ static int fjes_hw_alloc_shared_status_region(struct 
fjes_hw *hw)
return 0;
 }
 
+static void fjes_hw_free_shared_status_region(struct fjes_hw *hw)
+{
+   kfree(hw-hw_info.share);
+   hw-hw_info.share = NULL;
+}
+
 static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
 {
void *mem;
@@ -126,6 +138,18 @@ static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh)
return 0;
 }
 
+static void fjes_hw_free_epbuf(struct epbuf_handler *epbh)
+{
+   if (epbh-buffer)
+   vfree(epbh-buffer);
+
+   epbh-buffer = NULL;
+   epbh-size = 0;
+
+   epbh-info = NULL;
+   epbh-ring = NULL;
+}
+
 void fjes_hw_setup_epbuf(struct epbuf_handler *epbh, u8 *mac_addr, u32 mtu)
 {
union ep_buffer_info *info = epbh-info;
@@ -258,6 +282,32 @@ static int fjes_hw_setup(struct fjes_hw *hw)
return 0;
 }
 
+static void fjes_hw_cleanup(struct fjes_hw *hw)
+{
+   int epidx;
+
+   if (!hw-ep_shm_info)
+   return;
+
+   fjes_hw_free_shared_status_region(hw);
+
+   kfree(hw-hw_info.req_buf);
+   hw-hw_info.req_buf = NULL;
+
+   kfree(hw-hw_info.res_buf);
+   hw-hw_info.res_buf = NULL;
+
+   for (epidx = 0; epidx  hw-max_epid ; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+   fjes_hw_free_epbuf(hw-ep_shm_info[epidx].tx);
+   fjes_hw_free_epbuf(hw-ep_shm_info[epidx].rx);
+   }
+
+   kfree(hw-ep_shm_info);
+   hw-ep_shm_info = NULL;
+}
+
 int fjes_hw_init(struct fjes_hw *hw)
 {
int ret;
@@ -285,6 +335,22 @@ int fjes_hw_init(struct fjes_hw *hw)
return ret;
 }
 
+void fjes_hw_exit(struct fjes_hw *hw)
+{
+   int ret;
+
+   if (hw-base) {
+   ret = fjes_hw_reset(hw);
+   if (ret)
+   pr_err(%s: reset error, __func__);
+
+   fjes_hw_iounmap(hw);
+   hw-base = NULL;
+   }
+
+   fjes_hw_cleanup(hw);
+}
+
 void fjes_hw_set_irqmask(struct fjes_hw *hw,
 enum REG_ICTL_MASK intr_mask, bool mask)
 {
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 836ebe2..1b3e9ca 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -241,6 +241,7 @@ struct fjes_hw {
 };
 
 int fjes_hw_init(struct fjes_hw *);
+void fjes_hw_exit(struct fjes_hw *);
 int fjes_hw_reset(struct fjes_hw *);
 
 void fjes_hw_init_command_registers(struct fjes_hw *,
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.1 17/22] fjes: force_close_task

2015-07-22 Thread Taku Izumi
This patch adds force_close_task.
This task is used to close network device forcibly.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |  1 +
 drivers/net/fjes/fjes_main.c | 13 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index 1743dbb..d31d4c3 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -47,6 +47,7 @@ struct fjes_adapter {
unsigned long rx_last_jiffies;
bool unset_rx_last;
 
+   struct work_struct force_close_task;
bool force_reset;
bool open_guard;
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 2bf9f71..3a8cc5b 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -54,6 +54,7 @@ static void fjes_free_resources(struct fjes_adapter *);
 static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
 static void fjes_raise_intr_rxdata_task(struct work_struct *);
 static void fjes_tx_stall_task(struct work_struct *);
+static void fjes_force_close_task(struct work_struct *);
 static irqreturn_t fjes_intr(int, void*);
 static struct rtnl_link_stats64 *
 fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
@@ -494,6 +495,17 @@ static void fjes_tx_stall_task(struct work_struct *work)
queue_work(adapter-txrx_wq, adapter-tx_stall_task);
 }
 
+static void fjes_force_close_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter = container_of(work,
+   struct fjes_adapter, force_close_task);
+   struct net_device *netdev = adapter-netdev;
+
+   rtnl_lock();
+   dev_close(netdev);
+   rtnl_unlock();
+}
+
 static void fjes_raise_intr_rxdata_task(struct work_struct *work)
 {
struct fjes_adapter *adapter = container_of(work,
@@ -1006,6 +1018,7 @@ static int fjes_probe(struct platform_device *plat_dev)
if (err)
goto err_sw_init;
 
+   INIT_WORK(adapter-force_close_task, fjes_force_close_task);
adapter-force_reset = false;
adapter-open_guard = false;
 
-- 
1.8.3.1

--
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2.1 18/22] fjes: unshare_watch_task

2015-07-22 Thread Taku Izumi
This patch adds unshare_watch_task.
Shared buffer's status can be changed into unshared.
This task is used to monitor shared buffer's status.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes.h  |   3 ++
 drivers/net/fjes/fjes_main.c | 126 +++
 2 files changed, 129 insertions(+)

diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h
index d31d4c3..57feee8 100644
--- a/drivers/net/fjes/fjes.h
+++ b/drivers/net/fjes/fjes.h
@@ -59,6 +59,9 @@ struct fjes_adapter {
struct work_struct tx_stall_task;
struct work_struct raise_intr_rxdata_task;
 
+   struct work_struct unshare_watch_task;
+   unsigned long unshare_watch_bitmask;
+
struct delayed_work interrupt_watch_task;
bool interrupt_watch_enable;
 
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 3a8cc5b..e31a229 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -73,6 +73,7 @@ static int fjes_remove(struct platform_device *);
 static int fjes_sw_init(struct fjes_adapter *);
 static void fjes_netdev_setup(struct net_device *);
 static void fjes_irq_watch_task(struct work_struct *);
+static void fjes_watch_unshare_task(struct work_struct *);
 static void fjes_rx_irq(struct fjes_adapter *, int);
 static int fjes_poll(struct napi_struct *, int);
 
@@ -309,6 +310,8 @@ static int fjes_close(struct net_device *netdev)
fjes_free_irq(adapter);
 
cancel_delayed_work_sync(adapter-interrupt_watch_task);
+   cancel_work_sync(adapter-unshare_watch_task);
+   adapter-unshare_watch_bitmask = 0;
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
 
@@ -1028,6 +1031,8 @@ static int fjes_probe(struct platform_device *plat_dev)
INIT_WORK(adapter-tx_stall_task, fjes_tx_stall_task);
INIT_WORK(adapter-raise_intr_rxdata_task,
  fjes_raise_intr_rxdata_task);
+   INIT_WORK(adapter-unshare_watch_task, fjes_watch_unshare_task);
+   adapter-unshare_watch_bitmask = 0;
 
INIT_DELAYED_WORK(adapter-interrupt_watch_task, fjes_irq_watch_task);
adapter-interrupt_watch_enable = false;
@@ -1073,6 +1078,7 @@ static int fjes_remove(struct platform_device *plat_dev)
struct fjes_hw *hw = adapter-hw;
 
cancel_delayed_work_sync(adapter-interrupt_watch_task);
+   cancel_work_sync(adapter-unshare_watch_task);
cancel_work_sync(adapter-raise_intr_rxdata_task);
cancel_work_sync(adapter-tx_stall_task);
if (adapter-control_wq)
@@ -1132,6 +1138,126 @@ static void fjes_irq_watch_task(struct work_struct 
*work)
}
 }
 
+static void fjes_watch_unshare_task(struct work_struct *work)
+{
+   struct fjes_adapter *adapter =
+   container_of(work, struct fjes_adapter, unshare_watch_task);
+
+   struct fjes_hw *hw = adapter-hw;
+   struct net_device *netdev = adapter-netdev;
+   int epidx;
+   int max_epid, my_epid;
+   unsigned long unshare_watch_bitmask;
+   int wait_time = 0;
+   int is_shared;
+   int stop_req, stop_req_done;
+   int unshare_watch, unshare_reserve;
+   int ret;
+
+   my_epid = hw-my_epid;
+   max_epid = hw-max_epid;
+
+   unshare_watch_bitmask = adapter-unshare_watch_bitmask;
+   adapter-unshare_watch_bitmask = 0;
+
+   while ((unshare_watch_bitmask || hw-txrx_stop_req_bit) 
+  (wait_time  3000)) {
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid)
+   continue;
+
+   is_shared = fjes_hw_epid_is_shared(hw-hw_info.share,
+  epidx);
+
+   stop_req = test_bit(epidx, hw-txrx_stop_req_bit);
+
+   stop_req_done = 
hw-ep_shm_info[epidx].rx.info-v1i.rx_status 
+   FJES_RX_STOP_REQ_DONE;
+
+   unshare_watch = test_bit(epidx, unshare_watch_bitmask);
+
+   unshare_reserve = test_bit(epidx,
+  
hw-hw_info.buffer_unshare_reserve_bit);
+
+   if ((!stop_req ||
+(is_shared  (!is_shared || !stop_req_done))) 
+   (is_shared || !unshare_watch || !unshare_reserve))
+   continue;
+
+   mutex_lock(hw-hw_info.lock);
+   ret = fjes_hw_unregister_buff_addr(hw, epidx);
+   switch (ret) {
+   case 0:
+   break;
+   case -ENOMSG:
+   case -EBUSY:
+   default:
+   if (!work_pending(
+   adapter-force_close_task

[PATCH v2.1 19/22] fjes: update_zone_task

2015-07-22 Thread Taku Izumi
This patch adds update_zone_task.
Zoning information can be changed by user.
This task is used to monitor if zoning information is
changed or not.

Signed-off-by: Taku Izumi izumi.t...@jp.fujitsu.com
---
 drivers/net/fjes/fjes_hw.c   | 171 +++
 drivers/net/fjes/fjes_hw.h   |   1 +
 drivers/net/fjes/fjes_main.c |  14 
 3 files changed, 186 insertions(+)

diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 46e114c..4588ef3 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -22,6 +22,8 @@
 #include fjes_hw.h
 #include fjes.h
 
+static void fjes_hw_update_zone_task(struct work_struct *);
+
 /* supported MTU list */
 const u32 fjes_support_mtu[] = {
FJES_MTU_DEFINE(8 * 1024),
@@ -322,6 +324,8 @@ int fjes_hw_init(struct fjes_hw *hw)
 
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
 
+   INIT_WORK(hw-update_zone_task, fjes_hw_update_zone_task);
+
mutex_init(hw-hw_info.lock);
 
hw-max_epid = fjes_hw_get_max_epid(hw);
@@ -349,6 +353,8 @@ void fjes_hw_exit(struct fjes_hw *hw)
}
 
fjes_hw_cleanup(hw);
+
+   cancel_work_sync(hw-update_zone_task);
 }
 
 static enum fjes_dev_command_response_e
@@ -914,3 +920,168 @@ int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
return 0;
 }
 
+static void fjes_hw_update_zone_task(struct work_struct *work)
+{
+   struct fjes_hw *hw = container_of(work,
+   struct fjes_hw, update_zone_task);
+   struct fjes_adapter *adapter = (struct fjes_adapter *)hw-back;
+   struct net_device *netdev = adapter-netdev;
+   int ret;
+   int epidx;
+   enum ep_partner_status pstatus;
+   unsigned long share_bit = 0;
+   unsigned long unshare_bit = 0;
+   unsigned long irq_bit = 0;
+   union fjes_device_command_res *res_buf = hw-hw_info.res_buf;
+   struct my_s {u8 es_status; u8 zone; } *info =
+   (struct my_s *)res_buf-info.info;
+
+   mutex_lock(hw-hw_info.lock);
+
+   ret = fjes_hw_request_info(hw);
+   switch (ret) {
+   case -ENOMSG:
+   case -EBUSY:
+   default:
+   if (!work_pending(adapter-force_close_task)) {
+   adapter-force_reset = true;
+   schedule_work(adapter-force_close_task);
+   }
+   break;
+
+   case 0:
+
+   for (epidx = 0; epidx  hw-max_epid; epidx++) {
+   if (epidx == hw-my_epid) {
+   hw-ep_shm_info[epidx].es_status =
+   info[epidx].es_status;
+   hw-ep_shm_info[epidx].zone =
+   info[epidx].zone;
+   continue;
+   }
+
+   pstatus = fjes_hw_get_partner_ep_status(hw, epidx);
+   switch (pstatus) {
+   case EP_PARTNER_UNSHARE:
+   default:
+   if ((info[epidx].zone !=
+   FJES_ZONING_ZONE_TYPE_NONE) 
+   (info[epidx].es_status ==
+   FJES_ZONING_STATUS_ENABLE) 
+   (info[epidx].zone ==
+   info[hw-my_epid].zone))
+   set_bit(epidx, share_bit);
+   else
+   set_bit(epidx, unshare_bit);
+   break;
+
+   case EP_PARTNER_COMPLETE:
+   case EP_PARTNER_WAITING:
+   if ((info[epidx].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE) ||
+   (info[epidx].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (info[epidx].zone !=
+   info[hw-my_epid].zone)) {
+   set_bit(epidx,
+   
adapter-unshare_watch_bitmask);
+   set_bit(epidx,
+   
hw-hw_info.buffer_unshare_reserve_bit);
+   }
+   break;
+
+   case EP_PARTNER_SHARED:
+   if ((info[epidx].zone ==
+   FJES_ZONING_ZONE_TYPE_NONE) ||
+   (info[epidx].es_status !=
+   FJES_ZONING_STATUS_ENABLE) ||
+   (info[epidx].zone !=
+   info[hw-my_epid].zone))
+   set_bit(epidx, irq_bit

  1   2   >