···11+Linux NFC subsystem22+===================33+44+The Near Field Communication (NFC) subsystem is required to standardize the55+NFC device drivers development and to create an unified userspace interface.66+77+This document covers the architecture overview, the device driver interface88+description and the userspace interface description.99+1010+Architecture overview1111+---------------------1212+1313+The NFC subsystem is responsible for:1414+ - NFC adapters management;1515+ - Polling for targets;1616+ - Low-level data exchange;1717+1818+The subsystem is divided in some parts. The 'core' is responsible for1919+providing the device driver interface. On the other side, it is also2020+responsible for providing an interface to control operations and low-level2121+data exchange.2222+2323+The control operations are available to userspace via generic netlink.2424+2525+The low-level data exchange interface is provided by the new socket family2626+PF_NFC. The NFC_SOCKPROTO_RAW performs raw communication with NFC targets.2727+2828+2929+ +--------------------------------------+3030+ | USER SPACE |3131+ +--------------------------------------+3232+ ^ ^3333+ | low-level | control3434+ | data exchange | operations3535+ | |3636+ | v3737+ | +-----------+3838+ | AF_NFC | netlink |3939+ | socket +-----------+4040+ | raw ^4141+ | |4242+ v v4343+ +---------+ +-----------+4444+ | rawsock | <--------> | core |4545+ +---------+ +-----------+4646+ ^4747+ |4848+ v4949+ +-----------+5050+ | driver |5151+ +-----------+5252+5353+Device Driver Interface5454+-----------------------5555+5656+When registering on the NFC subsystem, the device driver must inform the core5757+of the set of supported NFC protocols and the set of ops callbacks. The ops5858+callbacks that must be implemented are the following:5959+6060+* start_poll - setup the device to poll for targets6161+* stop_poll - stop on progress polling operation6262+* activate_target - select and initialize one of the targets found6363+* deactivate_target - deselect and deinitialize the selected target6464+* data_exchange - send data and receive the response (transceive operation)6565+6666+Userspace interface6767+--------------------6868+6969+The userspace interface is divided in control operations and low-level data7070+exchange operation.7171+7272+CONTROL OPERATIONS:7373+7474+Generic netlink is used to implement the interface to the control operations.7575+The operations are composed by commands and events, all listed below:7676+7777+* NFC_CMD_GET_DEVICE - get specific device info or dump the device list7878+* NFC_CMD_START_POLL - setup a specific device to polling for targets7979+* NFC_CMD_STOP_POLL - stop the polling operation in a specific device8080+* NFC_CMD_GET_TARGET - dump the list of targets found by a specific device8181+8282+* NFC_EVENT_DEVICE_ADDED - reports an NFC device addition8383+* NFC_EVENT_DEVICE_REMOVED - reports an NFC device removal8484+* NFC_EVENT_TARGETS_FOUND - reports START_POLL results when 1 or more targets8585+are found8686+8787+The user must call START_POLL to poll for NFC targets, passing the desired NFC8888+protocols through NFC_ATTR_PROTOCOLS attribute. The device remains in polling8989+state until it finds any target. However, the user can stop the polling9090+operation by calling STOP_POLL command. In this case, it will be checked if9191+the requester of STOP_POLL is the same of START_POLL.9292+9393+If the polling operation finds one or more targets, the event TARGETS_FOUND is9494+sent (including the device id). The user must call GET_TARGET to get the list of9595+all targets found by such device. Each reply message has target attributes with9696+relevant information such as the supported NFC protocols.9797+9898+All polling operations requested through one netlink socket are stopped when9999+it's closed.100100+101101+LOW-LEVEL DATA EXCHANGE:102102+103103+The userspace must use PF_NFC sockets to perform any data communication with104104+targets. All NFC sockets use AF_NFC:105105+106106+struct sockaddr_nfc {107107+ sa_family_t sa_family;108108+ __u32 dev_idx;109109+ __u32 target_idx;110110+ __u32 nfc_protocol;111111+};112112+113113+To establish a connection with one target, the user must create an114114+NFC_SOCKPROTO_RAW socket and call the 'connect' syscall with the sockaddr_nfc115115+struct correctly filled. All information comes from NFC_EVENT_TARGETS_FOUND116116+netlink event. As a target can support more than one NFC protocol, the user117117+must inform which protocol it wants to use.118118+119119+Internally, 'connect' will result in an activate_target call to the driver.120120+When the socket is closed, the target is deactivated.121121+122122+The data format exchanged through the sockets is NFC protocol dependent. For123123+instance, when communicating with MIFARE tags, the data exchanged are MIFARE124124+commands and their responses.125125+126126+The first received package is the response to the first sent package and so127127+on. In order to allow valid "empty" responses, every data received has a NULL128128+header of 1 byte.
···2727 bool "Support for BCMA on PCI-host bus"2828 depends on BCMA_HOST_PCI_POSSIBLE29293030+config BCMA_DRIVER_PCI_HOSTMODE3131+ bool "Driver for PCI core working in hostmode"3232+ depends on BCMA && MIPS3333+ help3434+ PCI core hostmode operation (external PCI bus).3535+3036config BCMA_DEBUG3137 bool "BCMA debugging"3238 depends on BCMA
···157157 * Init.158158 **************************************************/159159160160-void bcma_core_pci_init(struct bcma_drv_pci *pc)160160+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)161161{162162 bcma_pcicore_serdes_workaround(pc);163163+}164164+165165+static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)166166+{167167+ struct bcma_bus *bus = pc->core->bus;168168+ u16 chipid_top;169169+170170+ chipid_top = (bus->chipinfo.id & 0xFF00);171171+ if (chipid_top != 0x4700 &&172172+ chipid_top != 0x5300)173173+ return false;174174+175175+ if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)176176+ return false;177177+178178+#if 0179179+ /* TODO: on BCMA we use address from EROM instead of magic formula */180180+ u32 tmp;181181+ return !mips_busprobe32(tmp, (bus->mmio +182182+ (pc->core->core_index * BCMA_CORE_SIZE)));183183+#endif184184+185185+ return true;186186+}187187+188188+void bcma_core_pci_init(struct bcma_drv_pci *pc)189189+{190190+ if (bcma_core_pci_is_in_hostmode(pc)) {191191+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE192192+ bcma_core_pci_hostmode_init(pc);193193+#else194194+ pr_err("Driver compiled without support for hostmode PCI\n");195195+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */196196+ } else {197197+ bcma_core_pci_clientmode_init(pc);198198+ }163199}164200165201int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
+14
drivers/bcma/driver_pci_host.c
···11+/*22+ * Broadcom specific AMBA33+ * PCI Core in hostmode44+ *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 bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)1212+{1313+ pr_err("No support for PCI core in hostmode yet\n");1414+}
···44 * RX/TX meta descriptor format55 *66 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>77- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>77+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>88 *99 * This program is free software; you can redistribute it and/or modify1010 * it under the terms of the GNU General Public License as published by···278278struct carl9170_tx_superframe {279279 struct carl9170_tx_superdesc s;280280 struct ar9170_tx_frame f;281281-} __packed;281281+} __packed __aligned(4);282282283283#endif /* __CARL9170FW__ */284284···328328 struct _carl9170_tx_superdesc s;329329 struct _ar9170_tx_hwdesc f;330330 u8 frame_data[0];331331-} __packed;331331+} __packed __aligned(4);332332333333#define CARL9170_TX_SUPERDESC_LEN 24334334#define AR9170_TX_HWDESC_LEN 8···404404 (t->DAidx & 0xc0) >> 6;405405}406406407407-enum ar9170_txq {408408- AR9170_TXQ_BE,409409-410410- AR9170_TXQ_VI,411411- AR9170_TXQ_VO,412412- AR9170_TXQ_BK,413413-414414- __AR9170_NUM_TXQ,415415-};416416-417407/*418408 * This is an workaround for several undocumented bugs.419409 * Don't mess with the QoS/AC <-> HW Queue map, if you don't···421431 * result, this makes the device pretty much useless422432 * for any serious 802.11n setup.423433 */424424-static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };434434+enum ar9170_txq {435435+ AR9170_TXQ_BK = 0, /* TXQ0 */436436+ AR9170_TXQ_BE, /* TXQ1 */437437+ AR9170_TXQ_VI, /* TXQ2 */438438+ AR9170_TXQ_VO, /* TXQ3 */439439+440440+ __AR9170_NUM_TXQ,441441+};425442426443#define AR9170_TXQ_DEPTH 32427444
···628628 /* the rest are 0 by default */629629};630630631631-void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)632632-{633633- unsigned long flags;634634- int i;635635- spin_lock_irqsave(&rxq->lock, flags);636636- INIT_LIST_HEAD(&rxq->rx_free);637637- INIT_LIST_HEAD(&rxq->rx_used);638638- /* Fill the rx_used queue with _all_ of the Rx buffers */639639- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {640640- /* In the reset function, these buffers may have been allocated641641- * to an SKB, so we need to unmap and free potential storage */642642- if (rxq->pool[i].page != NULL) {643643- dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,644644- PAGE_SIZE << priv->hw_params.rx_page_order,645645- DMA_FROM_DEVICE);646646- __iwl_free_pages(priv, rxq->pool[i].page);647647- rxq->pool[i].page = NULL;648648- }649649- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);650650- }651651-652652- for (i = 0; i < RX_QUEUE_SIZE; i++)653653- rxq->queue[i] = NULL;654654-655655- /* Set us so that we have processed and used all buffers, but have656656- * not restocked the Rx queue with fresh buffers */657657- rxq->read = rxq->write = 0;658658- rxq->write_actual = 0;659659- rxq->free_count = 0;660660- spin_unlock_irqrestore(&rxq->lock, flags);661661-}662662-663631int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)664632{665633 u32 rb_size;···699731{700732 unsigned long flags;701733 struct iwl_rx_queue *rxq = &priv->rxq;702702- int ret;703734704735 /* nic_init */705736 spin_lock_irqsave(&priv->lock, flags);···714747 priv->cfg->ops->lib->apm_ops.config(priv);715748716749 /* Allocate the RX queue, or reset if it is already allocated */717717- if (!rxq->bd) {718718- ret = iwl_rx_queue_alloc(priv);719719- if (ret) {720720- IWL_ERR(priv, "Unable to initialize Rx queue\n");721721- return -ENOMEM;722722- }723723- } else724724- iwlagn_rx_queue_reset(priv, rxq);750750+ priv->trans.ops->rx_init(priv);725751726752 iwlagn_rx_replenish(priv);727753···728768 spin_unlock_irqrestore(&priv->lock, flags);729769730770 /* Allocate or reset and init all Tx and Command queues */731731- if (!priv->txq) {732732- ret = iwlagn_txq_ctx_alloc(priv);733733- if (ret)734734- return ret;735735- } else736736- iwlagn_txq_ctx_reset(priv);771771+ if (priv->trans.ops->tx_init(priv))772772+ return -ENOMEM;737773738774 if (priv->cfg->base_params->shadow_reg_enable) {739775 /* enable shadow regs in HW */···903947 iwlagn_rx_allocate(priv, GFP_ATOMIC);904948905949 iwlagn_rx_queue_restock(priv);906906-}907907-908908-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.909909- * If an SKB has been detached, the POOL needs to have its SKB set to NULL910910- * This free routine walks the list of POOL entries and if SKB is set to911911- * non NULL it is unmapped and freed912912- */913913-void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)914914-{915915- int i;916916- for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {917917- if (rxq->pool[i].page != NULL) {918918- dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,919919- PAGE_SIZE << priv->hw_params.rx_page_order,920920- DMA_FROM_DEVICE);921921- __iwl_free_pages(priv, rxq->pool[i].page);922922- rxq->pool[i].page = NULL;923923- }924924- }925925-926926- dma_free_coherent(priv->bus.dev, 4 * RX_QUEUE_SIZE,927927- rxq->bd, rxq->bd_dma);928928- dma_free_coherent(priv->bus.dev,929929- sizeof(struct iwl_rb_status),930930- rxq->rb_stts, rxq->rb_stts_dma);931931- rxq->bd = NULL;932932- rxq->rb_stts = NULL;933950}934951935952int iwlagn_rxq_stop(struct iwl_priv *priv)···13661437 /* set scan bit here for PAN params */13671438 set_bit(STATUS_SCAN_HW, &priv->status);1368143913691369- if (priv->cfg->ops->hcmd->set_pan_params) {13701370- ret = priv->cfg->ops->hcmd->set_pan_params(priv);13711371- if (ret)13721372- return ret;13731373- }14401440+ ret = iwlagn_set_pan_params(priv);14411441+ if (ret)14421442+ return ret;1374144313751444 ret = iwl_send_cmd_sync(priv, &cmd);13761445 if (ret) {13771446 clear_bit(STATUS_SCAN_HW, &priv->status);13781378- if (priv->cfg->ops->hcmd->set_pan_params)13791379- priv->cfg->ops->hcmd->set_pan_params(priv);14471447+ iwlagn_set_pan_params(priv);13801448 }1381144913821450 return ret;
+7-12
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
···436436 if (ret)437437 return ret;438438439439- if (priv->cfg->ops->hcmd->set_pan_params) {440440- ret = priv->cfg->ops->hcmd->set_pan_params(priv);441441- if (ret)442442- return ret;443443- }439439+ ret = iwlagn_set_pan_params(priv);440440+ if (ret)441441+ return ret;444442445443 if (new_assoc)446444 return iwlagn_rxon_connect(priv, ctx);···481483 * set up the SM PS mode to OFF if an HT channel is482484 * configured.483485 */484484- if (priv->cfg->ops->hcmd->set_rxon_chain)485485- for_each_context(priv, ctx)486486- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);486486+ for_each_context(priv, ctx)487487+ iwlagn_set_rxon_chain(priv, ctx);487488 }488489489490 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {···738741 iwl_set_rxon_ht(priv, &priv->current_ht_config);739742 }740743741741- if (priv->cfg->ops->hcmd->set_rxon_chain)742742- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);744744+ iwlagn_set_rxon_chain(priv, ctx);743745744746 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))745747 ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;···817821 if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))818822 iwlagn_commit_rxon(priv, ctx);819823820820- if (priv->cfg->ops->hcmd->set_pan_params)821821- priv->cfg->ops->hcmd->set_pan_params(priv);824824+ iwlagn_set_pan_params(priv);822825}
-90
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
···878878}879879880880/**881881- * iwlagn_txq_ctx_alloc - allocate TX queue context882882- * Allocate all Tx DMA structures and initialize them883883- *884884- * @param priv885885- * @return error code886886- */887887-int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)888888-{889889- int ret;890890- int txq_id, slots_num;891891- unsigned long flags;892892-893893- /* Free all tx/cmd queues and keep-warm buffer */894894- iwlagn_hw_txq_ctx_free(priv);895895-896896- ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls,897897- priv->hw_params.scd_bc_tbls_size);898898- if (ret) {899899- IWL_ERR(priv, "Scheduler BC Table allocation failed\n");900900- goto error_bc_tbls;901901- }902902- /* Alloc keep-warm buffer */903903- ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);904904- if (ret) {905905- IWL_ERR(priv, "Keep Warm allocation failed\n");906906- goto error_kw;907907- }908908-909909- /* allocate tx queue structure */910910- ret = iwl_alloc_txq_mem(priv);911911- if (ret)912912- goto error;913913-914914- spin_lock_irqsave(&priv->lock, flags);915915-916916- /* Turn off all Tx DMA fifos */917917- iwlagn_txq_set_sched(priv, 0);918918-919919- /* Tell NIC where to find the "keep warm" buffer */920920- iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);921921-922922- spin_unlock_irqrestore(&priv->lock, flags);923923-924924- /* Alloc and init all Tx queues, including the command queue (#4/#9) */925925- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {926926- slots_num = (txq_id == priv->cmd_queue) ?927927- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;928928- ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,929929- txq_id);930930- if (ret) {931931- IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);932932- goto error;933933- }934934- }935935-936936- return ret;937937-938938- error:939939- iwlagn_hw_txq_ctx_free(priv);940940- iwlagn_free_dma_ptr(priv, &priv->kw);941941- error_kw:942942- iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);943943- error_bc_tbls:944944- return ret;945945-}946946-947947-void iwlagn_txq_ctx_reset(struct iwl_priv *priv)948948-{949949- int txq_id, slots_num;950950- unsigned long flags;951951-952952- spin_lock_irqsave(&priv->lock, flags);953953-954954- /* Turn off all Tx DMA fifos */955955- iwlagn_txq_set_sched(priv, 0);956956-957957- /* Tell NIC where to find the "keep warm" buffer */958958- iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);959959-960960- spin_unlock_irqrestore(&priv->lock, flags);961961-962962- /* Alloc and init all Tx queues, including the command queue (#4) */963963- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {964964- slots_num = txq_id == priv->cmd_queue ?965965- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;966966- iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);967967- }968968-}969969-970970-/**971881 * iwlagn_txq_ctx_stop - Stop all Tx DMA channels972882 */973883void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
+5-3
drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
···386386 spin_lock_irqsave(&priv->lock, flags);387387388388 priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR);389389- a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET;390390- for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET;389389+ a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND;390390+ /* reset conext data memory */391391+ for (; a < priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND;391392 a += 4)392393 iwl_write_targ_mem(priv, a, 0);393393- for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET;394394+ /* reset tx status memory */395395+ for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND;394396 a += 4)395397 iwl_write_targ_mem(priv, a, 0);396398 for (; a < priv->scd_base_addr +
+25-29
drivers/net/wireless/iwlwifi/iwl-agn.c
···5656#include "iwl-agn-calib.h"5757#include "iwl-agn.h"5858#include "iwl-pci.h"5959-5959+#include "iwl-trans.h"60606161/******************************************************************************6262 *···9090{9191 struct iwl_rxon_context *ctx;92929393- if (priv->cfg->ops->hcmd->set_rxon_chain) {9494- for_each_context(priv, ctx) {9595- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);9696- if (ctx->active.rx_chain != ctx->staging.rx_chain)9797- iwlagn_commit_rxon(priv, ctx);9898- }9393+ for_each_context(priv, ctx) {9494+ iwlagn_set_rxon_chain(priv, ctx);9595+ if (ctx->active.rx_chain != ctx->staging.rx_chain)9696+ iwlagn_commit_rxon(priv, ctx);9997 }10098}10199···258260 /* dont send host command if rf-kill is on */259261 if (!iwl_is_ready_rf(priv))260262 return;261261- priv->cfg->ops->hcmd->send_bt_config(priv);263263+ iwlagn_send_advance_bt_config(priv);262264}263265264266static void iwl_bg_bt_full_concurrency(struct work_struct *work)···285287 * to avoid 3-wire collisions286288 */287289 for_each_context(priv, ctx) {288288- if (priv->cfg->ops->hcmd->set_rxon_chain)289289- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);290290+ iwlagn_set_rxon_chain(priv, ctx);290291 iwlagn_commit_rxon(priv, ctx);291292 }292293293293- priv->cfg->ops->hcmd->send_bt_config(priv);294294+ iwlagn_send_advance_bt_config(priv);294295out:295296 mutex_unlock(&priv->mutex);296297}···20142017 priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;20152018 priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;20162019 priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;20172017- priv->cfg->ops->hcmd->send_bt_config(priv);20202020+ iwlagn_send_advance_bt_config(priv);20182021 priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;20192022 iwlagn_send_prio_tbl(priv);20202023···20272030 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);20282031 if (ret)20292032 return ret;20332033+ } else {20342034+ /*20352035+ * default is 2-wire BT coexexistence support20362036+ */20372037+ iwl_send_bt_config(priv);20302038 }20392039+20312040 if (priv->hw_params.calib_rt_cfg)20322041 iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);20332042···20422039 priv->active_rate = IWL_RATES_MASK;2043204020442041 /* Configure Tx antenna selection based on H/W config */20452045- if (priv->cfg->ops->hcmd->set_tx_ant)20462046- priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);20422042+ iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);2047204320482044 if (iwl_is_associated_ctx(ctx)) {20492045 struct iwl_rxon_cmd *active_rxon =···20562054 for_each_context(priv, tmp)20572055 iwl_connection_init_rx_config(priv, tmp);2058205620592059- if (priv->cfg->ops->hcmd->set_rxon_chain)20602060- priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);20612061- }20622062-20632063- if (!priv->cfg->bt_params || (priv->cfg->bt_params &&20642064- !priv->cfg->bt_params->advanced_bt_coexist)) {20652065- /*20662066- * default is 2-wire BT coexexistence support20672067- */20682068- priv->cfg->ops->hcmd->send_bt_config(priv);20572057+ iwlagn_set_rxon_chain(priv, ctx);20692058 }2070205920712060 iwl_reset_run_time_calib(priv);···32813288 priv->rx_statistics_jiffies = jiffies;3282328932833290 /* Choose which receivers/antennas to use */32843284- if (priv->cfg->ops->hcmd->set_rxon_chain)32853285- priv->cfg->ops->hcmd->set_rxon_chain(priv,32863286- &priv->contexts[IWL_RXON_CTX_BSS]);32913291+ iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);3287329232883293 iwl_init_scan_params(priv);32893294···35083517 priv->bus.ops->set_drv_data(&priv->bus, priv);35093518 priv->bus.dev = priv->bus.ops->get_dev(&priv->bus);3510351935203520+ iwl_trans_register(&priv->trans);35213521+35113522 /* At this point both hw and priv are allocated. */3512352335133524 SET_IEEE80211_DEV(hw, priv->bus.dev);···3709371637103717 iwl_dealloc_ucode(priv);3711371837123712- if (priv->rxq.bd)37133713- iwlagn_rx_queue_free(priv, &priv->rxq);37193719+ priv->trans.ops->rx_free(priv);37143720 iwlagn_hw_txq_ctx_free(priv);3715372137163722 iwl_eeprom_free(priv);···3811381938123820module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);38133821MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");38223822+38233823+module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO);38243824+MODULE_PARM_DESC(wd_disable,38253825+ "Disable stuck queue watchdog timer (default: 0 [enabled])");3814382638153827/*38163828 * set bt_coex_active to true, uCode will do kill/defer
···168168 * the scheduler (especially for queue #4/#9, the command queue, otherwise169169 * the driver can't issue commands!):170170 */171171+#define SCD_MEM_LOWER_BOUND (0x0000)171172172173/**173174 * Max Tx window size is the max number of contiguous TFDs that the scheduler···198197#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)199198#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)200199201201-#define IWLAGN_SCD_CONTEXT_DATA_OFFSET (0x600)202202-#define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET (0x7B1)203203-#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET (0x7E0)200200+/* Context Data */201201+#define IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600)202202+#define IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)203203+204204+/* Tx status */205205+#define IWLAGN_SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0)206206+#define IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)207207+208208+/* Translation Data */209209+#define IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0)210210+#define IWLAGN_SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808)204211205212#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\206206- (IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))213213+ (IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))207214208215#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \209209- ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)216216+ ((IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)210217211218#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \212219 (((1<<(priv)->hw_params.max_txq_num) - 1) &\
+3-44
drivers/net/wireless/iwlwifi/iwl-rx.c
···134134void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)135135{136136 unsigned long flags;137137- u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;138137 u32 reg;139138140139 spin_lock_irqsave(&q->lock, flags);···145146 /* shadow register enabled */146147 /* Device expects a multiple of 8 */147148 q->write_actual = (q->write & ~0x7);148148- iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual);149149+ iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual);149150 } else {150151 /* If power-saving is in use, make sure device is awake */151152 if (test_bit(STATUS_POWER_PMI, &priv->status)) {···161162 }162163163164 q->write_actual = (q->write & ~0x7);164164- iwl_write_direct32(priv, rx_wrt_ptr_reg,165165+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,165166 q->write_actual);166167167168 /* Else device is assumed to be awake */168169 } else {169170 /* Device expects a multiple of 8 */170171 q->write_actual = (q->write & ~0x7);171171- iwl_write_direct32(priv, rx_wrt_ptr_reg,172172+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,172173 q->write_actual);173174 }174175 }···176177177178 exit_unlock:178179 spin_unlock_irqrestore(&q->lock, flags);179179-}180180-181181-int iwl_rx_queue_alloc(struct iwl_priv *priv)182182-{183183- struct iwl_rx_queue *rxq = &priv->rxq;184184- struct device *dev = priv->bus.dev;185185- int i;186186-187187- spin_lock_init(&rxq->lock);188188- INIT_LIST_HEAD(&rxq->rx_free);189189- INIT_LIST_HEAD(&rxq->rx_used);190190-191191- /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */192192- rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,193193- GFP_KERNEL);194194- if (!rxq->bd)195195- goto err_bd;196196-197197- rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),198198- &rxq->rb_stts_dma, GFP_KERNEL);199199- if (!rxq->rb_stts)200200- goto err_rb;201201-202202- /* Fill the rx_used queue with _all_ of the Rx buffers */203203- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)204204- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);205205-206206- /* Set us so that we have processed and used all buffers, but have207207- * not restocked the Rx queue with fresh buffers */208208- rxq->read = rxq->write = 0;209209- rxq->write_actual = 0;210210- rxq->free_count = 0;211211- rxq->need_update = 0;212212- return 0;213213-214214-err_rb:215215- dma_free_coherent(dev, 4 * RX_QUEUE_SIZE, rxq->bd,216216- rxq->bd_dma);217217-err_bd:218218- return -ENOMEM;219180}220181221182/******************************************************************************
+132-104
drivers/net/wireless/iwlwifi/iwl-testmode.h
···6666#include <linux/types.h>676768686969-/* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and6969+/*7070+ * Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and7071 * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX).7171- * The command ID is carried with IWL_TM_ATTR_COMMAND. There are three types of7272- * of command from user space and two types of command from kernel space.7373- * See below.7272+ * The command ID is carried with IWL_TM_ATTR_COMMAND.7373+ *7474+ * @IWL_TM_CMD_APP2DEV_UCODE:7575+ * commands from user application to the uCode,7676+ * the actual uCode host command ID is carried with7777+ * IWL_TM_ATTR_UCODE_CMD_ID7878+ *7979+ * @IWL_TM_CMD_APP2DEV_REG_READ32:8080+ * @IWL_TM_CMD_APP2DEV_REG_WRITE32:8181+ * @IWL_TM_CMD_APP2DEV_REG_WRITE8:8282+ * commands from user applicaiton to access register8383+ *8484+ * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name8585+ * @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image8686+ * @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration8787+ * @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image8888+ * @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data8989+ * @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS9090+ * commands fom user space for pure driver level operations9191+ *9292+ * @IWL_TM_CMD_APP2DEV_BEGIN_TRACE:9393+ * @IWL_TM_CMD_APP2DEV_END_TRACE:9494+ * @IWL_TM_CMD_APP2DEV_READ_TRACE:9595+ * commands fom user space for uCode trace operations9696+ *9797+ * @IWL_TM_CMD_DEV2APP_SYNC_RSP:9898+ * commands from kernel space to carry the synchronous response9999+ * to user application100100+ * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT:101101+ * commands from kernel space to multicast the spontaneous messages102102+ * to user application103103+ * @IWL_TM_CMD_DEV2APP_EEPROM_RSP:104104+ * commands from kernel space to carry the eeprom response105105+ * to user application74106 */75107enum iwl_tm_cmd_t {7676- /* commands from user application to the uCode,7777- * the actual uCode host command ID is carried with7878- * IWL_TM_ATTR_UCODE_CMD_ID */7979- IWL_TM_CMD_APP2DEV_UCODE = 1,8080-8181- /* commands from user applicaiton to access register */8282- IWL_TM_CMD_APP2DEV_REG_READ32,8383- IWL_TM_CMD_APP2DEV_REG_WRITE32,8484- IWL_TM_CMD_APP2DEV_REG_WRITE8,8585-8686- /* commands fom user space for pure driver level operations */8787- IWL_TM_CMD_APP2DEV_GET_DEVICENAME,8888- IWL_TM_CMD_APP2DEV_LOAD_INIT_FW,8989- IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB,9090- IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW,9191- IWL_TM_CMD_APP2DEV_GET_EEPROM,9292- IWL_TM_CMD_APP2DEV_FIXRATE_REQ,9393- /* if there is other new command for the driver layer operation,9494- * append them here */9595-9696- /* commands fom user space for uCode trace operations */9797- IWL_TM_CMD_APP2DEV_BEGIN_TRACE,9898- IWL_TM_CMD_APP2DEV_END_TRACE,9999- IWL_TM_CMD_APP2DEV_READ_TRACE,100100-101101- /* commands from kernel space to carry the synchronous response102102- * to user application */103103- IWL_TM_CMD_DEV2APP_SYNC_RSP,104104-105105- /* commands from kernel space to multicast the spontaneous messages106106- * to user application */107107- IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,108108-109109- /* commands from kernel space to carry the eeprom response110110- * to user application */111111- IWL_TM_CMD_DEV2APP_EEPROM_RSP,112112-113113- IWL_TM_CMD_MAX,108108+ IWL_TM_CMD_APP2DEV_UCODE = 1,109109+ IWL_TM_CMD_APP2DEV_REG_READ32 = 2,110110+ IWL_TM_CMD_APP2DEV_REG_WRITE32 = 3,111111+ IWL_TM_CMD_APP2DEV_REG_WRITE8 = 4,112112+ IWL_TM_CMD_APP2DEV_GET_DEVICENAME = 5,113113+ IWL_TM_CMD_APP2DEV_LOAD_INIT_FW = 6,114114+ IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB = 7,115115+ IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW = 8,116116+ IWL_TM_CMD_APP2DEV_GET_EEPROM = 9,117117+ IWL_TM_CMD_APP2DEV_FIXRATE_REQ = 10,118118+ IWL_TM_CMD_APP2DEV_BEGIN_TRACE = 11,119119+ IWL_TM_CMD_APP2DEV_END_TRACE = 12,120120+ IWL_TM_CMD_APP2DEV_READ_TRACE = 13,121121+ IWL_TM_CMD_DEV2APP_SYNC_RSP = 14,122122+ IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15,123123+ IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16,124124+ IWL_TM_CMD_MAX = 17,114125};115126127127+/*128128+ * Atrribute filed in testmode command129129+ * See enum iwl_tm_cmd_t.130130+ *131131+ * @IWL_TM_ATTR_NOT_APPLICABLE:132132+ * The attribute is not applicable or invalid133133+ * @IWL_TM_ATTR_COMMAND:134134+ * From user space to kernel space:135135+ * the command either destines to ucode, driver, or register;136136+ * From kernel space to user space:137137+ * the command either carries synchronous response,138138+ * or the spontaneous message multicast from the device;139139+ *140140+ * @IWL_TM_ATTR_UCODE_CMD_ID:141141+ * @IWL_TM_ATTR_UCODE_CMD_DATA:142142+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,143143+ * The mandatory fields are :144144+ * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;145145+ * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands;146146+ * The optional fields are:147147+ * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload148148+ * to the ucode149149+ *150150+ * @IWL_TM_ATTR_REG_OFFSET:151151+ * @IWL_TM_ATTR_REG_VALUE8:152152+ * @IWL_TM_ATTR_REG_VALUE32:153153+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,154154+ * The mandatory fields are:155155+ * IWL_TM_ATTR_REG_OFFSET for the offset of the target register;156156+ * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value157157+ *158158+ * @IWL_TM_ATTR_SYNC_RSP:159159+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,160160+ * The mandatory fields are:161161+ * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user162162+ * application command163163+ *164164+ * @IWL_TM_ATTR_UCODE_RX_PKT:165165+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,166166+ * The mandatory fields are:167167+ * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user168168+ * application169169+ *170170+ * @IWL_TM_ATTR_EEPROM:171171+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,172172+ * The mandatory fields are:173173+ * IWL_TM_ATTR_EEPROM for the data content responging to the user174174+ * application175175+ *176176+ * @IWL_TM_ATTR_TRACE_ADDR:177177+ * @IWL_TM_ATTR_TRACE_SIZE:178178+ * @IWL_TM_ATTR_TRACE_DUMP:179179+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,180180+ * The mandatory fields are:181181+ * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address182182+ * IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size183183+ * IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump184184+ *185185+ * @IWL_TM_ATTR_FIXRATE:186186+ * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,187187+ * The mandatory fields are:188188+ * IWL_TM_ATTR_FIXRATE for the fixed rate189189+ *190190+ */116191enum iwl_tm_attr_t {117117- IWL_TM_ATTR_NOT_APPLICABLE = 0,118118-119119- /* From user space to kernel space:120120- * the command either destines to ucode, driver, or register;121121- * See enum iwl_tm_cmd_t.122122- *123123- * From kernel space to user space:124124- * the command either carries synchronous response,125125- * or the spontaneous message multicast from the device;126126- * See enum iwl_tm_cmd_t. */127127- IWL_TM_ATTR_COMMAND,128128-129129- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,130130- * The mandatory fields are :131131- * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;132132- * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands;133133- * The optional fields are:134134- * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload135135- * to the ucode */136136- IWL_TM_ATTR_UCODE_CMD_ID,137137- IWL_TM_ATTR_UCODE_CMD_DATA,138138-139139- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,140140- * The mandatory fields are:141141- * IWL_TM_ATTR_REG_OFFSET for the offset of the target register;142142- * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value */143143- IWL_TM_ATTR_REG_OFFSET,144144- IWL_TM_ATTR_REG_VALUE8,145145- IWL_TM_ATTR_REG_VALUE32,146146-147147- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,148148- * The mandatory fields are:149149- * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user150150- * application command */151151- IWL_TM_ATTR_SYNC_RSP,152152- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,153153- * The mandatory fields are:154154- * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user155155- * application */156156- IWL_TM_ATTR_UCODE_RX_PKT,157157-158158- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,159159- * The mandatory fields are:160160- * IWL_TM_ATTR_EEPROM for the data content responging to the user161161- * application */162162- IWL_TM_ATTR_EEPROM,163163-164164- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,165165- * The mandatory fields are:166166- * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address167167- */168168- IWL_TM_ATTR_TRACE_ADDR,169169- IWL_TM_ATTR_TRACE_SIZE,170170- IWL_TM_ATTR_TRACE_DUMP,171171-172172- /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,173173- * The mandatory fields are:174174- * IWL_TM_ATTR_FIXRATE for the fixed rate175175- */176176- IWL_TM_ATTR_FIXRATE,177177-178178- IWL_TM_ATTR_MAX,192192+ IWL_TM_ATTR_NOT_APPLICABLE = 0,193193+ IWL_TM_ATTR_COMMAND = 1,194194+ IWL_TM_ATTR_UCODE_CMD_ID = 2,195195+ IWL_TM_ATTR_UCODE_CMD_DATA = 3,196196+ IWL_TM_ATTR_REG_OFFSET = 4,197197+ IWL_TM_ATTR_REG_VALUE8 = 5,198198+ IWL_TM_ATTR_REG_VALUE32 = 6,199199+ IWL_TM_ATTR_SYNC_RSP = 7,200200+ IWL_TM_ATTR_UCODE_RX_PKT = 8,201201+ IWL_TM_ATTR_EEPROM = 9,202202+ IWL_TM_ATTR_TRACE_ADDR = 10,203203+ IWL_TM_ATTR_TRACE_SIZE = 11,204204+ IWL_TM_ATTR_TRACE_DUMP = 12,205205+ IWL_TM_ATTR_FIXRATE = 13,206206+ IWL_TM_ATTR_MAX = 14,179207};180208181209/* uCode trace buffer */
+423
drivers/net/wireless/iwlwifi/iwl-trans.c
···11+/******************************************************************************22+ *33+ * This file is provided under a dual BSD/GPLv2 license. When using or44+ * redistributing this file, you may do so under either license.55+ *66+ * GPL LICENSE SUMMARY77+ *88+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.99+ *1010+ * This program is free software; you can redistribute it and/or modify1111+ * it under the terms of version 2 of the GNU General Public License as1212+ * published by the Free Software Foundation.1313+ *1414+ * This program is distributed in the hope that it will be useful, but1515+ * WITHOUT ANY WARRANTY; without even the implied warranty of1616+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1717+ * General Public License for more details.1818+ *1919+ * You should have received a copy of the GNU General Public License2020+ * along with this program; if not, write to the Free Software2121+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,2222+ * USA2323+ *2424+ * The full GNU General Public License is included in this distribution2525+ * in the file called LICENSE.GPL.2626+ *2727+ * Contact Information:2828+ * Intel Linux Wireless <ilw@linux.intel.com>2929+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-64973030+ *3131+ * BSD LICENSE3232+ *3333+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.3434+ * All rights reserved.3535+ *3636+ * Redistribution and use in source and binary forms, with or without3737+ * modification, are permitted provided that the following conditions3838+ * are met:3939+ *4040+ * * Redistributions of source code must retain the above copyright4141+ * notice, this list of conditions and the following disclaimer.4242+ * * Redistributions in binary form must reproduce the above copyright4343+ * notice, this list of conditions and the following disclaimer in4444+ * the documentation and/or other materials provided with the4545+ * distribution.4646+ * * Neither the name Intel Corporation nor the names of its4747+ * contributors may be used to endorse or promote products derived4848+ * from this software without specific prior written permission.4949+ *5050+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS5151+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT5252+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR5353+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT5454+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,5555+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT5656+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,5757+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY5858+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT5959+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE6060+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.6161+ *6262+ *****************************************************************************/6363+#include "iwl-dev.h"6464+#include "iwl-trans.h"6565+#include "iwl-core.h"6666+#include "iwl-helpers.h"6767+/*TODO remove uneeded includes when the transport layer tx_free will be here */6868+#include "iwl-agn.h"6969+7070+static int iwl_trans_rx_alloc(struct iwl_priv *priv)7171+{7272+ struct iwl_rx_queue *rxq = &priv->rxq;7373+ struct device *dev = priv->bus.dev;7474+7575+ memset(&priv->rxq, 0, sizeof(priv->rxq));7676+7777+ spin_lock_init(&rxq->lock);7878+ INIT_LIST_HEAD(&rxq->rx_free);7979+ INIT_LIST_HEAD(&rxq->rx_used);8080+8181+ if (WARN_ON(rxq->bd || rxq->rb_stts))8282+ return -EINVAL;8383+8484+ /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */8585+ rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,8686+ &rxq->bd_dma, GFP_KERNEL);8787+ if (!rxq->bd)8888+ goto err_bd;8989+ memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);9090+9191+ /*Allocate the driver's pointer to receive buffer status */9292+ rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),9393+ &rxq->rb_stts_dma, GFP_KERNEL);9494+ if (!rxq->rb_stts)9595+ goto err_rb_stts;9696+ memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));9797+9898+ return 0;9999+100100+err_rb_stts:101101+ dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,102102+ rxq->bd, rxq->bd_dma);103103+ memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));104104+ rxq->bd = NULL;105105+err_bd:106106+ return -ENOMEM;107107+}108108+109109+static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv)110110+{111111+ struct iwl_rx_queue *rxq = &priv->rxq;112112+ int i;113113+114114+ /* Fill the rx_used queue with _all_ of the Rx buffers */115115+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {116116+ /* In the reset function, these buffers may have been allocated117117+ * to an SKB, so we need to unmap and free potential storage */118118+ if (rxq->pool[i].page != NULL) {119119+ dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,120120+ PAGE_SIZE << priv->hw_params.rx_page_order,121121+ DMA_FROM_DEVICE);122122+ __iwl_free_pages(priv, rxq->pool[i].page);123123+ rxq->pool[i].page = NULL;124124+ }125125+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);126126+ }127127+}128128+129129+static int iwl_trans_rx_init(struct iwl_priv *priv)130130+{131131+ struct iwl_rx_queue *rxq = &priv->rxq;132132+ int i, err;133133+ unsigned long flags;134134+135135+ if (!rxq->bd) {136136+ err = iwl_trans_rx_alloc(priv);137137+ if (err)138138+ return err;139139+ }140140+141141+ spin_lock_irqsave(&rxq->lock, flags);142142+ INIT_LIST_HEAD(&rxq->rx_free);143143+ INIT_LIST_HEAD(&rxq->rx_used);144144+145145+ iwl_trans_rxq_free_rx_bufs(priv);146146+147147+ for (i = 0; i < RX_QUEUE_SIZE; i++)148148+ rxq->queue[i] = NULL;149149+150150+ /* Set us so that we have processed and used all buffers, but have151151+ * not restocked the Rx queue with fresh buffers */152152+ rxq->read = rxq->write = 0;153153+ rxq->write_actual = 0;154154+ rxq->free_count = 0;155155+ spin_unlock_irqrestore(&rxq->lock, flags);156156+157157+ return 0;158158+}159159+160160+static void iwl_trans_rx_free(struct iwl_priv *priv)161161+{162162+ struct iwl_rx_queue *rxq = &priv->rxq;163163+ unsigned long flags;164164+165165+ /*if rxq->bd is NULL, it means that nothing has been allocated,166166+ * exit now */167167+ if (!rxq->bd) {168168+ IWL_DEBUG_INFO(priv, "Free NULL rx context\n");169169+ return;170170+ }171171+172172+ spin_lock_irqsave(&rxq->lock, flags);173173+ iwl_trans_rxq_free_rx_bufs(priv);174174+ spin_unlock_irqrestore(&rxq->lock, flags);175175+176176+ dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE,177177+ rxq->bd, rxq->bd_dma);178178+ memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));179179+ rxq->bd = NULL;180180+181181+ if (rxq->rb_stts)182182+ dma_free_coherent(priv->bus.dev,183183+ sizeof(struct iwl_rb_status),184184+ rxq->rb_stts, rxq->rb_stts_dma);185185+ else186186+ IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n");187187+ memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));188188+ rxq->rb_stts = NULL;189189+}190190+191191+/* TODO:remove this code duplication */192192+static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,193193+ struct iwl_dma_ptr *ptr, size_t size)194194+{195195+ if (WARN_ON(ptr->addr))196196+ return -EINVAL;197197+198198+ ptr->addr = dma_alloc_coherent(priv->bus.dev, size,199199+ &ptr->dma, GFP_KERNEL);200200+ if (!ptr->addr)201201+ return -ENOMEM;202202+ ptr->size = size;203203+ return 0;204204+}205205+206206+static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,207207+ int slots_num, u32 txq_id)208208+{209209+ size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;210210+ int i;211211+212212+ if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds))213213+ return -EINVAL;214214+215215+ txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num,216216+ GFP_KERNEL);217217+ txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num,218218+ GFP_KERNEL);219219+220220+ if (!txq->meta || !txq->cmd)221221+ goto error;222222+223223+ for (i = 0; i < slots_num; i++) {224224+ txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),225225+ GFP_KERNEL);226226+ if (!txq->cmd[i])227227+ goto error;228228+ }229229+230230+ /* Alloc driver data array and TFD circular buffer */231231+ /* Driver private data, only for Tx (not command) queues,232232+ * not shared with device. */233233+ if (txq_id != priv->cmd_queue) {234234+ txq->txb = kzalloc(sizeof(txq->txb[0]) *235235+ TFD_QUEUE_SIZE_MAX, GFP_KERNEL);236236+ if (!txq->txb) {237237+ IWL_ERR(priv, "kmalloc for auxiliary BD "238238+ "structures failed\n");239239+ goto error;240240+ }241241+ } else {242242+ txq->txb = NULL;243243+ }244244+245245+ /* Circular buffer of transmit frame descriptors (TFDs),246246+ * shared with device */247247+ txq->tfds = dma_alloc_coherent(priv->bus.dev, tfd_sz, &txq->q.dma_addr,248248+ GFP_KERNEL);249249+ if (!txq->tfds) {250250+ IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz);251251+ goto error;252252+ }253253+ txq->q.id = txq_id;254254+255255+ return 0;256256+error:257257+ kfree(txq->txb);258258+ txq->txb = NULL;259259+ /* since txq->cmd has been zeroed,260260+ * all non allocated cmd[i] will be NULL */261261+ if (txq->cmd)262262+ for (i = 0; i < slots_num; i++)263263+ kfree(txq->cmd[i]);264264+ kfree(txq->meta);265265+ kfree(txq->cmd);266266+ txq->meta = NULL;267267+ txq->cmd = NULL;268268+269269+ return -ENOMEM;270270+271271+}272272+273273+static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,274274+ int slots_num, u32 txq_id)275275+{276276+ int ret;277277+278278+ txq->need_update = 0;279279+ memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num);280280+281281+ /*282282+ * For the default queues 0-3, set up the swq_id283283+ * already -- all others need to get one later284284+ * (if they need one at all).285285+ */286286+ if (txq_id < 4)287287+ iwl_set_swq_id(txq, txq_id, txq_id);288288+289289+ /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise290290+ * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */291291+ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));292292+293293+ /* Initialize queue's high/low-water marks, and head/tail indexes */294294+ ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num,295295+ txq_id);296296+ if (ret)297297+ return ret;298298+299299+ /*300300+ * Tell nic where to find circular buffer of Tx Frame Descriptors for301301+ * given Tx queue, and enable the DMA channel used for that queue.302302+ * Circular buffer (TFD queue in DRAM) physical base address */303303+ iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),304304+ txq->q.dma_addr >> 8);305305+306306+ return 0;307307+}308308+309309+/**310310+ * iwl_trans_tx_alloc - allocate TX context311311+ * Allocate all Tx DMA structures and initialize them312312+ *313313+ * @param priv314314+ * @return error code315315+ */316316+static int iwl_trans_tx_alloc(struct iwl_priv *priv)317317+{318318+ int ret;319319+ int txq_id, slots_num;320320+321321+ /*It is not allowed to alloc twice, so warn when this happens.322322+ * We cannot rely on the previous allocation, so free and fail */323323+ if (WARN_ON(priv->txq)) {324324+ ret = -EINVAL;325325+ goto error;326326+ }327327+328328+ ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls,329329+ priv->hw_params.scd_bc_tbls_size);330330+ if (ret) {331331+ IWL_ERR(priv, "Scheduler BC Table allocation failed\n");332332+ goto error;333333+ }334334+335335+ /* Alloc keep-warm buffer */336336+ ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);337337+ if (ret) {338338+ IWL_ERR(priv, "Keep Warm allocation failed\n");339339+ goto error;340340+ }341341+342342+ priv->txq = kzalloc(sizeof(struct iwl_tx_queue) *343343+ priv->cfg->base_params->num_of_queues, GFP_KERNEL);344344+ if (!priv->txq) {345345+ IWL_ERR(priv, "Not enough memory for txq\n");346346+ ret = ENOMEM;347347+ goto error;348348+ }349349+350350+ /* Alloc and init all Tx queues, including the command queue (#4/#9) */351351+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {352352+ slots_num = (txq_id == priv->cmd_queue) ?353353+ TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;354354+ ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num,355355+ txq_id);356356+ if (ret) {357357+ IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id);358358+ goto error;359359+ }360360+ }361361+362362+ return 0;363363+364364+error:365365+ iwlagn_hw_txq_ctx_free(priv);366366+367367+ return ret;368368+}369369+static int iwl_trans_tx_init(struct iwl_priv *priv)370370+{371371+ int ret;372372+ int txq_id, slots_num;373373+ unsigned long flags;374374+ bool alloc = false;375375+376376+ if (!priv->txq) {377377+ ret = iwl_trans_tx_alloc(priv);378378+ if (ret)379379+ goto error;380380+ alloc = true;381381+ }382382+383383+ spin_lock_irqsave(&priv->lock, flags);384384+385385+ /* Turn off all Tx DMA fifos */386386+ iwl_write_prph(priv, IWLAGN_SCD_TXFACT, 0);387387+388388+ /* Tell NIC where to find the "keep warm" buffer */389389+ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);390390+391391+ spin_unlock_irqrestore(&priv->lock, flags);392392+393393+ /* Alloc and init all Tx queues, including the command queue (#4/#9) */394394+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {395395+ slots_num = (txq_id == priv->cmd_queue) ?396396+ TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;397397+ ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num,398398+ txq_id);399399+ if (ret) {400400+ IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);401401+ goto error;402402+ }403403+ }404404+405405+ return 0;406406+error:407407+ /*Upon error, free only if we allocated something */408408+ if (alloc)409409+ iwlagn_hw_txq_ctx_free(priv);410410+ return ret;411411+}412412+413413+static const struct iwl_trans_ops trans_ops = {414414+ .rx_init = iwl_trans_rx_init,415415+ .rx_free = iwl_trans_rx_free,416416+417417+ .tx_init = iwl_trans_tx_init,418418+};419419+420420+void iwl_trans_register(struct iwl_trans *trans)421421+{422422+ trans->ops = &trans_ops;423423+}
+64
drivers/net/wireless/iwlwifi/iwl-trans.h
···11+/******************************************************************************22+ *33+ * This file is provided under a dual BSD/GPLv2 license. When using or44+ * redistributing this file, you may do so under either license.55+ *66+ * GPL LICENSE SUMMARY77+ *88+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.99+ *1010+ * This program is free software; you can redistribute it and/or modify1111+ * it under the terms of version 2 of the GNU General Public License as1212+ * published by the Free Software Foundation.1313+ *1414+ * This program is distributed in the hope that it will be useful, but1515+ * WITHOUT ANY WARRANTY; without even the implied warranty of1616+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1717+ * General Public License for more details.1818+ *1919+ * You should have received a copy of the GNU General Public License2020+ * along with this program; if not, write to the Free Software2121+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,2222+ * USA2323+ *2424+ * The full GNU General Public License is included in this distribution2525+ * in the file called LICENSE.GPL.2626+ *2727+ * Contact Information:2828+ * Intel Linux Wireless <ilw@linux.intel.com>2929+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-64973030+ *3131+ * BSD LICENSE3232+ *3333+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.3434+ * All rights reserved.3535+ *3636+ * Redistribution and use in source and binary forms, with or without3737+ * modification, are permitted provided that the following conditions3838+ * are met:3939+ *4040+ * * Redistributions of source code must retain the above copyright4141+ * notice, this list of conditions and the following disclaimer.4242+ * * Redistributions in binary form must reproduce the above copyright4343+ * notice, this list of conditions and the following disclaimer in4444+ * the documentation and/or other materials provided with the4545+ * distribution.4646+ * * Neither the name Intel Corporation nor the names of its4747+ * contributors may be used to endorse or promote products derived4848+ * from this software without specific prior written permission.4949+ *5050+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS5151+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT5252+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR5353+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT5454+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,5555+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT5656+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,5757+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY5858+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT5959+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE6060+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.6161+ *6262+ *****************************************************************************/6363+6464+void iwl_trans_register(struct iwl_trans *trans);
+1-138
drivers/net/wireless/iwlwifi/iwl-tx.c
···220220 return 0;221221}222222223223-/*224224- * Tell nic where to find circular buffer of Tx Frame Descriptors for225225- * given Tx queue, and enable the DMA channel used for that queue.226226- *227227- * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA228228- * channels supported in hardware.229229- */230230-static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)231231-{232232- int txq_id = txq->q.id;233233-234234- /* Circular buffer (TFD queue in DRAM) physical base address */235235- iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),236236- txq->q.dma_addr >> 8);237237-238238- return 0;239239-}240240-241223/**242224 * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's243225 */···374392 return s;375393}376394377377-378395/**379396 * iwl_queue_init - Initialize queue's high/low-water and read/write indexes380397 */381381-static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,398398+int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,382399 int count, int slots_num, u32 id)383400{384401 q->n_bd = count;···405424 q->write_ptr = q->read_ptr = 0;406425407426 return 0;408408-}409409-410410-/**411411- * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue412412- */413413-static int iwl_tx_queue_alloc(struct iwl_priv *priv,414414- struct iwl_tx_queue *txq, u32 id)415415-{416416- struct device *dev = priv->bus.dev;417417- size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;418418-419419- /* Driver private data, only for Tx (not command) queues,420420- * not shared with device. */421421- if (id != priv->cmd_queue) {422422- txq->txb = kzalloc(sizeof(txq->txb[0]) *423423- TFD_QUEUE_SIZE_MAX, GFP_KERNEL);424424- if (!txq->txb) {425425- IWL_ERR(priv, "kmalloc for auxiliary BD "426426- "structures failed\n");427427- goto error;428428- }429429- } else {430430- txq->txb = NULL;431431- }432432-433433- /* Circular buffer of transmit frame descriptors (TFDs),434434- * shared with device */435435- txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,436436- GFP_KERNEL);437437- if (!txq->tfds) {438438- IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz);439439- goto error;440440- }441441- txq->q.id = id;442442-443443- return 0;444444-445445- error:446446- kfree(txq->txb);447447- txq->txb = NULL;448448-449449- return -ENOMEM;450450-}451451-452452-/**453453- * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue454454- */455455-int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,456456- int slots_num, u32 txq_id)457457-{458458- int i, len;459459- int ret;460460-461461- txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num,462462- GFP_KERNEL);463463- txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num,464464- GFP_KERNEL);465465-466466- if (!txq->meta || !txq->cmd)467467- goto out_free_arrays;468468-469469- len = sizeof(struct iwl_device_cmd);470470- for (i = 0; i < slots_num; i++) {471471- txq->cmd[i] = kmalloc(len, GFP_KERNEL);472472- if (!txq->cmd[i])473473- goto err;474474- }475475-476476- /* Alloc driver data array and TFD circular buffer */477477- ret = iwl_tx_queue_alloc(priv, txq, txq_id);478478- if (ret)479479- goto err;480480-481481- txq->need_update = 0;482482-483483- /*484484- * For the default queues 0-3, set up the swq_id485485- * already -- all others need to get one later486486- * (if they need one at all).487487- */488488- if (txq_id < 4)489489- iwl_set_swq_id(txq, txq_id, txq_id);490490-491491- /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise492492- * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */493493- BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));494494-495495- /* Initialize queue's high/low-water marks, and head/tail indexes */496496- ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);497497- if (ret)498498- return ret;499499-500500- /* Tell device where to find queue */501501- iwlagn_tx_queue_init(priv, txq);502502-503503- return 0;504504-err:505505- for (i = 0; i < slots_num; i++)506506- kfree(txq->cmd[i]);507507-out_free_arrays:508508- kfree(txq->meta);509509- kfree(txq->cmd);510510-511511- return -ENOMEM;512512-}513513-514514-void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,515515- int slots_num, u32 txq_id)516516-{517517- memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * slots_num);518518-519519- txq->need_update = 0;520520-521521- /* Initialize queue's high/low-water marks, and head/tail indexes */522522- iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);523523-524524- /* Tell device where to find queue */525525- iwlagn_tx_queue_init(priv, txq);526427}527428528429/*************** HOST COMMAND QUEUE FUNCTIONS *****/
···200200 skb_pull(skb, l2pad);201201}202202203203-static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,203203+static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,204204+ struct sk_buff *skb,204205 struct txentry_desc *txdesc)205206{206206- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);207207- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;207207+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);208208+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;208209 struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);209210210211 if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))···213212214213 __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);215214216216- if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))215215+ if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags))217216 return;218217219218 /*···238237239238}240239241241-static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,240240+static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,241241+ struct sk_buff *skb,242242 struct txentry_desc *txdesc,243243 const struct rt2x00_rate *hwrate)244244{245245- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;246246- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);245245+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);247246 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];248247 unsigned int data_length;249248 unsigned int duration;···260259 txdesc->u.plcp.ifs = IFS_SIFS;261260262261 /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */263263- data_length = entry->skb->len + 4;264264- data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb);262262+ data_length = skb->len + 4;263263+ data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);265264266265 /*267266 * PLCP setup···302301 }303302}304303305305-static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,304304+static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,305305+ struct sk_buff *skb,306306 struct txentry_desc *txdesc,307307 const struct rt2x00_rate *hwrate)308308{309309- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);309309+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);310310 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];311311- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;311311+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;312312313313 if (tx_info->control.sta)314314 txdesc->u.ht.mpdu_density =···382380 txdesc->u.ht.txop = TXOP_HTTXOP;383381}384382385385-static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,383383+static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,384384+ struct sk_buff *skb,386385 struct txentry_desc *txdesc)387386{388388- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;389389- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);390390- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;387387+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);388388+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;391389 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];392390 struct ieee80211_rate *rate;393391 const struct rt2x00_rate *hwrate = NULL;···397395 /*398396 * Header and frame information.399397 */400400- txdesc->length = entry->skb->len;401401- txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);398398+ txdesc->length = skb->len;399399+ txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);402400403401 /*404402 * Check whether this frame is to be acked.···473471 /*474472 * Apply TX descriptor handling by components475473 */476476- rt2x00crypto_create_tx_descriptor(entry, txdesc);477477- rt2x00queue_create_tx_descriptor_seq(entry, txdesc);474474+ rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc);475475+ rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);478476479477 if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))480480- rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);478478+ rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc,479479+ hwrate);481480 else482482- rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);481481+ rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,482482+ hwrate);483483}484484485485static int rt2x00queue_write_tx_data(struct queue_entry *entry,···559555 bool local)560556{561557 struct ieee80211_tx_info *tx_info;562562- struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);558558+ struct queue_entry *entry;563559 struct txentry_desc txdesc;564560 struct skb_frame_desc *skbdesc;565561 u8 rate_idx, rate_flags;566566-567567- if (unlikely(rt2x00queue_full(queue))) {568568- ERROR(queue->rt2x00dev,569569- "Dropping frame due to full tx queue %d.\n", queue->qid);570570- return -ENOBUFS;571571- }572572-573573- if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,574574- &entry->flags))) {575575- ERROR(queue->rt2x00dev,576576- "Arrived at non-free entry in the non-full queue %d.\n"577577- "Please file bug report to %s.\n",578578- queue->qid, DRV_PROJECT);579579- return -EINVAL;580580- }562562+ int ret = 0;581563582564 /*583565 * Copy all TX descriptor information into txdesc,584566 * after that we are free to use the skb->cb array585567 * for our information.586568 */587587- entry->skb = skb;588588- rt2x00queue_create_tx_descriptor(entry, &txdesc);569569+ rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc);589570590571 /*591572 * All information is retrieved from the skb->cb array,···582593 rate_flags = tx_info->control.rates[0].flags;583594 skbdesc = get_skb_frame_desc(skb);584595 memset(skbdesc, 0, sizeof(*skbdesc));585585- skbdesc->entry = entry;586596 skbdesc->tx_rate_idx = rate_idx;587597 skbdesc->tx_rate_flags = rate_flags;588598···610622 * for PCI devices.611623 */612624 if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))613613- rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);625625+ rt2x00queue_insert_l2pad(skb, txdesc.header_length);614626 else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))615615- rt2x00queue_align_frame(entry->skb);627627+ rt2x00queue_align_frame(skb);628628+629629+ spin_lock(&queue->tx_lock);630630+631631+ if (unlikely(rt2x00queue_full(queue))) {632632+ ERROR(queue->rt2x00dev,633633+ "Dropping frame due to full tx queue %d.\n", queue->qid);634634+ ret = -ENOBUFS;635635+ goto out;636636+ }637637+638638+ entry = rt2x00queue_get_entry(queue, Q_INDEX);639639+640640+ if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,641641+ &entry->flags))) {642642+ ERROR(queue->rt2x00dev,643643+ "Arrived at non-free entry in the non-full queue %d.\n"644644+ "Please file bug report to %s.\n",645645+ queue->qid, DRV_PROJECT);646646+ ret = -EINVAL;647647+ goto out;648648+ }649649+650650+ skbdesc->entry = entry;651651+ entry->skb = skb;616652617653 /*618654 * It could be possible that the queue was corrupted and this···646634 if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {647635 clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);648636 entry->skb = NULL;649649- return -EIO;637637+ ret = -EIO;638638+ goto out;650639 }651640652641 set_bit(ENTRY_DATA_PENDING, &entry->flags);···656643 rt2x00queue_write_tx_descriptor(entry, &txdesc);657644 rt2x00queue_kick_tx_queue(queue, &txdesc);658645659659- return 0;646646+out:647647+ spin_unlock(&queue->tx_lock);648648+ return ret;660649}661650662651int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,···712697 * after that we are free to use the skb->cb array713698 * for our information.714699 */715715- rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);700700+ rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc);716701717702 /*718703 * Fill in skb descriptor···11991184 struct data_queue *queue, enum data_queue_qid qid)12001185{12011186 mutex_init(&queue->status_lock);11871187+ spin_lock_init(&queue->tx_lock);12021188 spin_lock_init(&queue->index_lock);1203118912041190 queue->rt2x00dev = rt2x00dev;
+2
drivers/net/wireless/rt2x00/rt2x00queue.h
···432432 * @flags: Entry flags, see &enum queue_entry_flags.433433 * @status_lock: The mutex for protecting the start/stop/flush434434 * handling on this queue.435435+ * @tx_lock: Spinlock to serialize tx operations on this queue.435436 * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or436437 * @index_crypt needs to be changed this lock should be grabbed to prevent437438 * index corruption due to concurrency.···459458 unsigned long flags;460459461460 struct mutex status_lock;461461+ spinlock_t tx_lock;462462 spinlock_t index_lock;463463464464 unsigned int count;
···614614 (u8)615615 GET_RX_DESC_RXMCS(pdesc));616616 rx_status->mactime = GET_RX_DESC_TSFL(pdesc);617617- if (phystatus == true) {617617+ if (phystatus) {618618 p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +619619 stats->rx_bufshift);620620 _rtl92de_translate_rx_signal_stuff(hw,···876876877877void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)878878{879879- if (istx == true) {879879+ if (istx) {880880 switch (desc_name) {881881 case HW_DESC_OWN:882882 wmb();···917917{918918 u32 ret = 0;919919920920- if (istx == true) {920920+ if (istx) {921921 switch (desc_name) {922922 case HW_DESC_OWN:923923 ret = GET_TX_DESC_OWN(p_desc);
-3
drivers/net/wireless/rtlwifi/rtl8192se/hw.c
···12141214 rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);12151215 /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */12161216 rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);12171217-12181218- rtlpci->irq_enabled = true;12191217}1220121812211219void rtl92se_disable_interrupt(struct ieee80211_hw *hw)···12241226 rtl_write_dword(rtlpriv, INTA_MASK, 0);12251227 rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);1226122812271227- rtlpci->irq_enabled = false;12281229 synchronize_irq(rtlpci->pdev->irq);12291230}12301231
+1-1
drivers/net/wireless/wl12xx/Kconfig
···1111 depends on WL12XX_MENU && GENERIC_HARDIRQS1212 depends on INET1313 select FW_LOADER1414- select CRC71514 ---help---1615 This module adds support for wireless adapters based on TI wl1271 and1716 TI wl1273 chipsets. This module does *not* include support for wl1251.···3233config WL12XX_SPI3334 tristate "TI wl12xx SPI support"3435 depends on WL12XX && SPI_MASTER3636+ select CRC73537 ---help---3638 This module adds support for the SPI interface of adapters using3739 TI wl12xx chipsets. Select this if your platform is using
+48-1
drivers/net/wireless/wl12xx/acx.c
···25252626#include <linux/module.h>2727#include <linux/platform_device.h>2828-#include <linux/crc7.h>2928#include <linux/spi/spi.h>3029#include <linux/slab.h>3130···10671068 mem_conf->tx_free_req = mem->min_req_tx_blocks;10681069 mem_conf->rx_free_req = mem->min_req_rx_blocks;10691070 mem_conf->tx_min = mem->tx_min;10711071+ mem_conf->fwlog_blocks = wl->conf.fwlog.mem_blocks;1070107210711073 ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,10721074 sizeof(*mem_conf));···1574157415751575out:15761576 kfree(tsf_info);15771577+ return ret;15781578+}15791579+15801580+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)15811581+{15821582+ struct wl1271_acx_ps_rx_streaming *rx_streaming;15831583+ u32 conf_queues, enable_queues;15841584+ int i, ret = 0;15851585+15861586+ wl1271_debug(DEBUG_ACX, "acx ps rx streaming");15871587+15881588+ rx_streaming = kzalloc(sizeof(*rx_streaming), GFP_KERNEL);15891589+ if (!rx_streaming) {15901590+ ret = -ENOMEM;15911591+ goto out;15921592+ }15931593+15941594+ conf_queues = wl->conf.rx_streaming.queues;15951595+ if (enable)15961596+ enable_queues = conf_queues;15971597+ else15981598+ enable_queues = 0;15991599+16001600+ for (i = 0; i < 8; i++) {16011601+ /*16021602+ * Skip non-changed queues, to avoid redundant acxs.16031603+ * this check assumes conf.rx_streaming.queues can't16041604+ * be changed while rx_streaming is enabled.16051605+ */16061606+ if (!(conf_queues & BIT(i)))16071607+ continue;16081608+16091609+ rx_streaming->tid = i;16101610+ rx_streaming->enable = enable_queues & BIT(i);16111611+ rx_streaming->period = wl->conf.rx_streaming.interval;16121612+ rx_streaming->timeout = wl->conf.rx_streaming.interval;16131613+16141614+ ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING,16151615+ rx_streaming,16161616+ sizeof(*rx_streaming));16171617+ if (ret < 0) {16181618+ wl1271_warning("acx ps rx streaming failed: %d", ret);16191619+ goto out;16201620+ }16211621+ }16221622+out:16231623+ kfree(rx_streaming);15771624 return ret;15781625}15791626
···133133 if (ret < 0)134134 break;135135136136- /* enable beacon early termination */137137- ret = wl1271_acx_bet_enable(wl, true);138138- if (ret < 0)139139- break;136136+ /*137137+ * BET has only a minor effect in 5GHz and masks138138+ * channel switch IEs, so we only enable BET on 2.4GHz139139+ */140140+ if (wl->band == IEEE80211_BAND_2GHZ)141141+ /* enable beacon early termination */142142+ ret = wl1271_acx_bet_enable(wl, true);140143141144 if (wl->ps_compl) {142145 complete(wl->ps_compl);···186183 ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);187184}188185186186+static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,187187+ u8 enable)188188+{189189+ if (enable) {190190+ /* disable dynamic PS when requested by the firmware */191191+ ieee80211_disable_dyn_ps(wl->vif);192192+ set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);193193+ } else {194194+ ieee80211_enable_dyn_ps(wl->vif);195195+ clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);196196+ wl1271_recalc_rx_streaming(wl);197197+ }198198+199199+}200200+189201static void wl1271_event_mbox_dump(struct event_mailbox *mbox)190202{191203 wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");···244226 }245227 }246228247247- /* disable dynamic PS when requested by the firmware */248229 if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&249249- wl->bss_type == BSS_TYPE_STA_BSS) {250250- if (mbox->soft_gemini_sense_info)251251- ieee80211_disable_dyn_ps(wl->vif);252252- else253253- ieee80211_enable_dyn_ps(wl->vif);254254- }230230+ wl->bss_type == BSS_TYPE_STA_BSS)231231+ wl12xx_event_soft_gemini_sense(wl,232232+ mbox->soft_gemini_sense_info);255233256234 /*257235 * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
···321321 return 0;322322}323323324324+static int wl12xx_init_fwlog(struct wl1271 *wl)325325+{326326+ int ret;327327+328328+ if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)329329+ return 0;330330+331331+ ret = wl12xx_cmd_config_fwlog(wl);332332+ if (ret < 0)333333+ return ret;334334+335335+ return 0;336336+}337337+324338static int wl1271_sta_hw_init(struct wl1271 *wl)325339{326340 int ret;···393379 return ret;394380395381 ret = wl1271_acx_sta_mem_cfg(wl);382382+ if (ret < 0)383383+ return ret;384384+385385+ /* Configure the FW logger */386386+ ret = wl12xx_init_fwlog(wl);396387 if (ret < 0)397388 return ret;398389
+4-3
drivers/net/wireless/wl12xx/io.c
···23232424#include <linux/module.h>2525#include <linux/platform_device.h>2626-#include <linux/crc7.h>2726#include <linux/spi/spi.h>28272928#include "wl12xx.h"···127128128129void wl1271_io_reset(struct wl1271 *wl)129130{130130- wl->if_ops->reset(wl);131131+ if (wl->if_ops->reset)132132+ wl->if_ops->reset(wl);131133}132134133135void wl1271_io_init(struct wl1271 *wl)134136{135135- wl->if_ops->init(wl);137137+ if (wl->if_ops->init)138138+ wl->if_ops->init(wl);136139}137140138141void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
+14
drivers/net/wireless/wl12xx/io.h
···129129 wl1271_raw_write(wl, physical, buf, len, fixed);130130}131131132132+static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,133133+ void *buf, size_t len, bool fixed)134134+{135135+ int physical;136136+ int addr;137137+138138+ /* Addresses are stored internally as addresses to 32 bytes blocks */139139+ addr = hwaddr << 5;140140+141141+ physical = wl1271_translate_addr(wl, addr);142142+143143+ wl1271_raw_read(wl, physical, buf, len, fixed);144144+}145145+132146static inline u32 wl1271_read32(struct wl1271 *wl, int addr)133147{134148 return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
+486-108
drivers/net/wireless/wl12xx/main.c
···3131#include <linux/platform_device.h>3232#include <linux/slab.h>3333#include <linux/wl12xx.h>3434+#include <linux/sched.h>34353536#include "wl12xx.h"3637#include "wl12xx_80211.h"···363362 .fm_disturbed_band_margin = 0xff, /* default */364363 .swallow_clk_diff = 0xff, /* default */365364 },365365+ .rx_streaming = {366366+ .duration = 150,367367+ .queues = 0x1,368368+ .interval = 20,369369+ .always = 0,370370+ },371371+ .fwlog = {372372+ .mode = WL12XX_FWLOG_ON_DEMAND,373373+ .mem_blocks = 2,374374+ .severity = 0,375375+ .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,376376+ .output = WL12XX_FWLOG_OUTPUT_HOST,377377+ .threshold = 0,378378+ },366379 .hci_io_ds = HCI_IO_DS_6MA,367380};381381+382382+static char *fwlog_param;368383369384static void __wl1271_op_remove_interface(struct wl1271 *wl,370385 bool reset_tx_queues);···405388static DEFINE_MUTEX(wl_list_mutex);406389static LIST_HEAD(wl_list);407390391391+static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)392392+{393393+ int ret;394394+ if (operstate != IF_OPER_UP)395395+ return 0;396396+397397+ if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))398398+ return 0;399399+400400+ ret = wl1271_cmd_set_sta_state(wl);401401+ if (ret < 0)402402+ return ret;403403+404404+ wl1271_info("Association completed.");405405+ return 0;406406+}408407static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,409408 void *arg)410409{···470437 if (ret < 0)471438 goto out;472439473473- if ((dev->operstate == IF_OPER_UP) &&474474- !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) {475475- wl1271_cmd_set_sta_state(wl);476476- wl1271_info("Association completed.");477477- }440440+ wl1271_check_operstate(wl, dev->operstate);478441479442 wl1271_ps_elp_sleep(wl);480443···502473 return 0;503474}504475476476+static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable)477477+{478478+ int ret = 0;479479+480480+ /* we should hold wl->mutex */481481+ ret = wl1271_acx_ps_rx_streaming(wl, enable);482482+ if (ret < 0)483483+ goto out;484484+485485+ if (enable)486486+ set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);487487+ else488488+ clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);489489+out:490490+ return ret;491491+}492492+493493+/*494494+ * this function is being called when the rx_streaming interval495495+ * has beed changed or rx_streaming should be disabled496496+ */497497+int wl1271_recalc_rx_streaming(struct wl1271 *wl)498498+{499499+ int ret = 0;500500+ int period = wl->conf.rx_streaming.interval;501501+502502+ /* don't reconfigure if rx_streaming is disabled */503503+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))504504+ goto out;505505+506506+ /* reconfigure/disable according to new streaming_period */507507+ if (period &&508508+ test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&509509+ (wl->conf.rx_streaming.always ||510510+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))511511+ ret = wl1271_set_rx_streaming(wl, true);512512+ else {513513+ ret = wl1271_set_rx_streaming(wl, false);514514+ /* don't cancel_work_sync since we might deadlock */515515+ del_timer_sync(&wl->rx_streaming_timer);516516+ }517517+out:518518+ return ret;519519+}520520+521521+static void wl1271_rx_streaming_enable_work(struct work_struct *work)522522+{523523+ int ret;524524+ struct wl1271 *wl =525525+ container_of(work, struct wl1271, rx_streaming_enable_work);526526+527527+ mutex_lock(&wl->mutex);528528+529529+ if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) ||530530+ !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||531531+ (!wl->conf.rx_streaming.always &&532532+ !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))533533+ goto out;534534+535535+ if (!wl->conf.rx_streaming.interval)536536+ goto out;537537+538538+ ret = wl1271_ps_elp_wakeup(wl);539539+ if (ret < 0)540540+ goto out;541541+542542+ ret = wl1271_set_rx_streaming(wl, true);543543+ if (ret < 0)544544+ goto out_sleep;545545+546546+ /* stop it after some time of inactivity */547547+ mod_timer(&wl->rx_streaming_timer,548548+ jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration));549549+550550+out_sleep:551551+ wl1271_ps_elp_sleep(wl);552552+out:553553+ mutex_unlock(&wl->mutex);554554+}555555+556556+static void wl1271_rx_streaming_disable_work(struct work_struct *work)557557+{558558+ int ret;559559+ struct wl1271 *wl =560560+ container_of(work, struct wl1271, rx_streaming_disable_work);561561+562562+ mutex_lock(&wl->mutex);563563+564564+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))565565+ goto out;566566+567567+ ret = wl1271_ps_elp_wakeup(wl);568568+ if (ret < 0)569569+ goto out;570570+571571+ ret = wl1271_set_rx_streaming(wl, false);572572+ if (ret)573573+ goto out_sleep;574574+575575+out_sleep:576576+ wl1271_ps_elp_sleep(wl);577577+out:578578+ mutex_unlock(&wl->mutex);579579+}580580+581581+static void wl1271_rx_streaming_timer(unsigned long data)582582+{583583+ struct wl1271 *wl = (struct wl1271 *)data;584584+ ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work);585585+}586586+505587static void wl1271_conf_init(struct wl1271 *wl)506588{507589···628488629489 /* apply driver default configuration */630490 memcpy(&wl->conf, &default_conf, sizeof(default_conf));631631-}632491492492+ /* Adjust settings according to optional module parameters */493493+ if (fwlog_param) {494494+ if (!strcmp(fwlog_param, "continuous")) {495495+ wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;496496+ } else if (!strcmp(fwlog_param, "ondemand")) {497497+ wl->conf.fwlog.mode = WL12XX_FWLOG_ON_DEMAND;498498+ } else if (!strcmp(fwlog_param, "dbgpins")) {499499+ wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;500500+ wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_DBG_PINS;501501+ } else if (!strcmp(fwlog_param, "disable")) {502502+ wl->conf.fwlog.mem_blocks = 0;503503+ wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_NONE;504504+ } else {505505+ wl1271_error("Unknown fwlog parameter %s", fwlog_param);506506+ }507507+ }508508+}633509634510static int wl1271_plt_init(struct wl1271 *wl)635511{···897741898742 /* Return sent skbs to the network stack */899743 while ((skb = skb_dequeue(&wl->deferred_tx_queue)))900900- ieee80211_tx_status(wl->hw, skb);744744+ ieee80211_tx_status_ni(wl->hw, skb);901745}902746903747static void wl1271_netstack_work(struct work_struct *work)···964808 if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {965809 wl1271_error("watchdog interrupt received! "966810 "starting recovery.");967967- ieee80211_queue_work(wl->hw, &wl->recovery_work);811811+ wl12xx_queue_recovery_work(wl);968812969813 /* restarting the chip. ignore any other interrupt. */970814 goto out;···1126970 return ret;1127971}1128972973973+void wl12xx_queue_recovery_work(struct wl1271 *wl)974974+{975975+ if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))976976+ ieee80211_queue_work(wl->hw, &wl->recovery_work);977977+}978978+979979+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)980980+{981981+ size_t len = 0;982982+983983+ /* The FW log is a length-value list, find where the log end */984984+ while (len < maxlen) {985985+ if (memblock[len] == 0)986986+ break;987987+ if (len + memblock[len] + 1 > maxlen)988988+ break;989989+ len += memblock[len] + 1;990990+ }991991+992992+ /* Make sure we have enough room */993993+ len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size));994994+995995+ /* Fill the FW log file, consumed by the sysfs fwlog entry */996996+ memcpy(wl->fwlog + wl->fwlog_size, memblock, len);997997+ wl->fwlog_size += len;998998+999999+ return len;10001000+}10011001+10021002+static void wl12xx_read_fwlog_panic(struct wl1271 *wl)10031003+{10041004+ u32 addr;10051005+ u32 first_addr;10061006+ u8 *block;10071007+10081008+ if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) ||10091009+ (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||10101010+ (wl->conf.fwlog.mem_blocks == 0))10111011+ return;10121012+10131013+ wl1271_info("Reading FW panic log");10141014+10151015+ block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL);10161016+ if (!block)10171017+ return;10181018+10191019+ /*10201020+ * Make sure the chip is awake and the logger isn't active.10211021+ * This might fail if the firmware hanged.10221022+ */10231023+ if (!wl1271_ps_elp_wakeup(wl))10241024+ wl12xx_cmd_stop_fwlog(wl);10251025+10261026+ /* Read the first memory block address */10271027+ wl1271_fw_status(wl, wl->fw_status);10281028+ first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr);10291029+ if (!first_addr)10301030+ goto out;10311031+10321032+ /* Traverse the memory blocks linked list */10331033+ addr = first_addr;10341034+ do {10351035+ memset(block, 0, WL12XX_HW_BLOCK_SIZE);10361036+ wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE,10371037+ false);10381038+10391039+ /*10401040+ * Memory blocks are linked to one another. The first 4 bytes10411041+ * of each memory block hold the hardware address of the next10421042+ * one. The last memory block points to the first one.10431043+ */10441044+ addr = __le32_to_cpup((__le32 *)block);10451045+ if (!wl12xx_copy_fwlog(wl, block + sizeof(addr),10461046+ WL12XX_HW_BLOCK_SIZE - sizeof(addr)))10471047+ break;10481048+ } while (addr && (addr != first_addr));10491049+10501050+ wake_up_interruptible(&wl->fwlog_waitq);10511051+10521052+out:10531053+ kfree(block);10541054+}10551055+11291056static void wl1271_recovery_work(struct work_struct *work)11301057{11311058 struct wl1271 *wl =···12189791219980 if (wl->state != WL1271_STATE_ON)1220981 goto out;982982+983983+ /* Avoid a recursive recovery */984984+ set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);985985+986986+ wl12xx_read_fwlog_panic(wl);12219871222988 wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",1223989 wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));···12409961241997 /* reboot the chipset */1242998 __wl1271_op_remove_interface(wl, false);999999+10001000+ clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);10011001+12431002 ieee80211_restart_hw(wl->hw);1244100312451004 /*···13211074 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",13221075 wl->chip.id);1323107613241324- /* end-of-transaction flag should be set in wl127x AP mode */10771077+ /*10781078+ * 'end-of-transaction flag' and 'LPD mode flag'10791079+ * should be set in wl127x AP mode only10801080+ */13251081 if (wl->bss_type == BSS_TYPE_AP_BSS)13261326- wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;10821082+ wl->quirks |= (WL12XX_QUIRK_END_OF_TRANSACTION |10831083+ WL12XX_QUIRK_LPD_MODE);1327108413281085 ret = wl1271_setup(wl);13291086 if (ret < 0)···13401089 ret = wl1271_setup(wl);13411090 if (ret < 0)13421091 goto out;10921092+13431093 if (wl1271_set_block_size(wl))13441094 wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT;13451095 break;···1367111513681116out:13691117 return ret;13701370-}13711371-13721372-static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl)13731373-{13741374- unsigned int quirks = 0;13751375- unsigned int *fw_ver = wl->chip.fw_ver;13761376-13771377- /* Only for wl127x */13781378- if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&13791379- /* Check STA version */13801380- (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&13811381- (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||13821382- /* Check AP version */13831383- ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&13841384- (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))13851385- quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;13861386-13871387- return quirks;13881118}1389111913901120int wl1271_plt_start(struct wl1271 *wl)···14051171 wl1271_notice("firmware booted in PLT mode (%s)",14061172 wl->chip.fw_ver_str);1407117314081408- /* Check if any quirks are needed with older fw versions */14091409- wl->quirks |= wl1271_get_fw_ver_quirks(wl);14101174 goto out;1411117514121176irq_disable:···15841352};1585135315861354#ifdef CONFIG_PM15871587-static int wl1271_configure_suspend(struct wl1271 *wl)13551355+static int wl1271_configure_suspend_sta(struct wl1271 *wl)15881356{15891357 int ret;15901590-15911591- if (wl->bss_type != BSS_TYPE_STA_BSS)15921592- return 0;1593135815941359 mutex_lock(&wl->mutex);15951360···1632140316331404}1634140516351635-static void wl1271_configure_resume(struct wl1271 *wl)14061406+static int wl1271_configure_suspend_ap(struct wl1271 *wl)16361407{16371408 int ret;1638140916391639- if (wl->bss_type != BSS_TYPE_STA_BSS)14101410+ mutex_lock(&wl->mutex);14111411+14121412+ ret = wl1271_ps_elp_wakeup(wl);14131413+ if (ret < 0)14141414+ goto out_unlock;14151415+14161416+ ret = wl1271_acx_set_ap_beacon_filter(wl, true);14171417+14181418+ wl1271_ps_elp_sleep(wl);14191419+out_unlock:14201420+ mutex_unlock(&wl->mutex);14211421+ return ret;14221422+14231423+}14241424+14251425+static int wl1271_configure_suspend(struct wl1271 *wl)14261426+{14271427+ if (wl->bss_type == BSS_TYPE_STA_BSS)14281428+ return wl1271_configure_suspend_sta(wl);14291429+ if (wl->bss_type == BSS_TYPE_AP_BSS)14301430+ return wl1271_configure_suspend_ap(wl);14311431+ return 0;14321432+}14331433+14341434+static void wl1271_configure_resume(struct wl1271 *wl)14351435+{14361436+ int ret;14371437+ bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS;14381438+ bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS;14391439+14401440+ if (!is_sta && !is_ap)16401441 return;1641144216421443 mutex_lock(&wl->mutex);···16741415 if (ret < 0)16751416 goto out;1676141716771677- /* exit psm if it wasn't configured */16781678- if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))16791679- wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,16801680- wl->basic_rate, true);14181418+ if (is_sta) {14191419+ /* exit psm if it wasn't configured */14201420+ if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))14211421+ wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,14221422+ wl->basic_rate, true);14231423+ } else if (is_ap) {14241424+ wl1271_acx_set_ap_beacon_filter(wl, false);14251425+ }1681142616821427 wl1271_ps_elp_sleep(wl);16831428out:···16921429 struct cfg80211_wowlan *wow)16931430{16941431 struct wl1271 *wl = hw->priv;14321432+ int ret;14331433+16951434 wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);16961696- wl->wow_enabled = !!wow;16971697- if (wl->wow_enabled) {16981698- int ret;16991699- ret = wl1271_configure_suspend(wl);17001700- if (ret < 0) {17011701- wl1271_warning("couldn't prepare device to suspend");17021702- return ret;17031703- }17041704- /* flush any remaining work */17051705- wl1271_debug(DEBUG_MAC80211, "flushing remaining works");17061706- flush_delayed_work(&wl->scan_complete_work);14351435+ WARN_ON(!wow || !wow->any);1707143617081708- /*17091709- * disable and re-enable interrupts in order to flush17101710- * the threaded_irq17111711- */17121712- wl1271_disable_interrupts(wl);17131713-17141714- /*17151715- * set suspended flag to avoid triggering a new threaded_irq17161716- * work. no need for spinlock as interrupts are disabled.17171717- */17181718- set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);17191719-17201720- wl1271_enable_interrupts(wl);17211721- flush_work(&wl->tx_work);17221722- flush_delayed_work(&wl->pspoll_work);17231723- flush_delayed_work(&wl->elp_work);14371437+ wl->wow_enabled = true;14381438+ ret = wl1271_configure_suspend(wl);14391439+ if (ret < 0) {14401440+ wl1271_warning("couldn't prepare device to suspend");14411441+ return ret;17241442 }14431443+ /* flush any remaining work */14441444+ wl1271_debug(DEBUG_MAC80211, "flushing remaining works");14451445+ flush_delayed_work(&wl->scan_complete_work);14461446+14471447+ /*14481448+ * disable and re-enable interrupts in order to flush14491449+ * the threaded_irq14501450+ */14511451+ wl1271_disable_interrupts(wl);14521452+14531453+ /*14541454+ * set suspended flag to avoid triggering a new threaded_irq14551455+ * work. no need for spinlock as interrupts are disabled.14561456+ */14571457+ set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);14581458+14591459+ wl1271_enable_interrupts(wl);14601460+ flush_work(&wl->tx_work);14611461+ flush_delayed_work(&wl->pspoll_work);14621462+ flush_delayed_work(&wl->elp_work);14631463+17251464 return 0;17261465}1727146617281467static int wl1271_op_resume(struct ieee80211_hw *hw)17291468{17301469 struct wl1271 *wl = hw->priv;14701470+ unsigned long flags;14711471+ bool run_irq_work = false;14721472+17311473 wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",17321474 wl->wow_enabled);14751475+ WARN_ON(!wl->wow_enabled);1733147617341477 /*17351478 * re-enable irq_work enqueuing, and call irq_work directly if17361479 * there is a pending work.17371480 */17381738- if (wl->wow_enabled) {17391739- struct wl1271 *wl = hw->priv;17401740- unsigned long flags;17411741- bool run_irq_work = false;14811481+ spin_lock_irqsave(&wl->wl_lock, flags);14821482+ clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);14831483+ if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))14841484+ run_irq_work = true;14851485+ spin_unlock_irqrestore(&wl->wl_lock, flags);1742148617431743- spin_lock_irqsave(&wl->wl_lock, flags);17441744- clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);17451745- if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))17461746- run_irq_work = true;17471747- spin_unlock_irqrestore(&wl->wl_lock, flags);17481748-17491749- if (run_irq_work) {17501750- wl1271_debug(DEBUG_MAC80211,17511751- "run postponed irq_work directly");17521752- wl1271_irq(0, wl);17531753- wl1271_enable_interrupts(wl);17541754- }17551755-17561756- wl1271_configure_resume(wl);14871487+ if (run_irq_work) {14881488+ wl1271_debug(DEBUG_MAC80211,14891489+ "run postponed irq_work directly");14901490+ wl1271_irq(0, wl);14911491+ wl1271_enable_interrupts(wl);17571492 }14931493+ wl1271_configure_resume(wl);14941494+ wl->wow_enabled = false;1758149517591496 return 0;17601497}···18921629 strncpy(wiphy->fw_version, wl->chip.fw_ver_str,18931630 sizeof(wiphy->fw_version));1894163118951895- /* Check if any quirks are needed with older fw versions */18961896- wl->quirks |= wl1271_get_fw_ver_quirks(wl);18971897-18981632 /*18991633 * Now we know if 11a is supported (info from the NVS), so disable19001634 * 11a channels if not supported···19541694 cancel_delayed_work_sync(&wl->scan_complete_work);19551695 cancel_work_sync(&wl->netstack_work);19561696 cancel_work_sync(&wl->tx_work);16971697+ del_timer_sync(&wl->rx_streaming_timer);16981698+ cancel_work_sync(&wl->rx_streaming_enable_work);16991699+ cancel_work_sync(&wl->rx_streaming_disable_work);19571700 cancel_delayed_work_sync(&wl->pspoll_work);19581701 cancel_delayed_work_sync(&wl->elp_work);19591702···30432780 }30442781 }3045278230463046- if (changed & BSS_CHANGED_IBSS) {30473047- wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",30483048- bss_conf->ibss_joined);30493049-30503050- if (bss_conf->ibss_joined) {30513051- u32 rates = bss_conf->basic_rates;30523052- wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,30533053- rates);30543054- wl->basic_rate = wl1271_tx_min_rate_get(wl);30553055-30563056- /* by default, use 11b rates */30573057- wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;30583058- ret = wl1271_acx_sta_rate_policies(wl);30593059- if (ret < 0)30603060- goto out;30613061- }30623062- }30633063-30642783 ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);30652784 if (ret < 0)30662785 goto out;···32683023 }32693024 }3270302530263026+ if (changed & BSS_CHANGED_IBSS) {30273027+ wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",30283028+ bss_conf->ibss_joined);30293029+30303030+ if (bss_conf->ibss_joined) {30313031+ u32 rates = bss_conf->basic_rates;30323032+ wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,30333033+ rates);30343034+ wl->basic_rate = wl1271_tx_min_rate_get(wl);30353035+30363036+ /* by default, use 11b rates */30373037+ wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;30383038+ ret = wl1271_acx_sta_rate_policies(wl);30393039+ if (ret < 0)30403040+ goto out;30413041+ }30423042+ }30433043+32713044 ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);32723045 if (ret < 0)32733046 goto out;···33243061 wl1271_warning("cmd join failed %d", ret);33253062 goto out;33263063 }30643064+ wl1271_check_operstate(wl, ieee80211_get_operstate(vif));33273065 }3328306633293067out:···40483784static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR,40493785 wl1271_sysfs_show_hw_pg_ver, NULL);4050378637873787+static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,37883788+ struct bin_attribute *bin_attr,37893789+ char *buffer, loff_t pos, size_t count)37903790+{37913791+ struct device *dev = container_of(kobj, struct device, kobj);37923792+ struct wl1271 *wl = dev_get_drvdata(dev);37933793+ ssize_t len;37943794+ int ret;37953795+37963796+ ret = mutex_lock_interruptible(&wl->mutex);37973797+ if (ret < 0)37983798+ return -ERESTARTSYS;37993799+38003800+ /* Let only one thread read the log at a time, blocking others */38013801+ while (wl->fwlog_size == 0) {38023802+ DEFINE_WAIT(wait);38033803+38043804+ prepare_to_wait_exclusive(&wl->fwlog_waitq,38053805+ &wait,38063806+ TASK_INTERRUPTIBLE);38073807+38083808+ if (wl->fwlog_size != 0) {38093809+ finish_wait(&wl->fwlog_waitq, &wait);38103810+ break;38113811+ }38123812+38133813+ mutex_unlock(&wl->mutex);38143814+38153815+ schedule();38163816+ finish_wait(&wl->fwlog_waitq, &wait);38173817+38183818+ if (signal_pending(current))38193819+ return -ERESTARTSYS;38203820+38213821+ ret = mutex_lock_interruptible(&wl->mutex);38223822+ if (ret < 0)38233823+ return -ERESTARTSYS;38243824+ }38253825+38263826+ /* Check if the fwlog is still valid */38273827+ if (wl->fwlog_size < 0) {38283828+ mutex_unlock(&wl->mutex);38293829+ return 0;38303830+ }38313831+38323832+ /* Seeking is not supported - old logs are not kept. Disregard pos. */38333833+ len = min(count, (size_t)wl->fwlog_size);38343834+ wl->fwlog_size -= len;38353835+ memcpy(buffer, wl->fwlog, len);38363836+38373837+ /* Make room for new messages */38383838+ memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size);38393839+38403840+ mutex_unlock(&wl->mutex);38413841+38423842+ return len;38433843+}38443844+38453845+static struct bin_attribute fwlog_attr = {38463846+ .attr = {.name = "fwlog", .mode = S_IRUSR},38473847+ .read = wl1271_sysfs_read_fwlog,38483848+};38493849+40513850int wl1271_register_hw(struct wl1271 *wl)40523851{40533852 int ret;···42913964 INIT_WORK(&wl->tx_work, wl1271_tx_work);42923965 INIT_WORK(&wl->recovery_work, wl1271_recovery_work);42933966 INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);39673967+ INIT_WORK(&wl->rx_streaming_enable_work,39683968+ wl1271_rx_streaming_enable_work);39693969+ INIT_WORK(&wl->rx_streaming_disable_work,39703970+ wl1271_rx_streaming_disable_work);39713971+39723972+ wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");39733973+ if (!wl->freezable_wq) {39743974+ ret = -ENOMEM;39753975+ goto err_hw;39763976+ }39773977+42943978 wl->channel = WL1271_DEFAULT_CHANNEL;42953979 wl->beacon_int = WL1271_DEFAULT_BEACON_INT;42963980 wl->default_key = 0;···43273989 wl->quirks = 0;43283990 wl->platform_quirks = 0;43293991 wl->sched_scanning = false;39923992+ setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,39933993+ (unsigned long) wl);39943994+ wl->fwlog_size = 0;39953995+ init_waitqueue_head(&wl->fwlog_waitq);4330399643313997 memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));43323998 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)···43484006 wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);43494007 if (!wl->aggr_buf) {43504008 ret = -ENOMEM;43514351- goto err_hw;40094009+ goto err_wq;43524010 }4353401143544012 wl->dummy_packet = wl12xx_alloc_dummy_packet(wl);···43574015 goto err_aggr;43584016 }4359401740184018+ /* Allocate one page for the FW log */40194019+ wl->fwlog = (u8 *)get_zeroed_page(GFP_KERNEL);40204020+ if (!wl->fwlog) {40214021+ ret = -ENOMEM;40224022+ goto err_dummy_packet;40234023+ }40244024+43604025 /* Register platform device */43614026 ret = platform_device_register(wl->plat_dev);43624027 if (ret) {43634028 wl1271_error("couldn't register platform device");43644364- goto err_dummy_packet;40294029+ goto err_fwlog;43654030 }43664031 dev_set_drvdata(&wl->plat_dev->dev, wl);43674032···43864037 goto err_bt_coex_state;43874038 }4388403940404040+ /* Create sysfs file for the FW log */40414041+ ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr);40424042+ if (ret < 0) {40434043+ wl1271_error("failed to create sysfs file fwlog");40444044+ goto err_hw_pg_ver;40454045+ }40464046+43894047 return hw;40484048+40494049+err_hw_pg_ver:40504050+ device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver);4390405143914052err_bt_coex_state:43924053 device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);···44044045err_platform:44054046 platform_device_unregister(wl->plat_dev);4406404740484048+err_fwlog:40494049+ free_page((unsigned long)wl->fwlog);40504050+44074051err_dummy_packet:44084052 dev_kfree_skb(wl->dummy_packet);4409405344104054err_aggr:44114055 free_pages((unsigned long)wl->aggr_buf, order);40564056+40574057+err_wq:40584058+ destroy_workqueue(wl->freezable_wq);4412405944134060err_hw:44144061 wl1271_debugfs_exit(wl);···4431406644324067int wl1271_free_hw(struct wl1271 *wl)44334068{40694069+ /* Unblock any fwlog readers */40704070+ mutex_lock(&wl->mutex);40714071+ wl->fwlog_size = -1;40724072+ wake_up_interruptible_all(&wl->fwlog_waitq);40734073+ mutex_unlock(&wl->mutex);40744074+40754075+ device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr);44344076 platform_device_unregister(wl->plat_dev);40774077+ free_page((unsigned long)wl->fwlog);44354078 dev_kfree_skb(wl->dummy_packet);44364079 free_pages((unsigned long)wl->aggr_buf,44374080 get_order(WL1271_AGGR_BUFFER_SIZE));···4454408144554082 kfree(wl->fw_status);44564083 kfree(wl->tx_res_if);40844084+ destroy_workqueue(wl->freezable_wq);4457408544584086 ieee80211_free_hw(wl->hw);44594087···44664092EXPORT_SYMBOL_GPL(wl12xx_debug_level);44674093module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);44684094MODULE_PARM_DESC(debug_level, "wl12xx debugging level");40954095+40964096+module_param_named(fwlog, fwlog_param, charp, 0);40974097+MODULE_PARM_DESC(keymap,40984098+ "FW logger options: continuous, ondemand, dbgpins or disable");4469409944704100MODULE_LICENSE("GPL");44714101MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
+7-5
drivers/net/wireless/wl12xx/ps.c
···118118 &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));119119 if (ret == 0) {120120 wl1271_error("ELP wakeup timeout!");121121- ieee80211_queue_work(wl->hw, &wl->recovery_work);121121+ wl12xx_queue_recovery_work(wl);122122 ret = -ETIMEDOUT;123123 goto err;124124 } else if (ret < 0) {···169169 wl1271_debug(DEBUG_PSM, "leaving psm");170170171171 /* disable beacon early termination */172172- ret = wl1271_acx_bet_enable(wl, false);173173- if (ret < 0)174174- return ret;172172+ if (wl->band == IEEE80211_BAND_2GHZ) {173173+ ret = wl1271_acx_bet_enable(wl, false);174174+ if (ret < 0)175175+ return ret;176176+ }175177176178 /* disable beacon filtering */177179 ret = wl1271_acx_beacon_filter_opt(wl, false);···204202 info = IEEE80211_SKB_CB(skb);205203 info->flags |= IEEE80211_TX_STAT_TX_FILTERED;206204 info->status.rates[0].idx = -1;207207- ieee80211_tx_status(wl->hw, skb);205205+ ieee80211_tx_status_ni(wl->hw, skb);208206 filtered++;209207 }210208 }
+34-5
drivers/net/wireless/wl12xx/rx.c
···2222 */23232424#include <linux/gfp.h>2525+#include <linux/sched.h>25262627#include "wl12xx.h"2728#include "acx.h"···9695 struct ieee80211_hdr *hdr;9796 u8 *buf;9897 u8 beacon = 0;9898+ u8 is_data = 0;9999100100 /*101101 * In PLT mode we seem to get frames and mac80211 warns about them,···107105108106 /* the data read starts with the descriptor */109107 desc = (struct wl1271_rx_descriptor *) data;108108+109109+ if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) {110110+ size_t len = length - sizeof(*desc);111111+ wl12xx_copy_fwlog(wl, data + sizeof(*desc), len);112112+ wake_up_interruptible(&wl->fwlog_waitq);113113+ return 0;114114+ }110115111116 switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {112117 /* discard corrupted packets */···146137 hdr = (struct ieee80211_hdr *)skb->data;147138 if (ieee80211_is_beacon(hdr->frame_control))148139 beacon = 1;140140+ if (ieee80211_is_data_present(hdr->frame_control))141141+ is_data = 1;149142150143 wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);151144···158147 skb_trim(skb, skb->len - desc->pad_len);159148160149 skb_queue_tail(&wl->deferred_rx_queue, skb);161161- ieee80211_queue_work(wl->hw, &wl->netstack_work);150150+ queue_work(wl->freezable_wq, &wl->netstack_work);162151163163- return 0;152152+ return is_data;164153}165154166155void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)···173162 u32 mem_block;174163 u32 pkt_length;175164 u32 pkt_offset;165165+ bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);166166+ bool had_data = false;176167177168 while (drv_rx_counter != fw_rx_counter) {178169 buf_size = 0;···227214 * conditions, in that case the received frame will just228215 * be dropped.229216 */230230- wl1271_rx_handle_data(wl,231231- wl->aggr_buf + pkt_offset,232232- pkt_length);217217+ if (wl1271_rx_handle_data(wl,218218+ wl->aggr_buf + pkt_offset,219219+ pkt_length) == 1)220220+ had_data = true;221221+233222 wl->rx_counter++;234223 drv_rx_counter++;235224 drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;···245230 */246231 if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)247232 wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);233233+234234+ if (!is_ap && wl->conf.rx_streaming.interval && had_data &&235235+ (wl->conf.rx_streaming.always ||236236+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {237237+ u32 timeout = wl->conf.rx_streaming.duration;238238+239239+ /* restart rx streaming */240240+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))241241+ ieee80211_queue_work(wl->hw,242242+ &wl->rx_streaming_enable_work);243243+244244+ mod_timer(&wl->rx_streaming_timer,245245+ jiffies + msecs_to_jiffies(timeout));246246+ }248247}249248250249void wl1271_set_default_filters(struct wl1271 *wl)
···23232424#include <linux/irq.h>2525#include <linux/module.h>2626-#include <linux/crc7.h>2726#include <linux/vmalloc.h>2827#include <linux/mmc/sdio_func.h>2928#include <linux/mmc/sdio_ids.h>···4445#define SDIO_DEVICE_ID_TI_WL1271 0x40764546#endif46474747-static const struct sdio_device_id wl1271_devices[] = {4848+static const struct sdio_device_id wl1271_devices[] __devinitconst = {4849 { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },4950 {}5051};···106107 enable_irq(wl->irq);107108}108109109109-static void wl1271_sdio_reset(struct wl1271 *wl)110110-{111111-}112112-113113-static void wl1271_sdio_init(struct wl1271 *wl)114114-{115115-}116116-117110static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,118111 size_t len, bool fixed)119112{···161170 struct sdio_func *func = wl_to_func(wl);162171 int ret;163172164164- /* Make sure the card will not be powered off by runtime PM */165165- ret = pm_runtime_get_sync(&func->dev);166166- if (ret < 0)167167- goto out;173173+ /* If enabled, tell runtime PM not to power off the card */174174+ if (pm_runtime_enabled(&func->dev)) {175175+ ret = pm_runtime_get_sync(&func->dev);176176+ if (ret)177177+ goto out;178178+ }168179169180 /* Runtime PM might be disabled, so power up the card manually */170181 ret = mmc_power_restore_host(func->card->host);···193200 if (ret < 0)194201 return ret;195202196196- /* Let runtime PM know the card is powered off */197197- return pm_runtime_put_sync(&func->dev);203203+ /* If enabled, let runtime PM know the card is powered off */204204+ if (pm_runtime_enabled(&func->dev))205205+ ret = pm_runtime_put_sync(&func->dev);206206+207207+ return ret;198208}199209200210static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)···211215static struct wl1271_if_operations sdio_ops = {212216 .read = wl1271_sdio_raw_read,213217 .write = wl1271_sdio_raw_write,214214- .reset = wl1271_sdio_reset,215215- .init = wl1271_sdio_init,216218 .power = wl1271_sdio_set_power,217219 .dev = wl1271_sdio_wl_to_dev,218220 .enable_irq = wl1271_sdio_enable_interrupts,···272278 goto out_free;273279 }274280275275- enable_irq_wake(wl->irq);276276- device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);281281+ ret = enable_irq_wake(wl->irq);282282+ if (!ret) {283283+ wl->irq_wake_enabled = true;284284+ device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);277285286286+ /* if sdio can keep power while host is suspended, enable wow */287287+ mmcflags = sdio_get_host_pm_caps(func);288288+ wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);289289+290290+ if (mmcflags & MMC_PM_KEEP_POWER)291291+ hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;292292+ }278293 disable_irq(wl->irq);279279-280280- /* if sdio can keep power while host is suspended, enable wow */281281- mmcflags = sdio_get_host_pm_caps(func);282282- wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);283283-284284- if (mmcflags & MMC_PM_KEEP_POWER)285285- hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;286294287295 ret = wl1271_init_ieee80211(wl);288296 if (ret)···298302299303 /* Tell PM core that we don't need the card to be powered now */300304 pm_runtime_put_noidle(&func->dev);301301-302302- wl1271_notice("initialized");303305304306 return 0;305307···318324 pm_runtime_get_noresume(&func->dev);319325320326 wl1271_unregister_hw(wl);321321- device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);322322- disable_irq_wake(wl->irq);327327+ if (wl->irq_wake_enabled) {328328+ device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);329329+ disable_irq_wake(wl->irq);330330+ }323331 free_irq(wl->irq, wl);324332 wl1271_free_hw(wl);325333}···398402399403static int __init wl1271_init(void)400404{401401- int ret;402402-403403- ret = sdio_register_driver(&wl1271_sdio_driver);404404- if (ret < 0) {405405- wl1271_error("failed to register sdio driver: %d", ret);406406- goto out;407407- }408408-409409-out:410410- return ret;405405+ return sdio_register_driver(&wl1271_sdio_driver);411406}412407413408static void __exit wl1271_exit(void)414409{415410 sdio_unregister_driver(&wl1271_sdio_driver);416416-417417- wl1271_notice("unloaded");418411}419412420413module_init(wl1271_init);
+1-14
drivers/net/wireless/wl12xx/spi.c
···436436 if (ret)437437 goto out_irq;438438439439- wl1271_notice("initialized");440440-441439 return 0;442440443441 out_irq:···472474473475static int __init wl1271_init(void)474476{475475- int ret;476476-477477- ret = spi_register_driver(&wl1271_spi_driver);478478- if (ret < 0) {479479- wl1271_error("failed to register spi driver: %d", ret);480480- goto out;481481- }482482-483483-out:484484- return ret;477477+ return spi_register_driver(&wl1271_spi_driver);485478}486479487480static void __exit wl1271_exit(void)488481{489482 spi_unregister_driver(&wl1271_spi_driver);490490-491491- wl1271_notice("unloaded");492483}493484494485module_init(wl1271_init);
···226226#define FW_VER_MINOR_1_SPARE_STA_MIN 58227227#define FW_VER_MINOR_1_SPARE_AP_MIN 47228228229229+#define FW_VER_MINOR_FWLOG_STA_MIN 70230230+229231struct wl1271_chip {230232 u32 id;231233 char fw_ver_str[ETHTOOL_BUSINFO_LEN];···286284 u8 tx_total;287285 u8 reserved1;288286 __le16 reserved2;289289- /* Total structure size is 68 bytes */290290- u32 padding;287287+ __le32 log_start_addr;291288} __packed;292289293290struct wl1271_fw_full_status {···360359 WL1271_FLAG_DUMMY_PACKET_PENDING,361360 WL1271_FLAG_SUSPENDED,362361 WL1271_FLAG_PENDING_WORK,362362+ WL1271_FLAG_SOFT_GEMINI,363363+ WL1271_FLAG_RX_STREAMING_STARTED,364364+ WL1271_FLAG_RECOVERY_IN_PROGRESS,363365};364366365367struct wl1271_link {···447443 struct sk_buff_head deferred_tx_queue;448444449445 struct work_struct tx_work;446446+ struct workqueue_struct *freezable_wq;450447451448 /* Pending TX frames */452449 unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)];···472467473468 /* Network stack work */474469 struct work_struct netstack_work;470470+471471+ /* FW log buffer */472472+ u8 *fwlog;473473+474474+ /* Number of valid bytes in the FW log buffer */475475+ ssize_t fwlog_size;476476+477477+ /* Sysfs FW log entry readers wait queue */478478+ wait_queue_head_t fwlog_waitq;475479476480 /* Hardware recovery work */477481 struct work_struct recovery_work;···521507522508 /* Default key (for WEP) */523509 u32 default_key;510510+511511+ /* Rx Streaming */512512+ struct work_struct rx_streaming_enable_work;513513+ struct work_struct rx_streaming_disable_work;514514+ struct timer_list rx_streaming_timer;524515525516 unsigned int filters;526517 unsigned int rx_config;···592573 * (currently, only "ANY" trigger is supported)593574 */594575 bool wow_enabled;576576+ bool irq_wake_enabled;595577596578 /*597579 * AP-mode - links indexed by HLID. The global and broadcast links···622602623603int wl1271_plt_start(struct wl1271 *wl);624604int wl1271_plt_stop(struct wl1271 *wl);605605+int wl1271_recalc_rx_streaming(struct wl1271 *wl);606606+void wl12xx_queue_recovery_work(struct wl1271 *wl);607607+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);625608626609#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */627610···659636660637/* WL128X requires aggregated packets to be aligned to the SDIO block size */661638#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)639639+640640+/*641641+ * WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power642642+ * consumption643643+ */644644+#define WL12XX_QUIRK_LPD_MODE BIT(3)645645+646646+/* Older firmwares did not implement the FW logger over bus feature */647647+#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4)648648+649649+#define WL12XX_HW_BLOCK_SIZE 256662650663651#endif
+12-12
drivers/nfc/Kconfig
···22# Near Field Communication (NFC) devices33#4455-menuconfig NFC_DEVICES66- bool "Near Field Communication (NFC) devices"77- default n88- ---help---99- You'll have to say Y if your computer contains an NFC device that1010- you want to use under Linux.1111-1212- You can say N here if you don't have any Near Field Communication1313- devices connected to your computer.1414-1515-if NFC_DEVICES55+menu "Near Field Communication (NFC) devices"66+ depends on NFC167178config PN544_NFC189 tristate "PN544 NFC driver"···1726 To compile this driver as a module, choose m here. The module will1827 be called pn544.19282929+config NFC_PN5333030+ tristate "NXP PN533 USB driver"3131+ depends on USB3232+ help3333+ NXP PN533 USB driver.3434+ This driver provides support for NFC NXP PN533 devices.20352121-endif # NFC_DEVICES3636+ Say Y here to compile support for PN533 devices into the3737+ kernel or say M to compile it as module (pn533).3838+3939+endmenu
···11+/*22+ * Copyright (C) 2011 Instituto Nokia de Tecnologia33+ *44+ * Authors:55+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>66+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>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 the2020+ * Free Software Foundation, Inc.,2121+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.2222+ */2323+2424+#ifndef __LINUX_NFC_H2525+#define __LINUX_NFC_H2626+2727+#include <linux/types.h>2828+#include <linux/socket.h>2929+3030+#define NFC_GENL_NAME "nfc"3131+#define NFC_GENL_VERSION 13232+3333+#define NFC_GENL_MCAST_EVENT_NAME "events"3434+3535+/**3636+ * enum nfc_commands - supported nfc commands3737+ *3838+ * @NFC_CMD_UNSPEC: unspecified command3939+ *4040+ * @NFC_CMD_GET_DEVICE: request information about a device (requires4141+ * %NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices4242+ * @NFC_CMD_START_POLL: start polling for targets using the given protocols4343+ * (requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS)4444+ * @NFC_CMD_STOP_POLL: stop polling for targets (requires4545+ * %NFC_ATTR_DEVICE_INDEX)4646+ * @NFC_CMD_GET_TARGET: dump all targets found by the previous poll (requires4747+ * %NFC_ATTR_DEVICE_INDEX)4848+ * @NFC_EVENT_TARGETS_FOUND: event emitted when a new target is found4949+ * (it sends %NFC_ATTR_DEVICE_INDEX)5050+ * @NFC_EVENT_DEVICE_ADDED: event emitted when a new device is registred5151+ * (it sends %NFC_ATTR_DEVICE_NAME, %NFC_ATTR_DEVICE_INDEX and5252+ * %NFC_ATTR_PROTOCOLS)5353+ * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed5454+ * (it sends %NFC_ATTR_DEVICE_INDEX)5555+ */5656+enum nfc_commands {5757+ NFC_CMD_UNSPEC,5858+ NFC_CMD_GET_DEVICE,5959+ NFC_CMD_START_POLL,6060+ NFC_CMD_STOP_POLL,6161+ NFC_CMD_GET_TARGET,6262+ NFC_EVENT_TARGETS_FOUND,6363+ NFC_EVENT_DEVICE_ADDED,6464+ NFC_EVENT_DEVICE_REMOVED,6565+/* private: internal use only */6666+ __NFC_CMD_AFTER_LAST6767+};6868+#define NFC_CMD_MAX (__NFC_CMD_AFTER_LAST - 1)6969+7070+/**7171+ * enum nfc_attrs - supported nfc attributes7272+ *7373+ * @NFC_ATTR_UNSPEC: unspecified attribute7474+ *7575+ * @NFC_ATTR_DEVICE_INDEX: index of nfc device7676+ * @NFC_ATTR_DEVICE_NAME: device name, max 8 chars7777+ * @NFC_ATTR_PROTOCOLS: nfc protocols - bitwise or-ed combination from7878+ * NFC_PROTO_*_MASK constants7979+ * @NFC_ATTR_TARGET_INDEX: index of the nfc target8080+ * @NFC_ATTR_TARGET_SENS_RES: NFC-A targets extra information such as NFCID8181+ * @NFC_ATTR_TARGET_SEL_RES: NFC-A targets extra information (useful if the8282+ * target is not NFC-Forum compliant)8383+ */8484+enum nfc_attrs {8585+ NFC_ATTR_UNSPEC,8686+ NFC_ATTR_DEVICE_INDEX,8787+ NFC_ATTR_DEVICE_NAME,8888+ NFC_ATTR_PROTOCOLS,8989+ NFC_ATTR_TARGET_INDEX,9090+ NFC_ATTR_TARGET_SENS_RES,9191+ NFC_ATTR_TARGET_SEL_RES,9292+/* private: internal use only */9393+ __NFC_ATTR_AFTER_LAST9494+};9595+#define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1)9696+9797+#define NFC_DEVICE_NAME_MAXSIZE 89898+9999+/* NFC protocols */100100+#define NFC_PROTO_JEWEL 1101101+#define NFC_PROTO_MIFARE 2102102+#define NFC_PROTO_FELICA 3103103+#define NFC_PROTO_ISO14443 4104104+#define NFC_PROTO_NFC_DEP 5105105+106106+#define NFC_PROTO_MAX 6107107+108108+/* NFC protocols masks used in bitsets */109109+#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL)110110+#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE)111111+#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA)112112+#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443)113113+#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP)114114+115115+struct sockaddr_nfc {116116+ sa_family_t sa_family;117117+ __u32 dev_idx;118118+ __u32 target_idx;119119+ __u32 nfc_protocol;120120+};121121+122122+/* NFC socket protocols */123123+#define NFC_SOCKPROTO_RAW 0124124+#define NFC_SOCKPROTO_MAX 1125125+126126+#endif /*__LINUX_NFC_H */
+39
include/linux/nl80211.h
···483483 * more background information, see484484 * http://wireless.kernel.org/en/users/Documentation/WoWLAN.485485 *486486+ * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver487487+ * the necessary information for supporting GTK rekey offload. This488488+ * feature is typically used during WoWLAN. The configuration data489489+ * is contained in %NL80211_ATTR_REKEY_DATA (which is nested and490490+ * contains the data in sub-attributes). After rekeying happened,491491+ * this command may also be sent by the driver as an MLME event to492492+ * inform userspace of the new replay counter.493493+ *486494 * @NL80211_CMD_MAX: highest used command number487495 * @__NL80211_CMD_AFTER_LAST: internal use488496 */···612604 NL80211_CMD_STOP_SCHED_SCAN,613605 NL80211_CMD_SCHED_SCAN_RESULTS,614606 NL80211_CMD_SCHED_SCAN_STOPPED,607607+608608+ NL80211_CMD_SET_REKEY_OFFLOAD,615609616610 /* add new commands above here */617611···1006996 * are managed in software: interfaces of these types aren't subject to1007997 * any restrictions in their number or combinations.1008998 *999999+ * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information10001000+ * necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.10011001+ *10091002 * @NL80211_ATTR_MAX: highest attribute number currently defined10101003 * @__NL80211_ATTR_AFTER_LAST: internal use10111004 */···1206119312071194 NL80211_ATTR_INTERFACE_COMBINATIONS,12081195 NL80211_ATTR_SOFTWARE_IFTYPES,11961196+11971197+ NL80211_ATTR_REKEY_DATA,1209119812101199 /* add attributes here, update the policy in nl80211.c */12111200···23742359 /* keep last */23752360 NUM_NL80211_PLINK_STATES,23762361 MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 123622362+};23632363+23642364+#define NL80211_KCK_LEN 1623652365+#define NL80211_KEK_LEN 1623662366+#define NL80211_REPLAY_CTR_LEN 823672367+23682368+/**23692369+ * enum nl80211_rekey_data - attributes for GTK rekey offload23702370+ * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes23712371+ * @NL80211_REKEY_DATA_KEK: key encryption key (binary)23722372+ * @NL80211_REKEY_DATA_KCK: key confirmation key (binary)23732373+ * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary)23742374+ * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal)23752375+ * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal)23762376+ */23772377+enum nl80211_rekey_data {23782378+ __NL80211_REKEY_DATA_INVALID,23792379+ NL80211_REKEY_DATA_KEK,23802380+ NL80211_REKEY_DATA_KCK,23812381+ NL80211_REKEY_DATA_REPLAY_CTR,23822382+23832383+ /* keep last */23842384+ NUM_NL80211_REKEY_DATA,23852385+ MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 123772386};2378238723792388#endif /* __LINUX_NL80211_H */
···11541154};1155115511561156/**11571157+ * struct cfg80211_gtk_rekey_data - rekey data11581158+ * @kek: key encryption key11591159+ * @kck: key confirmation key11601160+ * @replay_ctr: replay counter11611161+ */11621162+struct cfg80211_gtk_rekey_data {11631163+ u8 kek[NL80211_KEK_LEN];11641164+ u8 kck[NL80211_KCK_LEN];11651165+ u8 replay_ctr[NL80211_REPLAY_CTR_LEN];11661166+};11671167+11681168+/**11571169 * struct cfg80211_ops - backend description for wireless configuration11581170 *11591171 * This struct is registered by fullmac card drivers and/or wireless stacks···12081196 * @set_default_key: set the default key on an interface12091197 *12101198 * @set_default_mgmt_key: set the default management frame key on an interface11991199+ *12001200+ * @set_rekey_data: give the data necessary for GTK rekeying to the driver12111201 *12121202 * @add_beacon: Add a beacon with given parameters, @head, @interval12131203 * and @dtim_period will be valid, @tail is optional.···15131499 struct net_device *dev,15141500 struct cfg80211_sched_scan_request *request);15151501 int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev);15021502+15031503+ int (*set_rekey_data)(struct wiphy *wiphy, struct net_device *dev,15041504+ struct cfg80211_gtk_rekey_data *data);15161505};1517150615181507/*···30493032 */30503033void cfg80211_cqm_pktloss_notify(struct net_device *dev,30513034 const u8 *peer, u32 num_packets, gfp_t gfp);30353035+30363036+/**30373037+ * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying30383038+ * @dev: network device30393039+ * @bssid: BSSID of AP (to avoid races)30403040+ * @replay_ctr: new replay counter30413041+ */30423042+void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,30433043+ const u8 *replay_ctr, gfp_t gfp);3052304430533045/* Logging, debugging and troubleshooting/diagnostic helpers. */30543046
+47
include/net/mac80211.h
···16281628 * ask the device to suspend. This is only invoked when WoWLAN is16291629 * configured, otherwise the device is deconfigured completely and16301630 * reconfigured at resume time.16311631+ * The driver may also impose special conditions under which it16321632+ * wants to use the "normal" suspend (deconfigure), say if it only16331633+ * supports WoWLAN when the device is associated. In this case, it16341634+ * must return 1 from this function.16311635 *16321636 * @resume: If WoWLAN was configured, this indicates that mac80211 is16331637 * now resuming its operation, after this the device must be fully···16991695 * This callback will be called in the context of Rx. Called for drivers17001696 * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.17011697 * The callback must be atomic.16981698+ *16991699+ * @set_rekey_data: If the device supports GTK rekeying, for example while the17001700+ * host is suspended, it can assign this callback to retrieve the data17011701+ * necessary to do GTK rekeying, this is the KEK, KCK and replay counter.17021702+ * After rekeying was done it should (for example during resume) notify17031703+ * userspace of the new replay counter using ieee80211_gtk_rekey_notify().17021704 *17031705 * @hw_scan: Ask the hardware to service the scan request, no need to start17041706 * the scan state machine in stack. The scan must honour the channel···19181908 struct ieee80211_key_conf *conf,19191909 struct ieee80211_sta *sta,19201910 u32 iv32, u16 *phase1key);19111911+ void (*set_rekey_data)(struct ieee80211_hw *hw,19121912+ struct ieee80211_vif *vif,19131913+ struct cfg80211_gtk_rekey_data *data);19211914 int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,19221915 struct cfg80211_scan_request *req);19231916 void (*cancel_hw_scan)(struct ieee80211_hw *hw,···25942581void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,25952582 struct sk_buff *skb,25962583 enum ieee80211_tkip_key_type type, u8 *key);25842584+25852585+/**25862586+ * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying25872587+ * @vif: virtual interface the rekeying was done on25882588+ * @bssid: The BSSID of the AP, for checking association25892589+ * @replay_ctr: the new replay counter after GTK rekeying25902590+ * @gfp: allocation flags25912591+ */25922592+void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,25932593+ const u8 *replay_ctr, gfp_t gfp);25942594+25972595/**25982596 * ieee80211_wake_queue - wake specific queue25992597 * @hw: pointer as obtained from ieee80211_alloc_hw().···28682844 */28692845void ieee80211_sta_block_awake(struct ieee80211_hw *hw,28702846 struct ieee80211_sta *pubsta, bool block);28472847+28482848+/**28492849+ * ieee80211_iter_keys - iterate keys programmed into the device28502850+ * @hw: pointer obtained from ieee80211_alloc_hw()28512851+ * @vif: virtual interface to iterate, may be %NULL for all28522852+ * @iter: iterator function that will be called for each key28532853+ * @iter_data: custom data to pass to the iterator function28542854+ *28552855+ * This function can be used to iterate all the keys known to28562856+ * mac80211, even those that weren't previously programmed into28572857+ * the device. This is intended for use in WoWLAN if the device28582858+ * needs reprogramming of the keys during suspend. Note that due28592859+ * to locking reasons, it is also only safe to call this at few28602860+ * spots since it must hold the RTNL and be able to sleep.28612861+ */28622862+void ieee80211_iter_keys(struct ieee80211_hw *hw,28632863+ struct ieee80211_vif *vif,28642864+ void (*iter)(struct ieee80211_hw *hw,28652865+ struct ieee80211_vif *vif,28662866+ struct ieee80211_sta *sta,28672867+ struct ieee80211_key_conf *key,28682868+ void *data),28692869+ void *iter_data);2871287028722871/**28732872 * ieee80211_ap_probereq_get - retrieve a Probe Request template
+156
include/net/nfc.h
···11+/*22+ * Copyright (C) 2011 Instituto Nokia de Tecnologia33+ *44+ * Authors:55+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>66+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>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 the2020+ * Free Software Foundation, Inc.,2121+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.2222+ */2323+2424+#ifndef __NET_NFC_H2525+#define __NET_NFC_H2626+2727+#include <linux/device.h>2828+#include <linux/skbuff.h>2929+3030+#define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg)3131+#define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg)3232+#define nfc_dev_dbg(dev, fmt, arg...) dev_dbg((dev), fmt "\n", ## arg)3333+3434+struct nfc_dev;3535+3636+/**3737+ * data_exchange_cb_t - Definition of nfc_data_exchange callback3838+ *3939+ * @context: nfc_data_exchange cb_context parameter4040+ * @skb: response data4141+ * @err: If an error has occurred during data exchange, it is the4242+ * error number. Zero means no error.4343+ *4444+ * When a rx or tx package is lost or corrupted or the target gets out4545+ * of the operating field, err is -EIO.4646+ */4747+typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,4848+ int err);4949+5050+struct nfc_ops {5151+ int (*start_poll)(struct nfc_dev *dev, u32 protocols);5252+ void (*stop_poll)(struct nfc_dev *dev);5353+ int (*activate_target)(struct nfc_dev *dev, u32 target_idx,5454+ u32 protocol);5555+ void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);5656+ int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,5757+ struct sk_buff *skb, data_exchange_cb_t cb,5858+ void *cb_context);5959+};6060+6161+struct nfc_target {6262+ u32 idx;6363+ u32 supported_protocols;6464+ u16 sens_res;6565+ u8 sel_res;6666+};6767+6868+struct nfc_genl_data {6969+ u32 poll_req_pid;7070+ struct mutex genl_data_mutex;7171+};7272+7373+struct nfc_dev {7474+ unsigned idx;7575+ unsigned target_idx;7676+ struct nfc_target *targets;7777+ int n_targets;7878+ int targets_generation;7979+ spinlock_t targets_lock;8080+ struct device dev;8181+ bool polling;8282+ struct nfc_genl_data genl_data;8383+ u32 supported_protocols;8484+8585+ struct nfc_ops *ops;8686+};8787+#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)8888+8989+extern struct class nfc_class;9090+9191+struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,9292+ u32 supported_protocols);9393+9494+/**9595+ * nfc_free_device - free nfc device9696+ *9797+ * @dev: The nfc device to free9898+ */9999+static inline void nfc_free_device(struct nfc_dev *dev)100100+{101101+ put_device(&dev->dev);102102+}103103+104104+int nfc_register_device(struct nfc_dev *dev);105105+106106+void nfc_unregister_device(struct nfc_dev *dev);107107+108108+/**109109+ * nfc_set_parent_dev - set the parent device110110+ *111111+ * @nfc_dev: The nfc device whose parent is being set112112+ * @dev: The parent device113113+ */114114+static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,115115+ struct device *dev)116116+{117117+ nfc_dev->dev.parent = dev;118118+}119119+120120+/**121121+ * nfc_set_drvdata - set driver specifc data122122+ *123123+ * @dev: The nfc device124124+ * @data: Pointer to driver specifc data125125+ */126126+static inline void nfc_set_drvdata(struct nfc_dev *dev, void *data)127127+{128128+ dev_set_drvdata(&dev->dev, data);129129+}130130+131131+/**132132+ * nfc_get_drvdata - get driver specifc data133133+ *134134+ * @dev: The nfc device135135+ */136136+static inline void *nfc_get_drvdata(struct nfc_dev *dev)137137+{138138+ return dev_get_drvdata(&dev->dev);139139+}140140+141141+/**142142+ * nfc_device_name - get the nfc device name143143+ *144144+ * @dev: The nfc device whose name to return145145+ */146146+static inline const char *nfc_device_name(struct nfc_dev *dev)147147+{148148+ return dev_name(&dev->dev);149149+}150150+151151+struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp);152152+153153+int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,154154+ int ntargets);155155+156156+#endif /* __NET_NFC_H */
+1
net/Kconfig
···322322source "net/9p/Kconfig"323323source "net/caif/Kconfig"324324source "net/ceph/Kconfig"325325+source "net/nfc/Kconfig"325326326327327328endif # if NET
···544544 /* keys */545545 struct list_head key_list;546546547547+ /* count for keys needing tailroom space allocation */548548+ int crypto_tx_tailroom_needed_cnt;549549+547550 struct net_device *dev;548551 struct ieee80211_local *local;549552
+94-2
net/mac80211/key.c
···6161 return NULL;6262}63636464+static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)6565+{6666+ /*6767+ * When this count is zero, SKB resizing for allocating tailroom6868+ * for IV or MMIC is skipped. But, this check has created two race6969+ * cases in xmit path while transiting from zero count to one:7070+ *7171+ * 1. SKB resize was skipped because no key was added but just before7272+ * the xmit key is added and SW encryption kicks off.7373+ *7474+ * 2. SKB resize was skipped because all the keys were hw planted but7575+ * just before xmit one of the key is deleted and SW encryption kicks7676+ * off.7777+ *7878+ * In both the above case SW encryption will find not enough space for7979+ * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)8080+ *8181+ * Solution has been explained at8282+ * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net8383+ */8484+8585+ if (!sdata->crypto_tx_tailroom_needed_cnt++) {8686+ /*8787+ * Flush all XMIT packets currently using HW encryption or no8888+ * encryption at all if the count transition is from 0 -> 1.8989+ */9090+ synchronize_net();9191+ }9292+}9393+6494static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)6595{6696 struct ieee80211_sub_if_data *sdata;···131101132102 if (!ret) {133103 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;104104+105105+ if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||106106+ (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))107107+ sdata->crypto_tx_tailroom_needed_cnt--;108108+134109 return 0;135110 }136111···176141177142 sta = get_sta_for_key(key);178143 sdata = key->sdata;144144+145145+ if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||146146+ (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))147147+ increment_tailroom_need_count(sdata);179148180149 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)181150 sdata = container_of(sdata->bss,···433394 ieee80211_aes_key_free(key->u.ccmp.tfm);434395 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)435396 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);436436- if (key->local)397397+ if (key->local) {437398 ieee80211_debugfs_key_remove(key);399399+ key->sdata->crypto_tx_tailroom_needed_cnt--;400400+ }438401439402 kfree(key);440403}···493452 else494453 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);495454455455+ increment_tailroom_need_count(sdata);456456+496457 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);497458 __ieee80211_key_destroy(old_key);498459···541498542499 mutex_lock(&sdata->local->key_mtx);543500544544- list_for_each_entry(key, &sdata->key_list, list)501501+ sdata->crypto_tx_tailroom_needed_cnt = 0;502502+503503+ list_for_each_entry(key, &sdata->key_list, list) {504504+ increment_tailroom_need_count(sdata);545505 ieee80211_key_enable_hw_accel(key);506506+ }546507547508 mutex_unlock(&sdata->local->key_mtx);548509}510510+511511+void ieee80211_iter_keys(struct ieee80211_hw *hw,512512+ struct ieee80211_vif *vif,513513+ void (*iter)(struct ieee80211_hw *hw,514514+ struct ieee80211_vif *vif,515515+ struct ieee80211_sta *sta,516516+ struct ieee80211_key_conf *key,517517+ void *data),518518+ void *iter_data)519519+{520520+ struct ieee80211_local *local = hw_to_local(hw);521521+ struct ieee80211_key *key;522522+ struct ieee80211_sub_if_data *sdata;523523+524524+ ASSERT_RTNL();525525+526526+ mutex_lock(&local->key_mtx);527527+ if (vif) {528528+ sdata = vif_to_sdata(vif);529529+ list_for_each_entry(key, &sdata->key_list, list)530530+ iter(hw, &sdata->vif,531531+ key->sta ? &key->sta->sta : NULL,532532+ &key->conf, iter_data);533533+ } else {534534+ list_for_each_entry(sdata, &local->interfaces, list)535535+ list_for_each_entry(key, &sdata->key_list, list)536536+ iter(hw, &sdata->vif,537537+ key->sta ? &key->sta->sta : NULL,538538+ &key->conf, iter_data);539539+ }540540+ mutex_unlock(&local->key_mtx);541541+}542542+EXPORT_SYMBOL(ieee80211_iter_keys);549543550544void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)551545{···613533614534 mutex_unlock(&sdata->local->key_mtx);615535}536536+537537+538538+void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,539539+ const u8 *replay_ctr, gfp_t gfp)540540+{541541+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);542542+543543+ trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr);544544+545545+ cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);546546+}547547+EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
···749749 container_of(work, struct ieee80211_local,750750 dynamic_ps_enable_work);751751 struct ieee80211_sub_if_data *sdata = local->ps_sdata;752752- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;752752+ struct ieee80211_if_managed *ifmgd;753753 unsigned long flags;754754 int q;755755756756 /* can only happen when PS was just disabled anyway */757757 if (!sdata)758758 return;759759+760760+ ifmgd = &sdata->u.mgd;759761760762 if (local->hw.conf.flags & IEEE80211_CONF_PS)761763 return;
···1474147414751475/* device xmit handlers */1476147614771477-static int ieee80211_skb_resize(struct ieee80211_local *local,14771477+static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,14781478 struct sk_buff *skb,14791479 int head_need, bool may_encrypt)14801480{14811481+ struct ieee80211_local *local = sdata->local;14811482 int tail_need = 0;1482148314831483- /*14841484- * This could be optimised, devices that do full hardware14851485- * crypto (including TKIP MMIC) need no tailroom... But we14861486- * have no drivers for such devices currently.14871487- */14881488- if (may_encrypt) {14841484+ if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {14891485 tail_need = IEEE80211_ENCRYPT_TAILROOM;14901486 tail_need -= skb_tailroom(skb);14911487 tail_need = max_t(int, tail_need, 0);···15741578 headroom -= skb_headroom(skb);15751579 headroom = max_t(int, 0, headroom);1576158015771577- if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) {15811581+ if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {15781582 dev_kfree_skb(skb);15791583 rcu_read_unlock();15801584 return;···19411945 head_need += IEEE80211_ENCRYPT_HEADROOM;19421946 head_need += local->tx_headroom;19431947 head_need = max_t(int, 0, head_need);19441944- if (ieee80211_skb_resize(local, skb, head_need, true))19481948+ if (ieee80211_skb_resize(sdata, skb, head_need, true))19451949 goto fail;19461950 }19471951
+16
net/nfc/Kconfig
···11+#22+# NFC sybsystem configuration33+#44+55+menuconfig NFC66+ depends on NET && EXPERIMENTAL77+ tristate "NFC subsystem support (EXPERIMENTAL)"88+ default n99+ help1010+ Say Y here if you want to build support for NFC (Near field1111+ communication) devices.1212+1313+ To compile this support as a module, choose M here: the module will1414+ be called nfc.1515+1616+source "drivers/nfc/Kconfig"
+7
net/nfc/Makefile
···11+#22+# Makefile for the Linux NFC subsystem.33+#44+55+obj-$(CONFIG_NFC) += nfc.o66+77+nfc-objs := core.o netlink.o af_nfc.o rawsock.o
+98
net/nfc/af_nfc.c
···11+/*22+ * Copyright (C) 2011 Instituto Nokia de Tecnologia33+ *44+ * Authors:55+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>66+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>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 the2020+ * Free Software Foundation, Inc.,2121+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.2222+ */2323+2424+#include <linux/nfc.h>2525+2626+#include "nfc.h"2727+2828+static DEFINE_RWLOCK(proto_tab_lock);2929+static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX];3030+3131+static int nfc_sock_create(struct net *net, struct socket *sock, int proto,3232+ int kern)3333+{3434+ int rc = -EPROTONOSUPPORT;3535+3636+ if (net != &init_net)3737+ return -EAFNOSUPPORT;3838+3939+ if (proto < 0 || proto >= NFC_SOCKPROTO_MAX)4040+ return -EINVAL;4141+4242+ read_lock(&proto_tab_lock);4343+ if (proto_tab[proto] && try_module_get(proto_tab[proto]->owner)) {4444+ rc = proto_tab[proto]->create(net, sock, proto_tab[proto]);4545+ module_put(proto_tab[proto]->owner);4646+ }4747+ read_unlock(&proto_tab_lock);4848+4949+ return rc;5050+}5151+5252+static struct net_proto_family nfc_sock_family_ops = {5353+ .owner = THIS_MODULE,5454+ .family = PF_NFC,5555+ .create = nfc_sock_create,5656+};5757+5858+int nfc_proto_register(const struct nfc_protocol *nfc_proto)5959+{6060+ int rc;6161+6262+ if (nfc_proto->id < 0 || nfc_proto->id >= NFC_SOCKPROTO_MAX)6363+ return -EINVAL;6464+6565+ rc = proto_register(nfc_proto->proto, 0);6666+ if (rc)6767+ return rc;6868+6969+ write_lock(&proto_tab_lock);7070+ if (proto_tab[nfc_proto->id])7171+ rc = -EBUSY;7272+ else7373+ proto_tab[nfc_proto->id] = nfc_proto;7474+ write_unlock(&proto_tab_lock);7575+7676+ return rc;7777+}7878+EXPORT_SYMBOL(nfc_proto_register);7979+8080+void nfc_proto_unregister(const struct nfc_protocol *nfc_proto)8181+{8282+ write_lock(&proto_tab_lock);8383+ proto_tab[nfc_proto->id] = NULL;8484+ write_unlock(&proto_tab_lock);8585+8686+ proto_unregister(nfc_proto->proto);8787+}8888+EXPORT_SYMBOL(nfc_proto_unregister);8989+9090+int __init af_nfc_init(void)9191+{9292+ return sock_register(&nfc_sock_family_ops);9393+}9494+9595+void af_nfc_exit(void)9696+{9797+ sock_unregister(PF_NFC);9898+}
+468
net/nfc/core.c
···11+/*22+ * Copyright (C) 2011 Instituto Nokia de Tecnologia33+ *44+ * Authors:55+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>66+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>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 the2020+ * Free Software Foundation, Inc.,2121+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.2222+ */2323+2424+#include <linux/init.h>2525+#include <linux/kernel.h>2626+#include <linux/module.h>2727+#include <linux/slab.h>2828+2929+#include "nfc.h"3030+3131+#define VERSION "0.1"3232+3333+int nfc_devlist_generation;3434+DEFINE_MUTEX(nfc_devlist_mutex);3535+3636+int nfc_printk(const char *level, const char *format, ...)3737+{3838+ struct va_format vaf;3939+ va_list args;4040+ int r;4141+4242+ va_start(args, format);4343+4444+ vaf.fmt = format;4545+ vaf.va = &args;4646+4747+ r = printk("%sNFC: %pV\n", level, &vaf);4848+4949+ va_end(args);5050+5151+ return r;5252+}5353+EXPORT_SYMBOL(nfc_printk);5454+5555+/**5656+ * nfc_start_poll - start polling for nfc targets5757+ *5858+ * @dev: The nfc device that must start polling5959+ * @protocols: bitset of nfc protocols that must be used for polling6060+ *6161+ * The device remains polling for targets until a target is found or6262+ * the nfc_stop_poll function is called.6363+ */6464+int nfc_start_poll(struct nfc_dev *dev, u32 protocols)6565+{6666+ int rc;6767+6868+ nfc_dbg("dev_name=%s protocols=0x%x", dev_name(&dev->dev), protocols);6969+7070+ if (!protocols)7171+ return -EINVAL;7272+7373+ device_lock(&dev->dev);7474+7575+ if (!device_is_registered(&dev->dev)) {7676+ rc = -ENODEV;7777+ goto error;7878+ }7979+8080+ if (dev->polling) {8181+ rc = -EBUSY;8282+ goto error;8383+ }8484+8585+ rc = dev->ops->start_poll(dev, protocols);8686+ if (!rc)8787+ dev->polling = true;8888+8989+error:9090+ device_unlock(&dev->dev);9191+ return rc;9292+}9393+9494+/**9595+ * nfc_stop_poll - stop polling for nfc targets9696+ *9797+ * @dev: The nfc device that must stop polling9898+ */9999+int nfc_stop_poll(struct nfc_dev *dev)100100+{101101+ int rc = 0;102102+103103+ nfc_dbg("dev_name=%s", dev_name(&dev->dev));104104+105105+ device_lock(&dev->dev);106106+107107+ if (!device_is_registered(&dev->dev)) {108108+ rc = -ENODEV;109109+ goto error;110110+ }111111+112112+ if (!dev->polling) {113113+ rc = -EINVAL;114114+ goto error;115115+ }116116+117117+ dev->ops->stop_poll(dev);118118+ dev->polling = false;119119+120120+error:121121+ device_unlock(&dev->dev);122122+ return rc;123123+}124124+125125+/**126126+ * nfc_activate_target - prepare the target for data exchange127127+ *128128+ * @dev: The nfc device that found the target129129+ * @target_idx: index of the target that must be activated130130+ * @protocol: nfc protocol that will be used for data exchange131131+ */132132+int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)133133+{134134+ int rc;135135+136136+ nfc_dbg("dev_name=%s target_idx=%u protocol=%u", dev_name(&dev->dev),137137+ target_idx, protocol);138138+139139+ device_lock(&dev->dev);140140+141141+ if (!device_is_registered(&dev->dev)) {142142+ rc = -ENODEV;143143+ goto error;144144+ }145145+146146+ rc = dev->ops->activate_target(dev, target_idx, protocol);147147+148148+error:149149+ device_unlock(&dev->dev);150150+ return rc;151151+}152152+153153+/**154154+ * nfc_deactivate_target - deactivate a nfc target155155+ *156156+ * @dev: The nfc device that found the target157157+ * @target_idx: index of the target that must be deactivated158158+ */159159+int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)160160+{161161+ int rc = 0;162162+163163+ nfc_dbg("dev_name=%s target_idx=%u", dev_name(&dev->dev), target_idx);164164+165165+ device_lock(&dev->dev);166166+167167+ if (!device_is_registered(&dev->dev)) {168168+ rc = -ENODEV;169169+ goto error;170170+ }171171+172172+ dev->ops->deactivate_target(dev, target_idx);173173+174174+error:175175+ device_unlock(&dev->dev);176176+ return rc;177177+}178178+179179+/**180180+ * nfc_data_exchange - transceive data181181+ *182182+ * @dev: The nfc device that found the target183183+ * @target_idx: index of the target184184+ * @skb: data to be sent185185+ * @cb: callback called when the response is received186186+ * @cb_context: parameter for the callback function187187+ *188188+ * The user must wait for the callback before calling this function again.189189+ */190190+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,191191+ struct sk_buff *skb,192192+ data_exchange_cb_t cb,193193+ void *cb_context)194194+{195195+ int rc;196196+197197+ nfc_dbg("dev_name=%s target_idx=%u skb->len=%u", dev_name(&dev->dev),198198+ target_idx, skb->len);199199+200200+ device_lock(&dev->dev);201201+202202+ if (!device_is_registered(&dev->dev)) {203203+ rc = -ENODEV;204204+ kfree_skb(skb);205205+ goto error;206206+ }207207+208208+ rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context);209209+210210+error:211211+ device_unlock(&dev->dev);212212+ return rc;213213+}214214+215215+/**216216+ * nfc_alloc_skb - allocate a skb for data exchange responses217217+ *218218+ * @size: size to allocate219219+ * @gfp: gfp flags220220+ */221221+struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)222222+{223223+ struct sk_buff *skb;224224+ unsigned int total_size;225225+226226+ total_size = size + 1;227227+ skb = alloc_skb(total_size, gfp);228228+229229+ if (skb)230230+ skb_reserve(skb, 1);231231+232232+ return skb;233233+}234234+EXPORT_SYMBOL(nfc_alloc_skb);235235+236236+/**237237+ * nfc_targets_found - inform that targets were found238238+ *239239+ * @dev: The nfc device that found the targets240240+ * @targets: array of nfc targets found241241+ * @ntargets: targets array size242242+ *243243+ * The device driver must call this function when one or many nfc targets244244+ * are found. After calling this function, the device driver must stop245245+ * polling for targets.246246+ */247247+int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,248248+ int n_targets)249249+{250250+ int i;251251+252252+ nfc_dbg("dev_name=%s n_targets=%d", dev_name(&dev->dev), n_targets);253253+254254+ dev->polling = false;255255+256256+ for (i = 0; i < n_targets; i++)257257+ targets[i].idx = dev->target_idx++;258258+259259+ spin_lock_bh(&dev->targets_lock);260260+261261+ dev->targets_generation++;262262+263263+ kfree(dev->targets);264264+ dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),265265+ GFP_ATOMIC);266266+267267+ if (!dev->targets) {268268+ dev->n_targets = 0;269269+ spin_unlock_bh(&dev->targets_lock);270270+ return -ENOMEM;271271+ }272272+273273+ dev->n_targets = n_targets;274274+ spin_unlock_bh(&dev->targets_lock);275275+276276+ nfc_genl_targets_found(dev);277277+278278+ return 0;279279+}280280+EXPORT_SYMBOL(nfc_targets_found);281281+282282+static void nfc_release(struct device *d)283283+{284284+ struct nfc_dev *dev = to_nfc_dev(d);285285+286286+ nfc_dbg("dev_name=%s", dev_name(&dev->dev));287287+288288+ nfc_genl_data_exit(&dev->genl_data);289289+ kfree(dev->targets);290290+ kfree(dev);291291+}292292+293293+struct class nfc_class = {294294+ .name = "nfc",295295+ .dev_release = nfc_release,296296+};297297+EXPORT_SYMBOL(nfc_class);298298+299299+static int match_idx(struct device *d, void *data)300300+{301301+ struct nfc_dev *dev = to_nfc_dev(d);302302+ unsigned *idx = data;303303+304304+ return dev->idx == *idx;305305+}306306+307307+struct nfc_dev *nfc_get_device(unsigned idx)308308+{309309+ struct device *d;310310+311311+ d = class_find_device(&nfc_class, NULL, &idx, match_idx);312312+ if (!d)313313+ return NULL;314314+315315+ return to_nfc_dev(d);316316+}317317+318318+/**319319+ * nfc_allocate_device - allocate a new nfc device320320+ *321321+ * @ops: device operations322322+ * @supported_protocols: NFC protocols supported by the device323323+ */324324+struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,325325+ u32 supported_protocols)326326+{327327+ static atomic_t dev_no = ATOMIC_INIT(0);328328+ struct nfc_dev *dev;329329+330330+ if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||331331+ !ops->deactivate_target || !ops->data_exchange)332332+ return NULL;333333+334334+ if (!supported_protocols)335335+ return NULL;336336+337337+ dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL);338338+ if (!dev)339339+ return NULL;340340+341341+ dev->dev.class = &nfc_class;342342+ dev->idx = atomic_inc_return(&dev_no) - 1;343343+ dev_set_name(&dev->dev, "nfc%d", dev->idx);344344+ device_initialize(&dev->dev);345345+346346+ dev->ops = ops;347347+ dev->supported_protocols = supported_protocols;348348+349349+ spin_lock_init(&dev->targets_lock);350350+ nfc_genl_data_init(&dev->genl_data);351351+352352+ /* first generation must not be 0 */353353+ dev->targets_generation = 1;354354+355355+ return dev;356356+}357357+EXPORT_SYMBOL(nfc_allocate_device);358358+359359+/**360360+ * nfc_register_device - register a nfc device in the nfc subsystem361361+ *362362+ * @dev: The nfc device to register363363+ */364364+int nfc_register_device(struct nfc_dev *dev)365365+{366366+ int rc;367367+368368+ nfc_dbg("dev_name=%s", dev_name(&dev->dev));369369+370370+ mutex_lock(&nfc_devlist_mutex);371371+ nfc_devlist_generation++;372372+ rc = device_add(&dev->dev);373373+ mutex_unlock(&nfc_devlist_mutex);374374+375375+ if (rc < 0)376376+ return rc;377377+378378+ rc = nfc_genl_device_added(dev);379379+ if (rc)380380+ nfc_dbg("The userspace won't be notified that the device %s was"381381+ " added", dev_name(&dev->dev));382382+383383+384384+ return 0;385385+}386386+EXPORT_SYMBOL(nfc_register_device);387387+388388+/**389389+ * nfc_unregister_device - unregister a nfc device in the nfc subsystem390390+ *391391+ * @dev: The nfc device to unregister392392+ */393393+void nfc_unregister_device(struct nfc_dev *dev)394394+{395395+ int rc;396396+397397+ nfc_dbg("dev_name=%s", dev_name(&dev->dev));398398+399399+ mutex_lock(&nfc_devlist_mutex);400400+ nfc_devlist_generation++;401401+402402+ /* lock to avoid unregistering a device while an operation403403+ is in progress */404404+ device_lock(&dev->dev);405405+ device_del(&dev->dev);406406+ device_unlock(&dev->dev);407407+408408+ mutex_unlock(&nfc_devlist_mutex);409409+410410+ rc = nfc_genl_device_removed(dev);411411+ if (rc)412412+ nfc_dbg("The userspace won't be notified that the device %s"413413+ " was removed", dev_name(&dev->dev));414414+415415+}416416+EXPORT_SYMBOL(nfc_unregister_device);417417+418418+static int __init nfc_init(void)419419+{420420+ int rc;421421+422422+ nfc_info("NFC Core ver %s", VERSION);423423+424424+ rc = class_register(&nfc_class);425425+ if (rc)426426+ return rc;427427+428428+ rc = nfc_genl_init();429429+ if (rc)430430+ goto err_genl;431431+432432+ /* the first generation must not be 0 */433433+ nfc_devlist_generation = 1;434434+435435+ rc = rawsock_init();436436+ if (rc)437437+ goto err_rawsock;438438+439439+ rc = af_nfc_init();440440+ if (rc)441441+ goto err_af_nfc;442442+443443+ return 0;444444+445445+err_af_nfc:446446+ rawsock_exit();447447+err_rawsock:448448+ nfc_genl_exit();449449+err_genl:450450+ class_unregister(&nfc_class);451451+ return rc;452452+}453453+454454+static void __exit nfc_exit(void)455455+{456456+ af_nfc_exit();457457+ rawsock_exit();458458+ nfc_genl_exit();459459+ class_unregister(&nfc_class);460460+}461461+462462+subsys_initcall(nfc_init);463463+module_exit(nfc_exit);464464+465465+MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");466466+MODULE_DESCRIPTION("NFC Core ver " VERSION);467467+MODULE_VERSION(VERSION);468468+MODULE_LICENSE("GPL");
+537
net/nfc/netlink.c
···11+/*22+ * Copyright (C) 2011 Instituto Nokia de Tecnologia33+ *44+ * Authors:55+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>66+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>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 the2020+ * Free Software Foundation, Inc.,2121+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.2222+ */2323+2424+#include <net/genetlink.h>2525+#include <linux/nfc.h>2626+#include <linux/slab.h>2727+2828+#include "nfc.h"2929+3030+static struct genl_multicast_group nfc_genl_event_mcgrp = {3131+ .name = NFC_GENL_MCAST_EVENT_NAME,3232+};3333+3434+struct genl_family nfc_genl_family = {3535+ .id = GENL_ID_GENERATE,3636+ .hdrsize = 0,3737+ .name = NFC_GENL_NAME,3838+ .version = NFC_GENL_VERSION,3939+ .maxattr = NFC_ATTR_MAX,4040+};4141+4242+static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {4343+ [NFC_ATTR_DEVICE_INDEX] = { .type = NLA_U32 },4444+ [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,4545+ .len = NFC_DEVICE_NAME_MAXSIZE },4646+ [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },4747+};4848+4949+static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,5050+ struct netlink_callback *cb, int flags)5151+{5252+ void *hdr;5353+5454+ nfc_dbg("entry");5555+5656+ hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,5757+ &nfc_genl_family, flags, NFC_CMD_GET_TARGET);5858+ if (!hdr)5959+ return -EMSGSIZE;6060+6161+ genl_dump_check_consistent(cb, hdr, &nfc_genl_family);6262+6363+ NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx);6464+ NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS,6565+ target->supported_protocols);6666+ NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res);6767+ NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res);6868+6969+ return genlmsg_end(msg, hdr);7070+7171+nla_put_failure:7272+ genlmsg_cancel(msg, hdr);7373+ return -EMSGSIZE;7474+}7575+7676+static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)7777+{7878+ struct nfc_dev *dev;7979+ int rc;8080+ u32 idx;8181+8282+ rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,8383+ nfc_genl_family.attrbuf,8484+ nfc_genl_family.maxattr,8585+ nfc_genl_policy);8686+ if (rc < 0)8787+ return ERR_PTR(rc);8888+8989+ if (!nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX])9090+ return ERR_PTR(-EINVAL);9191+9292+ idx = nla_get_u32(nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX]);9393+9494+ dev = nfc_get_device(idx);9595+ if (!dev)9696+ return ERR_PTR(-ENODEV);9797+9898+ return dev;9999+}100100+101101+static int nfc_genl_dump_targets(struct sk_buff *skb,102102+ struct netlink_callback *cb)103103+{104104+ int i = cb->args[0];105105+ struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];106106+ int rc;107107+108108+ nfc_dbg("entry");109109+110110+ if (!dev) {111111+ dev = __get_device_from_cb(cb);112112+ if (IS_ERR(dev))113113+ return PTR_ERR(dev);114114+115115+ cb->args[1] = (long) dev;116116+ }117117+118118+ spin_lock_bh(&dev->targets_lock);119119+120120+ cb->seq = dev->targets_generation;121121+122122+ while (i < dev->n_targets) {123123+ rc = nfc_genl_send_target(skb, &dev->targets[i], cb,124124+ NLM_F_MULTI);125125+ if (rc < 0)126126+ break;127127+128128+ i++;129129+ }130130+131131+ spin_unlock_bh(&dev->targets_lock);132132+133133+ cb->args[0] = i;134134+135135+ return skb->len;136136+}137137+138138+static int nfc_genl_dump_targets_done(struct netlink_callback *cb)139139+{140140+ struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];141141+142142+ nfc_dbg("entry");143143+144144+ if (dev)145145+ nfc_put_device(dev);146146+147147+ return 0;148148+}149149+150150+int nfc_genl_targets_found(struct nfc_dev *dev)151151+{152152+ struct sk_buff *msg;153153+ void *hdr;154154+155155+ nfc_dbg("entry");156156+157157+ dev->genl_data.poll_req_pid = 0;158158+159159+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);160160+ if (!msg)161161+ return -ENOMEM;162162+163163+ hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,164164+ NFC_EVENT_TARGETS_FOUND);165165+ if (!hdr)166166+ goto free_msg;167167+168168+ NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);169169+170170+ genlmsg_end(msg, hdr);171171+172172+ return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);173173+174174+nla_put_failure:175175+ genlmsg_cancel(msg, hdr);176176+free_msg:177177+ nlmsg_free(msg);178178+ return -EMSGSIZE;179179+}180180+181181+int nfc_genl_device_added(struct nfc_dev *dev)182182+{183183+ struct sk_buff *msg;184184+ void *hdr;185185+186186+ nfc_dbg("entry");187187+188188+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);189189+ if (!msg)190190+ return -ENOMEM;191191+192192+ hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,193193+ NFC_EVENT_DEVICE_ADDED);194194+ if (!hdr)195195+ goto free_msg;196196+197197+ NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));198198+ NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);199199+ NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);200200+201201+ genlmsg_end(msg, hdr);202202+203203+ genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);204204+205205+ return 0;206206+207207+nla_put_failure:208208+ genlmsg_cancel(msg, hdr);209209+free_msg:210210+ nlmsg_free(msg);211211+ return -EMSGSIZE;212212+}213213+214214+int nfc_genl_device_removed(struct nfc_dev *dev)215215+{216216+ struct sk_buff *msg;217217+ void *hdr;218218+219219+ nfc_dbg("entry");220220+221221+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);222222+ if (!msg)223223+ return -ENOMEM;224224+225225+ hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,226226+ NFC_EVENT_DEVICE_REMOVED);227227+ if (!hdr)228228+ goto free_msg;229229+230230+ NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);231231+232232+ genlmsg_end(msg, hdr);233233+234234+ genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);235235+236236+ return 0;237237+238238+nla_put_failure:239239+ genlmsg_cancel(msg, hdr);240240+free_msg:241241+ nlmsg_free(msg);242242+ return -EMSGSIZE;243243+}244244+245245+static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,246246+ u32 pid, u32 seq,247247+ struct netlink_callback *cb,248248+ int flags)249249+{250250+ void *hdr;251251+252252+ nfc_dbg("entry");253253+254254+ hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags,255255+ NFC_CMD_GET_DEVICE);256256+ if (!hdr)257257+ return -EMSGSIZE;258258+259259+ if (cb)260260+ genl_dump_check_consistent(cb, hdr, &nfc_genl_family);261261+262262+ NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));263263+ NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);264264+ NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);265265+266266+ return genlmsg_end(msg, hdr);267267+268268+nla_put_failure:269269+ genlmsg_cancel(msg, hdr);270270+ return -EMSGSIZE;271271+}272272+273273+static int nfc_genl_dump_devices(struct sk_buff *skb,274274+ struct netlink_callback *cb)275275+{276276+ struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];277277+ struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];278278+ bool first_call = false;279279+280280+ nfc_dbg("entry");281281+282282+ if (!iter) {283283+ first_call = true;284284+ iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL);285285+ if (!iter)286286+ return -ENOMEM;287287+ cb->args[0] = (long) iter;288288+ }289289+290290+ mutex_lock(&nfc_devlist_mutex);291291+292292+ cb->seq = nfc_devlist_generation;293293+294294+ if (first_call) {295295+ nfc_device_iter_init(iter);296296+ dev = nfc_device_iter_next(iter);297297+ }298298+299299+ while (dev) {300300+ int rc;301301+302302+ rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid,303303+ cb->nlh->nlmsg_seq,304304+ cb, NLM_F_MULTI);305305+ if (rc < 0)306306+ break;307307+308308+ dev = nfc_device_iter_next(iter);309309+ }310310+311311+ mutex_unlock(&nfc_devlist_mutex);312312+313313+ cb->args[1] = (long) dev;314314+315315+ return skb->len;316316+}317317+318318+static int nfc_genl_dump_devices_done(struct netlink_callback *cb)319319+{320320+ struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];321321+322322+ nfc_dbg("entry");323323+324324+ nfc_device_iter_exit(iter);325325+ kfree(iter);326326+327327+ return 0;328328+}329329+330330+static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info)331331+{332332+ struct sk_buff *msg;333333+ struct nfc_dev *dev;334334+ u32 idx;335335+ int rc = -ENOBUFS;336336+337337+ nfc_dbg("entry");338338+339339+ if (!info->attrs[NFC_ATTR_DEVICE_INDEX])340340+ return -EINVAL;341341+342342+ idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);343343+344344+ dev = nfc_get_device(idx);345345+ if (!dev)346346+ return -ENODEV;347347+348348+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);349349+ if (!msg) {350350+ rc = -ENOMEM;351351+ goto out_putdev;352352+ }353353+354354+ rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq,355355+ NULL, 0);356356+ if (rc < 0)357357+ goto out_free;358358+359359+ nfc_put_device(dev);360360+361361+ return genlmsg_reply(msg, info);362362+363363+out_free:364364+ nlmsg_free(msg);365365+out_putdev:366366+ nfc_put_device(dev);367367+ return rc;368368+}369369+370370+static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)371371+{372372+ struct nfc_dev *dev;373373+ int rc;374374+ u32 idx;375375+ u32 protocols;376376+377377+ nfc_dbg("entry");378378+379379+ if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||380380+ !info->attrs[NFC_ATTR_PROTOCOLS])381381+ return -EINVAL;382382+383383+ idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);384384+ protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);385385+386386+ dev = nfc_get_device(idx);387387+ if (!dev)388388+ return -ENODEV;389389+390390+ mutex_lock(&dev->genl_data.genl_data_mutex);391391+392392+ rc = nfc_start_poll(dev, protocols);393393+ if (!rc)394394+ dev->genl_data.poll_req_pid = info->snd_pid;395395+396396+ mutex_unlock(&dev->genl_data.genl_data_mutex);397397+398398+ nfc_put_device(dev);399399+ return rc;400400+}401401+402402+static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)403403+{404404+ struct nfc_dev *dev;405405+ int rc;406406+ u32 idx;407407+408408+ nfc_dbg("entry");409409+410410+ if (!info->attrs[NFC_ATTR_DEVICE_INDEX])411411+ return -EINVAL;412412+413413+ idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);414414+415415+ dev = nfc_get_device(idx);416416+ if (!dev)417417+ return -ENODEV;418418+419419+ mutex_lock(&dev->genl_data.genl_data_mutex);420420+421421+ if (dev->genl_data.poll_req_pid != info->snd_pid) {422422+ rc = -EBUSY;423423+ goto out;424424+ }425425+426426+ rc = nfc_stop_poll(dev);427427+ dev->genl_data.poll_req_pid = 0;428428+429429+out:430430+ mutex_unlock(&dev->genl_data.genl_data_mutex);431431+ nfc_put_device(dev);432432+ return rc;433433+}434434+435435+static struct genl_ops nfc_genl_ops[] = {436436+ {437437+ .cmd = NFC_CMD_GET_DEVICE,438438+ .doit = nfc_genl_get_device,439439+ .dumpit = nfc_genl_dump_devices,440440+ .done = nfc_genl_dump_devices_done,441441+ .policy = nfc_genl_policy,442442+ },443443+ {444444+ .cmd = NFC_CMD_START_POLL,445445+ .doit = nfc_genl_start_poll,446446+ .policy = nfc_genl_policy,447447+ },448448+ {449449+ .cmd = NFC_CMD_STOP_POLL,450450+ .doit = nfc_genl_stop_poll,451451+ .policy = nfc_genl_policy,452452+ },453453+ {454454+ .cmd = NFC_CMD_GET_TARGET,455455+ .dumpit = nfc_genl_dump_targets,456456+ .done = nfc_genl_dump_targets_done,457457+ .policy = nfc_genl_policy,458458+ },459459+};460460+461461+static int nfc_genl_rcv_nl_event(struct notifier_block *this,462462+ unsigned long event, void *ptr)463463+{464464+ struct netlink_notify *n = ptr;465465+ struct class_dev_iter iter;466466+ struct nfc_dev *dev;467467+468468+ if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC)469469+ goto out;470470+471471+ nfc_dbg("NETLINK_URELEASE event from id %d", n->pid);472472+473473+ nfc_device_iter_init(&iter);474474+ dev = nfc_device_iter_next(&iter);475475+476476+ while (dev) {477477+ mutex_lock(&dev->genl_data.genl_data_mutex);478478+ if (dev->genl_data.poll_req_pid == n->pid) {479479+ nfc_stop_poll(dev);480480+ dev->genl_data.poll_req_pid = 0;481481+ }482482+ mutex_unlock(&dev->genl_data.genl_data_mutex);483483+ dev = nfc_device_iter_next(&iter);484484+ }485485+486486+ nfc_device_iter_exit(&iter);487487+488488+out:489489+ return NOTIFY_DONE;490490+}491491+492492+void nfc_genl_data_init(struct nfc_genl_data *genl_data)493493+{494494+ genl_data->poll_req_pid = 0;495495+ mutex_init(&genl_data->genl_data_mutex);496496+}497497+498498+void nfc_genl_data_exit(struct nfc_genl_data *genl_data)499499+{500500+ mutex_destroy(&genl_data->genl_data_mutex);501501+}502502+503503+static struct notifier_block nl_notifier = {504504+ .notifier_call = nfc_genl_rcv_nl_event,505505+};506506+507507+/**508508+ * nfc_genl_init() - Initialize netlink interface509509+ *510510+ * This initialization function registers the nfc netlink family.511511+ */512512+int __init nfc_genl_init(void)513513+{514514+ int rc;515515+516516+ rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,517517+ ARRAY_SIZE(nfc_genl_ops));518518+ if (rc)519519+ return rc;520520+521521+ rc = genl_register_mc_group(&nfc_genl_family, &nfc_genl_event_mcgrp);522522+523523+ netlink_register_notifier(&nl_notifier);524524+525525+ return rc;526526+}527527+528528+/**529529+ * nfc_genl_exit() - Deinitialize netlink interface530530+ *531531+ * This exit function unregisters the nfc netlink family.532532+ */533533+void nfc_genl_exit(void)534534+{535535+ netlink_unregister_notifier(&nl_notifier);536536+ genl_unregister_family(&nfc_genl_family);537537+}
+117
net/nfc/nfc.h
···11+/*22+ * Copyright (C) 2011 Instituto Nokia de Tecnologia33+ *44+ * Authors:55+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>66+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>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 the2020+ * Free Software Foundation, Inc.,2121+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.2222+ */2323+2424+#ifndef __LOCAL_NFC_H2525+#define __LOCAL_NFC_H2626+2727+#include <net/nfc.h>2828+#include <net/sock.h>2929+3030+__attribute__((format (printf, 2, 3)))3131+int nfc_printk(const char *level, const char *fmt, ...);3232+3333+#define nfc_info(fmt, arg...) nfc_printk(KERN_INFO, fmt, ##arg)3434+#define nfc_err(fmt, arg...) nfc_printk(KERN_ERR, fmt, ##arg)3535+#define nfc_dbg(fmt, arg...) pr_debug(fmt "\n", ##arg)3636+3737+struct nfc_protocol {3838+ int id;3939+ struct proto *proto;4040+ struct module *owner;4141+ int (*create)(struct net *net, struct socket *sock,4242+ const struct nfc_protocol *nfc_proto);4343+};4444+4545+struct nfc_rawsock {4646+ struct sock sk;4747+ struct nfc_dev *dev;4848+ u32 target_idx;4949+ struct work_struct tx_work;5050+ bool tx_work_scheduled;5151+};5252+#define nfc_rawsock(sk) ((struct nfc_rawsock *) sk)5353+#define to_rawsock_sk(_tx_work) \5454+ ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work))5555+5656+int __init rawsock_init(void);5757+void rawsock_exit(void);5858+5959+int __init af_nfc_init(void);6060+void af_nfc_exit(void);6161+int nfc_proto_register(const struct nfc_protocol *nfc_proto);6262+void nfc_proto_unregister(const struct nfc_protocol *nfc_proto);6363+6464+extern int nfc_devlist_generation;6565+extern struct mutex nfc_devlist_mutex;6666+6767+int __init nfc_genl_init(void);6868+void nfc_genl_exit(void);6969+7070+void nfc_genl_data_init(struct nfc_genl_data *genl_data);7171+void nfc_genl_data_exit(struct nfc_genl_data *genl_data);7272+7373+int nfc_genl_targets_found(struct nfc_dev *dev);7474+7575+int nfc_genl_device_added(struct nfc_dev *dev);7676+int nfc_genl_device_removed(struct nfc_dev *dev);7777+7878+struct nfc_dev *nfc_get_device(unsigned idx);7979+8080+static inline void nfc_put_device(struct nfc_dev *dev)8181+{8282+ put_device(&dev->dev);8383+}8484+8585+static inline void nfc_device_iter_init(struct class_dev_iter *iter)8686+{8787+ class_dev_iter_init(iter, &nfc_class, NULL, NULL);8888+}8989+9090+static inline struct nfc_dev *nfc_device_iter_next(struct class_dev_iter *iter)9191+{9292+ struct device *d = class_dev_iter_next(iter);9393+ if (!d)9494+ return NULL;9595+9696+ return to_nfc_dev(d);9797+}9898+9999+static inline void nfc_device_iter_exit(struct class_dev_iter *iter)100100+{101101+ class_dev_iter_exit(iter);102102+}103103+104104+int nfc_start_poll(struct nfc_dev *dev, u32 protocols);105105+106106+int nfc_stop_poll(struct nfc_dev *dev);107107+108108+int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);109109+110110+int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);111111+112112+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,113113+ struct sk_buff *skb,114114+ data_exchange_cb_t cb,115115+ void *cb_context);116116+117117+#endif /* __LOCAL_NFC_H */
+354
net/nfc/rawsock.c
···11+/*22+ * Copyright (C) 2011 Instituto Nokia de Tecnologia33+ *44+ * Authors:55+ * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>66+ * Lauro Ramos Venancio <lauro.venancio@openbossa.org>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 the2020+ * Free Software Foundation, Inc.,2121+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.2222+ */2323+2424+#include <net/tcp_states.h>2525+#include <linux/nfc.h>2626+2727+#include "nfc.h"2828+2929+static void rawsock_write_queue_purge(struct sock *sk)3030+{3131+ nfc_dbg("sk=%p", sk);3232+3333+ spin_lock_bh(&sk->sk_write_queue.lock);3434+ __skb_queue_purge(&sk->sk_write_queue);3535+ nfc_rawsock(sk)->tx_work_scheduled = false;3636+ spin_unlock_bh(&sk->sk_write_queue.lock);3737+}3838+3939+static void rawsock_report_error(struct sock *sk, int err)4040+{4141+ nfc_dbg("sk=%p err=%d", sk, err);4242+4343+ sk->sk_shutdown = SHUTDOWN_MASK;4444+ sk->sk_err = -err;4545+ sk->sk_error_report(sk);4646+4747+ rawsock_write_queue_purge(sk);4848+}4949+5050+static int rawsock_release(struct socket *sock)5151+{5252+ struct sock *sk = sock->sk;5353+5454+ nfc_dbg("sock=%p", sock);5555+5656+ sock_orphan(sk);5757+ sock_put(sk);5858+5959+ return 0;6060+}6161+6262+static int rawsock_connect(struct socket *sock, struct sockaddr *_addr,6363+ int len, int flags)6464+{6565+ struct sock *sk = sock->sk;6666+ struct sockaddr_nfc *addr = (struct sockaddr_nfc *)_addr;6767+ struct nfc_dev *dev;6868+ int rc = 0;6969+7070+ nfc_dbg("sock=%p sk=%p flags=%d", sock, sk, flags);7171+7272+ if (!addr || len < sizeof(struct sockaddr_nfc) ||7373+ addr->sa_family != AF_NFC)7474+ return -EINVAL;7575+7676+ nfc_dbg("addr dev_idx=%u target_idx=%u protocol=%u", addr->dev_idx,7777+ addr->target_idx, addr->nfc_protocol);7878+7979+ lock_sock(sk);8080+8181+ if (sock->state == SS_CONNECTED) {8282+ rc = -EISCONN;8383+ goto error;8484+ }8585+8686+ dev = nfc_get_device(addr->dev_idx);8787+ if (!dev) {8888+ rc = -ENODEV;8989+ goto error;9090+ }9191+9292+ if (addr->target_idx > dev->target_idx - 1 ||9393+ addr->target_idx < dev->target_idx - dev->n_targets) {9494+ rc = -EINVAL;9595+ goto error;9696+ }9797+9898+ if (addr->target_idx > dev->target_idx - 1 ||9999+ addr->target_idx < dev->target_idx - dev->n_targets) {100100+ rc = -EINVAL;101101+ goto error;102102+ }103103+104104+ rc = nfc_activate_target(dev, addr->target_idx, addr->nfc_protocol);105105+ if (rc)106106+ goto put_dev;107107+108108+ nfc_rawsock(sk)->dev = dev;109109+ nfc_rawsock(sk)->target_idx = addr->target_idx;110110+ sock->state = SS_CONNECTED;111111+ sk->sk_state = TCP_ESTABLISHED;112112+ sk->sk_state_change(sk);113113+114114+ release_sock(sk);115115+ return 0;116116+117117+put_dev:118118+ nfc_put_device(dev);119119+error:120120+ release_sock(sk);121121+ return rc;122122+}123123+124124+static int rawsock_add_header(struct sk_buff *skb)125125+{126126+127127+ if (skb_cow_head(skb, 1))128128+ return -ENOMEM;129129+130130+ *skb_push(skb, 1) = 0;131131+132132+ return 0;133133+}134134+135135+static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb,136136+ int err)137137+{138138+ struct sock *sk = (struct sock *) context;139139+140140+ BUG_ON(in_irq());141141+142142+ nfc_dbg("sk=%p err=%d", sk, err);143143+144144+ if (err)145145+ goto error;146146+147147+ err = rawsock_add_header(skb);148148+ if (err)149149+ goto error;150150+151151+ err = sock_queue_rcv_skb(sk, skb);152152+ if (err)153153+ goto error;154154+155155+ spin_lock_bh(&sk->sk_write_queue.lock);156156+ if (!skb_queue_empty(&sk->sk_write_queue))157157+ schedule_work(&nfc_rawsock(sk)->tx_work);158158+ else159159+ nfc_rawsock(sk)->tx_work_scheduled = false;160160+ spin_unlock_bh(&sk->sk_write_queue.lock);161161+162162+ sock_put(sk);163163+ return;164164+165165+error:166166+ rawsock_report_error(sk, err);167167+ sock_put(sk);168168+}169169+170170+static void rawsock_tx_work(struct work_struct *work)171171+{172172+ struct sock *sk = to_rawsock_sk(work);173173+ struct nfc_dev *dev = nfc_rawsock(sk)->dev;174174+ u32 target_idx = nfc_rawsock(sk)->target_idx;175175+ struct sk_buff *skb;176176+ int rc;177177+178178+ nfc_dbg("sk=%p target_idx=%u", sk, target_idx);179179+180180+ if (sk->sk_shutdown & SEND_SHUTDOWN) {181181+ rawsock_write_queue_purge(sk);182182+ return;183183+ }184184+185185+ skb = skb_dequeue(&sk->sk_write_queue);186186+187187+ sock_hold(sk);188188+ rc = nfc_data_exchange(dev, target_idx, skb,189189+ rawsock_data_exchange_complete, sk);190190+ if (rc) {191191+ rawsock_report_error(sk, rc);192192+ sock_put(sk);193193+ }194194+}195195+196196+static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,197197+ struct msghdr *msg, size_t len)198198+{199199+ struct sock *sk = sock->sk;200200+ struct sk_buff *skb;201201+ int rc;202202+203203+ nfc_dbg("sock=%p sk=%p len=%zu", sock, sk, len);204204+205205+ if (msg->msg_namelen)206206+ return -EOPNOTSUPP;207207+208208+ if (sock->state != SS_CONNECTED)209209+ return -ENOTCONN;210210+211211+ skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT,212212+ &rc);213213+ if (!skb)214214+ return rc;215215+216216+ rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);217217+ if (rc < 0) {218218+ kfree_skb(skb);219219+ return rc;220220+ }221221+222222+ spin_lock_bh(&sk->sk_write_queue.lock);223223+ __skb_queue_tail(&sk->sk_write_queue, skb);224224+ if (!nfc_rawsock(sk)->tx_work_scheduled) {225225+ schedule_work(&nfc_rawsock(sk)->tx_work);226226+ nfc_rawsock(sk)->tx_work_scheduled = true;227227+ }228228+ spin_unlock_bh(&sk->sk_write_queue.lock);229229+230230+ return len;231231+}232232+233233+static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,234234+ struct msghdr *msg, size_t len, int flags)235235+{236236+ int noblock = flags & MSG_DONTWAIT;237237+ struct sock *sk = sock->sk;238238+ struct sk_buff *skb;239239+ int copied;240240+ int rc;241241+242242+ nfc_dbg("sock=%p sk=%p len=%zu flags=%d", sock, sk, len, flags);243243+244244+ skb = skb_recv_datagram(sk, flags, noblock, &rc);245245+ if (!skb)246246+ return rc;247247+248248+ msg->msg_namelen = 0;249249+250250+ copied = skb->len;251251+ if (len < copied) {252252+ msg->msg_flags |= MSG_TRUNC;253253+ copied = len;254254+ }255255+256256+ rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);257257+258258+ skb_free_datagram(sk, skb);259259+260260+ return rc ? : copied;261261+}262262+263263+264264+static const struct proto_ops rawsock_ops = {265265+ .family = PF_NFC,266266+ .owner = THIS_MODULE,267267+ .release = rawsock_release,268268+ .bind = sock_no_bind,269269+ .connect = rawsock_connect,270270+ .socketpair = sock_no_socketpair,271271+ .accept = sock_no_accept,272272+ .getname = sock_no_getname,273273+ .poll = datagram_poll,274274+ .ioctl = sock_no_ioctl,275275+ .listen = sock_no_listen,276276+ .shutdown = sock_no_shutdown,277277+ .setsockopt = sock_no_setsockopt,278278+ .getsockopt = sock_no_getsockopt,279279+ .sendmsg = rawsock_sendmsg,280280+ .recvmsg = rawsock_recvmsg,281281+ .mmap = sock_no_mmap,282282+};283283+284284+static void rawsock_destruct(struct sock *sk)285285+{286286+ nfc_dbg("sk=%p", sk);287287+288288+ if (sk->sk_state == TCP_ESTABLISHED) {289289+ nfc_deactivate_target(nfc_rawsock(sk)->dev,290290+ nfc_rawsock(sk)->target_idx);291291+ nfc_put_device(nfc_rawsock(sk)->dev);292292+ }293293+294294+ skb_queue_purge(&sk->sk_receive_queue);295295+296296+ if (!sock_flag(sk, SOCK_DEAD)) {297297+ nfc_err("Freeing alive NFC raw socket %p", sk);298298+ return;299299+ }300300+}301301+302302+static int rawsock_create(struct net *net, struct socket *sock,303303+ const struct nfc_protocol *nfc_proto)304304+{305305+ struct sock *sk;306306+307307+ nfc_dbg("sock=%p", sock);308308+309309+ if (sock->type != SOCK_SEQPACKET)310310+ return -ESOCKTNOSUPPORT;311311+312312+ sock->ops = &rawsock_ops;313313+314314+ sk = sk_alloc(net, PF_NFC, GFP_KERNEL, nfc_proto->proto);315315+ if (!sk)316316+ return -ENOMEM;317317+318318+ sock_init_data(sock, sk);319319+ sk->sk_protocol = nfc_proto->id;320320+ sk->sk_destruct = rawsock_destruct;321321+ sock->state = SS_UNCONNECTED;322322+323323+ INIT_WORK(&nfc_rawsock(sk)->tx_work, rawsock_tx_work);324324+ nfc_rawsock(sk)->tx_work_scheduled = false;325325+326326+ return 0;327327+}328328+329329+static struct proto rawsock_proto = {330330+ .name = "NFC_RAW",331331+ .owner = THIS_MODULE,332332+ .obj_size = sizeof(struct nfc_rawsock),333333+};334334+335335+static const struct nfc_protocol rawsock_nfc_proto = {336336+ .id = NFC_SOCKPROTO_RAW,337337+ .proto = &rawsock_proto,338338+ .owner = THIS_MODULE,339339+ .create = rawsock_create340340+};341341+342342+int __init rawsock_init(void)343343+{344344+ int rc;345345+346346+ rc = nfc_proto_register(&rawsock_nfc_proto);347347+348348+ return rc;349349+}350350+351351+void rawsock_exit(void)352352+{353353+ nfc_proto_unregister(&rawsock_nfc_proto);354354+}