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#include "i2400m-usb.h"
72
73
74#define D_SUBMODULE tx
75#include "usb-debug-levels.h"
76
77
78
79
80
81
82
83
84
85
86static
87int i2400mu_tx(struct i2400mu *i2400mu, struct i2400m_msg_hdr *tx_msg,
88 size_t tx_msg_size)
89{
90 int result = 0;
91 struct i2400m *i2400m = &i2400mu->i2400m;
92 struct device *dev = &i2400mu->usb_iface->dev;
93 int usb_pipe, sent_size, do_autopm;
94 struct usb_endpoint_descriptor *epd;
95
96 d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
97 do_autopm = atomic_read(&i2400mu->do_autopm);
98 result = do_autopm ?
99 usb_autopm_get_interface(i2400mu->usb_iface) : 0;
100 if (result < 0) {
101 dev_err(dev, "TX: can't get autopm: %d\n", result);
102 do_autopm = 0;
103 }
104 epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT);
105 usb_pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
106retry:
107 result = usb_bulk_msg(i2400mu->usb_dev, usb_pipe,
108 tx_msg, tx_msg_size, &sent_size, HZ);
109 usb_mark_last_busy(i2400mu->usb_dev);
110 switch (result) {
111 case 0:
112 if (sent_size != tx_msg_size) {
113 dev_err(dev, "TX: short write (%d B vs %zu "
114 "expected)\n", sent_size, tx_msg_size);
115 result = -EIO;
116 }
117 break;
118 case -EINVAL:
119 case -ENODEV:
120 case -ENOENT:
121 case -ESHUTDOWN:
122 case -ECONNRESET:
123 result = -ESHUTDOWN;
124 break;
125 default:
126 if (edc_inc(&i2400mu->urb_edc,
127 EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
128 dev_err(dev, "TX: maximum errors in URB "
129 "exceeded; resetting device\n");
130 usb_queue_reset_device(i2400mu->usb_iface);
131 } else {
132 dev_err(dev, "TX: cannot send URB; retrying. "
133 "tx_msg @%zu %zu B [%d sent]: %d\n",
134 (void *) tx_msg - i2400m->tx_buf,
135 tx_msg_size, sent_size, result);
136 goto retry;
137 }
138 }
139 if (do_autopm)
140 usb_autopm_put_interface(i2400mu->usb_iface);
141 d_fnend(4, dev, "(i2400mu %p) = result\n", i2400mu);
142 return result;
143}
144
145
146
147
148
149
150
151
152
153
154
155static
156int i2400mu_txd(void *_i2400mu)
157{
158 int result = 0;
159 struct i2400mu *i2400mu = _i2400mu;
160 struct i2400m *i2400m = &i2400mu->i2400m;
161 struct device *dev = &i2400mu->usb_iface->dev;
162 struct i2400m_msg_hdr *tx_msg;
163 size_t tx_msg_size;
164
165 d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
166
167 while (1) {
168 d_printf(2, dev, "TX: waiting for messages\n");
169 tx_msg = NULL;
170 wait_event_interruptible(
171 i2400mu->tx_wq,
172 (kthread_should_stop()
173 || (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size)))
174 );
175 if (kthread_should_stop())
176 break;
177 WARN_ON(tx_msg == NULL);
178 d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
179 d_dump(5, dev, tx_msg, tx_msg_size);
180
181 i2400mu_tx(i2400mu, tx_msg, tx_msg_size);
182 i2400m_tx_msg_sent(i2400m);
183 if (result < 0)
184 break;
185 }
186 d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result);
187 return result;
188}
189
190
191
192
193
194
195
196
197
198
199void i2400mu_bus_tx_kick(struct i2400m *i2400m)
200{
201 struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
202 struct device *dev = &i2400mu->usb_iface->dev;
203
204 d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
205 wake_up_all(&i2400mu->tx_wq);
206 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
207}
208
209
210int i2400mu_tx_setup(struct i2400mu *i2400mu)
211{
212 int result = 0;
213 struct i2400m *i2400m = &i2400mu->i2400m;
214 struct device *dev = &i2400mu->usb_iface->dev;
215 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
216
217 i2400mu->tx_kthread = kthread_run(i2400mu_txd, i2400mu, "%s-tx",
218 wimax_dev->name);
219 if (IS_ERR(i2400mu->tx_kthread)) {
220 result = PTR_ERR(i2400mu->tx_kthread);
221 dev_err(dev, "TX: cannot start thread: %d\n", result);
222 }
223 return result;
224}
225
226void i2400mu_tx_release(struct i2400mu *i2400mu)
227{
228 kthread_stop(i2400mu->tx_kthread);
229}
230