diff options
author | hselasky <hselasky@FreeBSD.org> | 2016-04-29 11:06:24 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2016-04-29 11:06:24 +0000 |
commit | 02ad600f2e9a3d9f9e61bd333e8550cef024880b (patch) | |
tree | d6b45313fe6b755dfec5443832fc7c421857b4c7 | |
parent | d58ddf1ae8d432c467a7432104842a4e0d70d32a (diff) | |
download | FreeBSD-src-02ad600f2e9a3d9f9e61bd333e8550cef024880b.zip FreeBSD-src-02ad600f2e9a3d9f9e61bd333e8550cef024880b.tar.gz |
MFC r297966:
Add missing port_up checks.
When downing a mlxen network adapter we need to check the port_up variable
to ensure we don't continue to transmit data or restart timers which can
reside in freed memory.
Sponsored by: Mellanox Technologies
-rw-r--r-- | sys/ofed/drivers/net/mlx4/en_tx.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c index 3614b0d..e9526c4 100644 --- a/sys/ofed/drivers/net/mlx4/en_tx.c +++ b/sys/ofed/drivers/net/mlx4/en_tx.c @@ -458,7 +458,7 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq) struct mlx4_en_priv *priv = netdev_priv(cq->dev); struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; - if (!spin_trylock(&ring->comp_lock)) + if (priv->port_up == 0 || !spin_trylock(&ring->comp_lock)) return; mlx4_en_process_tx_cq(cq->dev, cq); mod_timer(&cq->timer, jiffies + 1); @@ -474,6 +474,8 @@ void mlx4_en_poll_tx_cq(unsigned long data) INC_PERF_COUNTER(priv->pstats.tx_poll); + if (priv->port_up == 0) + return; if (!spin_trylock(&ring->comp_lock)) { mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); return; @@ -495,6 +497,9 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) struct mlx4_en_cq *cq = priv->tx_cq[tx_ind]; struct mlx4_en_tx_ring *ring = priv->tx_ring[tx_ind]; + if (priv->port_up == 0) + return; + /* If we don't have a pending timer, set one up to catch our recent post in case the interface becomes idle */ if (!timer_pending(&cq->timer)) @@ -1038,7 +1043,9 @@ mlx4_en_tx_que(void *context, int pending) priv = dev->if_softc; tx_ind = cq->ring; ring = priv->tx_ring[tx_ind]; - if (dev->if_drv_flags & IFF_DRV_RUNNING) { + + if (priv->port_up != 0 && + (dev->if_drv_flags & IFF_DRV_RUNNING) != 0) { mlx4_en_xmit_poll(priv, tx_ind); spin_lock(&ring->tx_lock); if (!drbr_empty(dev, ring->br)) @@ -1055,6 +1062,11 @@ mlx4_en_transmit(struct ifnet *dev, struct mbuf *m) struct mlx4_en_cq *cq; int i, err = 0; + if (priv->port_up == 0) { + m_freem(m); + return (ENETDOWN); + } + /* Compute which queue to use */ if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { i = (m->m_pkthdr.flowid % 128) % priv->tx_ring_num; @@ -1088,6 +1100,9 @@ mlx4_en_qflush(struct ifnet *dev) struct mlx4_en_tx_ring *ring; struct mbuf *m; + if (priv->port_up == 0) + return; + for (int i = 0; i < priv->tx_ring_num; i++) { ring = priv->tx_ring[i]; spin_lock(&ring->tx_lock); |