Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/mlx4/mlx4_en/mlx4_en_tx.c
Show First 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | bus_dmamap_unload(ring->dma_tag, tx_info->dma_map); | ||||
m_freem(mb); | m_freem(mb); | ||||
done: | done: | ||||
return (tx_info->nr_txbb); | return (tx_info->nr_txbb); | ||||
} | } | ||||
int mlx4_en_free_tx_buf(struct ifnet *dev, struct mlx4_en_tx_ring *ring) | int mlx4_en_free_tx_buf(struct ifnet *dev, struct mlx4_en_tx_ring *ring) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
int cnt = 0; | int cnt = 0; | ||||
/* Skip last polled descriptor */ | /* Skip last polled descriptor */ | ||||
ring->cons += ring->last_nr_txbb; | ring->cons += ring->last_nr_txbb; | ||||
en_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n", | en_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n", | ||||
ring->cons, ring->prod); | ring->cons, ring->prod); | ||||
if ((u32) (ring->prod - ring->cons) > ring->size) { | if ((u32) (ring->prod - ring->cons) > ring->size) { | ||||
Show All 20 Lines | mlx4_en_tx_ring_is_full(struct mlx4_en_tx_ring *ring) | ||||
int wqs; | int wqs; | ||||
wqs = ring->size - (ring->prod - ring->cons); | wqs = ring->size - (ring->prod - ring->cons); | ||||
return (wqs < (HEADROOM + (2 * MLX4_EN_TX_WQE_MAX_WQEBBS))); | return (wqs < (HEADROOM + (2 * MLX4_EN_TX_WQE_MAX_WQEBBS))); | ||||
} | } | ||||
static int mlx4_en_process_tx_cq(struct ifnet *dev, | static int mlx4_en_process_tx_cq(struct ifnet *dev, | ||||
struct mlx4_en_cq *cq) | struct mlx4_en_cq *cq) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_cq *mcq = &cq->mcq; | struct mlx4_cq *mcq = &cq->mcq; | ||||
struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; | struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; | ||||
struct mlx4_cqe *cqe; | struct mlx4_cqe *cqe; | ||||
u16 index; | u16 index; | ||||
u16 new_index, ring_index, stamp_index; | u16 new_index, ring_index, stamp_index; | ||||
u32 txbbs_skipped = 0; | u32 txbbs_skipped = 0; | ||||
u32 txbbs_stamp = 0; | u32 txbbs_stamp = 0; | ||||
u32 cons_index = mcq->cons_index; | u32 cons_index = mcq->cons_index; | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | static int mlx4_en_process_tx_cq(struct ifnet *dev, | ||||
ring->cons += txbbs_skipped; | ring->cons += txbbs_skipped; | ||||
return (0); | return (0); | ||||
} | } | ||||
void mlx4_en_tx_irq(struct mlx4_cq *mcq) | void mlx4_en_tx_irq(struct mlx4_cq *mcq) | ||||
{ | { | ||||
struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq); | struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq); | ||||
struct mlx4_en_priv *priv = netdev_priv(cq->dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(cq->dev); | ||||
struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; | struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; | ||||
if (priv->port_up == 0 || !spin_trylock(&ring->comp_lock)) | if (priv->port_up == 0 || !spin_trylock(&ring->comp_lock)) | ||||
return; | return; | ||||
mlx4_en_process_tx_cq(cq->dev, cq); | mlx4_en_process_tx_cq(cq->dev, cq); | ||||
mod_timer(&cq->timer, jiffies + 1); | mod_timer(&cq->timer, jiffies + 1); | ||||
spin_unlock(&ring->comp_lock); | spin_unlock(&ring->comp_lock); | ||||
} | } | ||||
void mlx4_en_poll_tx_cq(unsigned long data) | void mlx4_en_poll_tx_cq(unsigned long data) | ||||
{ | { | ||||
struct mlx4_en_cq *cq = (struct mlx4_en_cq *) data; | struct mlx4_en_cq *cq = (struct mlx4_en_cq *) data; | ||||
struct mlx4_en_priv *priv = netdev_priv(cq->dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(cq->dev); | ||||
struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; | struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; | ||||
u32 inflight; | u32 inflight; | ||||
INC_PERF_COUNTER(priv->pstats.tx_poll); | INC_PERF_COUNTER(priv->pstats.tx_poll); | ||||
if (priv->port_up == 0) | if (priv->port_up == 0) | ||||
return; | return; | ||||
if (!spin_trylock(&ring->comp_lock)) { | if (!spin_trylock(&ring->comp_lock)) { | ||||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | static void hashrandom_init(void *arg) | ||||
* initialized when this function is called: | * initialized when this function is called: | ||||
*/ | */ | ||||
hashrandom = m_ether_tcpip_hash_init(); | hashrandom = m_ether_tcpip_hash_init(); | ||||
} | } | ||||
SYSINIT(hashrandom_init, SI_SUB_RANDOM, SI_ORDER_ANY, &hashrandom_init, NULL); | SYSINIT(hashrandom_init, SI_SUB_RANDOM, SI_ORDER_ANY, &hashrandom_init, NULL); | ||||
u16 mlx4_en_select_queue(struct ifnet *dev, struct mbuf *mb) | u16 mlx4_en_select_queue(struct ifnet *dev, struct mbuf *mb) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
u32 rings_p_up = priv->num_tx_rings_p_up; | u32 rings_p_up = priv->num_tx_rings_p_up; | ||||
u32 up = 0; | u32 up = 0; | ||||
u32 queue_index; | u32 queue_index; | ||||
#if (MLX4_EN_NUM_UP > 1) | #if (MLX4_EN_NUM_UP > 1) | ||||
/* Obtain VLAN information if present */ | /* Obtain VLAN information if present */ | ||||
if (mb->m_flags & M_VLANTAG) { | if (mb->m_flags & M_VLANTAG) { | ||||
u32 vlan_tag = mb->m_pkthdr.ether_vtag; | u32 vlan_tag = mb->m_pkthdr.ether_vtag; | ||||
▲ Show 20 Lines • Show All 306 Lines • ▼ Show 20 Lines | tx_drop: | ||||
*mbp = NULL; | *mbp = NULL; | ||||
m_freem(mb); | m_freem(mb); | ||||
return (err); | return (err); | ||||
} | } | ||||
static int | static int | ||||
mlx4_en_transmit_locked(struct ifnet *ifp, int tx_ind, struct mbuf *mb) | mlx4_en_transmit_locked(struct ifnet *ifp, int tx_ind, struct mbuf *mb) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(ifp); | struct mlx4_en_priv *priv = mlx4_netdev_priv(ifp); | ||||
struct mlx4_en_tx_ring *ring = priv->tx_ring[tx_ind]; | struct mlx4_en_tx_ring *ring = priv->tx_ring[tx_ind]; | ||||
int err = 0; | int err = 0; | ||||
if (unlikely((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || | if (unlikely((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || | ||||
READ_ONCE(priv->port_up) == 0)) { | READ_ONCE(priv->port_up) == 0)) { | ||||
m_freem(mb); | m_freem(mb); | ||||
return (ENETDOWN); | return (ENETDOWN); | ||||
} | } | ||||
if (mlx4_en_xmit(priv, tx_ind, &mb) != 0) { | if (mlx4_en_xmit(priv, tx_ind, &mb) != 0) { | ||||
/* NOTE: m_freem() is NULL safe */ | /* NOTE: m_freem() is NULL safe */ | ||||
m_freem(mb); | m_freem(mb); | ||||
err = ENOBUFS; | err = ENOBUFS; | ||||
if (ring->watchdog_time == 0) | if (ring->watchdog_time == 0) | ||||
ring->watchdog_time = ticks + MLX4_EN_WATCHDOG_TIMEOUT; | ring->watchdog_time = ticks + MLX4_EN_WATCHDOG_TIMEOUT; | ||||
} else { | } else { | ||||
ring->watchdog_time = 0; | ring->watchdog_time = 0; | ||||
} | } | ||||
return (err); | return (err); | ||||
} | } | ||||
int | int | ||||
mlx4_en_transmit(struct ifnet *dev, struct mbuf *m) | mlx4_en_transmit(struct ifnet *dev, struct mbuf *m) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_tx_ring *ring; | struct mlx4_en_tx_ring *ring; | ||||
int i, err = 0; | int i, err = 0; | ||||
if (priv->port_up == 0) { | if (priv->port_up == 0) { | ||||
m_freem(m); | m_freem(m); | ||||
return (ENETDOWN); | return (ENETDOWN); | ||||
} | } | ||||
Show All 23 Lines | |||||
} | } | ||||
/* | /* | ||||
* Flush ring buffers. | * Flush ring buffers. | ||||
*/ | */ | ||||
void | void | ||||
mlx4_en_qflush(struct ifnet *dev) | mlx4_en_qflush(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
if (priv->port_up == 0) | if (priv->port_up == 0) | ||||
return; | return; | ||||
if_qflush(dev); | if_qflush(dev); | ||||
} | } |