linux/drivers/uwb/reset.c
<<
>>
Prefs
   1/*
   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#include <linux/slab.h>
  34#include <linux/delay.h>
  35
  36#include "uwb-internal.h"
  37
  38/**
  39 * Command result codes (WUSB1.0[T8-69])
  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/** Return a string matching the given error code */
  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);     /* Protect against rc->priv being removed */
  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 * Generic function for issuing commands to the Radio Control Interface
 145 *
 146 * @rc:       UWB Radio Control descriptor
 147 * @cmd_name: Name of the command being issued (for error messages)
 148 * @cmd:      Pointer to rccb structure containing the command;
 149 *            normally you embed this structure as the first member of
 150 *            the full command structure.
 151 * @cmd_size: Size of the whole command buffer pointed to by @cmd.
 152 * @reply:    Pointer to where to store the reply
 153 * @reply_size: @reply's size
 154 * @expected_type: Expected type in the return event
 155 * @expected_event: Expected event code in the return event
 156 * @preply:   Here a pointer to where the event data is received will
 157 *            be stored. Once done with the data, free with kfree().
 158 *
 159 * This function is generic; it works for commands that return a fixed
 160 * and known size or for commands that return a variable amount of data.
 161 *
 162 * If a buffer is provided, that is used, although it could be chopped
 163 * to the maximum size of the buffer. If the buffer is NULL, then one
 164 * be allocated in *preply with the whole contents of the reply.
 165 *
 166 * @rc needs to be referenced
 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(&params.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, &params);
 186        if (result)
 187                return result;
 188
 189        wait_for_completion(&params.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 * Generic function for issuing commands to the Radio Control Interface
 205 *
 206 * @rc:       UWB Radio Control descriptor
 207 * @cmd_name: Name of the command being issued (for error messages)
 208 * @cmd:      Pointer to rccb structure containing the command;
 209 *            normally you embed this structure as the first member of
 210 *            the full command structure.
 211 * @cmd_size: Size of the whole command buffer pointed to by @cmd.
 212 * @reply:    Pointer to the beginning of the confirmation event
 213 *            buffer. Normally bigger than an 'struct hwarc_rceb'.
 214 *            You need to fill out reply->bEventType and reply->wEvent (in
 215 *            cpu order) as the function will use them to verify the
 216 *            confirmation event.
 217 * @reply_size: Size of the reply buffer
 218 *
 219 * The function checks that the length returned in the reply is at
 220 * least as big as @reply_size; if not, it will be deemed an error and
 221 * -EIO returned.
 222 *
 223 * @rc needs to be referenced
 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 * Generic function for issuing commands to the Radio Control
 249 * Interface that return an unknown amount of data
 250 *
 251 * @rc:       UWB Radio Control descriptor
 252 * @cmd_name: Name of the command being issued (for error messages)
 253 * @cmd:      Pointer to rccb structure containing the command;
 254 *            normally you embed this structure as the first member of
 255 *            the full command structure.
 256 * @cmd_size: Size of the whole command buffer pointed to by @cmd.
 257 * @expected_type: Expected type in the return event
 258 * @expected_event: Expected event code in the return event
 259 * @preply:   Here a pointer to where the event data is received will
 260 *            be stored. Once done with the data, free with kfree().
 261 *
 262 * The function checks that the length returned in the reply is at
 263 * least as big as a 'struct uwb_rceb *'; if not, it will be deemed an
 264 * error and -EIO returned.
 265 *
 266 * @rc needs to be referenced
 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 * Reset a UWB Host Controller (and all radio settings)
 281 *
 282 * @rc:      Host Controller descriptor
 283 * @returns: 0 if ok, < 0 errno code on error
 284 *
 285 * We put the command on kmalloc'ed memory as some arches cannot do
 286 * USB from the stack. The reply event is copied from an stage buffer,
 287 * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details.
 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        /* Nothing can be done except try the reset again. Wait a bit
 335           to avoid reset loops during probe() or remove(). */
 336        msleep(1000);
 337        uwb_rc_reset_all(rc);
 338        return ret;
 339}
 340
 341/**
 342 * uwb_rc_reset_all - request a reset of the radio controller and PALs
 343 * @rc: the radio controller of the hardware device to be reset.
 344 *
 345 * The full hardware reset of the radio controller and all the PALs
 346 * will be scheduled.
 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);     /* will be put by uwbd's uwbd_event_handle() */
 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