summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c260
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: