diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 260 |
1 files changed, 80 insertions, 180 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index b36c02f..ff83a9f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -27,43 +27,36 @@ static const u32 qlcnic_fw_dump_level[] = { }; static const struct qlcnic_stats qlcnic_gstrings_stats[] = { - {"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)}, - {"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, {"xmit_called", QLC_SIZEOF(stats.xmitcalled), - QLC_OFF(stats.xmitcalled)}, + QLC_OFF(stats.xmitcalled)}, {"xmit_finished", QLC_SIZEOF(stats.xmitfinished), - QLC_OFF(stats.xmitfinished)}, - {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error), - QLC_OFF(stats.tx_dma_map_error)}, - {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, - {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)}, - {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error), - QLC_OFF(stats.rx_dma_map_error)}, - {"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)}, - {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, + QLC_OFF(stats.xmitfinished)}, {"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)}, - {"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)}, + {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)}, {"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)}, + {"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)}, {"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)}, + {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, + {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, {"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)}, {"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, + {"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)}, + {"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), QLC_OFF(stats.skb_alloc_failure)}, + {"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)}, + {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error), + QLC_OFF(stats.rx_dma_map_error)}, + {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error), + QLC_OFF(stats.tx_dma_map_error)}, {"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun), - QLC_OFF(stats.mac_filter_limit_overrun)}, + QLC_OFF(stats.mac_filter_limit_overrun)}, {"spurious intr", QLC_SIZEOF(stats.spurious_intr), QLC_OFF(stats.spurious_intr)}, }; static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { - "tx unicast frames", - "tx multicast frames", - "tx broadcast frames", - "tx dropped frames", - "tx errors", - "tx local frames", - "tx numbytes", "rx unicast frames", "rx multicast frames", "rx broadcast frames", @@ -71,6 +64,13 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { "rx errors", "rx local frames", "rx numbytes", + "tx unicast frames", + "tx multicast frames", + "tx broadcast frames", + "tx dropped frames", + "tx errors", + "tx local frames", + "tx numbytes", }; static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = { @@ -126,16 +126,13 @@ static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = { #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) -static const char qlcnic_tx_queue_stats_strings[][ETH_GSTRING_LEN] = { +static const char qlcnic_tx_ring_stats_strings[][ETH_GSTRING_LEN] = { "xmit_on", "xmit_off", "xmit_called", "xmit_finished", - "tx_bytes", }; -#define QLCNIC_TX_STATS_LEN ARRAY_SIZE(qlcnic_tx_queue_stats_strings) - static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { "ctx_rx_bytes", "ctx_rx_pkts", @@ -190,8 +187,8 @@ static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter) return -1; } -#define QLCNIC_TX_INTR_NOT_CONFIGURED 0X78563412 - +#define QLCNIC_RING_REGS_COUNT 20 +#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32)) #define QLCNIC_MAX_EEPROM_LEN 1024 static const u32 diag_registers[] = { @@ -222,15 +219,7 @@ static const u32 ext_diag_registers[] = { }; #define QLCNIC_MGMT_API_VERSION 2 -#define QLCNIC_ETHTOOL_REGS_VER 4 - -static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter) -{ - int ring_regs_cnt = (adapter->drv_tx_rings * 5) + - (adapter->max_rds_rings * 2) + - (adapter->drv_sds_rings * 3) + 5; - return ring_regs_cnt * sizeof(u32); -} +#define QLCNIC_ETHTOOL_REGS_VER 3 static int qlcnic_get_regs_len(struct net_device *dev) { @@ -242,9 +231,7 @@ static int qlcnic_get_regs_len(struct net_device *dev) else len = sizeof(ext_diag_registers) + sizeof(diag_registers); - len += ((QLCNIC_DEV_INFO_SIZE + 2) * sizeof(u32)); - len += qlcnic_get_ring_regs_len(adapter); - return len; + return QLCNIC_RING_REGS_LEN + len + QLCNIC_DEV_INFO_SIZE + 1; } static int qlcnic_get_eeprom_len(struct net_device *dev) @@ -506,8 +493,6 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) struct qlcnic_adapter *adapter = netdev_priv(dev); struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_host_rds_ring *rds_rings; - struct qlcnic_host_tx_ring *tx_ring; u32 *regs_buff = p; int ring, i = 0; @@ -527,35 +512,21 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) return; - /* Marker btw regs and TX ring count */ - regs_buff[i++] = 0xFFEFCDAB; - - regs_buff[i++] = adapter->drv_tx_rings; /* No. of TX ring */ - for (ring = 0; ring < adapter->drv_tx_rings; ring++) { - tx_ring = &adapter->tx_ring[ring]; - regs_buff[i++] = le32_to_cpu(*(tx_ring->hw_consumer)); - regs_buff[i++] = tx_ring->sw_consumer; - regs_buff[i++] = readl(tx_ring->crb_cmd_producer); - regs_buff[i++] = tx_ring->producer; - if (tx_ring->crb_intr_mask) - regs_buff[i++] = readl(tx_ring->crb_intr_mask); - else - regs_buff[i++] = QLCNIC_TX_INTR_NOT_CONFIGURED; - } + regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/ - regs_buff[i++] = adapter->max_rds_rings; /* No. of RX ring */ - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_rings = &recv_ctx->rds_rings[ring]; - regs_buff[i++] = readl(rds_rings->crb_rcv_producer); - regs_buff[i++] = rds_rings->producer; - } + regs_buff[i++] = 1; /* No. of tx ring */ + regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer)); + regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer); + + regs_buff[i++] = 2; /* No. of rx ring */ + regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer); + regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer); - regs_buff[i++] = adapter->drv_sds_rings; /* No. of SDS ring */ - for (ring = 0; ring < adapter->drv_sds_rings; ring++) { + regs_buff[i++] = adapter->max_sds_rings; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &(recv_ctx->sds_rings[ring]); regs_buff[i++] = readl(sds_ring->crb_sts_consumer); - regs_buff[i++] = sds_ring->consumer; - regs_buff[i++] = readl(sds_ring->crb_intr_mask); } } @@ -664,88 +635,46 @@ qlcnic_set_ringparam(struct net_device *dev, return qlcnic_reset_context(adapter); } -static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter, - u8 rx_ring, u8 tx_ring) -{ - if (rx_ring != 0) { - if (rx_ring > adapter->max_sds_rings) { - netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n", - rx_ring, adapter->max_sds_rings); - return -EINVAL; - } - } - - if (tx_ring != 0) { - if (qlcnic_82xx_check(adapter) && - (tx_ring > adapter->max_tx_rings)) { - netdev_err(adapter->netdev, - "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n", - tx_ring, adapter->max_tx_rings); - return -EINVAL; - } - - if (qlcnic_83xx_check(adapter) && - (tx_ring > QLCNIC_SINGLE_RING)) { - netdev_err(adapter->netdev, - "Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n", - tx_ring, QLCNIC_SINGLE_RING); - return -EINVAL; - } - } - - return 0; -} - static void qlcnic_get_channels(struct net_device *dev, struct ethtool_channels *channel) { struct qlcnic_adapter *adapter = netdev_priv(dev); + int min; + + min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus()); + channel->max_rx = rounddown_pow_of_two(min); + channel->max_tx = min_t(int, QLCNIC_MAX_TX_RINGS, num_online_cpus()); - channel->max_rx = adapter->max_sds_rings; - channel->max_tx = adapter->max_tx_rings; - channel->rx_count = adapter->drv_sds_rings; - channel->tx_count = adapter->drv_tx_rings; + channel->rx_count = adapter->max_sds_rings; + channel->tx_count = adapter->max_drv_tx_rings; } static int qlcnic_set_channels(struct net_device *dev, - struct ethtool_channels *channel) + struct ethtool_channels *channel) { struct qlcnic_adapter *adapter = netdev_priv(dev); int err; + int txq = 0; if (channel->other_count || channel->combined_count) return -EINVAL; - err = qlcnic_validate_ring_count(adapter, channel->rx_count, - channel->tx_count); - if (err) - return err; - if (channel->rx_count) { - err = qlcnic_validate_rings(adapter, channel->rx_count, - QLCNIC_RX_QUEUE); - if (err) { - netdev_err(dev, "Unable to configure %u SDS rings\n", - channel->rx_count); + err = qlcnic_validate_max_rss(adapter, channel->rx_count); + if (err) return err; - } } - if (channel->tx_count) { - err = qlcnic_validate_rings(adapter, channel->tx_count, - QLCNIC_TX_QUEUE); - if (err) { - netdev_err(dev, "Unable to configure %u Tx rings\n", - channel->tx_count); + if (qlcnic_82xx_check(adapter) && channel->tx_count) { + err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count); + if (err) return err; - } + txq = channel->tx_count; } - err = qlcnic_setup_rings(adapter, channel->rx_count, - channel->tx_count); - netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n", - adapter->drv_sds_rings, adapter->drv_tx_rings); - + err = qlcnic_set_max_rss(adapter, channel->rx_count, txq); + netdev_info(dev, "allocated 0x%x sds rings and 0x%x tx rings\n", + adapter->max_sds_rings, adapter->max_drv_tx_rings); return err; } @@ -947,7 +876,7 @@ static int qlcnic_irq_test(struct net_device *netdev) struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_cmd_args cmd; - int ret, drv_sds_rings = adapter->drv_sds_rings; + int ret, max_sds_rings = adapter->max_sds_rings; if (qlcnic_83xx_check(adapter)) return qlcnic_83xx_interrupt_test(netdev); @@ -976,10 +905,10 @@ done: qlcnic_free_mbx_args(&cmd); free_diag_res: - qlcnic_diag_free_res(netdev, drv_sds_rings); + qlcnic_diag_free_res(netdev, max_sds_rings); clear_diag_irq: - adapter->drv_sds_rings = drv_sds_rings; + adapter->max_sds_rings = max_sds_rings; clear_bit(__QLCNIC_RESETTING, &adapter->state); return ret; @@ -1055,8 +984,8 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) int qlcnic_loopback_test(struct net_device *netdev, u8 mode) { struct qlcnic_adapter *adapter = netdev_priv(netdev); - int drv_tx_rings = adapter->drv_tx_rings; - int drv_sds_rings = adapter->drv_sds_rings; + int max_drv_tx_rings = adapter->max_drv_tx_rings; + int max_sds_rings = adapter->max_sds_rings; struct qlcnic_host_sds_ring *sds_ring; struct qlcnic_hardware_context *ahw = adapter->ahw; int loop = 0; @@ -1111,11 +1040,11 @@ int qlcnic_loopback_test(struct net_device *netdev, u8 mode) qlcnic_clear_lb_mode(adapter, mode); free_res: - qlcnic_diag_free_res(netdev, drv_sds_rings); + qlcnic_diag_free_res(netdev, max_sds_rings); clear_it: - adapter->drv_sds_rings = drv_sds_rings; - adapter->drv_tx_rings = drv_tx_rings; + adapter->max_sds_rings = max_sds_rings; + adapter->max_drv_tx_rings = max_drv_tx_rings; clear_bit(__QLCNIC_RESETTING, &adapter->state); return ret; } @@ -1168,11 +1097,11 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) QLCNIC_TEST_LEN * ETH_GSTRING_LEN); break; case ETH_SS_STATS: - num_stats = ARRAY_SIZE(qlcnic_tx_queue_stats_strings); - for (i = 0; i < adapter->drv_tx_rings; i++) { + num_stats = ARRAY_SIZE(qlcnic_tx_ring_stats_strings); + for (i = 0; i < adapter->max_drv_tx_rings; i++) { for (index = 0; index < num_stats; index++) { - sprintf(data, "tx_queue_%d %s", i, - qlcnic_tx_queue_stats_strings[index]); + sprintf(data, "tx_ring_%d %s", i, + qlcnic_tx_ring_stats_strings[index]); data += ETH_GSTRING_LEN; } } @@ -1270,36 +1199,6 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type) return data; } -static void qlcnic_update_stats(struct qlcnic_adapter *adapter) -{ - struct qlcnic_host_tx_ring *tx_ring; - int ring; - - for (ring = 0; ring < adapter->drv_tx_rings; ring++) { - tx_ring = &adapter->tx_ring[ring]; - adapter->stats.xmit_on += tx_ring->tx_stats.xmit_on; - adapter->stats.xmit_off += tx_ring->tx_stats.xmit_off; - adapter->stats.xmitcalled += tx_ring->tx_stats.xmit_called; - adapter->stats.xmitfinished += tx_ring->tx_stats.xmit_finished; - adapter->stats.txbytes += tx_ring->tx_stats.tx_bytes; - } -} - -static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats) -{ - struct qlcnic_host_tx_ring *tx_ring; - - tx_ring = (struct qlcnic_host_tx_ring *)stats; - - *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_on); - *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_off); - *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_called); - *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_finished); - *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.tx_bytes); - - return data; -} - static void qlcnic_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { @@ -1307,20 +1206,19 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev, struct qlcnic_host_tx_ring *tx_ring; struct qlcnic_esw_statistics port_stats; struct qlcnic_mac_statistics mac_stats; - int index, ret, length, size, tx_size, ring; + int index, ret, length, size, ring; char *p; - tx_size = adapter->drv_tx_rings * QLCNIC_TX_STATS_LEN; - - memset(data, 0, tx_size * sizeof(u64)); - for (ring = 0, index = 0; ring < adapter->drv_tx_rings; ring++) { + memset(data, 0, adapter->max_drv_tx_rings * 4 * sizeof(u64)); + for (ring = 0, index = 0; ring < adapter->max_drv_tx_rings; ring++) { if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { tx_ring = &adapter->tx_ring[ring]; - data = qlcnic_fill_tx_queue_stats(data, tx_ring); - qlcnic_update_stats(adapter); + *data++ = tx_ring->xmit_on; + *data++ = tx_ring->xmit_off; + *data++ = tx_ring->xmit_called; + *data++ = tx_ring->xmit_finished; } } - memset(data, 0, stats->n_stats * sizeof(u64)); length = QLCNIC_STATS_LEN; for (index = 0; index < length; index++) { @@ -1362,7 +1260,7 @@ static int qlcnic_set_led(struct net_device *dev, enum ethtool_phys_id_state state) { struct qlcnic_adapter *adapter = netdev_priv(dev); - int drv_sds_rings = adapter->drv_sds_rings; + int max_sds_rings = adapter->max_sds_rings; int err = -EIO, active = 1; if (qlcnic_83xx_check(adapter)) @@ -1420,7 +1318,7 @@ static int qlcnic_set_led(struct net_device *dev, } if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) - qlcnic_diag_free_res(dev, drv_sds_rings); + qlcnic_diag_free_res(dev, max_sds_rings); if (!active || err) clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); @@ -1761,6 +1659,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; bool valid_mask = false; int i, ret = 0; + u32 state; switch (val->flag) { case QLCNIC_FORCE_FW_DUMP_KEY: @@ -1813,8 +1712,9 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) case QLCNIC_SET_QUIESCENT: case QLCNIC_RESET_QUIESCENT: - if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) - netdev_info(netdev, "Device is in non-operational state\n"); + state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); + if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) + netdev_info(netdev, "Device in FAILED state\n"); break; default: |