|
@@ -336,7 +336,8 @@ struct tx_queue {
|
|
|
struct tx_desc *tx_desc_area;
|
|
|
dma_addr_t tx_desc_dma;
|
|
|
int tx_desc_area_size;
|
|
|
- struct sk_buff **tx_skb;
|
|
|
+
|
|
|
+ struct sk_buff_head tx_skb;
|
|
|
|
|
|
unsigned long tx_packets;
|
|
|
unsigned long tx_bytes;
|
|
@@ -676,10 +677,8 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
|
|
|
desc->cmd_sts = BUFFER_OWNED_BY_DMA |
|
|
|
ZERO_PADDING | TX_LAST_DESC |
|
|
|
TX_ENABLE_INTERRUPT;
|
|
|
- txq->tx_skb[tx_index] = skb;
|
|
|
} else {
|
|
|
desc->cmd_sts = BUFFER_OWNED_BY_DMA;
|
|
|
- txq->tx_skb[tx_index] = NULL;
|
|
|
}
|
|
|
|
|
|
desc->l4i_chk = 0;
|
|
@@ -712,13 +711,10 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
|
|
|
|
|
|
if (nr_frags) {
|
|
|
txq_submit_frag_skb(txq, skb);
|
|
|
-
|
|
|
length = skb_headlen(skb);
|
|
|
- txq->tx_skb[tx_index] = NULL;
|
|
|
} else {
|
|
|
cmd_sts |= ZERO_PADDING | TX_LAST_DESC | TX_ENABLE_INTERRUPT;
|
|
|
length = skb->len;
|
|
|
- txq->tx_skb[tx_index] = skb;
|
|
|
}
|
|
|
|
|
|
desc->byte_cnt = length;
|
|
@@ -772,6 +768,8 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
|
|
|
desc->l4i_chk = 0;
|
|
|
}
|
|
|
|
|
|
+ __skb_queue_tail(&txq->tx_skb, skb);
|
|
|
+
|
|
|
/* ensure all other descriptors are written before first cmd_sts */
|
|
|
wmb();
|
|
|
desc->cmd_sts = cmd_sts;
|
|
@@ -884,8 +882,9 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
|
|
|
reclaimed++;
|
|
|
txq->tx_desc_count--;
|
|
|
|
|
|
- skb = txq->tx_skb[tx_index];
|
|
|
- txq->tx_skb[tx_index] = NULL;
|
|
|
+ skb = NULL;
|
|
|
+ if (cmd_sts & TX_LAST_DESC)
|
|
|
+ skb = __skb_dequeue(&txq->tx_skb);
|
|
|
|
|
|
if (cmd_sts & ERROR_SUMMARY) {
|
|
|
dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n");
|
|
@@ -1692,18 +1691,11 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
|
|
|
if (txq->tx_desc_area == NULL) {
|
|
|
dev_printk(KERN_ERR, &mp->dev->dev,
|
|
|
"can't allocate tx ring (%d bytes)\n", size);
|
|
|
- goto out;
|
|
|
+ return -ENOMEM;
|
|
|
}
|
|
|
memset(txq->tx_desc_area, 0, size);
|
|
|
|
|
|
txq->tx_desc_area_size = size;
|
|
|
- txq->tx_skb = kmalloc(txq->tx_ring_size * sizeof(*txq->tx_skb),
|
|
|
- GFP_KERNEL);
|
|
|
- if (txq->tx_skb == NULL) {
|
|
|
- dev_printk(KERN_ERR, &mp->dev->dev,
|
|
|
- "can't allocate tx skb ring\n");
|
|
|
- goto out_free;
|
|
|
- }
|
|
|
|
|
|
tx_desc = (struct tx_desc *)txq->tx_desc_area;
|
|
|
for (i = 0; i < txq->tx_ring_size; i++) {
|
|
@@ -1719,18 +1711,9 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
|
|
|
nexti * sizeof(struct tx_desc);
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ skb_queue_head_init(&txq->tx_skb);
|
|
|
|
|
|
-out_free:
|
|
|
- if (index == 0 && size <= mp->tx_desc_sram_size)
|
|
|
- iounmap(txq->tx_desc_area);
|
|
|
- else
|
|
|
- dma_free_coherent(NULL, size,
|
|
|
- txq->tx_desc_area,
|
|
|
- txq->tx_desc_dma);
|
|
|
-
|
|
|
-out:
|
|
|
- return -ENOMEM;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void txq_deinit(struct tx_queue *txq)
|
|
@@ -1748,8 +1731,6 @@ static void txq_deinit(struct tx_queue *txq)
|
|
|
else
|
|
|
dma_free_coherent(NULL, txq->tx_desc_area_size,
|
|
|
txq->tx_desc_area, txq->tx_desc_dma);
|
|
|
-
|
|
|
- kfree(txq->tx_skb);
|
|
|
}
|
|
|
|
|
|
|