18ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/****************************************************************************** 28ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 38ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * This file is provided under a dual BSD/GPLv2 license. When using or 48ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * redistributing this file, you may do so under either license. 58ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 68ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * GPL LICENSE SUMMARY 78ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 851368bf792c79eb917694a4155d62f04359e3734Emmanuel Grumbach * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 98b4139dc9f2171f313fc703c08269f6f8a6f6fc4Johannes Berg * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 108ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 118ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * This program is free software; you can redistribute it and/or modify 128ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * it under the terms of version 2 of the GNU General Public License as 138ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * published by the Free Software Foundation. 148ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 158ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * This program is distributed in the hope that it will be useful, but 168ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * WITHOUT ANY WARRANTY; without even the implied warranty of 178ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 188ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * General Public License for more details. 198ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 208ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * You should have received a copy of the GNU General Public License 218ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * along with this program; if not, write to the Free Software 228ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, 238ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * USA 248ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 258ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * The full GNU General Public License is included in this distribution 26410dc5aa5906ed49e2733b451a5287884e8a16dcEmmanuel Grumbach * in the file called COPYING. 278ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 288ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Contact Information: 298ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Intel Linux Wireless <ilw@linux.intel.com> 308ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 318ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 328ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * BSD LICENSE 338ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 3451368bf792c79eb917694a4155d62f04359e3734Emmanuel Grumbach * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. 358b4139dc9f2171f313fc703c08269f6f8a6f6fc4Johannes Berg * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH 368ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * All rights reserved. 378ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 388ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Redistribution and use in source and binary forms, with or without 398ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * modification, are permitted provided that the following conditions 408ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * are met: 418ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 428ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * * Redistributions of source code must retain the above copyright 438ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * notice, this list of conditions and the following disclaimer. 448ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * * Redistributions in binary form must reproduce the above copyright 458ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * notice, this list of conditions and the following disclaimer in 468ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * the documentation and/or other materials provided with the 478ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * distribution. 488ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * * Neither the name Intel Corporation nor the names of its 498ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * contributors may be used to endorse or promote products derived 508ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * from this software without specific prior written permission. 518ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 528ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 538ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 548ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 558ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 568ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 578ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 588ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 598ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 608ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 618ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 628ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 638ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 648ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *****************************************************************************/ 658ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include <net/mac80211.h> 668ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 678ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include "iwl-debug.h" 688ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include "iwl-io.h" 697b445f3501c8f9004a40994710deec0ad7c230aeEmmanuel Grumbach#include "iwl-prph.h" 708ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 718ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include "mvm.h" 728ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include "fw-api-rs.h" 738ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 748ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/* 758ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Will return 0 even if the cmd failed when RFKILL is asserted unless 768ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * CMD_WANT_SKB is set in cmd->flags. 778ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 788ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergint iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd) 798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg int ret; 818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 82debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) 83debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg if (WARN_ON(mvm->d3_test_active)) 84debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg return -EIO; 85debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg#endif 86debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg 878ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* 888ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Synchronous commands from this op-mode must hold 898ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * the mutex, this ensures we don't try to send two 908ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * (or more) synchronous commands at a time. 918ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 928ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (!(cmd->flags & CMD_ASYNC)) 938ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg lockdep_assert_held(&mvm->mutex); 948ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 958ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg ret = iwl_trans_send_cmd(mvm->trans, cmd); 968ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 978ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* 988ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * If the caller wants the SKB, then don't hide any problems, the 998ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * caller might access the response buffer which will be NULL if 1008ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * the command failed. 1018ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 1028ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (cmd->flags & CMD_WANT_SKB) 1038ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return ret; 1048ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1058ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* Silently ignore failures if RFKILL is asserted */ 1068ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (!ret || ret == -ERFKILL) 1078ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return 0; 1088ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return ret; 1098ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 1108ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1118ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergint iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u8 id, 1128ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 flags, u16 len, const void *data) 1138ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 1148ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_host_cmd cmd = { 1158ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .id = id, 1168ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .len = { len, }, 1178ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .data = { data, }, 1188ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .flags = flags, 1198ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg }; 1208ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1218ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return iwl_mvm_send_cmd(mvm, &cmd); 1228ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 1238ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1248ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/* 1258ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * We assume that the caller set the status to the sucess value 1268ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 1278ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergint iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd, 1288ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 *status) 1298ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 1308ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_rx_packet *pkt; 1318ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_cmd_response *resp; 1328ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg int ret, resp_len; 1338ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1348ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg lockdep_assert_held(&mvm->mutex); 1358ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 136debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) 137debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg if (WARN_ON(mvm->d3_test_active)) 138debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg return -EIO; 139debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg#endif 140debff6184c32149bd08cfecfafbebb96201be37dJohannes Berg 1418ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* 1428ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Only synchronous commands can wait for status, 1438ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * we use WANT_SKB so the caller can't. 1448ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 1458ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (WARN_ONCE(cmd->flags & (CMD_ASYNC | CMD_WANT_SKB), 1468ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg "cmd flags %x", cmd->flags)) 1478ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return -EINVAL; 1488ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 149a10229271946731959b2269370d0492d88cfab23Emmanuel Grumbach cmd->flags |= CMD_WANT_SKB; 1508ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1518ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg ret = iwl_trans_send_cmd(mvm->trans, cmd); 1528ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (ret == -ERFKILL) { 1538ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* 1548ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * The command failed because of RFKILL, don't update 1558ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * the status, leave it as success and return 0. 1568ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 1578ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return 0; 1588ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } else if (ret) { 1598ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return ret; 1608ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 1618ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1628ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg pkt = cmd->resp_pkt; 1638ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* Can happen if RFKILL is asserted */ 1648ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (!pkt) { 1658ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg ret = 0; 1668ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg goto out_free_resp; 1678ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 1688ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1698ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { 1708ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg ret = -EIO; 1718ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg goto out_free_resp; 1728ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 1738ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 17465b30348dbf9b529901b5c2b62dca6cad9017a2aJohannes Berg resp_len = iwl_rx_packet_payload_len(pkt); 17565b30348dbf9b529901b5c2b62dca6cad9017a2aJohannes Berg if (WARN_ON_ONCE(resp_len != sizeof(*resp))) { 1768ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg ret = -EIO; 1778ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg goto out_free_resp; 1788ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 1798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg resp = (void *)pkt->data; 1818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *status = le32_to_cpu(resp->status); 1828ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg out_free_resp: 1838ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg iwl_free_resp(cmd); 1848ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return ret; 1858ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 1868ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1878ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/* 1888ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * We assume that the caller set the status to the sucess value 1898ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 1908ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergint iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u8 id, u16 len, 1918ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg const void *data, u32 *status) 1928ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 1938ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_host_cmd cmd = { 1948ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .id = id, 1958ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .len = { len, }, 1968ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .data = { data, }, 1978ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg }; 1988ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 1998ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return iwl_mvm_send_cmd_status(mvm, &cmd, status); 2008ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 2018ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2028ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#define IWL_DECLARE_RATE_INFO(r) \ 2038ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP 2048ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2058ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/* 2068ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP 2078ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 2088ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergstatic const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = { 2098ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(1), 2108ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(2), 2118ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(5), 2128ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(11), 2138ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(6), 2148ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(9), 2158ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(12), 2168ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(18), 2178ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(24), 2188ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(36), 2198ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(48), 2208ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_DECLARE_RATE_INFO(54), 2218ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg}; 2228ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2238ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergint iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, 2248ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg enum ieee80211_band band) 2258ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 2268ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; 2278ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg int idx; 2288ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg int band_offset = 0; 2298ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2308ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* Legacy rate format, search for match in table */ 2318ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (band == IEEE80211_BAND_5GHZ) 2328ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg band_offset = IWL_FIRST_OFDM_RATE; 2338ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) 2348ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (fw_rate_idx_to_plcp[idx] == rate) 2358ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return idx - band_offset; 2368ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2378ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return -1; 2388ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 2398ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2408ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergu8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx) 2418ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 2428ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* Get PLCP rate for tx_cmd->rate_n_flags */ 2438ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return fw_rate_idx_to_plcp[rate_idx]; 2448ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 2458ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2468ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergint iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, 2478ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_device_cmd *cmd) 2488ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 2498ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_rx_packet *pkt = rxb_addr(rxb); 2508ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_error_resp *err_resp = (void *)pkt->data; 2518ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2528ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "FW Error notification: type 0x%08X cmd_id 0x%02X\n", 2538ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg le32_to_cpu(err_resp->error_type), err_resp->cmd_id); 2548ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "FW Error notification: seq 0x%04X service 0x%08X\n", 2558ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg le16_to_cpu(err_resp->bad_cmd_seq_num), 2568ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg le32_to_cpu(err_resp->error_service)); 2578ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "FW Error notification: timestamp 0x%16llX\n", 2588ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg le64_to_cpu(err_resp->timestamp)); 2598ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return 0; 2608ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 2618ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2628ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/* 2638ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Returns the first antenna as ANT_[ABC], as defined in iwl-config.h. 2648ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * The parameter should also be a combination of ANT_[ABC]. 2658ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 2668ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergu8 first_antenna(u8 mask) 2678ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 2688ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg BUILD_BUG_ON(ANT_A != BIT(0)); /* using ffs is wrong if not */ 269d7dad550e6ddb96db9d3e4d322f7d1dd8a6a9c8dEmmanuel Grumbach if (WARN_ON_ONCE(!mask)) /* ffs will return 0 if mask is zeroed */ 270d7dad550e6ddb96db9d3e4d322f7d1dd8a6a9c8dEmmanuel Grumbach return BIT(0); 271d7dad550e6ddb96db9d3e4d322f7d1dd8a6a9c8dEmmanuel Grumbach return BIT(ffs(mask) - 1); 2728ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 2738ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2748ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/* 2758ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Toggles between TX antennas to send the probe request on. 2768ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Receives the bitmask of valid TX antennas and the *index* used 2778ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * for the last TX, and returns the next valid *index* to use. 2788ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * In order to set it in the tx_cmd, must do BIT(idx). 2798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 2808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergu8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx) 2818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 2828ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u8 ind = last_idx; 2838ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg int i; 2848ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2858ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg for (i = 0; i < RATE_MCS_ANT_NUM; i++) { 2868ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg ind = (ind + 1) % RATE_MCS_ANT_NUM; 2878ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (valid & BIT(ind)) 2888ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return ind; 2898ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 2908ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 2918ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg WARN_ONCE(1, "Failed to toggle between antennas 0x%x", valid); 2928ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return last_idx; 2938ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 2948ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 295e5209263df94a41090199c95b21939139760fd85Johannes Bergstatic const struct { 296e5209263df94a41090199c95b21939139760fd85Johannes Berg const char *name; 2978ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u8 num; 2988ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} advanced_lookup[] = { 2998ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_WDG", 0x34 }, 3008ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "SYSASSERT", 0x35 }, 3018ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "UCODE_VERSION_MISMATCH", 0x37 }, 3028ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "BAD_COMMAND", 0x38 }, 3038ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, 3048ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "FATAL_ERROR", 0x3D }, 3058ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_TRM_HW_ERR", 0x46 }, 3068ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_TRM", 0x4C }, 3078ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, 3088ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, 3098ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, 3108ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_HOST", 0x66 }, 3118ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_ACTION_PT", 0x7C }, 3128ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_UNKNOWN", 0x84 }, 3138ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, 3148ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg { "ADVANCED_SYSASSERT", 0 }, 3158ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg}; 3168ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 3178ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergstatic const char *desc_lookup(u32 num) 3188ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 3198ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg int i; 3208ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 3218ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg for (i = 0; i < ARRAY_SIZE(advanced_lookup) - 1; i++) 3228ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (advanced_lookup[i].num == num) 3238ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return advanced_lookup[i].name; 3248ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 3258ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg /* No entry matches 'num', so it is the last: ADVANCED_SYSASSERT */ 3268ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return advanced_lookup[i].name; 3278ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 3288ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 3298ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/* 3308ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Note: This structure is read from the device with IO accesses, 3318ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * and the reading already does the endian conversion. As it is 3328ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * read with u32-sized accesses, any members with a different size 3338ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * need to be ordered correctly though! 3348ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 3358ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergstruct iwl_error_event_table { 3368ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 valid; /* (nonzero) valid, (0) log is empty */ 3378ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 error_id; /* type of error */ 3388ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 pc; /* program counter */ 3398ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 blink1; /* branch link */ 3408ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 blink2; /* branch link */ 3418ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 ilink1; /* interrupt link */ 3428ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 ilink2; /* interrupt link */ 3438ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 data1; /* error-specific data */ 3448ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 data2; /* error-specific data */ 3458ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 data3; /* error-specific data */ 3468ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 bcon_time; /* beacon timer */ 3478ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 tsf_low; /* network timestamp function timer */ 3488ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 tsf_hi; /* network timestamp function timer */ 3498ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 gp1; /* GP1 timer register */ 3508ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 gp2; /* GP2 timer register */ 3518ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 gp3; /* GP3 timer register */ 3528ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 ucode_ver; /* uCode version */ 3538ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 hw_ver; /* HW Silicon version */ 3548ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 brd_ver; /* HW board version */ 3558ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 log_pc; /* log program counter */ 3568ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 frame_ptr; /* frame pointer */ 3578ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 stack_ptr; /* stack pointer */ 3588ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 hcmd; /* last host command header */ 3598ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 isr0; /* isr status register LMPM_NIC_ISR0: 3608ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * rxtx_flag */ 3618ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 isr1; /* isr status register LMPM_NIC_ISR1: 3628ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * host_flag */ 3638ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 isr2; /* isr status register LMPM_NIC_ISR2: 3648ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * enc_flag */ 3658ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 isr3; /* isr status register LMPM_NIC_ISR3: 3668ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * time_flag */ 3678ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 isr4; /* isr status register LMPM_NIC_ISR4: 3688ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * wico interrupt */ 3698ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ 3708ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 wait_event; /* wait event() caller address */ 3718ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 l2p_control; /* L2pControlField */ 3728ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 l2p_duration; /* L2pDurationField */ 3738ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 l2p_mhvalid; /* L2pMhValidBits */ 3748ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 l2p_addr_match; /* L2pAddrMatchStat */ 3758ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 lmpm_pmg_sel; /* indicate which clocks are turned on 3768ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * (LMPM_PMG_SEL) */ 3778ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 u_timestamp; /* indicate when the date and time of the 3788ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * compilation */ 3798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 flow_handler; /* FH read/write pointers, RX credit */ 3808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} __packed; 3818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 38201a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary/* 38301a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary * UMAC error struct - relevant starting from family 8000 chip. 38401a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary * Note: This structure is read from the device with IO accesses, 38501a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary * and the reading already does the endian conversion. As it is 38601a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary * read with u32-sized accesses, any members with a different size 38701a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary * need to be ordered correctly though! 38801a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary */ 38901a9ca510ba4413895d4add6f26665d6c37a5413Eran Hararystruct iwl_umac_error_event_table { 39001a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 valid; /* (nonzero) valid, (0) log is empty */ 39101a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 error_id; /* type of error */ 39201a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 blink1; /* branch link */ 39301a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 blink2; /* branch link */ 39401a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 ilink1; /* interrupt link */ 39501a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 ilink2; /* interrupt link */ 39601a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 data1; /* error-specific data */ 39701a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 data2; /* error-specific data */ 39832be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary u32 data3; /* error-specific data */ 39932be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary u32 umac_fw_ver; /* UMAC version */ 40032be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary u32 umac_fw_api_ver; /* UMAC FW API ver */ 40132be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary u32 frame_pointer; /* core register 27*/ 40232be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary u32 stack_pointer; /* core register 28 */ 40332be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary u32 cmd_header; /* latest host cmd sent to UMAC */ 40432be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary u32 nic_isr_pref; /* ISR status register */ 40501a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary} __packed; 40601a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 4078ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#define ERROR_START_OFFSET (1 * sizeof(u32)) 4088ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#define ERROR_ELEM_SIZE (7 * sizeof(u32)) 4098ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 41001a9ca510ba4413895d4add6f26665d6c37a5413Eran Hararystatic void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) 41101a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary{ 41201a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary struct iwl_trans *trans = mvm->trans; 41301a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary struct iwl_umac_error_event_table table; 41401a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary u32 base; 41501a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 41601a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary base = mvm->umac_error_event_table; 41701a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 41832be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary if (base < 0x800000) { 41901a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, 42001a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary "Not valid error log pointer 0x%08X for %s uCode\n", 42101a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary base, 42201a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary (mvm->cur_ucode == IWL_UCODE_INIT) 42301a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary ? "Init" : "RT"); 42401a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary return; 42501a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary } 42601a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 42701a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); 42801a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 42901a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { 43001a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(trans, "Start IWL Error Log Dump:\n"); 43101a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", 43201a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary mvm->status, table.valid); 43301a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary } 43401a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 43501a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, 43601a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary desc_lookup(table.error_id)); 43701a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, "0x%08X | umac branchlink1\n", table.blink1); 43801a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, "0x%08X | umac branchlink2\n", table.blink2); 43901a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, "0x%08X | umac interruptlink1\n", table.ilink1); 44001a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, "0x%08X | umac interruptlink2\n", table.ilink2); 44101a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, "0x%08X | umac data1\n", table.data1); 44201a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary IWL_ERR(mvm, "0x%08X | umac data2\n", table.data2); 44332be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary IWL_ERR(mvm, "0x%08X | umac data3\n", table.data3); 44432be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary IWL_ERR(mvm, "0x%08X | umac version\n", table.umac_fw_ver); 44532be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary IWL_ERR(mvm, "0x%08X | umac api version\n", table.umac_fw_api_ver); 44632be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary IWL_ERR(mvm, "0x%08X | frame pointer\n", table.frame_pointer); 44732be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary IWL_ERR(mvm, "0x%08X | stack pointer\n", table.stack_pointer); 44832be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary IWL_ERR(mvm, "0x%08X | last host cmd\n", table.cmd_header); 44932be1a83af63c43fddcc39c2c1aedaa486af475fEran Harary IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref); 45001a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary} 45101a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 4528ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergvoid iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) 4538ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 4548ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_trans *trans = mvm->trans; 4558ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_error_event_table table; 4568ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg u32 base; 4578ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 4588ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg base = mvm->error_event_table; 4598ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (mvm->cur_ucode == IWL_UCODE_INIT) { 4608ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (!base) 4618ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg base = mvm->fw->init_errlog_ptr; 4628ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } else { 4638ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (!base) 4648ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg base = mvm->fw->inst_errlog_ptr; 4658ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 4668ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 46715ef4137928738fd9c7024597a6dbce1ed186d1eAriej Marjieh if (base < 0x800000) { 4688ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, 4698ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg "Not valid error log pointer 0x%08X for %s uCode\n", 4708ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg base, 4718ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg (mvm->cur_ucode == IWL_UCODE_INIT) 4728ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg ? "Init" : "RT"); 4738ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return; 4748ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 4758ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 4768ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); 4778ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 4788ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { 4798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(trans, "Start IWL Error Log Dump:\n"); 4808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", 4818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg mvm->status, table.valid); 4828ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg } 4838ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 4847b445f3501c8f9004a40994710deec0ad7c230aeEmmanuel Grumbach /* Do not change this output - scripts rely on it */ 4857b445f3501c8f9004a40994710deec0ad7c230aeEmmanuel Grumbach 486b900a87b2eb90c0b9586496c82a323a1b8832d73Emmanuel Grumbach IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); 487b900a87b2eb90c0b9586496c82a323a1b8832d73Emmanuel Grumbach 4888ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, 4898ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg table.data1, table.data2, table.data3, 4908ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg table.blink1, table.blink2, table.ilink1, 4918ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg table.ilink2, table.bcon_time, table.gp1, 4928ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg table.gp2, table.gp3, table.ucode_ver, 4938ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg table.hw_ver, table.brd_ver); 4948ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, 4958ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg desc_lookup(table.error_id)); 4968ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | uPc\n", table.pc); 4978ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | branchlink1\n", table.blink1); 4988ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | branchlink2\n", table.blink2); 4998ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | interruptlink1\n", table.ilink1); 5008ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | interruptlink2\n", table.ilink2); 5018ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | data1\n", table.data1); 5028ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | data2\n", table.data2); 5038ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | data3\n", table.data3); 5048ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | beacon time\n", table.bcon_time); 5058ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | tsf low\n", table.tsf_low); 5068ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | tsf hi\n", table.tsf_hi); 5078ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | time gp1\n", table.gp1); 5088ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | time gp2\n", table.gp2); 5098ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | time gp3\n", table.gp3); 5108ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | uCode version\n", table.ucode_ver); 5118ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | hw version\n", table.hw_ver); 5128ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | board version\n", table.brd_ver); 5138ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | hcmd\n", table.hcmd); 5148ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | isr0\n", table.isr0); 5158ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | isr1\n", table.isr1); 5168ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | isr2\n", table.isr2); 5178ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | isr3\n", table.isr3); 5188ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | isr4\n", table.isr4); 5198ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | isr_pref\n", table.isr_pref); 5208ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | wait_event\n", table.wait_event); 5218ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | l2p_control\n", table.l2p_control); 5228ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | l2p_duration\n", table.l2p_duration); 5238ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid); 5248ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | l2p_addr_match\n", table.l2p_addr_match); 5258ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel); 5268ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | timestamp\n", table.u_timestamp); 5278ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); 52801a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary 52901a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary if (mvm->support_umac_log) 53001a9ca510ba4413895d4add6f26665d6c37a5413Eran Harary iwl_mvm_dump_umac_error_log(mvm); 5318ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 5328ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 5333edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altmanvoid iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, 5343edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman const struct iwl_trans_txq_scd_cfg *cfg) 5353edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman{ 5363edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman if (iwl_mvm_is_dqa_supported(mvm)) { 5373edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman struct iwl_scd_txq_cfg_cmd cmd = { 5383edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .scd_queue = queue, 5393edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .enable = 1, 5403edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .window = cfg->frame_limit, 5413edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .sta_id = cfg->sta_id, 5423edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .ssn = cpu_to_le16(ssn), 5433edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .tx_fifo = cfg->fifo, 5443edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .aggregate = cfg->aggregate, 5453edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .flags = IWL_SCD_FLAGS_DQA_ENABLED, 5463edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .tid = cfg->tid, 5473edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .control = IWL_SCD_CONTROL_SET_SSN, 5483edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman }; 5493edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman int ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, 5503edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman sizeof(cmd), &cmd); 5513edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman if (ret) 5523edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman IWL_ERR(mvm, 5533edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman "Failed to configure queue %d on FIFO %d\n", 5543edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman queue, cfg->fifo); 5553edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman } 5563edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman 5573edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, 5583edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman iwl_mvm_is_dqa_supported(mvm) ? NULL : cfg); 5593edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman} 5603edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman 5613edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altmanvoid iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue) 5623edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman{ 5633edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman iwl_trans_txq_disable(mvm->trans, queue, 5643edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman !iwl_mvm_is_dqa_supported(mvm)); 5653edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman 5663edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman if (iwl_mvm_is_dqa_supported(mvm)) { 5673edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman struct iwl_scd_txq_cfg_cmd cmd = { 5683edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .scd_queue = queue, 5693edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman .enable = 0, 5703edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman }; 5713edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman int ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, CMD_ASYNC, 5723edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman sizeof(cmd), &cmd); 5733edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman if (ret) 5743edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n", 5753edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman queue, ret); 5763edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman } 5773edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman} 5783edf8ff6179dc470d53f3b88d4a778e241a73654Avri Altman 5798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/** 5808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * iwl_mvm_send_lq_cmd() - Send link quality command 5818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * @init: This command is sent as part of station initialization right 5828ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * after station has been added. 5838ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * 5848ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * The link quality command is sent as the last step of station creation. 5858ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * This is the special case in which init is set and we call a callback in 5868ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * this case to clear the state indicating that station creation is in 5878ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * progress. 5888ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg */ 5899e680946a48be7f7c074a60d8583b21815526d61Eyal Shapiraint iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init) 5908ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{ 5918ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg struct iwl_host_cmd cmd = { 5928ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .id = LQ_CMD, 5938ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .len = { sizeof(struct iwl_lq_cmd), }, 594a10229271946731959b2269370d0492d88cfab23Emmanuel Grumbach .flags = init ? 0 : CMD_ASYNC, 5958ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg .data = { lq, }, 5968ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg }; 5978ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 598881acd8987f6633280247087219df465de784a69Emmanuel Grumbach if (WARN_ON(lq->sta_id == IWL_MVM_STATION_COUNT)) 5998ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return -EINVAL; 6008ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg 6018ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg return iwl_mvm_send_cmd(mvm, &cmd); 6028ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg} 6039ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz 6049ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz/** 6059ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz * iwl_mvm_update_smps - Get a requst to change the SMPS mode 6069ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz * @req_type: The part of the driver who call for a change. 6079ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz * @smps_requests: The request to change the SMPS mode. 6089ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz * 6099ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz * Get a requst to change the SMPS mode, 6109ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz * and change it according to all other requests in the driver. 6119ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz */ 6129ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitzvoid iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 6139ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz enum iwl_mvm_smps_type_request req_type, 6149ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz enum ieee80211_smps_mode smps_request) 6159ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz{ 6169ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz struct iwl_mvm_vif *mvmvif; 617f6415f6bcf8f977b3708672e979f22450c1f5d66Emmanuel Grumbach enum ieee80211_smps_mode smps_mode; 6189ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz int i; 6199ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz 6209ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz lockdep_assert_held(&mvm->mutex); 621710e4d08f2ab6eed7950884ab30e684704e325caEmmanuel Grumbach 622710e4d08f2ab6eed7950884ab30e684704e325caEmmanuel Grumbach /* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */ 6234ed735e7599e60add8b04669a3ff6af69a31f769Johannes Berg if (num_of_ant(mvm->fw->valid_rx_ant) == 1) 624710e4d08f2ab6eed7950884ab30e684704e325caEmmanuel Grumbach return; 625710e4d08f2ab6eed7950884ab30e684704e325caEmmanuel Grumbach 626f6415f6bcf8f977b3708672e979f22450c1f5d66Emmanuel Grumbach if (vif->type == NL80211_IFTYPE_AP) 627f6415f6bcf8f977b3708672e979f22450c1f5d66Emmanuel Grumbach smps_mode = IEEE80211_SMPS_OFF; 628f6415f6bcf8f977b3708672e979f22450c1f5d66Emmanuel Grumbach else 629f6415f6bcf8f977b3708672e979f22450c1f5d66Emmanuel Grumbach smps_mode = IEEE80211_SMPS_AUTOMATIC; 630f6415f6bcf8f977b3708672e979f22450c1f5d66Emmanuel Grumbach 6319ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz mvmvif = iwl_mvm_vif_from_mac80211(vif); 6329ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz mvmvif->smps_requests[req_type] = smps_request; 6339ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { 6349ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC) { 6359ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz smps_mode = IEEE80211_SMPS_STATIC; 6369ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz break; 6379ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz } 6389ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz if (mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) 6399ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz smps_mode = IEEE80211_SMPS_DYNAMIC; 6409ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz } 6419ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz 6429ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz ieee80211_request_smps(vif, smps_mode); 6439ee718aa9269cf56040cf12f0f6ac6e0057397b2Eytan Lifshitz} 644a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg 6455c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbachstatic void iwl_mvm_diversity_iter(void *_data, u8 *mac, 6465c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach struct ieee80211_vif *vif) 6475c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach{ 6485c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 6495c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach bool *result = _data; 6505c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach int i; 6515c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 6525c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { 6535c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC || 6545c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) 6555c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach *result = false; 6565c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach } 6575c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach} 6585c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 6595c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbachbool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) 6605c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach{ 6615c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach bool result = true; 6625c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 6635c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach lockdep_assert_held(&mvm->mutex); 6645c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 6655c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach if (num_of_ant(mvm->fw->valid_rx_ant) == 1) 6665c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach return false; 6675c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 6685c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach if (!mvm->cfg->rx_with_siso_diversity) 6695c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach return false; 6705c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 6715c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach ieee80211_iterate_active_interfaces_atomic( 6725c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 6735c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach iwl_mvm_diversity_iter, &result); 6745c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 6755c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach return result; 6765c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach} 6775c90422439d62b574fd9e021fabaae2dc9a3065eEmmanuel Grumbach 678a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Bergint iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 679a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg bool value) 680a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg{ 681a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 682e03f9bef2f9de4295df91a235c6b521dd64ef655Johannes Berg int res; 683a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg 684a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg lockdep_assert_held(&mvm->mutex); 685a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg 6863510aea44ec0e5618f718c0952fe7bb0292bb2c4Johannes Berg if (mvmvif->low_latency == value) 6873510aea44ec0e5618f718c0952fe7bb0292bb2c4Johannes Berg return 0; 6883510aea44ec0e5618f718c0952fe7bb0292bb2c4Johannes Berg 689a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg mvmvif->low_latency = value; 690a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg 6910166230c6c696d501a2d2616a30e295b71e39d43Johannes Berg res = iwl_mvm_update_quotas(mvm, NULL); 692e03f9bef2f9de4295df91a235c6b521dd64ef655Johannes Berg if (res) 693e03f9bef2f9de4295df91a235c6b521dd64ef655Johannes Berg return res; 6940ee5bcdd77e7a7b54e0d79c2582dc22296c462cbEmmanuel Grumbach 6950ee5bcdd77e7a7b54e0d79c2582dc22296c462cbEmmanuel Grumbach iwl_mvm_bt_coex_vif_change(mvm); 6960ee5bcdd77e7a7b54e0d79c2582dc22296c462cbEmmanuel Grumbach 697999609f1206a14039db534058b251c6d5ab39322Arik Nemtsov return iwl_mvm_power_update_mac(mvm); 698a21d7bcbf4c65bb7f79e16287d41040e4c7f5596Johannes Berg} 69950df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar 70050df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondarstatic void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) 70150df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar{ 70250df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar bool *result = _data; 70350df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar 70450df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(vif))) 70550df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar *result = true; 70650df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar} 70750df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar 70850df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondarbool iwl_mvm_low_latency(struct iwl_mvm *mvm) 70950df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar{ 71050df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar bool result = false; 71150df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar 71250df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar ieee80211_iterate_active_interfaces_atomic( 71350df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 71450df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar iwl_mvm_ll_iter, &result); 71550df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar 71650df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar return result; 71750df8a3065404b9b953b1ae1455dd991e04a9ab7Alexander Bondar} 718bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel 719b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadelstatic void iwl_mvm_idle_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) 720bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel{ 721b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadel bool *idle = _data; 722bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel 723b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadel if (!vif->bss_conf.idle) 724b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadel *idle = false; 725bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel} 726bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel 727b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadelbool iwl_mvm_is_idle(struct iwl_mvm *mvm) 728bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel{ 729b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadel bool idle = true; 730bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel 731bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel ieee80211_iterate_active_interfaces_atomic( 732bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 733b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadel iwl_mvm_idle_iter, &idle); 734bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel 735b538b8ce76f69f7fa225bc0817bbb361b877ea23David Spinadel return idle; 736bd5e4744a6ca64299b57a2682c720d00a475a734David Spinadel} 737