···46464747 If unsure, say N48484949+config BCMA_SFLASH5050+ bool5151+ depends on BCMA_DRIVER_MIPS && BROKEN5252+ default y5353+5454+config BCMA_NFLASH5555+ bool5656+ depends on BCMA_DRIVER_MIPS && BROKEN5757+ default y5858+5959+config BCMA_DRIVER_GMAC_CMN6060+ bool "BCMA Broadcom GBIT MAC COMMON core driver"6161+ depends on BCMA6262+ help6363+ Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom6464+ specific Advanced Microcontroller Bus.6565+6666+ If unsure, say N6767+4968config BCMA_DEBUG5069 bool "BCMA debugging"5170 depends on BCMA
···11+/*22+ * Broadcom specific AMBA33+ * ChipCommon NAND flash interface44+ *55+ * Licensed under the GNU/GPL. See COPYING for details.66+ */77+88+#include <linux/bcma/bcma.h>99+#include <linux/bcma/bcma_driver_chipcommon.h>1010+#include <linux/delay.h>1111+1212+#include "bcma_private.h"1313+1414+/* Initialize NAND flash access */1515+int bcma_nflash_init(struct bcma_drv_cc *cc)1616+{1717+ bcma_err(cc->core->bus, "NAND flash support is broken\n");1818+ return 0;1919+}
+19
drivers/bcma/driver_chipcommon_sflash.c
···11+/*22+ * Broadcom specific AMBA33+ * ChipCommon serial flash interface44+ *55+ * Licensed under the GNU/GPL. See COPYING for details.66+ */77+88+#include <linux/bcma/bcma.h>99+#include <linux/bcma/bcma_driver_chipcommon.h>1010+#include <linux/delay.h>1111+1212+#include "bcma_private.h"1313+1414+/* Initialize serial flash access */1515+int bcma_sflash_init(struct bcma_drv_cc *cc)1616+{1717+ bcma_err(cc->core->bus, "Serial flash support is broken\n");1818+ return 0;1919+}
+14
drivers/bcma/driver_gmac_cmn.c
···11+/*22+ * Broadcom specific AMBA33+ * GBIT MAC COMMON Core44+ *55+ * Licensed under the GNU/GPL. See COPYING for details.66+ */77+88+#include "bcma_private.h"99+#include <linux/bcma/bcma.h>1010+1111+void __devinit bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc)1212+{1313+ mutex_init(&gc->phy_mutex);1414+}
+12-3
drivers/bcma/driver_mips.c
···185185 switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {186186 case BCMA_CC_FLASHT_STSER:187187 case BCMA_CC_FLASHT_ATSER:188188- bcma_err(bus, "Serial flash not supported.\n");188188+ bcma_debug(bus, "Found serial flash\n");189189+ bcma_sflash_init(&bus->drv_cc);189190 break;190191 case BCMA_CC_FLASHT_PARA:191191- bcma_info(bus, "found parallel flash.\n");192192+ bcma_debug(bus, "Found parallel flash\n");192193 bus->drv_cc.pflash.window = 0x1c000000;193194 bus->drv_cc.pflash.window_size = 0x02000000;194195···200199 bus->drv_cc.pflash.buswidth = 2;201200 break;202201 default:203203- bcma_err(bus, "flash not supported.\n");202202+ bcma_err(bus, "Flash type not supported\n");203203+ }204204+205205+ if (bus->drv_cc.core->id.rev == 38 ||206206+ bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {207207+ if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {208208+ bcma_debug(bus, "Found NAND flash\n");209209+ bcma_nflash_init(&bus->drv_cc);210210+ }204211 }205212}206213
+20-5
drivers/bcma/main.c
···6161 .dev_attrs = bcma_device_attrs,6262};63636464+static u16 bcma_cc_core_id(struct bcma_bus *bus)6565+{6666+ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)6767+ return BCMA_CORE_4706_CHIPCOMMON;6868+ return BCMA_CORE_CHIPCOMMON;6969+}7070+6471struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)6572{6673 struct bcma_device *core;···9891 list_for_each_entry(core, &bus->cores, list) {9992 /* We support that cores ourself */10093 switch (core->id.id) {9494+ case BCMA_CORE_4706_CHIPCOMMON:10195 case BCMA_CORE_CHIPCOMMON:10296 case BCMA_CORE_PCI:10397 case BCMA_CORE_PCIE:10498 case BCMA_CORE_MIPS_74K:9999+ case BCMA_CORE_4706_MAC_GBIT_COMMON:105100 continue;106101 }107102···166157 }167158168159 /* Init CC core */169169- core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);160160+ core = bcma_find_core(bus, bcma_cc_core_id(bus));170161 if (core) {171162 bus->drv_cc.core = core;172163 bcma_core_chipcommon_init(&bus->drv_cc);···184175 if (core) {185176 bus->drv_pci.core = core;186177 bcma_core_pci_init(&bus->drv_pci);178178+ }179179+180180+ /* Init GBIT MAC COMMON core */181181+ core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);182182+ if (core) {183183+ bus->drv_gmac_cmn.core = core;184184+ bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);187185 }188186189187 /* Try to get SPROM */···224208 bcma_init_bus(bus);225209226210 match.manuf = BCMA_MANUF_BCM;227227- match.id = BCMA_CORE_CHIPCOMMON;211211+ match.id = bcma_cc_core_id(bus);228212 match.class = BCMA_CL_SIM;229213 match.rev = BCMA_ANY_REV;230214···248232 }249233250234 /* Init CC core */251251- core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);235235+ core = bcma_find_core(bus, bcma_cc_core_id(bus));252236 if (core) {253237 bus->drv_cc.core = core;254238 bcma_core_chipcommon_init(&bus->drv_cc);···287271 struct bcma_device *core;288272289273 /* Init CC core */290290- core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);291291- if (core) {274274+ if (bus->drv_cc.core) {292275 bus->drv_cc.setup_done = false;293276 bcma_core_chipcommon_init(&bus->drv_cc);294277 }
+12-8
drivers/bcma/scan.c
···2121};22222323static const struct bcma_device_id_name bcma_arm_device_names[] = {2424+ { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },2425 { BCMA_CORE_ARM_1176, "ARM 1176" },2526 { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },2627 { BCMA_CORE_ARM_CM3, "ARM CM3" },···3433 { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },3534 { BCMA_CORE_AMEMC, "AMEMC (DDR)" },3635 { BCMA_CORE_ALTA, "ALTA (I2S)" },3737- { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },3836 { BCMA_CORE_INVALID, "Invalid" },3937 { BCMA_CORE_CHIPCOMMON, "ChipCommon" },4038 { BCMA_CORE_ILINE20, "ILine 20" },···295295296296 /* check if component is a core at all */297297 if (wrappers[0] + wrappers[1] == 0) {298298- /* we could save addrl of the router299299- if (cid == BCMA_CORE_OOB_ROUTER)300300- */301301- bcma_erom_skip_component(bus, eromptr);302302- return -ENXIO;298298+ /* Some specific cores don't need wrappers */299299+ switch (core->id.id) {300300+ case BCMA_CORE_4706_MAC_GBIT_COMMON:301301+ /* Not used yet: case BCMA_CORE_OOB_ROUTER: */302302+ break;303303+ default:304304+ bcma_erom_skip_component(bus, eromptr);305305+ return -ENXIO;306306+ }303307 }304308305309 if (bcma_erom_is_bridge(bus, eromptr)) {···491487 core->id.manuf, core->id.id, core->id.rev,492488 core->id.class);493489494494- list_add(&core->list, &bus->cores);490490+ list_add_tail(&core->list, &bus->cores);495491 }496492497493 if (bus->hosttype == BCMA_HOSTTYPE_SOC)···546542 core->id.manuf, core->id.id, core->id.rev,547543 core->id.class);548544549549- list_add(&core->list, &bus->cores);545545+ list_add_tail(&core->list, &bus->cores);550546 err = 0;551547 break;552548 }
···81818282 Say Y here to compile support for HCILL protocol.83838484+config BT_HCIUART_3WIRE8585+ bool "Three-wire UART (H5) protocol support"8686+ depends on BT_HCIUART8787+ help8888+ The HCI Three-wire UART Transport Layer makes it possible to8989+ user the Bluetooth HCI over a serial port interface. The HCI9090+ Three-wire UART Transport Layer assumes that the UART9191+ communication may have bit errors, overrun errors or burst9292+ errors and thereby making CTS/RTS lines unnecessary.9393+9494+ Say Y here to compile support for Three-wire UART protocol.9595+8496config BT_HCIBCM203X8597 tristate "HCI BCM203x USB driver"8698 depends on USB
···593593{594594 int *try = priv_data;595595596596- if (try == 0)596596+ if (!try)597597 p_dev->io_lines = 16;598598599599 if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+10-8
drivers/bluetooth/dtl1_cs.c
···586586static int dtl1_config(struct pcmcia_device *link)587587{588588 dtl1_info_t *info = link->priv;589589- int i;589589+ int ret;590590591591 /* Look for a generic full-sized window */592592 link->resource[0]->end = 8;593593- if (pcmcia_loop_config(link, dtl1_confcheck, NULL) < 0)593593+ ret = pcmcia_loop_config(link, dtl1_confcheck, NULL);594594+ if (ret)594595 goto failed;595596596596- i = pcmcia_request_irq(link, dtl1_interrupt);597597- if (i != 0)597597+ ret = pcmcia_request_irq(link, dtl1_interrupt);598598+ if (ret)598599 goto failed;599600600600- i = pcmcia_enable_device(link);601601- if (i != 0)601601+ ret = pcmcia_enable_device(link);602602+ if (ret)602603 goto failed;603604604604- if (dtl1_open(info) != 0)605605+ ret = dtl1_open(info);606606+ if (ret)605607 goto failed;606608607609 return 0;608610609611failed:610612 dtl1_detach(link);611611- return -ENODEV;613613+ return ret;612614}613615614616static const struct pcmcia_device_id dtl1_ids[] = {
+747
drivers/bluetooth/hci_h5.c
···11+/*22+ *33+ * Bluetooth HCI Three-wire UART driver44+ *55+ * Copyright (C) 2012 Intel Corporation66+ *77+ *88+ * This program is free software; you can redistribute it and/or modify99+ * it under the terms of the GNU General Public License as published by1010+ * the Free Software Foundation; either version 2 of the License, or1111+ * (at your option) any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful,1414+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1515+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616+ * GNU General Public License for more details.1717+ *1818+ * You should have received a copy of the GNU General Public License1919+ * along with this program; if not, write to the Free Software2020+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2121+ *2222+ */2323+2424+#include <linux/kernel.h>2525+#include <linux/errno.h>2626+#include <linux/skbuff.h>2727+2828+#include <net/bluetooth/bluetooth.h>2929+#include <net/bluetooth/hci_core.h>3030+3131+#include "hci_uart.h"3232+3333+#define HCI_3WIRE_ACK_PKT 03434+#define HCI_3WIRE_LINK_PKT 153535+3636+/* Sliding window size */3737+#define H5_TX_WIN_MAX 43838+3939+#define H5_ACK_TIMEOUT msecs_to_jiffies(250)4040+#define H5_SYNC_TIMEOUT msecs_to_jiffies(100)4141+4242+/*4343+ * Maximum Three-wire packet:4444+ * 4 byte header + max value for 12-bit length + 2 bytes for CRC4545+ */4646+#define H5_MAX_LEN (4 + 0xfff + 2)4747+4848+/* Convenience macros for reading Three-wire header values */4949+#define H5_HDR_SEQ(hdr) ((hdr)[0] & 0x07)5050+#define H5_HDR_ACK(hdr) (((hdr)[0] >> 3) & 0x07)5151+#define H5_HDR_CRC(hdr) (((hdr)[0] >> 6) & 0x01)5252+#define H5_HDR_RELIABLE(hdr) (((hdr)[0] >> 7) & 0x01)5353+#define H5_HDR_PKT_TYPE(hdr) ((hdr)[1] & 0x0f)5454+#define H5_HDR_LEN(hdr) ((((hdr)[1] >> 4) & 0xff) + ((hdr)[2] << 4))5555+5656+#define SLIP_DELIMITER 0xc05757+#define SLIP_ESC 0xdb5858+#define SLIP_ESC_DELIM 0xdc5959+#define SLIP_ESC_ESC 0xdd6060+6161+/* H5 state flags */6262+enum {6363+ H5_RX_ESC, /* SLIP escape mode */6464+ H5_TX_ACK_REQ, /* Pending ack to send */6565+};6666+6767+struct h5 {6868+ struct sk_buff_head unack; /* Unack'ed packets queue */6969+ struct sk_buff_head rel; /* Reliable packets queue */7070+ struct sk_buff_head unrel; /* Unreliable packets queue */7171+7272+ unsigned long flags;7373+7474+ struct sk_buff *rx_skb; /* Receive buffer */7575+ size_t rx_pending; /* Expecting more bytes */7676+ u8 rx_ack; /* Last ack number received */7777+7878+ int (*rx_func) (struct hci_uart *hu, u8 c);7979+8080+ struct timer_list timer; /* Retransmission timer */8181+8282+ u8 tx_seq; /* Next seq number to send */8383+ u8 tx_ack; /* Next ack number to send */8484+ u8 tx_win; /* Sliding window size */8585+8686+ enum {8787+ H5_UNINITIALIZED,8888+ H5_INITIALIZED,8989+ H5_ACTIVE,9090+ } state;9191+9292+ enum {9393+ H5_AWAKE,9494+ H5_SLEEPING,9595+ H5_WAKING_UP,9696+ } sleep;9797+};9898+9999+static void h5_reset_rx(struct h5 *h5);100100+101101+static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)102102+{103103+ struct h5 *h5 = hu->priv;104104+ struct sk_buff *nskb;105105+106106+ nskb = alloc_skb(3, GFP_ATOMIC);107107+ if (!nskb)108108+ return;109109+110110+ bt_cb(nskb)->pkt_type = HCI_3WIRE_LINK_PKT;111111+112112+ memcpy(skb_put(nskb, len), data, len);113113+114114+ skb_queue_tail(&h5->unrel, nskb);115115+}116116+117117+static u8 h5_cfg_field(struct h5 *h5)118118+{119119+ u8 field = 0;120120+121121+ /* Sliding window size (first 3 bits) */122122+ field |= (h5->tx_win & 7);123123+124124+ return field;125125+}126126+127127+static void h5_timed_event(unsigned long arg)128128+{129129+ const unsigned char sync_req[] = { 0x01, 0x7e };130130+ unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };131131+ struct hci_uart *hu = (struct hci_uart *) arg;132132+ struct h5 *h5 = hu->priv;133133+ struct sk_buff *skb;134134+ unsigned long flags;135135+136136+ BT_DBG("%s", hu->hdev->name);137137+138138+ if (h5->state == H5_UNINITIALIZED)139139+ h5_link_control(hu, sync_req, sizeof(sync_req));140140+141141+ if (h5->state == H5_INITIALIZED) {142142+ conf_req[2] = h5_cfg_field(h5);143143+ h5_link_control(hu, conf_req, sizeof(conf_req));144144+ }145145+146146+ if (h5->state != H5_ACTIVE) {147147+ mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT);148148+ goto wakeup;149149+ }150150+151151+ if (h5->sleep != H5_AWAKE) {152152+ h5->sleep = H5_SLEEPING;153153+ goto wakeup;154154+ }155155+156156+ BT_DBG("hu %p retransmitting %u pkts", hu, h5->unack.qlen);157157+158158+ spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);159159+160160+ while ((skb = __skb_dequeue_tail(&h5->unack)) != NULL) {161161+ h5->tx_seq = (h5->tx_seq - 1) & 0x07;162162+ skb_queue_head(&h5->rel, skb);163163+ }164164+165165+ spin_unlock_irqrestore(&h5->unack.lock, flags);166166+167167+wakeup:168168+ hci_uart_tx_wakeup(hu);169169+}170170+171171+static int h5_open(struct hci_uart *hu)172172+{173173+ struct h5 *h5;174174+ const unsigned char sync[] = { 0x01, 0x7e };175175+176176+ BT_DBG("hu %p", hu);177177+178178+ h5 = kzalloc(sizeof(*h5), GFP_KERNEL);179179+ if (!h5)180180+ return -ENOMEM;181181+182182+ hu->priv = h5;183183+184184+ skb_queue_head_init(&h5->unack);185185+ skb_queue_head_init(&h5->rel);186186+ skb_queue_head_init(&h5->unrel);187187+188188+ h5_reset_rx(h5);189189+190190+ init_timer(&h5->timer);191191+ h5->timer.function = h5_timed_event;192192+ h5->timer.data = (unsigned long) hu;193193+194194+ h5->tx_win = H5_TX_WIN_MAX;195195+196196+ set_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags);197197+198198+ /* Send initial sync request */199199+ h5_link_control(hu, sync, sizeof(sync));200200+ mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT);201201+202202+ return 0;203203+}204204+205205+static int h5_close(struct hci_uart *hu)206206+{207207+ struct h5 *h5 = hu->priv;208208+209209+ skb_queue_purge(&h5->unack);210210+ skb_queue_purge(&h5->rel);211211+ skb_queue_purge(&h5->unrel);212212+213213+ del_timer(&h5->timer);214214+215215+ kfree(h5);216216+217217+ return 0;218218+}219219+220220+static void h5_pkt_cull(struct h5 *h5)221221+{222222+ struct sk_buff *skb, *tmp;223223+ unsigned long flags;224224+ int i, to_remove;225225+ u8 seq;226226+227227+ spin_lock_irqsave(&h5->unack.lock, flags);228228+229229+ to_remove = skb_queue_len(&h5->unack);230230+ if (to_remove == 0)231231+ goto unlock;232232+233233+ seq = h5->tx_seq;234234+235235+ while (to_remove > 0) {236236+ if (h5->rx_ack == seq)237237+ break;238238+239239+ to_remove--;240240+ seq = (seq - 1) % 8;241241+ }242242+243243+ if (seq != h5->rx_ack)244244+ BT_ERR("Controller acked invalid packet");245245+246246+ i = 0;247247+ skb_queue_walk_safe(&h5->unack, skb, tmp) {248248+ if (i++ >= to_remove)249249+ break;250250+251251+ __skb_unlink(skb, &h5->unack);252252+ kfree_skb(skb);253253+ }254254+255255+ if (skb_queue_empty(&h5->unack))256256+ del_timer(&h5->timer);257257+258258+unlock:259259+ spin_unlock_irqrestore(&h5->unack.lock, flags);260260+}261261+262262+static void h5_handle_internal_rx(struct hci_uart *hu)263263+{264264+ struct h5 *h5 = hu->priv;265265+ const unsigned char sync_req[] = { 0x01, 0x7e };266266+ const unsigned char sync_rsp[] = { 0x02, 0x7d };267267+ unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };268268+ const unsigned char conf_rsp[] = { 0x04, 0x7b };269269+ const unsigned char wakeup_req[] = { 0x05, 0xfa };270270+ const unsigned char woken_req[] = { 0x06, 0xf9 };271271+ const unsigned char sleep_req[] = { 0x07, 0x78 };272272+ const unsigned char *hdr = h5->rx_skb->data;273273+ const unsigned char *data = &h5->rx_skb->data[4];274274+275275+ BT_DBG("%s", hu->hdev->name);276276+277277+ if (H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT)278278+ return;279279+280280+ if (H5_HDR_LEN(hdr) < 2)281281+ return;282282+283283+ conf_req[2] = h5_cfg_field(h5);284284+285285+ if (memcmp(data, sync_req, 2) == 0) {286286+ h5_link_control(hu, sync_rsp, 2);287287+ } else if (memcmp(data, sync_rsp, 2) == 0) {288288+ h5->state = H5_INITIALIZED;289289+ h5_link_control(hu, conf_req, 3);290290+ } else if (memcmp(data, conf_req, 2) == 0) {291291+ h5_link_control(hu, conf_rsp, 2);292292+ h5_link_control(hu, conf_req, 3);293293+ } else if (memcmp(data, conf_rsp, 2) == 0) {294294+ if (H5_HDR_LEN(hdr) > 2)295295+ h5->tx_win = (data[2] & 7);296296+ BT_DBG("Three-wire init complete. tx_win %u", h5->tx_win);297297+ h5->state = H5_ACTIVE;298298+ hci_uart_init_ready(hu);299299+ return;300300+ } else if (memcmp(data, sleep_req, 2) == 0) {301301+ BT_DBG("Peer went to sleep");302302+ h5->sleep = H5_SLEEPING;303303+ return;304304+ } else if (memcmp(data, woken_req, 2) == 0) {305305+ BT_DBG("Peer woke up");306306+ h5->sleep = H5_AWAKE;307307+ } else if (memcmp(data, wakeup_req, 2) == 0) {308308+ BT_DBG("Peer requested wakeup");309309+ h5_link_control(hu, woken_req, 2);310310+ h5->sleep = H5_AWAKE;311311+ } else {312312+ BT_DBG("Link Control: 0x%02hhx 0x%02hhx", data[0], data[1]);313313+ return;314314+ }315315+316316+ hci_uart_tx_wakeup(hu);317317+}318318+319319+static void h5_complete_rx_pkt(struct hci_uart *hu)320320+{321321+ struct h5 *h5 = hu->priv;322322+ const unsigned char *hdr = h5->rx_skb->data;323323+324324+ if (H5_HDR_RELIABLE(hdr)) {325325+ h5->tx_ack = (h5->tx_ack + 1) % 8;326326+ set_bit(H5_TX_ACK_REQ, &h5->flags);327327+ hci_uart_tx_wakeup(hu);328328+ }329329+330330+ h5->rx_ack = H5_HDR_ACK(hdr);331331+332332+ h5_pkt_cull(h5);333333+334334+ switch (H5_HDR_PKT_TYPE(hdr)) {335335+ case HCI_EVENT_PKT:336336+ case HCI_ACLDATA_PKT:337337+ case HCI_SCODATA_PKT:338338+ bt_cb(h5->rx_skb)->pkt_type = H5_HDR_PKT_TYPE(hdr);339339+340340+ /* Remove Three-wire header */341341+ skb_pull(h5->rx_skb, 4);342342+343343+ hci_recv_frame(h5->rx_skb);344344+ h5->rx_skb = NULL;345345+346346+ break;347347+348348+ default:349349+ h5_handle_internal_rx(hu);350350+ break;351351+ }352352+353353+ h5_reset_rx(h5);354354+}355355+356356+static int h5_rx_crc(struct hci_uart *hu, unsigned char c)357357+{358358+ struct h5 *h5 = hu->priv;359359+360360+ h5_complete_rx_pkt(hu);361361+ h5_reset_rx(h5);362362+363363+ return 0;364364+}365365+366366+static int h5_rx_payload(struct hci_uart *hu, unsigned char c)367367+{368368+ struct h5 *h5 = hu->priv;369369+ const unsigned char *hdr = h5->rx_skb->data;370370+371371+ if (H5_HDR_CRC(hdr)) {372372+ h5->rx_func = h5_rx_crc;373373+ h5->rx_pending = 2;374374+ } else {375375+ h5_complete_rx_pkt(hu);376376+ h5_reset_rx(h5);377377+ }378378+379379+ return 0;380380+}381381+382382+static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c)383383+{384384+ struct h5 *h5 = hu->priv;385385+ const unsigned char *hdr = h5->rx_skb->data;386386+387387+ BT_DBG("%s rx: seq %u ack %u crc %u rel %u type %u len %u",388388+ hu->hdev->name, H5_HDR_SEQ(hdr), H5_HDR_ACK(hdr),389389+ H5_HDR_CRC(hdr), H5_HDR_RELIABLE(hdr), H5_HDR_PKT_TYPE(hdr),390390+ H5_HDR_LEN(hdr));391391+392392+ if (((hdr[0] + hdr[1] + hdr[2] + hdr[3]) & 0xff) != 0xff) {393393+ BT_ERR("Invalid header checksum");394394+ h5_reset_rx(h5);395395+ return 0;396396+ }397397+398398+ if (H5_HDR_RELIABLE(hdr) && H5_HDR_SEQ(hdr) != h5->tx_ack) {399399+ BT_ERR("Out-of-order packet arrived (%u != %u)",400400+ H5_HDR_SEQ(hdr), h5->tx_ack);401401+ h5_reset_rx(h5);402402+ return 0;403403+ }404404+405405+ if (h5->state != H5_ACTIVE &&406406+ H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) {407407+ BT_ERR("Non-link packet received in non-active state");408408+ h5_reset_rx(h5);409409+ }410410+411411+ h5->rx_func = h5_rx_payload;412412+ h5->rx_pending = H5_HDR_LEN(hdr);413413+414414+ return 0;415415+}416416+417417+static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c)418418+{419419+ struct h5 *h5 = hu->priv;420420+421421+ if (c == SLIP_DELIMITER)422422+ return 1;423423+424424+ h5->rx_func = h5_rx_3wire_hdr;425425+ h5->rx_pending = 4;426426+427427+ h5->rx_skb = bt_skb_alloc(H5_MAX_LEN, GFP_ATOMIC);428428+ if (!h5->rx_skb) {429429+ BT_ERR("Can't allocate mem for new packet");430430+ h5_reset_rx(h5);431431+ return -ENOMEM;432432+ }433433+434434+ h5->rx_skb->dev = (void *) hu->hdev;435435+436436+ return 0;437437+}438438+439439+static int h5_rx_delimiter(struct hci_uart *hu, unsigned char c)440440+{441441+ struct h5 *h5 = hu->priv;442442+443443+ if (c == SLIP_DELIMITER)444444+ h5->rx_func = h5_rx_pkt_start;445445+446446+ return 1;447447+}448448+449449+static void h5_unslip_one_byte(struct h5 *h5, unsigned char c)450450+{451451+ const u8 delim = SLIP_DELIMITER, esc = SLIP_ESC;452452+ const u8 *byte = &c;453453+454454+ if (!test_bit(H5_RX_ESC, &h5->flags) && c == SLIP_ESC) {455455+ set_bit(H5_RX_ESC, &h5->flags);456456+ return;457457+ }458458+459459+ if (test_and_clear_bit(H5_RX_ESC, &h5->flags)) {460460+ switch (c) {461461+ case SLIP_ESC_DELIM:462462+ byte = &delim;463463+ break;464464+ case SLIP_ESC_ESC:465465+ byte = &esc;466466+ break;467467+ default:468468+ BT_ERR("Invalid esc byte 0x%02hhx", c);469469+ h5_reset_rx(h5);470470+ return;471471+ }472472+ }473473+474474+ memcpy(skb_put(h5->rx_skb, 1), byte, 1);475475+ h5->rx_pending--;476476+477477+ BT_DBG("unsliped 0x%02hhx, rx_pending %zu", *byte, h5->rx_pending);478478+}479479+480480+static void h5_reset_rx(struct h5 *h5)481481+{482482+ if (h5->rx_skb) {483483+ kfree_skb(h5->rx_skb);484484+ h5->rx_skb = NULL;485485+ }486486+487487+ h5->rx_func = h5_rx_delimiter;488488+ h5->rx_pending = 0;489489+ clear_bit(H5_RX_ESC, &h5->flags);490490+}491491+492492+static int h5_recv(struct hci_uart *hu, void *data, int count)493493+{494494+ struct h5 *h5 = hu->priv;495495+ unsigned char *ptr = data;496496+497497+ BT_DBG("%s pending %zu count %d", hu->hdev->name, h5->rx_pending,498498+ count);499499+500500+ while (count > 0) {501501+ int processed;502502+503503+ if (h5->rx_pending > 0) {504504+ if (*ptr == SLIP_DELIMITER) {505505+ BT_ERR("Too short H5 packet");506506+ h5_reset_rx(h5);507507+ continue;508508+ }509509+510510+ h5_unslip_one_byte(h5, *ptr);511511+512512+ ptr++; count--;513513+ continue;514514+ }515515+516516+ processed = h5->rx_func(hu, *ptr);517517+ if (processed < 0)518518+ return processed;519519+520520+ ptr += processed;521521+ count -= processed;522522+ }523523+524524+ return 0;525525+}526526+527527+static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)528528+{529529+ struct h5 *h5 = hu->priv;530530+531531+ if (skb->len > 0xfff) {532532+ BT_ERR("Packet too long (%u bytes)", skb->len);533533+ kfree_skb(skb);534534+ return 0;535535+ }536536+537537+ if (h5->state != H5_ACTIVE) {538538+ BT_ERR("Ignoring HCI data in non-active state");539539+ kfree_skb(skb);540540+ return 0;541541+ }542542+543543+ switch (bt_cb(skb)->pkt_type) {544544+ case HCI_ACLDATA_PKT:545545+ case HCI_COMMAND_PKT:546546+ skb_queue_tail(&h5->rel, skb);547547+ break;548548+549549+ case HCI_SCODATA_PKT:550550+ skb_queue_tail(&h5->unrel, skb);551551+ break;552552+553553+ default:554554+ BT_ERR("Unknown packet type %u", bt_cb(skb)->pkt_type);555555+ kfree_skb(skb);556556+ break;557557+ }558558+559559+ return 0;560560+}561561+562562+static void h5_slip_delim(struct sk_buff *skb)563563+{564564+ const char delim = SLIP_DELIMITER;565565+566566+ memcpy(skb_put(skb, 1), &delim, 1);567567+}568568+569569+static void h5_slip_one_byte(struct sk_buff *skb, u8 c)570570+{571571+ const char esc_delim[2] = { SLIP_ESC, SLIP_ESC_DELIM };572572+ const char esc_esc[2] = { SLIP_ESC, SLIP_ESC_ESC };573573+574574+ switch (c) {575575+ case SLIP_DELIMITER:576576+ memcpy(skb_put(skb, 2), &esc_delim, 2);577577+ break;578578+ case SLIP_ESC:579579+ memcpy(skb_put(skb, 2), &esc_esc, 2);580580+ break;581581+ default:582582+ memcpy(skb_put(skb, 1), &c, 1);583583+ }584584+}585585+586586+static bool valid_packet_type(u8 type)587587+{588588+ switch (type) {589589+ case HCI_ACLDATA_PKT:590590+ case HCI_COMMAND_PKT:591591+ case HCI_SCODATA_PKT:592592+ case HCI_3WIRE_LINK_PKT:593593+ case HCI_3WIRE_ACK_PKT:594594+ return true;595595+ default:596596+ return false;597597+ }598598+}599599+600600+static struct sk_buff *h5_prepare_pkt(struct hci_uart *hu, u8 pkt_type,601601+ const u8 *data, size_t len)602602+{603603+ struct h5 *h5 = hu->priv;604604+ struct sk_buff *nskb;605605+ u8 hdr[4];606606+ int i;607607+608608+ if (!valid_packet_type(pkt_type)) {609609+ BT_ERR("Unknown packet type %u", pkt_type);610610+ return NULL;611611+ }612612+613613+ /*614614+ * Max len of packet: (original len + 4 (H5 hdr) + 2 (crc)) * 2615615+ * (because bytes 0xc0 and 0xdb are escaped, worst case is when616616+ * the packet is all made of 0xc0 and 0xdb) + 2 (0xc0617617+ * delimiters at start and end).618618+ */619619+ nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC);620620+ if (!nskb)621621+ return NULL;622622+623623+ bt_cb(nskb)->pkt_type = pkt_type;624624+625625+ h5_slip_delim(nskb);626626+627627+ hdr[0] = h5->tx_ack << 3;628628+ clear_bit(H5_TX_ACK_REQ, &h5->flags);629629+630630+ /* Reliable packet? */631631+ if (pkt_type == HCI_ACLDATA_PKT || pkt_type == HCI_COMMAND_PKT) {632632+ hdr[0] |= 1 << 7;633633+ hdr[0] |= h5->tx_seq;634634+ h5->tx_seq = (h5->tx_seq + 1) % 8;635635+ }636636+637637+ hdr[1] = pkt_type | ((len & 0x0f) << 4);638638+ hdr[2] = len >> 4;639639+ hdr[3] = ~((hdr[0] + hdr[1] + hdr[2]) & 0xff);640640+641641+ BT_DBG("%s tx: seq %u ack %u crc %u rel %u type %u len %u",642642+ hu->hdev->name, H5_HDR_SEQ(hdr), H5_HDR_ACK(hdr),643643+ H5_HDR_CRC(hdr), H5_HDR_RELIABLE(hdr), H5_HDR_PKT_TYPE(hdr),644644+ H5_HDR_LEN(hdr));645645+646646+ for (i = 0; i < 4; i++)647647+ h5_slip_one_byte(nskb, hdr[i]);648648+649649+ for (i = 0; i < len; i++)650650+ h5_slip_one_byte(nskb, data[i]);651651+652652+ h5_slip_delim(nskb);653653+654654+ return nskb;655655+}656656+657657+static struct sk_buff *h5_dequeue(struct hci_uart *hu)658658+{659659+ struct h5 *h5 = hu->priv;660660+ unsigned long flags;661661+ struct sk_buff *skb, *nskb;662662+663663+ if (h5->sleep != H5_AWAKE) {664664+ const unsigned char wakeup_req[] = { 0x05, 0xfa };665665+666666+ if (h5->sleep == H5_WAKING_UP)667667+ return NULL;668668+669669+ h5->sleep = H5_WAKING_UP;670670+ BT_DBG("Sending wakeup request");671671+672672+ mod_timer(&h5->timer, jiffies + HZ / 100);673673+ return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2);674674+ }675675+676676+ if ((skb = skb_dequeue(&h5->unrel)) != NULL) {677677+ nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,678678+ skb->data, skb->len);679679+ if (nskb) {680680+ kfree_skb(skb);681681+ return nskb;682682+ }683683+684684+ skb_queue_head(&h5->unrel, skb);685685+ BT_ERR("Could not dequeue pkt because alloc_skb failed");686686+ }687687+688688+ spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);689689+690690+ if (h5->unack.qlen >= h5->tx_win)691691+ goto unlock;692692+693693+ if ((skb = skb_dequeue(&h5->rel)) != NULL) {694694+ nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,695695+ skb->data, skb->len);696696+ if (nskb) {697697+ __skb_queue_tail(&h5->unack, skb);698698+ mod_timer(&h5->timer, jiffies + H5_ACK_TIMEOUT);699699+ spin_unlock_irqrestore(&h5->unack.lock, flags);700700+ return nskb;701701+ }702702+703703+ skb_queue_head(&h5->rel, skb);704704+ BT_ERR("Could not dequeue pkt because alloc_skb failed");705705+ }706706+707707+unlock:708708+ spin_unlock_irqrestore(&h5->unack.lock, flags);709709+710710+ if (test_bit(H5_TX_ACK_REQ, &h5->flags))711711+ return h5_prepare_pkt(hu, HCI_3WIRE_ACK_PKT, NULL, 0);712712+713713+ return NULL;714714+}715715+716716+static int h5_flush(struct hci_uart *hu)717717+{718718+ BT_DBG("hu %p", hu);719719+ return 0;720720+}721721+722722+static struct hci_uart_proto h5p = {723723+ .id = HCI_UART_3WIRE,724724+ .open = h5_open,725725+ .close = h5_close,726726+ .recv = h5_recv,727727+ .enqueue = h5_enqueue,728728+ .dequeue = h5_dequeue,729729+ .flush = h5_flush,730730+};731731+732732+int __init h5_init(void)733733+{734734+ int err = hci_uart_register_proto(&h5p);735735+736736+ if (!err)737737+ BT_INFO("HCI Three-wire UART (H5) protocol initialized");738738+ else739739+ BT_ERR("HCI Three-wire UART (H5) protocol init failed");740740+741741+ return err;742742+}743743+744744+int __exit h5_deinit(void)745745+{746746+ return hci_uart_unregister_proto(&h5p);747747+}
+55-11
drivers/bluetooth/hci_ldisc.c
···156156 return 0;157157}158158159159+static void hci_uart_init_work(struct work_struct *work)160160+{161161+ struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);162162+ int err;163163+164164+ if (!test_and_clear_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))165165+ return;166166+167167+ err = hci_register_dev(hu->hdev);168168+ if (err < 0) {169169+ BT_ERR("Can't register HCI device");170170+ hci_free_dev(hu->hdev);171171+ hu->hdev = NULL;172172+ hu->proto->close(hu);173173+ }174174+175175+ set_bit(HCI_UART_REGISTERED, &hu->flags);176176+}177177+178178+int hci_uart_init_ready(struct hci_uart *hu)179179+{180180+ if (!test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))181181+ return -EALREADY;182182+183183+ schedule_work(&hu->init_ready);184184+185185+ return 0;186186+}187187+159188/* ------- Interface to HCI layer ------ */160189/* Initialize device */161190static int hci_uart_open(struct hci_dev *hdev)···293264 hu->tty = tty;294265 tty->receive_room = 65536;295266267267+ INIT_WORK(&hu->init_ready, hci_uart_init_work);268268+296269 spin_lock_init(&hu->rx_lock);297270298271 /* Flush any pending characters in the driver and line discipline. */···317286static void hci_uart_tty_close(struct tty_struct *tty)318287{319288 struct hci_uart *hu = (void *)tty->disc_data;289289+ struct hci_dev *hdev;320290321291 BT_DBG("tty %p", tty);322292323293 /* Detach from the tty */324294 tty->disc_data = NULL;325295326326- if (hu) {327327- struct hci_dev *hdev = hu->hdev;296296+ if (!hu)297297+ return;328298329329- if (hdev)330330- hci_uart_close(hdev);299299+ hdev = hu->hdev;300300+ if (hdev)301301+ hci_uart_close(hdev);331302332332- if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {333333- if (hdev) {303303+ if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {304304+ if (hdev) {305305+ if (test_bit(HCI_UART_REGISTERED, &hu->flags))334306 hci_unregister_dev(hdev);335335- hci_free_dev(hdev);336336- }337337- hu->proto->close(hu);307307+ hci_free_dev(hdev);338308 }339339-340340- kfree(hu);309309+ hu->proto->close(hu);341310 }311311+312312+ kfree(hu);342313}343314344315/* hci_uart_tty_wakeup()···434401 else435402 hdev->dev_type = HCI_BREDR;436403404404+ if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))405405+ return 0;406406+437407 if (hci_register_dev(hdev) < 0) {438408 BT_ERR("Can't register HCI device");439409 hci_free_dev(hdev);440410 return -ENODEV;441411 }412412+413413+ set_bit(HCI_UART_REGISTERED, &hu->flags);442414443415 return 0;444416}···596558#ifdef CONFIG_BT_HCIUART_ATH3K597559 ath_init();598560#endif561561+#ifdef CONFIG_BT_HCIUART_3WIRE562562+ h5_init();563563+#endif599564600565 return 0;601566}···618577#endif619578#ifdef CONFIG_BT_HCIUART_ATH3K620579 ath_deinit();580580+#endif581581+#ifdef CONFIG_BT_HCIUART_3WIRE582582+ h5_deinit();621583#endif622584623585 /* Release tty registration of line discipline */
···216216 * used exclusively for WLAN-BT coexistence starting from217217 * AR9462.218218 * @ATH_DBG_DFS: radar datection219219+ * @ATH_DBG_WOW: Wake on Wireless219220 * @ATH_DBG_ANY: enable all debugging220221 *221222 * The debug level is used to control the amount and type of debugging output···244243 ATH_DBG_BSTUCK = 0x00008000,245244 ATH_DBG_MCI = 0x00010000,246245 ATH_DBG_DFS = 0x00020000,246246+ ATH_DBG_WOW = 0x00040000,247247 ATH_DBG_ANY = 0xffffffff248248};249249
···64646565config ATH9K_DFS_CERTIFIED6666 bool "Atheros DFS support for certified platforms"6767- depends on ATH9K && EXPERT6767+ depends on ATH9K && CFG80211_CERTIFICATION_ONUS6868 default n6969 ---help---7070 This option enables DFS support for initiating radiation on
···5050 if (needreset) {5151 ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,5252 "tx hung, resetting the chip\n");5353- RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);5454- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);5353+ ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);5554 return;5655 }5756···6869 unsigned long flags;6970 int busy;7071 u8 is_alive, nbeacon = 1;7272+ enum ath_reset_type type;71737274 ath9k_ps_wakeup(sc);7375 is_alive = ath9k_hw_check_alive(sc->sc_ah);···7878 else if (!is_alive && AR_SREV_9300(sc->sc_ah)) {7979 ath_dbg(common, RESET,8080 "DCU stuck is detected. Schedule chip reset\n");8181- RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG);8181+ type = RESET_TYPE_MAC_HANG;8282 goto sched_reset;8383 }8484···9090 busy, sc->hw_busy_count + 1);9191 if (busy >= 99) {9292 if (++sc->hw_busy_count >= 3) {9393- RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);9393+ type = RESET_TYPE_BB_HANG;9494 goto sched_reset;9595 }9696 } else if (busy >= 0) {···102102 goto out;103103104104sched_reset:105105- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);105105+ ath9k_queue_reset(sc, type);106106out:107107 ath9k_ps_restore(sc);108108}···119119 count++;120120 if (count == 3) {121121 ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");122122- RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);123123- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);122122+ ath9k_queue_reset(sc, RESET_TYPE_PLL_HANG);124123 count = 0;125124 return true;126125 }···431432 }432433}433434434434-void ath_start_ani(struct ath_common *common)435435+void ath_start_ani(struct ath_softc *sc)435436{436436- struct ath_hw *ah = common->ah;437437+ struct ath_hw *ah = sc->sc_ah;438438+ struct ath_common *common = ath9k_hw_common(ah);437439 unsigned long timestamp = jiffies_to_msecs(jiffies);438438- struct ath_softc *sc = (struct ath_softc *) common->priv;439440440440- if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags))441441- return;442442-443443- if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)441441+ if (common->disable_ani ||442442+ !test_bit(SC_OP_ANI_RUN, &sc->sc_flags) ||443443+ (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))444444 return;445445446446 common->ani.longcal_timer = timestamp;447447 common->ani.shortcal_timer = timestamp;448448 common->ani.checkani_timer = timestamp;449449450450+ ath_dbg(common, ANI, "Starting ANI\n");450451 mod_timer(&common->ani.timer,451452 jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval));453453+}454454+455455+void ath_stop_ani(struct ath_softc *sc)456456+{457457+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);458458+459459+ ath_dbg(common, ANI, "Stopping ANI\n");460460+ del_timer_sync(&common->ani.timer);461461+}462462+463463+void ath_check_ani(struct ath_softc *sc)464464+{465465+ struct ath_hw *ah = sc->sc_ah;466466+ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;467467+468468+ /*469469+ * Check for the various conditions in which ANI has to470470+ * be stopped.471471+ */472472+ if (ah->opmode == NL80211_IFTYPE_ADHOC) {473473+ if (!cur_conf->enable_beacon)474474+ goto stop_ani;475475+ } else if (ah->opmode == NL80211_IFTYPE_AP) {476476+ if (!cur_conf->enable_beacon) {477477+ /*478478+ * Disable ANI only when there are no479479+ * associated stations.480480+ */481481+ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))482482+ goto stop_ani;483483+ }484484+ } else if (ah->opmode == NL80211_IFTYPE_STATION) {485485+ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))486486+ goto stop_ani;487487+ }488488+489489+ if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) {490490+ set_bit(SC_OP_ANI_RUN, &sc->sc_flags);491491+ ath_start_ani(sc);492492+ }493493+494494+ return;495495+496496+stop_ani:497497+ clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);498498+ ath_stop_ani(sc);452499}453500454501void ath_update_survey_nf(struct ath_softc *sc, int channel)
+523-184
drivers/net/wireless/ath/ath9k/main.c
···1919#include "ath9k.h"2020#include "btcoex.h"21212222+static void ath9k_set_assoc_state(struct ath_softc *sc,2323+ struct ieee80211_vif *vif);2424+2225u8 ath9k_parse_mpdudensity(u8 mpdudensity)2326{2427 /*···170167171168static void ath_restart_work(struct ath_softc *sc)172169{173173- struct ath_common *common = ath9k_hw_common(sc->sc_ah);174174-175170 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);176171177172 if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) ||···178177 msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));179178180179 ath_start_rx_poll(sc, 3);181181-182182- if (!common->disable_ani)183183- ath_start_ani(common);180180+ ath_start_ani(sc);184181}185182186183static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)187184{188185 struct ath_hw *ah = sc->sc_ah;189189- struct ath_common *common = ath9k_hw_common(ah);190186 bool ret = true;191187192188 ieee80211_stop_queues(sc->hw);193189194190 sc->hw_busy_count = 0;195195- del_timer_sync(&common->ani.timer);191191+ ath_stop_ani(sc);196192 del_timer_sync(&sc->rx_poll_timer);197193198194 ath9k_debug_samp_bb_mac(sc);···234236 if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))235237 goto work;236238237237- ath_set_beacon(sc);239239+ ath9k_set_beacon(sc);238240239241 if (ah->opmode == NL80211_IFTYPE_STATION &&240242 test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {···363365 struct ath_softc *sc = (struct ath_softc *)data;364366 struct ath_hw *ah = sc->sc_ah;365367 struct ath_common *common = ath9k_hw_common(ah);368368+ enum ath_reset_type type;366369 unsigned long flags;367370 u32 status = sc->intrstatus;368371 u32 rxmask;···373374374375 if ((status & ATH9K_INT_FATAL) ||375376 (status & ATH9K_INT_BB_WATCHDOG)) {376376-#ifdef CONFIG_ATH9K_DEBUGFS377377- enum ath_reset_type type;378377379378 if (status & ATH9K_INT_FATAL)380379 type = RESET_TYPE_FATAL_INT;381380 else382381 type = RESET_TYPE_BB_WATCHDOG;383382384384- RESET_STAT_INC(sc, type);385385-#endif386386- set_bit(SC_OP_HW_RESET, &sc->sc_flags);387387- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);383383+ ath9k_queue_reset(sc, type);388384 goto out;389385 }390386···487493 if (status & SCHED_INTR)488494 sched = true;489495496496+#ifdef CONFIG_PM_SLEEP497497+ if (status & ATH9K_INT_BMISS) {498498+ if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {499499+ ath_dbg(common, ANY, "during WoW we got a BMISS\n");500500+ atomic_inc(&sc->wow_got_bmiss_intr);501501+ atomic_dec(&sc->wow_sleep_proc_intr);502502+ }503503+ ath_dbg(common, INTERRUPT, "beacon miss interrupt\n");504504+ }505505+#endif506506+490507 /*491508 * If a FATAL or RXORN interrupt is received, we have to reset the492509 * chip immediately.···578573 ath9k_ps_restore(sc);579574580575 return r;576576+}577577+578578+void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)579579+{580580+#ifdef CONFIG_ATH9K_DEBUGFS581581+ RESET_STAT_INC(sc, type);582582+#endif583583+ set_bit(SC_OP_HW_RESET, &sc->sc_flags);584584+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);581585}582586583587void ath_reset_work(struct work_struct *work)···855841 }856842}857843858858-static void ath9k_reclaim_beacon(struct ath_softc *sc,859859- struct ieee80211_vif *vif)860860-{861861- struct ath_vif *avp = (void *)vif->drv_priv;862862-863863- ath9k_set_beaconing_status(sc, false);864864- ath_beacon_return(sc, avp);865865- ath9k_set_beaconing_status(sc, true);866866-}867867-868844static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)869845{870846 struct ath9k_vif_iter_data *iter_data = data;···884880 default:885881 break;886882 }883883+}884884+885885+static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)886886+{887887+ struct ath_softc *sc = data;888888+ struct ath_vif *avp = (void *)vif->drv_priv;889889+890890+ if (vif->type != NL80211_IFTYPE_STATION)891891+ return;892892+893893+ if (avp->primary_sta_vif)894894+ ath9k_set_assoc_state(sc, vif);887895}888896889897/* Called with sc->mutex held. */···931915 struct ath_hw *ah = sc->sc_ah;932916 struct ath_common *common = ath9k_hw_common(ah);933917 struct ath9k_vif_iter_data iter_data;918918+ enum nl80211_iftype old_opmode = ah->opmode;934919935920 ath9k_calculate_iter_data(hw, vif, &iter_data);936921937937- /* Set BSSID mask. */938922 memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);939923 ath_hw_setbssidmask(common);940924941941- /* Set op-mode & TSF */942925 if (iter_data.naps > 0) {943943- ath9k_hw_set_tsfadjust(ah, 1);944944- set_bit(SC_OP_TSF_RESET, &sc->sc_flags);926926+ ath9k_hw_set_tsfadjust(ah, true);945927 ah->opmode = NL80211_IFTYPE_AP;946928 } else {947947- ath9k_hw_set_tsfadjust(ah, 0);948948- clear_bit(SC_OP_TSF_RESET, &sc->sc_flags);929929+ ath9k_hw_set_tsfadjust(ah, false);949930950931 if (iter_data.nmeshes)951932 ah->opmode = NL80211_IFTYPE_MESH_POINT;···954941 ah->opmode = NL80211_IFTYPE_STATION;955942 }956943957957- /*958958- * Enable MIB interrupts when there are hardware phy counters.959959- */944944+ ath9k_hw_setopmode(ah);945945+960946 if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)961947 ah->imask |= ATH9K_INT_TSFOOR;962948 else···963951964952 ath9k_hw_set_interrupts(ah);965953966966- /* Set up ANI */967967- if (iter_data.naps > 0) {968968- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;969969-970970- if (!common->disable_ani) {971971- set_bit(SC_OP_ANI_RUN, &sc->sc_flags);972972- ath_start_ani(common);973973- }974974-975975- } else {976976- clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);977977- del_timer_sync(&common->ani.timer);978978- }979979-}980980-981981-/* Called with sc->mutex held, vif counts set up properly. */982982-static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,983983- struct ieee80211_vif *vif)984984-{985985- struct ath_softc *sc = hw->priv;986986-987987- ath9k_calculate_summary_state(hw, vif);988988-989989- if (ath9k_uses_beacons(vif->type)) {990990- /* Reserve a beacon slot for the vif */991991- ath9k_set_beaconing_status(sc, false);992992- ath_beacon_alloc(sc, vif);993993- ath9k_set_beaconing_status(sc, true);954954+ /*955955+ * If we are changing the opmode to STATION,956956+ * a beacon sync needs to be done.957957+ */958958+ if (ah->opmode == NL80211_IFTYPE_STATION &&959959+ old_opmode == NL80211_IFTYPE_AP &&960960+ test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {961961+ ieee80211_iterate_active_interfaces_atomic(sc->hw,962962+ ath9k_sta_vif_iter, sc);994963 }995964}996965···1014102110151022 sc->nvifs++;1016102310171017- ath9k_do_vif_add_setup(hw, vif);10241024+ ath9k_calculate_summary_state(hw, vif);10251025+ if (ath9k_uses_beacons(vif->type))10261026+ ath9k_beacon_assign_slot(sc, vif);10271027+10181028out:10191029 mutex_unlock(&sc->mutex);10201030 ath9k_ps_restore(sc);···10341038 int ret = 0;1035103910361040 ath_dbg(common, CONFIG, "Change Interface\n");10411041+10371042 mutex_lock(&sc->mutex);10381043 ath9k_ps_wakeup(sc);10391044···10471050 }10481051 }1049105210501050- /* Clean up old vif stuff */10511053 if (ath9k_uses_beacons(vif->type))10521052- ath9k_reclaim_beacon(sc, vif);10541054+ ath9k_beacon_remove_slot(sc, vif);1053105510541054- /* Add new settings */10551056 vif->type = new_type;10561057 vif->p2p = p2p;1057105810581058- ath9k_do_vif_add_setup(hw, vif);10591059+ ath9k_calculate_summary_state(hw, vif);10601060+ if (ath9k_uses_beacons(vif->type))10611061+ ath9k_beacon_assign_slot(sc, vif);10621062+10591063out:10601064 ath9k_ps_restore(sc);10611065 mutex_unlock(&sc->mutex);···1076107810771079 sc->nvifs--;1078108010791079- /* Reclaim beacon resources */10801081 if (ath9k_uses_beacons(vif->type))10811081- ath9k_reclaim_beacon(sc, vif);10821082+ ath9k_beacon_remove_slot(sc, vif);1082108310831084 ath9k_calculate_summary_state(hw, NULL);10841085···13741377 qi.tqi_aifs = params->aifs;13751378 qi.tqi_cwmin = params->cw_min;13761379 qi.tqi_cwmax = params->cw_max;13771377- qi.tqi_burstTime = params->txop;13801380+ qi.tqi_burstTime = params->txop * 32;1378138113791382 ath_dbg(common, CONFIG,13801383 "Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",13811384 queue, txq->axq_qnum, params->aifs, params->cw_min,13821385 params->cw_max, params->txop);1383138613871387+ ath_update_max_aggr_framelen(sc, queue, qi.tqi_burstTime);13841388 ret = ath_txq_update(sc, txq->axq_qnum, &qi);13851389 if (ret)13861390 ath_err(common, "TXQ Update failed\n");13871387-13881388- if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)13891389- if (queue == WME_AC_BE && !ret)13901390- ath_beaconq_config(sc);1391139113921392 mutex_unlock(&sc->mutex);13931393 ath9k_ps_restore(sc);···1454146014551461 return ret;14561462}14571457-static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)14631463+14641464+static void ath9k_set_assoc_state(struct ath_softc *sc,14651465+ struct ieee80211_vif *vif)14581466{14591459- struct ath_softc *sc = data;14601467 struct ath_common *common = ath9k_hw_common(sc->sc_ah);14611461- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;14621468 struct ath_vif *avp = (void *)vif->drv_priv;14691469+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;14631470 unsigned long flags;14711471+14721472+ set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);14731473+ avp->primary_sta_vif = true;14741474+14641475 /*14651465- * Skip iteration if primary station vif's bss info14661466- * was not changed14761476+ * Set the AID, BSSID and do beacon-sync only when14771477+ * the HW opmode is STATION.14781478+ *14791479+ * But the primary bit is set above in any case.14671480 */14681468- if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))14691469- return;14701470-14711471- if (bss_conf->assoc) {14721472- set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);14731473- avp->primary_sta_vif = true;14741474- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);14751475- common->curaid = bss_conf->aid;14761476- ath9k_hw_write_associd(sc->sc_ah);14771477- ath_dbg(common, CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",14781478- bss_conf->aid, common->curbssid);14791479- ath_beacon_config(sc, vif);14801480- /*14811481- * Request a re-configuration of Beacon related timers14821482- * on the receipt of the first Beacon frame (i.e.,14831483- * after time sync with the AP).14841484- */14851485- spin_lock_irqsave(&sc->sc_pm_lock, flags);14861486- sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;14871487- spin_unlock_irqrestore(&sc->sc_pm_lock, flags);14881488-14891489- /* Reset rssi stats */14901490- sc->last_rssi = ATH_RSSI_DUMMY_MARKER;14911491- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;14921492-14931493- ath_start_rx_poll(sc, 3);14941494-14951495- if (!common->disable_ani) {14961496- set_bit(SC_OP_ANI_RUN, &sc->sc_flags);14971497- ath_start_ani(common);14981498- }14991499-15001500- }15011501-}15021502-15031503-static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)15041504-{15051505- struct ath_common *common = ath9k_hw_common(sc->sc_ah);15061506- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;15071507- struct ath_vif *avp = (void *)vif->drv_priv;15081508-15091481 if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)15101482 return;1511148315121512- /* Reconfigure bss info */15131513- if (avp->primary_sta_vif && !bss_conf->assoc) {15141514- ath_dbg(common, CONFIG, "Bss Info DISASSOC %d, bssid %pM\n",15151515- common->curaid, common->curbssid);15161516- clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);15171517- clear_bit(SC_OP_BEACONS, &sc->sc_flags);15181518- avp->primary_sta_vif = false;15191519- memset(common->curbssid, 0, ETH_ALEN);15201520- common->curaid = 0;15211521- }14841484+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);14851485+ common->curaid = bss_conf->aid;14861486+ ath9k_hw_write_associd(sc->sc_ah);1522148715231523- ieee80211_iterate_active_interfaces_atomic(15241524- sc->hw, ath9k_bss_iter, sc);14881488+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;14891489+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;1525149015261526- /*15271527- * None of station vifs are associated.15281528- * Clear bssid & aid15291529- */15301530- if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {15311531- ath9k_hw_write_associd(sc->sc_ah);15321532- clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);15331533- del_timer_sync(&common->ani.timer);15341534- del_timer_sync(&sc->rx_poll_timer);15351535- memset(&sc->caldata, 0, sizeof(sc->caldata));15361536- }14911491+ spin_lock_irqsave(&sc->sc_pm_lock, flags);14921492+ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;14931493+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);14941494+14951495+ ath_dbg(common, CONFIG,14961496+ "Primary Station interface: %pM, BSSID: %pM\n",14971497+ vif->addr, common->curbssid);14981498+}14991499+15001500+static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)15011501+{15021502+ struct ath_softc *sc = data;15031503+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;15041504+15051505+ if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))15061506+ return;15071507+15081508+ if (bss_conf->assoc)15091509+ ath9k_set_assoc_state(sc, vif);15371510}1538151115391512static void ath9k_bss_info_changed(struct ieee80211_hw *hw,···15081547 struct ieee80211_bss_conf *bss_conf,15091548 u32 changed)15101549{15501550+#define CHECK_ANI \15511551+ (BSS_CHANGED_ASSOC | \15521552+ BSS_CHANGED_IBSS | \15531553+ BSS_CHANGED_BEACON_ENABLED)15541554+15111555 struct ath_softc *sc = hw->priv;15121556 struct ath_hw *ah = sc->sc_ah;15131557 struct ath_common *common = ath9k_hw_common(ah);···15231557 mutex_lock(&sc->mutex);1524155815251559 if (changed & BSS_CHANGED_ASSOC) {15261526- ath9k_config_bss(sc, vif);15601560+ ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",15611561+ bss_conf->bssid, bss_conf->assoc);1527156215281528- ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",15291529- common->curbssid, common->curaid);15301530- }15631563+ if (avp->primary_sta_vif && !bss_conf->assoc) {15641564+ clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);15651565+ avp->primary_sta_vif = false;1531156615321532- if (changed & BSS_CHANGED_IBSS) {15331533- /* There can be only one vif available */15341534- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);15351535- common->curaid = bss_conf->aid;15361536- ath9k_hw_write_associd(sc->sc_ah);15671567+ if (ah->opmode == NL80211_IFTYPE_STATION)15681568+ clear_bit(SC_OP_BEACONS, &sc->sc_flags);15691569+ }1537157015381538- if (bss_conf->ibss_joined) {15391539- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;15711571+ ieee80211_iterate_active_interfaces_atomic(sc->hw,15721572+ ath9k_bss_assoc_iter, sc);1540157315411541- if (!common->disable_ani) {15421542- set_bit(SC_OP_ANI_RUN, &sc->sc_flags);15431543- ath_start_ani(common);15441544- }15451545-15461546- } else {15471547- clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);15481548- del_timer_sync(&common->ani.timer);15491549- del_timer_sync(&sc->rx_poll_timer);15741574+ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&15751575+ ah->opmode == NL80211_IFTYPE_STATION) {15761576+ memset(common->curbssid, 0, ETH_ALEN);15771577+ common->curaid = 0;15781578+ ath9k_hw_write_associd(sc->sc_ah);15501579 }15511580 }1552158115531553- /*15541554- * In case of AP mode, the HW TSF has to be reset15551555- * when the beacon interval changes.15561556- */15571557- if ((changed & BSS_CHANGED_BEACON_INT) &&15581558- (vif->type == NL80211_IFTYPE_AP))15591559- set_bit(SC_OP_TSF_RESET, &sc->sc_flags);15821582+ if (changed & BSS_CHANGED_IBSS) {15831583+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);15841584+ common->curaid = bss_conf->aid;15851585+ ath9k_hw_write_associd(sc->sc_ah);15861586+ }1560158715611561- /* Configure beaconing (AP, IBSS, MESH) */15621562- if (ath9k_uses_beacons(vif->type) &&15631563- ((changed & BSS_CHANGED_BEACON) ||15641564- (changed & BSS_CHANGED_BEACON_ENABLED) ||15651565- (changed & BSS_CHANGED_BEACON_INT))) {15661566- ath9k_set_beaconing_status(sc, false);15671567- if (bss_conf->enable_beacon)15681568- ath_beacon_alloc(sc, vif);15691569- else15701570- avp->is_bslot_active = false;15711571- ath_beacon_config(sc, vif);15721572- ath9k_set_beaconing_status(sc, true);15881588+ if ((changed & BSS_CHANGED_BEACON_ENABLED) ||15891589+ (changed & BSS_CHANGED_BEACON_INT)) {15901590+ if (ah->opmode == NL80211_IFTYPE_AP &&15911591+ bss_conf->enable_beacon)15921592+ ath9k_set_tsfadjust(sc, vif);15931593+ if (ath9k_allow_beacon_config(sc, vif))15941594+ ath9k_beacon_config(sc, vif, changed);15731595 }1574159615751597 if (changed & BSS_CHANGED_ERP_SLOT) {···15791625 }15801626 }1581162716281628+ if (changed & CHECK_ANI)16291629+ ath_check_ani(sc);16301630+15821631 mutex_unlock(&sc->mutex);15831632 ath9k_ps_restore(sc);16331633+16341634+#undef CHECK_ANI15841635}1585163615861637static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)···18141855 if (!vif)18151856 return 0;1816185718171817- avp = (void *)vif->drv_priv;18181818- if (!avp->is_bslot_active)18581858+ if (!vif->bss_conf.enable_beacon)18191859 return 0;18601860+18611861+ avp = (void *)vif->drv_priv;1820186218211863 if (!sc->beacon.tx_processed && !edma) {18221864 tasklet_disable(&sc->bcon_tasklet);···18721912 return filled;18731913}1874191419151915+static bool validate_antenna_mask(struct ath_hw *ah, u32 val)19161916+{19171917+ switch (val & 0x7) {19181918+ case 0x1:19191919+ case 0x3:19201920+ case 0x7:19211921+ return true;19221922+ case 0x2:19231923+ return (ah->caps.rx_chainmask == 1);19241924+ default:19251925+ return false;19261926+ }19271927+}19281928+18751929static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)18761930{18771931 struct ath_softc *sc = hw->priv;18781932 struct ath_hw *ah = sc->sc_ah;1879193318801880- if (!rx_ant || !tx_ant)19341934+ if (ah->caps.rx_chainmask != 1)19351935+ rx_ant |= tx_ant;19361936+19371937+ if (!validate_antenna_mask(ah, rx_ant) || !tx_ant)18811938 return -EINVAL;1882193918831940 sc->ant_rx = rx_ant;···20522075#endif205320762054207720782078+#ifdef CONFIG_PM_SLEEP20792079+20802080+static void ath9k_wow_map_triggers(struct ath_softc *sc,20812081+ struct cfg80211_wowlan *wowlan,20822082+ u32 *wow_triggers)20832083+{20842084+ if (wowlan->disconnect)20852085+ *wow_triggers |= AH_WOW_LINK_CHANGE |20862086+ AH_WOW_BEACON_MISS;20872087+ if (wowlan->magic_pkt)20882088+ *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN;20892089+20902090+ if (wowlan->n_patterns)20912091+ *wow_triggers |= AH_WOW_USER_PATTERN_EN;20922092+20932093+ sc->wow_enabled = *wow_triggers;20942094+20952095+}20962096+20972097+static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)20982098+{20992099+ struct ath_hw *ah = sc->sc_ah;21002100+ struct ath_common *common = ath9k_hw_common(ah);21012101+ struct ath9k_hw_capabilities *pcaps = &ah->caps;21022102+ int pattern_count = 0;21032103+ int i, byte_cnt;21042104+ u8 dis_deauth_pattern[MAX_PATTERN_SIZE];21052105+ u8 dis_deauth_mask[MAX_PATTERN_SIZE];21062106+21072107+ memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE);21082108+ memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE);21092109+21102110+ /*21112111+ * Create Dissassociate / Deauthenticate packet filter21122112+ *21132113+ * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes21142114+ * +--------------+----------+---------+--------+--------+----21152115+ * + Frame Control+ Duration + DA + SA + BSSID +21162116+ * +--------------+----------+---------+--------+--------+----21172117+ *21182118+ * The above is the management frame format for disassociate/21192119+ * deauthenticate pattern, from this we need to match the first byte21202120+ * of 'Frame Control' and DA, SA, and BSSID fields21212121+ * (skipping 2nd byte of FC and Duration feild.21222122+ *21232123+ * Disassociate pattern21242124+ * --------------------21252125+ * Frame control = 00 00 101021262126+ * DA, SA, BSSID = x:x:x:x:x:x21272127+ * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x21282128+ * | x:x:x:x:x:x -- 22 bytes21292129+ *21302130+ * Deauthenticate pattern21312131+ * ----------------------21322132+ * Frame control = 00 00 110021332133+ * DA, SA, BSSID = x:x:x:x:x:x21342134+ * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x21352135+ * | x:x:x:x:x:x -- 22 bytes21362136+ */21372137+21382138+ /* Create Disassociate Pattern first */21392139+21402140+ byte_cnt = 0;21412141+21422142+ /* Fill out the mask with all FF's */21432143+21442144+ for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++)21452145+ dis_deauth_mask[i] = 0xff;21462146+21472147+ /* copy the first byte of frame control field */21482148+ dis_deauth_pattern[byte_cnt] = 0xa0;21492149+ byte_cnt++;21502150+21512151+ /* skip 2nd byte of frame control and Duration field */21522152+ byte_cnt += 3;21532153+21542154+ /*21552155+ * need not match the destination mac address, it can be a broadcast21562156+ * mac address or an unicast to this station21572157+ */21582158+ byte_cnt += 6;21592159+21602160+ /* copy the source mac address */21612161+ memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);21622162+21632163+ byte_cnt += 6;21642164+21652165+ /* copy the bssid, its same as the source mac address */21662166+21672167+ memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);21682168+21692169+ /* Create Disassociate pattern mask */21702170+21712171+ if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_EXACT) {21722172+21732173+ if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_DWORD) {21742174+ /*21752175+ * for AR9280, because of hardware limitation, the21762176+ * first 4 bytes have to be matched for all patterns.21772177+ * the mask for disassociation and de-auth pattern21782178+ * matching need to enable the first 4 bytes.21792179+ * also the duration field needs to be filled.21802180+ */21812181+ dis_deauth_mask[0] = 0xf0;21822182+21832183+ /*21842184+ * fill in duration field21852185+ FIXME: what is the exact value ?21862186+ */21872187+ dis_deauth_pattern[2] = 0xff;21882188+ dis_deauth_pattern[3] = 0xff;21892189+ } else {21902190+ dis_deauth_mask[0] = 0xfe;21912191+ }21922192+21932193+ dis_deauth_mask[1] = 0x03;21942194+ dis_deauth_mask[2] = 0xc0;21952195+ } else {21962196+ dis_deauth_mask[0] = 0xef;21972197+ dis_deauth_mask[1] = 0x3f;21982198+ dis_deauth_mask[2] = 0x00;21992199+ dis_deauth_mask[3] = 0xfc;22002200+ }22012201+22022202+ ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n");22032203+22042204+ ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,22052205+ pattern_count, byte_cnt);22062206+22072207+ pattern_count++;22082208+ /*22092209+ * for de-authenticate pattern, only the first byte of the frame22102210+ * control field gets changed from 0xA0 to 0xC022112211+ */22122212+ dis_deauth_pattern[0] = 0xC0;22132213+22142214+ ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,22152215+ pattern_count, byte_cnt);22162216+22172217+}22182218+22192219+static void ath9k_wow_add_pattern(struct ath_softc *sc,22202220+ struct cfg80211_wowlan *wowlan)22212221+{22222222+ struct ath_hw *ah = sc->sc_ah;22232223+ struct ath9k_wow_pattern *wow_pattern = NULL;22242224+ struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns;22252225+ int mask_len;22262226+ s8 i = 0;22272227+22282228+ if (!wowlan->n_patterns)22292229+ return;22302230+22312231+ /*22322232+ * Add the new user configured patterns22332233+ */22342234+ for (i = 0; i < wowlan->n_patterns; i++) {22352235+22362236+ wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL);22372237+22382238+ if (!wow_pattern)22392239+ return;22402240+22412241+ /*22422242+ * TODO: convert the generic user space pattern to22432243+ * appropriate chip specific/802.11 pattern.22442244+ */22452245+22462246+ mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);22472247+ memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE);22482248+ memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE);22492249+ memcpy(wow_pattern->pattern_bytes, patterns[i].pattern,22502250+ patterns[i].pattern_len);22512251+ memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len);22522252+ wow_pattern->pattern_len = patterns[i].pattern_len;22532253+22542254+ /*22552255+ * just need to take care of deauth and disssoc pattern,22562256+ * make sure we don't overwrite them.22572257+ */22582258+22592259+ ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes,22602260+ wow_pattern->mask_bytes,22612261+ i + 2,22622262+ wow_pattern->pattern_len);22632263+ kfree(wow_pattern);22642264+22652265+ }22662266+22672267+}22682268+22692269+static int ath9k_suspend(struct ieee80211_hw *hw,22702270+ struct cfg80211_wowlan *wowlan)22712271+{22722272+ struct ath_softc *sc = hw->priv;22732273+ struct ath_hw *ah = sc->sc_ah;22742274+ struct ath_common *common = ath9k_hw_common(ah);22752275+ u32 wow_triggers_enabled = 0;22762276+ int ret = 0;22772277+22782278+ mutex_lock(&sc->mutex);22792279+22802280+ ath_cancel_work(sc);22812281+ del_timer_sync(&common->ani.timer);22822282+ del_timer_sync(&sc->rx_poll_timer);22832283+22842284+ if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {22852285+ ath_dbg(common, ANY, "Device not present\n");22862286+ ret = -EINVAL;22872287+ goto fail_wow;22882288+ }22892289+22902290+ if (WARN_ON(!wowlan)) {22912291+ ath_dbg(common, WOW, "None of the WoW triggers enabled\n");22922292+ ret = -EINVAL;22932293+ goto fail_wow;22942294+ }22952295+22962296+ if (!device_can_wakeup(sc->dev)) {22972297+ ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n");22982298+ ret = 1;22992299+ goto fail_wow;23002300+ }23012301+23022302+ /*23032303+ * none of the sta vifs are associated23042304+ * and we are not currently handling multivif23052305+ * cases, for instance we have to seperately23062306+ * configure 'keep alive frame' for each23072307+ * STA.23082308+ */23092309+23102310+ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {23112311+ ath_dbg(common, WOW, "None of the STA vifs are associated\n");23122312+ ret = 1;23132313+ goto fail_wow;23142314+ }23152315+23162316+ if (sc->nvifs > 1) {23172317+ ath_dbg(common, WOW, "WoW for multivif is not yet supported\n");23182318+ ret = 1;23192319+ goto fail_wow;23202320+ }23212321+23222322+ ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled);23232323+23242324+ ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n",23252325+ wow_triggers_enabled);23262326+23272327+ ath9k_ps_wakeup(sc);23282328+23292329+ ath9k_stop_btcoex(sc);23302330+23312331+ /*23322332+ * Enable wake up on recieving disassoc/deauth23332333+ * frame by default.23342334+ */23352335+ ath9k_wow_add_disassoc_deauth_pattern(sc);23362336+23372337+ if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN)23382338+ ath9k_wow_add_pattern(sc, wowlan);23392339+23402340+ spin_lock_bh(&sc->sc_pcu_lock);23412341+ /*23422342+ * To avoid false wake, we enable beacon miss interrupt only23432343+ * when we go to sleep. We save the current interrupt mask23442344+ * so we can restore it after the system wakes up23452345+ */23462346+ sc->wow_intr_before_sleep = ah->imask;23472347+ ah->imask &= ~ATH9K_INT_GLOBAL;23482348+ ath9k_hw_disable_interrupts(ah);23492349+ ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL;23502350+ ath9k_hw_set_interrupts(ah);23512351+ ath9k_hw_enable_interrupts(ah);23522352+23532353+ spin_unlock_bh(&sc->sc_pcu_lock);23542354+23552355+ /*23562356+ * we can now sync irq and kill any running tasklets, since we already23572357+ * disabled interrupts and not holding a spin lock23582358+ */23592359+ synchronize_irq(sc->irq);23602360+ tasklet_kill(&sc->intr_tq);23612361+23622362+ ath9k_hw_wow_enable(ah, wow_triggers_enabled);23632363+23642364+ ath9k_ps_restore(sc);23652365+ ath_dbg(common, ANY, "WoW enabled in ath9k\n");23662366+ atomic_inc(&sc->wow_sleep_proc_intr);23672367+23682368+fail_wow:23692369+ mutex_unlock(&sc->mutex);23702370+ return ret;23712371+}23722372+23732373+static int ath9k_resume(struct ieee80211_hw *hw)23742374+{23752375+ struct ath_softc *sc = hw->priv;23762376+ struct ath_hw *ah = sc->sc_ah;23772377+ struct ath_common *common = ath9k_hw_common(ah);23782378+ u32 wow_status;23792379+23802380+ mutex_lock(&sc->mutex);23812381+23822382+ ath9k_ps_wakeup(sc);23832383+23842384+ spin_lock_bh(&sc->sc_pcu_lock);23852385+23862386+ ath9k_hw_disable_interrupts(ah);23872387+ ah->imask = sc->wow_intr_before_sleep;23882388+ ath9k_hw_set_interrupts(ah);23892389+ ath9k_hw_enable_interrupts(ah);23902390+23912391+ spin_unlock_bh(&sc->sc_pcu_lock);23922392+23932393+ wow_status = ath9k_hw_wow_wakeup(ah);23942394+23952395+ if (atomic_read(&sc->wow_got_bmiss_intr) == 0) {23962396+ /*23972397+ * some devices may not pick beacon miss23982398+ * as the reason they woke up so we add23992399+ * that here for that shortcoming.24002400+ */24012401+ wow_status |= AH_WOW_BEACON_MISS;24022402+ atomic_dec(&sc->wow_got_bmiss_intr);24032403+ ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n");24042404+ }24052405+24062406+ atomic_dec(&sc->wow_sleep_proc_intr);24072407+24082408+ if (wow_status) {24092409+ ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n",24102410+ ath9k_hw_wow_event_to_string(wow_status), wow_status);24112411+ }24122412+24132413+ ath_restart_work(sc);24142414+ ath9k_start_btcoex(sc);24152415+24162416+ ath9k_ps_restore(sc);24172417+ mutex_unlock(&sc->mutex);24182418+24192419+ return 0;24202420+}24212421+24222422+static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)24232423+{24242424+ struct ath_softc *sc = hw->priv;24252425+24262426+ mutex_lock(&sc->mutex);24272427+ device_init_wakeup(sc->dev, 1);24282428+ device_set_wakeup_enable(sc->dev, enabled);24292429+ mutex_unlock(&sc->mutex);24302430+}24312431+24322432+#endif24332433+20552434struct ieee80211_ops ath9k_ops = {20562435 .tx = ath9k_tx,20572436 .start = ath9k_start,···24362103 .get_stats = ath9k_get_stats,24372104 .set_antenna = ath9k_set_antenna,24382105 .get_antenna = ath9k_get_antenna,21062106+21072107+#ifdef CONFIG_PM_SLEEP21082108+ .suspend = ath9k_suspend,21092109+ .resume = ath9k_resume,21102110+ .set_wakeup = ath9k_set_wakeup,21112111+#endif2439211224402113#ifdef CONFIG_ATH9K_DEBUGFS24412114 .get_et_sset_count = ath9k_get_et_sset_count,
+1-1
drivers/net/wireless/ath/ath9k/mci.c
···202202 case MCI_GPM_BT_CAL_REQ:203203 if (mci_hw->bt_state == MCI_BT_AWAKE) {204204 ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START);205205- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);205205+ ath9k_queue_reset(sc, RESET_TYPE_MCI);206206 }207207 ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);208208 break;
+3
drivers/net/wireless/ath/ath9k/pci.c
···313313 struct ieee80211_hw *hw = pci_get_drvdata(pdev);314314 struct ath_softc *sc = hw->priv;315315316316+ if (sc->wow_enabled)317317+ return 0;318318+316319 /* The device has to be moved to FULLSLEEP forcibly.317320 * Otherwise the chip never moved to full sleep,318321 * when no interface is up.
+1-1
drivers/net/wireless/ath/ath9k/recv.c
···553553 sc->ps_flags &= ~PS_BEACON_SYNC;554554 ath_dbg(common, PS,555555 "Reconfigure Beacon timers based on timestamp from the AP\n");556556- ath_set_beacon(sc);556556+ ath9k_set_beacon(sc);557557 }558558559559 if (ath_beacon_dtim_pending_cab(skb)) {
···11+/*22+ * Copyright (c) 2012 Qualcomm Atheros, Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include <linux/export.h>1818+#include "ath9k.h"1919+#include "reg.h"2020+#include "hw-ops.h"2121+2222+const char *ath9k_hw_wow_event_to_string(u32 wow_event)2323+{2424+ if (wow_event & AH_WOW_MAGIC_PATTERN_EN)2525+ return "Magic pattern";2626+ if (wow_event & AH_WOW_USER_PATTERN_EN)2727+ return "User pattern";2828+ if (wow_event & AH_WOW_LINK_CHANGE)2929+ return "Link change";3030+ if (wow_event & AH_WOW_BEACON_MISS)3131+ return "Beacon miss";3232+3333+ return "unknown reason";3434+}3535+EXPORT_SYMBOL(ath9k_hw_wow_event_to_string);3636+3737+static void ath9k_hw_config_serdes_wow_sleep(struct ath_hw *ah)3838+{3939+ int i;4040+4141+ for (i = 0; i < ah->iniPcieSerdesWow.ia_rows; i++)4242+ REG_WRITE(ah, INI_RA(&ah->iniPcieSerdesWow, i, 0),4343+ INI_RA(&ah->iniPcieSerdesWow, i, 1));4444+4545+ usleep_range(1000, 1500);4646+}4747+4848+static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)4949+{5050+ struct ath_common *common = ath9k_hw_common(ah);5151+5252+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);5353+5454+ /* set rx disable bit */5555+ REG_WRITE(ah, AR_CR, AR_CR_RXD);5656+5757+ if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {5858+ ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",5959+ REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));6060+ return;6161+ } else {6262+ if (!AR_SREV_9300_20_OR_LATER(ah))6363+ REG_WRITE(ah, AR_RXDP, 0x0);6464+ }6565+6666+ /* AR9280 WoW has sleep issue, do not set it to sleep */6767+ if (AR_SREV_9280_20(ah))6868+ return;6969+7070+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);7171+}7272+7373+static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)7474+{7575+ struct ath_common *common = ath9k_hw_common(ah);7676+ u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN];7777+ u32 ctl[13] = {0};7878+ u32 data_word[KAL_NUM_DATA_WORDS];7979+ u8 i;8080+ u32 wow_ka_data_word0;8181+8282+ memcpy(sta_mac_addr, common->macaddr, ETH_ALEN);8383+ memcpy(ap_mac_addr, common->curbssid, ETH_ALEN);8484+8585+ /* set the transmit buffer */8686+ ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16));8787+8888+ if (!(AR_SREV_9300_20_OR_LATER(ah)))8989+ ctl[0] += (KAL_ANTENNA_MODE << 25);9090+9191+ ctl[1] = 0;9292+ ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */9393+ ctl[4] = 0;9494+ ctl[7] = (ah->txchainmask) << 2;9595+9696+ if (AR_SREV_9300_20_OR_LATER(ah))9797+ ctl[2] = 0xf << 16; /* tx_tries 0 */9898+ else9999+ ctl[2] = 0x7 << 16; /* tx_tries 0 */100100+101101+102102+ for (i = 0; i < KAL_NUM_DESC_WORDS; i++)103103+ REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);104104+105105+ /* for AR9300 family 13 descriptor words */106106+ if (AR_SREV_9300_20_OR_LATER(ah))107107+ REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);108108+109109+ data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) |110110+ (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16);111111+ data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |112112+ (ap_mac_addr[1] << 8) | (ap_mac_addr[0]);113113+ data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) |114114+ (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);115115+ data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) |116116+ (sta_mac_addr[3] << 8) | (sta_mac_addr[2]);117117+ data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |118118+ (ap_mac_addr[1] << 8) | (ap_mac_addr[0]);119119+ data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);120120+121121+ if (AR_SREV_9462_20_OR_LATER(ah)) {122122+ /* AR9462 2.0 has an extra descriptor word (time based123123+ * discard) compared to other chips */124124+ REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);125125+ wow_ka_data_word0 = AR_WOW_TXBUF(13);126126+ } else {127127+ wow_ka_data_word0 = AR_WOW_TXBUF(12);128128+ }129129+130130+ for (i = 0; i < KAL_NUM_DATA_WORDS; i++)131131+ REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]);132132+133133+}134134+135135+void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,136136+ u8 *user_mask, int pattern_count,137137+ int pattern_len)138138+{139139+ int i;140140+ u32 pattern_val, mask_val;141141+ u32 set, clr;142142+143143+ /* FIXME: should check count by querying the hardware capability */144144+ if (pattern_count >= MAX_NUM_PATTERN)145145+ return;146146+147147+ REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count));148148+149149+ /* set the registers for pattern */150150+ for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {151151+ memcpy(&pattern_val, user_pattern, 4);152152+ REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i),153153+ pattern_val);154154+ user_pattern += 4;155155+ }156156+157157+ /* set the registers for mask */158158+ for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {159159+ memcpy(&mask_val, user_mask, 4);160160+ REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val);161161+ user_mask += 4;162162+ }163163+164164+ /* set the pattern length to be matched165165+ *166166+ * AR_WOW_LENGTH1_REG1167167+ * bit 31:24 pattern 0 length168168+ * bit 23:16 pattern 1 length169169+ * bit 15:8 pattern 2 length170170+ * bit 7:0 pattern 3 length171171+ *172172+ * AR_WOW_LENGTH1_REG2173173+ * bit 31:24 pattern 4 length174174+ * bit 23:16 pattern 5 length175175+ * bit 15:8 pattern 6 length176176+ * bit 7:0 pattern 7 length177177+ *178178+ * the below logic writes out the new179179+ * pattern length for the corresponding180180+ * pattern_count, while masking out the181181+ * other fields182182+ */183183+184184+ ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);185185+186186+ if (!AR_SREV_9285_12_OR_LATER(ah))187187+ return;188188+189189+ if (pattern_count < 4) {190190+ /* Pattern 0-3 uses AR_WOW_LENGTH1 register */191191+ set = (pattern_len & AR_WOW_LENGTH_MAX) <<192192+ AR_WOW_LEN1_SHIFT(pattern_count);193193+ clr = AR_WOW_LENGTH1_MASK(pattern_count);194194+ REG_RMW(ah, AR_WOW_LENGTH1, set, clr);195195+ } else {196196+ /* Pattern 4-7 uses AR_WOW_LENGTH2 register */197197+ set = (pattern_len & AR_WOW_LENGTH_MAX) <<198198+ AR_WOW_LEN2_SHIFT(pattern_count);199199+ clr = AR_WOW_LENGTH2_MASK(pattern_count);200200+ REG_RMW(ah, AR_WOW_LENGTH2, set, clr);201201+ }202202+203203+}204204+EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern);205205+206206+u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)207207+{208208+ u32 wow_status = 0;209209+ u32 val = 0, rval;210210+ /*211211+ * read the WoW status register to know212212+ * the wakeup reason213213+ */214214+ rval = REG_READ(ah, AR_WOW_PATTERN);215215+ val = AR_WOW_STATUS(rval);216216+217217+ /*218218+ * mask only the WoW events that we have enabled. Sometimes219219+ * we have spurious WoW events from the AR_WOW_PATTERN220220+ * register. This mask will clean it up.221221+ */222222+223223+ val &= ah->wow_event_mask;224224+225225+ if (val) {226226+227227+ if (val & AR_WOW_MAGIC_PAT_FOUND)228228+ wow_status |= AH_WOW_MAGIC_PATTERN_EN;229229+230230+ if (AR_WOW_PATTERN_FOUND(val))231231+ wow_status |= AH_WOW_USER_PATTERN_EN;232232+233233+ if (val & AR_WOW_KEEP_ALIVE_FAIL)234234+ wow_status |= AH_WOW_LINK_CHANGE;235235+236236+ if (val & AR_WOW_BEACON_FAIL)237237+ wow_status |= AH_WOW_BEACON_MISS;238238+239239+ }240240+241241+ /*242242+ * set and clear WOW_PME_CLEAR registers for the chip to243243+ * generate next wow signal.244244+ * disable D3 before accessing other registers ?245245+ */246246+247247+ /* do we need to check the bit value 0x01000000 (7-10) ?? */248248+ REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR,249249+ AR_PMCTRL_PWR_STATE_D1D3);250250+251251+ /*252252+ * clear all events253253+ */254254+ REG_WRITE(ah, AR_WOW_PATTERN,255255+ AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN)));256256+257257+ /*258258+ * tie reset register for AR9002 family of chipsets259259+ * NB: not tieing it back might have some repurcussions.260260+ */261261+262262+ if (!AR_SREV_9300_20_OR_LATER(ah)) {263263+ REG_SET_BIT(ah, AR_WA, AR_WA_UNTIE_RESET_EN |264264+ AR_WA_POR_SHORT | AR_WA_RESET_EN);265265+ }266266+267267+268268+ /*269269+ * restore the beacon threshold to init value270270+ */271271+ REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);272272+273273+ /*274274+ * Restore the way the PCI-E reset, Power-On-Reset, external275275+ * PCIE_POR_SHORT pins are tied to its original value.276276+ * Previously just before WoW sleep, we untie the PCI-E277277+ * reset to our Chip's Power On Reset so that any PCI-E278278+ * reset from the bus will not reset our chip279279+ */280280+281281+ if (AR_SREV_9280_20_OR_LATER(ah) && ah->is_pciexpress)282282+ ath9k_hw_configpcipowersave(ah, false);283283+284284+ ah->wow_event_mask = 0;285285+286286+ return wow_status;287287+}288288+EXPORT_SYMBOL(ath9k_hw_wow_wakeup);289289+290290+void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)291291+{292292+ u32 wow_event_mask;293293+ u32 set, clr;294294+295295+ /*296296+ * wow_event_mask is a mask to the AR_WOW_PATTERN register to297297+ * indicate which WoW events we have enabled. The WoW events298298+ * are from the 'pattern_enable' in this function and299299+ * 'pattern_count' of ath9k_hw_wow_apply_pattern()300300+ */301301+302302+ wow_event_mask = ah->wow_event_mask;303303+304304+ /*305305+ * Untie Power-on-Reset from the PCI-E-Reset. When we are in306306+ * WOW sleep, we do want the Reset from the PCI-E to disturb307307+ * our hw state308308+ */309309+310310+ if (ah->is_pciexpress) {311311+312312+ /*313313+ * we need to untie the internal POR (power-on-reset)314314+ * to the external PCI-E reset. We also need to tie315315+ * the PCI-E Phy reset to the PCI-E reset.316316+ */317317+318318+ if (AR_SREV_9300_20_OR_LATER(ah)) {319319+ set = AR_WA_RESET_EN | AR_WA_POR_SHORT;320320+ clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE;321321+ REG_RMW(ah, AR_WA, set, clr);322322+ } else {323323+ if (AR_SREV_9285(ah) || AR_SREV_9287(ah))324324+ set = AR9285_WA_DEFAULT;325325+ else326326+ set = AR9280_WA_DEFAULT;327327+328328+ /*329329+ * In AR9280 and AR9285, bit 14 in WA register330330+ * (disable L1) should only be set when device331331+ * enters D3 state and be cleared when device332332+ * comes back to D0333333+ */334334+335335+ if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)336336+ set |= AR_WA_D3_L1_DISABLE;337337+338338+ clr = AR_WA_UNTIE_RESET_EN;339339+ set |= AR_WA_RESET_EN | AR_WA_POR_SHORT;340340+ REG_RMW(ah, AR_WA, set, clr);341341+342342+ /*343343+ * for WoW sleep, we reprogram the SerDes so that the344344+ * PLL and CLK REQ are both enabled. This uses more345345+ * power but otherwise WoW sleep is unstable and the346346+ * chip may disappear.347347+ */348348+349349+ if (AR_SREV_9285_12_OR_LATER(ah))350350+ ath9k_hw_config_serdes_wow_sleep(ah);351351+352352+ }353353+ }354354+355355+ /*356356+ * set the power states appropriately and enable PME357357+ */358358+ set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA |359359+ AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR;360360+361361+ /*362362+ * set and clear WOW_PME_CLEAR registers for the chip363363+ * to generate next wow signal.364364+ */365365+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);366366+ clr = AR_PMCTRL_WOW_PME_CLR;367367+ REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);368368+369369+ /*370370+ * Setup for:371371+ * - beacon misses372372+ * - magic pattern373373+ * - keep alive timeout374374+ * - pattern matching375375+ */376376+377377+ /*378378+ * Program default values for pattern backoff, aifs/slot/KAL count,379379+ * beacon miss timeout, KAL timeout, etc.380380+ */381381+382382+ set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF);383383+ REG_SET_BIT(ah, AR_WOW_PATTERN, set);384384+385385+ set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |386386+ AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |387387+ AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);388388+ REG_SET_BIT(ah, AR_WOW_COUNT, set);389389+390390+ if (pattern_enable & AH_WOW_BEACON_MISS)391391+ set = AR_WOW_BEACON_TIMO;392392+ /* We are not using beacon miss, program a large value */393393+ else394394+ set = AR_WOW_BEACON_TIMO_MAX;395395+396396+ REG_WRITE(ah, AR_WOW_BCN_TIMO, set);397397+398398+ /*399399+ * Keep alive timo in ms except AR9280400400+ */401401+ if (!pattern_enable || AR_SREV_9280(ah))402402+ set = AR_WOW_KEEP_ALIVE_NEVER;403403+ else404404+ set = KAL_TIMEOUT * 32;405405+406406+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set);407407+408408+ /*409409+ * Keep alive delay in us. based on 'power on clock',410410+ * therefore in usec411411+ */412412+ set = KAL_DELAY * 1000;413413+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set);414414+415415+ /*416416+ * Create keep alive pattern to respond to beacons417417+ */418418+ ath9k_wow_create_keep_alive_pattern(ah);419419+420420+ /*421421+ * Configure MAC WoW Registers422422+ */423423+424424+ set = 0;425425+ /* Send keep alive timeouts anyway */426426+ clr = AR_WOW_KEEP_ALIVE_AUTO_DIS;427427+428428+ if (pattern_enable & AH_WOW_LINK_CHANGE)429429+ wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;430430+ else431431+ set = AR_WOW_KEEP_ALIVE_FAIL_DIS;432432+433433+ /*434434+ * FIXME: For now disable keep alive frame435435+ * failure. This seems to sometimes trigger436436+ * unnecessary wake up with AR9485 chipsets.437437+ */438438+ set = AR_WOW_KEEP_ALIVE_FAIL_DIS;439439+440440+ REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr);441441+442442+443443+ /*444444+ * we are relying on a bmiss failure. ensure we have445445+ * enough threshold to prevent false positives446446+ */447447+ REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,448448+ AR_WOW_BMISSTHRESHOLD);449449+450450+ set = 0;451451+ clr = 0;452452+453453+ if (pattern_enable & AH_WOW_BEACON_MISS) {454454+ set = AR_WOW_BEACON_FAIL_EN;455455+ wow_event_mask |= AR_WOW_BEACON_FAIL;456456+ } else {457457+ clr = AR_WOW_BEACON_FAIL_EN;458458+ }459459+460460+ REG_RMW(ah, AR_WOW_BCN_EN, set, clr);461461+462462+ set = 0;463463+ clr = 0;464464+ /*465465+ * Enable the magic packet registers466466+ */467467+ if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) {468468+ set = AR_WOW_MAGIC_EN;469469+ wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;470470+ } else {471471+ clr = AR_WOW_MAGIC_EN;472472+ }473473+ set |= AR_WOW_MAC_INTR_EN;474474+ REG_RMW(ah, AR_WOW_PATTERN, set, clr);475475+476476+ /*477477+ * For AR9285 and later version of chipsets478478+ * enable WoW pattern match for packets less479479+ * than 256 bytes for all patterns480480+ */481481+ if (AR_SREV_9285_12_OR_LATER(ah))482482+ REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B,483483+ AR_WOW_PATTERN_SUPPORTED);484484+485485+ /*486486+ * Set the power states appropriately and enable PME487487+ */488488+ clr = 0;489489+ set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN |490490+ AR_PMCTRL_PWR_PM_CTRL_ENA;491491+ /*492492+ * This is needed for AR9300 chipsets to wake-up493493+ * the host.494494+ */495495+ if (AR_SREV_9300_20_OR_LATER(ah))496496+ clr = AR_PCIE_PM_CTRL_ENA;497497+498498+ REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr);499499+500500+ if (AR_SREV_9462(ah)) {501501+ /*502502+ * this is needed to prevent the chip waking up503503+ * the host within 3-4 seconds with certain504504+ * platform/BIOS. The fix is to enable505505+ * D1 & D3 to match original definition and506506+ * also match the OTP value. Anyway this507507+ * is more related to SW WOW.508508+ */509509+ clr = AR_PMCTRL_PWR_STATE_D1D3;510510+ REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);511511+512512+ set = AR_PMCTRL_PWR_STATE_D1D3_REAL;513513+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);514514+ }515515+516516+517517+518518+ REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);519519+520520+ if (AR_SREV_9300_20_OR_LATER(ah)) {521521+ /* to bring down WOW power low margin */522522+ set = BIT(13);523523+ REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set);524524+ /* HW WoW */525525+ clr = BIT(5);526526+ REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr);527527+ }528528+529529+ ath9k_hw_set_powermode_wow_sleep(ah);530530+ ah->wow_event_mask = wow_event_mask;531531+}532532+EXPORT_SYMBOL(ath9k_hw_wow_enable);
···870870 * handler, only. This basically is just the IRQ mask register. */871871 spinlock_t hardirq_lock;872872873873- /* The number of queues that were registered with the mac80211 subsystem874874- * initially. This is a backup copy of hw->queues in case hw->queues has875875- * to be dynamically lowered at runtime (Firmware does not support QoS).876876- * hw->queues has to be restored to the original value before unregistering877877- * from the mac80211 subsystem. */878878- u16 mac80211_initially_registered_queues;879879-880873 /* Set this if we call ieee80211_register_hw() and check if we call881874 * ieee80211_unregister_hw(). */882875 bool hw_registred;
+10-22
drivers/net/wireless/b43/main.c
···23592359 if (err)23602360 goto err_load;2361236123622362+ fw->opensource = (ctx->req_type == B43_FWTYPE_OPENSOURCE);23632363+23622364 return 0;2363236523642366err_no_ucode:···24362434 goto out;2437243524382436start_ieee80211:24372437+ wl->hw->queues = B43_QOS_QUEUE_NUM;24382438+ if (!modparam_qos || dev->fw.opensource)24392439+ wl->hw->queues = 1;24402440+24392441 err = ieee80211_register_hw(wl->hw);24402442 if (err)24412443 goto err_one_core_detach;···25432537 dev->fw.hdr_format = B43_FW_HDR_410;25442538 else25452539 dev->fw.hdr_format = B43_FW_HDR_351;25462546- dev->fw.opensource = (fwdate == 0xFFFF);25402540+ WARN_ON(dev->fw.opensource != (fwdate == 0xFFFF));2547254125482548- /* Default to use-all-queues. */25492549- dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;25502550- dev->qos_enabled = !!modparam_qos;25422542+ dev->qos_enabled = dev->wl->hw->queues > 1;25512543 /* Default to firmware/hardware crypto acceleration. */25522544 dev->hwcrypto_enabled = true;25532545···25632559 /* Disable hardware crypto and fall back to software crypto. */25642560 dev->hwcrypto_enabled = false;25652561 }25662566- if (!(fwcapa & B43_FWCAPA_QOS)) {25672567- b43info(dev->wl, "QoS not supported by firmware\n");25682568- /* Disable QoS. Tweak hw->queues to 1. It will be restored before25692569- * ieee80211_unregister to make sure the networking core can25702570- * properly free possible resources. */25712571- dev->wl->hw->queues = 1;25722572- dev->qos_enabled = false;25732573- }25622562+ /* adding QoS support should use an offline discovery mechanism */25632563+ WARN(fwcapa & B43_FWCAPA_QOS, "QoS in OpenFW not supported\n");25742564 } else {25752565 b43info(dev->wl, "Loading firmware version %u.%u "25762566 "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",···5296529852975299 hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;5298530052995299- hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1;53005300- wl->mac80211_initially_registered_queues = hw->queues;53015301 wl->hw_registred = false;53025302 hw->max_rates = 2;53035303 SET_IEEE80211_DEV(hw, dev->dev);···5370537453715375 B43_WARN_ON(!wl);53725376 if (wl->current_dev == wldev && wl->hw_registred) {53735373- /* Restore the queues count before unregistering, because firmware detect53745374- * might have modified it. Restoring is important, so the networking53755375- * stack can properly free resources. */53765376- wl->hw->queues = wl->mac80211_initially_registered_queues;53775377 b43_leds_stop(wldev);53785378 ieee80211_unregister_hw(wl->hw);53795379 }···5444545254455453 B43_WARN_ON(!wl);54465454 if (wl->current_dev == wldev && wl->hw_registred) {54475447- /* Restore the queues count before unregistering, because firmware detect54485448- * might have modified it. Restoring is important, so the networking54495449- * stack can properly free resources. */54505450- wl->hw->queues = wl->mac80211_initially_registered_queues;54515455 b43_leds_stop(wldev);54525456 ieee80211_unregister_hw(wl->hw);54535457 }
+5-4
drivers/net/wireless/b43/xmit.c
···663663 u32 uninitialized_var(macstat);664664 u16 chanid;665665 u16 phytype;666666- int padding;666666+ int padding, rate_idx;667667668668 memset(&status, 0, sizeof(status));669669···766766 }767767768768 if (phystat0 & B43_RX_PHYST0_OFDM)769769- status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,769769+ rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,770770 phytype == B43_PHYTYPE_A);771771 else772772- status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);773773- if (unlikely(status.rate_idx == -1)) {772772+ rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);773773+ if (unlikely(rate_idx == -1)) {774774 /* PLCP seems to be corrupted.775775 * Drop the frame, if we are not interested in corrupted frames. */776776 if (!(dev->wl->filter_flags & FIF_PLCPFAIL))777777 goto drop;778778 }779779+ status.rate_idx = rate_idx;779780 status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);780781781782 /*
···458458 /* The following fields are internal only */459459 struct kmem_cache *dev_cmd_pool;460460 size_t dev_cmd_headroom;461461+ char dev_cmd_pool_name[50];461462462463 /* pointer to trans specific struct */463464 /*Ensure that this pointer will always be aligned to sizeof pointer */
···152152 goto err;153153 }154154155155+ ret = lbs_set_11d_domain_info(priv);156156+ if (ret) {157157+ lbs_deb_net("set 11d domain info failed\n");158158+ goto err;159159+ }160160+155161 lbs_update_channel(priv);156162157163 priv->iface_running = true;
-5
drivers/net/wireless/mac80211_hwsim.c
···15401540 /* now send back TX status */15411541 txi = IEEE80211_SKB_CB(skb);1542154215431543- if (txi->control.vif)15441544- hwsim_check_magic(txi->control.vif);15451545- if (txi->control.sta)15461546- hwsim_check_sta_magic(txi->control.sta);15471547-15481543 ieee80211_tx_info_clear_status(txi);1549154415501545 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+152-135
drivers/net/wireless/mwifiex/cfg80211.c
···4848 * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE4949 */5050static u85151-mwifiex_cfg80211_channel_type_to_sec_chan_offset(enum nl80211_channel_type5252- channel_type)5151+mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)5352{5454- switch (channel_type) {5353+ switch (chan_type) {5554 case NL80211_CHAN_NO_HT:5655 case NL80211_CHAN_HT20:5756 return IEEE80211_HT_PARAM_CHA_SEC_NONE;···338339}339340340341/*341341- * This function sets the RF channel.342342- *343343- * This function creates multiple IOCTL requests, populates them accordingly344344- * and issues them to set the band/channel and frequency.345345- */346346-static int347347-mwifiex_set_rf_channel(struct mwifiex_private *priv,348348- struct ieee80211_channel *chan,349349- enum nl80211_channel_type channel_type)350350-{351351- struct mwifiex_chan_freq_power cfp;352352- u32 config_bands = 0;353353- struct wiphy *wiphy = priv->wdev->wiphy;354354- struct mwifiex_adapter *adapter = priv->adapter;355355-356356- if (chan) {357357- /* Set appropriate bands */358358- if (chan->band == IEEE80211_BAND_2GHZ) {359359- if (channel_type == NL80211_CHAN_NO_HT)360360- if (priv->adapter->config_bands == BAND_B ||361361- priv->adapter->config_bands == BAND_G)362362- config_bands =363363- priv->adapter->config_bands;364364- else365365- config_bands = BAND_B | BAND_G;366366- else367367- config_bands = BAND_B | BAND_G | BAND_GN;368368- } else {369369- if (channel_type == NL80211_CHAN_NO_HT)370370- config_bands = BAND_A;371371- else372372- config_bands = BAND_AN | BAND_A;373373- }374374-375375- if (!((config_bands | adapter->fw_bands) &376376- ~adapter->fw_bands)) {377377- adapter->config_bands = config_bands;378378- if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {379379- adapter->adhoc_start_band = config_bands;380380- if ((config_bands & BAND_GN) ||381381- (config_bands & BAND_AN))382382- adapter->adhoc_11n_enabled = true;383383- else384384- adapter->adhoc_11n_enabled = false;385385- }386386- }387387- adapter->sec_chan_offset =388388- mwifiex_cfg80211_channel_type_to_sec_chan_offset389389- (channel_type);390390- adapter->channel_type = channel_type;391391-392392- mwifiex_send_domain_info_cmd_fw(wiphy);393393- }394394-395395- wiphy_dbg(wiphy, "info: setting band %d, chan offset %d, mode %d\n",396396- config_bands, adapter->sec_chan_offset, priv->bss_mode);397397- if (!chan)398398- return 0;399399-400400- memset(&cfp, 0, sizeof(cfp));401401- cfp.freq = chan->center_freq;402402- cfp.channel = ieee80211_frequency_to_channel(chan->center_freq);403403-404404- if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {405405- if (mwifiex_bss_set_channel(priv, &cfp))406406- return -EFAULT;407407- return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);408408- }409409-410410- return 0;411411-}412412-413413-/*414342 * This function sets the fragmentation threshold.415343 *416344 * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE···552626mwifiex_dump_station_info(struct mwifiex_private *priv,553627 struct station_info *sinfo)554628{555555- struct mwifiex_rate_cfg rate;629629+ u32 rate;556630557631 sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES |558632 STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS |···578652579653 /*580654 * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid581581- * MCS index values for us are 0 to 7.655655+ * MCS index values for us are 0 to 15.582656 */583583- if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) {657657+ if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {584658 sinfo->txrate.mcs = priv->tx_rate;585659 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;586660 /* 40MHz rate */···598672 sinfo->tx_packets = priv->stats.tx_packets;599673 sinfo->signal = priv->bcn_rssi_avg;600674 /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */601601- sinfo->txrate.legacy = rate.rate * 5;675675+ sinfo->txrate.legacy = rate * 5;602676603677 if (priv->bss_mode == NL80211_IFTYPE_STATION) {604678 sinfo->filled |= STATION_INFO_BSS_PARAM;···753827/*754828 * CFG802.11 operation handler for setting bit rates.755829 *756756- * Function selects legacy bang B/G/BG from corresponding bitrates selection.757757- * Currently only 2.4GHz band is supported.830830+ * Function configures data rates to firmware using bitrate mask831831+ * provided by cfg80211.758832 */759833static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,760834 struct net_device *dev,···762836 const struct cfg80211_bitrate_mask *mask)763837{764838 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);765765- int index = 0, mode = 0, i;766766- struct mwifiex_adapter *adapter = priv->adapter;839839+ u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];840840+ enum ieee80211_band band;767841768768- /* Currently only 2.4GHz is supported */769769- for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {770770- /*771771- * Rates below 6 Mbps in the table are CCK rates; 802.11b772772- * and from 6 they are OFDM; 802.11G773773- */774774- if (mwifiex_rates[i].bitrate == 60) {775775- index = 1 << i;776776- break;777777- }842842+ if (!priv->media_connected) {843843+ dev_err(priv->adapter->dev,844844+ "Can not set Tx data rate in disconnected state\n");845845+ return -EINVAL;778846 }779847780780- if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) {781781- mode = BAND_B;782782- } else {783783- mode = BAND_G;784784- if (mask->control[IEEE80211_BAND_2GHZ].legacy % index)785785- mode |= BAND_B;786786- }848848+ band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);787849788788- if (!((mode | adapter->fw_bands) & ~adapter->fw_bands)) {789789- adapter->config_bands = mode;790790- if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {791791- adapter->adhoc_start_band = mode;792792- adapter->adhoc_11n_enabled = false;793793- }794794- }795795- adapter->sec_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;796796- adapter->channel_type = NL80211_CHAN_NO_HT;850850+ memset(bitmap_rates, 0, sizeof(bitmap_rates));797851798798- wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",799799- (mode & BAND_B) ? "b" : "", (mode & BAND_G) ? "g" : "");852852+ /* Fill HR/DSSS rates. */853853+ if (band == IEEE80211_BAND_2GHZ)854854+ bitmap_rates[0] = mask->control[band].legacy & 0x000f;800855801801- return 0;856856+ /* Fill OFDM rates */857857+ if (band == IEEE80211_BAND_2GHZ)858858+ bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;859859+ else860860+ bitmap_rates[1] = mask->control[band].legacy;861861+862862+ /* Fill MCS rates */863863+ bitmap_rates[2] = mask->control[band].mcs[0];864864+ if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2)865865+ bitmap_rates[2] |= mask->control[band].mcs[1] << 8;866866+867867+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,868868+ HostCmd_ACT_GEN_SET, 0, bitmap_rates);802869}803870804871/*···9261007{9271008 struct mwifiex_uap_bss_param *bss_cfg;9281009 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);10101010+ u8 config_bands = 0;92910119301012 if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP)9311013 return -1;···9671047 (u8)ieee80211_frequency_to_channel(params->channel->center_freq);9681048 bss_cfg->band_cfg = BAND_CONFIG_MANUAL;9691049970970- if (mwifiex_set_rf_channel(priv, params->channel,971971- params->channel_type)) {972972- kfree(bss_cfg);973973- wiphy_err(wiphy, "Failed to set band config information!\n");974974- return -1;10501050+ /* Set appropriate bands */10511051+ if (params->channel->band == IEEE80211_BAND_2GHZ) {10521052+ if (params->channel_type == NL80211_CHAN_NO_HT)10531053+ config_bands = BAND_B | BAND_G;10541054+ else10551055+ config_bands = BAND_B | BAND_G | BAND_GN;10561056+ } else {10571057+ if (params->channel_type == NL80211_CHAN_NO_HT)10581058+ config_bands = BAND_A;10591059+ else10601060+ config_bands = BAND_AN | BAND_A;9751061 }10621062+10631063+ if (!((config_bands | priv->adapter->fw_bands) &10641064+ ~priv->adapter->fw_bands))10651065+ priv->adapter->config_bands = config_bands;10661066+10671067+ mwifiex_send_domain_info_cmd_fw(wiphy);97610689771069 if (mwifiex_set_secure_params(priv, bss_cfg, params)) {9781070 kfree(bss_cfg);···11191187 struct cfg80211_ssid req_ssid;11201188 int ret, auth_type = 0;11211189 struct cfg80211_bss *bss = NULL;11221122- u8 is_scanning_required = 0;11901190+ u8 is_scanning_required = 0, config_bands = 0;1123119111241192 memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));11251193···11381206 /* disconnect before try to associate */11391207 mwifiex_deauthenticate(priv, NULL);1140120811411141- if (channel)11421142- ret = mwifiex_set_rf_channel(priv, channel,11431143- priv->adapter->channel_type);12091209+ if (channel) {12101210+ if (mode == NL80211_IFTYPE_STATION) {12111211+ if (channel->band == IEEE80211_BAND_2GHZ)12121212+ config_bands = BAND_B | BAND_G | BAND_GN;12131213+ else12141214+ config_bands = BAND_A | BAND_AN;12151215+12161216+ if (!((config_bands | priv->adapter->fw_bands) &12171217+ ~priv->adapter->fw_bands))12181218+ priv->adapter->config_bands = config_bands;12191219+ }12201220+ mwifiex_send_domain_info_cmd_fw(priv->wdev->wiphy);12211221+ }1144122211451223 /* As this is new association, clear locally stored11461224 * keys and security related flags */···13151373}1316137413171375/*13761376+ * This function sets following parameters for ibss network.13771377+ * - channel13781378+ * - start band13791379+ * - 11n flag13801380+ * - secondary channel offset13811381+ */13821382+static int mwifiex_set_ibss_params(struct mwifiex_private *priv,13831383+ struct cfg80211_ibss_params *params)13841384+{13851385+ struct wiphy *wiphy = priv->wdev->wiphy;13861386+ struct mwifiex_adapter *adapter = priv->adapter;13871387+ int index = 0, i;13881388+ u8 config_bands = 0;13891389+13901390+ if (params->channel->band == IEEE80211_BAND_2GHZ) {13911391+ if (!params->basic_rates) {13921392+ config_bands = BAND_B | BAND_G;13931393+ } else {13941394+ for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {13951395+ /*13961396+ * Rates below 6 Mbps in the table are CCK13971397+ * rates; 802.11b and from 6 they are OFDM;13981398+ * 802.11G13991399+ */14001400+ if (mwifiex_rates[i].bitrate == 60) {14011401+ index = 1 << i;14021402+ break;14031403+ }14041404+ }14051405+14061406+ if (params->basic_rates < index) {14071407+ config_bands = BAND_B;14081408+ } else {14091409+ config_bands = BAND_G;14101410+ if (params->basic_rates % index)14111411+ config_bands |= BAND_B;14121412+ }14131413+ }14141414+14151415+ if (params->channel_type != NL80211_CHAN_NO_HT)14161416+ config_bands |= BAND_GN;14171417+ } else {14181418+ if (params->channel_type == NL80211_CHAN_NO_HT)14191419+ config_bands = BAND_A;14201420+ else14211421+ config_bands = BAND_AN | BAND_A;14221422+ }14231423+14241424+ if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {14251425+ adapter->config_bands = config_bands;14261426+ adapter->adhoc_start_band = config_bands;14271427+14281428+ if ((config_bands & BAND_GN) || (config_bands & BAND_AN))14291429+ adapter->adhoc_11n_enabled = true;14301430+ else14311431+ adapter->adhoc_11n_enabled = false;14321432+ }14331433+14341434+ adapter->sec_chan_offset =14351435+ mwifiex_chan_type_to_sec_chan_offset(params->channel_type);14361436+ priv->adhoc_channel =14371437+ ieee80211_frequency_to_channel(params->channel->center_freq);14381438+14391439+ wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",14401440+ config_bands, priv->adhoc_channel, adapter->sec_chan_offset);14411441+14421442+ return 0;14431443+}14441444+14451445+/*13181446 * CFG802.11 operation handler to join an IBSS.13191447 *13201448 * This function does not work in any mode other than Ad-Hoc, or if···1405139314061394 wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",14071395 (char *) params->ssid, params->bssid);13961396+13971397+ mwifiex_set_ibss_params(priv, params);1408139814091399 ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,14101400 params->bssid, priv->bss_mode,···14541440 * it also informs the results.14551441 */14561442static int14571457-mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,14431443+mwifiex_cfg80211_scan(struct wiphy *wiphy,14581444 struct cfg80211_scan_request *request)14591445{14461446+ struct net_device *dev = request->wdev->netdev;14601447 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);14611448 int i;14621449 struct ieee80211_channel *chan;···15911576/*15921577 * create a new virtual interface with the given name15931578 */15941594-struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,15951595- char *name,15961596- enum nl80211_iftype type,15971597- u32 *flags,15981598- struct vif_params *params)15791579+struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,15801580+ char *name,15811581+ enum nl80211_iftype type,15821582+ u32 *flags,15831583+ struct vif_params *params)15991584{16001585 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);16011586 struct mwifiex_private *priv;···17161701#ifdef CONFIG_DEBUG_FS17171702 mwifiex_dev_debugfs_init(priv);17181703#endif17191719- return dev;17041704+ return wdev;17201705}17211706EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);1722170717231708/*17241709 * del_virtual_intf: remove the virtual interface determined by dev17251710 */17261726-int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)17111711+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)17271712{17281728- struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);17131713+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);1729171417301715#ifdef CONFIG_DEBUG_FS17311716 mwifiex_dev_debugfs_remove(priv);···17371722 if (netif_carrier_ok(priv->netdev))17381723 netif_carrier_off(priv->netdev);1739172417401740- if (dev->reg_state == NETREG_REGISTERED)17411741- unregister_netdevice(dev);17251725+ if (wdev->netdev->reg_state == NETREG_REGISTERED)17261726+ unregister_netdevice(wdev->netdev);1742172717431743- if (dev->reg_state == NETREG_UNREGISTERED)17441744- free_netdev(dev);17281728+ if (wdev->netdev->reg_state == NETREG_UNREGISTERED)17291729+ free_netdev(wdev->netdev);1745173017461731 /* Clear the priv in adapter */17471732 priv->netdev = NULL;···1832181718331818 wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;18341819 wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;18201820+18211821+ wiphy->features = NL80211_FEATURE_HT_IBSS;1835182218361823 /* Reserve space for mwifiex specific private data for BSS */18371824 wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
-31
drivers/net/wireless/mwifiex/cfp.c
···167167}168168169169/*170170- * This function maps a data rate value into corresponding index in supported171171- * rates table.172172- */173173-u8 mwifiex_data_rate_to_index(u32 rate)174174-{175175- u16 *ptr;176176-177177- if (rate) {178178- ptr = memchr(mwifiex_data_rates, rate,179179- sizeof(mwifiex_data_rates));180180- if (ptr)181181- return (u8) (ptr - mwifiex_data_rates);182182- }183183- return 0;184184-}185185-186186-/*187170 * This function returns the current active data rates.188171 *189172 * The result may vary depending upon connection status.···257274 return true;258275 else259276 return false;260260-}261261-262262-/*263263- * This function converts rate bitmap into rate index.264264- */265265-int mwifiex_get_rate_index(u16 *rate_bitmap, int size)266266-{267267- int i;268268-269269- for (i = 0; i < size * 8; i++)270270- if (rate_bitmap[i / 16] & (1 << (i % 16)))271271- return i;272272-273273- return 0;274277}275278276279/*
···745745}746746747747/*748748- * This function prepares command to set/get RF channel.749749- *750750- * Preparation includes -751751- * - Setting command ID, action and proper size752752- * - Setting RF type and current RF channel (for SET only)753753- * - Ensuring correct endian-ness754754- */755755-static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,756756- struct host_cmd_ds_command *cmd,757757- u16 cmd_action, u16 *channel)758758-{759759- struct host_cmd_ds_802_11_rf_channel *rf_chan =760760- &cmd->params.rf_channel;761761- uint16_t rf_type = le16_to_cpu(rf_chan->rf_type);762762-763763- cmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL);764764- cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rf_channel)765765- + S_DS_GEN);766766-767767- if (cmd_action == HostCmd_ACT_GEN_SET) {768768- if ((priv->adapter->adhoc_start_band & BAND_A) ||769769- (priv->adapter->adhoc_start_band & BAND_AN))770770- rf_chan->rf_type =771771- cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A);772772-773773- rf_type = le16_to_cpu(rf_chan->rf_type);774774- SET_SECONDARYCHAN(rf_type, priv->adapter->sec_chan_offset);775775- rf_chan->current_channel = cpu_to_le16(*channel);776776- }777777- rf_chan->action = cpu_to_le16(cmd_action);778778- return 0;779779-}780780-781781-/*782748 * This function prepares command to set/get IBSS coalescing status.783749 *784750 * Preparation includes -···11341168 cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) +11351169 S_DS_GEN);11361170 ret = 0;11371137- break;11381138- case HostCmd_CMD_802_11_RF_CHANNEL:11391139- ret = mwifiex_cmd_802_11_rf_channel(priv, cmd_ptr, cmd_action,11401140- data_buf);11411171 break;11421172 case HostCmd_CMD_FUNC_INIT:11431173 if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET)
+7-63
drivers/net/wireless/mwifiex/sta_cmdresp.c
···267267 *268268 * Based on the new rate bitmaps, the function re-evaluates if269269 * auto data rate has been activated. If not, it sends another270270- * query to the firmware to get the current Tx data rate and updates271271- * the driver value.270270+ * query to the firmware to get the current Tx data rate.272271 */273272static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,274274- struct host_cmd_ds_command *resp,275275- struct mwifiex_rate_cfg *ds_rate)273273+ struct host_cmd_ds_command *resp)276274{277275 struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;278276 struct mwifiex_rate_scope *rate_scope;···278280 u16 tlv, tlv_buf_len;279281 u8 *tlv_buf;280282 u32 i;281281- int ret = 0;282283283284 tlv_buf = ((u8 *)rate_cfg) +284285 sizeof(struct host_cmd_ds_tx_rate_cfg);···315318 if (priv->is_data_rate_auto)316319 priv->data_rate = 0;317320 else318318- ret = mwifiex_send_cmd_async(priv,319319- HostCmd_CMD_802_11_TX_RATE_QUERY,320320- HostCmd_ACT_GEN_GET, 0, NULL);321321+ return mwifiex_send_cmd_async(priv,322322+ HostCmd_CMD_802_11_TX_RATE_QUERY,323323+ HostCmd_ACT_GEN_GET, 0, NULL);321324322322- if (!ds_rate)323323- return ret;324324-325325- if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {326326- if (priv->is_data_rate_auto) {327327- ds_rate->is_rate_auto = 1;328328- return ret;329329- }330330- ds_rate->rate = mwifiex_get_rate_index(priv->bitmap_rates,331331- sizeof(priv->bitmap_rates));332332-333333- if (ds_rate->rate >= MWIFIEX_RATE_BITMAP_OFDM0 &&334334- ds_rate->rate <= MWIFIEX_RATE_BITMAP_OFDM7)335335- ds_rate->rate -= (MWIFIEX_RATE_BITMAP_OFDM0 -336336- MWIFIEX_RATE_INDEX_OFDM0);337337-338338- if (ds_rate->rate >= MWIFIEX_RATE_BITMAP_MCS0 &&339339- ds_rate->rate <= MWIFIEX_RATE_BITMAP_MCS127)340340- ds_rate->rate -= (MWIFIEX_RATE_BITMAP_MCS0 -341341- MWIFIEX_RATE_INDEX_MCS0);342342- }343343-344344- return ret;325325+ return 0;345326}346327347328/*···631656}632657633658/*634634- * This function handles the command response of get RF channel.635635- *636636- * Handling includes changing the header fields into CPU format637637- * and saving the new channel in driver.638638- */639639-static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,640640- struct host_cmd_ds_command *resp,641641- u16 *data_buf)642642-{643643- struct host_cmd_ds_802_11_rf_channel *rf_channel =644644- &resp->params.rf_channel;645645- u16 new_channel = le16_to_cpu(rf_channel->current_channel);646646-647647- if (priv->curr_bss_params.bss_descriptor.channel != new_channel) {648648- dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n",649649- priv->curr_bss_params.bss_descriptor.channel,650650- new_channel);651651- /* Update the channel again */652652- priv->curr_bss_params.bss_descriptor.channel = new_channel;653653- }654654-655655- if (data_buf)656656- *data_buf = new_channel;657657-658658- return 0;659659-}660660-661661-/*662659 * This function handles the command response of get extended version.663660 *664661 * Handling includes forming the extended version string and sending it···825878 ret = mwifiex_ret_mac_multicast_adr(priv, resp);826879 break;827880 case HostCmd_CMD_TX_RATE_CFG:828828- ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf);881881+ ret = mwifiex_ret_tx_rate_cfg(priv, resp);829882 break;830883 case HostCmd_CMD_802_11_SCAN:831884 ret = mwifiex_ret_802_11_scan(priv, resp);···875928 break;876929 case HostCmd_CMD_802_11_TX_RATE_QUERY:877930 ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);878878- break;879879- case HostCmd_CMD_802_11_RF_CHANNEL:880880- ret = mwifiex_ret_802_11_rf_channel(priv, resp, data_buf);881931 break;882932 case HostCmd_CMD_VERSION_EXT:883933 ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
+7-280
drivers/net/wireless/mwifiex/sta_ioctl.c
···497497EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds);498498499499/*500500- * IOCTL request handler to set/get active channel.501501- *502502- * This function performs validity checking on channel/frequency503503- * compatibility and returns failure if not valid.504504- */505505-int mwifiex_bss_set_channel(struct mwifiex_private *priv,506506- struct mwifiex_chan_freq_power *chan)507507-{508508- struct mwifiex_adapter *adapter = priv->adapter;509509- struct mwifiex_chan_freq_power *cfp = NULL;510510-511511- if (!chan)512512- return -1;513513-514514- if (!chan->channel && !chan->freq)515515- return -1;516516- if (adapter->adhoc_start_band & BAND_AN)517517- adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;518518- else if (adapter->adhoc_start_band & BAND_A)519519- adapter->adhoc_start_band = BAND_G | BAND_B;520520- if (chan->channel) {521521- if (chan->channel <= MAX_CHANNEL_BAND_BG)522522- cfp = mwifiex_get_cfp(priv, 0, (u16) chan->channel, 0);523523- if (!cfp) {524524- cfp = mwifiex_get_cfp(priv, BAND_A,525525- (u16) chan->channel, 0);526526- if (cfp) {527527- if (adapter->adhoc_11n_enabled)528528- adapter->adhoc_start_band = BAND_A529529- | BAND_AN;530530- else531531- adapter->adhoc_start_band = BAND_A;532532- }533533- }534534- } else {535535- if (chan->freq <= MAX_FREQUENCY_BAND_BG)536536- cfp = mwifiex_get_cfp(priv, 0, 0, chan->freq);537537- if (!cfp) {538538- cfp = mwifiex_get_cfp(priv, BAND_A, 0, chan->freq);539539- if (cfp) {540540- if (adapter->adhoc_11n_enabled)541541- adapter->adhoc_start_band = BAND_A542542- | BAND_AN;543543- else544544- adapter->adhoc_start_band = BAND_A;545545- }546546- }547547- }548548- if (!cfp || !cfp->channel) {549549- dev_err(adapter->dev, "invalid channel/freq\n");550550- return -1;551551- }552552- priv->adhoc_channel = (u8) cfp->channel;553553- chan->channel = cfp->channel;554554- chan->freq = cfp->freq;555555-556556- return 0;557557-}558558-559559-/*560560- * IOCTL request handler to set/get Ad-Hoc channel.561561- *562562- * This function prepares the correct firmware command and563563- * issues it to set or get the ad-hoc channel.564564- */565565-static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,566566- u16 action, u16 *channel)567567-{568568- if (action == HostCmd_ACT_GEN_GET) {569569- if (!priv->media_connected) {570570- *channel = priv->adhoc_channel;571571- return 0;572572- }573573- } else {574574- priv->adhoc_channel = (u8) *channel;575575- }576576-577577- return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL,578578- action, 0, channel);579579-}580580-581581-/*582582- * IOCTL request handler to change Ad-Hoc channel.583583- *584584- * This function allocates the IOCTL request buffer, fills it585585- * with requisite parameters and calls the IOCTL handler.586586- *587587- * The function follows the following steps to perform the change -588588- * - Get current IBSS information589589- * - Get current channel590590- * - If no change is required, return591591- * - If not connected, change channel and return592592- * - If connected,593593- * - Disconnect594594- * - Change channel595595- * - Perform specific SSID scan with same SSID596596- * - Start/Join the IBSS597597- */598598-int599599-mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel)600600-{601601- int ret;602602- struct mwifiex_bss_info bss_info;603603- struct mwifiex_ssid_bssid ssid_bssid;604604- u16 curr_chan = 0;605605- struct cfg80211_bss *bss = NULL;606606- struct ieee80211_channel *chan;607607- enum ieee80211_band band;608608-609609- memset(&bss_info, 0, sizeof(bss_info));610610-611611- /* Get BSS information */612612- if (mwifiex_get_bss_info(priv, &bss_info))613613- return -1;614614-615615- /* Get current channel */616616- ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET,617617- &curr_chan);618618-619619- if (curr_chan == channel) {620620- ret = 0;621621- goto done;622622- }623623- dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n",624624- curr_chan, channel);625625-626626- if (!bss_info.media_connected) {627627- ret = 0;628628- goto done;629629- }630630-631631- /* Do disonnect */632632- memset(&ssid_bssid, 0, ETH_ALEN);633633- ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid);634634-635635- ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET,636636- &channel);637637-638638- /* Do specific SSID scanning */639639- if (mwifiex_request_scan(priv, &bss_info.ssid)) {640640- ret = -1;641641- goto done;642642- }643643-644644- band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);645645- chan = __ieee80211_get_channel(priv->wdev->wiphy,646646- ieee80211_channel_to_frequency(channel,647647- band));648648-649649- /* Find the BSS we want using available scan results */650650- bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,651651- bss_info.ssid.ssid, bss_info.ssid.ssid_len,652652- WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);653653- if (!bss)654654- wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",655655- bss_info.bssid);656656-657657- ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);658658-done:659659- return ret;660660-}661661-662662-/*663663- * IOCTL request handler to get rate.664664- *665665- * This function prepares the correct firmware command and666666- * issues it to get the current rate if it is connected,667667- * otherwise, the function returns the lowest supported rate668668- * for the band.669669- */670670-static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,671671- struct mwifiex_rate_cfg *rate_cfg)672672-{673673- rate_cfg->is_rate_auto = priv->is_data_rate_auto;674674- return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,675675- HostCmd_ACT_GEN_GET, 0, NULL);676676-}677677-678678-/*679679- * IOCTL request handler to set rate.680680- *681681- * This function prepares the correct firmware command and682682- * issues it to set the current rate.683683- *684684- * The function also performs validation checking on the supplied value.685685- */686686-static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,687687- struct mwifiex_rate_cfg *rate_cfg)688688-{689689- u8 rates[MWIFIEX_SUPPORTED_RATES];690690- u8 *rate;691691- int rate_index, ret;692692- u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];693693- u32 i;694694- struct mwifiex_adapter *adapter = priv->adapter;695695-696696- if (rate_cfg->is_rate_auto) {697697- memset(bitmap_rates, 0, sizeof(bitmap_rates));698698- /* Support all HR/DSSS rates */699699- bitmap_rates[0] = 0x000F;700700- /* Support all OFDM rates */701701- bitmap_rates[1] = 0x00FF;702702- /* Support all HT-MCSs rate */703703- for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates) - 3; i++)704704- bitmap_rates[i + 2] = 0xFFFF;705705- bitmap_rates[9] = 0x3FFF;706706- } else {707707- memset(rates, 0, sizeof(rates));708708- mwifiex_get_active_data_rates(priv, rates);709709- rate = rates;710710- for (i = 0; (rate[i] && i < MWIFIEX_SUPPORTED_RATES); i++) {711711- dev_dbg(adapter->dev, "info: rate=%#x wanted=%#x\n",712712- rate[i], rate_cfg->rate);713713- if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f))714714- break;715715- }716716- if ((i == MWIFIEX_SUPPORTED_RATES) || !rate[i]) {717717- dev_err(adapter->dev, "fixed data rate %#x is out "718718- "of range\n", rate_cfg->rate);719719- return -1;720720- }721721- memset(bitmap_rates, 0, sizeof(bitmap_rates));722722-723723- rate_index = mwifiex_data_rate_to_index(rate_cfg->rate);724724-725725- /* Only allow b/g rates to be set */726726- if (rate_index >= MWIFIEX_RATE_INDEX_HRDSSS0 &&727727- rate_index <= MWIFIEX_RATE_INDEX_HRDSSS3) {728728- bitmap_rates[0] = 1 << rate_index;729729- } else {730730- rate_index -= 1; /* There is a 0x00 in the table */731731- if (rate_index >= MWIFIEX_RATE_INDEX_OFDM0 &&732732- rate_index <= MWIFIEX_RATE_INDEX_OFDM7)733733- bitmap_rates[1] = 1 << (rate_index -734734- MWIFIEX_RATE_INDEX_OFDM0);735735- }736736- }737737-738738- ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,739739- HostCmd_ACT_GEN_SET, 0, bitmap_rates);740740-741741- return ret;742742-}743743-744744-/*745745- * IOCTL request handler to set/get rate.746746- *747747- * This function can be used to set/get either the rate value or the748748- * rate index.749749- */750750-static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv,751751- struct mwifiex_rate_cfg *rate_cfg)752752-{753753- int status;754754-755755- if (!rate_cfg)756756- return -1;757757-758758- if (rate_cfg->action == HostCmd_ACT_GEN_GET)759759- status = mwifiex_rate_ioctl_get_rate_value(priv, rate_cfg);760760- else761761- status = mwifiex_rate_ioctl_set_rate_value(priv, rate_cfg);762762-763763- return status;764764-}765765-766766-/*767500 * Sends IOCTL request to get the data rate.768501 *769502 * This function allocates the IOCTL request buffer, fills it770503 * with requisite parameters and calls the IOCTL handler.771504 */772772-int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,773773- struct mwifiex_rate_cfg *rate)505505+int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate)774506{775507 int ret;776508777777- memset(rate, 0, sizeof(struct mwifiex_rate_cfg));778778- rate->action = HostCmd_ACT_GEN_GET;779779- ret = mwifiex_rate_ioctl_cfg(priv, rate);509509+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,510510+ HostCmd_ACT_GEN_GET, 0, NULL);780511781512 if (!ret) {782782- if (rate->is_rate_auto)783783- rate->rate = mwifiex_index_to_data_rate(priv,784784- priv->tx_rate,785785- priv->tx_htinfo786786- );513513+ if (priv->is_data_rate_auto)514514+ *rate = mwifiex_index_to_data_rate(priv, priv->tx_rate,515515+ priv->tx_htinfo);787516 else788788- rate->rate = priv->data_rate;789789- } else {790790- ret = -1;517517+ *rate = priv->data_rate;791518 }792519793520 return ret;
+4-1
drivers/net/wireless/mwl8k.c
···1665166516661666 info = IEEE80211_SKB_CB(skb);16671667 if (ieee80211_is_data(wh->frame_control)) {16681668- sta = info->control.sta;16681668+ rcu_read_lock();16691669+ sta = ieee80211_find_sta_by_ifaddr(hw, wh->addr1,16701670+ wh->addr2);16691671 if (sta) {16701672 sta_info = MWL8K_STA(sta);16711673 BUG_ON(sta_info == NULL);···16841682 sta_info->is_ampdu_allowed = true;16851683 }16861684 }16851685+ rcu_read_unlock();16871686 }1688168716891688 ieee80211_tx_info_clear_status(info);
···102102103103 /* Update the AID, this is needed for dynamic PS support */104104 rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;105105- rt2x00dev->last_beacon = bss_conf->last_tsf;105105+ rt2x00dev->last_beacon = bss_conf->sync_tsf;106106107107 /* Update global beacon interval time, this is needed for PS support */108108 rt2x00dev->beacon_int = bss_conf->beacon_int;
···85858686 memcpy(&gen_parms->general_params, gp, sizeof(*gp));87878888- if (gp->tx_bip_fem_auto_detect)8888+ /* If we started in PLT FEM_DETECT mode, force auto detect */8989+ if (wl->plt_mode == PLT_FEM_DETECT)9090+ gen_parms->general_params.tx_bip_fem_auto_detect = true;9191+9292+ if (gen_parms->general_params.tx_bip_fem_auto_detect)8993 answer = true;90949195 /* Override the REF CLK from the NVS with the one from platform data */···110106 goto out;111107 }112108109109+ /* If we are in calibrator based fem auto detect - save fem nr */110110+ if (wl->plt_mode == PLT_FEM_DETECT)111111+ wl->fem_manuf = gp->tx_bip_fem_manufacturer;112112+113113 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",114114- answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);114114+ answer == false ?115115+ "manual" :116116+ wl->plt_mode == PLT_FEM_DETECT ?117117+ "calibrator_fem_detect" :118118+ "auto",119119+ gp->tx_bip_fem_manufacturer);115120116121out:117122 kfree(gen_parms);···152139153140 memcpy(&gen_parms->general_params, gp, sizeof(*gp));154141155155- if (gp->tx_bip_fem_auto_detect)142142+ /* If we started in PLT FEM_DETECT mode, force auto detect */143143+ if (wl->plt_mode == PLT_FEM_DETECT)144144+ gen_parms->general_params.tx_bip_fem_auto_detect = true;145145+146146+ if (gen_parms->general_params.tx_bip_fem_auto_detect)156147 answer = true;157148158149 /* Replace REF and TCXO CLKs with the ones from platform data */···178161 goto out;179162 }180163164164+ /* If we are in calibrator based fem auto detect - save fem nr */165165+ if (wl->plt_mode == PLT_FEM_DETECT)166166+ wl->fem_manuf = gp->tx_bip_fem_manufacturer;167167+181168 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",182182- answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);169169+ answer == false ?170170+ "manual" :171171+ wl->plt_mode == PLT_FEM_DETECT ?172172+ "calibrator_fem_detect" :173173+ "auto",174174+ gp->tx_bip_fem_manufacturer);183175184176out:185177 kfree(gen_parms);
+23
drivers/net/wireless/ti/wl12xx/main.c
···13391339 ret = wl128x_cmd_general_parms(wl);13401340 if (ret < 0)13411341 goto out;13421342+13431343+ /*13441344+ * If we are in calibrator based auto detect then we got the FEM nr13451345+ * in wl->fem_manuf. No need to continue further13461346+ */13471347+ if (wl->plt_mode == PLT_FEM_DETECT)13481348+ goto out;13491349+13421350 ret = wl128x_cmd_radio_parms(wl);13431351 if (ret < 0)13441352 goto out;···13631355 ret = wl1271_cmd_general_parms(wl);13641356 if (ret < 0)13651357 goto out;13581358+13591359+ /*13601360+ * If we are in calibrator based auto detect then we got the FEM nr13611361+ * in wl->fem_manuf. No need to continue further13621362+ */13631363+ if (wl->plt_mode == PLT_FEM_DETECT)13641364+ goto out;13651365+13661366 ret = wl1271_cmd_radio_parms(wl);13671367 if (ret < 0)13681368 goto out;···15151499 ret = wl->ops->hw_init(wl);15161500 if (ret < 0)15171501 goto out_irq_disable;15021502+15031503+ /*15041504+ * If we are in calibrator based auto detect then we got the FEM nr15051505+ * in wl->fem_manuf. No need to continue further15061506+ */15071507+ if (wl->plt_mode == PLT_FEM_DETECT)15081508+ goto out;1518150915191510 ret = wl1271_acx_init_mem_config(wl);15201511 if (ret < 0)
···54545555int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)5656{5757- u32 val;5757+ u32 val = 0;5858 int ret;59596060 if (WARN_ON(addr % 2))
+85-32
drivers/net/wireless/ti/wl18xx/main.c
···43434444#define WL18XX_RX_CHECKSUM_MASK 0x4045454646-static char *ht_mode_param = "default";4747-static char *board_type_param = "hdk";4646+static char *ht_mode_param = NULL;4747+static char *board_type_param = NULL;4848static bool checksum_param = false;4949static bool enable_11a_param = true;5050static int num_rx_desc_param = -1;···494494};495495496496static struct wl18xx_priv_conf wl18xx_default_priv_conf = {497497+ .ht = {498498+ .mode = HT_MODE_DEFAULT,499499+ },497500 .phy = {498501 .phy_standalone = 0x00,499502 .primary_clock_setting_time = 0x05,500503 .clock_valid_on_wake_up = 0x00,501504 .secondary_clock_setting_time = 0x05,505505+ .board_type = BOARD_TYPE_HDK_18XX,502506 .rdl = 0x01,503507 .auto_detect = 0x00,504508 .dedicated_fem = FEM_NONE,505509 .low_band_component = COMPONENT_2_WAY_SWITCH,506506- .low_band_component_type = 0x05,510510+ .low_band_component_type = 0x06,507511 .high_band_component = COMPONENT_2_WAY_SWITCH,508512 .high_band_component_type = 0x09,509513 .tcxo_ldo_voltage = 0x00,···776772static int wl18xx_set_mac_and_phy(struct wl1271 *wl)777773{778774 struct wl18xx_priv *priv = wl->priv;775775+ struct wl18xx_mac_and_phy_params *params;779776 int ret;777777+778778+ params = kmemdup(&priv->conf.phy, sizeof(*params), GFP_KERNEL);779779+ if (!params) {780780+ ret = -ENOMEM;781781+ goto out;782782+ }780783781784 ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);782785 if (ret < 0)783786 goto out;784787785785- ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy,786786- sizeof(struct wl18xx_mac_and_phy_params), false);788788+ ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, params,789789+ sizeof(*params), false);787790788791out:792792+ kfree(params);789793 return ret;790794}791795···10131001 skb->ip_summed = CHECKSUM_UNNECESSARY;10141002}1015100310041004+static bool wl18xx_is_mimo_supported(struct wl1271 *wl)10051005+{10061006+ struct wl18xx_priv *priv = wl->priv;10071007+10081008+ return priv->conf.phy.number_of_assembled_ant2_4 >= 2;10091009+}10101010+10161011/*10171012 * TODO: instead of having these two functions to get the rate mask,10181013 * we should modify the wlvif->rate_set instead···1036101710371018 /* we don't support MIMO in wide-channel mode */10381019 hw_rate_set &= ~CONF_TX_MIMO_RATES;10201020+ } else if (wl18xx_is_mimo_supported(wl)) {10211021+ wl1271_debug(DEBUG_ACX, "using MIMO channel rate mask");10221022+ hw_rate_set |= CONF_TX_MIMO_RATES;10391023 }1040102410411025 return hw_rate_set;···10471025static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,10481026 struct wl12xx_vif *wlvif)10491027{10501050- struct wl18xx_priv *priv = wl->priv;10511051-10521028 if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||10531029 wlvif->channel_type == NL80211_CHAN_HT40PLUS) {10541030 wl1271_debug(DEBUG_ACX, "using wide channel rate mask");···10561036 return 0;1057103710581038 return CONF_TX_RATE_USE_WIDE_CHAN;10591059- } else if (priv->conf.phy.number_of_assembled_ant2_4 >= 2 &&10391039+ } else if (wl18xx_is_mimo_supported(wl) &&10601040 wlvif->band == IEEE80211_BAND_2GHZ) {10611041 wl1271_debug(DEBUG_ACX, "using MIMO rate mask");10621042 /*···11551135static int wl18xx_plt_init(struct wl1271 *wl)11561136{11571137 int ret;11381138+11391139+ /* calibrator based auto/fem detect not supported for 18xx */11401140+ if (wl->plt_mode == PLT_FEM_DETECT) {11411141+ wl1271_error("wl18xx_plt_init: PLT FEM_DETECT not supported");11421142+ return -EINVAL;11431143+ }1158114411591145 ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);11601146 if (ret < 0)···14091383 if (ret < 0)14101384 goto out_free;1411138514121412- if (!strcmp(board_type_param, "fpga")) {14131413- priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX;14141414- } else if (!strcmp(board_type_param, "hdk")) {14151415- priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX;14161416- /* HACK! Just for now we hardcode HDK to 0x06 */13861386+ /* If the module param is set, update it in conf */13871387+ if (board_type_param) {13881388+ if (!strcmp(board_type_param, "fpga")) {13891389+ priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX;13901390+ } else if (!strcmp(board_type_param, "hdk")) {13911391+ priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX;13921392+ } else if (!strcmp(board_type_param, "dvp")) {13931393+ priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX;13941394+ } else if (!strcmp(board_type_param, "evb")) {13951395+ priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX;13961396+ } else if (!strcmp(board_type_param, "com8")) {13971397+ priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX;13981398+ } else {13991399+ wl1271_error("invalid board type '%s'",14001400+ board_type_param);14011401+ ret = -EINVAL;14021402+ goto out_free;14031403+ }14041404+ }14051405+14061406+ /* HACK! Just for now we hardcode COM8 and HDK to 0x06 */14071407+ switch (priv->conf.phy.board_type) {14081408+ case BOARD_TYPE_HDK_18XX:14091409+ case BOARD_TYPE_COM8_18XX:14171410 priv->conf.phy.low_band_component_type = 0x06;14181418- } else if (!strcmp(board_type_param, "dvp")) {14191419- priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX;14201420- } else if (!strcmp(board_type_param, "evb")) {14211421- priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX;14221422- } else if (!strcmp(board_type_param, "com8")) {14231423- priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX;14241424- /* HACK! Just for now we hardcode COM8 to 0x06 */14251425- priv->conf.phy.low_band_component_type = 0x06;14261426- } else {14271427- wl1271_error("invalid board type '%s'", board_type_param);14111411+ break;14121412+ case BOARD_TYPE_FPGA_18XX:14131413+ case BOARD_TYPE_DVP_18XX:14141414+ case BOARD_TYPE_EVB_18XX:14151415+ priv->conf.phy.low_band_component_type = 0x05;14161416+ break;14171417+ default:14181418+ wl1271_error("invalid board type '%d'",14191419+ priv->conf.phy.board_type);14281420 ret = -EINVAL;14291421 goto out_free;14301422 }1431142314321432- /* If the module param is set, update it in conf */14331424 if (low_band_component_param != -1)14341425 priv->conf.phy.low_band_component = low_band_component_param;14351426 if (low_band_component_type_param != -1)···14671424 if (dc2dc_param != -1)14681425 priv->conf.phy.external_pa_dc2dc = dc2dc_param;1469142614701470- if (!strcmp(ht_mode_param, "default")) {14271427+ if (ht_mode_param) {14281428+ if (!strcmp(ht_mode_param, "default"))14291429+ priv->conf.ht.mode = HT_MODE_DEFAULT;14301430+ else if (!strcmp(ht_mode_param, "wide"))14311431+ priv->conf.ht.mode = HT_MODE_WIDE;14321432+ else if (!strcmp(ht_mode_param, "siso20"))14331433+ priv->conf.ht.mode = HT_MODE_SISO20;14341434+ else {14351435+ wl1271_error("invalid ht_mode '%s'", ht_mode_param);14361436+ ret = -EINVAL;14371437+ goto out_free;14381438+ }14391439+ }14401440+14411441+ if (priv->conf.ht.mode == HT_MODE_DEFAULT) {14711442 /*14721443 * Only support mimo with multiple antennas. Fall back to14731444 * siso20.14741445 */14751475- if (priv->conf.phy.number_of_assembled_ant2_4 >= 2)14461446+ if (wl18xx_is_mimo_supported(wl))14761447 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,14771448 &wl18xx_mimo_ht_cap_2ghz);14781449 else···14961439 /* 5Ghz is always wide */14971440 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,14981441 &wl18xx_siso40_ht_cap_5ghz);14991499- } else if (!strcmp(ht_mode_param, "wide")) {14421442+ } else if (priv->conf.ht.mode == HT_MODE_WIDE) {15001443 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,15011444 &wl18xx_siso40_ht_cap_2ghz);15021445 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,15031446 &wl18xx_siso40_ht_cap_5ghz);15041504- } else if (!strcmp(ht_mode_param, "siso20")) {14471447+ } else if (priv->conf.ht.mode == HT_MODE_SISO20) {15051448 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,15061449 &wl18xx_siso20_ht_cap);15071450 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,15081451 &wl18xx_siso20_ht_cap);15091509- } else {15101510- wl1271_error("invalid ht_mode '%s'", ht_mode_param);15111511- ret = -EINVAL;15121512- goto out_free;15131452 }1514145315151454 if (!checksum_param) {
+12
drivers/net/wireless/ti/wlcore/cmd.c
···497497{498498 struct wl12xx_cmd_role_stop *cmd;499499 int ret;500500+ bool timeout = false;500501501502 if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID))502503 return -EINVAL;···519518 wl1271_error("failed to initiate cmd role stop sta");520519 goto out_free;521520 }521521+522522+ /*523523+ * Sometimes the firmware doesn't send this event, so we just524524+ * time out without failing. Queue recovery for other525525+ * failures.526526+ */527527+ ret = wl1271_cmd_wait_for_event_or_timeout(wl,528528+ ROLE_STOP_COMPLETE_EVENT_ID,529529+ &timeout);530530+ if (ret)531531+ wl12xx_queue_recovery_work(wl);522532523533 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);524534
···10641064 return ret;10651065}1066106610671067-int wl1271_plt_start(struct wl1271 *wl)10671067+int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode)10681068{10691069 int retries = WL1271_BOOT_RETRIES;10701070 struct wiphy *wiphy = wl->hw->wiphy;10711071+10721072+ static const char* const PLT_MODE[] = {10731073+ "PLT_OFF",10741074+ "PLT_ON",10751075+ "PLT_FEM_DETECT"10761076+ };10771077+10711078 int ret;1072107910731080 mutex_lock(&wl->mutex);···10881081 goto out;10891082 }1090108310841084+ /* Indicate to lower levels that we are now in PLT mode */10851085+ wl->plt = true;10861086+ wl->plt_mode = plt_mode;10871087+10911088 while (retries) {10921089 retries--;10931090 ret = wl12xx_chip_wakeup(wl, true);···11021091 if (ret < 0)11031092 goto power_off;1104109311051105- wl->plt = true;11061094 wl->state = WL1271_STATE_ON;11071107- wl1271_notice("firmware booted in PLT mode (%s)",10951095+ wl1271_notice("firmware booted in PLT mode %s (%s)",10961096+ PLT_MODE[plt_mode],11081097 wl->chip.fw_ver_str);1109109811101099 /* update hw/fw version info in wiphy struct */···11171106power_off:11181107 wl1271_power_off(wl);11191108 }11091109+11101110+ wl->plt = false;11111111+ wl->plt_mode = PLT_OFF;1120111211211113 wl1271_error("firmware boot in PLT mode failed despite %d retries",11221114 WL1271_BOOT_RETRIES);···11731159 wl->sleep_auth = WL1271_PSM_ILLEGAL;11741160 wl->state = WL1271_STATE_OFF;11751161 wl->plt = false;11621162+ wl->plt_mode = PLT_OFF;11761163 wl->rx_counter = 0;11771164 mutex_unlock(&wl->mutex);11781165···16001585 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))16011586 goto out;1602158715881588+ if ((wl->conf.conn.suspend_wake_up_event ==15891589+ wl->conf.conn.wake_up_event) &&15901590+ (wl->conf.conn.suspend_listen_interval ==15911591+ wl->conf.conn.listen_interval))15921592+ goto out;15931593+16031594 ret = wl1271_ps_elp_wakeup(wl);16041595 if (ret < 0)16051596 goto out;···16671646 bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS;1668164716691648 if ((!is_ap) && (!is_sta))16491649+ return;16501650+16511651+ if (is_sta &&16521652+ ((wl->conf.conn.suspend_wake_up_event ==16531653+ wl->conf.conn.wake_up_event) &&16541654+ (wl->conf.conn.suspend_listen_interval ==16551655+ wl->conf.conn.listen_interval)))16701656 return;1671165716721658 ret = wl1271_ps_elp_wakeup(wl);···23922364 else23932365 wl->sta_count--;2394236623952395- /* Last AP, have more stations. Configure according to STA. */23672367+ /*23682368+ * Last AP, have more stations. Configure sleep auth according to STA.23692369+ * Don't do thin on unintended recovery.23702370+ */23712371+ if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags) &&23722372+ !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags))23732373+ goto unlock;23742374+23962375 if (wl->ap_count == 0 && is_ap && wl->sta_count) {23972376 u8 sta_auth = wl->conf.conn.sta_sleep_auth;23982377 /* Configure for power according to debugfs */···24132378 wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);24142379 }2415238023812381+unlock:24162382 mutex_unlock(&wl->mutex);2417238324182384 del_timer_sync(&wlvif->rx_streaming_timer);
+61-24
drivers/net/wireless/ti/wlcore/testmode.c
···129129 goto out_sleep;130130 }131131132132- if (nla_put(skb, WL1271_TM_ATTR_DATA, buf_len, buf))133133- goto nla_put_failure;132132+ if (nla_put(skb, WL1271_TM_ATTR_DATA, buf_len, buf)) {133133+ kfree_skb(skb);134134+ ret = -EMSGSIZE;135135+ goto out_sleep;136136+ }137137+134138 ret = cfg80211_testmode_reply(skb);135139 if (ret < 0)136140 goto out_sleep;···146142 mutex_unlock(&wl->mutex);147143148144 return ret;149149-150150-nla_put_failure:151151- kfree_skb(skb);152152- ret = -EMSGSIZE;153153- goto out_sleep;154145}155146156147static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])···191192 goto out_free;192193 }193194194194- if (nla_put(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd))195195- goto nla_put_failure;195195+ if (nla_put(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd)) {196196+ kfree_skb(skb);197197+ ret = -EMSGSIZE;198198+ goto out_free;199199+ }200200+196201 ret = cfg80211_testmode_reply(skb);197202 if (ret < 0)198203 goto out_free;···209206 mutex_unlock(&wl->mutex);210207211208 return ret;212212-213213-nla_put_failure:214214- kfree_skb(skb);215215- ret = -EMSGSIZE;216216- goto out_free;217209}218210219211static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])···243245 return 0;244246}245247248248+static int wl1271_tm_detect_fem(struct wl1271 *wl, struct nlattr *tb[])249249+{250250+ /* return FEM type */251251+ int ret, len;252252+ struct sk_buff *skb;253253+254254+ ret = wl1271_plt_start(wl, PLT_FEM_DETECT);255255+ if (ret < 0)256256+ goto out;257257+258258+ mutex_lock(&wl->mutex);259259+260260+ len = nla_total_size(sizeof(wl->fem_manuf));261261+ skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);262262+ if (!skb) {263263+ ret = -ENOMEM;264264+ goto out_mutex;265265+ }266266+267267+ if (nla_put(skb, WL1271_TM_ATTR_DATA, sizeof(wl->fem_manuf),268268+ &wl->fem_manuf)) {269269+ kfree_skb(skb);270270+ ret = -EMSGSIZE;271271+ goto out_mutex;272272+ }273273+274274+ ret = cfg80211_testmode_reply(skb);275275+276276+out_mutex:277277+ mutex_unlock(&wl->mutex);278278+279279+ /* We always stop plt after DETECT mode */280280+ wl1271_plt_stop(wl);281281+out:282282+ return ret;283283+}284284+246285static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])247286{248287 u32 val;···293258 val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]);294259295260 switch (val) {296296- case 0:261261+ case PLT_OFF:297262 ret = wl1271_plt_stop(wl);298263 break;299299- case 1:300300- ret = wl1271_plt_start(wl);264264+ case PLT_ON:265265+ ret = wl1271_plt_start(wl, PLT_ON);266266+ break;267267+ case PLT_FEM_DETECT:268268+ ret = wl1271_tm_detect_fem(wl, tb);301269 break;302270 default:303271 ret = -EINVAL;···341303 goto out;342304 }343305344344- if (nla_put(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr))345345- goto nla_put_failure;306306+ if (nla_put(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr)) {307307+ kfree_skb(skb);308308+ ret = -EMSGSIZE;309309+ goto out;310310+ }311311+346312 ret = cfg80211_testmode_reply(skb);347313 if (ret < 0)348314 goto out;···354312out:355313 mutex_unlock(&wl->mutex);356314 return ret;357357-358358-nla_put_failure:359359- kfree_skb(skb);360360- ret = -EMSGSIZE;361361- goto out;362315}363316364317int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
+8-6
drivers/net/wireless/ti/wlcore/tx.c
···306306 rate_idx = 0;307307 else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {308308 /*309309- * if the packets are destined for AP (have a STA entry)309309+ * if the packets are data packets310310 * send them with AP rate policies (EAPOLs are an exception),311311 * otherwise use default basic rates312312 */313313- if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE)314314- rate_idx = wlvif->sta.p2p_rate_idx;315315- else if (skb->protocol == cpu_to_be16(ETH_P_PAE))313313+ if (skb->protocol == cpu_to_be16(ETH_P_PAE))316314 rate_idx = wlvif->sta.basic_rate_idx;317317- else if (control->control.sta)315315+ else if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE)316316+ rate_idx = wlvif->sta.p2p_rate_idx;317317+ else if (ieee80211_is_data(frame_control))318318 rate_idx = wlvif->sta.ap_rate_idx;319319 else320320 rate_idx = wlvif->sta.basic_rate_idx;321321 } else {322322 if (hlid == wlvif->ap.global_hlid)323323 rate_idx = wlvif->ap.mgmt_rate_idx;324324- else if (hlid == wlvif->ap.bcast_hlid)324324+ else if (hlid == wlvif->ap.bcast_hlid ||325325+ skb->protocol == cpu_to_be16(ETH_P_PAE))326326+ /* send AP bcast and EAPOLs using the min basic rate */325327 rate_idx = wlvif->ap.bcast_rate_idx;326328 else327329 rate_idx = wlvif->ap.ucast_rate_idx[ac];
···77#include <linux/bcma/bcma_driver_chipcommon.h>88#include <linux/bcma/bcma_driver_pci.h>99#include <linux/bcma/bcma_driver_mips.h>1010+#include <linux/bcma/bcma_driver_gmac_cmn.h>1011#include <linux/ssb/ssb.h> /* SPROM sharing */11121213#include "bcma_regs.h"···253252 struct bcma_drv_cc drv_cc;254253 struct bcma_drv_pci drv_pci;255254 struct bcma_drv_mips drv_mips;255255+ struct bcma_drv_gmac_cmn drv_gmac_cmn;256256257257 /* We decided to share SPROM struct with SSB as long as we do not need258258 * any hacks for BCMA. This simplifies drivers code. */
···771771 * @NL80211_ATTR_IFNAME: network interface name772772 * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype773773 *774774+ * @NL80211_ATTR_WDEV: wireless device identifier, used for pseudo-devices775775+ * that don't have a netdev (u64)776776+ *774777 * @NL80211_ATTR_MAC: MAC address (various uses)775778 *776779 * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of···12451242 * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds12461243 * or 0 to disable background scan.12471244 *12451245+ * @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from12461246+ * userspace. If unset it is assumed the hint comes directly from12471247+ * a user. If set code could specify exactly what type of source12481248+ * was used to provide the hint. For the different types of12491249+ * allowed user regulatory hints see nl80211_user_reg_hint_type.12501250+ *12481251 * @NL80211_ATTR_MAX: highest attribute number currently defined12491252 * @__NL80211_ATTR_AFTER_LAST: internal use12501253 */···1502149315031494 NL80211_ATTR_BG_SCAN_PERIOD,1504149514961496+ NL80211_ATTR_WDEV,14971497+14981498+ NL80211_ATTR_USER_REG_HINT_TYPE,14991499+15051500 /* add attributes here, update the policy in nl80211.c */1506150115071502 __NL80211_ATTR_AFTER_LAST,···1557154415581545/* default RSSI threshold for scan results if none specified. */15591546#define NL80211_SCAN_RSSI_THOLD_OFF -30015471547+15481548+#define NL80211_CQM_TXE_MAX_INTVL 18001560154915611550/**15621551 * enum nl80211_iftype - (virtual) interface types···20662051 NL80211_DFS_FCC = 1,20672052 NL80211_DFS_ETSI = 2,20682053 NL80211_DFS_JP = 3,20542054+};20552055+20562056+/**20572057+ * enum nl80211_user_reg_hint_type - type of user regulatory hint20582058+ *20592059+ * @NL80211_USER_REG_HINT_USER: a user sent the hint. This is always20602060+ * assumed if the attribute is not set.20612061+ * @NL80211_USER_REG_HINT_CELL_BASE: the hint comes from a cellular20622062+ * base station. Device drivers that have been tested to work20632063+ * properly to support this type of hint can enable these hints20642064+ * by setting the NL80211_FEATURE_CELL_BASE_REG_HINTS feature20652065+ * capability on the struct wiphy. The wireless core will20662066+ * ignore all cell base station hints until at least one device20672067+ * present has been registered with the wireless core that20682068+ * has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a20692069+ * supported feature.20702070+ */20712071+enum nl80211_user_reg_hint_type {20722072+ NL80211_USER_REG_HINT_USER = 0,20732073+ NL80211_USER_REG_HINT_CELL_BASE = 1,20692074};2070207520712076/**···26192584 * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event26202585 * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many26212586 * consecutive packets were not acknowledged by the peer25872587+ * @NL80211_ATTR_CQM_TXE_RATE: TX error rate in %. Minimum % of TX failures25882588+ * during the given %NL80211_ATTR_CQM_TXE_INTVL before an25892589+ * %NL80211_CMD_NOTIFY_CQM with reported %NL80211_ATTR_CQM_TXE_RATE and25902590+ * %NL80211_ATTR_CQM_TXE_PKTS is generated.25912591+ * @NL80211_ATTR_CQM_TXE_PKTS: number of attempted packets in a given25922592+ * %NL80211_ATTR_CQM_TXE_INTVL before %NL80211_ATTR_CQM_TXE_RATE is25932593+ * checked.25942594+ * @NL80211_ATTR_CQM_TXE_INTVL: interval in seconds. Specifies the periodic25952595+ * interval in which %NL80211_ATTR_CQM_TXE_PKTS and25962596+ * %NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an25972597+ * %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting.26222598 * @__NL80211_ATTR_CQM_AFTER_LAST: internal26232599 * @NL80211_ATTR_CQM_MAX: highest key attribute26242600 */···26392593 NL80211_ATTR_CQM_RSSI_HYST,26402594 NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,26412595 NL80211_ATTR_CQM_PKT_LOSS_EVENT,25962596+ NL80211_ATTR_CQM_TXE_RATE,25972597+ NL80211_ATTR_CQM_TXE_PKTS,25982598+ NL80211_ATTR_CQM_TXE_INTVL,2642259926432600 /* keep last */26442601 __NL80211_ATTR_CQM_AFTER_LAST,···29912942 * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.29922943 * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up29932944 * the connected inactive stations in AP mode.29452945+ * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested29462946+ * to work properly to suppport receiving regulatory hints from29472947+ * cellular base stations.29942948 */29952949enum nl80211_feature_flags {29962950 NL80211_FEATURE_SK_TX_STATUS = 1 << 0,29972951 NL80211_FEATURE_HT_IBSS = 1 << 1,29982952 NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,29532953+ NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,29992954};3000295530012956/**
···999999 * @ie_len: length of ie in octets10001000 * @rates: bitmap of rates to advertise for each band10011001 * @wiphy: the wiphy this was for10021002- * @dev: the interface10021002+ * @wdev: the wireless device to scan for10031003 * @aborted: (internal) scan request was notified as aborted10041004 * @no_cck: used to send probe requests at non CCK rate in 2GHz band10051005 */···1012101210131013 u32 rates[IEEE80211_NUM_BANDS];1014101410151015+ struct wireless_dev *wdev;10161016+10151017 /* internal */10161018 struct wiphy *wiphy;10171017- struct net_device *dev;10181019 bool aborted;10191020 bool no_cck;10201021···14361435 *14371436 * @add_virtual_intf: create a new virtual interface with the given name,14381437 * must set the struct wireless_dev's iftype. Beware: You must create14391439- * the new netdev in the wiphy's network namespace! Returns the netdev,14401440- * or an ERR_PTR.14381438+ * the new netdev in the wiphy's network namespace! Returns the struct14391439+ * wireless_dev, or an ERR_PTR.14411440 *14421442- * @del_virtual_intf: remove the virtual interface determined by ifindex.14411441+ * @del_virtual_intf: remove the virtual interface14431442 *14441443 * @change_virtual_intf: change type/configuration of virtual interface,14451444 * keep the struct wireless_dev's iftype updated.···15041503 * interfaces are active this callback should reject the configuration.15051504 * If no interfaces are active or the device is down, the channel should15061505 * be stored for when a monitor interface becomes active.15071507- * @set_monitor_enabled: Notify driver that there are only monitor15081508- * interfaces running.15091506 *15101507 * @scan: Request to do a scan. If returning zero, the scan request is given15111508 * the driver, and will be valid until passed to cfg80211_scan_done().···15731574 * @set_power_mgmt: Configure WLAN power management. A timeout value of -115741575 * allows the driver to adjust the dynamic ps timeout value.15751576 * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.15771577+ * @set_cqm_txe_config: Configure connection quality monitor TX error15781578+ * thresholds.15761579 * @sched_scan_start: Tell the driver to start a scheduled scan.15771580 * @sched_scan_stop: Tell the driver to stop an ongoing scheduled15781581 * scan. The driver_initiated flag specifies whether the driver···16121611 * @get_et_strings: Ethtool API to get a set of strings to describe stats16131612 * and perhaps other supported types of ethtool data-sets.16141613 * See @ethtool_ops.get_strings16141614+ *16151615+ * @get_channel: Get the current operating channel for the virtual interface.16161616+ * For monitor interfaces, it should return %NULL unless there's a single16171617+ * current monitoring channel.16151618 */16161619struct cfg80211_ops {16171620 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);16181621 int (*resume)(struct wiphy *wiphy);16191622 void (*set_wakeup)(struct wiphy *wiphy, bool enabled);1620162316211621- struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,16221622- char *name,16231623- enum nl80211_iftype type,16241624- u32 *flags,16251625- struct vif_params *params);16261626- int (*del_virtual_intf)(struct wiphy *wiphy, struct net_device *dev);16241624+ struct wireless_dev * (*add_virtual_intf)(struct wiphy *wiphy,16251625+ char *name,16261626+ enum nl80211_iftype type,16271627+ u32 *flags,16281628+ struct vif_params *params);16291629+ int (*del_virtual_intf)(struct wiphy *wiphy,16301630+ struct wireless_dev *wdev);16271631 int (*change_virtual_intf)(struct wiphy *wiphy,16281632 struct net_device *dev,16291633 enum nl80211_iftype type, u32 *flags,···17051699 struct ieee80211_channel *chan,17061700 enum nl80211_channel_type channel_type);1707170117081708- int (*scan)(struct wiphy *wiphy, struct net_device *dev,17021702+ int (*scan)(struct wiphy *wiphy,17091703 struct cfg80211_scan_request *request);1710170417111705 int (*auth)(struct wiphy *wiphy, struct net_device *dev,···17591753 int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);1760175417611755 int (*remain_on_channel)(struct wiphy *wiphy,17621762- struct net_device *dev,17561756+ struct wireless_dev *wdev,17631757 struct ieee80211_channel *chan,17641758 enum nl80211_channel_type channel_type,17651759 unsigned int duration,17661760 u64 *cookie);17671761 int (*cancel_remain_on_channel)(struct wiphy *wiphy,17681768- struct net_device *dev,17621762+ struct wireless_dev *wdev,17691763 u64 cookie);1770176417711771- int (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev,17651765+ int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,17721766 struct ieee80211_channel *chan, bool offchan,17731767 enum nl80211_channel_type channel_type,17741768 bool channel_type_valid, unsigned int wait,17751769 const u8 *buf, size_t len, bool no_cck,17761770 bool dont_wait_for_ack, u64 *cookie);17771771 int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,17781778- struct net_device *dev,17721772+ struct wireless_dev *wdev,17791773 u64 cookie);1780177417811775 int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,···17851779 struct net_device *dev,17861780 s32 rssi_thold, u32 rssi_hyst);1787178117821782+ int (*set_cqm_txe_config)(struct wiphy *wiphy,17831783+ struct net_device *dev,17841784+ u32 rate, u32 pkts, u32 intvl);17851785+17881786 void (*mgmt_frame_register)(struct wiphy *wiphy,17891789- struct net_device *dev,17871787+ struct wireless_dev *wdev,17901788 u16 frame_type, bool reg);1791178917921790 int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);···18281818 void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,18291819 u32 sset, u8 *data);1830182018311831- void (*set_monitor_enabled)(struct wiphy *wiphy, bool enabled);18211821+ struct ieee80211_channel *18221822+ (*get_channel)(struct wiphy *wiphy,18231823+ struct wireless_dev *wdev,18241824+ enum nl80211_channel_type *type);18321825};1833182618341827/*···23542341struct cfg80211_cached_keys;2355234223562343/**23572357- * struct wireless_dev - wireless per-netdev state23442344+ * struct wireless_dev - wireless device state23582345 *23592359- * This structure must be allocated by the driver/stack23602360- * that uses the ieee80211_ptr field in struct net_device23612361- * (this is intentional so it can be allocated along with23622362- * the netdev.)23462346+ * For netdevs, this structure must be allocated by the driver23472347+ * that uses the ieee80211_ptr field in struct net_device (this23482348+ * is intentional so it can be allocated along with the netdev.)23492349+ * It need not be registered then as netdev registration will23502350+ * be intercepted by cfg80211 to see the new wireless device.23512351+ *23522352+ * For non-netdev uses, it must also be allocated by the driver23532353+ * in response to the cfg80211 callbacks that require it, as23542354+ * there's no netdev registration in that case it may not be23552355+ * allocated outside of callback operations that return it.23632356 *23642357 * @wiphy: pointer to hardware description23652358 * @iftype: interface type23662359 * @list: (private) Used to collect the interfaces23672367- * @netdev: (private) Used to reference back to the netdev23602360+ * @netdev: (private) Used to reference back to the netdev, may be %NULL23612361+ * @identifier: (private) Identifier used in nl80211 to identify this23622362+ * wireless device if it has no netdev23682363 * @current_bss: (private) Used by the internal configuration code23692364 * @channel: (private) Used by the internal configuration code to track23702365 * the user-set AP, monitor and WDS channel···24032382 /* the remainder of this struct should be private to cfg80211 */24042383 struct list_head list;24052384 struct net_device *netdev;23852385+23862386+ u32 identifier;2406238724072388 struct list_head mgmt_registrations;24082389 spinlock_t mgmt_registrations_lock;···3292326932933270/**32943271 * cfg80211_ready_on_channel - notification of remain_on_channel start32953295- * @dev: network device32723272+ * @wdev: wireless device32963273 * @cookie: the request cookie32973274 * @chan: The current channel (from remain_on_channel request)32983275 * @channel_type: Channel type···33003277 * channel33013278 * @gfp: allocation flags33023279 */33033303-void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,32803280+void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,33043281 struct ieee80211_channel *chan,33053282 enum nl80211_channel_type channel_type,33063283 unsigned int duration, gfp_t gfp);3307328433083285/**33093286 * cfg80211_remain_on_channel_expired - remain_on_channel duration expired33103310- * @dev: network device32873287+ * @wdev: wireless device33113288 * @cookie: the request cookie33123289 * @chan: The current channel (from remain_on_channel request)33133290 * @channel_type: Channel type33143291 * @gfp: allocation flags33153292 */33163316-void cfg80211_remain_on_channel_expired(struct net_device *dev,33173317- u64 cookie,32933293+void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,33183294 struct ieee80211_channel *chan,33193295 enum nl80211_channel_type channel_type,33203296 gfp_t gfp);···3341331933423320/**33433321 * cfg80211_rx_mgmt - notification of received, unprocessed management frame33443344- * @dev: network device33223322+ * @wdev: wireless device receiving the frame33453323 * @freq: Frequency on which the frame was received in MHz33463324 * @sig_dbm: signal strength in mBm, or 0 if unknown33473325 * @buf: Management frame (header + body)···33563334 * This function is called whenever an Action frame is received for a station33573335 * mode interface, but is not processed in kernel.33583336 */33593359-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,33373337+bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm,33603338 const u8 *buf, size_t len, gfp_t gfp);3361333933623340/**33633341 * cfg80211_mgmt_tx_status - notification of TX status for management frame33643364- * @dev: network device33423342+ * @wdev: wireless device receiving the frame33653343 * @cookie: Cookie returned by cfg80211_ops::mgmt_tx()33663344 * @buf: Management frame (header + body)33673345 * @len: length of the frame data···33723350 * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the33733351 * transmission attempt.33743352 */33753375-void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,33533353+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,33763354 const u8 *buf, size_t len, bool ack, gfp_t gfp);3377335533783356···34003378 */34013379void cfg80211_cqm_pktloss_notify(struct net_device *dev,34023380 const u8 *peer, u32 num_packets, gfp_t gfp);33813381+33823382+/**33833383+ * cfg80211_cqm_txe_notify - TX error rate event33843384+ * @dev: network device33853385+ * @peer: peer's MAC address33863386+ * @num_packets: how many packets were lost33873387+ * @rate: % of packets which failed transmission33883388+ * @intvl: interval (in s) over which the TX failure threshold was breached.33893389+ * @gfp: context flags33903390+ *33913391+ * Notify userspace when configured % TX failures over number of packets in a33923392+ * given interval is exceeded.33933393+ */33943394+void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,33953395+ u32 num_packets, u32 rate, u32 intvl, gfp_t gfp);3403339634043397/**34053398 * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
+15-25
include/net/mac80211.h
···233233 * valid in station mode only while @assoc is true and if also234234 * requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf235235 * @ps_dtim_period)236236- * @last_tsf: last beacon's/probe response's TSF timestamp (could be old236236+ * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old237237 * as it may have been received during scanning long ago)238238+ * @sync_device_ts: the device timestamp corresponding to the sync_tsf,239239+ * the driver/device can use this to calculate synchronisation238240 * @beacon_int: beacon interval239241 * @assoc_capability: capabilities taken from assoc resp240242 * @basic_rates: bitmap of basic rates, each bit stands for an···283281 u8 dtim_period;284282 u16 beacon_int;285283 u16 assoc_capability;286286- u64 last_tsf;284284+ u64 sync_tsf;285285+ u32 sync_device_ts;287286 u32 basic_rates;288287 int mcast_rate[IEEE80211_NUM_BANDS];289288 u16 ht_operation_mode;···699696 *700697 * @mactime: value in microseconds of the 64-bit Time Synchronization Function701698 * (TSF) timer when the first data symbol (MPDU) arrived at the hardware.699699+ * @device_timestamp: arbitrary timestamp for the device, mac80211 doesn't use700700+ * it but can store it and pass it back to the driver for synchronisation702701 * @band: the active band when this frame was received703702 * @freq: frequency the radio was tuned to when receiving this frame, in MHz704703 * @signal: signal strength when receiving this frame, either in dBm, in dB or···714709 */715710struct ieee80211_rx_status {716711 u64 mactime;717717- enum ieee80211_band band;718718- int freq;719719- int signal;720720- int antenna;721721- int rate_idx;722722- int flag;723723- unsigned int rx_flags;712712+ u32 device_timestamp;713713+ u16 flag;714714+ u16 freq;715715+ u8 rate_idx;716716+ u8 rx_flags;717717+ u8 band;718718+ u8 antenna;719719+ s8 signal;724720};725721726722/**···35963590 */35973591void ieee80211_request_smps(struct ieee80211_vif *vif,35983592 enum ieee80211_smps_mode smps_mode);35993599-36003600-/**36013601- * ieee80211_key_removed - disable hw acceleration for key36023602- * @key_conf: The key hw acceleration should be disabled for36033603- *36043604- * This allows drivers to indicate that the given key has been36053605- * removed from hardware acceleration, due to a new key that36063606- * was added. Don't use this if the key can continue to be used36073607- * for TX, if the key restriction is on RX only it is permitted36083608- * to keep the key for TX only and not call this function.36093609- *36103610- * Due to locking constraints, it may only be called during36113611- * @set_key. This function must be allowed to sleep, and the36123612- * key it tries to disable may still be used until it returns.36133613- */36143614-void ieee80211_key_removed(struct ieee80211_key_conf *key_conf);3615359336163594/**36173595 * ieee80211_ready_on_channel - notification of remain-on-channel start
+5
include/net/regulatory.h
···5252 * DFS master operation on a known DFS region (NL80211_DFS_*),5353 * dfs_region represents that region. Drivers can use this and the5454 * @alpha2 to adjust their device's DFS parameters as required.5555+ * @user_reg_hint_type: if the @initiator was of type5656+ * %NL80211_REGDOM_SET_BY_USER, this classifies the type5757+ * of hint passed. This could be any of the %NL80211_USER_REG_HINT_*5858+ * types.5559 * @intersect: indicates whether the wireless core should intersect5660 * the requested regulatory domain with the presently set regulatory5761 * domain.···7470struct regulatory_request {7571 int wiphy_idx;7672 enum nl80211_reg_initiator initiator;7373+ enum nl80211_user_reg_hint_type user_reg_hint_type;7774 char alpha2[2];7875 u8 dfs_region;7976 bool intersect;
···112112 }113113 }114114115115- if (local->scan_sdata &&116116- !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {115115+ sdata = rcu_dereference_protected(local->scan_sdata,116116+ lockdep_is_held(&local->mtx));117117+ if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {117118 scanning = true;118118- local->scan_sdata->vif.bss_conf.idle = false;119119+ sdata->vif.bss_conf.idle = false;119120 }120121121122 list_for_each_entry(sdata, &local->interfaces, list) {···331330 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;332331}333332334334-int ieee80211_add_virtual_monitor(struct ieee80211_local *local)333333+static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)335334{336335 struct ieee80211_sub_if_data *sdata;337337- int ret;336336+ int ret = 0;338337339338 if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))340339 return 0;341340341341+ mutex_lock(&local->iflist_mtx);342342+342343 if (local->monitor_sdata)343343- return 0;344344+ goto out_unlock;344345345346 sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);346346- if (!sdata)347347- return -ENOMEM;347347+ if (!sdata) {348348+ ret = -ENOMEM;349349+ goto out_unlock;350350+ }348351349352 /* set up data */350353 sdata->local = local;···362357 if (WARN_ON(ret)) {363358 /* ok .. stupid driver, it asked for this! */364359 kfree(sdata);365365- return ret;360360+ goto out_unlock;366361 }367362368363 ret = ieee80211_check_queues(sdata);369364 if (ret) {370365 kfree(sdata);371371- return ret;366366+ goto out_unlock;372367 }373368374369 rcu_assign_pointer(local->monitor_sdata, sdata);375375-376376- return 0;370370+ out_unlock:371371+ mutex_unlock(&local->iflist_mtx);372372+ return ret;377373}378374379379-void ieee80211_del_virtual_monitor(struct ieee80211_local *local)375375+static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)380376{381377 struct ieee80211_sub_if_data *sdata;382378383379 if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))384380 return;385381386386- sdata = rtnl_dereference(local->monitor_sdata);382382+ mutex_lock(&local->iflist_mtx);387383384384+ sdata = rcu_dereference_protected(local->monitor_sdata,385385+ lockdep_is_held(&local->iflist_mtx));388386 if (!sdata)389389- return;387387+ goto out_unlock;390388391389 rcu_assign_pointer(local->monitor_sdata, NULL);392390 synchronize_net();···397389 drv_remove_interface(local, sdata);398390399391 kfree(sdata);392392+ out_unlock:393393+ mutex_unlock(&local->iflist_mtx);400394}401395402396/*···497487 break;498488 }499489490490+ if (local->monitors == 0 && local->open_count == 0) {491491+ res = ieee80211_add_virtual_monitor(local);492492+ if (res)493493+ goto err_stop;494494+ }495495+500496 /* must be before the call to ieee80211_configure_filter */501497 local->monitors++;502498 if (local->monitors == 1) {···517501 break;518502 default:519503 if (coming_up) {504504+ ieee80211_del_virtual_monitor(local);505505+520506 res = drv_add_interface(local, sdata);521507 if (res)522508 goto err_stop;···646628647629 clear_bit(SDATA_STATE_RUNNING, &sdata->state);648630649649- if (local->scan_sdata == sdata)631631+ if (rcu_access_pointer(local->scan_sdata) == sdata)650632 ieee80211_scan_cancel(local);651633652634 /*···753735 if (local->monitors == 0) {754736 local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;755737 hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;738738+ ieee80211_del_virtual_monitor(local);756739 }757740758741 ieee80211_adjust_monitor_flags(sdata, -1);···827808 }828809 }829810 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);811811+812812+ if (local->monitors == local->open_count && local->monitors > 0)813813+ ieee80211_add_virtual_monitor(local);830814}831815832816static int ieee80211_stop(struct net_device *dev)···13951373}1396137413971375int ieee80211_if_add(struct ieee80211_local *local, const char *name,13981398- struct net_device **new_dev, enum nl80211_iftype type,13761376+ struct wireless_dev **new_wdev, enum nl80211_iftype type,13991377 struct vif_params *params)14001378{14011379 struct net_device *ndev;···14851463 list_add_tail_rcu(&sdata->list, &local->interfaces);14861464 mutex_unlock(&local->iflist_mtx);1487146514881488- if (new_dev)14891489- *new_dev = ndev;14661466+ if (new_wdev)14671467+ *new_wdev = &sdata->wdev;1490146814911469 return 0;14921470
-20
net/mac80211/key.c
···194194 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;195195}196196197197-void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)198198-{199199- struct ieee80211_key *key;200200-201201- key = container_of(key_conf, struct ieee80211_key, conf);202202-203203- might_sleep();204204- assert_key_lock(key->local);205205-206206- key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;207207-208208- /*209209- * Flush TX path to avoid attempts to use this key210210- * after this function returns. Until then, drivers211211- * must be prepared to handle the key.212212- */213213- synchronize_rcu();214214-}215215-EXPORT_SYMBOL_GPL(ieee80211_key_removed);216216-217197static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,218198 int idx, bool uni, bool multi)219199{
+2-1
net/mac80211/main.c
···322322323323 mutex_lock(&local->mtx);324324 WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||325325- local->sched_scanning,325325+ rcu_dereference_protected(local->sched_scan_sdata,326326+ lockdep_is_held(&local->mtx)),326327 "%s called with hardware scan in progress\n", __func__);327328 mutex_unlock(&local->mtx);328329
+34-28
net/mac80211/mlme.c
···11081108}1109110911101110/* MLME */11111111-static void ieee80211_sta_wmm_params(struct ieee80211_local *local,11111111+static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,11121112 struct ieee80211_sub_if_data *sdata,11131113 u8 *wmm_param, size_t wmm_param_len)11141114{···11191119 u8 *pos, uapsd_queues = 0;1120112011211121 if (!local->ops->conf_tx)11221122- return;11221122+ return false;1123112311241124 if (local->hw.queues < IEEE80211_NUM_ACS)11251125- return;11251125+ return false;1126112611271127 if (!wmm_param)11281128- return;11281128+ return false;1129112911301130 if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)11311131- return;11311131+ return false;1132113211331133 if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)11341134 uapsd_queues = ifmgd->uapsd_queues;1135113511361136 count = wmm_param[6] & 0x0f;11371137 if (count == ifmgd->wmm_last_param_set)11381138- return;11381138+ return false;11391139 ifmgd->wmm_last_param_set = count;1140114011411141 pos = wmm_param + 8;···1202120212031203 /* enable WMM or activate new settings */12041204 sdata->vif.bss_conf.qos = true;12051205+ return true;12051206}1206120712071208static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)···12691268 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;1270126912711270 bss_info_changed |= BSS_CHANGED_ASSOC;12721272- /* set timing information */12731273- bss_conf->beacon_int = cbss->beacon_interval;12741274- bss_conf->last_tsf = cbss->tsf;12751275-12761276- bss_info_changed |= BSS_CHANGED_BEACON_INT;12771271 bss_info_changed |= ieee80211_handle_bss_capability(sdata,12781272 bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);12791273···13601364 }13611365 mutex_unlock(&local->sta_mtx);1362136613671367+ /*13681368+ * if we want to get out of ps before disassoc (why?) we have13691369+ * to do it before sending disassoc, as otherwise the null-packet13701370+ * won't be valid.13711371+ */13721372+ if (local->hw.conf.flags & IEEE80211_CONF_PS) {13731373+ local->hw.conf.flags &= ~IEEE80211_CONF_PS;13741374+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);13751375+ }13761376+ local->ps_sdata = NULL;13771377+13631378 /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */13641379 if (tx)13651380 drv_flush(local, false);···1405139814061399 del_timer_sync(&local->dynamic_ps_timer);14071400 cancel_work_sync(&local->dynamic_ps_enable_work);14081408-14091409- if (local->hw.conf.flags & IEEE80211_CONF_PS) {14101410- local->hw.conf.flags &= ~IEEE80211_CONF_PS;14111411- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);14121412- }14131413- local->ps_sdata = NULL;1414140114151402 /* Disable ARP filtering */14161403 if (sdata->vif.bss_conf.arp_filter_enabled) {···24362435 directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len,24372436 ifmgd->aid);2438243724392439- if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) {24402440- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,24412441- true);24422442-24432443- ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,24442444- elems.wmm_param_len);24452445- }24462446-24472438 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {24482439 if (directed_tim) {24492440 if (local->hw.conf.dynamic_ps_timeout > 0) {···24652472 return;24662473 ifmgd->beacon_crc = ncrc;24672474 ifmgd->beacon_crc_valid = true;24752475+24762476+ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,24772477+ true);24782478+24792479+ if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,24802480+ elems.wmm_param_len))24812481+ changed |= BSS_CHANGED_QOS;2468248224692483 if (elems.erp_info && elems.erp_info_len >= 1) {24702484 erp_valid = true;···29742974/* scan finished notification */29752975void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)29762976{29772977- struct ieee80211_sub_if_data *sdata = local->scan_sdata;29772977+ struct ieee80211_sub_if_data *sdata;2978297829792979 /* Restart STA timers */29802980 rcu_read_lock();···3132313231333133 memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN);3134313431353135- /* tell driver about BSSID and basic rates */31353135+ /* set timing information */31363136+ sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;31373137+ sdata->vif.bss_conf.sync_tsf = cbss->tsf;31383138+ sdata->vif.bss_conf.sync_device_ts = bss->device_ts;31393139+31403140+ /* tell driver about BSSID, basic rates and timing */31363141 ieee80211_bss_info_change_notify(sdata,31373137- BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES);31423142+ BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |31433143+ BSS_CHANGED_BEACON_INT);3138314431393145 if (assoc)31403146 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
+7-5
net/mac80211/offchannel.c
···191191 roc->frame = NULL;192192 }193193 } else {194194- cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc,194194+ cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc,195195 roc->chan, roc->chan_type,196196 roc->req_duration, GFP_KERNEL);197197 }···299299300300 /* was never transmitted */301301 if (roc->frame) {302302- cfg80211_mgmt_tx_status(roc->sdata->dev,302302+ cfg80211_mgmt_tx_status(&roc->sdata->wdev,303303 (unsigned long)roc->frame,304304 roc->frame->data, roc->frame->len,305305 false, GFP_KERNEL);···307307 }308308309309 if (!roc->mgmt_tx_cookie)310310- cfg80211_remain_on_channel_expired(roc->sdata->dev,310310+ cfg80211_remain_on_channel_expired(&roc->sdata->wdev,311311 (unsigned long)roc,312312 roc->chan, roc->chan_type,313313 GFP_KERNEL);···324324 container_of(work, struct ieee80211_roc_work, work.work);325325 struct ieee80211_sub_if_data *sdata = roc->sdata;326326 struct ieee80211_local *local = sdata->local;327327+ bool started;327328328329 mutex_lock(&local->mtx);329330···367366 /* finish this ROC */368367 finish:369368 list_del(&roc->list);369369+ started = roc->started;370370 ieee80211_roc_notify_destroy(roc);371371372372- if (roc->started) {372372+ if (started) {373373 drv_flush(local, false);374374375375 local->tmp_channel = NULL;···381379382380 ieee80211_recalc_idle(local);383381384384- if (roc->started)382382+ if (started)385383 ieee80211_start_next_roc(local);386384 }387385
+6-2
net/mac80211/rc80211_minstrel_ht.c
···626626627627#ifdef CONFIG_MAC80211_DEBUGFS628628 /* use fixed index if set */629629- if (mp->fixed_rate_idx != -1)630630- sample_idx = mp->fixed_rate_idx;629629+ if (mp->fixed_rate_idx != -1) {630630+ mi->max_tp_rate = mp->fixed_rate_idx;631631+ mi->max_tp_rate2 = mp->fixed_rate_idx;632632+ mi->max_prob_rate = mp->fixed_rate_idx;633633+ sample_idx = -1;634634+ }631635#endif632636633637 if (sample_idx >= 0) {
+9-40
net/mac80211/rx.c
···413413414414/* rx handlers */415415416416-static ieee80211_rx_result debug_noinline417417-ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)418418-{419419- struct ieee80211_local *local = rx->local;420420- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);421421- struct sk_buff *skb = rx->skb;422422-423423- if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&424424- !local->sched_scanning))425425- return RX_CONTINUE;426426-427427- if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||428428- test_bit(SCAN_SW_SCANNING, &local->scanning) ||429429- test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||430430- local->sched_scanning)431431- return ieee80211_scan_rx(rx->sdata, skb);432432-433433- /* scanning finished during invoking of handlers */434434- I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);435435- return RX_DROP_UNUSABLE;436436-}437437-438438-439416static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb)440417{441418 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;···23812404 if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)23822405 sig = status->signal;2383240623842384- if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig,24072407+ if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,23852408 rx->skb->data, rx->skb->len,23862409 GFP_ATOMIC)) {23872410 if (rx->sta)···26722695 goto rxh_next; \26732696 } while (0);2674269726752675- CALL_RXH(ieee80211_rx_h_passive_scan)26762698 CALL_RXH(ieee80211_rx_h_check)2677269926782700 ieee80211_rx_reorder_ampdu(rx);···27412765 return 0;27422766 if (ieee80211_is_beacon(hdr->frame_control)) {27432767 return 1;27442744- }27452745- else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {27462746- if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))27472747- return 0;27482748- status->rx_flags &= ~IEEE80211_RX_RA_MATCH;27682768+ } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {27692769+ return 0;27492770 } else if (!multicast &&27502771 !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {27512772 if (!(sdata->dev->flags & IFF_PROMISC))···27802807 * and location updates. Note that mac8021127812808 * itself never looks at these frames.27822809 */27832783- if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&27842784- ieee80211_is_public_action(hdr, skb->len))28102810+ if (ieee80211_is_public_action(hdr, skb->len))27852811 return 1;27862786- if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&27872787- !ieee80211_is_beacon(hdr->frame_control))28122812+ if (!ieee80211_is_beacon(hdr->frame_control))27882813 return 0;27892814 status->rx_flags &= ~IEEE80211_RX_RA_MATCH;27902815 }···28482877static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,28492878 struct sk_buff *skb)28502879{28512851- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);28522880 struct ieee80211_local *local = hw_to_local(hw);28532881 struct ieee80211_sub_if_data *sdata;28542882 struct ieee80211_hdr *hdr;···28652895 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))28662896 local->dot11ReceivedFragmentCount++;2867289728682868- if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||28692869- test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||28702870- test_bit(SCAN_SW_SCANNING, &local->scanning)))28712871- status->rx_flags |= IEEE80211_RX_IN_SCAN;28722872-28732898 if (ieee80211_is_mgmt(fc))28742899 err = skb_linearize(skb);28752900 else···28782913 hdr = (struct ieee80211_hdr *)skb->data;28792914 ieee80211_parse_qos(&rx);28802915 ieee80211_verify_alignment(&rx);29162916+29172917+ if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||29182918+ ieee80211_is_beacon(hdr->frame_control)))29192919+ ieee80211_scan_rx(local, skb);2881292028822921 if (ieee80211_is_data(fc)) {28832922 prev_sta = NULL;
+62-54
net/mac80211/scan.c
···83838484 cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,8585 mgmt, len, signal, GFP_ATOMIC);8686-8786 if (!cbss)8887 return NULL;89889089 cbss->free_priv = ieee80211_rx_bss_free;9190 bss = (void *)cbss->priv;9191+9292+ bss->device_ts = rx_status->device_timestamp;92939394 if (elems->parse_error) {9495 if (beacon)···165164 return bss;166165}167166168168-ieee80211_rx_result169169-ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)167167+void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)170168{171169 struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);172172- struct ieee80211_mgmt *mgmt;170170+ struct ieee80211_sub_if_data *sdata1, *sdata2;171171+ struct ieee80211_mgmt *mgmt = (void *)skb->data;173172 struct ieee80211_bss *bss;174173 u8 *elements;175174 struct ieee80211_channel *channel;176175 size_t baselen;177176 int freq;178178- __le16 fc;179179- bool presp, beacon = false;177177+ bool beacon;180178 struct ieee802_11_elems elems;181179182182- if (skb->len < 2)183183- return RX_DROP_UNUSABLE;180180+ if (skb->len < 24 ||181181+ (!ieee80211_is_probe_resp(mgmt->frame_control) &&182182+ !ieee80211_is_beacon(mgmt->frame_control)))183183+ return;184184185185- mgmt = (struct ieee80211_mgmt *) skb->data;186186- fc = mgmt->frame_control;185185+ sdata1 = rcu_dereference(local->scan_sdata);186186+ sdata2 = rcu_dereference(local->sched_scan_sdata);187187188188- if (ieee80211_is_ctl(fc))189189- return RX_CONTINUE;188188+ if (likely(!sdata1 && !sdata2))189189+ return;190190191191- if (skb->len < 24)192192- return RX_CONTINUE;193193-194194- presp = ieee80211_is_probe_resp(fc);195195- if (presp) {191191+ if (ieee80211_is_probe_resp(mgmt->frame_control)) {196192 /* ignore ProbeResp to foreign address */197197- if (!ether_addr_equal(mgmt->da, sdata->vif.addr))198198- return RX_DROP_MONITOR;193193+ if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) &&194194+ (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))195195+ return;199196200200- presp = true;201197 elements = mgmt->u.probe_resp.variable;202198 baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);199199+ beacon = false;203200 } else {204204- beacon = ieee80211_is_beacon(fc);205201 baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);206202 elements = mgmt->u.beacon.variable;203203+ beacon = true;207204 }208205209209- if (!presp && !beacon)210210- return RX_CONTINUE;211211-212206 if (baselen > skb->len)213213- return RX_DROP_MONITOR;207207+ return;214208215209 ieee802_11_parse_elems(elements, skb->len - baselen, &elems);216210···215219 else216220 freq = rx_status->freq;217221218218- channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq);222222+ channel = ieee80211_get_channel(local->hw.wiphy, freq);219223220224 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)221221- return RX_DROP_MONITOR;225225+ return;222226223223- bss = ieee80211_bss_info_update(sdata->local, rx_status,227227+ bss = ieee80211_bss_info_update(local, rx_status,224228 mgmt, skb->len, &elems,225229 channel, beacon);226230 if (bss)227227- ieee80211_rx_bss_put(sdata->local, bss);228228-229229- if (channel == sdata->local->oper_channel)230230- return RX_CONTINUE;231231-232232- dev_kfree_skb(skb);233233- return RX_QUEUED;231231+ ieee80211_rx_bss_put(local, bss);234232}235233236234/* return false if no more work */···282292 return;283293284294 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {285285- int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);295295+ int rc;296296+297297+ rc = drv_hw_scan(local,298298+ rcu_dereference_protected(local->scan_sdata,299299+ lockdep_is_held(&local->mtx)),300300+ local->hw_scan_req);301301+286302 if (rc == 0)287303 return;288304 }···389393 if (!local->scan_req || local->scanning)390394 return;391395392392- if (!ieee80211_can_scan(local, local->scan_sdata))396396+ if (!ieee80211_can_scan(local,397397+ rcu_dereference_protected(398398+ local->scan_sdata,399399+ lockdep_is_held(&local->mtx))))393400 return;394401395402 ieee80211_queue_delayed_work(&local->hw, &local->scan_work,···403404 unsigned long *next_delay)404405{405406 int i;406406- struct ieee80211_sub_if_data *sdata = local->scan_sdata;407407+ struct ieee80211_sub_if_data *sdata;407408 enum ieee80211_band band = local->hw.conf.channel->band;409409+410410+ sdata = rcu_dereference_protected(local->scan_sdata,411411+ lockdep_is_held(&local->mtx));;408412409413 for (i = 0; i < local->scan_req->n_ssids; i++)410414 ieee80211_send_probe_req(···440438 if (!ieee80211_can_scan(local, sdata)) {441439 /* wait for the work to finish/time out */442440 local->scan_req = req;443443- local->scan_sdata = sdata;441441+ rcu_assign_pointer(local->scan_sdata, sdata);444442 return 0;445443 }446444···474472 }475473476474 local->scan_req = req;477477- local->scan_sdata = sdata;475475+ rcu_assign_pointer(local->scan_sdata, sdata);478476479477 if (local->ops->hw_scan) {480478 __set_bit(SCAN_HW_SCANNING, &local->scanning);···534532 ieee80211_recalc_idle(local);535533536534 local->scan_req = NULL;537537- local->scan_sdata = NULL;535535+ rcu_assign_pointer(local->scan_sdata, NULL);538536 }539537540538 return rc;···721719722720 mutex_lock(&local->mtx);723721724724- sdata = local->scan_sdata;722722+ sdata = rcu_dereference_protected(local->scan_sdata,723723+ lockdep_is_held(&local->mtx));725724726725 /* When scanning on-channel, the first-callback means completed. */727726 if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {···743740 int rc;744741745742 local->scan_req = NULL;746746- local->scan_sdata = NULL;743743+ rcu_assign_pointer(local->scan_sdata, NULL);747744748745 rc = __ieee80211_start_scan(sdata, req);749746 if (rc) {···895892896893 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {897894 if (local->ops->cancel_hw_scan)898898- drv_cancel_hw_scan(local, local->scan_sdata);895895+ drv_cancel_hw_scan(local,896896+ rcu_dereference_protected(local->scan_sdata,897897+ lockdep_is_held(&local->mtx)));899898 goto out;900899 }901900···919914 struct ieee80211_local *local = sdata->local;920915 int ret, i;921916922922- mutex_lock(&sdata->local->mtx);917917+ mutex_lock(&local->mtx);923918924924- if (local->sched_scanning) {919919+ if (rcu_access_pointer(local->sched_scan_sdata)) {925920 ret = -EBUSY;926921 goto out;927922 }···932927 }933928934929 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {930930+ if (!local->hw.wiphy->bands[i])931931+ continue;932932+935933 local->sched_scan_ies.ie[i] = kzalloc(2 +936934 IEEE80211_MAX_SSID_LEN +937935 local->scan_ies_len +···955947 ret = drv_sched_scan_start(local, sdata, req,956948 &local->sched_scan_ies);957949 if (ret == 0) {958958- local->sched_scanning = true;950950+ rcu_assign_pointer(local->sched_scan_sdata, sdata);959951 goto out;960952 }961953···963955 while (i > 0)964956 kfree(local->sched_scan_ies.ie[--i]);965957out:966966- mutex_unlock(&sdata->local->mtx);958958+ mutex_unlock(&local->mtx);967959 return ret;968960}969961···972964 struct ieee80211_local *local = sdata->local;973965 int ret = 0, i;974966975975- mutex_lock(&sdata->local->mtx);967967+ mutex_lock(&local->mtx);976968977969 if (!local->ops->sched_scan_stop) {978970 ret = -ENOTSUPP;979971 goto out;980972 }981973982982- if (local->sched_scanning) {974974+ if (rcu_access_pointer(local->sched_scan_sdata)) {983975 for (i = 0; i < IEEE80211_NUM_BANDS; i++)984976 kfree(local->sched_scan_ies.ie[i]);985977986978 drv_sched_scan_stop(local, sdata);987987- local->sched_scanning = false;979979+ rcu_assign_pointer(local->sched_scan_sdata, NULL);988980 }989981out:990990- mutex_unlock(&sdata->local->mtx);982982+ mutex_unlock(&local->mtx);991983992984 return ret;993985}···1011100310121004 mutex_lock(&local->mtx);1013100510141014- if (!local->sched_scanning) {10061006+ if (!rcu_access_pointer(local->sched_scan_sdata)) {10151007 mutex_unlock(&local->mtx);10161008 return;10171009 }···10191011 for (i = 0; i < IEEE80211_NUM_BANDS; i++)10201012 kfree(local->sched_scan_ies.ie[i]);1021101310221022- local->sched_scanning = false;10141014+ rcu_assign_pointer(local->sched_scan_sdata, NULL);1023101510241016 mutex_unlock(&local->mtx);10251017
+7-2
net/mac80211/status.c
···519519 u64 cookie = (unsigned long)skb;520520 acked = info->flags & IEEE80211_TX_STAT_ACK;521521522522+ /*523523+ * TODO: When we have non-netdev frame TX,524524+ * we cannot use skb->dev->ieee80211_ptr525525+ */526526+522527 if (ieee80211_is_nullfunc(hdr->frame_control) ||523528 ieee80211_is_qos_nullfunc(hdr->frame_control))524529 cfg80211_probe_status(skb->dev, hdr->addr1,525530 cookie, acked, GFP_ATOMIC);526531 else527532 cfg80211_mgmt_tx_status(528528- skb->dev, cookie, skb->data, skb->len,529529- acked, GFP_ATOMIC);533533+ skb->dev->ieee80211_ptr, cookie, skb->data,534534+ skb->len, acked, GFP_ATOMIC);530535 }531536532537 if (unlikely(info->ack_frame_id)) {
···74747575 If unsure, say N.76767777+config CFG80211_CERTIFICATION_ONUS7878+ bool "cfg80211 certification onus"7979+ depends on CFG80211 && EXPERT8080+ default n8181+ ---help---8282+ You should disable this option unless you are both capable8383+ and willing to ensure your system will remain regulatory8484+ compliant with the features available under this option.8585+ Some options may still be under heavy development and8686+ for whatever reason regulatory compliance has not or8787+ cannot yet be verified. Regulatory verification may at8888+ times only be possible until you have the final system8989+ in place.9090+9191+ This option should only be enabled by system integrators9292+ or distributions that have done work necessary to ensure9393+ regulatory certification on the system with the enabled9494+ features. Alternatively you can enable this option if9595+ you are a wireless researcher and are working in a controlled9696+ and approved environment by your local regulatory agency.9797+7798config CFG80211_DEFAULT_PS7899 bool "enable powersave by default"79100 depends on CFG80211
+11-13
net/wireless/chan.c
···8282 int freq, enum nl80211_channel_type chantype)8383{8484 struct ieee80211_channel *chan;8585- int err;86858786 if (!rdev->ops->set_monitor_channel)8887 return -EOPNOTSUPP;···9293 if (!chan)9394 return -EINVAL;94959595- err = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);9696- if (!err) {9797- rdev->monitor_channel = chan;9898- rdev->monitor_channel_type = chantype;9999- }100100-101101- return err;9696+ return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);10297}1039810499void105105-cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,106106- struct wireless_dev *wdev,100100+cfg80211_get_chan_state(struct wireless_dev *wdev,107101 struct ieee80211_channel **chan,108102 enum cfg80211_chan_mode *chanmode)109103{110104 *chan = NULL;111105 *chanmode = CHAN_MODE_UNDEFINED;112106113113- ASSERT_RDEV_LOCK(rdev);114107 ASSERT_WDEV_LOCK(wdev);115108116109 if (!netif_running(wdev->netdev))···127136 break;128137 case NL80211_IFTYPE_AP:129138 case NL80211_IFTYPE_P2P_GO:139139+ if (wdev->beacon_interval) {140140+ *chan = wdev->channel;141141+ *chanmode = CHAN_MODE_SHARED;142142+ }143143+ return;130144 case NL80211_IFTYPE_MESH_POINT:131131- *chan = wdev->channel;132132- *chanmode = CHAN_MODE_SHARED;145145+ if (wdev->mesh_id_len) {146146+ *chan = wdev->channel;147147+ *chanmode = CHAN_MODE_SHARED;148148+ }133149 return;134150 case NL80211_IFTYPE_MONITOR:135151 case NL80211_IFTYPE_AP_VLAN:
+21-58
net/wireless/core.c
···176176 if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))177177 return -EOPNOTSUPP;178178179179- list_for_each_entry(wdev, &rdev->netdev_list, list) {179179+ list_for_each_entry(wdev, &rdev->wdev_list, list) {180180+ if (!wdev->netdev)181181+ continue;180182 wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;181183 err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");182184 if (err)···190188 /* failed -- clean up to old netns */191189 net = wiphy_net(&rdev->wiphy);192190193193- list_for_each_entry_continue_reverse(wdev, &rdev->netdev_list,191191+ list_for_each_entry_continue_reverse(wdev, &rdev->wdev_list,194192 list) {193193+ if (!wdev->netdev)194194+ continue;195195 wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;196196 err = dev_change_net_namespace(wdev->netdev, net,197197 "wlan%d");···230226 rtnl_lock();231227 mutex_lock(&rdev->devlist_mtx);232228233233- list_for_each_entry(wdev, &rdev->netdev_list, list)234234- dev_close(wdev->netdev);229229+ list_for_each_entry(wdev, &rdev->wdev_list, list)230230+ if (wdev->netdev)231231+ dev_close(wdev->netdev);235232236233 mutex_unlock(&rdev->devlist_mtx);237234 rtnl_unlock();···309304 mutex_init(&rdev->mtx);310305 mutex_init(&rdev->devlist_mtx);311306 mutex_init(&rdev->sched_scan_mtx);312312- INIT_LIST_HEAD(&rdev->netdev_list);307307+ INIT_LIST_HEAD(&rdev->wdev_list);313308 spin_lock_init(&rdev->bss_lock);314309 INIT_LIST_HEAD(&rdev->bss_list);315310 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);···542537 }543538544539 /* set up regulatory info */545545- regulatory_update(wiphy, NL80211_REGDOM_SET_BY_CORE);540540+ wiphy_regulatory_register(wiphy);546541547542 list_add_rcu(&rdev->list, &cfg80211_rdev_list);548543 cfg80211_rdev_list_generation++;···627622 __count == 0; }));628623629624 mutex_lock(&rdev->devlist_mtx);630630- BUG_ON(!list_empty(&rdev->netdev_list));625625+ BUG_ON(!list_empty(&rdev->wdev_list));631626 mutex_unlock(&rdev->devlist_mtx);632627633628 /*···652647 /* nothing */653648 cfg80211_unlock_rdev(rdev);654649655655- /* If this device got a regulatory hint tell core its656656- * free to listen now to a new shiny device regulatory hint */657657- reg_device_remove(wiphy);650650+ /*651651+ * If this device got a regulatory hint tell core its652652+ * free to listen now to a new shiny device regulatory hint653653+ */654654+ wiphy_regulatory_deregister(wiphy);658655659656 cfg80211_rdev_list_generation++;660657 device_del(&rdev->wiphy.dev);···710703711704 cfg80211_lock_rdev(rdev);712705713713- if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == wdev->netdev)) {706706+ if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {714707 rdev->scan_req->aborted = true;715708 ___cfg80211_scan_done(rdev, true);716709 }···738731 .name = "wlan",739732};740733741741-static struct ieee80211_channel *742742-cfg80211_get_any_chan(struct cfg80211_registered_device *rdev)743743-{744744- struct ieee80211_supported_band *sband;745745- int i;746746-747747- for (i = 0; i < IEEE80211_NUM_BANDS; i++) {748748- sband = rdev->wiphy.bands[i];749749- if (sband && sband->n_channels > 0)750750- return &sband->channels[0];751751- }752752-753753- return NULL;754754-}755755-756756-static void cfg80211_init_mon_chan(struct cfg80211_registered_device *rdev)757757-{758758- struct ieee80211_channel *chan;759759-760760- chan = cfg80211_get_any_chan(rdev);761761- if (WARN_ON(!chan))762762- return;763763-764764- mutex_lock(&rdev->devlist_mtx);765765- WARN_ON(cfg80211_set_monitor_channel(rdev, chan->center_freq,766766- NL80211_CHAN_NO_HT));767767- mutex_unlock(&rdev->devlist_mtx);768768-}769769-770734void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,771735 enum nl80211_iftype iftype, int num)772736{773773- bool has_monitors_only_old = cfg80211_has_monitors_only(rdev);774774- bool has_monitors_only_new;775775-776737 ASSERT_RTNL();777738778739 rdev->num_running_ifaces += num;779740 if (iftype == NL80211_IFTYPE_MONITOR)780741 rdev->num_running_monitor_ifaces += num;781781-782782- has_monitors_only_new = cfg80211_has_monitors_only(rdev);783783- if (has_monitors_only_new != has_monitors_only_old) {784784- rdev->ops->set_monitor_enabled(&rdev->wiphy,785785- has_monitors_only_new);786786-787787- if (!has_monitors_only_new) {788788- rdev->monitor_channel = NULL;789789- rdev->monitor_channel_type = NL80211_CHAN_NO_HT;790790- } else {791791- cfg80211_init_mon_chan(rdev);792792- }793793- }794742}795743796744static int cfg80211_netdev_notifier_call(struct notifier_block *nb,···782820 spin_lock_init(&wdev->mgmt_registrations_lock);783821784822 mutex_lock(&rdev->devlist_mtx);785785- list_add_rcu(&wdev->list, &rdev->netdev_list);823823+ wdev->identifier = ++rdev->wdev_id;824824+ list_add_rcu(&wdev->list, &rdev->wdev_list);786825 rdev->devlist_generation++;787826 /* can only change netns with wiphy */788827 dev->features |= NETIF_F_NETNS_LOCAL;···868905 mutex_unlock(&rdev->devlist_mtx);869906 dev_put(dev);870907 }908908+ cfg80211_update_iface_num(rdev, wdev->iftype, 1);871909 cfg80211_lock_rdev(rdev);872910 mutex_lock(&rdev->devlist_mtx);873911 wdev_lock(wdev);···963999 mutex_unlock(&rdev->devlist_mtx);9641000 if (ret)9651001 return notifier_from_errno(ret);966966- cfg80211_update_iface_num(rdev, wdev->iftype, 1);9671002 break;9681003 }9691004
+5-9
net/wireless/core.h
···4747 /* wiphy index, internal only */4848 int wiphy_idx;49495050- /* associate netdev list */5050+ /* associated wireless interfaces */5151 struct mutex devlist_mtx;5252 /* protected by devlist_mtx or RCU */5353- struct list_head netdev_list;5454- int devlist_generation;5353+ struct list_head wdev_list;5454+ int devlist_generation, wdev_id;5555 int opencount; /* also protected by devlist_mtx */5656 wait_queue_head_t dev_wait;5757···6060 /* protected by RTNL only */6161 int num_running_ifaces;6262 int num_running_monitor_ifaces;6363-6464- struct ieee80211_channel *monitor_channel;6565- enum nl80211_channel_type monitor_channel_type;66636764 /* BSSes/scanning */6865 spinlock_t bss_lock;···369372void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);370373void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);371374int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,372372- struct net_device *dev,375375+ struct wireless_dev *wdev,373376 struct ieee80211_channel *chan, bool offchan,374377 enum nl80211_channel_type channel_type,375378 bool channel_type_valid, unsigned int wait,···460463}461464462465void463463-cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,464464- struct wireless_dev *wdev,466466+cfg80211_get_chan_state(struct wireless_dev *wdev,465467 struct ieee80211_channel **chan,466468 enum cfg80211_chan_mode *chanmode);467469
···793793794794 mutex_lock(&rdev->devlist_mtx);795795796796- list_for_each_entry(wdev, &rdev->netdev_list, list)796796+ list_for_each_entry(wdev, &rdev->wdev_list, list)797797 cfg80211_process_wdev_events(wdev);798798799799 mutex_unlock(&rdev->devlist_mtx);···994994995995 mutex_lock(&rdev->devlist_mtx);996996997997- list_for_each_entry(wdev, &rdev->netdev_list, list) {997997+ list_for_each_entry(wdev, &rdev->wdev_list, list) {998998 if (!wdev->beacon_interval)999999 continue;10001000 if (wdev->beacon_interval != beacon_int) {···10501050 break;10511051 }1052105210531053- list_for_each_entry(wdev_iter, &rdev->netdev_list, list) {10531053+ list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {10541054 if (wdev_iter == wdev)10551055 continue;10561056 if (!netif_running(wdev_iter->netdev))···10591059 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))10601060 continue;1061106110621062- cfg80211_get_chan_state(rdev, wdev_iter, &ch, &chmode);10621062+ /*10631063+ * We may be holding the "wdev" mutex, but now need to lock10641064+ * wdev_iter. This is OK because once we get here wdev_iter10651065+ * is not wdev (tested above), but we need to use the nested10661066+ * locking for lockdep.10671067+ */10681068+ mutex_lock_nested(&wdev_iter->mtx, 1);10691069+ __acquire(wdev_iter->mtx);10701070+ cfg80211_get_chan_state(wdev_iter, &ch, &chmode);10711071+ wdev_unlock(wdev_iter);1063107210641073 switch (chmode) {10651074 case CHAN_MODE_UNDEFINED:
+7-2
net/wireless/wext-compat.c
···827827{828828 struct wireless_dev *wdev = dev->ieee80211_ptr;829829 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);830830+ struct ieee80211_channel *chan;831831+ enum nl80211_channel_type channel_type;830832831833 switch (wdev->iftype) {832834 case NL80211_IFTYPE_STATION:···836834 case NL80211_IFTYPE_ADHOC:837835 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);838836 case NL80211_IFTYPE_MONITOR:839839- if (!rdev->monitor_channel)837837+ if (!rdev->ops->get_channel)840838 return -EINVAL;841839842842- freq->m = rdev->monitor_channel->center_freq;840840+ chan = rdev->ops->get_channel(wdev->wiphy, wdev, &channel_type);841841+ if (!chan)842842+ return -EINVAL;843843+ freq->m = chan->center_freq;843844 freq->e = 6;844845 return 0;845846 default: