Commit bb9f8692 authored by Zhu Yi's avatar Zhu Yi Committed by John W. Linville

iwmc3200wifi: Add new Intel Wireless Multicomm 802.11 driver

This driver supports Intel's full MAC wireless multicomm 802.11 hardware.
Although the hardware is a 802.11agn device, we currently only support
802.11ag, in managed and ad-hoc mode (no AP mode for now).
Signed-off-by: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarSamuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e31a16d6
...@@ -501,5 +501,6 @@ source "drivers/net/wireless/zd1211rw/Kconfig" ...@@ -501,5 +501,6 @@ source "drivers/net/wireless/zd1211rw/Kconfig"
source "drivers/net/wireless/rt2x00/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig"
source "drivers/net/wireless/orinoco/Kconfig" source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/wl12xx/Kconfig" source "drivers/net/wireless/wl12xx/Kconfig"
source "drivers/net/wireless/iwmc3200wifi/Kconfig"
endmenu endmenu
...@@ -60,3 +60,5 @@ obj-$(CONFIG_ATH_COMMON) += ath/ ...@@ -60,3 +60,5 @@ obj-$(CONFIG_ATH_COMMON) += ath/
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_WL12XX) += wl12xx/ obj-$(CONFIG_WL12XX) += wl12xx/
obj-$(CONFIG_IWM) += iwmc3200wifi/
config IWM
tristate "Intel Wireless Multicomm 3200 WiFi driver"
depends on MMC && WLAN_80211 && EXPERIMENTAL
select LIB80211
select FW_LOADER
select RFKILL
config IWM_DEBUG
bool "Enable full debugging output in iwmc3200wifi"
depends on IWM && DEBUG_FS
---help---
This option will enable debug tracing and setting for iwm
You can set the debug level and module through debugfs. By
default all modules are set to the IWL_DL_ERR level.
To see the list of debug modules and levels, see iwm/debug.h
For example, if you want the full MLME debug output:
echo 0xff > /debug/iwm/phyN/debug/mlme
Or, if you want the full debug, for all modules:
echo 0xff > /debug/iwm/phyN/debug/level
echo 0xff > /debug/iwm/phyN/debug/modules
obj-$(CONFIG_IWM) := iwmc3200wifi.o
iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o rfkill.o
iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#ifndef __IWM_BUS_H__
#define __IWM_BUS_H__
#include "iwm.h"
struct iwm_if_ops {
int (*enable)(struct iwm_priv *iwm);
int (*disable)(struct iwm_priv *iwm);
int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
void (*debugfs_exit)(struct iwm_priv *iwm);
const char *umac_name;
const char *calib_lmac_name;
const char *lmac_name;
};
static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
{
return iwm->bus_ops->send_chunk(iwm, buf, count);
}
static inline int iwm_bus_enable(struct iwm_priv *iwm)
{
return iwm->bus_ops->enable(iwm);
}
static inline int iwm_bus_disable(struct iwm_priv *iwm)
{
return iwm->bus_ops->disable(iwm);
}
#endif
This diff is collapsed.
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#ifndef __IWM_CFG80211_H__
#define __IWM_CFG80211_H__
int iwm_cfg80211_inform_bss(struct iwm_priv *iwm);
struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev);
void iwm_wdev_free(struct iwm_priv *iwm);
#endif
This diff is collapsed.
This diff is collapsed.
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#ifndef __IWM_DEBUG_H__
#define __IWM_DEBUG_H__
#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a)
#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a)
#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a)
#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a)
#ifdef CONFIG_IWM_DEBUG
#define IWM_DEBUG_MODULE(i, level, module, f, a...) \
do { \
if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
dev_printk(KERN_INFO, (iwm_to_dev(i)), \
"%s " f, __func__ , ## a); \
} while (0)
#define IWM_HEXDUMP(i, level, module, pref, buf, len) \
do { \
if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET, \
16, 1, buf, len, 1); \
} while (0)
#else
#define IWM_DEBUG_MODULE(i, level, module, f, a...)
#define IWM_HEXDUMP(i, level, module, pref, buf, len)
#endif /* CONFIG_IWM_DEBUG */
/* Debug modules */
enum iwm_debug_module_id {
IWM_DM_BOOT = 0,
IWM_DM_FW,
IWM_DM_SDIO,
IWM_DM_NTF,
IWM_DM_RX,
IWM_DM_TX,
IWM_DM_MLME,
IWM_DM_CMD,
IWM_DM_WEXT,
__IWM_DM_NR,
};
#define IWM_DM_DEFAULT 0
#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a)
#define IWM_DBG_FW(i, l, f, a...) IWM_DEBUG_MODULE(i, l, FW, f, ## a)
#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a)
#define IWM_DBG_NTF(i, l, f, a...) IWM_DEBUG_MODULE(i, l, NTF, f, ## a)
#define IWM_DBG_RX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, RX, f, ## a)
#define IWM_DBG_TX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, TX, f, ## a)
#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a)
#define IWM_DBG_CMD(i, l, f, a...) IWM_DEBUG_MODULE(i, l, CMD, f, ## a)
#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a)
/* Debug levels */
enum iwm_debug_level {
IWM_DL_NONE = 0,
IWM_DL_ERR,
IWM_DL_WARN,
IWM_DL_INFO,
IWM_DL_DBG,
};
#define IWM_DL_DEFAULT IWM_DL_ERR
struct iwm_debugfs {
struct iwm_priv *iwm;
struct dentry *rootdir;
struct dentry *devdir;
struct dentry *dbgdir;
struct dentry *txdir;
struct dentry *rxdir;
struct dentry *busdir;
u32 dbg_level;
struct dentry *dbg_level_dentry;
unsigned long dbg_modules;
struct dentry *dbg_modules_dentry;
u8 dbg_module[__IWM_DM_NR];
struct dentry *dbg_module_dentries[__IWM_DM_NR];
struct dentry *txq_dentry;
struct dentry *tx_credit_dentry;
struct dentry *rx_ticket_dentry;
};
#ifdef CONFIG_IWM_DEBUG
int iwm_debugfs_init(struct iwm_priv *iwm);
void iwm_debugfs_exit(struct iwm_priv *iwm);
#else
static inline int iwm_debugfs_init(struct iwm_priv *iwm)
{
return 0;
}
static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
#endif
#endif
This diff is collapsed.
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
*/
#include <linux/kernel.h>
#include "iwm.h"
#include "umac.h"
#include "commands.h"
#include "eeprom.h"
static struct iwm_eeprom_entry eeprom_map[] = {
[IWM_EEPROM_SIG] =
{"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN},
[IWM_EEPROM_VERSION] =
{"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN},
[IWM_EEPROM_OEM_HW_VERSION] =
{"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF,
IWM_EEPROM_OEM_HW_VERSION_LEN},
[IWM_EEPROM_MAC_VERSION] =
{"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN},
[IWM_EEPROM_CARD_ID] =
{"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN},
[IWM_EEPROM_RADIO_CONF] =
{"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN},
[IWM_EEPROM_SKU_CAP] =
{"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN},
[IWM_EEPROM_CALIB_RXIQ_OFFSET] =
{"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN},
[IWM_EEPROM_CALIB_RXIQ] =
{"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN},
};
static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id)
{
int ret;
u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0;
u32 addr;
struct iwm_udma_wifi_cmd udma_cmd;
struct iwm_umac_cmd umac_cmd;
struct iwm_umac_cmd_eeprom_proxy eeprom_cmd;
if (eeprom_id > (IWM_EEPROM_LAST - 1))
return -EINVAL;
entry_size = eeprom_map[eeprom_id].length;
if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) {
/* indirect data */
u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA +
IWM_EEPROM_INDIRECT_OFFSET;
eeprom_map[eeprom_id].offset =
*(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1;
}
addr = eeprom_map[eeprom_id].offset;
udma_cmd.eop = 1;
udma_cmd.credit_group = 0x4;
udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD;
udma_cmd.lmac_offset = 0;
umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY;
umac_cmd.resp = 1;
while (entry_size > 0) {
chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN);
eeprom_cmd.hdr.type =
cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ);
eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset);
eeprom_cmd.hdr.len = cpu_to_le32(chunk_size);
ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd,
&umac_cmd, &eeprom_cmd,
sizeof(struct iwm_umac_cmd_eeprom_proxy));
if (ret < 0) {
IWM_ERR(iwm, "Couldn't read eeprom\n");
return ret;
}
ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY,
IWM_SRC_UMAC, 2*HZ);
if (ret < 0) {
IWM_ERR(iwm, "Did not get any eeprom answer\n");
return ret;
}
data_offset += chunk_size;
addr_offset += chunk_size;
entry_size -= chunk_size;
}
return 0;
}
u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id)
{
if (!iwm->eeprom)
return ERR_PTR(-ENODEV);
return iwm->eeprom + eeprom_map[eeprom_id].offset;
}
int iwm_eeprom_init(struct iwm_priv *iwm)
{
int i, ret = 0;
char name[32];
iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL);
if (!iwm->eeprom)
return -ENOMEM;
for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
#ifdef CONFIG_IWM_B0_HW_SUPPORT
if (iwm->conf.hw_b0 && (i >= IWM_EEPROM_INDIRECT_OFFSET))
break;
#endif
ret = iwm_eeprom_read(iwm, i);
if (ret < 0) {
IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n",
i, eeprom_map[i].name);
break;
}
}
IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n");
for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
memset(name, 0, 32);
sprintf(name, "%s: ", eeprom_map[i].name);
IWM_HEXDUMP(iwm, DBG, BOOT, name,
iwm->eeprom + eeprom_map[i].offset,
eeprom_map[i].length);
}
return ret;
}
void iwm_eeprom_exit(struct iwm_priv *iwm)
{
kfree(iwm->eeprom);
}
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
*/
#ifndef __IWM_EEPROM_H__
#define __IWM_EEPROM_H__
enum {
IWM_EEPROM_SIG = 0,
IWM_EEPROM_FIRST = IWM_EEPROM_SIG,
IWM_EEPROM_VERSION,
IWM_EEPROM_OEM_HW_VERSION,
IWM_EEPROM_MAC_VERSION,
IWM_EEPROM_CARD_ID,
IWM_EEPROM_RADIO_CONF,
IWM_EEPROM_SKU_CAP,
IWM_EEPROM_INDIRECT_OFFSET,
IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET,
IWM_EEPROM_INDIRECT_DATA,
IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA,
IWM_EEPROM_LAST,
};
#define IWM_EEPROM_SIG_OFF 0x00
#define IWM_EEPROM_VERSION_OFF (0x54 << 1)
#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1)
#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1)
#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1)
#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1)
#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1)
#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1)
#define IWM_EEPROM_SIG_LEN 4
#define IWM_EEPROM_VERSION_LEN 2
#define IWM_EEPROM_OEM_HW_VERSION_LEN 2
#define IWM_EEPROM_MAC_VERSION_LEN 1
#define IWM_EEPROM_CARD_ID_LEN 2
#define IWM_EEPROM_RADIO_CONF_LEN 2
#define IWM_EEPROM_SKU_CAP_LEN 2
#define IWM_EEPROM_INDIRECT_LEN 2
#define IWM_MAX_EEPROM_DATA_LEN 240
#define IWM_EEPROM_LEN 0x800
#define IWM_EEPROM_MIN_ALLOWED_VERSION 0x0610
#define IWM_EEPROM_MAX_ALLOWED_VERSION 0x0700
#define IWM_EEPROM_CURRENT_VERSION 0x0612
#define IWM_EEPROM_SKU_CAP_BAND_24GHZ (1 << 4)
#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
enum {
IWM_EEPROM_CALIB_CAL_HDR,
IWM_EEPROM_CALIB_TX_POWER,
IWM_EEPROM_CALIB_XTAL,
IWM_EEPROM_CALIB_TEMPERATURE,
IWM_EEPROM_CALIB_RX_BB_FILTER,
IWM_EEPROM_CALIB_RX_IQ,
IWM_EEPROM_CALIB_MAX,
};
#define IWM_EEPROM_CALIB_RXIQ_OFF (IWM_EEPROM_CALIB_CONFIG_OFF + \
(IWM_EEPROM_CALIB_RX_IQ << 1))
#define IWM_EEPROM_CALIB_RXIQ_LEN sizeof(struct iwm_lmac_calib_rxiq)
struct iwm_eeprom_entry {
char *name;
u32 offset;
u32 length;
};
int iwm_eeprom_init(struct iwm_priv *iwm);
void iwm_eeprom_exit(struct iwm_priv *iwm);
u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id);
#endif
This diff is collapsed.
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
*/
#ifndef __IWM_FW_H__
#define __IWM_FW_H__
/**
* struct iwm_fw_hdr_rec - An iwm firmware image is a
* concatenation of various records. Each of them is
* defined by an ID (aka op code), a length, and the
* actual data.
* @op_code: The record ID, see IWM_HDR_REC_OP_*
*
* @len: The record payload length
*
* @buf: The record payload
*/
struct iwm_fw_hdr_rec {
u16 op_code;
u16 len;
u8 buf[0];
};
/* Header's definitions */
#define IWM_HDR_LEN (512)
#define IWM_HDR_BARKER_LEN (16)
/* Header's opcodes */
#define IWM_HDR_REC_OP_INVALID (0x00)
#define IWM_HDR_REC_OP_BUILD_DATE (0x01)
#define IWM_HDR_REC_OP_BUILD_TAG (0x02)
#define IWM_HDR_REC_OP_SW_VER (0x03)
#define IWM_HDR_REC_OP_HW_SKU (0x04)
#define IWM_HDR_REC_OP_BUILD_OPT (0x05)
#define IWM_HDR_REC_OP_MEM_DESC (0x06)
#define IWM_HDR_REC_USERDEFS (0x07)
/* Header's records length (in bytes) */
#define IWM_HDR_REC_LEN_BUILD_DATE (4)
#define IWM_HDR_REC_LEN_BUILD_TAG (64)
#define IWM_HDR_REC_LEN_SW_VER (4)
#define IWM_HDR_REC_LEN_HW_SKU (4)
#define IWM_HDR_REC_LEN_BUILD_OPT (4)
#define IWM_HDR_REC_LEN_MEM_DESC (12)
#define IWM_HDR_REC_LEN_USERDEF (64)
#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff)
#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff)
#define IWM_BUILD_DAY(date) (date & 0xff)
struct iwm_fw_img_desc {
u32 offset;
u32 address;
u32 length;
};
struct iwm_fw_img_ver {
u8 minor;
u8 major;
u16 reserved;
};
int iwm_load_fw(struct iwm_priv *iwm);
#endif
This diff is collapsed.
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
*/
#ifndef _IWM_HAL_H_
#define _IWM_HAL_H_
#include "umac.h"
#define GET_VAL8(s, name) ((s >> name##_POS) & name##_SEED)
#define GET_VAL16(s, name) ((le16_to_cpu(s) >> name##_POS) & name##_SEED)
#define GET_VAL32(s, name) ((le32_to_cpu(s) >> name##_POS) & name##_SEED)
#define SET_VAL8(s, name, val) \
do { \
s = (s & ~(name##_SEED << name##_POS)) | \
((val & name##_SEED) << name##_POS); \
} while (0)
#define SET_VAL16(s, name, val) \
do { \
s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
((val & name##_SEED) << name##_POS)); \
} while (0)
#define SET_VAL32(s, name, val) \
do { \
s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
((val & name##_SEED) << name##_POS)); \
} while (0)
#define UDMA_UMAC_INIT { .eop = 1, \
.credit_group = 0x4, \
.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
.lmac_offset = 0 }
#define UDMA_LMAC_INIT { .eop = 1, \
.credit_group = 0x4, \
.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
.lmac_offset = 4 }
/* UDMA IN OP CODE -- cmd bits [3:0] */
#define UDMA_IN_OPCODE_MASK 0xF
#define UDMA_IN_OPCODE_GENERAL_RESP 0x0
#define UDMA_IN_OPCODE_READ_RESP 0x1
#define UDMA_IN_OPCODE_WRITE_RESP 0x2
#define UDMA_IN_OPCODE_PERS_WRITE_RESP 0x5
#define UDMA_IN_OPCODE_PERS_READ_RESP 0x6
#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP 0x7
#define UDMA_IN_OPCODE_EP_MNGMT_MSG 0x8
#define UDMA_IN_OPCODE_CRDT_CHNG_MSG 0x9
#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG 0xA
#define UDMA_IN_OPCODE_SW_MSG 0xB
#define UDMA_IN_OPCODE_WIFI 0xF
#define UDMA_IN_OPCODE_WIFI_LMAC 0x1F
#define UDMA_IN_OPCODE_WIFI_UMAC 0x2F
/* HW API: udma_hdi_nonwifi API (OUT and IN) */
/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */
#define UDMA_HDI_OUT_NW_CMD_RESP_POS 9
#define UDMA_HDI_OUT_NW_CMD_RESP_SEED 0x1
/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */
#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS 11
#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED 0x1
/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */
#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS 12
#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED 0xF
/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */
#define UDMA_IN_NW_HW_SEQ_NUM_POS 12
#define UDMA_IN_NW_HW_SEQ_NUM_SEED 0xF
/* UDMA IN Non-WIFI HW signature -- bits [16:31] */
#define UDMA_IN_NW_HW_SIG_POS 16
#define UDMA_IN_NW_HW_SIG_SEED 0xFFFF
/* fixed signature */
#define UDMA_IN_NW_HW_SIG 0xCBBC
/* UDMA IN Non-WIFI HW block length -- bits [32:35] */
#define UDMA_IN_NW_HW_LENGTH_SEED 0xF
#define UDMA_IN_NW_HW_LENGTH_POS 32
/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */
#define IWM_SDIO_FW_MAX_CHUNK_SIZE 2032
#define IWM_MAX_WIFI_HEADERS_SIZE 32
#define IWM_MAX_NONWIFI_HEADERS_SIZE 16
#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
IWM_MAX_NONWIFI_HEADERS_SIZE)
#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
IWM_MAX_WIFI_HEADERS_SIZE)
#define IWM_HAL_CONCATENATE_BUF_SIZE 8192
struct iwm_wifi_cmd_buff {
u16 len;
u8 *start;
u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE];
u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE];
};
struct iwm_nonwifi_cmd_buff {
u16 len;
u8 *start;
u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE];
u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE];
};
struct iwm_udma_nonwifi_cmd {
u8 opcode;
u8 eop;
u8 resp;
u8 handle_by_hw;
__le32 addr;
__le32 op1_sz;
__le32 op2;
__le16 seq_num;
};
struct iwm_udma_wifi_cmd {
__le16 count;
u8 eop;
u8 credit_group;
u8 ra_tid;
u8 lmac_offset;
};
struct iwm_umac_cmd {
u8 id;
__le16 count;
u8 resp;
__le16 seq_num;
u8 color;
};
struct iwm_lmac_cmd {
u8 id;
__le16 count;
u8 resp;
__le16 seq_num;
};
struct iwm_nonwifi_cmd {
u16 seq_num;
bool resp_received;
struct list_head pending;
struct iwm_udma_nonwifi_cmd udma_cmd;
struct iwm_umac_cmd umac_cmd;
struct iwm_lmac_cmd lmac_cmd;
struct iwm_nonwifi_cmd_buff buf;
u32 flags;
};
struct iwm_wifi_cmd {
u16 seq_num;
struct list_head pending;
struct iwm_udma_wifi_cmd udma_cmd;
struct iwm_umac_cmd umac_cmd;
struct iwm_lmac_cmd lmac_cmd;
struct iwm_wifi_cmd_buff buf;
u32 flags;
};
void iwm_cmd_flush(struct iwm_priv *iwm);
struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm,
u16 seq_num);
struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
u8 seq_num, u8 cmd_opcode);
int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
struct iwm_udma_nonwifi_cmd *ucmd,
const void *payload);
int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
struct iwm_udma_wifi_cmd *udma_cmd,
struct iwm_umac_cmd *umac_cmd,
struct iwm_lmac_cmd *lmac_cmd,
const void *payload, u16 payload_size);
int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
struct iwm_udma_wifi_cmd *udma_cmd,
struct iwm_umac_cmd *umac_cmd,
const void *payload, u16 payload_size);
u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm);
void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop);
void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
struct iwm_udma_out_wifi_hdr *hdr,
struct iwm_udma_wifi_cmd *cmd);
void iwm_build_umac_hdr(struct iwm_priv *iwm,
struct iwm_umac_fw_cmd_hdr *hdr,
struct iwm_umac_cmd *cmd);
#endif /* _IWM_HAL_H_ */
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
*/
#ifndef __IWM_H__
#define __IWM_H__
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/cfg80211.h>
#include "debug.h"
#include "hal.h"
#include "umac.h"
#include "lmac.h"
#include "eeprom.h"
#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
#define IWM_AUTHOR "<ilw@linux.intel.com>"
#define CONFIG_IWM_B0_HW_SUPPORT 1
#define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX
#define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA
#define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW
#define IWM_SRC_NUM 3
#define IWM_POWER_INDEX_MIN 0
#define IWM_POWER_INDEX_MAX 5
#define IWM_POWER_INDEX_DEFAULT 3
struct iwm_conf {
u32 sdio_ior_timeout;
unsigned long init_calib_map;
unsigned long periodic_calib_map;
bool reset_on_fatal_err;
bool auto_connect;
bool wimax_not_present;
bool enable_qos;
u32 mode;
u32 power_index;
u32 frag_threshold;
u32 rts_threshold;
bool cts_to_self;
u32 assoc_timeout;
u32 roam_timeout;
u32 wireless_mode;
u32 coexist_mode;
u8 ibss_band;
u8 ibss_channel;
u8 mac_addr[ETH_ALEN];
#ifdef CONFIG_IWM_B0_HW_SUPPORT
bool hw_b0;
#endif
};
enum {
COEX_MODE_SA = 1,
COEX_MODE_XOR,
COEX_MODE_CM,
COEX_MODE_MAX,
};
struct iwm_if_ops;
struct iwm_wifi_cmd;
struct pool_entry {
int id; /* group id */
int sid; /* super group id */
int min_pages; /* min capacity in pages */
int max_pages; /* max capacity in pages */
int alloc_pages; /* allocated # of pages. incresed by driver */
int total_freed_pages; /* total freed # of pages. incresed by UMAC */
};
struct spool_entry {
int id;
int max_pages;
int alloc_pages;
};
struct iwm_tx_credit {
spinlock_t lock;
int pool_nr;
unsigned long full_pools_map; /* bitmap for # of filled tx pools */
struct pool_entry pools[IWM_MACS_OUT_GROUPS];
struct spool_entry spools[IWM_MACS_OUT_SGROUPS];
};
struct iwm_notif {
struct list_head pending;
u32 cmd_id;
void *cmd;
u8 src;
void *buf;
unsigned long buf_size;
};
struct iwm_sta_info {
u8 addr[ETH_ALEN];
bool valid;
bool qos;
u8 color;
};
struct iwm_tx_info {
u8 sta;
u8 color;
u8 tid;
};
struct iwm_rx_info {
unsigned long rx_size;
unsigned long rx_buf_size;
};
#define IWM_NUM_KEYS 4
struct iwm_umac_key_hdr {
u8 mac[ETH_ALEN];
u8 key_idx;
u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */
} __attribute__ ((packed));
struct iwm_key {
struct iwm_umac_key_hdr hdr;
u8 in_use;
u8 alg;
u32 flags;
u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE];
u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE];
u8 key_len;
u8 key[32];
};
#define IWM_RX_ID_HASH 0xff
#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH)
#define IWM_STA_TABLE_NUM 16
#define IWM_TX_LIST_SIZE 64
#define IWM_RX_LIST_SIZE 256
#define IWM_SCAN_ID_MAX 0xff
#define IWM_STATUS_READY 0
#define IWM_STATUS_SCANNING 1
#define IWM_STATUS_SCAN_ABORTING 2
#define IWM_STATUS_ASSOCIATING 3
#define IWM_STATUS_ASSOCIATED 4
#define IWM_RADIO_RFKILL_OFF 0
#define IWM_RADIO_RFKILL_HW 1
#define IWM_RADIO_RFKILL_SW 2
struct iwm_tx_queue {
int id;
struct sk_buff_head queue;
struct workqueue_struct *wq;
struct work_struct worker;
u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE];
int concat_count;
u8 *concat_ptr;
};
/* Queues 0 ~ 3 for AC data, 5 for iPAN */
#define IWM_TX_QUEUES 5
#define IWM_TX_DATA_QUEUES 4
#define IWM_TX_CMD_QUEUE 4
struct iwm_bss_info {
struct list_head node;
struct cfg80211_bss *cfg_bss;
struct iwm_umac_notif_bss_info *bss;
};
typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf,
unsigned long buf_size, struct iwm_wifi_cmd *cmd);
#define IWM_WATCHDOG_PERIOD (6 * HZ)
struct iwm_priv {
struct wireless_dev *wdev;
struct iwm_if_ops *bus_ops;
struct iwm_conf conf;
unsigned long status;
unsigned long radio;
struct list_head pending_notif;
wait_queue_head_t notif_queue;
wait_queue_head_t nonwifi_queue;
unsigned long calib_done_map;
struct {
u8 *buf;
u32 size;
} calib_res[CALIBRATION_CMD_NUM];
struct iwm_umac_profile *umac_profile;
bool umac_profile_active;
u8 bssid[ETH_ALEN];
u8 channel;
u16 rate;
struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM];
struct list_head bss_list;
void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX])
(struct iwm_priv *priv, u8 *buf, unsigned long buf_size);
const iwm_handler *umac_handlers;
const iwm_handler *lmac_handlers;
DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM);
DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM);
DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM);
struct list_head wifi_pending_cmd;
struct list_head nonwifi_pending_cmd;
u16 wifi_seq_num;
u8 nonwifi_seq_num;
spinlock_t cmd_lock;
u32 core_enabled;
u8 scan_id;
struct cfg80211_scan_request *scan_request;
struct sk_buff_head rx_list;
struct list_head rx_tickets;
struct list_head rx_packets[IWM_RX_ID_HASH];
struct workqueue_struct *rx_wq;
struct work_struct rx_worker;
struct iwm_tx_credit tx_credit;
struct iwm_tx_queue txq[IWM_TX_QUEUES];
struct iwm_key keys[IWM_NUM_KEYS];
struct iwm_key *default_key;
wait_queue_head_t mlme_queue;
struct iw_statistics wstats;
struct delayed_work stats_request;
struct iwm_debugfs dbg;
u8 *eeprom;
struct timer_list watchdog;
struct work_struct reset_worker;
struct rfkill *rfkill;
char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
};
static inline void *iwm_private(struct iwm_priv *iwm)
{
BUG_ON(!iwm);
return &iwm->private;
}
#define hw_to_iwm(h) (h->iwm)
#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy))
#define iwm_to_wiphy(i) (i->wdev->wiphy)
#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w))
#define iwm_to_wdev(i) (i->wdev)
#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w))
#define iwm_to_ndev(i) (i->wdev->netdev)
#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr))
#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb))
#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb)
extern const struct iw_handler_def iwm_iw_handler_def;
void *iwm_if_alloc(int sizeof_bus, struct device *dev,
struct iwm_if_ops *if_ops);
void iwm_if_free(struct iwm_priv *iwm);
int iwm_mode_to_nl80211_iftype(int mode);
int iwm_priv_init(struct iwm_priv *iwm);
void iwm_reset(struct iwm_priv *iwm);
void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
struct iwm_umac_notif_alive *alive);
int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);
int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size);
int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout);
void iwm_init_default_profile(struct iwm_priv *iwm,
struct iwm_umac_profile *profile);
void iwm_link_on(struct iwm_priv *iwm);
void iwm_link_off(struct iwm_priv *iwm);
int iwm_up(struct iwm_priv *iwm);
int iwm_down(struct iwm_priv *iwm);
/* TX API */
void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages);
void iwm_tx_worker(struct work_struct *work);
int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
/* RX API */
void iwm_rx_setup_handlers(struct iwm_priv *iwm);
int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size);
int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
struct iwm_wifi_cmd *cmd);
void iwm_rx_free(struct iwm_priv *iwm);
/* RF Kill API */
int iwm_rfkill_init(struct iwm_priv *iwm);
void iwm_rfkill_exit(struct iwm_priv *iwm);
#endif
This diff is collapsed.
This diff is collapsed.
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
/*
* This is the netdev related hooks for iwm.
*
* Some interesting code paths:
*
* iwm_open() (Called at netdev interface bringup time)
* -> iwm_up() (main.c)
* -> iwm_bus_enable()
* -> if_sdio_enable() (In case of an SDIO bus)
* -> sdio_enable_func()
* -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker)
* -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker)
* -> iwm_load_fw() (fw.c)
* -> iwm_load_umac()
* -> iwm_load_lmac() (Calibration LMAC)
* -> iwm_load_lmac() (Operational LMAC)
* -> iwm_send_umac_config()
*
* iwm_stop() (Called at netdev interface bringdown time)
* -> iwm_down()
* -> iwm_bus_disable()
* -> if_sdio_disable() (In case of an SDIO bus)
* -> sdio_disable_func()
*/
#include <linux/netdevice.h>
#include "iwm.h"
#include "cfg80211.h"
#include "debug.h"
static int iwm_open(struct net_device *ndev)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
int ret = 0;
if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
ret = iwm_up(iwm);
return ret;
}
static int iwm_stop(struct net_device *ndev)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
int ret = 0;
if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
ret = iwm_down(iwm);
return ret;
}
/*
* iwm AC to queue mapping
*
* AC_VO -> queue 3
* AC_VI -> queue 2
* AC_BE -> queue 1
* AC_BK -> queue 0
*/
static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb)
{
skb->priority = cfg80211_classify8021d(skb);
return iwm_1d_to_queue[skb->priority];
}
static const struct net_device_ops iwm_netdev_ops = {
.ndo_open = iwm_open,
.ndo_stop = iwm_stop,
.ndo_start_xmit = iwm_xmit_frame,
.ndo_select_queue = iwm_select_queue,
};
void *iwm_if_alloc(int sizeof_bus, struct device *dev,
struct iwm_if_ops *if_ops)
{
struct net_device *ndev;
struct wireless_dev *wdev;
struct iwm_priv *iwm;
int ret = 0;
wdev = iwm_wdev_alloc(sizeof_bus, dev);
if (!wdev) {
dev_err(dev, "no memory for wireless device instance\n");
return ERR_PTR(-ENOMEM);
}
iwm = wdev_to_iwm(wdev);
iwm->bus_ops = if_ops;
iwm->wdev = wdev;
iwm_priv_init(iwm);
wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode);
ndev = alloc_netdev_mq(0, "wlan%d", ether_setup,
IWM_TX_QUEUES);
if (!ndev) {
dev_err(dev, "no memory for network device instance\n");
goto out_wdev;
}
ndev->netdev_ops = &iwm_netdev_ops;
ndev->wireless_handlers = &iwm_iw_handler_def;
ndev->ieee80211_ptr = wdev;
SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
ret = register_netdev(ndev);
if (ret < 0) {
dev_err(dev, "Failed to register netdev: %d\n", ret);
goto out_ndev;
}
wdev->netdev = ndev;
ret = iwm_rfkill_init(iwm);
if (ret) {
dev_err(dev, "Failed to init rfkill\n");
goto out_rfkill;
}
return iwm;
out_rfkill:
unregister_netdev(ndev);
out_ndev:
free_netdev(ndev);
out_wdev:
iwm_wdev_free(iwm);
return ERR_PTR(ret);
}
void iwm_if_free(struct iwm_priv *iwm)
{
int i;
if (!iwm_to_ndev(iwm))
return;
iwm_rfkill_exit(iwm);
unregister_netdev(iwm_to_ndev(iwm));
free_netdev(iwm_to_ndev(iwm));
iwm_wdev_free(iwm);
destroy_workqueue(iwm->rx_wq);
for (i = 0; i < IWM_TX_QUEUES; i++)
destroy_workqueue(iwm->txq[i].wq);
}
This diff is collapsed.
This diff is collapsed.
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
*/
#ifndef __IWM_RX_H__
#define __IWM_RX_H__
#include <linux/skbuff.h>
#include "umac.h"
struct iwm_rx_ticket_node {
struct list_head node;
struct iwm_rx_ticket *ticket;
};
struct iwm_rx_packet {
struct list_head node;
u16 id;
struct sk_buff *skb;
unsigned long pkt_size;
};
void iwm_rx_worker(struct work_struct *work);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment