Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.35 4214 lines 102 kB view raw
1/* 2 * drivers/net/wireless/mwl8k.c 3 * Driver for Marvell TOPDOG 802.11 Wireless cards 4 * 5 * Copyright (C) 2008, 2009, 2010 Marvell Semiconductor Inc. 6 * 7 * This file is licensed under the terms of the GNU General Public 8 * License version 2. This program is licensed "as is" without any 9 * warranty of any kind, whether express or implied. 10 */ 11 12#include <linux/init.h> 13#include <linux/module.h> 14#include <linux/kernel.h> 15#include <linux/sched.h> 16#include <linux/spinlock.h> 17#include <linux/list.h> 18#include <linux/pci.h> 19#include <linux/delay.h> 20#include <linux/completion.h> 21#include <linux/etherdevice.h> 22#include <linux/slab.h> 23#include <net/mac80211.h> 24#include <linux/moduleparam.h> 25#include <linux/firmware.h> 26#include <linux/workqueue.h> 27 28#define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" 29#define MWL8K_NAME KBUILD_MODNAME 30#define MWL8K_VERSION "0.12" 31 32/* Register definitions */ 33#define MWL8K_HIU_GEN_PTR 0x00000c10 34#define MWL8K_MODE_STA 0x0000005a 35#define MWL8K_MODE_AP 0x000000a5 36#define MWL8K_HIU_INT_CODE 0x00000c14 37#define MWL8K_FWSTA_READY 0xf0f1f2f4 38#define MWL8K_FWAP_READY 0xf1f2f4a5 39#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 40#define MWL8K_HIU_SCRATCH 0x00000c40 41 42/* Host->device communications */ 43#define MWL8K_HIU_H2A_INTERRUPT_EVENTS 0x00000c18 44#define MWL8K_HIU_H2A_INTERRUPT_STATUS 0x00000c1c 45#define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20 46#define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24 47#define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 48#define MWL8K_H2A_INT_DUMMY (1 << 20) 49#define MWL8K_H2A_INT_RESET (1 << 15) 50#define MWL8K_H2A_INT_DOORBELL (1 << 1) 51#define MWL8K_H2A_INT_PPA_READY (1 << 0) 52 53/* Device->host communications */ 54#define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c 55#define MWL8K_HIU_A2H_INTERRUPT_STATUS 0x00000c30 56#define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34 57#define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 58#define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c 59#define MWL8K_A2H_INT_DUMMY (1 << 20) 60#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) 61#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) 62#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) 63#define MWL8K_A2H_INT_RADIO_ON (1 << 6) 64#define MWL8K_A2H_INT_RADIO_OFF (1 << 5) 65#define MWL8K_A2H_INT_MAC_EVENT (1 << 3) 66#define MWL8K_A2H_INT_OPC_DONE (1 << 2) 67#define MWL8K_A2H_INT_RX_READY (1 << 1) 68#define MWL8K_A2H_INT_TX_DONE (1 << 0) 69 70#define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ 71 MWL8K_A2H_INT_CHNL_SWITCHED | \ 72 MWL8K_A2H_INT_QUEUE_EMPTY | \ 73 MWL8K_A2H_INT_RADAR_DETECT | \ 74 MWL8K_A2H_INT_RADIO_ON | \ 75 MWL8K_A2H_INT_RADIO_OFF | \ 76 MWL8K_A2H_INT_MAC_EVENT | \ 77 MWL8K_A2H_INT_OPC_DONE | \ 78 MWL8K_A2H_INT_RX_READY | \ 79 MWL8K_A2H_INT_TX_DONE) 80 81#define MWL8K_RX_QUEUES 1 82#define MWL8K_TX_QUEUES 4 83 84struct rxd_ops { 85 int rxd_size; 86 void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); 87 void (*rxd_refill)(void *rxd, dma_addr_t addr, int len); 88 int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status, 89 __le16 *qos); 90}; 91 92struct mwl8k_device_info { 93 char *part_name; 94 char *helper_image; 95 char *fw_image; 96 struct rxd_ops *ap_rxd_ops; 97}; 98 99struct mwl8k_rx_queue { 100 int rxd_count; 101 102 /* hw receives here */ 103 int head; 104 105 /* refill descs here */ 106 int tail; 107 108 void *rxd; 109 dma_addr_t rxd_dma; 110 struct { 111 struct sk_buff *skb; 112 DECLARE_PCI_UNMAP_ADDR(dma) 113 } *buf; 114}; 115 116struct mwl8k_tx_queue { 117 /* hw transmits here */ 118 int head; 119 120 /* sw appends here */ 121 int tail; 122 123 unsigned int len; 124 struct mwl8k_tx_desc *txd; 125 dma_addr_t txd_dma; 126 struct sk_buff **skb; 127}; 128 129struct mwl8k_priv { 130 struct ieee80211_hw *hw; 131 struct pci_dev *pdev; 132 133 struct mwl8k_device_info *device_info; 134 135 void __iomem *sram; 136 void __iomem *regs; 137 138 /* firmware */ 139 struct firmware *fw_helper; 140 struct firmware *fw_ucode; 141 142 /* hardware/firmware parameters */ 143 bool ap_fw; 144 struct rxd_ops *rxd_ops; 145 struct ieee80211_supported_band band_24; 146 struct ieee80211_channel channels_24[14]; 147 struct ieee80211_rate rates_24[14]; 148 struct ieee80211_supported_band band_50; 149 struct ieee80211_channel channels_50[4]; 150 struct ieee80211_rate rates_50[9]; 151 u32 ap_macids_supported; 152 u32 sta_macids_supported; 153 154 /* firmware access */ 155 struct mutex fw_mutex; 156 struct task_struct *fw_mutex_owner; 157 int fw_mutex_depth; 158 struct completion *hostcmd_wait; 159 160 /* lock held over TX and TX reap */ 161 spinlock_t tx_lock; 162 163 /* TX quiesce completion, protected by fw_mutex and tx_lock */ 164 struct completion *tx_wait; 165 166 /* List of interfaces. */ 167 u32 macids_used; 168 struct list_head vif_list; 169 170 /* power management status cookie from firmware */ 171 u32 *cookie; 172 dma_addr_t cookie_dma; 173 174 u16 num_mcaddrs; 175 u8 hw_rev; 176 u32 fw_rev; 177 178 /* 179 * Running count of TX packets in flight, to avoid 180 * iterating over the transmit rings each time. 181 */ 182 int pending_tx_pkts; 183 184 struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; 185 struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; 186 187 bool radio_on; 188 bool radio_short_preamble; 189 bool sniffer_enabled; 190 bool wmm_enabled; 191 192 /* XXX need to convert this to handle multiple interfaces */ 193 bool capture_beacon; 194 u8 capture_bssid[ETH_ALEN]; 195 struct sk_buff *beacon_skb; 196 197 /* 198 * This FJ worker has to be global as it is scheduled from the 199 * RX handler. At this point we don't know which interface it 200 * belongs to until the list of bssids waiting to complete join 201 * is checked. 202 */ 203 struct work_struct finalize_join_worker; 204 205 /* Tasklet to perform TX reclaim. */ 206 struct tasklet_struct poll_tx_task; 207 208 /* Tasklet to perform RX. */ 209 struct tasklet_struct poll_rx_task; 210}; 211 212/* Per interface specific private data */ 213struct mwl8k_vif { 214 struct list_head list; 215 struct ieee80211_vif *vif; 216 217 /* Firmware macid for this vif. */ 218 int macid; 219 220 /* Non AMPDU sequence number assigned by driver. */ 221 u16 seqno; 222}; 223#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) 224 225struct mwl8k_sta { 226 /* Index into station database. Returned by UPDATE_STADB. */ 227 u8 peer_id; 228}; 229#define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) 230 231static const struct ieee80211_channel mwl8k_channels_24[] = { 232 { .center_freq = 2412, .hw_value = 1, }, 233 { .center_freq = 2417, .hw_value = 2, }, 234 { .center_freq = 2422, .hw_value = 3, }, 235 { .center_freq = 2427, .hw_value = 4, }, 236 { .center_freq = 2432, .hw_value = 5, }, 237 { .center_freq = 2437, .hw_value = 6, }, 238 { .center_freq = 2442, .hw_value = 7, }, 239 { .center_freq = 2447, .hw_value = 8, }, 240 { .center_freq = 2452, .hw_value = 9, }, 241 { .center_freq = 2457, .hw_value = 10, }, 242 { .center_freq = 2462, .hw_value = 11, }, 243 { .center_freq = 2467, .hw_value = 12, }, 244 { .center_freq = 2472, .hw_value = 13, }, 245 { .center_freq = 2484, .hw_value = 14, }, 246}; 247 248static const struct ieee80211_rate mwl8k_rates_24[] = { 249 { .bitrate = 10, .hw_value = 2, }, 250 { .bitrate = 20, .hw_value = 4, }, 251 { .bitrate = 55, .hw_value = 11, }, 252 { .bitrate = 110, .hw_value = 22, }, 253 { .bitrate = 220, .hw_value = 44, }, 254 { .bitrate = 60, .hw_value = 12, }, 255 { .bitrate = 90, .hw_value = 18, }, 256 { .bitrate = 120, .hw_value = 24, }, 257 { .bitrate = 180, .hw_value = 36, }, 258 { .bitrate = 240, .hw_value = 48, }, 259 { .bitrate = 360, .hw_value = 72, }, 260 { .bitrate = 480, .hw_value = 96, }, 261 { .bitrate = 540, .hw_value = 108, }, 262 { .bitrate = 720, .hw_value = 144, }, 263}; 264 265static const struct ieee80211_channel mwl8k_channels_50[] = { 266 { .center_freq = 5180, .hw_value = 36, }, 267 { .center_freq = 5200, .hw_value = 40, }, 268 { .center_freq = 5220, .hw_value = 44, }, 269 { .center_freq = 5240, .hw_value = 48, }, 270}; 271 272static const struct ieee80211_rate mwl8k_rates_50[] = { 273 { .bitrate = 60, .hw_value = 12, }, 274 { .bitrate = 90, .hw_value = 18, }, 275 { .bitrate = 120, .hw_value = 24, }, 276 { .bitrate = 180, .hw_value = 36, }, 277 { .bitrate = 240, .hw_value = 48, }, 278 { .bitrate = 360, .hw_value = 72, }, 279 { .bitrate = 480, .hw_value = 96, }, 280 { .bitrate = 540, .hw_value = 108, }, 281 { .bitrate = 720, .hw_value = 144, }, 282}; 283 284/* Set or get info from Firmware */ 285#define MWL8K_CMD_SET 0x0001 286#define MWL8K_CMD_GET 0x0000 287 288/* Firmware command codes */ 289#define MWL8K_CMD_CODE_DNLD 0x0001 290#define MWL8K_CMD_GET_HW_SPEC 0x0003 291#define MWL8K_CMD_SET_HW_SPEC 0x0004 292#define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 293#define MWL8K_CMD_GET_STAT 0x0014 294#define MWL8K_CMD_RADIO_CONTROL 0x001c 295#define MWL8K_CMD_RF_TX_POWER 0x001e 296#define MWL8K_CMD_RF_ANTENNA 0x0020 297#define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */ 298#define MWL8K_CMD_SET_PRE_SCAN 0x0107 299#define MWL8K_CMD_SET_POST_SCAN 0x0108 300#define MWL8K_CMD_SET_RF_CHANNEL 0x010a 301#define MWL8K_CMD_SET_AID 0x010d 302#define MWL8K_CMD_SET_RATE 0x0110 303#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 304#define MWL8K_CMD_RTS_THRESHOLD 0x0113 305#define MWL8K_CMD_SET_SLOT 0x0114 306#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 307#define MWL8K_CMD_SET_WMM_MODE 0x0123 308#define MWL8K_CMD_MIMO_CONFIG 0x0125 309#define MWL8K_CMD_USE_FIXED_RATE 0x0126 310#define MWL8K_CMD_ENABLE_SNIFFER 0x0150 311#define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ 312#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 313#define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ 314#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ 315#define MWL8K_CMD_UPDATE_STADB 0x1123 316 317static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) 318{ 319#define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\ 320 snprintf(buf, bufsize, "%s", #x);\ 321 return buf;\ 322 } while (0) 323 switch (cmd & ~0x8000) { 324 MWL8K_CMDNAME(CODE_DNLD); 325 MWL8K_CMDNAME(GET_HW_SPEC); 326 MWL8K_CMDNAME(SET_HW_SPEC); 327 MWL8K_CMDNAME(MAC_MULTICAST_ADR); 328 MWL8K_CMDNAME(GET_STAT); 329 MWL8K_CMDNAME(RADIO_CONTROL); 330 MWL8K_CMDNAME(RF_TX_POWER); 331 MWL8K_CMDNAME(RF_ANTENNA); 332 MWL8K_CMDNAME(SET_BEACON); 333 MWL8K_CMDNAME(SET_PRE_SCAN); 334 MWL8K_CMDNAME(SET_POST_SCAN); 335 MWL8K_CMDNAME(SET_RF_CHANNEL); 336 MWL8K_CMDNAME(SET_AID); 337 MWL8K_CMDNAME(SET_RATE); 338 MWL8K_CMDNAME(SET_FINALIZE_JOIN); 339 MWL8K_CMDNAME(RTS_THRESHOLD); 340 MWL8K_CMDNAME(SET_SLOT); 341 MWL8K_CMDNAME(SET_EDCA_PARAMS); 342 MWL8K_CMDNAME(SET_WMM_MODE); 343 MWL8K_CMDNAME(MIMO_CONFIG); 344 MWL8K_CMDNAME(USE_FIXED_RATE); 345 MWL8K_CMDNAME(ENABLE_SNIFFER); 346 MWL8K_CMDNAME(SET_MAC_ADDR); 347 MWL8K_CMDNAME(SET_RATEADAPT_MODE); 348 MWL8K_CMDNAME(BSS_START); 349 MWL8K_CMDNAME(SET_NEW_STN); 350 MWL8K_CMDNAME(UPDATE_STADB); 351 default: 352 snprintf(buf, bufsize, "0x%x", cmd); 353 } 354#undef MWL8K_CMDNAME 355 356 return buf; 357} 358 359/* Hardware and firmware reset */ 360static void mwl8k_hw_reset(struct mwl8k_priv *priv) 361{ 362 iowrite32(MWL8K_H2A_INT_RESET, 363 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 364 iowrite32(MWL8K_H2A_INT_RESET, 365 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 366 msleep(20); 367} 368 369/* Release fw image */ 370static void mwl8k_release_fw(struct firmware **fw) 371{ 372 if (*fw == NULL) 373 return; 374 release_firmware(*fw); 375 *fw = NULL; 376} 377 378static void mwl8k_release_firmware(struct mwl8k_priv *priv) 379{ 380 mwl8k_release_fw(&priv->fw_ucode); 381 mwl8k_release_fw(&priv->fw_helper); 382} 383 384/* Request fw image */ 385static int mwl8k_request_fw(struct mwl8k_priv *priv, 386 const char *fname, struct firmware **fw) 387{ 388 /* release current image */ 389 if (*fw != NULL) 390 mwl8k_release_fw(fw); 391 392 return request_firmware((const struct firmware **)fw, 393 fname, &priv->pdev->dev); 394} 395 396static int mwl8k_request_firmware(struct mwl8k_priv *priv) 397{ 398 struct mwl8k_device_info *di = priv->device_info; 399 int rc; 400 401 if (di->helper_image != NULL) { 402 rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper); 403 if (rc) { 404 printk(KERN_ERR "%s: Error requesting helper " 405 "firmware file %s\n", pci_name(priv->pdev), 406 di->helper_image); 407 return rc; 408 } 409 } 410 411 rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode); 412 if (rc) { 413 printk(KERN_ERR "%s: Error requesting firmware file %s\n", 414 pci_name(priv->pdev), di->fw_image); 415 mwl8k_release_fw(&priv->fw_helper); 416 return rc; 417 } 418 419 return 0; 420} 421 422struct mwl8k_cmd_pkt { 423 __le16 code; 424 __le16 length; 425 __u8 seq_num; 426 __u8 macid; 427 __le16 result; 428 char payload[0]; 429} __attribute__((packed)); 430 431/* 432 * Firmware loading. 433 */ 434static int 435mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) 436{ 437 void __iomem *regs = priv->regs; 438 dma_addr_t dma_addr; 439 int loops; 440 441 dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE); 442 if (pci_dma_mapping_error(priv->pdev, dma_addr)) 443 return -ENOMEM; 444 445 iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); 446 iowrite32(0, regs + MWL8K_HIU_INT_CODE); 447 iowrite32(MWL8K_H2A_INT_DOORBELL, 448 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 449 iowrite32(MWL8K_H2A_INT_DUMMY, 450 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 451 452 loops = 1000; 453 do { 454 u32 int_code; 455 456 int_code = ioread32(regs + MWL8K_HIU_INT_CODE); 457 if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { 458 iowrite32(0, regs + MWL8K_HIU_INT_CODE); 459 break; 460 } 461 462 cond_resched(); 463 udelay(1); 464 } while (--loops); 465 466 pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE); 467 468 return loops ? 0 : -ETIMEDOUT; 469} 470 471static int mwl8k_load_fw_image(struct mwl8k_priv *priv, 472 const u8 *data, size_t length) 473{ 474 struct mwl8k_cmd_pkt *cmd; 475 int done; 476 int rc = 0; 477 478 cmd = kmalloc(sizeof(*cmd) + 256, GFP_KERNEL); 479 if (cmd == NULL) 480 return -ENOMEM; 481 482 cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD); 483 cmd->seq_num = 0; 484 cmd->macid = 0; 485 cmd->result = 0; 486 487 done = 0; 488 while (length) { 489 int block_size = length > 256 ? 256 : length; 490 491 memcpy(cmd->payload, data + done, block_size); 492 cmd->length = cpu_to_le16(block_size); 493 494 rc = mwl8k_send_fw_load_cmd(priv, cmd, 495 sizeof(*cmd) + block_size); 496 if (rc) 497 break; 498 499 done += block_size; 500 length -= block_size; 501 } 502 503 if (!rc) { 504 cmd->length = 0; 505 rc = mwl8k_send_fw_load_cmd(priv, cmd, sizeof(*cmd)); 506 } 507 508 kfree(cmd); 509 510 return rc; 511} 512 513static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, 514 const u8 *data, size_t length) 515{ 516 unsigned char *buffer; 517 int may_continue, rc = 0; 518 u32 done, prev_block_size; 519 520 buffer = kmalloc(1024, GFP_KERNEL); 521 if (buffer == NULL) 522 return -ENOMEM; 523 524 done = 0; 525 prev_block_size = 0; 526 may_continue = 1000; 527 while (may_continue > 0) { 528 u32 block_size; 529 530 block_size = ioread32(priv->regs + MWL8K_HIU_SCRATCH); 531 if (block_size & 1) { 532 block_size &= ~1; 533 may_continue--; 534 } else { 535 done += prev_block_size; 536 length -= prev_block_size; 537 } 538 539 if (block_size > 1024 || block_size > length) { 540 rc = -EOVERFLOW; 541 break; 542 } 543 544 if (length == 0) { 545 rc = 0; 546 break; 547 } 548 549 if (block_size == 0) { 550 rc = -EPROTO; 551 may_continue--; 552 udelay(1); 553 continue; 554 } 555 556 prev_block_size = block_size; 557 memcpy(buffer, data + done, block_size); 558 559 rc = mwl8k_send_fw_load_cmd(priv, buffer, block_size); 560 if (rc) 561 break; 562 } 563 564 if (!rc && length != 0) 565 rc = -EREMOTEIO; 566 567 kfree(buffer); 568 569 return rc; 570} 571 572static int mwl8k_load_firmware(struct ieee80211_hw *hw) 573{ 574 struct mwl8k_priv *priv = hw->priv; 575 struct firmware *fw = priv->fw_ucode; 576 int rc; 577 int loops; 578 579 if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { 580 struct firmware *helper = priv->fw_helper; 581 582 if (helper == NULL) { 583 printk(KERN_ERR "%s: helper image needed but none " 584 "given\n", pci_name(priv->pdev)); 585 return -EINVAL; 586 } 587 588 rc = mwl8k_load_fw_image(priv, helper->data, helper->size); 589 if (rc) { 590 printk(KERN_ERR "%s: unable to load firmware " 591 "helper image\n", pci_name(priv->pdev)); 592 return rc; 593 } 594 msleep(5); 595 596 rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); 597 } else { 598 rc = mwl8k_load_fw_image(priv, fw->data, fw->size); 599 } 600 601 if (rc) { 602 printk(KERN_ERR "%s: unable to load firmware image\n", 603 pci_name(priv->pdev)); 604 return rc; 605 } 606 607 iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); 608 609 loops = 500000; 610 do { 611 u32 ready_code; 612 613 ready_code = ioread32(priv->regs + MWL8K_HIU_INT_CODE); 614 if (ready_code == MWL8K_FWAP_READY) { 615 priv->ap_fw = 1; 616 break; 617 } else if (ready_code == MWL8K_FWSTA_READY) { 618 priv->ap_fw = 0; 619 break; 620 } 621 622 cond_resched(); 623 udelay(1); 624 } while (--loops); 625 626 return loops ? 0 : -ETIMEDOUT; 627} 628 629 630/* DMA header used by firmware and hardware. */ 631struct mwl8k_dma_data { 632 __le16 fwlen; 633 struct ieee80211_hdr wh; 634 char data[0]; 635} __attribute__((packed)); 636 637/* Routines to add/remove DMA header from skb. */ 638static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) 639{ 640 struct mwl8k_dma_data *tr; 641 int hdrlen; 642 643 tr = (struct mwl8k_dma_data *)skb->data; 644 hdrlen = ieee80211_hdrlen(tr->wh.frame_control); 645 646 if (hdrlen != sizeof(tr->wh)) { 647 if (ieee80211_is_data_qos(tr->wh.frame_control)) { 648 memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2); 649 *((__le16 *)(tr->data - 2)) = qos; 650 } else { 651 memmove(tr->data - hdrlen, &tr->wh, hdrlen); 652 } 653 } 654 655 if (hdrlen != sizeof(*tr)) 656 skb_pull(skb, sizeof(*tr) - hdrlen); 657} 658 659static inline void mwl8k_add_dma_header(struct sk_buff *skb) 660{ 661 struct ieee80211_hdr *wh; 662 int hdrlen; 663 struct mwl8k_dma_data *tr; 664 665 /* 666 * Add a firmware DMA header; the firmware requires that we 667 * present a 2-byte payload length followed by a 4-address 668 * header (without QoS field), followed (optionally) by any 669 * WEP/ExtIV header (but only filled in for CCMP). 670 */ 671 wh = (struct ieee80211_hdr *)skb->data; 672 673 hdrlen = ieee80211_hdrlen(wh->frame_control); 674 if (hdrlen != sizeof(*tr)) 675 skb_push(skb, sizeof(*tr) - hdrlen); 676 677 if (ieee80211_is_data_qos(wh->frame_control)) 678 hdrlen -= 2; 679 680 tr = (struct mwl8k_dma_data *)skb->data; 681 if (wh != &tr->wh) 682 memmove(&tr->wh, wh, hdrlen); 683 if (hdrlen != sizeof(tr->wh)) 684 memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen); 685 686 /* 687 * Firmware length is the length of the fully formed "802.11 688 * payload". That is, everything except for the 802.11 header. 689 * This includes all crypto material including the MIC. 690 */ 691 tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr)); 692} 693 694 695/* 696 * Packet reception for 88w8366 AP firmware. 697 */ 698struct mwl8k_rxd_8366_ap { 699 __le16 pkt_len; 700 __u8 sq2; 701 __u8 rate; 702 __le32 pkt_phys_addr; 703 __le32 next_rxd_phys_addr; 704 __le16 qos_control; 705 __le16 htsig2; 706 __le32 hw_rssi_info; 707 __le32 hw_noise_floor_info; 708 __u8 noise_floor; 709 __u8 pad0[3]; 710 __u8 rssi; 711 __u8 rx_status; 712 __u8 channel; 713 __u8 rx_ctrl; 714} __attribute__((packed)); 715 716#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 717#define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 718#define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) 719 720#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 721 722static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) 723{ 724 struct mwl8k_rxd_8366_ap *rxd = _rxd; 725 726 rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); 727 rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; 728} 729 730static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) 731{ 732 struct mwl8k_rxd_8366_ap *rxd = _rxd; 733 734 rxd->pkt_len = cpu_to_le16(len); 735 rxd->pkt_phys_addr = cpu_to_le32(addr); 736 wmb(); 737 rxd->rx_ctrl = 0; 738} 739 740static int 741mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, 742 __le16 *qos) 743{ 744 struct mwl8k_rxd_8366_ap *rxd = _rxd; 745 746 if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) 747 return -1; 748 rmb(); 749 750 memset(status, 0, sizeof(*status)); 751 752 status->signal = -rxd->rssi; 753 754 if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { 755 status->flag |= RX_FLAG_HT; 756 if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) 757 status->flag |= RX_FLAG_40MHZ; 758 status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); 759 } else { 760 int i; 761 762 for (i = 0; i < ARRAY_SIZE(mwl8k_rates_24); i++) { 763 if (mwl8k_rates_24[i].hw_value == rxd->rate) { 764 status->rate_idx = i; 765 break; 766 } 767 } 768 } 769 770 if (rxd->channel > 14) { 771 status->band = IEEE80211_BAND_5GHZ; 772 if (!(status->flag & RX_FLAG_HT)) 773 status->rate_idx -= 5; 774 } else { 775 status->band = IEEE80211_BAND_2GHZ; 776 } 777 status->freq = ieee80211_channel_to_frequency(rxd->channel); 778 779 *qos = rxd->qos_control; 780 781 return le16_to_cpu(rxd->pkt_len); 782} 783 784static struct rxd_ops rxd_8366_ap_ops = { 785 .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), 786 .rxd_init = mwl8k_rxd_8366_ap_init, 787 .rxd_refill = mwl8k_rxd_8366_ap_refill, 788 .rxd_process = mwl8k_rxd_8366_ap_process, 789}; 790 791/* 792 * Packet reception for STA firmware. 793 */ 794struct mwl8k_rxd_sta { 795 __le16 pkt_len; 796 __u8 link_quality; 797 __u8 noise_level; 798 __le32 pkt_phys_addr; 799 __le32 next_rxd_phys_addr; 800 __le16 qos_control; 801 __le16 rate_info; 802 __le32 pad0[4]; 803 __u8 rssi; 804 __u8 channel; 805 __le16 pad1; 806 __u8 rx_ctrl; 807 __u8 rx_status; 808 __u8 pad2[2]; 809} __attribute__((packed)); 810 811#define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000 812#define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) 813#define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) 814#define MWL8K_STA_RATE_INFO_40MHZ 0x0004 815#define MWL8K_STA_RATE_INFO_SHORTGI 0x0002 816#define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 817 818#define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 819 820static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) 821{ 822 struct mwl8k_rxd_sta *rxd = _rxd; 823 824 rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); 825 rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST; 826} 827 828static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len) 829{ 830 struct mwl8k_rxd_sta *rxd = _rxd; 831 832 rxd->pkt_len = cpu_to_le16(len); 833 rxd->pkt_phys_addr = cpu_to_le32(addr); 834 wmb(); 835 rxd->rx_ctrl = 0; 836} 837 838static int 839mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, 840 __le16 *qos) 841{ 842 struct mwl8k_rxd_sta *rxd = _rxd; 843 u16 rate_info; 844 845 if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST)) 846 return -1; 847 rmb(); 848 849 rate_info = le16_to_cpu(rxd->rate_info); 850 851 memset(status, 0, sizeof(*status)); 852 853 status->signal = -rxd->rssi; 854 status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info); 855 status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); 856 857 if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE) 858 status->flag |= RX_FLAG_SHORTPRE; 859 if (rate_info & MWL8K_STA_RATE_INFO_40MHZ) 860 status->flag |= RX_FLAG_40MHZ; 861 if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI) 862 status->flag |= RX_FLAG_SHORT_GI; 863 if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT) 864 status->flag |= RX_FLAG_HT; 865 866 if (rxd->channel > 14) { 867 status->band = IEEE80211_BAND_5GHZ; 868 if (!(status->flag & RX_FLAG_HT)) 869 status->rate_idx -= 5; 870 } else { 871 status->band = IEEE80211_BAND_2GHZ; 872 } 873 status->freq = ieee80211_channel_to_frequency(rxd->channel); 874 875 *qos = rxd->qos_control; 876 877 return le16_to_cpu(rxd->pkt_len); 878} 879 880static struct rxd_ops rxd_sta_ops = { 881 .rxd_size = sizeof(struct mwl8k_rxd_sta), 882 .rxd_init = mwl8k_rxd_sta_init, 883 .rxd_refill = mwl8k_rxd_sta_refill, 884 .rxd_process = mwl8k_rxd_sta_process, 885}; 886 887 888#define MWL8K_RX_DESCS 256 889#define MWL8K_RX_MAXSZ 3800 890 891static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) 892{ 893 struct mwl8k_priv *priv = hw->priv; 894 struct mwl8k_rx_queue *rxq = priv->rxq + index; 895 int size; 896 int i; 897 898 rxq->rxd_count = 0; 899 rxq->head = 0; 900 rxq->tail = 0; 901 902 size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size; 903 904 rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma); 905 if (rxq->rxd == NULL) { 906 printk(KERN_ERR "%s: failed to alloc RX descriptors\n", 907 wiphy_name(hw->wiphy)); 908 return -ENOMEM; 909 } 910 memset(rxq->rxd, 0, size); 911 912 rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL); 913 if (rxq->buf == NULL) { 914 printk(KERN_ERR "%s: failed to alloc RX skbuff list\n", 915 wiphy_name(hw->wiphy)); 916 pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma); 917 return -ENOMEM; 918 } 919 memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf)); 920 921 for (i = 0; i < MWL8K_RX_DESCS; i++) { 922 int desc_size; 923 void *rxd; 924 int nexti; 925 dma_addr_t next_dma_addr; 926 927 desc_size = priv->rxd_ops->rxd_size; 928 rxd = rxq->rxd + (i * priv->rxd_ops->rxd_size); 929 930 nexti = i + 1; 931 if (nexti == MWL8K_RX_DESCS) 932 nexti = 0; 933 next_dma_addr = rxq->rxd_dma + (nexti * desc_size); 934 935 priv->rxd_ops->rxd_init(rxd, next_dma_addr); 936 } 937 938 return 0; 939} 940 941static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) 942{ 943 struct mwl8k_priv *priv = hw->priv; 944 struct mwl8k_rx_queue *rxq = priv->rxq + index; 945 int refilled; 946 947 refilled = 0; 948 while (rxq->rxd_count < MWL8K_RX_DESCS && limit--) { 949 struct sk_buff *skb; 950 dma_addr_t addr; 951 int rx; 952 void *rxd; 953 954 skb = dev_alloc_skb(MWL8K_RX_MAXSZ); 955 if (skb == NULL) 956 break; 957 958 addr = pci_map_single(priv->pdev, skb->data, 959 MWL8K_RX_MAXSZ, DMA_FROM_DEVICE); 960 961 rxq->rxd_count++; 962 rx = rxq->tail++; 963 if (rxq->tail == MWL8K_RX_DESCS) 964 rxq->tail = 0; 965 rxq->buf[rx].skb = skb; 966 pci_unmap_addr_set(&rxq->buf[rx], dma, addr); 967 968 rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size); 969 priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ); 970 971 refilled++; 972 } 973 974 return refilled; 975} 976 977/* Must be called only when the card's reception is completely halted */ 978static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) 979{ 980 struct mwl8k_priv *priv = hw->priv; 981 struct mwl8k_rx_queue *rxq = priv->rxq + index; 982 int i; 983 984 for (i = 0; i < MWL8K_RX_DESCS; i++) { 985 if (rxq->buf[i].skb != NULL) { 986 pci_unmap_single(priv->pdev, 987 pci_unmap_addr(&rxq->buf[i], dma), 988 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); 989 pci_unmap_addr_set(&rxq->buf[i], dma, 0); 990 991 kfree_skb(rxq->buf[i].skb); 992 rxq->buf[i].skb = NULL; 993 } 994 } 995 996 kfree(rxq->buf); 997 rxq->buf = NULL; 998 999 pci_free_consistent(priv->pdev, 1000 MWL8K_RX_DESCS * priv->rxd_ops->rxd_size, 1001 rxq->rxd, rxq->rxd_dma); 1002 rxq->rxd = NULL; 1003} 1004 1005 1006/* 1007 * Scan a list of BSSIDs to process for finalize join. 1008 * Allows for extension to process multiple BSSIDs. 1009 */ 1010static inline int 1011mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh) 1012{ 1013 return priv->capture_beacon && 1014 ieee80211_is_beacon(wh->frame_control) && 1015 !compare_ether_addr(wh->addr3, priv->capture_bssid); 1016} 1017 1018static inline void mwl8k_save_beacon(struct ieee80211_hw *hw, 1019 struct sk_buff *skb) 1020{ 1021 struct mwl8k_priv *priv = hw->priv; 1022 1023 priv->capture_beacon = false; 1024 memset(priv->capture_bssid, 0, ETH_ALEN); 1025 1026 /* 1027 * Use GFP_ATOMIC as rxq_process is called from 1028 * the primary interrupt handler, memory allocation call 1029 * must not sleep. 1030 */ 1031 priv->beacon_skb = skb_copy(skb, GFP_ATOMIC); 1032 if (priv->beacon_skb != NULL) 1033 ieee80211_queue_work(hw, &priv->finalize_join_worker); 1034} 1035 1036static int rxq_process(struct ieee80211_hw *hw, int index, int limit) 1037{ 1038 struct mwl8k_priv *priv = hw->priv; 1039 struct mwl8k_rx_queue *rxq = priv->rxq + index; 1040 int processed; 1041 1042 processed = 0; 1043 while (rxq->rxd_count && limit--) { 1044 struct sk_buff *skb; 1045 void *rxd; 1046 int pkt_len; 1047 struct ieee80211_rx_status status; 1048 __le16 qos; 1049 1050 skb = rxq->buf[rxq->head].skb; 1051 if (skb == NULL) 1052 break; 1053 1054 rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size); 1055 1056 pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos); 1057 if (pkt_len < 0) 1058 break; 1059 1060 rxq->buf[rxq->head].skb = NULL; 1061 1062 pci_unmap_single(priv->pdev, 1063 pci_unmap_addr(&rxq->buf[rxq->head], dma), 1064 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); 1065 pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0); 1066 1067 rxq->head++; 1068 if (rxq->head == MWL8K_RX_DESCS) 1069 rxq->head = 0; 1070 1071 rxq->rxd_count--; 1072 1073 skb_put(skb, pkt_len); 1074 mwl8k_remove_dma_header(skb, qos); 1075 1076 /* 1077 * Check for a pending join operation. Save a 1078 * copy of the beacon and schedule a tasklet to 1079 * send a FINALIZE_JOIN command to the firmware. 1080 */ 1081 if (mwl8k_capture_bssid(priv, (void *)skb->data)) 1082 mwl8k_save_beacon(hw, skb); 1083 1084 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); 1085 ieee80211_rx_irqsafe(hw, skb); 1086 1087 processed++; 1088 } 1089 1090 return processed; 1091} 1092 1093 1094/* 1095 * Packet transmission. 1096 */ 1097 1098#define MWL8K_TXD_STATUS_OK 0x00000001 1099#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 1100#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 1101#define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 1102#define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 1103 1104#define MWL8K_QOS_QLEN_UNSPEC 0xff00 1105#define MWL8K_QOS_ACK_POLICY_MASK 0x0060 1106#define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000 1107#define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060 1108#define MWL8K_QOS_EOSP 0x0010 1109 1110struct mwl8k_tx_desc { 1111 __le32 status; 1112 __u8 data_rate; 1113 __u8 tx_priority; 1114 __le16 qos_control; 1115 __le32 pkt_phys_addr; 1116 __le16 pkt_len; 1117 __u8 dest_MAC_addr[ETH_ALEN]; 1118 __le32 next_txd_phys_addr; 1119 __le32 reserved; 1120 __le16 rate_info; 1121 __u8 peer_id; 1122 __u8 tx_frag_cnt; 1123} __attribute__((packed)); 1124 1125#define MWL8K_TX_DESCS 128 1126 1127static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) 1128{ 1129 struct mwl8k_priv *priv = hw->priv; 1130 struct mwl8k_tx_queue *txq = priv->txq + index; 1131 int size; 1132 int i; 1133 1134 txq->len = 0; 1135 txq->head = 0; 1136 txq->tail = 0; 1137 1138 size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc); 1139 1140 txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma); 1141 if (txq->txd == NULL) { 1142 printk(KERN_ERR "%s: failed to alloc TX descriptors\n", 1143 wiphy_name(hw->wiphy)); 1144 return -ENOMEM; 1145 } 1146 memset(txq->txd, 0, size); 1147 1148 txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL); 1149 if (txq->skb == NULL) { 1150 printk(KERN_ERR "%s: failed to alloc TX skbuff list\n", 1151 wiphy_name(hw->wiphy)); 1152 pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma); 1153 return -ENOMEM; 1154 } 1155 memset(txq->skb, 0, MWL8K_TX_DESCS * sizeof(*txq->skb)); 1156 1157 for (i = 0; i < MWL8K_TX_DESCS; i++) { 1158 struct mwl8k_tx_desc *tx_desc; 1159 int nexti; 1160 1161 tx_desc = txq->txd + i; 1162 nexti = (i + 1) % MWL8K_TX_DESCS; 1163 1164 tx_desc->status = 0; 1165 tx_desc->next_txd_phys_addr = 1166 cpu_to_le32(txq->txd_dma + nexti * sizeof(*tx_desc)); 1167 } 1168 1169 return 0; 1170} 1171 1172static inline void mwl8k_tx_start(struct mwl8k_priv *priv) 1173{ 1174 iowrite32(MWL8K_H2A_INT_PPA_READY, 1175 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 1176 iowrite32(MWL8K_H2A_INT_DUMMY, 1177 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 1178 ioread32(priv->regs + MWL8K_HIU_INT_CODE); 1179} 1180 1181static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) 1182{ 1183 struct mwl8k_priv *priv = hw->priv; 1184 int i; 1185 1186 for (i = 0; i < MWL8K_TX_QUEUES; i++) { 1187 struct mwl8k_tx_queue *txq = priv->txq + i; 1188 int fw_owned = 0; 1189 int drv_owned = 0; 1190 int unused = 0; 1191 int desc; 1192 1193 for (desc = 0; desc < MWL8K_TX_DESCS; desc++) { 1194 struct mwl8k_tx_desc *tx_desc = txq->txd + desc; 1195 u32 status; 1196 1197 status = le32_to_cpu(tx_desc->status); 1198 if (status & MWL8K_TXD_STATUS_FW_OWNED) 1199 fw_owned++; 1200 else 1201 drv_owned++; 1202 1203 if (tx_desc->pkt_len == 0) 1204 unused++; 1205 } 1206 1207 printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d " 1208 "fw_owned=%d drv_owned=%d unused=%d\n", 1209 wiphy_name(hw->wiphy), i, 1210 txq->len, txq->head, txq->tail, 1211 fw_owned, drv_owned, unused); 1212 } 1213} 1214 1215/* 1216 * Must be called with priv->fw_mutex held and tx queues stopped. 1217 */ 1218#define MWL8K_TX_WAIT_TIMEOUT_MS 5000 1219 1220static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) 1221{ 1222 struct mwl8k_priv *priv = hw->priv; 1223 DECLARE_COMPLETION_ONSTACK(tx_wait); 1224 int retry; 1225 int rc; 1226 1227 might_sleep(); 1228 1229 /* 1230 * The TX queues are stopped at this point, so this test 1231 * doesn't need to take ->tx_lock. 1232 */ 1233 if (!priv->pending_tx_pkts) 1234 return 0; 1235 1236 retry = 0; 1237 rc = 0; 1238 1239 spin_lock_bh(&priv->tx_lock); 1240 priv->tx_wait = &tx_wait; 1241 while (!rc) { 1242 int oldcount; 1243 unsigned long timeout; 1244 1245 oldcount = priv->pending_tx_pkts; 1246 1247 spin_unlock_bh(&priv->tx_lock); 1248 timeout = wait_for_completion_timeout(&tx_wait, 1249 msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS)); 1250 spin_lock_bh(&priv->tx_lock); 1251 1252 if (timeout) { 1253 WARN_ON(priv->pending_tx_pkts); 1254 if (retry) { 1255 printk(KERN_NOTICE "%s: tx rings drained\n", 1256 wiphy_name(hw->wiphy)); 1257 } 1258 break; 1259 } 1260 1261 if (priv->pending_tx_pkts < oldcount) { 1262 printk(KERN_NOTICE "%s: waiting for tx rings " 1263 "to drain (%d -> %d pkts)\n", 1264 wiphy_name(hw->wiphy), oldcount, 1265 priv->pending_tx_pkts); 1266 retry = 1; 1267 continue; 1268 } 1269 1270 priv->tx_wait = NULL; 1271 1272 printk(KERN_ERR "%s: tx rings stuck for %d ms\n", 1273 wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS); 1274 mwl8k_dump_tx_rings(hw); 1275 1276 rc = -ETIMEDOUT; 1277 } 1278 spin_unlock_bh(&priv->tx_lock); 1279 1280 return rc; 1281} 1282 1283#define MWL8K_TXD_SUCCESS(status) \ 1284 ((status) & (MWL8K_TXD_STATUS_OK | \ 1285 MWL8K_TXD_STATUS_OK_RETRY | \ 1286 MWL8K_TXD_STATUS_OK_MORE_RETRY)) 1287 1288static int 1289mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) 1290{ 1291 struct mwl8k_priv *priv = hw->priv; 1292 struct mwl8k_tx_queue *txq = priv->txq + index; 1293 int processed; 1294 1295 processed = 0; 1296 while (txq->len > 0 && limit--) { 1297 int tx; 1298 struct mwl8k_tx_desc *tx_desc; 1299 unsigned long addr; 1300 int size; 1301 struct sk_buff *skb; 1302 struct ieee80211_tx_info *info; 1303 u32 status; 1304 1305 tx = txq->head; 1306 tx_desc = txq->txd + tx; 1307 1308 status = le32_to_cpu(tx_desc->status); 1309 1310 if (status & MWL8K_TXD_STATUS_FW_OWNED) { 1311 if (!force) 1312 break; 1313 tx_desc->status &= 1314 ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED); 1315 } 1316 1317 txq->head = (tx + 1) % MWL8K_TX_DESCS; 1318 BUG_ON(txq->len == 0); 1319 txq->len--; 1320 priv->pending_tx_pkts--; 1321 1322 addr = le32_to_cpu(tx_desc->pkt_phys_addr); 1323 size = le16_to_cpu(tx_desc->pkt_len); 1324 skb = txq->skb[tx]; 1325 txq->skb[tx] = NULL; 1326 1327 BUG_ON(skb == NULL); 1328 pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); 1329 1330 mwl8k_remove_dma_header(skb, tx_desc->qos_control); 1331 1332 /* Mark descriptor as unused */ 1333 tx_desc->pkt_phys_addr = 0; 1334 tx_desc->pkt_len = 0; 1335 1336 info = IEEE80211_SKB_CB(skb); 1337 ieee80211_tx_info_clear_status(info); 1338 if (MWL8K_TXD_SUCCESS(status)) 1339 info->flags |= IEEE80211_TX_STAT_ACK; 1340 1341 ieee80211_tx_status_irqsafe(hw, skb); 1342 1343 processed++; 1344 } 1345 1346 if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) 1347 ieee80211_wake_queue(hw, index); 1348 1349 return processed; 1350} 1351 1352/* must be called only when the card's transmit is completely halted */ 1353static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) 1354{ 1355 struct mwl8k_priv *priv = hw->priv; 1356 struct mwl8k_tx_queue *txq = priv->txq + index; 1357 1358 mwl8k_txq_reclaim(hw, index, INT_MAX, 1); 1359 1360 kfree(txq->skb); 1361 txq->skb = NULL; 1362 1363 pci_free_consistent(priv->pdev, 1364 MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc), 1365 txq->txd, txq->txd_dma); 1366 txq->txd = NULL; 1367} 1368 1369static int 1370mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) 1371{ 1372 struct mwl8k_priv *priv = hw->priv; 1373 struct ieee80211_tx_info *tx_info; 1374 struct mwl8k_vif *mwl8k_vif; 1375 struct ieee80211_hdr *wh; 1376 struct mwl8k_tx_queue *txq; 1377 struct mwl8k_tx_desc *tx; 1378 dma_addr_t dma; 1379 u32 txstatus; 1380 u8 txdatarate; 1381 u16 qos; 1382 1383 wh = (struct ieee80211_hdr *)skb->data; 1384 if (ieee80211_is_data_qos(wh->frame_control)) 1385 qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); 1386 else 1387 qos = 0; 1388 1389 mwl8k_add_dma_header(skb); 1390 wh = &((struct mwl8k_dma_data *)skb->data)->wh; 1391 1392 tx_info = IEEE80211_SKB_CB(skb); 1393 mwl8k_vif = MWL8K_VIF(tx_info->control.vif); 1394 1395 if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 1396 wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 1397 wh->seq_ctrl |= cpu_to_le16(mwl8k_vif->seqno); 1398 mwl8k_vif->seqno += 0x10; 1399 } 1400 1401 /* Setup firmware control bit fields for each frame type. */ 1402 txstatus = 0; 1403 txdatarate = 0; 1404 if (ieee80211_is_mgmt(wh->frame_control) || 1405 ieee80211_is_ctl(wh->frame_control)) { 1406 txdatarate = 0; 1407 qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP; 1408 } else if (ieee80211_is_data(wh->frame_control)) { 1409 txdatarate = 1; 1410 if (is_multicast_ether_addr(wh->addr1)) 1411 txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; 1412 1413 qos &= ~MWL8K_QOS_ACK_POLICY_MASK; 1414 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) 1415 qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK; 1416 else 1417 qos |= MWL8K_QOS_ACK_POLICY_NORMAL; 1418 } 1419 1420 dma = pci_map_single(priv->pdev, skb->data, 1421 skb->len, PCI_DMA_TODEVICE); 1422 1423 if (pci_dma_mapping_error(priv->pdev, dma)) { 1424 printk(KERN_DEBUG "%s: failed to dma map skb, " 1425 "dropping TX frame.\n", wiphy_name(hw->wiphy)); 1426 dev_kfree_skb(skb); 1427 return NETDEV_TX_OK; 1428 } 1429 1430 spin_lock_bh(&priv->tx_lock); 1431 1432 txq = priv->txq + index; 1433 1434 BUG_ON(txq->skb[txq->tail] != NULL); 1435 txq->skb[txq->tail] = skb; 1436 1437 tx = txq->txd + txq->tail; 1438 tx->data_rate = txdatarate; 1439 tx->tx_priority = index; 1440 tx->qos_control = cpu_to_le16(qos); 1441 tx->pkt_phys_addr = cpu_to_le32(dma); 1442 tx->pkt_len = cpu_to_le16(skb->len); 1443 tx->rate_info = 0; 1444 if (!priv->ap_fw && tx_info->control.sta != NULL) 1445 tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; 1446 else 1447 tx->peer_id = 0; 1448 wmb(); 1449 tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); 1450 1451 txq->len++; 1452 priv->pending_tx_pkts++; 1453 1454 txq->tail++; 1455 if (txq->tail == MWL8K_TX_DESCS) 1456 txq->tail = 0; 1457 1458 if (txq->head == txq->tail) 1459 ieee80211_stop_queue(hw, index); 1460 1461 mwl8k_tx_start(priv); 1462 1463 spin_unlock_bh(&priv->tx_lock); 1464 1465 return NETDEV_TX_OK; 1466} 1467 1468 1469/* 1470 * Firmware access. 1471 * 1472 * We have the following requirements for issuing firmware commands: 1473 * - Some commands require that the packet transmit path is idle when 1474 * the command is issued. (For simplicity, we'll just quiesce the 1475 * transmit path for every command.) 1476 * - There are certain sequences of commands that need to be issued to 1477 * the hardware sequentially, with no other intervening commands. 1478 * 1479 * This leads to an implementation of a "firmware lock" as a mutex that 1480 * can be taken recursively, and which is taken by both the low-level 1481 * command submission function (mwl8k_post_cmd) as well as any users of 1482 * that function that require issuing of an atomic sequence of commands, 1483 * and quiesces the transmit path whenever it's taken. 1484 */ 1485static int mwl8k_fw_lock(struct ieee80211_hw *hw) 1486{ 1487 struct mwl8k_priv *priv = hw->priv; 1488 1489 if (priv->fw_mutex_owner != current) { 1490 int rc; 1491 1492 mutex_lock(&priv->fw_mutex); 1493 ieee80211_stop_queues(hw); 1494 1495 rc = mwl8k_tx_wait_empty(hw); 1496 if (rc) { 1497 ieee80211_wake_queues(hw); 1498 mutex_unlock(&priv->fw_mutex); 1499 1500 return rc; 1501 } 1502 1503 priv->fw_mutex_owner = current; 1504 } 1505 1506 priv->fw_mutex_depth++; 1507 1508 return 0; 1509} 1510 1511static void mwl8k_fw_unlock(struct ieee80211_hw *hw) 1512{ 1513 struct mwl8k_priv *priv = hw->priv; 1514 1515 if (!--priv->fw_mutex_depth) { 1516 ieee80211_wake_queues(hw); 1517 priv->fw_mutex_owner = NULL; 1518 mutex_unlock(&priv->fw_mutex); 1519 } 1520} 1521 1522 1523/* 1524 * Command processing. 1525 */ 1526 1527/* Timeout firmware commands after 10s */ 1528#define MWL8K_CMD_TIMEOUT_MS 10000 1529 1530static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) 1531{ 1532 DECLARE_COMPLETION_ONSTACK(cmd_wait); 1533 struct mwl8k_priv *priv = hw->priv; 1534 void __iomem *regs = priv->regs; 1535 dma_addr_t dma_addr; 1536 unsigned int dma_size; 1537 int rc; 1538 unsigned long timeout = 0; 1539 u8 buf[32]; 1540 1541 cmd->result = 0xffff; 1542 dma_size = le16_to_cpu(cmd->length); 1543 dma_addr = pci_map_single(priv->pdev, cmd, dma_size, 1544 PCI_DMA_BIDIRECTIONAL); 1545 if (pci_dma_mapping_error(priv->pdev, dma_addr)) 1546 return -ENOMEM; 1547 1548 rc = mwl8k_fw_lock(hw); 1549 if (rc) { 1550 pci_unmap_single(priv->pdev, dma_addr, dma_size, 1551 PCI_DMA_BIDIRECTIONAL); 1552 return rc; 1553 } 1554 1555 priv->hostcmd_wait = &cmd_wait; 1556 iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); 1557 iowrite32(MWL8K_H2A_INT_DOORBELL, 1558 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 1559 iowrite32(MWL8K_H2A_INT_DUMMY, 1560 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); 1561 1562 timeout = wait_for_completion_timeout(&cmd_wait, 1563 msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); 1564 1565 priv->hostcmd_wait = NULL; 1566 1567 mwl8k_fw_unlock(hw); 1568 1569 pci_unmap_single(priv->pdev, dma_addr, dma_size, 1570 PCI_DMA_BIDIRECTIONAL); 1571 1572 if (!timeout) { 1573 printk(KERN_ERR "%s: Command %s timeout after %u ms\n", 1574 wiphy_name(hw->wiphy), 1575 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), 1576 MWL8K_CMD_TIMEOUT_MS); 1577 rc = -ETIMEDOUT; 1578 } else { 1579 int ms; 1580 1581 ms = MWL8K_CMD_TIMEOUT_MS - jiffies_to_msecs(timeout); 1582 1583 rc = cmd->result ? -EINVAL : 0; 1584 if (rc) 1585 printk(KERN_ERR "%s: Command %s error 0x%x\n", 1586 wiphy_name(hw->wiphy), 1587 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), 1588 le16_to_cpu(cmd->result)); 1589 else if (ms > 2000) 1590 printk(KERN_NOTICE "%s: Command %s took %d ms\n", 1591 wiphy_name(hw->wiphy), 1592 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), 1593 ms); 1594 } 1595 1596 return rc; 1597} 1598 1599static int mwl8k_post_pervif_cmd(struct ieee80211_hw *hw, 1600 struct ieee80211_vif *vif, 1601 struct mwl8k_cmd_pkt *cmd) 1602{ 1603 if (vif != NULL) 1604 cmd->macid = MWL8K_VIF(vif)->macid; 1605 return mwl8k_post_cmd(hw, cmd); 1606} 1607 1608/* 1609 * Setup code shared between STA and AP firmware images. 1610 */ 1611static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw) 1612{ 1613 struct mwl8k_priv *priv = hw->priv; 1614 1615 BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl8k_channels_24)); 1616 memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24)); 1617 1618 BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24)); 1619 memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24)); 1620 1621 priv->band_24.band = IEEE80211_BAND_2GHZ; 1622 priv->band_24.channels = priv->channels_24; 1623 priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24); 1624 priv->band_24.bitrates = priv->rates_24; 1625 priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24); 1626 1627 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; 1628} 1629 1630static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw) 1631{ 1632 struct mwl8k_priv *priv = hw->priv; 1633 1634 BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl8k_channels_50)); 1635 memcpy(priv->channels_50, mwl8k_channels_50, sizeof(mwl8k_channels_50)); 1636 1637 BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl8k_rates_50)); 1638 memcpy(priv->rates_50, mwl8k_rates_50, sizeof(mwl8k_rates_50)); 1639 1640 priv->band_50.band = IEEE80211_BAND_5GHZ; 1641 priv->band_50.channels = priv->channels_50; 1642 priv->band_50.n_channels = ARRAY_SIZE(mwl8k_channels_50); 1643 priv->band_50.bitrates = priv->rates_50; 1644 priv->band_50.n_bitrates = ARRAY_SIZE(mwl8k_rates_50); 1645 1646 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; 1647} 1648 1649/* 1650 * CMD_GET_HW_SPEC (STA version). 1651 */ 1652struct mwl8k_cmd_get_hw_spec_sta { 1653 struct mwl8k_cmd_pkt header; 1654 __u8 hw_rev; 1655 __u8 host_interface; 1656 __le16 num_mcaddrs; 1657 __u8 perm_addr[ETH_ALEN]; 1658 __le16 region_code; 1659 __le32 fw_rev; 1660 __le32 ps_cookie; 1661 __le32 caps; 1662 __u8 mcs_bitmap[16]; 1663 __le32 rx_queue_ptr; 1664 __le32 num_tx_queues; 1665 __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; 1666 __le32 caps2; 1667 __le32 num_tx_desc_per_queue; 1668 __le32 total_rxd; 1669} __attribute__((packed)); 1670 1671#define MWL8K_CAP_MAX_AMSDU 0x20000000 1672#define MWL8K_CAP_GREENFIELD 0x08000000 1673#define MWL8K_CAP_AMPDU 0x04000000 1674#define MWL8K_CAP_RX_STBC 0x01000000 1675#define MWL8K_CAP_TX_STBC 0x00800000 1676#define MWL8K_CAP_SHORTGI_40MHZ 0x00400000 1677#define MWL8K_CAP_SHORTGI_20MHZ 0x00200000 1678#define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000 1679#define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000 1680#define MWL8K_CAP_DELAY_BA 0x00003000 1681#define MWL8K_CAP_MIMO 0x00000200 1682#define MWL8K_CAP_40MHZ 0x00000100 1683#define MWL8K_CAP_BAND_MASK 0x00000007 1684#define MWL8K_CAP_5GHZ 0x00000004 1685#define MWL8K_CAP_2GHZ4 0x00000001 1686 1687static void 1688mwl8k_set_ht_caps(struct ieee80211_hw *hw, 1689 struct ieee80211_supported_band *band, u32 cap) 1690{ 1691 int rx_streams; 1692 int tx_streams; 1693 1694 band->ht_cap.ht_supported = 1; 1695 1696 if (cap & MWL8K_CAP_MAX_AMSDU) 1697 band->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; 1698 if (cap & MWL8K_CAP_GREENFIELD) 1699 band->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; 1700 if (cap & MWL8K_CAP_AMPDU) { 1701 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; 1702 band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 1703 band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; 1704 } 1705 if (cap & MWL8K_CAP_RX_STBC) 1706 band->ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC; 1707 if (cap & MWL8K_CAP_TX_STBC) 1708 band->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; 1709 if (cap & MWL8K_CAP_SHORTGI_40MHZ) 1710 band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; 1711 if (cap & MWL8K_CAP_SHORTGI_20MHZ) 1712 band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; 1713 if (cap & MWL8K_CAP_DELAY_BA) 1714 band->ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA; 1715 if (cap & MWL8K_CAP_40MHZ) 1716 band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; 1717 1718 rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK); 1719 tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK); 1720 1721 band->ht_cap.mcs.rx_mask[0] = 0xff; 1722 if (rx_streams >= 2) 1723 band->ht_cap.mcs.rx_mask[1] = 0xff; 1724 if (rx_streams >= 3) 1725 band->ht_cap.mcs.rx_mask[2] = 0xff; 1726 band->ht_cap.mcs.rx_mask[4] = 0x01; 1727 band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 1728 1729 if (rx_streams != tx_streams) { 1730 band->ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 1731 band->ht_cap.mcs.tx_params |= (tx_streams - 1) << 1732 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; 1733 } 1734} 1735 1736static void 1737mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) 1738{ 1739 struct mwl8k_priv *priv = hw->priv; 1740 1741 if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { 1742 mwl8k_setup_2ghz_band(hw); 1743 if (caps & MWL8K_CAP_MIMO) 1744 mwl8k_set_ht_caps(hw, &priv->band_24, caps); 1745 } 1746 1747 if (caps & MWL8K_CAP_5GHZ) { 1748 mwl8k_setup_5ghz_band(hw); 1749 if (caps & MWL8K_CAP_MIMO) 1750 mwl8k_set_ht_caps(hw, &priv->band_50, caps); 1751 } 1752} 1753 1754static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) 1755{ 1756 struct mwl8k_priv *priv = hw->priv; 1757 struct mwl8k_cmd_get_hw_spec_sta *cmd; 1758 int rc; 1759 int i; 1760 1761 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 1762 if (cmd == NULL) 1763 return -ENOMEM; 1764 1765 cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC); 1766 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 1767 1768 memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); 1769 cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); 1770 cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); 1771 cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); 1772 for (i = 0; i < MWL8K_TX_QUEUES; i++) 1773 cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); 1774 cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); 1775 cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); 1776 1777 rc = mwl8k_post_cmd(hw, &cmd->header); 1778 1779 if (!rc) { 1780 SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); 1781 priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); 1782 priv->fw_rev = le32_to_cpu(cmd->fw_rev); 1783 priv->hw_rev = cmd->hw_rev; 1784 mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); 1785 priv->ap_macids_supported = 0x00000000; 1786 priv->sta_macids_supported = 0x00000001; 1787 } 1788 1789 kfree(cmd); 1790 return rc; 1791} 1792 1793/* 1794 * CMD_GET_HW_SPEC (AP version). 1795 */ 1796struct mwl8k_cmd_get_hw_spec_ap { 1797 struct mwl8k_cmd_pkt header; 1798 __u8 hw_rev; 1799 __u8 host_interface; 1800 __le16 num_wcb; 1801 __le16 num_mcaddrs; 1802 __u8 perm_addr[ETH_ALEN]; 1803 __le16 region_code; 1804 __le16 num_antenna; 1805 __le32 fw_rev; 1806 __le32 wcbbase0; 1807 __le32 rxwrptr; 1808 __le32 rxrdptr; 1809 __le32 ps_cookie; 1810 __le32 wcbbase1; 1811 __le32 wcbbase2; 1812 __le32 wcbbase3; 1813} __attribute__((packed)); 1814 1815static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) 1816{ 1817 struct mwl8k_priv *priv = hw->priv; 1818 struct mwl8k_cmd_get_hw_spec_ap *cmd; 1819 int rc; 1820 1821 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 1822 if (cmd == NULL) 1823 return -ENOMEM; 1824 1825 cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC); 1826 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 1827 1828 memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); 1829 cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); 1830 1831 rc = mwl8k_post_cmd(hw, &cmd->header); 1832 1833 if (!rc) { 1834 int off; 1835 1836 SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); 1837 priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); 1838 priv->fw_rev = le32_to_cpu(cmd->fw_rev); 1839 priv->hw_rev = cmd->hw_rev; 1840 mwl8k_setup_2ghz_band(hw); 1841 priv->ap_macids_supported = 0x000000ff; 1842 priv->sta_macids_supported = 0x00000000; 1843 1844 off = le32_to_cpu(cmd->wcbbase0) & 0xffff; 1845 iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); 1846 1847 off = le32_to_cpu(cmd->rxwrptr) & 0xffff; 1848 iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off); 1849 1850 off = le32_to_cpu(cmd->rxrdptr) & 0xffff; 1851 iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off); 1852 1853 off = le32_to_cpu(cmd->wcbbase1) & 0xffff; 1854 iowrite32(cpu_to_le32(priv->txq[1].txd_dma), priv->sram + off); 1855 1856 off = le32_to_cpu(cmd->wcbbase2) & 0xffff; 1857 iowrite32(cpu_to_le32(priv->txq[2].txd_dma), priv->sram + off); 1858 1859 off = le32_to_cpu(cmd->wcbbase3) & 0xffff; 1860 iowrite32(cpu_to_le32(priv->txq[3].txd_dma), priv->sram + off); 1861 } 1862 1863 kfree(cmd); 1864 return rc; 1865} 1866 1867/* 1868 * CMD_SET_HW_SPEC. 1869 */ 1870struct mwl8k_cmd_set_hw_spec { 1871 struct mwl8k_cmd_pkt header; 1872 __u8 hw_rev; 1873 __u8 host_interface; 1874 __le16 num_mcaddrs; 1875 __u8 perm_addr[ETH_ALEN]; 1876 __le16 region_code; 1877 __le32 fw_rev; 1878 __le32 ps_cookie; 1879 __le32 caps; 1880 __le32 rx_queue_ptr; 1881 __le32 num_tx_queues; 1882 __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; 1883 __le32 flags; 1884 __le32 num_tx_desc_per_queue; 1885 __le32 total_rxd; 1886} __attribute__((packed)); 1887 1888#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 1889#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 1890#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 1891 1892static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) 1893{ 1894 struct mwl8k_priv *priv = hw->priv; 1895 struct mwl8k_cmd_set_hw_spec *cmd; 1896 int rc; 1897 int i; 1898 1899 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 1900 if (cmd == NULL) 1901 return -ENOMEM; 1902 1903 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_HW_SPEC); 1904 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 1905 1906 cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); 1907 cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); 1908 cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); 1909 for (i = 0; i < MWL8K_TX_QUEUES; i++) 1910 cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); 1911 cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | 1912 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | 1913 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON); 1914 cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); 1915 cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); 1916 1917 rc = mwl8k_post_cmd(hw, &cmd->header); 1918 kfree(cmd); 1919 1920 return rc; 1921} 1922 1923/* 1924 * CMD_MAC_MULTICAST_ADR. 1925 */ 1926struct mwl8k_cmd_mac_multicast_adr { 1927 struct mwl8k_cmd_pkt header; 1928 __le16 action; 1929 __le16 numaddr; 1930 __u8 addr[0][ETH_ALEN]; 1931}; 1932 1933#define MWL8K_ENABLE_RX_DIRECTED 0x0001 1934#define MWL8K_ENABLE_RX_MULTICAST 0x0002 1935#define MWL8K_ENABLE_RX_ALL_MULTICAST 0x0004 1936#define MWL8K_ENABLE_RX_BROADCAST 0x0008 1937 1938static struct mwl8k_cmd_pkt * 1939__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, 1940 struct netdev_hw_addr_list *mc_list) 1941{ 1942 struct mwl8k_priv *priv = hw->priv; 1943 struct mwl8k_cmd_mac_multicast_adr *cmd; 1944 int size; 1945 int mc_count = 0; 1946 1947 if (mc_list) 1948 mc_count = netdev_hw_addr_list_count(mc_list); 1949 1950 if (allmulti || mc_count > priv->num_mcaddrs) { 1951 allmulti = 1; 1952 mc_count = 0; 1953 } 1954 1955 size = sizeof(*cmd) + mc_count * ETH_ALEN; 1956 1957 cmd = kzalloc(size, GFP_ATOMIC); 1958 if (cmd == NULL) 1959 return NULL; 1960 1961 cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); 1962 cmd->header.length = cpu_to_le16(size); 1963 cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_DIRECTED | 1964 MWL8K_ENABLE_RX_BROADCAST); 1965 1966 if (allmulti) { 1967 cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST); 1968 } else if (mc_count) { 1969 struct netdev_hw_addr *ha; 1970 int i = 0; 1971 1972 cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); 1973 cmd->numaddr = cpu_to_le16(mc_count); 1974 netdev_hw_addr_list_for_each(ha, mc_list) { 1975 memcpy(cmd->addr[i], ha->addr, ETH_ALEN); 1976 } 1977 } 1978 1979 return &cmd->header; 1980} 1981 1982/* 1983 * CMD_GET_STAT. 1984 */ 1985struct mwl8k_cmd_get_stat { 1986 struct mwl8k_cmd_pkt header; 1987 __le32 stats[64]; 1988} __attribute__((packed)); 1989 1990#define MWL8K_STAT_ACK_FAILURE 9 1991#define MWL8K_STAT_RTS_FAILURE 12 1992#define MWL8K_STAT_FCS_ERROR 24 1993#define MWL8K_STAT_RTS_SUCCESS 11 1994 1995static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw, 1996 struct ieee80211_low_level_stats *stats) 1997{ 1998 struct mwl8k_cmd_get_stat *cmd; 1999 int rc; 2000 2001 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2002 if (cmd == NULL) 2003 return -ENOMEM; 2004 2005 cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT); 2006 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2007 2008 rc = mwl8k_post_cmd(hw, &cmd->header); 2009 if (!rc) { 2010 stats->dot11ACKFailureCount = 2011 le32_to_cpu(cmd->stats[MWL8K_STAT_ACK_FAILURE]); 2012 stats->dot11RTSFailureCount = 2013 le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_FAILURE]); 2014 stats->dot11FCSErrorCount = 2015 le32_to_cpu(cmd->stats[MWL8K_STAT_FCS_ERROR]); 2016 stats->dot11RTSSuccessCount = 2017 le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_SUCCESS]); 2018 } 2019 kfree(cmd); 2020 2021 return rc; 2022} 2023 2024/* 2025 * CMD_RADIO_CONTROL. 2026 */ 2027struct mwl8k_cmd_radio_control { 2028 struct mwl8k_cmd_pkt header; 2029 __le16 action; 2030 __le16 control; 2031 __le16 radio_on; 2032} __attribute__((packed)); 2033 2034static int 2035mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force) 2036{ 2037 struct mwl8k_priv *priv = hw->priv; 2038 struct mwl8k_cmd_radio_control *cmd; 2039 int rc; 2040 2041 if (enable == priv->radio_on && !force) 2042 return 0; 2043 2044 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2045 if (cmd == NULL) 2046 return -ENOMEM; 2047 2048 cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL); 2049 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2050 cmd->action = cpu_to_le16(MWL8K_CMD_SET); 2051 cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1); 2052 cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000); 2053 2054 rc = mwl8k_post_cmd(hw, &cmd->header); 2055 kfree(cmd); 2056 2057 if (!rc) 2058 priv->radio_on = enable; 2059 2060 return rc; 2061} 2062 2063static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw) 2064{ 2065 return mwl8k_cmd_radio_control(hw, 0, 0); 2066} 2067 2068static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw) 2069{ 2070 return mwl8k_cmd_radio_control(hw, 1, 0); 2071} 2072 2073static int 2074mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) 2075{ 2076 struct mwl8k_priv *priv = hw->priv; 2077 2078 priv->radio_short_preamble = short_preamble; 2079 2080 return mwl8k_cmd_radio_control(hw, 1, 1); 2081} 2082 2083/* 2084 * CMD_RF_TX_POWER. 2085 */ 2086#define MWL8K_TX_POWER_LEVEL_TOTAL 8 2087 2088struct mwl8k_cmd_rf_tx_power { 2089 struct mwl8k_cmd_pkt header; 2090 __le16 action; 2091 __le16 support_level; 2092 __le16 current_level; 2093 __le16 reserved; 2094 __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; 2095} __attribute__((packed)); 2096 2097static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) 2098{ 2099 struct mwl8k_cmd_rf_tx_power *cmd; 2100 int rc; 2101 2102 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2103 if (cmd == NULL) 2104 return -ENOMEM; 2105 2106 cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_TX_POWER); 2107 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2108 cmd->action = cpu_to_le16(MWL8K_CMD_SET); 2109 cmd->support_level = cpu_to_le16(dBm); 2110 2111 rc = mwl8k_post_cmd(hw, &cmd->header); 2112 kfree(cmd); 2113 2114 return rc; 2115} 2116 2117/* 2118 * CMD_RF_ANTENNA. 2119 */ 2120struct mwl8k_cmd_rf_antenna { 2121 struct mwl8k_cmd_pkt header; 2122 __le16 antenna; 2123 __le16 mode; 2124} __attribute__((packed)); 2125 2126#define MWL8K_RF_ANTENNA_RX 1 2127#define MWL8K_RF_ANTENNA_TX 2 2128 2129static int 2130mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask) 2131{ 2132 struct mwl8k_cmd_rf_antenna *cmd; 2133 int rc; 2134 2135 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2136 if (cmd == NULL) 2137 return -ENOMEM; 2138 2139 cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_ANTENNA); 2140 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2141 cmd->antenna = cpu_to_le16(antenna); 2142 cmd->mode = cpu_to_le16(mask); 2143 2144 rc = mwl8k_post_cmd(hw, &cmd->header); 2145 kfree(cmd); 2146 2147 return rc; 2148} 2149 2150/* 2151 * CMD_SET_BEACON. 2152 */ 2153struct mwl8k_cmd_set_beacon { 2154 struct mwl8k_cmd_pkt header; 2155 __le16 beacon_len; 2156 __u8 beacon[0]; 2157}; 2158 2159static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, 2160 struct ieee80211_vif *vif, u8 *beacon, int len) 2161{ 2162 struct mwl8k_cmd_set_beacon *cmd; 2163 int rc; 2164 2165 cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL); 2166 if (cmd == NULL) 2167 return -ENOMEM; 2168 2169 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON); 2170 cmd->header.length = cpu_to_le16(sizeof(*cmd) + len); 2171 cmd->beacon_len = cpu_to_le16(len); 2172 memcpy(cmd->beacon, beacon, len); 2173 2174 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); 2175 kfree(cmd); 2176 2177 return rc; 2178} 2179 2180/* 2181 * CMD_SET_PRE_SCAN. 2182 */ 2183struct mwl8k_cmd_set_pre_scan { 2184 struct mwl8k_cmd_pkt header; 2185} __attribute__((packed)); 2186 2187static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw) 2188{ 2189 struct mwl8k_cmd_set_pre_scan *cmd; 2190 int rc; 2191 2192 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2193 if (cmd == NULL) 2194 return -ENOMEM; 2195 2196 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_PRE_SCAN); 2197 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2198 2199 rc = mwl8k_post_cmd(hw, &cmd->header); 2200 kfree(cmd); 2201 2202 return rc; 2203} 2204 2205/* 2206 * CMD_SET_POST_SCAN. 2207 */ 2208struct mwl8k_cmd_set_post_scan { 2209 struct mwl8k_cmd_pkt header; 2210 __le32 isibss; 2211 __u8 bssid[ETH_ALEN]; 2212} __attribute__((packed)); 2213 2214static int 2215mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac) 2216{ 2217 struct mwl8k_cmd_set_post_scan *cmd; 2218 int rc; 2219 2220 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2221 if (cmd == NULL) 2222 return -ENOMEM; 2223 2224 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN); 2225 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2226 cmd->isibss = 0; 2227 memcpy(cmd->bssid, mac, ETH_ALEN); 2228 2229 rc = mwl8k_post_cmd(hw, &cmd->header); 2230 kfree(cmd); 2231 2232 return rc; 2233} 2234 2235/* 2236 * CMD_SET_RF_CHANNEL. 2237 */ 2238struct mwl8k_cmd_set_rf_channel { 2239 struct mwl8k_cmd_pkt header; 2240 __le16 action; 2241 __u8 current_channel; 2242 __le32 channel_flags; 2243} __attribute__((packed)); 2244 2245static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, 2246 struct ieee80211_conf *conf) 2247{ 2248 struct ieee80211_channel *channel = conf->channel; 2249 struct mwl8k_cmd_set_rf_channel *cmd; 2250 int rc; 2251 2252 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2253 if (cmd == NULL) 2254 return -ENOMEM; 2255 2256 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RF_CHANNEL); 2257 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2258 cmd->action = cpu_to_le16(MWL8K_CMD_SET); 2259 cmd->current_channel = channel->hw_value; 2260 2261 if (channel->band == IEEE80211_BAND_2GHZ) 2262 cmd->channel_flags |= cpu_to_le32(0x00000001); 2263 else if (channel->band == IEEE80211_BAND_5GHZ) 2264 cmd->channel_flags |= cpu_to_le32(0x00000004); 2265 2266 if (conf->channel_type == NL80211_CHAN_NO_HT || 2267 conf->channel_type == NL80211_CHAN_HT20) 2268 cmd->channel_flags |= cpu_to_le32(0x00000080); 2269 else if (conf->channel_type == NL80211_CHAN_HT40MINUS) 2270 cmd->channel_flags |= cpu_to_le32(0x000001900); 2271 else if (conf->channel_type == NL80211_CHAN_HT40PLUS) 2272 cmd->channel_flags |= cpu_to_le32(0x000000900); 2273 2274 rc = mwl8k_post_cmd(hw, &cmd->header); 2275 kfree(cmd); 2276 2277 return rc; 2278} 2279 2280/* 2281 * CMD_SET_AID. 2282 */ 2283#define MWL8K_FRAME_PROT_DISABLED 0x00 2284#define MWL8K_FRAME_PROT_11G 0x07 2285#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 2286#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 2287 2288struct mwl8k_cmd_update_set_aid { 2289 struct mwl8k_cmd_pkt header; 2290 __le16 aid; 2291 2292 /* AP's MAC address (BSSID) */ 2293 __u8 bssid[ETH_ALEN]; 2294 __le16 protection_mode; 2295 __u8 supp_rates[14]; 2296} __attribute__((packed)); 2297 2298static void legacy_rate_mask_to_array(u8 *rates, u32 mask) 2299{ 2300 int i; 2301 int j; 2302 2303 /* 2304 * Clear nonstandard rates 4 and 13. 2305 */ 2306 mask &= 0x1fef; 2307 2308 for (i = 0, j = 0; i < 14; i++) { 2309 if (mask & (1 << i)) 2310 rates[j++] = mwl8k_rates_24[i].hw_value; 2311 } 2312} 2313 2314static int 2315mwl8k_cmd_set_aid(struct ieee80211_hw *hw, 2316 struct ieee80211_vif *vif, u32 legacy_rate_mask) 2317{ 2318 struct mwl8k_cmd_update_set_aid *cmd; 2319 u16 prot_mode; 2320 int rc; 2321 2322 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2323 if (cmd == NULL) 2324 return -ENOMEM; 2325 2326 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); 2327 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2328 cmd->aid = cpu_to_le16(vif->bss_conf.aid); 2329 memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); 2330 2331 if (vif->bss_conf.use_cts_prot) { 2332 prot_mode = MWL8K_FRAME_PROT_11G; 2333 } else { 2334 switch (vif->bss_conf.ht_operation_mode & 2335 IEEE80211_HT_OP_MODE_PROTECTION) { 2336 case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: 2337 prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; 2338 break; 2339 case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: 2340 prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; 2341 break; 2342 default: 2343 prot_mode = MWL8K_FRAME_PROT_DISABLED; 2344 break; 2345 } 2346 } 2347 cmd->protection_mode = cpu_to_le16(prot_mode); 2348 2349 legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask); 2350 2351 rc = mwl8k_post_cmd(hw, &cmd->header); 2352 kfree(cmd); 2353 2354 return rc; 2355} 2356 2357/* 2358 * CMD_SET_RATE. 2359 */ 2360struct mwl8k_cmd_set_rate { 2361 struct mwl8k_cmd_pkt header; 2362 __u8 legacy_rates[14]; 2363 2364 /* Bitmap for supported MCS codes. */ 2365 __u8 mcs_set[16]; 2366 __u8 reserved[16]; 2367} __attribute__((packed)); 2368 2369static int 2370mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2371 u32 legacy_rate_mask, u8 *mcs_rates) 2372{ 2373 struct mwl8k_cmd_set_rate *cmd; 2374 int rc; 2375 2376 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2377 if (cmd == NULL) 2378 return -ENOMEM; 2379 2380 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); 2381 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2382 legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask); 2383 memcpy(cmd->mcs_set, mcs_rates, 16); 2384 2385 rc = mwl8k_post_cmd(hw, &cmd->header); 2386 kfree(cmd); 2387 2388 return rc; 2389} 2390 2391/* 2392 * CMD_FINALIZE_JOIN. 2393 */ 2394#define MWL8K_FJ_BEACON_MAXLEN 128 2395 2396struct mwl8k_cmd_finalize_join { 2397 struct mwl8k_cmd_pkt header; 2398 __le32 sleep_interval; /* Number of beacon periods to sleep */ 2399 __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; 2400} __attribute__((packed)); 2401 2402static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame, 2403 int framelen, int dtim) 2404{ 2405 struct mwl8k_cmd_finalize_join *cmd; 2406 struct ieee80211_mgmt *payload = frame; 2407 int payload_len; 2408 int rc; 2409 2410 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2411 if (cmd == NULL) 2412 return -ENOMEM; 2413 2414 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); 2415 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2416 cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); 2417 2418 payload_len = framelen - ieee80211_hdrlen(payload->frame_control); 2419 if (payload_len < 0) 2420 payload_len = 0; 2421 else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) 2422 payload_len = MWL8K_FJ_BEACON_MAXLEN; 2423 2424 memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); 2425 2426 rc = mwl8k_post_cmd(hw, &cmd->header); 2427 kfree(cmd); 2428 2429 return rc; 2430} 2431 2432/* 2433 * CMD_SET_RTS_THRESHOLD. 2434 */ 2435struct mwl8k_cmd_set_rts_threshold { 2436 struct mwl8k_cmd_pkt header; 2437 __le16 action; 2438 __le16 threshold; 2439} __attribute__((packed)); 2440 2441static int 2442mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh) 2443{ 2444 struct mwl8k_cmd_set_rts_threshold *cmd; 2445 int rc; 2446 2447 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2448 if (cmd == NULL) 2449 return -ENOMEM; 2450 2451 cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); 2452 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2453 cmd->action = cpu_to_le16(MWL8K_CMD_SET); 2454 cmd->threshold = cpu_to_le16(rts_thresh); 2455 2456 rc = mwl8k_post_cmd(hw, &cmd->header); 2457 kfree(cmd); 2458 2459 return rc; 2460} 2461 2462/* 2463 * CMD_SET_SLOT. 2464 */ 2465struct mwl8k_cmd_set_slot { 2466 struct mwl8k_cmd_pkt header; 2467 __le16 action; 2468 __u8 short_slot; 2469} __attribute__((packed)); 2470 2471static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) 2472{ 2473 struct mwl8k_cmd_set_slot *cmd; 2474 int rc; 2475 2476 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2477 if (cmd == NULL) 2478 return -ENOMEM; 2479 2480 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); 2481 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2482 cmd->action = cpu_to_le16(MWL8K_CMD_SET); 2483 cmd->short_slot = short_slot_time; 2484 2485 rc = mwl8k_post_cmd(hw, &cmd->header); 2486 kfree(cmd); 2487 2488 return rc; 2489} 2490 2491/* 2492 * CMD_SET_EDCA_PARAMS. 2493 */ 2494struct mwl8k_cmd_set_edca_params { 2495 struct mwl8k_cmd_pkt header; 2496 2497 /* See MWL8K_SET_EDCA_XXX below */ 2498 __le16 action; 2499 2500 /* TX opportunity in units of 32 us */ 2501 __le16 txop; 2502 2503 union { 2504 struct { 2505 /* Log exponent of max contention period: 0...15 */ 2506 __le32 log_cw_max; 2507 2508 /* Log exponent of min contention period: 0...15 */ 2509 __le32 log_cw_min; 2510 2511 /* Adaptive interframe spacing in units of 32us */ 2512 __u8 aifs; 2513 2514 /* TX queue to configure */ 2515 __u8 txq; 2516 } ap; 2517 struct { 2518 /* Log exponent of max contention period: 0...15 */ 2519 __u8 log_cw_max; 2520 2521 /* Log exponent of min contention period: 0...15 */ 2522 __u8 log_cw_min; 2523 2524 /* Adaptive interframe spacing in units of 32us */ 2525 __u8 aifs; 2526 2527 /* TX queue to configure */ 2528 __u8 txq; 2529 } sta; 2530 }; 2531} __attribute__((packed)); 2532 2533#define MWL8K_SET_EDCA_CW 0x01 2534#define MWL8K_SET_EDCA_TXOP 0x02 2535#define MWL8K_SET_EDCA_AIFS 0x04 2536 2537#define MWL8K_SET_EDCA_ALL (MWL8K_SET_EDCA_CW | \ 2538 MWL8K_SET_EDCA_TXOP | \ 2539 MWL8K_SET_EDCA_AIFS) 2540 2541static int 2542mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, 2543 __u16 cw_min, __u16 cw_max, 2544 __u8 aifs, __u16 txop) 2545{ 2546 struct mwl8k_priv *priv = hw->priv; 2547 struct mwl8k_cmd_set_edca_params *cmd; 2548 int rc; 2549 2550 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2551 if (cmd == NULL) 2552 return -ENOMEM; 2553 2554 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); 2555 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2556 cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); 2557 cmd->txop = cpu_to_le16(txop); 2558 if (priv->ap_fw) { 2559 cmd->ap.log_cw_max = cpu_to_le32(ilog2(cw_max + 1)); 2560 cmd->ap.log_cw_min = cpu_to_le32(ilog2(cw_min + 1)); 2561 cmd->ap.aifs = aifs; 2562 cmd->ap.txq = qnum; 2563 } else { 2564 cmd->sta.log_cw_max = (u8)ilog2(cw_max + 1); 2565 cmd->sta.log_cw_min = (u8)ilog2(cw_min + 1); 2566 cmd->sta.aifs = aifs; 2567 cmd->sta.txq = qnum; 2568 } 2569 2570 rc = mwl8k_post_cmd(hw, &cmd->header); 2571 kfree(cmd); 2572 2573 return rc; 2574} 2575 2576/* 2577 * CMD_SET_WMM_MODE. 2578 */ 2579struct mwl8k_cmd_set_wmm_mode { 2580 struct mwl8k_cmd_pkt header; 2581 __le16 action; 2582} __attribute__((packed)); 2583 2584static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) 2585{ 2586 struct mwl8k_priv *priv = hw->priv; 2587 struct mwl8k_cmd_set_wmm_mode *cmd; 2588 int rc; 2589 2590 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2591 if (cmd == NULL) 2592 return -ENOMEM; 2593 2594 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); 2595 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2596 cmd->action = cpu_to_le16(!!enable); 2597 2598 rc = mwl8k_post_cmd(hw, &cmd->header); 2599 kfree(cmd); 2600 2601 if (!rc) 2602 priv->wmm_enabled = enable; 2603 2604 return rc; 2605} 2606 2607/* 2608 * CMD_MIMO_CONFIG. 2609 */ 2610struct mwl8k_cmd_mimo_config { 2611 struct mwl8k_cmd_pkt header; 2612 __le32 action; 2613 __u8 rx_antenna_map; 2614 __u8 tx_antenna_map; 2615} __attribute__((packed)); 2616 2617static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) 2618{ 2619 struct mwl8k_cmd_mimo_config *cmd; 2620 int rc; 2621 2622 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2623 if (cmd == NULL) 2624 return -ENOMEM; 2625 2626 cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); 2627 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2628 cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); 2629 cmd->rx_antenna_map = rx; 2630 cmd->tx_antenna_map = tx; 2631 2632 rc = mwl8k_post_cmd(hw, &cmd->header); 2633 kfree(cmd); 2634 2635 return rc; 2636} 2637 2638/* 2639 * CMD_USE_FIXED_RATE (STA version). 2640 */ 2641struct mwl8k_cmd_use_fixed_rate_sta { 2642 struct mwl8k_cmd_pkt header; 2643 __le32 action; 2644 __le32 allow_rate_drop; 2645 __le32 num_rates; 2646 struct { 2647 __le32 is_ht_rate; 2648 __le32 enable_retry; 2649 __le32 rate; 2650 __le32 retry_count; 2651 } rate_entry[8]; 2652 __le32 rate_type; 2653 __le32 reserved1; 2654 __le32 reserved2; 2655} __attribute__((packed)); 2656 2657#define MWL8K_USE_AUTO_RATE 0x0002 2658#define MWL8K_UCAST_RATE 0 2659 2660static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw) 2661{ 2662 struct mwl8k_cmd_use_fixed_rate_sta *cmd; 2663 int rc; 2664 2665 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2666 if (cmd == NULL) 2667 return -ENOMEM; 2668 2669 cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); 2670 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2671 cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE); 2672 cmd->rate_type = cpu_to_le32(MWL8K_UCAST_RATE); 2673 2674 rc = mwl8k_post_cmd(hw, &cmd->header); 2675 kfree(cmd); 2676 2677 return rc; 2678} 2679 2680/* 2681 * CMD_USE_FIXED_RATE (AP version). 2682 */ 2683struct mwl8k_cmd_use_fixed_rate_ap { 2684 struct mwl8k_cmd_pkt header; 2685 __le32 action; 2686 __le32 allow_rate_drop; 2687 __le32 num_rates; 2688 struct mwl8k_rate_entry_ap { 2689 __le32 is_ht_rate; 2690 __le32 enable_retry; 2691 __le32 rate; 2692 __le32 retry_count; 2693 } rate_entry[4]; 2694 u8 multicast_rate; 2695 u8 multicast_rate_type; 2696 u8 management_rate; 2697} __attribute__((packed)); 2698 2699static int 2700mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt) 2701{ 2702 struct mwl8k_cmd_use_fixed_rate_ap *cmd; 2703 int rc; 2704 2705 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2706 if (cmd == NULL) 2707 return -ENOMEM; 2708 2709 cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); 2710 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2711 cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE); 2712 cmd->multicast_rate = mcast; 2713 cmd->management_rate = mgmt; 2714 2715 rc = mwl8k_post_cmd(hw, &cmd->header); 2716 kfree(cmd); 2717 2718 return rc; 2719} 2720 2721/* 2722 * CMD_ENABLE_SNIFFER. 2723 */ 2724struct mwl8k_cmd_enable_sniffer { 2725 struct mwl8k_cmd_pkt header; 2726 __le32 action; 2727} __attribute__((packed)); 2728 2729static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) 2730{ 2731 struct mwl8k_cmd_enable_sniffer *cmd; 2732 int rc; 2733 2734 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2735 if (cmd == NULL) 2736 return -ENOMEM; 2737 2738 cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); 2739 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2740 cmd->action = cpu_to_le32(!!enable); 2741 2742 rc = mwl8k_post_cmd(hw, &cmd->header); 2743 kfree(cmd); 2744 2745 return rc; 2746} 2747 2748/* 2749 * CMD_SET_MAC_ADDR. 2750 */ 2751struct mwl8k_cmd_set_mac_addr { 2752 struct mwl8k_cmd_pkt header; 2753 union { 2754 struct { 2755 __le16 mac_type; 2756 __u8 mac_addr[ETH_ALEN]; 2757 } mbss; 2758 __u8 mac_addr[ETH_ALEN]; 2759 }; 2760} __attribute__((packed)); 2761 2762#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 2763#define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1 2764#define MWL8K_MAC_TYPE_PRIMARY_AP 2 2765#define MWL8K_MAC_TYPE_SECONDARY_AP 3 2766 2767static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, 2768 struct ieee80211_vif *vif, u8 *mac) 2769{ 2770 struct mwl8k_priv *priv = hw->priv; 2771 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); 2772 struct mwl8k_cmd_set_mac_addr *cmd; 2773 int mac_type; 2774 int rc; 2775 2776 mac_type = MWL8K_MAC_TYPE_PRIMARY_AP; 2777 if (vif != NULL && vif->type == NL80211_IFTYPE_STATION) { 2778 if (mwl8k_vif->macid + 1 == ffs(priv->sta_macids_supported)) 2779 mac_type = MWL8K_MAC_TYPE_PRIMARY_CLIENT; 2780 else 2781 mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT; 2782 } else if (vif != NULL && vif->type == NL80211_IFTYPE_AP) { 2783 if (mwl8k_vif->macid + 1 == ffs(priv->ap_macids_supported)) 2784 mac_type = MWL8K_MAC_TYPE_PRIMARY_AP; 2785 else 2786 mac_type = MWL8K_MAC_TYPE_SECONDARY_AP; 2787 } 2788 2789 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2790 if (cmd == NULL) 2791 return -ENOMEM; 2792 2793 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); 2794 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2795 if (priv->ap_fw) { 2796 cmd->mbss.mac_type = cpu_to_le16(mac_type); 2797 memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); 2798 } else { 2799 memcpy(cmd->mac_addr, mac, ETH_ALEN); 2800 } 2801 2802 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); 2803 kfree(cmd); 2804 2805 return rc; 2806} 2807 2808/* 2809 * CMD_SET_RATEADAPT_MODE. 2810 */ 2811struct mwl8k_cmd_set_rate_adapt_mode { 2812 struct mwl8k_cmd_pkt header; 2813 __le16 action; 2814 __le16 mode; 2815} __attribute__((packed)); 2816 2817static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) 2818{ 2819 struct mwl8k_cmd_set_rate_adapt_mode *cmd; 2820 int rc; 2821 2822 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2823 if (cmd == NULL) 2824 return -ENOMEM; 2825 2826 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); 2827 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2828 cmd->action = cpu_to_le16(MWL8K_CMD_SET); 2829 cmd->mode = cpu_to_le16(mode); 2830 2831 rc = mwl8k_post_cmd(hw, &cmd->header); 2832 kfree(cmd); 2833 2834 return rc; 2835} 2836 2837/* 2838 * CMD_BSS_START. 2839 */ 2840struct mwl8k_cmd_bss_start { 2841 struct mwl8k_cmd_pkt header; 2842 __le32 enable; 2843} __attribute__((packed)); 2844 2845static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, 2846 struct ieee80211_vif *vif, int enable) 2847{ 2848 struct mwl8k_cmd_bss_start *cmd; 2849 int rc; 2850 2851 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2852 if (cmd == NULL) 2853 return -ENOMEM; 2854 2855 cmd->header.code = cpu_to_le16(MWL8K_CMD_BSS_START); 2856 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2857 cmd->enable = cpu_to_le32(enable); 2858 2859 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); 2860 kfree(cmd); 2861 2862 return rc; 2863} 2864 2865/* 2866 * CMD_SET_NEW_STN. 2867 */ 2868struct mwl8k_cmd_set_new_stn { 2869 struct mwl8k_cmd_pkt header; 2870 __le16 aid; 2871 __u8 mac_addr[6]; 2872 __le16 stn_id; 2873 __le16 action; 2874 __le16 rsvd; 2875 __le32 legacy_rates; 2876 __u8 ht_rates[4]; 2877 __le16 cap_info; 2878 __le16 ht_capabilities_info; 2879 __u8 mac_ht_param_info; 2880 __u8 rev; 2881 __u8 control_channel; 2882 __u8 add_channel; 2883 __le16 op_mode; 2884 __le16 stbc; 2885 __u8 add_qos_info; 2886 __u8 is_qos_sta; 2887 __le32 fw_sta_ptr; 2888} __attribute__((packed)); 2889 2890#define MWL8K_STA_ACTION_ADD 0 2891#define MWL8K_STA_ACTION_REMOVE 2 2892 2893static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, 2894 struct ieee80211_vif *vif, 2895 struct ieee80211_sta *sta) 2896{ 2897 struct mwl8k_cmd_set_new_stn *cmd; 2898 u32 rates; 2899 int rc; 2900 2901 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2902 if (cmd == NULL) 2903 return -ENOMEM; 2904 2905 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); 2906 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2907 cmd->aid = cpu_to_le16(sta->aid); 2908 memcpy(cmd->mac_addr, sta->addr, ETH_ALEN); 2909 cmd->stn_id = cpu_to_le16(sta->aid); 2910 cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD); 2911 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) 2912 rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; 2913 else 2914 rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; 2915 cmd->legacy_rates = cpu_to_le32(rates); 2916 if (sta->ht_cap.ht_supported) { 2917 cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0]; 2918 cmd->ht_rates[1] = sta->ht_cap.mcs.rx_mask[1]; 2919 cmd->ht_rates[2] = sta->ht_cap.mcs.rx_mask[2]; 2920 cmd->ht_rates[3] = sta->ht_cap.mcs.rx_mask[3]; 2921 cmd->ht_capabilities_info = cpu_to_le16(sta->ht_cap.cap); 2922 cmd->mac_ht_param_info = (sta->ht_cap.ampdu_factor & 3) | 2923 ((sta->ht_cap.ampdu_density & 7) << 2); 2924 cmd->is_qos_sta = 1; 2925 } 2926 2927 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); 2928 kfree(cmd); 2929 2930 return rc; 2931} 2932 2933static int mwl8k_cmd_set_new_stn_add_self(struct ieee80211_hw *hw, 2934 struct ieee80211_vif *vif) 2935{ 2936 struct mwl8k_cmd_set_new_stn *cmd; 2937 int rc; 2938 2939 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2940 if (cmd == NULL) 2941 return -ENOMEM; 2942 2943 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); 2944 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2945 memcpy(cmd->mac_addr, vif->addr, ETH_ALEN); 2946 2947 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); 2948 kfree(cmd); 2949 2950 return rc; 2951} 2952 2953static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw, 2954 struct ieee80211_vif *vif, u8 *addr) 2955{ 2956 struct mwl8k_cmd_set_new_stn *cmd; 2957 int rc; 2958 2959 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2960 if (cmd == NULL) 2961 return -ENOMEM; 2962 2963 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); 2964 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 2965 memcpy(cmd->mac_addr, addr, ETH_ALEN); 2966 cmd->action = cpu_to_le16(MWL8K_STA_ACTION_REMOVE); 2967 2968 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); 2969 kfree(cmd); 2970 2971 return rc; 2972} 2973 2974/* 2975 * CMD_UPDATE_STADB. 2976 */ 2977struct ewc_ht_info { 2978 __le16 control1; 2979 __le16 control2; 2980 __le16 control3; 2981} __attribute__((packed)); 2982 2983struct peer_capability_info { 2984 /* Peer type - AP vs. STA. */ 2985 __u8 peer_type; 2986 2987 /* Basic 802.11 capabilities from assoc resp. */ 2988 __le16 basic_caps; 2989 2990 /* Set if peer supports 802.11n high throughput (HT). */ 2991 __u8 ht_support; 2992 2993 /* Valid if HT is supported. */ 2994 __le16 ht_caps; 2995 __u8 extended_ht_caps; 2996 struct ewc_ht_info ewc_info; 2997 2998 /* Legacy rate table. Intersection of our rates and peer rates. */ 2999 __u8 legacy_rates[12]; 3000 3001 /* HT rate table. Intersection of our rates and peer rates. */ 3002 __u8 ht_rates[16]; 3003 __u8 pad[16]; 3004 3005 /* If set, interoperability mode, no proprietary extensions. */ 3006 __u8 interop; 3007 __u8 pad2; 3008 __u8 station_id; 3009 __le16 amsdu_enabled; 3010} __attribute__((packed)); 3011 3012struct mwl8k_cmd_update_stadb { 3013 struct mwl8k_cmd_pkt header; 3014 3015 /* See STADB_ACTION_TYPE */ 3016 __le32 action; 3017 3018 /* Peer MAC address */ 3019 __u8 peer_addr[ETH_ALEN]; 3020 3021 __le32 reserved; 3022 3023 /* Peer info - valid during add/update. */ 3024 struct peer_capability_info peer_info; 3025} __attribute__((packed)); 3026 3027#define MWL8K_STA_DB_MODIFY_ENTRY 1 3028#define MWL8K_STA_DB_DEL_ENTRY 2 3029 3030/* Peer Entry flags - used to define the type of the peer node */ 3031#define MWL8K_PEER_TYPE_ACCESSPOINT 2 3032 3033static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, 3034 struct ieee80211_vif *vif, 3035 struct ieee80211_sta *sta) 3036{ 3037 struct mwl8k_cmd_update_stadb *cmd; 3038 struct peer_capability_info *p; 3039 u32 rates; 3040 int rc; 3041 3042 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 3043 if (cmd == NULL) 3044 return -ENOMEM; 3045 3046 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); 3047 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 3048 cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY); 3049 memcpy(cmd->peer_addr, sta->addr, ETH_ALEN); 3050 3051 p = &cmd->peer_info; 3052 p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; 3053 p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); 3054 p->ht_support = sta->ht_cap.ht_supported; 3055 p->ht_caps = sta->ht_cap.cap; 3056 p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) | 3057 ((sta->ht_cap.ampdu_density & 7) << 2); 3058 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) 3059 rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; 3060 else 3061 rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; 3062 legacy_rate_mask_to_array(p->legacy_rates, rates); 3063 memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16); 3064 p->interop = 1; 3065 p->amsdu_enabled = 0; 3066 3067 rc = mwl8k_post_cmd(hw, &cmd->header); 3068 kfree(cmd); 3069 3070 return rc ? rc : p->station_id; 3071} 3072 3073static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, 3074 struct ieee80211_vif *vif, u8 *addr) 3075{ 3076 struct mwl8k_cmd_update_stadb *cmd; 3077 int rc; 3078 3079 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 3080 if (cmd == NULL) 3081 return -ENOMEM; 3082 3083 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); 3084 cmd->header.length = cpu_to_le16(sizeof(*cmd)); 3085 cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY); 3086 memcpy(cmd->peer_addr, addr, ETH_ALEN); 3087 3088 rc = mwl8k_post_cmd(hw, &cmd->header); 3089 kfree(cmd); 3090 3091 return rc; 3092} 3093 3094 3095/* 3096 * Interrupt handling. 3097 */ 3098static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) 3099{ 3100 struct ieee80211_hw *hw = dev_id; 3101 struct mwl8k_priv *priv = hw->priv; 3102 u32 status; 3103 3104 status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); 3105 if (!status) 3106 return IRQ_NONE; 3107 3108 if (status & MWL8K_A2H_INT_TX_DONE) { 3109 status &= ~MWL8K_A2H_INT_TX_DONE; 3110 tasklet_schedule(&priv->poll_tx_task); 3111 } 3112 3113 if (status & MWL8K_A2H_INT_RX_READY) { 3114 status &= ~MWL8K_A2H_INT_RX_READY; 3115 tasklet_schedule(&priv->poll_rx_task); 3116 } 3117 3118 if (status) 3119 iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); 3120 3121 if (status & MWL8K_A2H_INT_OPC_DONE) { 3122 if (priv->hostcmd_wait != NULL) 3123 complete(priv->hostcmd_wait); 3124 } 3125 3126 if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { 3127 if (!mutex_is_locked(&priv->fw_mutex) && 3128 priv->radio_on && priv->pending_tx_pkts) 3129 mwl8k_tx_start(priv); 3130 } 3131 3132 return IRQ_HANDLED; 3133} 3134 3135static void mwl8k_tx_poll(unsigned long data) 3136{ 3137 struct ieee80211_hw *hw = (struct ieee80211_hw *)data; 3138 struct mwl8k_priv *priv = hw->priv; 3139 int limit; 3140 int i; 3141 3142 limit = 32; 3143 3144 spin_lock_bh(&priv->tx_lock); 3145 3146 for (i = 0; i < MWL8K_TX_QUEUES; i++) 3147 limit -= mwl8k_txq_reclaim(hw, i, limit, 0); 3148 3149 if (!priv->pending_tx_pkts && priv->tx_wait != NULL) { 3150 complete(priv->tx_wait); 3151 priv->tx_wait = NULL; 3152 } 3153 3154 spin_unlock_bh(&priv->tx_lock); 3155 3156 if (limit) { 3157 writel(~MWL8K_A2H_INT_TX_DONE, 3158 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); 3159 } else { 3160 tasklet_schedule(&priv->poll_tx_task); 3161 } 3162} 3163 3164static void mwl8k_rx_poll(unsigned long data) 3165{ 3166 struct ieee80211_hw *hw = (struct ieee80211_hw *)data; 3167 struct mwl8k_priv *priv = hw->priv; 3168 int limit; 3169 3170 limit = 32; 3171 limit -= rxq_process(hw, 0, limit); 3172 limit -= rxq_refill(hw, 0, limit); 3173 3174 if (limit) { 3175 writel(~MWL8K_A2H_INT_RX_READY, 3176 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); 3177 } else { 3178 tasklet_schedule(&priv->poll_rx_task); 3179 } 3180} 3181 3182 3183/* 3184 * Core driver operations. 3185 */ 3186static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 3187{ 3188 struct mwl8k_priv *priv = hw->priv; 3189 int index = skb_get_queue_mapping(skb); 3190 int rc; 3191 3192 if (!priv->radio_on) { 3193 printk(KERN_DEBUG "%s: dropped TX frame since radio " 3194 "disabled\n", wiphy_name(hw->wiphy)); 3195 dev_kfree_skb(skb); 3196 return NETDEV_TX_OK; 3197 } 3198 3199 rc = mwl8k_txq_xmit(hw, index, skb); 3200 3201 return rc; 3202} 3203 3204static int mwl8k_start(struct ieee80211_hw *hw) 3205{ 3206 struct mwl8k_priv *priv = hw->priv; 3207 int rc; 3208 3209 rc = request_irq(priv->pdev->irq, mwl8k_interrupt, 3210 IRQF_SHARED, MWL8K_NAME, hw); 3211 if (rc) { 3212 printk(KERN_ERR "%s: failed to register IRQ handler\n", 3213 wiphy_name(hw->wiphy)); 3214 return -EIO; 3215 } 3216 3217 /* Enable TX reclaim and RX tasklets. */ 3218 tasklet_enable(&priv->poll_tx_task); 3219 tasklet_enable(&priv->poll_rx_task); 3220 3221 /* Enable interrupts */ 3222 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 3223 3224 rc = mwl8k_fw_lock(hw); 3225 if (!rc) { 3226 rc = mwl8k_cmd_radio_enable(hw); 3227 3228 if (!priv->ap_fw) { 3229 if (!rc) 3230 rc = mwl8k_cmd_enable_sniffer(hw, 0); 3231 3232 if (!rc) 3233 rc = mwl8k_cmd_set_pre_scan(hw); 3234 3235 if (!rc) 3236 rc = mwl8k_cmd_set_post_scan(hw, 3237 "\x00\x00\x00\x00\x00\x00"); 3238 } 3239 3240 if (!rc) 3241 rc = mwl8k_cmd_set_rateadapt_mode(hw, 0); 3242 3243 if (!rc) 3244 rc = mwl8k_cmd_set_wmm_mode(hw, 0); 3245 3246 mwl8k_fw_unlock(hw); 3247 } 3248 3249 if (rc) { 3250 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 3251 free_irq(priv->pdev->irq, hw); 3252 tasklet_disable(&priv->poll_tx_task); 3253 tasklet_disable(&priv->poll_rx_task); 3254 } 3255 3256 return rc; 3257} 3258 3259static void mwl8k_stop(struct ieee80211_hw *hw) 3260{ 3261 struct mwl8k_priv *priv = hw->priv; 3262 int i; 3263 3264 mwl8k_cmd_radio_disable(hw); 3265 3266 ieee80211_stop_queues(hw); 3267 3268 /* Disable interrupts */ 3269 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 3270 free_irq(priv->pdev->irq, hw); 3271 3272 /* Stop finalize join worker */ 3273 cancel_work_sync(&priv->finalize_join_worker); 3274 if (priv->beacon_skb != NULL) 3275 dev_kfree_skb(priv->beacon_skb); 3276 3277 /* Stop TX reclaim and RX tasklets. */ 3278 tasklet_disable(&priv->poll_tx_task); 3279 tasklet_disable(&priv->poll_rx_task); 3280 3281 /* Return all skbs to mac80211 */ 3282 for (i = 0; i < MWL8K_TX_QUEUES; i++) 3283 mwl8k_txq_reclaim(hw, i, INT_MAX, 1); 3284} 3285 3286static int mwl8k_add_interface(struct ieee80211_hw *hw, 3287 struct ieee80211_vif *vif) 3288{ 3289 struct mwl8k_priv *priv = hw->priv; 3290 struct mwl8k_vif *mwl8k_vif; 3291 u32 macids_supported; 3292 int macid; 3293 3294 /* 3295 * Reject interface creation if sniffer mode is active, as 3296 * STA operation is mutually exclusive with hardware sniffer 3297 * mode. (Sniffer mode is only used on STA firmware.) 3298 */ 3299 if (priv->sniffer_enabled) { 3300 printk(KERN_INFO "%s: unable to create STA " 3301 "interface due to sniffer mode being enabled\n", 3302 wiphy_name(hw->wiphy)); 3303 return -EINVAL; 3304 } 3305 3306 3307 switch (vif->type) { 3308 case NL80211_IFTYPE_AP: 3309 macids_supported = priv->ap_macids_supported; 3310 break; 3311 case NL80211_IFTYPE_STATION: 3312 macids_supported = priv->sta_macids_supported; 3313 break; 3314 default: 3315 return -EINVAL; 3316 } 3317 3318 macid = ffs(macids_supported & ~priv->macids_used); 3319 if (!macid--) 3320 return -EBUSY; 3321 3322 /* Setup driver private area. */ 3323 mwl8k_vif = MWL8K_VIF(vif); 3324 memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); 3325 mwl8k_vif->vif = vif; 3326 mwl8k_vif->macid = macid; 3327 mwl8k_vif->seqno = 0; 3328 3329 /* Set the mac address. */ 3330 mwl8k_cmd_set_mac_addr(hw, vif, vif->addr); 3331 3332 if (priv->ap_fw) 3333 mwl8k_cmd_set_new_stn_add_self(hw, vif); 3334 3335 priv->macids_used |= 1 << mwl8k_vif->macid; 3336 list_add_tail(&mwl8k_vif->list, &priv->vif_list); 3337 3338 return 0; 3339} 3340 3341static void mwl8k_remove_interface(struct ieee80211_hw *hw, 3342 struct ieee80211_vif *vif) 3343{ 3344 struct mwl8k_priv *priv = hw->priv; 3345 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); 3346 3347 if (priv->ap_fw) 3348 mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); 3349 3350 mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00"); 3351 3352 priv->macids_used &= ~(1 << mwl8k_vif->macid); 3353 list_del(&mwl8k_vif->list); 3354} 3355 3356static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) 3357{ 3358 struct ieee80211_conf *conf = &hw->conf; 3359 struct mwl8k_priv *priv = hw->priv; 3360 int rc; 3361 3362 if (conf->flags & IEEE80211_CONF_IDLE) { 3363 mwl8k_cmd_radio_disable(hw); 3364 return 0; 3365 } 3366 3367 rc = mwl8k_fw_lock(hw); 3368 if (rc) 3369 return rc; 3370 3371 rc = mwl8k_cmd_radio_enable(hw); 3372 if (rc) 3373 goto out; 3374 3375 rc = mwl8k_cmd_set_rf_channel(hw, conf); 3376 if (rc) 3377 goto out; 3378 3379 if (conf->power_level > 18) 3380 conf->power_level = 18; 3381 rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); 3382 if (rc) 3383 goto out; 3384 3385 if (priv->ap_fw) { 3386 rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7); 3387 if (!rc) 3388 rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7); 3389 } else { 3390 rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7); 3391 } 3392 3393out: 3394 mwl8k_fw_unlock(hw); 3395 3396 return rc; 3397} 3398 3399static void 3400mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 3401 struct ieee80211_bss_conf *info, u32 changed) 3402{ 3403 struct mwl8k_priv *priv = hw->priv; 3404 u32 ap_legacy_rates; 3405 u8 ap_mcs_rates[16]; 3406 int rc; 3407 3408 if (mwl8k_fw_lock(hw)) 3409 return; 3410 3411 /* 3412 * No need to capture a beacon if we're no longer associated. 3413 */ 3414 if ((changed & BSS_CHANGED_ASSOC) && !vif->bss_conf.assoc) 3415 priv->capture_beacon = false; 3416 3417 /* 3418 * Get the AP's legacy and MCS rates. 3419 */ 3420 if (vif->bss_conf.assoc) { 3421 struct ieee80211_sta *ap; 3422 3423 rcu_read_lock(); 3424 3425 ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); 3426 if (ap == NULL) { 3427 rcu_read_unlock(); 3428 goto out; 3429 } 3430 3431 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) { 3432 ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; 3433 } else { 3434 ap_legacy_rates = 3435 ap->supp_rates[IEEE80211_BAND_5GHZ] << 5; 3436 } 3437 memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16); 3438 3439 rcu_read_unlock(); 3440 } 3441 3442 if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { 3443 rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates, ap_mcs_rates); 3444 if (rc) 3445 goto out; 3446 3447 rc = mwl8k_cmd_use_fixed_rate_sta(hw); 3448 if (rc) 3449 goto out; 3450 } 3451 3452 if (changed & BSS_CHANGED_ERP_PREAMBLE) { 3453 rc = mwl8k_set_radio_preamble(hw, 3454 vif->bss_conf.use_short_preamble); 3455 if (rc) 3456 goto out; 3457 } 3458 3459 if (changed & BSS_CHANGED_ERP_SLOT) { 3460 rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot); 3461 if (rc) 3462 goto out; 3463 } 3464 3465 if (vif->bss_conf.assoc && 3466 (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT | 3467 BSS_CHANGED_HT))) { 3468 rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates); 3469 if (rc) 3470 goto out; 3471 } 3472 3473 if (vif->bss_conf.assoc && 3474 (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INT))) { 3475 /* 3476 * Finalize the join. Tell rx handler to process 3477 * next beacon from our BSSID. 3478 */ 3479 memcpy(priv->capture_bssid, vif->bss_conf.bssid, ETH_ALEN); 3480 priv->capture_beacon = true; 3481 } 3482 3483out: 3484 mwl8k_fw_unlock(hw); 3485} 3486 3487static void 3488mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 3489 struct ieee80211_bss_conf *info, u32 changed) 3490{ 3491 int rc; 3492 3493 if (mwl8k_fw_lock(hw)) 3494 return; 3495 3496 if (changed & BSS_CHANGED_ERP_PREAMBLE) { 3497 rc = mwl8k_set_radio_preamble(hw, 3498 vif->bss_conf.use_short_preamble); 3499 if (rc) 3500 goto out; 3501 } 3502 3503 if (changed & BSS_CHANGED_BASIC_RATES) { 3504 int idx; 3505 int rate; 3506 3507 /* 3508 * Use lowest supported basic rate for multicasts 3509 * and management frames (such as probe responses -- 3510 * beacons will always go out at 1 Mb/s). 3511 */ 3512 idx = ffs(vif->bss_conf.basic_rates); 3513 if (idx) 3514 idx--; 3515 3516 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) 3517 rate = mwl8k_rates_24[idx].hw_value; 3518 else 3519 rate = mwl8k_rates_50[idx].hw_value; 3520 3521 mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate); 3522 } 3523 3524 if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { 3525 struct sk_buff *skb; 3526 3527 skb = ieee80211_beacon_get(hw, vif); 3528 if (skb != NULL) { 3529 mwl8k_cmd_set_beacon(hw, vif, skb->data, skb->len); 3530 kfree_skb(skb); 3531 } 3532 } 3533 3534 if (changed & BSS_CHANGED_BEACON_ENABLED) 3535 mwl8k_cmd_bss_start(hw, vif, info->enable_beacon); 3536 3537out: 3538 mwl8k_fw_unlock(hw); 3539} 3540 3541static void 3542mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 3543 struct ieee80211_bss_conf *info, u32 changed) 3544{ 3545 struct mwl8k_priv *priv = hw->priv; 3546 3547 if (!priv->ap_fw) 3548 mwl8k_bss_info_changed_sta(hw, vif, info, changed); 3549 else 3550 mwl8k_bss_info_changed_ap(hw, vif, info, changed); 3551} 3552 3553static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, 3554 struct netdev_hw_addr_list *mc_list) 3555{ 3556 struct mwl8k_cmd_pkt *cmd; 3557 3558 /* 3559 * Synthesize and return a command packet that programs the 3560 * hardware multicast address filter. At this point we don't 3561 * know whether FIF_ALLMULTI is being requested, but if it is, 3562 * we'll end up throwing this packet away and creating a new 3563 * one in mwl8k_configure_filter(). 3564 */ 3565 cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_list); 3566 3567 return (unsigned long)cmd; 3568} 3569 3570static int 3571mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, 3572 unsigned int changed_flags, 3573 unsigned int *total_flags) 3574{ 3575 struct mwl8k_priv *priv = hw->priv; 3576 3577 /* 3578 * Hardware sniffer mode is mutually exclusive with STA 3579 * operation, so refuse to enable sniffer mode if a STA 3580 * interface is active. 3581 */ 3582 if (!list_empty(&priv->vif_list)) { 3583 if (net_ratelimit()) 3584 printk(KERN_INFO "%s: not enabling sniffer " 3585 "mode because STA interface is active\n", 3586 wiphy_name(hw->wiphy)); 3587 return 0; 3588 } 3589 3590 if (!priv->sniffer_enabled) { 3591 if (mwl8k_cmd_enable_sniffer(hw, 1)) 3592 return 0; 3593 priv->sniffer_enabled = true; 3594 } 3595 3596 *total_flags &= FIF_PROMISC_IN_BSS | FIF_ALLMULTI | 3597 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL | 3598 FIF_OTHER_BSS; 3599 3600 return 1; 3601} 3602 3603static struct mwl8k_vif *mwl8k_first_vif(struct mwl8k_priv *priv) 3604{ 3605 if (!list_empty(&priv->vif_list)) 3606 return list_entry(priv->vif_list.next, struct mwl8k_vif, list); 3607 3608 return NULL; 3609} 3610 3611static void mwl8k_configure_filter(struct ieee80211_hw *hw, 3612 unsigned int changed_flags, 3613 unsigned int *total_flags, 3614 u64 multicast) 3615{ 3616 struct mwl8k_priv *priv = hw->priv; 3617 struct mwl8k_cmd_pkt *cmd = (void *)(unsigned long)multicast; 3618 3619 /* 3620 * AP firmware doesn't allow fine-grained control over 3621 * the receive filter. 3622 */ 3623 if (priv->ap_fw) { 3624 *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; 3625 kfree(cmd); 3626 return; 3627 } 3628 3629 /* 3630 * Enable hardware sniffer mode if FIF_CONTROL or 3631 * FIF_OTHER_BSS is requested. 3632 */ 3633 if (*total_flags & (FIF_CONTROL | FIF_OTHER_BSS) && 3634 mwl8k_configure_filter_sniffer(hw, changed_flags, total_flags)) { 3635 kfree(cmd); 3636 return; 3637 } 3638 3639 /* Clear unsupported feature flags */ 3640 *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; 3641 3642 if (mwl8k_fw_lock(hw)) { 3643 kfree(cmd); 3644 return; 3645 } 3646 3647 if (priv->sniffer_enabled) { 3648 mwl8k_cmd_enable_sniffer(hw, 0); 3649 priv->sniffer_enabled = false; 3650 } 3651 3652 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { 3653 if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { 3654 /* 3655 * Disable the BSS filter. 3656 */ 3657 mwl8k_cmd_set_pre_scan(hw); 3658 } else { 3659 struct mwl8k_vif *mwl8k_vif; 3660 const u8 *bssid; 3661 3662 /* 3663 * Enable the BSS filter. 3664 * 3665 * If there is an active STA interface, use that 3666 * interface's BSSID, otherwise use a dummy one 3667 * (where the OUI part needs to be nonzero for 3668 * the BSSID to be accepted by POST_SCAN). 3669 */ 3670 mwl8k_vif = mwl8k_first_vif(priv); 3671 if (mwl8k_vif != NULL) 3672 bssid = mwl8k_vif->vif->bss_conf.bssid; 3673 else 3674 bssid = "\x01\x00\x00\x00\x00\x00"; 3675 3676 mwl8k_cmd_set_post_scan(hw, bssid); 3677 } 3678 } 3679 3680 /* 3681 * If FIF_ALLMULTI is being requested, throw away the command 3682 * packet that ->prepare_multicast() built and replace it with 3683 * a command packet that enables reception of all multicast 3684 * packets. 3685 */ 3686 if (*total_flags & FIF_ALLMULTI) { 3687 kfree(cmd); 3688 cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, NULL); 3689 } 3690 3691 if (cmd != NULL) { 3692 mwl8k_post_cmd(hw, cmd); 3693 kfree(cmd); 3694 } 3695 3696 mwl8k_fw_unlock(hw); 3697} 3698 3699static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 3700{ 3701 return mwl8k_cmd_set_rts_threshold(hw, value); 3702} 3703 3704static int mwl8k_sta_remove(struct ieee80211_hw *hw, 3705 struct ieee80211_vif *vif, 3706 struct ieee80211_sta *sta) 3707{ 3708 struct mwl8k_priv *priv = hw->priv; 3709 3710 if (priv->ap_fw) 3711 return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr); 3712 else 3713 return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr); 3714} 3715 3716static int mwl8k_sta_add(struct ieee80211_hw *hw, 3717 struct ieee80211_vif *vif, 3718 struct ieee80211_sta *sta) 3719{ 3720 struct mwl8k_priv *priv = hw->priv; 3721 int ret; 3722 3723 if (!priv->ap_fw) { 3724 ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); 3725 if (ret >= 0) { 3726 MWL8K_STA(sta)->peer_id = ret; 3727 return 0; 3728 } 3729 3730 return ret; 3731 } 3732 3733 return mwl8k_cmd_set_new_stn_add(hw, vif, sta); 3734} 3735 3736static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, 3737 const struct ieee80211_tx_queue_params *params) 3738{ 3739 struct mwl8k_priv *priv = hw->priv; 3740 int rc; 3741 3742 rc = mwl8k_fw_lock(hw); 3743 if (!rc) { 3744 if (!priv->wmm_enabled) 3745 rc = mwl8k_cmd_set_wmm_mode(hw, 1); 3746 3747 if (!rc) 3748 rc = mwl8k_cmd_set_edca_params(hw, queue, 3749 params->cw_min, 3750 params->cw_max, 3751 params->aifs, 3752 params->txop); 3753 3754 mwl8k_fw_unlock(hw); 3755 } 3756 3757 return rc; 3758} 3759 3760static int mwl8k_get_stats(struct ieee80211_hw *hw, 3761 struct ieee80211_low_level_stats *stats) 3762{ 3763 return mwl8k_cmd_get_stat(hw, stats); 3764} 3765 3766static int 3767mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 3768 enum ieee80211_ampdu_mlme_action action, 3769 struct ieee80211_sta *sta, u16 tid, u16 *ssn) 3770{ 3771 switch (action) { 3772 case IEEE80211_AMPDU_RX_START: 3773 case IEEE80211_AMPDU_RX_STOP: 3774 if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) 3775 return -ENOTSUPP; 3776 return 0; 3777 default: 3778 return -ENOTSUPP; 3779 } 3780} 3781 3782static const struct ieee80211_ops mwl8k_ops = { 3783 .tx = mwl8k_tx, 3784 .start = mwl8k_start, 3785 .stop = mwl8k_stop, 3786 .add_interface = mwl8k_add_interface, 3787 .remove_interface = mwl8k_remove_interface, 3788 .config = mwl8k_config, 3789 .bss_info_changed = mwl8k_bss_info_changed, 3790 .prepare_multicast = mwl8k_prepare_multicast, 3791 .configure_filter = mwl8k_configure_filter, 3792 .set_rts_threshold = mwl8k_set_rts_threshold, 3793 .sta_add = mwl8k_sta_add, 3794 .sta_remove = mwl8k_sta_remove, 3795 .conf_tx = mwl8k_conf_tx, 3796 .get_stats = mwl8k_get_stats, 3797 .ampdu_action = mwl8k_ampdu_action, 3798}; 3799 3800static void mwl8k_finalize_join_worker(struct work_struct *work) 3801{ 3802 struct mwl8k_priv *priv = 3803 container_of(work, struct mwl8k_priv, finalize_join_worker); 3804 struct sk_buff *skb = priv->beacon_skb; 3805 struct ieee80211_mgmt *mgmt = (void *)skb->data; 3806 int len = skb->len - offsetof(struct ieee80211_mgmt, u.beacon.variable); 3807 const u8 *tim = cfg80211_find_ie(WLAN_EID_TIM, 3808 mgmt->u.beacon.variable, len); 3809 int dtim_period = 1; 3810 3811 if (tim && tim[1] >= 2) 3812 dtim_period = tim[3]; 3813 3814 mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim_period); 3815 3816 dev_kfree_skb(skb); 3817 priv->beacon_skb = NULL; 3818} 3819 3820enum { 3821 MWL8363 = 0, 3822 MWL8687, 3823 MWL8366, 3824}; 3825 3826static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { 3827 [MWL8363] = { 3828 .part_name = "88w8363", 3829 .helper_image = "mwl8k/helper_8363.fw", 3830 .fw_image = "mwl8k/fmimage_8363.fw", 3831 }, 3832 [MWL8687] = { 3833 .part_name = "88w8687", 3834 .helper_image = "mwl8k/helper_8687.fw", 3835 .fw_image = "mwl8k/fmimage_8687.fw", 3836 }, 3837 [MWL8366] = { 3838 .part_name = "88w8366", 3839 .helper_image = "mwl8k/helper_8366.fw", 3840 .fw_image = "mwl8k/fmimage_8366.fw", 3841 .ap_rxd_ops = &rxd_8366_ap_ops, 3842 }, 3843}; 3844 3845MODULE_FIRMWARE("mwl8k/helper_8363.fw"); 3846MODULE_FIRMWARE("mwl8k/fmimage_8363.fw"); 3847MODULE_FIRMWARE("mwl8k/helper_8687.fw"); 3848MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); 3849MODULE_FIRMWARE("mwl8k/helper_8366.fw"); 3850MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); 3851 3852static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { 3853 { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, 3854 { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, 3855 { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, 3856 { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, 3857 { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, 3858 { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, 3859 { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, 3860 { }, 3861}; 3862MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); 3863 3864static int __devinit mwl8k_probe(struct pci_dev *pdev, 3865 const struct pci_device_id *id) 3866{ 3867 static int printed_version = 0; 3868 struct ieee80211_hw *hw; 3869 struct mwl8k_priv *priv; 3870 int rc; 3871 int i; 3872 3873 if (!printed_version) { 3874 printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); 3875 printed_version = 1; 3876 } 3877 3878 3879 rc = pci_enable_device(pdev); 3880 if (rc) { 3881 printk(KERN_ERR "%s: Cannot enable new PCI device\n", 3882 MWL8K_NAME); 3883 return rc; 3884 } 3885 3886 rc = pci_request_regions(pdev, MWL8K_NAME); 3887 if (rc) { 3888 printk(KERN_ERR "%s: Cannot obtain PCI resources\n", 3889 MWL8K_NAME); 3890 goto err_disable_device; 3891 } 3892 3893 pci_set_master(pdev); 3894 3895 3896 hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); 3897 if (hw == NULL) { 3898 printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); 3899 rc = -ENOMEM; 3900 goto err_free_reg; 3901 } 3902 3903 SET_IEEE80211_DEV(hw, &pdev->dev); 3904 pci_set_drvdata(pdev, hw); 3905 3906 priv = hw->priv; 3907 priv->hw = hw; 3908 priv->pdev = pdev; 3909 priv->device_info = &mwl8k_info_tbl[id->driver_data]; 3910 3911 3912 priv->sram = pci_iomap(pdev, 0, 0x10000); 3913 if (priv->sram == NULL) { 3914 printk(KERN_ERR "%s: Cannot map device SRAM\n", 3915 wiphy_name(hw->wiphy)); 3916 goto err_iounmap; 3917 } 3918 3919 /* 3920 * If BAR0 is a 32 bit BAR, the register BAR will be BAR1. 3921 * If BAR0 is a 64 bit BAR, the register BAR will be BAR2. 3922 */ 3923 priv->regs = pci_iomap(pdev, 1, 0x10000); 3924 if (priv->regs == NULL) { 3925 priv->regs = pci_iomap(pdev, 2, 0x10000); 3926 if (priv->regs == NULL) { 3927 printk(KERN_ERR "%s: Cannot map device registers\n", 3928 wiphy_name(hw->wiphy)); 3929 goto err_iounmap; 3930 } 3931 } 3932 3933 3934 /* Reset firmware and hardware */ 3935 mwl8k_hw_reset(priv); 3936 3937 /* Ask userland hotplug daemon for the device firmware */ 3938 rc = mwl8k_request_firmware(priv); 3939 if (rc) { 3940 printk(KERN_ERR "%s: Firmware files not found\n", 3941 wiphy_name(hw->wiphy)); 3942 goto err_stop_firmware; 3943 } 3944 3945 /* Load firmware into hardware */ 3946 rc = mwl8k_load_firmware(hw); 3947 if (rc) { 3948 printk(KERN_ERR "%s: Cannot start firmware\n", 3949 wiphy_name(hw->wiphy)); 3950 goto err_stop_firmware; 3951 } 3952 3953 /* Reclaim memory once firmware is successfully loaded */ 3954 mwl8k_release_firmware(priv); 3955 3956 3957 if (priv->ap_fw) { 3958 priv->rxd_ops = priv->device_info->ap_rxd_ops; 3959 if (priv->rxd_ops == NULL) { 3960 printk(KERN_ERR "%s: Driver does not have AP " 3961 "firmware image support for this hardware\n", 3962 wiphy_name(hw->wiphy)); 3963 goto err_stop_firmware; 3964 } 3965 } else { 3966 priv->rxd_ops = &rxd_sta_ops; 3967 } 3968 3969 priv->sniffer_enabled = false; 3970 priv->wmm_enabled = false; 3971 priv->pending_tx_pkts = 0; 3972 3973 3974 /* 3975 * Extra headroom is the size of the required DMA header 3976 * minus the size of the smallest 802.11 frame (CTS frame). 3977 */ 3978 hw->extra_tx_headroom = 3979 sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); 3980 3981 hw->channel_change_time = 10; 3982 3983 hw->queues = MWL8K_TX_QUEUES; 3984 3985 /* Set rssi values to dBm */ 3986 hw->flags |= IEEE80211_HW_SIGNAL_DBM; 3987 hw->vif_data_size = sizeof(struct mwl8k_vif); 3988 hw->sta_data_size = sizeof(struct mwl8k_sta); 3989 3990 priv->macids_used = 0; 3991 INIT_LIST_HEAD(&priv->vif_list); 3992 3993 /* Set default radio state and preamble */ 3994 priv->radio_on = 0; 3995 priv->radio_short_preamble = 0; 3996 3997 /* Finalize join worker */ 3998 INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); 3999 4000 /* TX reclaim and RX tasklets. */ 4001 tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); 4002 tasklet_disable(&priv->poll_tx_task); 4003 tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); 4004 tasklet_disable(&priv->poll_rx_task); 4005 4006 /* Power management cookie */ 4007 priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); 4008 if (priv->cookie == NULL) 4009 goto err_stop_firmware; 4010 4011 rc = mwl8k_rxq_init(hw, 0); 4012 if (rc) 4013 goto err_free_cookie; 4014 rxq_refill(hw, 0, INT_MAX); 4015 4016 mutex_init(&priv->fw_mutex); 4017 priv->fw_mutex_owner = NULL; 4018 priv->fw_mutex_depth = 0; 4019 priv->hostcmd_wait = NULL; 4020 4021 spin_lock_init(&priv->tx_lock); 4022 4023 priv->tx_wait = NULL; 4024 4025 for (i = 0; i < MWL8K_TX_QUEUES; i++) { 4026 rc = mwl8k_txq_init(hw, i); 4027 if (rc) 4028 goto err_free_queues; 4029 } 4030 4031 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); 4032 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 4033 iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY, 4034 priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); 4035 iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); 4036 4037 rc = request_irq(priv->pdev->irq, mwl8k_interrupt, 4038 IRQF_SHARED, MWL8K_NAME, hw); 4039 if (rc) { 4040 printk(KERN_ERR "%s: failed to register IRQ handler\n", 4041 wiphy_name(hw->wiphy)); 4042 goto err_free_queues; 4043 } 4044 4045 /* 4046 * Temporarily enable interrupts. Initial firmware host 4047 * commands use interrupts and avoid polling. Disable 4048 * interrupts when done. 4049 */ 4050 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 4051 4052 /* Get config data, mac addrs etc */ 4053 if (priv->ap_fw) { 4054 rc = mwl8k_cmd_get_hw_spec_ap(hw); 4055 if (!rc) 4056 rc = mwl8k_cmd_set_hw_spec(hw); 4057 } else { 4058 rc = mwl8k_cmd_get_hw_spec_sta(hw); 4059 } 4060 if (rc) { 4061 printk(KERN_ERR "%s: Cannot initialise firmware\n", 4062 wiphy_name(hw->wiphy)); 4063 goto err_free_irq; 4064 } 4065 4066 hw->wiphy->interface_modes = 0; 4067 if (priv->ap_macids_supported) 4068 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); 4069 if (priv->sta_macids_supported) 4070 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); 4071 4072 4073 /* Turn radio off */ 4074 rc = mwl8k_cmd_radio_disable(hw); 4075 if (rc) { 4076 printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); 4077 goto err_free_irq; 4078 } 4079 4080 /* Clear MAC address */ 4081 rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00"); 4082 if (rc) { 4083 printk(KERN_ERR "%s: Cannot clear MAC address\n", 4084 wiphy_name(hw->wiphy)); 4085 goto err_free_irq; 4086 } 4087 4088 /* Disable interrupts */ 4089 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 4090 free_irq(priv->pdev->irq, hw); 4091 4092 rc = ieee80211_register_hw(hw); 4093 if (rc) { 4094 printk(KERN_ERR "%s: Cannot register device\n", 4095 wiphy_name(hw->wiphy)); 4096 goto err_free_queues; 4097 } 4098 4099 printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", 4100 wiphy_name(hw->wiphy), priv->device_info->part_name, 4101 priv->hw_rev, hw->wiphy->perm_addr, 4102 priv->ap_fw ? "AP" : "STA", 4103 (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff, 4104 (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff); 4105 4106 return 0; 4107 4108err_free_irq: 4109 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 4110 free_irq(priv->pdev->irq, hw); 4111 4112err_free_queues: 4113 for (i = 0; i < MWL8K_TX_QUEUES; i++) 4114 mwl8k_txq_deinit(hw, i); 4115 mwl8k_rxq_deinit(hw, 0); 4116 4117err_free_cookie: 4118 if (priv->cookie != NULL) 4119 pci_free_consistent(priv->pdev, 4, 4120 priv->cookie, priv->cookie_dma); 4121 4122err_stop_firmware: 4123 mwl8k_hw_reset(priv); 4124 mwl8k_release_firmware(priv); 4125 4126err_iounmap: 4127 if (priv->regs != NULL) 4128 pci_iounmap(pdev, priv->regs); 4129 4130 if (priv->sram != NULL) 4131 pci_iounmap(pdev, priv->sram); 4132 4133 pci_set_drvdata(pdev, NULL); 4134 ieee80211_free_hw(hw); 4135 4136err_free_reg: 4137 pci_release_regions(pdev); 4138 4139err_disable_device: 4140 pci_disable_device(pdev); 4141 4142 return rc; 4143} 4144 4145static void __devexit mwl8k_shutdown(struct pci_dev *pdev) 4146{ 4147 printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__); 4148} 4149 4150static void __devexit mwl8k_remove(struct pci_dev *pdev) 4151{ 4152 struct ieee80211_hw *hw = pci_get_drvdata(pdev); 4153 struct mwl8k_priv *priv; 4154 int i; 4155 4156 if (hw == NULL) 4157 return; 4158 priv = hw->priv; 4159 4160 ieee80211_stop_queues(hw); 4161 4162 ieee80211_unregister_hw(hw); 4163 4164 /* Remove TX reclaim and RX tasklets. */ 4165 tasklet_kill(&priv->poll_tx_task); 4166 tasklet_kill(&priv->poll_rx_task); 4167 4168 /* Stop hardware */ 4169 mwl8k_hw_reset(priv); 4170 4171 /* Return all skbs to mac80211 */ 4172 for (i = 0; i < MWL8K_TX_QUEUES; i++) 4173 mwl8k_txq_reclaim(hw, i, INT_MAX, 1); 4174 4175 for (i = 0; i < MWL8K_TX_QUEUES; i++) 4176 mwl8k_txq_deinit(hw, i); 4177 4178 mwl8k_rxq_deinit(hw, 0); 4179 4180 pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma); 4181 4182 pci_iounmap(pdev, priv->regs); 4183 pci_iounmap(pdev, priv->sram); 4184 pci_set_drvdata(pdev, NULL); 4185 ieee80211_free_hw(hw); 4186 pci_release_regions(pdev); 4187 pci_disable_device(pdev); 4188} 4189 4190static struct pci_driver mwl8k_driver = { 4191 .name = MWL8K_NAME, 4192 .id_table = mwl8k_pci_id_table, 4193 .probe = mwl8k_probe, 4194 .remove = __devexit_p(mwl8k_remove), 4195 .shutdown = __devexit_p(mwl8k_shutdown), 4196}; 4197 4198static int __init mwl8k_init(void) 4199{ 4200 return pci_register_driver(&mwl8k_driver); 4201} 4202 4203static void __exit mwl8k_exit(void) 4204{ 4205 pci_unregister_driver(&mwl8k_driver); 4206} 4207 4208module_init(mwl8k_init); 4209module_exit(mwl8k_exit); 4210 4211MODULE_DESCRIPTION(MWL8K_DESC); 4212MODULE_VERSION(MWL8K_VERSION); 4213MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com>"); 4214MODULE_LICENSE("GPL");