|
|
@@ -6837,6 +6837,36 @@ static void ixgbe_tx_olinfo_status(union ixgbe_adv_tx_desc *tx_desc,
|
|
|
tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
|
|
|
}
|
|
|
|
|
|
+static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
|
|
|
+{
|
|
|
+ netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
|
|
|
+
|
|
|
+ /* Herbert's original patch had:
|
|
|
+ * smp_mb__after_netif_stop_queue();
|
|
|
+ * but since that doesn't exist yet, just open code it.
|
|
|
+ */
|
|
|
+ smp_mb();
|
|
|
+
|
|
|
+ /* We need to check again in a case another CPU has just
|
|
|
+ * made room available.
|
|
|
+ */
|
|
|
+ if (likely(ixgbe_desc_unused(tx_ring) < size))
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
+ /* A reprieve! - use start_queue because it doesn't call schedule */
|
|
|
+ netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
|
|
|
+ ++tx_ring->tx_stats.restart_queue;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
|
|
|
+{
|
|
|
+ if (likely(ixgbe_desc_unused(tx_ring) >= size))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return __ixgbe_maybe_stop_tx(tx_ring, size);
|
|
|
+}
|
|
|
+
|
|
|
#define IXGBE_TXD_CMD (IXGBE_TXD_CMD_EOP | \
|
|
|
IXGBE_TXD_CMD_RS)
|
|
|
|
|
|
@@ -6958,10 +6988,13 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
|
|
|
|
|
|
tx_ring->next_to_use = i;
|
|
|
|
|
|
- if (!skb->xmit_more) {
|
|
|
+ ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
|
|
|
+
|
|
|
+ if (netif_xmit_stopped(txring_txq(tx_ring)) || !skb->xmit_more) {
|
|
|
/* notify HW of packet */
|
|
|
ixgbe_write_tail(tx_ring, i);
|
|
|
}
|
|
|
+
|
|
|
return;
|
|
|
dma_error:
|
|
|
dev_err(tx_ring->dev, "TX DMA map failed\n");
|
|
|
@@ -7068,32 +7101,6 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
|
|
|
input, common, ring->queue_index);
|
|
|
}
|
|
|
|
|
|
-static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
|
|
|
-{
|
|
|
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
|
|
|
- /* Herbert's original patch had:
|
|
|
- * smp_mb__after_netif_stop_queue();
|
|
|
- * but since that doesn't exist yet, just open code it. */
|
|
|
- smp_mb();
|
|
|
-
|
|
|
- /* We need to check again in a case another CPU has just
|
|
|
- * made room available. */
|
|
|
- if (likely(ixgbe_desc_unused(tx_ring) < size))
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
- /* A reprieve! - use start_queue because it doesn't call schedule */
|
|
|
- netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
|
|
|
- ++tx_ring->tx_stats.restart_queue;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
|
|
|
-{
|
|
|
- if (likely(ixgbe_desc_unused(tx_ring) >= size))
|
|
|
- return 0;
|
|
|
- return __ixgbe_maybe_stop_tx(tx_ring, size);
|
|
|
-}
|
|
|
-
|
|
|
static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
|
|
|
void *accel_priv, select_queue_fallback_t fallback)
|
|
|
{
|
|
|
@@ -7262,8 +7269,6 @@ xmit_fcoe:
|
|
|
#endif /* IXGBE_FCOE */
|
|
|
ixgbe_tx_map(tx_ring, first, hdr_len);
|
|
|
|
|
|
- ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
|
|
|
-
|
|
|
return NETDEV_TX_OK;
|
|
|
|
|
|
out_drop:
|