liquidio: New statistics support
This patch adds extensive support of statistics for data path, control path and firmware. Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com> Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com> Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com> Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com> Signed-off-by: Raghu Vatsavayi <rvatsavayi@caviumnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
78e6a9b4a4
commit
1f164717cb
@ -40,6 +40,8 @@
|
||||
#include "cn68xx_device.h"
|
||||
#include "liquidio_image.h"
|
||||
|
||||
static int octnet_get_link_stats(struct net_device *netdev);
|
||||
|
||||
struct oct_mdio_cmd_context {
|
||||
int octeon_id;
|
||||
wait_queue_head_t wc;
|
||||
@ -77,28 +79,109 @@ enum {
|
||||
#define OCT_ETHTOOL_REGDUMP_LEN 4096
|
||||
#define OCT_ETHTOOL_REGSVER 1
|
||||
|
||||
static const char oct_iq_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
"Instr posted",
|
||||
"Instr processed",
|
||||
"Instr dropped",
|
||||
"Bytes Sent",
|
||||
"Sgentry_sent",
|
||||
"Inst cntreg",
|
||||
"Tx done",
|
||||
"Tx Iq busy",
|
||||
"Tx dropped",
|
||||
"Tx bytes",
|
||||
/* statistics of PF */
|
||||
static const char oct_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
"rx_packets",
|
||||
"tx_packets",
|
||||
"rx_bytes",
|
||||
"tx_bytes",
|
||||
"rx_errors", /*jabber_err+l2_err+frame_err */
|
||||
"tx_errors", /*fw_err_pko+fw_err_link+fw_err_drop */
|
||||
"rx_dropped", /*st->fromwire.total_rcvd - st->fromwire.fw_total_rcvd
|
||||
*+st->fromwire.dmac_drop + st->fromwire.fw_err_drop
|
||||
*/
|
||||
"tx_dropped",
|
||||
|
||||
"tx_total_sent",
|
||||
"tx_total_fwd",
|
||||
"tx_err_pko",
|
||||
"tx_err_link",
|
||||
"tx_err_drop",
|
||||
|
||||
"tx_tso",
|
||||
"tx_tso_packets",
|
||||
"tx_tso_err",
|
||||
|
||||
"mac_tx_total_pkts",
|
||||
"mac_tx_total_bytes",
|
||||
"mac_tx_mcast_pkts",
|
||||
"mac_tx_bcast_pkts",
|
||||
"mac_tx_ctl_packets", /*oct->link_stats.fromhost.ctl_sent */
|
||||
"mac_tx_total_collisions",
|
||||
"mac_tx_one_collision",
|
||||
"mac_tx_multi_collison",
|
||||
"mac_tx_max_collision_fail",
|
||||
"mac_tx_max_deferal_fail",
|
||||
"mac_tx_fifo_err",
|
||||
"mac_tx_runts",
|
||||
|
||||
"rx_total_rcvd",
|
||||
"rx_total_fwd",
|
||||
"rx_jabber_err",
|
||||
"rx_l2_err",
|
||||
"rx_frame_err",
|
||||
"rx_err_pko",
|
||||
"rx_err_link",
|
||||
"rx_err_drop",
|
||||
|
||||
"rx_lro_pkts",
|
||||
"rx_lro_bytes",
|
||||
"rx_total_lro",
|
||||
|
||||
"rx_lro_aborts",
|
||||
"rx_lro_aborts_port",
|
||||
"rx_lro_aborts_seq",
|
||||
"rx_lro_aborts_tsval",
|
||||
"rx_lro_aborts_timer",
|
||||
"rx_fwd_rate",
|
||||
|
||||
"mac_rx_total_rcvd",
|
||||
"mac_rx_bytes",
|
||||
"mac_rx_total_bcst",
|
||||
"mac_rx_total_mcst",
|
||||
"mac_rx_runts",
|
||||
"mac_rx_ctl_packets",
|
||||
"mac_rx_fifo_err",
|
||||
"mac_rx_dma_drop",
|
||||
"mac_rx_fcs_err",
|
||||
|
||||
"link_state_changes",
|
||||
};
|
||||
|
||||
/* statistics of host tx queue */
|
||||
static const char oct_iq_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
"packets", /*oct->instr_queue[iq_no]->stats.tx_done*/
|
||||
"bytes", /*oct->instr_queue[iq_no]->stats.tx_tot_bytes*/
|
||||
"dropped",
|
||||
"iq_busy",
|
||||
"sgentry_sent",
|
||||
|
||||
"fw_instr_posted",
|
||||
"fw_instr_processed",
|
||||
"fw_instr_dropped",
|
||||
"fw_bytes_sent",
|
||||
|
||||
"tso",
|
||||
"txq_restart",
|
||||
};
|
||||
|
||||
/* statistics of host rx queue */
|
||||
static const char oct_droq_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
"OQ Pkts Received",
|
||||
"OQ Bytes Received",
|
||||
"Dropped no dispatch",
|
||||
"Dropped nomem",
|
||||
"Dropped toomany",
|
||||
"Stack RX cnt",
|
||||
"Stack RX Bytes",
|
||||
"RX dropped",
|
||||
"packets", /*oct->droq[oq_no]->stats.rx_pkts_received */
|
||||
"bytes", /*oct->droq[oq_no]->stats.rx_bytes_received */
|
||||
"dropped", /*oct->droq[oq_no]->stats.rx_dropped+
|
||||
*oct->droq[oq_no]->stats.dropped_nodispatch+
|
||||
*oct->droq[oq_no]->stats.dropped_toomany+
|
||||
*oct->droq[oq_no]->stats.dropped_nomem
|
||||
*/
|
||||
"dropped_nomem",
|
||||
"dropped_toomany",
|
||||
"fw_dropped",
|
||||
"fw_pkts_received",
|
||||
"fw_bytes_received",
|
||||
"fw_dropped_nodispatch",
|
||||
|
||||
"buffer_alloc_failure",
|
||||
};
|
||||
|
||||
#define OCTNIC_NCMD_AUTONEG_ON 0x1
|
||||
@ -516,8 +599,13 @@ lio_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
|
||||
/* Notes: Not supporting any auto negotiation in these
|
||||
* drivers. Just report pause frame support.
|
||||
*/
|
||||
pause->tx_pause = 1;
|
||||
pause->rx_pause = 1; /* TODO: Need to support RX pause frame!!. */
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
|
||||
pause->autoneg = 0;
|
||||
|
||||
pause->tx_pause = oct->tx_pause;
|
||||
pause->rx_pause = oct->rx_pause;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -526,51 +614,245 @@ lio_get_ethtool_stats(struct net_device *netdev,
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct_dev = lio->oct_dev;
|
||||
struct net_device_stats *netstats = &netdev->stats;
|
||||
int i = 0, j;
|
||||
|
||||
for (j = 0; j < MAX_OCTEON_INSTR_QUEUES(oct); j++) {
|
||||
netdev->netdev_ops->ndo_get_stats(netdev);
|
||||
octnet_get_link_stats(netdev);
|
||||
|
||||
/*sum of oct->droq[oq_no]->stats->rx_pkts_received */
|
||||
data[i++] = CVM_CAST64(netstats->rx_packets);
|
||||
/*sum of oct->instr_queue[iq_no]->stats.tx_done */
|
||||
data[i++] = CVM_CAST64(netstats->tx_packets);
|
||||
/*sum of oct->droq[oq_no]->stats->rx_bytes_received */
|
||||
data[i++] = CVM_CAST64(netstats->rx_bytes);
|
||||
/*sum of oct->instr_queue[iq_no]->stats.tx_tot_bytes */
|
||||
data[i++] = CVM_CAST64(netstats->tx_bytes);
|
||||
data[i++] = CVM_CAST64(netstats->rx_errors);
|
||||
data[i++] = CVM_CAST64(netstats->tx_errors);
|
||||
/*sum of oct->droq[oq_no]->stats->rx_dropped +
|
||||
*oct->droq[oq_no]->stats->dropped_nodispatch +
|
||||
*oct->droq[oq_no]->stats->dropped_toomany +
|
||||
*oct->droq[oq_no]->stats->dropped_nomem
|
||||
*/
|
||||
data[i++] = CVM_CAST64(netstats->rx_dropped);
|
||||
/*sum of oct->instr_queue[iq_no]->stats.tx_dropped */
|
||||
data[i++] = CVM_CAST64(netstats->tx_dropped);
|
||||
|
||||
/*data[i++] = CVM_CAST64(stats->multicast); */
|
||||
/*data[i++] = CVM_CAST64(stats->collisions); */
|
||||
|
||||
/* firmware tx stats */
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[mdata->from_ifidx].
|
||||
*fromhost.fw_total_sent
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_total_sent);
|
||||
/*per_core_stats[i].link_stats[port].fromwire.fw_total_fwd */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_total_fwd);
|
||||
/*per_core_stats[j].link_stats[i].fromhost.fw_err_pko */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_pko);
|
||||
/*per_core_stats[j].link_stats[i].fromhost.fw_err_link */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_link);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.
|
||||
*fw_err_drop
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_drop);
|
||||
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.fw_tso */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_tso);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.
|
||||
*fw_tso_fwd
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_tso_fwd);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[idx].fromhost.
|
||||
*fw_err_tso
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fw_err_tso);
|
||||
|
||||
/* mac tx statistics */
|
||||
/*CVMX_BGXX_CMRX_TX_STAT5 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.total_pkts_sent);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT4 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.total_bytes_sent);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT15 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.mcast_pkts_sent);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT14 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.bcast_pkts_sent);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT17 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.ctl_sent);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT0 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.total_collisions);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT3 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.one_collision_sent);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT2 */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->link_stats.fromhost.multi_collision_sent);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT0 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.max_collision_fail);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT1 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.max_deferral_fail);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT16 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.fifo_err);
|
||||
/*CVMX_BGXX_CMRX_TX_STAT6 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromhost.runts);
|
||||
|
||||
/* RX firmware stats */
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_total_rcvd
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_total_rcvd);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_total_fwd
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_total_fwd);
|
||||
/*per_core_stats[core_id].link_stats[ifidx].fromwire.jabber_err */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.jabber_err);
|
||||
/*per_core_stats[core_id].link_stats[ifidx].fromwire.l2_err */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.l2_err);
|
||||
/*per_core_stats[core_id].link_stats[ifidx].fromwire.frame_err */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.frame_err);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_err_pko
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_err_pko);
|
||||
/*per_core_stats[j].link_stats[i].fromwire.fw_err_link */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_err_link);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[lro_ctx->ifidx].
|
||||
*fromwire.fw_err_drop
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_err_drop);
|
||||
|
||||
/* LRO */
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_lro_pkts
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_pkts);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_lro_octs
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_octs);
|
||||
/*per_core_stats[j].link_stats[i].fromwire.fw_total_lro */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_total_lro);
|
||||
/*per_core_stats[j].link_stats[i].fromwire.fw_lro_aborts */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_lro_aborts_port
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_port);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_lro_aborts_seq
|
||||
*/
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_seq);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_lro_aborts_tsval
|
||||
*/
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_tsval);
|
||||
/*per_core_stats[cvmx_get_core_num()].link_stats[ifidx].fromwire.
|
||||
*fw_lro_aborts_timer
|
||||
*/
|
||||
/* intrmod: packet forward rate */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->link_stats.fromwire.fw_lro_aborts_timer);
|
||||
/*per_core_stats[j].link_stats[i].fromwire.fw_lro_aborts */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fwd_rate);
|
||||
|
||||
/* mac: link-level stats */
|
||||
/*CVMX_BGXX_CMRX_RX_STAT0 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.total_rcvd);
|
||||
/*CVMX_BGXX_CMRX_RX_STAT1 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.bytes_rcvd);
|
||||
/*CVMX_PKI_STATX_STAT5 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.total_bcst);
|
||||
/*CVMX_PKI_STATX_STAT5 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.total_mcst);
|
||||
/*wqe->word2.err_code or wqe->word2.err_level */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.runts);
|
||||
/*CVMX_BGXX_CMRX_RX_STAT2 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.ctl_rcvd);
|
||||
/*CVMX_BGXX_CMRX_RX_STAT6 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fifo_err);
|
||||
/*CVMX_BGXX_CMRX_RX_STAT4 */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.dmac_drop);
|
||||
/*wqe->word2.err_code or wqe->word2.err_level */
|
||||
data[i++] = CVM_CAST64(oct_dev->link_stats.fromwire.fcs_err);
|
||||
/*lio->link_changes*/
|
||||
data[i++] = CVM_CAST64(lio->link_changes);
|
||||
|
||||
/* TX -- lio_update_stats(lio); */
|
||||
for (j = 0; j < MAX_OCTEON_INSTR_QUEUES(oct_dev); j++) {
|
||||
if (!(oct_dev->io_qmask.iq & (1ULL << j)))
|
||||
continue;
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_posted);
|
||||
data[i++] =
|
||||
CVM_CAST64(
|
||||
oct_dev->instr_queue[j]->stats.instr_processed);
|
||||
data[i++] =
|
||||
CVM_CAST64(
|
||||
oct_dev->instr_queue[j]->stats.instr_dropped);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.bytes_sent);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.sgentry_sent);
|
||||
data[i++] =
|
||||
readl(oct_dev->instr_queue[j]->inst_cnt_reg);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_done);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_iq_busy);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_dropped);
|
||||
/*packets to network port*/
|
||||
/*# of packets tx to network */
|
||||
data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_done);
|
||||
/*# of bytes tx to network */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_tot_bytes);
|
||||
/*# of packets dropped */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_dropped);
|
||||
/*# of tx fails due to queue full */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_iq_busy);
|
||||
/*XXX gather entries sent */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.sgentry_sent);
|
||||
|
||||
/*instruction to firmware: data and control */
|
||||
/*# of instructions to the queue */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_posted);
|
||||
/*# of instructions processed */
|
||||
data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->
|
||||
stats.instr_processed);
|
||||
/*# of instructions could not be processed */
|
||||
data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->
|
||||
stats.instr_dropped);
|
||||
/*bytes sent through the queue */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.bytes_sent);
|
||||
|
||||
/*tso request*/
|
||||
data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_gso);
|
||||
/*txq restart*/
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_restart);
|
||||
}
|
||||
|
||||
/* for (j = 0; j < oct_dev->num_oqs; j++){ */
|
||||
for (j = 0; j < MAX_OCTEON_OUTPUT_QUEUES(oct); j++) {
|
||||
/* RX */
|
||||
/* for (j = 0; j < oct_dev->num_oqs; j++) { */
|
||||
for (j = 0; j < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); j++) {
|
||||
if (!(oct_dev->io_qmask.oq & (1ULL << j)))
|
||||
continue;
|
||||
data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.pkts_received);
|
||||
data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.bytes_received);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.dropped_nodispatch);
|
||||
data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem);
|
||||
data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_toomany);
|
||||
|
||||
/*packets send to TCP/IP network stack */
|
||||
/*# of packets to network stack */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.rx_pkts_received);
|
||||
/*# of bytes to network stack */
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.rx_bytes_received);
|
||||
/*# of packets dropped */
|
||||
data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem +
|
||||
oct_dev->droq[j]->stats.dropped_toomany +
|
||||
oct_dev->droq[j]->stats.rx_dropped);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.dropped_toomany);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.rx_dropped);
|
||||
|
||||
/*control and data path*/
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.pkts_received);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.bytes_received);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.dropped_nodispatch);
|
||||
data[i++] =
|
||||
CVM_CAST64(oct_dev->droq[j]->stats.rx_alloc_failure);
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,26 +861,43 @@ static void lio_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct_dev = lio->oct_dev;
|
||||
int num_iq_stats, num_oq_stats, i, j;
|
||||
int num_stats;
|
||||
|
||||
num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
|
||||
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
|
||||
if (!(oct_dev->io_qmask.iq & (1ULL << i)))
|
||||
continue;
|
||||
for (j = 0; j < num_iq_stats; j++) {
|
||||
sprintf(data, "IQ%d %s", i, oct_iq_stats_strings[j]);
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
num_stats = ARRAY_SIZE(oct_stats_strings);
|
||||
for (j = 0; j < num_stats; j++) {
|
||||
sprintf(data, "%s", oct_stats_strings[j]);
|
||||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
|
||||
/* for (i = 0; i < oct_dev->num_oqs; i++) { */
|
||||
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
|
||||
if (!(oct_dev->io_qmask.oq & (1ULL << i)))
|
||||
continue;
|
||||
for (j = 0; j < num_oq_stats; j++) {
|
||||
sprintf(data, "OQ%d %s", i, oct_droq_stats_strings[j]);
|
||||
data += ETH_GSTRING_LEN;
|
||||
num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
|
||||
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct_dev); i++) {
|
||||
if (!(oct_dev->io_qmask.iq & (1ULL << i)))
|
||||
continue;
|
||||
for (j = 0; j < num_iq_stats; j++) {
|
||||
sprintf(data, "tx-%d-%s", i,
|
||||
oct_iq_stats_strings[j]);
|
||||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
|
||||
/* for (i = 0; i < oct_dev->num_oqs; i++) { */
|
||||
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); i++) {
|
||||
if (!(oct_dev->io_qmask.oq & (1ULL << i)))
|
||||
continue;
|
||||
for (j = 0; j < num_oq_stats; j++) {
|
||||
sprintf(data, "rx-%d-%s", i,
|
||||
oct_droq_stats_strings[j]);
|
||||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
netif_info(lio, drv, lio->netdev, "Unknown Stringset !!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -607,8 +906,14 @@ static int lio_get_sset_count(struct net_device *netdev, int sset)
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct_dev = lio->oct_dev;
|
||||
|
||||
return (ARRAY_SIZE(oct_iq_stats_strings) * oct_dev->num_iqs) +
|
||||
(ARRAY_SIZE(oct_droq_stats_strings) * oct_dev->num_oqs);
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
return (ARRAY_SIZE(oct_stats_strings) +
|
||||
ARRAY_SIZE(oct_iq_stats_strings) * oct_dev->num_iqs +
|
||||
ARRAY_SIZE(oct_droq_stats_strings) * oct_dev->num_oqs);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int lio_get_intr_coalesce(struct net_device *netdev,
|
||||
@ -731,6 +1036,155 @@ static int octnet_set_intrmod_cfg(struct lio *lio,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
octnet_nic_stats_callback(struct octeon_device *oct_dev,
|
||||
u32 status, void *ptr)
|
||||
{
|
||||
struct octeon_soft_command *sc = (struct octeon_soft_command *)ptr;
|
||||
struct oct_nic_stats_resp *resp = (struct oct_nic_stats_resp *)
|
||||
sc->virtrptr;
|
||||
struct oct_nic_stats_ctrl *ctrl = (struct oct_nic_stats_ctrl *)
|
||||
sc->ctxptr;
|
||||
struct nic_rx_stats *rsp_rstats = &resp->stats.fromwire;
|
||||
struct nic_tx_stats *rsp_tstats = &resp->stats.fromhost;
|
||||
|
||||
struct nic_rx_stats *rstats = &oct_dev->link_stats.fromwire;
|
||||
struct nic_tx_stats *tstats = &oct_dev->link_stats.fromhost;
|
||||
|
||||
if ((status != OCTEON_REQUEST_TIMEOUT) && !resp->status) {
|
||||
octeon_swap_8B_data((u64 *)&resp->stats,
|
||||
(sizeof(struct oct_link_stats)) >> 3);
|
||||
|
||||
/* RX link-level stats */
|
||||
rstats->total_rcvd = rsp_rstats->total_rcvd;
|
||||
rstats->bytes_rcvd = rsp_rstats->bytes_rcvd;
|
||||
rstats->total_bcst = rsp_rstats->total_bcst;
|
||||
rstats->total_mcst = rsp_rstats->total_mcst;
|
||||
rstats->runts = rsp_rstats->runts;
|
||||
rstats->ctl_rcvd = rsp_rstats->ctl_rcvd;
|
||||
/* Accounts for over/under-run of buffers */
|
||||
rstats->fifo_err = rsp_rstats->fifo_err;
|
||||
rstats->dmac_drop = rsp_rstats->dmac_drop;
|
||||
rstats->fcs_err = rsp_rstats->fcs_err;
|
||||
rstats->jabber_err = rsp_rstats->jabber_err;
|
||||
rstats->l2_err = rsp_rstats->l2_err;
|
||||
rstats->frame_err = rsp_rstats->frame_err;
|
||||
|
||||
/* RX firmware stats */
|
||||
rstats->fw_total_rcvd = rsp_rstats->fw_total_rcvd;
|
||||
rstats->fw_total_fwd = rsp_rstats->fw_total_fwd;
|
||||
rstats->fw_err_pko = rsp_rstats->fw_err_pko;
|
||||
rstats->fw_err_link = rsp_rstats->fw_err_link;
|
||||
rstats->fw_err_drop = rsp_rstats->fw_err_drop;
|
||||
/* Number of packets that are LROed */
|
||||
rstats->fw_lro_pkts = rsp_rstats->fw_lro_pkts;
|
||||
/* Number of octets that are LROed */
|
||||
rstats->fw_lro_octs = rsp_rstats->fw_lro_octs;
|
||||
/* Number of LRO packets formed */
|
||||
rstats->fw_total_lro = rsp_rstats->fw_total_lro;
|
||||
/* Number of times lRO of packet aborted */
|
||||
rstats->fw_lro_aborts = rsp_rstats->fw_lro_aborts;
|
||||
rstats->fw_lro_aborts_port = rsp_rstats->fw_lro_aborts_port;
|
||||
rstats->fw_lro_aborts_seq = rsp_rstats->fw_lro_aborts_seq;
|
||||
rstats->fw_lro_aborts_tsval = rsp_rstats->fw_lro_aborts_tsval;
|
||||
rstats->fw_lro_aborts_timer = rsp_rstats->fw_lro_aborts_timer;
|
||||
/* intrmod: packet forward rate */
|
||||
rstats->fwd_rate = rsp_rstats->fwd_rate;
|
||||
|
||||
/* TX link-level stats */
|
||||
tstats->total_pkts_sent = rsp_tstats->total_pkts_sent;
|
||||
tstats->total_bytes_sent = rsp_tstats->total_bytes_sent;
|
||||
tstats->mcast_pkts_sent = rsp_tstats->mcast_pkts_sent;
|
||||
tstats->bcast_pkts_sent = rsp_tstats->bcast_pkts_sent;
|
||||
tstats->ctl_sent = rsp_tstats->ctl_sent;
|
||||
/* Packets sent after one collision*/
|
||||
tstats->one_collision_sent = rsp_tstats->one_collision_sent;
|
||||
/* Packets sent after multiple collision*/
|
||||
tstats->multi_collision_sent = rsp_tstats->multi_collision_sent;
|
||||
/* Packets not sent due to max collisions */
|
||||
tstats->max_collision_fail = rsp_tstats->max_collision_fail;
|
||||
/* Packets not sent due to max deferrals */
|
||||
tstats->max_deferral_fail = rsp_tstats->max_deferral_fail;
|
||||
/* Accounts for over/under-run of buffers */
|
||||
tstats->fifo_err = rsp_tstats->fifo_err;
|
||||
tstats->runts = rsp_tstats->runts;
|
||||
/* Total number of collisions detected */
|
||||
tstats->total_collisions = rsp_tstats->total_collisions;
|
||||
|
||||
/* firmware stats */
|
||||
tstats->fw_total_sent = rsp_tstats->fw_total_sent;
|
||||
tstats->fw_total_fwd = rsp_tstats->fw_total_fwd;
|
||||
tstats->fw_err_pko = rsp_tstats->fw_err_pko;
|
||||
tstats->fw_err_link = rsp_tstats->fw_err_link;
|
||||
tstats->fw_err_drop = rsp_tstats->fw_err_drop;
|
||||
tstats->fw_tso = rsp_tstats->fw_tso;
|
||||
tstats->fw_tso_fwd = rsp_tstats->fw_tso_fwd;
|
||||
tstats->fw_err_tso = rsp_tstats->fw_err_tso;
|
||||
resp->status = 1;
|
||||
} else {
|
||||
resp->status = -1;
|
||||
}
|
||||
complete(&ctrl->complete);
|
||||
}
|
||||
|
||||
/* Configure interrupt moderation parameters */
|
||||
static int octnet_get_link_stats(struct net_device *netdev)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct_dev = lio->oct_dev;
|
||||
|
||||
struct octeon_soft_command *sc;
|
||||
struct oct_nic_stats_ctrl *ctrl;
|
||||
struct oct_nic_stats_resp *resp;
|
||||
|
||||
int retval;
|
||||
|
||||
/* Alloc soft command */
|
||||
sc = (struct octeon_soft_command *)
|
||||
octeon_alloc_soft_command(oct_dev,
|
||||
0,
|
||||
sizeof(struct oct_nic_stats_resp),
|
||||
sizeof(struct octnic_ctrl_pkt));
|
||||
|
||||
if (!sc)
|
||||
return -ENOMEM;
|
||||
|
||||
resp = (struct oct_nic_stats_resp *)sc->virtrptr;
|
||||
memset(resp, 0, sizeof(struct oct_nic_stats_resp));
|
||||
|
||||
ctrl = (struct oct_nic_stats_ctrl *)sc->ctxptr;
|
||||
memset(ctrl, 0, sizeof(struct oct_nic_stats_ctrl));
|
||||
ctrl->netdev = netdev;
|
||||
init_completion(&ctrl->complete);
|
||||
|
||||
sc->iq_no = lio->linfo.txpciq[0].s.q_no;
|
||||
|
||||
octeon_prepare_soft_command(oct_dev, sc, OPCODE_NIC,
|
||||
OPCODE_NIC_PORT_STATS, 0, 0, 0);
|
||||
|
||||
sc->callback = octnet_nic_stats_callback;
|
||||
sc->callback_arg = sc;
|
||||
sc->wait_time = 500; /*in milli seconds*/
|
||||
|
||||
retval = octeon_send_soft_command(oct_dev, sc);
|
||||
if (retval == IQ_SEND_FAILED) {
|
||||
octeon_free_soft_command(oct_dev, sc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wait_for_completion_timeout(&ctrl->complete, msecs_to_jiffies(1000));
|
||||
|
||||
if (resp->status != 1) {
|
||||
octeon_free_soft_command(oct_dev, sc);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
octeon_free_soft_command(oct_dev, sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable/Disable auto interrupt Moderation */
|
||||
static int oct_cfg_adaptive_intr(struct lio *lio, struct ethtool_coalesce
|
||||
*intr_coal)
|
||||
|
@ -72,6 +72,9 @@ MODULE_PARM_DESC(console_bitmask,
|
||||
|
||||
#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
|
||||
|
||||
#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count) \
|
||||
(octeon_dev_ptr->instr_queue[iq_no]->stats.field += count)
|
||||
|
||||
static int debug = -1;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
|
||||
@ -682,13 +685,24 @@ static inline void txqs_start(struct net_device *netdev)
|
||||
*/
|
||||
static inline void txqs_wake(struct net_device *netdev)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
|
||||
if (netif_is_multiqueue(netdev)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < netdev->num_tx_queues; i++)
|
||||
if (__netif_subqueue_stopped(netdev, i))
|
||||
for (i = 0; i < netdev->num_tx_queues; i++) {
|
||||
int qno = lio->linfo.txpciq[i %
|
||||
(lio->linfo.num_txpciq)].s.q_no;
|
||||
|
||||
if (__netif_subqueue_stopped(netdev, i)) {
|
||||
INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, qno,
|
||||
tx_restart, 1);
|
||||
netif_wake_subqueue(netdev, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, lio->txq,
|
||||
tx_restart, 1);
|
||||
netif_wake_queue(netdev);
|
||||
}
|
||||
}
|
||||
@ -763,6 +777,8 @@ static inline int check_txq_status(struct lio *lio)
|
||||
continue;
|
||||
if (__netif_subqueue_stopped(lio->netdev, q)) {
|
||||
wake_q(lio->netdev, q);
|
||||
INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq,
|
||||
tx_restart, 1);
|
||||
ret_val++;
|
||||
}
|
||||
}
|
||||
@ -770,6 +786,8 @@ static inline int check_txq_status(struct lio *lio)
|
||||
if (octnet_iq_is_full(lio->oct_dev, lio->txq))
|
||||
return 0;
|
||||
wake_q(lio->netdev, lio->txq);
|
||||
INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, lio->txq,
|
||||
tx_restart, 1);
|
||||
ret_val = 1;
|
||||
}
|
||||
return ret_val;
|
||||
@ -981,10 +999,16 @@ static void update_txq_status(struct octeon_device *oct, int iq_num)
|
||||
if (__netif_subqueue_stopped(netdev, iq->q_index) &&
|
||||
lio->linfo.link.s.link_up &&
|
||||
(!octnet_iq_is_full(oct, iq_num))) {
|
||||
INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq_num,
|
||||
tx_restart, 1);
|
||||
netif_wake_subqueue(netdev, iq->q_index);
|
||||
} else {
|
||||
if (!octnet_iq_is_full(oct, lio->txq))
|
||||
if (!octnet_iq_is_full(oct, lio->txq)) {
|
||||
INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev,
|
||||
lio->txq,
|
||||
tx_restart, 1);
|
||||
wake_q(netdev, lio->txq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1115,6 +1139,9 @@ static int liquidio_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
oct_dev->rx_pause = 1;
|
||||
oct_dev->tx_pause = 1;
|
||||
|
||||
dev_dbg(&oct_dev->pci_dev->dev, "Device is ready\n");
|
||||
|
||||
return 0;
|
||||
@ -1468,8 +1495,10 @@ static inline int check_txq_state(struct lio *lio, struct sk_buff *skb)
|
||||
if (octnet_iq_is_full(lio->oct_dev, iq))
|
||||
return 0;
|
||||
|
||||
if (__netif_subqueue_stopped(lio->netdev, q))
|
||||
if (__netif_subqueue_stopped(lio->netdev, q)) {
|
||||
INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq, tx_restart, 1);
|
||||
wake_q(lio->netdev, q);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2382,6 +2411,10 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
|
||||
|
||||
break;
|
||||
|
||||
case OCTNET_CMD_SET_FLOW_CTL:
|
||||
netif_info(lio, probe, lio->netdev, "Set RX/TX flow control parameters\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(&oct->pci_dev->dev, "%s Unknown cmd %d\n", __func__,
|
||||
nctrl->ncmd.s.cmd);
|
||||
@ -2976,7 +3009,9 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
if (skb_shinfo(skb)->gso_size) {
|
||||
tx_info->s.gso_size = skb_shinfo(skb)->gso_size;
|
||||
tx_info->s.gso_segs = skb_shinfo(skb)->gso_segs;
|
||||
stats->tx_gso++;
|
||||
}
|
||||
|
||||
/* HW insert VLAN tag */
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
irh->priority = skb_vlan_tag_get(skb) >> 13;
|
||||
@ -2999,7 +3034,10 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
|
||||
netif_trans_update(netdev);
|
||||
|
||||
stats->tx_done++;
|
||||
if (skb_shinfo(skb)->gso_size)
|
||||
stats->tx_done += skb_shinfo(skb)->gso_segs;
|
||||
else
|
||||
stats->tx_done++;
|
||||
stats->tx_tot_bytes += skb->len;
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
@ -736,10 +736,16 @@ struct nic_rx_stats {
|
||||
u64 fw_err_pko;
|
||||
u64 fw_err_link;
|
||||
u64 fw_err_drop;
|
||||
|
||||
/* LRO */
|
||||
u64 fw_lro_pkts; /* Number of packets that are LROed */
|
||||
u64 fw_lro_octs; /* Number of octets that are LROed */
|
||||
u64 fw_total_lro; /* Number of LRO packets formed */
|
||||
u64 fw_lro_aborts; /* Number of times lRO of packet aborted */
|
||||
u64 fw_lro_aborts_port;
|
||||
u64 fw_lro_aborts_seq;
|
||||
u64 fw_lro_aborts_tsval;
|
||||
u64 fw_lro_aborts_timer;
|
||||
/* intrmod: packet forward rate */
|
||||
u64 fwd_rate;
|
||||
};
|
||||
@ -763,9 +769,13 @@ struct nic_tx_stats {
|
||||
/* firmware stats */
|
||||
u64 fw_total_sent;
|
||||
u64 fw_total_fwd;
|
||||
u64 fw_total_fwd_bytes;
|
||||
u64 fw_err_pko;
|
||||
u64 fw_err_link;
|
||||
u64 fw_err_drop;
|
||||
u64 fw_err_tso;
|
||||
u64 fw_tso; /* number of tso requests */
|
||||
u64 fw_tso_fwd; /* number of packets segmented in tso */
|
||||
};
|
||||
|
||||
struct oct_link_stats {
|
||||
|
@ -394,6 +394,12 @@ struct octeon_device {
|
||||
struct cavium_wk console_poll_work[MAX_OCTEON_MAPS];
|
||||
|
||||
void *priv;
|
||||
|
||||
int rx_pause;
|
||||
int tx_pause;
|
||||
|
||||
struct oct_link_stats link_stats; /*stastics from firmware*/
|
||||
|
||||
};
|
||||
|
||||
#define OCT_DRV_ONLINE 1
|
||||
|
@ -65,6 +65,10 @@ struct oct_iq_stats {
|
||||
u64 tx_iq_busy;/**< Numof times this iq was found to be full. */
|
||||
u64 tx_dropped;/**< Numof pkts dropped dueto xmitpath errors. */
|
||||
u64 tx_tot_bytes;/**< Total count of bytes sento to network. */
|
||||
u64 tx_gso; /* count of tso */
|
||||
u64 tx_dmamap_fail;
|
||||
u64 tx_restart;
|
||||
/*u64 tx_timeout_count;*/
|
||||
};
|
||||
|
||||
#define OCT_IQ_STATS_SIZE (sizeof(struct oct_iq_stats))
|
||||
|
@ -30,6 +30,17 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
|
||||
struct oct_nic_stats_resp {
|
||||
u64 rh;
|
||||
struct oct_link_stats stats;
|
||||
u64 status;
|
||||
};
|
||||
|
||||
struct oct_nic_stats_ctrl {
|
||||
struct completion complete;
|
||||
struct net_device *netdev;
|
||||
};
|
||||
|
||||
/** LiquidIO per-interface network private data */
|
||||
struct lio {
|
||||
/** State of the interface. Rx/Tx happens only in the RUNNING state. */
|
||||
|
Loading…
Reference in New Issue
Block a user