提交 f2abba49 编写于 作者: J John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
...@@ -263,8 +263,7 @@ Who: Ravikiran Thirumalai <kiran@scalex86.org> ...@@ -263,8 +263,7 @@ Who: Ravikiran Thirumalai <kiran@scalex86.org>
What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS
(in net/core/net-sysfs.c) (in net/core/net-sysfs.c)
When: After the only user (hal) has seen a release with the patches When: 3.5
for enough time, probably some time in 2010.
Why: Over 1K .text/.data size reduction, data is available in other Why: Over 1K .text/.data size reduction, data is available in other
ways (ioctls) ways (ioctls)
Who: Johannes Berg <johannes@sipsolutions.net> Who: Johannes Berg <johannes@sipsolutions.net>
......
...@@ -21,48 +21,58 @@ static void bcma_host_pci_switch_core(struct bcma_device *core) ...@@ -21,48 +21,58 @@ static void bcma_host_pci_switch_core(struct bcma_device *core)
pr_debug("Switched to core: 0x%X\n", core->id.id); pr_debug("Switched to core: 0x%X\n", core->id.id);
} }
static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) /* Provides access to the requested core. Returns base offset that has to be
* used. It makes use of fixed windows when possible. */
static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core)
{ {
switch (core->id.id) {
case BCMA_CORE_CHIPCOMMON:
return 3 * BCMA_CORE_SIZE;
case BCMA_CORE_PCIE:
return 2 * BCMA_CORE_SIZE;
}
if (core->bus->mapped_core != core) if (core->bus->mapped_core != core)
bcma_host_pci_switch_core(core); bcma_host_pci_switch_core(core);
return 0;
}
static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
{
offset += bcma_host_pci_provide_access_to_core(core);
return ioread8(core->bus->mmio + offset); return ioread8(core->bus->mmio + offset);
} }
static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
{ {
if (core->bus->mapped_core != core) offset += bcma_host_pci_provide_access_to_core(core);
bcma_host_pci_switch_core(core);
return ioread16(core->bus->mmio + offset); return ioread16(core->bus->mmio + offset);
} }
static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
{ {
if (core->bus->mapped_core != core) offset += bcma_host_pci_provide_access_to_core(core);
bcma_host_pci_switch_core(core);
return ioread32(core->bus->mmio + offset); return ioread32(core->bus->mmio + offset);
} }
static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
u8 value) u8 value)
{ {
if (core->bus->mapped_core != core) offset += bcma_host_pci_provide_access_to_core(core);
bcma_host_pci_switch_core(core);
iowrite8(value, core->bus->mmio + offset); iowrite8(value, core->bus->mmio + offset);
} }
static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
u16 value) u16 value)
{ {
if (core->bus->mapped_core != core) offset += bcma_host_pci_provide_access_to_core(core);
bcma_host_pci_switch_core(core);
iowrite16(value, core->bus->mmio + offset); iowrite16(value, core->bus->mmio + offset);
} }
static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
u32 value) u32 value)
{ {
if (core->bus->mapped_core != core) offset += bcma_host_pci_provide_access_to_core(core);
bcma_host_pci_switch_core(core);
iowrite32(value, core->bus->mmio + offset); iowrite32(value, core->bus->mmio + offset);
} }
......
...@@ -188,7 +188,7 @@ config BT_MRVL ...@@ -188,7 +188,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices. The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787. Marvell Bluetooth devices, such as 8688/8787/8797.
Say Y here to compile Marvell Bluetooth driver Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
...@@ -201,8 +201,8 @@ config BT_MRVL_SDIO ...@@ -201,8 +201,8 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787 chipsets are devices with SDIO interface. Currently SD8688/SD8787/SD8797
supported. chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver Say Y here to compile support for Marvell BT-over-SDIO driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
......
...@@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { ...@@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
.io_port_1 = 0x01, .io_port_1 = 0x01,
.io_port_2 = 0x02, .io_port_2 = 0x02,
}; };
static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
.cfg = 0x00, .cfg = 0x00,
.host_int_mask = 0x02, .host_int_mask = 0x02,
.host_intstatus = 0x03, .host_intstatus = 0x03,
...@@ -92,7 +92,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { ...@@ -92,7 +92,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8787_uapsta.bin", .firmware = "mrvl/sd8787_uapsta.bin",
.reg = &btmrvl_reg_8787, .reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin",
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -103,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { ...@@ -103,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8787 Bluetooth device */ /* Marvell SD8787 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, .driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
/* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -1076,3 +1086,4 @@ MODULE_LICENSE("GPL v2"); ...@@ -1076,3 +1086,4 @@ MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688_helper.bin");
MODULE_FIRMWARE("sd8688.bin"); MODULE_FIRMWARE("sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
...@@ -785,9 +785,8 @@ static int btusb_send_frame(struct sk_buff *skb) ...@@ -785,9 +785,8 @@ static int btusb_send_frame(struct sk_buff *skb)
usb_mark_last_busy(data->udev); usb_mark_last_busy(data->udev);
} }
usb_free_urb(urb);
done: done:
usb_free_urb(urb);
return err; return err;
} }
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#define VERSION "1.3" #define VERSION "1.3"
static bool amp;
struct vhci_data { struct vhci_data {
struct hci_dev *hdev; struct hci_dev *hdev;
...@@ -239,6 +241,9 @@ static int vhci_open(struct inode *inode, struct file *file) ...@@ -239,6 +241,9 @@ static int vhci_open(struct inode *inode, struct file *file)
hdev->bus = HCI_VIRTUAL; hdev->bus = HCI_VIRTUAL;
hdev->driver_data = data; hdev->driver_data = data;
if (amp)
hdev->dev_type = HCI_AMP;
hdev->open = vhci_open_dev; hdev->open = vhci_open_dev;
hdev->close = vhci_close_dev; hdev->close = vhci_close_dev;
hdev->flush = vhci_flush; hdev->flush = vhci_flush;
...@@ -303,6 +308,9 @@ static void __exit vhci_exit(void) ...@@ -303,6 +308,9 @@ static void __exit vhci_exit(void)
module_init(vhci_init); module_init(vhci_init);
module_exit(vhci_exit); module_exit(vhci_exit);
module_param(amp, bool, 0644);
MODULE_PARM_DESC(amp, "Create AMP controller device");
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
......
...@@ -203,7 +203,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) ...@@ -203,7 +203,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
i); i);
ath_dbg(common, ATH_DBG_CALIBRATE, ath_dbg(common, ATH_DBG_CALIBRATE,
"Orignal: Chn %diq_corr_meas = 0x%08x\n", "Original: Chn %d iq_corr_meas = 0x%08x\n",
i, ah->totalIqCorrMeas[i]); i, ah->totalIqCorrMeas[i]);
iqCorrNeg = 0; iqCorrNeg = 0;
......
...@@ -226,7 +226,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) ...@@ -226,7 +226,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
i); i);
ath_dbg(common, ATH_DBG_CALIBRATE, ath_dbg(common, ATH_DBG_CALIBRATE,
"Orignal: Chn %diq_corr_meas = 0x%08x\n", "Original: Chn %d iq_corr_meas = 0x%08x\n",
i, ah->totalIqCorrMeas[i]); i, ah->totalIqCorrMeas[i]);
iqCorrNeg = 0; iqCorrNeg = 0;
......
...@@ -41,24 +41,24 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { ...@@ -41,24 +41,24 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = {
static const u32 ar9462_2p0_baseband_postamble[][5] = { static const u32 ar9462_2p0_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d},
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
{0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x5ac640de}, {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
{0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x0796be89}, {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81},
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x92c84d2e}, {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x33795d5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
{0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0}, {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0},
...@@ -81,6 +81,15 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { ...@@ -81,6 +81,15 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000},
{0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa},
{0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00},
{0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
{0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce},
{0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
{0x0000a428, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce},
{0x0000a42c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
{0x0000a430, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000}, {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
...@@ -1107,11 +1116,11 @@ static const u32 ar9462_2p0_baseband_core[][2] = { ...@@ -1107,11 +1116,11 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
{0x00009e30, 0x06336f77}, {0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f}, {0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00}, {0x00009e38, 0x0cc80c00},
{0x00009e40, 0x0d261820}, {0x00009e40, 0x15262820},
{0x00009e4c, 0x00001004}, {0x00009e4c, 0x00001004},
{0x00009e50, 0x00ff03f1}, {0x00009e50, 0x00ff03f1},
{0x00009e54, 0xe4c355c7}, {0x00009e54, 0xe4c555c2},
{0x00009e58, 0xfd897735}, {0x00009e58, 0xfd857722},
{0x00009e5c, 0xe9198724}, {0x00009e5c, 0xe9198724},
{0x00009fc0, 0x803e4788}, {0x00009fc0, 0x803e4788},
{0x00009fc4, 0x0001efb5}, {0x00009fc4, 0x0001efb5},
...@@ -1142,9 +1151,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = { ...@@ -1142,9 +1151,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
{0x0000a398, 0x001f0e0f}, {0x0000a398, 0x001f0e0f},
{0x0000a39c, 0x0075393f}, {0x0000a39c, 0x0075393f},
{0x0000a3a0, 0xb79f6427}, {0x0000a3a0, 0xb79f6427},
{0x0000a3a4, 0x00000000},
{0x0000a3a8, 0xaaaaaaaa},
{0x0000a3ac, 0x3c466478},
{0x0000a3c0, 0x20202020}, {0x0000a3c0, 0x20202020},
{0x0000a3c4, 0x22222220}, {0x0000a3c4, 0x22222220},
{0x0000a3c8, 0x20200020}, {0x0000a3c8, 0x20200020},
...@@ -1167,12 +1173,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = { ...@@ -1167,12 +1173,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
{0x0000a40c, 0x00820820}, {0x0000a40c, 0x00820820},
{0x0000a414, 0x1ce739ce}, {0x0000a414, 0x1ce739ce},
{0x0000a418, 0x2d001dce}, {0x0000a418, 0x2d001dce},
{0x0000a41c, 0x1ce739ce},
{0x0000a420, 0x000001ce},
{0x0000a424, 0x1ce739ce},
{0x0000a428, 0x000001ce},
{0x0000a42c, 0x1ce739ce},
{0x0000a430, 0x1ce739ce},
{0x0000a434, 0x00000000}, {0x0000a434, 0x00000000},
{0x0000a438, 0x00001801}, {0x0000a438, 0x00001801},
{0x0000a43c, 0x00100000}, {0x0000a43c, 0x00100000},
......
...@@ -808,7 +808,8 @@ void ath9k_htc_ani_work(struct work_struct *work) ...@@ -808,7 +808,8 @@ void ath9k_htc_ani_work(struct work_struct *work)
} }
/* Verify whether we must check ANI */ /* Verify whether we must check ANI */
if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { if (ah->config.enable_ani &&
(timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
aniflag = true; aniflag = true;
common->ani.checkani_timer = timestamp; common->ani.checkani_timer = timestamp;
} }
...@@ -838,7 +839,7 @@ void ath9k_htc_ani_work(struct work_struct *work) ...@@ -838,7 +839,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
* short calibration and long calibration. * short calibration and long calibration.
*/ */
cal_interval = ATH_LONG_CALINTERVAL; cal_interval = ATH_LONG_CALINTERVAL;
if (priv->ah->config.enable_ani) if (ah->config.enable_ani)
cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
if (!common->ani.caldone) if (!common->ani.caldone)
cal_interval = min(cal_interval, (u32)short_cal_interval); cal_interval = min(cal_interval, (u32)short_cal_interval);
......
...@@ -504,7 +504,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) ...@@ -504,7 +504,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
return ecode; return ecode;
} }
if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { if (ah->config.enable_ani) {
ath9k_hw_ani_setup(ah); ath9k_hw_ani_setup(ah);
ath9k_hw_ani_init(ah); ath9k_hw_ani_init(ah);
} }
...@@ -610,6 +610,10 @@ static int __ath9k_hw_init(struct ath_hw *ah) ...@@ -610,6 +610,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (!AR_SREV_9300_20_OR_LATER(ah)) if (!AR_SREV_9300_20_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_MRC_CCK; ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
/* disable ANI for 9340 */
if (AR_SREV_9340(ah))
ah->config.enable_ani = false;
ath9k_hw_init_mode_regs(ah); ath9k_hw_init_mode_regs(ah);
if (!ah->is_pciexpress) if (!ah->is_pciexpress)
......
...@@ -1110,7 +1110,6 @@ bool ath9k_hw_disable(struct ath_hw *ah); ...@@ -1110,7 +1110,6 @@ bool ath9k_hw_disable(struct ath_hw *ah);
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setopmode(struct ath_hw *ah);
void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
void ath9k_hw_setbssidmask(struct ath_hw *ah);
void ath9k_hw_write_associd(struct ath_hw *ah); void ath9k_hw_write_associd(struct ath_hw *ah);
u32 ath9k_hw_gettsf32(struct ath_hw *ah); u32 ath9k_hw_gettsf32(struct ath_hw *ah);
u64 ath9k_hw_gettsf64(struct ath_hw *ah); u64 ath9k_hw_gettsf64(struct ath_hw *ah);
......
...@@ -258,6 +258,8 @@ static void setup_ht_cap(struct ath_softc *sc, ...@@ -258,6 +258,8 @@ static void setup_ht_cap(struct ath_softc *sc,
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
max_streams = 1; max_streams = 1;
else if (AR_SREV_9462(ah))
max_streams = 2;
else if (AR_SREV_9300_20_OR_LATER(ah)) else if (AR_SREV_9300_20_OR_LATER(ah))
max_streams = 3; max_streams = 3;
else else
......
...@@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *sc) ...@@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *sc)
if (--sc->ps_usecount != 0) if (--sc->ps_usecount != 0)
goto unlock; goto unlock;
if (sc->ps_idle) if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
mode = ATH9K_PM_FULL_SLEEP; mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled && else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON | !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
...@@ -332,7 +332,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, ...@@ -332,7 +332,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
hchan = ah->curchan; hchan = ah->curchan;
} }
if (fastcc && !ath9k_hw_check_alive(ah)) if (fastcc && (ah->chip_fullsleep ||
!ath9k_hw_check_alive(ah)))
fastcc = false; fastcc = false;
if (!ath_prepare_reset(sc, retry_tx, flush)) if (!ath_prepare_reset(sc, retry_tx, flush))
...@@ -561,7 +562,6 @@ void ath_ani_calibrate(unsigned long data) ...@@ -561,7 +562,6 @@ void ath_ani_calibrate(unsigned long data)
/* Long calibration runs independently of short calibration. */ /* Long calibration runs independently of short calibration. */
if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
longcal = true; longcal = true;
ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
common->ani.longcal_timer = timestamp; common->ani.longcal_timer = timestamp;
} }
...@@ -569,8 +569,6 @@ void ath_ani_calibrate(unsigned long data) ...@@ -569,8 +569,6 @@ void ath_ani_calibrate(unsigned long data)
if (!common->ani.caldone) { if (!common->ani.caldone) {
if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
shortcal = true; shortcal = true;
ath_dbg(common, ATH_DBG_ANI,
"shortcal @%lu\n", jiffies);
common->ani.shortcal_timer = timestamp; common->ani.shortcal_timer = timestamp;
common->ani.resetcal_timer = timestamp; common->ani.resetcal_timer = timestamp;
} }
...@@ -584,8 +582,9 @@ void ath_ani_calibrate(unsigned long data) ...@@ -584,8 +582,9 @@ void ath_ani_calibrate(unsigned long data)
} }
/* Verify whether we must check ANI */ /* Verify whether we must check ANI */
if ((timestamp - common->ani.checkani_timer) >= if (sc->sc_ah->config.enable_ani
ah->config.ani_poll_interval) { && (timestamp - common->ani.checkani_timer) >=
ah->config.ani_poll_interval) {
aniflag = true; aniflag = true;
common->ani.checkani_timer = timestamp; common->ani.checkani_timer = timestamp;
} }
...@@ -605,6 +604,11 @@ void ath_ani_calibrate(unsigned long data) ...@@ -605,6 +604,11 @@ void ath_ani_calibrate(unsigned long data)
ah->rxchainmask, longcal); ah->rxchainmask, longcal);
} }
ath_dbg(common, ATH_DBG_ANI,
"Calibration @%lu finished: %s %s %s, caldone: %s\n", jiffies,
longcal ? "long" : "", shortcal ? "short" : "",
aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
set_timer: set_timer:
...@@ -886,82 +890,6 @@ irqreturn_t ath_isr(int irq, void *dev) ...@@ -886,82 +890,6 @@ irqreturn_t ath_isr(int irq, void *dev)
#undef SCHED_INTR #undef SCHED_INTR
} }
static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_channel *channel = hw->conf.channel;
int r;
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
atomic_set(&ah->intr_ref_cnt, -1);
ath9k_hw_configpcipowersave(ah, false);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_err(common,
"Unable to reset channel (%u MHz), reset status %d\n",
channel->center_freq, r);
}
ath_complete_reset(sc, true);
/* Enable LED */
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
}
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_hw *ah = sc->sc_ah;
struct ieee80211_channel *channel = hw->conf.channel;
int r;
ath9k_ps_wakeup(sc);
ath_cancel_work(sc);
spin_lock_bh(&sc->sc_pcu_lock);
/*
* Keep the LED on when the radio is disabled
* during idle unassociated state.
*/
if (!sc->ps_idle) {
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
}
ath_prepare_reset(sc, false, true);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_err(ath9k_hw_common(sc->sc_ah),
"Unable to reset channel (%u MHz), reset status %d\n",
channel->center_freq, r);
}
ath9k_hw_phy_disable(ah);
ath9k_hw_configpcipowersave(ah, true);
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
}
static int ath_reset(struct ath_softc *sc, bool retry_tx) static int ath_reset(struct ath_softc *sc, bool retry_tx)
{ {
int r; int r;
...@@ -1097,6 +1025,9 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -1097,6 +1025,9 @@ static int ath9k_start(struct ieee80211_hw *hw)
* and then setup of the interrupt mask. * and then setup of the interrupt mask.
*/ */
spin_lock_bh(&sc->sc_pcu_lock); spin_lock_bh(&sc->sc_pcu_lock);
atomic_set(&ah->intr_ref_cnt, -1);
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (r) { if (r) {
ath_err(common, ath_err(common,
...@@ -1138,6 +1069,18 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -1138,6 +1069,18 @@ static int ath9k_start(struct ieee80211_hw *hw)
goto mutex_unlock; goto mutex_unlock;
} }
if (ah->led_pin >= 0) {
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
}
/*
* Reset key cache to sane defaults (all entries cleared) instead of
* semi-random values after suspend/resume.
*/
ath9k_cmn_init_crypto(sc->sc_ah);
spin_unlock_bh(&sc->sc_pcu_lock); spin_unlock_bh(&sc->sc_pcu_lock);
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
...@@ -1183,6 +1126,13 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -1183,6 +1126,13 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
} }
} }
/*
* Cannot tx while the hardware is in full sleep, it first needs a full
* chip reset to recover from that
*/
if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP))
goto exit;
if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
/* /*
* We are using PS-Poll and mac80211 can request TX while in * We are using PS-Poll and mac80211 can request TX while in
...@@ -1229,6 +1179,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) ...@@ -1229,6 +1179,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
...@@ -1259,35 +1210,45 @@ static void ath9k_stop(struct ieee80211_hw *hw) ...@@ -1259,35 +1210,45 @@ static void ath9k_stop(struct ieee80211_hw *hw)
* before setting the invalid flag. */ * before setting the invalid flag. */
ath9k_hw_disable_interrupts(ah); ath9k_hw_disable_interrupts(ah);
if (!(sc->sc_flags & SC_OP_INVALID)) { spin_unlock_bh(&sc->sc_pcu_lock);
ath_drain_all_txq(sc, false);
ath_stoprecv(sc); /* we can now sync irq and kill any running tasklets, since we already
ath9k_hw_phy_disable(ah); * disabled interrupts and not holding a spin lock */
} else synchronize_irq(sc->irq);
sc->rx.rxlink = NULL; tasklet_kill(&sc->intr_tq);
tasklet_kill(&sc->bcon_tasklet);
prev_idle = sc->ps_idle;
sc->ps_idle = true;
spin_lock_bh(&sc->sc_pcu_lock);
if (ah->led_pin >= 0) {
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
}
ath_prepare_reset(sc, false, true);
if (sc->rx.frag) { if (sc->rx.frag) {
dev_kfree_skb_any(sc->rx.frag); dev_kfree_skb_any(sc->rx.frag);
sc->rx.frag = NULL; sc->rx.frag = NULL;
} }
/* disable HAL and put h/w to sleep */ if (!ah->curchan)
ath9k_hw_disable(ah); ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
spin_unlock_bh(&sc->sc_pcu_lock); ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
ath9k_hw_phy_disable(ah);
/* we can now sync irq and kill any running tasklets, since we already ath9k_hw_configpcipowersave(ah, true);
* disabled interrupts and not holding a spin lock */
synchronize_irq(sc->irq);
tasklet_kill(&sc->intr_tq);
tasklet_kill(&sc->bcon_tasklet);
ath9k_ps_restore(sc); spin_unlock_bh(&sc->sc_pcu_lock);
sc->ps_idle = true; ath9k_ps_restore(sc);
ath_radio_disable(sc, hw);
sc->sc_flags |= SC_OP_INVALID; sc->sc_flags |= SC_OP_INVALID;
sc->ps_idle = prev_idle;
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
...@@ -1627,8 +1588,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1627,8 +1588,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &hw->conf; struct ieee80211_conf *conf = &hw->conf;
bool disable_radio = false;
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
/* /*
...@@ -1639,13 +1600,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1639,13 +1600,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
*/ */
if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (changed & IEEE80211_CONF_CHANGE_IDLE) {
sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
if (!sc->ps_idle) { if (sc->ps_idle)
ath_radio_enable(sc, hw); ath_cancel_work(sc);
ath_dbg(common, ATH_DBG_CONFIG,
"not-idle: enabling radio\n");
} else {
disable_radio = true;
}
} }
/* /*
...@@ -1752,18 +1708,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1752,18 +1708,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath_dbg(common, ATH_DBG_CONFIG, ath_dbg(common, ATH_DBG_CONFIG,
"Set power: %d\n", conf->power_level); "Set power: %d\n", conf->power_level);
sc->config.txpowlimit = 2 * conf->power_level; sc->config.txpowlimit = 2 * conf->power_level;
ath9k_ps_wakeup(sc);
ath9k_cmn_update_txpow(ah, sc->curtxpow, ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow); sc->config.txpowlimit, &sc->curtxpow);
ath9k_ps_restore(sc);
}
if (disable_radio) {
ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
ath_radio_disable(sc, hw);
} }
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
return 0; return 0;
} }
...@@ -2331,9 +2281,6 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) ...@@ -2331,9 +2281,6 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
return; return;
} }
if (drop)
timeout = 1;
for (j = 0; j < timeout; j++) { for (j = 0; j < timeout; j++) {
bool npend = false; bool npend = false;
...@@ -2351,21 +2298,22 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) ...@@ -2351,21 +2298,22 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
} }
if (!npend) if (!npend)
goto out; break;
} }
ath9k_ps_wakeup(sc); if (drop) {
spin_lock_bh(&sc->sc_pcu_lock); ath9k_ps_wakeup(sc);
drain_txq = ath_drain_all_txq(sc, false); spin_lock_bh(&sc->sc_pcu_lock);
spin_unlock_bh(&sc->sc_pcu_lock); drain_txq = ath_drain_all_txq(sc, false);
spin_unlock_bh(&sc->sc_pcu_lock);
if (!drain_txq) if (!drain_txq)
ath_reset(sc, false); ath_reset(sc, false);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
ieee80211_wake_queues(hw); ieee80211_wake_queues(hw);
}
out:
ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
} }
......
...@@ -307,12 +307,11 @@ static int ath_pci_suspend(struct device *device) ...@@ -307,12 +307,11 @@ static int ath_pci_suspend(struct device *device)
struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
/* The device has to be moved to FULLSLEEP forcibly. /* The device has to be moved to FULLSLEEP forcibly.
* Otherwise the chip never moved to full sleep, * Otherwise the chip never moved to full sleep,
* when no interface is up. * when no interface is up.
*/ */
ath9k_hw_disable(sc->sc_ah);
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
return 0; return 0;
...@@ -321,8 +320,6 @@ static int ath_pci_suspend(struct device *device) ...@@ -321,8 +320,6 @@ static int ath_pci_suspend(struct device *device)
static int ath_pci_resume(struct device *device) static int ath_pci_resume(struct device *device)
{ {
struct pci_dev *pdev = to_pci_dev(device); struct pci_dev *pdev = to_pci_dev(device);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv;
u32 val; u32 val;
/* /*
...@@ -334,22 +331,6 @@ static int ath_pci_resume(struct device *device) ...@@ -334,22 +331,6 @@ static int ath_pci_resume(struct device *device)
if ((val & 0x0000ff00) != 0) if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
ath9k_ps_wakeup(sc);
/* Enable LED */
ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
/*
* Reset key cache to sane defaults (all entries cleared) instead of
* semi-random values after suspend/resume.
*/
ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_ps_restore(sc);
sc->ps_idle = true;
ath_radio_disable(sc, hw);
return 0; return 0;
} }
......
...@@ -1954,7 +1954,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, ...@@ -1954,7 +1954,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
skb_pull(skb, padsize); skb_pull(skb, padsize);
} }
if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
ath_dbg(common, ATH_DBG_PS, ath_dbg(common, ATH_DBG_PS,
"Going back to sleep after having received TX status (0x%lx)\n", "Going back to sleep after having received TX status (0x%lx)\n",
......
...@@ -2786,9 +2786,8 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) ...@@ -2786,9 +2786,8 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id)
/* Driver ilate data, only for Tx (not command) queues, /* Driver ilate data, only for Tx (not command) queues,
* not shared with device. */ * not shared with device. */
if (id != il->cmd_queue) { if (id != il->cmd_queue) {
txq->txb = txq->txb = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->txb[0]),
kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
GFP_KERNEL);
if (!txq->txb) { if (!txq->txb) {
IL_ERR("kmalloc for auxiliary BD " IL_ERR("kmalloc for auxiliary BD "
"structures failed\n"); "structures failed\n");
......
# WIFI # WIFI
obj-$(CONFIG_IWLWIFI) += iwlwifi.o obj-$(CONFIG_IWLWIFI) += iwlwifi.o
iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o
iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o iwlwifi-objs += iwl-ucode.o iwl-agn-tx.o
iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o
...@@ -18,7 +18,7 @@ iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o ...@@ -18,7 +18,7 @@ iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-testmode.o
CFLAGS_iwl-devtrace.o := -I$(src) CFLAGS_iwl-devtrace.o := -I$(src)
......
...@@ -934,57 +934,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) ...@@ -934,57 +934,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
return ant; return ant;
} }
/* notification wait support */
void iwlagn_init_notification_wait(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
void *data),
void *fn_data)
{
wait_entry->fn = fn;
wait_entry->fn_data = fn_data;
wait_entry->cmd = cmd;
wait_entry->triggered = false;
wait_entry->aborted = false;
spin_lock_bh(&priv->notif_wait_lock);
list_add(&wait_entry->list, &priv->notif_waits);
spin_unlock_bh(&priv->notif_wait_lock);
}
int iwlagn_wait_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
unsigned long timeout)
{
int ret;
ret = wait_event_timeout(priv->notif_waitq,
wait_entry->triggered || wait_entry->aborted,
timeout);
spin_lock_bh(&priv->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&priv->notif_wait_lock);
if (wait_entry->aborted)
return -EIO;
/* return value is always >= 0 */
if (ret <= 0)
return -ETIMEDOUT;
return 0;
}
void iwlagn_remove_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry)
{
spin_lock_bh(&priv->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&priv->notif_wait_lock);
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
{ {
......
...@@ -1131,9 +1131,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) ...@@ -1131,9 +1131,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
/* set up notification wait support */ /* set up notification wait support */
spin_lock_init(&priv->notif_wait_lock); spin_lock_init(&priv->shrd->notif_wait_lock);
INIT_LIST_HEAD(&priv->notif_waits); INIT_LIST_HEAD(&priv->shrd->notif_waits);
init_waitqueue_head(&priv->notif_waitq); init_waitqueue_head(&priv->shrd->notif_waitq);
/* Set up BT Rx handlers */ /* Set up BT Rx handlers */
if (priv->cfg->lib->bt_rx_handler_setup) if (priv->cfg->lib->bt_rx_handler_setup)
...@@ -1152,11 +1152,11 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, ...@@ -1152,11 +1152,11 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
* even if the RX handler consumes the RXB we have * even if the RX handler consumes the RXB we have
* access to it in the notification wait entry. * access to it in the notification wait entry.
*/ */
if (!list_empty(&priv->notif_waits)) { if (!list_empty(&priv->shrd->notif_waits)) {
struct iwl_notification_wait *w; struct iwl_notification_wait *w;
spin_lock(&priv->notif_wait_lock); spin_lock(&priv->shrd->notif_wait_lock);
list_for_each_entry(w, &priv->notif_waits, list) { list_for_each_entry(w, &priv->shrd->notif_waits, list) {
if (w->cmd != pkt->hdr.cmd) if (w->cmd != pkt->hdr.cmd)
continue; continue;
IWL_DEBUG_RX(priv, IWL_DEBUG_RX(priv,
...@@ -1167,9 +1167,9 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, ...@@ -1167,9 +1167,9 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
if (w->fn) if (w->fn)
w->fn(priv, pkt, w->fn_data); w->fn(priv, pkt, w->fn_data);
} }
spin_unlock(&priv->notif_wait_lock); spin_unlock(&priv->shrd->notif_wait_lock);
wake_up_all(&priv->notif_waitq); wake_up_all(&priv->shrd->notif_waitq);
} }
if (priv->pre_rx_handler) if (priv->pre_rx_handler)
......
...@@ -60,7 +60,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, ...@@ -60,7 +60,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
u8 old_dev_type = send->dev_type; u8 old_dev_type = send->dev_type;
int ret; int ret;
iwlagn_init_notification_wait(priv, &disable_wait, iwl_init_notification_wait(priv->shrd, &disable_wait,
REPLY_WIPAN_DEACTIVATION_COMPLETE, REPLY_WIPAN_DEACTIVATION_COMPLETE,
NULL, NULL); NULL, NULL);
...@@ -74,9 +74,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, ...@@ -74,9 +74,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
if (ret) { if (ret) {
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
iwlagn_remove_notification(priv, &disable_wait); iwl_remove_notification(priv->shrd, &disable_wait);
} else { } else {
ret = iwlagn_wait_notification(priv, &disable_wait, HZ); ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ);
if (ret) if (ret)
IWL_ERR(priv, "Timed out waiting for PAN disable\n"); IWL_ERR(priv, "Timed out waiting for PAN disable\n");
} }
......
...@@ -1232,14 +1232,14 @@ int iwl_alive_start(struct iwl_priv *priv) ...@@ -1232,14 +1232,14 @@ int iwl_alive_start(struct iwl_priv *priv)
priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
priv->cur_rssi_ctx = NULL; priv->cur_rssi_ctx = NULL;
iwlagn_send_prio_tbl(priv); iwl_send_prio_tbl(trans(priv));
/* FIXME: w/a to force change uCode BT state machine */ /* FIXME: w/a to force change uCode BT state machine */
ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret) if (ret)
return ret; return ret;
ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret) if (ret)
return ret; return ret;
......
...@@ -108,8 +108,8 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf, ...@@ -108,8 +108,8 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
int iwlagn_rx_calib_result(struct iwl_priv *priv, int iwlagn_rx_calib_result(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb, struct iwl_rx_mem_buffer *rxb,
struct iwl_device_cmd *cmd); struct iwl_device_cmd *cmd);
int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
void iwlagn_send_prio_tbl(struct iwl_priv *priv); void iwl_send_prio_tbl(struct iwl_trans *trans);
int iwlagn_run_init_ucode(struct iwl_priv *priv); int iwlagn_run_init_ucode(struct iwl_priv *priv);
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
enum iwl_ucode_type ucode_type); enum iwl_ucode_type ucode_type);
...@@ -356,22 +356,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) ...@@ -356,22 +356,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
/* notification wait support */
void __acquires(wait_entry)
iwlagn_init_notification_wait(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
void *data),
void *fn_data);
int __must_check __releases(wait_entry)
iwlagn_wait_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry,
unsigned long timeout);
void __releases(wait_entry)
iwlagn_remove_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry);
extern int iwlagn_init_alive_start(struct iwl_priv *priv); extern int iwlagn_init_alive_start(struct iwl_priv *priv);
extern int iwl_alive_start(struct iwl_priv *priv); extern int iwl_alive_start(struct iwl_priv *priv);
/* svtool */ /* svtool */
......
...@@ -836,19 +836,6 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, ...@@ -836,19 +836,6 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
} }
#endif #endif
static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
{
unsigned long flags;
struct iwl_notification_wait *wait_entry;
spin_lock_irqsave(&priv->notif_wait_lock, flags);
list_for_each_entry(wait_entry, &priv->notif_waits, list)
wait_entry->aborted = true;
spin_unlock_irqrestore(&priv->notif_wait_lock, flags);
wake_up_all(&priv->notif_waitq);
}
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
{ {
unsigned int reload_msec; unsigned int reload_msec;
...@@ -860,7 +847,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) ...@@ -860,7 +847,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
/* Cancel currently queued command. */ /* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
iwlagn_abort_notification_waits(priv); iwl_abort_notification_waits(priv->shrd);
/* Keep the restart process from trying to send host /* Keep the restart process from trying to send host
* commands by clearing the ready bit */ * commands by clearing the ready bit */
......
...@@ -134,48 +134,43 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) ...@@ -134,48 +134,43 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
*/ */
/* 0x0000000F - 0x00000001 */ /* 0x0000000F - 0x00000001 */
#define IWL_DL_INFO (1 << 0) #define IWL_DL_INFO 0x00000001
#define IWL_DL_MAC80211 (1 << 1) #define IWL_DL_MAC80211 0x00000002
#define IWL_DL_HCMD (1 << 2) #define IWL_DL_HCMD 0x00000004
#define IWL_DL_STATE (1 << 3) #define IWL_DL_STATE 0x00000008
/* 0x000000F0 - 0x00000010 */ /* 0x000000F0 - 0x00000010 */
#define IWL_DL_MACDUMP (1 << 4) #define IWL_DL_EEPROM 0x00000040
#define IWL_DL_HCMD_DUMP (1 << 5) #define IWL_DL_RADIO 0x00000080
#define IWL_DL_EEPROM (1 << 6)
#define IWL_DL_RADIO (1 << 7)
/* 0x00000F00 - 0x00000100 */ /* 0x00000F00 - 0x00000100 */
#define IWL_DL_POWER (1 << 8) #define IWL_DL_POWER 0x00000100
#define IWL_DL_TEMP (1 << 9) #define IWL_DL_TEMP 0x00000200
/* reserved (1 << 10) */ #define IWL_DL_SCAN 0x00000800
#define IWL_DL_SCAN (1 << 11)
/* 0x0000F000 - 0x00001000 */ /* 0x0000F000 - 0x00001000 */
#define IWL_DL_ASSOC (1 << 12) #define IWL_DL_ASSOC 0x00001000
#define IWL_DL_DROP (1 << 13) #define IWL_DL_DROP 0x00002000
/* reserved (1 << 14) */ #define IWL_DL_COEX 0x00008000
#define IWL_DL_COEX (1 << 15)
/* 0x000F0000 - 0x00010000 */ /* 0x000F0000 - 0x00010000 */
#define IWL_DL_FW (1 << 16) #define IWL_DL_FW 0x00010000
#define IWL_DL_RF_KILL (1 << 17) #define IWL_DL_RF_KILL 0x00020000
#define IWL_DL_FW_ERRORS (1 << 18) #define IWL_DL_FW_ERRORS 0x00040000
#define IWL_DL_LED (1 << 19) #define IWL_DL_LED 0x00080000
/* 0x00F00000 - 0x00100000 */ /* 0x00F00000 - 0x00100000 */
#define IWL_DL_RATE (1 << 20) #define IWL_DL_RATE 0x00100000
#define IWL_DL_CALIB (1 << 21) #define IWL_DL_CALIB 0x00200000
#define IWL_DL_WEP (1 << 22) #define IWL_DL_WEP 0x00400000
#define IWL_DL_TX (1 << 23) #define IWL_DL_TX 0x00800000
/* 0x0F000000 - 0x01000000 */ /* 0x0F000000 - 0x01000000 */
#define IWL_DL_RX (1 << 24) #define IWL_DL_RX 0x01000000
#define IWL_DL_ISR (1 << 25) #define IWL_DL_ISR 0x02000000
#define IWL_DL_HT (1 << 26) #define IWL_DL_HT 0x04000000
/* 0xF0000000 - 0x10000000 */ /* 0xF0000000 - 0x10000000 */
#define IWL_DL_11H (1 << 28) #define IWL_DL_11H 0x10000000
#define IWL_DL_STATS (1 << 29) #define IWL_DL_STATS 0x20000000
#define IWL_DL_TX_REPLY (1 << 30) #define IWL_DL_TX_REPLY 0x40000000
#define IWL_DL_TX_QUEUES (1 << 31) #define IWL_DL_TX_QUEUES 0x80000000
#define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) #define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) #define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
#define IWL_DEBUG_MACDUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a)
#define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a) #define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
#define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a) #define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a)
#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) #define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a)
...@@ -184,7 +179,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) ...@@ -184,7 +179,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
#define IWL_DEBUG_HC_DUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a)
#define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) #define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a)
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
...@@ -206,8 +200,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) ...@@ -206,8 +200,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_STATS_LIMIT(p, f, a...) \ #define IWL_DEBUG_STATS_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a) IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a)
#define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a) #define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a)
#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a)
#define IWL_DEBUG_TX_QUEUES(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_QUEUES, f, ## a) #define IWL_DEBUG_TX_QUEUES(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_QUEUES, f, ## a)
#define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a) #define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
......
...@@ -234,11 +234,12 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, ...@@ -234,11 +234,12 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
/* default is to dump the entire data segment */ /* default is to dump the entire data segment */
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
struct iwl_trans *trans = trans(priv);
priv->dbgfs_sram_offset = 0x800000; priv->dbgfs_sram_offset = 0x800000;
if (priv->ucode_type == IWL_UCODE_INIT) if (trans->shrd->ucode_type == IWL_UCODE_INIT)
priv->dbgfs_sram_len = trans(priv)->ucode_init.data.len; priv->dbgfs_sram_len = trans->ucode_init.data.len;
else else
priv->dbgfs_sram_len = trans(priv)->ucode_rt.data.len; priv->dbgfs_sram_len = trans->ucode_rt.data.len;
} }
len = priv->dbgfs_sram_len; len = priv->dbgfs_sram_len;
......
...@@ -689,35 +689,6 @@ struct iwl_force_reset { ...@@ -689,35 +689,6 @@ struct iwl_force_reset {
*/ */
#define IWLAGN_EXT_BEACON_TIME_POS 22 #define IWLAGN_EXT_BEACON_TIME_POS 22
/**
* struct iwl_notification_wait - notification wait entry
* @list: list head for global list
* @fn: function called with the notification
* @cmd: command ID
*
* This structure is not used directly, to wait for a
* notification declare it on the stack, and call
* iwlagn_init_notification_wait() with appropriate
* parameters. Then do whatever will cause the ucode
* to notify the driver, and to wait for that then
* call iwlagn_wait_notification().
*
* Each notification is one-shot. If at some point we
* need to support multi-shot notifications (which
* can't be allocated on the stack) we need to modify
* the code for them.
*/
struct iwl_notification_wait {
struct list_head list;
void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt,
void *data);
void *fn_data;
u8 cmd;
bool triggered, aborted;
};
struct iwl_rxon_context { struct iwl_rxon_context {
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
...@@ -790,6 +761,12 @@ struct iwl_testmode_trace { ...@@ -790,6 +761,12 @@ struct iwl_testmode_trace {
dma_addr_t dma_addr; dma_addr_t dma_addr;
bool trace_enabled; bool trace_enabled;
}; };
struct iwl_testmode_sram {
u32 buff_size;
u32 num_chunks;
u8 *buff_addr;
bool sram_readed;
};
#endif #endif
struct iwl_wipan_noa_data { struct iwl_wipan_noa_data {
...@@ -883,7 +860,6 @@ struct iwl_priv { ...@@ -883,7 +860,6 @@ struct iwl_priv {
u32 ucode_ver; /* version of ucode, copy of u32 ucode_ver; /* version of ucode, copy of
iwl_ucode.ver */ iwl_ucode.ver */
enum iwl_ucode_type ucode_type;
char firmware_name[25]; char firmware_name[25];
struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
...@@ -987,10 +963,6 @@ struct iwl_priv { ...@@ -987,10 +963,6 @@ struct iwl_priv {
/* counts reply_tx error */ /* counts reply_tx error */
struct reply_tx_error_statistics reply_tx_stats; struct reply_tx_error_statistics reply_tx_stats;
struct reply_agg_tx_error_statistics reply_agg_tx_stats; struct reply_agg_tx_error_statistics reply_agg_tx_stats;
/* notification wait support */
struct list_head notif_waits;
spinlock_t notif_wait_lock;
wait_queue_head_t notif_waitq;
/* remain-on-channel offload support */ /* remain-on-channel offload support */
struct ieee80211_channel *hw_roc_channel; struct ieee80211_channel *hw_roc_channel;
...@@ -1070,6 +1042,7 @@ struct iwl_priv { ...@@ -1070,6 +1042,7 @@ struct iwl_priv {
bool led_registered; bool led_registered;
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
struct iwl_testmode_trace testmode_trace; struct iwl_testmode_trace testmode_trace;
struct iwl_testmode_sram testmode_sram;
u32 tm_fixed_rate; u32 tm_fixed_rate;
#endif #endif
......
...@@ -481,15 +481,11 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -481,15 +481,11 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{ {
struct iwl_priv *priv = hw->priv; struct iwl_priv *priv = hw->priv;
IWL_DEBUG_MACDUMP(priv, "enter\n");
IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
if (iwlagn_tx_skb(priv, skb)) if (iwlagn_tx_skb(priv, skb))
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
IWL_DEBUG_MACDUMP(priv, "leave\n");
} }
static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
...@@ -521,6 +517,17 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -521,6 +517,17 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
/* fall through */
case WLAN_CIPHER_SUITE_CCMP:
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
break;
default:
break;
}
/* /*
* We could program these keys into the hardware as well, but we * We could program these keys into the hardware as well, but we
* don't expect much multicast traffic in IBSS and having keys * don't expect much multicast traffic in IBSS and having keys
......
...@@ -256,6 +256,52 @@ struct iwl_tid_data { ...@@ -256,6 +256,52 @@ struct iwl_tid_data {
struct iwl_ht_agg agg; struct iwl_ht_agg agg;
}; };
/**
* enum iwl_ucode_type
*
* The type of ucode currently loaded on the hardware.
*
* @IWL_UCODE_NONE: No ucode loaded
* @IWL_UCODE_REGULAR: Normal runtime ucode
* @IWL_UCODE_INIT: Initial ucode
* @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
*/
enum iwl_ucode_type {
IWL_UCODE_NONE,
IWL_UCODE_REGULAR,
IWL_UCODE_INIT,
IWL_UCODE_WOWLAN,
};
/**
* struct iwl_notification_wait - notification wait entry
* @list: list head for global list
* @fn: function called with the notification
* @cmd: command ID
*
* This structure is not used directly, to wait for a
* notification declare it on the stack, and call
* iwlagn_init_notification_wait() with appropriate
* parameters. Then do whatever will cause the ucode
* to notify the driver, and to wait for that then
* call iwlagn_wait_notification().
*
* Each notification is one-shot. If at some point we
* need to support multi-shot notifications (which
* can't be allocated on the stack) we need to modify
* the code for them.
*/
struct iwl_notification_wait {
struct list_head list;
void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt,
void *data);
void *fn_data;
u8 cmd;
bool triggered, aborted;
};
/** /**
* struct iwl_shared - shared fields for all the layers of the driver * struct iwl_shared - shared fields for all the layers of the driver
* *
...@@ -273,6 +319,10 @@ struct iwl_tid_data { ...@@ -273,6 +319,10 @@ struct iwl_tid_data {
* @sta_lock: protects the station table. * @sta_lock: protects the station table.
* If lock and sta_lock are needed, lock must be acquired first. * If lock and sta_lock are needed, lock must be acquired first.
* @mutex: * @mutex:
* @ucode_type: indicator of loaded ucode image
* @notif_waits: things waiting for notification
* @notif_wait_lock: lock protecting notification
* @notif_waitq: head of notification wait queue
*/ */
struct iwl_shared { struct iwl_shared {
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
...@@ -300,6 +350,14 @@ struct iwl_shared { ...@@ -300,6 +350,14 @@ struct iwl_shared {
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
wait_queue_head_t wait_command_queue; wait_queue_head_t wait_command_queue;
/* ucode related variables */
enum iwl_ucode_type ucode_type;
/* notification wait support */
struct list_head notif_waits;
spinlock_t notif_wait_lock;
wait_queue_head_t notif_waitq;
}; };
/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
...@@ -443,6 +501,24 @@ bool iwl_check_for_ct_kill(struct iwl_priv *priv); ...@@ -443,6 +501,24 @@ bool iwl_check_for_ct_kill(struct iwl_priv *priv);
void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac); void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac);
void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac); void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac);
/* notification wait support */
void iwl_abort_notification_waits(struct iwl_shared *shrd);
void __acquires(wait_entry)
iwl_init_notification_wait(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
void *data),
void *fn_data);
int __must_check __releases(wait_entry)
iwl_wait_notification(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry,
unsigned long timeout);
void __releases(wait_entry)
iwl_remove_notification(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_reset_traffic_log(struct iwl_priv *priv); void iwl_reset_traffic_log(struct iwl_priv *priv);
#endif /* CONFIG_IWLWIFI_DEBUGFS */ #endif /* CONFIG_IWLWIFI_DEBUGFS */
......
...@@ -106,6 +106,10 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { ...@@ -106,6 +106,10 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
[IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
[IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
[IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, },
[IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, },
[IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, },
}; };
/* /*
...@@ -177,6 +181,18 @@ void iwl_testmode_init(struct iwl_priv *priv) ...@@ -177,6 +181,18 @@ void iwl_testmode_init(struct iwl_priv *priv)
{ {
priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
priv->testmode_trace.trace_enabled = false; priv->testmode_trace.trace_enabled = false;
priv->testmode_sram.sram_readed = false;
}
static void iwl_sram_cleanup(struct iwl_priv *priv)
{
if (priv->testmode_sram.sram_readed) {
kfree(priv->testmode_sram.buff_addr);
priv->testmode_sram.buff_addr = NULL;
priv->testmode_sram.buff_size = 0;
priv->testmode_sram.num_chunks = 0;
priv->testmode_sram.sram_readed = false;
}
} }
static void iwl_trace_cleanup(struct iwl_priv *priv) static void iwl_trace_cleanup(struct iwl_priv *priv)
...@@ -201,6 +217,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv) ...@@ -201,6 +217,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv)
void iwl_testmode_cleanup(struct iwl_priv *priv) void iwl_testmode_cleanup(struct iwl_priv *priv)
{ {
iwl_trace_cleanup(priv); iwl_trace_cleanup(priv);
iwl_sram_cleanup(priv);
} }
/* /*
...@@ -356,7 +373,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) ...@@ -356,7 +373,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
struct iwl_notification_wait calib_wait; struct iwl_notification_wait calib_wait;
int ret; int ret;
iwlagn_init_notification_wait(priv, &calib_wait, iwl_init_notification_wait(priv->shrd, &calib_wait,
CALIBRATION_COMPLETE_NOTIFICATION, CALIBRATION_COMPLETE_NOTIFICATION,
NULL, NULL); NULL, NULL);
ret = iwlagn_init_alive_start(priv); ret = iwlagn_init_alive_start(priv);
...@@ -366,14 +383,14 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) ...@@ -366,14 +383,14 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
goto cfg_init_calib_error; goto cfg_init_calib_error;
} }
ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
if (ret) if (ret)
IWL_DEBUG_INFO(priv, "Error detecting" IWL_DEBUG_INFO(priv, "Error detecting"
" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
return ret; return ret;
cfg_init_calib_error: cfg_init_calib_error:
iwlagn_remove_notification(priv, &calib_wait); iwl_remove_notification(priv->shrd, &calib_wait);
return ret; return ret;
} }
...@@ -446,6 +463,21 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) ...@@ -446,6 +463,21 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
"Error starting the device: %d\n", status); "Error starting the device: %d\n", status);
break; break;
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
iwl_scan_cancel_timeout(priv, 200);
iwl_trans_stop_device(trans(priv));
status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
if (status) {
IWL_DEBUG_INFO(priv,
"Error loading WOWLAN ucode: %d\n", status);
break;
}
status = iwl_alive_start(priv);
if (status)
IWL_DEBUG_INFO(priv,
"Error starting the device: %d\n", status);
break;
case IWL_TM_CMD_APP2DEV_GET_EEPROM: case IWL_TM_CMD_APP2DEV_GET_EEPROM:
if (priv->eeprom) { if (priv->eeprom) {
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
...@@ -558,7 +590,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) ...@@ -558,7 +590,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
} }
priv->testmode_trace.num_chunks = priv->testmode_trace.num_chunks =
DIV_ROUND_UP(priv->testmode_trace.buff_size, DIV_ROUND_UP(priv->testmode_trace.buff_size,
TRACE_CHUNK_SIZE); DUMP_CHUNK_SIZE);
break; break;
case IWL_TM_CMD_APP2DEV_END_TRACE: case IWL_TM_CMD_APP2DEV_END_TRACE:
...@@ -590,15 +622,15 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, ...@@ -590,15 +622,15 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
idx = cb->args[4]; idx = cb->args[4];
if (idx >= priv->testmode_trace.num_chunks) if (idx >= priv->testmode_trace.num_chunks)
return -ENOENT; return -ENOENT;
length = TRACE_CHUNK_SIZE; length = DUMP_CHUNK_SIZE;
if (((idx + 1) == priv->testmode_trace.num_chunks) && if (((idx + 1) == priv->testmode_trace.num_chunks) &&
(priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE)) (priv->testmode_trace.buff_size % DUMP_CHUNK_SIZE))
length = priv->testmode_trace.buff_size % length = priv->testmode_trace.buff_size %
TRACE_CHUNK_SIZE; DUMP_CHUNK_SIZE;
NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length, NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
priv->testmode_trace.trace_addr + priv->testmode_trace.trace_addr +
(TRACE_CHUNK_SIZE * idx)); (DUMP_CHUNK_SIZE * idx));
idx++; idx++;
cb->args[4] = idx; cb->args[4] = idx;
return 0; return 0;
...@@ -644,6 +676,110 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) ...@@ -644,6 +676,110 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
return 0; return 0;
} }
/*
* This function handles the user application commands for SRAM data dump
*
* It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and
* IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading
*
* Several error will be retured, -EBUSY if the SRAM data retrieved by
* previous command has not been delivered to userspace, or -ENOMSG if
* the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE)
* are missing, or -ENOMEM if the buffer allocation fails.
*
* Otherwise 0 is replied indicating the success of the SRAM reading.
*
* @hw: ieee80211_hw object that represents the device
* @tb: gnl message fields from the user space
*/
static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb)
{
struct iwl_priv *priv = hw->priv;
u32 base, ofs, size, maxsize;
if (priv->testmode_sram.sram_readed)
return -EBUSY;
if (!tb[IWL_TM_ATTR_SRAM_ADDR]) {
IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n");
return -ENOMSG;
}
ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]);
if (!tb[IWL_TM_ATTR_SRAM_SIZE]) {
IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n");
return -ENOMSG;
}
size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]);
switch (priv->shrd->ucode_type) {
case IWL_UCODE_REGULAR:
maxsize = trans(priv)->ucode_rt.data.len;
break;
case IWL_UCODE_INIT:
maxsize = trans(priv)->ucode_init.data.len;
break;
case IWL_UCODE_WOWLAN:
maxsize = trans(priv)->ucode_wowlan.data.len;
break;
case IWL_UCODE_NONE:
IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n");
return -ENOSYS;
default:
IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n");
return -ENOSYS;
}
if ((ofs + size) > maxsize) {
IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n");
return -EINVAL;
}
priv->testmode_sram.buff_size = (size / 4) * 4;
priv->testmode_sram.buff_addr =
kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL);
if (priv->testmode_sram.buff_addr == NULL) {
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
return -ENOMEM;
}
base = 0x800000;
_iwl_read_targ_mem_words(bus(priv), base + ofs,
priv->testmode_sram.buff_addr,
priv->testmode_sram.buff_size / 4);
priv->testmode_sram.num_chunks =
DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE);
priv->testmode_sram.sram_readed = true;
return 0;
}
static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb,
struct sk_buff *skb,
struct netlink_callback *cb)
{
struct iwl_priv *priv = hw->priv;
int idx, length;
if (priv->testmode_sram.sram_readed) {
idx = cb->args[4];
if (idx >= priv->testmode_sram.num_chunks) {
iwl_sram_cleanup(priv);
return -ENOENT;
}
length = DUMP_CHUNK_SIZE;
if (((idx + 1) == priv->testmode_sram.num_chunks) &&
(priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE))
length = priv->testmode_sram.buff_size %
DUMP_CHUNK_SIZE;
NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length,
priv->testmode_sram.buff_addr +
(DUMP_CHUNK_SIZE * idx));
idx++;
cb->args[4] = idx;
return 0;
} else
return -EFAULT;
nla_put_failure:
return -ENOBUFS;
}
/* The testmode gnl message handler that takes the gnl message from the /* The testmode gnl message handler that takes the gnl message from the
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
...@@ -705,6 +841,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) ...@@ -705,6 +841,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
case IWL_TM_CMD_APP2DEV_GET_EEPROM: case IWL_TM_CMD_APP2DEV_GET_EEPROM:
case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
result = iwl_testmode_driver(hw, tb); result = iwl_testmode_driver(hw, tb);
break; break;
...@@ -721,6 +858,11 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) ...@@ -721,6 +858,11 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
result = iwl_testmode_ownership(hw, tb); result = iwl_testmode_ownership(hw, tb);
break; break;
case IWL_TM_CMD_APP2DEV_READ_SRAM:
IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n");
result = iwl_testmode_sram(hw, tb);
break;
default: default:
IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
result = -ENOSYS; result = -ENOSYS;
...@@ -769,6 +911,10 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -769,6 +911,10 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
result = iwl_testmode_trace_dump(hw, tb, skb, cb); result = iwl_testmode_trace_dump(hw, tb, skb, cb);
break; break;
case IWL_TM_CMD_APP2DEV_DUMP_SRAM:
IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
result = iwl_testmode_sram_dump(hw, tb, skb, cb);
break;
default: default:
result = -EINVAL; result = -EINVAL;
break; break;
......
...@@ -103,14 +103,22 @@ ...@@ -103,14 +103,22 @@
* @IWL_TM_CMD_DEV2APP_EEPROM_RSP: * @IWL_TM_CMD_DEV2APP_EEPROM_RSP:
* commands from kernel space to carry the eeprom response * commands from kernel space to carry the eeprom response
* to user application * to user application
*
* @IWL_TM_CMD_APP2DEV_OWNERSHIP: * @IWL_TM_CMD_APP2DEV_OWNERSHIP:
* commands from user application to own change the ownership of the uCode * commands from user application to own change the ownership of the uCode
* if application has the ownership, the only host command from * if application has the ownership, the only host command from
* testmode will deliver to uCode. Default owner is driver * testmode will deliver to uCode. Default owner is driver
*
* @IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
* @IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
* commands from user applicaiton to indirectly access peripheral register * commands from user applicaiton to indirectly access peripheral register
* *
* @IWL_TM_CMD_APP2DEV_READ_SRAM:
* @IWL_TM_CMD_APP2DEV_DUMP_SRAM:
* commands from user applicaiton to read data in sram
*
* @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image
*
*/ */
enum iwl_tm_cmd_t { enum iwl_tm_cmd_t {
IWL_TM_CMD_APP2DEV_UCODE = 1, IWL_TM_CMD_APP2DEV_UCODE = 1,
...@@ -132,7 +140,10 @@ enum iwl_tm_cmd_t { ...@@ -132,7 +140,10 @@ enum iwl_tm_cmd_t {
IWL_TM_CMD_APP2DEV_OWNERSHIP = 17, IWL_TM_CMD_APP2DEV_OWNERSHIP = 17,
IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32 = 18, IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32 = 18,
IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32 = 19, IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32 = 19,
IWL_TM_CMD_MAX = 20, IWL_TM_CMD_APP2DEV_READ_SRAM = 20,
IWL_TM_CMD_APP2DEV_DUMP_SRAM = 21,
IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22,
IWL_TM_CMD_MAX = 23,
}; };
/* /*
...@@ -202,6 +213,18 @@ enum iwl_tm_cmd_t { ...@@ -202,6 +213,18 @@ enum iwl_tm_cmd_t {
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP, * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP,
* The mandatory fields are: * The mandatory fields are:
* IWL_TM_ATTR_UCODE_OWNER for the new owner * IWL_TM_ATTR_UCODE_OWNER for the new owner
*
* @IWL_TM_ATTR_SRAM_ADDR:
* @IWL_TM_ATTR_SRAM_SIZE:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_READ_SRAM,
* The mandatory fields are:
* IWL_TM_ATTR_SRAM_ADDR for the address in sram
* IWL_TM_ATTR_SRAM_SIZE for the buffer size of data reading
*
* @IWL_TM_ATTR_SRAM_DUMP:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM,
* IWL_TM_ATTR_SRAM_DUMP for the data in sram
*
*/ */
enum iwl_tm_attr_t { enum iwl_tm_attr_t {
IWL_TM_ATTR_NOT_APPLICABLE = 0, IWL_TM_ATTR_NOT_APPLICABLE = 0,
...@@ -219,7 +242,10 @@ enum iwl_tm_attr_t { ...@@ -219,7 +242,10 @@ enum iwl_tm_attr_t {
IWL_TM_ATTR_TRACE_DUMP = 12, IWL_TM_ATTR_TRACE_DUMP = 12,
IWL_TM_ATTR_FIXRATE = 13, IWL_TM_ATTR_FIXRATE = 13,
IWL_TM_ATTR_UCODE_OWNER = 14, IWL_TM_ATTR_UCODE_OWNER = 14,
IWL_TM_ATTR_MAX = 15, IWL_TM_ATTR_SRAM_ADDR = 15,
IWL_TM_ATTR_SRAM_SIZE = 16,
IWL_TM_ATTR_SRAM_DUMP = 17,
IWL_TM_ATTR_MAX = 18,
}; };
/* uCode trace buffer */ /* uCode trace buffer */
...@@ -227,6 +253,8 @@ enum iwl_tm_attr_t { ...@@ -227,6 +253,8 @@ enum iwl_tm_attr_t {
#define TRACE_BUFF_SIZE_MIN 0x20000 #define TRACE_BUFF_SIZE_MIN 0x20000
#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN #define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN
#define TRACE_BUFF_PADD 0x2000 #define TRACE_BUFF_PADD 0x2000
#define TRACE_CHUNK_SIZE (PAGE_SIZE - 1024)
/* Maximum data size of each dump it packet */
#define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024)
#endif #endif
...@@ -595,7 +595,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) ...@@ -595,7 +595,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
IWL_TRANS_GET_PCIE_TRANS(trans); IWL_TRANS_GET_PCIE_TRANS(trans);
base = priv->device_pointers.error_event_table; base = priv->device_pointers.error_event_table;
if (priv->ucode_type == IWL_UCODE_INIT) { if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
if (!base) if (!base)
base = priv->init_errlog_ptr; base = priv->init_errlog_ptr;
} else { } else {
...@@ -607,7 +607,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) ...@@ -607,7 +607,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
IWL_ERR(trans, IWL_ERR(trans,
"Not valid error log pointer 0x%08X for %s uCode\n", "Not valid error log pointer 0x%08X for %s uCode\n",
base, base,
(priv->ucode_type == IWL_UCODE_INIT) (trans->shrd->ucode_type == IWL_UCODE_INIT)
? "Init" : "RT"); ? "Init" : "RT");
return; return;
} }
...@@ -710,7 +710,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, ...@@ -710,7 +710,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
return pos; return pos;
base = priv->device_pointers.log_event_table; base = priv->device_pointers.log_event_table;
if (priv->ucode_type == IWL_UCODE_INIT) { if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
if (!base) if (!base)
base = priv->init_evtlog_ptr; base = priv->init_evtlog_ptr;
} else { } else {
...@@ -824,7 +824,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, ...@@ -824,7 +824,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
struct iwl_priv *priv = priv(trans); struct iwl_priv *priv = priv(trans);
base = priv->device_pointers.log_event_table; base = priv->device_pointers.log_event_table;
if (priv->ucode_type == IWL_UCODE_INIT) { if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
logsize = priv->init_evtlog_size; logsize = priv->init_evtlog_size;
if (!base) if (!base)
base = priv->init_evtlog_ptr; base = priv->init_evtlog_ptr;
...@@ -838,7 +838,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, ...@@ -838,7 +838,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
IWL_ERR(trans, IWL_ERR(trans,
"Invalid event log pointer 0x%08X for %s uCode\n", "Invalid event log pointer 0x%08X for %s uCode\n",
base, base,
(priv->ucode_type == IWL_UCODE_INIT) (trans->shrd->ucode_type == IWL_UCODE_INIT)
? "Init" : "RT"); ? "Init" : "RT");
return -EINVAL; return -EINVAL;
} }
......
...@@ -220,13 +220,6 @@ struct fw_img { ...@@ -220,13 +220,6 @@ struct fw_img {
struct fw_desc data; /* firmware data image */ struct fw_desc data; /* firmware data image */
}; };
enum iwl_ucode_type {
IWL_UCODE_NONE,
IWL_UCODE_REGULAR,
IWL_UCODE_INIT,
IWL_UCODE_WOWLAN,
};
/** /**
* struct iwl_trans - transport common data * struct iwl_trans - transport common data
* @ops - pointer to iwl_trans_ops * @ops - pointer to iwl_trans_ops
......
...@@ -122,7 +122,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, ...@@ -122,7 +122,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
/* /*
* ucode * ucode
*/ */
static int iwlagn_load_section(struct iwl_trans *trans, const char *name, static int iwl_load_section(struct iwl_trans *trans, const char *name,
struct fw_desc *image, u32 dst_addr) struct fw_desc *image, u32 dst_addr)
{ {
struct iwl_bus *bus = bus(trans); struct iwl_bus *bus = bus(trans);
...@@ -188,7 +188,7 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, ...@@ -188,7 +188,7 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
return NULL; return NULL;
} }
static int iwlagn_load_given_ucode(struct iwl_trans *trans, static int iwl_load_given_ucode(struct iwl_trans *trans,
enum iwl_ucode_type ucode_type) enum iwl_ucode_type ucode_type)
{ {
int ret = 0; int ret = 0;
...@@ -201,19 +201,19 @@ static int iwlagn_load_given_ucode(struct iwl_trans *trans, ...@@ -201,19 +201,19 @@ static int iwlagn_load_given_ucode(struct iwl_trans *trans,
return -EINVAL; return -EINVAL;
} }
ret = iwlagn_load_section(trans, "INST", &image->code, ret = iwl_load_section(trans, "INST", &image->code,
IWLAGN_RTC_INST_LOWER_BOUND); IWLAGN_RTC_INST_LOWER_BOUND);
if (ret) if (ret)
return ret; return ret;
return iwlagn_load_section(trans, "DATA", &image->data, return iwl_load_section(trans, "DATA", &image->data,
IWLAGN_RTC_DATA_LOWER_BOUND); IWLAGN_RTC_DATA_LOWER_BOUND);
} }
/* /*
* Calibration * Calibration
*/ */
static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) static int iwl_set_Xtal_calib(struct iwl_priv *priv)
{ {
struct iwl_calib_xtal_freq_cmd cmd; struct iwl_calib_xtal_freq_cmd cmd;
__le16 *xtal_calib = __le16 *xtal_calib =
...@@ -225,7 +225,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) ...@@ -225,7 +225,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
} }
static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
{ {
struct iwl_calib_temperature_offset_cmd cmd; struct iwl_calib_temperature_offset_cmd cmd;
__le16 *offset_calib = __le16 *offset_calib =
...@@ -242,7 +242,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) ...@@ -242,7 +242,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
} }
static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
{ {
struct iwl_calib_temperature_offset_v2_cmd cmd; struct iwl_calib_temperature_offset_v2_cmd cmd;
__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv,
...@@ -277,7 +277,7 @@ static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) ...@@ -277,7 +277,7 @@ static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv)
return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
} }
static int iwlagn_send_calib_cfg(struct iwl_priv *priv) static int iwl_send_calib_cfg(struct iwl_trans *trans)
{ {
struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_calib_cfg_cmd calib_cfg_cmd;
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
...@@ -293,7 +293,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) ...@@ -293,7 +293,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
calib_cfg_cmd.ucd_calib_cfg.flags = calib_cfg_cmd.ucd_calib_cfg.flags =
IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
return iwl_trans_send_cmd(trans(priv), &cmd); return iwl_trans_send_cmd(trans, &cmd);
} }
int iwlagn_rx_calib_result(struct iwl_priv *priv, int iwlagn_rx_calib_result(struct iwl_priv *priv,
...@@ -326,14 +326,14 @@ int iwlagn_init_alive_start(struct iwl_priv *priv) ...@@ -326,14 +326,14 @@ int iwlagn_init_alive_start(struct iwl_priv *priv)
* no need to close the envlope since we are going * no need to close the envlope since we are going
* to load the runtime uCode later. * to load the runtime uCode later.
*/ */
ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret) if (ret)
return ret; return ret;
} }
ret = iwlagn_send_calib_cfg(priv); ret = iwl_send_calib_cfg(trans(priv));
if (ret) if (ret)
return ret; return ret;
...@@ -343,15 +343,15 @@ int iwlagn_init_alive_start(struct iwl_priv *priv) ...@@ -343,15 +343,15 @@ int iwlagn_init_alive_start(struct iwl_priv *priv)
*/ */
if (priv->cfg->need_temp_offset_calib) { if (priv->cfg->need_temp_offset_calib) {
if (priv->cfg->temp_offset_v2) if (priv->cfg->temp_offset_v2)
return iwlagn_set_temperature_offset_calib_v2(priv); return iwl_set_temperature_offset_calib_v2(priv);
else else
return iwlagn_set_temperature_offset_calib(priv); return iwl_set_temperature_offset_calib(priv);
} }
return 0; return 0;
} }
static int iwlagn_send_wimax_coex(struct iwl_priv *priv) static int iwl_send_wimax_coex(struct iwl_priv *priv)
{ {
struct iwl_wimax_coex_cmd coex_cmd; struct iwl_wimax_coex_cmd coex_cmd;
...@@ -379,7 +379,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) ...@@ -379,7 +379,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
sizeof(coex_cmd), &coex_cmd); sizeof(coex_cmd), &coex_cmd);
} }
static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
...@@ -401,42 +401,42 @@ static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { ...@@ -401,42 +401,42 @@ static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0
}; };
void iwlagn_send_prio_tbl(struct iwl_priv *priv) void iwl_send_prio_tbl(struct iwl_trans *trans)
{ {
struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl,
sizeof(iwlagn_bt_prio_tbl)); sizeof(iwl_bt_prio_tbl));
if (iwl_trans_send_cmd_pdu(trans(priv), if (iwl_trans_send_cmd_pdu(trans,
REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
sizeof(prio_tbl_cmd), &prio_tbl_cmd)) sizeof(prio_tbl_cmd), &prio_tbl_cmd))
IWL_ERR(priv, "failed to send BT prio tbl command\n"); IWL_ERR(trans, "failed to send BT prio tbl command\n");
} }
int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type)
{ {
struct iwl_bt_coex_prot_env_cmd env_cmd; struct iwl_bt_coex_prot_env_cmd env_cmd;
int ret; int ret;
env_cmd.action = action; env_cmd.action = action;
env_cmd.type = type; env_cmd.type = type;
ret = iwl_trans_send_cmd_pdu(trans(priv), ret = iwl_trans_send_cmd_pdu(trans,
REPLY_BT_COEX_PROT_ENV, CMD_SYNC, REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
sizeof(env_cmd), &env_cmd); sizeof(env_cmd), &env_cmd);
if (ret) if (ret)
IWL_ERR(priv, "failed to send BT env command\n"); IWL_ERR(trans, "failed to send BT env command\n");
return ret; return ret;
} }
static int iwlagn_alive_notify(struct iwl_priv *priv) static int iwl_alive_notify(struct iwl_priv *priv)
{ {
struct iwl_rxon_context *ctx; struct iwl_rxon_context *ctx;
int ret; int ret;
if (!priv->tx_cmd_pool) if (!priv->tx_cmd_pool)
priv->tx_cmd_pool = priv->tx_cmd_pool =
kmem_cache_create("iwlagn_dev_cmd", kmem_cache_create("iwl_dev_cmd",
sizeof(struct iwl_device_cmd), sizeof(struct iwl_device_cmd),
sizeof(void *), 0, NULL); sizeof(void *), 0, NULL);
...@@ -447,12 +447,12 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) ...@@ -447,12 +447,12 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
for_each_context(priv, ctx) for_each_context(priv, ctx)
ctx->last_tx_rejected = false; ctx->last_tx_rejected = false;
ret = iwlagn_send_wimax_coex(priv); ret = iwl_send_wimax_coex(priv);
if (ret) if (ret)
return ret; return ret;
if (!priv->cfg->no_xtal_calib) { if (!priv->cfg->no_xtal_calib) {
ret = iwlagn_set_Xtal_calib(priv); ret = iwl_set_Xtal_calib(priv);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -548,7 +548,7 @@ struct iwlagn_alive_data { ...@@ -548,7 +548,7 @@ struct iwlagn_alive_data {
u8 subtype; u8 subtype;
}; };
static void iwlagn_alive_fn(struct iwl_priv *priv, static void iwl_alive_fn(struct iwl_priv *priv,
struct iwl_rx_packet *pkt, struct iwl_rx_packet *pkt,
void *data) void *data)
{ {
...@@ -571,6 +571,70 @@ static void iwlagn_alive_fn(struct iwl_priv *priv, ...@@ -571,6 +571,70 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
alive_data->valid = palive->is_valid == UCODE_VALID_OK; alive_data->valid = palive->is_valid == UCODE_VALID_OK;
} }
/* notification wait support */
void iwl_init_notification_wait(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
void *data),
void *fn_data)
{
wait_entry->fn = fn;
wait_entry->fn_data = fn_data;
wait_entry->cmd = cmd;
wait_entry->triggered = false;
wait_entry->aborted = false;
spin_lock_bh(&shrd->notif_wait_lock);
list_add(&wait_entry->list, &shrd->notif_waits);
spin_unlock_bh(&shrd->notif_wait_lock);
}
int iwl_wait_notification(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry,
unsigned long timeout)
{
int ret;
ret = wait_event_timeout(shrd->notif_waitq,
wait_entry->triggered || wait_entry->aborted,
timeout);
spin_lock_bh(&shrd->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&shrd->notif_wait_lock);
if (wait_entry->aborted)
return -EIO;
/* return value is always >= 0 */
if (ret <= 0)
return -ETIMEDOUT;
return 0;
}
void iwl_remove_notification(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry)
{
spin_lock_bh(&shrd->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&shrd->notif_wait_lock);
}
void iwl_abort_notification_waits(struct iwl_shared *shrd)
{
unsigned long flags;
struct iwl_notification_wait *wait_entry;
spin_lock_irqsave(&shrd->notif_wait_lock, flags);
list_for_each_entry(wait_entry, &shrd->notif_waits, list)
wait_entry->aborted = true;
spin_unlock_irqrestore(&shrd->notif_wait_lock, flags);
wake_up_all(&shrd->notif_waitq);
}
#define UCODE_ALIVE_TIMEOUT HZ #define UCODE_ALIVE_TIMEOUT HZ
#define UCODE_CALIB_TIMEOUT (2*HZ) #define UCODE_CALIB_TIMEOUT (2*HZ)
...@@ -579,41 +643,43 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, ...@@ -579,41 +643,43 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
{ {
struct iwl_notification_wait alive_wait; struct iwl_notification_wait alive_wait;
struct iwlagn_alive_data alive_data; struct iwlagn_alive_data alive_data;
struct iwl_trans *trans = trans(priv);
int ret; int ret;
enum iwl_ucode_type old_type; enum iwl_ucode_type old_type;
ret = iwl_trans_start_device(trans(priv)); ret = iwl_trans_start_device(trans);
if (ret) if (ret)
return ret; return ret;
iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE,
iwlagn_alive_fn, &alive_data); iwl_alive_fn, &alive_data);
old_type = priv->ucode_type; old_type = trans->shrd->ucode_type;
priv->ucode_type = ucode_type; trans->shrd->ucode_type = ucode_type;
ret = iwlagn_load_given_ucode(trans(priv), ucode_type); ret = iwl_load_given_ucode(trans, ucode_type);
if (ret) { if (ret) {
priv->ucode_type = old_type; trans->shrd->ucode_type = old_type;
iwlagn_remove_notification(priv, &alive_wait); iwl_remove_notification(trans->shrd, &alive_wait);
return ret; return ret;
} }
iwl_trans_kick_nic(trans(priv)); iwl_trans_kick_nic(trans);
/* /*
* Some things may run in the background now, but we * Some things may run in the background now, but we
* just wait for the ALIVE notification here. * just wait for the ALIVE notification here.
*/ */
ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); ret = iwl_wait_notification(trans->shrd, &alive_wait,
UCODE_ALIVE_TIMEOUT);
if (ret) { if (ret) {
priv->ucode_type = old_type; trans->shrd->ucode_type = old_type;
return ret; return ret;
} }
if (!alive_data.valid) { if (!alive_data.valid) {
IWL_ERR(priv, "Loaded ucode is not valid!\n"); IWL_ERR(priv, "Loaded ucode is not valid!\n");
priv->ucode_type = old_type; trans->shrd->ucode_type = old_type;
return -EIO; return -EIO;
} }
...@@ -623,9 +689,9 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, ...@@ -623,9 +689,9 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
* skip it for WoWLAN. * skip it for WoWLAN.
*/ */
if (ucode_type != IWL_UCODE_WOWLAN) { if (ucode_type != IWL_UCODE_WOWLAN) {
ret = iwl_verify_ucode(trans(priv), ucode_type); ret = iwl_verify_ucode(trans, ucode_type);
if (ret) { if (ret) {
priv->ucode_type = old_type; trans->shrd->ucode_type = old_type;
return ret; return ret;
} }
...@@ -633,11 +699,11 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, ...@@ -633,11 +699,11 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
msleep(5); msleep(5);
} }
ret = iwlagn_alive_notify(priv); ret = iwl_alive_notify(priv);
if (ret) { if (ret) {
IWL_WARN(priv, IWL_WARN(priv,
"Could not complete ALIVE transition: %d\n", ret); "Could not complete ALIVE transition: %d\n", ret);
priv->ucode_type = old_type; trans->shrd->ucode_type = old_type;
return ret; return ret;
} }
...@@ -655,10 +721,10 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) ...@@ -655,10 +721,10 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
if (!trans(priv)->ucode_init.code.len) if (!trans(priv)->ucode_init.code.len)
return 0; return 0;
if (priv->ucode_type != IWL_UCODE_NONE) if (priv->shrd->ucode_type != IWL_UCODE_NONE)
return 0; return 0;
iwlagn_init_notification_wait(priv, &calib_wait, iwl_init_notification_wait(priv->shrd, &calib_wait,
CALIBRATION_COMPLETE_NOTIFICATION, CALIBRATION_COMPLETE_NOTIFICATION,
NULL, NULL); NULL, NULL);
...@@ -675,12 +741,13 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) ...@@ -675,12 +741,13 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
* Some things may run in the background now, but we * Some things may run in the background now, but we
* just wait for the calibration complete notification. * just wait for the calibration complete notification.
*/ */
ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); ret = iwl_wait_notification(priv->shrd, &calib_wait,
UCODE_CALIB_TIMEOUT);
goto out; goto out;
error: error:
iwlagn_remove_notification(priv, &calib_wait); iwl_remove_notification(priv->shrd, &calib_wait);
out: out:
/* Whatever happened, stop the device */ /* Whatever happened, stop the device */
iwl_trans_stop_device(trans(priv)); iwl_trans_stop_device(trans(priv));
......
...@@ -831,11 +831,11 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, ...@@ -831,11 +831,11 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
if (spec->supported_rates & SUPPORT_RATE_OFDM) if (spec->supported_rates & SUPPORT_RATE_OFDM)
num_rates += 8; num_rates += 8;
channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); channels = kcalloc(spec->num_channels, sizeof(*channels), GFP_KERNEL);
if (!channels) if (!channels)
return -ENOMEM; return -ENOMEM;
rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL); rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL);
if (!rates) if (!rates)
goto exit_free_channels; goto exit_free_channels;
......
...@@ -262,10 +262,10 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) ...@@ -262,10 +262,10 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
u32 fwsize; u32 fwsize;
enum version_8192c version = rtlhal->version; enum version_8192c version = rtlhal->version;
pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
if (!rtlhal->pfirmware) if (!rtlhal->pfirmware)
return 1; return 1;
pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
pfwdata = (u8 *) rtlhal->pfirmware; pfwdata = (u8 *) rtlhal->pfirmware;
fwsize = rtlhal->fwsize; fwsize = rtlhal->fwsize;
......
...@@ -42,16 +42,6 @@ config WL12XX_SDIO ...@@ -42,16 +42,6 @@ config WL12XX_SDIO
If you choose to build a module, it'll be called wl12xx_sdio. If you choose to build a module, it'll be called wl12xx_sdio.
Say N if unsure. Say N if unsure.
config WL12XX_SDIO_TEST
tristate "TI wl12xx SDIO testing support"
depends on WL12XX && MMC && WL12XX_SDIO
default n
---help---
This module adds support for the SDIO bus testing with the
TI wl12xx chipsets. You probably don't want this unless you are
testing a new hardware platform. Select this if you want to test the
SDIO bus which is connected to the wl12xx chip.
config WL12XX_PLATFORM_DATA config WL12XX_PLATFORM_DATA
bool bool
depends on WL12XX_SDIO != n || WL1251_SDIO != n depends on WL12XX_SDIO != n || WL1251_SDIO != n
......
...@@ -3,14 +3,11 @@ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ ...@@ -3,14 +3,11 @@ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
wl12xx_spi-objs = spi.o wl12xx_spi-objs = spi.o
wl12xx_sdio-objs = sdio.o wl12xx_sdio-objs = sdio.o
wl12xx_sdio_test-objs = sdio_test.o
wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_WL12XX) += wl12xx.o obj-$(CONFIG_WL12XX) += wl12xx.o
obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o
obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o
obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o
# small builtin driver bit # small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
...@@ -29,11 +29,12 @@ ...@@ -29,11 +29,12 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "wl12xx.h" #include "wl12xx.h"
#include "debug.h"
#include "wl12xx_80211.h" #include "wl12xx_80211.h"
#include "reg.h" #include "reg.h"
#include "ps.h" #include "ps.h"
int wl1271_acx_wake_up_conditions(struct wl1271 *wl) int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
struct acx_wake_up_condition *wake_up; struct acx_wake_up_condition *wake_up;
int ret; int ret;
...@@ -46,7 +47,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl) ...@@ -46,7 +47,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
goto out; goto out;
} }
wake_up->role_id = wl->role_id; wake_up->role_id = wlvif->role_id;
wake_up->wake_up_event = wl->conf.conn.wake_up_event; wake_up->wake_up_event = wl->conf.conn.wake_up_event;
wake_up->listen_interval = wl->conf.conn.listen_interval; wake_up->listen_interval = wl->conf.conn.listen_interval;
...@@ -84,7 +85,8 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) ...@@ -84,7 +85,8 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
return ret; return ret;
} }
int wl1271_acx_tx_power(struct wl1271 *wl, int power) int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int power)
{ {
struct acx_current_tx_power *acx; struct acx_current_tx_power *acx;
int ret; int ret;
...@@ -100,7 +102,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) ...@@ -100,7 +102,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->current_tx_power = power * 10; acx->current_tx_power = power * 10;
ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
...@@ -114,7 +116,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) ...@@ -114,7 +116,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
return ret; return ret;
} }
int wl1271_acx_feature_cfg(struct wl1271 *wl) int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
struct acx_feature_config *feature; struct acx_feature_config *feature;
int ret; int ret;
...@@ -128,7 +130,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl) ...@@ -128,7 +130,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl)
} }
/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
feature->role_id = wl->role_id; feature->role_id = wlvif->role_id;
feature->data_flow_options = 0; feature->data_flow_options = 0;
feature->options = 0; feature->options = 0;
...@@ -210,7 +212,8 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) ...@@ -210,7 +212,8 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum acx_slot_type slot_time)
{ {
struct acx_slot *slot; struct acx_slot *slot;
int ret; int ret;
...@@ -223,7 +226,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) ...@@ -223,7 +226,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
goto out; goto out;
} }
slot->role_id = wl->role_id; slot->role_id = wlvif->role_id;
slot->wone_index = STATION_WONE_INDEX; slot->wone_index = STATION_WONE_INDEX;
slot->slot_time = slot_time; slot->slot_time = slot_time;
...@@ -238,8 +241,8 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) ...@@ -238,8 +241,8 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
return ret; return ret;
} }
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif,
void *mc_list, u32 mc_list_len) bool enable, void *mc_list, u32 mc_list_len)
{ {
struct acx_dot11_grp_addr_tbl *acx; struct acx_dot11_grp_addr_tbl *acx;
int ret; int ret;
...@@ -253,7 +256,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, ...@@ -253,7 +256,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
} }
/* MAC filtering */ /* MAC filtering */
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->enabled = enable; acx->enabled = enable;
acx->num_groups = mc_list_len; acx->num_groups = mc_list_len;
memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
...@@ -270,7 +273,8 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, ...@@ -270,7 +273,8 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
return ret; return ret;
} }
int wl1271_acx_service_period_timeout(struct wl1271 *wl) int wl1271_acx_service_period_timeout(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
{ {
struct acx_rx_timeout *rx_timeout; struct acx_rx_timeout *rx_timeout;
int ret; int ret;
...@@ -283,7 +287,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl) ...@@ -283,7 +287,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
wl1271_debug(DEBUG_ACX, "acx service period timeout"); wl1271_debug(DEBUG_ACX, "acx service period timeout");
rx_timeout->role_id = wl->role_id; rx_timeout->role_id = wlvif->role_id;
rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout);
rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout);
...@@ -300,7 +304,8 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl) ...@@ -300,7 +304,8 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) int wl1271_acx_rts_threshold(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u32 rts_threshold)
{ {
struct acx_rts_threshold *rts; struct acx_rts_threshold *rts;
int ret; int ret;
...@@ -320,7 +325,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) ...@@ -320,7 +325,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold)
goto out; goto out;
} }
rts->role_id = wl->role_id; rts->role_id = wlvif->role_id;
rts->threshold = cpu_to_le16((u16)rts_threshold); rts->threshold = cpu_to_le16((u16)rts_threshold);
ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
...@@ -363,7 +368,8 @@ int wl1271_acx_dco_itrim_params(struct wl1271 *wl) ...@@ -363,7 +368,8 @@ int wl1271_acx_dco_itrim_params(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool enable_filter)
{ {
struct acx_beacon_filter_option *beacon_filter = NULL; struct acx_beacon_filter_option *beacon_filter = NULL;
int ret = 0; int ret = 0;
...@@ -380,7 +386,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) ...@@ -380,7 +386,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
goto out; goto out;
} }
beacon_filter->role_id = wl->role_id; beacon_filter->role_id = wlvif->role_id;
beacon_filter->enable = enable_filter; beacon_filter->enable = enable_filter;
/* /*
...@@ -401,7 +407,8 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) ...@@ -401,7 +407,8 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
return ret; return ret;
} }
int wl1271_acx_beacon_filter_table(struct wl1271 *wl) int wl1271_acx_beacon_filter_table(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
{ {
struct acx_beacon_filter_ie_table *ie_table; struct acx_beacon_filter_ie_table *ie_table;
int i, idx = 0; int i, idx = 0;
...@@ -417,7 +424,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl) ...@@ -417,7 +424,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
} }
/* configure default beacon pass-through rules */ /* configure default beacon pass-through rules */
ie_table->role_id = wl->role_id; ie_table->role_id = wlvif->role_id;
ie_table->num_ie = 0; ie_table->num_ie = 0;
for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) {
struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]);
...@@ -458,7 +465,8 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl) ...@@ -458,7 +465,8 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
#define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff #define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff
int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) int wl1271_acx_conn_monit_params(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool enable)
{ {
struct acx_conn_monit_params *acx; struct acx_conn_monit_params *acx;
u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE;
...@@ -479,7 +487,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) ...@@ -479,7 +487,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
timeout = wl->conf.conn.bss_lose_timeout; timeout = wl->conf.conn.bss_lose_timeout;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->synch_fail_thold = cpu_to_le32(threshold); acx->synch_fail_thold = cpu_to_le32(threshold);
acx->bss_lose_timeout = cpu_to_le32(timeout); acx->bss_lose_timeout = cpu_to_le32(timeout);
...@@ -582,7 +590,7 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl) ...@@ -582,7 +590,7 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
struct acx_beacon_broadcast *bb; struct acx_beacon_broadcast *bb;
int ret; int ret;
...@@ -595,7 +603,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) ...@@ -595,7 +603,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
goto out; goto out;
} }
bb->role_id = wl->role_id; bb->role_id = wlvif->role_id;
bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout);
bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout);
bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps;
...@@ -612,7 +620,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) ...@@ -612,7 +620,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_aid(struct wl1271 *wl, u16 aid) int wl1271_acx_aid(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid)
{ {
struct acx_aid *acx_aid; struct acx_aid *acx_aid;
int ret; int ret;
...@@ -625,7 +633,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid) ...@@ -625,7 +633,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
goto out; goto out;
} }
acx_aid->role_id = wl->role_id; acx_aid->role_id = wlvif->role_id;
acx_aid->aid = cpu_to_le16(aid); acx_aid->aid = cpu_to_le16(aid);
ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
...@@ -668,7 +676,8 @@ int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask) ...@@ -668,7 +676,8 @@ int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask)
return ret; return ret;
} }
int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum acx_preamble_type preamble)
{ {
struct acx_preamble *acx; struct acx_preamble *acx;
int ret; int ret;
...@@ -681,7 +690,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) ...@@ -681,7 +690,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->preamble = preamble; acx->preamble = preamble;
ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
...@@ -695,7 +704,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) ...@@ -695,7 +704,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
return ret; return ret;
} }
int wl1271_acx_cts_protect(struct wl1271 *wl, int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum acx_ctsprotect_type ctsprotect) enum acx_ctsprotect_type ctsprotect)
{ {
struct acx_ctsprotect *acx; struct acx_ctsprotect *acx;
...@@ -709,7 +718,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, ...@@ -709,7 +718,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->ctsprotect = ctsprotect; acx->ctsprotect = ctsprotect;
ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
...@@ -739,7 +748,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) ...@@ -739,7 +748,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
return 0; return 0;
} }
int wl1271_acx_sta_rate_policies(struct wl1271 *wl) int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
struct acx_rate_policy *acx; struct acx_rate_policy *acx;
struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf; struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
...@@ -755,11 +764,11 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) ...@@ -755,11 +764,11 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
} }
wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
wl->basic_rate, wl->rate_set); wlvif->basic_rate, wlvif->rate_set);
/* configure one basic rate class */ /* configure one basic rate class */
acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE); acx->rate_policy_idx = cpu_to_le32(wlvif->sta.basic_rate_idx);
acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate); acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->basic_rate);
acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.short_retry_limit = c->short_retry_limit;
acx->rate_policy.long_retry_limit = c->long_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit;
acx->rate_policy.aflags = c->aflags; acx->rate_policy.aflags = c->aflags;
...@@ -771,8 +780,8 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) ...@@ -771,8 +780,8 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
} }
/* configure one AP supported rate class */ /* configure one AP supported rate class */
acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE); acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx);
acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set); acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set);
acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.short_retry_limit = c->short_retry_limit;
acx->rate_policy.long_retry_limit = c->long_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit;
acx->rate_policy.aflags = c->aflags; acx->rate_policy.aflags = c->aflags;
...@@ -788,7 +797,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) ...@@ -788,7 +797,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
* (p2p packets should always go out with OFDM rates, even * (p2p packets should always go out with OFDM rates, even
* if we are currently connected to 11b AP) * if we are currently connected to 11b AP)
*/ */
acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P); acx->rate_policy_idx = cpu_to_le32(wlvif->sta.p2p_rate_idx);
acx->rate_policy.enabled_rates = acx->rate_policy.enabled_rates =
cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P); cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P);
acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.short_retry_limit = c->short_retry_limit;
...@@ -839,8 +848,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, ...@@ -839,8 +848,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
return ret; return ret;
} }
int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 aifsn, u16 txop) u8 ac, u8 cw_min, u16 cw_max, u8 aifsn, u16 txop)
{ {
struct acx_ac_cfg *acx; struct acx_ac_cfg *acx;
int ret = 0; int ret = 0;
...@@ -855,7 +864,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, ...@@ -855,7 +864,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->ac = ac; acx->ac = ac;
acx->cw_min = cw_min; acx->cw_min = cw_min;
acx->cw_max = cpu_to_le16(cw_max); acx->cw_max = cpu_to_le16(cw_max);
...@@ -873,7 +882,8 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, ...@@ -873,7 +882,8 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
return ret; return ret;
} }
int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, int wl1271_acx_tid_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 queue_id, u8 channel_type,
u8 tsid, u8 ps_scheme, u8 ack_policy, u8 tsid, u8 ps_scheme, u8 ack_policy,
u32 apsd_conf0, u32 apsd_conf1) u32 apsd_conf0, u32 apsd_conf1)
{ {
...@@ -889,7 +899,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, ...@@ -889,7 +899,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->queue_id = queue_id; acx->queue_id = queue_id;
acx->channel_type = channel_type; acx->channel_type = channel_type;
acx->tsid = tsid; acx->tsid = tsid;
...@@ -1098,7 +1108,8 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) ...@@ -1098,7 +1108,8 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool enable)
{ {
struct wl1271_acx_bet_enable *acx = NULL; struct wl1271_acx_bet_enable *acx = NULL;
int ret = 0; int ret = 0;
...@@ -1114,7 +1125,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) ...@@ -1114,7 +1125,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
acx->max_consecutive = wl->conf.conn.bet_max_consecutive; acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
...@@ -1129,7 +1140,8 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) ...@@ -1129,7 +1140,8 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
return ret; return ret;
} }
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) int wl1271_acx_arp_ip_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 enable, __be32 address)
{ {
struct wl1271_acx_arp_filter *acx; struct wl1271_acx_arp_filter *acx;
int ret; int ret;
...@@ -1142,7 +1154,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) ...@@ -1142,7 +1154,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->version = ACX_IPV4_VERSION; acx->version = ACX_IPV4_VERSION;
acx->enable = enable; acx->enable = enable;
...@@ -1189,7 +1201,8 @@ int wl1271_acx_pm_config(struct wl1271 *wl) ...@@ -1189,7 +1201,8 @@ int wl1271_acx_pm_config(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool enable)
{ {
struct wl1271_acx_keep_alive_mode *acx = NULL; struct wl1271_acx_keep_alive_mode *acx = NULL;
int ret = 0; int ret = 0;
...@@ -1202,7 +1215,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) ...@@ -1202,7 +1215,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->enabled = enable; acx->enabled = enable;
ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx));
...@@ -1216,7 +1229,8 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) ...@@ -1216,7 +1229,8 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
return ret; return ret;
} }
int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 index, u8 tpl_valid)
{ {
struct wl1271_acx_keep_alive_config *acx = NULL; struct wl1271_acx_keep_alive_config *acx = NULL;
int ret = 0; int ret = 0;
...@@ -1229,7 +1243,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) ...@@ -1229,7 +1243,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval);
acx->index = index; acx->index = index;
acx->tpl_validation = tpl_valid; acx->tpl_validation = tpl_valid;
...@@ -1247,8 +1261,8 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) ...@@ -1247,8 +1261,8 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
return ret; return ret;
} }
int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif,
s16 thold, u8 hyst) bool enable, s16 thold, u8 hyst)
{ {
struct wl1271_acx_rssi_snr_trigger *acx = NULL; struct wl1271_acx_rssi_snr_trigger *acx = NULL;
int ret = 0; int ret = 0;
...@@ -1261,9 +1275,9 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, ...@@ -1261,9 +1275,9 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
goto out; goto out;
} }
wl->last_rssi_event = -1; wlvif->last_rssi_event = -1;
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing);
acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON;
acx->type = WL1271_ACX_TRIG_TYPE_EDGE; acx->type = WL1271_ACX_TRIG_TYPE_EDGE;
...@@ -1288,7 +1302,8 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, ...@@ -1288,7 +1302,8 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
return ret; return ret;
} }
int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
{ {
struct wl1271_acx_rssi_snr_avg_weights *acx = NULL; struct wl1271_acx_rssi_snr_avg_weights *acx = NULL;
struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger; struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger;
...@@ -1302,7 +1317,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) ...@@ -1302,7 +1317,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->rssi_beacon = c->avg_weight_rssi_beacon; acx->rssi_beacon = c->avg_weight_rssi_beacon;
acx->rssi_data = c->avg_weight_rssi_data; acx->rssi_data = c->avg_weight_rssi_data;
acx->snr_beacon = c->avg_weight_snr_beacon; acx->snr_beacon = c->avg_weight_snr_beacon;
...@@ -1367,6 +1382,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, ...@@ -1367,6 +1382,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
} }
int wl1271_acx_set_ht_information(struct wl1271 *wl, int wl1271_acx_set_ht_information(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
u16 ht_operation_mode) u16 ht_operation_mode)
{ {
struct wl1271_acx_ht_information *acx; struct wl1271_acx_ht_information *acx;
...@@ -1380,7 +1396,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, ...@@ -1380,7 +1396,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
goto out; goto out;
} }
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->ht_protection = acx->ht_protection =
(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
acx->rifs_mode = 0; acx->rifs_mode = 0;
...@@ -1402,7 +1418,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, ...@@ -1402,7 +1418,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
} }
/* Configure BA session initiator/receiver parameters setting in the FW. */ /* Configure BA session initiator/receiver parameters setting in the FW. */
int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
{ {
struct wl1271_acx_ba_initiator_policy *acx; struct wl1271_acx_ba_initiator_policy *acx;
int ret; int ret;
...@@ -1416,7 +1433,7 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) ...@@ -1416,7 +1433,7 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl)
} }
/* set for the current role */ /* set for the current role */
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap; acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap;
acx->win_size = wl->conf.ht.tx_ba_win_size; acx->win_size = wl->conf.ht.tx_ba_win_size;
acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
...@@ -1494,7 +1511,8 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) ...@@ -1494,7 +1511,8 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
return ret; return ret;
} }
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool enable)
{ {
struct wl1271_acx_ps_rx_streaming *rx_streaming; struct wl1271_acx_ps_rx_streaming *rx_streaming;
u32 conf_queues, enable_queues; u32 conf_queues, enable_queues;
...@@ -1523,7 +1541,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) ...@@ -1523,7 +1541,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
if (!(conf_queues & BIT(i))) if (!(conf_queues & BIT(i)))
continue; continue;
rx_streaming->role_id = wl->role_id; rx_streaming->role_id = wlvif->role_id;
rx_streaming->tid = i; rx_streaming->tid = i;
rx_streaming->enable = enable_queues & BIT(i); rx_streaming->enable = enable_queues & BIT(i);
rx_streaming->period = wl->conf.rx_streaming.interval; rx_streaming->period = wl->conf.rx_streaming.interval;
...@@ -1542,7 +1560,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) ...@@ -1542,7 +1560,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
return ret; return ret;
} }
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
struct wl1271_acx_ap_max_tx_retry *acx = NULL; struct wl1271_acx_ap_max_tx_retry *acx = NULL;
int ret; int ret;
...@@ -1553,7 +1571,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) ...@@ -1553,7 +1571,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
if (!acx) if (!acx)
return -ENOMEM; return -ENOMEM;
acx->role_id = wl->role_id; acx->role_id = wlvif->role_id;
acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);
ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
...@@ -1567,7 +1585,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) ...@@ -1567,7 +1585,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_config_ps(struct wl1271 *wl) int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
struct wl1271_acx_config_ps *config_ps; struct wl1271_acx_config_ps *config_ps;
int ret; int ret;
...@@ -1582,7 +1600,7 @@ int wl1271_acx_config_ps(struct wl1271 *wl) ...@@ -1582,7 +1600,7 @@ int wl1271_acx_config_ps(struct wl1271 *wl)
config_ps->exit_retries = wl->conf.conn.psm_exit_retries; config_ps->exit_retries = wl->conf.conn.psm_exit_retries;
config_ps->enter_retries = wl->conf.conn.psm_entry_retries; config_ps->enter_retries = wl->conf.conn.psm_entry_retries;
config_ps->null_data_rate = cpu_to_le32(wl->basic_rate); config_ps->null_data_rate = cpu_to_le32(wlvif->basic_rate);
ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps, ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps,
sizeof(*config_ps)); sizeof(*config_ps));
......
...@@ -654,11 +654,6 @@ struct acx_rate_class { ...@@ -654,11 +654,6 @@ struct acx_rate_class {
u8 reserved; u8 reserved;
}; };
#define ACX_TX_BASIC_RATE 0
#define ACX_TX_AP_FULL_RATE 1
#define ACX_TX_BASIC_RATE_P2P 2
#define ACX_TX_AP_MODE_MGMT_RATE 4
#define ACX_TX_AP_MODE_BCST_RATE 5
struct acx_rate_policy { struct acx_rate_policy {
struct acx_header header; struct acx_header header;
...@@ -1234,39 +1229,49 @@ enum { ...@@ -1234,39 +1229,49 @@ enum {
}; };
int wl1271_acx_wake_up_conditions(struct wl1271 *wl); int wl1271_acx_wake_up_conditions(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
int wl1271_acx_tx_power(struct wl1271 *wl, int power); int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_acx_feature_cfg(struct wl1271 *wl); int power);
int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_acx_mem_map(struct wl1271 *wl, int wl1271_acx_mem_map(struct wl1271 *wl,
struct acx_header *mem_map, size_t len); struct acx_header *mem_map, size_t len);
int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
int wl1271_acx_pd_threshold(struct wl1271 *wl); int wl1271_acx_pd_threshold(struct wl1271 *wl);
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, enum acx_slot_type slot_time);
void *mc_list, u32 mc_list_len); int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_acx_service_period_timeout(struct wl1271 *wl); bool enable, void *mc_list, u32 mc_list_len);
int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold); int wl1271_acx_service_period_timeout(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl1271_acx_rts_threshold(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u32 rts_threshold);
int wl1271_acx_dco_itrim_params(struct wl1271 *wl); int wl1271_acx_dco_itrim_params(struct wl1271 *wl);
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_acx_beacon_filter_table(struct wl1271 *wl); bool enable_filter);
int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); int wl1271_acx_beacon_filter_table(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl1271_acx_conn_monit_params(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool enable);
int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable);
int wl12xx_acx_sg_cfg(struct wl1271 *wl); int wl12xx_acx_sg_cfg(struct wl1271 *wl);
int wl1271_acx_cca_threshold(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl);
int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_acx_aid(struct wl1271 *wl, u16 aid); int wl1271_acx_aid(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid);
int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask); int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask);
int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_acx_cts_protect(struct wl1271 *wl, enum acx_preamble_type preamble);
int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif,
enum acx_ctsprotect_type ctsprotect); enum acx_ctsprotect_type ctsprotect);
int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
int wl1271_acx_sta_rate_policies(struct wl1271 *wl); int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
u8 idx); u8 idx);
int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 aifsn, u16 txop); u8 ac, u8 cw_min, u16 cw_max, u8 aifsn, u16 txop);
int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, int wl1271_acx_tid_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 queue_id, u8 channel_type,
u8 tsid, u8 ps_scheme, u8 ack_policy, u8 tsid, u8 ps_scheme, u8 ack_policy,
u32 apsd_conf0, u32 apsd_conf1); u32 apsd_conf0, u32 apsd_conf1);
int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
...@@ -1276,26 +1281,34 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl); ...@@ -1276,26 +1281,34 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
int wl1271_acx_smart_reflex(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl);
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address); bool enable);
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 enable, __be32 address);
int wl1271_acx_pm_config(struct wl1271 *wl); int wl1271_acx_pm_config(struct wl1271 *wl);
int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *vif,
int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); bool enable);
int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif,
s16 thold, u8 hyst); u8 index, u8 tpl_valid);
int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool enable, s16 thold, u8 hyst);
int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_sta_ht_cap *ht_cap,
bool allow_ht_operation, u8 hlid); bool allow_ht_operation, u8 hlid);
int wl1271_acx_set_ht_information(struct wl1271 *wl, int wl1271_acx_set_ht_information(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
u16 ht_operation_mode); u16 ht_operation_mode);
int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl); int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
u16 ssn, bool enable, u8 peer_hlid); u16 ssn, bool enable, u8 peer_hlid);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); bool enable);
int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
int wl1271_acx_fm_coex(struct wl1271 *wl); int wl1271_acx_fm_coex(struct wl1271 *wl);
int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/wl12xx.h> #include <linux/wl12xx.h>
#include <linux/export.h> #include <linux/export.h>
#include "debug.h"
#include "acx.h" #include "acx.h"
#include "reg.h" #include "reg.h"
#include "boot.h" #include "boot.h"
...@@ -347,6 +348,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) ...@@ -347,6 +348,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr += 3; nvs_ptr += 3;
for (i = 0; i < burst_len; i++) { for (i = 0; i < burst_len; i++) {
if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
goto out_badnvs;
val = (nvs_ptr[0] | (nvs_ptr[1] << 8) val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
| (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
...@@ -358,6 +362,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) ...@@ -358,6 +362,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr += 4; nvs_ptr += 4;
dest_addr += 4; dest_addr += 4;
} }
if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
goto out_badnvs;
} }
/* /*
...@@ -369,6 +376,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) ...@@ -369,6 +376,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/ */
nvs_ptr = (u8 *)wl->nvs + nvs_ptr = (u8 *)wl->nvs +
ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
goto out_badnvs;
nvs_len -= nvs_ptr - (u8 *)wl->nvs; nvs_len -= nvs_ptr - (u8 *)wl->nvs;
/* Now we must set the partition correctly */ /* Now we must set the partition correctly */
...@@ -384,6 +395,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) ...@@ -384,6 +395,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
kfree(nvs_aligned); kfree(nvs_aligned);
return 0; return 0;
out_badnvs:
wl1271_error("nvs data is malformed");
return -EILSEQ;
} }
static void wl1271_boot_enable_interrupts(struct wl1271 *wl) static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
......
此差异已折叠。
...@@ -36,45 +36,54 @@ int wl128x_cmd_general_parms(struct wl1271 *wl); ...@@ -36,45 +36,54 @@ int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id); int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type,
u8 *role_id);
int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
int wl12xx_cmd_role_start_dev(struct wl1271 *wl); int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_start_sta(struct wl1271 *wl); int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_stop_sta(struct wl1271 *wl); int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_start_ap(struct wl1271 *wl); int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_stop_ap(struct wl1271 *wl); int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_cmd_role_start_ibss(struct wl1271 *wl); int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 ps_mode);
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
size_t len); size_t len);
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
void *buf, size_t buf_len, int index, u32 rates); void *buf, size_t buf_len, int index, u32 rates);
int wl1271_cmd_build_null_data(struct wl1271 *wl); int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_cmd_build_probe_req(struct wl1271 *wl, u16 aid);
int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
const u8 *ssid, size_t ssid_len, const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band); const u8 *ie, size_t ie_len, u8 band);
struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct sk_buff *skb); struct sk_buff *skb);
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl1271_build_qos_null_data(struct wl1271 *wl); __be32 ip_addr);
int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif);
int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid);
int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr, u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16); u32 tx_seq_32, u16 tx_seq_16);
int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
u16 tx_seq_16); u16 tx_seq_16);
int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid); int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid);
int wl12xx_roc(struct wl1271 *wl, u8 role_id); int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id);
int wl12xx_croc(struct wl1271 *wl, u8 role_id); int wl12xx_croc(struct wl1271 *wl, u8 role_id);
int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct ieee80211_sta *sta, u8 hlid);
int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
int wl12xx_cmd_config_fwlog(struct wl1271 *wl); int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
int wl12xx_cmd_start_fwlog(struct wl1271 *wl); int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
...@@ -82,6 +91,9 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); ...@@ -82,6 +91,9 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
int wl12xx_cmd_channel_switch(struct wl1271 *wl, int wl12xx_cmd_channel_switch(struct wl1271 *wl,
struct ieee80211_channel_switch *ch_switch); struct ieee80211_channel_switch *ch_switch);
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 *hlid);
void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid);
enum wl1271_commands { enum wl1271_commands {
CMD_INTERROGATE = 1, /*use this to read information elements*/ CMD_INTERROGATE = 1, /*use this to read information elements*/
......
...@@ -440,6 +440,10 @@ struct conf_rx_settings { ...@@ -440,6 +440,10 @@ struct conf_rx_settings {
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
CONF_HW_BIT_RATE_54MBPS) CONF_HW_BIT_RATE_54MBPS)
#define CONF_TX_CCK_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
CONF_HW_BIT_RATE_11MBPS)
#define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \ #define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \
CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \ CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \
CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \
......
/*
* This file is part of wl12xx
*
* Copyright (C) 2011 Texas Instruments. All rights reserved.
* Copyright (C) 2008-2009 Nokia Corporation
*
* Contact: Luciano Coelho <coelho@ti.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 St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __DEBUG_H__
#define __DEBUG_H__
#include <linux/bitops.h>
#include <linux/printk.h>
#define DRIVER_NAME "wl12xx"
#define DRIVER_PREFIX DRIVER_NAME ": "
enum {
DEBUG_NONE = 0,
DEBUG_IRQ = BIT(0),
DEBUG_SPI = BIT(1),
DEBUG_BOOT = BIT(2),
DEBUG_MAILBOX = BIT(3),
DEBUG_TESTMODE = BIT(4),
DEBUG_EVENT = BIT(5),
DEBUG_TX = BIT(6),
DEBUG_RX = BIT(7),
DEBUG_SCAN = BIT(8),
DEBUG_CRYPT = BIT(9),
DEBUG_PSM = BIT(10),
DEBUG_MAC80211 = BIT(11),
DEBUG_CMD = BIT(12),
DEBUG_ACX = BIT(13),
DEBUG_SDIO = BIT(14),
DEBUG_FILTERS = BIT(15),
DEBUG_ADHOC = BIT(16),
DEBUG_AP = BIT(17),
DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP),
DEBUG_ALL = ~0,
};
extern u32 wl12xx_debug_level;
#define DEBUG_DUMP_LIMIT 1024
#define wl1271_error(fmt, arg...) \
pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
#define wl1271_warning(fmt, arg...) \
pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
#define wl1271_notice(fmt, arg...) \
pr_info(DRIVER_PREFIX fmt "\n", ##arg)
#define wl1271_info(fmt, arg...) \
pr_info(DRIVER_PREFIX fmt "\n", ##arg)
#define wl1271_debug(level, fmt, arg...) \
do { \
if (level & wl12xx_debug_level) \
pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \
} while (0)
/* TODO: use pr_debug_hex_dump when it becomes available */
#define wl1271_dump(level, prefix, buf, len) \
do { \
if (level & wl12xx_debug_level) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
DUMP_PREFIX_OFFSET, 16, 1, \
buf, \
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
0); \
} while (0)
#define wl1271_dump_ascii(level, prefix, buf, len) \
do { \
if (level & wl12xx_debug_level) \
print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
DUMP_PREFIX_OFFSET, 16, 1, \
buf, \
min_t(size_t, len, DEBUG_DUMP_LIMIT), \
true); \
} while (0)
#endif /* __DEBUG_H__ */
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "wl12xx.h" #include "wl12xx.h"
#include "debug.h"
#include "acx.h" #include "acx.h"
#include "ps.h" #include "ps.h"
#include "io.h" #include "io.h"
...@@ -346,29 +347,14 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, ...@@ -346,29 +347,14 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(tx_results_count); DRIVER_STATE_PRINT_INT(tx_results_count);
DRIVER_STATE_PRINT_LHEX(flags); DRIVER_STATE_PRINT_LHEX(flags);
DRIVER_STATE_PRINT_INT(tx_blocks_freed); DRIVER_STATE_PRINT_INT(tx_blocks_freed);
DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(rx_counter);
DRIVER_STATE_PRINT_INT(session_counter);
DRIVER_STATE_PRINT_INT(state); DRIVER_STATE_PRINT_INT(state);
DRIVER_STATE_PRINT_INT(bss_type);
DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(channel);
DRIVER_STATE_PRINT_HEX(rate_set);
DRIVER_STATE_PRINT_HEX(basic_rate_set);
DRIVER_STATE_PRINT_HEX(basic_rate);
DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(band);
DRIVER_STATE_PRINT_INT(beacon_int);
DRIVER_STATE_PRINT_INT(psm_entry_retry);
DRIVER_STATE_PRINT_INT(ps_poll_failures);
DRIVER_STATE_PRINT_INT(power_level); DRIVER_STATE_PRINT_INT(power_level);
DRIVER_STATE_PRINT_INT(rssi_thold);
DRIVER_STATE_PRINT_INT(last_rssi_event);
DRIVER_STATE_PRINT_INT(sg_enabled); DRIVER_STATE_PRINT_INT(sg_enabled);
DRIVER_STATE_PRINT_INT(enable_11a); DRIVER_STATE_PRINT_INT(enable_11a);
DRIVER_STATE_PRINT_INT(noise); DRIVER_STATE_PRINT_INT(noise);
DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]);
DRIVER_STATE_PRINT_INT(last_tx_hlid);
DRIVER_STATE_PRINT_INT(ba_support);
DRIVER_STATE_PRINT_HEX(ba_rx_bitmap);
DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
DRIVER_STATE_PRINT_LHEX(ap_ps_map); DRIVER_STATE_PRINT_LHEX(ap_ps_map);
DRIVER_STATE_PRINT_HEX(quirks); DRIVER_STATE_PRINT_HEX(quirks);
...@@ -399,6 +385,115 @@ static const struct file_operations driver_state_ops = { ...@@ -399,6 +385,115 @@ static const struct file_operations driver_state_ops = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
struct wl12xx_vif *wlvif;
int ret, res = 0;
const int buf_size = 4096;
char *buf;
char tmp_buf[64];
buf = kzalloc(buf_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
mutex_lock(&wl->mutex);
#define VIF_STATE_PRINT(x, fmt) \
(res += scnprintf(buf + res, buf_size - res, \
#x " = " fmt "\n", wlvif->x))
#define VIF_STATE_PRINT_LONG(x) VIF_STATE_PRINT(x, "%ld")
#define VIF_STATE_PRINT_INT(x) VIF_STATE_PRINT(x, "%d")
#define VIF_STATE_PRINT_STR(x) VIF_STATE_PRINT(x, "%s")
#define VIF_STATE_PRINT_LHEX(x) VIF_STATE_PRINT(x, "0x%lx")
#define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx")
#define VIF_STATE_PRINT_HEX(x) VIF_STATE_PRINT(x, "0x%x")
#define VIF_STATE_PRINT_NSTR(x, len) \
do { \
memset(tmp_buf, 0, sizeof(tmp_buf)); \
memcpy(tmp_buf, wlvif->x, \
min_t(u8, len, sizeof(tmp_buf) - 1)); \
res += scnprintf(buf + res, buf_size - res, \
#x " = %s\n", tmp_buf); \
} while (0)
wl12xx_for_each_wlvif(wl, wlvif) {
VIF_STATE_PRINT_INT(role_id);
VIF_STATE_PRINT_INT(bss_type);
VIF_STATE_PRINT_LHEX(flags);
VIF_STATE_PRINT_INT(p2p);
VIF_STATE_PRINT_INT(dev_role_id);
VIF_STATE_PRINT_INT(dev_hlid);
if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
wlvif->bss_type == BSS_TYPE_IBSS) {
VIF_STATE_PRINT_INT(sta.hlid);
VIF_STATE_PRINT_INT(sta.ba_rx_bitmap);
VIF_STATE_PRINT_INT(sta.basic_rate_idx);
VIF_STATE_PRINT_INT(sta.ap_rate_idx);
VIF_STATE_PRINT_INT(sta.p2p_rate_idx);
} else {
VIF_STATE_PRINT_INT(ap.global_hlid);
VIF_STATE_PRINT_INT(ap.bcast_hlid);
VIF_STATE_PRINT_LHEX(ap.sta_hlid_map[0]);
VIF_STATE_PRINT_INT(ap.mgmt_rate_idx);
VIF_STATE_PRINT_INT(ap.bcast_rate_idx);
VIF_STATE_PRINT_INT(ap.ucast_rate_idx[0]);
VIF_STATE_PRINT_INT(ap.ucast_rate_idx[1]);
VIF_STATE_PRINT_INT(ap.ucast_rate_idx[2]);
VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]);
}
VIF_STATE_PRINT_INT(last_tx_hlid);
VIF_STATE_PRINT_LHEX(links_map[0]);
VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len);
VIF_STATE_PRINT_INT(band);
VIF_STATE_PRINT_INT(channel);
VIF_STATE_PRINT_HEX(bitrate_masks[0]);
VIF_STATE_PRINT_HEX(bitrate_masks[1]);
VIF_STATE_PRINT_HEX(basic_rate_set);
VIF_STATE_PRINT_HEX(basic_rate);
VIF_STATE_PRINT_HEX(rate_set);
VIF_STATE_PRINT_INT(beacon_int);
VIF_STATE_PRINT_INT(default_key);
VIF_STATE_PRINT_INT(aid);
VIF_STATE_PRINT_INT(session_counter);
VIF_STATE_PRINT_INT(ps_poll_failures);
VIF_STATE_PRINT_INT(psm_entry_retry);
VIF_STATE_PRINT_INT(power_level);
VIF_STATE_PRINT_INT(rssi_thold);
VIF_STATE_PRINT_INT(last_rssi_event);
VIF_STATE_PRINT_INT(ba_support);
VIF_STATE_PRINT_INT(ba_allowed);
VIF_STATE_PRINT_LLHEX(tx_security_seq);
VIF_STATE_PRINT_INT(tx_security_last_seq_lsb);
}
#undef VIF_STATE_PRINT_INT
#undef VIF_STATE_PRINT_LONG
#undef VIF_STATE_PRINT_HEX
#undef VIF_STATE_PRINT_LHEX
#undef VIF_STATE_PRINT_LLHEX
#undef VIF_STATE_PRINT_STR
#undef VIF_STATE_PRINT_NSTR
#undef VIF_STATE_PRINT
mutex_unlock(&wl->mutex);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
kfree(buf);
return ret;
}
static const struct file_operations vifs_state_ops = {
.read = vifs_state_read,
.open = wl1271_open_file_generic,
.llseek = default_llseek,
};
static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, static ssize_t dtim_interval_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
...@@ -520,6 +615,7 @@ static ssize_t rx_streaming_interval_write(struct file *file, ...@@ -520,6 +615,7 @@ static ssize_t rx_streaming_interval_write(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct wl1271 *wl = file->private_data; struct wl1271 *wl = file->private_data;
struct wl12xx_vif *wlvif;
unsigned long value; unsigned long value;
int ret; int ret;
...@@ -543,7 +639,9 @@ static ssize_t rx_streaming_interval_write(struct file *file, ...@@ -543,7 +639,9 @@ static ssize_t rx_streaming_interval_write(struct file *file,
if (ret < 0) if (ret < 0)
goto out; goto out;
wl1271_recalc_rx_streaming(wl); wl12xx_for_each_wlvif_sta(wl, wlvif) {
wl1271_recalc_rx_streaming(wl, wlvif);
}
wl1271_ps_elp_sleep(wl); wl1271_ps_elp_sleep(wl);
out: out:
...@@ -572,6 +670,7 @@ static ssize_t rx_streaming_always_write(struct file *file, ...@@ -572,6 +670,7 @@ static ssize_t rx_streaming_always_write(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct wl1271 *wl = file->private_data; struct wl1271 *wl = file->private_data;
struct wl12xx_vif *wlvif;
unsigned long value; unsigned long value;
int ret; int ret;
...@@ -595,7 +694,9 @@ static ssize_t rx_streaming_always_write(struct file *file, ...@@ -595,7 +694,9 @@ static ssize_t rx_streaming_always_write(struct file *file,
if (ret < 0) if (ret < 0)
goto out; goto out;
wl1271_recalc_rx_streaming(wl); wl12xx_for_each_wlvif_sta(wl, wlvif) {
wl1271_recalc_rx_streaming(wl, wlvif);
}
wl1271_ps_elp_sleep(wl); wl1271_ps_elp_sleep(wl);
out: out:
...@@ -624,6 +725,7 @@ static ssize_t beacon_filtering_write(struct file *file, ...@@ -624,6 +725,7 @@ static ssize_t beacon_filtering_write(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct wl1271 *wl = file->private_data; struct wl1271 *wl = file->private_data;
struct wl12xx_vif *wlvif;
char buf[10]; char buf[10];
size_t len; size_t len;
unsigned long value; unsigned long value;
...@@ -646,7 +748,9 @@ static ssize_t beacon_filtering_write(struct file *file, ...@@ -646,7 +748,9 @@ static ssize_t beacon_filtering_write(struct file *file,
if (ret < 0) if (ret < 0)
goto out; goto out;
ret = wl1271_acx_beacon_filter_opt(wl, !!value); wl12xx_for_each_wlvif(wl, wlvif) {
ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value);
}
wl1271_ps_elp_sleep(wl); wl1271_ps_elp_sleep(wl);
out: out:
...@@ -770,6 +874,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, ...@@ -770,6 +874,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(gpio_power, rootdir); DEBUGFS_ADD(gpio_power, rootdir);
DEBUGFS_ADD(start_recovery, rootdir); DEBUGFS_ADD(start_recovery, rootdir);
DEBUGFS_ADD(driver_state, rootdir); DEBUGFS_ADD(driver_state, rootdir);
DEBUGFS_ADD(vifs_state, rootdir);
DEBUGFS_ADD(dtim_interval, rootdir); DEBUGFS_ADD(dtim_interval, rootdir);
DEBUGFS_ADD(beacon_interval, rootdir); DEBUGFS_ADD(beacon_interval, rootdir);
DEBUGFS_ADD(beacon_filtering, rootdir); DEBUGFS_ADD(beacon_filtering, rootdir);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
#include "wl12xx.h" #include "wl12xx.h"
#include "debug.h"
#include "reg.h" #include "reg.h"
#include "io.h" #include "io.h"
#include "event.h" #include "event.h"
...@@ -31,12 +32,16 @@ ...@@ -31,12 +32,16 @@
void wl1271_pspoll_work(struct work_struct *work) void wl1271_pspoll_work(struct work_struct *work)
{ {
struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif;
struct delayed_work *dwork; struct delayed_work *dwork;
struct wl1271 *wl; struct wl1271 *wl;
int ret; int ret;
dwork = container_of(work, struct delayed_work, work); dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, pspoll_work); wlvif = container_of(dwork, struct wl12xx_vif, pspoll_work);
vif = container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
wl = wlvif->wl;
wl1271_debug(DEBUG_EVENT, "pspoll work"); wl1271_debug(DEBUG_EVENT, "pspoll work");
...@@ -45,10 +50,10 @@ void wl1271_pspoll_work(struct work_struct *work) ...@@ -45,10 +50,10 @@ void wl1271_pspoll_work(struct work_struct *work)
if (unlikely(wl->state == WL1271_STATE_OFF)) if (unlikely(wl->state == WL1271_STATE_OFF))
goto out; goto out;
if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags))
goto out; goto out;
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
goto out; goto out;
/* /*
...@@ -60,31 +65,33 @@ void wl1271_pspoll_work(struct work_struct *work) ...@@ -60,31 +65,33 @@ void wl1271_pspoll_work(struct work_struct *work)
if (ret < 0) if (ret < 0)
goto out; goto out;
wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE,
wlvif->basic_rate, true);
wl1271_ps_elp_sleep(wl); wl1271_ps_elp_sleep(wl);
out: out:
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
}; };
static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl,
struct wl12xx_vif *wlvif)
{ {
int delay = wl->conf.conn.ps_poll_recovery_period; int delay = wl->conf.conn.ps_poll_recovery_period;
int ret; int ret;
wl->ps_poll_failures++; wlvif->ps_poll_failures++;
if (wl->ps_poll_failures == 1) if (wlvif->ps_poll_failures == 1)
wl1271_info("AP with dysfunctional ps-poll, " wl1271_info("AP with dysfunctional ps-poll, "
"trying to work around it."); "trying to work around it.");
/* force active mode receive data from the AP */ /* force active mode receive data from the AP */
if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE,
wl->basic_rate, true); wlvif->basic_rate, true);
if (ret < 0) if (ret < 0)
return; return;
set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags);
ieee80211_queue_delayed_work(wl->hw, &wl->pspoll_work, ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work,
msecs_to_jiffies(delay)); msecs_to_jiffies(delay));
} }
...@@ -97,6 +104,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) ...@@ -97,6 +104,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
} }
static int wl1271_event_ps_report(struct wl1271 *wl, static int wl1271_event_ps_report(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct event_mailbox *mbox, struct event_mailbox *mbox,
bool *beacon_loss) bool *beacon_loss)
{ {
...@@ -109,41 +117,37 @@ static int wl1271_event_ps_report(struct wl1271 *wl, ...@@ -109,41 +117,37 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
case EVENT_ENTER_POWER_SAVE_FAIL: case EVENT_ENTER_POWER_SAVE_FAIL:
wl1271_debug(DEBUG_PSM, "PSM entry failed"); wl1271_debug(DEBUG_PSM, "PSM entry failed");
if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
/* remain in active mode */ /* remain in active mode */
wl->psm_entry_retry = 0; wlvif->psm_entry_retry = 0;
break; break;
} }
if (wl->psm_entry_retry < total_retries) { if (wlvif->psm_entry_retry < total_retries) {
wl->psm_entry_retry++; wlvif->psm_entry_retry++;
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, ret = wl1271_ps_set_mode(wl, wlvif,
wl->basic_rate, true); STATION_POWER_SAVE_MODE,
wlvif->basic_rate, true);
} else { } else {
wl1271_info("No ack to nullfunc from AP."); wl1271_info("No ack to nullfunc from AP.");
wl->psm_entry_retry = 0; wlvif->psm_entry_retry = 0;
*beacon_loss = true; *beacon_loss = true;
} }
break; break;
case EVENT_ENTER_POWER_SAVE_SUCCESS: case EVENT_ENTER_POWER_SAVE_SUCCESS:
wl->psm_entry_retry = 0; wlvif->psm_entry_retry = 0;
/* enable beacon filtering */
ret = wl1271_acx_beacon_filter_opt(wl, true);
if (ret < 0)
break;
/* /*
* BET has only a minor effect in 5GHz and masks * BET has only a minor effect in 5GHz and masks
* channel switch IEs, so we only enable BET on 2.4GHz * channel switch IEs, so we only enable BET on 2.4GHz
*/ */
if (wl->band == IEEE80211_BAND_2GHZ) if (wlvif->band == IEEE80211_BAND_2GHZ)
/* enable beacon early termination */ /* enable beacon early termination */
ret = wl1271_acx_bet_enable(wl, true); ret = wl1271_acx_bet_enable(wl, wlvif, true);
if (wl->ps_compl) { if (wlvif->ps_compl) {
complete(wl->ps_compl); complete(wlvif->ps_compl);
wl->ps_compl = NULL; wlvif->ps_compl = NULL;
} }
break; break;
default: default:
...@@ -154,39 +158,44 @@ static int wl1271_event_ps_report(struct wl1271 *wl, ...@@ -154,39 +158,44 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
} }
static void wl1271_event_rssi_trigger(struct wl1271 *wl, static void wl1271_event_rssi_trigger(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct event_mailbox *mbox) struct event_mailbox *mbox)
{ {
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
enum nl80211_cqm_rssi_threshold_event event; enum nl80211_cqm_rssi_threshold_event event;
s8 metric = mbox->rssi_snr_trigger_metric[0]; s8 metric = mbox->rssi_snr_trigger_metric[0];
wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric);
if (metric <= wl->rssi_thold) if (metric <= wlvif->rssi_thold)
event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
else else
event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
if (event != wl->last_rssi_event) if (event != wlvif->last_rssi_event)
ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL); ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL);
wl->last_rssi_event = event; wlvif->last_rssi_event = event;
} }
static void wl1271_stop_ba_event(struct wl1271 *wl) static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
if (wl->bss_type != BSS_TYPE_AP_BSS) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
if (!wl->ba_rx_bitmap)
if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
if (!wlvif->sta.ba_rx_bitmap)
return; return;
ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, ieee80211_stop_rx_ba_session(vif, wlvif->sta.ba_rx_bitmap,
wl->bssid); vif->bss_conf.bssid);
} else { } else {
int i; u8 hlid;
struct wl1271_link *lnk; struct wl1271_link *lnk;
for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) { for_each_set_bit(hlid, wlvif->ap.sta_hlid_map,
lnk = &wl->links[i]; WL12XX_MAX_LINKS) {
if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap) lnk = &wl->links[hlid];
if (!lnk->ba_bitmap)
continue; continue;
ieee80211_stop_rx_ba_session(wl->vif, ieee80211_stop_rx_ba_session(vif,
lnk->ba_bitmap, lnk->ba_bitmap,
lnk->addr); lnk->addr);
} }
...@@ -196,14 +205,23 @@ static void wl1271_stop_ba_event(struct wl1271 *wl) ...@@ -196,14 +205,23 @@ static void wl1271_stop_ba_event(struct wl1271 *wl)
static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
u8 enable) u8 enable)
{ {
struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif;
if (enable) { if (enable) {
/* disable dynamic PS when requested by the firmware */ /* disable dynamic PS when requested by the firmware */
ieee80211_disable_dyn_ps(wl->vif); wl12xx_for_each_wlvif_sta(wl, wlvif) {
vif = wl12xx_wlvif_to_vif(wlvif);
ieee80211_disable_dyn_ps(vif);
}
set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
} else { } else {
ieee80211_enable_dyn_ps(wl->vif);
clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
wl1271_recalc_rx_streaming(wl); wl12xx_for_each_wlvif_sta(wl, wlvif) {
vif = wl12xx_wlvif_to_vif(wlvif);
ieee80211_enable_dyn_ps(vif);
wl1271_recalc_rx_streaming(wl, wlvif);
}
} }
} }
...@@ -217,10 +235,11 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox) ...@@ -217,10 +235,11 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
{ {
struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif;
int ret; int ret;
u32 vector; u32 vector;
bool beacon_loss = false; bool beacon_loss = false;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
bool disconnect_sta = false; bool disconnect_sta = false;
unsigned long sta_bitmap = 0; unsigned long sta_bitmap = 0;
...@@ -234,7 +253,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) ...@@ -234,7 +253,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_debug(DEBUG_EVENT, "status: 0x%x", wl1271_debug(DEBUG_EVENT, "status: 0x%x",
mbox->scheduled_scan_status); mbox->scheduled_scan_status);
wl1271_scan_stm(wl); wl1271_scan_stm(wl, wl->scan_vif);
} }
if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
...@@ -253,8 +272,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) ...@@ -253,8 +272,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
} }
} }
if (vector & SOFT_GEMINI_SENSE_EVENT_ID && if (vector & SOFT_GEMINI_SENSE_EVENT_ID)
wl->bss_type == BSS_TYPE_STA_BSS)
wl12xx_event_soft_gemini_sense(wl, wl12xx_event_soft_gemini_sense(wl,
mbox->soft_gemini_sense_info); mbox->soft_gemini_sense_info);
...@@ -267,40 +285,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) ...@@ -267,40 +285,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
* BSS_LOSE_EVENT, beacon loss has to be reported to the stack. * BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
* *
*/ */
if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) { if (vector & BSS_LOSE_EVENT_ID) {
/* TODO: check for multi-role */
wl1271_info("Beacon loss detected."); wl1271_info("Beacon loss detected.");
/* indicate to the stack, that beacons have been lost */ /* indicate to the stack, that beacons have been lost */
beacon_loss = true; beacon_loss = true;
} }
if ((vector & PS_REPORT_EVENT_ID) && !is_ap) { if (vector & PS_REPORT_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); wl12xx_for_each_wlvif_sta(wl, wlvif) {
if (ret < 0) ret = wl1271_event_ps_report(wl, wlvif,
return ret; mbox, &beacon_loss);
if (ret < 0)
return ret;
}
} }
if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap) if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
wl1271_event_pspoll_delivery_fail(wl); wl12xx_for_each_wlvif_sta(wl, wlvif) {
wl1271_event_pspoll_delivery_fail(wl, wlvif);
}
if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
/* TODO: check actual multi-role support */
wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT");
if (wl->vif) wl12xx_for_each_wlvif_sta(wl, wlvif) {
wl1271_event_rssi_trigger(wl, mbox); wl1271_event_rssi_trigger(wl, wlvif, mbox);
}
} }
if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) { if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) {
u8 role_id = mbox->role_id;
wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
"ba_allowed = 0x%x", mbox->rx_ba_allowed); "ba_allowed = 0x%x, role_id=%d",
mbox->rx_ba_allowed, role_id);
wl->ba_allowed = !!mbox->rx_ba_allowed; wl12xx_for_each_wlvif(wl, wlvif) {
if (role_id != 0xff && role_id != wlvif->role_id)
continue;
if (wl->vif && !wl->ba_allowed) wlvif->ba_allowed = !!mbox->rx_ba_allowed;
wl1271_stop_ba_event(wl); if (!wlvif->ba_allowed)
wl1271_stop_ba_event(wl, wlvif);
}
} }
if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) { if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. " wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
"status = 0x%x", "status = 0x%x",
mbox->channel_switch_status); mbox->channel_switch_status);
...@@ -309,50 +341,65 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) ...@@ -309,50 +341,65 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
* 1) channel switch complete with status=0 * 1) channel switch complete with status=0
* 2) channel switch failed status=1 * 2) channel switch failed status=1
*/ */
if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) &&
(wl->vif)) /* TODO: configure only the relevant vif */
ieee80211_chswitch_done(wl->vif, wl12xx_for_each_wlvif_sta(wl, wlvif) {
mbox->channel_switch_status ? false : true); struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
bool success;
if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS,
&wl->flags))
continue;
success = mbox->channel_switch_status ? false : true;
ieee80211_chswitch_done(vif, success);
}
} }
if ((vector & DUMMY_PACKET_EVENT_ID)) { if ((vector & DUMMY_PACKET_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif) wl1271_tx_dummy_packet(wl);
wl1271_tx_dummy_packet(wl);
} }
/* /*
* "TX retries exceeded" has a different meaning according to mode. * "TX retries exceeded" has a different meaning according to mode.
* In AP mode the offending station is disconnected. * In AP mode the offending station is disconnected.
*/ */
if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) { if (vector & MAX_TX_RETRY_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
disconnect_sta = true; disconnect_sta = true;
} }
if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { if (vector & INACTIVE_STA_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
disconnect_sta = true; disconnect_sta = true;
} }
if (is_ap && disconnect_sta) { if (disconnect_sta) {
u32 num_packets = wl->conf.tx.max_tx_retries; u32 num_packets = wl->conf.tx.max_tx_retries;
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
const u8 *addr; const u8 *addr;
int h; int h;
for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) {
h < AP_MAX_LINKS; bool found = false;
h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { /* find the ap vif connected to this sta */
if (!wl1271_is_active_sta(wl, h)) wl12xx_for_each_wlvif_ap(wl, wlvif) {
if (!test_bit(h, wlvif->ap.sta_hlid_map))
continue;
found = true;
break;
}
if (!found)
continue; continue;
vif = wl12xx_wlvif_to_vif(wlvif);
addr = wl->links[h].addr; addr = wl->links[h].addr;
rcu_read_lock(); rcu_read_lock();
sta = ieee80211_find_sta(wl->vif, addr); sta = ieee80211_find_sta(vif, addr);
if (sta) { if (sta) {
wl1271_debug(DEBUG_EVENT, "remove sta %d", h); wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
ieee80211_report_low_ack(sta, num_packets); ieee80211_report_low_ack(sta, num_packets);
...@@ -361,8 +408,11 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) ...@@ -361,8 +408,11 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
} }
} }
if (wl->vif && beacon_loss) if (beacon_loss)
ieee80211_connection_loss(wl->vif); wl12xx_for_each_wlvif_sta(wl, wlvif) {
vif = wl12xx_wlvif_to_vif(wlvif);
ieee80211_connection_loss(vif);
}
return 0; return 0;
} }
......
...@@ -132,7 +132,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl); ...@@ -132,7 +132,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
int wl1271_event_handle(struct wl1271 *wl, u8 mbox); int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
void wl1271_pspoll_work(struct work_struct *work); void wl1271_pspoll_work(struct work_struct *work);
/* Functions from main.c */
bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
#endif #endif
此差异已折叠。
...@@ -27,13 +27,14 @@ ...@@ -27,13 +27,14 @@
#include "wl12xx.h" #include "wl12xx.h"
int wl1271_hw_init_power_auth(struct wl1271 *wl); int wl1271_hw_init_power_auth(struct wl1271 *wl);
int wl1271_sta_init_templates_config(struct wl1271 *wl); int wl1271_init_templates_config(struct wl1271 *wl);
int wl1271_init_phy_config(struct wl1271 *wl); int wl1271_init_phy_config(struct wl1271 *wl);
int wl1271_init_pta(struct wl1271 *wl); int wl1271_init_pta(struct wl1271 *wl);
int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_init_energy_detection(struct wl1271 *wl);
int wl1271_chip_specific_init(struct wl1271 *wl); int wl1271_chip_specific_init(struct wl1271 *wl);
int wl1271_hw_init(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl);
int wl1271_init_ap_rates(struct wl1271 *wl); int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif);
int wl1271_ap_init_templates(struct wl1271 *wl); int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif);
#endif #endif
...@@ -24,8 +24,10 @@ ...@@ -24,8 +24,10 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/interrupt.h>
#include "wl12xx.h" #include "wl12xx.h"
#include "debug.h"
#include "wl12xx_80211.h" #include "wl12xx_80211.h"
#include "io.h" #include "io.h"
#include "tx.h" #include "tx.h"
...@@ -46,7 +48,7 @@ ...@@ -46,7 +48,7 @@
bool wl1271_set_block_size(struct wl1271 *wl) bool wl1271_set_block_size(struct wl1271 *wl)
{ {
if (wl->if_ops->set_block_size) { if (wl->if_ops->set_block_size) {
wl->if_ops->set_block_size(wl, WL12XX_BUS_BLOCK_SIZE); wl->if_ops->set_block_size(wl->dev, WL12XX_BUS_BLOCK_SIZE);
return true; return true;
} }
...@@ -55,12 +57,12 @@ bool wl1271_set_block_size(struct wl1271 *wl) ...@@ -55,12 +57,12 @@ bool wl1271_set_block_size(struct wl1271 *wl)
void wl1271_disable_interrupts(struct wl1271 *wl) void wl1271_disable_interrupts(struct wl1271 *wl)
{ {
wl->if_ops->disable_irq(wl); disable_irq(wl->irq);
} }
void wl1271_enable_interrupts(struct wl1271 *wl) void wl1271_enable_interrupts(struct wl1271 *wl)
{ {
wl->if_ops->enable_irq(wl); enable_irq(wl->irq);
} }
/* Set the SPI partitions to access the chip addresses /* Set the SPI partitions to access the chip addresses
...@@ -128,13 +130,13 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition); ...@@ -128,13 +130,13 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition);
void wl1271_io_reset(struct wl1271 *wl) void wl1271_io_reset(struct wl1271 *wl)
{ {
if (wl->if_ops->reset) if (wl->if_ops->reset)
wl->if_ops->reset(wl); wl->if_ops->reset(wl->dev);
} }
void wl1271_io_init(struct wl1271 *wl) void wl1271_io_init(struct wl1271 *wl)
{ {
if (wl->if_ops->init) if (wl->if_ops->init)
wl->if_ops->init(wl); wl->if_ops->init(wl->dev);
} }
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
......
...@@ -51,23 +51,17 @@ void wl1271_enable_interrupts(struct wl1271 *wl); ...@@ -51,23 +51,17 @@ void wl1271_enable_interrupts(struct wl1271 *wl);
void wl1271_io_reset(struct wl1271 *wl); void wl1271_io_reset(struct wl1271 *wl);
void wl1271_io_init(struct wl1271 *wl); void wl1271_io_init(struct wl1271 *wl);
static inline struct device *wl1271_wl_to_dev(struct wl1271 *wl)
{
return wl->if_ops->dev(wl);
}
/* Raw target IO, address is not translated */ /* Raw target IO, address is not translated */
static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed) size_t len, bool fixed)
{ {
wl->if_ops->write(wl, addr, buf, len, fixed); wl->if_ops->write(wl->dev, addr, buf, len, fixed);
} }
static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed) size_t len, bool fixed)
{ {
wl->if_ops->read(wl, addr, buf, len, fixed); wl->if_ops->read(wl->dev, addr, buf, len, fixed);
} }
static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
...@@ -155,13 +149,13 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) ...@@ -155,13 +149,13 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
static inline void wl1271_power_off(struct wl1271 *wl) static inline void wl1271_power_off(struct wl1271 *wl)
{ {
wl->if_ops->power(wl, false); wl->if_ops->power(wl->dev, false);
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
} }
static inline int wl1271_power_on(struct wl1271 *wl) static inline int wl1271_power_on(struct wl1271 *wl)
{ {
int ret = wl->if_ops->power(wl, true); int ret = wl->if_ops->power(wl->dev, true);
if (ret == 0) if (ret == 0)
set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
...@@ -176,15 +170,10 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); ...@@ -176,15 +170,10 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
int wl1271_set_partition(struct wl1271 *wl, int wl1271_set_partition(struct wl1271 *wl,
struct wl1271_partition_set *p); struct wl1271_partition_set *p);
bool wl1271_set_block_size(struct wl1271 *wl);
/* Functions from wl1271_main.c */ /* Functions from wl1271_main.c */
int wl1271_register_hw(struct wl1271 *wl);
void wl1271_unregister_hw(struct wl1271 *wl);
int wl1271_init_ieee80211(struct wl1271 *wl);
struct ieee80211_hw *wl1271_alloc_hw(void);
int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data);
bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl); int wl1271_tx_dummy_packet(struct wl1271 *wl);
#endif #endif
此差异已折叠。
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "ps.h" #include "ps.h"
#include "io.h" #include "io.h"
#include "tx.h" #include "tx.h"
#include "debug.h"
#define WL1271_WAKEUP_TIMEOUT 500 #define WL1271_WAKEUP_TIMEOUT 500
...@@ -32,6 +33,7 @@ void wl1271_elp_work(struct work_struct *work) ...@@ -32,6 +33,7 @@ void wl1271_elp_work(struct work_struct *work)
{ {
struct delayed_work *dwork; struct delayed_work *dwork;
struct wl1271 *wl; struct wl1271 *wl;
struct wl12xx_vif *wlvif;
dwork = container_of(work, struct delayed_work, work); dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, elp_work); wl = container_of(dwork, struct wl1271, elp_work);
...@@ -47,11 +49,15 @@ void wl1271_elp_work(struct work_struct *work) ...@@ -47,11 +49,15 @@ void wl1271_elp_work(struct work_struct *work)
if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
goto out; goto out;
if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
(!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
!test_bit(WL1271_FLAG_IDLE, &wl->flags)))
goto out; goto out;
wl12xx_for_each_wlvif(wl, wlvif) {
if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
!test_bit(WL1271_FLAG_IDLE, &wl->flags))
goto out;
}
wl1271_debug(DEBUG_PSM, "chip to elp"); wl1271_debug(DEBUG_PSM, "chip to elp");
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
set_bit(WL1271_FLAG_IN_ELP, &wl->flags); set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
...@@ -65,13 +71,17 @@ void wl1271_elp_work(struct work_struct *work) ...@@ -65,13 +71,17 @@ void wl1271_elp_work(struct work_struct *work)
/* Routines to toggle sleep mode while in ELP */ /* Routines to toggle sleep mode while in ELP */
void wl1271_ps_elp_sleep(struct wl1271 *wl) void wl1271_ps_elp_sleep(struct wl1271 *wl)
{ {
struct wl12xx_vif *wlvif;
/* we shouldn't get consecutive sleep requests */ /* we shouldn't get consecutive sleep requests */
if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
return; return;
if (!test_bit(WL1271_FLAG_PSM, &wl->flags) && wl12xx_for_each_wlvif(wl, wlvif) {
!test_bit(WL1271_FLAG_IDLE, &wl->flags)) if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
return; !test_bit(WL1271_FLAG_IDLE, &wl->flags))
return;
}
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
msecs_to_jiffies(ELP_ENTRY_DELAY)); msecs_to_jiffies(ELP_ENTRY_DELAY));
...@@ -143,8 +153,8 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) ...@@ -143,8 +153,8 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
return 0; return 0;
} }
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u32 rates, bool send) enum wl1271_cmd_ps_mode mode, u32 rates, bool send)
{ {
int ret; int ret;
...@@ -152,39 +162,34 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, ...@@ -152,39 +162,34 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case STATION_POWER_SAVE_MODE: case STATION_POWER_SAVE_MODE:
wl1271_debug(DEBUG_PSM, "entering psm"); wl1271_debug(DEBUG_PSM, "entering psm");
ret = wl1271_acx_wake_up_conditions(wl); ret = wl1271_acx_wake_up_conditions(wl, wlvif);
if (ret < 0) { if (ret < 0) {
wl1271_error("couldn't set wake up conditions"); wl1271_error("couldn't set wake up conditions");
return ret; return ret;
} }
ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE);
if (ret < 0) if (ret < 0)
return ret; return ret;
set_bit(WL1271_FLAG_PSM, &wl->flags); set_bit(WLVIF_FLAG_PSM, &wlvif->flags);
break; break;
case STATION_ACTIVE_MODE: case STATION_ACTIVE_MODE:
default: default:
wl1271_debug(DEBUG_PSM, "leaving psm"); wl1271_debug(DEBUG_PSM, "leaving psm");
/* disable beacon early termination */ /* disable beacon early termination */
if (wl->band == IEEE80211_BAND_2GHZ) { if (wlvif->band == IEEE80211_BAND_2GHZ) {
ret = wl1271_acx_bet_enable(wl, false); ret = wl1271_acx_bet_enable(wl, wlvif, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
/* disable beacon filtering */ ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE);
ret = wl1271_acx_beacon_filter_opt(wl, false);
if (ret < 0)
return ret;
ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
if (ret < 0) if (ret < 0)
return ret; return ret;
clear_bit(WL1271_FLAG_PSM, &wl->flags); clear_bit(WLVIF_FLAG_PSM, &wlvif->flags);
break; break;
} }
...@@ -223,9 +228,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) ...@@ -223,9 +228,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
wl1271_handle_tx_low_watermark(wl); wl1271_handle_tx_low_watermark(wl);
} }
void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 hlid, bool clean_queues)
{ {
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
if (test_bit(hlid, &wl->ap_ps_map)) if (test_bit(hlid, &wl->ap_ps_map))
return; return;
...@@ -235,7 +242,7 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) ...@@ -235,7 +242,7 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
clean_queues); clean_queues);
rcu_read_lock(); rcu_read_lock();
sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr); sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
if (!sta) { if (!sta) {
wl1271_error("could not find sta %pM for starting ps", wl1271_error("could not find sta %pM for starting ps",
wl->links[hlid].addr); wl->links[hlid].addr);
...@@ -253,9 +260,10 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) ...@@ -253,9 +260,10 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
__set_bit(hlid, &wl->ap_ps_map); __set_bit(hlid, &wl->ap_ps_map);
} }
void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid) void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
{ {
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
if (!test_bit(hlid, &wl->ap_ps_map)) if (!test_bit(hlid, &wl->ap_ps_map))
return; return;
...@@ -265,7 +273,7 @@ void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid) ...@@ -265,7 +273,7 @@ void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid)
__clear_bit(hlid, &wl->ap_ps_map); __clear_bit(hlid, &wl->ap_ps_map);
rcu_read_lock(); rcu_read_lock();
sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr); sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
if (!sta) { if (!sta) {
wl1271_error("could not find sta %pM for ending ps", wl1271_error("could not find sta %pM for ending ps",
wl->links[hlid].addr); wl->links[hlid].addr);
......
...@@ -27,13 +27,14 @@ ...@@ -27,13 +27,14 @@
#include "wl12xx.h" #include "wl12xx.h"
#include "acx.h" #include "acx.h"
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u32 rates, bool send); enum wl1271_cmd_ps_mode mode, u32 rates, bool send);
void wl1271_ps_elp_sleep(struct wl1271 *wl); void wl1271_ps_elp_sleep(struct wl1271 *wl);
int wl1271_ps_elp_wakeup(struct wl1271 *wl); int wl1271_ps_elp_wakeup(struct wl1271 *wl);
void wl1271_elp_work(struct work_struct *work); void wl1271_elp_work(struct work_struct *work);
void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); u8 hlid, bool clean_queues);
void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
#define WL1271_PS_COMPLETE_TIMEOUT 500 #define WL1271_PS_COMPLETE_TIMEOUT 500
......
...@@ -408,7 +408,7 @@ ...@@ -408,7 +408,7 @@
/* Firmware image load chunk size */ /* Firmware image load chunk size */
#define CHUNK_SIZE 512 #define CHUNK_SIZE 16384
/* Firmware image header size */ /* Firmware image header size */
#define FW_HDR_SIZE 8 #define FW_HDR_SIZE 8
......
...@@ -25,9 +25,11 @@ ...@@ -25,9 +25,11 @@
#include <linux/sched.h> #include <linux/sched.h>
#include "wl12xx.h" #include "wl12xx.h"
#include "debug.h"
#include "acx.h" #include "acx.h"
#include "reg.h" #include "reg.h"
#include "rx.h" #include "rx.h"
#include "tx.h"
#include "io.h" #include "io.h"
static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
...@@ -96,7 +98,7 @@ static void wl1271_rx_status(struct wl1271 *wl, ...@@ -96,7 +98,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
} }
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
bool unaligned) bool unaligned, u8 *hlid)
{ {
struct wl1271_rx_descriptor *desc; struct wl1271_rx_descriptor *desc;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -159,6 +161,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, ...@@ -159,6 +161,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
* payload aligned to 4 bytes. * payload aligned to 4 bytes.
*/ */
memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
*hlid = desc->hlid;
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_beacon(hdr->frame_control)) if (ieee80211_is_beacon(hdr->frame_control))
...@@ -169,10 +172,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, ...@@ -169,10 +172,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb, wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb,
skb->len - desc->pad_len, skb->len - desc->pad_len,
beacon ? "beacon" : "", beacon ? "beacon" : "",
seq_num); seq_num, *hlid);
skb_trim(skb, skb->len - desc->pad_len); skb_trim(skb, skb->len - desc->pad_len);
...@@ -185,6 +188,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, ...@@ -185,6 +188,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
{ {
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
u32 buf_size; u32 buf_size;
u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
...@@ -192,8 +196,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) ...@@ -192,8 +196,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
u32 mem_block; u32 mem_block;
u32 pkt_length; u32 pkt_length;
u32 pkt_offset; u32 pkt_offset;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); u8 hlid;
bool had_data = false;
bool unaligned = false; bool unaligned = false;
while (drv_rx_counter != fw_rx_counter) { while (drv_rx_counter != fw_rx_counter) {
...@@ -253,8 +256,11 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) ...@@ -253,8 +256,11 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
*/ */
if (wl1271_rx_handle_data(wl, if (wl1271_rx_handle_data(wl,
wl->aggr_buf + pkt_offset, wl->aggr_buf + pkt_offset,
pkt_length, unaligned) == 1) pkt_length, unaligned,
had_data = true; &hlid) == 1) {
WARN_ON(hlid >= WL12XX_MAX_LINKS);
__set_bit(hlid, active_hlids);
}
wl->rx_counter++; wl->rx_counter++;
drv_rx_counter++; drv_rx_counter++;
...@@ -270,17 +276,5 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) ...@@ -270,17 +276,5 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
if (!is_ap && wl->conf.rx_streaming.interval && had_data && wl12xx_rearm_rx_streaming(wl, active_hlids);
(wl->conf.rx_streaming.always ||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
u32 timeout = wl->conf.rx_streaming.duration;
/* restart rx streaming */
if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
ieee80211_queue_work(wl->hw,
&wl->rx_streaming_enable_work);
mod_timer(&wl->rx_streaming_timer,
jiffies + msecs_to_jiffies(timeout));
}
} }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/ieee80211.h> #include <linux/ieee80211.h>
#include "wl12xx.h" #include "wl12xx.h"
#include "debug.h"
#include "cmd.h" #include "cmd.h"
#include "scan.h" #include "scan.h"
#include "acx.h" #include "acx.h"
...@@ -34,6 +35,8 @@ void wl1271_scan_complete_work(struct work_struct *work) ...@@ -34,6 +35,8 @@ void wl1271_scan_complete_work(struct work_struct *work)
{ {
struct delayed_work *dwork; struct delayed_work *dwork;
struct wl1271 *wl; struct wl1271 *wl;
struct ieee80211_vif *vif;
struct wl12xx_vif *wlvif;
int ret; int ret;
bool is_sta, is_ibss; bool is_sta, is_ibss;
...@@ -50,28 +53,31 @@ void wl1271_scan_complete_work(struct work_struct *work) ...@@ -50,28 +53,31 @@ void wl1271_scan_complete_work(struct work_struct *work)
if (wl->scan.state == WL1271_SCAN_STATE_IDLE) if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
goto out; goto out;
vif = wl->scan_vif;
wlvif = wl12xx_vif_to_data(vif);
wl->scan.state = WL1271_SCAN_STATE_IDLE; wl->scan.state = WL1271_SCAN_STATE_IDLE;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
wl->scan.req = NULL; wl->scan.req = NULL;
wl->scan_vif = NULL;
ret = wl1271_ps_elp_wakeup(wl); ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
/* restore hardware connection monitoring template */ /* restore hardware connection monitoring template */
wl1271_cmd_build_ap_probe_req(wl, wl->probereq); wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
} }
/* return to ROC if needed */ /* return to ROC if needed */
is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS);
is_ibss = (wl->bss_type == BSS_TYPE_IBSS); is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS);
if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) ||
(is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) &&
!test_bit(wl->dev_role_id, wl->roc_map)) { !test_bit(wlvif->dev_role_id, wl->roc_map)) {
/* restore remain on channel */ /* restore remain on channel */
wl12xx_cmd_role_start_dev(wl); wl12xx_start_dev(wl, wlvif);
wl12xx_roc(wl, wl->dev_role_id);
} }
wl1271_ps_elp_sleep(wl); wl1271_ps_elp_sleep(wl);
...@@ -155,9 +161,11 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, ...@@ -155,9 +161,11 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
#define WL1271_NOTHING_TO_SCAN 1 #define WL1271_NOTHING_TO_SCAN 1
static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
bool passive, u32 basic_rate) enum ieee80211_band band,
bool passive, u32 basic_rate)
{ {
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271_cmd_scan *cmd; struct wl1271_cmd_scan *cmd;
struct wl1271_cmd_trigger_scan_to *trigger; struct wl1271_cmd_trigger_scan_to *trigger;
int ret; int ret;
...@@ -177,11 +185,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, ...@@ -177,11 +185,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
if (passive) if (passive)
scan_options |= WL1271_SCAN_OPT_PASSIVE; scan_options |= WL1271_SCAN_OPT_PASSIVE;
if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
cmd->params.role_id = wl->role_id; cmd->params.role_id = wlvif->role_id;
cmd->params.scan_options = cpu_to_le16(scan_options); cmd->params.scan_options = cpu_to_le16(scan_options);
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
...@@ -194,7 +202,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, ...@@ -194,7 +202,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.tid_trigger = 0; cmd->params.tid_trigger = 0;
cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
...@@ -208,11 +215,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, ...@@ -208,11 +215,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
} }
memcpy(cmd->addr, wl->mac_addr, ETH_ALEN); memcpy(cmd->addr, vif->addr, ETH_ALEN);
ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid,
wl->scan.req->ie, wl->scan.req->ie_len, wl->scan.ssid_len, wl->scan.req->ie,
band); wl->scan.req->ie_len, band);
if (ret < 0) { if (ret < 0) {
wl1271_error("PROBE request template failed"); wl1271_error("PROBE request template failed");
goto out; goto out;
...@@ -241,11 +248,12 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, ...@@ -241,11 +248,12 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
return ret; return ret;
} }
void wl1271_scan_stm(struct wl1271 *wl) void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif)
{ {
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
int ret = 0; int ret = 0;
enum ieee80211_band band; enum ieee80211_band band;
u32 rate; u32 rate, mask;
switch (wl->scan.state) { switch (wl->scan.state) {
case WL1271_SCAN_STATE_IDLE: case WL1271_SCAN_STATE_IDLE:
...@@ -253,47 +261,59 @@ void wl1271_scan_stm(struct wl1271 *wl) ...@@ -253,47 +261,59 @@ void wl1271_scan_stm(struct wl1271 *wl)
case WL1271_SCAN_STATE_2GHZ_ACTIVE: case WL1271_SCAN_STATE_2GHZ_ACTIVE:
band = IEEE80211_BAND_2GHZ; band = IEEE80211_BAND_2GHZ;
rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); mask = wlvif->bitrate_masks[band];
ret = wl1271_scan_send(wl, band, false, rate); if (wl->scan.req->no_cck) {
mask &= ~CONF_TX_CCK_RATES;
if (!mask)
mask = CONF_TX_RATE_MASK_BASIC_P2P;
}
rate = wl1271_tx_min_rate_get(wl, mask);
ret = wl1271_scan_send(wl, vif, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
wl1271_scan_stm(wl); wl1271_scan_stm(wl, vif);
} }
break; break;
case WL1271_SCAN_STATE_2GHZ_PASSIVE: case WL1271_SCAN_STATE_2GHZ_PASSIVE:
band = IEEE80211_BAND_2GHZ; band = IEEE80211_BAND_2GHZ;
rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); mask = wlvif->bitrate_masks[band];
ret = wl1271_scan_send(wl, band, true, rate); if (wl->scan.req->no_cck) {
mask &= ~CONF_TX_CCK_RATES;
if (!mask)
mask = CONF_TX_RATE_MASK_BASIC_P2P;
}
rate = wl1271_tx_min_rate_get(wl, mask);
ret = wl1271_scan_send(wl, vif, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
if (wl->enable_11a) if (wl->enable_11a)
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
else else
wl->scan.state = WL1271_SCAN_STATE_DONE; wl->scan.state = WL1271_SCAN_STATE_DONE;
wl1271_scan_stm(wl); wl1271_scan_stm(wl, vif);
} }
break; break;
case WL1271_SCAN_STATE_5GHZ_ACTIVE: case WL1271_SCAN_STATE_5GHZ_ACTIVE:
band = IEEE80211_BAND_5GHZ; band = IEEE80211_BAND_5GHZ;
rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, band, false, rate); ret = wl1271_scan_send(wl, vif, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
wl1271_scan_stm(wl); wl1271_scan_stm(wl, vif);
} }
break; break;
case WL1271_SCAN_STATE_5GHZ_PASSIVE: case WL1271_SCAN_STATE_5GHZ_PASSIVE:
band = IEEE80211_BAND_5GHZ; band = IEEE80211_BAND_5GHZ;
rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
ret = wl1271_scan_send(wl, band, true, rate); ret = wl1271_scan_send(wl, vif, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_DONE; wl->scan.state = WL1271_SCAN_STATE_DONE;
wl1271_scan_stm(wl); wl1271_scan_stm(wl, vif);
} }
break; break;
...@@ -317,7 +337,8 @@ void wl1271_scan_stm(struct wl1271 *wl) ...@@ -317,7 +337,8 @@ void wl1271_scan_stm(struct wl1271 *wl)
} }
} }
int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif,
const u8 *ssid, size_t ssid_len,
struct cfg80211_scan_request *req) struct cfg80211_scan_request *req)
{ {
/* /*
...@@ -338,6 +359,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, ...@@ -338,6 +359,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
wl->scan.ssid_len = 0; wl->scan.ssid_len = 0;
} }
wl->scan_vif = vif;
wl->scan.req = req; wl->scan.req = req;
memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
...@@ -346,7 +368,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, ...@@ -346,7 +368,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
wl1271_scan_stm(wl); wl1271_scan_stm(wl, vif);
return 0; return 0;
} }
...@@ -550,6 +572,9 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, ...@@ -550,6 +572,9 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
* so they're used in probe requests. * so they're used in probe requests.
*/ */
for (i = 0; i < req->n_ssids; i++) { for (i = 0; i < req->n_ssids; i++) {
if (!req->ssids[i].ssid_len)
continue;
for (j = 0; j < cmd->n_ssids; j++) for (j = 0; j < cmd->n_ssids; j++)
if (!memcmp(req->ssids[i].ssid, if (!memcmp(req->ssids[i].ssid,
cmd->ssids[j].ssid, cmd->ssids[j].ssid,
...@@ -585,6 +610,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, ...@@ -585,6 +610,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
} }
int wl1271_scan_sched_scan_config(struct wl1271 *wl, int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req, struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies) struct ieee80211_sched_scan_ies *ies)
{ {
...@@ -631,7 +657,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, ...@@ -631,7 +657,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
} }
if (!force_passive && cfg->active[0]) { if (!force_passive && cfg->active[0]) {
ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
req->ssids[0].ssid_len, req->ssids[0].ssid_len,
ies->ie[IEEE80211_BAND_2GHZ], ies->ie[IEEE80211_BAND_2GHZ],
ies->len[IEEE80211_BAND_2GHZ], ies->len[IEEE80211_BAND_2GHZ],
...@@ -643,7 +669,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, ...@@ -643,7 +669,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
} }
if (!force_passive && cfg->active[1]) { if (!force_passive && cfg->active[1]) {
ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
req->ssids[0].ssid_len, req->ssids[0].ssid_len,
ies->ie[IEEE80211_BAND_5GHZ], ies->ie[IEEE80211_BAND_5GHZ],
ies->len[IEEE80211_BAND_5GHZ], ies->len[IEEE80211_BAND_5GHZ],
...@@ -667,14 +693,14 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, ...@@ -667,14 +693,14 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
return ret; return ret;
} }
int wl1271_scan_sched_scan_start(struct wl1271 *wl) int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{ {
struct wl1271_cmd_sched_scan_start *start; struct wl1271_cmd_sched_scan_start *start;
int ret = 0; int ret = 0;
wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); wl1271_debug(DEBUG_CMD, "cmd periodic scan start");
if (wl->bss_type != BSS_TYPE_STA_BSS) if (wlvif->bss_type != BSS_TYPE_STA_BSS)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) if (!test_bit(WL1271_FLAG_IDLE, &wl->flags))
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册