diff options
author | Ido Schimmel <idosch@mellanox.com> | 2015-08-06 16:41:56 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-09 22:54:10 -0700 |
commit | d003462a50de8605e66be0966e6370ab9821e07e (patch) | |
tree | 3cee43925b4037dc5efd5b6212aa47f2945bbc27 /drivers/net/ethernet/mellanox/mlxsw/switchx2.c | |
parent | 7b7b9cff7468fdf38ab189dde6ecb4750b171bc8 (diff) | |
download | lwn-d003462a50de8605e66be0966e6370ab9821e07e.tar.gz lwn-d003462a50de8605e66be0966e6370ab9821e07e.zip |
mlxsw: Simplify mlxsw_sx_port_xmit function
Previously we only checked if the transmission queue is not full in the
middle of the xmit function. This lead to complex logic due to the fact
that sometimes we need to reallocate the headroom for our Tx header.
Allow the switch driver to know if the transmission queue is not full
before sending the packet and remove this complex logic.
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/switchx2.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 25 |
1 files changed, 10 insertions, 15 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 7eb045ef797a..fce9b453433b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -300,31 +300,26 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb, .local_port = mlxsw_sx_port->local_port, .is_emad = false, }; - struct sk_buff *skb_old = NULL; int err; + if (mlxsw_core_skb_transmit_busy(mlxsw_sx, &tx_info)) + return NETDEV_TX_BUSY; + if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) { - struct sk_buff *skb_new; + struct sk_buff *skb_orig = skb; - skb_old = skb; - skb_new = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN); - if (!skb_new) { + skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN); + if (!skb) { this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped); - dev_kfree_skb_any(skb_old); + dev_kfree_skb_any(skb_orig); return NETDEV_TX_OK; } - skb = skb_new; } mlxsw_sx_txhdr_construct(skb, &tx_info); + /* Due to a race we might fail here because of a full queue. In that + * unlikely case we simply drop the packet. + */ err = mlxsw_core_skb_transmit(mlxsw_sx, skb, &tx_info); - if (err == -EAGAIN) { - if (skb_old) - dev_kfree_skb_any(skb); - return NETDEV_TX_BUSY; - } - - if (skb_old) - dev_kfree_skb_any(skb_old); if (!err) { pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats); |