Commit 086c18f2 authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller

ionic: centralize queue reset code

The queue reset pattern is used in a couple different places,
only slightly different from each other, and could cause
issues if one gets changed and the other didn't.  This puts
them together so that only one version is needed, yet each
can have slighty different effects by passing in a pointer
to a work function to do whatever configuration twiddling is
needed in the middle of the reset.

This specifically addresses issues seen where under loops
of changing ring size or queue count parameters we could
occasionally bump into the netdev watchdog.

v2: added more commit message commentary

Fixes: 4d03e00a ("ionic: Add initial ethtool support")
Signed-off-by: default avatarShannon Nelson <snelson@pensando.io>
Acked-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 469acedd
...@@ -468,12 +468,18 @@ static void ionic_get_ringparam(struct net_device *netdev, ...@@ -468,12 +468,18 @@ static void ionic_get_ringparam(struct net_device *netdev,
ring->rx_pending = lif->nrxq_descs; ring->rx_pending = lif->nrxq_descs;
} }
static void ionic_set_ringsize(struct ionic_lif *lif, void *arg)
{
struct ethtool_ringparam *ring = arg;
lif->ntxq_descs = ring->tx_pending;
lif->nrxq_descs = ring->rx_pending;
}
static int ionic_set_ringparam(struct net_device *netdev, static int ionic_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring) struct ethtool_ringparam *ring)
{ {
struct ionic_lif *lif = netdev_priv(netdev); struct ionic_lif *lif = netdev_priv(netdev);
bool running;
int err;
if (ring->rx_mini_pending || ring->rx_jumbo_pending) { if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
netdev_info(netdev, "Changing jumbo or mini descriptors not supported\n"); netdev_info(netdev, "Changing jumbo or mini descriptors not supported\n");
...@@ -491,22 +497,7 @@ static int ionic_set_ringparam(struct net_device *netdev, ...@@ -491,22 +497,7 @@ static int ionic_set_ringparam(struct net_device *netdev,
ring->rx_pending == lif->nrxq_descs) ring->rx_pending == lif->nrxq_descs)
return 0; return 0;
err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET); return ionic_reset_queues(lif, ionic_set_ringsize, ring);
if (err)
return err;
running = test_bit(IONIC_LIF_F_UP, lif->state);
if (running)
ionic_stop(netdev);
lif->ntxq_descs = ring->tx_pending;
lif->nrxq_descs = ring->rx_pending;
if (running)
ionic_open(netdev);
clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
return 0;
} }
static void ionic_get_channels(struct net_device *netdev, static void ionic_get_channels(struct net_device *netdev,
...@@ -521,12 +512,17 @@ static void ionic_get_channels(struct net_device *netdev, ...@@ -521,12 +512,17 @@ static void ionic_get_channels(struct net_device *netdev,
ch->combined_count = lif->nxqs; ch->combined_count = lif->nxqs;
} }
static void ionic_set_queuecount(struct ionic_lif *lif, void *arg)
{
struct ethtool_channels *ch = arg;
lif->nxqs = ch->combined_count;
}
static int ionic_set_channels(struct net_device *netdev, static int ionic_set_channels(struct net_device *netdev,
struct ethtool_channels *ch) struct ethtool_channels *ch)
{ {
struct ionic_lif *lif = netdev_priv(netdev); struct ionic_lif *lif = netdev_priv(netdev);
bool running;
int err;
if (!ch->combined_count || ch->other_count || if (!ch->combined_count || ch->other_count ||
ch->rx_count || ch->tx_count) ch->rx_count || ch->tx_count)
...@@ -535,21 +531,7 @@ static int ionic_set_channels(struct net_device *netdev, ...@@ -535,21 +531,7 @@ static int ionic_set_channels(struct net_device *netdev,
if (ch->combined_count == lif->nxqs) if (ch->combined_count == lif->nxqs)
return 0; return 0;
err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET); return ionic_reset_queues(lif, ionic_set_queuecount, ch);
if (err)
return err;
running = test_bit(IONIC_LIF_F_UP, lif->state);
if (running)
ionic_stop(netdev);
lif->nxqs = ch->combined_count;
if (running)
ionic_open(netdev);
clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
return 0;
} }
static u32 ionic_get_priv_flags(struct net_device *netdev) static u32 ionic_get_priv_flags(struct net_device *netdev)
......
...@@ -1313,7 +1313,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -1313,7 +1313,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
return err; return err;
netdev->mtu = new_mtu; netdev->mtu = new_mtu;
err = ionic_reset_queues(lif); err = ionic_reset_queues(lif, NULL, NULL);
return err; return err;
} }
...@@ -1325,7 +1325,7 @@ static void ionic_tx_timeout_work(struct work_struct *ws) ...@@ -1325,7 +1325,7 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
netdev_info(lif->netdev, "Tx Timeout recovery\n"); netdev_info(lif->netdev, "Tx Timeout recovery\n");
rtnl_lock(); rtnl_lock();
ionic_reset_queues(lif); ionic_reset_queues(lif, NULL, NULL);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -1988,7 +1988,7 @@ static const struct net_device_ops ionic_netdev_ops = { ...@@ -1988,7 +1988,7 @@ static const struct net_device_ops ionic_netdev_ops = {
.ndo_get_vf_stats = ionic_get_vf_stats, .ndo_get_vf_stats = ionic_get_vf_stats,
}; };
int ionic_reset_queues(struct ionic_lif *lif) int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg)
{ {
bool running; bool running;
int err = 0; int err = 0;
...@@ -2001,12 +2001,19 @@ int ionic_reset_queues(struct ionic_lif *lif) ...@@ -2001,12 +2001,19 @@ int ionic_reset_queues(struct ionic_lif *lif)
if (running) { if (running) {
netif_device_detach(lif->netdev); netif_device_detach(lif->netdev);
err = ionic_stop(lif->netdev); err = ionic_stop(lif->netdev);
if (err)
goto reset_out;
} }
if (!err && running) {
ionic_open(lif->netdev); if (cb)
cb(lif, arg);
if (running) {
err = ionic_open(lif->netdev);
netif_device_attach(lif->netdev); netif_device_attach(lif->netdev);
} }
reset_out:
clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state); clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
return err; return err;
......
...@@ -248,6 +248,8 @@ static inline u32 ionic_coal_hw_to_usec(struct ionic *ionic, u32 units) ...@@ -248,6 +248,8 @@ static inline u32 ionic_coal_hw_to_usec(struct ionic *ionic, u32 units)
return (units * div) / mult; return (units * div) / mult;
} }
typedef void (*ionic_reset_cb)(struct ionic_lif *lif, void *arg);
void ionic_link_status_check_request(struct ionic_lif *lif); void ionic_link_status_check_request(struct ionic_lif *lif);
void ionic_get_stats64(struct net_device *netdev, void ionic_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *ns); struct rtnl_link_stats64 *ns);
...@@ -267,7 +269,7 @@ int ionic_lif_rss_config(struct ionic_lif *lif, u16 types, ...@@ -267,7 +269,7 @@ int ionic_lif_rss_config(struct ionic_lif *lif, u16 types,
int ionic_open(struct net_device *netdev); int ionic_open(struct net_device *netdev);
int ionic_stop(struct net_device *netdev); int ionic_stop(struct net_device *netdev);
int ionic_reset_queues(struct ionic_lif *lif); int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg);
static inline void debug_stats_txq_post(struct ionic_qcq *qcq, static inline void debug_stats_txq_post(struct ionic_qcq *qcq,
struct ionic_txq_desc *desc, bool dbell) struct ionic_txq_desc *desc, bool dbell)
......
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