1 --- a/drivers/net/ethernet/cavium/cns3xxx_eth.c
2 +++ b/drivers/net/ethernet/cavium/cns3xxx_eth.c
7 +#define TX_DESC_RESERVE 20
9 #define RX_POOL_ALLOC_SIZE (sizeof(struct rx_desc) * RX_DESCS)
10 #define TX_POOL_ALLOC_SIZE (sizeof(struct tx_desc) * TX_DESCS)
11 @@ -266,6 +267,7 @@ struct _tx_ring {
19 @@ -546,7 +548,34 @@ out:
20 rx_ring->alloc_index = i;
23 -static void clear_tx_desc(struct sw *sw)
24 +static void eth_check_num_used(struct _tx_ring *tx_ring)
29 + if (tx_ring->num_used >= TX_DESCS - TX_DESC_RESERVE)
32 + if (tx_ring->stopped == stop)
35 + tx_ring->stopped = stop;
36 + for (i = 0; i < 4; i++) {
37 + struct port *port = switch_port_tab[i];
38 + struct net_device *dev;
45 + netif_stop_queue(dev);
47 + netif_wake_queue(dev);
51 +static void eth_complete_tx(struct sw *sw)
53 struct _tx_ring *tx_ring = sw->tx_ring;
55 @@ -555,9 +584,6 @@ static void clear_tx_desc(struct sw *sw)
56 int num_used = tx_ring->num_used;
59 - if (num_used < (TX_DESCS >> 1))
62 index = tx_ring->free_index;
63 desc = &(tx_ring)->desc[index];
64 for (i = 0; i < num_used; i++) {
65 @@ -580,6 +606,7 @@ static void clear_tx_desc(struct sw *sw)
67 tx_ring->free_index = index;
68 tx_ring->num_used -= i;
69 + eth_check_num_used(tx_ring);
72 static int eth_poll(struct napi_struct *napi, int budget)
73 @@ -688,6 +715,10 @@ static int eth_poll(struct napi_struct *
77 + spin_lock_bh(&tx_lock);
78 + eth_complete_tx(sw);
79 + spin_unlock_bh(&tx_lock);
84 @@ -732,21 +763,19 @@ static int eth_xmit(struct sk_buff *skb,
85 skb_walk_frags(skb, skb1)
88 - spin_lock(&tx_lock);
89 + spin_lock_bh(&tx_lock);
91 + eth_complete_tx(sw);
92 if ((tx_ring->num_used + nr_desc + 1) >= TX_DESCS) {
94 - if ((tx_ring->num_used + nr_desc + 1) >= TX_DESCS) {
95 - spin_unlock(&tx_lock);
96 - return NETDEV_TX_BUSY;
98 + spin_unlock_bh(&tx_lock);
99 + return NETDEV_TX_BUSY;
102 index = index0 = tx_ring->cur_index;
103 index_last = (index0 + nr_desc) % TX_DESCS;
104 tx_ring->cur_index = (index_last + 1) % TX_DESCS;
106 - spin_unlock(&tx_lock);
107 + spin_unlock_bh(&tx_lock);
109 config0 = FORCE_ROUTE;
110 if (skb->ip_summed == CHECKSUM_PARTIAL)