cmd.c revision 95dac04f881322b510c45e5ae83f0dbee4f823a2
1f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/* 2f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * This file is part of wl1271 3f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 42f826f55404ca43efced94d548356182820e764fLuciano Coelho * Copyright (C) 2009-2010 Nokia Corporation 5f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 6f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * Contact: Luciano Coelho <luciano.coelho@nokia.com> 7f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 8f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * This program is free software; you can redistribute it and/or 9f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * modify it under the terms of the GNU General Public License 10f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * version 2 as published by the Free Software Foundation. 11f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 12f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * This program is distributed in the hope that it will be useful, but 13f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * WITHOUT ANY WARRANTY; without even the implied warranty of 14f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * General Public License for more details. 16f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 17f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * You should have received a copy of the GNU General Public License 18f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * along with this program; if not, write to the Free Software 19f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 02110-1301 USA 21f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 22f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 23f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 24f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/module.h> 25f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/platform_device.h> 26f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/spi/spi.h> 27f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/etherdevice.h> 28023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo#include <linux/ieee80211.h> 295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 30f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 3100d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "wl12xx.h" 3200d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "reg.h" 3300d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "io.h" 3400d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "acx.h" 35f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl12xx_80211.h" 3600d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "cmd.h" 3700d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "event.h" 3898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov#include "tx.h" 39f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 4016092b5cccd6f3a8d1957ca004c97947e07018dbJuuso Oikarinen#define WL1271_CMD_FAST_POLL_COUNT 50 41f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 42f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/* 43f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * send command to firmware 44f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 45f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 46f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: command id 47f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing the command, must work with dma 48f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of the buffer 49f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 50fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinenint wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, 51fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen size_t res_len) 52f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 53f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_header *cmd; 54f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho unsigned long timeout; 55f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u32 intr; 56f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 57ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen u16 status; 58bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal u16 poll_count = 0; 59f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 60f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = buf; 61d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->id = cpu_to_le16(id); 62f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->status = 0; 63f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 64f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(len % 4 != 0); 6524225b37bd78d3e2edaa1a39316c54786adaa465Arik Nemtsov WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); 66f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 677b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write(wl, wl->cmd_box_addr, buf, len, false); 68f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 697b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); 70f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 71f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); 72f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 737b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 74f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { 75f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (time_after(jiffies, timeout)) { 76f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("command complete timeout"); 77f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ETIMEDOUT; 78f482b76202f4ac0f62a77b0e55ac1a1cfe480e2bArik Nemtsov goto fail; 79f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 80f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 81bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal poll_count++; 8216092b5cccd6f3a8d1957ca004c97947e07018dbJuuso Oikarinen if (poll_count < WL1271_CMD_FAST_POLL_COUNT) 8316092b5cccd6f3a8d1957ca004c97947e07018dbJuuso Oikarinen udelay(10); 8416092b5cccd6f3a8d1957ca004c97947e07018dbJuuso Oikarinen else 8516092b5cccd6f3a8d1957ca004c97947e07018dbJuuso Oikarinen msleep(1); 86f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 877b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 88f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 89f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 903b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen /* read back the status code of the command */ 91fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (res_len == 0) 92fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen res_len = sizeof(struct wl1271_cmd_header); 937b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); 943b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen 95ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen status = le16_to_cpu(cmd->status); 96ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen if (status != CMD_STATUS_SUCCESS) { 97ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen wl1271_error("command execute failure %d", status); 983b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen ret = -EIO; 99f482b76202f4ac0f62a77b0e55ac1a1cfe480e2bArik Nemtsov goto fail; 1003b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen } 1013b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen 1027b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, 1037b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi WL1271_ACX_INTR_CMD_COMPLETE); 104f482b76202f4ac0f62a77b0e55ac1a1cfe480e2bArik Nemtsov return 0; 105f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 106f482b76202f4ac0f62a77b0e55ac1a1cfe480e2bArik Nemtsovfail: 107f482b76202f4ac0f62a77b0e55ac1a1cfe480e2bArik Nemtsov WARN_ON(1); 108baacb9aed020b890ddf6a57837a169092a25fc9bIdo Yariv wl12xx_queue_recovery_work(wl); 109f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 110f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 111f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 11298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelhoint wl1271_cmd_general_parms(struct wl1271 *wl) 11398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho{ 11498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho struct wl1271_general_parms_cmd *gen_parms; 11549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi struct wl1271_ini_general_params *gp = 11649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi &((struct wl1271_nvs_file *)wl->nvs)->general_params; 11749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi bool answer = false; 11849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi int ret; 11949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 12049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi if (!wl->nvs) 12149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi return -ENODEV; 12249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 12349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 12449d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi if (!gen_parms) 12549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi return -ENOMEM; 12649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 12749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; 12849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 12949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi memcpy(&gen_parms->general_params, gp, sizeof(*gp)); 13049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 13149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi if (gp->tx_bip_fem_auto_detect) 13249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi answer = true; 13349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 134b03acadea4f46884aa3c3e4d3a6ce03d283525e6Shahar Levi /* Override the REF CLK from the NVS with the one from platform data */ 135b03acadea4f46884aa3c3e4d3a6ce03d283525e6Shahar Levi gen_parms->general_params.ref_clock = wl->ref_clock; 136b03acadea4f46884aa3c3e4d3a6ce03d283525e6Shahar Levi 1370c005048aa3cd3ac7bfdd3c6fcc20ea4f0ab667dShahar Levi /* LPD mode enable (bits 6-7) in WL1271 AP mode only */ 1380c005048aa3cd3ac7bfdd3c6fcc20ea4f0ab667dShahar Levi if (wl->quirks & WL12XX_QUIRK_LPD_MODE) 1390c005048aa3cd3ac7bfdd3c6fcc20ea4f0ab667dShahar Levi gen_parms->general_params.general_settings |= 1400c005048aa3cd3ac7bfdd3c6fcc20ea4f0ab667dShahar Levi GENERAL_SETTINGS_DRPW_LPD; 1410c005048aa3cd3ac7bfdd3c6fcc20ea4f0ab667dShahar Levi 14249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); 14349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi if (ret < 0) { 14449d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); 14549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi goto out; 14649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi } 14749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 14849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi gp->tx_bip_fem_manufacturer = 14949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi gen_parms->general_params.tx_bip_fem_manufacturer; 15049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 15149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 15249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 15349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 15449d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Leviout: 15549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi kfree(gen_parms); 15649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi return ret; 15749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi} 15849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 15949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Leviint wl128x_cmd_general_parms(struct wl1271 *wl) 16049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi{ 16149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi struct wl128x_general_parms_cmd *gen_parms; 16249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi struct wl128x_ini_general_params *gp = 16349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi &((struct wl128x_nvs_file *)wl->nvs)->general_params; 1644b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen bool answer = false; 16598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho int ret; 16698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 167152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen if (!wl->nvs) 168152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen return -ENODEV; 169152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 17098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 17198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (!gen_parms) 17298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return -ENOMEM; 17398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 17498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; 17598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 1764b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen memcpy(&gen_parms->general_params, gp, sizeof(*gp)); 1774b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen 1784b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen if (gp->tx_bip_fem_auto_detect) 1794b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen answer = true; 18076c0f8d396bd306111d349cfe770e1c4fcf70248Luciano Coelho 181b03acadea4f46884aa3c3e4d3a6ce03d283525e6Shahar Levi /* Replace REF and TCXO CLKs with the ones from platform data */ 182b03acadea4f46884aa3c3e4d3a6ce03d283525e6Shahar Levi gen_parms->general_params.ref_clock = wl->ref_clock; 183b03acadea4f46884aa3c3e4d3a6ce03d283525e6Shahar Levi gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; 184b03acadea4f46884aa3c3e4d3a6ce03d283525e6Shahar Levi 1854b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); 1864b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen if (ret < 0) { 18798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); 1884b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen goto out; 1894b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen } 19098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 1914b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen gp->tx_bip_fem_manufacturer = 1924b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen gen_parms->general_params.tx_bip_fem_manufacturer; 1934b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen 1944b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 1954b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 1964b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinen 1974b34d432b0fcff422304de4eb49d6da861fe335cJuuso Oikarinenout: 19898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho kfree(gen_parms); 19998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return ret; 20098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho} 20198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 20298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelhoint wl1271_cmd_radio_parms(struct wl1271 *wl) 20398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho{ 204bc765bf3b9a095b3e41c8cda80643901884c3dd4Shahar Levi struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; 20598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho struct wl1271_radio_parms_cmd *radio_parms; 206bc765bf3b9a095b3e41c8cda80643901884c3dd4Shahar Levi struct wl1271_ini_general_params *gp = &nvs->general_params; 207152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen int ret; 208152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 209152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen if (!wl->nvs) 210152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen return -ENODEV; 21198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 21298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); 21398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (!radio_parms) 21498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return -ENOMEM; 21598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 21698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; 21798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 218a7da74fc88bff6f82f8255f2def49907f82f4c61Juuso Oikarinen /* 2.4GHz parameters */ 219bc765bf3b9a095b3e41c8cda80643901884c3dd4Shahar Levi memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, 220eb70eb723b489dd4e233e22e47d993f59858cdd8Juuso Oikarinen sizeof(struct wl1271_ini_band_params_2)); 221eb70eb723b489dd4e233e22e47d993f59858cdd8Juuso Oikarinen memcpy(&radio_parms->dyn_params_2, 222bc765bf3b9a095b3e41c8cda80643901884c3dd4Shahar Levi &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, 223eb70eb723b489dd4e233e22e47d993f59858cdd8Juuso Oikarinen sizeof(struct wl1271_ini_fem_params_2)); 224152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 225a7da74fc88bff6f82f8255f2def49907f82f4c61Juuso Oikarinen /* 5GHz parameters */ 226a7da74fc88bff6f82f8255f2def49907f82f4c61Juuso Oikarinen memcpy(&radio_parms->static_params_5, 227bc765bf3b9a095b3e41c8cda80643901884c3dd4Shahar Levi &nvs->stat_radio_params_5, 228a7da74fc88bff6f82f8255f2def49907f82f4c61Juuso Oikarinen sizeof(struct wl1271_ini_band_params_5)); 229a7da74fc88bff6f82f8255f2def49907f82f4c61Juuso Oikarinen memcpy(&radio_parms->dyn_params_5, 230bc765bf3b9a095b3e41c8cda80643901884c3dd4Shahar Levi &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, 231a7da74fc88bff6f82f8255f2def49907f82f4c61Juuso Oikarinen sizeof(struct wl1271_ini_fem_params_5)); 23298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 23398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", 23498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms, sizeof(*radio_parms)); 23598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 23698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); 23798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (ret < 0) 23898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); 23998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 24098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho kfree(radio_parms); 24198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return ret; 24298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho} 24398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 24449d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Leviint wl128x_cmd_radio_parms(struct wl1271 *wl) 24549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi{ 24649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; 24749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi struct wl128x_radio_parms_cmd *radio_parms; 24849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi struct wl128x_ini_general_params *gp = &nvs->general_params; 24949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi int ret; 25049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 25149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi if (!wl->nvs) 25249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi return -ENODEV; 25349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 25449d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); 25549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi if (!radio_parms) 25649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi return -ENOMEM; 25749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 25849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; 25949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 26049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi /* 2.4GHz parameters */ 26149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, 26249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi sizeof(struct wl128x_ini_band_params_2)); 26349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi memcpy(&radio_parms->dyn_params_2, 26449d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, 26549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi sizeof(struct wl128x_ini_fem_params_2)); 26649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 26749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi /* 5GHz parameters */ 26849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi memcpy(&radio_parms->static_params_5, 26949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi &nvs->stat_radio_params_5, 27049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi sizeof(struct wl128x_ini_band_params_5)); 27149d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi memcpy(&radio_parms->dyn_params_5, 27249d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, 27349d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi sizeof(struct wl128x_ini_fem_params_5)); 27449d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 27549d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; 27649d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 27749d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", 27849d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi radio_parms, sizeof(*radio_parms)); 27949d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi 28049d750ca14cd49e76ab039b33b5a621e0a92b9fdShahar Levi ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); 28198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (ret < 0) 28298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); 28398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 28498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho kfree(radio_parms); 28598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return ret; 28698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho} 28798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 288644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinenint wl1271_cmd_ext_radio_parms(struct wl1271 *wl) 289644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen{ 290644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen struct wl1271_ext_radio_parms_cmd *ext_radio_parms; 291644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen struct conf_rf_settings *rf = &wl->conf.rf; 292644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen int ret; 293644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 294644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen if (!wl->nvs) 295644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen return -ENODEV; 296644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 297644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); 298644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen if (!ext_radio_parms) 299644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen return -ENOMEM; 300644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 301644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; 302644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 303644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, 304644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen rf->tx_per_channel_power_compensation_2, 305644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen CONF_TX_PWR_COMPENSATION_LEN_2); 306644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, 307644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen rf->tx_per_channel_power_compensation_5, 308644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen CONF_TX_PWR_COMPENSATION_LEN_5); 309644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 310644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", 311644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen ext_radio_parms, sizeof(*ext_radio_parms)); 312644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 313644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); 314644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen if (ret < 0) 315644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); 316644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 317644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen kfree(ext_radio_parms); 318644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen return ret; 319644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen} 320644a48607cd40954b6fb095b39a3ccaa0204191eJuuso Oikarinen 32199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho/* 32299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho * Poll the mailbox event field until any of the bits in the mask is set or a 32399d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) 32499d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho */ 32505285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsovstatic int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) 32699d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho{ 32799d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho u32 events_vector, event; 32899d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho unsigned long timeout; 32999d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 33099d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); 33199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 33299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho do { 33352b0e7a61fd4b67fe8efe295297d8549f052f786Juuso Oikarinen if (time_after(jiffies, timeout)) { 33405285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", 33505285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov (int)mask); 33699d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho return -ETIMEDOUT; 33752b0e7a61fd4b67fe8efe295297d8549f052f786Juuso Oikarinen } 33899d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 33999d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho msleep(1); 34099d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 34199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho /* read from both event fields */ 34299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho wl1271_read(wl, wl->mbox_ptr[0], &events_vector, 34399d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho sizeof(events_vector), false); 34499d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho event = events_vector & mask; 34599d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho wl1271_read(wl, wl->mbox_ptr[1], &events_vector, 34699d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho sizeof(events_vector), false); 34799d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho event |= events_vector & mask; 34899d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho } while (!event); 34999d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 35099d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho return 0; 35199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho} 35299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 35305285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsovstatic int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) 35405285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov{ 35505285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov int ret; 35605285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov 35705285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); 35805285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov if (ret != 0) { 359baacb9aed020b890ddf6a57837a169092a25fc9bIdo Yariv wl12xx_queue_recovery_work(wl); 36005285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov return ret; 36105285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov } 36205285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov 36305285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov return 0; 36405285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov} 36505285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov 36615305498a443c181c8fb5deafb94eae585fe3ad5Juuso Oikarinenint wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) 367f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 368f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_join *join; 369f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret, i; 370f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u8 *bssid; 371f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 372f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join = kzalloc(sizeof(*join), GFP_KERNEL); 373f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!join) { 374f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 375f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 376f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 377f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 378f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd join"); 379f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 380f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* Reverse order BSSID */ 381f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho bssid = (u8 *) &join->bssid_lsb; 382f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho for (i = 0; i < ETH_ALEN; i++) 383f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho bssid[i] = wl->bssid[ETH_ALEN - i - 1]; 384f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 385d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_config_options = cpu_to_le32(wl->rx_config); 386d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_filter_options = cpu_to_le32(wl->rx_filter); 38715305498a443c181c8fb5deafb94eae585fe3ad5Juuso Oikarinen join->bss_type = bss_type; 38823a7a51c5a35b30aa3edcc31a6a57b01c523b4cdLuciano Coelho join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); 38972c2d9e511846a4f2759389b38ed8a5553579eb3Eliad Peller join->supported_rate_set = cpu_to_le32(wl->rate_set); 390f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 391ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen if (wl->band == IEEE80211_BAND_5GHZ) 392a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; 393f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 39460e84c2ebb7b04361cf1ba0d325cc93366bd04a6Juuso Oikarinen join->beacon_interval = cpu_to_le16(wl->beacon_int); 395ae751bab9f55c3152ebf713c89a4fb6f439c2575Luciano Coelho join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; 396a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi 397f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->channel = wl->channel; 398f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ssid_len = wl->ssid_len; 399f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(join->ssid, wl->ssid, wl->ssid_len); 400f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 401f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; 402f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 403ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen /* reset TX security counters */ 404ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen wl->tx_security_last_seq = 0; 40504e36fc5f1ff4e349ea21de8d15e4e1844d04197Juuso Oikarinen wl->tx_security_seq = 0; 406f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 40772c2d9e511846a4f2759389b38ed8a5553579eb3Eliad Peller wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x", 40872c2d9e511846a4f2759389b38ed8a5553579eb3Eliad Peller join->basic_rate_set, join->supported_rate_set); 40972c2d9e511846a4f2759389b38ed8a5553579eb3Eliad Peller 410fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); 411f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 412f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("failed to initiate cmd join"); 413f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out_free; 414f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 415f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 41699d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); 41799d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho if (ret < 0) 41899d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho wl1271_error("cmd join event completion error"); 419f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 420f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout_free: 421f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(join); 422f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 423f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 424f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 425f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 426f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 427f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 428f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * send test command to firmware 429f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 430f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 431f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing the command, with all headers, must work with dma 432f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of the buffer 433f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @answer: is answer needed 434f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 435f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) 436f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 437f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 438fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen size_t res_len = 0; 439f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 440f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd test"); 441f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 442fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (answer) 443fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen res_len = buf_len; 444fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen 445fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len, res_len); 446f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 447f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 448f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST command failed"); 449f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 450f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 451f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 452fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen return ret; 453f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 454f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 455f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 456f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * read acx from firmware 457f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 458f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 459f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: acx id 460f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer for the response, including all headers, must work with dma 46125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * @len: length of buf 462f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 463f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) 464f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 465f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct acx_header *acx = buf; 466f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 467f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 468f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd interrogate"); 469f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 470d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->id = cpu_to_le16(id); 471f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 472f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* payload length, does not include any headers */ 473d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->len = cpu_to_le16(len - sizeof(*acx)); 474f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 475fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); 476fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (ret < 0) 477f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("INTERROGATE command failed"); 478f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 479f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 480f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 481f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 482f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 483f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * write acx value to firmware 484f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 485f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 486f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: acx id 487f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing acx, including all headers, must work with dma 488f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of buf 489f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 490f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) 491f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 492f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct acx_header *acx = buf; 493f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 494f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 495f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd configure"); 496f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 497d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->id = cpu_to_le16(id); 498f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 499f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* payload length, does not include any headers */ 500d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->len = cpu_to_le16(len - sizeof(*acx)); 501f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 502fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0); 503f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 504f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("CONFIGURE command NOK"); 505f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 506f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 507f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 508f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return 0; 509f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 510f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 51194210897e2b7df8446fdecd360342149e5b4a400Luciano Coelhoint wl1271_cmd_data_path(struct wl1271 *wl, bool enable) 512f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 513f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct cmd_enabledisable_path *cmd; 514f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 515f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u16 cmd_rx, cmd_tx; 516f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 517f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd data path"); 518f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 519f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 520f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 521f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 522f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 523f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 524f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 52594210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho /* the channel here is only used for calibration, so hardcoded to 1 */ 52694210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho cmd->channel = 1; 527f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 528f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (enable) { 529f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_rx = CMD_ENABLE_RX; 530f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_tx = CMD_ENABLE_TX; 531f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } else { 532f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_rx = CMD_DISABLE_RX; 533f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_tx = CMD_DISABLE_TX; 534f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 535f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 536fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); 537f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 538f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("rx %s cmd for channel %d failed", 53994210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 540f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 541f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 542f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 543f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", 54494210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 545f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 546fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); 547f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 548f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("tx %s cmd for channel %d failed", 54994210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 5501b00f2b560028a68cdbc57a0352163afd79822ddJuuso Oikarinen goto out; 551f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 552f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 553f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", 55494210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 555f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 556f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 557f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 558f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 559f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 560f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 561c8bde243421d759844264cf11e4248e7862c2722Eliad Pellerint wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) 562f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 563f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_ps_params *ps_params = NULL; 564f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 565f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 566f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd set ps mode"); 567f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 568f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); 569f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!ps_params) { 570f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 571f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 572f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 573f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 574f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params->ps_mode = ps_mode; 575f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 576f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, 577fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen sizeof(*ps_params), 0); 578f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 579f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("cmd set_ps_mode failed"); 580f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 581f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 582f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 583f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 584f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(ps_params); 585f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 586f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 587f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 588f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, 589606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen void *buf, size_t buf_len, int index, u32 rates) 590f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 591f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_template_set *cmd; 592f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 593f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 594f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id); 595f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 596f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); 597f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); 598f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 599f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 600f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 601f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 602f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 603f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 604f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 605f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->len = cpu_to_le16(buf_len); 606f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->template_type = template_id; 607606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen cmd->enabled_rates = cpu_to_le32(rates); 6081e05a81888318752e9a6d2158a95ddd6442ae117Arik Nemtsov cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit; 6091e05a81888318752e9a6d2158a95ddd6442ae117Arik Nemtsov cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit; 610bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen cmd->index = index; 611f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 612f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (buf) 613f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->template_data, buf, buf_len); 614f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 615fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd), 0); 616f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 617f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("cmd set_template failed: %d", ret); 618f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out_free; 619f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 620f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 621f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout_free: 622f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 623f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 624f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 625f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 626f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 627f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 628f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_build_null_data(struct wl1271 *wl) 629f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 630a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen struct sk_buff *skb = NULL; 631a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen int size; 632a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen void *ptr; 633a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen int ret = -ENOMEM; 634f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 635f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 636a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen if (wl->bss_type == BSS_TYPE_IBSS) { 637a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen size = sizeof(struct wl12xx_null_data_template); 638a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen ptr = NULL; 639a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen } else { 640a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen skb = ieee80211_nullfunc_get(wl->hw, wl->vif); 641a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen if (!skb) 642a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen goto out; 643a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen size = skb->len; 644a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen ptr = skb->data; 645a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen } 646a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen 647606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, 6488eab7b4708b5ef4701ecbe5d659f99743b77b668Juuso Oikarinen wl->basic_rate); 649f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 650899e6e65c39990a76c17940625dbe6001f618734Kalle Valoout: 651899e6e65c39990a76c17940625dbe6001f618734Kalle Valo dev_kfree_skb(skb); 652a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen if (ret) 653a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen wl1271_warning("cmd buld null data failed %d", ret); 654a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen 655899e6e65c39990a76c17940625dbe6001f618734Kalle Valo return ret; 656f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 657f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 658f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 659bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinenint wl1271_cmd_build_klv_null_data(struct wl1271 *wl) 660bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen{ 661bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen struct sk_buff *skb = NULL; 662bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen int ret = -ENOMEM; 663bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 664bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen skb = ieee80211_nullfunc_get(wl->hw, wl->vif); 665bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen if (!skb) 666bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen goto out; 667bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 668bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, 669bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen skb->data, skb->len, 670606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen CMD_TEMPL_KLV_IDX_NULL_DATA, 6718eab7b4708b5ef4701ecbe5d659f99743b77b668Juuso Oikarinen wl->basic_rate); 672bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 673bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinenout: 674bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen dev_kfree_skb(skb); 675bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen if (ret) 676bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen wl1271_warning("cmd build klv null data failed %d", ret); 677bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 678bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen return ret; 679bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 680bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen} 681bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 682f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) 683f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 684899e6e65c39990a76c17940625dbe6001f618734Kalle Valo struct sk_buff *skb; 685899e6e65c39990a76c17940625dbe6001f618734Kalle Valo int ret = 0; 686c3fea1994ac34dafa3ebb40d4f95354b2782af31Juuso Oikarinen 687899e6e65c39990a76c17940625dbe6001f618734Kalle Valo skb = ieee80211_pspoll_get(wl->hw, wl->vif); 688899e6e65c39990a76c17940625dbe6001f618734Kalle Valo if (!skb) 689899e6e65c39990a76c17940625dbe6001f618734Kalle Valo goto out; 690f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 691899e6e65c39990a76c17940625dbe6001f618734Kalle Valo ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, 692849923f43ca681cc86a401178db31acb60e79f3bJuuso Oikarinen skb->len, 0, wl->basic_rate_set); 693f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 694899e6e65c39990a76c17940625dbe6001f618734Kalle Valoout: 695899e6e65c39990a76c17940625dbe6001f618734Kalle Valo dev_kfree_skb(skb); 696899e6e65c39990a76c17940625dbe6001f618734Kalle Valo return ret; 697f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 698f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 699818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valoint wl1271_cmd_build_probe_req(struct wl1271 *wl, 700818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo const u8 *ssid, size_t ssid_len, 701818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo const u8 *ie, size_t ie_len, u8 band) 702f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 703818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo struct sk_buff *skb; 704abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi int ret; 705f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 706818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, 707818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo ie, ie_len); 708818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo if (!skb) { 709818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo ret = -ENOMEM; 710818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo goto out; 711818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo } 712818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo 713818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); 714f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 715abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == IEEE80211_BAND_2GHZ) 716abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, 717606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen skb->data, skb->len, 0, 718606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen wl->conf.tx.basic_rate); 719abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else 720abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, 721606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen skb->data, skb->len, 0, 722606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen wl->conf.tx.basic_rate_5); 723818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo 724818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valoout: 725818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo dev_kfree_skb(skb); 726abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi return ret; 727f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 728f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 7292f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinenstruct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, 7302f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen struct sk_buff *skb) 7312f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen{ 7322f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen int ret; 7332f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen 7342f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen if (!skb) 7352f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); 7362f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen if (!skb) 7372f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen goto out; 7382f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen 7392f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); 7402f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen 7412f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen if (wl->band == IEEE80211_BAND_2GHZ) 7422f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, 7432f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen skb->data, skb->len, 0, 7442f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen wl->conf.tx.basic_rate); 7452f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen else 7462f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, 7472f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen skb->data, skb->len, 0, 7482f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen wl->conf.tx.basic_rate_5); 7492f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen 7502f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen if (ret < 0) 7512f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen wl1271_error("Unable to set ap probe request template."); 7522f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen 7532f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinenout: 7542f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen return skb; 7552f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen} 7562f6724b24525fc989c0707974b23d96b36132385Juuso Oikarinen 757c5312772156bb5f9b2e95e4c91526d578426a069Eliad Pellerint wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) 758c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller{ 759c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller int ret; 760c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller struct wl12xx_arp_rsp_template tmpl; 761c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller struct ieee80211_hdr_3addr *hdr; 762c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller struct arphdr *arp_hdr; 763c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 764c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller memset(&tmpl, 0, sizeof(tmpl)); 765c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 766c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller /* mac80211 header */ 767c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller hdr = &tmpl.hdr; 768c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 769c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller IEEE80211_STYPE_DATA | 770c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller IEEE80211_FCTL_TODS); 771c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN); 772c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN); 773c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller memset(hdr->addr3, 0xff, ETH_ALEN); 774c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 775c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller /* llc layer */ 776c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header)); 7776177eaea277527e48753d050723cd138494c98a8Eliad Peller tmpl.llc_type = cpu_to_be16(ETH_P_ARP); 778c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 779c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller /* arp header */ 780c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller arp_hdr = &tmpl.arp_hdr; 7816177eaea277527e48753d050723cd138494c98a8Eliad Peller arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER); 7826177eaea277527e48753d050723cd138494c98a8Eliad Peller arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP); 783c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller arp_hdr->ar_hln = ETH_ALEN; 784c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller arp_hdr->ar_pln = 4; 7856177eaea277527e48753d050723cd138494c98a8Eliad Peller arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); 786c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 787c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller /* arp payload */ 788c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); 789c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller tmpl.sender_ip = ip_addr; 790c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 791c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, 792c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller &tmpl, sizeof(tmpl), 0, 793c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller wl->basic_rate); 794c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 795c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller return ret; 796c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller} 797c5312772156bb5f9b2e95e4c91526d578426a069Eliad Peller 798023e082609ba3225dbd5c33933a90156d2201d7fKalle Valoint wl1271_build_qos_null_data(struct wl1271 *wl) 799023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo{ 800023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo struct ieee80211_qos_hdr template; 801023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 802023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memset(&template, 0, sizeof(template)); 803023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 804023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memcpy(template.addr1, wl->bssid, ETH_ALEN); 805023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memcpy(template.addr2, wl->mac_addr, ETH_ALEN); 806023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memcpy(template.addr3, wl->bssid, ETH_ALEN); 807023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 808023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 809023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo IEEE80211_STYPE_QOS_NULLFUNC | 810023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo IEEE80211_FCTL_TODS); 811023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 812023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo /* FIXME: not sure what priority to use here */ 813023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo template.qos_ctrl = cpu_to_le16(0); 814023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 815023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, 816606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen sizeof(template), 0, 8178eab7b4708b5ef4701ecbe5d659f99743b77b668Juuso Oikarinen wl->basic_rate); 818023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo} 819023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 82098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) 821f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 82298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_set_sta_keys *cmd; 823f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 824f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 825f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); 826f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 827f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 828f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 829f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 830f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 831f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 832f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 833f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->id = id; 834d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->key_action = cpu_to_le16(KEY_SET_ID); 835f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_type = KEY_WEP; 836f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 837fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 838f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 839f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("cmd set_default_wep_key failed: %d", ret); 840f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 841f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 842f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 843f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 844f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 845f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 846f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 847f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 848f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 84998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id) 85098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov{ 85198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_set_ap_keys *cmd; 85298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov int ret = 0; 85398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 85498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id); 85598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 85698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 85798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (!cmd) { 85898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = -ENOMEM; 85998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 86098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 86198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 86298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->hlid = WL1271_AP_BROADCAST_HLID; 86398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->key_id = id; 86498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; 86598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->key_action = cpu_to_le16(KEY_SET_ID); 86698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->key_type = KEY_WEP; 86798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 86898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 86998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (ret < 0) { 87098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret); 87198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 87298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 87398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 87498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout: 87598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov kfree(cmd); 87698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 87798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov return ret; 87898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov} 87998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 88098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 881ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen u8 key_size, const u8 *key, const u8 *addr, 882ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen u32 tx_seq_32, u16 tx_seq_16) 883f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 88498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_set_sta_keys *cmd; 885f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 886f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 887f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 888f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 889f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 890f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 891f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 892f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 893f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (key_type != KEY_WEP) 894f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->addr, addr, ETH_ALEN); 895f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 896d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->key_action = cpu_to_le16(action); 897f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_size = key_size; 898f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_type = key_type; 899f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 900d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); 901d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); 902ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen 903f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* we have only one SSID profile */ 904f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->ssid_profile = 0; 905f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 906f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->id = id; 907f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 908f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (key_type == KEY_TKIP) { 909f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* 910f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * We get the key in the following form: 911f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) 912f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * but the target is expecting: 913f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * TKIP - RX MIC - TX MIC 914f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 915f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key, key, 16); 916f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key + 16, key + 24, 8); 917f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key + 24, key + 16, 8); 918f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 919f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } else { 920f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key, key, key_size); 921f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 922f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 923f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd)); 924f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 925fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 926f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 927f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("could not set keys"); 928152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen goto out; 929f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 930f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 931f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 932f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 933f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 934f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 935f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 93625a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 93798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 93898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, 93998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov u16 tx_seq_16) 94098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov{ 94198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_set_ap_keys *cmd; 94298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov int ret = 0; 94398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov u8 lid_type; 94498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 94598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 94698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (!cmd) 94798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov return -ENOMEM; 94898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 94998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (hlid == WL1271_AP_BROADCAST_HLID) { 95098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (key_type == KEY_WEP) 95198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov lid_type = WEP_DEFAULT_LID_TYPE; 95298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov else 95398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov lid_type = BROADCAST_LID_TYPE; 95498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } else { 95598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov lid_type = UNICAST_LID_TYPE; 95698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 95798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 95898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d" 95998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov " hlid: %d", (int)action, (int)id, (int)lid_type, 96098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov (int)key_type, (int)hlid); 96198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 96298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->lid_key_type = lid_type; 96398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->hlid = hlid; 96498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->key_action = cpu_to_le16(action); 96598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->key_size = key_size; 96698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->key_type = key_type; 96798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->key_id = id; 96898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); 96998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); 97098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 97198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (key_type == KEY_TKIP) { 97298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov /* 97398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * We get the key in the following form: 97498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) 97598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * but the target is expecting: 97698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * TKIP - RX MIC - TX MIC 97798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov */ 97898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov memcpy(cmd->key, key, 16); 97998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov memcpy(cmd->key + 16, key + 24, 8); 98098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov memcpy(cmd->key + 24, key + 16, 8); 98198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } else { 98298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov memcpy(cmd->key, key, key_size); 98398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 98498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 98598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_dump(DEBUG_CRYPT, "TARGET AP KEY: ", cmd, sizeof(*cmd)); 98698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 98798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 98898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (ret < 0) { 98998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_warning("could not set ap keys"); 99098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 99198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 99298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 99398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout: 99498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov kfree(cmd); 99598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov return ret; 99698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov} 99798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 99825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoint wl1271_cmd_disconnect(struct wl1271 *wl) 99925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho{ 100025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho struct wl1271_cmd_disconnect *cmd; 100125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho int ret = 0; 100225a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 100325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd disconnect"); 100425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 100525a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 100625a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho if (!cmd) { 100725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho ret = -ENOMEM; 100825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho goto out; 100925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho } 101025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 1011d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->rx_config_options = cpu_to_le32(wl->rx_config); 1012d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->rx_filter_options = cpu_to_le32(wl->rx_filter); 101325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho /* disconnect reason is not used in immediate disconnections */ 101425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho cmd->type = DISCONNECT_IMMEDIATE; 101525a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 1016fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0); 101725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho if (ret < 0) { 101825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho wl1271_error("failed to send disconnect command"); 101925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho goto out_free; 102025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho } 102125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 10222f826f55404ca43efced94d548356182820e764fLuciano Coelho ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); 10232f826f55404ca43efced94d548356182820e764fLuciano Coelho if (ret < 0) 10242f826f55404ca43efced94d548356182820e764fLuciano Coelho wl1271_error("cmd disconnect event completion error"); 10252f826f55404ca43efced94d548356182820e764fLuciano Coelho 102625a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoout_free: 102725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho kfree(cmd); 102825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 102925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoout: 103025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho return ret; 103125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho} 1032be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen 1033be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinenint wl1271_cmd_set_sta_state(struct wl1271 *wl) 1034be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen{ 1035be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen struct wl1271_cmd_set_sta_state *cmd; 1036be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen int ret = 0; 1037be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen 1038be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen wl1271_debug(DEBUG_CMD, "cmd set sta state"); 1039be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen 1040be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 1041be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen if (!cmd) { 1042be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen ret = -ENOMEM; 1043be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen goto out; 1044be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen } 1045be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen 1046be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen cmd->state = WL1271_CMD_STA_STATE_CONNECTED; 1047be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen 1048be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0); 1049be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen if (ret < 0) { 1050be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen wl1271_error("failed to send set STA state command"); 1051be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen goto out_free; 1052be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen } 1053be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen 1054be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinenout_free: 1055be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen kfree(cmd); 1056be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen 1057be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinenout: 1058be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen return ret; 1059be86cbea1e9c3a4dd8faedcfa327495d09fe3531Juuso Oikarinen} 106098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 106198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_start_bss(struct wl1271 *wl) 106298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov{ 106398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_bss_start *cmd; 106498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; 106598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov int ret; 106698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 106798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_debug(DEBUG_CMD, "cmd start bss"); 106898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 106998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov /* 107098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * FIXME: We currently do not support hidden SSID. The real SSID 107198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * should be fetched from mac80211 first. 107298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov */ 107398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (wl->ssid_len == 0) { 107498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_warning("Hidden SSID currently not supported for AP"); 107598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = -EINVAL; 107698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 107798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 107898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 107998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 108098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (!cmd) { 108198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = -ENOMEM; 108298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 108398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 108498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 108598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); 108698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 108725eaea30cd7b009ba2ca693708330d2f395cbc4dLuciano Coelho cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); 108898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->bss_index = WL1271_AP_BSS_INDEX; 108998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->global_hlid = WL1271_AP_GLOBAL_HLID; 109098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; 109198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set); 109298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->beacon_interval = cpu_to_le16(wl->beacon_int); 109398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->dtim_interval = bss_conf->dtim_period; 109498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP; 109598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->channel = wl->channel; 109698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->ssid_len = wl->ssid_len; 109798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->ssid_type = SSID_TYPE_PUBLIC; 109898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov memcpy(cmd->ssid, wl->ssid, wl->ssid_len); 109998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 110098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov switch (wl->band) { 110198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov case IEEE80211_BAND_2GHZ: 110298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->band = RADIO_BAND_2_4GHZ; 110398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov break; 110498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov case IEEE80211_BAND_5GHZ: 110598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->band = RADIO_BAND_5GHZ; 110698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov break; 110798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov default: 110898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_warning("bss start - unknown band: %d", (int)wl->band); 110998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->band = RADIO_BAND_2_4GHZ; 111098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov break; 111198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 111298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 111398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0); 111498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (ret < 0) { 111598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_error("failed to initiate cmd start bss"); 111698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out_free; 111798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 111898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 111998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout_free: 112098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov kfree(cmd); 112198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 112298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout: 112398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov return ret; 112498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov} 112598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 112698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_stop_bss(struct wl1271 *wl) 112798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov{ 112898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_bss_start *cmd; 112998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov int ret; 113098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 113198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_debug(DEBUG_CMD, "cmd stop bss"); 113298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 113398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 113498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (!cmd) { 113598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = -ENOMEM; 113698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 113798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 113898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 113998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->bss_index = WL1271_AP_BSS_INDEX; 114098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 114198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0); 114298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (ret < 0) { 114398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_error("failed to initiate cmd stop bss"); 114498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out_free; 114598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 114698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 114798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout_free: 114898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov kfree(cmd); 114998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 115098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout: 115198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov return ret; 115298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov} 115398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 115498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) 115598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov{ 115698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_add_sta *cmd; 115798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov int ret; 115898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 115998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid); 116098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 116198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 116298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (!cmd) { 116398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = -ENOMEM; 116498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 116598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 116698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 116798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov /* currently we don't support UAPSD */ 116898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->sp_len = 0; 116998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 117098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov memcpy(cmd->addr, sta->addr, ETH_ALEN); 117198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->bss_index = WL1271_AP_BSS_INDEX; 117298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->aid = sta->aid; 117398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->hlid = hlid; 117498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 117598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov /* 117698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * FIXME: Does STA support QOS? We need to propagate this info from 117798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * hostapd. Currently not that important since this is only used for 117898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * sending the correct flavor of null-data packet in response to a 117998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov * trigger. 118098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov */ 118198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->wmm = 0; 118298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 118398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, 118498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov sta->supp_rates[wl->band])); 118598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 118698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates); 118798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 118898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0); 118998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (ret < 0) { 119098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_error("failed to initiate cmd add sta"); 119198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out_free; 119298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 119398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 119498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout_free: 119598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov kfree(cmd); 119698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 119798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout: 119898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov return ret; 119998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov} 120098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 120198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovint wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) 120298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov{ 120398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov struct wl1271_cmd_remove_sta *cmd; 120498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov int ret; 120598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 120698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid); 120798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 120898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 120998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (!cmd) { 121098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = -ENOMEM; 121198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out; 121298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 121398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 121498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->hlid = hlid; 121598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov /* We never send a deauth, mac80211 is in charge of this */ 121698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->reason_opcode = 0; 121798bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov cmd->send_deauth_flag = 0; 121898bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 121998bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0); 122098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov if (ret < 0) { 122198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov wl1271_error("failed to initiate cmd remove sta"); 122298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov goto out_free; 122398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov } 122498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 122505285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov /* 122605285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov * We are ok with a timeout here. The event is sometimes not sent 122705285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov * due to a firmware bug. 122805285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov */ 122905285cf9b581af05813cfaa60e23227b009b7754Arik Nemtsov wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID); 123098bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 123198bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout_free: 123298bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov kfree(cmd); 123398bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov 123498bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsovout: 123598bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov return ret; 123698bdaabbbced007c7eb89cd373f9cb1640635b46Arik Nemtsov} 123795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 123895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivint wl12xx_cmd_config_fwlog(struct wl1271 *wl) 123995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv{ 124095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv struct wl12xx_cmd_config_fwlog *cmd; 124195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv int ret = 0; 124295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 124395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv wl1271_debug(DEBUG_CMD, "cmd config firmware logger"); 124495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 124595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 124695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv if (!cmd) { 124795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv ret = -ENOMEM; 124895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv goto out; 124995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv } 125095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 125195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd->logger_mode = wl->conf.fwlog.mode; 125295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd->log_severity = wl->conf.fwlog.severity; 125395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd->timestamp = wl->conf.fwlog.timestamp; 125495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd->output = wl->conf.fwlog.output; 125595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd->threshold = wl->conf.fwlog.threshold; 125695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 125795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0); 125895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv if (ret < 0) { 125995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv wl1271_error("failed to send config firmware logger command"); 126095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv goto out_free; 126195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv } 126295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 126395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivout_free: 126495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv kfree(cmd); 126595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 126695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivout: 126795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv return ret; 126895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv} 126995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 127095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivint wl12xx_cmd_start_fwlog(struct wl1271 *wl) 127195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv{ 127295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv struct wl12xx_cmd_start_fwlog *cmd; 127395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv int ret = 0; 127495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 127595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv wl1271_debug(DEBUG_CMD, "cmd start firmware logger"); 127695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 127795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 127895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv if (!cmd) { 127995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv ret = -ENOMEM; 128095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv goto out; 128195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv } 128295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 128395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0); 128495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv if (ret < 0) { 128595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv wl1271_error("failed to send start firmware logger command"); 128695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv goto out_free; 128795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv } 128895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 128995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivout_free: 129095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv kfree(cmd); 129195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 129295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivout: 129395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv return ret; 129495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv} 129595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 129695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivint wl12xx_cmd_stop_fwlog(struct wl1271 *wl) 129795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv{ 129895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv struct wl12xx_cmd_stop_fwlog *cmd; 129995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv int ret = 0; 130095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 130195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv wl1271_debug(DEBUG_CMD, "cmd stop firmware logger"); 130295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 130395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 130495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv if (!cmd) { 130595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv ret = -ENOMEM; 130695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv goto out; 130795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv } 130895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 130995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0); 131095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv if (ret < 0) { 131195dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv wl1271_error("failed to send stop firmware logger command"); 131295dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv goto out_free; 131395dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv } 131495dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 131595dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivout_free: 131695dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv kfree(cmd); 131795dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv 131895dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yarivout: 131995dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv return ret; 132095dac04f881322b510c45e5ae83f0dbee4f823a2Ido Yariv} 1321