linux/drivers/uwb/wlp/wlp-lc.c
<<
>>
Prefs
   1/*
   2 * WiMedia Logical Link Control Protocol (WLP)
   3 *
   4 * Copyright (C) 2005-2006 Intel Corporation
   5 * Reinette Chatre <reinette.chatre@intel.com>
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License version
   9 * 2 as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19 * 02110-1301, USA.
  20 *
  21 *
  22 * FIXME: docs
  23 */
  24#include <linux/wlp.h>
  25
  26#include "wlp-internal.h"
  27
  28static
  29void wlp_neighbor_init(struct wlp_neighbor_e *neighbor)
  30{
  31        INIT_LIST_HEAD(&neighbor->wssid);
  32}
  33
  34/**
  35 * Create area for device information storage
  36 *
  37 * wlp->mutex must be held
  38 */
  39int __wlp_alloc_device_info(struct wlp *wlp)
  40{
  41        struct device *dev = &wlp->rc->uwb_dev.dev;
  42        BUG_ON(wlp->dev_info != NULL);
  43        wlp->dev_info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
  44        if (wlp->dev_info == NULL) {
  45                dev_err(dev, "WLP: Unable to allocate memory for "
  46                        "device information.\n");
  47                return -ENOMEM;
  48        }
  49        return 0;
  50}
  51
  52
  53/**
  54 * Fill in device information using function provided by driver
  55 *
  56 * wlp->mutex must be held
  57 */
  58static
  59void __wlp_fill_device_info(struct wlp *wlp)
  60{
  61        wlp->fill_device_info(wlp, wlp->dev_info);
  62}
  63
  64/**
  65 * Setup device information
  66 *
  67 * Allocate area for device information and populate it.
  68 *
  69 * wlp->mutex must be held
  70 */
  71int __wlp_setup_device_info(struct wlp *wlp)
  72{
  73        int result;
  74        struct device *dev = &wlp->rc->uwb_dev.dev;
  75
  76        result = __wlp_alloc_device_info(wlp);
  77        if (result < 0) {
  78                dev_err(dev, "WLP: Unable to allocate area for "
  79                        "device information.\n");
  80                return result;
  81        }
  82        __wlp_fill_device_info(wlp);
  83        return 0;
  84}
  85
  86/**
  87 * Remove information about neighbor stored temporarily
  88 *
  89 * Information learned during discovey should only be stored when the
  90 * device enrolls in the neighbor's WSS. We do need to store this
  91 * information temporarily in order to present it to the user.
  92 *
  93 * We are only interested in keeping neighbor WSS information if that
  94 * neighbor is accepting enrollment.
  95 *
  96 * should be called with wlp->nbmutex held
  97 */
  98void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor)
  99{
 100        struct wlp_wssid_e *wssid_e, *next;
 101        u8 keep;
 102        if (!list_empty(&neighbor->wssid)) {
 103                list_for_each_entry_safe(wssid_e, next, &neighbor->wssid,
 104                                         node) {
 105                        if (wssid_e->info != NULL) {
 106                                keep = wssid_e->info->accept_enroll;
 107                                kfree(wssid_e->info);
 108                                wssid_e->info = NULL;
 109                                if (!keep) {
 110                                        list_del(&wssid_e->node);
 111                                        kfree(wssid_e);
 112                                }
 113                        }
 114                }
 115        }
 116        if (neighbor->info != NULL) {
 117                kfree(neighbor->info);
 118                neighbor->info = NULL;
 119        }
 120}
 121
 122/*
 123 * Populate WLP neighborhood cache with neighbor information
 124 *
 125 * A new neighbor is found. If it is discoverable then we add it to the
 126 * neighborhood cache.
 127 *
 128 */
 129static
 130int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev)
 131{
 132        int result = 0;
 133        int discoverable;
 134        struct wlp_neighbor_e *neighbor;
 135
 136        /*
 137         * FIXME:
 138         * Use contents of WLP IE found in beacon cache to determine if
 139         * neighbor is discoverable.
 140         * The device does not support WLP IE yet so this still needs to be
 141         * done. Until then we assume all devices are discoverable.
 142         */
 143        discoverable = 1; /* will be changed when FIXME disappears */
 144        if (discoverable) {
 145                /* Add neighbor to cache for discovery */
 146                neighbor = kzalloc(sizeof(*neighbor), GFP_KERNEL);
 147                if (neighbor == NULL) {
 148                        dev_err(&dev->dev, "Unable to create memory for "
 149                                "new neighbor. \n");
 150                        result = -ENOMEM;
 151                        goto error_no_mem;
 152                }
 153                wlp_neighbor_init(neighbor);
 154                uwb_dev_get(dev);
 155                neighbor->uwb_dev = dev;
 156                list_add(&neighbor->node, &wlp->neighbors);
 157        }
 158error_no_mem:
 159        return result;
 160}
 161
 162/**
 163 * Remove one neighbor from cache
 164 */
 165static
 166void __wlp_neighbor_release(struct wlp_neighbor_e *neighbor)
 167{
 168        struct wlp_wssid_e *wssid_e, *next_wssid_e;
 169
 170        list_for_each_entry_safe(wssid_e, next_wssid_e,
 171                                 &neighbor->wssid, node) {
 172                list_del(&wssid_e->node);
 173                kfree(wssid_e);
 174        }
 175        uwb_dev_put(neighbor->uwb_dev);
 176        list_del(&neighbor->node);
 177        kfree(neighbor);
 178}
 179
 180/**
 181 * Clear entire neighborhood cache.
 182 */
 183static
 184void __wlp_neighbors_release(struct wlp *wlp)
 185{
 186        struct wlp_neighbor_e *neighbor, *next;
 187        if (list_empty(&wlp->neighbors))
 188                return;
 189        list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
 190                __wlp_neighbor_release(neighbor);
 191        }
 192}
 193
 194static
 195void wlp_neighbors_release(struct wlp *wlp)
 196{
 197        mutex_lock(&wlp->nbmutex);
 198        __wlp_neighbors_release(wlp);
 199        mutex_unlock(&wlp->nbmutex);
 200}
 201
 202
 203
 204/**
 205 * Send D1 message to neighbor, receive D2 message
 206 *
 207 * @neighbor: neighbor to which D1 message will be sent
 208 * @wss:      if not NULL, it is an enrollment request for this WSS
 209 * @wssid:    if wss not NULL, this is the wssid of the WSS in which we
 210 *            want to enroll
 211 *
 212 * A D1/D2 exchange is done for one of two reasons: discovery or
 213 * enrollment. If done for discovery the D1 message is sent to the neighbor
 214 * and the contents of the D2 response is stored in a temporary cache.
 215 * If done for enrollment the @wss and @wssid are provided also. In this
 216 * case the D1 message is sent to the neighbor, the D2 response is parsed
 217 * for enrollment of the WSS with wssid.
 218 *
 219 * &wss->mutex is held
 220 */
 221static
 222int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
 223                      struct wlp_wss *wss, struct wlp_uuid *wssid)
 224{
 225        int result;
 226        struct device *dev = &wlp->rc->uwb_dev.dev;
 227        DECLARE_COMPLETION_ONSTACK(completion);
 228        struct wlp_session session;
 229        struct sk_buff  *skb;
 230        struct wlp_frame_assoc *resp;
 231        struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
 232
 233        mutex_lock(&wlp->mutex);
 234        if (!wlp_uuid_is_set(&wlp->uuid)) {
 235                dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
 236                        "proceed.\n");
 237                result = -ENXIO;
 238                goto out;
 239        }
 240        /* Send D1 association frame */
 241        result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_D1);
 242        if (result < 0) {
 243                dev_err(dev, "Unable to send D1 frame to neighbor "
 244                        "%02x:%02x (%d)\n", dev_addr->data[1],
 245                        dev_addr->data[0], result);
 246                goto out;
 247        }
 248        /* Create session, wait for response */
 249        session.exp_message = WLP_ASSOC_D2;
 250        session.cb = wlp_session_cb;
 251        session.cb_priv = &completion;
 252        session.neighbor_addr = *dev_addr;
 253        BUG_ON(wlp->session != NULL);
 254        wlp->session = &session;
 255        /* Wait for D2/F0 frame */
 256        result = wait_for_completion_interruptible_timeout(&completion,
 257                                                   WLP_PER_MSG_TIMEOUT * HZ);
 258        if (result == 0) {
 259                result = -ETIMEDOUT;
 260                dev_err(dev, "Timeout while sending D1 to neighbor "
 261                             "%02x:%02x.\n", dev_addr->data[1],
 262                             dev_addr->data[0]);
 263                goto error_session;
 264        }
 265        if (result < 0) {
 266                dev_err(dev, "Unable to discover/enroll neighbor %02x:%02x.\n",
 267                        dev_addr->data[1], dev_addr->data[0]);
 268                goto error_session;
 269        }
 270        /* Parse message in session->data: it will be either D2 or F0 */
 271        skb = session.data;
 272        resp = (void *) skb->data;
 273
 274        if (resp->type == WLP_ASSOC_F0) {
 275                result = wlp_parse_f0(wlp, skb);
 276                if (result < 0)
 277                        dev_err(dev, "WLP: Unable to parse F0 from neighbor "
 278                                "%02x:%02x.\n", dev_addr->data[1],
 279                                dev_addr->data[0]);
 280                result = -EINVAL;
 281                goto error_resp_parse;
 282        }
 283        if (wss == NULL) {
 284                /* Discovery */
 285                result = wlp_parse_d2_frame_to_cache(wlp, skb, neighbor);
 286                if (result < 0) {
 287                        dev_err(dev, "WLP: Unable to parse D2 message from "
 288                                "neighbor %02x:%02x for discovery.\n",
 289                                dev_addr->data[1], dev_addr->data[0]);
 290                        goto error_resp_parse;
 291                }
 292        } else {
 293                /* Enrollment */
 294                result = wlp_parse_d2_frame_to_enroll(wss, skb, neighbor,
 295                                                      wssid);
 296                if (result < 0) {
 297                        dev_err(dev, "WLP: Unable to parse D2 message from "
 298                                "neighbor %02x:%02x for enrollment.\n",
 299                                dev_addr->data[1], dev_addr->data[0]);
 300                        goto error_resp_parse;
 301                }
 302        }
 303error_resp_parse:
 304        kfree_skb(skb);
 305error_session:
 306        wlp->session = NULL;
 307out:
 308        mutex_unlock(&wlp->mutex);
 309        return result;
 310}
 311
 312/**
 313 * Enroll into WSS of provided WSSID by using neighbor as registrar
 314 *
 315 * &wss->mutex is held
 316 */
 317int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
 318                        struct wlp_wss *wss, struct wlp_uuid *wssid)
 319{
 320        int result = 0;
 321        struct device *dev = &wlp->rc->uwb_dev.dev;
 322        char buf[WLP_WSS_UUID_STRSIZE];
 323        struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
 324
 325        wlp_wss_uuid_print(buf, sizeof(buf), wssid);
 326
 327        result =  wlp_d1d2_exchange(wlp, neighbor, wss, wssid);
 328        if (result < 0) {
 329                dev_err(dev, "WLP: D1/D2 message exchange for enrollment "
 330                        "failed. result = %d \n", result);
 331                goto out;
 332        }
 333        if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
 334                dev_err(dev, "WLP: Unable to enroll into WSS %s using "
 335                        "neighbor %02x:%02x. \n", buf,
 336                        dev_addr->data[1], dev_addr->data[0]);
 337                result = -EINVAL;
 338                goto out;
 339        }
 340        if (wss->secure_status == WLP_WSS_SECURE) {
 341                dev_err(dev, "FIXME: need to complete secure enrollment.\n");
 342                result = -EINVAL;
 343                goto error;
 344        } else {
 345                wss->state = WLP_WSS_STATE_ENROLLED;
 346                dev_dbg(dev, "WLP: Success Enrollment into unsecure WSS "
 347                        "%s using neighbor %02x:%02x. \n",
 348                        buf, dev_addr->data[1], dev_addr->data[0]);
 349        }
 350out:
 351        return result;
 352error:
 353        wlp_wss_reset(wss);
 354        return result;
 355}
 356
 357/**
 358 * Discover WSS information of neighbor's active WSS
 359 */
 360static
 361int wlp_discover_neighbor(struct wlp *wlp,
 362                          struct wlp_neighbor_e *neighbor)
 363{
 364        return wlp_d1d2_exchange(wlp, neighbor, NULL, NULL);
 365}
 366
 367
 368/**
 369 * Each neighbor in the neighborhood cache is discoverable. Discover it.
 370 *
 371 * Discovery is done through sending of D1 association frame and parsing
 372 * the D2 association frame response. Only wssid from D2 will be included
 373 * in neighbor cache, rest is just displayed to user and forgotten.
 374 *
 375 * The discovery is not done in parallel. This is simple and enables us to
 376 * maintain only one association context.
 377 *
 378 * The discovery of one neighbor does not affect the other, but if the
 379 * discovery of a neighbor fails it is removed from the neighborhood cache.
 380 */
 381static
 382int wlp_discover_all_neighbors(struct wlp *wlp)
 383{
 384        int result = 0;
 385        struct device *dev = &wlp->rc->uwb_dev.dev;
 386        struct wlp_neighbor_e *neighbor, *next;
 387
 388        list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
 389                result = wlp_discover_neighbor(wlp, neighbor);
 390                if (result < 0) {
 391                        dev_err(dev, "WLP: Unable to discover neighbor "
 392                                "%02x:%02x, removing from neighborhood. \n",
 393                                neighbor->uwb_dev->dev_addr.data[1],
 394                                neighbor->uwb_dev->dev_addr.data[0]);
 395                        __wlp_neighbor_release(neighbor);
 396                }
 397        }
 398        return result;
 399}
 400
 401static int wlp_add_neighbor_helper(struct device *dev, void *priv)
 402{
 403        struct wlp *wlp = priv;
 404        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
 405
 406        return wlp_add_neighbor(wlp, uwb_dev);
 407}
 408
 409/**
 410 * Discover WLP neighborhood
 411 *
 412 * Will send D1 association frame to all devices in beacon group that have
 413 * discoverable bit set in WLP IE. D2 frames will be received, information
 414 * displayed to user in @buf. Partial information (from D2 association
 415 * frame) will be cached to assist with future association
 416 * requests.
 417 *
 418 * The discovery of the WLP neighborhood is triggered by the user. This
 419 * should occur infrequently and we thus free current cache and re-allocate
 420 * memory if needed.
 421 *
 422 * If one neighbor fails during initial discovery (determining if it is a
 423 * neighbor or not), we fail all - note that interaction with neighbor has
 424 * not occured at this point so if a failure occurs we know something went wrong
 425 * locally. We thus undo everything.
 426 */
 427ssize_t wlp_discover(struct wlp *wlp)
 428{
 429        int result = 0;
 430        struct device *dev = &wlp->rc->uwb_dev.dev;
 431
 432        mutex_lock(&wlp->nbmutex);
 433        /* Clear current neighborhood cache. */
 434        __wlp_neighbors_release(wlp);
 435        /* Determine which devices in neighborhood. Repopulate cache. */
 436        result = uwb_dev_for_each(wlp->rc, wlp_add_neighbor_helper, wlp);
 437        if (result < 0) {
 438                /* May have partial neighbor information, release all. */
 439                __wlp_neighbors_release(wlp);
 440                goto error_dev_for_each;
 441        }
 442        /* Discover the properties of devices in neighborhood. */
 443        result = wlp_discover_all_neighbors(wlp);
 444        /* In case of failure we still print our partial results. */
 445        if (result < 0) {
 446                dev_err(dev, "Unable to fully discover neighborhood. \n");
 447                result = 0;
 448        }
 449error_dev_for_each:
 450        mutex_unlock(&wlp->nbmutex);
 451        return result;
 452}
 453
 454/**
 455 * Handle events from UWB stack
 456 *
 457 * We handle events conservatively. If a neighbor goes off the air we
 458 * remove it from the neighborhood. If an association process is in
 459 * progress this function will block waiting for the nbmutex to become
 460 * free. The association process will thus be allowed to complete before it
 461 * is removed.
 462 */
 463static
 464void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev,
 465                       enum uwb_notifs event)
 466{
 467        struct wlp *wlp = _wlp;
 468        struct device *dev = &wlp->rc->uwb_dev.dev;
 469        struct wlp_neighbor_e *neighbor, *next;
 470        int result;
 471        switch (event) {
 472        case UWB_NOTIF_ONAIR:
 473                result = wlp_eda_create_node(&wlp->eda,
 474                                             uwb_dev->mac_addr.data,
 475                                             &uwb_dev->dev_addr);
 476                if (result < 0)
 477                        dev_err(dev, "WLP: Unable to add new neighbor "
 478                                "%02x:%02x to EDA cache.\n",
 479                                uwb_dev->dev_addr.data[1],
 480                                uwb_dev->dev_addr.data[0]);
 481                break;
 482        case UWB_NOTIF_OFFAIR:
 483                wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr);
 484                mutex_lock(&wlp->nbmutex);
 485                list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
 486                        if (neighbor->uwb_dev == uwb_dev)
 487                                __wlp_neighbor_release(neighbor);
 488                }
 489                mutex_unlock(&wlp->nbmutex);
 490                break;
 491        default:
 492                dev_err(dev, "don't know how to handle event %d from uwb\n",
 493                                event);
 494        }
 495}
 496
 497static void wlp_channel_changed(struct uwb_pal *pal, int channel)
 498{
 499        struct wlp *wlp = container_of(pal, struct wlp, pal);
 500
 501        if (channel < 0)
 502                netif_carrier_off(wlp->ndev);
 503        else
 504                netif_carrier_on(wlp->ndev);
 505}
 506
 507int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev)
 508{
 509        int result;
 510
 511        BUG_ON(wlp->fill_device_info == NULL);
 512        BUG_ON(wlp->xmit_frame == NULL);
 513        BUG_ON(wlp->stop_queue == NULL);
 514        BUG_ON(wlp->start_queue == NULL);
 515
 516        wlp->rc = rc;
 517        wlp->ndev = ndev;
 518        wlp_eda_init(&wlp->eda);/* Set up address cache */
 519        wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb;
 520        wlp->uwb_notifs_handler.data = wlp;
 521        uwb_notifs_register(rc, &wlp->uwb_notifs_handler);
 522
 523        uwb_pal_init(&wlp->pal);
 524        wlp->pal.rc = rc;
 525        wlp->pal.channel_changed = wlp_channel_changed;
 526        result = uwb_pal_register(&wlp->pal);
 527        if (result < 0)
 528                uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
 529
 530        return result;
 531}
 532EXPORT_SYMBOL_GPL(wlp_setup);
 533
 534void wlp_remove(struct wlp *wlp)
 535{
 536        wlp_neighbors_release(wlp);
 537        uwb_pal_unregister(&wlp->pal);
 538        uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
 539        wlp_eda_release(&wlp->eda);
 540        mutex_lock(&wlp->mutex);
 541        if (wlp->dev_info != NULL)
 542                kfree(wlp->dev_info);
 543        mutex_unlock(&wlp->mutex);
 544        wlp->rc = NULL;
 545}
 546EXPORT_SYMBOL_GPL(wlp_remove);
 547
 548/**
 549 * wlp_reset_all - reset the WLP hardware
 550 * @wlp: the WLP device to reset.
 551 *
 552 * This schedules a full hardware reset of the WLP device.  The radio
 553 * controller and any other PALs will also be reset.
 554 */
 555void wlp_reset_all(struct wlp *wlp)
 556{
 557        uwb_rc_reset_all(wlp->rc);
 558}
 559EXPORT_SYMBOL_GPL(wlp_reset_all);
 560