Commit 21b7efbc authored by Taku Izumi's avatar Taku Izumi Committed by David S. Miller

fjes: Enhance ethtool -S for fjes driver

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: default avatarTaku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 462d8074
...@@ -49,10 +49,18 @@ static const struct fjes_stats fjes_gstrings_stats[] = { ...@@ -49,10 +49,18 @@ static const struct fjes_stats fjes_gstrings_stats[] = {
FJES_STAT("tx_dropped", stats64.tx_dropped), 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, static void fjes_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data) struct ethtool_stats *stats, u64 *data)
{ {
struct fjes_adapter *adapter = netdev_priv(netdev); struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = &adapter->hw;
int epidx;
char *p; char *p;
int i; int i;
...@@ -61,11 +69,39 @@ static void fjes_get_ethtool_stats(struct net_device *netdev, ...@@ -61,11 +69,39 @@ static void fjes_get_ethtool_stats(struct net_device *netdev,
data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64)) data[i] = (fjes_gstrings_stats[i].sizeof_stat == sizeof(u64))
? *(u64 *)p : *(u32 *)p; ? *(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, static void fjes_get_strings(struct net_device *netdev,
u32 stringset, u8 *data) u32 stringset, u8 *data)
{ {
struct fjes_adapter *adapter = netdev_priv(netdev);
struct fjes_hw *hw = &adapter->hw;
u8 *p = data; u8 *p = data;
int i; int i;
...@@ -76,6 +112,38 @@ static void fjes_get_strings(struct net_device *netdev, ...@@ -76,6 +112,38 @@ static void fjes_get_strings(struct net_device *netdev,
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
p += 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", i);
p += ETH_GSTRING_LEN;
sprintf(p, "ep%u_recv_intr_stop", i);
p += ETH_GSTRING_LEN;
sprintf(p, "ep%u_recv_intr_zoneupdate", i);
p += ETH_GSTRING_LEN;
sprintf(p, "ep%u_tx_buffer_full", i);
p += ETH_GSTRING_LEN;
sprintf(p, "ep%u_tx_dropped_not_shared", i);
p += ETH_GSTRING_LEN;
sprintf(p, "ep%u_tx_dropped_ver_mismatch", i);
p += ETH_GSTRING_LEN;
sprintf(p, "ep%u_tx_dropped_buf_size_mismatch", i);
p += ETH_GSTRING_LEN;
sprintf(p, "ep%u_tx_dropped_vlanid_mismatch", i);
p += ETH_GSTRING_LEN;
}
break; break;
} }
} }
...@@ -84,7 +152,7 @@ static int fjes_get_sset_count(struct net_device *netdev, int sset) ...@@ -84,7 +152,7 @@ static int fjes_get_sset_count(struct net_device *netdev, int sset)
{ {
switch (sset) { switch (sset) {
case ETH_SS_STATS: case ETH_SS_STATS:
return ARRAY_SIZE(fjes_gstrings_stats); return FJES_STATS_LEN;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -752,6 +752,7 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw) ...@@ -752,6 +752,7 @@ void fjes_hw_raise_epstop(struct fjes_hw *hw)
case EP_PARTNER_SHARED: case EP_PARTNER_SHARED:
fjes_hw_raise_interrupt(hw, epidx, fjes_hw_raise_interrupt(hw, epidx,
REG_ICTL_MASK_TXRX_STOP_REQ); REG_ICTL_MASK_TXRX_STOP_REQ);
hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
break; break;
default: default:
break; break;
...@@ -1062,6 +1063,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work) ...@@ -1062,6 +1063,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
break; break;
} }
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
hw->ep_shm_info[epidx].ep_stats
.com_regist_buf_exec += 1;
} }
if (test_bit(epidx, &unshare_bit)) { if (test_bit(epidx, &unshare_bit)) {
...@@ -1085,6 +1089,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work) ...@@ -1085,6 +1089,9 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
hw->ep_shm_info[epidx].ep_stats
.com_unregist_buf_exec += 1;
if (ret == 0) { if (ret == 0) {
spin_lock_irqsave(&hw->rx_status_lock, flags); spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf( fjes_hw_setup_epbuf(
...@@ -1099,6 +1106,8 @@ static void fjes_hw_update_zone_task(struct work_struct *work) ...@@ -1099,6 +1106,8 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
fjes_hw_raise_interrupt(hw, epidx, fjes_hw_raise_interrupt(hw, epidx,
REG_ICTL_MASK_TXRX_STOP_REQ); REG_ICTL_MASK_TXRX_STOP_REQ);
hw->ep_shm_info[epidx].ep_stats.send_intr_unshare += 1;
set_bit(epidx, &hw->txrx_stop_req_bit); set_bit(epidx, &hw->txrx_stop_req_bit);
spin_lock_irqsave(&hw->rx_status_lock, flags); spin_lock_irqsave(&hw->rx_status_lock, flags);
hw->ep_shm_info[epidx].tx. hw->ep_shm_info[epidx].tx.
......
...@@ -228,6 +228,24 @@ union ep_buffer_info { ...@@ -228,6 +228,24 @@ union ep_buffer_info {
}; };
/* statistics of EP */
struct fjes_drv_ep_stats {
u64 com_regist_buf_exec;
u64 com_unregist_buf_exec;
u64 send_intr_rx;
u64 send_intr_unshare;
u64 send_intr_zoneupdate;
u64 recv_intr_rx;
u64 recv_intr_unshare;
u64 recv_intr_stop;
u64 recv_intr_zoneupdate;
u64 tx_buffer_full;
u64 tx_dropped_not_shared;
u64 tx_dropped_ver_mismatch;
u64 tx_dropped_buf_size_mismatch;
u64 tx_dropped_vlanid_mismatch;
};
/* buffer pair for Extended Partition */ /* buffer pair for Extended Partition */
struct ep_share_mem_info { struct ep_share_mem_info {
struct epbuf_handler { struct epbuf_handler {
...@@ -238,6 +256,7 @@ struct ep_share_mem_info { ...@@ -238,6 +256,7 @@ struct ep_share_mem_info {
} tx, rx; } tx, rx;
struct rtnl_link_stats64 net_stats; struct rtnl_link_stats64 net_stats;
struct fjes_drv_ep_stats ep_stats;
u16 tx_status_work; u16 tx_status_work;
......
...@@ -366,6 +366,8 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) ...@@ -366,6 +366,8 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
FJES_ZONING_STATUS_ENABLE)) { FJES_ZONING_STATUS_ENABLE)) {
fjes_hw_raise_interrupt(hw, epidx, fjes_hw_raise_interrupt(hw, epidx,
REG_ICTL_MASK_INFO_UPDATE); REG_ICTL_MASK_INFO_UPDATE);
hw->ep_shm_info[epidx].ep_stats
.send_intr_zoneupdate += 1;
} }
} }
...@@ -397,6 +399,9 @@ static int fjes_setup_resources(struct fjes_adapter *adapter) ...@@ -397,6 +399,9 @@ static int fjes_setup_resources(struct fjes_adapter *adapter)
adapter->force_reset = true; adapter->force_reset = true;
return result; return result;
} }
hw->ep_shm_info[epidx].ep_stats
.com_regist_buf_exec += 1;
} }
} }
...@@ -422,6 +427,8 @@ static void fjes_free_resources(struct fjes_adapter *adapter) ...@@ -422,6 +427,8 @@ static void fjes_free_resources(struct fjes_adapter *adapter)
result = fjes_hw_unregister_buff_addr(hw, epidx); result = fjes_hw_unregister_buff_addr(hw, epidx);
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
hw->ep_shm_info[epidx].ep_stats.com_unregist_buf_exec += 1;
if (result) if (result)
reset_flag = true; reset_flag = true;
...@@ -567,6 +574,7 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work) ...@@ -567,6 +574,7 @@ static void fjes_raise_intr_rxdata_task(struct work_struct *work)
FJES_RX_POLL_WORK)) { FJES_RX_POLL_WORK)) {
fjes_hw_raise_interrupt(hw, epid, fjes_hw_raise_interrupt(hw, epid,
REG_ICTL_MASK_RX_DATA); REG_ICTL_MASK_RX_DATA);
hw->ep_shm_info[epid].ep_stats.send_intr_rx += 1;
} }
} }
...@@ -663,6 +671,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -663,6 +671,9 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid); pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
if (pstatus != EP_PARTNER_SHARED) { if (pstatus != EP_PARTNER_SHARED) {
if (!is_multi)
hw->ep_shm_info[dest_epid].ep_stats
.tx_dropped_not_shared += 1;
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
} else if (!fjes_hw_check_epbuf_version( } else if (!fjes_hw_check_epbuf_version(
&adapter->hw.ep_shm_info[dest_epid].rx, 0)) { &adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
...@@ -670,6 +681,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -670,6 +681,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
adapter->stats64.tx_carrier_errors += 1; adapter->stats64.tx_carrier_errors += 1;
hw->ep_shm_info[dest_epid].net_stats hw->ep_shm_info[dest_epid].net_stats
.tx_carrier_errors += 1; .tx_carrier_errors += 1;
hw->ep_shm_info[dest_epid].ep_stats
.tx_dropped_ver_mismatch += 1;
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
} else if (!fjes_hw_check_mtu( } else if (!fjes_hw_check_mtu(
...@@ -679,12 +692,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -679,12 +692,16 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1; hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1;
adapter->stats64.tx_errors += 1; adapter->stats64.tx_errors += 1;
hw->ep_shm_info[dest_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_buf_size_mismatch += 1;
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
} else if (vlan && } else if (vlan &&
!fjes_hw_check_vlan_id( !fjes_hw_check_vlan_id(
&adapter->hw.ep_shm_info[dest_epid].rx, &adapter->hw.ep_shm_info[dest_epid].rx,
vlan_id)) { vlan_id)) {
hw->ep_shm_info[dest_epid].ep_stats
.tx_dropped_vlanid_mismatch += 1;
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
} else { } else {
if (len < VLAN_ETH_HLEN) { if (len < VLAN_ETH_HLEN) {
...@@ -718,6 +735,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -718,6 +735,8 @@ fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
} else { } else {
netif_trans_update(netdev); netif_trans_update(netdev);
hw->ep_shm_info[dest_epid].ep_stats
.tx_buffer_full += 1;
netif_tx_stop_queue(cur_queue); netif_tx_stop_queue(cur_queue);
if (!work_pending(&adapter->tx_stall_task)) if (!work_pending(&adapter->tx_stall_task))
...@@ -970,21 +989,33 @@ static irqreturn_t fjes_intr(int irq, void *data) ...@@ -970,21 +989,33 @@ static irqreturn_t fjes_intr(int irq, void *data)
icr = fjes_hw_capture_interrupt_status(hw); 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) if (icr & REG_ICTL_MASK_RX_DATA) {
fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID); fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
.recv_intr_rx += 1;
}
if (icr & REG_ICTL_MASK_DEV_STOP_REQ) if (icr & REG_ICTL_MASK_DEV_STOP_REQ) {
fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID); fjes_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
.recv_intr_stop += 1;
}
if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) if (icr & REG_ICTL_MASK_TXRX_STOP_REQ) {
fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID); fjes_txrx_stop_req_irq(adapter, icr & REG_IS_MASK_EPID);
hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
.recv_intr_unshare += 1;
}
if (icr & REG_ICTL_MASK_TXRX_STOP_DONE) if (icr & REG_ICTL_MASK_TXRX_STOP_DONE)
fjes_hw_set_irqmask(hw, fjes_hw_set_irqmask(hw,
REG_ICTL_MASK_TXRX_STOP_DONE, true); REG_ICTL_MASK_TXRX_STOP_DONE, true);
if (icr & REG_ICTL_MASK_INFO_UPDATE) if (icr & REG_ICTL_MASK_INFO_UPDATE) {
fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID); fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID);
hw->ep_shm_info[icr & REG_IS_MASK_EPID].ep_stats
.recv_intr_zoneupdate += 1;
}
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} else { } else {
...@@ -1364,6 +1395,8 @@ static void fjes_watch_unshare_task(struct work_struct *work) ...@@ -1364,6 +1395,8 @@ static void fjes_watch_unshare_task(struct work_struct *work)
break; break;
} }
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
hw->ep_shm_info[epidx].ep_stats
.com_unregist_buf_exec += 1;
spin_lock_irqsave(&hw->rx_status_lock, flags); spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx,
...@@ -1406,6 +1439,9 @@ static void fjes_watch_unshare_task(struct work_struct *work) ...@@ -1406,6 +1439,9 @@ static void fjes_watch_unshare_task(struct work_struct *work)
} }
mutex_unlock(&hw->hw_info.lock); mutex_unlock(&hw->hw_info.lock);
hw->ep_shm_info[epidx].ep_stats
.com_unregist_buf_exec += 1;
spin_lock_irqsave(&hw->rx_status_lock, flags); spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf( fjes_hw_setup_epbuf(
&hw->ep_shm_info[epidx].tx, &hw->ep_shm_info[epidx].tx,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment