Commit 37dd3482 authored by Ivan Vecera's avatar Ivan Vecera Committed by David S. Miller

bna: fix crash in bnad_get_strings()

Commit 6e7333d3 "net: add rx_nohandler stat counter" added the new entry
rx_nohandler into struct rtnl_link_stats64. Unfortunately the bna
driver foolishly depends on the structure. It uses part of it for
ethtool statistics and it's not bad but the driver assumes its size
is constant as it defines string for each existing entry. The problem
occurs when the structure is extended because you need to modify bna
driver as well. If not any attempt to retrieve ethtool statistics results
in crash in bnad_get_strings().
The patch changes BNAD_ETHTOOL_STATS_NUM so it counts real number of
strings in the array and also removes rtnl_link_stats64 entries that
are not used in output and are always zero.

Fixes: 6e7333d3 "net: add rx_nohandler stat counter"
Signed-off-by: default avatarIvan Vecera <ivecera@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2835d2d9
...@@ -34,12 +34,7 @@ ...@@ -34,12 +34,7 @@
#define BNAD_NUM_RXQ_COUNTERS 7 #define BNAD_NUM_RXQ_COUNTERS 7
#define BNAD_NUM_TXQ_COUNTERS 5 #define BNAD_NUM_TXQ_COUNTERS 5
#define BNAD_ETHTOOL_STATS_NUM \ static const char *bnad_net_stats_strings[] = {
(sizeof(struct rtnl_link_stats64) / sizeof(u64) + \
sizeof(struct bnad_drv_stats) / sizeof(u64) + \
offsetof(struct bfi_enet_stats, rxf_stats[0]) / sizeof(u64))
static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"rx_packets", "rx_packets",
"tx_packets", "tx_packets",
"rx_bytes", "rx_bytes",
...@@ -50,22 +45,10 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = { ...@@ -50,22 +45,10 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"tx_dropped", "tx_dropped",
"multicast", "multicast",
"collisions", "collisions",
"rx_length_errors", "rx_length_errors",
"rx_over_errors",
"rx_crc_errors", "rx_crc_errors",
"rx_frame_errors", "rx_frame_errors",
"rx_fifo_errors",
"rx_missed_errors",
"tx_aborted_errors",
"tx_carrier_errors",
"tx_fifo_errors", "tx_fifo_errors",
"tx_heartbeat_errors",
"tx_window_errors",
"rx_compressed",
"tx_compressed",
"netif_queue_stop", "netif_queue_stop",
"netif_queue_wakeup", "netif_queue_wakeup",
...@@ -254,6 +237,8 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = { ...@@ -254,6 +237,8 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
"fc_tx_fid_parity_errors", "fc_tx_fid_parity_errors",
}; };
#define BNAD_ETHTOOL_STATS_NUM ARRAY_SIZE(bnad_net_stats_strings)
static int static int
bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
{ {
...@@ -859,9 +844,9 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, ...@@ -859,9 +844,9 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
u64 *buf) u64 *buf)
{ {
struct bnad *bnad = netdev_priv(netdev); struct bnad *bnad = netdev_priv(netdev);
int i, j, bi; int i, j, bi = 0;
unsigned long flags; unsigned long flags;
struct rtnl_link_stats64 *net_stats64; struct rtnl_link_stats64 net_stats64;
u64 *stats64; u64 *stats64;
u32 bmap; u32 bmap;
...@@ -876,14 +861,25 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, ...@@ -876,14 +861,25 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
* under the same lock * under the same lock
*/ */
spin_lock_irqsave(&bnad->bna_lock, flags); spin_lock_irqsave(&bnad->bna_lock, flags);
bi = 0;
memset(buf, 0, stats->n_stats * sizeof(u64));
net_stats64 = (struct rtnl_link_stats64 *)buf;
bnad_netdev_qstats_fill(bnad, net_stats64);
bnad_netdev_hwstats_fill(bnad, net_stats64);
bi = sizeof(*net_stats64) / sizeof(u64); memset(&net_stats64, 0, sizeof(net_stats64));
bnad_netdev_qstats_fill(bnad, &net_stats64);
bnad_netdev_hwstats_fill(bnad, &net_stats64);
buf[bi++] = net_stats64.rx_packets;
buf[bi++] = net_stats64.tx_packets;
buf[bi++] = net_stats64.rx_bytes;
buf[bi++] = net_stats64.tx_bytes;
buf[bi++] = net_stats64.rx_errors;
buf[bi++] = net_stats64.tx_errors;
buf[bi++] = net_stats64.rx_dropped;
buf[bi++] = net_stats64.tx_dropped;
buf[bi++] = net_stats64.multicast;
buf[bi++] = net_stats64.collisions;
buf[bi++] = net_stats64.rx_length_errors;
buf[bi++] = net_stats64.rx_crc_errors;
buf[bi++] = net_stats64.rx_frame_errors;
buf[bi++] = net_stats64.tx_fifo_errors;
/* Get netif_queue_stopped from stack */ /* Get netif_queue_stopped from stack */
bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev); bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev);
......
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