blob: 70f8050221ff5efe5d0e733541f2465e63b41ee0 [file] [log] [blame]
Inaky Perez-Gonzalez0612edf2008-09-17 16:34:07 +01001/*
2 * Ultra Wide Band
3 * UWB basic command support and radio reset
4 *
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 *
23 * FIXME:
24 *
25 * - docs
26 *
27 * - Now we are serializing (using the uwb_dev->mutex) the command
28 * execution; it should be parallelized as much as possible some
29 * day.
30 */
31#include <linux/kernel.h>
32#include <linux/err.h>
33
34#include "uwb-internal.h"
Inaky Perez-Gonzalez0612edf2008-09-17 16:34:07 +010035
36/**
37 * Command result codes (WUSB1.0[T8-69])
38 */
39static
40const char *__strerror[] = {
41 "success",
42 "failure",
43 "hardware failure",
44 "no more slots",
45 "beacon is too large",
46 "invalid parameter",
47 "unsupported power level",
48 "time out (wa) or invalid ie data (whci)",
49 "beacon size exceeded",
50 "cancelled",
51 "invalid state",
52 "invalid size",
53 "ack not recieved",
54 "no more asie notification",
55};
56
57
58/** Return a string matching the given error code */
59const char *uwb_rc_strerror(unsigned code)
60{
61 if (code == 255)
62 return "time out";
63 if (code >= ARRAY_SIZE(__strerror))
64 return "unknown error";
65 return __strerror[code];
66}
67
68int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name,
69 struct uwb_rccb *cmd, size_t cmd_size,
70 u8 expected_type, u16 expected_event,
71 uwb_rc_cmd_cb_f cb, void *arg)
72{
73 struct device *dev = &rc->uwb_dev.dev;
74 struct uwb_rc_neh *neh;
75 int needtofree = 0;
76 int result;
77
78 uwb_dev_lock(&rc->uwb_dev); /* Protect against rc->priv being removed */
79 if (rc->priv == NULL) {
80 uwb_dev_unlock(&rc->uwb_dev);
81 return -ESHUTDOWN;
82 }
83
84 if (rc->filter_cmd) {
85 needtofree = rc->filter_cmd(rc, &cmd, &cmd_size);
86 if (needtofree < 0 && needtofree != -ENOANO) {
87 dev_err(dev, "%s: filter error: %d\n",
88 cmd_name, needtofree);
89 uwb_dev_unlock(&rc->uwb_dev);
90 return needtofree;
91 }
92 }
93
94 neh = uwb_rc_neh_add(rc, cmd, expected_type, expected_event, cb, arg);
95 if (IS_ERR(neh)) {
96 result = PTR_ERR(neh);
97 goto out;
98 }
99
100 result = rc->cmd(rc, cmd, cmd_size);
101 uwb_dev_unlock(&rc->uwb_dev);
102 if (result < 0)
103 uwb_rc_neh_rm(rc, neh);
104 else
105 uwb_rc_neh_arm(rc, neh);
106 uwb_rc_neh_put(neh);
107out:
108 if (needtofree == 1)
109 kfree(cmd);
110 return result < 0 ? result : 0;
111}
112EXPORT_SYMBOL_GPL(uwb_rc_cmd_async);
113
114struct uwb_rc_cmd_done_params {
115 struct completion completion;
116 struct uwb_rceb *reply;
117 ssize_t reply_size;
118};
119
120static void uwb_rc_cmd_done(struct uwb_rc *rc, void *arg,
121 struct uwb_rceb *reply, ssize_t reply_size)
122{
123 struct uwb_rc_cmd_done_params *p = (struct uwb_rc_cmd_done_params *)arg;
124
125 if (reply_size > 0) {
126 if (p->reply)
127 reply_size = min(p->reply_size, reply_size);
128 else
129 p->reply = kmalloc(reply_size, GFP_ATOMIC);
130
131 if (p->reply)
132 memcpy(p->reply, reply, reply_size);
133 else
134 reply_size = -ENOMEM;
135 }
136 p->reply_size = reply_size;
137 complete(&p->completion);
138}
139
140
141/**
142 * Generic function for issuing commands to the Radio Control Interface
143 *
144 * @rc: UWB Radio Control descriptor
145 * @cmd_name: Name of the command being issued (for error messages)
146 * @cmd: Pointer to rccb structure containing the command;
147 * normally you embed this structure as the first member of
148 * the full command structure.
149 * @cmd_size: Size of the whole command buffer pointed to by @cmd.
150 * @reply: Pointer to where to store the reply
151 * @reply_size: @reply's size
152 * @expected_type: Expected type in the return event
153 * @expected_event: Expected event code in the return event
154 * @preply: Here a pointer to where the event data is received will
155 * be stored. Once done with the data, free with kfree().
156 *
157 * This function is generic; it works for commands that return a fixed
158 * and known size or for commands that return a variable amount of data.
159 *
160 * If a buffer is provided, that is used, although it could be chopped
161 * to the maximum size of the buffer. If the buffer is NULL, then one
162 * be allocated in *preply with the whole contents of the reply.
163 *
164 * @rc needs to be referenced
165 */
166static
167ssize_t __uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name,
168 struct uwb_rccb *cmd, size_t cmd_size,
169 struct uwb_rceb *reply, size_t reply_size,
170 u8 expected_type, u16 expected_event,
171 struct uwb_rceb **preply)
172{
173 ssize_t result = 0;
174 struct device *dev = &rc->uwb_dev.dev;
175 struct uwb_rc_cmd_done_params params;
176
177 init_completion(&params.completion);
178 params.reply = reply;
179 params.reply_size = reply_size;
180
181 result = uwb_rc_cmd_async(rc, cmd_name, cmd, cmd_size,
182 expected_type, expected_event,
183 uwb_rc_cmd_done, &params);
184 if (result)
185 return result;
186
187 wait_for_completion(&params.completion);
188
189 if (preply)
190 *preply = params.reply;
191
192 if (params.reply_size < 0)
193 dev_err(dev, "%s: confirmation event 0x%02x/%04x/%02x "
194 "reception failed: %d\n", cmd_name,
195 expected_type, expected_event, cmd->bCommandContext,
196 (int)params.reply_size);
197 return params.reply_size;
198}
199
200
201/**
202 * Generic function for issuing commands to the Radio Control Interface
203 *
204 * @rc: UWB Radio Control descriptor
205 * @cmd_name: Name of the command being issued (for error messages)
206 * @cmd: Pointer to rccb structure containing the command;
207 * normally you embed this structure as the first member of
208 * the full command structure.
209 * @cmd_size: Size of the whole command buffer pointed to by @cmd.
210 * @reply: Pointer to the beginning of the confirmation event
211 * buffer. Normally bigger than an 'struct hwarc_rceb'.
212 * You need to fill out reply->bEventType and reply->wEvent (in
213 * cpu order) as the function will use them to verify the
214 * confirmation event.
215 * @reply_size: Size of the reply buffer
216 *
217 * The function checks that the length returned in the reply is at
218 * least as big as @reply_size; if not, it will be deemed an error and
219 * -EIO returned.
220 *
221 * @rc needs to be referenced
222 */
223ssize_t uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name,
224 struct uwb_rccb *cmd, size_t cmd_size,
225 struct uwb_rceb *reply, size_t reply_size)
226{
227 struct device *dev = &rc->uwb_dev.dev;
228 ssize_t result;
229
230 result = __uwb_rc_cmd(rc, cmd_name,
231 cmd, cmd_size, reply, reply_size,
232 reply->bEventType, reply->wEvent, NULL);
233
234 if (result > 0 && result < reply_size) {
235 dev_err(dev, "%s: not enough data returned for decoding reply "
236 "(%zu bytes received vs at least %zu needed)\n",
237 cmd_name, result, reply_size);
238 result = -EIO;
239 }
240 return result;
241}
242EXPORT_SYMBOL_GPL(uwb_rc_cmd);
243
244
245/**
246 * Generic function for issuing commands to the Radio Control
247 * Interface that return an unknown amount of data
248 *
249 * @rc: UWB Radio Control descriptor
250 * @cmd_name: Name of the command being issued (for error messages)
251 * @cmd: Pointer to rccb structure containing the command;
252 * normally you embed this structure as the first member of
253 * the full command structure.
254 * @cmd_size: Size of the whole command buffer pointed to by @cmd.
255 * @expected_type: Expected type in the return event
256 * @expected_event: Expected event code in the return event
257 * @preply: Here a pointer to where the event data is received will
258 * be stored. Once done with the data, free with kfree().
259 *
260 * The function checks that the length returned in the reply is at
261 * least as big as a 'struct uwb_rceb *'; if not, it will be deemed an
262 * error and -EIO returned.
263 *
264 * @rc needs to be referenced
265 */
266ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name,
267 struct uwb_rccb *cmd, size_t cmd_size,
268 u8 expected_type, u16 expected_event,
269 struct uwb_rceb **preply)
270{
271 return __uwb_rc_cmd(rc, cmd_name, cmd, cmd_size, NULL, 0,
272 expected_type, expected_event, preply);
273}
274EXPORT_SYMBOL_GPL(uwb_rc_vcmd);
275
276
277/**
278 * Reset a UWB Host Controller (and all radio settings)
279 *
280 * @rc: Host Controller descriptor
281 * @returns: 0 if ok, < 0 errno code on error
282 *
283 * We put the command on kmalloc'ed memory as some arches cannot do
284 * USB from the stack. The reply event is copied from an stage buffer,
285 * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details.
286 */
287int uwb_rc_reset(struct uwb_rc *rc)
288{
289 int result = -ENOMEM;
290 struct uwb_rc_evt_confirm reply;
291 struct uwb_rccb *cmd;
292 size_t cmd_size = sizeof(*cmd);
293
294 mutex_lock(&rc->uwb_dev.mutex);
295 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
296 if (cmd == NULL)
297 goto error_kzalloc;
298 cmd->bCommandType = UWB_RC_CET_GENERAL;
299 cmd->wCommand = cpu_to_le16(UWB_RC_CMD_RESET);
300 reply.rceb.bEventType = UWB_RC_CET_GENERAL;
301 reply.rceb.wEvent = UWB_RC_CMD_RESET;
302 result = uwb_rc_cmd(rc, "RESET", cmd, cmd_size,
303 &reply.rceb, sizeof(reply));
304 if (result < 0)
305 goto error_cmd;
306 if (reply.bResultCode != UWB_RC_RES_SUCCESS) {
307 dev_err(&rc->uwb_dev.dev,
308 "RESET: command execution failed: %s (%d)\n",
309 uwb_rc_strerror(reply.bResultCode), reply.bResultCode);
310 result = -EIO;
311 }
312error_cmd:
313 kfree(cmd);
314error_kzalloc:
315 mutex_unlock(&rc->uwb_dev.mutex);
316 return result;
317}
318
319int uwbd_msg_handle_reset(struct uwb_event *evt)
320{
321 struct uwb_rc *rc = evt->rc;
322 int ret;
323
Inaky Perez-Gonzalez0612edf2008-09-17 16:34:07 +0100324 dev_info(&rc->uwb_dev.dev, "resetting radio controller\n");
325 ret = rc->reset(rc);
David Vrabel307ba6d2008-11-07 17:37:33 +0000326 if (ret) {
Inaky Perez-Gonzalez0612edf2008-09-17 16:34:07 +0100327 dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret);
David Vrabel307ba6d2008-11-07 17:37:33 +0000328 goto error;
329 }
330 return 0;
331error:
332 /* Nothing can be done except try the reset again. */
333 uwb_rc_reset_all(rc);
Inaky Perez-Gonzalez0612edf2008-09-17 16:34:07 +0100334 return ret;
335}
336
337/**
338 * uwb_rc_reset_all - request a reset of the radio controller and PALs
339 * @rc: the radio controller of the hardware device to be reset.
340 *
341 * The full hardware reset of the radio controller and all the PALs
342 * will be scheduled.
343 */
344void uwb_rc_reset_all(struct uwb_rc *rc)
345{
346 struct uwb_event *evt;
347
348 evt = kzalloc(sizeof(struct uwb_event), GFP_ATOMIC);
349 if (unlikely(evt == NULL))
350 return;
351
352 evt->rc = __uwb_rc_get(rc); /* will be put by uwbd's uwbd_event_handle() */
353 evt->ts_jiffies = jiffies;
354 evt->type = UWB_EVT_TYPE_MSG;
355 evt->message = UWB_EVT_MSG_RESET;
356
357 uwbd_event_queue(evt);
358}
359EXPORT_SYMBOL_GPL(uwb_rc_reset_all);
David Vrabel307ba6d2008-11-07 17:37:33 +0000360
361void uwb_rc_pre_reset(struct uwb_rc *rc)
362{
363 rc->stop(rc);
364 uwbd_flush(rc);
365
David Vrabel6fae35f2008-11-17 15:53:42 +0000366 uwb_radio_reset_state(rc);
David Vrabel307ba6d2008-11-07 17:37:33 +0000367 uwb_rsv_remove_all(rc);
368}
369EXPORT_SYMBOL_GPL(uwb_rc_pre_reset);
370
371void uwb_rc_post_reset(struct uwb_rc *rc)
372{
373 int ret;
374
375 ret = rc->start(rc);
376 if (ret)
377 goto error;
378 ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr);
379 if (ret)
380 goto error;
381 ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr);
382 if (ret)
383 goto error;
384 return;
385error:
386 /* Nothing can be done except try the reset again. */
387 uwb_rc_reset_all(rc);
388}
389EXPORT_SYMBOL_GPL(uwb_rc_post_reset);