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#include <linux/kernel.h>
32#include <linux/err.h>
33#include <linux/slab.h>
34#include <linux/delay.h>
35
36#include "uwb-internal.h"
37
38
39
40
41static
42const char *__strerror[] = {
43 "success",
44 "failure",
45 "hardware failure",
46 "no more slots",
47 "beacon is too large",
48 "invalid parameter",
49 "unsupported power level",
50 "time out (wa) or invalid ie data (whci)",
51 "beacon size exceeded",
52 "cancelled",
53 "invalid state",
54 "invalid size",
55 "ack not received",
56 "no more asie notification",
57};
58
59
60
61const char *uwb_rc_strerror(unsigned code)
62{
63 if (code == 255)
64 return "time out";
65 if (code >= ARRAY_SIZE(__strerror))
66 return "unknown error";
67 return __strerror[code];
68}
69
70int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name,
71 struct uwb_rccb *cmd, size_t cmd_size,
72 u8 expected_type, u16 expected_event,
73 uwb_rc_cmd_cb_f cb, void *arg)
74{
75 struct device *dev = &rc->uwb_dev.dev;
76 struct uwb_rc_neh *neh;
77 int needtofree = 0;
78 int result;
79
80 uwb_dev_lock(&rc->uwb_dev);
81 if (rc->priv == NULL) {
82 uwb_dev_unlock(&rc->uwb_dev);
83 return -ESHUTDOWN;
84 }
85
86 if (rc->filter_cmd) {
87 needtofree = rc->filter_cmd(rc, &cmd, &cmd_size);
88 if (needtofree < 0 && needtofree != -ENOANO) {
89 dev_err(dev, "%s: filter error: %d\n",
90 cmd_name, needtofree);
91 uwb_dev_unlock(&rc->uwb_dev);
92 return needtofree;
93 }
94 }
95
96 neh = uwb_rc_neh_add(rc, cmd, expected_type, expected_event, cb, arg);
97 if (IS_ERR(neh)) {
98 result = PTR_ERR(neh);
99 goto out;
100 }
101
102 result = rc->cmd(rc, cmd, cmd_size);
103 uwb_dev_unlock(&rc->uwb_dev);
104 if (result < 0)
105 uwb_rc_neh_rm(rc, neh);
106 else
107 uwb_rc_neh_arm(rc, neh);
108 uwb_rc_neh_put(neh);
109out:
110 if (needtofree == 1)
111 kfree(cmd);
112 return result < 0 ? result : 0;
113}
114EXPORT_SYMBOL_GPL(uwb_rc_cmd_async);
115
116struct uwb_rc_cmd_done_params {
117 struct completion completion;
118 struct uwb_rceb *reply;
119 ssize_t reply_size;
120};
121
122static void uwb_rc_cmd_done(struct uwb_rc *rc, void *arg,
123 struct uwb_rceb *reply, ssize_t reply_size)
124{
125 struct uwb_rc_cmd_done_params *p = (struct uwb_rc_cmd_done_params *)arg;
126
127 if (reply_size > 0) {
128 if (p->reply)
129 reply_size = min(p->reply_size, reply_size);
130 else
131 p->reply = kmalloc(reply_size, GFP_ATOMIC);
132
133 if (p->reply)
134 memcpy(p->reply, reply, reply_size);
135 else
136 reply_size = -ENOMEM;
137 }
138 p->reply_size = reply_size;
139 complete(&p->completion);
140}
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168static
169ssize_t __uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name,
170 struct uwb_rccb *cmd, size_t cmd_size,
171 struct uwb_rceb *reply, size_t reply_size,
172 u8 expected_type, u16 expected_event,
173 struct uwb_rceb **preply)
174{
175 ssize_t result = 0;
176 struct device *dev = &rc->uwb_dev.dev;
177 struct uwb_rc_cmd_done_params params;
178
179 init_completion(¶ms.completion);
180 params.reply = reply;
181 params.reply_size = reply_size;
182
183 result = uwb_rc_cmd_async(rc, cmd_name, cmd, cmd_size,
184 expected_type, expected_event,
185 uwb_rc_cmd_done, ¶ms);
186 if (result)
187 return result;
188
189 wait_for_completion(¶ms.completion);
190
191 if (preply)
192 *preply = params.reply;
193
194 if (params.reply_size < 0)
195 dev_err(dev, "%s: confirmation event 0x%02x/%04x/%02x "
196 "reception failed: %d\n", cmd_name,
197 expected_type, expected_event, cmd->bCommandContext,
198 (int)params.reply_size);
199 return params.reply_size;
200}
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225ssize_t uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name,
226 struct uwb_rccb *cmd, size_t cmd_size,
227 struct uwb_rceb *reply, size_t reply_size)
228{
229 struct device *dev = &rc->uwb_dev.dev;
230 ssize_t result;
231
232 result = __uwb_rc_cmd(rc, cmd_name,
233 cmd, cmd_size, reply, reply_size,
234 reply->bEventType, reply->wEvent, NULL);
235
236 if (result > 0 && result < reply_size) {
237 dev_err(dev, "%s: not enough data returned for decoding reply "
238 "(%zu bytes received vs at least %zu needed)\n",
239 cmd_name, result, reply_size);
240 result = -EIO;
241 }
242 return result;
243}
244EXPORT_SYMBOL_GPL(uwb_rc_cmd);
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name,
269 struct uwb_rccb *cmd, size_t cmd_size,
270 u8 expected_type, u16 expected_event,
271 struct uwb_rceb **preply)
272{
273 return __uwb_rc_cmd(rc, cmd_name, cmd, cmd_size, NULL, 0,
274 expected_type, expected_event, preply);
275}
276EXPORT_SYMBOL_GPL(uwb_rc_vcmd);
277
278
279
280
281
282
283
284
285
286
287
288
289int uwb_rc_reset(struct uwb_rc *rc)
290{
291 int result = -ENOMEM;
292 struct uwb_rc_evt_confirm reply;
293 struct uwb_rccb *cmd;
294 size_t cmd_size = sizeof(*cmd);
295
296 mutex_lock(&rc->uwb_dev.mutex);
297 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
298 if (cmd == NULL)
299 goto error_kzalloc;
300 cmd->bCommandType = UWB_RC_CET_GENERAL;
301 cmd->wCommand = cpu_to_le16(UWB_RC_CMD_RESET);
302 reply.rceb.bEventType = UWB_RC_CET_GENERAL;
303 reply.rceb.wEvent = UWB_RC_CMD_RESET;
304 result = uwb_rc_cmd(rc, "RESET", cmd, cmd_size,
305 &reply.rceb, sizeof(reply));
306 if (result < 0)
307 goto error_cmd;
308 if (reply.bResultCode != UWB_RC_RES_SUCCESS) {
309 dev_err(&rc->uwb_dev.dev,
310 "RESET: command execution failed: %s (%d)\n",
311 uwb_rc_strerror(reply.bResultCode), reply.bResultCode);
312 result = -EIO;
313 }
314error_cmd:
315 kfree(cmd);
316error_kzalloc:
317 mutex_unlock(&rc->uwb_dev.mutex);
318 return result;
319}
320
321int uwbd_msg_handle_reset(struct uwb_event *evt)
322{
323 struct uwb_rc *rc = evt->rc;
324 int ret;
325
326 dev_info(&rc->uwb_dev.dev, "resetting radio controller\n");
327 ret = rc->reset(rc);
328 if (ret < 0) {
329 dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret);
330 goto error;
331 }
332 return 0;
333error:
334
335
336 msleep(1000);
337 uwb_rc_reset_all(rc);
338 return ret;
339}
340
341
342
343
344
345
346
347
348void uwb_rc_reset_all(struct uwb_rc *rc)
349{
350 struct uwb_event *evt;
351
352 evt = kzalloc(sizeof(struct uwb_event), GFP_ATOMIC);
353 if (unlikely(evt == NULL))
354 return;
355
356 evt->rc = __uwb_rc_get(rc);
357 evt->ts_jiffies = jiffies;
358 evt->type = UWB_EVT_TYPE_MSG;
359 evt->message = UWB_EVT_MSG_RESET;
360
361 uwbd_event_queue(evt);
362}
363EXPORT_SYMBOL_GPL(uwb_rc_reset_all);
364
365void uwb_rc_pre_reset(struct uwb_rc *rc)
366{
367 rc->stop(rc);
368 uwbd_flush(rc);
369
370 uwb_radio_reset_state(rc);
371 uwb_rsv_remove_all(rc);
372}
373EXPORT_SYMBOL_GPL(uwb_rc_pre_reset);
374
375int uwb_rc_post_reset(struct uwb_rc *rc)
376{
377 int ret;
378
379 ret = rc->start(rc);
380 if (ret)
381 goto out;
382 ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr);
383 if (ret)
384 goto out;
385 ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr);
386 if (ret)
387 goto out;
388out:
389 return ret;
390}
391EXPORT_SYMBOL_GPL(uwb_rc_post_reset);
392