195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/* 29c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> 395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn <http://rt2x00.serialmonkey.com> 495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn This program is free software; you can redistribute it and/or modify 695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn it under the terms of the GNU General Public License as published by 795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn the Free Software Foundation; either version 2 of the License, or 895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn (at your option) any later version. 995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 1095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn This program is distributed in the hope that it will be useful, 1195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn but WITHOUT ANY WARRANTY; without even the implied warranty of 1295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn GNU General Public License for more details. 1495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 1595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn You should have received a copy of the GNU General Public License 1695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn along with this program; if not, write to the 1795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn Free Software Foundation, Inc., 1895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */ 2095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 2195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn/* 2295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn Module: rt2x00lib 2395ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn Abstract: rt2x00 generic configuration routines. 2495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */ 2595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 2695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/kernel.h> 2795ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include <linux/module.h> 2895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 2995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include "rt2x00.h" 3095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn#include "rt2x00lib.h" 3195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 326bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doornvoid rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, 336bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn struct rt2x00_intf *intf, 3405c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg enum nl80211_iftype type, 355f936f11613c32ca7f8ed5fa333bb38a4501deebJohannes Berg const u8 *mac, const u8 *bssid) 3695ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{ 376bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn struct rt2x00intf_conf conf; 386bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn unsigned int flags = 0; 3995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 406bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn conf.type = type; 41feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn 42feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn switch (type) { 4305c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg case NL80211_IFTYPE_ADHOC: 44ab8966ddc2f7fa3e631efa7478ea2c76d6c9942fHelmut Schaa conf.sync = TSF_SYNC_ADHOC; 45ab8966ddc2f7fa3e631efa7478ea2c76d6c9942fHelmut Schaa break; 4605c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg case NL80211_IFTYPE_AP: 47a07dbea210e146aedf8929cdabe082b58696260cAndrey Yurovsky case NL80211_IFTYPE_MESH_POINT: 48ce292a640228fded0d2e232216a19cba33e2cd0fIvo van Doorn case NL80211_IFTYPE_WDS: 49ab8966ddc2f7fa3e631efa7478ea2c76d6c9942fHelmut Schaa conf.sync = TSF_SYNC_AP_NONE; 50feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn break; 5105c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg case NL80211_IFTYPE_STATION: 526bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn conf.sync = TSF_SYNC_INFRA; 53feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn break; 54feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn default: 556bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn conf.sync = TSF_SYNC_NONE; 56feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn break; 57feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn } 58feb24691e3e87a740caec4568be1a202db786f20Ivo van Doorn 596bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn /* 606bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn * Note that when NULL is passed as address we will send 616bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn * 00:00:00:00:00 to the device to clear the address. 626bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn * This will prevent the device being confused when it wants 6325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * to ACK frames or considers itself associated. 646bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn */ 65736e3acadce8438e610b897af2b1c472ed58444bGertjan van Wingerde memset(conf.mac, 0, sizeof(conf.mac)); 666bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn if (mac) 67736e3acadce8438e610b897af2b1c472ed58444bGertjan van Wingerde memcpy(conf.mac, mac, ETH_ALEN); 686bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn 69736e3acadce8438e610b897af2b1c472ed58444bGertjan van Wingerde memset(conf.bssid, 0, sizeof(conf.bssid)); 706bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn if (bssid) 71736e3acadce8438e610b897af2b1c472ed58444bGertjan van Wingerde memcpy(conf.bssid, bssid, ETH_ALEN); 726bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn 736bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn flags |= CONFIG_UPDATE_TYPE; 746bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) 756bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn flags |= CONFIG_UPDATE_MAC; 766bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) 776bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn flags |= CONFIG_UPDATE_BSSID; 786bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn 796bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags); 806bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn} 816bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn 82728103794316f7ff8d98bc2ce044aff7a260ee21Ivo van Doornvoid rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, 83728103794316f7ff8d98bc2ce044aff7a260ee21Ivo van Doorn struct rt2x00_intf *intf, 840204464329c17ba6d293e1899f71223599a0e582Helmut Schaa struct ieee80211_bss_conf *bss_conf, 850204464329c17ba6d293e1899f71223599a0e582Helmut Schaa u32 changed) 866bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn{ 87728103794316f7ff8d98bc2ce044aff7a260ee21Ivo van Doorn struct rt2x00lib_erp erp; 886bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn 89728103794316f7ff8d98bc2ce044aff7a260ee21Ivo van Doorn memset(&erp, 0, sizeof(erp)); 90728103794316f7ff8d98bc2ce044aff7a260ee21Ivo van Doorn 91728103794316f7ff8d98bc2ce044aff7a260ee21Ivo van Doorn erp.short_preamble = bss_conf->use_short_preamble; 92e360c4cb2bc2fb2a37981809685984efe8433c52Ivo van Doorn erp.cts_protection = bss_conf->use_cts_prot; 93e360c4cb2bc2fb2a37981809685984efe8433c52Ivo van Doorn 94e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME; 95e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn erp.sifs = SIFS; 96e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS; 97e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS; 98e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS; 996bb40dd13b458beb55f5c60dba1cb28e814bd640Ivo van Doorn 100e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn erp.basic_rates = bss_conf->basic_rates; 1018a566afea0639fc387add782bc799009512a911bIvo van Doorn erp.beacon_int = bss_conf->beacon_int; 102e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn 1031c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn /* Update the AID, this is needed for dynamic PS support */ 1041c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0; 105e9ac0745c734d39cb55ce45f1fb03a85c972b35aJohannes Berg rt2x00dev->last_beacon = bss_conf->last_tsf; 1061c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn 1076b347bff145f9a8a0972ca8fc3c44dd1f91b0f16Ivo van Doorn /* Update global beacon interval time, this is needed for PS support */ 1086b347bff145f9a8a0972ca8fc3c44dd1f91b0f16Ivo van Doorn rt2x00dev->beacon_int = bss_conf->beacon_int; 1096b347bff145f9a8a0972ca8fc3c44dd1f91b0f16Ivo van Doorn 11087c1915d2c271a8998a79f16bcf5353e2c28db45Helmut Schaa if (changed & BSS_CHANGED_HT) 11187c1915d2c271a8998a79f16bcf5353e2c28db45Helmut Schaa erp.ht_opmode = bss_conf->ht_operation_mode; 11287c1915d2c271a8998a79f16bcf5353e2c28db45Helmut Schaa 1130204464329c17ba6d293e1899f71223599a0e582Helmut Schaa rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed); 11495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn} 11595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 11669f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doornvoid rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, 117bdfa500b8b8ca87dfe7a311f569fe8b39746c299Ivo van Doorn struct antenna_setup config) 11869f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn{ 119bdfa500b8b8ca87dfe7a311f569fe8b39746c299Ivo van Doorn struct link_ant *ant = &rt2x00dev->link.ant; 1200b927a079106e5f66c736e297370d3feb008e28eIvo van Doorn struct antenna_setup *def = &rt2x00dev->default_ant; 1210b927a079106e5f66c736e297370d3feb008e28eIvo van Doorn struct antenna_setup *active = &rt2x00dev->link.ant.active; 1220b927a079106e5f66c736e297370d3feb008e28eIvo van Doorn 1236d64360ac56cda95243f15738a06f2a123c663e5Ivo van Doorn /* 1240ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn * When the caller tries to send the SW diversity, 1250ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn * we must update the ANTENNA_RX_DIVERSITY flag to 1260ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn * enable the antenna diversity in the link tuner. 1270ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn * 1280ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn * Secondly, we must guarentee we never send the 1290ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn * software antenna diversity command to the driver. 1306d64360ac56cda95243f15738a06f2a123c663e5Ivo van Doorn */ 1310ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn if (!(ant->flags & ANTENNA_RX_DIVERSITY)) { 1320ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn if (config.rx == ANTENNA_SW_DIVERSITY) { 1330ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn ant->flags |= ANTENNA_RX_DIVERSITY; 1340ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn 1350ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn if (def->rx == ANTENNA_SW_DIVERSITY) 1360ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn config.rx = ANTENNA_B; 1370ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn else 1380ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn config.rx = def->rx; 1390ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn } 1400ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn } else if (config.rx == ANTENNA_SW_DIVERSITY) 141bdfa500b8b8ca87dfe7a311f569fe8b39746c299Ivo van Doorn config.rx = active->rx; 14269f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn 1430ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn if (!(ant->flags & ANTENNA_TX_DIVERSITY)) { 1440ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn if (config.tx == ANTENNA_SW_DIVERSITY) { 1450ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn ant->flags |= ANTENNA_TX_DIVERSITY; 1460ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn 1470ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn if (def->tx == ANTENNA_SW_DIVERSITY) 1480ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn config.tx = ANTENNA_B; 1490ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn else 1500ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn config.tx = def->tx; 1510ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn } 1520ed7b3c04434788ef03d267190c5e9e6e3f8e9ceIvo van Doorn } else if (config.tx == ANTENNA_SW_DIVERSITY) 153bdfa500b8b8ca87dfe7a311f569fe8b39746c299Ivo van Doorn config.tx = active->tx; 154bdfa500b8b8ca87dfe7a311f569fe8b39746c299Ivo van Doorn 15569f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn /* 156e25c4bb913e54d729631ba7eb50daf1d9aacbef6Ivo van Doorn * Antenna setup changes require the RX to be disabled, 157e25c4bb913e54d729631ba7eb50daf1d9aacbef6Ivo van Doorn * else the changes will be ignored by the device. 158e25c4bb913e54d729631ba7eb50daf1d9aacbef6Ivo van Doorn */ 1590262ab0df64a67d4c0ed7577a29b7d866819cc68Ivo van Doorn if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 1600b7fde54f94979edc67bbf86b5adba702ebfefe8Ivo van Doorn rt2x00queue_stop_queue(rt2x00dev->rx); 161e25c4bb913e54d729631ba7eb50daf1d9aacbef6Ivo van Doorn 162e25c4bb913e54d729631ba7eb50daf1d9aacbef6Ivo van Doorn /* 16369f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn * Write new antenna setup to device and reset the link tuner. 16469f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn * The latter is required since we need to recalibrate the 16569f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn * noise-sensitivity ratio for the new setup. 16669f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn */ 167bdfa500b8b8ca87dfe7a311f569fe8b39746c299Ivo van Doorn rt2x00dev->ops->lib->config_ant(rt2x00dev, &config); 168e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn 16984e3196ff867c623056eea02c11a45e046490d89Ivo van Doorn rt2x00link_reset_tuner(rt2x00dev, true); 17069f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn 171bdfa500b8b8ca87dfe7a311f569fe8b39746c299Ivo van Doorn memcpy(active, &config, sizeof(config)); 172e25c4bb913e54d729631ba7eb50daf1d9aacbef6Ivo van Doorn 1730262ab0df64a67d4c0ed7577a29b7d866819cc68Ivo van Doorn if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 1740b7fde54f94979edc67bbf86b5adba702ebfefe8Ivo van Doorn rt2x00queue_start_queue(rt2x00dev->rx); 17569f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn} 17669f81a2cac860cf183eb9ef7787525c3552d4612Ivo van Doorn 17746a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerdestatic u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, 17846a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde struct ieee80211_conf *conf) 17946a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde{ 18046a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde struct hw_mode_spec *spec = &rt2x00dev->spec; 18146a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde int center_channel; 18246a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde u16 i; 18346a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde 18446a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde /* 18546a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde * Initialize center channel to current channel. 18646a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde */ 18746a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde center_channel = spec->channels[conf->channel->hw_value].channel; 18846a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde 18946a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde /* 19046a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde * Adjust center channel to HT40+ and HT40- operation. 19146a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde */ 19246a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde if (conf_is_ht40_plus(conf)) 19346a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde center_channel += 2; 19446a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde else if (conf_is_ht40_minus(conf)) 19546a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde center_channel -= (center_channel == 14) ? 1 : 2; 19646a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde 19746a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde for (i = 0; i < spec->num_channels; i++) 19846a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde if (spec->channels[i].channel == center_channel) 19946a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde return i; 20046a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde 20146a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde WARN_ON(1); 20246a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde return conf->channel->hw_value; 20346a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde} 20446a01ec00d05581c5bd0c37e680d5b37af4953b4Gertjan van Wingerde 205066cb637b1b562bebd09d237bfaaca6724f247e5Ivo van Doornvoid rt2x00lib_config(struct rt2x00_dev *rt2x00dev, 206e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn struct ieee80211_conf *conf, 207e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn unsigned int ieee80211_flags) 20895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn{ 2095c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn struct rt2x00lib_conf libconf; 21006443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde u16 hw_value; 2111c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn u16 autowake_timeout; 2121c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn u16 beacon_int; 2131c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn u16 beacon_diff; 21495ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 2155c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn memset(&libconf, 0, sizeof(libconf)); 2165c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn 217e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn libconf.conf = conf; 2185c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn 219e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { 22006443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde if (conf_is_ht40(conf)) { 2217dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); 22206443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde hw_value = rt2x00ht_center_channel(rt2x00dev, conf); 22306443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde } else { 2247dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); 22506443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde hw_value = conf->channel->hw_value; 22606443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde } 22735f00cfcc06bb85e0659f9847400518008d78145Ivo van Doorn 2285c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn memcpy(&libconf.rf, 22906443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde &rt2x00dev->spec.channels[hw_value], 2305c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn sizeof(libconf.rf)); 2318c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn 2328c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn memcpy(&libconf.channel, 23306443e46c65915d74b03fe1de10c00748e4706eeGertjan van Wingerde &rt2x00dev->spec.channels_info[hw_value], 2348c5e7a5f59f9d11597bd47de28334da318ea0e80Ivo van Doorn sizeof(libconf.channel)); 2352e9c43dd45ced5bd77c94d4216f96b4a49448d73John Li 2362e9c43dd45ced5bd77c94d4216f96b4a49448d73John Li /* Used for VCO periodic calibration */ 2372e9c43dd45ced5bd77c94d4216f96b4a49448d73John Li rt2x00dev->rf_channel = libconf.rf.channel; 2385c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn } 2395c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn 2401c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && 2411c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn (ieee80211_flags & IEEE80211_CONF_CHANGE_PS)) 2421c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); 2431c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn 2445c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn /* 2455c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn * Start configuration. 2465c58ee51ff8c0aca74c225e0263bc5dd2b917781Ivo van Doorn */ 247e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags); 24895ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 24995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn /* 25095ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * Some configuration changes affect the link quality 25195ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn * which means we need to reset the link tuner. 25295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn */ 253e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) 25484e3196ff867c623056eea02c11a45e046490d89Ivo van Doorn rt2x00link_reset_tuner(rt2x00dev, false); 25595ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn 2563bb42a64960253353278876ca8da6b0a7d3bea87Stanislaw Gruszka if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && 2573bb42a64960253353278876ca8da6b0a7d3bea87Stanislaw Gruszka test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && 2581c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) && 2591c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn (conf->flags & IEEE80211_CONF_PS)) { 2601c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon; 2611c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int); 2621c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn 2631c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn if (beacon_diff > beacon_int) 2641c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn beacon_diff = 0; 2651c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn 2661c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff; 2671c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn queue_delayed_work(rt2x00dev->workqueue, 2681c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn &rt2x00dev->autowakeup_work, 2691c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn autowake_timeout - 15); 2701c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn } 2711c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn 2721c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn if (conf->flags & IEEE80211_CONF_PS) 2731c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); 2741c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn else 2751c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); 2761c0bcf89d85cc97a0d9ce4cd909351a81fa4fddeIvo van Doorn 277e4ea1c403acece78c271bf9cd6f797d1cb093df9Ivo van Doorn rt2x00dev->curr_band = conf->channel->band; 278e5ef5bad345f97f1fef7ccdc01a88c298629a5d9Ivo van Doorn rt2x00dev->curr_freq = conf->channel->center_freq; 27995ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn rt2x00dev->tx_power = conf->power_level; 28042c8285767dd17f450d986bdb163a8d56fb0330aIvo van Doorn rt2x00dev->short_retry = conf->short_frame_max_tx_count; 28142c8285767dd17f450d986bdb163a8d56fb0330aIvo van Doorn rt2x00dev->long_retry = conf->long_frame_max_tx_count; 28295ea36275f3c9a1d3d04c217b4b576c657c4e70eIvo van Doorn} 283