1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
From 7b4062c1b950287f4b588a72edd520d050e92745 Mon Sep 17 00:00:00 2001
From: Robert Nelson <robertcnelson@gmail.com>
Date: Thu, 29 Sep 2011 11:54:12 -0500
Subject: [PATCH 13/14] ksz8851 add ks8851_tx_check
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
---
drivers/net/ethernet/micrel/ks8851.c | 36 +++++++++++++++++-----------------
1 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index e22ce5d..b72baa6 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -108,11 +108,13 @@ struct ks8851_net {
struct mii_if_info mii;
struct ks8851_rxctrl rxctrl;
+ struct work_struct tx_check;
struct work_struct tx_work;
struct work_struct irq_work;
struct work_struct rxctrl_work;
struct sk_buff_head txq;
+ int tx_len;
struct spi_message spi_msg1;
struct spi_message spi_msg2;
@@ -621,19 +623,6 @@ static void ks8851_irq_work(struct work_struct *work)
if (status & IRQ_RXPSI)
handled |= IRQ_RXPSI;
- if (status & IRQ_TXI) {
- handled |= IRQ_TXI;
-
- /* no lock here, tx queue should have been stopped */
-
- /* update our idea of how much tx space is available to the
- * system */
- ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
-
- netif_dbg(ks, intr, ks->netdev,
- "%s: txspace %d\n", __func__, ks->tx_space);
- }
-
if (status & IRQ_RXI)
handled |= IRQ_RXI;
@@ -674,9 +663,6 @@ static void ks8851_irq_work(struct work_struct *work)
mutex_unlock(&ks->lock);
- if (status & IRQ_TXI)
- netif_wake_queue(ks->netdev);
-
if (is_level_irq(ks->irq_flags))
enable_irq(ks->netdev->irq);
}
@@ -754,6 +740,17 @@ static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb)
dev_kfree_skb(txb);
}
+static void ks8851_tx_check(struct work_struct *work)
+{
+ struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_check);
+
+ ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
+ if (ks->tx_space > ks->tx_len)
+ netif_wake_queue(ks->netdev);
+ else
+ schedule_work(&ks->tx_check);
+}
+
/**
* ks8851_tx_work - process tx packet(s)
* @work: The work strucutre what was scheduled.
@@ -865,7 +862,6 @@ static int ks8851_net_open(struct net_device *dev)
/* clear then enable interrupts */
#define STD_IRQ (IRQ_LCI | /* Link Change */ \
- IRQ_TXI | /* TX done */ \
IRQ_RXI | /* RX done */ \
IRQ_SPIBEI | /* SPI bus error */ \
IRQ_TXPSI | /* TX process stop */ \
@@ -903,6 +899,7 @@ static int ks8851_net_stop(struct net_device *dev)
/* stop any outstanding work */
flush_work(&ks->irq_work);
+ flush_work(&ks->tx_check);
flush_work(&ks->tx_work);
flush_work(&ks->rxctrl_work);
@@ -960,14 +957,16 @@ static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb,
if (needed > ks->tx_space) {
netif_stop_queue(dev);
+ ks->tx_len = needed;
+ schedule_work(&ks->tx_check);
ret = NETDEV_TX_BUSY;
} else {
ks->tx_space -= needed;
skb_queue_tail(&ks->txq, skb);
+ schedule_work(&ks->tx_work);
}
spin_unlock(&ks->statelock);
- schedule_work(&ks->tx_work);
return ret;
}
@@ -1712,6 +1711,7 @@ static int __devinit ks8851_probe(struct spi_device *spi)
mutex_init(&ks->lock);
spin_lock_init(&ks->statelock);
+ INIT_WORK(&ks->tx_check, ks8851_tx_check);
INIT_WORK(&ks->tx_work, ks8851_tx_work);
INIT_WORK(&ks->irq_work, ks8851_irq_work);
INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work);
--
1.7.7.4
|