linux/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010 Broadcom Corporation
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/etherdevice.h>
  19#include <linux/module.h>
  20#include <net/cfg80211.h>
  21#include <net/rtnetlink.h>
  22#include <brcmu_utils.h>
  23#include <brcmu_wifi.h>
  24
  25#include "dhd.h"
  26#include "dhd_bus.h"
  27#include "dhd_proto.h"
  28#include "dhd_dbg.h"
  29#include "fwil_types.h"
  30#include "p2p.h"
  31#include "wl_cfg80211.h"
  32#include "fwil.h"
  33#include "fwsignal.h"
  34
  35MODULE_AUTHOR("Broadcom Corporation");
  36MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
  37MODULE_LICENSE("Dual BSD/GPL");
  38
  39#define MAX_WAIT_FOR_8021X_TX           50      /* msecs */
  40
  41/* Error bits */
  42int brcmf_msg_level;
  43module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
  44MODULE_PARM_DESC(debug, "level of debug output");
  45
  46/* P2P0 enable */
  47static int brcmf_p2p_enable;
  48#ifdef CONFIG_BRCMDBG
  49module_param_named(p2pon, brcmf_p2p_enable, int, 0);
  50MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
  51#endif
  52
  53char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
  54{
  55        if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
  56                brcmf_err("ifidx %d out of range\n", ifidx);
  57                return "<if_bad>";
  58        }
  59
  60        if (drvr->iflist[ifidx] == NULL) {
  61                brcmf_err("null i/f %d\n", ifidx);
  62                return "<if_null>";
  63        }
  64
  65        if (drvr->iflist[ifidx]->ndev)
  66                return drvr->iflist[ifidx]->ndev->name;
  67
  68        return "<if_none>";
  69}
  70
  71static void _brcmf_set_multicast_list(struct work_struct *work)
  72{
  73        struct brcmf_if *ifp;
  74        struct net_device *ndev;
  75        struct netdev_hw_addr *ha;
  76        u32 cmd_value, cnt;
  77        __le32 cnt_le;
  78        char *buf, *bufp;
  79        u32 buflen;
  80        s32 err;
  81
  82        ifp = container_of(work, struct brcmf_if, multicast_work);
  83
  84        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
  85
  86        ndev = ifp->ndev;
  87
  88        /* Determine initial value of allmulti flag */
  89        cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
  90
  91        /* Send down the multicast list first. */
  92        cnt = netdev_mc_count(ndev);
  93        buflen = sizeof(cnt) + (cnt * ETH_ALEN);
  94        buf = kmalloc(buflen, GFP_ATOMIC);
  95        if (!buf)
  96                return;
  97        bufp = buf;
  98
  99        cnt_le = cpu_to_le32(cnt);
 100        memcpy(bufp, &cnt_le, sizeof(cnt_le));
 101        bufp += sizeof(cnt_le);
 102
 103        netdev_for_each_mc_addr(ha, ndev) {
 104                if (!cnt)
 105                        break;
 106                memcpy(bufp, ha->addr, ETH_ALEN);
 107                bufp += ETH_ALEN;
 108                cnt--;
 109        }
 110
 111        err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
 112        if (err < 0) {
 113                brcmf_err("Setting mcast_list failed, %d\n", err);
 114                cmd_value = cnt ? true : cmd_value;
 115        }
 116
 117        kfree(buf);
 118
 119        /*
 120         * Now send the allmulti setting.  This is based on the setting in the
 121         * net_device flags, but might be modified above to be turned on if we
 122         * were trying to set some addresses and dongle rejected it...
 123         */
 124        err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
 125        if (err < 0)
 126                brcmf_err("Setting allmulti failed, %d\n", err);
 127
 128        /*Finally, pick up the PROMISC flag */
 129        cmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
 130        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value);
 131        if (err < 0)
 132                brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
 133                          err);
 134}
 135
 136static void
 137_brcmf_set_mac_address(struct work_struct *work)
 138{
 139        struct brcmf_if *ifp;
 140        s32 err;
 141
 142        ifp = container_of(work, struct brcmf_if, setmacaddr_work);
 143
 144        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 145
 146        err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
 147                                       ETH_ALEN);
 148        if (err < 0) {
 149                brcmf_err("Setting cur_etheraddr failed, %d\n", err);
 150        } else {
 151                brcmf_dbg(TRACE, "MAC address updated to %pM\n",
 152                          ifp->mac_addr);
 153                memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
 154        }
 155}
 156
 157static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 158{
 159        struct brcmf_if *ifp = netdev_priv(ndev);
 160        struct sockaddr *sa = (struct sockaddr *)addr;
 161
 162        memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
 163        schedule_work(&ifp->setmacaddr_work);
 164        return 0;
 165}
 166
 167static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
 168{
 169        struct brcmf_if *ifp = netdev_priv(ndev);
 170
 171        schedule_work(&ifp->multicast_work);
 172}
 173
 174static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
 175                                           struct net_device *ndev)
 176{
 177        int ret;
 178        struct brcmf_if *ifp = netdev_priv(ndev);
 179        struct brcmf_pub *drvr = ifp->drvr;
 180        struct ethhdr *eh;
 181
 182        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 183
 184        /* Can the device send data? */
 185        if (drvr->bus_if->state != BRCMF_BUS_DATA) {
 186                brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
 187                netif_stop_queue(ndev);
 188                dev_kfree_skb(skb);
 189                ret = -ENODEV;
 190                goto done;
 191        }
 192
 193        if (!drvr->iflist[ifp->bssidx]) {
 194                brcmf_err("bad ifidx %d\n", ifp->bssidx);
 195                netif_stop_queue(ndev);
 196                dev_kfree_skb(skb);
 197                ret = -ENODEV;
 198                goto done;
 199        }
 200
 201        /* Make sure there's enough room for any header */
 202        if (skb_headroom(skb) < drvr->hdrlen) {
 203                struct sk_buff *skb2;
 204
 205                brcmf_dbg(INFO, "%s: insufficient headroom\n",
 206                          brcmf_ifname(drvr, ifp->bssidx));
 207                drvr->bus_if->tx_realloc++;
 208                skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
 209                dev_kfree_skb(skb);
 210                skb = skb2;
 211                if (skb == NULL) {
 212                        brcmf_err("%s: skb_realloc_headroom failed\n",
 213                                  brcmf_ifname(drvr, ifp->bssidx));
 214                        ret = -ENOMEM;
 215                        goto done;
 216                }
 217        }
 218
 219        /* validate length for ether packet */
 220        if (skb->len < sizeof(*eh)) {
 221                ret = -EINVAL;
 222                dev_kfree_skb(skb);
 223                goto done;
 224        }
 225
 226        ret = brcmf_fws_process_skb(ifp, skb);
 227
 228done:
 229        if (ret) {
 230                ifp->stats.tx_dropped++;
 231        } else {
 232                ifp->stats.tx_packets++;
 233                ifp->stats.tx_bytes += skb->len;
 234        }
 235
 236        /* Return ok: we always eat the packet */
 237        return NETDEV_TX_OK;
 238}
 239
 240void brcmf_txflowblock_if(struct brcmf_if *ifp,
 241                          enum brcmf_netif_stop_reason reason, bool state)
 242{
 243        if (!ifp)
 244                return;
 245
 246        brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
 247                  ifp->bssidx, ifp->netif_stop, reason, state);
 248        if (state) {
 249                if (!ifp->netif_stop)
 250                        netif_stop_queue(ifp->ndev);
 251                ifp->netif_stop |= reason;
 252        } else {
 253                ifp->netif_stop &= ~reason;
 254                if (!ifp->netif_stop)
 255                        netif_wake_queue(ifp->ndev);
 256        }
 257}
 258
 259void brcmf_txflowblock(struct device *dev, bool state)
 260{
 261        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 262        struct brcmf_pub *drvr = bus_if->drvr;
 263        int i;
 264
 265        brcmf_dbg(TRACE, "Enter\n");
 266
 267        for (i = 0; i < BRCMF_MAX_IFS; i++)
 268                brcmf_txflowblock_if(drvr->iflist[i],
 269                                     BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state);
 270}
 271
 272void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
 273{
 274        unsigned char *eth;
 275        uint len;
 276        struct sk_buff *skb, *pnext;
 277        struct brcmf_if *ifp;
 278        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 279        struct brcmf_pub *drvr = bus_if->drvr;
 280        u8 ifidx;
 281        int ret;
 282
 283        brcmf_dbg(TRACE, "Enter\n");
 284
 285        skb_queue_walk_safe(skb_list, skb, pnext) {
 286                skb_unlink(skb, skb_list);
 287
 288                /* process and remove protocol-specific header */
 289                ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb);
 290                ifp = drvr->iflist[ifidx];
 291
 292                if (ret || !ifp || !ifp->ndev) {
 293                        if ((ret != -ENODATA) && ifp)
 294                                ifp->stats.rx_errors++;
 295                        brcmu_pkt_buf_free_skb(skb);
 296                        continue;
 297                }
 298
 299                /* Get the protocol, maintain skb around eth_type_trans()
 300                 * The main reason for this hack is for the limitation of
 301                 * Linux 2.4 where 'eth_type_trans' uses the
 302                 * 'net->hard_header_len'
 303                 * to perform skb_pull inside vs ETH_HLEN. Since to avoid
 304                 * coping of the packet coming from the network stack to add
 305                 * BDC, Hardware header etc, during network interface
 306                 * registration
 307                 * we set the 'net->hard_header_len' to ETH_HLEN + extra space
 308                 * required
 309                 * for BDC, Hardware header etc. and not just the ETH_HLEN
 310                 */
 311                eth = skb->data;
 312                len = skb->len;
 313
 314                skb->dev = ifp->ndev;
 315                skb->protocol = eth_type_trans(skb, skb->dev);
 316
 317                if (skb->pkt_type == PACKET_MULTICAST)
 318                        ifp->stats.multicast++;
 319
 320                skb->data = eth;
 321                skb->len = len;
 322
 323                /* Strip header, count, deliver upward */
 324                skb_pull(skb, ETH_HLEN);
 325
 326                /* Process special event packets */
 327                brcmf_fweh_process_skb(drvr, skb);
 328
 329                if (!(ifp->ndev->flags & IFF_UP)) {
 330                        brcmu_pkt_buf_free_skb(skb);
 331                        continue;
 332                }
 333
 334                ifp->stats.rx_bytes += skb->len;
 335                ifp->stats.rx_packets++;
 336
 337                if (in_interrupt())
 338                        netif_rx(skb);
 339                else
 340                        /* If the receive is not processed inside an ISR,
 341                         * the softirqd must be woken explicitly to service
 342                         * the NET_RX_SOFTIRQ.  In 2.6 kernels, this is handled
 343                         * by netif_rx_ni(), but in earlier kernels, we need
 344                         * to do it manually.
 345                         */
 346                        netif_rx_ni(skb);
 347        }
 348}
 349
 350void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
 351                      bool success)
 352{
 353        struct brcmf_if *ifp;
 354        struct ethhdr *eh;
 355        u8 ifidx;
 356        u16 type;
 357        int res;
 358
 359        res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
 360
 361        ifp = drvr->iflist[ifidx];
 362        if (!ifp)
 363                goto done;
 364
 365        if (res == 0) {
 366                eh = (struct ethhdr *)(txp->data);
 367                type = ntohs(eh->h_proto);
 368
 369                if (type == ETH_P_PAE) {
 370                        atomic_dec(&ifp->pend_8021x_cnt);
 371                        if (waitqueue_active(&ifp->pend_8021x_wait))
 372                                wake_up(&ifp->pend_8021x_wait);
 373                }
 374        }
 375        if (!success)
 376                ifp->stats.tx_errors++;
 377done:
 378        brcmu_pkt_buf_free_skb(txp);
 379}
 380
 381void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
 382{
 383        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 384        struct brcmf_pub *drvr = bus_if->drvr;
 385
 386        /* await txstatus signal for firmware if active */
 387        if (brcmf_fws_fc_active(drvr->fws)) {
 388                if (!success)
 389                        brcmf_fws_bustxfail(drvr->fws, txp);
 390        } else {
 391                brcmf_txfinalize(drvr, txp, success);
 392        }
 393}
 394
 395static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
 396{
 397        struct brcmf_if *ifp = netdev_priv(ndev);
 398
 399        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 400
 401        return &ifp->stats;
 402}
 403
 404/*
 405 * Set current toe component enables in toe_ol iovar,
 406 * and set toe global enable iovar
 407 */
 408static int brcmf_toe_set(struct brcmf_if *ifp, u32 toe_ol)
 409{
 410        s32 err;
 411
 412        err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
 413        if (err < 0) {
 414                brcmf_err("Setting toe_ol failed, %d\n", err);
 415                return err;
 416        }
 417
 418        err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
 419        if (err < 0)
 420                brcmf_err("Setting toe failed, %d\n", err);
 421
 422        return err;
 423
 424}
 425
 426static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
 427                                    struct ethtool_drvinfo *info)
 428{
 429        struct brcmf_if *ifp = netdev_priv(ndev);
 430        struct brcmf_pub *drvr = ifp->drvr;
 431
 432        strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 433        snprintf(info->version, sizeof(info->version), "%lu",
 434                 drvr->drv_version);
 435        strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
 436                sizeof(info->bus_info));
 437}
 438
 439static const struct ethtool_ops brcmf_ethtool_ops = {
 440        .get_drvinfo = brcmf_ethtool_get_drvinfo,
 441};
 442
 443static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
 444{
 445        struct brcmf_pub *drvr = ifp->drvr;
 446        struct ethtool_drvinfo info;
 447        char drvname[sizeof(info.driver)];
 448        u32 cmd;
 449        struct ethtool_value edata;
 450        u32 toe_cmpnt, csum_dir;
 451        int ret;
 452
 453        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 454
 455        /* all ethtool calls start with a cmd word */
 456        if (copy_from_user(&cmd, uaddr, sizeof(u32)))
 457                return -EFAULT;
 458
 459        switch (cmd) {
 460        case ETHTOOL_GDRVINFO:
 461                /* Copy out any request driver name */
 462                if (copy_from_user(&info, uaddr, sizeof(info)))
 463                        return -EFAULT;
 464                strncpy(drvname, info.driver, sizeof(info.driver));
 465                drvname[sizeof(info.driver) - 1] = '\0';
 466
 467                /* clear struct for return */
 468                memset(&info, 0, sizeof(info));
 469                info.cmd = cmd;
 470
 471                /* if requested, identify ourselves */
 472                if (strcmp(drvname, "?dhd") == 0) {
 473                        sprintf(info.driver, "dhd");
 474                        strcpy(info.version, BRCMF_VERSION_STR);
 475                }
 476                /* report dongle driver type */
 477                else
 478                        sprintf(info.driver, "wl");
 479
 480                sprintf(info.version, "%lu", drvr->drv_version);
 481                if (copy_to_user(uaddr, &info, sizeof(info)))
 482                        return -EFAULT;
 483                brcmf_dbg(TRACE, "given %*s, returning %s\n",
 484                          (int)sizeof(drvname), drvname, info.driver);
 485                break;
 486
 487                /* Get toe offload components from dongle */
 488        case ETHTOOL_GRXCSUM:
 489        case ETHTOOL_GTXCSUM:
 490                ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
 491                if (ret < 0)
 492                        return ret;
 493
 494                csum_dir =
 495                    (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
 496
 497                edata.cmd = cmd;
 498                edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
 499
 500                if (copy_to_user(uaddr, &edata, sizeof(edata)))
 501                        return -EFAULT;
 502                break;
 503
 504                /* Set toe offload components in dongle */
 505        case ETHTOOL_SRXCSUM:
 506        case ETHTOOL_STXCSUM:
 507                if (copy_from_user(&edata, uaddr, sizeof(edata)))
 508                        return -EFAULT;
 509
 510                /* Read the current settings, update and write back */
 511                ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
 512                if (ret < 0)
 513                        return ret;
 514
 515                csum_dir =
 516                    (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
 517
 518                if (edata.data != 0)
 519                        toe_cmpnt |= csum_dir;
 520                else
 521                        toe_cmpnt &= ~csum_dir;
 522
 523                ret = brcmf_toe_set(ifp, toe_cmpnt);
 524                if (ret < 0)
 525                        return ret;
 526
 527                /* If setting TX checksum mode, tell Linux the new mode */
 528                if (cmd == ETHTOOL_STXCSUM) {
 529                        if (edata.data)
 530                                ifp->ndev->features |= NETIF_F_IP_CSUM;
 531                        else
 532                                ifp->ndev->features &= ~NETIF_F_IP_CSUM;
 533                }
 534
 535                break;
 536
 537        default:
 538                return -EOPNOTSUPP;
 539        }
 540
 541        return 0;
 542}
 543
 544static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
 545                                    int cmd)
 546{
 547        struct brcmf_if *ifp = netdev_priv(ndev);
 548        struct brcmf_pub *drvr = ifp->drvr;
 549
 550        brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd);
 551
 552        if (!drvr->iflist[ifp->bssidx])
 553                return -1;
 554
 555        if (cmd == SIOCETHTOOL)
 556                return brcmf_ethtool(ifp, ifr->ifr_data);
 557
 558        return -EOPNOTSUPP;
 559}
 560
 561static int brcmf_netdev_stop(struct net_device *ndev)
 562{
 563        struct brcmf_if *ifp = netdev_priv(ndev);
 564
 565        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 566
 567        brcmf_cfg80211_down(ndev);
 568
 569        /* Set state and stop OS transmissions */
 570        netif_stop_queue(ndev);
 571
 572        return 0;
 573}
 574
 575static int brcmf_netdev_open(struct net_device *ndev)
 576{
 577        struct brcmf_if *ifp = netdev_priv(ndev);
 578        struct brcmf_pub *drvr = ifp->drvr;
 579        struct brcmf_bus *bus_if = drvr->bus_if;
 580        u32 toe_ol;
 581        s32 ret = 0;
 582
 583        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 584
 585        /* If bus is not ready, can't continue */
 586        if (bus_if->state != BRCMF_BUS_DATA) {
 587                brcmf_err("failed bus is not ready\n");
 588                return -EAGAIN;
 589        }
 590
 591        atomic_set(&ifp->pend_8021x_cnt, 0);
 592
 593        /* Get current TOE mode from dongle */
 594        if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
 595            && (toe_ol & TOE_TX_CSUM_OL) != 0)
 596                ndev->features |= NETIF_F_IP_CSUM;
 597        else
 598                ndev->features &= ~NETIF_F_IP_CSUM;
 599
 600        /* Allow transmit calls */
 601        netif_start_queue(ndev);
 602        if (brcmf_cfg80211_up(ndev)) {
 603                brcmf_err("failed to bring up cfg80211\n");
 604                return -1;
 605        }
 606
 607        return ret;
 608}
 609
 610static const struct net_device_ops brcmf_netdev_ops_pri = {
 611        .ndo_open = brcmf_netdev_open,
 612        .ndo_stop = brcmf_netdev_stop,
 613        .ndo_get_stats = brcmf_netdev_get_stats,
 614        .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
 615        .ndo_start_xmit = brcmf_netdev_start_xmit,
 616        .ndo_set_mac_address = brcmf_netdev_set_mac_address,
 617        .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
 618};
 619
 620int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
 621{
 622        struct brcmf_pub *drvr = ifp->drvr;
 623        struct net_device *ndev;
 624        s32 err;
 625
 626        brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
 627                  ifp->mac_addr);
 628        ndev = ifp->ndev;
 629
 630        /* set appropriate operations */
 631        ndev->netdev_ops = &brcmf_netdev_ops_pri;
 632
 633        ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
 634        ndev->ethtool_ops = &brcmf_ethtool_ops;
 635
 636        drvr->rxsz = ndev->mtu + ndev->hard_header_len +
 637                              drvr->hdrlen;
 638
 639        /* set the mac address */
 640        memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
 641
 642        INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
 643        INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
 644
 645        if (rtnl_locked)
 646                err = register_netdevice(ndev);
 647        else
 648                err = register_netdev(ndev);
 649        if (err != 0) {
 650                brcmf_err("couldn't register the net device\n");
 651                goto fail;
 652        }
 653
 654        brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
 655
 656        ndev->destructor = free_netdev;
 657        return 0;
 658
 659fail:
 660        drvr->iflist[ifp->bssidx] = NULL;
 661        ndev->netdev_ops = NULL;
 662        free_netdev(ndev);
 663        return -EBADE;
 664}
 665
 666static int brcmf_net_p2p_open(struct net_device *ndev)
 667{
 668        brcmf_dbg(TRACE, "Enter\n");
 669
 670        return brcmf_cfg80211_up(ndev);
 671}
 672
 673static int brcmf_net_p2p_stop(struct net_device *ndev)
 674{
 675        brcmf_dbg(TRACE, "Enter\n");
 676
 677        return brcmf_cfg80211_down(ndev);
 678}
 679
 680static int brcmf_net_p2p_do_ioctl(struct net_device *ndev,
 681                                  struct ifreq *ifr, int cmd)
 682{
 683        brcmf_dbg(TRACE, "Enter\n");
 684        return 0;
 685}
 686
 687static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
 688                                            struct net_device *ndev)
 689{
 690        if (skb)
 691                dev_kfree_skb_any(skb);
 692
 693        return NETDEV_TX_OK;
 694}
 695
 696static const struct net_device_ops brcmf_netdev_ops_p2p = {
 697        .ndo_open = brcmf_net_p2p_open,
 698        .ndo_stop = brcmf_net_p2p_stop,
 699        .ndo_do_ioctl = brcmf_net_p2p_do_ioctl,
 700        .ndo_start_xmit = brcmf_net_p2p_start_xmit
 701};
 702
 703static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
 704{
 705        struct net_device *ndev;
 706
 707        brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
 708                  ifp->mac_addr);
 709        ndev = ifp->ndev;
 710
 711        ndev->netdev_ops = &brcmf_netdev_ops_p2p;
 712
 713        /* set the mac address */
 714        memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
 715
 716        if (register_netdev(ndev) != 0) {
 717                brcmf_err("couldn't register the p2p net device\n");
 718                goto fail;
 719        }
 720
 721        brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
 722
 723        return 0;
 724
 725fail:
 726        ifp->drvr->iflist[ifp->bssidx] = NULL;
 727        ndev->netdev_ops = NULL;
 728        free_netdev(ndev);
 729        return -EBADE;
 730}
 731
 732struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
 733                              char *name, u8 *mac_addr)
 734{
 735        struct brcmf_if *ifp;
 736        struct net_device *ndev;
 737
 738        brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx);
 739
 740        ifp = drvr->iflist[bssidx];
 741        /*
 742         * Delete the existing interface before overwriting it
 743         * in case we missed the BRCMF_E_IF_DEL event.
 744         */
 745        if (ifp) {
 746                brcmf_err("ERROR: netdev:%s already exists\n",
 747                          ifp->ndev->name);
 748                if (ifidx) {
 749                        netif_stop_queue(ifp->ndev);
 750                        unregister_netdev(ifp->ndev);
 751                        free_netdev(ifp->ndev);
 752                        drvr->iflist[bssidx] = NULL;
 753                } else {
 754                        brcmf_err("ignore IF event\n");
 755                        return ERR_PTR(-EINVAL);
 756                }
 757        }
 758
 759        if (!brcmf_p2p_enable && bssidx == 1) {
 760                /* this is P2P_DEVICE interface */
 761                brcmf_dbg(INFO, "allocate non-netdev interface\n");
 762                ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
 763                if (!ifp)
 764                        return ERR_PTR(-ENOMEM);
 765        } else {
 766                brcmf_dbg(INFO, "allocate netdev interface\n");
 767                /* Allocate netdev, including space for private structure */
 768                ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
 769                if (!ndev)
 770                        return ERR_PTR(-ENOMEM);
 771
 772                ifp = netdev_priv(ndev);
 773                ifp->ndev = ndev;
 774        }
 775
 776        ifp->drvr = drvr;
 777        drvr->iflist[bssidx] = ifp;
 778        ifp->ifidx = ifidx;
 779        ifp->bssidx = bssidx;
 780
 781        init_waitqueue_head(&ifp->pend_8021x_wait);
 782
 783        if (mac_addr != NULL)
 784                memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
 785
 786        brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
 787                  current->pid, name, ifp->mac_addr);
 788
 789        return ifp;
 790}
 791
 792void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
 793{
 794        struct brcmf_if *ifp;
 795
 796        ifp = drvr->iflist[bssidx];
 797        drvr->iflist[bssidx] = NULL;
 798        if (!ifp) {
 799                brcmf_err("Null interface, idx=%d\n", bssidx);
 800                return;
 801        }
 802        brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
 803        if (ifp->ndev) {
 804                if (bssidx == 0) {
 805                        if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
 806                                rtnl_lock();
 807                                brcmf_netdev_stop(ifp->ndev);
 808                                rtnl_unlock();
 809                        }
 810                } else {
 811                        netif_stop_queue(ifp->ndev);
 812                }
 813
 814                if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
 815                        cancel_work_sync(&ifp->setmacaddr_work);
 816                        cancel_work_sync(&ifp->multicast_work);
 817                }
 818                /* unregister will take care of freeing it */
 819                unregister_netdev(ifp->ndev);
 820                if (bssidx == 0)
 821                        brcmf_cfg80211_detach(drvr->config);
 822        } else {
 823                kfree(ifp);
 824        }
 825}
 826
 827int brcmf_attach(uint bus_hdrlen, struct device *dev)
 828{
 829        struct brcmf_pub *drvr = NULL;
 830        int ret = 0;
 831
 832        brcmf_dbg(TRACE, "Enter\n");
 833
 834        /* Allocate primary brcmf_info */
 835        drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
 836        if (!drvr)
 837                return -ENOMEM;
 838
 839        mutex_init(&drvr->proto_block);
 840
 841        /* Link to bus module */
 842        drvr->hdrlen = bus_hdrlen;
 843        drvr->bus_if = dev_get_drvdata(dev);
 844        drvr->bus_if->drvr = drvr;
 845
 846        /* create device debugfs folder */
 847        brcmf_debugfs_attach(drvr);
 848
 849        /* Attach and link in the protocol */
 850        ret = brcmf_proto_attach(drvr);
 851        if (ret != 0) {
 852                brcmf_err("brcmf_prot_attach failed\n");
 853                goto fail;
 854        }
 855
 856        /* attach firmware event handler */
 857        brcmf_fweh_attach(drvr);
 858
 859        INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
 860
 861        return ret;
 862
 863fail:
 864        brcmf_detach(dev);
 865
 866        return ret;
 867}
 868
 869int brcmf_bus_start(struct device *dev)
 870{
 871        int ret = -1;
 872        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 873        struct brcmf_pub *drvr = bus_if->drvr;
 874        struct brcmf_if *ifp;
 875        struct brcmf_if *p2p_ifp;
 876
 877        brcmf_dbg(TRACE, "\n");
 878
 879        /* Bring up the bus */
 880        ret = brcmf_bus_init(bus_if);
 881        if (ret != 0) {
 882                brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
 883                return ret;
 884        }
 885
 886        /* add primary networking interface */
 887        ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
 888        if (IS_ERR(ifp))
 889                return PTR_ERR(ifp);
 890
 891        if (brcmf_p2p_enable)
 892                p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
 893        else
 894                p2p_ifp = NULL;
 895        if (IS_ERR(p2p_ifp))
 896                p2p_ifp = NULL;
 897
 898        /* signal bus ready */
 899        bus_if->state = BRCMF_BUS_DATA;
 900
 901        /* Bus is ready, do any initialization */
 902        ret = brcmf_c_preinit_dcmds(ifp);
 903        if (ret < 0)
 904                goto fail;
 905
 906        drvr->fw_signals = true;
 907        ret = brcmf_fws_init(drvr);
 908        if (ret < 0)
 909                goto fail;
 910
 911        brcmf_fws_add_interface(ifp);
 912
 913        drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
 914        if (drvr->config == NULL) {
 915                ret = -ENOMEM;
 916                goto fail;
 917        }
 918
 919        ret = brcmf_fweh_activate_events(ifp);
 920        if (ret < 0)
 921                goto fail;
 922
 923        ret = brcmf_net_attach(ifp, false);
 924fail:
 925        if (ret < 0) {
 926                brcmf_err("failed: %d\n", ret);
 927                if (drvr->config)
 928                        brcmf_cfg80211_detach(drvr->config);
 929                if (drvr->fws) {
 930                        brcmf_fws_del_interface(ifp);
 931                        brcmf_fws_deinit(drvr);
 932                }
 933                if (drvr->iflist[0]) {
 934                        free_netdev(ifp->ndev);
 935                        drvr->iflist[0] = NULL;
 936                }
 937                if (p2p_ifp) {
 938                        free_netdev(p2p_ifp->ndev);
 939                        drvr->iflist[1] = NULL;
 940                }
 941                return ret;
 942        }
 943        if ((brcmf_p2p_enable) && (p2p_ifp))
 944                if (brcmf_net_p2p_attach(p2p_ifp) < 0)
 945                        brcmf_p2p_enable = 0;
 946
 947        return 0;
 948}
 949
 950static void brcmf_bus_detach(struct brcmf_pub *drvr)
 951{
 952        brcmf_dbg(TRACE, "Enter\n");
 953
 954        if (drvr) {
 955                /* Stop the protocol module */
 956                brcmf_proto_stop(drvr);
 957
 958                /* Stop the bus module */
 959                brcmf_bus_stop(drvr->bus_if);
 960        }
 961}
 962
 963void brcmf_dev_reset(struct device *dev)
 964{
 965        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 966        struct brcmf_pub *drvr = bus_if->drvr;
 967
 968        if (drvr == NULL)
 969                return;
 970
 971        if (drvr->iflist[0])
 972                brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
 973}
 974
 975void brcmf_detach(struct device *dev)
 976{
 977        s32 i;
 978        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 979        struct brcmf_pub *drvr = bus_if->drvr;
 980
 981        brcmf_dbg(TRACE, "Enter\n");
 982
 983        if (drvr == NULL)
 984                return;
 985
 986        /* stop firmware event handling */
 987        brcmf_fweh_detach(drvr);
 988
 989        /* make sure primary interface removed last */
 990        for (i = BRCMF_MAX_IFS-1; i > -1; i--)
 991                if (drvr->iflist[i]) {
 992                        brcmf_fws_del_interface(drvr->iflist[i]);
 993                        brcmf_del_if(drvr, i);
 994                }
 995
 996        brcmf_bus_detach(drvr);
 997
 998        if (drvr->prot)
 999                brcmf_proto_detach(drvr);
1000
1001        brcmf_fws_deinit(drvr);
1002
1003        brcmf_debugfs_detach(drvr);
1004        bus_if->drvr = NULL;
1005        kfree(drvr);
1006}
1007
1008static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
1009{
1010        return atomic_read(&ifp->pend_8021x_cnt);
1011}
1012
1013int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
1014{
1015        struct brcmf_if *ifp = netdev_priv(ndev);
1016        int err;
1017
1018        err = wait_event_timeout(ifp->pend_8021x_wait,
1019                                 !brcmf_get_pend_8021x_cnt(ifp),
1020                                 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));
1021
1022        WARN_ON(!err);
1023
1024        return !err;
1025}
1026
1027/*
1028 * return chip id and rev of the device encoded in u32.
1029 */
1030u32 brcmf_get_chip_info(struct brcmf_if *ifp)
1031{
1032        struct brcmf_bus *bus = ifp->drvr->bus_if;
1033
1034        return bus->chip << 4 | bus->chiprev;
1035}
1036
1037static void brcmf_driver_init(struct work_struct *work)
1038{
1039        brcmf_debugfs_init();
1040
1041#ifdef CONFIG_BRCMFMAC_SDIO
1042        brcmf_sdio_init();
1043#endif
1044#ifdef CONFIG_BRCMFMAC_USB
1045        brcmf_usb_init();
1046#endif
1047}
1048static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
1049
1050static int __init brcmfmac_module_init(void)
1051{
1052        if (!schedule_work(&brcmf_driver_work))
1053                return -EBUSY;
1054
1055        return 0;
1056}
1057
1058static void __exit brcmfmac_module_exit(void)
1059{
1060        cancel_work_sync(&brcmf_driver_work);
1061
1062#ifdef CONFIG_BRCMFMAC_SDIO
1063        brcmf_sdio_exit();
1064#endif
1065#ifdef CONFIG_BRCMFMAC_USB
1066        brcmf_usb_exit();
1067#endif
1068        brcmf_debugfs_exit();
1069}
1070
1071module_init(brcmfmac_module_init);
1072module_exit(brcmfmac_module_exit);
1073