From 811aa9cad1bd927999888ab56ed9592519d2fef6 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:42:53 +0100 Subject: rt2x00: Update copyright notice Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 07adc576db49..c247ee77b3a3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify -- cgit v1.2.3-59-g8ed1b From 6bb40dd13b458beb55f5c60dba1cb28e814bd640 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:49:59 +0100 Subject: rt2x00: Add per-interface structure Rework the interface handling. Delete the interface structure and replace it with a per-interface structure. This changes the way rt2x00 handles the active interface drastically. Copy ieee80211_bss_conf to the this rt2x00_intf structure during the bss_info_changed() callback function. This will allow us to reference it later, and removes the requirement for the device flag SHORT_PREAMBLE flag which is interface specific. Drivers receive the option to give the maximum number of virtual interfaces the device can handle. Virtual interface support: rt2400pci: 1 sta or 1 ap, * monitor interfaces rt2500pci: 1 sta or 1 ap, * monitor interfaces rt2500usb: 1 sta or 1 ap, * monitor interfaces rt61pci: 1 sta or 4 ap, * monitor interfaces rt73usb: 1 sta or 4 ap, * monitor interfaces At the moment none of the drivers support AP and STA interfaces simultaneously, this is a hardware limitation so future support will be very unlikely. Each interface structure receives its dedicated beacon entry, with this we can easily work with beaconing while multiple master mode interfaces are currently active. The configuration handlers for the MAC, BSSID and type are often called together since they all belong to the interface configuration. Merge the 3 configuration calls and cleanup the API between rt2x00lib and the drivers. While we are cleaning up the interface configuration anyway, we might as well clean up the configuration handler as well. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 84 ++++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 98 +++++++------- drivers/net/wireless/rt2x00/rt2500usb.c | 207 ++++++++++++++++------------- drivers/net/wireless/rt2x00/rt2500usb.h | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 113 +++++++++++----- drivers/net/wireless/rt2x00/rt2x00config.c | 119 ++++++++++------- drivers/net/wireless/rt2x00/rt2x00dev.c | 154 ++++++++++++++------- drivers/net/wireless/rt2x00/rt2x00lib.h | 10 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 152 ++++++++++++++------- drivers/net/wireless/rt2x00/rt2x00pci.c | 32 ++--- drivers/net/wireless/rt2x00/rt2x00queue.h | 3 - drivers/net/wireless/rt2x00/rt61pci.c | 169 ++++++++++++----------- drivers/net/wireless/rt2x00/rt61pci.h | 18 ++- drivers/net/wireless/rt2x00/rt73usb.c | 179 ++++++++++++++----------- drivers/net/wireless/rt2x00/rt73usb.h | 17 ++- 15 files changed, 826 insertions(+), 530 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index fc161084a8d3..61766ed800e3 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -246,50 +246,50 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) +static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, - (2 * sizeof(__le32))); -} + unsigned int bcn_preload; + u32 reg; -static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_TYPE) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); -static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); + rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); + rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - rt2x00pci_register_write(rt2x00dev, CSR14, 0); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + } - /* - * Enable beacon config - */ - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); + if (flags & CONFIG_UPDATE_MAC) + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, + conf->mac, sizeof(conf->mac)); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); + if (flags & CONFIG_UPDATE_BSSID) + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, + conf->bssid, sizeof(conf->bssid)); } -static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { int preamble_mask; u32 reg; @@ -327,6 +327,8 @@ static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + + return 0; } static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -481,8 +483,8 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -1553,9 +1555,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, - .config_mac_addr = rt2400pci_config_mac_addr, - .config_bssid = rt2400pci_config_bssid, - .config_type = rt2400pci_config_type, + .config_intf = rt2400pci_config_intf, .config_preamble = rt2400pci_config_preamble, .config = rt2400pci_config, }; @@ -1590,6 +1590,8 @@ static const struct data_queue_desc rt2400pci_queue_atim = { static const struct rt2x00_ops rt2400pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2400pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0a54b6512207..6a558bf74f11 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -246,53 +246,53 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, - (2 * sizeof(__le32))); -} - -static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, - (2 * sizeof(__le32))); -} - -static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) +static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + unsigned int bcn_preload; u32 reg; - rt2x00pci_register_write(rt2x00dev, CSR14, 0); + if (flags & CONFIG_UPDATE_TYPE) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); - /* - * Enable beacon config - */ - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); + rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); + rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); + rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + } + + if (flags & CONFIG_UPDATE_MAC) + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, + conf->mac, sizeof(conf->mac)); + + if (flags & CONFIG_UPDATE_BSSID) + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, + conf->bssid, sizeof(conf->bssid)); } -static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { int preamble_mask; u32 reg; @@ -330,6 +330,8 @@ static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + + return 0; } static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -529,8 +531,8 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -609,9 +611,10 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * To prevent collisions with MAC ASIC on chipsets * up to version C the link tuning should halt after 20 - * seconds. + * seconds while being associated. */ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && + rt2x00dev->intf_associated && rt2x00dev->link.count > 20) return; @@ -619,9 +622,12 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Chipset versions C and lower should directly continue - * to the dynamic CCA tuning. + * to the dynamic CCA tuning. Chipset version D and higher + * should go straight to dynamic CCA tuning when they + * are not associated. */ - if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D) + if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || + !rt2x00dev->intf_associated) goto dynamic_cca_tune; /* @@ -1861,9 +1867,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, - .config_mac_addr = rt2500pci_config_mac_addr, - .config_bssid = rt2500pci_config_bssid, - .config_type = rt2500pci_config_type, + .config_intf = rt2500pci_config_intf, .config_preamble = rt2500pci_config_preamble, .config = rt2500pci_config, }; @@ -1898,6 +1902,8 @@ static const struct data_queue_desc rt2500pci_queue_atim = { static const struct rt2x00_ops rt2500pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2500pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index edc16a5fc754..31258ee24ee3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -285,70 +285,65 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { /* * Configuration handlers. */ -static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) -{ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (3 * sizeof(__le16))); -} - -static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid, - (3 * sizeof(__le16))); -} - -static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) +static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { + unsigned int bcn_preload; u16 reg; - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); + if (flags & CONFIG_UPDATE_TYPE) { + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); - /* - * Enable beacon config - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); - rt2x00_set_field16(®, TXRX_CSR20_OFFSET, - (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6); - if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0); - else - rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 2); - rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); + rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); + rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, + 2 * (conf->type != IEEE80211_IF_TYPE_STA)); + rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); - /* - * Enable synchronisation. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + /* + * Enable synchronisation. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); + rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + } - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, - (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); - rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, tsf_sync); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + if (flags & CONFIG_UPDATE_MAC) + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac, + (3 * sizeof(__le16))); + + if (flags & CONFIG_UPDATE_BSSID) + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid, + (3 * sizeof(__le16))); } -static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u16 reg; /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. + * When in atomic context, we should let rt2x00lib + * try this configuration again later. */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); - return; - } + if (in_atomic()) + return -EAGAIN; rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout); @@ -358,6 +353,8 @@ static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, !!short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); + + return 0; } static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -518,8 +515,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2500usb_config_phymode(rt2x00dev, libconf->phymode, @@ -625,6 +622,24 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) u8 up_bound; u8 low_bound; + /* + * Read current r17 value, as well as the sensitivity values + * for the r17 register. + */ + rt2500usb_bbp_read(rt2x00dev, 17, &r17); + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); + up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); + low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER); + + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Determine the BBP tuning threshold and correctly * set BBP 24, 25 and 61. @@ -650,13 +665,6 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) rt2500usb_bbp_write(rt2x00dev, 25, r25); rt2500usb_bbp_write(rt2x00dev, 61, r61); - /* - * Read current r17 value, as well as the sensitivity values - * for the r17 register. - */ - rt2500usb_bbp_read(rt2x00dev, 17, &r17); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); - /* * A too low RSSI will cause too much false CCA which will * then corrupt the R17 tuning. To remidy this the tuning should @@ -692,14 +700,9 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); - vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); - low_bound = 0x32; - if (rssi >= -77) - up_bound = vgc_bound; - else - up_bound = vgc_bound - (-77 - rssi); + if (rssi < -77) + up_bound -= (-77 - rssi); if (up_bound < low_bound) up_bound = low_bound; @@ -707,7 +710,16 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) if (r17 > up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, up_bound); rt2x00dev->link.vgc_level = up_bound; - } else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { + return; + } + +dynamic_cca_tune: + + /* + * R17 is inside the dynamic tuning range, + * start tuning the link based on the false cca counter. + */ + if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, ++r17); rt2x00dev->link.vgc_level = r17; } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { @@ -1203,6 +1215,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) { u16 word; u8 *mac; + u8 bbp; rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); @@ -1257,9 +1270,17 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word); } + /* + * Switch lower vgc bound to current BBP R17 value, + * lower the value a bit for better quality. + */ + rt2500usb_bbp_read(rt2x00dev, 17, &bbp); + bbp -= 6; + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40); + rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word); } @@ -1270,6 +1291,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word); + } else { + rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); + rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); } rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word); @@ -1705,40 +1729,40 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_usb_bcn *priv_bcn; struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; int pipe = usb_sndbulkpipe(usb_dev, 1); int length; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); - priv_bcn = entry->priv_data; + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_bcn = intf->beacon->priv_data; /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case mac80211 doesn't set this correctly, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* @@ -1749,7 +1773,8 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, length = rt2500usb_get_tx_data_len(rt2x00dev, skb); usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe, - skb->data, length, rt2500usb_beacondone, entry); + skb->data, length, rt2500usb_beacondone, + intf->beacon); /* * Second we need to create the guardian byte. @@ -1759,7 +1784,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, priv_bcn->guardian_data = 0; usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe, &priv_bcn->guardian_data, 1, rt2500usb_beacondone, - entry); + intf->beacon); /* * Send out the guardian byte. @@ -1769,7 +1794,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, /* * Enable beacon generation. */ - rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt2500usb_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -1805,9 +1830,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, - .config_mac_addr = rt2500usb_config_mac_addr, - .config_bssid = rt2500usb_config_bssid, - .config_type = rt2500usb_config_type, + .config_intf = rt2500usb_config_intf, .config_preamble = rt2500usb_config_preamble, .config = rt2500usb_config, }; @@ -1842,6 +1865,8 @@ static const struct data_queue_desc rt2500usb_queue_atim = { static const struct rt2x00_ops rt2500usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2500usb_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index e9f2cd90da58..23ba0c15741f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -686,6 +686,7 @@ */ #define EEPROM_BBPTUNE_VGC 0x0034 #define EEPROM_BBPTUNE_VGCUPPER FIELD16(0x00ff) +#define EEPROM_BBPTUNE_VGCLOWER FIELD16(0xff00) /* * EEPROM BBP R17 Tuning. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6a25195816db..2363ca4903cc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -343,20 +343,22 @@ static inline int rt2x00_update_ant_rssi(struct link *link, int rssi) /* * Interface structure - * Configuration details about the current interface. + * Per interface configuration details, this structure + * is allocated as the private data for ieee80211_vif. */ -struct interface { +struct rt2x00_intf { /* - * Interface identification. The value is assigned - * to us by the 80211 stack, and is used to request - * new beacons. + * All fields within the rt2x00_intf structure + * must be protected with a spinlock. */ - struct ieee80211_vif *id; + spinlock_t lock; /* - * Current working type (IEEE80211_IF_TYPE_*). + * BSS configuration. Copied from the structure + * passed to us through the bss_info_changed() + * callback funtion. */ - int type; + struct ieee80211_bss_conf conf; /* * MAC of the device. @@ -367,16 +369,25 @@ struct interface { * BBSID of the AP to associate with. */ u8 bssid[ETH_ALEN]; -}; -static inline int is_interface_present(struct interface *intf) -{ - return !!intf->id; -} + /* + * Entry in the beacon queue which belongs to + * this interface. Each interface has its own + * dedicated beacon entry. + */ + struct queue_entry *beacon; -static inline int is_interface_type(struct interface *intf, int type) + /* + * Actions that needed rescheduling. + */ + unsigned int delayed_flags; +#define DELAYED_UPDATE_BEACON 0x00000001 +#define DELAYED_CONFIG_PREAMBLE 0x00000002 +}; + +static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) { - return intf->type == type; + return (struct rt2x00_intf *)vif->drv_priv; } /* @@ -429,6 +440,37 @@ struct rt2x00lib_conf { short eifs; }; +/* + * Configuration structure wrapper around the + * rt2x00 interface configuration handler. + */ +struct rt2x00intf_conf { + /* + * Interface type + */ + enum ieee80211_if_types type; + + /* + * TSF sync value, this is dependant on the operation type. + */ + enum tsf_sync sync; + + /* + * The MAC and BSSID addressess are simple array of bytes, + * these arrays are little endian, so when sending the addressess + * to the drivers, copy the it into a endian-signed variable. + * + * Note that all devices (except rt2500usb) have 32 bits + * register word sizes. This means that whatever variable we + * pass _must_ be a multiple of 32 bits. Otherwise the device + * might not accept what we are sending to it. + * This will also make it easier for the driver to write + * the data to the device. + */ + __le32 mac[2]; + __le32 bssid[2]; +}; + /* * rt2x00lib callback functions. */ @@ -495,16 +537,21 @@ struct rt2x00lib_ops { /* * Configuration handlers. */ - void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac); - void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid); - void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync); - void (*config_preamble) (struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time); - void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags, - struct rt2x00lib_conf *libconf); + void (*config_intf) (struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags); +#define CONFIG_UPDATE_TYPE ( 1 << 1 ) +#define CONFIG_UPDATE_MAC ( 1 << 2 ) +#define CONFIG_UPDATE_BSSID ( 1 << 3 ) + + int (*config_preamble) (struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time); + void (*config) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags); #define CONFIG_UPDATE_PHYMODE ( 1 << 1 ) #define CONFIG_UPDATE_CHANNEL ( 1 << 2 ) #define CONFIG_UPDATE_TXPOWER ( 1 << 3 ) @@ -519,6 +566,8 @@ struct rt2x00lib_ops { */ struct rt2x00_ops { const char *name; + const unsigned int max_sta_intf; + const unsigned int max_ap_intf; const unsigned int eeprom_size; const unsigned int rf_size; const struct data_queue_desc *rx; @@ -550,6 +599,7 @@ enum rt2x00_flags { /* * Driver features */ + DRIVER_SUPPORT_MIXED_INTERFACES, DRIVER_REQUIRE_FIRMWARE, DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, DRIVER_REQUIRE_FIRMWARE_CCITT, @@ -566,7 +616,6 @@ enum rt2x00_flags { CONFIG_EXTERNAL_LNA_BG, CONFIG_DOUBLE_ANTENNA, CONFIG_DISABLE_LINK_TUNING, - CONFIG_SHORT_PREAMBLE, }; /* @@ -670,9 +719,14 @@ struct rt2x00_dev { unsigned int packet_filter; /* - * Interface configuration. + * Interface details: + * - Open ap interface count. + * - Open sta interface count. + * - Association count. */ - struct interface interface; + unsigned int intf_ap_count; + unsigned int intf_sta_count; + unsigned int intf_associated; /* * Link quality @@ -738,9 +792,8 @@ struct rt2x00_dev { /* * Scheduled work. */ - struct work_struct beacon_work; + struct work_struct intf_work; struct work_struct filter_work; - struct work_struct config_work; /* * Data queue arrays for RX, TX and Beacon. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index c247ee77b3a3..20231e0c53fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -29,64 +29,89 @@ #include "rt2x00.h" #include "rt2x00lib.h" - -/* - * The MAC and BSSID addressess are simple array of bytes, - * these arrays are little endian, so when sending the addressess - * to the drivers, copy the it into a endian-signed variable. - * - * Note that all devices (except rt2500usb) have 32 bits - * register word sizes. This means that whatever variable we - * pass _must_ be a multiple of 32 bits. Otherwise the device - * might not accept what we are sending to it. - * This will also make it easier for the driver to write - * the data to the device. - * - * Also note that when NULL is passed as address the - * we will send 00:00:00:00:00 to the device to clear the address. - * This will prevent the device being confused when it wants - * to ACK frames or consideres itself associated. - */ -void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac) +void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + enum ieee80211_if_types type, + u8 *mac, u8 *bssid) { - __le32 reg[2]; - - memset(®, 0, sizeof(reg)); - if (mac) - memcpy(®, mac, ETH_ALEN); - - rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, ®[0]); -} + struct rt2x00intf_conf conf; + unsigned int flags = 0; -void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) -{ - __le32 reg[2]; - - memset(®, 0, sizeof(reg)); - if (bssid) - memcpy(®, bssid, ETH_ALEN); - - rt2x00dev->ops->lib->config_bssid(rt2x00dev, ®[0]); -} - -void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type) -{ - int tsf_sync; + conf.type = type; switch (type) { case IEEE80211_IF_TYPE_IBSS: case IEEE80211_IF_TYPE_AP: - tsf_sync = TSF_SYNC_BEACON; + conf.sync = TSF_SYNC_BEACON; break; case IEEE80211_IF_TYPE_STA: - tsf_sync = TSF_SYNC_INFRA; + conf.sync = TSF_SYNC_INFRA; break; default: - tsf_sync = TSF_SYNC_NONE; + conf.sync = TSF_SYNC_NONE; break; } - rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync); + /* + * Note that when NULL is passed as address we will send + * 00:00:00:00:00 to the device to clear the address. + * This will prevent the device being confused when it wants + * to ACK frames or consideres itself associated. + */ + memset(&conf.mac, 0, sizeof(conf.mac)); + if (mac) + memcpy(&conf.mac, mac, ETH_ALEN); + + memset(&conf.bssid, 0, sizeof(conf.bssid)); + if (bssid) + memcpy(&conf.bssid, bssid, ETH_ALEN); + + flags |= CONFIG_UPDATE_TYPE; + if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) + flags |= CONFIG_UPDATE_MAC; + if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) + flags |= CONFIG_UPDATE_BSSID; + + rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags); +} + +void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + const unsigned int short_preamble) +{ + int retval; + int ack_timeout; + int ack_consume_time; + + ack_timeout = PLCP + get_duration(ACK_SIZE, 10); + ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); + + if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) + ack_timeout += SHORT_DIFS; + else + ack_timeout += DIFS; + + if (short_preamble) { + ack_timeout += SHORT_PREAMBLE; + ack_consume_time += SHORT_PREAMBLE; + } else { + ack_timeout += PREAMBLE; + ack_consume_time += PREAMBLE; + } + + retval = rt2x00dev->ops->lib->config_preamble(rt2x00dev, + short_preamble, + ack_timeout, + ack_consume_time); + + spin_lock(&intf->lock); + + if (retval) { + intf->delayed_flags |= DELAYED_CONFIG_PREAMBLE; + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + } + + spin_unlock(&intf->lock); } void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, @@ -113,7 +138,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, * The latter is required since we need to recalibrate the * noise-sensitivity ratio for the new setup. */ - rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf); + rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA); rt2x00lib_reset_link_tuner(rt2x00dev); rt2x00dev->link.ant.active.rx = libconf.ant.rx; @@ -266,7 +291,7 @@ config: /* * Start configuration. */ - rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf); + rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags); /* * Some configuration changes affect the link quality diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index bc07c56f89b3..014c307c270c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -136,12 +136,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Stop all scheduled work. */ - if (work_pending(&rt2x00dev->beacon_work)) - cancel_work_sync(&rt2x00dev->beacon_work); + if (work_pending(&rt2x00dev->intf_work)) + cancel_work_sync(&rt2x00dev->intf_work); if (work_pending(&rt2x00dev->filter_work)) cancel_work_sync(&rt2x00dev->filter_work); - if (work_pending(&rt2x00dev->config_work)) - cancel_work_sync(&rt2x00dev->config_work); /* * Stop the TX queues. @@ -173,7 +171,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) * When we are enabling the RX, we should also start the link tuner. */ if (state == STATE_RADIO_RX_ON && - is_interface_present(&rt2x00dev->interface)) + (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count)) rt2x00lib_start_link_tuner(rt2x00dev); } @@ -401,10 +399,10 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) unsigned int filter = rt2x00dev->packet_filter; /* - * Since we had stored the filter inside interface.filter, + * Since we had stored the filter inside rt2x00dev->packet_filter, * we should now clear that field. Otherwise the driver will * assume nothing has changed (*total_flags will be compared - * to interface.filter to determine if any action is required). + * to rt2x00dev->packet_filter to determine if any action is required). */ rt2x00dev->packet_filter = 0; @@ -412,41 +410,72 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) filter, &filter, 0, NULL); } -static void rt2x00lib_configuration_scheduled(struct work_struct *work) +static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) { - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, config_work); - struct ieee80211_bss_conf bss_conf; + struct rt2x00_dev *rt2x00dev = data; + struct rt2x00_intf *intf = vif_to_intf(vif); + struct sk_buff *skb; + struct ieee80211_tx_control control; + struct ieee80211_bss_conf conf; + int delayed_flags; + + /* + * Copy all data we need during this action under the protection + * of a spinlock. Otherwise race conditions might occur which results + * into an invalid configuration. + */ + spin_lock(&intf->lock); + + memcpy(&conf, &intf->conf, sizeof(conf)); + delayed_flags = intf->delayed_flags; + intf->delayed_flags = 0; + + spin_unlock(&intf->lock); + + if (delayed_flags & DELAYED_UPDATE_BEACON) { + skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); + if (skb) { + rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, + &control); + dev_kfree_skb(skb); + } + } + + if (delayed_flags & DELAYED_CONFIG_PREAMBLE) + rt2x00lib_config_preamble(rt2x00dev, intf, + intf->conf.use_short_preamble); +} - bss_conf.use_short_preamble = - test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); +static void rt2x00lib_intf_scheduled(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, intf_work); /* - * FIXME: shouldn't invoke it this way because all other contents - * of bss_conf is invalid. + * Iterate over each interface and perform the + * requested configurations. */ - rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id, - &bss_conf, BSS_CHANGED_ERP_PREAMBLE); + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_intf_scheduled_iter, + rt2x00dev); } /* * Interrupt context handlers. */ -static void rt2x00lib_beacondone_scheduled(struct work_struct *work) +static void rt2x00lib_beacondone_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) { - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, beacon_work); - struct ieee80211_tx_control control; - struct sk_buff *skb; + struct rt2x00_intf *intf = vif_to_intf(vif); - skb = ieee80211_beacon_get(rt2x00dev->hw, - rt2x00dev->interface.id, &control); - if (!skb) + if (vif->type != IEEE80211_IF_TYPE_AP && + vif->type != IEEE80211_IF_TYPE_IBSS) return; - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, &control); - - dev_kfree_skb(skb); + spin_lock(&intf->lock); + intf->delayed_flags |= DELAYED_UPDATE_BEACON; + spin_unlock(&intf->lock); } void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) @@ -454,7 +483,11 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work); + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_beacondone_iter, + rt2x00dev); + + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -1037,6 +1070,10 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) return retval; } + rt2x00dev->intf_ap_count = 0; + rt2x00dev->intf_sta_count = 0; + rt2x00dev->intf_associated = 0; + __set_bit(DEVICE_STARTED, &rt2x00dev->flags); return 0; @@ -1053,6 +1090,10 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) */ rt2x00lib_disable_radio(rt2x00dev); + rt2x00dev->intf_ap_count = 0; + rt2x00dev->intf_sta_count = 0; + rt2x00dev->intf_associated = 0; + __clear_bit(DEVICE_STARTED, &rt2x00dev->flags); } @@ -1063,6 +1104,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; + /* + * Make room for rt2x00_intf inside the per-interface + * structure ieee80211_vif. + */ + rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); + /* * Let the driver probe the device to detect the capabilities. */ @@ -1075,16 +1122,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ - INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled); + INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); - INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); - /* - * Reset current working type. - */ - rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID; - /* * Allocate queue array. */ @@ -1203,9 +1244,30 @@ exit: } EXPORT_SYMBOL_GPL(rt2x00lib_suspend); +static void rt2x00lib_resume_intf(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rt2x00_dev *rt2x00dev = data; + struct rt2x00_intf *intf = vif_to_intf(vif); + + spin_lock(&intf->lock); + + rt2x00lib_config_intf(rt2x00dev, intf, + vif->type, intf->mac, intf->bssid); + + + /* + * Master or Ad-hoc mode require a new beacon update. + */ + if (vif->type == IEEE80211_IF_TYPE_AP || + vif->type == IEEE80211_IF_TYPE_IBSS) + intf->delayed_flags |= DELAYED_UPDATE_BEACON; + + spin_unlock(&intf->lock); +} + int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) { - struct interface *intf = &rt2x00dev->interface; int retval; NOTICE(rt2x00dev, "Waking up.\n"); @@ -1235,9 +1297,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) if (!rt2x00dev->hw->conf.radio_enabled) rt2x00lib_disable_radio(rt2x00dev); - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); - rt2x00lib_config_type(rt2x00dev, intf->type); + /* + * Iterator over each active interface to + * reconfigure the hardware. + */ + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_resume_intf, rt2x00dev); /* * We are ready again to receive requests from mac80211. @@ -1253,12 +1318,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) ieee80211_start_queues(rt2x00dev->hw); /* - * When in Master or Ad-hoc mode, - * restart Beacon transmitting by faking a beacondone event. + * During interface iteration we might have changed the + * delayed_flags, time to handles the event by calling + * the work handler directly. */ - if (intf->type == IEEE80211_IF_TYPE_AP || - intf->type == IEEE80211_IF_TYPE_IBSS) - rt2x00lib_beacondone(rt2x00dev); + rt2x00lib_intf_scheduled(&rt2x00dev->intf_work); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5c835f42a455..f6789fdaaf6e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -50,9 +50,13 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev); /* * Configuration handlers. */ -void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac); -void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid); -void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type); +void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + enum ieee80211_if_types type, + u8 *mac, u8 *bssid); +void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + const unsigned int short_preamble); void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, enum antenna rx, enum antenna tx); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f08c151ee4ba..65a2bcd18aa1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -52,11 +52,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, skb_put(skb, size); if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) - ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id, + ieee80211_ctstoself_get(rt2x00dev->hw, control->vif, frag_skb->data, frag_skb->len, control, (struct ieee80211_cts *)(skb->data)); else - ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id, + ieee80211_rts_get(rt2x00dev->hw, control->vif, frag_skb->data, frag_skb->len, control, (struct ieee80211_rts *)(skb->data)); @@ -162,19 +162,67 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(conf->vif); + struct data_queue *queue = + rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + struct queue_entry *entry = NULL; + unsigned int i; /* - * Don't allow interfaces to be added while - * either the device has disappeared or when - * another interface is already present. + * Don't allow interfaces to be added + * the device has disappeared. */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || - is_interface_present(intf)) + !test_bit(DEVICE_STARTED, &rt2x00dev->flags)) + return -ENODEV; + + /* + * When we don't support mixed interfaces (a combination + * of sta and ap virtual interfaces) then we can only + * add this interface when the rival interface count is 0. + */ + if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) && + ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) || + (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count))) + return -ENOBUFS; + + /* + * Check if we exceeded the maximum amount of supported interfaces. + */ + if ((conf->type == IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) || + (conf->type != IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf)) + return -ENOBUFS; + + /* + * Loop through all beacon queues to find a free + * entry. Since there are as much beacon entries + * as the maximum interfaces, this search shouldn't + * fail. + */ + for (i = 0; i < queue->limit; i++) { + entry = &queue->entries[i]; + if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) + break; + } + + if (unlikely(i == queue->limit)) return -ENOBUFS; - intf->id = conf->vif; - intf->type = conf->type; + /* + * We are now absolutely sure the interface can be created, + * increase interface count and start initialization. + */ + + if (conf->type == IEEE80211_IF_TYPE_AP) + rt2x00dev->intf_ap_count++; + else + rt2x00dev->intf_sta_count++; + + spin_lock_init(&intf->lock); + intf->beacon = entry; + if (conf->type == IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); @@ -184,8 +232,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * has been initialized. Otherwise the device can reset * the MAC registers. */ - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_type(rt2x00dev, conf->type); + rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); return 0; } @@ -195,7 +242,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(conf->vif); /* * Don't allow interfaces to be remove while @@ -203,21 +250,27 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, * no interface is present. */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || - !is_interface_present(intf)) + (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) || + (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count)) return; - intf->id = NULL; - intf->type = IEEE80211_IF_TYPE_INVALID; - memset(&intf->bssid, 0x00, ETH_ALEN); - memset(&intf->mac, 0x00, ETH_ALEN); + if (conf->type == IEEE80211_IF_TYPE_AP) + rt2x00dev->intf_ap_count--; + else + rt2x00dev->intf_sta_count--; + + /* + * Release beacon entry so it is available for + * new interfaces again. + */ + __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags); /* * Make sure the bssid and mac address registers * are cleared to prevent false ACKing of frames. */ - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); - rt2x00lib_config_type(rt2x00dev, intf->type); + rt2x00lib_config_intf(rt2x00dev, intf, + IEEE80211_IF_TYPE_INVALID, NULL, NULL); } EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); @@ -262,7 +315,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_if_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(vif); int status; /* @@ -272,12 +325,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) return 0; - /* - * If the given type does not match the configured type, - * there has been a problem. - */ - if (conf->type != intf->type) - return -EINVAL; + spin_lock(&intf->lock); /* * If the interface does not work in master mode, @@ -286,7 +334,9 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, */ if (conf->type != IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->bssid, ETH_ALEN); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); + rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, intf->bssid); + + spin_unlock(&intf->lock); /* * We only need to initialize the beacon when master mode is enabled. @@ -342,35 +392,35 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct rt2x00_dev *rt2x00dev = hw->priv; - int short_preamble; - int ack_timeout; - int ack_consume_time; - int difs; - int preamble; + struct rt2x00_intf *intf = vif_to_intf(vif); /* - * We only support changing preamble mode. + * When the association status has changed we must reset the link + * tuner counter. This is because some drivers determine if they + * should perform link tuning based on the number of seconds + * while associated or not associated. */ - if (!(changes & BSS_CHANGED_ERP_PREAMBLE)) - return; - - short_preamble = bss_conf->use_short_preamble; - preamble = bss_conf->use_short_preamble ? - SHORT_PREAMBLE : PREAMBLE; + if (changes & BSS_CHANGED_ASSOC) { + rt2x00dev->link.count = 0; - difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS; - ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10); - - ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10); + if (bss_conf->assoc) + rt2x00dev->intf_associated++; + else + rt2x00dev->intf_associated--; + } - if (short_preamble) - __set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); - else - __clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); + /* + * When the preamble mode has changed, we should perform additional + * configuration steps. For all other changes we are already done. + */ + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + rt2x00lib_config_preamble(rt2x00dev, intf, + bss_conf->use_short_preamble); - rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble, - ack_timeout, ack_consume_time); + spin_lock(&intf->lock); + memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); + spin_unlock(&intf->lock); + } } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 63cfe33e95da..764147dd5aea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -38,20 +38,14 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; - /* - * Just in case mac80211 doesn't set this correctly, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); - priv_tx = entry->priv_data; + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_tx = intf->beacon->priv_data; /* * Fill in skb descriptor @@ -59,17 +53,25 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = skb->data; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; - memcpy(priv_tx->data, skb->data, skb->len); + /* + * Just in case mac80211 doesn't set this correctly, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Enable beacon generation. + * Write entire beacon with descriptor to register, + * and kick the beacon generator. */ + memcpy(priv_tx->data, skb->data, skb->len); rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 507116c6c9fe..75af48eddc25 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -46,9 +46,6 @@ * queue would be sufficient. Although this is almost one third of * the amount the legacy driver allocated, the queues aren't getting * filled to the maximum even when working with the maximum rate. - * - * FIXME: For virtual interfaces we need a different number - * of beacons, since more interfaces require more beacons. */ #define RX_ENTRIES 12 #define TX_ENTRIES 12 diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b5ab771bbac2..b432cc21d248 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -271,63 +271,60 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) +static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - u32 tmp; - - tmp = le32_to_cpu(mac[1]); - rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - mac[1] = cpu_to_le32(tmp); - - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (2 * sizeof(__le32))); -} + unsigned int beacon_base; + u32 reg; -static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) -{ - u32 tmp; + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); + rt2x00pci_register_write(rt2x00dev, beacon_base, 0); - tmp = le32_to_cpu(bssid[1]); - rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); - bssid[1] = cpu_to_le32(tmp); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); -static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, + conf->mac, sizeof(conf->mac)); + } - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); + conf->bssid[1] = cpu_to_le32(reg); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, - (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, + conf->bssid, sizeof(conf->bssid)); + } } -static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u32 reg; @@ -339,6 +336,8 @@ static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); + + return 0; } static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -667,8 +666,8 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt61pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt61pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -815,6 +814,13 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) } } + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Special big-R17 for very short distance */ @@ -866,6 +872,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) return; } +dynamic_cca_tune: + /* * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. @@ -1214,6 +1222,17 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48); rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + /* * We must clear the error counters. * These registers are cleared on read, @@ -2378,25 +2397,20 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; + unsigned int beacon_base; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); + if (unlikely(!intf->beacon)) + return -ENOBUFS; /* * We need to append the descriptor in front of the * beacon frame. */ - if (skb_headroom(skb) < queue->desc_size) { - if (pskb_expand_head(skb, queue->desc_size, 0, GFP_ATOMIC)) { + if (skb_headroom(skb) < intf->beacon->queue->desc_size) { + if (pskb_expand_head(skb, intf->beacon->queue->desc_size, + 0, GFP_ATOMIC)) { dev_kfree_skb(skb); return -ENOMEM; } @@ -2405,29 +2419,36 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case the ieee80211 doesn't set this, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, * and kick the beacon generator. */ - rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0, + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, skb->data, skb->len); - rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt61pci_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -2469,9 +2490,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, - .config_mac_addr = rt61pci_config_mac_addr, - .config_bssid = rt61pci_config_bssid, - .config_type = rt61pci_config_type, + .config_intf = rt61pci_config_intf, .config_preamble = rt61pci_config_preamble, .config = rt61pci_config, }; @@ -2491,7 +2510,7 @@ static const struct data_queue_desc rt61pci_queue_tx = { }; static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 4 * BEACON_ENTRIES, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci_tx), @@ -2499,6 +2518,8 @@ static const struct data_queue_desc rt61pci_queue_bcn = { static const struct rt2x00_ops rt61pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt61pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 10519f8c5783..d291c0fe405c 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -161,7 +161,9 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE1 0x2d00 #define HW_BEACON_BASE2 0x2e00 #define HW_BEACON_BASE3 0x2f00 -#define HW_BEACON_OFFSET 0x0100 + +#define HW_BEACON_OFFSET(__index) \ + ( HW_BEACON_BASE0 + (__index * 0x0100) ) /* * HOST-MCU shared memory. @@ -234,6 +236,11 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR3: STA MAC register 1. + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK */ #define MAC_CSR3 0x300c #define MAC_CSR3_BYTE4 FIELD32(0x000000ff) @@ -251,7 +258,14 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID. + * BSS_ID_MASK: + * This mask is used to mask off bits 0 and 1 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 2-BSSID mode (BSS index: byte5, bit 1) + * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) */ #define MAC_CSR5 0x3014 #define MAC_CSR5_BYTE4 FIELD32(0x000000ff) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 8ebf3fed9815..7907fd0d4aa5 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -281,74 +281,69 @@ static const struct rt2x00debug rt73usb_rt2x00debug = { /* * Configuration handlers. */ -static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) +static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - u32 tmp; - - tmp = le32_to_cpu(mac[1]); - rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - mac[1] = cpu_to_le32(tmp); - - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (2 * sizeof(__le32))); -} + unsigned int beacon_base; + u32 reg; -static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) -{ - u32 tmp; + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); + rt73usb_register_write(rt2x00dev, beacon_base, 0); - tmp = le32_to_cpu(bssid[1]); - rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); - bssid[1] = cpu_to_le32(tmp); + /* + * Enable synchronisation. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); -static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, + conf->mac, sizeof(conf->mac)); + } - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); + conf->bssid[1] = cpu_to_le32(reg); - /* - * Enable synchronisation. - */ - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, - (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, + conf->bssid, sizeof(conf->bssid)); + } } -static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u32 reg; /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. + * When in atomic context, we should let rt2x00lib + * try this configuration again later. */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); - return; - } + if (in_atomic()) + return -EAGAIN; rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); @@ -358,6 +353,8 @@ static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!short_preamble); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); + + return 0; } static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -617,8 +614,8 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt73usb_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt73usb_config_phymode(rt2x00dev, libconf->basic_rates); @@ -765,6 +762,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) } } + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Special big-R17 for very short distance */ @@ -815,6 +819,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) return; } +dynamic_cca_tune: + /* * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. @@ -1020,6 +1026,17 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + /* * We must clear the error counters. * These registers are cleared on read, @@ -1985,52 +2002,52 @@ static void rt73usb_reset_tsf(struct ieee80211_hw *hw) } static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ieee80211_tx_control *control) + struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; - int timeout; + unsigned int beacon_base; + unsigned int timeout; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); + if (unlikely(!intf->beacon)) + return -ENOBUFS; /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case the ieee80211 doesn't set this, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, * and kick the beacon generator. */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32)); rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - HW_BEACON_BASE0, 0x0000, + USB_VENDOR_REQUEST_OUT, beacon_base, 0, skb->data, skb->len, timeout); - rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt73usb_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -2071,9 +2088,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, - .config_mac_addr = rt73usb_config_mac_addr, - .config_bssid = rt73usb_config_bssid, - .config_type = rt73usb_config_type, + .config_intf = rt73usb_config_intf, .config_preamble = rt73usb_config_preamble, .config = rt73usb_config, }; @@ -2093,7 +2108,7 @@ static const struct data_queue_desc rt73usb_queue_tx = { }; static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 4 * BEACON_ENTRIES, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb_tx), @@ -2101,6 +2116,8 @@ static const struct data_queue_desc rt73usb_queue_bcn = { static const struct rt2x00_ops rt73usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt73usb_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index da62b4f091a7..3f9675655eb9 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -114,6 +114,9 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE2 0x2600 #define HW_BEACON_BASE3 0x2700 +#define HW_BEACON_OFFSET(__index) \ + ( HW_BEACON_BASE0 + (__index * 0x0100) ) + /* * MAC Control/Status Registers(CSR). * Some values are set in TU, whereas 1 TU == 1024 us. @@ -146,6 +149,11 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR3: STA MAC register 1. + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK */ #define MAC_CSR3 0x300c #define MAC_CSR3_BYTE4 FIELD32(0x000000ff) @@ -163,7 +171,14 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID. + * BSS_ID_MASK: + * This mask is used to mask off bits 0 and 1 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 2-BSSID mode (BSS index: byte5, bit 1) + * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) */ #define MAC_CSR5 0x3014 #define MAC_CSR5_BYTE4 FIELD32(0x000000ff) -- cgit v1.2.3-59-g8ed1b From 8318d78a44d49ac1edf2bdec7299de3617c4232e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Jan 2008 19:38:38 +0100 Subject: cfg80211 API for channels/bitrates, mac80211 and driver conversion This patch creates new cfg80211 wiphy API for channel and bitrate registration and converts mac80211 and drivers to the new API. The old mac80211 API is completely ripped out. All drivers (except ath5k) are updated to the new API, in many cases I expect that optimisations can be done. Along with the regulatory code I've also ripped out the IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag, I believe it to be unnecessary if the hardware simply gives us whatever channels it wants to support and we then enable/disable them as required, which is pretty much required for travelling. Additionally, the patch adds proper "basic" rate handling for STA mode interface, AP mode interface will have to have new API added to allow userspace to set the basic rate set, currently it'll be empty... However, the basic rate handling will need to be moved to the BSS conf stuff. I do expect there to be bugs in this, especially wrt. transmit power handling where I'm basically clueless about how it should work. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/adm8211.c | 80 ++--- drivers/net/wireless/adm8211.h | 65 +--- drivers/net/wireless/b43/b43.h | 5 - drivers/net/wireless/b43/main.c | 119 +++---- drivers/net/wireless/b43/sysfs.c | 89 +----- drivers/net/wireless/b43/xmit.c | 81 ++--- drivers/net/wireless/b43legacy/b43legacy.h | 4 - drivers/net/wireless/b43legacy/main.c | 159 +++++----- drivers/net/wireless/b43legacy/xmit.c | 64 ++-- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 88 +++--- drivers/net/wireless/iwlwifi/iwl-3945.c | 35 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 13 +- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 82 ++--- drivers/net/wireless/iwlwifi/iwl-4965.c | 43 ++- drivers/net/wireless/iwlwifi/iwl-4965.h | 16 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 445 ++++++++------------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 438 +++++++------------------- drivers/net/wireless/p54.h | 4 - drivers/net/wireless/p54common.c | 74 +++-- drivers/net/wireless/p54common.h | 75 ----- drivers/net/wireless/rt2x00/rt2x00.h | 11 +- drivers/net/wireless/rt2x00/rt2x00config.c | 33 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 149 ++++----- drivers/net/wireless/rt2x00/rt61pci.c | 23 +- drivers/net/wireless/rt2x00/rt73usb.c | 23 +- drivers/net/wireless/rtl8180.h | 2 +- drivers/net/wireless/rtl8180_dev.c | 93 ++++-- drivers/net/wireless/rtl8180_grf5101.c | 5 +- drivers/net/wireless/rtl8180_max2820.c | 5 +- drivers/net/wireless/rtl8180_rtl8225.c | 15 +- drivers/net/wireless/rtl8180_sa2400.c | 5 +- drivers/net/wireless/rtl8187.h | 2 +- drivers/net/wireless/rtl8187_dev.c | 82 +++-- drivers/net/wireless/rtl8187_rtl8225.c | 15 +- drivers/net/wireless/rtl818x.h | 70 ----- drivers/net/wireless/zd1211rw/zd_chip.c | 15 +- drivers/net/wireless/zd1211rw/zd_ieee80211.c | 11 +- drivers/net/wireless/zd1211rw/zd_mac.c | 170 +++++----- drivers/net/wireless/zd1211rw/zd_mac.h | 2 +- include/net/mac80211.h | 197 ++---------- include/net/wireless.h | 168 ++++++++++ net/mac80211/Makefile | 1 - net/mac80211/cfg.c | 11 +- net/mac80211/debugfs.c | 47 +-- net/mac80211/debugfs_sta.c | 18 -- net/mac80211/ieee80211.c | 112 +++---- net/mac80211/ieee80211_i.h | 63 +--- net/mac80211/ieee80211_iface.c | 2 + net/mac80211/ieee80211_ioctl.c | 127 ++++---- net/mac80211/ieee80211_rate.c | 15 +- net/mac80211/ieee80211_rate.h | 28 +- net/mac80211/ieee80211_sta.c | 384 ++++++++++++----------- net/mac80211/rc80211_pid_algo.c | 76 ++--- net/mac80211/rc80211_simple.c | 66 ++-- net/mac80211/regdomain.c | 152 --------- net/mac80211/rx.c | 82 ++--- net/mac80211/sta_info.c | 24 -- net/mac80211/sta_info.h | 10 +- net/mac80211/tx.c | 164 ++++++---- net/mac80211/util.c | 142 ++------- net/wireless/Makefile | 2 +- net/wireless/core.c | 41 +++ net/wireless/core.h | 3 + net/wireless/reg.c | 153 +++++++++ net/wireless/util.c | 98 ++++++ 66 files changed, 2116 insertions(+), 2781 deletions(-) delete mode 100644 net/mac80211/regdomain.c create mode 100644 net/wireless/reg.c create mode 100644 net/wireless/util.c (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 714a6ca30ad2..cd5fcc67e954 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -735,6 +735,7 @@ config P54_PCI config ATH5K tristate "Atheros 5xxx wireless cards support" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + depends on BROKEN ---help--- This module adds support for wireless adapters based on Atheros 5xxx chipset. diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 79796186713e..7d4218206c47 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -48,6 +48,32 @@ static struct pci_device_id adm8211_pci_id_table[] __devinitdata = { { 0 } }; +static struct ieee80211_rate adm8211_rates[] = { + { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */ +}; + +static const struct ieee80211_channel adm8211_channels[] = { + { .center_freq = 2412}, + { .center_freq = 2417}, + { .center_freq = 2422}, + { .center_freq = 2427}, + { .center_freq = 2432}, + { .center_freq = 2437}, + { .center_freq = 2442}, + { .center_freq = 2447}, + { .center_freq = 2452}, + { .center_freq = 2457}, + { .center_freq = 2462}, + { .center_freq = 2467}, + { .center_freq = 2472}, + { .center_freq = 2484}, +}; + + static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom) { struct adm8211_priv *priv = eeprom->data; @@ -155,17 +181,17 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev) printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n", pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max); - priv->modes[0].num_channels = chan_range.max - chan_range.min + 1; - priv->modes[0].channels = priv->channels; + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels)); - memcpy(priv->channels, adm8211_channels, sizeof(adm8211_channels)); + memcpy(priv->channels, adm8211_channels, sizeof(priv->channels)); + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(adm8211_channels); + priv->band.bitrates = adm8211_rates; + priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates); for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++) - if (i >= chan_range.min && i <= chan_range.max) - priv->channels[i - 1].flag = - IEEE80211_CHAN_W_SCAN | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_IBSS; + if (i < chan_range.min || i > chan_range.max) + priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED; switch (priv->eeprom->specific_bbptype) { case ADM8211_BBP_RFMD3000: @@ -347,7 +373,6 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) unsigned int pktlen; struct sk_buff *skb, *newskb; unsigned int limit = priv->rx_ring_size; - static const u8 rate_tbl[] = {10, 20, 55, 110, 220}; u8 rssi, rate; while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) { @@ -425,12 +450,10 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) else rx_status.ssi = 100 - rssi; - if (rate <= 4) - rx_status.rate = rate_tbl[rate]; + rx_status.rate_idx = rate; - rx_status.channel = priv->channel; - rx_status.freq = adm8211_channels[priv->channel - 1].freq; - rx_status.phymode = MODE_IEEE80211B; + rx_status.freq = adm8211_channels[priv->channel - 1].center_freq; + rx_status.band = IEEE80211_BAND_2GHZ; ieee80211_rx_irqsafe(dev, skb, &rx_status); } @@ -1054,7 +1077,7 @@ static int adm8211_set_rate(struct ieee80211_hw *dev) if (priv->pdev->revision != ADM8211_REV_BA) { rate_buf[0] = ARRAY_SIZE(adm8211_rates); for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++) - rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80; + rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80; } else { /* workaround for rev BA specific bug */ rate_buf[0] = 0x04; @@ -1303,9 +1326,10 @@ static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len) static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct adm8211_priv *priv = dev->priv; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - if (conf->channel != priv->channel) { - priv->channel = conf->channel; + if (channel != priv->channel) { + priv->channel = channel; adm8211_rf_set_channel(dev, priv->channel); } @@ -1680,10 +1704,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb, if (control->tx_rate < 0) { short_preamble = 1; - plcp_signal = -control->tx_rate; + plcp_signal = -control->tx_rate->bitrate; } else { short_preamble = 0; - plcp_signal = control->tx_rate; + plcp_signal = control->tx_rate->bitrate; } hdr = (struct ieee80211_hdr *)skb->data; @@ -1880,18 +1904,11 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, SET_IEEE80211_PERM_ADDR(dev, perm_addr); dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); - dev->flags = IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED; - /* IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ + /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ dev->channel_change_time = 1000; dev->max_rssi = 100; /* FIXME: find better value */ - priv->modes[0].mode = MODE_IEEE80211B; - /* channel info filled in by adm8211_read_eeprom */ - memcpy(priv->rates, adm8211_rates, sizeof(adm8211_rates)); - priv->modes[0].num_rates = ARRAY_SIZE(adm8211_rates); - priv->modes[0].rates = priv->rates; - dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */ priv->retry_limit = 3; @@ -1917,14 +1934,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, goto err_free_desc; } - priv->channel = priv->modes[0].channels[0].chan; - - err = ieee80211_register_hwmode(dev, &priv->modes[0]); - if (err) { - printk(KERN_ERR "%s (adm8211): Can't register hwmode\n", - pci_name(pdev)); - goto err_free_desc; - } + priv->channel = 1; err = ieee80211_register_hw(dev); if (err) { diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h index ef326fed42e4..8d7c564b3b04 100644 --- a/drivers/net/wireless/adm8211.h +++ b/drivers/net/wireless/adm8211.h @@ -534,61 +534,6 @@ struct adm8211_eeprom { u8 cis_data[0]; /* 0x80, 384 bytes */ } __attribute__ ((packed)); -static const struct ieee80211_rate adm8211_rates[] = { - { .rate = 10, - .val = 10, - .val2 = -10, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 20, - .val = 20, - .val2 = -20, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 55, - .val = 55, - .val2 = -55, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 110, - .val = 110, - .val2 = -110, - .flags = IEEE80211_RATE_CCK_2 } -}; - -struct ieee80211_chan_range { - u8 min; - u8 max; -}; - -static const struct ieee80211_channel adm8211_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484}, -}; - struct adm8211_priv { struct pci_dev *pdev; spinlock_t lock; @@ -603,9 +548,8 @@ struct adm8211_priv { unsigned int cur_tx, dirty_tx, cur_rx; struct ieee80211_low_level_stats stats; - struct ieee80211_hw_mode modes[1]; - struct ieee80211_channel channels[ARRAY_SIZE(adm8211_channels)]; - struct ieee80211_rate rates[ARRAY_SIZE(adm8211_rates)]; + struct ieee80211_supported_band band; + struct ieee80211_channel channels[14]; int mode; int channel; @@ -643,6 +587,11 @@ struct adm8211_priv { } transceiver_type; }; +struct ieee80211_chan_range { + u8 min; + u8 max; +}; + static const struct ieee80211_chan_range cranges[] = { {1, 11}, /* FCC */ {1, 11}, /* IC */ diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f13346ba9dd2..3e40323cd43f 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -468,10 +468,6 @@ struct b43_phy { u8 possible_phymodes; /* GMODE bit enabled? */ bool gmode; - /* Possible ieee80211 subsystem hwmodes for this PHY. - * Which mode is selected, depends on thr GMODE enabled bit */ -#define B43_MAX_PHYHWMODES 2 - struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES]; /* Analog Type */ u8 analog; @@ -727,7 +723,6 @@ struct b43_wldev { bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ - bool short_preamble; /* TRUE, if short preamble is enabled. */ bool short_slot; /* TRUE, if short slot timing is enabled. */ bool radio_hw_enable; /* saved state of radio hardware enabled state */ bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 51dfce16178a..017a041d07d0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -96,25 +96,29 @@ MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl); * data in there. This data is the same for all devices, so we don't * get concurrency issues */ #define RATETAB_ENT(_rateid, _flags) \ - { \ - .rate = B43_RATE_TO_BASE100KBPS(_rateid), \ - .val = (_rateid), \ - .val2 = (_rateid), \ - .flags = (_flags), \ + { \ + .bitrate = B43_RATE_TO_BASE100KBPS(_rateid), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ } + +/* + * NOTE: When changing this, sync with xmit.c's + * b43_plcp_get_bitrate_idx_* functions! + */ static struct ieee80211_rate __b43_ratetable[] = { - RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK), - RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM), + RATETAB_ENT(B43_CCK_RATE_1MB, 0), + RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43_OFDM_RATE_6MB, 0), + RATETAB_ENT(B43_OFDM_RATE_9MB, 0), + RATETAB_ENT(B43_OFDM_RATE_12MB, 0), + RATETAB_ENT(B43_OFDM_RATE_18MB, 0), + RATETAB_ENT(B43_OFDM_RATE_24MB, 0), + RATETAB_ENT(B43_OFDM_RATE_36MB, 0), + RATETAB_ENT(B43_OFDM_RATE_48MB, 0), + RATETAB_ENT(B43_OFDM_RATE_54MB, 0), }; #define b43_a_ratetable (__b43_ratetable + 4) @@ -126,14 +130,8 @@ static struct ieee80211_rate __b43_ratetable[] = { #define CHANTAB_ENT(_chanid, _freq) \ { \ - .chan = (_chanid), \ - .freq = (_freq), \ - .val = (_chanid), \ - .flag = IEEE80211_CHAN_W_SCAN | \ - IEEE80211_CHAN_W_ACTIVE_SCAN | \ - IEEE80211_CHAN_W_IBSS, \ - .power_level = 0xFF, \ - .antenna_max = 0xFF, \ + .center_freq = (_freq), \ + .hw_value = (_chanid), \ } static struct ieee80211_channel b43_2ghz_chantable[] = { CHANTAB_ENT(1, 2412), @@ -151,9 +149,8 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { CHANTAB_ENT(13, 2472), CHANTAB_ENT(14, 2484), }; -#define b43_2ghz_chantable_size ARRAY_SIZE(b43_2ghz_chantable) -#if 0 +#ifdef NOTYET static struct ieee80211_channel b43_5ghz_chantable[] = { CHANTAB_ENT(36, 5180), CHANTAB_ENT(40, 5200), @@ -169,9 +166,22 @@ static struct ieee80211_channel b43_5ghz_chantable[] = { CHANTAB_ENT(161, 5805), CHANTAB_ENT(165, 5825), }; -#define b43_5ghz_chantable_size ARRAY_SIZE(b43_5ghz_chantable) + +static struct ieee80211_supported_band b43_band_5GHz = { + .channels = b43_5ghz_chantable, + .n_channels = ARRAY_SIZE(b43_5ghz_chantable), + .bitrates = b43_a_ratetable, + .n_bitrates = b43_a_ratetable_size, +}; #endif +static struct ieee80211_supported_band b43_band_2GHz = { + .channels = b43_2ghz_chantable, + .n_channels = ARRAY_SIZE(b43_2ghz_chantable), + .bitrates = b43_g_ratetable, + .n_bitrates = b43_g_ratetable_size, +}; + static void b43_wireless_core_exit(struct b43_wldev *dev); static int b43_wireless_core_init(struct b43_wldev *dev); static void b43_wireless_core_stop(struct b43_wldev *dev); @@ -1222,17 +1232,18 @@ static void b43_write_beacon_template(struct b43_wldev *dev, } static void b43_write_probe_resp_plcp(struct b43_wldev *dev, - u16 shm_offset, u16 size, u8 rate) + u16 shm_offset, u16 size, + struct ieee80211_rate *rate) { struct b43_plcp_hdr4 plcp; u32 tmp; __le16 dur; plcp.data = 0; - b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); + b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, size, - B43_RATE_TO_BASE100KBPS(rate)); + rate); /* Write PLCP in two parts and timing for packet transfer */ tmp = le32_to_cpu(plcp.data); b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF); @@ -1247,7 +1258,8 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev, * 3) Stripping TIM */ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev, - u16 *dest_size, u8 rate) + u16 *dest_size, + struct ieee80211_rate *rate) { const u8 *src_data; u8 *dest_data; @@ -1292,7 +1304,7 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev, IEEE80211_STYPE_PROBE_RESP); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, *dest_size, - B43_RATE_TO_BASE100KBPS(rate)); + rate); hdr->duration_id = dur; return dest_data; @@ -1300,7 +1312,8 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev, static void b43_write_probe_resp_template(struct b43_wldev *dev, u16 ram_offset, - u16 shm_size_offset, u8 rate) + u16 shm_size_offset, + struct ieee80211_rate *rate) { const u8 *probe_resp_data; u16 size; @@ -1313,14 +1326,15 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev, /* Looks like PLCP headers plus packet timings are stored for * all possible basic rates */ - b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB); - b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB); - b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB); - b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB); + b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]); + b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]); + b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]); + b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]); size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6)); b43_write_template_common(dev, probe_resp_data, - size, ram_offset, shm_size_offset, rate); + size, ram_offset, shm_size_offset, + rate->hw_value); kfree(probe_resp_data); } @@ -1388,7 +1402,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB); b43_write_probe_resp_template(dev, 0x268, 0x4A, - B43_CCK_RATE_11MB); + &__b43_ratetable[3]); wl->beacon0_uploaded = 1; } cmd |= B43_MACCMD_BEACON0_VALID; @@ -2830,14 +2844,11 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) mutex_lock(&wl->mutex); /* Switch the PHY mode (if necessary). */ - switch (conf->phymode) { - case MODE_IEEE80211A: + switch (conf->channel->band) { + case IEEE80211_BAND_5GHZ: new_phymode = B43_PHYMODE_A; break; - case MODE_IEEE80211B: - new_phymode = B43_PHYMODE_B; - break; - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: new_phymode = B43_PHYMODE_G; break; default: @@ -2863,8 +2874,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) /* Switch to the requested channel. * The firmware takes care of races with the TX handler. */ - if (conf->channel_val != phy->channel) - b43_radio_selectchannel(dev, conf->channel_val, 0); + if (conf->channel->hw_value != phy->channel) + b43_radio_selectchannel(dev, conf->channel->hw_value, 0); /* Enable/Disable ShortSlot timing. */ if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != @@ -3810,9 +3821,7 @@ static int b43_setup_modes(struct b43_wldev *dev, bool have_2ghz_phy, bool have_5ghz_phy) { struct ieee80211_hw *hw = dev->wl->hw; - struct ieee80211_hw_mode *mode; struct b43_phy *phy = &dev->phy; - int err; /* XXX: This function will go away soon, when mac80211 * band stuff is rewritten. So this is just a hack. @@ -3821,15 +3830,7 @@ static int b43_setup_modes(struct b43_wldev *dev, * This assumption is OK, as any B, N or A PHY will already * have died a horrible sanity check death earlier. */ - mode = &phy->hwmodes[0]; - mode->mode = MODE_IEEE80211G; - mode->num_channels = b43_2ghz_chantable_size; - mode->channels = b43_2ghz_chantable; - mode->num_rates = b43_g_ratetable_size; - mode->rates = b43_g_ratetable; - err = ieee80211_register_hwmode(hw, mode); - if (err) - return err; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; phy->possible_phymodes |= B43_PHYMODE_G; return 0; diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c index f4faff6a7d6c..275095b8cbe7 100644 --- a/drivers/net/wireless/b43/sysfs.c +++ b/drivers/net/wireless/b43/sysfs.c @@ -47,29 +47,6 @@ static int get_integer(const char *buf, size_t count) return ret; } -static int get_boolean(const char *buf, size_t count) -{ - if (count != 0) { - if (buf[0] == '1') - return 1; - if (buf[0] == '0') - return 0; - if (count >= 4 && memcmp(buf, "true", 4) == 0) - return 1; - if (count >= 5 && memcmp(buf, "false", 5) == 0) - return 0; - if (count >= 3 && memcmp(buf, "yes", 3) == 0) - return 1; - if (count >= 2 && memcmp(buf, "no", 2) == 0) - return 0; - if (count >= 2 && memcmp(buf, "on", 2) == 0) - return 1; - if (count >= 3 && memcmp(buf, "off", 3) == 0) - return 0; - } - return -EINVAL; -} - static ssize_t b43_attr_interfmode_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -155,82 +132,18 @@ static ssize_t b43_attr_interfmode_store(struct device *dev, static DEVICE_ATTR(interference, 0644, b43_attr_interfmode_show, b43_attr_interfmode_store); -static ssize_t b43_attr_preamble_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct b43_wldev *wldev = dev_to_b43_wldev(dev); - ssize_t count; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&wldev->wl->mutex); - - if (wldev->short_preamble) - count = - snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); - else - count = - snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); - - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static ssize_t b43_attr_preamble_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct b43_wldev *wldev = dev_to_b43_wldev(dev); - unsigned long flags; - int value; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - value = get_boolean(buf, count); - if (value < 0) - return value; - mutex_lock(&wldev->wl->mutex); - spin_lock_irqsave(&wldev->wl->irq_lock, flags); - - wldev->short_preamble = !!value; - - spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static DEVICE_ATTR(shortpreamble, 0644, - b43_attr_preamble_show, b43_attr_preamble_store); - int b43_sysfs_register(struct b43_wldev *wldev) { struct device *dev = wldev->dev->dev; - int err; B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); - err = device_create_file(dev, &dev_attr_interference); - if (err) - goto out; - err = device_create_file(dev, &dev_attr_shortpreamble); - if (err) - goto err_remove_interfmode; - - out: - return err; - err_remove_interfmode: - device_remove_file(dev, &dev_attr_interference); - goto out; + return device_create_file(dev, &dev_attr_interference); } void b43_sysfs_unregister(struct b43_wldev *wldev) { struct device *dev = wldev->dev->dev; - device_remove_file(dev, &dev_attr_shortpreamble); device_remove_file(dev, &dev_attr_interference); } diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 7caa26eb4105..4014b6c8272b 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -32,46 +32,48 @@ #include "dma.h" -/* Extract the bitrate out of a CCK PLCP header. */ -static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp) +/* Extract the bitrate index out of a CCK PLCP header. */ +static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) { switch (plcp->raw[0]) { case 0x0A: - return B43_CCK_RATE_1MB; + return 0; case 0x14: - return B43_CCK_RATE_2MB; + return 1; case 0x37: - return B43_CCK_RATE_5MB; + return 2; case 0x6E: - return B43_CCK_RATE_11MB; + return 3; } B43_WARN_ON(1); - return 0; + return -1; } -/* Extract the bitrate out of an OFDM PLCP header. */ -static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp) +/* Extract the bitrate index out of an OFDM PLCP header. */ +static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) { + int base = aphy ? 0 : 4; + switch (plcp->raw[0] & 0xF) { case 0xB: - return B43_OFDM_RATE_6MB; + return base + 0; case 0xF: - return B43_OFDM_RATE_9MB; + return base + 1; case 0xA: - return B43_OFDM_RATE_12MB; + return base + 2; case 0xE: - return B43_OFDM_RATE_18MB; + return base + 3; case 0x9: - return B43_OFDM_RATE_24MB; + return base + 4; case 0xD: - return B43_OFDM_RATE_36MB; + return base + 5; case 0x8: - return B43_OFDM_RATE_48MB; + return base + 6; case 0xC: - return B43_OFDM_RATE_54MB; + return base + 7; } B43_WARN_ON(1); - return 0; + return -1; } u8 b43_plcp_get_ratecode_cck(const u8 bitrate) @@ -191,6 +193,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, (const struct ieee80211_hdr *)fragment_data; int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); u16 fctl = le16_to_cpu(wlhdr->frame_control); + struct ieee80211_rate *fbrate; u8 rate, rate_fb; int rate_ofdm, rate_fb_ofdm; unsigned int plcp_fragment_len; @@ -200,9 +203,11 @@ int b43_generate_txhdr(struct b43_wldev *dev, memset(txhdr, 0, sizeof(*txhdr)); - rate = txctl->tx_rate; + WARN_ON(!txctl->tx_rate); + rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB; rate_ofdm = b43_is_ofdm_rate(rate); - rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate; + fbrate = txctl->alt_retry_rate ? : txctl->tx_rate; + rate_fb = fbrate->hw_value; rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); if (rate_ofdm) @@ -221,11 +226,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, * use the original dur_id field. */ txhdr->dur_fb = wlhdr->duration_id; } else { - int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb); txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, txctl->vif, fragment_len, - fbrate_base100kbps); + fbrate); } plcp_fragment_len = fragment_len + FCS_LEN; @@ -287,7 +291,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, phy_ctl |= B43_TXH_PHY_ENC_OFDM; else phy_ctl |= B43_TXH_PHY_ENC_CCK; - if (dev->short_preamble) + if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) phy_ctl |= B43_TXH_PHY_SHORTPRMBL; switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { @@ -332,7 +336,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, int rts_rate_ofdm, rts_rate_fb_ofdm; struct b43_plcp_hdr6 *plcp; - rts_rate = txctl->rts_cts_rate; + WARN_ON(!txctl->rts_cts_rate); + rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB; rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); rts_rate_fb = b43_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); @@ -506,6 +511,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) u16 phystat0, phystat3, chanstat, mactime; u32 macstat; u16 chanid; + u16 phytype; u8 jssi; int padding; @@ -518,6 +524,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) macstat = le32_to_cpu(rxhdr->mac_status); mactime = le16_to_cpu(rxhdr->mac_time); chanstat = le16_to_cpu(rxhdr->channel); + phytype = chanstat & B43_RX_CHAN_PHYTYPE; if (macstat & B43_RX_MAC_FCSERR) dev->wl->ieee_stats.dot11FCSErrorCount++; @@ -575,9 +582,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) /* the next line looks wrong, but is what mac80211 wants */ status.signal = (jssi * 100) / B43_RX_MAX_SSI; if (phystat0 & B43_RX_PHYST0_OFDM) - status.rate = b43_plcp_get_bitrate_ofdm(plcp); + status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, + phytype == B43_PHYTYPE_A); else - status.rate = b43_plcp_get_bitrate_cck(plcp); + status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); /* @@ -601,29 +609,28 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; switch (chanstat & B43_RX_CHAN_PHYTYPE) { case B43_PHYTYPE_A: - status.phymode = MODE_IEEE80211A; + status.band = IEEE80211_BAND_5GHZ; B43_WARN_ON(1); /* FIXME: We don't really know which value the "chanid" contains. * So the following assignment might be wrong. */ - status.channel = chanid; - status.freq = b43_channel_to_freq_5ghz(status.channel); + status.freq = b43_channel_to_freq_5ghz(chanid); break; case B43_PHYTYPE_G: - status.phymode = MODE_IEEE80211G; + status.band = IEEE80211_BAND_2GHZ; /* chanid is the radio channel cookie value as used * to tune the radio. */ status.freq = chanid + 2400; - status.channel = b43_freq_to_channel_2ghz(status.freq); break; case B43_PHYTYPE_N: - status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/; /* chanid is the SHM channel cookie. Which is the plain * channel number in b43. */ - status.channel = chanid; - if (chanstat & B43_RX_CHAN_5GHZ) - status.freq = b43_freq_to_channel_5ghz(status.freq); - else - status.freq = b43_freq_to_channel_2ghz(status.freq); + if (chanstat & B43_RX_CHAN_5GHZ) { + status.band = IEEE80211_BAND_5GHZ; + status.freq = b43_freq_to_channel_5ghz(chanid); + } else { + status.band = IEEE80211_BAND_2GHZ; + status.freq = b43_freq_to_channel_2ghz(chanid); + } break; default: B43_WARN_ON(1); diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 93d45b71799a..5f217d6d2e6a 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -392,10 +392,6 @@ struct b43legacy_phy { u8 possible_phymodes; /* GMODE bit enabled in MACCTL? */ bool gmode; - /* Possible ieee80211 subsystem hwmodes for this PHY. - * Which mode is selected, depends on thr GMODE enabled bit */ -#define B43legacy_MAX_PHYHWMODES 2 - struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES]; /* Analog Type */ u8 analog; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c39de422e220..d2a72a2cd178 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -95,28 +95,29 @@ MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl); * data in there. This data is the same for all devices, so we don't * get concurrency issues */ #define RATETAB_ENT(_rateid, _flags) \ - { \ - .rate = B43legacy_RATE_TO_100KBPS(_rateid), \ - .val = (_rateid), \ - .val2 = (_rateid), \ - .flags = (_flags), \ + { \ + .bitrate = B43legacy_RATE_TO_100KBPS(_rateid), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ } +/* + * NOTE: When changing this, sync with xmit.c's + * b43legacy_plcp_get_bitrate_idx_* functions! + */ static struct ieee80211_rate __b43legacy_ratetable[] = { - RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK), - RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM), + RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0), + RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0), }; -#define b43legacy_a_ratetable (__b43legacy_ratetable + 4) -#define b43legacy_a_ratetable_size 8 #define b43legacy_b_ratetable (__b43legacy_ratetable + 0) #define b43legacy_b_ratetable_size 4 #define b43legacy_g_ratetable (__b43legacy_ratetable + 0) @@ -124,14 +125,8 @@ static struct ieee80211_rate __b43legacy_ratetable[] = { #define CHANTAB_ENT(_chanid, _freq) \ { \ - .chan = (_chanid), \ - .freq = (_freq), \ - .val = (_chanid), \ - .flag = IEEE80211_CHAN_W_SCAN | \ - IEEE80211_CHAN_W_ACTIVE_SCAN | \ - IEEE80211_CHAN_W_IBSS, \ - .power_level = 0x0A, \ - .antenna_max = 0xFF, \ + .center_freq = (_freq), \ + .hw_value = (_chanid), \ } static struct ieee80211_channel b43legacy_bg_chantable[] = { CHANTAB_ENT(1, 2412), @@ -149,7 +144,20 @@ static struct ieee80211_channel b43legacy_bg_chantable[] = { CHANTAB_ENT(13, 2472), CHANTAB_ENT(14, 2484), }; -#define b43legacy_bg_chantable_size ARRAY_SIZE(b43legacy_bg_chantable) + +static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = { + .channels = b43legacy_bg_chantable, + .n_channels = ARRAY_SIZE(b43legacy_bg_chantable), + .bitrates = b43legacy_b_ratetable, + .n_bitrates = b43legacy_b_ratetable_size, +}; + +static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = { + .channels = b43legacy_bg_chantable, + .n_channels = ARRAY_SIZE(b43legacy_bg_chantable), + .bitrates = b43legacy_g_ratetable, + .n_bitrates = b43legacy_g_ratetable_size, +}; static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev); static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev); @@ -969,18 +977,18 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, u16 shm_offset, u16 size, - u8 rate) + struct ieee80211_rate *rate) { struct b43legacy_plcp_hdr4 plcp; u32 tmp; __le16 dur; plcp.data = 0; - b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); + b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, size, - B43legacy_RATE_TO_100KBPS(rate)); + rate); /* Write PLCP in two parts and timing for packet transfer */ tmp = le32_to_cpu(plcp.data); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset, @@ -998,7 +1006,8 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, * 3) Stripping TIM */ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, - u16 *dest_size, u8 rate) + u16 *dest_size, + struct ieee80211_rate *rate) { const u8 *src_data; u8 *dest_data; @@ -1046,7 +1055,7 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, *dest_size, - B43legacy_RATE_TO_100KBPS(rate)); + rate); hdr->duration_id = dur; return dest_data; @@ -1054,7 +1063,8 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, u16 ram_offset, - u16 shm_size_offset, u8 rate) + u16 shm_size_offset, + struct ieee80211_rate *rate) { u8 *probe_resp_data; u16 size; @@ -1069,19 +1079,19 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, * all possible basic rates */ b43legacy_write_probe_resp_plcp(dev, 0x31A, size, - B43legacy_CCK_RATE_1MB); + &b43legacy_b_ratetable[0]); b43legacy_write_probe_resp_plcp(dev, 0x32C, size, - B43legacy_CCK_RATE_2MB); + &b43legacy_b_ratetable[1]); b43legacy_write_probe_resp_plcp(dev, 0x33E, size, - B43legacy_CCK_RATE_5MB); + &b43legacy_b_ratetable[2]); b43legacy_write_probe_resp_plcp(dev, 0x350, size, - B43legacy_CCK_RATE_11MB); + &b43legacy_b_ratetable[3]); size = min((size_t)size, 0x200 - sizeof(struct b43legacy_plcp_hdr6)); b43legacy_write_template_common(dev, probe_resp_data, size, ram_offset, - shm_size_offset, rate); + shm_size_offset, rate->bitrate); kfree(probe_resp_data); } @@ -1106,7 +1116,7 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev) b43legacy_write_beacon_template(dev, 0x468, 0x1A, B43legacy_CCK_RATE_1MB); b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, - B43legacy_CCK_RATE_11MB); + &b43legacy_b_ratetable[0]); status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); status |= 0x03; @@ -2550,14 +2560,16 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx); mutex_lock(&wl->mutex); + dev = wl->current_dev; + phy = &dev->phy; /* Switch the PHY mode (if necessary). */ - switch (conf->phymode) { - case MODE_IEEE80211B: - new_phymode = B43legacy_PHYMODE_B; - break; - case MODE_IEEE80211G: - new_phymode = B43legacy_PHYMODE_G; + switch (conf->channel->band) { + case IEEE80211_BAND_2GHZ: + if (phy->type == B43legacy_PHYTYPE_B) + new_phymode = B43legacy_PHYMODE_B; + else + new_phymode = B43legacy_PHYMODE_G; break; default: B43legacy_WARN_ON(1); @@ -2565,8 +2577,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, err = b43legacy_switch_phymode(wl, new_phymode); if (err) goto out_unlock_mutex; - dev = wl->current_dev; - phy = &dev->phy; /* Disable IRQs while reconfiguring the device. * This makes it possible to drop the spinlock throughout @@ -2582,8 +2592,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, /* Switch to the requested channel. * The firmware takes care of races with the TX handler. */ - if (conf->channel_val != phy->channel) - b43legacy_radio_selectchannel(dev, conf->channel_val, 0); + if (conf->channel->hw_value != phy->channel) + b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0); /* Enable/Disable ShortSlot timing. */ if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) @@ -3398,48 +3408,19 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev, int have_gphy) { struct ieee80211_hw *hw = dev->wl->hw; - struct ieee80211_hw_mode *mode; struct b43legacy_phy *phy = &dev->phy; - int cnt = 0; - int err; phy->possible_phymodes = 0; - for (; 1; cnt++) { - if (have_bphy) { - B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES); - mode = &phy->hwmodes[cnt]; - - mode->mode = MODE_IEEE80211B; - mode->num_channels = b43legacy_bg_chantable_size; - mode->channels = b43legacy_bg_chantable; - mode->num_rates = b43legacy_b_ratetable_size; - mode->rates = b43legacy_b_ratetable; - err = ieee80211_register_hwmode(hw, mode); - if (err) - return err; - - phy->possible_phymodes |= B43legacy_PHYMODE_B; - have_bphy = 0; - continue; - } - if (have_gphy) { - B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES); - mode = &phy->hwmodes[cnt]; - - mode->mode = MODE_IEEE80211G; - mode->num_channels = b43legacy_bg_chantable_size; - mode->channels = b43legacy_bg_chantable; - mode->num_rates = b43legacy_g_ratetable_size; - mode->rates = b43legacy_g_ratetable; - err = ieee80211_register_hwmode(hw, mode); - if (err) - return err; - - phy->possible_phymodes |= B43legacy_PHYMODE_G; - have_gphy = 0; - continue; - } - break; + if (have_bphy) { + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &b43legacy_band_2GHz_BPHY; + phy->possible_phymodes |= B43legacy_PHYMODE_B; + } + + if (have_gphy) { + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &b43legacy_band_2GHz_GPHY; + phy->possible_phymodes |= B43legacy_PHYMODE_G; } return 0; diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index d84408a82db9..47e130e9fdf2 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -37,45 +37,48 @@ /* Extract the bitrate out of a CCK PLCP header. */ -static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp) +static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp) { switch (plcp->raw[0]) { case 0x0A: - return B43legacy_CCK_RATE_1MB; + return 0; case 0x14: - return B43legacy_CCK_RATE_2MB; + return 1; case 0x37: - return B43legacy_CCK_RATE_5MB; + return 2; case 0x6E: - return B43legacy_CCK_RATE_11MB; + return 3; } B43legacy_BUG_ON(1); - return 0; + return -1; } /* Extract the bitrate out of an OFDM PLCP header. */ -static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp) +static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp, + bool aphy) { + int base = aphy ? 0 : 4; + switch (plcp->raw[0] & 0xF) { case 0xB: - return B43legacy_OFDM_RATE_6MB; + return base + 0; case 0xF: - return B43legacy_OFDM_RATE_9MB; + return base + 1; case 0xA: - return B43legacy_OFDM_RATE_12MB; + return base + 2; case 0xE: - return B43legacy_OFDM_RATE_18MB; + return base + 3; case 0x9: - return B43legacy_OFDM_RATE_24MB; + return base + 4; case 0xD: - return B43legacy_OFDM_RATE_36MB; + return base + 5; case 0x8: - return B43legacy_OFDM_RATE_48MB; + return base + 6; case 0xC: - return B43legacy_OFDM_RATE_54MB; + return base + 7; } B43legacy_BUG_ON(1); - return 0; + return -1; } u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate) @@ -192,7 +195,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); u16 fctl; u8 rate; - u8 rate_fb; + struct ieee80211_rate *rate_fb; int rate_ofdm; int rate_fb_ofdm; unsigned int plcp_fragment_len; @@ -204,16 +207,16 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, memset(txhdr, 0, sizeof(*txhdr)); - rate = txctl->tx_rate; + rate = txctl->tx_rate->hw_value; rate_ofdm = b43legacy_is_ofdm_rate(rate); - rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate; - rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb); + rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate; + rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); txhdr->mac_frame_ctl = wlhdr->frame_control; memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); /* Calculate duration for fallback rate */ - if ((rate_fb == rate) || + if ((rate_fb->hw_value == rate) || (wlhdr->duration_id & cpu_to_le16(0x8000)) || (wlhdr->duration_id == cpu_to_le16(0))) { /* If the fallback rate equals the normal rate or the @@ -221,11 +224,10 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, * use the original dur_id field. */ txhdr->dur_fb = wlhdr->duration_id; } else { - int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb); txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, txctl->vif, fragment_len, - fbrate_base100kbps); + rate_fb); } plcp_fragment_len = fragment_len + FCS_LEN; @@ -266,7 +268,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, rate); b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) (&txhdr->plcp_fb), plcp_fragment_len, - rate_fb); + rate_fb->hw_value); /* PHY TX Control word */ if (rate_ofdm) @@ -310,7 +312,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, int rts_rate_ofdm; int rts_rate_fb_ofdm; - rts_rate = txctl->rts_cts_rate; + rts_rate = txctl->rts_cts_rate->hw_value; rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate); rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb); @@ -536,10 +538,11 @@ void b43legacy_rx(struct b43legacy_wldev *dev, (phystat3 & B43legacy_RX_PHYST3_TRSTATE)); status.noise = dev->stats.link_noise; status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI; + /* change to support A PHY */ if (phystat0 & B43legacy_RX_PHYST0_OFDM) - status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp); + status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false); else - status.rate = b43legacy_plcp_get_bitrate_cck(plcp); + status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp); status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT); /* @@ -564,14 +567,9 @@ void b43legacy_rx(struct b43legacy_wldev *dev, B43legacy_RX_CHAN_ID_SHIFT; switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) { case B43legacy_PHYTYPE_B: - status.phymode = MODE_IEEE80211B; - status.freq = chanid + 2400; - status.channel = b43legacy_freq_to_channel_bg(chanid + 2400); - break; case B43legacy_PHYTYPE_G: - status.phymode = MODE_IEEE80211G; + status.band = IEEE80211_BAND_2GHZ; status.freq = chanid + 2400; - status.channel = b43legacy_freq_to_channel_bg(chanid + 2400); break; default: b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 80d31ae51e77..f018ce464d97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -100,14 +100,6 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = { {-89, IWL_RATE_6M_INDEX} }; -static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = { - {-86, IWL_RATE_11M_INDEX}, - {-88, IWL_RATE_5M_INDEX}, - {-90, IWL_RATE_2M_INDEX}, - {-92, IWL_RATE_1M_INDEX} - -}; - static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { {-60, IWL_RATE_54M_INDEX}, {-64, IWL_RATE_48M_INDEX}, @@ -129,7 +121,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { #define IWL_RATE_MIN_SUCCESS_TH 8 #define IWL_RATE_DECREASE_TH 1920 -static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode) +static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) { u32 index = 0; u32 table_size = 0; @@ -138,21 +130,19 @@ static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode) if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL)) rssi = IWL_MIN_RSSI_VAL; - switch (mode) { - case MODE_IEEE80211G: + switch (band) { + case IEEE80211_BAND_2GHZ: tpt_table = iwl3945_tpt_table_g; table_size = ARRAY_SIZE(iwl3945_tpt_table_g); break; - case MODE_IEEE80211A: + case IEEE80211_BAND_5GHZ: tpt_table = iwl3945_tpt_table_a; table_size = ARRAY_SIZE(iwl3945_tpt_table_a); break; default: - case MODE_IEEE80211B: - tpt_table = iwl3945_tpt_table_b; - table_size = ARRAY_SIZE(iwl3945_tpt_table_b); + BUG(); break; } @@ -340,17 +330,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, * after assoc.. */ for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { - if (sta->supp_rates & (1 << i)) { - sta->txrate = i; + if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) { + sta->txrate_idx = i; break; } } - sta->last_txrate = sta->txrate; + sta->last_txrate_idx = sta->txrate_idx; - /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */ - if (local->hw.conf.phymode == MODE_IEEE80211A) - sta->last_txrate += IWL_FIRST_OFDM_RATE; + /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ + if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; IWL_DEBUG_RATE("leave\n"); } @@ -429,17 +419,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) { int next_rate = iwl3945_get_prev_ieee_rate(rate); - switch (priv->phymode) { - case MODE_IEEE80211A: + switch (priv->band) { + case IEEE80211_BAND_5GHZ: if (rate == IWL_RATE_12M_INDEX) next_rate = IWL_RATE_9M_INDEX; else if (rate == IWL_RATE_6M_INDEX) next_rate = IWL_RATE_6M_INDEX; break; +/* XXX cannot be invoked in current mac80211 so not a regression case MODE_IEEE80211B: if (rate == IWL_RATE_11M_INDEX_TABLE) next_rate = IWL_RATE_5M_INDEX_TABLE; break; + */ default: break; } @@ -465,15 +457,17 @@ static void rs_tx_status(void *priv_rate, struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct iwl3945_rs_sta *rs_sta; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; IWL_DEBUG_RATE("enter\n"); retries = tx_resp->retry_count; - first_index = tx_resp->control.tx_rate; + first_index = &sband->bitrates[0] - tx_resp->control.tx_rate; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { - IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n", - tx_resp->control.tx_rate, first_index); + IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; } @@ -561,14 +555,14 @@ static void rs_tx_status(void *priv_rate, } static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, - u8 index, u16 rate_mask, int phymode) + u8 index, u16 rate_mask, enum ieee80211_band band) { u8 high = IWL_RATE_INVALID; u8 low = IWL_RATE_INVALID; /* 802.11A walks to the next literal adjacent rate in * the rate table */ - if (unlikely(phymode == MODE_IEEE80211A)) { + if (unlikely(band == IEEE80211_BAND_5GHZ)) { int i; u32 mask; @@ -639,7 +633,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * */ static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct ieee80211_supported_band *band, + struct sk_buff *skb, struct rate_selection *sel) { u8 low = IWL_RATE_INVALID; @@ -672,16 +667,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate = rate_lowest(local, local->oper_hw_mode, sta); + sel->rate = rate_lowest(local, band, sta); if (sta) sta_info_put(sta); return; } - rate_mask = sta->supp_rates; - index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1); + rate_mask = sta->supp_rates[band->band]; + index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); - if (priv->phymode == (u8) MODE_IEEE80211A) + if (priv->band == IEEE80211_BAND_5GHZ) rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; rs_sta = (void *)sta->rate_ctrl_priv; @@ -732,7 +727,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, current_tpt = window->average_tpt; high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, - local->hw.conf.phymode); + band->band); low = high_low & 0xff; high = (high_low >> 8) & 0xff; @@ -810,11 +805,11 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, out: - sta->last_txrate = index; - if (priv->phymode == (u8) MODE_IEEE80211A) - sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE; + sta->last_txrate_idx = index; + if (priv->band == IEEE80211_BAND_5GHZ) + sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; else - sta->txrate = sta->last_txrate; + sta->txrate_idx = sta->last_txrate_idx; sta_info_put(sta); @@ -945,8 +940,9 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) spin_lock_irqsave(&rs_sta->lock, flags); rs_sta->tgg = 0; - switch (priv->phymode) { - case MODE_IEEE80211G: + switch (priv->band) { + case IEEE80211_BAND_2GHZ: + /* TODO: this always does G, not a regression */ if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { rs_sta->tgg = 1; rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; @@ -954,14 +950,11 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rs_sta->expected_tpt = iwl3945_expected_tpt_g; break; - case MODE_IEEE80211A: + case IEEE80211_BAND_5GHZ: rs_sta->expected_tpt = iwl3945_expected_tpt_a; break; - - default: - IWL_WARNING("Invalid phymode. Defaulting to 802.11b\n"); - case MODE_IEEE80211B: - rs_sta->expected_tpt = iwl3945_expected_tpt_b; + case IEEE80211_NUM_BANDS: + BUG(); break; } @@ -974,8 +967,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi); - rs_sta->start_rate = - iwl3945_get_rate_index_by_rssi(rssi, priv->phymode); + rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band); IWL_DEBUG_RATE("leave: rssi %d assign rate index: " "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8d4d91d35fd2..50d927bb2170 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -247,7 +247,7 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, * the information provided in the skb from the hardware */ s8 signal = stats->ssi; s8 noise = 0; - int rate = stats->rate; + int rate = stats->rate_idx; u64 tsf = stats->mactime; __le16 phy_flags_hw = rx_hdr->phy_flags; @@ -315,7 +315,6 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, IEEE80211_CHAN_2GHZ), &iwl3945_rt->rt_chbitmask); - rate = iwl3945_rate_index_from_plcp(rate); if (rate == -1) iwl3945_rt->rt_rate = 0; else @@ -387,11 +386,10 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, struct ieee80211_rx_status stats = { .mactime = le64_to_cpu(rx_end->timestamp), .freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)), - .channel = le16_to_cpu(rx_hdr->channel), - .phymode = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - MODE_IEEE80211G : MODE_IEEE80211A, + .band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, .antenna = 0, - .rate = rx_hdr->rate, + .rate_idx = iwl3945_rate_index_from_plcp(rx_hdr->rate), .flag = 0, }; u8 network_packet; @@ -450,8 +448,6 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, stats.ssi, stats.noise, stats.signal, rx_stats_sig_avg, rx_stats_noise_diff); - stats.freq = ieee80211chan2mhz(stats.channel); - /* can be covered by iwl3945_report_frame() in most cases */ /* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */ @@ -464,8 +460,9 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, IWL_DEBUG_STATS ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n", network_packet ? '*' : ' ', - stats.channel, stats.ssi, stats.ssi, - stats.ssi, stats.rate); + le16_to_cpu(rx_hdr->channel), + stats.ssi, stats.ssi, + stats.ssi, stats.rate_idx); if (iwl3945_debug_level & (IWL_DL_RX)) /* Set "1" to report good data frames in groups of 100 */ @@ -689,7 +686,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr, int sta_id, int tx_id) { unsigned long flags; - u16 rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1); + u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1); u16 rate_mask; int rate; u8 rts_retry_limit; @@ -1552,14 +1549,14 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) .channel = priv->active_rxon.channel, }; - txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1; + txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; ch_info = iwl3945_get_channel_info(priv, - priv->phymode, + priv->band, le16_to_cpu(priv->active_rxon.channel)); if (!ch_info) { IWL_ERROR ("Failed to get channel info for channel %d [%d]\n", - le16_to_cpu(priv->active_rxon.channel), priv->phymode); + le16_to_cpu(priv->active_rxon.channel), priv->band); return -EINVAL; } @@ -2241,8 +2238,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index; } - switch (priv->phymode) { - case MODE_IEEE80211A: + switch (priv->band) { + case IEEE80211_BAND_5GHZ: IWL_DEBUG_RATE("Select A mode rate scale\n"); /* If one of the following CCK rates is used, * have it fall back to the 6M OFDM rate */ @@ -2257,8 +2254,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index; break; - case MODE_IEEE80211B: - IWL_DEBUG_RATE("Select B mode rate scale\n"); + case IEEE80211_BAND_2GHZ: + IWL_DEBUG_RATE("Select B/G mode rate scale\n"); /* If an OFDM rate is used, have it fall back to the * 1M CCK rates */ for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++) @@ -2269,7 +2266,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) break; default: - IWL_DEBUG_RATE("Select G mode rate scale\n"); + WARN_ON(1); break; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 1da14f9bbe0f..1beb5b676797 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -195,7 +195,7 @@ struct iwl3945_channel_info { u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ - u8 phymode; /* MODE_IEEE80211{A,B,G} */ + enum ieee80211_band band; /* Radio/DSP gain settings for each "normal" data Tx rate. * These include, in addition to RF and DSP gain, a few fields for @@ -699,14 +699,14 @@ struct iwl3945_priv { struct list_head free_frames; int frames_count; - u8 phymode; + enum ieee80211_band band; int alloc_rxb_skb; bool add_radiotap; void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb); - const struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT /* spectrum measurement report caching */ @@ -937,13 +937,12 @@ static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info) static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info) { - return ch_info->phymode == MODE_IEEE80211A; + return ch_info->band == IEEE80211_BAND_5GHZ; } static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info) { - return ((ch_info->phymode == MODE_IEEE80211B) || - (ch_info->phymode == MODE_IEEE80211G)); + return ch_info->band == IEEE80211_BAND_2GHZ; } static inline int is_channel_passive(const struct iwl3945_channel_info *ch) @@ -967,7 +966,7 @@ static inline int iwl3945_rate_index_from_plcp(int plcp) } extern const struct iwl3945_channel_info *iwl3945_get_channel_info( - const struct iwl3945_priv *priv, int phymode, u16 channel); + const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); /* Requires full declaration of iwl3945_priv before including */ #include "iwl-3945-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 660671f17a3b..48a6a85355ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -139,7 +139,7 @@ struct iwl4965_lq_sta { u8 valid_antenna; u8 is_green; u8 is_dup; - u8 phymode; + enum ieee80211_band band; u8 ibss_sta_added; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ @@ -563,7 +563,8 @@ static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate, * fill "search" or "active" tx mode table. */ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, - int phymode, struct iwl4965_scale_tbl_info *tbl, + enum ieee80211_band band, + struct iwl4965_scale_tbl_info *tbl, int *rate_idx) { int index; @@ -588,7 +589,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, tbl->lq_type = LQ_NONE; else { - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -766,7 +767,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta, if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { switch_to_legacy = 1; scale_index = rs_ht_to_legacy[scale_index]; - if (lq_sta->phymode == MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -784,7 +785,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta, /* Mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { /* supp_rates has no CCK bits in A mode */ - if (lq_sta->phymode == (u8) MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) rate_mask = (u16)(rate_mask & (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); else @@ -883,9 +884,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, search_win = (struct iwl4965_rate_scale_data *) &(search_tbl->win[0]); - tx_mcs.rate_n_flags = tx_resp->control.tx_rate; + tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; - rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n", @@ -918,7 +919,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, * Each tx attempt steps one entry deeper in the rate table. */ tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags); - rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); /* If type matches "search" table, @@ -959,12 +960,12 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, * else look up the rate that was, finally, successful. */ if (!tx_resp->retry_count) - tx_mcs.rate_n_flags = tx_resp->control.tx_rate; + tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; else tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags); - rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); /* Update frame history window with "success" if Tx got ACKed ... */ @@ -1801,7 +1802,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, is_green = lq_sta->is_green; /* current tx rate */ - index = sta->last_txrate; + index = sta->last_txrate_idx; IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, tbl->lq_type); @@ -1814,7 +1815,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { - if (lq_sta->phymode == (u8) MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) /* supp_rates has no CCK bits in A mode */ rate_scale_index_msk = (u16) (rate_mask & (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); @@ -2134,15 +2135,15 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, out: rs_mcs_from_tbl(&tbl->current_rate, tbl, index, is_green); i = index; - sta->last_txrate = i; + sta->last_txrate_idx = i; - /* sta->txrate is an index to A mode rates which start + /* sta->txrate_idx is an index to A mode rates which start * at IWL_FIRST_OFDM_RATE */ - if (lq_sta->phymode == (u8) MODE_IEEE80211A) - sta->txrate = i - IWL_FIRST_OFDM_RATE; + if (lq_sta->band == IEEE80211_BAND_5GHZ) + sta->txrate_idx = i - IWL_FIRST_OFDM_RATE; else - sta->txrate = i; + sta->txrate_idx = i; return; } @@ -2164,7 +2165,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv, goto out; lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate; + i = sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) @@ -2188,7 +2189,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv, mcs_rate.rate_n_flags |= RATE_MCS_CCK_MSK; tbl->antenna_type = ANT_AUX; - rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx); + rs_get_tbl_info_from_mcs(&mcs_rate, priv->band, tbl, &rate_idx); if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type)) rs_toggle_antenna(&mcs_rate, tbl); @@ -2202,7 +2203,8 @@ static void rs_initialize_lq(struct iwl4965_priv *priv, } static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct ieee80211_supported_band *sband, + struct sk_buff *skb, struct rate_selection *sel) { @@ -2224,14 +2226,14 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, fc = le16_to_cpu(hdr->frame_control); if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { - sel->rate = rate_lowest(local, local->oper_hw_mode, sta); + sel->rate = rate_lowest(local, sband, sta); if (sta) sta_info_put(sta); return; } lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate; + i = sta->last_txrate_idx; if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && !lq_sta->ibss_sta_added) { @@ -2256,7 +2258,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, done: if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate = rate_lowest(local, local->oper_hw_mode, sta); + sel->rate = rate_lowest(local, sband, sta); return; } sta_info_put(sta); @@ -2291,13 +2293,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, { int i, j; struct ieee80211_conf *conf = &local->hw.conf; - struct ieee80211_hw_mode *mode = local->oper_hw_mode; + struct ieee80211_supported_band *sband; struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; struct iwl4965_lq_sta *lq_sta = priv_sta; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + lq_sta->flush_timer = 0; - lq_sta->supp_rates = sta->supp_rates; - sta->txrate = 3; + lq_sta->supp_rates = sta->supp_rates[sband->band]; + sta->txrate_idx = 3; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i])); @@ -2332,15 +2336,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, } /* Find highest tx rate supported by hardware and destination station */ - for (i = 0; i < mode->num_rates; i++) { - if ((sta->supp_rates & BIT(i)) && - (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) - sta->txrate = i; - } - sta->last_txrate = sta->txrate; + for (i = 0; i < sband->n_bitrates; i++) + if (sta->supp_rates[sband->band] & BIT(i)) + sta->txrate_idx = i; + + sta->last_txrate_idx = sta->txrate_idx; + /* WTF is with this bogus comment? A doesn't have cck rates */ /* For MODE_IEEE80211A, cck rates are at end of rate table */ - if (local->hw.conf.phymode == MODE_IEEE80211A) - sta->last_txrate += IWL_FIRST_OFDM_RATE; + if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_dup = 0; lq_sta->valid_antenna = priv->valid_antenna; @@ -2349,7 +2353,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->active_rate = priv->active_rate; lq_sta->active_rate &= ~(0x1000); lq_sta->active_rate_basic = priv->active_rate_basic; - lq_sta->phymode = priv->phymode; + lq_sta->band = priv->band; #ifdef CONFIG_IWL4965_HT /* * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), @@ -2401,7 +2405,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, rs_dbgfs_set_mcs(lq_sta, tx_mcs, index); /* Interpret rate_n_flags */ - rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode, + rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->band, &tbl_type, &rate_idx); /* How many times should we repeat the initial rate? */ @@ -2455,7 +2459,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, index++; } - rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type, + rs_get_tbl_info_from_mcs(&new_rate, lq_sta->band, &tbl_type, &rate_idx); /* Indicate to uCode which entries might be MIMO. @@ -2542,7 +2546,7 @@ static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, { u32 base_rate; - if (lq_sta->phymode == (u8) MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) base_rate = 0x800D; else base_rate = 0x820A; @@ -2802,7 +2806,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d " "active_search %d rate index %d\n", lq_type, antenna, - lq_sta->search_better_tbl, sta->last_txrate); + lq_sta->search_better_tbl, sta->last_txrate_idx); sta_info_put(sta); return cnt; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 0bded8570275..a89439320498 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -339,14 +339,15 @@ static int iwl4965_kw_alloc(struct iwl4965_priv *priv) * * Does not set up a command, or touch hardware. */ -int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel, +int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel) { struct iwl4965_channel_info *ch_info; ch_info = (struct iwl4965_channel_info *) - iwl4965_get_channel_info(priv, phymode, channel); + iwl4965_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return -1; @@ -1939,11 +1940,12 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, } static const struct iwl4965_channel_info * -iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, u8 phymode, u16 channel) +iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel) { const struct iwl4965_channel_info *ch_info; - ch_info = iwl4965_get_channel_info(priv, phymode, channel); + ch_info = iwl4965_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return NULL; @@ -2392,7 +2394,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan /* Get current (RXON) channel, band, width */ ch_info = - iwl4965_get_channel_txpower_info(priv, priv->phymode, channel); + iwl4965_get_channel_txpower_info(priv, priv->band, channel); IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band, is_fat); @@ -2619,8 +2621,7 @@ int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv) return -EAGAIN; } - band = ((priv->phymode == MODE_IEEE80211B) || - (priv->phymode == MODE_IEEE80211G)); + band = priv->band == IEEE80211_BAND_2GHZ; is_fat = is_fat_channel(priv->active_rxon.flags); @@ -2650,10 +2651,9 @@ int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel) struct iwl4965_channel_switch_cmd cmd = { 0 }; const struct iwl4965_channel_info *ch_info; - band = ((priv->phymode == MODE_IEEE80211B) || - (priv->phymode == MODE_IEEE80211G)); + band = priv->band == IEEE80211_BAND_2GHZ; - ch_info = iwl4965_get_channel_info(priv, priv->phymode, channel); + ch_info = iwl4965_get_channel_info(priv, priv->band, channel); is_fat = is_fat_channel(priv->staging_rxon.flags); @@ -2698,7 +2698,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv, u16 fc = le16_to_cpu(hdr->frame_control); u8 rate_plcp; u16 rate_flags = 0; - int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1); + int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1); rate_plcp = iwl4965_rates[rate_idx].plcp; @@ -3178,7 +3178,7 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv, { s8 signal = stats->ssi; s8 noise = 0; - int rate = stats->rate; + int rate = stats->rate_idx; u64 tsf = stats->mactime; __le16 phy_flags_hw = rx_start->phy_flags; struct iwl4965_rt_rx_hdr { @@ -3246,7 +3246,6 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv, IEEE80211_CHAN_2GHZ), &iwl4965_rt->rt_chbitmask); - rate = iwl4965_rate_index_from_plcp(rate); if (rate == -1) iwl4965_rt->rt_rate = 0; else @@ -3542,12 +3541,13 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, u16 fc; struct ieee80211_rx_status stats = { .mactime = le64_to_cpu(rx_start->timestamp), - .channel = le16_to_cpu(rx_start->channel), - .phymode = + .freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)), + .band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - MODE_IEEE80211G : MODE_IEEE80211A, + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, .antenna = 0, - .rate = iwl4965_hw_get_rate(rx_start->rate_n_flags), + .rate_idx = iwl4965_hw_get_rate( + le32_to_cpu(rx_start->rate_n_flags)), .flag = 0, }; u8 network_packet; @@ -3598,8 +3598,6 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); - stats.freq = ieee80211chan2mhz(stats.channel); - /* Find max signal strength (dBm) among 3 antenna/receiver chains */ stats.ssi = iwl4965_calc_rssi(rx_start); @@ -4185,7 +4183,7 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) * all the way down to 1M in IEEE order, and then spin on 1M */ if (is_ap) r = IWL_RATE_54M_INDEX; - else if (priv->phymode == MODE_IEEE80211A) + else if (priv->band == IEEE80211_BAND_5GHZ) r = IWL_RATE_6M_INDEX; else r = IWL_RATE_1M_INDEX; @@ -4218,12 +4216,13 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) #ifdef CONFIG_IWL4965_HT -static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode, +static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel, u8 extension_chan_offset) { const struct iwl4965_channel_info *ch_info; - ch_info = iwl4965_get_channel_info(priv, phymode, channel); + ch_info = iwl4965_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index de5c1bf8fc42..cb8f7f2a8d48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -206,7 +206,7 @@ struct iwl4965_channel_info { u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ - u8 phymode; /* MODE_IEEE80211{A,B,G} */ + enum ieee80211_band band; /* Radio/DSP gain settings for each "normal" data Tx rate. * These include, in addition to RF and DSP gain, a few fields for @@ -764,7 +764,8 @@ extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode); extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv); extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force); -extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, +extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel); @@ -977,14 +978,14 @@ struct iwl4965_priv { struct list_head free_frames; int frames_count; - u8 phymode; + enum ieee80211_band band; int alloc_rxb_skb; bool add_radiotap; void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb); - const struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT /* spectrum measurement report caching */ @@ -1243,13 +1244,12 @@ static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info) static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info) { - return ch_info->phymode == MODE_IEEE80211A; + return ch_info->band == IEEE80211_BAND_5GHZ; } static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info) { - return ((ch_info->phymode == MODE_IEEE80211B) || - (ch_info->phymode == MODE_IEEE80211G)); + return ch_info->band == IEEE80211_BAND_2GHZ; } static inline int is_channel_passive(const struct iwl4965_channel_info *ch) @@ -1263,7 +1263,7 @@ static inline int is_channel_ibss(const struct iwl4965_channel_info *ch) } extern const struct iwl4965_channel_info *iwl4965_get_channel_info( - const struct iwl4965_priv *priv, int phymode, u16 channel); + const struct iwl4965_priv *priv, enum ieee80211_band band, u16 channel); /* Requires full declaration of iwl4965_priv before including */ #include "iwl-4965-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 40b71bc2c4a4..57a1d70f2abf 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -116,16 +116,10 @@ static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr) return NULL; } -static const struct ieee80211_hw_mode *iwl3945_get_hw_mode( - struct iwl3945_priv *priv, int mode) +static const struct ieee80211_supported_band *iwl3945_get_band( + struct iwl3945_priv *priv, enum ieee80211_band band) { - int i; - - for (i = 0; i < 3; i++) - if (priv->modes[i].mode == mode) - return &priv->modes[i]; - - return NULL; + return priv->hw->wiphy->bands[band]; } static int iwl3945_is_empty_essid(const char *essid, int essid_len) @@ -547,7 +541,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 station->sta.sta.sta_id = index; station->sta.station_flags = 0; - if (priv->phymode == MODE_IEEE80211A) + if (priv->band == IEEE80211_BAND_5GHZ) rate = IWL_RATE_6M_PLCP; else rate = IWL_RATE_1M_PLCP; @@ -894,35 +888,37 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv) /** * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON - * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz - * @channel: Any channel valid for the requested phymode + * @band: 2.4 or 5 GHz band + * @channel: Any channel valid for the requested band - * In addition to setting the staging RXON, priv->phymode is also set. + * In addition to setting the staging RXON, priv->band is also set. * * NOTE: Does not commit to the hardware; it sets appropriate bit fields - * in the staging RXON flag structure based on the phymode + * in the staging RXON flag structure based on the band */ -static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel) +static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, + enum ieee80211_band band, + u16 channel) { - if (!iwl3945_get_channel_info(priv, phymode, channel)) { + if (!iwl3945_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", - channel, phymode); + channel, band); return -EINVAL; } if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && - (priv->phymode == phymode)) + (priv->band == band)) return 0; priv->staging_rxon.channel = cpu_to_le16(channel); - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; else priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->phymode = phymode; + priv->band = band; - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode); + IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); return 0; } @@ -1210,8 +1206,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) return -EIO; } - /* Init the hardware's rate fallback order based on the - * phymode */ + /* Init the hardware's rate fallback order based on the band */ rc = iwl3945_init_hw_rate_table(priv); if (rc) { IWL_ERROR("Error setting HW rate table: %02X\n", rc); @@ -2461,9 +2456,10 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt) return 0; } -static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode) +static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) { + if (band == IEEE80211_BAND_5GHZ) { priv->staging_rxon.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -2526,7 +2522,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif - ch_info = iwl3945_get_channel_info(priv, priv->phymode, + ch_info = iwl3945_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info) @@ -2542,11 +2538,11 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); if (is_channel_a_band(ch_info)) - priv->phymode = MODE_IEEE80211A; + priv->band = IEEE80211_BAND_5GHZ; else - priv->phymode = MODE_IEEE80211G; + priv->band = IEEE80211_BAND_2GHZ; - iwl3945_set_flags_for_phymode(priv, priv->phymode); + iwl3945_set_flags_for_phymode(priv, priv->band); priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; @@ -2560,7 +2556,7 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) const struct iwl3945_channel_info *ch_info; ch_info = iwl3945_get_channel_info(priv, - priv->phymode, + priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { @@ -2792,7 +2788,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, goto drop_unlock; } - if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) { + if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) { IWL_ERROR("ERROR: No TX rate available.\n"); goto drop_unlock; } @@ -2992,12 +2988,12 @@ drop: static void iwl3945_set_rate(struct iwl3945_priv *priv) { - const struct ieee80211_hw_mode *hw = NULL; + const struct ieee80211_supported_band *sband = NULL; struct ieee80211_rate *rate; int i; - hw = iwl3945_get_hw_mode(priv, priv->phymode); - if (!hw) { + sband = iwl3945_get_band(priv, priv->band); + if (!sband) { IWL_ERROR("Failed to set rate: unable to get hw mode\n"); return; } @@ -3005,24 +3001,17 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv) priv->active_rate = 0; priv->active_rate_basic = 0; - IWL_DEBUG_RATE("Setting rates for 802.11%c\n", - hw->mode == MODE_IEEE80211A ? - 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g')); - - for (i = 0; i < hw->num_rates; i++) { - rate = &(hw->rates[i]); - if ((rate->val < IWL_RATE_COUNT) && - (rate->flags & IEEE80211_RATE_SUPPORTED)) { - IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n", - rate->val, iwl3945_rates[rate->val].plcp, - (rate->flags & IEEE80211_RATE_BASIC) ? - "*" : ""); - priv->active_rate |= (1 << rate->val); - if (rate->flags & IEEE80211_RATE_BASIC) - priv->active_rate_basic |= (1 << rate->val); - } else - IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n", - rate->val, iwl3945_rates[rate->val].plcp); + IWL_DEBUG_RATE("Setting rates for %s GHz\n", + sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5"); + + for (i = 0; i < sband->n_bitrates; i++) { + rate = &sband->bitrates[i]; + if ((rate->hw_value < IWL_RATE_COUNT) && + !(rate->flags & IEEE80211_CHAN_DISABLED)) { + IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n", + rate->hw_value, iwl3945_rates[rate->hw_value].plcp); + priv->active_rate |= (1 << rate->hw_value); + } } IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", @@ -3436,8 +3425,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, tx_status->flags = iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; - tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate); - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", txq_id, iwl3945_get_tx_fail_reason(status), status, tx_resp->rate, tx_resp->failure_frame); @@ -5026,24 +5013,24 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban * Based on band and channel number. */ const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv, - int phymode, u16 channel) + enum ieee80211_band band, u16 channel) { int i; - switch (phymode) { - case MODE_IEEE80211A: + switch (band) { + case IEEE80211_BAND_5GHZ: for (i = 14; i < priv->channel_count; i++) { if (priv->channel_info[i].channel == channel) return &priv->channel_info[i]; } break; - case MODE_IEEE80211B: - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: if (channel >= 1 && channel <= 14) return &priv->channel_info[channel - 1]; break; - + case IEEE80211_NUM_BANDS: + WARN_ON(1); } return NULL; @@ -5106,8 +5093,8 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { ch_info->channel = eeprom_ch_index[ch]; - ch_info->phymode = (band == 1) ? MODE_IEEE80211B : - MODE_IEEE80211A; + ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; /* permanently store EEPROM's channel regulatory flags * and max power in channel info database. */ @@ -5203,18 +5190,20 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 -static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode) +static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52; else return IWL_ACTIVE_DWELL_TIME_24; } -static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode) +static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, + enum ieee80211_band band) { - u16 active = iwl3945_get_active_dwell_time(priv, phymode); - u16 passive = (phymode != MODE_IEEE80211A) ? + u16 active = iwl3945_get_active_dwell_time(priv, band); + u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -5234,28 +5223,29 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode return passive; } -static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, +static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, + enum ieee80211_band band, u8 is_active, u8 direct_mask, struct iwl3945_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode; + const struct ieee80211_supported_band *sband; const struct iwl3945_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; - hw_mode = iwl3945_get_hw_mode(priv, phymode); - if (!hw_mode) + sband = iwl3945_get_band(priv, band); + if (!sband) return 0; - channels = hw_mode->channels; + channels = sband->channels; - active_dwell = iwl3945_get_active_dwell_time(priv, phymode); - passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode); + active_dwell = iwl3945_get_active_dwell_time(priv, band); + passive_dwell = iwl3945_get_passive_dwell_time(priv, band); - for (i = 0, added = 0; i < hw_mode->num_channels; i++) { - if (channels[i].chan == + for (i = 0, added = 0; i < sband->n_channels; i++) { + if (channels[i].hw_value == le16_to_cpu(priv->active_rxon.channel)) { if (iwl3945_is_associated(priv)) { IWL_DEBUG_SCAN @@ -5266,9 +5256,9 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, } else if (priv->only_active_channel) continue; - scan_ch->channel = channels[i].chan; + scan_ch->channel = channels[i].hw_value; - ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel); + ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", scan_ch->channel); @@ -5276,7 +5266,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, } if (!is_active || is_channel_passive(ch_info) || - !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN)) + (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) scan_ch->type = 0; /* passive */ else scan_ch->type = 1; /* active */ @@ -5295,7 +5285,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, /* scan_pwr_info->tpc.dsp_atten; */ /*scan_pwr_info->tpc.tx_gain; */ - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); @@ -5319,41 +5309,23 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, return added; } -static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv) -{ - int i, j; - for (i = 0; i < 3; i++) { - struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i]; - for (j = 0; j < hw_mode->num_channels; j++) - hw_mode->channels[j].flag = hw_mode->channels[j].val; - } -} - static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, struct ieee80211_rate *rates) { int i; for (i = 0; i < IWL_RATE_COUNT; i++) { - rates[i].rate = iwl3945_rates[i].ieee * 5; - rates[i].val = i; /* Rate scaling will work on indexes */ - rates[i].val2 = i; - rates[i].flags = IEEE80211_RATE_SUPPORTED; - /* Only OFDM have the bits-per-symbol set */ - if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE)) - rates[i].flags |= IEEE80211_RATE_OFDM; - else { + rates[i].bitrate = iwl3945_rates[i].ieee * 5; + rates[i].hw_value = i; /* Rate scaling will work on indexes */ + rates[i].hw_value_short = i; + rates[i].flags = 0; + if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { /* - * If CCK 1M then set rate flag to CCK else CCK_2 - * which is CCK | PREAMBLE2 + * If CCK != 1M then set short preamble rate flag. */ rates[i].flags |= (iwl3945_rates[i].plcp == 10) ? - IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2; + 0 : IEEE80211_RATE_SHORT_PREAMBLE; } - - /* Set up which ones are basic rates... */ - if (IWL_BASIC_RATES_MASK & (1 << i)) - rates[i].flags |= IEEE80211_RATE_BASIC; } } @@ -5363,67 +5335,41 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, static int iwl3945_init_geos(struct iwl3945_priv *priv) { struct iwl3945_channel_info *ch; - struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band *band; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; int i = 0; - enum { - A = 0, - B = 1, - G = 2, - }; - int mode_count = 3; - if (priv->modes) { + if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || + priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO("Geography modes already initialized.\n"); set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } - modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count, - GFP_KERNEL); - if (!modes) - return -ENOMEM; - channels = kzalloc(sizeof(struct ieee80211_channel) * priv->channel_count, GFP_KERNEL); - if (!channels) { - kfree(modes); + if (!channels) return -ENOMEM; - } rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), GFP_KERNEL); if (!rates) { - kfree(modes); kfree(channels); return -ENOMEM; } - /* 0 = 802.11a - * 1 = 802.11b - * 2 = 802.11g - */ - /* 5.2GHz channels start after the 2.4GHz channels */ - modes[A].mode = MODE_IEEE80211A; - modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; - modes[A].rates = &rates[4]; - modes[A].num_rates = 8; /* just OFDM */ - modes[A].num_channels = 0; - - modes[B].mode = MODE_IEEE80211B; - modes[B].channels = channels; - modes[B].rates = rates; - modes[B].num_rates = 4; /* just CCK */ - modes[B].num_channels = 0; - - modes[G].mode = MODE_IEEE80211G; - modes[G].channels = channels; - modes[G].rates = rates; - modes[G].num_rates = 12; /* OFDM & CCK */ - modes[G].num_channels = 0; + band = &priv->bands[IEEE80211_BAND_5GHZ]; + band->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; + band->bitrates = &rates[4]; + band->n_bitrates = 8; /* just OFDM */ + + band = &priv->bands[IEEE80211_BAND_2GHZ]; + band->channels = channels; + band->bitrates = rates; + band->n_bitrates = 12; /* OFDM & CCK */ priv->ieee_channels = channels; priv->ieee_rates = rates; @@ -5442,37 +5388,32 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) } if (is_channel_a_band(ch)) - geo_ch = &modes[A].channels[modes[A].num_channels++]; - else { - geo_ch = &modes[B].channels[modes[B].num_channels++]; - modes[G].num_channels++; - } + geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; + else + geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; - geo_ch->freq = ieee80211chan2mhz(ch->channel); - geo_ch->chan = ch->channel; - geo_ch->power_level = ch->max_power_avg; - geo_ch->antenna_max = 0xff; + geo_ch->center_freq = ieee80211chan2mhz(ch->channel); + geo_ch->max_power = ch->max_power_avg; + geo_ch->max_antenna_gain = 0xff; if (is_channel_valid(ch)) { - geo_ch->flag = IEEE80211_CHAN_W_SCAN; - if (ch->flags & EEPROM_CHANNEL_IBSS) - geo_ch->flag |= IEEE80211_CHAN_W_IBSS; + if (!(ch->flags & EEPROM_CHANNEL_IBSS)) + geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; - if (ch->flags & EEPROM_CHANNEL_ACTIVE) - geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN; + if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) + geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT; + geo_ch->flags |= IEEE80211_CHAN_RADAR; if (ch->max_power_avg > priv->max_channel_txpower_limit) priv->max_channel_txpower_limit = ch->max_power_avg; - } - - geo_ch->val = geo_ch->flag; + } else + geo_ch->flags |= IEEE80211_CHAN_DISABLED; } - if ((modes[A].num_channels == 0) && priv->is_abg) { + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { printk(KERN_INFO DRV_NAME ": Incorrectly detected BG card as ABG. Please send " "your PCI ID 0x%04X:0x%04X to maintainer.\n", @@ -5482,24 +5423,12 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) printk(KERN_INFO DRV_NAME ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", - modes[G].num_channels, modes[A].num_channels); + priv->bands[IEEE80211_BAND_2GHZ].n_channels, + priv->bands[IEEE80211_BAND_5GHZ].n_channels); - /* - * NOTE: We register these in preference of order -- the - * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick - * a phymode based on rates or AP capabilities but seems to - * configure it purely on if the channel being configured - * is supported by a mode -- and the first match is taken - */ - - if (modes[G].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[G]); - if (modes[B].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[B]); - if (modes[A].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[A]); + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; - priv->modes = modes; set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; @@ -5510,7 +5439,6 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) */ static void iwl3945_free_geos(struct iwl3945_priv *priv) { - kfree(priv->modes); kfree(priv->ieee_channels); kfree(priv->ieee_rates); clear_bit(STATUS_GEO_CONFIGURED, &priv->status); @@ -6519,7 +6447,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) struct iwl3945_scan_cmd *scan; struct ieee80211_conf *conf = NULL; u8 direct_mask; - int phymode; + enum ieee80211_band band; conf = ieee80211_get_hw_conf(priv->hw); @@ -6651,13 +6579,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate = IWL_RATE_1M_PLCP; scan->good_CRC_th = 0; - phymode = MODE_IEEE80211G; + band = IEEE80211_BAND_2GHZ; break; case 1: scan->tx_cmd.rate = IWL_RATE_6M_PLCP; scan->good_CRC_th = IWL_GOOD_CRC_TH; - phymode = MODE_IEEE80211A; + band = IEEE80211_BAND_5GHZ; break; default: @@ -6680,7 +6608,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->channel_count = iwl3945_get_channels_for_scan( - priv, phymode, 1, /* active */ + priv, band, 1, /* active */ direct_mask, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); @@ -6825,7 +6753,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data) iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0); iwl3945_add_station(priv, priv->bssid, 0, 0); iwl3945_sync_sta(priv, IWL_STA_ID, - (priv->phymode == MODE_IEEE80211A)? + (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, CMD_ASYNC); iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); @@ -7020,7 +6948,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, - ctl->tx_rate); + ctl->tx_rate->bitrate); if (iwl3945_tx_skb(priv, skb, ctl)) dev_kfree_skb_any(skb); @@ -7079,7 +7007,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co int ret = 0; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); + IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); @@ -7099,19 +7027,20 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); - ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel); + ch_info = iwl3945_get_channel_info(priv, conf->channel->band, + conf->channel->hw_value); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", - conf->channel, conf->phymode); + conf->channel->hw_value, conf->channel->band); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); ret = -EINVAL; goto out; } - iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel); + iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value); - iwl3945_set_flags_for_phymode(priv, conf->phymode); + iwl3945_set_flags_for_phymode(priv, conf->channel->band); /* The list of supported rates and rate mask can be different * for each phymode; since the phymode may have changed, reset @@ -7892,65 +7821,6 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -static ssize_t show_tune(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; - - return sprintf(buf, "0x%04X\n", - (priv->phymode << 8) | - le16_to_cpu(priv->active_rxon.channel)); -} - -static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode); - -static ssize_t store_tune(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; - char *p = (char *)buf; - u16 tune = simple_strtoul(p, &p, 0); - u8 phymode = (tune >> 8) & 0xff; - u16 channel = tune & 0xff; - - IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel); - - mutex_lock(&priv->mutex); - if ((le16_to_cpu(priv->staging_rxon.channel) != channel) || - (priv->phymode != phymode)) { - const struct iwl3945_channel_info *ch_info; - - ch_info = iwl3945_get_channel_info(priv, phymode, channel); - if (!ch_info) { - IWL_WARNING("Requested invalid phymode/channel " - "combination: %d %d\n", phymode, channel); - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - /* Cancel any currently running scans... */ - if (iwl3945_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO("Committing phymode and " - "rxon.channel = %d %d\n", - phymode, channel); - - iwl3945_set_rxon_channel(priv, phymode, channel); - iwl3945_set_flags_for_phymode(priv, phymode); - - iwl3945_set_rate(priv); - iwl3945_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune); - #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT static ssize_t show_measurement(struct device *d, @@ -8165,73 +8035,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, static ssize_t show_channels(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); - int len = 0, i; - struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode = NULL; - int count = 0; - - if (!iwl3945_is_ready(priv)) - return -EAGAIN; - - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G); - if (!hw_mode) - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } - - len += - sprintf(&buf[len], - "Displaying %d channels in 2.4GHz band " - "(802.11bg):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } else { - channels = NULL; - count = 0; - } - - len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band " - "(802.11a):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - return len; + /* all this shit doesn't belong into sysfs anyway */ + return 0; } static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); @@ -8411,7 +8216,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, - &dev_attr_tune.attr, &dev_attr_tx_power.attr, NULL @@ -8532,7 +8336,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->data_retry_limit = -1; priv->ieee_channels = NULL; priv->ieee_rates = NULL; - priv->phymode = -1; + priv->band = IEEE80211_BAND_2GHZ; err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (!err) @@ -8614,7 +8418,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->qos_data.qos_cap.val = 0; #endif /* CONFIG_IWL3945_QOS */ - iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6); + iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); iwl3945_setup_deferred_work(priv); iwl3945_setup_rx_handlers(priv); @@ -8665,7 +8469,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_ERROR("initializing geos failed: %d\n", err); goto out_free_channel_map; } - iwl3945_reset_channel_flag(priv); iwl3945_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5f38fc585eda..6de969de4c84 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -115,16 +115,10 @@ __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr) return NULL; } -static const struct ieee80211_hw_mode *iwl4965_get_hw_mode( - struct iwl4965_priv *priv, int mode) +static const struct ieee80211_supported_band *iwl4965_get_hw_mode( + struct iwl4965_priv *priv, enum ieee80211_band band) { - int i; - - for (i = 0; i < 3; i++) - if (priv->modes[i].mode == mode) - return &priv->modes[i]; - - return NULL; + return priv->hw->wiphy->bands[band]; } static int iwl4965_is_empty_essid(const char *essid, int essid_len) @@ -937,28 +931,29 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, * NOTE: Does not commit to the hardware; it sets appropriate bit fields * in the staging RXON flag structure based on the phymode */ -static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode, +static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel) { - if (!iwl4965_get_channel_info(priv, phymode, channel)) { + if (!iwl4965_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", - channel, phymode); + channel, band); return -EINVAL; } if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && - (priv->phymode == phymode)) + (priv->band == band)) return 0; priv->staging_rxon.channel = cpu_to_le16(channel); - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; else priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->phymode = phymode; + priv->band = band; - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode); + IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); return 0; } @@ -2571,9 +2566,10 @@ static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt) return 0; } -static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode) +static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) { + if (band == IEEE80211_BAND_5GHZ) { priv->staging_rxon.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -2636,7 +2632,7 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif - ch_info = iwl4965_get_channel_info(priv, priv->phymode, + ch_info = iwl4965_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info) @@ -2651,12 +2647,9 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv) ch_info = &priv->channel_info[0]; priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); - if (is_channel_a_band(ch_info)) - priv->phymode = MODE_IEEE80211A; - else - priv->phymode = MODE_IEEE80211G; + priv->band = ch_info->band; - iwl4965_set_flags_for_phymode(priv, priv->phymode); + iwl4965_set_flags_for_phymode(priv, priv->band); priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; @@ -2678,7 +2671,7 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode) const struct iwl4965_channel_info *ch_info; ch_info = iwl4965_get_channel_info(priv, - priv->phymode, + priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { @@ -2918,7 +2911,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, goto drop_unlock; } - if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) { + if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) { IWL_ERROR("ERROR: No TX rate available.\n"); goto drop_unlock; } @@ -3125,11 +3118,11 @@ drop: static void iwl4965_set_rate(struct iwl4965_priv *priv) { - const struct ieee80211_hw_mode *hw = NULL; + const struct ieee80211_supported_band *hw = NULL; struct ieee80211_rate *rate; int i; - hw = iwl4965_get_hw_mode(priv, priv->phymode); + hw = iwl4965_get_hw_mode(priv, priv->band); if (!hw) { IWL_ERROR("Failed to set rate: unable to get hw mode\n"); return; @@ -3138,24 +3131,10 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv) priv->active_rate = 0; priv->active_rate_basic = 0; - IWL_DEBUG_RATE("Setting rates for 802.11%c\n", - hw->mode == MODE_IEEE80211A ? - 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g')); - - for (i = 0; i < hw->num_rates; i++) { - rate = &(hw->rates[i]); - if ((rate->val < IWL_RATE_COUNT) && - (rate->flags & IEEE80211_RATE_SUPPORTED)) { - IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n", - rate->val, iwl4965_rates[rate->val].plcp, - (rate->flags & IEEE80211_RATE_BASIC) ? - "*" : ""); - priv->active_rate |= (1 << rate->val); - if (rate->flags & IEEE80211_RATE_BASIC) - priv->active_rate_basic |= (1 << rate->val); - } else - IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n", - rate->val, iwl4965_rates[rate->val].plcp); + for (i = 0; i < hw->n_bitrates; i++) { + rate = &(hw->bitrates[i]); + if (rate->hw_value < IWL_RATE_COUNT) + priv->active_rate |= (1 << rate->hw_value); } IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", @@ -3775,9 +3754,6 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, tx_status->flags = iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; - tx_status->control.tx_rate = - iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags); - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status), status, le32_to_cpu(tx_resp->rate_n_flags), @@ -5419,24 +5395,23 @@ static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, * Based on band and channel number. */ const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv, - int phymode, u16 channel) + enum ieee80211_band band, u16 channel) { int i; - switch (phymode) { - case MODE_IEEE80211A: + switch (band) { + case IEEE80211_BAND_5GHZ: for (i = 14; i < priv->channel_count; i++) { if (priv->channel_info[i].channel == channel) return &priv->channel_info[i]; } break; - - case MODE_IEEE80211B: - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: if (channel >= 1 && channel <= 14) return &priv->channel_info[channel - 1]; break; - + default: + BUG(); } return NULL; @@ -5499,8 +5474,8 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { ch_info->channel = eeprom_ch_index[ch]; - ch_info->phymode = (band == 1) ? MODE_IEEE80211B : - MODE_IEEE80211A; + ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; /* permanently store EEPROM's channel regulatory flags * and max power in channel info database. */ @@ -5559,14 +5534,14 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ for (band = 6; band <= 7; band++) { - int phymode; + enum ieee80211_band ieeeband; u8 fat_extension_chan; iwl4965_init_band_reference(priv, band, &eeprom_ch_count, &eeprom_ch_info, &eeprom_ch_index); /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ - phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A; + ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { @@ -5580,13 +5555,13 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; /* Set up driver's info for lower half */ - iwl4965_set_fat_chan_info(priv, phymode, + iwl4965_set_fat_chan_info(priv, ieeeband, eeprom_ch_index[ch], &(eeprom_ch_info[ch]), fat_extension_chan); /* Set up driver's info for upper half */ - iwl4965_set_fat_chan_info(priv, phymode, + iwl4965_set_fat_chan_info(priv, ieeeband, (eeprom_ch_index[ch] + 4), &(eeprom_ch_info[ch]), HT_IE_EXT_CHANNEL_BELOW); @@ -5628,18 +5603,20 @@ static void iwl4965_free_channel_map(struct iwl4965_priv *priv) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 -static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, int phymode) +static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52; else return IWL_ACTIVE_DWELL_TIME_24; } -static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode) +static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, + enum ieee80211_band band) { - u16 active = iwl4965_get_active_dwell_time(priv, phymode); - u16 passive = (phymode != MODE_IEEE80211A) ? + u16 active = iwl4965_get_active_dwell_time(priv, band); + u16 passive = (band != IEEE80211_BAND_5GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -5659,28 +5636,29 @@ static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode return passive; } -static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, +static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, + enum ieee80211_band band, u8 is_active, u8 direct_mask, struct iwl4965_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode; + const struct ieee80211_supported_band *sband; const struct iwl4965_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; - hw_mode = iwl4965_get_hw_mode(priv, phymode); - if (!hw_mode) + sband = iwl4965_get_hw_mode(priv, band); + if (!sband) return 0; - channels = hw_mode->channels; + channels = sband->channels; - active_dwell = iwl4965_get_active_dwell_time(priv, phymode); - passive_dwell = iwl4965_get_passive_dwell_time(priv, phymode); + active_dwell = iwl4965_get_active_dwell_time(priv, band); + passive_dwell = iwl4965_get_passive_dwell_time(priv, band); - for (i = 0, added = 0; i < hw_mode->num_channels; i++) { - if (channels[i].chan == + for (i = 0, added = 0; i < sband->n_channels; i++) { + if (ieee80211_frequency_to_channel(channels[i].center_freq) == le16_to_cpu(priv->active_rxon.channel)) { if (iwl4965_is_associated(priv)) { IWL_DEBUG_SCAN @@ -5691,9 +5669,9 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, } else if (priv->only_active_channel) continue; - scan_ch->channel = channels[i].chan; + scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq); - ch_info = iwl4965_get_channel_info(priv, phymode, + ch_info = iwl4965_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", @@ -5702,7 +5680,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, } if (!is_active || is_channel_passive(ch_info) || - !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN)) + (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) scan_ch->type = 0; /* passive */ else scan_ch->type = 1; /* active */ @@ -5721,7 +5699,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, /* scan_pwr_info->tpc.dsp_atten; */ /*scan_pwr_info->tpc.tx_gain; */ - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); @@ -5745,41 +5723,23 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, return added; } -static void iwl4965_reset_channel_flag(struct iwl4965_priv *priv) -{ - int i, j; - for (i = 0; i < 3; i++) { - struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i]; - for (j = 0; j < hw_mode->num_channels; j++) - hw_mode->channels[j].flag = hw_mode->channels[j].val; - } -} - static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, struct ieee80211_rate *rates) { int i; for (i = 0; i < IWL_RATE_COUNT; i++) { - rates[i].rate = iwl4965_rates[i].ieee * 5; - rates[i].val = i; /* Rate scaling will work on indexes */ - rates[i].val2 = i; - rates[i].flags = IEEE80211_RATE_SUPPORTED; - /* Only OFDM have the bits-per-symbol set */ - if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE)) - rates[i].flags |= IEEE80211_RATE_OFDM; - else { + rates[i].bitrate = iwl4965_rates[i].ieee * 5; + rates[i].hw_value = i; /* Rate scaling will work on indexes */ + rates[i].hw_value_short = i; + rates[i].flags = 0; + if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { /* - * If CCK 1M then set rate flag to CCK else CCK_2 - * which is CCK | PREAMBLE2 + * If CCK != 1M then set short preamble rate flag. */ rates[i].flags |= (iwl4965_rates[i].plcp == 10) ? - IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2; + 0 : IEEE80211_RATE_SHORT_PREAMBLE; } - - /* Set up which ones are basic rates... */ - if (IWL_BASIC_RATES_MASK & (1 << i)) - rates[i].flags |= IEEE80211_RATE_BASIC; } } @@ -5789,74 +5749,47 @@ static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, static int iwl4965_init_geos(struct iwl4965_priv *priv) { struct iwl4965_channel_info *ch; - struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band *band; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; int i = 0; - enum { - A = 0, - B = 1, - G = 2, - }; - int mode_count = 3; - if (priv->modes) { + if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || + priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO("Geography modes already initialized.\n"); set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } - modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count, - GFP_KERNEL); - if (!modes) - return -ENOMEM; - channels = kzalloc(sizeof(struct ieee80211_channel) * priv->channel_count, GFP_KERNEL); - if (!channels) { - kfree(modes); + if (!channels) return -ENOMEM; - } rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), GFP_KERNEL); if (!rates) { - kfree(modes); kfree(channels); return -ENOMEM; } - /* 0 = 802.11a - * 1 = 802.11b - * 2 = 802.11g - */ - /* 5.2GHz channels start after the 2.4GHz channels */ - modes[A].mode = MODE_IEEE80211A; - modes[A].channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; - modes[A].rates = rates; - modes[A].num_rates = 8; /* just OFDM */ - modes[A].rates = &rates[4]; - modes[A].num_channels = 0; #ifdef CONFIG_IWL4965_HT iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A); #endif - - modes[B].mode = MODE_IEEE80211B; - modes[B].channels = channels; - modes[B].rates = rates; - modes[B].num_rates = 4; /* just CCK */ - modes[B].num_channels = 0; - - modes[G].mode = MODE_IEEE80211G; - modes[G].channels = channels; - modes[G].rates = rates; - modes[G].num_rates = 12; /* OFDM & CCK */ - modes[G].num_channels = 0; #ifdef CONFIG_IWL4965_HT iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G); #endif + band = &priv->bands[IEEE80211_BAND_5GHZ]; + band->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; + band->bitrates = &rates[4]; + band->n_bitrates = 8; /* just OFDM */ + + band = &priv->bands[IEEE80211_BAND_2GHZ]; + band->channels = channels; + band->bitrates = rates; + band->n_bitrates = 12; /* OFDM & CCK */ priv->ieee_channels = channels; priv->ieee_rates = rates; @@ -5875,37 +5808,32 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) } if (is_channel_a_band(ch)) { - geo_ch = &modes[A].channels[modes[A].num_channels++]; - } else { - geo_ch = &modes[B].channels[modes[B].num_channels++]; - modes[G].num_channels++; - } + geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; + } else + geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; - geo_ch->freq = ieee80211chan2mhz(ch->channel); - geo_ch->chan = ch->channel; - geo_ch->power_level = ch->max_power_avg; - geo_ch->antenna_max = 0xff; + geo_ch->center_freq = ieee80211chan2mhz(ch->channel); + geo_ch->max_power = ch->max_power_avg; + geo_ch->max_antenna_gain = 0xff; if (is_channel_valid(ch)) { - geo_ch->flag = IEEE80211_CHAN_W_SCAN; - if (ch->flags & EEPROM_CHANNEL_IBSS) - geo_ch->flag |= IEEE80211_CHAN_W_IBSS; + if (!(ch->flags & EEPROM_CHANNEL_IBSS)) + geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; - if (ch->flags & EEPROM_CHANNEL_ACTIVE) - geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN; + if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) + geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT; + geo_ch->flags |= IEEE80211_CHAN_RADAR; if (ch->max_power_avg > priv->max_channel_txpower_limit) priv->max_channel_txpower_limit = ch->max_power_avg; - } - - geo_ch->val = geo_ch->flag; + } else + geo_ch->flags |= IEEE80211_CHAN_DISABLED; } - if ((modes[A].num_channels == 0) && priv->is_abg) { + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { printk(KERN_INFO DRV_NAME ": Incorrectly detected BG card as ABG. Please send " "your PCI ID 0x%04X:0x%04X to maintainer.\n", @@ -5915,24 +5843,12 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) printk(KERN_INFO DRV_NAME ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", - modes[G].num_channels, modes[A].num_channels); - - /* - * NOTE: We register these in preference of order -- the - * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick - * a phymode based on rates or AP capabilities but seems to - * configure it purely on if the channel being configured - * is supported by a mode -- and the first match is taken - */ + priv->bands[IEEE80211_BAND_2GHZ].n_channels, + priv->bands[IEEE80211_BAND_5GHZ].n_channels); - if (modes[G].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[G]); - if (modes[B].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[B]); - if (modes[A].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[A]); + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; - priv->modes = modes; set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; @@ -5943,7 +5859,6 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) */ static void iwl4965_free_geos(struct iwl4965_priv *priv) { - kfree(priv->modes); kfree(priv->ieee_channels); kfree(priv->ieee_rates); clear_bit(STATUS_GEO_CONFIGURED, &priv->status); @@ -6945,7 +6860,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) struct iwl4965_scan_cmd *scan; struct ieee80211_conf *conf = NULL; u8 direct_mask; - int phymode; + enum ieee80211_band band; conf = ieee80211_get_hw_conf(priv->hw); @@ -7075,7 +6990,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK); scan->good_CRC_th = 0; - phymode = MODE_IEEE80211G; + band = IEEE80211_BAND_2GHZ; break; case 1: @@ -7083,7 +6998,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, RATE_MCS_ANT_B_MSK); scan->good_CRC_th = IWL_GOOD_CRC_TH; - phymode = MODE_IEEE80211A; + band = IEEE80211_BAND_5GHZ; break; default: @@ -7113,7 +7028,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) scan->channel_count = iwl4965_get_channels_for_scan( - priv, phymode, 1, /* active */ + priv, band, 1, /* active */ direct_mask, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); @@ -7463,7 +7378,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, - ctl->tx_rate); + ctl->tx_rate->bitrate); if (iwl4965_tx_skb(priv, skb, ctl)) dev_kfree_skb_any(skb); @@ -7522,7 +7437,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co int ret = 0; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); + IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); @@ -7542,10 +7457,9 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); - ch_info = iwl4965_get_channel_info(priv, conf->phymode, conf->channel); + ch_info = iwl4965_get_channel_info(priv, conf->channel->band, + ieee80211_frequency_to_channel(conf->channel->center_freq)); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", - conf->channel, conf->phymode); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); ret = -EINVAL; @@ -7564,12 +7478,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co priv->staging_rxon.flags = 0; #endif /* CONFIG_IWL4965_HT */ - iwl4965_set_rxon_channel(priv, conf->phymode, conf->channel); + iwl4965_set_rxon_channel(priv, conf->channel->band, + ieee80211_frequency_to_channel(conf->channel->center_freq)); - iwl4965_set_flags_for_phymode(priv, conf->phymode); + iwl4965_set_flags_for_phymode(priv, conf->channel->band); /* The list of supported rates and rate mask can be different - * for each phymode; since the phymode may have changed, reset + * for each band; since the band may have changed, reset * the rate mask to what mac80211 lists */ iwl4965_set_rate(priv); @@ -7839,7 +7754,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_ERP_CTS_PROT) { - if (bss_conf->use_cts_prot && (priv->phymode != MODE_IEEE80211A)) + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; @@ -8277,7 +8192,6 @@ static void iwl4965_set_ht_capab(struct ieee80211_hw *hw, u8 use_current_config) { struct ieee80211_conf *conf = &hw->conf; - struct ieee80211_hw_mode *mode = conf->mode; if (use_current_config) { ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap); @@ -8488,65 +8402,6 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -static ssize_t show_tune(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; - - return sprintf(buf, "0x%04X\n", - (priv->phymode << 8) | - le16_to_cpu(priv->active_rxon.channel)); -} - -static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode); - -static ssize_t store_tune(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; - char *p = (char *)buf; - u16 tune = simple_strtoul(p, &p, 0); - u8 phymode = (tune >> 8) & 0xff; - u16 channel = tune & 0xff; - - IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel); - - mutex_lock(&priv->mutex); - if ((le16_to_cpu(priv->staging_rxon.channel) != channel) || - (priv->phymode != phymode)) { - const struct iwl4965_channel_info *ch_info; - - ch_info = iwl4965_get_channel_info(priv, phymode, channel); - if (!ch_info) { - IWL_WARNING("Requested invalid phymode/channel " - "combination: %d %d\n", phymode, channel); - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - /* Cancel any currently running scans... */ - if (iwl4965_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO("Committing phymode and " - "rxon.channel = %d %d\n", - phymode, channel); - - iwl4965_set_rxon_channel(priv, phymode, channel); - iwl4965_set_flags_for_phymode(priv, phymode); - - iwl4965_set_rate(priv); - iwl4965_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune); - #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT static ssize_t show_measurement(struct device *d, @@ -8736,73 +8591,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, static ssize_t show_channels(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = dev_get_drvdata(d); - int len = 0, i; - struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode = NULL; - int count = 0; - - if (!iwl4965_is_ready(priv)) - return -EAGAIN; - - hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211G); - if (!hw_mode) - hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211B); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } - - len += - sprintf(&buf[len], - "Displaying %d channels in 2.4GHz band " - "(802.11bg):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211A); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } else { - channels = NULL; - count = 0; - } - - len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band " - "(802.11a):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - return len; + /* all this shit doesn't belong into sysfs anyway */ + return 0; } static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); @@ -8981,7 +8771,6 @@ static struct attribute *iwl4965_sysfs_entries[] = { &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, - &dev_attr_tune.attr, &dev_attr_tx_power.attr, NULL @@ -9109,7 +8898,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->data_retry_limit = -1; priv->ieee_channels = NULL; priv->ieee_rates = NULL; - priv->phymode = -1; + priv->band = IEEE80211_BAND_2GHZ; err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (!err) @@ -9175,7 +8964,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->qos_data.qos_cap.val = 0; #endif /* CONFIG_IWL4965_QOS */ - iwl4965_set_rxon_channel(priv, MODE_IEEE80211G, 6); + iwl4965_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); iwl4965_setup_deferred_work(priv); iwl4965_setup_rx_handlers(priv); @@ -9226,7 +9015,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_ERROR("initializing geos failed: %d\n", err); goto out_free_channel_map; } - iwl4965_reset_channel_flag(priv); iwl4965_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); diff --git a/drivers/net/wireless/p54.h b/drivers/net/wireless/p54.h index 744c866066c5..06d2c67f4c81 100644 --- a/drivers/net/wireless/p54.h +++ b/drivers/net/wireless/p54.h @@ -64,10 +64,6 @@ struct p54_common { unsigned int tx_hdr_len; void *cached_vdcf; unsigned int fw_var; - /* FIXME: this channels/modes/rates stuff sucks */ - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; struct ieee80211_tx_queue_stats tx_stats; }; diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 5cda49aff3a8..218ff7770ef6 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -27,6 +27,46 @@ MODULE_DESCRIPTION("Softmac Prism54 common code"); MODULE_LICENSE("GPL"); MODULE_ALIAS("prism54common"); +static struct ieee80211_rate p54_rates[] = { + { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static struct ieee80211_channel p54_channels[] = { + { .center_freq = 2412, .hw_value = 1, }, + { .center_freq = 2417, .hw_value = 2, }, + { .center_freq = 2422, .hw_value = 3, }, + { .center_freq = 2427, .hw_value = 4, }, + { .center_freq = 2432, .hw_value = 5, }, + { .center_freq = 2437, .hw_value = 6, }, + { .center_freq = 2442, .hw_value = 7, }, + { .center_freq = 2447, .hw_value = 8, }, + { .center_freq = 2452, .hw_value = 9, }, + { .center_freq = 2457, .hw_value = 10, }, + { .center_freq = 2462, .hw_value = 11, }, + { .center_freq = 2467, .hw_value = 12, }, + { .center_freq = 2472, .hw_value = 13, }, + { .center_freq = 2484, .hw_value = 14, }, +}; + +struct ieee80211_supported_band band_2GHz = { + .channels = p54_channels, + .n_channels = ARRAY_SIZE(p54_channels), + .bitrates = p54_rates, + .n_bitrates = ARRAY_SIZE(p54_rates), +}; + + void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) { struct p54_common *priv = dev->priv; @@ -308,10 +348,10 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) u16 freq = le16_to_cpu(hdr->freq); rx_status.ssi = hdr->rssi; - rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */ - rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5; + /* XX correct? */ + rx_status.rate_idx = hdr->rate & 0xf; rx_status.freq = freq; - rx_status.phymode = MODE_IEEE80211G; + rx_status.band = IEEE80211_BAND_2GHZ; rx_status.antenna = hdr->antenna; rx_status.mactime = le64_to_cpu(hdr->timestamp); rx_status.flag |= RX_FLAG_TSFT; @@ -547,7 +587,9 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb, txhdr->padding2 = 0; /* TODO: add support for alternate retry TX rates */ - rate = control->tx_rate; + rate = control->tx_rate->hw_value; + if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) + rate |= 0x10; if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) rate |= 0x40; else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) @@ -849,7 +891,7 @@ static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { int ret; - ret = p54_set_freq(dev, cpu_to_le16(conf->freq)); + ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); p54_set_vdcf(dev); return ret; } @@ -944,7 +986,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) { struct ieee80211_hw *dev; struct p54_common *priv; - int i; dev = ieee80211_alloc_hw(priv_data_len, &p54_ops); if (!dev) @@ -953,18 +994,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) priv = dev->priv; priv->mode = IEEE80211_IF_TYPE_INVALID; skb_queue_head_init(&priv->tx_queue); - memcpy(priv->channels, p54_channels, sizeof(p54_channels)); - memcpy(priv->rates, p54_rates, sizeof(p54_rates)); - priv->modes[1].mode = MODE_IEEE80211B; - priv->modes[1].num_rates = 4; - priv->modes[1].rates = priv->rates; - priv->modes[1].num_channels = ARRAY_SIZE(p54_channels); - priv->modes[1].channels = priv->channels; - priv->modes[0].mode = MODE_IEEE80211G; - priv->modes[0].num_rates = ARRAY_SIZE(p54_rates); - priv->modes[0].rates = priv->rates; - priv->modes[0].num_channels = ARRAY_SIZE(p54_channels); - priv->modes[0].channels = priv->channels; + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ IEEE80211_HW_RX_INCLUDES_FCS; dev->channel_change_time = 1000; /* TODO: find actual value */ @@ -986,14 +1016,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) p54_init_vdcf(dev); - for (i = 0; i < 2; i++) { - if (ieee80211_register_hwmode(dev, &priv->modes[i])) { - kfree(priv->cached_vdcf); - ieee80211_free_hw(dev); - return NULL; - } - } - return dev; } EXPORT_SYMBOL_GPL(p54_init_common); diff --git a/drivers/net/wireless/p54common.h b/drivers/net/wireless/p54common.h index a721334e20d9..dc9f4cef585e 100644 --- a/drivers/net/wireless/p54common.h +++ b/drivers/net/wireless/p54common.h @@ -251,79 +251,4 @@ struct p54_tx_control_vdcf { __le16 frameburst; } __attribute__ ((packed)); -static const struct ieee80211_rate p54_rates[] = { - { .rate = 10, - .val = 0, - .val2 = 0x10, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 20, - .val = 1, - .val2 = 0x11, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 55, - .val = 2, - .val2 = 0x12, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 110, - .val = 3, - .val2 = 0x13, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 60, - .val = 4, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 90, - .val = 5, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 120, - .val = 6, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 180, - .val = 7, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 240, - .val = 8, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 360, - .val = 9, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 480, - .val = 10, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 540, - .val = 11, - .flags = IEEE80211_RATE_OFDM }, -}; - -// TODO: just generate this.. -static const struct ieee80211_channel p54_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484} -}; - #endif /* PRISM54COMMON_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index b0e4ea7c9dca..4fa762bdb734 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -390,6 +390,10 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) return (struct rt2x00_intf *)vif->drv_priv; } +#define HWMODE_B 0 +#define HWMODE_G 1 +#define HWMODE_A 2 + /* * Details about the supported modes, rates and channels * of a particular chipset. This is used by rt2x00lib @@ -644,11 +648,8 @@ struct rt2x00_dev { * IEEE80211 control structure. */ struct ieee80211_hw *hw; - struct ieee80211_hw_mode *hwmodes; - unsigned int curr_hwmode; -#define HWMODE_B 0 -#define HWMODE_G 1 -#define HWMODE_A 2 + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + enum ieee80211_band curr_band; /* * rfkill structure for RF state switching support. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 20231e0c53fa..9fba485a40ac 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -152,7 +152,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config) { struct rt2x00lib_conf libconf; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *band; struct ieee80211_rate *rate; struct antenna_setup *default_ant = &rt2x00dev->default_ant; struct antenna_setup *active_ant = &rt2x00dev->link.ant.active; @@ -172,9 +172,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, * Check which configuration options have been * updated and should be send to the device. */ - if (rt2x00dev->rx_status.phymode != conf->phymode) + if (rt2x00dev->rx_status.band != conf->channel->band) flags |= CONFIG_UPDATE_PHYMODE; - if (rt2x00dev->rx_status.channel != conf->channel) + if (rt2x00dev->rx_status.freq != conf->channel->center_freq) flags |= CONFIG_UPDATE_CHANNEL; if (rt2x00dev->tx_power != conf->power_level) flags |= CONFIG_UPDATE_TXPOWER; @@ -229,33 +229,31 @@ config: memset(&libconf, 0, sizeof(libconf)); if (flags & CONFIG_UPDATE_PHYMODE) { - switch (conf->phymode) { - case MODE_IEEE80211A: + switch (conf->channel->band) { + case IEEE80211_BAND_5GHZ: libconf.phymode = HWMODE_A; break; - case MODE_IEEE80211B: - libconf.phymode = HWMODE_B; - break; - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: + /* Uh oh. what about B? */ libconf.phymode = HWMODE_G; break; default: ERROR(rt2x00dev, "Attempt to configure unsupported mode (%d)" - "Defaulting to 802.11b", conf->phymode); + "Defaulting to 802.11b", conf->channel->band); libconf.phymode = HWMODE_B; } - mode = &rt2x00dev->hwmodes[libconf.phymode]; - rate = &mode->rates[mode->num_rates - 1]; + band = &rt2x00dev->bands[conf->channel->band]; + rate = &band->bitrates[band->n_bitrates - 1]; libconf.basic_rates = - DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK; + DEVICE_GET_RATE_FIELD(rate->hw_value, RATEMASK) & DEV_BASIC_RATEMASK; } if (flags & CONFIG_UPDATE_CHANNEL) { memcpy(&libconf.rf, - &rt2x00dev->spec.channels[conf->channel_val], + &rt2x00dev->spec.channels[conf->channel->hw_value], sizeof(libconf.rf)); } @@ -301,12 +299,11 @@ config: rt2x00lib_reset_link_tuner(rt2x00dev); if (flags & CONFIG_UPDATE_PHYMODE) { - rt2x00dev->curr_hwmode = libconf.phymode; - rt2x00dev->rx_status.phymode = conf->phymode; + rt2x00dev->curr_band = conf->channel->band; + rt2x00dev->rx_status.band = conf->channel->band; } - rt2x00dev->rx_status.freq = conf->freq; - rt2x00dev->rx_status.channel = conf->channel; + rt2x00dev->rx_status.freq = conf->channel->center_freq; rt2x00dev->tx_power = conf->power_level; if (flags & CONFIG_UPDATE_ANTENNA) { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 0df8062b1a8e..83a72ae36638 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -550,19 +550,19 @@ void rt2x00lib_rxdone(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; struct ieee80211_rate *rate; struct ieee80211_hdr *hdr; unsigned int i; - int val = 0; + int val = 0, idx = -1; u16 fc; /* * Update RX statistics. */ - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - for (i = 0; i < mode->num_rates; i++) { - rate = &mode->rates[i]; + sband = &rt2x00dev->bands[rt2x00dev->curr_band]; + for (i = 0; i < sband->n_bitrates; i++) { + rate = &sband->bitrates[i]; /* * When frame was received with an OFDM bitrate, @@ -570,12 +570,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry, * a CCK bitrate the signal is the rate in 0.5kbit/s. */ if (!rxdesc->ofdm) - val = DEVICE_GET_RATE_FIELD(rate->val, RATE); + val = DEVICE_GET_RATE_FIELD(rate->hw_value, RATE); else - val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); + val = DEVICE_GET_RATE_FIELD(rate->hw_value, PLCP); if (val == rxdesc->signal) { - val = rate->val; + idx = i; break; } } @@ -590,7 +590,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, rt2x00dev->link.qual.rx_success++; - rx_status->rate = val; + rx_status->rate_idx = idx; rx_status->signal = rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi); rx_status->ssi = rxdesc->rssi; @@ -639,7 +639,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, frame_control = le16_to_cpu(ieee80211hdr->frame_control); seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); - tx_rate = control->tx_rate; + tx_rate = control->tx_rate->hw_value; /* * Check whether this frame is to be acked @@ -658,7 +658,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, } else __clear_bit(ENTRY_TXD_ACK, &txdesc.flags); if (control->rts_cts_rate) - tx_rate = control->rts_cts_rate; + tx_rate = control->rts_cts_rate->hw_value; } /* @@ -760,54 +760,45 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, const int channel, const int tx_power, const int value) { - entry->chan = channel; if (channel <= 14) - entry->freq = 2407 + (5 * channel); + entry->center_freq = 2407 + (5 * channel); else - entry->freq = 5000 + (5 * channel); - entry->val = value; - entry->flag = - IEEE80211_CHAN_W_IBSS | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_SCAN; - entry->power_level = tx_power; - entry->antenna_max = 0xff; + entry->center_freq = 5000 + (5 * channel); + entry->hw_value = value; + entry->max_power = tx_power; + entry->max_antenna_gain = 0xff; } static void rt2x00lib_rate(struct ieee80211_rate *entry, const int rate, const int mask, const int plcp, const int flags) { - entry->rate = rate; - entry->val = + entry->bitrate = rate; + entry->hw_value = DEVICE_SET_RATE_FIELD(rate, RATE) | DEVICE_SET_RATE_FIELD(mask, RATEMASK) | DEVICE_SET_RATE_FIELD(plcp, PLCP); entry->flags = flags; - entry->val2 = entry->val; - if (entry->flags & IEEE80211_RATE_PREAMBLE2) - entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE); - entry->min_rssi_ack = 0; - entry->min_rssi_ack_delta = 0; + entry->hw_value_short = entry->hw_value; + if (entry->flags & IEEE80211_RATE_SHORT_PREAMBLE) + entry->hw_value_short |= DEVICE_SET_RATE_FIELD(1, PREAMBLE); } static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, struct hw_mode_spec *spec) { struct ieee80211_hw *hw = rt2x00dev->hw; - struct ieee80211_hw_mode *hwmodes; + struct ieee80211_supported_band *sbands; struct ieee80211_channel *channels; struct ieee80211_rate *rates; unsigned int i; unsigned char tx_power; - hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL); - if (!hwmodes) - goto exit; + sbands = &rt2x00dev->bands[0]; channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); if (!channels) - goto exit_free_modes; + return -ENOMEM; rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL); if (!rates) @@ -817,31 +808,31 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Initialize Rate list. */ rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB, - 0x00, IEEE80211_RATE_CCK); + 0x00, 0); rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB, - 0x01, IEEE80211_RATE_CCK_2); + 0x01, IEEE80211_RATE_SHORT_PREAMBLE); rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB, - 0x02, IEEE80211_RATE_CCK_2); + 0x02, IEEE80211_RATE_SHORT_PREAMBLE); rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB, - 0x03, IEEE80211_RATE_CCK_2); + 0x03, IEEE80211_RATE_SHORT_PREAMBLE); if (spec->num_rates > 4) { rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB, - 0x0b, IEEE80211_RATE_OFDM); + 0x0b, 0); rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB, - 0x0f, IEEE80211_RATE_OFDM); + 0x0f, 0); rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB, - 0x0a, IEEE80211_RATE_OFDM); + 0x0a, 0); rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB, - 0x0e, IEEE80211_RATE_OFDM); + 0x0e, 0); rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB, - 0x09, IEEE80211_RATE_OFDM); + 0x09, 0); rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB, - 0x0d, IEEE80211_RATE_OFDM); + 0x0d, 0); rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB, - 0x08, IEEE80211_RATE_OFDM); + 0x08, 0); rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB, - 0x0c, IEEE80211_RATE_OFDM); + 0x0c, 0); } /* @@ -862,27 +853,27 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, /* * Intitialize 802.11b * Rates: CCK. - * Channels: OFDM. + * Channels: 2.4 GHz */ if (spec->num_modes > HWMODE_B) { - hwmodes[HWMODE_B].mode = MODE_IEEE80211B; - hwmodes[HWMODE_B].num_channels = 14; - hwmodes[HWMODE_B].num_rates = 4; - hwmodes[HWMODE_B].channels = channels; - hwmodes[HWMODE_B].rates = rates; + sbands[IEEE80211_BAND_2GHZ].n_channels = 14; + sbands[IEEE80211_BAND_2GHZ].n_bitrates = 4; + sbands[IEEE80211_BAND_2GHZ].channels = channels; + sbands[IEEE80211_BAND_2GHZ].bitrates = rates; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; } /* * Intitialize 802.11g * Rates: CCK, OFDM. - * Channels: OFDM. + * Channels: 2.4 GHz */ if (spec->num_modes > HWMODE_G) { - hwmodes[HWMODE_G].mode = MODE_IEEE80211G; - hwmodes[HWMODE_G].num_channels = 14; - hwmodes[HWMODE_G].num_rates = spec->num_rates; - hwmodes[HWMODE_G].channels = channels; - hwmodes[HWMODE_G].rates = rates; + sbands[IEEE80211_BAND_2GHZ].n_channels = 14; + sbands[IEEE80211_BAND_2GHZ].n_bitrates = spec->num_rates; + sbands[IEEE80211_BAND_2GHZ].channels = channels; + sbands[IEEE80211_BAND_2GHZ].bitrates = rates; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; } /* @@ -891,39 +882,17 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Channels: OFDM, UNII, HiperLAN2. */ if (spec->num_modes > HWMODE_A) { - hwmodes[HWMODE_A].mode = MODE_IEEE80211A; - hwmodes[HWMODE_A].num_channels = spec->num_channels - 14; - hwmodes[HWMODE_A].num_rates = spec->num_rates - 4; - hwmodes[HWMODE_A].channels = &channels[14]; - hwmodes[HWMODE_A].rates = &rates[4]; + sbands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14; + sbands[IEEE80211_BAND_5GHZ].n_bitrates = spec->num_rates - 4; + sbands[IEEE80211_BAND_5GHZ].channels = &channels[14]; + sbands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; } - if (spec->num_modes > HWMODE_G && - ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G])) - goto exit_free_rates; - - if (spec->num_modes > HWMODE_B && - ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B])) - goto exit_free_rates; - - if (spec->num_modes > HWMODE_A && - ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A])) - goto exit_free_rates; - - rt2x00dev->hwmodes = hwmodes; - return 0; -exit_free_rates: - kfree(rates); - -exit_free_channels: + exit_free_channels: kfree(channels); - -exit_free_modes: - kfree(hwmodes); - -exit: ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n"); return -ENOMEM; } @@ -933,11 +902,11 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev) if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags)) ieee80211_unregister_hw(rt2x00dev->hw); - if (likely(rt2x00dev->hwmodes)) { - kfree(rt2x00dev->hwmodes->channels); - kfree(rt2x00dev->hwmodes->rates); - kfree(rt2x00dev->hwmodes); - rt2x00dev->hwmodes = NULL; + if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) { + kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels); + kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates); + rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; } } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 59e87a1d96a4..1dd30510ed1e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -426,12 +426,12 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - (rt2x00dev->curr_hwmode != HWMODE_A)); + (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ)); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); @@ -446,7 +446,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_B: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); @@ -602,7 +602,7 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, unsigned int i; u32 reg; - if (rt2x00dev->curr_hwmode == HWMODE_A) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); } else { @@ -616,10 +616,9 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - (rt2x00dev->curr_hwmode == HWMODE_B || - rt2x00dev->curr_hwmode == HWMODE_G)); + rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - (rt2x00dev->curr_hwmode == HWMODE_A)); + rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); @@ -698,9 +697,9 @@ static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, - (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)); + rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, - (rt2x00dev->rx_status.phymode != MODE_IEEE80211A)); + rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ); arg0 = rt2x00dev->led_reg & 0xff; arg1 = (rt2x00dev->led_reg >> 8) & 0xff; @@ -798,7 +797,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Determine r17 bounds. */ - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { low_bound = 0x28; up_bound = 0x48; if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { @@ -1544,8 +1543,10 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); +/* XXX: removed for now rt2x00_set_field32(&word, TXD_W5_TX_POWER, TXPOWER_TO_DEV(control->power_level)); + */ rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); @@ -1637,7 +1638,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) offset += 14; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 4b5bde8b53de..9cbc879da037 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -439,13 +439,13 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) - && (rt2x00dev->curr_hwmode != HWMODE_A); + && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); @@ -460,7 +460,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_B: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); @@ -555,7 +555,7 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, unsigned int i; u32 reg; - if (rt2x00dev->curr_hwmode == HWMODE_A) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); } else { @@ -569,10 +569,9 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, rt73usb_register_read(rt2x00dev, PHY_CSR0, ®); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - (rt2x00dev->curr_hwmode == HWMODE_B || - rt2x00dev->curr_hwmode == HWMODE_G)); + (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - (rt2x00dev->curr_hwmode == HWMODE_A)); + (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)); rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); @@ -644,9 +643,9 @@ static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, - (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)); + (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, - (rt2x00dev->rx_status.phymode != MODE_IEEE80211A)); + (rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ)); rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, rt2x00dev->led_reg, REGISTER_TIMEOUT); @@ -736,7 +735,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Determine r17 bounds. */ - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; @@ -1278,8 +1277,10 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); +/* XXX: removed for now rt2x00_set_field32(&word, TXD_W5_TX_POWER, TXPOWER_TO_DEV(control->power_level)); + */ rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); @@ -1370,7 +1371,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { if (lna == 3 || lna == 2) offset += 10; diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h index 2cbfe3c8081f..082a11f93beb 100644 --- a/drivers/net/wireless/rtl8180.h +++ b/drivers/net/wireless/rtl8180.h @@ -102,7 +102,7 @@ struct rtl8180_priv { struct rtl8180_tx_ring tx_ring[4]; struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; + struct ieee80211_supported_band band; struct pci_dev *pdev; u32 rx_conf; diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 5e9a8ace0d81..d0928c91c21c 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -49,6 +49,41 @@ static struct pci_device_id rtl8180_table[] __devinitdata = { MODULE_DEVICE_TABLE(pci, rtl8180_table); +static const struct ieee80211_rate rtl818x_rates[] = { + { .bitrate = 10, .hw_value = 0, }, + { .bitrate = 20, .hw_value = 1, }, + { .bitrate = 55, .hw_value = 2, }, + { .bitrate = 110, .hw_value = 3, }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static const struct ieee80211_channel rtl818x_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + + + + void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) { struct rtl8180_priv *priv = dev->priv; @@ -99,10 +134,10 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) /* TODO: improve signal/rssi reporting */ rx_status.signal = flags2 & 0xFF; rx_status.ssi = (flags2 >> 8) & 0x7F; - rx_status.rate = (flags >> 20) & 0xF; - rx_status.freq = dev->conf.freq; - rx_status.channel = dev->conf.channel; - rx_status.phymode = dev->conf.phymode; + /* XXX: is this correct? */ + rx_status.rate_idx = (flags >> 20) & 0xF; + rx_status.freq = dev->conf.channel->center_freq; + rx_status.band = dev->conf.channel->band; rx_status.mactime = le64_to_cpu(entry->tsft); rx_status.flag |= RX_FLAG_TSFT; if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR) @@ -223,8 +258,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb, skb->len, PCI_DMA_TODEVICE); tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS | - RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) | - (control->rts_cts_rate << 19) | skb->len; + RTL8180_TX_DESC_FLAG_LS | + (control->tx_rate->hw_value << 24) | + (control->rts_cts_rate->hw_value << 19) | skb->len; if (priv->r8185) tx_flags |= RTL8180_TX_DESC_FLAG_DMA | @@ -246,9 +282,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb, unsigned int remainder; plcp_len = DIV_ROUND_UP(16 * (skb->len + 4), - (control->rate->rate * 2) / 10); + (control->tx_rate->bitrate * 2) / 10); remainder = (16 * (skb->len + 4)) % - ((control->rate->rate * 2) / 10); + ((control->tx_rate->bitrate * 2) / 10); if (remainder > 0 && remainder <= 6) plcp_len |= 1 << 15; } @@ -261,8 +297,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb, entry->plcp_len = cpu_to_le16(plcp_len); entry->tx_buf = cpu_to_le32(mapping); entry->frame_len = cpu_to_le32(skb->len); - entry->flags2 = control->alt_retry_rate != -1 ? - control->alt_retry_rate << 4 : 0; + entry->flags2 = control->alt_retry_rate != NULL ? + control->alt_retry_rate->bitrate << 4 : 0; entry->retry_limit = control->retry_limit; entry->flags = cpu_to_le32(tx_flags); __skb_queue_tail(&ring->queue, skb); @@ -838,19 +874,19 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, goto err_free_dev; } + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); + BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); + memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); - priv->modes[0].mode = MODE_IEEE80211G; - priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates); - priv->modes[0].rates = priv->rates; - priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[0].channels = priv->channels; - priv->modes[1].mode = MODE_IEEE80211B; - priv->modes[1].num_rates = 4; - priv->modes[1].rates = priv->rates; - priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[1].channels = priv->channels; - priv->mode = IEEE80211_IF_TYPE_INVALID; + + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = 4; + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS; dev->queues = 1; @@ -879,15 +915,10 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC; if (priv->r8185) { - if ((err = ieee80211_register_hwmode(dev, &priv->modes[0]))) - goto err_iounmap; - + priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); pci_try_set_mwi(pdev); } - if ((err = ieee80211_register_hwmode(dev, &priv->modes[1]))) - goto err_iounmap; - eeprom.data = dev; eeprom.register_read = rtl8180_eeprom_register_read; eeprom.register_write = rtl8180_eeprom_register_write; @@ -950,8 +981,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, for (i = 0; i < 14; i += 2) { u16 txpwr; eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr); - priv->channels[i].val = txpwr & 0xFF; - priv->channels[i + 1].val = txpwr >> 8; + priv->channels[i].hw_value = txpwr & 0xFF; + priv->channels[i + 1].hw_value = txpwr >> 8; } /* OFDM TX power */ @@ -959,8 +990,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, for (i = 0; i < 14; i += 2) { u16 txpwr; eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); - priv->channels[i].val |= (txpwr & 0xFF) << 8; - priv->channels[i + 1].val |= txpwr & 0xFF00; + priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; + priv->channels[i + 1].hw_value |= txpwr & 0xFF00; } } diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c index 8293e19c4c59..5d47935dbac3 100644 --- a/drivers/net/wireless/rtl8180_grf5101.c +++ b/drivers/net/wireless/rtl8180_grf5101.c @@ -73,8 +73,9 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; - u32 txpw = priv->channels[conf->channel - 1].val & 0xFF; - u32 chan = conf->channel - 1; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; + u32 chan = channel - 1; /* set TX power */ write_grf5101(dev, 0x15, 0x0); diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c index 98fe9fd64968..a34dfd382b6d 100644 --- a/drivers/net/wireless/rtl8180_max2820.c +++ b/drivers/net/wireless/rtl8180_max2820.c @@ -78,8 +78,9 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; - unsigned int chan_idx = conf ? conf->channel - 1 : 0; - u32 txpw = priv->channels[chan_idx].val & 0xFF; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + unsigned int chan_idx = channel - 1; + u32 txpw = priv->channels[chan_idx].hw_value & 0xFF; u32 chan = max2820_chan[chan_idx]; /* While philips SA2400 drive the PA bias from diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl8180_rtl8225.c index ef3832bee85c..cd22781728a9 100644 --- a/drivers/net/wireless/rtl8180_rtl8225.c +++ b/drivers/net/wireless/rtl8180_rtl8225.c @@ -261,8 +261,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) u32 reg; int i; - cck_power = priv->channels[channel - 1].val & 0xFF; - ofdm_power = priv->channels[channel - 1].val >> 8; + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + ofdm_power = priv->channels[channel - 1].hw_value >> 8; cck_power = min(cck_power, (u8)35); ofdm_power = min(ofdm_power, (u8)35); @@ -476,8 +476,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) const u8 *tmp; int i; - cck_power = priv->channels[channel - 1].val & 0xFF; - ofdm_power = priv->channels[channel - 1].val >> 8; + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + ofdm_power = priv->channels[channel - 1].hw_value >> 8; if (channel == 14) tmp = rtl8225z2_tx_power_cck_ch14; @@ -716,13 +716,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; + int chan = ieee80211_frequency_to_channel(conf->channel->center_freq); if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, conf->channel); + rtl8225_rf_set_tx_power(dev, chan); else - rtl8225z2_rf_set_tx_power(dev, conf->channel); + rtl8225z2_rf_set_tx_power(dev, chan); - rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]); + rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); msleep(10); if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c index e08ace7b1cb7..0311b4ea124c 100644 --- a/drivers/net/wireless/rtl8180_sa2400.c +++ b/drivers/net/wireless/rtl8180_sa2400.c @@ -80,8 +80,9 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; - u32 txpw = priv->channels[conf->channel - 1].val & 0xFF; - u32 chan = sa2400_chan[conf->channel - 1]; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; + u32 chan = sa2400_chan[channel - 1]; write_sa2400(dev, 7, txpw); diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index 8680a0b6433c..076d88b6db0e 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h @@ -71,7 +71,7 @@ struct rtl8187_priv { /* rtl8187 specific */ struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; + struct ieee80211_supported_band band; struct usb_device *udev; u32 rx_conf; u16 txpwr_base; diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index f44505994a0e..6ef67990692d 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -45,6 +45,38 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { MODULE_DEVICE_TABLE(usb, rtl8187_table); +static const struct ieee80211_rate rtl818x_rates[] = { + { .bitrate = 10, .hw_value = 0, }, + { .bitrate = 20, .hw_value = 1, }, + { .bitrate = 55, .hw_value = 2, }, + { .bitrate = 110, .hw_value = 3, }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static const struct ieee80211_channel rtl818x_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + static void rtl8187_iowrite_async_cb(struct urb *urb) { kfree(urb->context); @@ -146,8 +178,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, flags = skb->len; flags |= RTL8187_TX_FLAG_NO_ENCRYPT; - flags |= control->rts_cts_rate << 19; - flags |= control->tx_rate << 24; + flags |= control->rts_cts_rate->hw_value << 19; + flags |= control->tx_rate->hw_value << 24; if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data)) flags |= RTL8187_TX_FLAG_MORE_FRAG; if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { @@ -225,10 +257,9 @@ static void rtl8187_rx_cb(struct urb *urb) rx_status.antenna = (hdr->signal >> 7) & 1; rx_status.signal = 64 - min(hdr->noise, (u8)64); rx_status.ssi = signal; - rx_status.rate = rate; - rx_status.freq = dev->conf.freq; - rx_status.channel = dev->conf.channel; - rx_status.phymode = dev->conf.phymode; + rx_status.rate_idx = rate; + rx_status.freq = dev->conf.channel->center_freq; + rx_status.band = dev->conf.channel->band; rx_status.mactime = le64_to_cpu(hdr->mac_time); rx_status.flag |= RX_FLAG_TSFT; if (flags & (1 << 13)) @@ -682,19 +713,22 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, usb_get_dev(udev); skb_queue_head_init(&priv->rx_queue); + + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); + BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); + memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); priv->map = (struct rtl818x_csr *)0xFF00; - priv->modes[0].mode = MODE_IEEE80211G; - priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates); - priv->modes[0].rates = priv->rates; - priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[0].channels = priv->channels; - priv->modes[1].mode = MODE_IEEE80211B; - priv->modes[1].num_rates = 4; - priv->modes[1].rates = priv->rates; - priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[1].channels = priv->channels; + + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + priv->mode = IEEE80211_IF_TYPE_MNTR; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS; @@ -703,10 +737,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->max_rssi = 65; dev->max_signal = 64; - for (i = 0; i < 2; i++) - if ((err = ieee80211_register_hwmode(dev, &priv->modes[i]))) - goto err_free_dev; - eeprom.data = dev; eeprom.register_read = rtl8187_eeprom_register_read; eeprom.register_write = rtl8187_eeprom_register_write; @@ -730,20 +760,20 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, for (i = 0; i < 3; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i, &txpwr); - (*channel++).val = txpwr & 0xFF; - (*channel++).val = txpwr >> 8; + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; } for (i = 0; i < 2; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i, &txpwr); - (*channel++).val = txpwr & 0xFF; - (*channel++).val = txpwr >> 8; + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; } for (i = 0; i < 2; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i, &txpwr); - (*channel++).val = txpwr & 0xFF; - (*channel++).val = txpwr >> 8; + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; } eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c index b713de17ba0a..9146387b4c5e 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl8187_rtl8225.c @@ -283,8 +283,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) u32 reg; int i; - cck_power = priv->channels[channel - 1].val & 0xF; - ofdm_power = priv->channels[channel - 1].val >> 4; + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; cck_power = min(cck_power, (u8)11); ofdm_power = min(ofdm_power, (u8)35); @@ -500,8 +500,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) u32 reg; int i; - cck_power = priv->channels[channel - 1].val & 0xF; - ofdm_power = priv->channels[channel - 1].val >> 4; + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; cck_power = min(cck_power, (u8)15); cck_power += priv->txpwr_base & 0xF; @@ -735,13 +735,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8187_priv *priv = dev->priv; + int chan = ieee80211_frequency_to_channel(conf->channel->center_freq); if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, conf->channel); + rtl8225_rf_set_tx_power(dev, chan); else - rtl8225z2_rf_set_tx_power(dev, conf->channel); + rtl8225z2_rf_set_tx_power(dev, chan); - rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]); + rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); msleep(10); } diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 1e7d6f8278d7..4f7d38f506eb 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h @@ -175,74 +175,4 @@ struct rtl818x_rf_ops { void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); }; -static const struct ieee80211_rate rtl818x_rates[] = { - { .rate = 10, - .val = 0, - .flags = IEEE80211_RATE_CCK }, - { .rate = 20, - .val = 1, - .flags = IEEE80211_RATE_CCK }, - { .rate = 55, - .val = 2, - .flags = IEEE80211_RATE_CCK }, - { .rate = 110, - .val = 3, - .flags = IEEE80211_RATE_CCK }, - { .rate = 60, - .val = 4, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 90, - .val = 5, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 120, - .val = 6, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 180, - .val = 7, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 240, - .val = 8, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 360, - .val = 9, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 480, - .val = 10, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 540, - .val = 11, - .flags = IEEE80211_RATE_OFDM }, -}; - -static const struct ieee80211_channel rtl818x_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484} -}; - #endif /* RTL818X_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 99e5b03b3f51..e3fba6f09455 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -986,7 +986,7 @@ static int print_fw_version(struct zd_chip *chip) return 0; } -static int set_mandatory_rates(struct zd_chip *chip, int mode) +static int set_mandatory_rates(struct zd_chip *chip, int gmode) { u32 rates; ZD_ASSERT(mutex_is_locked(&chip->mutex)); @@ -994,17 +994,12 @@ static int set_mandatory_rates(struct zd_chip *chip, int mode) * that the device is supporting. Until further notice we should try * to support 802.11g also for full speed USB. */ - switch (mode) { - case MODE_IEEE80211B: + if (!gmode) rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M; - break; - case MODE_IEEE80211G: + else rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M| CR_RATE_6M|CR_RATE_12M|CR_RATE_24M; - break; - default: - return -EINVAL; - } + return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); } @@ -1108,7 +1103,7 @@ int zd_chip_init_hw(struct zd_chip *chip) * It might be discussed, whether we should suppport pure b mode for * full speed USB. */ - r = set_mandatory_rates(chip, MODE_IEEE80211G); + r = set_mandatory_rates(chip, 1); if (r) goto out; /* Disabling interrupts is certainly a smart thing here. diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c index 7c277ec43f79..d8dc41ec0e5d 100644 --- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c @@ -65,16 +65,14 @@ static const struct channel_range *zd_channel_range(u8 regdomain) static void unmask_bg_channels(struct ieee80211_hw *hw, const struct channel_range *range, - struct ieee80211_hw_mode *mode) + struct ieee80211_supported_band *sband) { u8 channel; for (channel = range->start; channel < range->end; channel++) { struct ieee80211_channel *chan = - &mode->channels[CHAN_TO_IDX(channel)]; - chan->flag |= IEEE80211_CHAN_W_SCAN | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_IBSS; + &sband->channels[CHAN_TO_IDX(channel)]; + chan->flags = 0; } } @@ -97,7 +95,6 @@ void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain) range = zd_channel_range(ZD_REGDOMAIN_FCC); } - unmask_bg_channels(hw, range, &mac->modes[0]); - unmask_bg_channels(hw, range, &mac->modes[1]); + unmask_bg_channels(hw, range, &mac->band); } diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 76ef2d83919d..21b653458831 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -34,76 +34,61 @@ /* This table contains the hardware specific values for the modulation rates. */ static const struct ieee80211_rate zd_rates[] = { - { .rate = 10, - .val = ZD_CCK_RATE_1M, - .flags = IEEE80211_RATE_CCK }, - { .rate = 20, - .val = ZD_CCK_RATE_2M, - .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 55, - .val = ZD_CCK_RATE_5_5M, - .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 110, - .val = ZD_CCK_RATE_11M, - .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 60, - .val = ZD_OFDM_RATE_6M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 90, - .val = ZD_OFDM_RATE_9M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 120, - .val = ZD_OFDM_RATE_12M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 180, - .val = ZD_OFDM_RATE_18M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 240, - .val = ZD_OFDM_RATE_24M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 360, - .val = ZD_OFDM_RATE_36M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 480, - .val = ZD_OFDM_RATE_48M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 540, - .val = ZD_OFDM_RATE_54M, - .flags = IEEE80211_RATE_OFDM }, + { .bitrate = 10, + .hw_value = ZD_CCK_RATE_1M, }, + { .bitrate = 20, + .hw_value = ZD_CCK_RATE_2M, + .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, + .hw_value = ZD_CCK_RATE_5_5M, + .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, + .hw_value = ZD_CCK_RATE_11M, + .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60, + .hw_value = ZD_OFDM_RATE_6M, + .flags = 0 }, + { .bitrate = 90, + .hw_value = ZD_OFDM_RATE_9M, + .flags = 0 }, + { .bitrate = 120, + .hw_value = ZD_OFDM_RATE_12M, + .flags = 0 }, + { .bitrate = 180, + .hw_value = ZD_OFDM_RATE_18M, + .flags = 0 }, + { .bitrate = 240, + .hw_value = ZD_OFDM_RATE_24M, + .flags = 0 }, + { .bitrate = 360, + .hw_value = ZD_OFDM_RATE_36M, + .flags = 0 }, + { .bitrate = 480, + .hw_value = ZD_OFDM_RATE_48M, + .flags = 0 }, + { .bitrate = 540, + .hw_value = ZD_OFDM_RATE_54M, + .flags = 0 }, }; static const struct ieee80211_channel zd_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484} + { .center_freq = 2412, .hw_value = 1 }, + { .center_freq = 2417, .hw_value = 2 }, + { .center_freq = 2422, .hw_value = 3 }, + { .center_freq = 2427, .hw_value = 4 }, + { .center_freq = 2432, .hw_value = 5 }, + { .center_freq = 2437, .hw_value = 6 }, + { .center_freq = 2442, .hw_value = 7 }, + { .center_freq = 2447, .hw_value = 8 }, + { .center_freq = 2452, .hw_value = 9 }, + { .center_freq = 2457, .hw_value = 10 }, + { .center_freq = 2462, .hw_value = 11 }, + { .center_freq = 2467, .hw_value = 12 }, + { .center_freq = 2472, .hw_value = 13 }, + { .center_freq = 2484, .hw_value = 14 }, }; static void housekeeping_init(struct zd_mac *mac); @@ -503,7 +488,9 @@ static int fill_ctrlset(struct zd_mac *mac, ZD_ASSERT(frag_len <= 0xffff); - cs->modulation = control->tx_rate; + cs->modulation = control->tx_rate->hw_value; + if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) + cs->modulation = control->tx_rate->hw_value_short; cs->tx_length = cpu_to_le16(frag_len); @@ -631,6 +618,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) int bad_frame = 0; u16 fc; bool is_qos, is_4addr, need_padding; + int i; + u8 rate; if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ + FCS_LEN + sizeof(struct rx_status)) @@ -660,14 +649,19 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) } } - stats.channel = _zd_chip_get_channel(&mac->chip); - stats.freq = zd_channels[stats.channel - 1].freq; - stats.phymode = MODE_IEEE80211G; + stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; + stats.band = IEEE80211_BAND_2GHZ; stats.ssi = status->signal_strength; stats.signal = zd_rx_qual_percent(buffer, length - sizeof(struct rx_status), status); - stats.rate = zd_rx_rate(buffer, status); + + rate = zd_rx_rate(buffer, status); + + /* todo: return index in the big switches in zd_rx_rate instead */ + for (i = 0; i < mac->band.n_bitrates; i++) + if (rate == mac->band.bitrates[i].hw_value) + stats.rate_idx = i; length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status); buffer += ZD_PLCP_HEADER_SIZE; @@ -736,7 +730,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw, static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) { struct zd_mac *mac = zd_hw_mac(hw); - return zd_chip_set_channel(&mac->chip, conf->channel); + return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); } static int zd_op_config_interface(struct ieee80211_hw *hw, @@ -894,7 +888,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) { struct zd_mac *mac; struct ieee80211_hw *hw; - int i; hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops); if (!hw) { @@ -912,19 +905,14 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) memcpy(mac->channels, zd_channels, sizeof(zd_channels)); memcpy(mac->rates, zd_rates, sizeof(zd_rates)); - mac->modes[0].mode = MODE_IEEE80211G; - mac->modes[0].num_rates = ARRAY_SIZE(zd_rates); - mac->modes[0].rates = mac->rates; - mac->modes[0].num_channels = ARRAY_SIZE(zd_channels); - mac->modes[0].channels = mac->channels; - mac->modes[1].mode = MODE_IEEE80211B; - mac->modes[1].num_rates = 4; - mac->modes[1].rates = mac->rates; - mac->modes[1].num_channels = ARRAY_SIZE(zd_channels); - mac->modes[1].channels = mac->channels; - - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED; + mac->band.n_bitrates = ARRAY_SIZE(zd_rates); + mac->band.bitrates = mac->rates; + mac->band.n_channels = ARRAY_SIZE(zd_channels); + mac->band.channels = mac->channels; + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; + + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS; hw->max_rssi = 100; hw->max_signal = 100; @@ -933,14 +921,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) skb_queue_head_init(&mac->ack_wait_queue); - for (i = 0; i < 2; i++) { - if (ieee80211_register_hwmode(hw, &mac->modes[i])) { - dev_dbg_f(&intf->dev, "cannot register hwmode\n"); - ieee80211_free_hw(hw); - return NULL; - } - } - zd_chip_init(&mac->chip, hw, intf); housekeeping_init(mac); INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 2dde108df767..67dea9739c8f 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -185,7 +185,7 @@ struct zd_mac { struct sk_buff_head ack_wait_queue; struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; + struct ieee80211_supported_band band; /* Short preamble (used for RTS/CTS) */ unsigned int short_preamble:1; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 277488176a44..460da54a0019 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -69,95 +69,6 @@ * not do so then mac80211 may add this under certain circumstances. */ -#define IEEE80211_CHAN_W_SCAN 0x00000001 -#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002 -#define IEEE80211_CHAN_W_IBSS 0x00000004 - -/* Channel information structure. Low-level driver is expected to fill in chan, - * freq, and val fields. Other fields will be filled in by 80211.o based on - * hostapd information and low-level driver does not need to use them. The - * limits for each channel will be provided in 'struct ieee80211_conf' when - * configuring the low-level driver with hw->config callback. If a device has - * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED - * can be set to let the driver configure all fields */ -struct ieee80211_channel { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int val; /* hw specific value for the channel */ - int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */ - unsigned char power_level; - unsigned char antenna_max; -}; - -#define IEEE80211_RATE_ERP 0x00000001 -#define IEEE80211_RATE_BASIC 0x00000002 -#define IEEE80211_RATE_PREAMBLE2 0x00000004 -#define IEEE80211_RATE_SUPPORTED 0x00000010 -#define IEEE80211_RATE_OFDM 0x00000020 -#define IEEE80211_RATE_CCK 0x00000040 -#define IEEE80211_RATE_MANDATORY 0x00000100 - -#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2) -#define IEEE80211_RATE_MODULATION(f) \ - (f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM)) - -/* Low-level driver should set PREAMBLE2, OFDM and CCK flags. - * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the - * configuration. */ -struct ieee80211_rate { - int rate; /* rate in 100 kbps */ - int val; /* hw specific value for the rate */ - int flags; /* IEEE80211_RATE_ flags */ - int val2; /* hw specific value for the rate when using short preamble - * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for - * 2, 5.5, and 11 Mbps) */ - signed char min_rssi_ack; - unsigned char min_rssi_ack_delta; - - /* following fields are set by 80211.o and need not be filled by the - * low-level driver */ - int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for - * optimizing channel utilization estimates */ -}; - -/** - * enum ieee80211_phymode - PHY modes - * - * @MODE_IEEE80211A: 5GHz as defined by 802.11a/802.11h - * @MODE_IEEE80211B: 2.4 GHz as defined by 802.11b - * @MODE_IEEE80211G: 2.4 GHz as defined by 802.11g (with OFDM), - * backwards compatible with 11b mode - * @NUM_IEEE80211_MODES: internal - */ -enum ieee80211_phymode { - MODE_IEEE80211A, - MODE_IEEE80211B, - MODE_IEEE80211G, - - /* keep last */ - NUM_IEEE80211_MODES -}; - -/** - * struct ieee80211_ht_info - describing STA's HT capabilities - * - * This structure describes most essential parameters needed - * to describe 802.11n HT capabilities for an STA. - * - * @ht_supported: is HT supported by STA, 0: no, 1: yes - * @cap: HT capabilities map as described in 802.11n spec - * @ampdu_factor: Maximum A-MPDU length factor - * @ampdu_density: Minimum A-MPDU spacing - * @supp_mcs_set: Supported MCS set as described in 802.11n spec - */ -struct ieee80211_ht_info { - u8 ht_supported; - u16 cap; /* use IEEE80211_HT_CAP_ */ - u8 ampdu_factor; - u8 ampdu_density; - u8 supp_mcs_set[16]; -}; - /** * struct ieee80211_ht_bss_info - describing BSS's HT characteristics * @@ -174,30 +85,6 @@ struct ieee80211_ht_bss_info { u8 bss_op_mode; /* use IEEE80211_HT_IE_ */ }; -/** - * struct ieee80211_hw_mode - PHY mode definition - * - * This structure describes the capabilities supported by the device - * in a single PHY mode. - * - * @list: internal - * @channels: pointer to array of supported channels - * @rates: pointer to array of supported bitrates - * @mode: the PHY mode for this definition - * @num_channels: number of supported channels - * @num_rates: number of supported bitrates - * @ht_info: PHY's 802.11n HT abilities for this mode - */ -struct ieee80211_hw_mode { - struct list_head list; - struct ieee80211_channel *channels; - struct ieee80211_rate *rates; - enum ieee80211_phymode mode; - int num_channels; - int num_rates; - struct ieee80211_ht_info ht_info; -}; - /** * struct ieee80211_tx_queue_params - transmit queue configuration * @@ -320,11 +207,13 @@ struct ieee80211_bss_conf { struct ieee80211_tx_control { struct ieee80211_vif *vif; - int tx_rate; /* Transmit rate, given as the hw specific value for the - * rate (from struct ieee80211_rate) */ - int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw - * specific value for the rate (from - * struct ieee80211_rate) */ + struct ieee80211_rate *tx_rate; + + /* Transmit rate for RTS/CTS frame */ + struct ieee80211_rate *rts_cts_rate; + + /* retry rate for the last retries */ + struct ieee80211_rate *alt_retry_rate; #define IEEE80211_TXCTL_REQ_TX_STATUS (1<<0)/* request TX status callback for * this frame */ @@ -343,6 +232,7 @@ struct ieee80211_tx_control { #define IEEE80211_TXCTL_REQUEUE (1<<7) #define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8) /* this is a first fragment of * the frame */ +#define IEEE80211_TXCTL_SHORT_PREAMBLE (1<<9) #define IEEE80211_TXCTL_LONG_RETRY_LIMIT (1<<10) /* this frame should be send * using the through * set_retry_limit configured @@ -359,20 +249,11 @@ struct ieee80211_tx_control { u8 retry_limit; /* 1 = only first attempt, 2 = one retry, .. * This could be used when set_retry_limit * is not implemented by the driver */ - u8 power_level; /* per-packet transmit power level, in dBm */ u8 antenna_sel_tx; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */ u8 icv_len; /* length of the ICV/MIC field in octets */ u8 iv_len; /* length of the IV field in octets */ u8 queue; /* hardware queue to use for this frame; * 0 = highest, hw->queues-1 = lowest */ - struct ieee80211_rate *rate; /* internal 80211.o rate */ - struct ieee80211_rate *rts_rate; /* internal 80211.o rate - * for RTS/CTS */ - int alt_retry_rate; /* retry rate for the last retries, given as the - * hw specific value for the rate (from - * struct ieee80211_rate). To be used to limit - * packet dropping when probing higher rates, if hw - * supports multiple retry rates. -1 = not used */ int type; /* internal */ }; @@ -415,26 +296,24 @@ enum mac80211_rx_flags { * supported by hardware) to the 802.11 code with each received * frame. * @mactime: MAC timestamp as defined by 802.11 + * @band: the active band when this frame was received * @freq: frequency the radio was tuned to when receiving this frame, in MHz - * @channel: channel the radio was tuned to - * @phymode: active PHY mode * @ssi: signal strength when receiving this frame * @signal: used as 'qual' in statistics reporting * @noise: PHY noise when receiving this frame * @antenna: antenna used - * @rate: data rate + * @rate_idx: index of data rate into band's supported rates * @flag: %RX_FLAG_* */ struct ieee80211_rx_status { u64 mactime; + enum ieee80211_band band; int freq; - int channel; - enum ieee80211_phymode phymode; int ssi; int signal; int noise; int antenna; - int rate; + int rate_idx; int flag; }; @@ -509,41 +388,30 @@ enum ieee80211_conf_flags { * * @radio_enabled: when zero, driver is required to switch off the radio. * TODO make a flag - * @channel: IEEE 802.11 channel number - * @freq: frequency in MHz - * @channel_val: hardware specific channel value for the channel - * @phymode: PHY mode to activate (REMOVE) - * @chan: channel to switch to, pointer to the channel information - * @mode: pointer to mode definition - * @regulatory_domain: ?? * @beacon_int: beacon interval (TODO make interface config) * @flags: configuration flags defined above - * @power_level: transmit power limit for current regulatory domain in dBm - * @antenna_max: maximum antenna gain + * @power_level: requested transmit power (in dBm) + * @max_antenna_gain: maximum antenna gain (in dBi) * @antenna_sel_tx: transmit antenna selection, 0: default/diversity, * 1/2: antenna 0/1 * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx * @ht_conf: describes current self configuration of 802.11n HT capabilies * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters + * @channel: the channel to tune to */ struct ieee80211_conf { - int channel; /* IEEE 802.11 channel number */ - int freq; /* MHz */ - int channel_val; /* hw specific value for the channel */ - - enum ieee80211_phymode phymode; - struct ieee80211_channel *chan; - struct ieee80211_hw_mode *mode; unsigned int regulatory_domain; int radio_enabled; int beacon_int; u32 flags; - u8 power_level; - u8 antenna_max; + int power_level; + int max_antenna_gain; u8 antenna_sel_tx; u8 antenna_sel_rx; + struct ieee80211_channel *channel; + struct ieee80211_ht_info ht_conf; struct ieee80211_ht_bss_info ht_bss_conf; }; @@ -764,15 +632,19 @@ enum sta_notify_cmd { * %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is also not set because * otherwise the stack will not know when the DTIM beacon was sent. * - * @IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED: - * Channels are already configured to the default regulatory domain - * specified in the device's EEPROM + * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE: + * Hardware is not capable of short slot operation on the 2.4 GHz band. + * + * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE: + * Hardware is not capable of receiving frames with short preamble on + * the 2.4 GHz band. */ enum ieee80211_hw_flags { IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE = 1<<0, IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, - IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED = 1<<3, + IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, + IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, }; /** @@ -784,7 +656,8 @@ enum ieee80211_hw_flags { * @wiphy: This points to the &struct wiphy allocated for this * 802.11 PHY. You must fill in the @perm_addr and @dev * members of this structure using SET_IEEE80211_DEV() - * and SET_IEEE80211_PERM_ADDR(). + * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported + * bands (with channels, bitrates) are registered here. * * @conf: &struct ieee80211_conf, device configuration, don't use. * @@ -1062,7 +935,9 @@ enum ieee80211_ampdu_mlme_action { * given local_address is enabled. * * @hw_scan: Ask the hardware to service the scan request, no need to start - * the scan state machine in stack. + * the scan state machine in stack. The scan must honour the channel + * configuration done by the regulatory agent in the wiphy's registered + * bands. * * @get_stats: return low-level statistics * @@ -1284,10 +1159,6 @@ static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) #endif } -/* Register a new hardware PHYMODE capability to the stack. */ -int ieee80211_register_hwmode(struct ieee80211_hw *hw, - struct ieee80211_hw_mode *mode); - /** * ieee80211_unregister_hw - Unregister a hardware device * @@ -1461,7 +1332,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, * @hw: pointer obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. * @frame_len: the length of the frame. - * @rate: the rate (in 100kbps) at which the frame is going to be transmitted. + * @rate: the rate at which the frame is going to be transmitted. * * Calculate the duration field of some generic frame, given its * length and transmission rate (in 100kbps). @@ -1469,7 +1340,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, size_t frame_len, - int rate); + struct ieee80211_rate *rate); /** * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames diff --git a/include/net/wireless.h b/include/net/wireless.h index d30c4ba8fd99..c7f805ee5545 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -12,6 +12,162 @@ #include #include +/** + * enum ieee80211_band - supported frequency bands + * + * The bands are assigned this way because the supported + * bitrates differ in these bands. + * + * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band + * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) + */ +enum ieee80211_band { + IEEE80211_BAND_2GHZ, + IEEE80211_BAND_5GHZ, + + /* keep last */ + IEEE80211_NUM_BANDS +}; + +/** + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted + * on this channel. + * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + */ +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, + IEEE80211_CHAN_NO_IBSS = 1<<2, + IEEE80211_CHAN_RADAR = 1<<3, +}; + +/** + * struct ieee80211_channel - channel definition + * + * This structure describes a single channel for use + * with cfg80211. + * + * @center_freq: center frequency in MHz + * @hw_value: hardware-specific value for the channel + * @flags: channel flags from &enum ieee80211_channel_flags. + * @orig_flags: channel flags at registration time, used by regulatory + * code to support devices with additional restrictions + * @band: band this channel belongs to. + * @max_antenna_gain: maximum antenna gain in dBi + * @max_power: maximum transmission power (in dBm) + * @orig_mag: internal use + * @orig_mpwr: internal use + */ +struct ieee80211_channel { + enum ieee80211_band band; + u16 center_freq; + u16 hw_value; + u32 flags; + int max_antenna_gain; + int max_power; + u32 orig_flags; + int orig_mag, orig_mpwr; +}; + +/** + * enum ieee80211_rate_flags - rate flags + * + * Hardware/specification flags for rates. These are structured + * in a way that allows using the same bitrate structure for + * different bands/PHY modes. + * + * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short + * preamble on this bitrate; only relevant in 2.4GHz band and + * with CCK rates. + * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate + * when used with 802.11a (on the 5 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate + * when used with 802.11b (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate + * when used with 802.11g (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode. + */ +enum ieee80211_rate_flags { + IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, + IEEE80211_RATE_MANDATORY_A = 1<<1, + IEEE80211_RATE_MANDATORY_B = 1<<2, + IEEE80211_RATE_MANDATORY_G = 1<<3, + IEEE80211_RATE_ERP_G = 1<<4, +}; + +/** + * struct ieee80211_rate - bitrate definition + * + * This structure describes a bitrate that an 802.11 PHY can + * operate with. The two values @hw_value and @hw_value_short + * are only for driver use when pointers to this structure are + * passed around. + * + * @flags: rate-specific flags + * @bitrate: bitrate in units of 100 Kbps + * @hw_value: driver/hardware value for this rate + * @hw_value_short: driver/hardware value for this rate when + * short preamble is used + */ +struct ieee80211_rate { + u32 flags; + u16 bitrate; + u16 hw_value, hw_value_short; +}; + +/** + * struct ieee80211_ht_info - describing STA's HT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11n HT capabilities for an STA. + * + * @ht_supported: is HT supported by STA, 0: no, 1: yes + * @cap: HT capabilities map as described in 802.11n spec + * @ampdu_factor: Maximum A-MPDU length factor + * @ampdu_density: Minimum A-MPDU spacing + * @supp_mcs_set: Supported MCS set as described in 802.11n spec + */ +struct ieee80211_ht_info { + u16 cap; /* use IEEE80211_HT_CAP_ */ + u8 ht_supported; + u8 ampdu_factor; + u8 ampdu_density; + u8 supp_mcs_set[16]; +}; + +/** + * struct ieee80211_supported_band - frequency band definition + * + * This structure describes a frequency band a wiphy + * is able to operate in. + * + * @channels: Array of channels the hardware can operate in + * in this band. + * @band: the band this structure represents + * @n_channels: Number of channels in @channels + * @bitrates: Array of bitrates the hardware can operate with + * in this band. Must be sorted to give a valid "supported + * rates" IE, i.e. CCK rates first, then OFDM. + * @n_bitrates: Number of bitrates in @bitrates + */ +struct ieee80211_supported_band { + struct ieee80211_channel *channels; + struct ieee80211_rate *bitrates; + enum ieee80211_band band; + int n_channels; + int n_bitrates; + struct ieee80211_ht_info ht_info; +}; + /** * struct wiphy - wireless hardware description * @idx: the wiphy index assigned to this item @@ -30,6 +186,8 @@ struct wiphy { * help determine whether you own this wiphy or not. */ void *privid; + struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; + /* fields below are read-only, assigned by cfg80211 */ /* the item in /sys/class/ieee80211/ points to this, @@ -136,4 +294,14 @@ extern void wiphy_unregister(struct wiphy *wiphy); */ extern void wiphy_free(struct wiphy *wiphy); +/** + * ieee80211_channel_to_frequency - convert channel number to frequency + */ +extern int ieee80211_channel_to_frequency(int chan); + +/** + * ieee80211_frequency_to_channel - convert frequency to channel number + */ +extern int ieee80211_frequency_to_channel(int freq); + #endif /* __NET_WIRELESS_H */ diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 54f46bc80cfe..9d7a19581a29 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -19,7 +19,6 @@ mac80211-y := \ ieee80211_iface.o \ ieee80211_rate.o \ michael.o \ - regdomain.o \ tkip.o \ aes_ccm.o \ cfg.o \ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 22c9619ba776..15b8cf94f510 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -498,7 +498,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, { u32 rates; int i, j; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; if (params->station_flags & STATION_FLAG_CHANGED) { sta->flags &= ~WLAN_STA_AUTHORIZED; @@ -525,15 +525,16 @@ static void sta_apply_parameters(struct ieee80211_local *local, if (params->supported_rates) { rates = 0; - mode = local->oper_hw_mode; + sband = local->hw.wiphy->bands[local->oper_channel->band]; + for (i = 0; i < params->supported_rates_len; i++) { int rate = (params->supported_rates[i] & 0x7f) * 5; - for (j = 0; j < mode->num_rates; j++) { - if (mode->rates[j].rate == rate) + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) rates |= BIT(j); } } - sta->supp_rates = rates; + sta->supp_rates[local->oper_channel->band] = rates; } } diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 60514b2c97b9..4736c64937b4 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -19,41 +19,6 @@ int mac80211_open_file_generic(struct inode *inode, struct file *file) return 0; } -static const char *ieee80211_mode_str(int mode) -{ - switch (mode) { - case MODE_IEEE80211A: - return "IEEE 802.11a"; - case MODE_IEEE80211B: - return "IEEE 802.11b"; - case MODE_IEEE80211G: - return "IEEE 802.11g"; - default: - return "UNKNOWN"; - } -} - -static ssize_t modes_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ieee80211_local *local = file->private_data; - struct ieee80211_hw_mode *mode; - char buf[150], *p = buf; - - /* FIXME: locking! */ - list_for_each_entry(mode, &local->modes_list, list) { - p += scnprintf(p, sizeof(buf)+buf-p, - "%s\n", ieee80211_mode_str(mode->mode)); - } - - return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf); -} - -static const struct file_operations modes_ops = { - .read = modes_read, - .open = mac80211_open_file_generic, -}; - #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ static ssize_t name## _read(struct file *file, char __user *userbuf, \ size_t count, loff_t *ppos) \ @@ -80,10 +45,8 @@ static const struct file_operations name## _ops = { \ local->debugfs.name = NULL; -DEBUGFS_READONLY_FILE(channel, 20, "%d", - local->hw.conf.channel); DEBUGFS_READONLY_FILE(frequency, 20, "%d", - local->hw.conf.freq); + local->hw.conf.channel->center_freq); DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d", local->hw.conf.antenna_sel_tx); DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", @@ -100,8 +63,6 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", local->long_retry_limit); DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", local->total_ps_buffered); -DEBUGFS_READONLY_FILE(mode, 20, "%s", - ieee80211_mode_str(local->hw.conf.phymode)); DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x", local->wep_iv & 0xffffff); DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", @@ -294,7 +255,6 @@ void debugfs_hw_add(struct ieee80211_local *local) local->debugfs.stations = debugfs_create_dir("stations", phyd); local->debugfs.keys = debugfs_create_dir("keys", phyd); - DEBUGFS_ADD(channel); DEBUGFS_ADD(frequency); DEBUGFS_ADD(antenna_sel_tx); DEBUGFS_ADD(antenna_sel_rx); @@ -304,9 +264,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(short_retry_limit); DEBUGFS_ADD(long_retry_limit); DEBUGFS_ADD(total_ps_buffered); - DEBUGFS_ADD(mode); DEBUGFS_ADD(wep_iv); - DEBUGFS_ADD(modes); statsd = debugfs_create_dir("statistics", phyd); local->debugfs.statistics = statsd; @@ -356,7 +314,6 @@ void debugfs_hw_add(struct ieee80211_local *local) void debugfs_hw_del(struct ieee80211_local *local) { - DEBUGFS_DEL(channel); DEBUGFS_DEL(frequency); DEBUGFS_DEL(antenna_sel_tx); DEBUGFS_DEL(antenna_sel_rx); @@ -366,9 +323,7 @@ void debugfs_hw_del(struct ieee80211_local *local) DEBUGFS_DEL(short_retry_limit); DEBUGFS_DEL(long_retry_limit); DEBUGFS_DEL(total_ps_buffered); - DEBUGFS_DEL(mode); DEBUGFS_DEL(wep_iv); - DEBUGFS_DEL(modes); DEBUGFS_STATS_DEL(transmitted_fragment_count); DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index df25abf63137..49660f4e845d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -33,22 +33,6 @@ static ssize_t sta_ ##name## _read(struct file *file, \ #define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n") #define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n") -#define STA_READ_RATE(name, field) \ -static ssize_t sta_##name##_read(struct file *file, \ - char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct sta_info *sta = file->private_data; \ - struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\ - struct ieee80211_hw_mode *mode = local->oper_hw_mode; \ - char buf[20]; \ - int res = scnprintf(buf, sizeof(buf), "%d\n", \ - (sta->field >= 0 && \ - sta->field < mode->num_rates) ? \ - mode->rates[sta->field].rate : -1); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ -} - #define STA_OPS(name) \ static const struct file_operations sta_ ##name## _ops = { \ .read = sta_##name##_read, \ @@ -77,8 +61,6 @@ STA_FILE(rx_fragments, rx_fragments, LU); STA_FILE(rx_dropped, rx_dropped, LU); STA_FILE(tx_fragments, tx_fragments, LU); STA_FILE(tx_filtered, tx_filtered_count, LU); -STA_FILE(txrate, txrate, RATE); -STA_FILE(last_txrate, last_txrate, RATE); STA_FILE(tx_retry_failed, tx_retry_failed, LU); STA_FILE(tx_retry_count, tx_retry_count, LU); STA_FILE(last_rssi, last_rssi, D); diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 3961d4c4320c..de894b61a23c 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -876,37 +876,28 @@ int ieee80211_if_config_beacon(struct net_device *dev) int ieee80211_hw_config(struct ieee80211_local *local) { - struct ieee80211_hw_mode *mode; struct ieee80211_channel *chan; int ret = 0; - if (local->sta_sw_scanning) { + if (local->sta_sw_scanning) chan = local->scan_channel; - mode = local->scan_hw_mode; - } else { + else chan = local->oper_channel; - mode = local->oper_hw_mode; - } - local->hw.conf.channel = chan->chan; - local->hw.conf.channel_val = chan->val; - if (!local->hw.conf.power_level) { - local->hw.conf.power_level = chan->power_level; - } else { - local->hw.conf.power_level = min(chan->power_level, - local->hw.conf.power_level); - } - local->hw.conf.freq = chan->freq; - local->hw.conf.phymode = mode->mode; - local->hw.conf.antenna_max = chan->antenna_max; - local->hw.conf.chan = chan; - local->hw.conf.mode = mode; + local->hw.conf.channel = chan; + + if (!local->hw.conf.power_level) + local->hw.conf.power_level = chan->max_power; + else + local->hw.conf.power_level = min(chan->max_power, + local->hw.conf.power_level); + + local->hw.conf.max_antenna_gain = chan->max_antenna_gain; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d " - "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq, - local->hw.conf.phymode); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ + printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n", + wiphy_name(local->hw.wiphy), chan->center_freq); +#endif if (local->open_count) ret = local->ops->config(local_to_hw(local), &local->hw.conf); @@ -924,11 +915,13 @@ int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, struct ieee80211_ht_bss_info *req_bss_cap) { struct ieee80211_conf *conf = &local->hw.conf; - struct ieee80211_hw_mode *mode = conf->mode; + struct ieee80211_supported_band *sband; int i; + sband = local->hw.wiphy->bands[conf->channel->band]; + /* HT is not supported */ - if (!mode->ht_info.ht_supported) { + if (!sband->ht_info.ht_supported) { conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; return -EOPNOTSUPP; } @@ -938,17 +931,17 @@ int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; } else { conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; - conf->ht_conf.cap = req_ht_cap->cap & mode->ht_info.cap; + conf->ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; conf->ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); conf->ht_conf.cap |= - mode->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; + sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; conf->ht_bss_conf.primary_channel = req_bss_cap->primary_channel; conf->ht_bss_conf.bss_cap = req_bss_cap->bss_cap; conf->ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; for (i = 0; i < SUPP_MCS_SET_LEN; i++) conf->ht_conf.supp_mcs_set[i] = - mode->ht_info.supp_mcs_set[i] & + sband->ht_info.supp_mcs_set[i] & req_ht_cap->supp_mcs_set[i]; /* In STA mode, this gives us indication @@ -1418,10 +1411,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->long_retry_limit = 4; local->hw.conf.radio_enabled = 1; - local->enabled_modes = ~0; - - INIT_LIST_HEAD(&local->modes_list); - INIT_LIST_HEAD(&local->interfaces); INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); @@ -1466,6 +1455,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) struct ieee80211_local *local = hw_to_local(hw); const char *name; int result; + enum ieee80211_band band; + + /* + * generic code guarantees at least one band, + * set this very early because much code assumes + * that hw.conf.channel is assigned + */ + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[band]; + if (sband) { + /* init channel we're on */ + local->hw.conf.channel = + local->oper_channel = + local->scan_channel = &sband->channels[0]; + break; + } + } result = wiphy_register(local->hw.wiphy); if (result < 0) @@ -1567,44 +1575,10 @@ fail_workqueue: } EXPORT_SYMBOL(ieee80211_register_hw); -int ieee80211_register_hwmode(struct ieee80211_hw *hw, - struct ieee80211_hw_mode *mode) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_rate *rate; - int i; - - INIT_LIST_HEAD(&mode->list); - list_add_tail(&mode->list, &local->modes_list); - - local->hw_modes |= (1 << mode->mode); - for (i = 0; i < mode->num_rates; i++) { - rate = &(mode->rates[i]); - rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate; - } - ieee80211_prepare_rates(local, mode); - - if (!local->oper_hw_mode) { - /* Default to this mode */ - local->hw.conf.phymode = mode->mode; - local->oper_hw_mode = local->scan_hw_mode = mode; - local->oper_channel = local->scan_channel = &mode->channels[0]; - local->hw.conf.mode = local->oper_hw_mode; - local->hw.conf.chan = local->oper_channel; - } - - if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED)) - ieee80211_set_default_regdomain(mode); - - return 0; -} -EXPORT_SYMBOL(ieee80211_register_hwmode); - void ieee80211_unregister_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata, *tmp; - int i; tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); @@ -1645,11 +1619,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) rate_control_deinitialize(local); debugfs_hw_del(local); - for (i = 0; i < NUM_IEEE80211_MODES; i++) { - kfree(local->supp_rates[i]); - kfree(local->basic_rates[i]); - } - if (skb_queue_len(&local->skb_queue) || skb_queue_len(&local->skb_queue_unreliable)) printk(KERN_WARNING "%s: skb_queue not empty\n", @@ -1696,7 +1665,6 @@ static int __init ieee80211_init(void) } ieee80211_debugfs_netdev_init(); - ieee80211_regdomain_init(); return 0; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9d09ba8cc02b..54eea5f24474 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -79,8 +79,7 @@ struct ieee80211_sta_bss { u8 ssid[IEEE80211_MAX_SSID_LEN]; size_t ssid_len; u16 capability; /* host byte order */ - int hw_mode; - int channel; + enum ieee80211_band band; int freq; int rssi, signal, noise; u8 *wpa_ie; @@ -136,13 +135,12 @@ struct ieee80211_txrx_data { union { struct { struct ieee80211_tx_control *control; - struct ieee80211_hw_mode *mode; + struct ieee80211_channel *channel; struct ieee80211_rate *rate; /* use this rate (if set) for last fragment; rate can * be set to lower rate for the first fragments, e.g., * when using CTS protection with IEEE 802.11g. */ struct ieee80211_rate *last_frag_rate; - int last_frag_hwrate; /* Extra fragments (in addition to the first fragment * in skb) */ @@ -151,6 +149,7 @@ struct ieee80211_txrx_data { } tx; struct { struct ieee80211_rx_status *status; + struct ieee80211_rate *rate; int sent_ps_buffered; int queue; int load; @@ -179,8 +178,6 @@ struct ieee80211_tx_stored_packet { struct sk_buff *skb; int num_extra_frag; struct sk_buff **extra_frag; - int last_frag_rateidx; - int last_frag_hwrate; struct ieee80211_rate *last_frag_rate; unsigned int last_frag_rate_ctrl_probe; }; @@ -283,7 +280,7 @@ struct ieee80211_if_sta { unsigned long ibss_join_req; struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ - u32 supp_rates_bits; + u32 supp_rates_bits[IEEE80211_NUM_BANDS]; int wmm_last_param_set; }; @@ -293,6 +290,7 @@ struct ieee80211_if_sta { #define IEEE80211_SDATA_ALLMULTI BIT(0) #define IEEE80211_SDATA_PROMISC BIT(1) #define IEEE80211_SDATA_USERSPACE_MLME BIT(2) +#define IEEE80211_SDATA_OPERATING_GMODE BIT(3) struct ieee80211_sub_if_data { struct list_head list; @@ -313,6 +311,11 @@ struct ieee80211_sub_if_data { */ int ieee802_1x_pac; + /* + * basic rates of this AP or the AP we're associated to + */ + u64 basic_rates; + u16 sequence; /* Fragment table for host-based reassembly */ @@ -420,9 +423,6 @@ struct ieee80211_local { const struct ieee80211_ops *ops; - /* List of registered struct ieee80211_hw_mode */ - struct list_head modes_list; - struct net_device *mdev; /* wmaster# - "master" 802.11 device */ int open_count; int monitors; @@ -462,11 +462,6 @@ struct ieee80211_local { struct rate_control_ref *rate_ctrl; - /* Supported and basic rate filters for different modes. These are - * pointers to -1 terminated lists and rates in 100 kbps units. */ - int *supp_rates[NUM_IEEE80211_MODES]; - int *basic_rates[NUM_IEEE80211_MODES]; - int rts_threshold; int fragmentation_threshold; int short_retry_limit; /* dot11ShortRetryLimit */ @@ -488,12 +483,13 @@ struct ieee80211_local { bool sta_sw_scanning; bool sta_hw_scanning; int scan_channel_idx; + enum ieee80211_band scan_band; + enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; unsigned long last_scan_completed; struct delayed_work scan_work; struct net_device *scan_dev; struct ieee80211_channel *oper_channel, *scan_channel; - struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; struct list_head sta_bss_list; @@ -562,14 +558,8 @@ struct ieee80211_local { int wifi_wme_noack_test; unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ - unsigned int enabled_modes; /* bitfield of allowed modes; - * (1 << MODE_*) */ - unsigned int hw_modes; /* bitfield of supported hardware modes; - * (1 << MODE_*) */ - #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { - struct dentry *channel; struct dentry *frequency; struct dentry *antenna_sel_tx; struct dentry *antenna_sel_rx; @@ -579,9 +569,7 @@ struct ieee80211_local { struct dentry *short_retry_limit; struct dentry *long_retry_limit; struct dentry *total_ps_buffered; - struct dentry *mode; struct dentry *wep_iv; - struct dentry *modes; struct dentry *statistics; struct local_debugfsdentries_statsdentries { struct dentry *transmitted_fragment_count; @@ -692,23 +680,6 @@ static inline void bss_tim_clear(struct ieee80211_local *local, read_unlock_bh(&local->sta_lock); } -/** - * ieee80211_is_erp_rate - Check if a rate is an ERP rate - * @phymode: The PHY-mode for this rate (MODE_IEEE80211...) - * @rate: Transmission rate to check, in 100 kbps - * - * Check if a given rate is an Extended Rate PHY (ERP) rate. - */ -static inline int ieee80211_is_erp_rate(int phymode, int rate) -{ - if (phymode == MODE_IEEE80211G) { - if (rate != 10 && rate != 20 && - rate != 55 && rate != 110) - return 1; - } - return 0; -} - static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) { return compare_ether_addr(raddr, addr) == 0 || @@ -720,13 +691,9 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) int ieee80211_hw_config(struct ieee80211_local *local); int ieee80211_if_config(struct net_device *dev); int ieee80211_if_config_beacon(struct net_device *dev); -void ieee80211_prepare_rates(struct ieee80211_local *local, - struct ieee80211_hw_mode *mode); void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); void ieee80211_if_setup(struct net_device *dev); -struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local, - int phymode, int hwrate); int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, struct ieee80211_ht_info *req_ht_cap, struct ieee80211_ht_bss_info *req_bss_cap); @@ -757,7 +724,7 @@ extern const struct iw_handler_def ieee80211_iw_handler_def; /* ieee80211_ioctl.c */ int ieee80211_set_compression(struct ieee80211_local *local, struct net_device *dev, struct sta_info *sta); -int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq); +int ieee80211_set_freq(struct ieee80211_local *local, int freq); /* ieee80211_sta.c */ void ieee80211_sta_timer(unsigned long data); void ieee80211_sta_work(struct work_struct *work); @@ -810,10 +777,6 @@ int ieee80211_if_remove(struct net_device *dev, const char *name, int id); void ieee80211_if_free(struct net_device *dev); void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata); -/* regdomain.c */ -void ieee80211_regdomain_init(void); -void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode); - /* rx handling */ extern ieee80211_rx_handler ieee80211_rx_handlers[]; diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index 92f1eb2da311..27cee580f9f1 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c @@ -118,6 +118,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type) sdata->bss = NULL; sdata->vif.type = type; + sdata->basic_rates = 0; + switch (type) { case IEEE80211_IF_TYPE_WDS: /* nothing special */ diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 5024d3733834..54ad07aafe2d 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -129,22 +129,7 @@ static int ieee80211_ioctl_giwname(struct net_device *dev, struct iw_request_info *info, char *name, char *extra) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - switch (local->hw.conf.phymode) { - case MODE_IEEE80211A: - strcpy(name, "IEEE 802.11a"); - break; - case MODE_IEEE80211B: - strcpy(name, "IEEE 802.11b"); - break; - case MODE_IEEE80211G: - strcpy(name, "IEEE 802.11g"); - break; - default: - strcpy(name, "IEEE 802.11"); - break; - } + strcpy(name, "IEEE 802.11"); return 0; } @@ -156,7 +141,7 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct iw_range *range = (struct iw_range *) extra; - struct ieee80211_hw_mode *mode = NULL; + enum ieee80211_band band; int c = 0; data->length = sizeof(struct iw_range); @@ -191,24 +176,27 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - list_for_each_entry(mode, &local->modes_list, list) { - int i = 0; - if (!(local->enabled_modes & (1 << mode->mode)) || - (local->hw_modes & local->enabled_modes & - (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B)) + for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { + int i; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[band]; + + if (!sband) continue; - while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) { - struct ieee80211_channel *chan = &mode->channels[i]; + for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) { + struct ieee80211_channel *chan = &sband->channels[i]; - if (chan->flag & IEEE80211_CHAN_W_SCAN) { - range->freq[c].i = chan->chan; - range->freq[c].m = chan->freq * 100000; - range->freq[c].e = 1; + if (!(chan->flags & IEEE80211_CHAN_DISABLED)) { + range->freq[c].i = + ieee80211_frequency_to_channel( + chan->center_freq); + range->freq[c].m = chan->center_freq; + range->freq[c].e = 6; c++; } - i++; } } range->num_channels = c; @@ -294,22 +282,29 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, return 0; } -int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq) +int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz) { - struct ieee80211_hw_mode *mode; - int c, set = 0; + int set = 0; int ret = -EINVAL; + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { + sband = local->hw.wiphy->bands[band]; - list_for_each_entry(mode, &local->modes_list, list) { - if (!(local->enabled_modes & (1 << mode->mode))) + if (!sband) continue; - for (c = 0; c < mode->num_channels; c++) { - struct ieee80211_channel *chan = &mode->channels[c]; - if (chan->flag & IEEE80211_CHAN_W_SCAN && - ((chan->chan == channel) || (chan->freq == freq))) { - local->oper_channel = chan; - local->oper_hw_mode = mode; + + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *chan = &sband->channels[i]; + + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + + if (chan->center_freq == freqMHz) { set = 1; + local->oper_channel = chan; break; } } @@ -347,13 +342,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; } else - return ieee80211_set_channel(local, freq->m, -1); + return ieee80211_set_freq(local, + ieee80211_channel_to_frequency(freq->m)); } else { int i, div = 1000000; for (i = 0; i < freq->e; i++) div /= 10; if (div > 0) - return ieee80211_set_channel(local, -1, freq->m / div); + return ieee80211_set_freq(local, freq->m / div); else return -EINVAL; } @@ -366,10 +362,7 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level - * driver for the current channel with firmware-based management */ - - freq->m = local->hw.conf.freq; + freq->m = local->hw.conf.channel->center_freq; freq->e = 6; return 0; @@ -566,15 +559,17 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, struct iw_param *rate, char *extra) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw_mode *mode; - int i; + int i, err = -EINVAL; u32 target_rate = rate->value / 100000; struct ieee80211_sub_if_data *sdata; + struct ieee80211_supported_band *sband; sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata->bss) return -ENODEV; - mode = local->oper_hw_mode; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates * target_rate = X, rate->fixed = 1 means only rate X * target_rate = X, rate->fixed = 0 means all rates <= X */ @@ -582,18 +577,20 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, sdata->bss->force_unicast_rateidx = -1; if (rate->value < 0) return 0; - for (i=0; i < mode->num_rates; i++) { - struct ieee80211_rate *rates = &mode->rates[i]; - int this_rate = rates->rate; + + for (i=0; i< sband->n_bitrates; i++) { + struct ieee80211_rate *brate = &sband->bitrates[i]; + int this_rate = brate->bitrate; if (target_rate == this_rate) { sdata->bss->max_ratectrl_rateidx = i; if (rate->fixed) sdata->bss->force_unicast_rateidx = i; - return 0; + err = 0; + break; } } - return -EINVAL; + return err; } static int ieee80211_ioctl_giwrate(struct net_device *dev, @@ -603,18 +600,24 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct sta_info *sta; struct ieee80211_sub_if_data *sdata; + struct ieee80211_supported_band *sband; sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) sta = sta_info_get(local, sdata->u.sta.bssid); else return -EOPNOTSUPP; if (!sta) return -ENODEV; - if (sta->txrate < local->oper_hw_mode->num_rates) - rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + if (sta->txrate_idx < sband->n_bitrates) + rate->value = sband->bitrates[sta->txrate_idx].bitrate; else rate->value = 0; + rate->value *= 100000; sta_info_put(sta); return 0; } @@ -625,7 +628,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); bool need_reconfig = 0; - u8 new_power_level; + int new_power_level; if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) return -EINVAL; @@ -635,13 +638,15 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev, if (data->txpower.fixed) { new_power_level = data->txpower.value; } else { - /* Automatic power level. Get the px power from the current - * channel. */ - struct ieee80211_channel* chan = local->oper_channel; + /* + * Automatic power level. Use maximum power for the current + * channel. Should be part of rate control. + */ + struct ieee80211_channel* chan = local->hw.conf.channel; if (!chan) return -EINVAL; - new_power_level = chan->power_level; + new_power_level = chan->max_power; } if (local->hw.conf.power_level != new_power_level) { diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c index b957e67c5fba..ebe29b716b27 100644 --- a/net/mac80211/ieee80211_rate.c +++ b/net/mac80211/ieee80211_rate.c @@ -163,7 +163,8 @@ static void rate_control_release(struct kref *kref) } void rate_control_get_rate(struct net_device *dev, - struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct ieee80211_supported_band *sband, + struct sk_buff *skb, struct rate_selection *sel) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); @@ -174,17 +175,17 @@ void rate_control_get_rate(struct net_device *dev, memset(sel, 0, sizeof(struct rate_selection)); - ref->ops->get_rate(ref->priv, dev, mode, skb, sel); + ref->ops->get_rate(ref->priv, dev, sband, skb, sel); /* Select a non-ERP backup rate. */ if (!sel->nonerp) { - for (i = 0; i < mode->num_rates - 1; i++) { - struct ieee80211_rate *rate = &mode->rates[i]; - if (sel->rate->rate < rate->rate) + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; + if (sel->rate->bitrate < rate->bitrate) break; - if (rate_supported(sta, mode, i) && - !(rate->flags & IEEE80211_RATE_ERP)) + if (rate_supported(sta, sband->band, i) && + !(rate->flags & IEEE80211_RATE_ERP_G)) sel->nonerp = rate; } } diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h index 73f19e8aa51c..5f9a2ca49a57 100644 --- a/net/mac80211/ieee80211_rate.h +++ b/net/mac80211/ieee80211_rate.h @@ -18,6 +18,7 @@ #include "ieee80211_i.h" #include "sta_info.h" +/* TODO: kdoc */ struct rate_selection { /* Selected transmission rate */ struct ieee80211_rate *rate; @@ -34,7 +35,8 @@ struct rate_control_ops { struct sk_buff *skb, struct ieee80211_tx_status *status); void (*get_rate)(void *priv, struct net_device *dev, - struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct ieee80211_supported_band *band, + struct sk_buff *skb, struct rate_selection *sel); void (*rate_init)(void *priv, void *priv_sta, struct ieee80211_local *local, struct sta_info *sta); @@ -66,7 +68,8 @@ void ieee80211_rate_control_unregister(struct rate_control_ops *ops); struct rate_control_ref *rate_control_alloc(const char *name, struct ieee80211_local *local); void rate_control_get_rate(struct net_device *dev, - struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct ieee80211_supported_band *sband, + struct sk_buff *skb, struct rate_selection *sel); struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); void rate_control_put(struct rate_control_ref *ref); @@ -127,23 +130,23 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) #endif } -static inline int -rate_supported(struct sta_info *sta, struct ieee80211_hw_mode *mode, int index) +static inline int rate_supported(struct sta_info *sta, + enum ieee80211_band band, + int index) { - return (sta == NULL || sta->supp_rates & BIT(index)) && - (mode->rates[index].flags & IEEE80211_RATE_SUPPORTED); + return (sta == NULL || sta->supp_rates[band] & BIT(index)); } static inline int -rate_lowest_index(struct ieee80211_local *local, struct ieee80211_hw_mode *mode, +rate_lowest_index(struct ieee80211_local *local, + struct ieee80211_supported_band *sband, struct sta_info *sta) { int i; - for (i = 0; i < mode->num_rates; i++) { - if (rate_supported(sta, mode, i)) + for (i = 0; i < sband->n_bitrates; i++) + if (rate_supported(sta, sband->band, i)) return i; - } /* warn when we cannot find a rate. */ WARN_ON(1); @@ -152,10 +155,11 @@ rate_lowest_index(struct ieee80211_local *local, struct ieee80211_hw_mode *mode, } static inline struct ieee80211_rate * -rate_lowest(struct ieee80211_local *local, struct ieee80211_hw_mode *mode, +rate_lowest(struct ieee80211_local *local, + struct ieee80211_supported_band *sband, struct sta_info *sta) { - return &mode->rates[rate_lowest_index(local, mode, sta)]; + return &sband->bitrates[rate_lowest_index(local, sband, sta)]; } diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index d0273ccbdbae..2628222a5085 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -74,7 +74,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, u8 *ssid, size_t ssid_len); static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); static void ieee80211_rx_bss_put(struct net_device *dev, struct ieee80211_sta_bss *bss); @@ -466,7 +466,7 @@ static void ieee80211_set_associated(struct net_device *dev, return; bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel, + local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->has_erp_value) @@ -593,7 +593,6 @@ static void ieee80211_send_assoc(struct net_device *dev, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw_mode *mode; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, *ies; @@ -601,6 +600,7 @@ static void ieee80211_send_assoc(struct net_device *dev, u16 capab; struct ieee80211_sta_bss *bss; int wmm = 0; + struct ieee80211_supported_band *sband; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ifsta->extra_ie_len + @@ -612,13 +612,19 @@ static void ieee80211_send_assoc(struct net_device *dev, } skb_reserve(skb, local->hw.extra_tx_headroom); - mode = local->oper_hw_mode; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + capab = ifsta->capab; - if (mode->mode == MODE_IEEE80211G) { - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | - WLAN_CAPABILITY_SHORT_PREAMBLE; + + if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) { + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, + + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) @@ -657,23 +663,23 @@ static void ieee80211_send_assoc(struct net_device *dev, *pos++ = ifsta->ssid_len; memcpy(pos, ifsta->ssid, ifsta->ssid_len); - len = mode->num_rates; + len = sband->n_bitrates; if (len > 8) len = 8; pos = skb_put(skb, len + 2); *pos++ = WLAN_EID_SUPP_RATES; *pos++ = len; for (i = 0; i < len; i++) { - int rate = mode->rates[i].rate; + int rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } - if (mode->num_rates > len) { - pos = skb_put(skb, mode->num_rates - len + 2); + if (sband->n_bitrates > len) { + pos = skb_put(skb, sband->n_bitrates - len + 2); *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = mode->num_rates - len; - for (i = len; i < mode->num_rates; i++) { - int rate = mode->rates[i].rate; + *pos++ = sband->n_bitrates - len; + for (i = len; i < sband->n_bitrates; i++) { + int rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } } @@ -696,17 +702,18 @@ static void ieee80211_send_assoc(struct net_device *dev, *pos++ = 0; } /* wmm support is a must to HT */ - if (wmm && mode->ht_info.ht_supported) { - __le16 tmp = cpu_to_le16(mode->ht_info.cap); + if (wmm && sband->ht_info.ht_supported) { + __le16 tmp = cpu_to_le16(sband->ht_info.cap); pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); *pos++ = WLAN_EID_HT_CAPABILITY; *pos++ = sizeof(struct ieee80211_ht_cap); memset(pos, 0, sizeof(struct ieee80211_ht_cap)); memcpy(pos, &tmp, sizeof(u16)); pos += sizeof(u16); - *pos++ = (mode->ht_info.ampdu_factor | - (mode->ht_info.ampdu_density << 2)); - memcpy(pos, mode->ht_info.supp_mcs_set, 16); + /* TODO: needs a define here for << 2 */ + *pos++ = sband->ht_info.ampdu_factor | + (sband->ht_info.ampdu_density << 2); + memcpy(pos, sband->ht_info.supp_mcs_set, 16); } kfree(ifsta->assocreq_ies); @@ -789,7 +796,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (!bss) return 0; @@ -899,7 +907,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, u8 *ssid, size_t ssid_len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, *supp_rates, *esupp_rates = NULL; @@ -933,11 +941,10 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, supp_rates = skb_put(skb, 2); supp_rates[0] = WLAN_EID_SUPP_RATES; supp_rates[1] = 0; - mode = local->oper_hw_mode; - for (i = 0; i < mode->num_rates; i++) { - struct ieee80211_rate *rate = &mode->rates[i]; - if (!(rate->flags & IEEE80211_RATE_SUPPORTED)) - continue; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; if (esupp_rates) { pos = skb_put(skb, 1); esupp_rates[1]++; @@ -950,7 +957,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, pos = skb_put(skb, 1); supp_rates[1]++; } - *pos = rate->rate / 5; + *pos = rate->bitrate / 5; } ieee80211_sta_tx(dev, skb, 0); @@ -1146,9 +1153,11 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, } /* determine default buffer size */ if (buf_size == 0) { - struct ieee80211_hw_mode *mode = conf->mode; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[conf->channel->band]; buf_size = IEEE80211_MIN_AMPDU_BUF; - buf_size = buf_size << mode->ht_info.ampdu_factor; + buf_size = buf_size << sband->ht_info.ampdu_factor; } tid_agg_rx = &sta->ampdu_mlme.tid_rx[tid]; @@ -1718,15 +1727,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct net_device *dev = sdata->dev; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; struct sta_info *sta; - u32 rates; + u64 rates, basic_rates; u16 capab_info, status_code, aid; struct ieee802_11_elems elems; struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; u8 *pos; int i, j; DECLARE_MAC_BUF(mac); + bool have_higher_than_11mbit = false; /* AssocResp and ReassocResp have identical structure, so process both * of them in this function. */ @@ -1796,10 +1806,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (ifsta->assocresp_ies) memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len); - /* set AID, ieee80211_set_associated() will tell the driver */ - bss_conf->aid = aid; - ieee80211_set_associated(dev, ifsta, 1); - /* Add STA entry for the AP */ sta = sta_info_get(local, ifsta->bssid); if (!sta) { @@ -1811,7 +1817,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, return; } bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel, + local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { sta->last_rssi = bss->rssi; @@ -1825,20 +1831,46 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP; rates = 0; - mode = local->oper_hw_mode; + basic_rates = 0; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + for (i = 0; i < elems.supp_rates_len; i++) { int rate = (elems.supp_rates[i] & 0x7f) * 5; - for (j = 0; j < mode->num_rates; j++) - if (mode->rates[j].rate == rate) + + if (rate > 110) + have_higher_than_11mbit = true; + + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) rates |= BIT(j); + if (elems.supp_rates[i] & 0x80) + basic_rates |= BIT(j); + } } + for (i = 0; i < elems.ext_supp_rates_len; i++) { int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; - for (j = 0; j < mode->num_rates; j++) - if (mode->rates[j].rate == rate) + + if (rate > 110) + have_higher_than_11mbit = true; + + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) rates |= BIT(j); + if (elems.ext_supp_rates[i] & 0x80) + basic_rates |= BIT(j); + } } - sta->supp_rates = rates; + + sta->supp_rates[local->hw.conf.channel->band] = rates; + sdata->basic_rates = basic_rates; + + /* cf. IEEE 802.11 9.2.12 */ + if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && + have_higher_than_11mbit) + sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; + else + sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && local->ops->conf_ht) { @@ -1861,6 +1893,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, elems.wmm_param_len); } + /* set AID, ieee80211_set_associated() will tell the driver */ + bss_conf->aid = aid; + ieee80211_set_associated(dev, ifsta, 1); sta_info_put(sta); @@ -1901,7 +1936,7 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev, static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, +ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); @@ -1913,7 +1948,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, atomic_inc(&bss->users); atomic_inc(&bss->users); memcpy(bss->bssid, bssid, ETH_ALEN); - bss->channel = channel; + bss->freq = freq; if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { memcpy(bss->ssid, ssid, ssid_len); bss->ssid_len = ssid_len; @@ -1929,7 +1964,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); @@ -1939,7 +1974,7 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, bss = local->sta_bss_hash[STA_HASH(bssid)]; while (bss) { if (!memcmp(bss->bssid, bssid, ETH_ALEN) && - bss->channel == channel && + bss->freq == freq && bss->ssid_len == ssid_len && (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { atomic_inc(&bss->users); @@ -2004,7 +2039,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee802_11_elems elems; size_t baselen; - int channel, clen; + int freq, clen; struct ieee80211_sta_bss *bss; struct sta_info *sta; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -2055,26 +2090,22 @@ static void ieee80211_rx_bss_info(struct net_device *dev, if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && (sta = sta_info_get(local, mgmt->sa))) { - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rates; + struct ieee80211_supported_band *sband; + struct ieee80211_rate *bitrates; size_t num_rates; - u32 supp_rates, prev_rates; + u64 supp_rates, prev_rates; int i, j; - mode = local->sta_sw_scanning ? - local->scan_hw_mode : local->oper_hw_mode; - - if (local->sta_hw_scanning) { - /* search for the correct mode matches the beacon */ - list_for_each_entry(mode, &local->modes_list, list) - if (mode->mode == rx_status->phymode) - break; + sband = local->hw.wiphy->bands[rx_status->band]; - if (mode == NULL) - mode = local->oper_hw_mode; + if (!sband) { + WARN_ON(1); + sband = local->hw.wiphy->bands[ + local->hw.conf.channel->band]; } - rates = mode->rates; - num_rates = mode->num_rates; + + bitrates = sband->bitrates; + num_rates = sband->n_bitrates; supp_rates = 0; for (i = 0; i < elems.supp_rates_len + @@ -2088,24 +2119,27 @@ static void ieee80211_rx_bss_info(struct net_device *dev, [i - elems.supp_rates_len]; own_rate = 5 * (rate & 0x7f); for (j = 0; j < num_rates; j++) - if (rates[j].rate == own_rate) + if (bitrates[j].bitrate == own_rate) supp_rates |= BIT(j); } - prev_rates = sta->supp_rates; - sta->supp_rates &= supp_rates; - if (sta->supp_rates == 0) { + prev_rates = sta->supp_rates[rx_status->band]; + sta->supp_rates[rx_status->band] &= supp_rates; + if (sta->supp_rates[rx_status->band] == 0) { /* No matching rates - this should not really happen. * Make sure that at least one rate is marked * supported to avoid issues with TX rate ctrl. */ - sta->supp_rates = sdata->u.sta.supp_rates_bits; + sta->supp_rates[rx_status->band] = + sdata->u.sta.supp_rates_bits[rx_status->band]; } - if (sta->supp_rates != prev_rates) { + if (sta->supp_rates[rx_status->band] != prev_rates) { printk(KERN_DEBUG "%s: updated supp_rates set for " - "%s based on beacon info (0x%x & 0x%x -> " - "0x%x)\n", - dev->name, print_mac(mac, sta->addr), prev_rates, - supp_rates, sta->supp_rates); + "%s based on beacon info (0x%llx & 0x%llx -> " + "0x%llx)\n", + dev->name, print_mac(mac, sta->addr), + (unsigned long long) prev_rates, + (unsigned long long) supp_rates, + (unsigned long long) sta->supp_rates[rx_status->band]); } sta_info_put(sta); } @@ -2114,14 +2148,14 @@ static void ieee80211_rx_bss_info(struct net_device *dev, return; if (elems.ds_params && elems.ds_params_len == 1) - channel = elems.ds_params[0]; + freq = ieee80211_channel_to_frequency(elems.ds_params[0]); else - channel = rx_status->channel; + freq = rx_status->freq; - bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel, + bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq, elems.ssid, elems.ssid_len); if (!bss) { - bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel, + bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq, elems.ssid, elems.ssid_len); if (!bss) return; @@ -2134,6 +2168,8 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #endif } + bss->band = rx_status->band; + if (bss->probe_resp && beacon) { /* Do not allow beacon to override data from Probe Response. */ ieee80211_rx_bss_put(dev, bss); @@ -2232,20 +2268,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->ht_ie_len = 0; } - bss->hw_mode = rx_status->phymode; - bss->freq = rx_status->freq; - if (channel != rx_status->channel && - (bss->hw_mode == MODE_IEEE80211G || - bss->hw_mode == MODE_IEEE80211B) && - channel >= 1 && channel <= 14) { - static const int freq_list[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 - }; - /* IEEE 802.11g/b mode can receive packets from neighboring - * channels, so map the channel into frequency. */ - bss->freq = freq_list[channel - 1]; - } bss->timestamp = timestamp; bss->last_update = jiffies; bss->rssi = rx_status->ssi; @@ -2817,7 +2839,7 @@ static int ieee80211_sta_config_auth(struct net_device *dev, } spin_lock_bh(&local->sta_bss_lock); - freq = local->oper_channel->freq; + freq = local->oper_channel->center_freq; list_for_each_entry(bss, &local->sta_bss_list, list) { if (!(bss->capability & WLAN_CAPABILITY_ESS)) continue; @@ -2848,7 +2870,7 @@ static int ieee80211_sta_config_auth(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); if (selected) { - ieee80211_set_channel(local, -1, selected->freq); + ieee80211_set_freq(local, selected->freq); if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) ieee80211_sta_set_ssid(dev, selected->ssid, selected->ssid_len); @@ -2881,10 +2903,12 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, struct sk_buff *skb; struct ieee80211_mgmt *mgmt; struct ieee80211_tx_control control; - struct ieee80211_hw_mode *mode; struct rate_selection ratesel; u8 *pos; struct ieee80211_sub_if_data *sdata; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; /* Remove possible STA entries from other IBSS networks. */ sta_info_flush(local, NULL); @@ -2904,12 +2928,11 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, sdata->drop_unencrypted = bss->capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - res = ieee80211_set_channel(local, -1, bss->freq); + res = ieee80211_set_freq(local, bss->freq); - if (!(local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)) { - printk(KERN_DEBUG "%s: IBSS not allowed on channel %d " - "(%d MHz)\n", dev->name, local->hw.conf.channel, - local->hw.conf.freq); + if (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS) { + printk(KERN_DEBUG "%s: IBSS not allowed on frequency " + "%d MHz\n", dev->name, local->oper_channel->center_freq); return -1; } @@ -2946,10 +2969,12 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, *pos++ = rates; memcpy(pos, bss->supp_rates, rates); - pos = skb_put(skb, 2 + 1); - *pos++ = WLAN_EID_DS_PARAMS; - *pos++ = 1; - *pos++ = bss->channel; + if (bss->band == IEEE80211_BAND_2GHZ) { + pos = skb_put(skb, 2 + 1); + *pos++ = WLAN_EID_DS_PARAMS; + *pos++ = 1; + *pos++ = ieee80211_frequency_to_channel(bss->freq); + } pos = skb_put(skb, 2 + 2); *pos++ = WLAN_EID_IBSS_PARAMS; @@ -2967,19 +2992,18 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, } memset(&control, 0, sizeof(control)); - rate_control_get_rate(dev, local->oper_hw_mode, skb, &ratesel); + rate_control_get_rate(dev, sband, skb, &ratesel); if (!ratesel.rate) { printk(KERN_DEBUG "%s: Failed to determine TX rate " "for IBSS beacon\n", dev->name); break; } control.vif = &sdata->vif; - control.tx_rate = - (sdata->bss_conf.use_short_preamble && - (ratesel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ? - ratesel.rate->val2 : ratesel.rate->val; + control.tx_rate = ratesel.rate; + if (sdata->bss_conf.use_short_preamble && + ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) + control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; control.antenna_sel_tx = local->hw.conf.antenna_sel_tx; - control.power_level = local->hw.conf.power_level; control.flags |= IEEE80211_TXCTL_NO_ACK; control.retry_limit = 1; @@ -3004,14 +3028,14 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, } rates = 0; - mode = local->oper_hw_mode; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; for (i = 0; i < bss->supp_rates_len; i++) { int bitrate = (bss->supp_rates[i] & 0x7f) * 5; - for (j = 0; j < mode->num_rates; j++) - if (mode->rates[j].rate == bitrate) + for (j = 0; j < sband->n_bitrates; j++) + if (sband->bitrates[j].bitrate == bitrate) rates |= BIT(j); } - ifsta->supp_rates_bits = rates; + ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; } while (0); if (skb) { @@ -3035,7 +3059,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN], *pos; int i; DECLARE_MAC_BUF(mac); @@ -3057,28 +3081,28 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", dev->name, print_mac(mac, bssid)); - bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel, + bss = ieee80211_rx_bss_add(dev, bssid, + local->hw.conf.channel->center_freq, sdata->u.sta.ssid, sdata->u.sta.ssid_len); if (!bss) return -ENOMEM; - mode = local->oper_hw_mode; + bss->band = local->hw.conf.channel->band; + sband = local->hw.wiphy->bands[bss->band]; if (local->hw.conf.beacon_int == 0) local->hw.conf.beacon_int = 100; bss->beacon_int = local->hw.conf.beacon_int; - bss->hw_mode = local->hw.conf.phymode; - bss->freq = local->hw.conf.freq; bss->last_update = jiffies; bss->capability = WLAN_CAPABILITY_IBSS; if (sdata->default_key) { bss->capability |= WLAN_CAPABILITY_PRIVACY; } else sdata->drop_unencrypted = 0; - bss->supp_rates_len = mode->num_rates; + bss->supp_rates_len = sband->n_bitrates; pos = bss->supp_rates; - for (i = 0; i < mode->num_rates; i++) { - int rate = mode->rates[i].rate; + for (i = 0; i < sband->n_bitrates; i++) { + int rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); } @@ -3127,7 +3151,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && - (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel, + (bss = ieee80211_rx_bss_get(dev, bssid, + local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len))) { printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" " based on configured SSID\n", @@ -3155,13 +3180,13 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, if (time_after(jiffies, ifsta->ibss_join_req + IEEE80211_IBSS_JOIN_TIMEOUT)) { if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && - local->oper_channel->flag & IEEE80211_CHAN_W_IBSS) + (!(local->oper_channel->flags & + IEEE80211_CHAN_NO_IBSS))) return ieee80211_sta_create_ibss(dev, ifsta); if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { - printk(KERN_DEBUG "%s: IBSS not allowed on the" - " configured channel %d (%d MHz)\n", - dev->name, local->hw.conf.channel, - local->hw.conf.freq); + printk(KERN_DEBUG "%s: IBSS not allowed on" + " %d MHz\n", dev->name, + local->hw.conf.channel->center_freq); } /* No IBSS found - decrease scan interval and continue @@ -3180,7 +3205,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); @@ -3194,18 +3219,23 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) int i; memset(&qparam, 0, sizeof(qparam)); - /* TODO: are these ok defaults for all hw_modes? */ + qparam.aifs = 2; - qparam.cw_min = - local->hw.conf.phymode == MODE_IEEE80211B ? 31 : 15; + + if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && + !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) + qparam.cw_min = 31; + else + qparam.cw_min = 15; + qparam.cw_max = 1023; qparam.burst_time = 0; + for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++) - { local->ops->conf_tx(local_to_hw(local), i + IEEE80211_TX_QUEUE_DATA0, &qparam); - } + /* IBSS uses different parameters for Beacon sending */ qparam.cw_min++; qparam.cw_min *= 2; @@ -3214,7 +3244,6 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) IEEE80211_TX_QUEUE_BEACON, &qparam); } - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) @@ -3373,7 +3402,7 @@ void ieee80211_sta_scan_work(struct work_struct *work) container_of(work, struct ieee80211_local, scan_work.work); struct net_device *dev = local->scan_dev; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; int skip; unsigned long next_delay = 0; @@ -3383,44 +3412,47 @@ void ieee80211_sta_scan_work(struct work_struct *work) switch (local->scan_state) { case SCAN_SET_CHANNEL: - mode = local->scan_hw_mode; - if (local->scan_hw_mode->list.next == &local->modes_list && - local->scan_channel_idx >= mode->num_channels) { + /* get current scan band */ + if (local->scan_band < IEEE80211_NUM_BANDS) + sband = local->hw.wiphy->bands[local->scan_band]; + else + sband = NULL; + + /* if we started at an unsupported one, advance */ + while (!sband && local->scan_band < IEEE80211_NUM_BANDS) { + local->scan_band++; + sband = local->hw.wiphy->bands[local->scan_band]; + local->scan_channel_idx = 0; + } + + if (!sband || + (local->scan_channel_idx >= sband->n_channels && + local->scan_band >= IEEE80211_NUM_BANDS)) { ieee80211_scan_completed(local_to_hw(local)); return; } - skip = !(local->enabled_modes & (1 << mode->mode)); - chan = &mode->channels[local->scan_channel_idx]; - if (!(chan->flag & IEEE80211_CHAN_W_SCAN) || + skip = 0; + chan = &sband->channels[local->scan_channel_idx]; + + if (chan->flags & IEEE80211_CHAN_DISABLED || (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && - !(chan->flag & IEEE80211_CHAN_W_IBSS)) || - (local->hw_modes & local->enabled_modes & - (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B)) + chan->flags & IEEE80211_CHAN_NO_IBSS)) skip = 1; if (!skip) { -#if 0 - printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n", - dev->name, chan->chan, chan->freq); -#endif - local->scan_channel = chan; if (ieee80211_hw_config(local)) { - printk(KERN_DEBUG "%s: failed to set channel " - "%d (%d MHz) for scan\n", dev->name, - chan->chan, chan->freq); + printk(KERN_DEBUG "%s: failed to set freq to " + "%d MHz for scan\n", dev->name, + chan->center_freq); skip = 1; } } local->scan_channel_idx++; - if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) { - if (local->scan_hw_mode->list.next != &local->modes_list) { - local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next, - struct ieee80211_hw_mode, - list); - local->scan_channel_idx = 0; - } + if (local->scan_channel_idx >= sband->n_channels) { + local->scan_band++; + local->scan_channel_idx = 0; } if (skip) @@ -3431,13 +3463,14 @@ void ieee80211_sta_scan_work(struct work_struct *work) local->scan_state = SCAN_SEND_PROBE; break; case SCAN_SEND_PROBE: - if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) { - ieee80211_send_probe_req(dev, NULL, local->scan_ssid, - local->scan_ssid_len); - next_delay = IEEE80211_CHANNEL_TIME; - } else - next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; + next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; local->scan_state = SCAN_SET_CHANNEL; + + if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) + break; + ieee80211_send_probe_req(dev, NULL, local->scan_ssid, + local->scan_ssid_len); + next_delay = IEEE80211_CHANNEL_TIME; break; } @@ -3512,10 +3545,8 @@ static int ieee80211_sta_start_scan(struct net_device *dev, } else local->scan_ssid_len = 0; local->scan_state = SCAN_SET_CHANNEL; - local->scan_hw_mode = list_entry(local->modes_list.next, - struct ieee80211_hw_mode, - list); local->scan_channel_idx = 0; + local->scan_band = IEEE80211_BAND_2GHZ; local->scan_dev = dev; netif_tx_lock_bh(local->mdev); @@ -3570,9 +3601,6 @@ ieee80211_sta_scan_result(struct net_device *dev, bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) return current_ev; - if (!(local->enabled_modes & (1 << bss->hw_mode))) - return current_ev; - memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; @@ -3600,12 +3628,15 @@ ieee80211_sta_scan_result(struct net_device *dev, memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = bss->channel; - iwe.u.freq.e = 0; + iwe.u.freq.m = bss->freq; + iwe.u.freq.e = 6; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); - iwe.u.freq.m = bss->freq * 100000; - iwe.u.freq.e = 1; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); + iwe.u.freq.e = 0; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); @@ -3748,7 +3779,8 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev, if (!sta) return NULL; - sta->supp_rates = sdata->u.sta.supp_rates_bits; + sta->supp_rates[local->hw.conf.channel->band] = + sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band]; rate_control_rate_init(sta, local); diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index c339571632b2..c5a607ca8440 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -102,23 +102,23 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, struct rc_pid_rateinfo *rinfo) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; int newidx; int maxrate; int back = (adj > 0) ? 1 : -1; sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); - mode = local->oper_hw_mode; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1; - newidx = rate_control_pid_shift_adjust(rinfo, adj, sta->txrate, - mode->num_rates); + newidx = rate_control_pid_shift_adjust(rinfo, adj, sta->txrate_idx, + sband->n_bitrates); - while (newidx != sta->txrate) { - if (rate_supported(sta, mode, newidx) && + while (newidx != sta->txrate_idx) { + if (rate_supported(sta, sband->band, newidx) && (maxrate < 0 || newidx <= maxrate)) { - sta->txrate = newidx; + sta->txrate_idx = newidx; break; } @@ -128,7 +128,7 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, #ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_rate_change( &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, - newidx, mode->rates[newidx].rate); + newidx, sband->bitrates[newidx].bitrate); #endif } @@ -155,7 +155,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, { struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; struct rc_pid_rateinfo *rinfo = pinfo->rinfo; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; u32 pf; s32 err_avg; u32 err_prop; @@ -164,7 +164,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, int adj, i, j, tmp; unsigned long period; - mode = local->oper_hw_mode; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; spinfo = sta->rate_ctrl_priv; /* In case nothing happened during the previous control interval, turn @@ -190,18 +190,18 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, spinfo->tx_num_failed = 0; /* If we just switched rate, update the rate behaviour info. */ - if (pinfo->oldrate != sta->txrate) { + if (pinfo->oldrate != sta->txrate_idx) { i = rinfo[pinfo->oldrate].rev_index; - j = rinfo[sta->txrate].rev_index; + j = rinfo[sta->txrate_idx].rev_index; tmp = (pf - spinfo->last_pf); tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); rinfo[j].diff = rinfo[i].diff + tmp; - pinfo->oldrate = sta->txrate; + pinfo->oldrate = sta->txrate_idx; } - rate_control_pid_normalize(pinfo, mode->num_rates); + rate_control_pid_normalize(pinfo, sband->n_bitrates); /* Compute the proportional, integral and derivative errors. */ err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf; @@ -242,8 +242,10 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, struct sta_info *sta; struct rc_pid_sta_info *spinfo; unsigned long period; + struct ieee80211_supported_band *sband; sta = sta_info_get(local, hdr->addr1); + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; if (!sta) return; @@ -251,13 +253,13 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, /* Don't update the state if we're not controlling the rate. */ sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { - sta->txrate = sdata->bss->max_ratectrl_rateidx; + sta->txrate_idx = sdata->bss->max_ratectrl_rateidx; return; } /* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ - if (status->control.rate != &local->oper_hw_mode->rates[sta->txrate]) + if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx]) goto ignore; spinfo = sta->rate_ctrl_priv; @@ -304,7 +306,7 @@ ignore: } static void rate_control_pid_get_rate(void *priv, struct net_device *dev, - struct ieee80211_hw_mode *mode, + struct ieee80211_supported_band *sband, struct sk_buff *skb, struct rate_selection *sel) { @@ -322,7 +324,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || !sta) { - sel->rate = rate_lowest(local, mode, sta); + sel->rate = rate_lowest(local, sband, sta); if (sta) sta_info_put(sta); return; @@ -331,23 +333,23 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, /* If a forced rate is in effect, select it. */ sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) - sta->txrate = sdata->bss->force_unicast_rateidx; + sta->txrate_idx = sdata->bss->force_unicast_rateidx; - rateidx = sta->txrate; + rateidx = sta->txrate_idx; - if (rateidx >= mode->num_rates) - rateidx = mode->num_rates - 1; + if (rateidx >= sband->n_bitrates) + rateidx = sband->n_bitrates - 1; - sta->last_txrate = rateidx; + sta->last_txrate_idx = rateidx; sta_info_put(sta); - sel->rate = &mode->rates[rateidx]; + sel->rate = &sband->bitrates[rateidx]; #ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_tx_rate( &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, - rateidx, mode->rates[rateidx].rate); + rateidx, sband->bitrates[rateidx].bitrate); #endif } @@ -359,28 +361,32 @@ static void rate_control_pid_rate_init(void *priv, void *priv_sta, * as we need to have IEEE 802.1X auth succeed immediately after assoc.. * Until that method is implemented, we will use the lowest supported * rate as a workaround. */ - sta->txrate = rate_lowest_index(local, local->oper_hw_mode, sta); + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sta->txrate_idx = rate_lowest_index(local, sband, sta); } static void *rate_control_pid_alloc(struct ieee80211_local *local) { struct rc_pid_info *pinfo; struct rc_pid_rateinfo *rinfo; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; int i, j, tmp; bool s; #ifdef CONFIG_MAC80211_DEBUGFS struct rc_pid_debugfs_entries *de; #endif + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); if (!pinfo) return NULL; - /* We can safely assume that oper_hw_mode won't change unless we get + /* We can safely assume that sband won't change unless we get * reinitialized. */ - mode = local->oper_hw_mode; - rinfo = kmalloc(sizeof(*rinfo) * mode->num_rates, GFP_ATOMIC); + rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC); if (!rinfo) { kfree(pinfo); return NULL; @@ -389,7 +395,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) /* Sort the rates. This is optimized for the most common case (i.e. * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed * mapping too. */ - for (i = 0; i < mode->num_rates; i++) { + for (i = 0; i < sband->n_bitrates; i++) { rinfo[i].index = i; rinfo[i].rev_index = i; if (pinfo->fast_start) @@ -397,11 +403,11 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) else rinfo[i].diff = i * pinfo->norm_offset; } - for (i = 1; i < mode->num_rates; i++) { + for (i = 1; i < sband->n_bitrates; i++) { s = 0; - for (j = 0; j < mode->num_rates - i; j++) - if (unlikely(mode->rates[rinfo[j].index].rate > - mode->rates[rinfo[j + 1].index].rate)) { + for (j = 0; j < sband->n_bitrates - i; j++) + if (unlikely(sband->bitrates[rinfo[j].index].bitrate > + sband->bitrates[rinfo[j + 1].index].bitrate)) { tmp = rinfo[j].index; rinfo[j].index = rinfo[j + 1].index; rinfo[j + 1].index = tmp; diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c index 9a78b116acff..c4678905a142 100644 --- a/net/mac80211/rc80211_simple.c +++ b/net/mac80211/rc80211_simple.c @@ -35,8 +35,8 @@ static void rate_control_rate_inc(struct ieee80211_local *local, struct sta_info *sta) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_hw_mode *mode; - int i = sta->txrate; + struct ieee80211_supported_band *sband; + int i = sta->txrate_idx; int maxrate; sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); @@ -45,18 +45,17 @@ static void rate_control_rate_inc(struct ieee80211_local *local, return; } - mode = local->oper_hw_mode; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1; - if (i > mode->num_rates) - i = mode->num_rates - 2; + if (i > sband->n_bitrates) + i = sband->n_bitrates - 2; - while (i + 1 < mode->num_rates) { + while (i + 1 < sband->n_bitrates) { i++; - if (sta->supp_rates & BIT(i) && - mode->rates[i].flags & IEEE80211_RATE_SUPPORTED && + if (rate_supported(sta, sband->band, i) && (maxrate < 0 || i <= maxrate)) { - sta->txrate = i; + sta->txrate_idx = i; break; } } @@ -67,8 +66,8 @@ static void rate_control_rate_dec(struct ieee80211_local *local, struct sta_info *sta) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_hw_mode *mode; - int i = sta->txrate; + struct ieee80211_supported_band *sband; + int i = sta->txrate_idx; sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { @@ -76,15 +75,14 @@ static void rate_control_rate_dec(struct ieee80211_local *local, return; } - mode = local->oper_hw_mode; - if (i > mode->num_rates) - i = mode->num_rates; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + if (i > sband->n_bitrates) + i = sband->n_bitrates; while (i > 0) { i--; - if (sta->supp_rates & BIT(i) && - mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) { - sta->txrate = i; + if (rate_supported(sta, sband->band, i)) { + sta->txrate_idx = i; break; } } @@ -168,7 +166,7 @@ static void rate_control_simple_tx_status(void *priv, struct net_device *dev, } else if (per_failed < RATE_CONTROL_NUM_UP) { rate_control_rate_inc(local, sta); } - srctrl->tx_avg_rate_sum += status->control.rate->rate; + srctrl->tx_avg_rate_sum += status->control.tx_rate->bitrate; srctrl->tx_avg_rate_num++; srctrl->tx_num_failures = 0; srctrl->tx_num_xmit = 0; @@ -201,7 +199,7 @@ static void rate_control_simple_tx_status(void *priv, struct net_device *dev, static void rate_control_simple_get_rate(void *priv, struct net_device *dev, - struct ieee80211_hw_mode *mode, + struct ieee80211_supported_band *sband, struct sk_buff *skb, struct rate_selection *sel) { @@ -219,7 +217,7 @@ rate_control_simple_get_rate(void *priv, struct net_device *dev, fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || !sta) { - sel->rate = rate_lowest(local, mode, sta); + sel->rate = rate_lowest(local, sband, sta); if (sta) sta_info_put(sta); return; @@ -228,18 +226,18 @@ rate_control_simple_get_rate(void *priv, struct net_device *dev, /* If a forced rate is in effect, select it. */ sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) - sta->txrate = sdata->bss->force_unicast_rateidx; + sta->txrate_idx = sdata->bss->force_unicast_rateidx; - rateidx = sta->txrate; + rateidx = sta->txrate_idx; - if (rateidx >= mode->num_rates) - rateidx = mode->num_rates - 1; + if (rateidx >= sband->n_bitrates) + rateidx = sband->n_bitrates - 1; - sta->last_txrate = rateidx; + sta->last_txrate_idx = rateidx; sta_info_put(sta); - sel->rate = &mode->rates[rateidx]; + sel->rate = &sband->bitrates[rateidx]; } @@ -247,21 +245,15 @@ static void rate_control_simple_rate_init(void *priv, void *priv_sta, struct ieee80211_local *local, struct sta_info *sta) { - struct ieee80211_hw_mode *mode; - int i; - sta->txrate = 0; - mode = local->oper_hw_mode; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + /* TODO: This routine should consider using RSSI from previous packets * as we need to have IEEE 802.1X auth succeed immediately after assoc.. * Until that method is implemented, we will use the lowest supported rate * as a workaround, */ - for (i = 0; i < mode->num_rates; i++) { - if ((sta->supp_rates & BIT(i)) && - (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) { - sta->txrate = i; - break; - } - } + sta->txrate_idx = rate_lowest_index(local, sband, sta); } diff --git a/net/mac80211/regdomain.c b/net/mac80211/regdomain.c deleted file mode 100644 index f42678fa62d1..000000000000 --- a/net/mac80211/regdomain.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * This regulatory domain control implementation is known to be incomplete - * and confusing. mac80211 regulatory domain control will be significantly - * reworked in the not-too-distant future. - * - * For now, drivers wishing to control which channels are and aren't available - * are advised as follows: - * - set the IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag - * - continue to include *ALL* possible channels in the modes registered - * through ieee80211_register_hwmode() - * - for each allowable ieee80211_channel structure registered in the above - * call, set the flag member to some meaningful value such as - * IEEE80211_CHAN_W_SCAN | IEEE80211_CHAN_W_ACTIVE_SCAN | - * IEEE80211_CHAN_W_IBSS. - * - leave flag as 0 for non-allowable channels - * - * The usual implementation is for a driver to read a device EEPROM to - * determine which regulatory domain it should be operating under, then - * looking up the allowable channels in a driver-local table, then performing - * the above. - */ - -#include -#include -#include -#include "ieee80211_i.h" - -static int ieee80211_regdom = 0x10; /* FCC */ -module_param(ieee80211_regdom, int, 0444); -MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK"); - -/* - * If firmware is upgraded by the vendor, additional channels can be used based - * on the new Japanese regulatory rules. This is indicated by setting - * ieee80211_japan_5ghz module parameter to one when loading the 80211 kernel - * module. - */ -static int ieee80211_japan_5ghz /* = 0 */; -module_param(ieee80211_japan_5ghz, int, 0444); -MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz"); - - -struct ieee80211_channel_range { - short start_freq; - short end_freq; - unsigned char power_level; - unsigned char antenna_max; -}; - -static const struct ieee80211_channel_range ieee80211_fcc_channels[] = { - { 2412, 2462, 27, 6 } /* IEEE 802.11b/g, channels 1..11 */, - { 5180, 5240, 17, 6 } /* IEEE 802.11a, channels 36..48 */, - { 5260, 5320, 23, 6 } /* IEEE 802.11a, channels 52..64 */, - { 5745, 5825, 30, 6 } /* IEEE 802.11a, channels 149..165, outdoor */, - { 0 } -}; - -static const struct ieee80211_channel_range ieee80211_mkk_channels[] = { - { 2412, 2472, 20, 6 } /* IEEE 802.11b/g, channels 1..13 */, - { 5170, 5240, 20, 6 } /* IEEE 802.11a, channels 34..48 */, - { 5260, 5320, 20, 6 } /* IEEE 802.11a, channels 52..64 */, - { 0 } -}; - - -static const struct ieee80211_channel_range *channel_range = - ieee80211_fcc_channels; - - -static void ieee80211_unmask_channel(int mode, struct ieee80211_channel *chan) -{ - int i; - - chan->flag = 0; - - for (i = 0; channel_range[i].start_freq; i++) { - const struct ieee80211_channel_range *r = &channel_range[i]; - if (r->start_freq <= chan->freq && r->end_freq >= chan->freq) { - if (ieee80211_regdom == 64 && !ieee80211_japan_5ghz && - chan->freq >= 5260 && chan->freq <= 5320) { - /* - * Skip new channels in Japan since the - * firmware was not marked having been upgraded - * by the vendor. - */ - continue; - } - - if (ieee80211_regdom == 0x10 && - (chan->freq == 5190 || chan->freq == 5210 || - chan->freq == 5230)) { - /* Skip MKK channels when in FCC domain. */ - continue; - } - - chan->flag |= IEEE80211_CHAN_W_SCAN | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_IBSS; - chan->power_level = r->power_level; - chan->antenna_max = r->antenna_max; - - if (ieee80211_regdom == 64 && - (chan->freq == 5170 || chan->freq == 5190 || - chan->freq == 5210 || chan->freq == 5230)) { - /* - * New regulatory rules in Japan have backwards - * compatibility with old channels in 5.15-5.25 - * GHz band, but the station is not allowed to - * use active scan on these old channels. - */ - chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN; - } - - if (ieee80211_regdom == 64 && - (chan->freq == 5260 || chan->freq == 5280 || - chan->freq == 5300 || chan->freq == 5320)) { - /* - * IBSS is not allowed on 5.25-5.35 GHz band - * due to radar detection requirements. - */ - chan->flag &= ~IEEE80211_CHAN_W_IBSS; - } - - break; - } - } -} - - -void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode) -{ - int c; - for (c = 0; c < mode->num_channels; c++) - ieee80211_unmask_channel(mode->mode, &mode->channels[c]); -} - - -void ieee80211_regdomain_init(void) -{ - if (ieee80211_regdom == 0x40) - channel_range = ieee80211_mkk_channels; -} - diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3aae8e9e4e0a..c9ff98a93211 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -82,10 +82,10 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status, */ static struct sk_buff * ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, - struct ieee80211_rx_status *status) + struct ieee80211_rx_status *status, + struct ieee80211_rate *rate) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_rate *rate; int needed_headroom = 0; struct ieee80211_radiotap_header *rthdr; __le64 *rttsft = NULL; @@ -194,14 +194,11 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, rtfixed->rx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); - rate = ieee80211_get_rate(local, status->phymode, - status->rate); - if (rate) - rtfixed->rate = rate->rate / 5; + rtfixed->rate = rate->bitrate / 5; rtfixed->chan_freq = cpu_to_le16(status->freq); - if (status->phymode == MODE_IEEE80211A) + if (status->band == IEEE80211_BAND_5GHZ) rtfixed->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ); @@ -320,34 +317,21 @@ static void ieee80211_verify_ip_alignment(struct ieee80211_txrx_data *rx) static u32 ieee80211_rx_load_stats(struct ieee80211_local *local, - struct sk_buff *skb, - struct ieee80211_rx_status *status) + struct sk_buff *skb, + struct ieee80211_rx_status *status, + struct ieee80211_rate *rate) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; u32 load = 0, hdrtime; - struct ieee80211_rate *rate; - struct ieee80211_hw_mode *mode = local->hw.conf.mode; - int i; /* Estimate total channel use caused by this frame */ - if (unlikely(mode->num_rates < 0)) - return TXRX_CONTINUE; - - rate = &mode->rates[0]; - for (i = 0; i < mode->num_rates; i++) { - if (mode->rates[i].val == status->rate) { - rate = &mode->rates[i]; - break; - } - } - /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values, * 1 usec = 1/8 * (1080 / 10) = 13.5 */ - if (mode->mode == MODE_IEEE80211A || - (mode->mode == MODE_IEEE80211G && - rate->flags & IEEE80211_RATE_ERP)) + if (status->band == IEEE80211_BAND_5GHZ || + (status->band == IEEE80211_BAND_5GHZ && + rate->flags & IEEE80211_RATE_ERP_G)) hdrtime = CHAN_UTIL_HDR_SHORT; else hdrtime = CHAN_UTIL_HDR_LONG; @@ -356,7 +340,8 @@ static u32 ieee80211_rx_load_stats(struct ieee80211_local *local, if (!is_multicast_ether_addr(hdr->addr1)) load += hdrtime; - load += skb->len * rate->rate_inv; + /* TODO: optimise again */ + load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate; /* Divide channel_use by 8 to avoid wrapping around the counter */ load >>= CHAN_UTIL_SHIFT; @@ -1685,7 +1670,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_rx_status *status, - u32 load) + u32 load, + struct ieee80211_rate *rate) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; @@ -1705,6 +1691,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, rx.u.rx.status = status; rx.u.rx.load = load; + rx.u.rx.rate = rate; rx.fc = le16_to_cpu(hdr->frame_control); type = rx.fc & IEEE80211_FCTL_FTYPE; @@ -1837,6 +1824,8 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, u16 head_seq_num, buf_size; int index; u32 pkt_load; + struct ieee80211_supported_band *sband; + struct ieee80211_rate *rate; buf_size = tid_agg_rx->buf_size; head_seq_num = tid_agg_rx->head_seq_num; @@ -1867,12 +1856,14 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); + sband = local->hw.wiphy->bands[status.band]; + rate = &sband->bitrates[status.rate_idx]; pkt_load = ieee80211_rx_load_stats(local, tid_agg_rx->reorder_buf[index], - &status); + &status, rate); __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], - &status, pkt_load); + &status, pkt_load, rate); tid_agg_rx->stored_mpdu_num--; tid_agg_rx->reorder_buf[index] = NULL; } @@ -1912,11 +1903,13 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, /* release the reordered frame back to stack */ memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); + sband = local->hw.wiphy->bands[status.band]; + rate = &sband->bitrates[status.rate_idx]; pkt_load = ieee80211_rx_load_stats(local, tid_agg_rx->reorder_buf[index], - &status); + &status, rate); __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], - &status, pkt_load); + &status, pkt_load, rate); tid_agg_rx->stored_mpdu_num--; tid_agg_rx->reorder_buf[index] = NULL; tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); @@ -1997,6 +1990,25 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, { struct ieee80211_local *local = hw_to_local(hw); u32 pkt_load; + struct ieee80211_rate *rate = NULL; + struct ieee80211_supported_band *sband; + + if (status->band < 0 || + status->band > IEEE80211_NUM_BANDS) { + WARN_ON(1); + return; + } + + sband = local->hw.wiphy->bands[status->band]; + + if (!sband || + status->rate_idx < 0 || + status->rate_idx >= sband->n_bitrates) { + WARN_ON(1); + return; + } + + rate = &sband->bitrates[status->rate_idx]; /* * key references and virtual interfaces are protected using RCU @@ -2011,17 +2023,17 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, * if it was previously present. * Also, frames with less than 16 bytes are dropped. */ - skb = ieee80211_rx_monitor(local, skb, status); + skb = ieee80211_rx_monitor(local, skb, status, rate); if (!skb) { rcu_read_unlock(); return; } - pkt_load = ieee80211_rx_load_stats(local, skb, status); + pkt_load = ieee80211_rx_load_stats(local, skb, status, rate); local->channel_use_raw += pkt_load; if (!ieee80211_rx_reorder_ampdu(local, skb)) - __ieee80211_rx_handle_packet(hw, skb, status, pkt_load); + __ieee80211_rx_handle_packet(hw, skb, status, pkt_load, rate); rcu_read_unlock(); } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ddc1f47194dd..746bbdea6b4c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -74,30 +74,6 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) } EXPORT_SYMBOL(sta_info_get); -int sta_info_min_txrate_get(struct ieee80211_local *local) -{ - struct sta_info *sta; - struct ieee80211_hw_mode *mode; - int min_txrate = 9999999; - int i; - - read_lock_bh(&local->sta_lock); - mode = local->oper_hw_mode; - for (i = 0; i < STA_HASH_SIZE; i++) { - sta = local->sta_hash[i]; - while (sta) { - if (sta->txrate < min_txrate) - min_txrate = sta->txrate; - sta = sta->hnext; - } - } - read_unlock_bh(&local->sta_lock); - if (min_txrate == 9999999) - min_txrate = 0; - - return mode->rates[min_txrate].rate; -} - static void sta_info_release(struct kref *kref) { diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 75573dc79d7a..3573743dfa59 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -133,10 +133,11 @@ struct sta_info { unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */ unsigned long last_rx; - u32 supp_rates; /* bitmap of supported rates in local->curr_rates */ - int txrate; /* index in local->curr_rates */ - int last_txrate; /* last rate used to send a frame to this STA */ - int last_nonerp_idx; + /* bitmap of supported rates per band */ + u64 supp_rates[IEEE80211_NUM_BANDS]; + int txrate_idx; + /* last rates used to send a frame to this STA */ + int last_txrate_idx, last_nonerp_txrate_idx; struct net_device *dev; /* which net device is this station associated * to */ @@ -222,7 +223,6 @@ static inline void __sta_info_get(struct sta_info *sta) } struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr); -int sta_info_min_txrate_get(struct ieee80211_local *local); void sta_info_put(struct sta_info *sta); struct sta_info * sta_info_add(struct ieee80211_local *local, struct net_device *dev, u8 *addr, gfp_t gfp); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 38e1b2bd8245..9e5359991985 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -92,9 +92,13 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr, int rate, mrate, erp, dur, i; struct ieee80211_rate *txrate = tx->u.tx.rate; struct ieee80211_local *local = tx->local; - struct ieee80211_hw_mode *mode = tx->u.tx.mode; + struct ieee80211_supported_band *sband; - erp = txrate->flags & IEEE80211_RATE_ERP; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + erp = 0; + if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + erp = txrate->flags & IEEE80211_RATE_ERP_G; /* * data and mgmt (except PS Poll): @@ -150,20 +154,36 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr, * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps */ rate = -1; - mrate = 10; /* use 1 Mbps if everything fails */ - for (i = 0; i < mode->num_rates; i++) { - struct ieee80211_rate *r = &mode->rates[i]; - if (r->rate > txrate->rate) - break; + /* use lowest available if everything fails */ + mrate = sband->bitrates[0].bitrate; + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *r = &sband->bitrates[i]; - if (IEEE80211_RATE_MODULATION(txrate->flags) != - IEEE80211_RATE_MODULATION(r->flags)) - continue; + if (r->bitrate > txrate->bitrate) + break; - if (r->flags & IEEE80211_RATE_BASIC) - rate = r->rate; - else if (r->flags & IEEE80211_RATE_MANDATORY) - mrate = r->rate; + if (tx->sdata->basic_rates & BIT(i)) + rate = r->bitrate; + + switch (sband->band) { + case IEEE80211_BAND_2GHZ: { + u32 flag; + if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + flag = IEEE80211_RATE_MANDATORY_G; + else + flag = IEEE80211_RATE_MANDATORY_B; + if (r->flags & flag) + mrate = r->bitrate; + break; + } + case IEEE80211_BAND_5GHZ: + if (r->flags & IEEE80211_RATE_MANDATORY_A) + mrate = r->bitrate; + break; + case IEEE80211_NUM_BANDS: + WARN_ON(1); + break; + } } if (rate == -1) { /* No matching basic rate found; use highest suitable mandatory @@ -184,7 +204,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr, dur *= 2; /* ACK + SIFS */ /* next fragment */ dur += ieee80211_frame_duration(local, next_frag_len, - txrate->rate, erp, + txrate->bitrate, erp, tx->sdata->bss_conf.use_short_preamble); } @@ -585,26 +605,28 @@ static ieee80211_txrx_result ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) { struct rate_selection rsel; + struct ieee80211_supported_band *sband; + + sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band]; if (likely(!tx->u.tx.rate)) { - rate_control_get_rate(tx->dev, tx->u.tx.mode, tx->skb, &rsel); + rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); tx->u.tx.rate = rsel.rate; - if (unlikely(rsel.probe != NULL)) { + if (unlikely(rsel.probe)) { tx->u.tx.control->flags |= IEEE80211_TXCTL_RATE_CTRL_PROBE; tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG; - tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val; + tx->u.tx.control->alt_retry_rate = tx->u.tx.rate; tx->u.tx.rate = rsel.probe; } else - tx->u.tx.control->alt_retry_rate = -1; + tx->u.tx.control->alt_retry_rate = NULL; if (!tx->u.tx.rate) return TXRX_DROP; } else - tx->u.tx.control->alt_retry_rate = -1; + tx->u.tx.control->alt_retry_rate = NULL; - if (tx->u.tx.mode->mode == MODE_IEEE80211G && - tx->sdata->bss_conf.use_cts_prot && + if (tx->sdata->bss_conf.use_cts_prot && (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && rsel.nonerp) { tx->u.tx.last_frag_rate = tx->u.tx.rate; if (rsel.probe) @@ -612,13 +634,13 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) else tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG; tx->u.tx.rate = rsel.nonerp; - tx->u.tx.control->rate = rsel.nonerp; + tx->u.tx.control->tx_rate = rsel.nonerp; tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE; } else { tx->u.tx.last_frag_rate = tx->u.tx.rate; - tx->u.tx.control->rate = tx->u.tx.rate; + tx->u.tx.control->tx_rate = tx->u.tx.rate; } - tx->u.tx.control->tx_rate = tx->u.tx.rate->val; + tx->u.tx.control->tx_rate = tx->u.tx.rate; return TXRX_CONTINUE; } @@ -630,7 +652,6 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) u16 fc = le16_to_cpu(hdr->frame_control); u16 dur; struct ieee80211_tx_control *control = tx->u.tx.control; - struct ieee80211_hw_mode *mode = tx->u.tx.mode; if (!control->retry_limit) { if (!is_multicast_ether_addr(hdr->addr1)) { @@ -657,14 +678,14 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) * frames. * TODO: The last fragment could still use multiple retry * rates. */ - control->alt_retry_rate = -1; + control->alt_retry_rate = NULL; } /* Use CTS protection for unicast frames sent using extended rates if * there are associated non-ERP stations and RTS/CTS is not configured * for the frame. */ - if (mode->mode == MODE_IEEE80211G && - (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) && + if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) && + (tx->u.tx.rate->flags & IEEE80211_RATE_ERP_G) && (tx->flags & IEEE80211_TXRXD_TXUNICAST) && tx->sdata->bss_conf.use_cts_prot && !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) @@ -674,10 +695,10 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) * short preambles at the selected rate and short preambles are * available on the network at the current point in time. */ if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && - (tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) && + (tx->u.tx.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && tx->sdata->bss_conf.use_short_preamble && (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) { - tx->u.tx.control->tx_rate = tx->u.tx.rate->val2; + tx->u.tx.control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; } /* Setup duration field for the first fragment of the frame. Duration @@ -690,19 +711,33 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) || (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) { - struct ieee80211_rate *rate; + struct ieee80211_supported_band *sband; + struct ieee80211_rate *rate, *baserate; + int idx; + + sband = tx->local->hw.wiphy->bands[ + tx->local->hw.conf.channel->band]; /* Do not use multiple retry rates when using RTS/CTS */ - control->alt_retry_rate = -1; + control->alt_retry_rate = NULL; /* Use min(data rate, max base rate) as CTS/RTS rate */ rate = tx->u.tx.rate; - while (rate > mode->rates && - !(rate->flags & IEEE80211_RATE_BASIC)) - rate--; + baserate = NULL; + + for (idx = 0; idx < sband->n_bitrates; idx++) { + if (sband->bitrates[idx].bitrate > rate->bitrate) + continue; + if (tx->sdata->basic_rates & BIT(idx) && + (!baserate || + (baserate->bitrate < sband->bitrates[idx].bitrate))) + baserate = &sband->bitrates[idx]; + } - control->rts_cts_rate = rate->val; - control->rts_rate = rate; + if (baserate) + control->rts_cts_rate = baserate; + else + control->rts_cts_rate = &sband->bitrates[0]; } if (tx->sta) { @@ -726,10 +761,10 @@ static ieee80211_txrx_result ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx) { struct ieee80211_local *local = tx->local; - struct ieee80211_hw_mode *mode = tx->u.tx.mode; struct sk_buff *skb = tx->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; u32 load = 0, hdrtime; + struct ieee80211_rate *rate = tx->u.tx.rate; /* TODO: this could be part of tx_status handling, so that the number * of retries would be known; TX rate should in that case be stored @@ -740,9 +775,9 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx) /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values, * 1 usec = 1/8 * (1080 / 10) = 13.5 */ - if (mode->mode == MODE_IEEE80211A || - (mode->mode == MODE_IEEE80211G && - tx->u.tx.rate->flags & IEEE80211_RATE_ERP)) + if (tx->u.tx.channel->band == IEEE80211_BAND_5GHZ || + (tx->u.tx.channel->band == IEEE80211_BAND_2GHZ && + rate->flags & IEEE80211_RATE_ERP_G)) hdrtime = CHAN_UTIL_HDR_SHORT; else hdrtime = CHAN_UTIL_HDR_LONG; @@ -756,14 +791,15 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx) else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) load += hdrtime; - load += skb->len * tx->u.tx.rate->rate_inv; + /* TODO: optimise again */ + load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate; if (tx->u.tx.extra_frag) { int i; for (i = 0; i < tx->u.tx.num_extra_frag; i++) { load += 2 * hdrtime; load += tx->u.tx.extra_frag[i]->len * - tx->u.tx.rate->rate; + tx->u.tx.rate->bitrate; } } @@ -816,10 +852,12 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx, struct ieee80211_radiotap_iterator iterator; struct ieee80211_radiotap_header *rthdr = (struct ieee80211_radiotap_header *) skb->data; - struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode; + struct ieee80211_supported_band *sband; int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); struct ieee80211_tx_control *control = tx->u.tx.control; + sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band]; + control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT; tx->flags |= IEEE80211_TXRXD_TX_INJECTED; tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED; @@ -852,10 +890,12 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx, * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps */ target_rate = (*iterator.this_arg) * 5; - for (i = 0; i < mode->num_rates; i++) { - struct ieee80211_rate *r = &mode->rates[i]; + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *r; - if (r->rate == target_rate) { + r = &sband->bitrates[i]; + + if (r->bitrate == target_rate) { tx->u.tx.rate = r; break; } @@ -870,9 +910,11 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx, control->antenna_sel_tx = (*iterator.this_arg) + 1; break; +#if 0 case IEEE80211_RADIOTAP_DBM_TX_POWER: control->power_level = *iterator.this_arg; break; +#endif case IEEE80211_RADIOTAP_FLAGS: if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { @@ -1054,8 +1096,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, if (__ieee80211_queue_stopped(local, control->queue)) return IEEE80211_TX_FRAG_AGAIN; if (i == tx->u.tx.num_extra_frag) { - control->tx_rate = tx->u.tx.last_frag_hwrate; - control->rate = tx->u.tx.last_frag_rate; + control->tx_rate = tx->u.tx.last_frag_rate; + if (tx->flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG) control->flags |= IEEE80211_TXCTL_RATE_CTRL_PROBE; @@ -1114,7 +1156,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, rcu_read_lock(); sta = tx.sta; - tx.u.tx.mode = local->hw.conf.mode; + tx.u.tx.channel = local->hw.conf.channel; for (handler = local->tx_handlers; *handler != NULL; handler++) { @@ -1151,7 +1193,6 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, } else { next_len = 0; tx.u.tx.rate = tx.u.tx.last_frag_rate; - tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val; } dur = ieee80211_duration(&tx, 0, next_len); hdr->duration_id = cpu_to_le16(dur); @@ -1188,7 +1229,6 @@ retry: store->skb = skb; store->extra_frag = tx.u.tx.extra_frag; store->num_extra_frag = tx.u.tx.num_extra_frag; - store->last_frag_hwrate = tx.u.tx.last_frag_hwrate; store->last_frag_rate = tx.u.tx.last_frag_rate; store->last_frag_rate_ctrl_probe = !!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG); @@ -1609,7 +1649,6 @@ void ieee80211_tx_pending(unsigned long data) tx.u.tx.control = &store->control; tx.u.tx.extra_frag = store->extra_frag; tx.u.tx.num_extra_frag = store->num_extra_frag; - tx.u.tx.last_frag_hwrate = store->last_frag_hwrate; tx.u.tx.last_frag_rate = store->last_frag_rate; tx.flags = 0; if (store->last_frag_rate_ctrl_probe) @@ -1712,6 +1751,9 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_if_ap *ap = NULL; struct rate_selection rsel; struct beacon_data *beacon; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; rcu_read_lock(); @@ -1750,8 +1792,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, beacon->tail_len); if (control) { - rate_control_get_rate(local->mdev, local->oper_hw_mode, skb, - &rsel); + rate_control_get_rate(local->mdev, sband, skb, &rsel); if (!rsel.rate) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: ieee80211_beacon_get: " @@ -1764,12 +1805,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, } control->vif = vif; - control->tx_rate = - (sdata->bss_conf.use_short_preamble && - (rsel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ? - rsel.rate->val2 : rsel.rate->val; + control->tx_rate = rsel.rate; + if (sdata->bss_conf.use_short_preamble && + rsel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) + control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; - control->power_level = local->hw.conf.power_level; control->flags |= IEEE80211_TXCTL_NO_ACK; control->retry_limit = 1; control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK; @@ -1874,7 +1914,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, } sta = tx.sta; tx.flags |= IEEE80211_TXRXD_TXPS_BUFFERED; - tx.u.tx.mode = local->hw.conf.mode; + tx.u.tx.channel = local->hw.conf.channel; for (handler = local->tx_handlers; *handler != NULL; handler++) { res = (*handler)(&tx); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5e631ce98d7e..f64804fed0a9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -41,92 +41,6 @@ const unsigned char bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -static int rate_list_match(const int *rate_list, int rate) -{ - int i; - - if (!rate_list) - return 0; - - for (i = 0; rate_list[i] >= 0; i++) - if (rate_list[i] == rate) - return 1; - - return 0; -} - -void ieee80211_prepare_rates(struct ieee80211_local *local, - struct ieee80211_hw_mode *mode) -{ - int i; - - for (i = 0; i < mode->num_rates; i++) { - struct ieee80211_rate *rate = &mode->rates[i]; - - rate->flags &= ~(IEEE80211_RATE_SUPPORTED | - IEEE80211_RATE_BASIC); - - if (local->supp_rates[mode->mode]) { - if (!rate_list_match(local->supp_rates[mode->mode], - rate->rate)) - continue; - } - - rate->flags |= IEEE80211_RATE_SUPPORTED; - - /* Use configured basic rate set if it is available. If not, - * use defaults that are sane for most cases. */ - if (local->basic_rates[mode->mode]) { - if (rate_list_match(local->basic_rates[mode->mode], - rate->rate)) - rate->flags |= IEEE80211_RATE_BASIC; - } else switch (mode->mode) { - case MODE_IEEE80211A: - if (rate->rate == 60 || rate->rate == 120 || - rate->rate == 240) - rate->flags |= IEEE80211_RATE_BASIC; - break; - case MODE_IEEE80211B: - if (rate->rate == 10 || rate->rate == 20) - rate->flags |= IEEE80211_RATE_BASIC; - break; - case MODE_IEEE80211G: - if (rate->rate == 10 || rate->rate == 20 || - rate->rate == 55 || rate->rate == 110) - rate->flags |= IEEE80211_RATE_BASIC; - break; - case NUM_IEEE80211_MODES: - /* not useful */ - break; - } - - /* Set ERP and MANDATORY flags based on phymode */ - switch (mode->mode) { - case MODE_IEEE80211A: - if (rate->rate == 60 || rate->rate == 120 || - rate->rate == 240) - rate->flags |= IEEE80211_RATE_MANDATORY; - break; - case MODE_IEEE80211B: - if (rate->rate == 10) - rate->flags |= IEEE80211_RATE_MANDATORY; - break; - case MODE_IEEE80211G: - if (rate->rate == 10 || rate->rate == 20 || - rate->rate == 55 || rate->rate == 110 || - rate->rate == 60 || rate->rate == 120 || - rate->rate == 240) - rate->flags |= IEEE80211_RATE_MANDATORY; - break; - case NUM_IEEE80211_MODES: - /* not useful */ - break; - } - if (ieee80211_is_erp_rate(mode->mode, rate->rate)) - rate->flags |= IEEE80211_RATE_ERP; - } -} - u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, enum ieee80211_if_types type) { @@ -262,7 +176,7 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, * DIV_ROUND_UP() operations. */ - if (local->hw.conf.phymode == MODE_IEEE80211A || erp) { + if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { /* * OFDM: * @@ -304,15 +218,19 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, /* Exported duration function for driver use */ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - size_t frame_len, int rate) + size_t frame_len, + struct ieee80211_rate *rate) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); u16 dur; int erp; - erp = ieee80211_is_erp_rate(hw->conf.phymode, rate); - dur = ieee80211_frame_duration(local, frame_len, rate, erp, + erp = 0; + if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + erp = rate->flags & IEEE80211_RATE_ERP_G; + + dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, sdata->bss_conf.use_short_preamble); return cpu_to_le16(dur); @@ -332,17 +250,20 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, short_preamble = sdata->bss_conf.use_short_preamble; - rate = frame_txctl->rts_rate; - erp = !!(rate->flags & IEEE80211_RATE_ERP); + rate = frame_txctl->rts_cts_rate; + + erp = 0; + if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + erp = rate->flags & IEEE80211_RATE_ERP_G; /* CTS duration */ - dur = ieee80211_frame_duration(local, 10, rate->rate, + dur = ieee80211_frame_duration(local, 10, rate->bitrate, erp, short_preamble); /* Data frame duration */ - dur += ieee80211_frame_duration(local, frame_len, rate->rate, + dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, short_preamble); /* ACK duration */ - dur += ieee80211_frame_duration(local, 10, rate->rate, + dur += ieee80211_frame_duration(local, 10, rate->bitrate, erp, short_preamble); return cpu_to_le16(dur); @@ -363,15 +284,17 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, short_preamble = sdata->bss_conf.use_short_preamble; - rate = frame_txctl->rts_rate; - erp = !!(rate->flags & IEEE80211_RATE_ERP); + rate = frame_txctl->rts_cts_rate; + erp = 0; + if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + erp = rate->flags & IEEE80211_RATE_ERP_G; /* Data frame duration */ - dur = ieee80211_frame_duration(local, frame_len, rate->rate, + dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, short_preamble); if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) { /* ACK duration */ - dur += ieee80211_frame_duration(local, 10, rate->rate, + dur += ieee80211_frame_duration(local, 10, rate->bitrate, erp, short_preamble); } @@ -379,27 +302,6 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_ctstoself_duration); -struct ieee80211_rate * -ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate) -{ - struct ieee80211_hw_mode *mode; - int r; - - list_for_each_entry(mode, &local->modes_list, list) { - if (mode->mode != phymode) - continue; - for (r = 0; r < mode->num_rates; r++) { - struct ieee80211_rate *rate = &mode->rates[r]; - if (rate->val == hw_rate || - (rate->flags & IEEE80211_RATE_PREAMBLE2 && - rate->val2 == hw_rate)) - return rate; - } - } - - return NULL; -} - void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) { struct ieee80211_local *local = hw_to_local(hw); diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 65710a42e5a7..b9f943c45f3b 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_WIRELESS_EXT) += wext.o obj-$(CONFIG_CFG80211) += cfg80211.o -cfg80211-y += core.o sysfs.o radiotap.o +cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o cfg80211-$(CONFIG_NL80211) += nl80211.o diff --git a/net/wireless/core.c b/net/wireless/core.c index cfc5fc5f9e75..80afacdae46c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -232,6 +232,47 @@ int wiphy_register(struct wiphy *wiphy) { struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); int res; + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + bool have_band = false; + int i; + + /* sanity check supported bands/channels */ + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + if (!sband) + continue; + + sband->band = band; + + if (!sband->n_channels || !sband->n_bitrates) { + WARN_ON(1); + return -EINVAL; + } + + for (i = 0; i < sband->n_channels; i++) { + sband->channels[i].orig_flags = + sband->channels[i].flags; + sband->channels[i].orig_mag = + sband->channels[i].max_antenna_gain; + sband->channels[i].orig_mpwr = + sband->channels[i].max_power; + sband->channels[i].band = band; + } + + have_band = true; + } + + if (!have_band) { + WARN_ON(1); + return -EINVAL; + } + + /* check and set up bitrates */ + ieee80211_set_bitrate_flags(wiphy); + + /* set up regulatory info */ + wiphy_update_regulatory(wiphy); mutex_lock(&cfg80211_drv_mutex); diff --git a/net/wireless/core.h b/net/wireless/core.h index eb0f846b40df..7a02c356d63d 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -78,4 +78,7 @@ extern void cfg80211_dev_free(struct cfg80211_registered_device *drv); extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, char *newname); +void ieee80211_set_bitrate_flags(struct wiphy *wiphy); +void wiphy_update_regulatory(struct wiphy *wiphy); + #endif /* __NET_WIRELESS_CORE_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c new file mode 100644 index 000000000000..2b63c96dcf19 --- /dev/null +++ b/net/wireless/reg.c @@ -0,0 +1,153 @@ +/* + * Copyright 2002-2005, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright 2007 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * This regulatory domain control implementation is highly incomplete, it + * only exists for the purpose of not regressing mac80211. + * + * For now, drivers can restrict the set of allowed channels by either + * not registering those channels or setting the IEEE80211_CHAN_DISABLED + * flag; that flag will only be *set* by this code, never *cleared. + * + * The usual implementation is for a driver to read a device EEPROM to + * determine which regulatory domain it should be operating under, then + * looking up the allowable channels in a driver-local table and finally + * registering those channels in the wiphy structure. + * + * Alternatively, drivers that trust the regulatory domain control here + * will register a complete set of capabilities and the control code + * will restrict the set by setting the IEEE80211_CHAN_* flags. + */ +#include +#include +#include "core.h" + +static char *ieee80211_regdom = "US"; +module_param(ieee80211_regdom, charp, 0444); +MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); + +struct ieee80211_channel_range { + short start_freq; + short end_freq; + int max_power; + int max_antenna_gain; + u32 flags; +}; + +struct ieee80211_regdomain { + const char *code; + const struct ieee80211_channel_range *ranges; + int n_ranges; +}; + +#define RANGE_PWR(_start, _end, _pwr, _ag, _flags) \ + { _start, _end, _pwr, _ag, _flags } + + +/* + * Ideally, in the future, these definitions will be loaded from a + * userspace table via some daemon. + */ +static const struct ieee80211_channel_range ieee80211_US_channels[] = { + /* IEEE 802.11b/g, channels 1..11 */ + RANGE_PWR(2412, 2462, 27, 6, 0), + /* IEEE 802.11a, channels 52..64 */ + RANGE_PWR(5260, 5320, 23, 6, 0), + /* IEEE 802.11a, channels 149..165, outdoor */ + RANGE_PWR(5745, 5825, 30, 6, 0), +}; + +static const struct ieee80211_channel_range ieee80211_JP_channels[] = { + /* IEEE 802.11b/g, channels 1..14 */ + RANGE_PWR(2412, 2484, 20, 6, 0), + /* IEEE 802.11a, channels 34..48 */ + RANGE_PWR(5170, 5240, 20, 6, IEEE80211_CHAN_PASSIVE_SCAN), + /* IEEE 802.11a, channels 52..64 */ + RANGE_PWR(5260, 5320, 20, 6, IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_RADAR), +}; + +#define REGDOM(_code) \ + { \ + .code = __stringify(_code), \ + .ranges = ieee80211_ ##_code## _channels, \ + .n_ranges = ARRAY_SIZE(ieee80211_ ##_code## _channels), \ + } + +static const struct ieee80211_regdomain ieee80211_regdoms[] = { + REGDOM(US), + REGDOM(JP), +}; + + +static const struct ieee80211_regdomain *get_regdom(void) +{ + static const struct ieee80211_channel_range + ieee80211_world_channels[] = { + /* IEEE 802.11b/g, channels 1..11 */ + RANGE_PWR(2412, 2462, 27, 6, 0), + }; + static const struct ieee80211_regdomain regdom_world = REGDOM(world); + int i; + + for (i = 0; i < ARRAY_SIZE(ieee80211_regdoms); i++) + if (strcmp(ieee80211_regdom, ieee80211_regdoms[i].code) == 0) + return &ieee80211_regdoms[i]; + + return ®dom_world; +} + + +static void handle_channel(struct ieee80211_channel *chan, + const struct ieee80211_regdomain *rd) +{ + int i; + u32 flags = chan->orig_flags; + const struct ieee80211_channel_range *rg = NULL; + + for (i = 0; i < rd->n_ranges; i++) { + if (rd->ranges[i].start_freq <= chan->center_freq && + chan->center_freq <= rd->ranges[i].end_freq) { + rg = &rd->ranges[i]; + break; + } + } + + if (!rg) { + /* not found */ + flags |= IEEE80211_CHAN_DISABLED; + chan->flags = flags; + return; + } + + chan->flags = flags; + chan->max_antenna_gain = min(chan->orig_mag, + rg->max_antenna_gain); + chan->max_power = min(chan->orig_mpwr, rg->max_power); +} + +static void handle_band(struct ieee80211_supported_band *sband, + const struct ieee80211_regdomain *rd) +{ + int i; + + for (i = 0; i < sband->n_channels; i++) + handle_channel(&sband->channels[i], rd); +} + +void wiphy_update_regulatory(struct wiphy *wiphy) +{ + enum ieee80211_band band; + const struct ieee80211_regdomain *rd = get_regdom(); + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) + if (wiphy->bands[band]) + handle_band(wiphy->bands[band], rd); +} diff --git a/net/wireless/util.c b/net/wireless/util.c new file mode 100644 index 000000000000..0dcccbf3eb57 --- /dev/null +++ b/net/wireless/util.c @@ -0,0 +1,98 @@ +/* + * Wireless utility functions + * + * Copyright 2007 Johannes Berg + */ +#include +#include +#include "core.h" + +int ieee80211_channel_to_frequency(int chan) +{ + if (chan < 14) + return 2407 + chan * 5; + + if (chan == 14) + return 2484; + + /* FIXME: 802.11j 17.3.8.3.2 */ + return (chan + 1000) * 5; +} +EXPORT_SYMBOL(ieee80211_channel_to_frequency); + +int ieee80211_frequency_to_channel(int freq) +{ + if (freq == 2484) + return 14; + + if (freq < 2484) + return (freq - 2407) / 5; + + /* FIXME: 802.11j 17.3.8.3.2 */ + return freq/5 - 1000; +} +EXPORT_SYMBOL(ieee80211_frequency_to_channel); + +static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, + enum ieee80211_band band) +{ + int i, want; + + switch (band) { + case IEEE80211_BAND_5GHZ: + want = 3; + for (i = 0; i < sband->n_bitrates; i++) { + if (sband->bitrates[i].bitrate == 60 || + sband->bitrates[i].bitrate == 120 || + sband->bitrates[i].bitrate == 240) { + sband->bitrates[i].flags |= + IEEE80211_RATE_MANDATORY_A; + want--; + } + } + WARN_ON(want); + break; + case IEEE80211_BAND_2GHZ: + want = 7; + for (i = 0; i < sband->n_bitrates; i++) { + if (sband->bitrates[i].bitrate == 10) { + sband->bitrates[i].flags |= + IEEE80211_RATE_MANDATORY_B | + IEEE80211_RATE_MANDATORY_G; + want--; + } + + if (sband->bitrates[i].bitrate == 20 || + sband->bitrates[i].bitrate == 55 || + sband->bitrates[i].bitrate == 110 || + sband->bitrates[i].bitrate == 60 || + sband->bitrates[i].bitrate == 120 || + sband->bitrates[i].bitrate == 240) { + sband->bitrates[i].flags |= + IEEE80211_RATE_MANDATORY_G; + want--; + } + + if (sband->bitrates[i].bitrate == 10 || + sband->bitrates[i].bitrate == 20 || + sband->bitrates[i].bitrate == 55 || + sband->bitrates[i].bitrate == 110) + sband->bitrates[i].flags |= + IEEE80211_RATE_ERP_G; + } + WARN_ON(want != 0 && want != 6); + break; + case IEEE80211_NUM_BANDS: + WARN_ON(1); + break; + } +} + +void ieee80211_set_bitrate_flags(struct wiphy *wiphy) +{ + enum ieee80211_band band; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) + if (wiphy->bands[band]) + set_mandatory_flags_band(wiphy->bands[band], band); +} -- cgit v1.2.3-59-g8ed1b From 70e2fed4ec14df84ed72554d573794714b15a078 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:50:40 +0100 Subject: rt2x00: Rate structure overhaul Recent changes to the rate structure registration broke rt2x00, the hw_value was reduced from 32bits to 16bits while rt2x00 used the full 32bits. However the way rt2x00 used the value was inflexible and needed to be changed anyway. This patch creates a array containing information for each rate, the hw_value passed to mac80211 is the index value for that array including a field to indicate if short preamble should be enabled. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 4 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 173 ++++++++++++++++++----------- drivers/net/wireless/rt2x00/rt2x00lib.h | 45 ++++++++ drivers/net/wireless/rt2x00/rt2x00reg.h | 71 ------------ 4 files changed, 153 insertions(+), 140 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 9fba485a40ac..a4d7917f2df5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -246,9 +246,7 @@ config: band = &rt2x00dev->bands[conf->channel->band]; rate = &band->bitrates[band->n_bitrates - 1]; - - libconf.basic_rates = - DEVICE_GET_RATE_FIELD(rate->hw_value, RATEMASK) & DEV_BASIC_RATEMASK; + libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask; } if (flags & CONFIG_UPDATE_CHANNEL) { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 83a72ae36638..f0ba481c51e6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -551,10 +551,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_supported_band *sband; - struct ieee80211_rate *rate; struct ieee80211_hdr *hdr; + const struct rt2x00_rate *rate; unsigned int i; - int val = 0, idx = -1; + int idx = -1; u16 fc; /* @@ -562,19 +562,15 @@ void rt2x00lib_rxdone(struct queue_entry *entry, */ sband = &rt2x00dev->bands[rt2x00dev->curr_band]; for (i = 0; i < sband->n_bitrates; i++) { - rate = &sband->bitrates[i]; + rate = rt2x00_get_rate(sband->bitrates[i].hw_value); /* * When frame was received with an OFDM bitrate, * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 0.5kbit/s. + * a CCK bitrate the signal is the rate in 100kbit/s. */ - if (!rxdesc->ofdm) - val = DEVICE_GET_RATE_FIELD(rate->hw_value, RATE); - else - val = DEVICE_GET_RATE_FIELD(rate->hw_value, PLCP); - - if (val == rxdesc->signal) { + if ((rxdesc->ofdm && rate->plcp == rxdesc->signal) || + (!rxdesc->ofdm && rate->bitrate == rxdesc->signal)) { idx = i; break; } @@ -583,7 +579,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, /* * Only update link status if this is a beacon frame carrying our bssid. */ - hdr = (struct ieee80211_hdr*)entry->skb->data; + hdr = (struct ieee80211_hdr *)entry->skb->data; fc = le16_to_cpu(hdr->frame_control); if (is_beacon(fc) && rxdesc->my_bss) rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi); @@ -617,9 +613,9 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, { struct txentry_desc txdesc; struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + const struct rt2x00_rate *rate; int tx_rate; - int bitrate; int length; int duration; int residual; @@ -636,8 +632,8 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Read required fields from ieee80211 header. */ - frame_control = le16_to_cpu(ieee80211hdr->frame_control); - seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); + frame_control = le16_to_cpu(hdr->frame_control); + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); tx_rate = control->tx_rate->hw_value; @@ -661,16 +657,12 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, tx_rate = control->rts_cts_rate->hw_value; } - /* - * Check for OFDM - */ - if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK) - __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); + rate = rt2x00_get_rate(tx_rate); /* * Check if more fragments are pending */ - if (ieee80211_get_morefrag(ieee80211hdr)) { + if (ieee80211_get_morefrag(hdr)) { __set_bit(ENTRY_TXD_BURST, &txdesc.flags); __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags); } @@ -698,21 +690,21 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * PLCP setup * Length calculation depends on OFDM/CCK rate. */ - txdesc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + txdesc.signal = rate->plcp; txdesc.service = 0x04; length = skb->len + FCS_LEN; - if (test_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags)) { + if (rate->flags & DEV_RATE_OFDM) { + __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); + txdesc.length_high = (length >> 6) & 0x3f; txdesc.length_low = length & 0x3f; } else { - bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); - /* * Convert length to microseconds. */ - residual = get_duration_res(length, bitrate); - duration = get_duration(length, bitrate); + residual = get_duration_res(length, rate->bitrate); + duration = get_duration(length, rate->bitrate); if (residual != 0) { duration++; @@ -720,7 +712,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Check if we need to set the Length Extension */ - if (bitrate == 110 && residual <= 30) + if (rate->bitrate == 110 && residual <= 30) txdesc.service |= 0x80; } @@ -731,7 +723,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * When preamble is enabled we should set the * preamble bit for the signal. */ - if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) + if (rt2x00_get_rate_preamble(tx_rate)) txdesc.signal |= 0x08; } @@ -756,6 +748,81 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); /* * Driver initialization handlers. */ +const struct rt2x00_rate rt2x00_supported_rates[12] = { + { + .flags = 0, + .bitrate = 10, + .ratemask = DEV_RATEMASK_1MB, + .plcp = 0x00, + }, + { + .flags = DEV_RATE_SHORT_PREAMBLE, + .bitrate = 20, + .ratemask = DEV_RATEMASK_2MB, + .plcp = 0x01, + }, + { + .flags = DEV_RATE_SHORT_PREAMBLE, + .bitrate = 55, + .ratemask = DEV_RATEMASK_5_5MB, + .plcp = 0x02, + }, + { + .flags = DEV_RATE_SHORT_PREAMBLE, + .bitrate = 110, + .ratemask = DEV_RATEMASK_11MB, + .plcp = 0x03, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 60, + .ratemask = DEV_RATEMASK_6MB, + .plcp = 0x0b, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 90, + .ratemask = DEV_RATEMASK_9MB, + .plcp = 0x0f, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 120, + .ratemask = DEV_RATEMASK_12MB, + .plcp = 0x0a, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 180, + .ratemask = DEV_RATEMASK_18MB, + .plcp = 0x0e, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 240, + .ratemask = DEV_RATEMASK_24MB, + .plcp = 0x09, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 360, + .ratemask = DEV_RATEMASK_36MB, + .plcp = 0x0d, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 480, + .ratemask = DEV_RATEMASK_48MB, + .plcp = 0x08, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 540, + .ratemask = DEV_RATEMASK_54MB, + .plcp = 0x0c, + }, +}; + static void rt2x00lib_channel(struct ieee80211_channel *entry, const int channel, const int tx_power, const int value) @@ -770,18 +837,17 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, } static void rt2x00lib_rate(struct ieee80211_rate *entry, - const int rate, const int mask, - const int plcp, const int flags) + const u16 index, const struct rt2x00_rate *rate) { - entry->bitrate = rate; - entry->hw_value = - DEVICE_SET_RATE_FIELD(rate, RATE) | - DEVICE_SET_RATE_FIELD(mask, RATEMASK) | - DEVICE_SET_RATE_FIELD(plcp, PLCP); - entry->flags = flags; + entry->flags = 0; + entry->bitrate = rate->bitrate; + entry->hw_value = rt2x00_create_rate_hw_value(index, 0); entry->hw_value_short = entry->hw_value; - if (entry->flags & IEEE80211_RATE_SHORT_PREAMBLE) - entry->hw_value_short |= DEVICE_SET_RATE_FIELD(1, PREAMBLE); + + if (rate->flags & DEV_RATE_SHORT_PREAMBLE) { + entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE; + entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1); + } } static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, @@ -807,33 +873,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, /* * Initialize Rate list. */ - rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB, - 0x00, 0); - rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB, - 0x01, IEEE80211_RATE_SHORT_PREAMBLE); - rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB, - 0x02, IEEE80211_RATE_SHORT_PREAMBLE); - rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB, - 0x03, IEEE80211_RATE_SHORT_PREAMBLE); - - if (spec->num_rates > 4) { - rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB, - 0x0b, 0); - rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB, - 0x0f, 0); - rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB, - 0x0a, 0); - rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB, - 0x0e, 0); - rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB, - 0x09, 0); - rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB, - 0x0d, 0); - rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB, - 0x08, 0); - rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB, - 0x0c, 0); - } + for (i = 0; i < spec->num_rates; i++) + rt2x00lib_rate(&rates[0], i, rt2x00_get_rate(i)); /* * Initialize Channel list. diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index f6789fdaaf6e..ca9630c75520 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -33,6 +33,51 @@ #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) #define RFKILL_POLL_INTERVAL ( 1000 ) +/* + * rt2x00_rate: Per rate device information + */ +struct rt2x00_rate { + unsigned short flags; +#define DEV_RATE_OFDM 0x0001 +#define DEV_RATE_SHORT_PREAMBLE 0x0002 + + unsigned short bitrate; /* In 100kbit/s */ + + unsigned short ratemask; +#define DEV_RATEMASK_1MB ( (1 << 1) - 1 ) +#define DEV_RATEMASK_2MB ( (1 << 2) - 1 ) +#define DEV_RATEMASK_5_5MB ( (1 << 3) - 1 ) +#define DEV_RATEMASK_11MB ( (1 << 4) - 1 ) +#define DEV_RATEMASK_6MB ( (1 << 5) - 1 ) +#define DEV_RATEMASK_9MB ( (1 << 6) - 1 ) +#define DEV_RATEMASK_12MB ( (1 << 7) - 1 ) +#define DEV_RATEMASK_18MB ( (1 << 8) - 1 ) +#define DEV_RATEMASK_24MB ( (1 << 9) - 1 ) +#define DEV_RATEMASK_36MB ( (1 << 10) - 1 ) +#define DEV_RATEMASK_48MB ( (1 << 11) - 1 ) +#define DEV_RATEMASK_54MB ( (1 << 12) - 1 ) + + unsigned short plcp; +}; + +extern const struct rt2x00_rate rt2x00_supported_rates[12]; + +static inline u16 rt2x00_create_rate_hw_value(const u16 index, + const u16 short_preamble) +{ + return (short_preamble << 8) | (index & 0xff); +} + +static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) +{ + return &rt2x00_supported_rates[hw_value & 0xff]; +} + +static inline int rt2x00_get_rate_preamble(const u16 hw_value) +{ + return (hw_value & 0xff00); +} + /* * Radio control handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index e0ebe51c082f..0325bed2fbf5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -220,75 +220,4 @@ static inline u8 rt2x00_get_field8(const u8 reg, return (reg & field.bit_mask) >> field.bit_offset; } -/* - * Device specific rate value. - * We will have to create the device specific rate value - * passed to the ieee80211 kernel. We need to make it a consist of - * multiple fields because we want to store more then 1 device specific - * values inside the value. - * 1 - rate, stored as 100 kbit/s. - * 2 - preamble, short_preamble enabled flag. - * 3 - MASK_RATE, which rates are enabled in this mode, this mask - * corresponds with the TX register format for the current device. - * 4 - plcp, 802.11b rates are device specific, - * 802.11g rates are set according to the ieee802.11a-1999 p.14. - * The bit to enable preamble is set in a seperate define. - */ -#define DEV_RATE FIELD32(0x000007ff) -#define DEV_PREAMBLE FIELD32(0x00000800) -#define DEV_RATEMASK FIELD32(0x00fff000) -#define DEV_PLCP FIELD32(0xff000000) - -/* - * Bitfields - */ -#define DEV_RATEBIT_1MB ( 1 << 0 ) -#define DEV_RATEBIT_2MB ( 1 << 1 ) -#define DEV_RATEBIT_5_5MB ( 1 << 2 ) -#define DEV_RATEBIT_11MB ( 1 << 3 ) -#define DEV_RATEBIT_6MB ( 1 << 4 ) -#define DEV_RATEBIT_9MB ( 1 << 5 ) -#define DEV_RATEBIT_12MB ( 1 << 6 ) -#define DEV_RATEBIT_18MB ( 1 << 7 ) -#define DEV_RATEBIT_24MB ( 1 << 8 ) -#define DEV_RATEBIT_36MB ( 1 << 9 ) -#define DEV_RATEBIT_48MB ( 1 << 10 ) -#define DEV_RATEBIT_54MB ( 1 << 11 ) - -/* - * Bitmasks for DEV_RATEMASK - */ -#define DEV_RATEMASK_1MB ( (DEV_RATEBIT_1MB << 1) -1 ) -#define DEV_RATEMASK_2MB ( (DEV_RATEBIT_2MB << 1) -1 ) -#define DEV_RATEMASK_5_5MB ( (DEV_RATEBIT_5_5MB << 1) -1 ) -#define DEV_RATEMASK_11MB ( (DEV_RATEBIT_11MB << 1) -1 ) -#define DEV_RATEMASK_6MB ( (DEV_RATEBIT_6MB << 1) -1 ) -#define DEV_RATEMASK_9MB ( (DEV_RATEBIT_9MB << 1) -1 ) -#define DEV_RATEMASK_12MB ( (DEV_RATEBIT_12MB << 1) -1 ) -#define DEV_RATEMASK_18MB ( (DEV_RATEBIT_18MB << 1) -1 ) -#define DEV_RATEMASK_24MB ( (DEV_RATEBIT_24MB << 1) -1 ) -#define DEV_RATEMASK_36MB ( (DEV_RATEBIT_36MB << 1) -1 ) -#define DEV_RATEMASK_48MB ( (DEV_RATEBIT_48MB << 1) -1 ) -#define DEV_RATEMASK_54MB ( (DEV_RATEBIT_54MB << 1) -1 ) - -/* - * Bitmask groups of bitrates - */ -#define DEV_BASIC_RATEMASK \ - ( DEV_RATEMASK_11MB | \ - DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB ) - -#define DEV_CCK_RATEMASK ( DEV_RATEMASK_11MB ) -#define DEV_OFDM_RATEMASK ( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK ) - -/* - * Macro's to set and get specific fields from the device specific val and val2 - * fields inside the ieee80211_rate entry. - */ -#define DEVICE_SET_RATE_FIELD(__value, __mask) \ - (int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask ) - -#define DEVICE_GET_RATE_FIELD(__value, __mask) \ - (int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset ) - #endif /* RT2X00REG_H */ -- cgit v1.2.3-59-g8ed1b From f5507ce90be4e00a84b5bb4c7b4324455aa6ee21 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:51:13 +0100 Subject: rt2x00: Remove HWMODE_{A,B,G} rt2500usb initialized the SIFS and EIFS without using the values coming from rt2x000lib. After this is fixed HWMODE_{A,B,G} is now unused and can be removed in favour of the ieee80211_band enumeration which could still be usefull later. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 14 +++----------- drivers/net/wireless/rt2x00/rt2500usb.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 6 +----- drivers/net/wireless/rt2x00/rt2x00config.c | 17 ++--------------- drivers/net/wireless/rt2x00/rt2x00dev.c | 6 +++--- 5 files changed, 10 insertions(+), 35 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 38c968ee50f1..df176cd2ef42 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -358,18 +358,9 @@ static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, } static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, - const int phymode, const int basic_rate_mask) { rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask); - - if (phymode == HWMODE_B) { - rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040); - } else { - rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c); - } } static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, @@ -507,6 +498,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, u16 reg; rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time); + rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs); + rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs); rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, @@ -519,8 +512,7 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) - rt2500usb_config_phymode(rt2x00dev, libconf->phymode, - libconf->basic_rates); + rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates); if (flags & CONFIG_UPDATE_CHANNEL) rt2500usb_config_channel(rt2x00dev, &libconf->rf, libconf->conf->power_level); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 23ba0c15741f..647cd2d56ab9 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -135,7 +135,7 @@ * Misc MAC_CSR registers. * MAC_CSR9: Timer control. * MAC_CSR10: Slot time. - * MAC_CSR11: IFS. + * MAC_CSR11: SIFS. * MAC_CSR12: EIFS. * MAC_CSR13: Power mode0. * MAC_CSR14: Power mode1. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4fa762bdb734..93dbe2b286d5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -390,10 +390,6 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) return (struct rt2x00_intf *)vif->drv_priv; } -#define HWMODE_B 0 -#define HWMODE_G 1 -#define HWMODE_A 2 - /* * Details about the supported modes, rates and channels * of a particular chipset. This is used by rt2x00lib @@ -433,7 +429,7 @@ struct rt2x00lib_conf { struct antenna_setup ant; - int phymode; + enum ieee80211_band band; int basic_rates; int slot_time; diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index a4d7917f2df5..69959124d25d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -229,23 +229,10 @@ config: memset(&libconf, 0, sizeof(libconf)); if (flags & CONFIG_UPDATE_PHYMODE) { - switch (conf->channel->band) { - case IEEE80211_BAND_5GHZ: - libconf.phymode = HWMODE_A; - break; - case IEEE80211_BAND_2GHZ: - /* Uh oh. what about B? */ - libconf.phymode = HWMODE_G; - break; - default: - ERROR(rt2x00dev, - "Attempt to configure unsupported mode (%d)" - "Defaulting to 802.11b", conf->channel->band); - libconf.phymode = HWMODE_B; - } - band = &rt2x00dev->bands[conf->channel->band]; rate = &band->bitrates[band->n_bitrates - 1]; + + libconf.band = conf->channel->band; libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask; } diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index f0ba481c51e6..72c4f13a5336 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -896,7 +896,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: CCK. * Channels: 2.4 GHz */ - if (spec->num_modes > HWMODE_B) { + if (spec->num_modes > 0) { sbands[IEEE80211_BAND_2GHZ].n_channels = 14; sbands[IEEE80211_BAND_2GHZ].n_bitrates = 4; sbands[IEEE80211_BAND_2GHZ].channels = channels; @@ -909,7 +909,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: CCK, OFDM. * Channels: 2.4 GHz */ - if (spec->num_modes > HWMODE_G) { + if (spec->num_modes > 1) { sbands[IEEE80211_BAND_2GHZ].n_channels = 14; sbands[IEEE80211_BAND_2GHZ].n_bitrates = spec->num_rates; sbands[IEEE80211_BAND_2GHZ].channels = channels; @@ -922,7 +922,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: OFDM. * Channels: OFDM, UNII, HiperLAN2. */ - if (spec->num_modes > HWMODE_A) { + if (spec->num_modes > 2) { sbands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14; sbands[IEEE80211_BAND_5GHZ].n_bitrates = spec->num_rates - 4; sbands[IEEE80211_BAND_5GHZ].channels = &channels[14]; -- cgit v1.2.3-59-g8ed1b From 728103794316f7ff8d98bc2ce044aff7a260ee21 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:46:18 +0100 Subject: rt2x00: Rename config_preamble() to config_erp() Rename config_preamble() to config_erp() and cleanup argument list by putting it all into a single structure. This will make the function more meaningful and easier to expand later. This second option is mostly intended to make the patch "mac80211: proper short-slot handling" from Johannes Berg easier to apply for rt2x00. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 16 +++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 16 +++++------ drivers/net/wireless/rt2x00/rt2500usb.c | 12 ++++----- drivers/net/wireless/rt2x00/rt2x00.h | 18 +++++++++---- drivers/net/wireless/rt2x00/rt2x00config.c | 43 ++++++++++++++---------------- drivers/net/wireless/rt2x00/rt2x00dev.c | 5 ++-- drivers/net/wireless/rt2x00/rt2x00lib.h | 6 ++--- drivers/net/wireless/rt2x00/rt2x00mac.c | 16 +++++------ drivers/net/wireless/rt2x00/rt61pci.c | 12 ++++----- drivers/net/wireless/rt2x00/rt73usb.c | 12 ++++----- 10 files changed, 76 insertions(+), 80 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 0ac0c6e08732..70f711e86362 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -304,10 +304,8 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -315,11 +313,13 @@ static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, /* * When short preamble is enabled, we should set bit 0x08 */ - preamble_mask = short_preamble << 3; + preamble_mask = erp->short_preamble << 3; rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, + erp->ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, + erp->ack_consume_time); rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); @@ -1601,7 +1601,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, .config_intf = rt2400pci_config_intf, - .config_preamble = rt2400pci_config_preamble, + .config_erp = rt2400pci_config_erp, .config = rt2400pci_config, }; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d85e1a44d5cd..a46206c69760 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -307,10 +307,8 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -318,11 +316,13 @@ static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, /* * When short preamble is enabled, we should set bit 0x08 */ - preamble_mask = short_preamble << 3; + preamble_mask = erp->short_preamble << 3; rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, + erp->ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, + erp->ack_consume_time); rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); @@ -1911,7 +1911,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, .config_intf = rt2500pci_config_intf, - .config_preamble = rt2500pci_config_preamble, + .config_erp = rt2500pci_config_erp, .config = rt2500pci_config, }; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 7ea4247442b3..43da93a22e77 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -356,10 +356,8 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, (3 * sizeof(__le16))); } -static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u16 reg; @@ -371,12 +369,12 @@ static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, return -EAGAIN; rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); - rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout); rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, - !!short_preamble); + !!erp->short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); return 0; @@ -1842,7 +1840,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_intf = rt2500usb_config_intf, - .config_preamble = rt2500usb_config_preamble, + .config_erp = rt2500usb_config_erp, .config = rt2500usb_config, }; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8718ad3dcc00..a324ff3ed7e7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -384,7 +384,7 @@ struct rt2x00_intf { */ unsigned int delayed_flags; #define DELAYED_UPDATE_BEACON 0x00000001 -#define DELAYED_CONFIG_PREAMBLE 0x00000002 +#define DELAYED_CONFIG_ERP 0x00000002 }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) @@ -450,6 +450,16 @@ struct rt2x00lib_conf { short eifs; }; +/* + * Configuration structure for erp settings. + */ +struct rt2x00lib_erp { + int short_preamble; + + int ack_timeout; + int ack_consume_time; +}; + /* * Configuration structure wrapper around the * rt2x00 interface configuration handler. @@ -558,10 +568,8 @@ struct rt2x00lib_ops { #define CONFIG_UPDATE_MAC ( 1 << 2 ) #define CONFIG_UPDATE_BSSID ( 1 << 3 ) - int (*config_preamble) (struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time); + int (*config_erp) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp); void (*config) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 69959124d25d..72111694154e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -75,43 +75,40 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags); } -void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - const unsigned int short_preamble) +void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct ieee80211_bss_conf *bss_conf) { + struct rt2x00lib_erp erp; int retval; - int ack_timeout; - int ack_consume_time; - ack_timeout = PLCP + get_duration(ACK_SIZE, 10); - ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); + memset(&erp, 0, sizeof(erp)); + + erp.short_preamble = bss_conf->use_short_preamble; + erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10); + erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) - ack_timeout += SHORT_DIFS; + erp.ack_timeout += SHORT_DIFS; else - ack_timeout += DIFS; + erp.ack_timeout += DIFS; - if (short_preamble) { - ack_timeout += SHORT_PREAMBLE; - ack_consume_time += SHORT_PREAMBLE; + if (bss_conf->use_short_preamble) { + erp.ack_timeout += SHORT_PREAMBLE; + erp.ack_consume_time += SHORT_PREAMBLE; } else { - ack_timeout += PREAMBLE; - ack_consume_time += PREAMBLE; + erp.ack_timeout += PREAMBLE; + erp.ack_consume_time += PREAMBLE; } - retval = rt2x00dev->ops->lib->config_preamble(rt2x00dev, - short_preamble, - ack_timeout, - ack_consume_time); - - spin_lock(&intf->lock); + retval = rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); if (retval) { - intf->delayed_flags |= DELAYED_CONFIG_PREAMBLE; + spin_lock(&intf->lock); + intf->delayed_flags |= DELAYED_CONFIG_ERP; queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + spin_unlock(&intf->lock); } - - spin_unlock(&intf->lock); } void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 455d0763503e..d6b12789ba77 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -447,9 +447,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, } } - if (delayed_flags & DELAYED_CONFIG_PREAMBLE) - rt2x00lib_config_preamble(rt2x00dev, intf, - intf->conf.use_short_preamble); + if (delayed_flags & DELAYED_CONFIG_ERP) + rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); } static void rt2x00lib_intf_scheduled(struct work_struct *work) diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 34ccb3de687e..6bd5a01ddfce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -100,9 +100,9 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, enum ieee80211_if_types type, u8 *mac, u8 *bssid); -void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - const unsigned int short_preamble); +void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct ieee80211_bss_conf *conf); void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, enum antenna rx, enum antenna tx); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 76a2a7c118b2..0a11c27d603b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -436,17 +436,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, } /* - * When the preamble mode has changed, we should perform additional - * configuration steps. For all other changes we are already done. + * When the erp information has changed, we should perform + * additional configuration steps. For all other changes we are done. */ - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - rt2x00lib_config_preamble(rt2x00dev, intf, - bss_conf->use_short_preamble); + if (changes & BSS_CHANGED_ERP_PREAMBLE) + rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); - spin_lock(&intf->lock); - memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); - spin_unlock(&intf->lock); - } + spin_lock(&intf->lock); + memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); + spin_unlock(&intf->lock); } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f912a8515b5c..99f18d4ae855 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -366,20 +366,18 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!short_preamble); + !!erp->short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); return 0; @@ -2481,7 +2479,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, .config_intf = rt61pci_config_intf, - .config_preamble = rt61pci_config_preamble, + .config_erp = rt61pci_config_erp, .config = rt61pci_config, }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d0e97e1dfaf6..ddb59c037750 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -378,10 +378,8 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; @@ -393,12 +391,12 @@ static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, return -EAGAIN; rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!short_preamble); + !!erp->short_preamble); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); return 0; @@ -2090,7 +2088,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_intf = rt73usb_config_intf, - .config_preamble = rt73usb_config_preamble, + .config_erp = rt73usb_config_erp, .config = rt73usb_config, }; -- cgit v1.2.3-59-g8ed1b From aa776721b472e343a8db7f3c0673b1fa24e6c7f7 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:48:08 +0100 Subject: rt2x00: Fix basic rate initialization The basic rate which is configured in the register should not match all supported rates, but only the _basic_ rates. Fix this by adding a new flag to the rt2x00_rate structure and whenever the mode is changed, loop over all available rates for that band to get the basic rate mask. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 4 ++-- drivers/net/wireless/rt2x00/rt2x00config.c | 19 ++++++++++++--- drivers/net/wireless/rt2x00/rt2x00dev.c | 38 +++++++++++++++--------------- drivers/net/wireless/rt2x00/rt2x00lib.h | 14 +---------- 4 files changed, 38 insertions(+), 37 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a324ff3ed7e7..ea2786ce1cf5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -441,8 +441,8 @@ struct rt2x00lib_conf { enum ieee80211_band band; - int basic_rates; - int slot_time; + u32 basic_rates; + u32 slot_time; short sifs; short pifs; diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 72111694154e..5e2d81a9e438 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -145,12 +145,26 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); } +static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band) +{ + const struct rt2x00_rate *rate; + unsigned int i; + u32 mask = 0; + + for (i = 0; i < band->n_bitrates; i++) { + rate = rt2x00_get_rate(band->bitrates[i].hw_value); + if (rate->flags & DEV_RATE_BASIC) + mask |= rate->ratemask; + } + + return mask; +} + void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config) { struct rt2x00lib_conf libconf; struct ieee80211_supported_band *band; - struct ieee80211_rate *rate; struct antenna_setup *default_ant = &rt2x00dev->default_ant; struct antenna_setup *active_ant = &rt2x00dev->link.ant.active; int flags = 0; @@ -227,10 +241,9 @@ config: if (flags & CONFIG_UPDATE_PHYMODE) { band = &rt2x00dev->bands[conf->channel->band]; - rate = &band->bitrates[band->n_bitrates - 1]; libconf.band = conf->channel->band; - libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask; + libconf.basic_rates = rt2x00lib_get_basic_rates(band); } if (flags & CONFIG_UPDATE_CHANNEL) { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d6b12789ba77..eb2d21c4e8e9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -766,75 +766,75 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); */ const struct rt2x00_rate rt2x00_supported_rates[12] = { { - .flags = DEV_RATE_CCK, + .flags = DEV_RATE_CCK | DEV_RATE_BASIC, .bitrate = 10, - .ratemask = DEV_RATEMASK_1MB, + .ratemask = BIT(0), .plcp = 0x00, }, { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, .bitrate = 20, - .ratemask = DEV_RATEMASK_2MB, + .ratemask = BIT(1), .plcp = 0x01, }, { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, .bitrate = 55, - .ratemask = DEV_RATEMASK_5_5MB, + .ratemask = BIT(2), .plcp = 0x02, }, { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, .bitrate = 110, - .ratemask = DEV_RATEMASK_11MB, + .ratemask = BIT(3), .plcp = 0x03, }, { - .flags = DEV_RATE_OFDM, + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, .bitrate = 60, - .ratemask = DEV_RATEMASK_6MB, + .ratemask = BIT(4), .plcp = 0x0b, }, { .flags = DEV_RATE_OFDM, .bitrate = 90, - .ratemask = DEV_RATEMASK_9MB, + .ratemask = BIT(5), .plcp = 0x0f, }, { - .flags = DEV_RATE_OFDM, + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, .bitrate = 120, - .ratemask = DEV_RATEMASK_12MB, + .ratemask = BIT(6), .plcp = 0x0a, }, { .flags = DEV_RATE_OFDM, .bitrate = 180, - .ratemask = DEV_RATEMASK_18MB, + .ratemask = BIT(7), .plcp = 0x0e, }, { - .flags = DEV_RATE_OFDM, + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, .bitrate = 240, - .ratemask = DEV_RATEMASK_24MB, + .ratemask = BIT(8), .plcp = 0x09, }, { .flags = DEV_RATE_OFDM, .bitrate = 360, - .ratemask = DEV_RATEMASK_36MB, + .ratemask = BIT(9), .plcp = 0x0d, }, { .flags = DEV_RATE_OFDM, .bitrate = 480, - .ratemask = DEV_RATEMASK_48MB, + .ratemask = BIT(10), .plcp = 0x08, }, { .flags = DEV_RATE_OFDM, .bitrate = 540, - .ratemask = DEV_RATEMASK_54MB, + .ratemask = BIT(11), .plcp = 0x0c, }, }; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index a15227d2fe40..e4b4dd23d611 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -41,22 +41,10 @@ struct rt2x00_rate { #define DEV_RATE_CCK 0x0001 #define DEV_RATE_OFDM 0x0002 #define DEV_RATE_SHORT_PREAMBLE 0x0004 +#define DEV_RATE_BASIC 0x0008 unsigned short bitrate; /* In 100kbit/s */ - unsigned short ratemask; -#define DEV_RATEMASK_1MB ( (1 << 1) - 1 ) -#define DEV_RATEMASK_2MB ( (1 << 2) - 1 ) -#define DEV_RATEMASK_5_5MB ( (1 << 3) - 1 ) -#define DEV_RATEMASK_11MB ( (1 << 4) - 1 ) -#define DEV_RATEMASK_6MB ( (1 << 5) - 1 ) -#define DEV_RATEMASK_9MB ( (1 << 6) - 1 ) -#define DEV_RATEMASK_12MB ( (1 << 7) - 1 ) -#define DEV_RATEMASK_18MB ( (1 << 8) - 1 ) -#define DEV_RATEMASK_24MB ( (1 << 9) - 1 ) -#define DEV_RATEMASK_36MB ( (1 << 10) - 1 ) -#define DEV_RATEMASK_48MB ( (1 << 11) - 1 ) -#define DEV_RATEMASK_54MB ( (1 << 12) - 1 ) unsigned short plcp; }; -- cgit v1.2.3-59-g8ed1b From 3a643d244f09fa1fdd25d48a56a073c1a69583ee Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 25 Mar 2008 14:13:18 +0100 Subject: rt2x00: Fix in_atomic() usage rt73usb and rt2500usb used in_atomic to determine if a configuration step should be rescheduled or not. Since in_atomic() is not a valid method to determine if sleeping is allowed we should fix the way this is handled by adding a new flag to rt2x00. In addition mark LED class support for the drivers broken since that also uses the broken in_atomic() method but so far no solution exists to have LED triggers work only in scheduled context. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 4 +- drivers/net/wireless/rt2x00/rt2400pci.c | 92 +++++++--------------- drivers/net/wireless/rt2x00/rt2500pci.c | 101 ++++++++---------------- drivers/net/wireless/rt2x00/rt2500usb.c | 118 ++++++++-------------------- drivers/net/wireless/rt2x00/rt2x00.h | 11 ++- drivers/net/wireless/rt2x00/rt2x00config.c | 10 +-- drivers/net/wireless/rt2x00/rt2x00mac.c | 57 +++++++++++++- drivers/net/wireless/rt2x00/rt61pci.c | 105 +++++++++---------------- drivers/net/wireless/rt2x00/rt73usb.c | 122 +++++++++-------------------- 9 files changed, 234 insertions(+), 386 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 4709c11da419..ad1549592c00 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -134,7 +134,7 @@ config RT2500USB config RT2500USB_LEDS bool "RT2500 leds support" - depends on RT2500USB + depends on RT2500USB && BROKEN select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. @@ -152,7 +152,7 @@ config RT73USB config RT73USB_LEDS bool "RT73 leds support" - depends on RT73USB + depends on RT73USB && BROKEN select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index c58b1c0abc3c..a6e9c89c802a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -270,6 +270,31 @@ static void rt2400pci_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * since there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); +} + static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -306,8 +331,8 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -347,8 +372,6 @@ static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - return 0; } static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1397,64 +1420,6 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt2400pci_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - */ - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * since there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -1580,7 +1545,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2400pci_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2400pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -1608,6 +1573,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, + .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, .config_erp = rt2400pci_config_erp, .config = rt2400pci_config, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 9468dde3c95e..1bdb873b65f2 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -270,6 +270,35 @@ static void rt2500pci_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, RXCSR0_DROP_MCAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); +} + static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -309,8 +338,8 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -350,8 +379,6 @@ static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - return 0; } static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1731,69 +1758,6 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt2500pci_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - */ - if (mc_count) - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, RXCSR0_DROP_MCAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -1894,7 +1858,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2500pci_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2500pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -1922,6 +1886,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, + .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, .config_erp = rt2500pci_config_erp, .config = rt2500pci_config, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8959a684f40b..f5c18f011e93 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -316,6 +316,35 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u16 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); + rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); +} + static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -358,18 +387,11 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, (3 * sizeof(__le16))); } -static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u16 reg; - /* - * When in atomic context, we should let rt2x00lib - * try this configuration again later. - */ - if (in_atomic()) - return -EAGAIN; - rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout); rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); @@ -378,8 +400,6 @@ static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); - - return 0; } static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1644,6 +1664,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) */ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1656,78 +1677,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt2500usb_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u16 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - */ - if (mc_count) - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. - */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); - return; - } - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); - rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); -} - static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) @@ -1824,7 +1773,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2500usb_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, @@ -1848,6 +1797,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, + .config_filter = rt2500usb_config_filter, .config_intf = rt2500usb_config_intf, .config_erp = rt2500usb_config_erp, .config = rt2500usb_config, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c016bfe1defd..333484ddb993 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -560,6 +560,8 @@ struct rt2x00lib_ops { /* * Configuration handlers. */ + void (*config_filter) (struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags); void (*config_intf) (struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -568,8 +570,8 @@ struct rt2x00lib_ops { #define CONFIG_UPDATE_MAC ( 1 << 2 ) #define CONFIG_UPDATE_BSSID ( 1 << 3 ) - int (*config_erp) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp); + void (*config_erp) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp); void (*config) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags); @@ -624,6 +626,7 @@ enum rt2x00_flags { DRIVER_REQUIRE_FIRMWARE, DRIVER_REQUIRE_BEACON_GUARD, DRIVER_REQUIRE_ATIM_QUEUE, + DRIVER_REQUIRE_SCHEDULED, /* * Driver configuration @@ -987,6 +990,10 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); int rt2x00mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf); +void rt2x00mac_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_addr_list *mc_list); int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 5e2d81a9e438..a9930a03f450 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -80,7 +80,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, struct ieee80211_bss_conf *bss_conf) { struct rt2x00lib_erp erp; - int retval; memset(&erp, 0, sizeof(erp)); @@ -101,14 +100,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, erp.ack_consume_time += PREAMBLE; } - retval = rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); - - if (retval) { - spin_lock(&intf->lock); - intf->delayed_flags |= DELAYED_CONFIG_ERP; - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); - spin_unlock(&intf->lock); - } + rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); } void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 0a11c27d603b..17b6bb034ebf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -380,6 +380,50 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2x00mac_config_interface); +void rt2x00mac_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_addr_list *mc_list) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + + /* + * Mask off any flags we are going to ignore + * from the total_flags field. + */ + *total_flags &= + FIF_ALLMULTI | + FIF_FCSFAIL | + FIF_PLCPFAIL | + FIF_CONTROL | + FIF_OTHER_BSS | + FIF_PROMISC_IN_BSS; + + /* + * Apply some rules to the filters: + * - Some filters imply different filters to be set. + * - Some things we can't filter out at all. + * - Multicast filter seems to kill broadcast traffic so never use it. + */ + *total_flags |= FIF_ALLMULTI; + if (*total_flags & FIF_OTHER_BSS || + *total_flags & FIF_PROMISC_IN_BSS) + *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; + + /* + * Check if there is any work left for us. + */ + if (rt2x00dev->packet_filter == *total_flags) + return; + rt2x00dev->packet_filter = *total_flags; + + if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); + else + rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); +} +EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); + int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -419,6 +463,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); + unsigned int delayed = 0; /* * When the association status has changed we must reset the link @@ -439,11 +484,19 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ - if (changes & BSS_CHANGED_ERP_PREAMBLE) - rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) + rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); + else + delayed |= DELAYED_CONFIG_ERP; + } spin_lock(&intf->lock); memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); + if (delayed) { + intf->delayed_flags |= delayed; + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + } spin_unlock(&intf->lock); } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6e643c8db42e..0d2e6f7dd692 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -321,6 +321,37 @@ static void rt61pci_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(filter_flags & FIF_CONTROL)); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); +} + static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -368,8 +399,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; @@ -381,8 +412,6 @@ static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); - - return 0; } static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -2284,71 +2313,6 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt61pci_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - * - Multicast filter seems to kill broadcast traffic so never use it. - */ - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, - !(*total_flags & FIF_CONTROL)); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static int rt61pci_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -2457,7 +2421,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt61pci_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt61pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -2487,6 +2451,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, + .config_filter = rt61pci_config_filter, .config_intf = rt61pci_config_intf, .config_erp = rt61pci_config_erp, .config = rt61pci_config, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b50f476e4bd1..187e832bab2e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -333,6 +333,37 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(filter_flags & FIF_CONTROL)); + rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); +} + static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -380,18 +411,11 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; - /* - * When in atomic context, we should let rt2x00lib - * try this configuration again later. - */ - if (in_atomic()) - return -EAGAIN; - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); @@ -400,8 +424,6 @@ static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); - - return 0; } static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1872,6 +1894,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1884,80 +1907,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt73usb_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - * - Multicast filter seems to kill broadcast traffic so never use it. - */ - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. - */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); - return; - } - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, - !(*total_flags & FIF_CONTROL)); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static int rt73usb_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -2067,7 +2016,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt73usb_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt73usb_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -2096,6 +2045,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, + .config_filter = rt73usb_config_filter, .config_intf = rt73usb_config_intf, .config_erp = rt73usb_config_erp, .config = rt73usb_config, -- cgit v1.2.3-59-g8ed1b