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