cmd.c revision 606c1487ac894798121bc2c64d27c1953c5a6210
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/crc7.h> 27f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/spi/spi.h> 28f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include <linux/etherdevice.h> 29023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo#include <linux/ieee80211.h> 30f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 31f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271.h" 32f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271_reg.h" 337b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi#include "wl1271_io.h" 34f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271_acx.h" 35f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl12xx_80211.h" 36f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho#include "wl1271_cmd.h" 3799d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho#include "wl1271_event.h" 38f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 39bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal#define WL1271_CMD_POLL_COUNT 5 40bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal 41f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/* 42f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * send command to firmware 43f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 44f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 45f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: command id 46f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing the command, must work with dma 47f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of the buffer 48f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 49fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinenint wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, 50fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen size_t res_len) 51f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 52f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_header *cmd; 53f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho unsigned long timeout; 54f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u32 intr; 55f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 56ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen u16 status; 57bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal u16 poll_count = 0; 58f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 59f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = buf; 60d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->id = cpu_to_le16(id); 61f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->status = 0; 62f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 63f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(len % 4 != 0); 64f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 657b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write(wl, wl->cmd_box_addr, buf, len, false); 66f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 677b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); 68f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 69f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); 70f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 717b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 72f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { 73f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (time_after(jiffies, timeout)) { 74f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("command complete timeout"); 75f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ETIMEDOUT; 76f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 77f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 78f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 79bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal udelay(10); 80bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal poll_count++; 81bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal if (poll_count == WL1271_CMD_POLL_COUNT) 82bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal wl1271_info("cmd polling took over %d cycles", 83bc0f03ea579d78f845a44a0c611806da64057b03Saravanan Dhanabal poll_count); 84f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 857b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 86f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 87f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 883b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen /* read back the status code of the command */ 89fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (res_len == 0) 90fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen res_len = sizeof(struct wl1271_cmd_header); 917b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); 923b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen 93ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen status = le16_to_cpu(cmd->status); 94ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen if (status != CMD_STATUS_SUCCESS) { 95ad150e966e987edcf737e1871d9e44a30d1aa58dJuuso Oikarinen wl1271_error("command execute failure %d", status); 963b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen ret = -EIO; 973b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen } 983b775b4b27818130291e7716f3ce1e24664004c9Juuso Oikarinen 997b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, 1007b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi WL1271_ACX_INTR_CMD_COMPLETE); 101f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 102f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 103f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 104f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 105f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 106938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal_channel_tune(struct wl1271 *wl) 107f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 108f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_cal_channel_tune *cmd; 109f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 110f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 111f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 112f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) 113f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 114f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 115f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->test.id = TEST_CMD_CHANNEL_TUNE; 116f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 117f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->band = WL1271_CHANNEL_TUNE_BAND_2_4; 118f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* set up any channel, 7 is in the middle of the range */ 119f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->channel = 7; 120f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 121f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); 122f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 123f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST_CMD_CHANNEL_TUNE failed"); 124f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 125f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 126f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 127f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 128f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 129938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl) 130f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 131f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_cal_update_ref_point *cmd; 132f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 133f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 134f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 135f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) 136f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 137f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 138f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT; 139f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 140f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* FIXME: still waiting for the correct values */ 141f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->ref_power = 0; 142f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->ref_detector = 0; 143f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 144f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->sub_band = WL1271_PD_REFERENCE_POINT_BAND_B_G; 145f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 146f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); 147f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 148f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed"); 149f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 150f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 151f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 152f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 153f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 154938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal_p2g(struct wl1271 *wl) 155f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 156f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_cal_p2g *cmd; 157f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 158f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 159f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 160f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) 161f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 162f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 163f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->test.id = TEST_CMD_P2G_CAL; 164f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 165f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->sub_band_mask = WL1271_CAL_P2G_BAND_B_G; 166f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 167f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); 168f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 169f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST_CMD_P2G_CAL failed"); 170f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 171f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 172f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 173f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 174f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 175938e30c9301fbd7c3677d01ad01c7eb4ad78b998Luciano Coelhostatic int wl1271_cmd_cal(struct wl1271 *wl) 176f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 177f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* 178f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * FIXME: we must make sure that we're not sleeping when calibration 179f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * is done 180f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 181f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 182f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 183f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_notice("performing tx calibration"); 184f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 185f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal_channel_tune(wl); 186f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 187f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 188f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 189f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal_update_ref_point(wl); 190f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 191f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 192f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 193f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal_p2g(wl); 194f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 195f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 196f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 197f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 198f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 199f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 20098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelhoint wl1271_cmd_general_parms(struct wl1271 *wl) 20198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho{ 20298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho struct wl1271_general_parms_cmd *gen_parms; 20398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho int ret; 20498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 205152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen if (!wl->nvs) 206152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen return -ENODEV; 207152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 20898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 20998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (!gen_parms) 21098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return -ENOMEM; 21198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 21298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; 21398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 214152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen memcpy(gen_parms->params, wl->nvs->general_params, 215152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen WL1271_NVS_GENERAL_PARAMS_SIZE); 21676c0f8d396bd306111d349cfe770e1c4fcf70248Luciano Coelho 21798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); 21898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (ret < 0) 21998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); 22098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 22198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho kfree(gen_parms); 22298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return ret; 22398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho} 22498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 22598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelhoint wl1271_cmd_radio_parms(struct wl1271 *wl) 22698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho{ 22798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho struct wl1271_radio_parms_cmd *radio_parms; 228152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen struct conf_radio_parms *rparam = &wl->conf.init.radioparam; 229152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen int ret; 230152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 231152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen if (!wl->nvs) 232152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen return -ENODEV; 23398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 23498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); 23598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (!radio_parms) 23698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return -ENOMEM; 23798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 23898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; 23998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 240152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params, 241152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen WL1271_NVS_STAT_RADIO_PARAMS_SIZE); 242152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen memcpy(radio_parms->dyn_radio_params, 243152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen wl->nvs->dyn_radio_params[rparam->fem], 244152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen WL1271_NVS_DYN_RADIO_PARAMS_SIZE); 245152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen 246152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen /* FIXME: current NVS is missing 5GHz parameters */ 24798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 24898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", 24998b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho radio_parms, sizeof(*radio_parms)); 25098b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 25198b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); 25298b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho if (ret < 0) 25398b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); 25498b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 25598b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho kfree(radio_parms); 25698b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho return ret; 25798b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho} 25898b5dd5ded8cb59b598b2c0c396100054779eda7Luciano Coelho 25999d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho/* 26099d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho * Poll the mailbox event field until any of the bits in the mask is set or a 26199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) 26299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho */ 26399d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelhostatic int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) 26499d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho{ 26599d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho u32 events_vector, event; 26699d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho unsigned long timeout; 26799d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 26899d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); 26999d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 27099d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho do { 27199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho if (time_after(jiffies, timeout)) 27299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho return -ETIMEDOUT; 27399d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 27499d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho msleep(1); 27599d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 27699d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho /* read from both event fields */ 27799d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho wl1271_read(wl, wl->mbox_ptr[0], &events_vector, 27899d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho sizeof(events_vector), false); 27999d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho event = events_vector & mask; 28099d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho wl1271_read(wl, wl->mbox_ptr[1], &events_vector, 28199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho sizeof(events_vector), false); 28299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho event |= events_vector & mask; 28399d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho } while (!event); 28499d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 28599d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho return 0; 28699d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho} 28799d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho 28815305498a443c181c8fb5deafb94eae585fe3ad5Juuso Oikarinenint wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) 289f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 290f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho static bool do_cal = true; 291f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_join *join; 292f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret, i; 293f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u8 *bssid; 294f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 295f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* FIXME: remove when we get calibration from the factory */ 296f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (do_cal) { 297f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_cal(wl); 298f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) 299f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("couldn't calibrate"); 300f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho else 301f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho do_cal = false; 302f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 303f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 304f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join = kzalloc(sizeof(*join), GFP_KERNEL); 305f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!join) { 306f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 307f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 308f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 309f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 310f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd join"); 311f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 312f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* Reverse order BSSID */ 313f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho bssid = (u8 *) &join->bssid_lsb; 314f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho for (i = 0; i < ETH_ALEN; i++) 315f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho bssid[i] = wl->bssid[ETH_ALEN - i - 1]; 316f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 317d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_config_options = cpu_to_le32(wl->rx_config); 318d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho join->rx_filter_options = cpu_to_le32(wl->rx_filter); 31915305498a443c181c8fb5deafb94eae585fe3ad5Juuso Oikarinen join->bss_type = bss_type; 320ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen join->basic_rate_set = wl->basic_rate_set; 321f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 322ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen if (wl->band == IEEE80211_BAND_5GHZ) 323a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; 324f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 32560e84c2ebb7b04361cf1ba0d325cc93366bd04a6Juuso Oikarinen join->beacon_interval = cpu_to_le16(wl->beacon_int); 326ae751bab9f55c3152ebf713c89a4fb6f439c2575Luciano Coelho join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; 327a410264553447ff90bf13e3662684e794e5ff83eTeemu Paasikivi 328f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->channel = wl->channel; 329f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ssid_len = wl->ssid_len; 330f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(join->ssid, wl->ssid, wl->ssid_len); 331f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH; 332f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 333f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* increment the session counter */ 334f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl->session_counter++; 335f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (wl->session_counter >= SESSION_COUNTER_MAX) 336f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl->session_counter = 0; 337f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 338f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; 339f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 340ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen /* reset TX security counters */ 341ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen wl->tx_security_last_seq = 0; 34204e36fc5f1ff4e349ea21de8d15e4e1844d04197Juuso Oikarinen wl->tx_security_seq = 0; 343f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 344fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); 345f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 346f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("failed to initiate cmd join"); 347f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out_free; 348f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 349f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 35099d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); 35199d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho if (ret < 0) 35299d84c1de8fdf5f9b09f07fdbc628857a040bf8bLuciano Coelho wl1271_error("cmd join event completion error"); 353f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 354f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout_free: 355f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(join); 356f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 357f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 358f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 359f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 360f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 361f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 362f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * send test command to firmware 363f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 364f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 365f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing the command, with all headers, must work with dma 366f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of the buffer 367f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @answer: is answer needed 368f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 369f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) 370f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 371f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 372fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen size_t res_len = 0; 373f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 374f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd test"); 375f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 376fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (answer) 377fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen res_len = buf_len; 378fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen 379fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len, res_len); 380f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 381f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 382f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("TEST command failed"); 383f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 384f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 385f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 386fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen return ret; 387f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 388f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 389f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 390f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * read acx from firmware 391f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 392f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 393f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: acx id 394f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer for the response, including all headers, must work with dma 395f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: lenght of buf 396f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 397f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) 398f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 399f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct acx_header *acx = buf; 400f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 401f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 402f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd interrogate"); 403f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 404d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->id = cpu_to_le16(id); 405f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 406f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* payload length, does not include any headers */ 407d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->len = cpu_to_le16(len - sizeof(*acx)); 408f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 409fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); 410fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen if (ret < 0) 411f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("INTERROGATE command failed"); 412f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 413f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 414f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 415f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 416f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho/** 417f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * write acx value to firmware 418f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * 419f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @wl: wl struct 420f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @id: acx id 421f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @buf: buffer containing acx, including all headers, must work with dma 422f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * @len: length of buf 423f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 424f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) 425f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 426f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct acx_header *acx = buf; 427f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 428f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 429f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd configure"); 430f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 431d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->id = cpu_to_le16(id); 432f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 433f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* payload length, does not include any headers */ 434d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho acx->len = cpu_to_le16(len - sizeof(*acx)); 435f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 436fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0); 437f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 438f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("CONFIGURE command NOK"); 439f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 440f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 441f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 442f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return 0; 443f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 444f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 44594210897e2b7df8446fdecd360342149e5b4a400Luciano Coelhoint wl1271_cmd_data_path(struct wl1271 *wl, bool enable) 446f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 447f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct cmd_enabledisable_path *cmd; 448f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret; 449f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u16 cmd_rx, cmd_tx; 450f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 451f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd data path"); 452f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 453f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 454f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 455f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 456f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 457f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 458f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 45994210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho /* the channel here is only used for calibration, so hardcoded to 1 */ 46094210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho cmd->channel = 1; 461f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 462f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (enable) { 463f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_rx = CMD_ENABLE_RX; 464f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_tx = CMD_ENABLE_TX; 465f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } else { 466f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_rx = CMD_DISABLE_RX; 467f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd_tx = CMD_DISABLE_TX; 468f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 469f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 470fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); 471f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 472f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("rx %s cmd for channel %d failed", 47394210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 474f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 475f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 476f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 477f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", 47894210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 479f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 480fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); 481f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 482f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("tx %s cmd for channel %d failed", 48394210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 4841b00f2b560028a68cdbc57a0352163afd79822ddJuuso Oikarinen goto out; 485f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 486f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 487f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", 48894210897e2b7df8446fdecd360342149e5b4a400Luciano Coelho enable ? "start" : "stop", cmd->channel); 489f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 490f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 491f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 492f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 493f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 494f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 495d8c42c0c282a5edd9ea2eef4c929d9cec2798653Juuso Oikarinenint wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) 496f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 497f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_ps_params *ps_params = NULL; 498f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 499f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 500f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* FIXME: this should be in ps.c */ 50151f2be24328957f9e2acf116b1b1d2dfd10bf41fJuuso Oikarinen ret = wl1271_acx_wake_up_conditions(wl); 502f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 503f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("couldn't set wake up conditions"); 504f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 505f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 506f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 507f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd set ps mode"); 508f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 509f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); 510f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!ps_params) { 511f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 512f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 513f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 514f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 515f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params->ps_mode = ps_mode; 516d8c42c0c282a5edd9ea2eef4c929d9cec2798653Juuso Oikarinen ps_params->send_null_data = send; 517f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params->retries = 5; 518f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ps_params->hang_over_period = 128; 519d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ 520f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 521f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, 522fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen sizeof(*ps_params), 0); 523f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 524f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("cmd set_ps_mode failed"); 525f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 526f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 527f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 528f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 529f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(ps_params); 530f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 531f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 532f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 533f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, 534f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho size_t len) 535f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 536f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct cmd_read_write_memory *cmd; 537f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 538f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 539f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd read memory"); 540f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 541f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 542f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 543f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 544f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 545f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 546f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 547f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(len > MAX_READ_SIZE); 548f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho len = min_t(size_t, len, MAX_READ_SIZE); 549f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 550d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->addr = cpu_to_le32(addr); 551d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->size = cpu_to_le32(len); 552f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 553fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd), 554fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen sizeof(*cmd)); 555f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 556f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("read memory command failed: %d", ret); 557f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 558f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 559f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 560fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen /* the read command got in */ 561f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(answer, cmd->value, len); 562f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 563f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 564f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 565f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 566f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 567f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 568818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valoint wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, 569818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo const u8 *ie, size_t ie_len, u8 active_scan, 570818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo u8 high_prio, u8 band, u8 probe_requests) 571f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 572f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 573f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_trigger_scan_to *trigger = NULL; 574f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_scan *params = NULL; 575311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi struct ieee80211_channel *channels; 576ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen u32 rate; 577311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi int i, j, n_ch, ret; 578f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho u16 scan_options = 0; 579abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi u8 ieee_band; 580abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi 581ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen if (band == WL1271_SCAN_BAND_2_4_GHZ) { 582abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ieee_band = IEEE80211_BAND_2GHZ; 583ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen rate = wl->conf.tx.basic_rate; 584ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { 585abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ieee_band = IEEE80211_BAND_2GHZ; 586ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen rate = wl->conf.tx.basic_rate; 587ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { 588abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ieee_band = IEEE80211_BAND_5GHZ; 589ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen rate = wl->conf.tx.basic_rate_5; 590ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen } else 591abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi return -EINVAL; 592f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 593abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) 594f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -EINVAL; 595f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 596abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi channels = wl->hw->wiphy->bands[ieee_band]->channels; 597abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; 598abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi 59971449f8d7059b69e6e45063997d225d8202221a2Juuso Oikarinen if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) 600abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi return -EINVAL; 601311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi 602f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params = kzalloc(sizeof(*params), GFP_KERNEL); 603f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!params) 604f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return -ENOMEM; 605f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 606f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); 607f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.rx_filter_options = 608f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); 609f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 610f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!active_scan) 611f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho scan_options |= WL1271_SCAN_OPT_PASSIVE; 612f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (high_prio) 613f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; 614d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho params->params.scan_options = cpu_to_le16(scan_options); 615f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 616f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.num_probe_requests = probe_requests; 617ebba60c66b3aa321a84c9a90a343c91fde972066Juuso Oikarinen params->params.tx_rate = rate; 618f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.tid_trigger = 0; 619f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; 620f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 621abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == WL1271_SCAN_BAND_DUAL) 622abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi params->params.band = WL1271_SCAN_BAND_2_4_GHZ; 623abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else 624abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi params->params.band = band; 625abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi 626311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) { 627311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) { 628311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].min_duration = 629311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); 630311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].max_duration = 631311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); 632311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi memset(¶ms->channels[j].bssid_lsb, 0xff, 4); 633311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi memset(¶ms->channels[j].bssid_msb, 0xff, 2); 634311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].early_termination = 0; 635311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].tx_power_att = 636311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi WL1271_SCAN_CURRENT_TX_PWR; 637311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->channels[j].channel = channels[i].hw_value; 638311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi j++; 639311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi } 640f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 641f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 642311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi params->params.num_channels = j; 643311494c47fb670a1fd74eea54fa4d02a56fcc2adTeemu Paasikivi 644818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo if (ssid_len && ssid) { 645818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo params->params.ssid_len = ssid_len; 646818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo memcpy(params->params.ssid, ssid, ssid_len); 647f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 648f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 649818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, 650818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo ie, ie_len, ieee_band); 651f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 652f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("PROBE request template failed"); 653f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 654f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 655f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 656f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); 657f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!trigger) { 658f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 659f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 660f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 661f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 662f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* disable the timeout */ 663f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho trigger->timeout = 0; 664f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 665f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, 666fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen sizeof(*trigger), 0); 667f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 668f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("trigger scan to failed for hw scan"); 669f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 670f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 671f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 672f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); 673f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 67471449f8d7059b69e6e45063997d225d8202221a2Juuso Oikarinen set_bit(WL1271_FLAG_SCANNING, &wl->flags); 675abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (wl1271_11a_enabled()) { 676abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.state = band; 677abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == WL1271_SCAN_BAND_DUAL) { 678abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.active = active_scan; 679abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.high_prio = high_prio; 680abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.probe_requests = probe_requests; 681818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo if (ssid_len && ssid) { 682818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo wl->scan.ssid_len = ssid_len; 683818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo memcpy(wl->scan.ssid, ssid, ssid_len); 684abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } else 685abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi wl->scan.ssid_len = 0; 686abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } 687abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi } 688f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 689fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); 690f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 691f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_error("SCAN failed"); 69271449f8d7059b69e6e45063997d225d8202221a2Juuso Oikarinen clear_bit(WL1271_FLAG_SCANNING, &wl->flags); 693f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 694f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 695f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 696f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 697f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(params); 6989cea461fb0a37dae9ef0a83714c5fcdc4b2074c8Juuso Oikarinen kfree(trigger); 699f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 700f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 701f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 702f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, 703606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen void *buf, size_t buf_len, int index, u32 rates) 704f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 705f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_template_set *cmd; 706f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 707f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 708f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id); 709f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 710f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); 711f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); 712f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 713f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 714f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 715f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 716f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 717f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 718f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 719f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->len = cpu_to_le16(buf_len); 720f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->template_type = template_id; 721606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen cmd->enabled_rates = cpu_to_le32(rates); 72245b531a86f93c82d8e390e19a6258111b3627bb0Juuso Oikarinen cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; 72345b531a86f93c82d8e390e19a6258111b3627bb0Juuso Oikarinen cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; 724bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen cmd->index = index; 725f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 726f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (buf) 727f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->template_data, buf, buf_len); 728f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 729fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd), 0); 730f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 731f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("cmd set_template failed: %d", ret); 732f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out_free; 733f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 734f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 735f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout_free: 736f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 737f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 738f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 739f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 740f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 741f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 742f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_build_null_data(struct wl1271 *wl) 743f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 744a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen struct sk_buff *skb = NULL; 745a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen int size; 746a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen void *ptr; 747a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen int ret = -ENOMEM; 748f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 749f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 750a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen if (wl->bss_type == BSS_TYPE_IBSS) { 751a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen size = sizeof(struct wl12xx_null_data_template); 752a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen ptr = NULL; 753a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen } else { 754a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen skb = ieee80211_nullfunc_get(wl->hw, wl->vif); 755a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen if (!skb) 756a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen goto out; 757a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen size = skb->len; 758a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen ptr = skb->data; 759a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen } 760a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen 761606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, 762606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen WL1271_RATE_AUTOMATIC); 763f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 764899e6e65c39990a76c17940625dbe6001f618734Kalle Valoout: 765899e6e65c39990a76c17940625dbe6001f618734Kalle Valo dev_kfree_skb(skb); 766a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen if (ret) 767a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen wl1271_warning("cmd buld null data failed %d", ret); 768a0cb7be4f4fa765dcfa82675811cd7e7713b5610Juuso Oikarinen 769899e6e65c39990a76c17940625dbe6001f618734Kalle Valo return ret; 770f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 771f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 772f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 773bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinenint wl1271_cmd_build_klv_null_data(struct wl1271 *wl) 774bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen{ 775bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen struct sk_buff *skb = NULL; 776bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen int ret = -ENOMEM; 777bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 778bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen skb = ieee80211_nullfunc_get(wl->hw, wl->vif); 779bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen if (!skb) 780bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen goto out; 781bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 782bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, 783bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen skb->data, skb->len, 784606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen CMD_TEMPL_KLV_IDX_NULL_DATA, 785606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen WL1271_RATE_AUTOMATIC); 786bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 787bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinenout: 788bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen dev_kfree_skb(skb); 789bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen if (ret) 790bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen wl1271_warning("cmd build klv null data failed %d", ret); 791bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 792bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen return ret; 793bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 794bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen} 795bfb24c9e16921f0e57fcec5180ffa20929832545Juuso Oikarinen 796f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) 797f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 798899e6e65c39990a76c17940625dbe6001f618734Kalle Valo struct sk_buff *skb; 799899e6e65c39990a76c17940625dbe6001f618734Kalle Valo int ret = 0; 800c3fea1994ac34dafa3ebb40d4f95354b2782af31Juuso Oikarinen 801899e6e65c39990a76c17940625dbe6001f618734Kalle Valo skb = ieee80211_pspoll_get(wl->hw, wl->vif); 802899e6e65c39990a76c17940625dbe6001f618734Kalle Valo if (!skb) 803899e6e65c39990a76c17940625dbe6001f618734Kalle Valo goto out; 804f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 805899e6e65c39990a76c17940625dbe6001f618734Kalle Valo ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, 806606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen skb->len, 0, wl->basic_rate); 807f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 808899e6e65c39990a76c17940625dbe6001f618734Kalle Valoout: 809899e6e65c39990a76c17940625dbe6001f618734Kalle Valo dev_kfree_skb(skb); 810899e6e65c39990a76c17940625dbe6001f618734Kalle Valo return ret; 811f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 812f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 813818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valoint wl1271_cmd_build_probe_req(struct wl1271 *wl, 814818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo const u8 *ssid, size_t ssid_len, 815818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo const u8 *ie, size_t ie_len, u8 band) 816f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 817818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo struct sk_buff *skb; 818abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi int ret; 819f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 820818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, 821818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo ie, ie_len); 822818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo if (!skb) { 823818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo ret = -ENOMEM; 824818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo goto out; 825818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo } 826818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo 827818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); 828f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 829abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi if (band == IEEE80211_BAND_2GHZ) 830abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, 831606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen skb->data, skb->len, 0, 832606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen wl->conf.tx.basic_rate); 833abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi else 834abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, 835606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen skb->data, skb->len, 0, 836606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen wl->conf.tx.basic_rate_5); 837818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo 838818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valoout: 839818e3063a9546fcd826155dd47582a6e2f4d1c37Kalle Valo dev_kfree_skb(skb); 840abb0b3bfb2d2411034b721df21c31964265b851eTeemu Paasikivi return ret; 841f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 842f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 843023e082609ba3225dbd5c33933a90156d2201d7fKalle Valoint wl1271_build_qos_null_data(struct wl1271 *wl) 844023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo{ 845023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo struct ieee80211_qos_hdr template; 846023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 847023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memset(&template, 0, sizeof(template)); 848023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 849023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memcpy(template.addr1, wl->bssid, ETH_ALEN); 850023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memcpy(template.addr2, wl->mac_addr, ETH_ALEN); 851023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo memcpy(template.addr3, wl->bssid, ETH_ALEN); 852023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 853023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 854023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo IEEE80211_STYPE_QOS_NULLFUNC | 855023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo IEEE80211_FCTL_TODS); 856023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 857023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo /* FIXME: not sure what priority to use here */ 858023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo template.qos_ctrl = cpu_to_le16(0); 859023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 860023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, 861606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen sizeof(template), 0, 862606c1487ac894798121bc2c64d27c1953c5a6210Juuso Oikarinen WL1271_RATE_AUTOMATIC); 863023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo} 864023e082609ba3225dbd5c33933a90156d2201d7fKalle Valo 865f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) 866f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 867f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_set_keys *cmd; 868f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 869f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 870f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); 871f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 872f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 873f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 874f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 875f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 876f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 877f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 878f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->id = id; 879d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->key_action = cpu_to_le16(KEY_SET_ID); 880f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_type = KEY_WEP; 881f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 882fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 883f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 884f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("cmd set_default_wep_key failed: %d", ret); 885f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 886f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 887f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 888f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 889f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 890f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 891f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 892f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 893f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 894f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoint wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 895ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen u8 key_size, const u8 *key, const u8 *addr, 896ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen u32 tx_seq_32, u16 tx_seq_16) 897f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho{ 898f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho struct wl1271_cmd_set_keys *cmd; 899f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho int ret = 0; 900f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 901f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 902f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (!cmd) { 903f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho ret = -ENOMEM; 904f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho goto out; 905f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 906f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 907f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (key_type != KEY_WEP) 908f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->addr, addr, ETH_ALEN); 909f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 910d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->key_action = cpu_to_le16(action); 911f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_size = key_size; 912f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->key_type = key_type; 913f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 914d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); 915d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); 916ac4e4ce54eb9cb4963a1d3d91fc65536d882ffb2Juuso Oikarinen 917f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* we have only one SSID profile */ 918f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->ssid_profile = 0; 919f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 920f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho cmd->id = id; 921f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 922f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (key_type == KEY_TKIP) { 923f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho /* 924f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * We get the key in the following form: 925f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) 926f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * but the target is expecting: 927f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho * TKIP - RX MIC - TX MIC 928f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho */ 929f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key, key, 16); 930f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key + 16, key + 24, 8); 931f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key + 24, key + 16, 8); 932f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 933f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } else { 934f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho memcpy(cmd->key, key, key_size); 935f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 936f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 937f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd)); 938f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 939fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); 940f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho if (ret < 0) { 941f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho wl1271_warning("could not set keys"); 942152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95Juuso Oikarinen goto out; 943f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho } 944f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 945f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelhoout: 946f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho kfree(cmd); 947f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho 948f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho return ret; 949f5fc0f86b02afef1119b523623b4cde41475bc8cLuciano Coelho} 95025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 95125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoint wl1271_cmd_disconnect(struct wl1271 *wl) 95225a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho{ 95325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho struct wl1271_cmd_disconnect *cmd; 95425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho int ret = 0; 95525a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 95625a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho wl1271_debug(DEBUG_CMD, "cmd disconnect"); 95725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 95825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 95925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho if (!cmd) { 96025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho ret = -ENOMEM; 96125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho goto out; 96225a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho } 96325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 964d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->rx_config_options = cpu_to_le32(wl->rx_config); 965d0f63b202146f3281800ee44823740c8bbf38f11Luciano Coelho cmd->rx_filter_options = cpu_to_le32(wl->rx_filter); 96625a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho /* disconnect reason is not used in immediate disconnections */ 96725a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho cmd->type = DISCONNECT_IMMEDIATE; 96825a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 969fa867e7355a1bdcd9bf7d55ebe9296f5b9c4028aJuuso Oikarinen ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0); 97025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho if (ret < 0) { 97125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho wl1271_error("failed to send disconnect command"); 97225a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho goto out_free; 97325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho } 97425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 9752f826f55404ca43efced94d548356182820e764fLuciano Coelho ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); 9762f826f55404ca43efced94d548356182820e764fLuciano Coelho if (ret < 0) 9772f826f55404ca43efced94d548356182820e764fLuciano Coelho wl1271_error("cmd disconnect event completion error"); 9782f826f55404ca43efced94d548356182820e764fLuciano Coelho 97925a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoout_free: 98025a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho kfree(cmd); 98125a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho 98225a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelhoout: 98325a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho return ret; 98425a7dc6d22adda590be4932ebc772ea35914880cLuciano Coelho} 985