cmd.c revision 899e6e65c39990a76c17940625dbe6001f618734
1f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/* 2f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * This file is part of wl1271 3f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 4f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * Copyright (C) 2009 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/crc7.h> 27f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/spi/spi.h> 28f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/etherdevice.h> 29f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 30f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271.h" 31f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271_reg.h" 327b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi#include "wl1271_io.h" 33f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271_acx.h" 34f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl12xx_80211.h" 35f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271_cmd.h" 36f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 37f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/* 38f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * send command to firmware 39f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 40f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 41f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: command id 42f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing the command, must work with dma 43f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of the buffer 44f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 45fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinenint wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, 46fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen size_t res_len) 47f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 48f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_header *cmd; 49f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho unsigned long timeout; 50f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u32 intr; 51f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 52ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen u16 status; 53f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 54f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = buf; 55d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->id = cpu_to_le16(id); 56f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->status = 0; 57f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 58f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(len % 4 != 0); 59f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 607b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write(wl, wl->cmd_box_addr, buf, len, false); 61f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 627b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); 63f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 64f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); 65f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 667b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 67f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { 68f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (time_after(jiffies, timeout)) { 69f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("command complete timeout"); 70f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ETIMEDOUT; 71f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 72f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 73f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 74f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho msleep(1); 75f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 767b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 77f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 78f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 793b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen /* read back the status code of the command */ 80fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (res_len == 0) 81fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen res_len = sizeof(struct wl1271_cmd_header); 827b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); 833b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen 84ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen status = le16_to_cpu(cmd->status); 85ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen if (status != CMD_STATUS_SUCCESS) { 86ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen wl1271_error("command execute failure %d", status); 873b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen ret = -EIO; 883b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen } 893b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen 907b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, 917b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi WL1271_ACX_INTR_CMD_COMPLETE); 92f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 93f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 94f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 95f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 96f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 97938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal_channel_tune(struct wl1271 *wl) 98f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 99f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_cal_channel_tune *cmd; 100f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 101f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 102f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 103f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) 104f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 105f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 106f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->test.id = TEST_CMD_CHANNEL_TUNE; 107f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 108f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->band = WL1271_CHANNEL_TUNE_BAND_2_4; 109f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* set up any channel, 7 is in the middle of the range */ 110f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->channel = 7; 111f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 112f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); 113f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 114f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST_CMD_CHANNEL_TUNE failed"); 115f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 116f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 117f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 118f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 119f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 120938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl) 121f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 122f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_cal_update_ref_point *cmd; 123f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 124f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 125f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 126f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) 127f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 128f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 129f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT; 130f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 131f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* FIXME: still waiting for the correct values */ 132f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->ref_power = 0; 133f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->ref_detector = 0; 134f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 135f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->sub_band = WL1271_PD_REFERENCE_POINT_BAND_B_G; 136f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 137f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); 138f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 139f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed"); 140f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 141f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 142f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 143f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 144f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 145938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal_p2g(struct wl1271 *wl) 146f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 147f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_cal_p2g *cmd; 148f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 149f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 150f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 151f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) 152f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 153f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 154f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->test.id = TEST_CMD_P2G_CAL; 155f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 156f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->sub_band_mask = WL1271_CAL_P2G_BAND_B_G; 157f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 158f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); 159f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 160f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST_CMD_P2G_CAL failed"); 161f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 162f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 163f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 164f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 165f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 166938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal(struct wl1271 *wl) 167f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 168f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* 169f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * FIXME: we must make sure that we're not sleeping when calibration 170f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * is done 171f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 172f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 173f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 174f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_notice("performing tx calibration"); 175f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 176f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal_channel_tune(wl); 177f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 178f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 179f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 180f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal_update_ref_point(wl); 181f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 182f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 183f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 184f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal_p2g(wl); 185f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 186f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 187f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 188f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 189f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 190f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 19198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelhoint wl1271_cmd_general_parms(struct wl1271 *wl) 19298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho{ 19398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho struct wl1271_general_parms_cmd *gen_parms; 19498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho int ret; 19598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 196152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen if (!wl->nvs) 197152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen return -ENODEV; 198152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 19998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 20098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (!gen_parms) 20198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return -ENOMEM; 20298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 20398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; 20498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 205152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen memcpy(gen_parms->params, wl->nvs->general_params, 206152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen WL1271_NVS_GENERAL_PARAMS_SIZE); 20776c0f8d396bd306111d349cfe770e1c4fcf70248Luciano Coelho 20898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); 20998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (ret < 0) 21098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); 21198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 21298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho kfree(gen_parms); 21398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return ret; 21498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho} 21598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 21698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelhoint wl1271_cmd_radio_parms(struct wl1271 *wl) 21798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho{ 21898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho struct wl1271_radio_parms_cmd *radio_parms; 219152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen struct conf_radio_parms *rparam = &wl->conf.init.radioparam; 220152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen int ret; 221152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 222152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen if (!wl->nvs) 223152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen return -ENODEV; 22498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 22598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); 22698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (!radio_parms) 22798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return -ENOMEM; 22898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 22998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; 23098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 231152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params, 232152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen WL1271_NVS_STAT_RADIO_PARAMS_SIZE); 233152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen memcpy(radio_parms->dyn_radio_params, 234152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen wl->nvs->dyn_radio_params[rparam->fem], 235152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen WL1271_NVS_DYN_RADIO_PARAMS_SIZE); 236152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 237152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen /* FIXME: current NVS is missing 5GHz parameters */ 23898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 23998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", 24098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms, sizeof(*radio_parms)); 24198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 24298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); 24398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (ret < 0) 24498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); 24598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 24698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho kfree(radio_parms); 24798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return ret; 24898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho} 24998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 25015305498a443c181c8fb5deafb94eae585fe3ad5Juuso Oikarinenint wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) 251f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 252f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho static bool do_cal = true; 253f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_join *join; 254f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret, i; 255f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u8 *bssid; 256f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 257f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* FIXME: remove when we get calibration from the factory */ 258f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (do_cal) { 259f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal(wl); 260f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 261f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("couldn't calibrate"); 262f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho else 263f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho do_cal = false; 264f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 265f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 266f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join = kzalloc(sizeof(*join), GFP_KERNEL); 267f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!join) { 268f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 269f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 270f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 271f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 272f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd join"); 273f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 274f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* Reverse order BSSID */ 275f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho bssid = (u8 *) &join->bssid_lsb; 276f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho for (i = 0; i < ETH_ALEN; i++) 277f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho bssid[i] = wl->bssid[ETH_ALEN - i - 1]; 278f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 279d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_config_options = cpu_to_le32(wl->rx_config); 280d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_filter_options = cpu_to_le32(wl->rx_filter); 28115305498a443c181c8fb5deafb94eae585fe3ad5Juuso Oikarinen join->bss_type = bss_type; 282f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 28364a7f67287c75f5bb28018a6ff2750a59ee1195aLuciano Coelho /* 28464a7f67287c75f5bb28018a6ff2750a59ee1195aLuciano Coelho * FIXME: disable temporarily all filters because after commit 28564a7f67287c75f5bb28018a6ff2750a59ee1195aLuciano Coelho * 9cef8737 "mac80211: fix managed mode BSSID handling" broke 28664a7f67287c75f5bb28018a6ff2750a59ee1195aLuciano Coelho * association. The filter logic needs to be implemented properly 28764a7f67287c75f5bb28018a6ff2750a59ee1195aLuciano Coelho * and once that is done, this hack can be removed. 28864a7f67287c75f5bb28018a6ff2750a59ee1195aLuciano Coelho */ 289d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_config_options = cpu_to_le32(0); 290d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_filter_options = cpu_to_le32(WL1271_DEFAULT_RX_FILTER); 29164a7f67287c75f5bb28018a6ff2750a59ee1195aLuciano Coelho 292a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi if (wl->band == IEEE80211_BAND_2GHZ) 293d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | 294d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho CONF_HW_BIT_RATE_2MBPS | 295d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho CONF_HW_BIT_RATE_5_5MBPS | 296d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho CONF_HW_BIT_RATE_11MBPS); 297a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi else { 298a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; 299d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS | 300d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho CONF_HW_BIT_RATE_12MBPS | 301d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho CONF_HW_BIT_RATE_24MBPS); 302a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi } 303f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 304d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT); 305ae751bab9f55c3152ebf713c89a4fb6f439c2575Luciano Coelho join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; 306a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi 307f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->channel = wl->channel; 308f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ssid_len = wl->ssid_len; 309f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(join->ssid, wl->ssid, wl->ssid_len); 310f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH; 311f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 312f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* increment the session counter */ 313f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl->session_counter++; 314f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (wl->session_counter >= SESSION_COUNTER_MAX) 315f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl->session_counter = 0; 316f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 317f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; 318f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 319ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen /* reset TX security counters */ 320ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen wl->tx_security_last_seq = 0; 32104e36fc5f1ff4e349ea21de8d15e4e1844d04197Juuso Oikarinen wl->tx_security_seq = 0; 322f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 323fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); 324f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 325f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("failed to initiate cmd join"); 326f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out_free; 327f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 328f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 329f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* 330f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to 331f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * simplify locking we just sleep instead, for now 332f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 333d94cd297e58b55bb272fdfd51ff0de7acbc1941bJuuso Oikarinen msleep(10); 334f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 335f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout_free: 336f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(join); 337f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 338f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 339f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 340f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 341f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 342f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 343f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * send test command to firmware 344f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 345f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 346f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing the command, with all headers, must work with dma 347f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of the buffer 348f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @answer: is answer needed 349f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 350f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) 351f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 352f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 353fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen size_t res_len = 0; 354f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 355f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd test"); 356f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 357fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (answer) 358fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen res_len = buf_len; 359fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen 360fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len, res_len); 361f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 362f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 363f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST command failed"); 364f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 365f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 366f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 367fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen return ret; 368f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 369f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 370f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 371f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * read acx from firmware 372f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 373f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 374f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: acx id 375f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer for the response, including all headers, must work with dma 376f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: lenght of buf 377f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 378f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) 379f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 380f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct acx_header *acx = buf; 381f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 382f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 383f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd interrogate"); 384f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 385d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->id = cpu_to_le16(id); 386f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 387f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* payload length, does not include any headers */ 388d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->len = cpu_to_le16(len - sizeof(*acx)); 389f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 390fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); 391fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (ret < 0) 392f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("INTERROGATE command failed"); 393f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 394f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 395f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 396f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 397f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 398f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * write acx value to firmware 399f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 400f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 401f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: acx id 402f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing acx, including all headers, must work with dma 403f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of buf 404f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 405f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) 406f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 407f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct acx_header *acx = buf; 408f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 409f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 410f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd configure"); 411f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 412d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->id = cpu_to_le16(id); 413f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 414f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* payload length, does not include any headers */ 415d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->len = cpu_to_le16(len - sizeof(*acx)); 416f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 417fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0); 418f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 419f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("CONFIGURE command NOK"); 420f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 421f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 422f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 423f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return 0; 424f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 425f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 42694210897e2b7df8446fdecd360342149e5b4a400Luciano Coelhoint wl1271_cmd_data_path(struct wl1271 *wl, bool enable) 427f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 428f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct cmd_enabledisable_path *cmd; 429f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 430f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u16 cmd_rx, cmd_tx; 431f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 432f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd data path"); 433f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 434f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 435f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 436f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 437f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 438f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 439f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 44094210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho /* the channel here is only used for calibration, so hardcoded to 1 */ 44194210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho cmd->channel = 1; 442f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 443f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (enable) { 444f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_rx = CMD_ENABLE_RX; 445f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_tx = CMD_ENABLE_TX; 446f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } else { 447f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_rx = CMD_DISABLE_RX; 448f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_tx = CMD_DISABLE_TX; 449f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 450f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 451fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); 452f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 453f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("rx %s cmd for channel %d failed", 45494210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 455f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 456f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 457f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 458f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", 45994210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 460f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 461fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); 462f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 463f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("tx %s cmd for channel %d failed", 46494210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 465f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 466f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 467f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 468f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", 46994210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 470f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 471f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 472f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 473f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 474f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 475f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 476d8c42c0c282a5edd9ea2eef4c929d9cec2798653Juuso Oikarinenint wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) 477f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 478f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_ps_params *ps_params = NULL; 479f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 480f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 481f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* FIXME: this should be in ps.c */ 48251f2be24328957f9e2acf116b1b1d2dfd10bf41fJuuso Oikarinen ret = wl1271_acx_wake_up_conditions(wl); 483f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 484f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("couldn't set wake up conditions"); 485f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 486f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 487f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 488f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd set ps mode"); 489f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 490f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); 491f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!ps_params) { 492f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 493f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 494f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 495f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 496f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params->ps_mode = ps_mode; 497d8c42c0c282a5edd9ea2eef4c929d9cec2798653Juuso Oikarinen ps_params->send_null_data = send; 498f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params->retries = 5; 499f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params->hang_over_period = 128; 500d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ 501f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 502f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, 503fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen sizeof(*ps_params), 0); 504f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 505f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("cmd set_ps_mode failed"); 506f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 507f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 508f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 509f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 510f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(ps_params); 511f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 512f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 513f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 514f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, 515f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho size_t len) 516f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 517f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct cmd_read_write_memory *cmd; 518f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 519f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 520f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd read memory"); 521f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 522f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 523f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 524f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 525f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 526f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 527f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 528f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(len > MAX_READ_SIZE); 529f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho len = min_t(size_t, len, MAX_READ_SIZE); 530f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 531d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->addr = cpu_to_le32(addr); 532d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->size = cpu_to_le32(len); 533f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 534fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd), 535fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen sizeof(*cmd)); 536f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 537f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("read memory command failed: %d", ret); 538f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 539f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 540f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 541fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen /* the read command got in */ 542f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(answer, cmd->value, len); 543f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 544f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 545f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 546f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 547f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 548f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 549f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, 550abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi u8 active_scan, u8 high_prio, u8 band, 551f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u8 probe_requests) 552f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 553f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 554f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_trigger_scan_to *trigger = NULL; 555f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_scan *params = NULL; 556311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi struct ieee80211_channel *channels; 557311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi int i, j, n_ch, ret; 558f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u16 scan_options = 0; 559abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi u8 ieee_band; 560abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi 561abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == WL1271_SCAN_BAND_2_4_GHZ) 562abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ieee_band = IEEE80211_BAND_2GHZ; 563abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) 564abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ieee_band = IEEE80211_BAND_2GHZ; 565abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) 566abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ieee_band = IEEE80211_BAND_5GHZ; 567abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else 568abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi return -EINVAL; 569f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 570abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) 571f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -EINVAL; 572f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 573abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi channels = wl->hw->wiphy->bands[ieee_band]->channels; 574abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; 575abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi 57671449f8d7059b69e6e45063997d225d8202221a2Juuso Oikarinen if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) 577abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi return -EINVAL; 578311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi 579f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params = kzalloc(sizeof(*params), GFP_KERNEL); 580f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!params) 581f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 582f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 583f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); 584f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.rx_filter_options = 585f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); 586f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 587f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!active_scan) 588f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho scan_options |= WL1271_SCAN_OPT_PASSIVE; 589f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (high_prio) 590f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; 591d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho params->params.scan_options = cpu_to_le16(scan_options); 592f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 593f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.num_probe_requests = probe_requests; 594abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi /* Let the fw autodetect suitable tx_rate for probes */ 595abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi params->params.tx_rate = 0; 596f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.tid_trigger = 0; 597f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; 598f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 599abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == WL1271_SCAN_BAND_DUAL) 600abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi params->params.band = WL1271_SCAN_BAND_2_4_GHZ; 601abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else 602abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi params->params.band = band; 603abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi 604311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) { 605311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) { 606311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].min_duration = 607311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); 608311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].max_duration = 609311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); 610311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi memset(¶ms->channels[j].bssid_lsb, 0xff, 4); 611311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi memset(¶ms->channels[j].bssid_msb, 0xff, 2); 612311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].early_termination = 0; 613311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].tx_power_att = 614311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi WL1271_SCAN_CURRENT_TX_PWR; 615311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].channel = channels[i].hw_value; 616311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi j++; 617311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi } 618f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 619f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 620311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->params.num_channels = j; 621311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi 622f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (len && ssid) { 623f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.ssid_len = len; 624f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(params->params.ssid, ssid, len); 625f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 626f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 627abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band); 628f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 629f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("PROBE request template failed"); 630f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 631f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 632f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 633f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); 634f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!trigger) { 635f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 636f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 637f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 638f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 639f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* disable the timeout */ 640f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho trigger->timeout = 0; 641f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 642f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, 643fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen sizeof(*trigger), 0); 644f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 645f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("trigger scan to failed for hw scan"); 646f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 647f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 648f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 649f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); 650f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 65171449f8d7059b69e6e45063997d225d8202221a2Juuso Oikarinen set_bit(WL1271_FLAG_SCANNING, &wl->flags); 652abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (wl1271_11a_enabled()) { 653abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.state = band; 654abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == WL1271_SCAN_BAND_DUAL) { 655abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.active = active_scan; 656abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.high_prio = high_prio; 657abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.probe_requests = probe_requests; 658abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (len && ssid) { 659abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.ssid_len = len; 660abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi memcpy(wl->scan.ssid, ssid, len); 661abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } else 662abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.ssid_len = 0; 663abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } 664abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } 665f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 666fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); 667f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 668f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("SCAN failed"); 66971449f8d7059b69e6e45063997d225d8202221a2Juuso Oikarinen clear_bit(WL1271_FLAG_SCANNING, &wl->flags); 670f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 671f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 672f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 673f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 674f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(params); 675f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 676f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 677f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 678f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, 679f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho void *buf, size_t buf_len) 680f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 681f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_template_set *cmd; 682f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 683f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 684f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id); 685f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 686f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); 687f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); 688f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 689f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 690f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 691f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 692f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 693f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 694f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 695f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->len = cpu_to_le16(buf_len); 696f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->template_type = template_id; 697d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); 69845b531a86f93c82d8e390e19a6258111b3627bb0Juuso Oikarinen cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; 69945b531a86f93c82d8e390e19a6258111b3627bb0Juuso Oikarinen cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; 700f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 701f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (buf) 702f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->template_data, buf, buf_len); 703f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 704fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd), 0); 705f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 706f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("cmd set_template failed: %d", ret); 707f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out_free; 708f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 709f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 710f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout_free: 711f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 712f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 713f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 714f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 715f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 716f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 717befabac2d8e4925b97c5eebc78ecc4b2079fd9ddDan Carpenterstatic int wl1271_build_basic_rates(u8 *rates, u8 band) 718f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 719f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u8 index = 0; 720f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 721abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == IEEE80211_BAND_2GHZ) { 722abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 723abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; 724abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 725abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; 726abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 727abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; 728abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 729abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; 730abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } else if (band == IEEE80211_BAND_5GHZ) { 731abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 732abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; 733abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 734abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; 735abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 736abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; 737abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } else { 738abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl1271_error("build_basic_rates invalid band: %d", band); 739abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } 740f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 741f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return index; 742f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 743f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 744befabac2d8e4925b97c5eebc78ecc4b2079fd9ddDan Carpenterstatic int wl1271_build_extended_rates(u8 *rates, u8 band) 745f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 746f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u8 index = 0; 747f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 748abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == IEEE80211_BAND_2GHZ) { 749abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_6MB; 750abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_9MB; 751abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_12MB; 752abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_18MB; 753abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_24MB; 754abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_36MB; 755abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_48MB; 756abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = IEEE80211_OFDM_RATE_54MB; 757abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } else if (band == IEEE80211_BAND_5GHZ) { 758abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 759abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; 760abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 761abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; 762abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 763abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; 764abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 765abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; 766abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 767abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; 768abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates[index++] = 769abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; 770abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } else { 771abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl1271_error("build_basic_rates invalid band: %d", band); 772abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } 773f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 774f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return index; 775f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 776f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 777f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_build_null_data(struct wl1271 *wl) 778f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 779899e6e65c39990a76c17940625dbe6001f618734Kalle Valo struct sk_buff *skb; 780899e6e65c39990a76c17940625dbe6001f618734Kalle Valo int ret = 0; 781f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 782899e6e65c39990a76c17940625dbe6001f618734Kalle Valo skb = ieee80211_nullfunc_get(wl->hw, wl->vif); 783899e6e65c39990a76c17940625dbe6001f618734Kalle Valo if (!skb) 784899e6e65c39990a76c17940625dbe6001f618734Kalle Valo goto out; 785f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 786899e6e65c39990a76c17940625dbe6001f618734Kalle Valo ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, skb->data, 787899e6e65c39990a76c17940625dbe6001f618734Kalle Valo skb->len); 788f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 789899e6e65c39990a76c17940625dbe6001f618734Kalle Valoout: 790899e6e65c39990a76c17940625dbe6001f618734Kalle Valo dev_kfree_skb(skb); 791899e6e65c39990a76c17940625dbe6001f618734Kalle Valo return ret; 792f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 793f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 794f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 795f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) 796f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 797899e6e65c39990a76c17940625dbe6001f618734Kalle Valo struct sk_buff *skb; 798899e6e65c39990a76c17940625dbe6001f618734Kalle Valo int ret = 0; 799c3fea1994ac34dafa3ebb40d4f95354b2782af31Juuso Oikarinen 800899e6e65c39990a76c17940625dbe6001f618734Kalle Valo skb = ieee80211_pspoll_get(wl->hw, wl->vif); 801899e6e65c39990a76c17940625dbe6001f618734Kalle Valo if (!skb) 802899e6e65c39990a76c17940625dbe6001f618734Kalle Valo goto out; 803f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 804899e6e65c39990a76c17940625dbe6001f618734Kalle Valo ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, 805899e6e65c39990a76c17940625dbe6001f618734Kalle Valo skb->len); 806f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 807899e6e65c39990a76c17940625dbe6001f618734Kalle Valoout: 808899e6e65c39990a76c17940625dbe6001f618734Kalle Valo dev_kfree_skb(skb); 809899e6e65c39990a76c17940625dbe6001f618734Kalle Valo return ret; 810f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 811f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 812abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikiviint wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, 813abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi u8 band) 814f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 815f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl12xx_probe_req_template template; 816f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl12xx_ie_rates *rates; 817f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho char *ptr; 818f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u16 size; 819abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi int ret; 820f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 821f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ptr = (char *)&template; 822f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho size = sizeof(struct ieee80211_header); 823f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 824f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memset(template.header.da, 0xff, ETH_ALEN); 825f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memset(template.header.bssid, 0xff, ETH_ALEN); 826f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); 827f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); 828f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 829f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* IEs */ 830f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* SSID */ 831f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho template.ssid.header.id = WLAN_EID_SSID; 832f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho template.ssid.header.len = ssid_len; 833f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ssid_len && ssid) 834f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(template.ssid.ssid, ssid, ssid_len); 835f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho size += sizeof(struct wl12xx_ie_header) + ssid_len; 836f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ptr += size; 837f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 838f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* Basic Rates */ 839f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho rates = (struct wl12xx_ie_rates *)ptr; 840f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho rates->header.id = WLAN_EID_SUPP_RATES; 841abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates->header.len = wl1271_build_basic_rates(rates->rates, band); 842f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho size += sizeof(struct wl12xx_ie_header) + rates->header.len; 843f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; 844f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 845f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* Extended rates */ 846f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho rates = (struct wl12xx_ie_rates *)ptr; 847f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho rates->header.id = WLAN_EID_EXT_SUPP_RATES; 848abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi rates->header.len = wl1271_build_extended_rates(rates->rates, band); 849f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho size += sizeof(struct wl12xx_ie_header) + rates->header.len; 850f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 851f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); 852f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 853abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == IEEE80211_BAND_2GHZ) 854abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, 855abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi &template, size); 856abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else 857abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, 858abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi &template, size); 859abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi return ret; 860f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 861f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 862f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) 863f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 864f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_set_keys *cmd; 865f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 866f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 867f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); 868f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 869f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 870f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 871f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 872f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 873f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 874f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 875f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->id = id; 876d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->key_action = cpu_to_le16(KEY_SET_ID); 877f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_type = KEY_WEP; 878f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 879fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 880f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 881f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("cmd set_default_wep_key failed: %d", ret); 882f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 883f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 884f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 885f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 886f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 887f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 888f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 889f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 890f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 891f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 892ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen u8 key_size, const u8 *key, const u8 *addr, 893ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen u32 tx_seq_32, u16 tx_seq_16) 894f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 895f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_set_keys *cmd; 896f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 897f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 898f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 899f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 900f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 901f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 902f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 903f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 904f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (key_type != KEY_WEP) 905f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->addr, addr, ETH_ALEN); 906f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 907d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->key_action = cpu_to_le16(action); 908f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_size = key_size; 909f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_type = key_type; 910f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 911d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); 912d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); 913ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen 914f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* we have only one SSID profile */ 915f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->ssid_profile = 0; 916f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 917f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->id = id; 918f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 919f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (key_type == KEY_TKIP) { 920f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* 921f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * We get the key in the following form: 922f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) 923f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * but the target is expecting: 924f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * TKIP - RX MIC - TX MIC 925f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 926f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key, key, 16); 927f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key + 16, key + 24, 8); 928f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key + 24, key + 16, 8); 929f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 930f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } else { 931f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key, key, key_size); 932f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 933f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 934f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd)); 935f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 936fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 937f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 938f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("could not set keys"); 939152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen goto out; 940f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 941f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 942f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 943f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 944f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 945f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 946f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 94725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 94825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoint wl1271_cmd_disconnect(struct wl1271 *wl) 94925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho{ 95025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho struct wl1271_cmd_disconnect *cmd; 95125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho int ret = 0; 95225a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 95325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd disconnect"); 95425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 95525a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 95625a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho if (!cmd) { 95725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho ret = -ENOMEM; 95825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho goto out; 95925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho } 96025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 961d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->rx_config_options = cpu_to_le32(wl->rx_config); 962d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->rx_filter_options = cpu_to_le32(wl->rx_filter); 96325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho /* disconnect reason is not used in immediate disconnections */ 96425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho cmd->type = DISCONNECT_IMMEDIATE; 96525a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 966fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0); 96725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho if (ret < 0) { 96825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho wl1271_error("failed to send disconnect command"); 96925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho goto out_free; 97025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho } 97125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 97225a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoout_free: 97325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho kfree(cmd); 97425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 97525a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoout: 97625a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho return ret; 97725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho} 978