|
@@ -1189,12 +1189,13 @@ static void
|
|
fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
|
|
fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
|
|
{
|
|
{
|
|
struct fec_enet_private *fep;
|
|
struct fec_enet_private *fep;
|
|
- struct bufdesc *bdp;
|
|
|
|
|
|
+ struct bufdesc *bdp, *bdp_t;
|
|
unsigned short status;
|
|
unsigned short status;
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
struct fec_enet_priv_tx_q *txq;
|
|
struct fec_enet_priv_tx_q *txq;
|
|
struct netdev_queue *nq;
|
|
struct netdev_queue *nq;
|
|
int index = 0;
|
|
int index = 0;
|
|
|
|
+ int i, bdnum;
|
|
int entries_free;
|
|
int entries_free;
|
|
|
|
|
|
fep = netdev_priv(ndev);
|
|
fep = netdev_priv(ndev);
|
|
@@ -1215,18 +1216,29 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
|
|
if (bdp == txq->cur_tx)
|
|
if (bdp == txq->cur_tx)
|
|
break;
|
|
break;
|
|
|
|
|
|
- index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep);
|
|
|
|
-
|
|
|
|
|
|
+ bdp_t = bdp;
|
|
|
|
+ bdnum = 1;
|
|
|
|
+ index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep);
|
|
skb = txq->tx_skbuff[index];
|
|
skb = txq->tx_skbuff[index];
|
|
- txq->tx_skbuff[index] = NULL;
|
|
|
|
- if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
|
|
|
|
- dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
|
|
|
|
- bdp->cbd_datlen, DMA_TO_DEVICE);
|
|
|
|
- bdp->cbd_bufaddr = 0;
|
|
|
|
- if (!skb) {
|
|
|
|
- bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
|
|
|
|
- continue;
|
|
|
|
|
|
+ while (!skb) {
|
|
|
|
+ bdp_t = fec_enet_get_nextdesc(bdp_t, fep, queue_id);
|
|
|
|
+ index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep);
|
|
|
|
+ skb = txq->tx_skbuff[index];
|
|
|
|
+ bdnum++;
|
|
}
|
|
}
|
|
|
|
+ if (skb_shinfo(skb)->nr_frags &&
|
|
|
|
+ (status = bdp_t->cbd_sc) & BD_ENET_TX_READY)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < bdnum; i++) {
|
|
|
|
+ if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr))
|
|
|
|
+ dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
|
|
|
|
+ bdp->cbd_datlen, DMA_TO_DEVICE);
|
|
|
|
+ bdp->cbd_bufaddr = 0;
|
|
|
|
+ if (i < bdnum - 1)
|
|
|
|
+ bdp = fec_enet_get_nextdesc(bdp, fep, queue_id);
|
|
|
|
+ }
|
|
|
|
+ txq->tx_skbuff[index] = NULL;
|
|
|
|
|
|
/* Check for errors. */
|
|
/* Check for errors. */
|
|
if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
|
|
if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
|