diff options
Diffstat (limited to 'drivers/net/ethernet/moxa/moxart_ether.c')
-rw-r--r-- | drivers/net/ethernet/moxa/moxart_ether.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index 06c9f4100cb9..6ad44be08b33 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
26 | #include <linux/crc32.h> | 26 | #include <linux/crc32.h> |
27 | #include <linux/crc32c.h> | 27 | #include <linux/crc32c.h> |
28 | #include <linux/circ_buf.h> | ||
28 | 29 | ||
29 | #include "moxart_ether.h" | 30 | #include "moxart_ether.h" |
30 | 31 | ||
@@ -278,6 +279,13 @@ rx_next: | |||
278 | return rx; | 279 | return rx; |
279 | } | 280 | } |
280 | 281 | ||
282 | static int moxart_tx_queue_space(struct net_device *ndev) | ||
283 | { | ||
284 | struct moxart_mac_priv_t *priv = netdev_priv(ndev); | ||
285 | |||
286 | return CIRC_SPACE(priv->tx_head, priv->tx_tail, TX_DESC_NUM); | ||
287 | } | ||
288 | |||
281 | static void moxart_tx_finished(struct net_device *ndev) | 289 | static void moxart_tx_finished(struct net_device *ndev) |
282 | { | 290 | { |
283 | struct moxart_mac_priv_t *priv = netdev_priv(ndev); | 291 | struct moxart_mac_priv_t *priv = netdev_priv(ndev); |
@@ -297,6 +305,9 @@ static void moxart_tx_finished(struct net_device *ndev) | |||
297 | tx_tail = TX_NEXT(tx_tail); | 305 | tx_tail = TX_NEXT(tx_tail); |
298 | } | 306 | } |
299 | priv->tx_tail = tx_tail; | 307 | priv->tx_tail = tx_tail; |
308 | if (netif_queue_stopped(ndev) && | ||
309 | moxart_tx_queue_space(ndev) >= TX_WAKE_THRESHOLD) | ||
310 | netif_wake_queue(ndev); | ||
300 | } | 311 | } |
301 | 312 | ||
302 | static irqreturn_t moxart_mac_interrupt(int irq, void *dev_id) | 313 | static irqreturn_t moxart_mac_interrupt(int irq, void *dev_id) |
@@ -324,13 +335,18 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
324 | struct moxart_mac_priv_t *priv = netdev_priv(ndev); | 335 | struct moxart_mac_priv_t *priv = netdev_priv(ndev); |
325 | void *desc; | 336 | void *desc; |
326 | unsigned int len; | 337 | unsigned int len; |
327 | unsigned int tx_head = priv->tx_head; | 338 | unsigned int tx_head; |
328 | u32 txdes1; | 339 | u32 txdes1; |
329 | int ret = NETDEV_TX_BUSY; | 340 | int ret = NETDEV_TX_BUSY; |
330 | 341 | ||
342 | spin_lock_irq(&priv->txlock); | ||
343 | |||
344 | tx_head = priv->tx_head; | ||
331 | desc = priv->tx_desc_base + (TX_REG_DESC_SIZE * tx_head); | 345 | desc = priv->tx_desc_base + (TX_REG_DESC_SIZE * tx_head); |
332 | 346 | ||
333 | spin_lock_irq(&priv->txlock); | 347 | if (moxart_tx_queue_space(ndev) == 1) |
348 | netif_stop_queue(ndev); | ||
349 | |||
334 | if (moxart_desc_read(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) { | 350 | if (moxart_desc_read(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) { |
335 | net_dbg_ratelimited("no TX space for packet\n"); | 351 | net_dbg_ratelimited("no TX space for packet\n"); |
336 | priv->stats.tx_dropped++; | 352 | priv->stats.tx_dropped++; |