From e0f114e82e3781087a0ad0e92c94ff0d55012c1a Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 7 Jul 2009 19:08:07 +0200 Subject: p54: re-enable power save feature This patch re-enables p54's power save features and adds a workaround which temporarily alters the device's power state in order to allow ps-polls to be sent and buffered data to be retrieved during psm. (Incorporates patch originally posted as "p54: fix beacon template dtim IE corruption". -- JWL) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/fwio.c | 7 ++-- drivers/net/wireless/p54/lmac.h | 3 ++ drivers/net/wireless/p54/main.c | 77 +++++++++++++++++++++++++---------------- drivers/net/wireless/p54/p54.h | 1 + drivers/net/wireless/p54/txrx.c | 42 ++++++++++++++++++++++ 5 files changed, 98 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index dc4f3f5ee0c8..349375f4a14b 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -585,7 +585,8 @@ int p54_set_ps(struct p54_common *priv) unsigned int i; u16 mode; - if (priv->hw->conf.flags & IEEE80211_CONF_PS) + if (priv->hw->conf.flags & IEEE80211_CONF_PS && + !priv->powersave_override) mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | P54_PSM_CHECKSUM | P54_PSM_MCBC; else @@ -607,8 +608,8 @@ int p54_set_ps(struct p54_common *priv) psm->beacon_rssi_skip_max = 200; psm->rssi_delta_threshold = 0; - psm->nr = 10; - psm->exclude[0] = 0; + psm->nr = 1; + psm->exclude[0] = WLAN_EID_TIM; p54_tx(priv, skb); return 0; diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h index 0496cff26b35..af35cfcd4fe3 100644 --- a/drivers/net/wireless/p54/lmac.h +++ b/drivers/net/wireless/p54/lmac.h @@ -548,4 +548,7 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot, int p54_download_eeprom(struct p54_common *priv, void *buf, u16 offset, u16 len); +/* utility */ +u8 *p54_find_ie(struct sk_buff *skb, u8 ie); + #endif /* LMAC_H */ diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index f9b4f6a238ea..c9a054548d95 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -65,51 +65,64 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, return p54_update_beacon_tim(priv, sta->aid, set); } -static int p54_beacon_format_ie_tim(struct sk_buff *skb) +u8 *p54_find_ie(struct sk_buff *skb, u8 ie) { - /* - * the good excuse for this mess is ... the firmware. - * The dummy TIM MUST be at the end of the beacon frame, - * because it'll be overwritten! - */ - struct ieee80211_mgmt *mgmt = (void *)skb->data; u8 *pos, *end; if (skb->len <= sizeof(mgmt)) - return -EINVAL; + return NULL; pos = (u8 *)mgmt->u.beacon.variable; end = skb->data + skb->len; while (pos < end) { if (pos + 2 + pos[1] > end) - return -EINVAL; + return NULL; - if (pos[0] == WLAN_EID_TIM) { - u8 dtim_len = pos[1]; - u8 dtim_period = pos[3]; - u8 *next = pos + 2 + dtim_len; + if (pos[0] == ie) + return pos; - if (dtim_len < 3) - return -EINVAL; + pos += 2 + pos[1]; + } + return NULL; +} - memmove(pos, next, end - next); +static int p54_beacon_format_ie_tim(struct sk_buff *skb) +{ + /* + * the good excuse for this mess is ... the firmware. + * The dummy TIM MUST be at the end of the beacon frame, + * because it'll be overwritten! + */ + u8 *tim; + u8 dtim_len; + u8 dtim_period; + u8 *next; - if (dtim_len > 3) - skb_trim(skb, skb->len - (dtim_len - 3)); + tim = p54_find_ie(skb, WLAN_EID_TIM); + if (!tim) + return 0; - pos = end - (dtim_len + 2); + dtim_len = tim[1]; + dtim_period = tim[3]; + next = tim + 2 + dtim_len; + + if (dtim_len < 3) + return -EINVAL; + + memmove(tim, next, skb_tail_pointer(skb) - next); + tim = skb_tail_pointer(skb) - (dtim_len + 2); + + /* add the dummy at the end */ + tim[0] = WLAN_EID_TIM; + tim[1] = 3; + tim[2] = 0; + tim[3] = dtim_period; + tim[4] = 0; + + if (dtim_len > 3) + skb_trim(skb, skb->len - (dtim_len - 3)); - /* add the dummy at the end */ - pos[0] = WLAN_EID_TIM; - pos[1] = 3; - pos[2] = 0; - pos[3] = dtim_period; - pos[4] = 0; - return 0; - } - pos += 2 + pos[1]; - } return 0; } @@ -384,6 +397,9 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, priv->wakeup_timer = info->beacon_int * info->dtim_period * 5; p54_setup_mac(priv); + } else { + priv->wakeup_timer = 500; + priv->aid = 0; } } @@ -517,6 +533,9 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) skb_queue_head_init(&priv->tx_pending); dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_NOISE_DBM; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 19d085c73d7d..6772ed505d4d 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -208,6 +208,7 @@ struct p54_common { u32 tsf_low32, tsf_high32; u32 basic_rate_mask; u16 aid; + bool powersave_override; __le32 beacon_req_id; /* cryptographic engine information */ diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 6426d2cae6de..01eadb1683fa 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -288,6 +288,45 @@ static int p54_rssi_to_dbm(struct p54_common *priv, int rssi) priv->rssical_db[band].add) / 4; } +/* + * Even if the firmware is capable of dealing with incoming traffic, + * while dozing, we have to prepared in case mac80211 uses PS-POLL + * to retrieve outstanding frames from our AP. + * (see comment in net/mac80211/mlme.c @ line 1993) + */ +static void p54_pspoll_workaround(struct p54_common *priv, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (void *) skb->data; + struct ieee80211_tim_ie *tim_ie; + u8 *tim; + u8 tim_len; + bool new_psm; + + /* only beacons have a TIM IE */ + if (!ieee80211_is_beacon(hdr->frame_control)) + return; + + if (!priv->aid) + return; + + /* only consider beacons from the associated BSSID */ + if (compare_ether_addr(hdr->addr3, priv->bssid)) + return; + + tim = p54_find_ie(skb, WLAN_EID_TIM); + if (!tim) + return; + + tim_len = tim[1]; + tim_ie = (struct ieee80211_tim_ie *) &tim[2]; + + new_psm = ieee80211_check_tim(tim_ie, tim_len, priv->aid); + if (new_psm != priv->powersave_override) { + priv->powersave_override = new_psm; + p54_set_ps(priv); + } +} + static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) { struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data; @@ -340,6 +379,9 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) skb_pull(skb, header_len); skb_trim(skb, le16_to_cpu(hdr->len)); + if (unlikely(priv->hw->conf.flags & IEEE80211_CONF_PS)) + p54_pspoll_workaround(priv, skb); + ieee80211_rx_irqsafe(priv->hw, skb); queue_delayed_work(priv->hw->workqueue, &priv->work, -- cgit v1.2.2 From f874011bb01e7fb19904db7f739bb343a0a53fd5 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 8 Jul 2009 22:03:13 +0200 Subject: wireless: fix supported cards for rtl8187 Different revisions of WUSB54GC-EU use different chipsets - v2 uses rtl8187, but v3 uses Ralink RT3070. Signed-off-by: Marcin Slusarz Cc: Przemyslaw Kulczycki Cc: John W. Linville Cc: Linux wireless Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5bc00db21b24..7d5902d1349a 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -431,7 +431,7 @@ config RTL8187 ASUS P5B Deluxe Toshiba Satellite Pro series of laptops Asus Wireless Link - Linksys WUSB54GC-EU + Linksys WUSB54GC-EU v2 Thanks to Realtek for their support! -- cgit v1.2.2 From f5ad69fa47e7b204d0032d569812544cd9a351fb Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 9 Jul 2009 10:33:36 -0700 Subject: iwlwifi: move show_qos to debugfs This move the show_qos file from sysfs to debugfs because the "one value per file" sysfs rule. The file is located in /sys/kernel/debug/ieee80211/phy0/iwlagn/data Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 21 --------------------- drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 25 +++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e2cc5994d108..ad5002211ab4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2627,26 +2627,6 @@ static ssize_t show_power_level(struct device *d, static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, store_power_level); -static ssize_t show_qos(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - char *p = buf; - int q; - - for (q = 0; q < AC_NUM; q++) { - p += sprintf(p, "\tcw_min\tcw_max\taifsn\ttxop\n"); - p += sprintf(p, "AC[%d]\t%u\t%u\t%u\t%u\n", q, - priv->qos_data.def_qos_parm.ac[q].cw_min, - priv->qos_data.def_qos_parm.ac[q].cw_max, - priv->qos_data.def_qos_parm.ac[q].aifsn, - priv->qos_data.def_qos_parm.ac[q].edca_txop); - } - - return p - buf + 1; -} - -static DEVICE_ATTR(qos, S_IRUGO, show_qos, NULL); static ssize_t show_statistics(struct device *d, struct device_attribute *attr, char *buf) @@ -2747,7 +2727,6 @@ static struct attribute *iwl_sysfs_entries[] = { &dev_attr_debug_level.attr, #endif &dev_attr_version.attr, - &dev_attr_qos.attr, NULL }; diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 65bbce0f1717..1555676fc519 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -82,6 +82,7 @@ struct iwl_debugfs { struct dentry *file_channels; struct dentry *file_status; struct dentry *file_interrupt; + struct dentry *file_qos; } dbgfs_data_files; struct dir_rf_files { struct dentry *file_disable_sensitivity; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index f32ac74b69ac..e38ec81b839b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -566,6 +566,28 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0, i; + char buf[256]; + const size_t bufsz = sizeof(buf); + ssize_t ret; + + for (i = 0; i < AC_NUM; i++) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tcw_min\tcw_max\taifsn\ttxop\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "AC[%d]\t%u\t%u\t%u\t%u\n", i, + priv->qos_data.def_qos_parm.ac[i].cw_min, + priv->qos_data.def_qos_parm.ac[i].cw_max, + priv->qos_data.def_qos_parm.ac[i].aifsn, + priv->qos_data.def_qos_parm.ac[i].edca_txop); + } + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; +} DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_WRITE_FILE_OPS(log_event); @@ -576,6 +598,7 @@ DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(status); DEBUGFS_READ_WRITE_FILE_OPS(interrupt); +DEBUGFS_READ_FILE_OPS(qos); /* * Create the debugfs files and directories @@ -612,6 +635,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(channels, data); DEBUGFS_ADD_FILE(status, data); DEBUGFS_ADD_FILE(interrupt, data); + DEBUGFS_ADD_FILE(qos, data); DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, &priv->disable_chain_noise_cal); @@ -646,6 +670,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); DEBUGFS_REMOVE(priv->dbgfs->dir_data); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); -- cgit v1.2.2 From fcf89d05404dafcde581d44dfa89bd8c8def27f9 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 9 Jul 2009 10:33:38 -0700 Subject: iwlwifi: fix permissions on debugfs files debugfs files are created with 644 permissions which gives everybody read access. This presents a security issue if a user opens the file and holds it open at the time the driver removes the file. At this point invalid memory will be accessed. Fix this by only allowing root to read debugfs files. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index e38ec81b839b..0b9e824b67c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -49,7 +49,8 @@ #define DEBUGFS_ADD_FILE(name, parent) do { \ dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \ + debugfs_create_file(#name, S_IWUSR | S_IRUSR, \ + dbgfs->dir_##parent, priv, \ &iwl_dbgfs_##name##_ops); \ if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ goto err; \ @@ -57,7 +58,8 @@ #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr); \ + debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ + dbgfs->dir_##parent, ptr); \ if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ || !dbgfs->dbgfs_##parent##_files.file_##name) \ goto err; \ @@ -65,7 +67,7 @@ #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_x32(#name, 0444, dbgfs->dir_##parent, ptr); \ + debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \ if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ || !dbgfs->dbgfs_##parent##_files.file_##name) \ goto err; \ -- cgit v1.2.2 From 5905a1aa71488b5f78822100c865ed7c4f9fcd8f Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 9 Jul 2009 10:33:40 -0700 Subject: iwl3945: cleanup number of queues settings * Rename maximum number of queue (TFD_QUEUE_MAX) to IWL39_NUM_QUEUES to be consistent with rest of iwlwifi. * Remove unused defines. * Fix loops that iterate over number of TX queues to stop when maximum is reached (currently it is maximum + 1). * Remove queues_num module parameter as it is not used. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 7 ++----- drivers/net/wireless/iwlwifi/iwl-3945.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 15 +-------------- 4 files changed, 7 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 73f93a0ff2df..b569c6f38e5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -232,9 +232,8 @@ struct iwl3945_eeprom { #define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ #define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ -#define TFD_QUEUE_MIN 0 -#define TFD_QUEUE_MAX 5 /* 4 DATA + 1 CMD */ - +/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ +#define IWL39_NUM_QUEUES 5 #define IWL_NUM_SCAN_RATES (2) #define IWL_DEFAULT_TX_RETRY 15 @@ -280,8 +279,6 @@ struct iwl3945_eeprom { /* Size of uCode instruction memory in bootstrap state machine */ #define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE -#define IWL39_MAX_NUM_QUEUES 8 - static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) { return (addr >= IWL39_RTC_DATA_LOWER_BOUND) && diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b0246dbda99a..1227ed2960fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -963,7 +963,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) goto error; /* Tx queue(s) */ - for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, @@ -1140,7 +1140,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) int txq_id; /* Tx queues */ - for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) if (txq_id == IWL_CMD_QUEUE_NUM) iwl_cmd_queue_free(priv); else @@ -1156,7 +1156,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); /* reset TFD queues */ - for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), @@ -2552,7 +2552,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) } /* Assign number of Usable TX queues */ - priv->hw_params.max_txq_num = TFD_QUEUE_MAX; + priv->hw_params.max_txq_num = IWL39_NUM_QUEUES; priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index fbb3a573463e..f2ffc48cbaf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -111,9 +111,6 @@ enum iwl3945_antenna { #define IWL_TX_FIFO_HCCA_2 6 #define IWL_TX_FIFO_NONE 7 -/* Minimum number of queues. MAX_NUM is defined in hw specific files */ -#define IWL_MIN_NUM_QUEUES 4 - #define IEEE80211_DATA_LEN 2304 #define IEEE80211_4ADDR_LEN 30 #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7ff95f80b817..c9b3ea927144 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -89,7 +89,7 @@ MODULE_LICENSE("GPL"); /* module parameters */ struct iwl_mod_params iwl3945_mod_params = { - .num_of_queues = IWL39_MAX_NUM_QUEUES, + .num_of_queues = IWL39_NUM_QUEUES, /* Not used */ .sw_crypto = 1, .restart_fw = 1, /* the rest are 0 by default */ @@ -3947,15 +3947,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv = hw->priv; SET_IEEE80211_DEV(hw, &pdev->dev); - if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) || - (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) { - IWL_ERR(priv, - "invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); - err = -EINVAL; - goto out_ieee80211_free_hw; - } - /* * Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. @@ -4272,10 +4263,6 @@ module_param_named(debug, iwl3945_mod_params.debug, uint, 0444); MODULE_PARM_DESC(debug, "debug output mask"); module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); - -module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444); -MODULE_PARM_DESC(queues_num, "number of hw queues."); - module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); -- cgit v1.2.2 From 01a7e08436929271c6173b5daf3e193ef5b3561a Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 9 Jul 2009 10:33:41 -0700 Subject: iwlagn: fix minimum number of queues setting We need to provide a reasonable minimum that will result in a working setup if used. Set minimum to be 10 to provide for 4 standard TX queues + 1 command queue + 2 (unused) HCCA queues + 4 HT queues (one per AC). We allow the user to change the number of queues used via a module parameter and use this minimum value to check if it is valid. Without this patch a user can select a value for the number of queues that will result in a failing setup. Signed-off-by: Reinette Chatre Reviewed-by: Tomas Winkler Acked-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1a2fe37d4735..b989d5c08d34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -258,8 +258,10 @@ struct iwl_channel_info { #define IWL_TX_FIFO_HCCA_2 6 #define IWL_TX_FIFO_NONE 7 -/* Minimum number of queues. MAX_NUM is defined in hw specific files */ -#define IWL_MIN_NUM_QUEUES 4 +/* Minimum number of queues. MAX_NUM is defined in hw specific files. + * Set the minimum to accommodate the 4 standard TX queues, 1 command + * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ +#define IWL_MIN_NUM_QUEUES 10 /* Power management (not Tx power) structures */ -- cgit v1.2.2 From 4b14c96dfbf068acb85c3fa2446b3949c0230deb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 10 Jul 2009 16:56:59 +0200 Subject: mac80211_hwsim: report fixed signal strength There's no reason to think that hwsim has any actual signal strength, but for testing it is very useful to have it report _some_ value to the stack so I can see if the value ends up being reported correctly Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e9b5442f1dda..78431abc8b40 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -406,7 +406,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, rx_status.freq = data->channel->center_freq; rx_status.band = data->channel->band; rx_status.rate_idx = info->control.rates[0].idx; - /* TODO: simulate signal strength (and optional packet drop) */ + /* TODO: simulate real signal strength (and optional packet loss) */ + rx_status.signal = -50; if (data->ps != PS_DISABLED) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); @@ -1024,7 +1025,8 @@ static int __init init_mac80211_hwsim(void) BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT); - hw->flags = IEEE80211_HW_MFP_CAPABLE; + hw->flags = IEEE80211_HW_MFP_CAPABLE | + IEEE80211_HW_SIGNAL_DBM; /* ask mac80211 to reserve space for magic */ hw->vif_data_size = sizeof(struct hwsim_vif_priv); -- cgit v1.2.2 From 930c06f27120fa8cf0bfb6fa000a701cfaf01ed6 Mon Sep 17 00:00:00 2001 From: Stefan Steuerwald Date: Fri, 10 Jul 2009 20:42:55 +0200 Subject: rt2x00: Implement set_tim callback for all drivers Implement set_tim callback for all rt2x00 drivers, this makes the device wake up powersaving stations properly while in AP mode. The only way to update the beacon is by simply calling mac80211 and requesting the new beacon. This means the set_tim() event is mostly the same as a beacon_done() event which was already defined in rt2x00lib. Signed-off-by: Stefan Steuerwald Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 1 + drivers/net/wireless/rt2x00/rt2500usb.c | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00mac.c | 10 ++++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 1 + 8 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index d8035e3575e8..30185ad28d93 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1561,6 +1561,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2400pci_conf_tx, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c123e28396d0..3b3171578b14 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1860,6 +1860,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 00611b32d08b..de48c5c68eff 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1896,6 +1896,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index a204e66753c2..66e001c392b0 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -2786,6 +2786,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, .get_tkip_seq = rt2800usb_get_tkip_seq, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 71f37cb476b0..3e177175e34b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -963,6 +963,8 @@ 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_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set); #ifdef CONFIG_RT2X00_LIB_CRYPTO int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index b7e0ddda38f5..3425984a55c7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -454,6 +454,16 @@ static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) sizeof(crypto->rx_mic)); } +int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + + rt2x00lib_beacondone(rt2x00dev); + return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); + int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8a49d99df682..b435c140cb96 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2716,6 +2716,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ad2898ca8677..4f9b1772e1a1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2241,6 +2241,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, -- cgit v1.2.2 From 1a9b6679adfb8ef1f1f3dbb7ebd2ee72e2ea4b56 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 11 Jul 2009 01:22:26 +0200 Subject: p54: generate channel list dynamically This patch enhances the eeprom parser to generate customized channel list for every device. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/eeprom.c | 323 ++++++++++++++++++++++++++++++-------- drivers/net/wireless/p54/main.c | 4 + drivers/net/wireless/p54/p54.h | 1 + 3 files changed, 261 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index a2a044ef1012..549ef2d19cd7 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -41,30 +42,6 @@ static struct ieee80211_rate p54_bgrates[] = { { .bitrate = 540, .hw_value = 11, }, }; -static struct ieee80211_channel p54_bgchannels[] = { - { .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 struct ieee80211_supported_band band_2GHz = { - .channels = p54_bgchannels, - .n_channels = ARRAY_SIZE(p54_bgchannels), - .bitrates = p54_bgrates, - .n_bitrates = ARRAY_SIZE(p54_bgrates), -}; - static struct ieee80211_rate p54_arates[] = { { .bitrate = 60, .hw_value = 4, }, { .bitrate = 90, .hw_value = 5, }, @@ -76,51 +53,257 @@ static struct ieee80211_rate p54_arates[] = { { .bitrate = 540, .hw_value = 11, }, }; -static struct ieee80211_channel p54_achannels[] = { - { .center_freq = 4920 }, - { .center_freq = 4940 }, - { .center_freq = 4960 }, - { .center_freq = 4980 }, - { .center_freq = 5040 }, - { .center_freq = 5060 }, - { .center_freq = 5080 }, - { .center_freq = 5170 }, - { .center_freq = 5180 }, - { .center_freq = 5190 }, - { .center_freq = 5200 }, - { .center_freq = 5210 }, - { .center_freq = 5220 }, - { .center_freq = 5230 }, - { .center_freq = 5240 }, - { .center_freq = 5260 }, - { .center_freq = 5280 }, - { .center_freq = 5300 }, - { .center_freq = 5320 }, - { .center_freq = 5500 }, - { .center_freq = 5520 }, - { .center_freq = 5540 }, - { .center_freq = 5560 }, - { .center_freq = 5580 }, - { .center_freq = 5600 }, - { .center_freq = 5620 }, - { .center_freq = 5640 }, - { .center_freq = 5660 }, - { .center_freq = 5680 }, - { .center_freq = 5700 }, - { .center_freq = 5745 }, - { .center_freq = 5765 }, - { .center_freq = 5785 }, - { .center_freq = 5805 }, - { .center_freq = 5825 }, +#define CHAN_HAS_CAL BIT(0) +#define CHAN_HAS_LIMIT BIT(1) +#define CHAN_HAS_CURVE BIT(2) +#define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE) + +struct p54_channel_entry { + u16 freq; + u16 data; + int index; + enum ieee80211_band band; }; -static struct ieee80211_supported_band band_5GHz = { - .channels = p54_achannels, - .n_channels = ARRAY_SIZE(p54_achannels), - .bitrates = p54_arates, - .n_bitrates = ARRAY_SIZE(p54_arates), +struct p54_channel_list { + struct p54_channel_entry *channels; + size_t entries; + size_t max_entries; + size_t band_channel_num[IEEE80211_NUM_BANDS]; }; +static int p54_get_band_from_freq(u16 freq) +{ + /* FIXME: sync these values with the 802.11 spec */ + + if ((freq >= 2412) && (freq <= 2484)) + return IEEE80211_BAND_2GHZ; + + if ((freq >= 4920) && (freq <= 5825)) + return IEEE80211_BAND_5GHZ; + + return -1; +} + +static int p54_compare_channels(const void *_a, + const void *_b) +{ + const struct p54_channel_entry *a = _a; + const struct p54_channel_entry *b = _b; + + return a->index - b->index; +} + +static int p54_fill_band_bitrates(struct ieee80211_hw *dev, + struct ieee80211_supported_band *band_entry, + enum ieee80211_band band) +{ + /* TODO: generate rate array dynamically */ + + switch (band) { + case IEEE80211_BAND_2GHZ: + band_entry->bitrates = p54_bgrates; + band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates); + break; + case IEEE80211_BAND_5GHZ: + band_entry->bitrates = p54_arates; + band_entry->n_bitrates = ARRAY_SIZE(p54_arates); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int p54_generate_band(struct ieee80211_hw *dev, + struct p54_channel_list *list, + enum ieee80211_band band) +{ + struct p54_common *priv = dev->priv; + struct ieee80211_supported_band *tmp, *old; + unsigned int i, j; + int ret = -ENOMEM; + + if ((!list->entries) || (!list->band_channel_num[band])) + return 0; + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + goto err_out; + + tmp->channels = kzalloc(sizeof(struct ieee80211_channel) * + list->band_channel_num[band], GFP_KERNEL); + if (!tmp->channels) + goto err_out; + + ret = p54_fill_band_bitrates(dev, tmp, band); + if (ret) + goto err_out; + + for (i = 0, j = 0; (j < list->band_channel_num[band]) && + (i < list->entries); i++) { + + if (list->channels[i].band != band) + continue; + + if (list->channels[i].data != CHAN_HAS_ALL) { + printk(KERN_ERR "%s:%s%s%s is/are missing for " + "channel:%d [%d MHz].\n", + wiphy_name(dev->wiphy), + (list->channels[i].data & CHAN_HAS_CAL ? "" : + " [iqauto calibration data]"), + (list->channels[i].data & CHAN_HAS_LIMIT ? "" : + " [output power limits]"), + (list->channels[i].data & CHAN_HAS_CURVE ? "" : + " [curve data]"), + list->channels[i].index, list->channels[i].freq); + } + + tmp->channels[j].band = list->channels[i].band; + tmp->channels[j].center_freq = list->channels[i].freq; + j++; + } + + tmp->n_channels = list->band_channel_num[band]; + old = priv->band_table[band]; + priv->band_table[band] = tmp; + if (old) { + kfree(old->channels); + kfree(old); + } + + return 0; + +err_out: + if (tmp) { + kfree(tmp->channels); + kfree(tmp); + } + + return ret; +} + +static void p54_update_channel_param(struct p54_channel_list *list, + u16 freq, u16 data) +{ + int band, i; + + /* + * usually all lists in the eeprom are mostly sorted. + * so it's very likely that the entry we are looking for + * is right at the end of the list + */ + for (i = list->entries; i >= 0; i--) { + if (freq == list->channels[i].freq) { + list->channels[i].data |= data; + break; + } + } + + if ((i < 0) && (list->entries < list->max_entries)) { + /* entry does not exist yet. Initialize a new one. */ + band = p54_get_band_from_freq(freq); + + /* + * filter out frequencies which don't belong into + * any supported band. + */ + if (band < 0) + return ; + + i = list->entries++; + list->band_channel_num[band]++; + + list->channels[i].freq = freq; + list->channels[i].data = data; + list->channels[i].band = band; + list->channels[i].index = ieee80211_frequency_to_channel(freq); + /* TODO: parse output_limit and fill max_power */ + } +} + +static int p54_generate_channel_lists(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + struct p54_channel_list *list; + unsigned int i, j, max_channel_num; + int ret = -ENOMEM; + u16 freq; + + if ((priv->iq_autocal_len != priv->curve_data->entries) || + (priv->iq_autocal_len != priv->output_limit->entries)) + printk(KERN_ERR "%s: EEPROM is damaged... you may not be able" + "to use all channels with this device.\n", + wiphy_name(dev->wiphy)); + + max_channel_num = max_t(unsigned int, priv->output_limit->entries, + priv->iq_autocal_len); + max_channel_num = max_t(unsigned int, max_channel_num, + priv->curve_data->entries); + + list = kzalloc(sizeof(*list), GFP_KERNEL); + if (!list) + goto free; + + list->max_entries = max_channel_num; + list->channels = kzalloc(sizeof(struct p54_channel_entry) * + max_channel_num, GFP_KERNEL); + if (!list->channels) + goto free; + + for (i = 0; i < max_channel_num; i++) { + if (i < priv->iq_autocal_len) { + freq = le16_to_cpu(priv->iq_autocal[i].freq); + p54_update_channel_param(list, freq, CHAN_HAS_CAL); + } + + if (i < priv->output_limit->entries) { + freq = le16_to_cpup((__le16 *) (i * + priv->output_limit->entry_size + + priv->output_limit->offset + + priv->output_limit->data)); + + p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); + } + + if (i < priv->curve_data->entries) { + freq = le16_to_cpup((__le16 *) (i * + priv->curve_data->entry_size + + priv->curve_data->offset + + priv->curve_data->data)); + + p54_update_channel_param(list, freq, CHAN_HAS_CURVE); + } + } + + /* sort the list by the channel index */ + sort(list->channels, list->entries, sizeof(struct p54_channel_entry), + p54_compare_channels, NULL); + + for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { + if (list->band_channel_num[i]) { + ret = p54_generate_band(dev, list, i); + if (ret) + goto free; + + j++; + } + } + if (j == 0) { + /* no useable band available. */ + ret = -EINVAL; + } + +free: + if (list) { + kfree(list->channels); + kfree(list); + } + + return ret; +} + static int p54_convert_rev0(struct ieee80211_hw *dev, struct pda_pa_curve_data *curve_data) { @@ -487,13 +670,19 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) goto err; } + err = p54_generate_channel_lists(dev); + if (err) + goto err; + priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) p54_init_xbow_synth(priv); if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = + priv->band_table[IEEE80211_BAND_2GHZ]; if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) - dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz; + dev->wiphy->bands[IEEE80211_BAND_5GHZ] = + priv->band_table[IEEE80211_BAND_5GHZ]; if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED) priv->rx_diversity_mask = 3; if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED) diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index c9a054548d95..f19add2c3cac 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -598,6 +598,10 @@ EXPORT_SYMBOL_GPL(p54_register_common); void p54_free_common(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; + unsigned int i; + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + kfree(priv->band_table[i]); kfree(priv->iq_autocal); kfree(priv->output_limit); diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 6772ed505d4d..584b1560aff0 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -198,6 +198,7 @@ struct p54_common { struct p54_cal_database *curve_data; struct p54_cal_database *output_limit; struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; + struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS]; /* BBP/MAC state */ u8 mac_addr[ETH_ALEN]; -- cgit v1.2.2 From acbadf01ff6727a2c7dc6e12f70ce8d05a16dc06 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 11 Jul 2009 17:24:14 +0200 Subject: ar9170: implement transmit aggregation This patch roughly implements xmit aggregation for ar9170-like device. Not all AP are compatible with the driver(and firmware) yet, so YMMV. A more refined code will definitely need the final HT specification to be available for the public, lots of firmware modification and possibly a redesigned driver just for good measure. Sadly, these conditions won't come true anytime soon... Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 52 +++ drivers/net/wireless/ath/ar9170/main.c | 608 +++++++++++++++++++++++++++++-- 2 files changed, 634 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index bb97981fb248..e6c3ee3e0581 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -109,11 +109,52 @@ struct ar9170_rxstream_mpdu_merge { bool has_plcp; }; +#define AR9170_NUM_MAX_BA_RETRY 5 +#define AR9170_NUM_TID 16 +#define WME_BA_BMP_SIZE 64 +#define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) + +#define WME_AC_BE 2 +#define WME_AC_BK 3 +#define WME_AC_VI 1 +#define WME_AC_VO 0 + +#define TID_TO_WME_AC(_tid) \ + ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ + (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ + (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ + WME_AC_VO) + +#define BAW_WITHIN(_start, _bawsz, _seqno) \ + ((((_seqno) - (_start)) & 0xfff) < (_bawsz)) + +enum ar9170_tid_state { + AR9170_TID_STATE_INVALID, + AR9170_TID_STATE_SHUTDOWN, + AR9170_TID_STATE_PROGRESS, + AR9170_TID_STATE_COMPLETE, +}; + +struct ar9170_sta_tid { + struct list_head list; + struct sk_buff_head queue; + u8 addr[ETH_ALEN]; + u16 ssn; + u16 tid; + enum ar9170_tid_state state; + bool active; + u8 retry; +}; + #define AR9170_QUEUE_TIMEOUT 64 #define AR9170_TX_TIMEOUT 8 +#define AR9170_BA_TIMEOUT 4 #define AR9170_JANITOR_DELAY 128 #define AR9170_TX_INVALID_RATE 0xffffffff +#define AR9170_NUM_TX_STATUS 128 +#define AR9170_NUM_TX_AGG_MAX 30 + struct ar9170 { struct ieee80211_hw *hw; struct mutex mutex; @@ -187,14 +228,25 @@ struct ar9170 { struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; struct delayed_work tx_janitor; + /* tx ampdu */ + struct sk_buff_head tx_status_ampdu; + spinlock_t tx_ampdu_list_lock; + struct list_head tx_ampdu_list; + unsigned int tx_ampdu_pending; /* rxstream mpdu merge */ struct ar9170_rxstream_mpdu_merge rx_mpdu; struct sk_buff *rx_failover; int rx_failover_missing; + + /* (cached) HW A-MPDU settings */ + u8 global_ampdu_density; + u8 global_ampdu_factor; }; struct ar9170_sta_info { + struct ar9170_sta_tid agg[AR9170_NUM_TID]; + unsigned int ampdu_max_len; }; #define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 51753ed1b8ba..cfe6fc78067a 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -49,6 +49,10 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static int modparam_ht; +module_param_named(ht, modparam_ht, bool, S_IRUGO); +MODULE_PARM_DESC(ht, "enable MPDU aggregation."); + #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ .bitrate = (_bitrate), \ .flags = (_flags), \ @@ -148,12 +152,15 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = { .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ IEEE80211_HT_CAP_SGI_40 | \ + IEEE80211_HT_CAP_GRN_FLD | \ IEEE80211_HT_CAP_DSSSCCK40 | \ IEEE80211_HT_CAP_SM_PS, \ .ampdu_factor = 3, \ .ampdu_density = 6, \ .mcs = { \ - .rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \ + .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ + .rx_highest = cpu_to_le16(300), \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ }, \ } @@ -174,8 +181,31 @@ static struct ieee80211_supported_band ar9170_band_5GHz = { }; static void ar9170_tx(struct ar9170 *ar); +static bool ar9170_tx_ampdu(struct ar9170 *ar); -#ifdef AR9170_QUEUE_DEBUG +static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) +{ + return le16_to_cpu(hdr->seq_ctrl) >> 4; +} + +static inline u16 ar9170_get_seq(struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + return ar9170_get_seq_h((void *) txc->frame_data); +} + +static inline u16 ar9170_get_tid(struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *) txc->frame_data; + + return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; +} + +#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) +#define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb))) + +#if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG) static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) { struct ar9170_tx_control *txc = (void *) skb->data; @@ -183,10 +213,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; struct ieee80211_hdr *hdr = (void *) txc->frame_data; - printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x " + printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), arinfo->flags, + ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), jiffies_to_msecs(arinfo->timeout - jiffies)); } @@ -210,7 +240,9 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, "mismatch %d != %d\n", skb_queue_len(queue), i); printk(KERN_DEBUG "---[ end ]---\n"); } +#endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */ +#ifdef AR9170_QUEUE_DEBUG static void ar9170_dump_txqueue(struct ar9170 *ar, struct sk_buff_head *queue) { @@ -220,7 +252,9 @@ static void ar9170_dump_txqueue(struct ar9170 *ar, __ar9170_dump_txqueue(ar, queue); spin_unlock_irqrestore(&queue->lock, flags); } +#endif /* AR9170_QUEUE_DEBUG */ +#ifdef AR9170_QUEUE_STOP_DEBUG static void __ar9170_dump_txstats(struct ar9170 *ar) { int i; @@ -229,20 +263,27 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) wiphy_name(ar->hw->wiphy)); for (i = 0; i < __AR9170_NUM_TXQ; i++) - printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d\n", - wiphy_name(ar->hw->wiphy), i, ar->tx_stats[i].limit, - ar->tx_stats[i].len, skb_queue_len(&ar->tx_status[i])); + printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d " + " stopped:%d\n", wiphy_name(ar->hw->wiphy), i, + ar->tx_stats[i].limit, ar->tx_stats[i].len, + skb_queue_len(&ar->tx_status[i]), + ieee80211_queue_stopped(ar->hw, i)); } +#endif /* AR9170_QUEUE_STOP_DEBUG */ -static void ar9170_dump_txstats(struct ar9170 *ar) +#ifdef AR9170_TXAGG_DEBUG +static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) { unsigned long flags; - spin_lock_irqsave(&ar->tx_stats_lock, flags); - __ar9170_dump_txstats(ar); - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); + printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", + wiphy_name(ar->hw->wiphy)); + __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); + spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); } -#endif /* AR9170_QUEUE_DEBUG */ + +#endif /* AR9170_TXAGG_DEBUG */ /* caller must guarantee exclusive access for _bin_ queue. */ static void ar9170_recycle_expired(struct ar9170 *ar, @@ -315,6 +356,70 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, ieee80211_tx_status_irqsafe(ar->hw, skb); } +static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) +{ + struct sk_buff_head success; + struct sk_buff *skb; + unsigned int i; + unsigned long queue_bitmap = 0; + + skb_queue_head_init(&success); + + while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS) + __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu)); + + ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success); + +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n", + wiphy_name(ar->hw->wiphy), skb_queue_len(&success)); + __ar9170_dump_txqueue(ar, &success); +#endif /* AR9170_TXAGG_DEBUG */ + + while ((skb = __skb_dequeue(&success))) { + struct ieee80211_tx_info *txinfo; + + queue_bitmap |= BIT(skb_get_queue_mapping(skb)); + + txinfo = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(txinfo); + + txinfo->flags |= IEEE80211_TX_STAT_ACK; + txinfo->status.rates[0].count = 1; + + skb_pull(skb, sizeof(struct ar9170_tx_control)); + ieee80211_tx_status_irqsafe(ar->hw, skb); + } + + for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { +#ifdef AR9170_QUEUE_STOP_DEBUG + printk(KERN_DEBUG "%s: wake queue %d\n", + wiphy_name(ar->hw->wiphy), i); + __ar9170_dump_txstats(ar); +#endif /* AR9170_QUEUE_STOP_DEBUG */ + ieee80211_wake_queue(ar->hw, i); + } + + if (queue_bitmap) + ar9170_tx(ar); +} + +static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); + struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; + + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_BA_TIMEOUT); + + skb_queue_tail(&ar->tx_status_ampdu, skb); + ar9170_tx_fake_ampdu_status(ar); + ar->tx_ampdu_pending--; + + if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) + ar9170_tx_ampdu(ar); +} + void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -336,7 +441,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) spin_unlock_irqrestore(&ar->tx_stats_lock, flags); if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { - dev_kfree_skb_any(skb); + ar9170_tx_ampdu_callback(ar, skb); } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_TX_TIMEOUT); @@ -420,6 +525,38 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, return NULL; } +static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r) +{ + struct sk_buff *skb; + struct ieee80211_tx_info *txinfo; + + while (count) { + skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r); + if (!skb) + break; + + txinfo = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(txinfo); + + /* FIXME: maybe more ? */ + txinfo->status.rates[0].count = 1; + + skb_pull(skb, sizeof(struct ar9170_tx_control)); + ieee80211_tx_status_irqsafe(ar->hw, skb); + count--; + } + +#ifdef AR9170_TXAGG_DEBUG + if (count) { + printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more " + "suitable frames left in tx_status queue.\n", + wiphy_name(ar->hw->wiphy), count); + + ar9170_dump_tx_status_ampdu(ar); + } +#endif /* AR9170_TXAGG_DEBUG */ +} + /* * This worker tries to keeps an maintain tx_status queues. * So we can guarantee that incoming tx_status reports are @@ -456,6 +593,8 @@ static void ar9170_tx_janitor(struct work_struct *work) resched = true; } + ar9170_tx_fake_ampdu_status(ar); + if (resched) queue_delayed_work(ar->hw->workqueue, &ar->tx_janitor, @@ -528,8 +667,15 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) break; case 0xc4: + /* BlockACK bitmap */ + break; + case 0xc5: /* BlockACK events */ + ar9170_handle_block_ack(ar, + le16_to_cpu(cmd->ba_fail_cnt.failed), + le16_to_cpu(cmd->ba_fail_cnt.rate)); + ar9170_tx_fake_ampdu_status(ar); break; case 0xc6: @@ -1098,6 +1244,10 @@ static int ar9170_op_start(struct ieee80211_hw *hw) AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ + /* set sane AMPDU defaults */ + ar->global_ampdu_density = 6; + ar->global_ampdu_factor = 3; + ar->bad_hw_nagger = jiffies; err = ar->open(ar); @@ -1143,6 +1293,7 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) flush_workqueue(ar->hw->workqueue); cancel_delayed_work_sync(&ar->tx_janitor); + cancel_delayed_work_sync(&ar->led_work); cancel_work_sync(&ar->filter_config_work); cancel_work_sync(&ar->beacon_work); mutex_lock(&ar->mutex); @@ -1159,9 +1310,40 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) skb_queue_purge(&ar->tx_pending[i]); skb_queue_purge(&ar->tx_status[i]); } + skb_queue_purge(&ar->tx_status_ampdu); + mutex_unlock(&ar->mutex); } +static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU); +} + +static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst, + struct sk_buff *src) +{ + struct ar9170_tx_control *dst_txc, *src_txc; + struct ieee80211_tx_info *dst_info, *src_info; + struct ar9170_tx_info *dst_arinfo, *src_arinfo; + + src_txc = (void *) src->data; + src_info = IEEE80211_SKB_CB(src); + src_arinfo = (void *) src_info->rate_driver_data; + + dst_txc = (void *) dst->data; + dst_info = IEEE80211_SKB_CB(dst); + dst_arinfo = (void *) dst_info->rate_driver_data; + + dst_txc->phy_control = src_txc->phy_control; + + /* same MCS for the whole aggregate */ + memcpy(dst_info->driver_rates, src_info->driver_rates, + sizeof(dst_info->driver_rates)); +} + static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) { struct ieee80211_hdr *hdr; @@ -1230,6 +1412,7 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; + goto out; } @@ -1360,6 +1543,159 @@ static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); } +static bool ar9170_tx_ampdu(struct ar9170 *ar) +{ + struct sk_buff_head agg; + struct ar9170_sta_tid *tid_info = NULL, *tmp; + struct sk_buff *skb, *first = NULL; + unsigned long flags, f2; + unsigned int i = 0; + u16 seq, queue, tmpssn; + bool run = false; + + skb_queue_head_init(&agg); + + spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); + if (list_empty(&ar->tx_ampdu_list)) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: aggregation list is empty.\n", + wiphy_name(ar->hw->wiphy)); +#endif /* AR9170_TXAGG_DEBUG */ + goto out_unlock; + } + + list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) { + if (tid_info->state != AR9170_TID_STATE_COMPLETE) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: dangling aggregation entry!\n", + wiphy_name(ar->hw->wiphy)); +#endif /* AR9170_TXAGG_DEBUG */ + continue; + } + + if (++i > 64) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: enough frames aggregated.\n", + wiphy_name(ar->hw->wiphy)); +#endif /* AR9170_TXAGG_DEBUG */ + break; + } + + queue = TID_TO_WME_AC(tid_info->tid); + + if (skb_queue_len(&ar->tx_pending[queue]) >= + AR9170_NUM_TX_AGG_MAX) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: queue %d full.\n", + wiphy_name(ar->hw->wiphy), queue); +#endif /* AR9170_TXAGG_DEBUG */ + continue; + } + + list_del_init(&tid_info->list); + + spin_lock_irqsave(&tid_info->queue.lock, f2); + tmpssn = seq = tid_info->ssn; + first = skb_peek(&tid_info->queue); + + if (likely(first)) + tmpssn = ar9170_get_seq(first); + + if (unlikely(tmpssn != seq)) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.", + wiphy_name(ar->hw->wiphy), seq, tmpssn); +#endif /* AR9170_TXAGG_DEBUG */ + tid_info->ssn = tmpssn; + } + +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with " + "%d queued frames.\n", wiphy_name(ar->hw->wiphy), + tid_info->tid, tid_info->ssn, + skb_queue_len(&tid_info->queue)); + __ar9170_dump_txqueue(ar, &tid_info->queue); +#endif /* AR9170_TXAGG_DEBUG */ + + while ((skb = skb_peek(&tid_info->queue))) { + if (unlikely(ar9170_get_seq(skb) != seq)) + break; + + __skb_unlink(skb, &tid_info->queue); + tid_info->ssn = seq = GET_NEXT_SEQ(seq); + + if (unlikely(skb_get_queue_mapping(skb) != queue)) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d " + "!match.\n", wiphy_name(ar->hw->wiphy), + tid_info->tid, + TID_TO_WME_AC(tid_info->tid), + skb_get_queue_mapping(skb)); +#endif /* AR9170_TXAGG_DEBUG */ + dev_kfree_skb_any(skb); + continue; + } + + if (unlikely(first == skb)) { + ar9170_tx_prepare_phy(ar, skb); + __skb_queue_tail(&agg, skb); + first = skb; + } else { + ar9170_tx_copy_phy(ar, skb, first); + __skb_queue_tail(&agg, skb); + } + + if (unlikely(skb_queue_len(&agg) == + AR9170_NUM_TX_AGG_MAX)) + break; + } + + if (skb_queue_empty(&tid_info->queue)) + tid_info->active = false; + else + list_add_tail(&tid_info->list, + &ar->tx_ampdu_list); + + spin_unlock_irqrestore(&tid_info->queue.lock, f2); + + if (unlikely(skb_queue_empty(&agg))) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: queued empty list!\n", + wiphy_name(ar->hw->wiphy)); +#endif /* AR9170_TXAGG_DEBUG */ + continue; + } + + /* + * tell the FW/HW that this is the last frame, + * that way it will wait for the immediate block ack. + */ + if (likely(skb_peek_tail(&agg))) + ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); + +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", + wiphy_name(ar->hw->wiphy)); + __ar9170_dump_txqueue(ar, &agg); +#endif /* AR9170_TXAGG_DEBUG */ + + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); + + spin_lock_irqsave(&ar->tx_pending[queue].lock, flags); + skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); + spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags); + run = true; + + spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); + } + +out_unlock: + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); + __skb_queue_purge(&agg); + + return run; +} + static void ar9170_tx(struct ar9170 *ar) { struct sk_buff *skb; @@ -1384,11 +1720,17 @@ static void ar9170_tx(struct ar9170 *ar) printk(KERN_DEBUG "%s: queue %d full\n", wiphy_name(ar->hw->wiphy), i); - __ar9170_dump_txstats(ar); - printk(KERN_DEBUG "stuck frames: ===> \n"); + printk(KERN_DEBUG "%s: stuck frames: ===> \n", + wiphy_name(ar->hw->wiphy)); ar9170_dump_txqueue(ar, &ar->tx_pending[i]); ar9170_dump_txqueue(ar, &ar->tx_status[i]); #endif /* AR9170_QUEUE_DEBUG */ + +#ifdef AR9170_QUEUE_STOP_DEBUG + printk(KERN_DEBUG "%s: stop queue %d\n", + wiphy_name(ar->hw->wiphy), i); + __ar9170_dump_txstats(ar); +#endif /* AR9170_QUEUE_STOP_DEBUG */ ieee80211_stop_queue(ar->hw, i); spin_unlock_irqrestore(&ar->tx_stats_lock, flags); continue; @@ -1403,8 +1745,6 @@ static void ar9170_tx(struct ar9170 *ar) "remaining slots:%d, needed:%d\n", wiphy_name(ar->hw->wiphy), i, remaining_space, frames); - - ar9170_dump_txstats(ar); #endif /* AR9170_QUEUE_DEBUG */ frames = remaining_space; } @@ -1432,6 +1772,9 @@ static void ar9170_tx(struct ar9170 *ar) arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_TX_TIMEOUT); + if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) + ar->tx_ampdu_pending++; + #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: send frame q:%d =>\n", wiphy_name(ar->hw->wiphy), i); @@ -1440,6 +1783,9 @@ static void ar9170_tx(struct ar9170 *ar) err = ar->tx(ar, skb); if (unlikely(err)) { + if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) + ar->tx_ampdu_pending--; + frames_failed++; dev_kfree_skb_any(skb); } else { @@ -1461,13 +1807,18 @@ static void ar9170_tx(struct ar9170 *ar) if (unlikely(frames_failed)) { #ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: frames failed =>\n", + printk(KERN_DEBUG "%s: frames failed %d =>\n", wiphy_name(ar->hw->wiphy), frames_failed); #endif /* AR9170_QUEUE_DEBUG */ spin_lock_irqsave(&ar->tx_stats_lock, flags); ar->tx_stats[i].len -= frames_failed; ar->tx_stats[i].count -= frames_failed; +#ifdef AR9170_QUEUE_STOP_DEBUG + printk(KERN_DEBUG "%s: wake queue %d\n", + wiphy_name(ar->hw->wiphy), i); + __ar9170_dump_txstats(ar); +#endif /* AR9170_QUEUE_STOP_DEBUG */ ieee80211_wake_queue(ar->hw, i); spin_unlock_irqrestore(&ar->tx_stats_lock, flags); } @@ -1479,6 +1830,90 @@ static void ar9170_tx(struct ar9170 *ar) msecs_to_jiffies(AR9170_JANITOR_DELAY)); } +static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ieee80211_tx_info *txinfo; + struct ar9170_sta_info *sta_info; + struct ar9170_sta_tid *agg; + struct sk_buff *iter; + unsigned long flags, f2; + unsigned int max; + u16 tid, seq, qseq; + bool run = false, queue = false; + + tid = ar9170_get_tid(skb); + seq = ar9170_get_seq(skb); + txinfo = IEEE80211_SKB_CB(skb); + sta_info = (void *) txinfo->control.sta->drv_priv; + agg = &sta_info->agg[tid]; + max = sta_info->ampdu_max_len; + + spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); + + if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: BlockACK session not fully initialized " + "for ESS:%pM tid:%d state:%d.\n", + wiphy_name(ar->hw->wiphy), agg->addr, agg->tid, + agg->state); +#endif /* AR9170_TXAGG_DEBUG */ + goto err_unlock; + } + + if (!agg->active) { + agg->active = true; + agg->ssn = seq; + queue = true; + } + + /* check if seq is within the BA window */ + if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) { +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not " + "fit into BA window (%d - %d)\n", + wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn, + (agg->ssn + max) & 0xfff); +#endif /* AR9170_TXAGG_DEBUG */ + goto err_unlock; + } + + spin_lock_irqsave(&agg->queue.lock, f2); + + skb_queue_reverse_walk(&agg->queue, iter) { + qseq = ar9170_get_seq(iter); + + if (GET_NEXT_SEQ(qseq) == seq) { + __skb_queue_after(&agg->queue, iter, skb); + goto queued; + } + } + + __skb_queue_head(&agg->queue, skb); + +queued: + spin_unlock_irqrestore(&agg->queue.lock, f2); + +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_DEBUG "%s: new aggregate %p queued.\n", + wiphy_name(ar->hw->wiphy), skb); + __ar9170_dump_txqueue(ar, &agg->queue); +#endif /* AR9170_TXAGG_DEBUG */ + + if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX) + run = true; + + if (queue) + list_add_tail(&agg->list, &ar->tx_ampdu_list); + + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); + return run; + +err_unlock: + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); + dev_kfree_skb_irq(skb); + return false; +} + int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ar9170 *ar = hw->priv; @@ -1492,8 +1927,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) info = IEEE80211_SKB_CB(skb); if (info->flags & IEEE80211_TX_CTL_AMPDU) { - /* drop frame, we do not allow TX A-MPDU aggregation yet. */ - goto err_free; + bool run = ar9170_tx_ampdu_queue(ar, skb); + + if (run || !ar->tx_ampdu_pending) + ar9170_tx_ampdu(ar); } else { unsigned int queue = skb_get_queue_mapping(skb); @@ -1931,6 +2368,53 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { + struct ar9170 *ar = hw->priv; + struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; + unsigned int i; + + switch (cmd) { + case STA_NOTIFY_ADD: + memset(sta_info, 0, sizeof(*sta_info)); + + if (!sta->ht_cap.ht_supported) + break; + + if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) + ar->global_ampdu_density = sta->ht_cap.ampdu_density; + + if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) + ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; + + for (i = 0; i < AR9170_NUM_TID; i++) { + sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; + sta_info->agg[i].active = false; + sta_info->agg[i].ssn = 0; + sta_info->agg[i].retry = 0; + sta_info->agg[i].tid = i; + INIT_LIST_HEAD(&sta_info->agg[i].list); + skb_queue_head_init(&sta_info->agg[i].queue); + } + + sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); + break; + + case STA_NOTIFY_REMOVE: + if (!sta->ht_cap.ht_supported) + break; + + for (i = 0; i < AR9170_NUM_TID; i++) { + sta_info->agg[i].state = AR9170_TID_STATE_INVALID; + skb_queue_purge(&sta_info->agg[i].queue); + } + + break; + + default: + break; + } + + if (IS_STARTED(ar) && ar->filter_changed) + queue_work(ar->hw->workqueue, &ar->filter_config_work); } static int ar9170_get_stats(struct ieee80211_hw *hw, @@ -1985,18 +2469,65 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { + struct ar9170 *ar = hw->priv; + struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; + struct ar9170_sta_tid *tid_info = &sta_info->agg[tid]; + unsigned long flags; + + if (!modparam_ht) + return -EOPNOTSUPP; + switch (action) { + case IEEE80211_AMPDU_TX_START: + spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); + if (tid_info->state != AR9170_TID_STATE_SHUTDOWN || + !list_empty(&tid_info->list)) { + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] " + "is in a very bad state!\n", + wiphy_name(hw->wiphy), sta->addr, tid); +#endif /* AR9170_TXAGG_DEBUG */ + return -EBUSY; + } + + *ssn = tid_info->ssn; + tid_info->state = AR9170_TID_STATE_PROGRESS; + tid_info->active = false; + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); + ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); + break; + + case IEEE80211_AMPDU_TX_STOP: + spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); + tid_info->state = AR9170_TID_STATE_SHUTDOWN; + list_del_init(&tid_info->list); + tid_info->active = false; + skb_queue_purge(&tid_info->queue); + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); + ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); + break; + + case IEEE80211_AMPDU_TX_OPERATIONAL: +#ifdef AR9170_TXAGG_DEBUG + printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n", + wiphy_name(hw->wiphy), sta->addr, tid); +#endif /* AR9170_TXAGG_DEBUG */ + spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); + sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE; + spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); + break; + case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_STOP: - /* - * Something goes wrong -- RX locks up - * after a while of receiving aggregated - * frames -- not enabling for now. - */ - return -EOPNOTSUPP; + /* Handled by firmware */ + break; + default: return -EOPNOTSUPP; } + + return 0; } static const struct ieee80211_ops ar9170_ops = { @@ -2045,6 +2576,8 @@ void *ar9170_alloc(size_t priv_size) mutex_init(&ar->mutex); spin_lock_init(&ar->cmdlock); spin_lock_init(&ar->tx_stats_lock); + spin_lock_init(&ar->tx_ampdu_list_lock); + skb_queue_head_init(&ar->tx_status_ampdu); for (i = 0; i < __AR9170_NUM_TXQ; i++) { skb_queue_head_init(&ar->tx_status[i]); skb_queue_head_init(&ar->tx_pending[i]); @@ -2053,6 +2586,7 @@ void *ar9170_alloc(size_t priv_size) INIT_WORK(&ar->filter_config_work, ar9170_set_filters); INIT_WORK(&ar->beacon_work, ar9170_new_beacon); INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); + INIT_LIST_HEAD(&ar->tx_ampdu_list); /* all hw supports 2.4 GHz, so set channel to 1 by default */ ar->channel = &ar9170_2ghz_chantable[0]; @@ -2066,6 +2600,13 @@ void *ar9170_alloc(size_t priv_size) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + if (modparam_ht) { + ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; + } else { + ar9170_band_2GHz.ht_cap.ht_supported = false; + ar9170_band_5GHz.ht_cap.ht_supported = false; + } + ar->hw->queues = __AR9170_NUM_TXQ; ar->hw->extra_tx_headroom = 8; ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); @@ -2091,6 +2632,7 @@ static int ar9170_read_eeprom(struct ar9170 *ar) u8 *eeprom = (void *)&ar->eeprom; u8 *addr = ar->eeprom.mac_address; __le32 offsets[RW]; + unsigned int rx_streams, tx_streams, tx_params = 0; int i, j, err, bands = 0; BUILD_BUG_ON(sizeof(ar->eeprom) & 3); @@ -2127,6 +2669,20 @@ static int ar9170_read_eeprom(struct ar9170 *ar) ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; bands++; } + + rx_streams = hweight8(ar->eeprom.rx_mask); + tx_streams = hweight8(ar->eeprom.tx_mask); + + if (rx_streams != tx_streams) + tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; + + if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) + tx_params = (tx_streams - 1) << + IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; + + ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; + ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; + /* * I measured this, a bandswitch takes roughly * 135 ms and a frequency switch about 80. -- cgit v1.2.2 From 4b9631a4734e25e37c83e72c3e0ffcbb08de5791 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 11 Jul 2009 18:00:19 +0200 Subject: rt2x00: Remove DEVICE_STATE_DISABLED_RADIO_HW The DEVICE_STATE_DISABLED_RADIO_HW flag is only read but never set, it is an ancient part of one of the many versions of the rfkill implementations in rt2x00. It is about time is disappears. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 1 - drivers/net/wireless/rt2x00/rt2x00dev.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 3e177175e34b..4c76c8d93cb5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -594,7 +594,6 @@ enum rt2x00_flags { DEVICE_STATE_INITIALIZED, DEVICE_STATE_STARTED, DEVICE_STATE_ENABLED_RADIO, - DEVICE_STATE_DISABLED_RADIO_HW, /* * Driver requirements diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 4fff3a83f7df..658a63bfb761 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -40,8 +40,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) * Don't enable the radio twice. * And check if the hardware button has been disabled. */ - if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || - test_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags)) + if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return 0; /* -- cgit v1.2.2 From ec96cfd8215af1cda016837efb266409164e3a30 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 12 Jul 2009 22:05:33 +0200 Subject: drivers/net: Drop unnecessary NULL test The result of container_of should not be NULL. In particular, in this case the argument to the enclosing function has passed though INIT_WORK, which dereferences it, implying that its container cannot be NULL. A simplified version of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ identifier fn,work,x,fld; type T; expression E1,E2; statement S; @@ static fn(struct work_struct *work) { ... when != work = E1 x = container_of(work,T,fld) ... when != x = E2 - if (x == NULL) S ... } // Signed-off-by: Julia Lawall Acked-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index d726b3c6077a..2dc1cdbb4939 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -7250,9 +7250,6 @@ static void ipw_bg_qos_activate(struct work_struct *work) struct ipw_priv *priv = container_of(work, struct ipw_priv, qos_activate); - if (priv == NULL) - return; - mutex_lock(&priv->mutex); if (priv->status & STATUS_ASSOCIATED) -- cgit v1.2.2 From 8f75e07aa14107668d33f60fa4d78afa2d7aa22b Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Mon, 13 Jul 2009 23:20:37 +0100 Subject: zd1211rw: adding Accton Technology Corp (083a:e501) as a ZD1211B device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New device supported by the zd1211rw driver reported to linux-wireless. Device string from lsusb: "ID 083a:e501 Accton Technology Corp. ZD1211B" RF type from dmesg: zd1211b chip 083a:e501 v4810 high 00-1a-2a AL2230_RF pa0 g--NS Signed-off-by: Hin-Tak Leung Tested-by: Adrián Cereto Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 07d7ab674a0f..38688847d568 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -76,6 +76,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x083a, 0xe501), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, -- cgit v1.2.2 From 256fc96028f0eae5f7a3f6f77358cdd30a72c988 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 14 Jul 2009 00:05:56 +0100 Subject: rtl8187: updating Kconfig with info of branded devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding more detailed info about Asus motherboards and Ralink devices. Signed-off-by: Hin-Tak Leung Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7d5902d1349a..ca7a8a31d0b9 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -428,10 +428,12 @@ config RTL8187 Micronet SP907GK V5 Encore ENUWI-G2 Trendnet TEW-424UB - ASUS P5B Deluxe + ASUS P5B Deluxe/P5K Premium motherboards Toshiba Satellite Pro series of laptops Asus Wireless Link Linksys WUSB54GC-EU v2 + (v1 = rt73usb; v3 is rt2070-based, + use staging/rt3070 or try rt2800usb) Thanks to Realtek for their support! -- cgit v1.2.2 From a94ca4e7af0e6b63ef5345750fad8e1400274ba4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 14 Jul 2009 15:48:11 +0200 Subject: iwlwifi: make some logging functions static/unexport iwl_dump_nic_error_log can be static and iwl_dump_nic_event_log doesn't need to be exported. Signed-off-by: Johannes Berg Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 367 ++++++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 2 files changed, 182 insertions(+), 186 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d5cd9a20edca..b82480a51782 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1290,6 +1290,188 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) } #endif +static const char *desc_lookup_text[] = { + "OK", + "FAIL", + "BAD_PARAM", + "BAD_CHECKSUM", + "NMI_INTERRUPT_WDG", + "SYSASSERT", + "FATAL_ERROR", + "BAD_COMMAND", + "HW_ERROR_TUNE_LOCK", + "HW_ERROR_TEMPERATURE", + "ILLEGAL_CHAN_FREQ", + "VCC_NOT_STABLE", + "FH_ERROR", + "NMI_INTERRUPT_HOST", + "NMI_INTERRUPT_ACTION_PT", + "NMI_INTERRUPT_UNKNOWN", + "UCODE_VERSION_MISMATCH", + "HW_ERROR_ABS_LOCK", + "HW_ERROR_CAL_LOCK_FAIL", + "NMI_INTERRUPT_INST_ACTION_PT", + "NMI_INTERRUPT_DATA_ACTION_PT", + "NMI_TRM_HW_ER", + "NMI_INTERRUPT_TRM", + "NMI_INTERRUPT_BREAK_POINT" + "DEBUG_0", + "DEBUG_1", + "DEBUG_2", + "DEBUG_3", + "UNKNOWN" +}; + +static const char *desc_lookup(int i) +{ + int max = ARRAY_SIZE(desc_lookup_text) - 1; + + if (i < 0 || i > max) + i = max; + + return desc_lookup_text[i]; +} + +#define ERROR_START_OFFSET (1 * sizeof(u32)) +#define ERROR_ELEM_SIZE (7 * sizeof(u32)) + +static void iwl_dump_nic_error_log(struct iwl_priv *priv) +{ + u32 data2, line; + u32 desc, time, count, base, data1; + u32 blink1, blink2, ilink1, ilink2; + + if (priv->ucode_type == UCODE_INIT) + base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); + else + base = le32_to_cpu(priv->card_alive.error_event_table_ptr); + + if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); + return; + } + + count = iwl_read_targ_mem(priv, base); + + if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { + IWL_ERR(priv, "Start IWL Error Log Dump:\n"); + IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", + priv->status, count); + } + + desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); + blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); + blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); + ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); + ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); + data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); + data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); + line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); + time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); + + IWL_ERR(priv, "Desc Time " + "data1 data2 line\n"); + IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", + desc_lookup(desc), desc, time, data1, data2, line); + IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); + IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, + ilink1, ilink2); + +} + +#define EVENT_START_OFFSET (4 * sizeof(u32)) + +/** + * iwl_print_event_log - Dump error event log to syslog + * + */ +static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, + u32 num_events, u32 mode) +{ + u32 i; + u32 base; /* SRAM byte address of event log header */ + u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ + u32 ptr; /* SRAM byte address of log data */ + u32 ev, time, data; /* event log data */ + + if (num_events == 0) + return; + if (priv->ucode_type == UCODE_INIT) + base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); + else + base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + + if (mode == 0) + event_size = 2 * sizeof(u32); + else + event_size = 3 * sizeof(u32); + + ptr = base + EVENT_START_OFFSET + (start_idx * event_size); + + /* "time" is actually "data" for mode 0 (no timestamp). + * place event id # at far right for easier visual parsing. */ + for (i = 0; i < num_events; i++) { + ev = iwl_read_targ_mem(priv, ptr); + ptr += sizeof(u32); + time = iwl_read_targ_mem(priv, ptr); + ptr += sizeof(u32); + if (mode == 0) { + /* data, ev */ + IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); + } else { + data = iwl_read_targ_mem(priv, ptr); + ptr += sizeof(u32); + IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + } + } +} + +void iwl_dump_nic_event_log(struct iwl_priv *priv) +{ + u32 base; /* SRAM byte address of event log header */ + u32 capacity; /* event log capacity in # entries */ + u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ + u32 num_wraps; /* # times uCode wrapped to top of log */ + u32 next_entry; /* index of next entry to be written by uCode */ + u32 size; /* # entries that we'll print */ + + if (priv->ucode_type == UCODE_INIT) + base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); + else + base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + + if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); + return; + } + + /* event log header */ + capacity = iwl_read_targ_mem(priv, base); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); + + size = num_wraps ? capacity : next_entry; + + /* bail out if nothing in log */ + if (size == 0) { + IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); + return; + } + + IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", + size, num_wraps); + + /* if uCode has wrapped back to top of log, start at the oldest entry, + * i.e the next one that uCode would fill. */ + if (num_wraps) + iwl_print_event_log(priv, next_entry, + capacity - next_entry, mode); + /* (then/else) start at top of log */ + iwl_print_event_log(priv, 0, next_entry, mode); + +} /** * iwl_irq_handle_error - called for HW or SW error interrupt from card */ @@ -2040,191 +2222,6 @@ int iwl_verify_ucode(struct iwl_priv *priv) EXPORT_SYMBOL(iwl_verify_ucode); -static const char *desc_lookup_text[] = { - "OK", - "FAIL", - "BAD_PARAM", - "BAD_CHECKSUM", - "NMI_INTERRUPT_WDG", - "SYSASSERT", - "FATAL_ERROR", - "BAD_COMMAND", - "HW_ERROR_TUNE_LOCK", - "HW_ERROR_TEMPERATURE", - "ILLEGAL_CHAN_FREQ", - "VCC_NOT_STABLE", - "FH_ERROR", - "NMI_INTERRUPT_HOST", - "NMI_INTERRUPT_ACTION_PT", - "NMI_INTERRUPT_UNKNOWN", - "UCODE_VERSION_MISMATCH", - "HW_ERROR_ABS_LOCK", - "HW_ERROR_CAL_LOCK_FAIL", - "NMI_INTERRUPT_INST_ACTION_PT", - "NMI_INTERRUPT_DATA_ACTION_PT", - "NMI_TRM_HW_ER", - "NMI_INTERRUPT_TRM", - "NMI_INTERRUPT_BREAK_POINT" - "DEBUG_0", - "DEBUG_1", - "DEBUG_2", - "DEBUG_3", - "UNKNOWN" -}; - -static const char *desc_lookup(int i) -{ - int max = ARRAY_SIZE(desc_lookup_text) - 1; - - if (i < 0 || i > max) - i = max; - - return desc_lookup_text[i]; -} - -#define ERROR_START_OFFSET (1 * sizeof(u32)) -#define ERROR_ELEM_SIZE (7 * sizeof(u32)) - -void iwl_dump_nic_error_log(struct iwl_priv *priv) -{ - u32 data2, line; - u32 desc, time, count, base, data1; - u32 blink1, blink2, ilink1, ilink2; - - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); - else - base = le32_to_cpu(priv->card_alive.error_event_table_ptr); - - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); - return; - } - - count = iwl_read_targ_mem(priv, base); - - if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { - IWL_ERR(priv, "Start IWL Error Log Dump:\n"); - IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->status, count); - } - - desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); - blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); - blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); - ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); - ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); - data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); - data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); - line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); - time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); - - IWL_ERR(priv, "Desc Time " - "data1 data2 line\n"); - IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", - desc_lookup(desc), desc, time, data1, data2, line); - IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); - IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, - ilink1, ilink2); - -} -EXPORT_SYMBOL(iwl_dump_nic_error_log); - -#define EVENT_START_OFFSET (4 * sizeof(u32)) - -/** - * iwl_print_event_log - Dump error event log to syslog - * - */ -static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, - u32 num_events, u32 mode) -{ - u32 i; - u32 base; /* SRAM byte address of event log header */ - u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ - u32 ptr; /* SRAM byte address of log data */ - u32 ev, time, data; /* event log data */ - - if (num_events == 0) - return; - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - - if (mode == 0) - event_size = 2 * sizeof(u32); - else - event_size = 3 * sizeof(u32); - - ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - - /* "time" is actually "data" for mode 0 (no timestamp). - * place event id # at far right for easier visual parsing. */ - for (i = 0; i < num_events; i++) { - ev = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - time = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - if (mode == 0) { - /* data, ev */ - IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); - } else { - data = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - } - } -} - -void iwl_dump_nic_event_log(struct iwl_priv *priv) -{ - u32 base; /* SRAM byte address of event log header */ - u32 capacity; /* event log capacity in # entries */ - u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ - u32 num_wraps; /* # times uCode wrapped to top of log */ - u32 next_entry; /* index of next entry to be written by uCode */ - u32 size; /* # entries that we'll print */ - - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); - return; - } - - /* event log header */ - capacity = iwl_read_targ_mem(priv, base); - mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - - size = num_wraps ? capacity : next_entry; - - /* bail out if nothing in log */ - if (size == 0) { - IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - return; - } - - IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", - size, num_wraps); - - /* if uCode has wrapped back to top of log, start at the oldest entry, - * i.e the next one that uCode would fill. */ - if (num_wraps) - iwl_print_event_log(priv, next_entry, - capacity - next_entry, mode); - /* (then/else) start at top of log */ - iwl_print_event_log(priv, 0, next_entry, mode); - -} -EXPORT_SYMBOL(iwl_dump_nic_event_log); - void iwl_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl_ct_kill_config cmd; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a658410e66a4..640c4644a165 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -472,7 +472,6 @@ int iwl_pci_resume(struct pci_dev *pdev); /***************************************************** * Error Handling Debugging ******************************************************/ -void iwl_dump_nic_error_log(struct iwl_priv *priv); void iwl_dump_nic_event_log(struct iwl_priv *priv); void iwl_clear_isr_stats(struct iwl_priv *priv); -- cgit v1.2.2 From fe643414dbf330d6d910e01edd48dd93dc6f2942 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 14 Jul 2009 22:37:13 +0200 Subject: wireless: wl12xx, fix lock imbalance Add omitted mutex_unlock to one of wl12xx_op_start fail paths (when wl12xx_chip_wakeup fails). [v2] Power off the device, because: \= cite from http://marc.info/?l=linux-kernel&m=124755028209880&w=2 If the chip cannot be booted, why should it remain powered on? In some rare cases, the chip might fail to initialize, but can recover if powered off and on again, so turning it off at this point is the right thing to do. =/ Signed-off-by: Jiri Slaby Reviewed-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index cf5e0549fa14..106b0f265192 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -349,7 +349,7 @@ static int wl1251_op_start(struct ieee80211_hw *hw) ret = wl1251_chip_wakeup(wl); if (ret < 0) - return ret; + goto out; ret = wl->chip.op_boot(wl); if (ret < 0) -- cgit v1.2.2 From e43419f9ad99112a2715ee34c634ffeac3bf730d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:13:54 -0400 Subject: ath9k: downgrade assert in rc.c for invalid rate The case where no vaid rate is found should not happen now but to help debugging and downgrade this to a warn. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ba06e78b2f50..d7f403080f7a 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -741,10 +741,18 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, if (rate > (ath_rc_priv->rate_table_size - 1)) rate = ath_rc_priv->rate_table_size - 1; - ASSERT((rate_table->info[rate].valid && - (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) || - (rate_table->info[rate].valid_single_stream && - !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))); + if (rate_table->info[rate].valid && + (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) + return rate; + + if (rate_table->info[rate].valid_single_stream && + !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)); + return rate; + + /* This should not happen */ + WARN_ON(1); + + rate = ath_rc_priv->valid_rate_index[0]; return rate; } -- cgit v1.2.2 From 0ab216d9727c0728c8b5f9ad627b6955570303d7 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:13:55 -0400 Subject: iwlwifi: remove rs_get_rate workaround This removes the work around implemented for transmitting on an unsupported band on iwlwifi. This was added via the patch: 8e1856e82cb8f541e925738bebfbc473420cda68: iwlwifi: fix rs_get_rate WARN_ON() Cc: Mohamed Abbas Cc: Reinette Chatre Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 12 ++---------- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 11 +---------- 2 files changed, 3 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 5eb538d18a80..b23fd537f21f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -674,28 +674,20 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, unsigned long flags; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u16 fc; - u16 rate_mask = 0; + u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; s8 max_rate_idx = -1; struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE(priv, "enter\n"); - if (sta) - rate_mask = sta->supp_rates[sband->band]; - /* Send management frames and NO_ACK data using lowest rate. */ fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !priv_sta) { IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); - if (!rate_mask) - info->control.rates[0].idx = - rate_lowest_index(sband, NULL); - else - info->control.rates[0].idx = - rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); if (info->flags & IEEE80211_TX_CTL_NO_ACK) info->control.rates[0].count = 1; return; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index ff20e5048a55..3fea027f35d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2466,7 +2466,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; int rate_idx; - u64 mask_bit = 0; IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n"); @@ -2481,18 +2480,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, lq_sta->max_rate_idx = -1; } - if (sta) - mask_bit = sta->supp_rates[sband->band]; - /* Send management frames and NO_ACK data using lowest rate. */ if (!ieee80211_is_data(hdr->frame_control) || info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !lq_sta) { - if (!mask_bit) - info->control.rates[0].idx = - rate_lowest_index(sband, NULL); - else - info->control.rates[0].idx = - rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); if (info->flags & IEEE80211_TX_CTL_NO_ACK) info->control.rates[0].count = 1; return; -- cgit v1.2.2 From dd1901830ca7baaaae2e58f549f770f215c6f3af Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:13:56 -0400 Subject: ath9k: cleanup try count for MRR in rate control This has no functional change and just cleans up the code to be more legible and removes a useless variable for Multi Rate Retry. For regular frames we use 2 retries for MRR segments [0-2]. For the last MRR segment [3] we use 4. MRR[0] = 2 MRR[1] = 2 MRR[2] = 2 MRR[3] = 4 Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/main.c | 3 ++- drivers/net/wireless/ath/ath9k/rc.c | 29 ++++++++++++++++++++--------- 3 files changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index eb9d5228cb6c..3afd7ee41a63 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -164,7 +164,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, #define WME_NUM_TID 16 #define ATH_TXBUF 512 #define ATH_TXMAXTRY 13 -#define ATH_11N_TXMAXTRY 10 #define ATH_MGT_TXMAXTRY 4 #define WME_BA_BMP_SIZE 64 #define WME_MAX_BA WME_BA_BMP_SIZE diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 961b0ce6ef3e..19df7882d0d3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1540,7 +1540,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->max_rates = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 10; - hw->max_rate_tries = ATH_11N_TXMAXTRY; + /* Hardware supports 10 but we use 4 */ + hw->max_rate_tries = 4; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index d7f403080f7a..a23b66bdbe92 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -853,9 +853,21 @@ static void ath_rc_ratefind(struct ath_softc *sc, struct ieee80211_tx_rate *rates = tx_info->control.rates; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc = hdr->frame_control; - u8 try_per_rate = 0, i = 0, rix, nrix; + u8 try_per_rate, i = 0, rix, nrix; int is_probe = 0; + /* + * For Multi Rate Retry we use a different number of + * retry attempt counts. This ends up looking like this: + * + * MRR[0] = 2 + * MRR[1] = 2 + * MRR[2] = 2 + * MRR[3] = 4 + * + */ + try_per_rate = sc->hw->max_rate_tries; + rate_table = sc->cur_rate_table; rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe); nrix = rix; @@ -866,7 +878,6 @@ static void ath_rc_ratefind(struct ath_softc *sc, ath_rc_rate_set_series(rate_table, &rates[i++], txrc, 1, nrix, 0); - try_per_rate = (ATH_11N_TXMAXTRY/4); /* Get the next tried/allowed rate. No RTS for the next series * after the probe rate */ @@ -877,7 +888,6 @@ static void ath_rc_ratefind(struct ath_softc *sc, tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; } else { - try_per_rate = (ATH_11N_TXMAXTRY/4); /* Set the choosen rate. No RTS for first series entry. */ ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); @@ -885,18 +895,19 @@ static void ath_rc_ratefind(struct ath_softc *sc, /* Fill in the other rates for multirate retry */ for ( ; i < 4; i++) { - u8 try_num; u8 min_rate; - try_num = ((i + 1) == 4) ? - ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ; + /* Use twice the number of tries for the last MRR segment. */ + if (i + 1 == 4) + try_per_rate = 4; + min_rate = (((i + 1) == 4) && 0); nrix = ath_rc_rate_getidx(sc, ath_rc_priv, rate_table, nrix, 1, min_rate); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, - try_num, nrix, 1); + try_per_rate, nrix, 1); } /* @@ -1529,7 +1540,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, /* * If underrun error is seen assume it as an excessive retry only * if prefetch trigger level have reached the max (0x3f for 5416) - * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY + * Adjust the long retry as if the frame was tried hw->max_rate_tries * times. This affects how ratectrl updates PER for the failed rate. */ if (tx_info_priv->tx.ts_flags & @@ -1544,7 +1555,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, tx_status = 1; ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, - (is_underrun) ? ATH_11N_TXMAXTRY : + (is_underrun) ? sc->hw->max_rate_tries : tx_info_priv->tx.ts_longretry); /* Check if aggregation has to be enabled for this tid */ -- cgit v1.2.2 From 984d021d56f036e5ffbef191cb5e498cf159784d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:13:57 -0400 Subject: ath9k: remove unused min rate calculation code This is not used, and when we need to get the lowest rate we should simply use mac80211's own rate_lowest_index(sband, sta). Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a23b66bdbe92..7b37b2798dfc 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -817,28 +817,17 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, static u8 ath_rc_rate_getidx(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, const struct ath_rate_table *rate_table, - u8 rix, u16 stepdown, - u16 min_rate) + u8 rix, u16 stepdown) { u32 j; u8 nextindex = 0; - if (min_rate) { - for (j = RATE_TABLE_SIZE; j > 0; j--) { - if (ath_rc_get_nextlowervalid_txrate(rate_table, - ath_rc_priv, rix, &nextindex)) - rix = nextindex; - else - break; - } - } else { - for (j = stepdown; j > 0; j--) { - if (ath_rc_get_nextlowervalid_txrate(rate_table, - ath_rc_priv, rix, &nextindex)) - rix = nextindex; - else - break; - } + for (j = stepdown; j > 0; j--) { + if (ath_rc_get_nextlowervalid_txrate(rate_table, + ath_rc_priv, rix, &nextindex)) + rix = nextindex; + else + break; } return rix; } @@ -882,7 +871,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, * after the probe rate */ nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix, 1, 0); + rate_table, nrix, 1); ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); @@ -895,16 +884,12 @@ static void ath_rc_ratefind(struct ath_softc *sc, /* Fill in the other rates for multirate retry */ for ( ; i < 4; i++) { - u8 min_rate; - /* Use twice the number of tries for the last MRR segment. */ if (i + 1 == 4) try_per_rate = 4; - min_rate = (((i + 1) == 4) && 0); - nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix, 1, min_rate); + rate_table, nrix, 1); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, try_per_rate, nrix, 1); -- cgit v1.2.2 From 7466c524a42110e921e79b390b58bfc6ca6d249e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:13:58 -0400 Subject: ath9k: remove unused stepdown when looking for the next rate This is not used, remove this. Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 7b37b2798dfc..64cb697805b8 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -817,19 +817,14 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, static u8 ath_rc_rate_getidx(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, const struct ath_rate_table *rate_table, - u8 rix, u16 stepdown) + u8 rix) { - u32 j; u8 nextindex = 0; - - for (j = stepdown; j > 0; j--) { - if (ath_rc_get_nextlowervalid_txrate(rate_table, - ath_rc_priv, rix, &nextindex)) - rix = nextindex; - else - break; - } - return rix; + if (ath_rc_get_nextlowervalid_txrate(rate_table, + ath_rc_priv, rix, &nextindex)) + return nextindex; + else + return rix; } static void ath_rc_ratefind(struct ath_softc *sc, @@ -871,7 +866,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, * after the probe rate */ nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix, 1); + rate_table, nrix); ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); @@ -889,7 +884,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, try_per_rate = 4; nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix, 1); + rate_table, nrix); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, try_per_rate, nrix, 1); -- cgit v1.2.2 From 20f57215a2ff75f7c2e4004b7583e1fec925679e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:13:59 -0400 Subject: ath9k: remove pointless wrapper ath_rc_rate_getidx() This is just calling another helper, so just use the other helper directly. This should make it clear that when do not find the next rate we stick to the current one. Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 64cb697805b8..03e7df42675f 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -814,19 +814,6 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, tx_info->control.rts_cts_rate_idx = cix; } -static u8 ath_rc_rate_getidx(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - u8 rix) -{ - u8 nextindex = 0; - if (ath_rc_get_nextlowervalid_txrate(rate_table, - ath_rc_priv, rix, &nextindex)) - return nextindex; - else - return rix; -} - static void ath_rc_ratefind(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_rate_control *txrc) @@ -865,8 +852,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, /* Get the next tried/allowed rate. No RTS for the next series * after the probe rate */ - nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix); + ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, + rix, &nrix); ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); @@ -883,8 +870,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, if (i + 1 == 4) try_per_rate = 4; - nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix); + ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, + rix, &nrix); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, try_per_rate, nrix, 1); -- cgit v1.2.2 From 39448b0a27529f2feecd876729ef0fba25354363 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:00 -0400 Subject: ath9k: rename ath_rc_get_nextlowervalid_txrate() What this does is get us our next lower rate so call it that, ath_rc_get_lower_rix(). Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 03e7df42675f..c8f800e6c299 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -501,9 +501,9 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) } static inline int -ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, u8 *next_idx) +ath_rc_get_lower_rix(const struct ath_rate_table *rate_table, + struct ath_rate_priv *ath_rc_priv, + u8 cur_valid_txrate, u8 *next_idx) { int8_t i; @@ -852,8 +852,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, /* Get the next tried/allowed rate. No RTS for the next series * after the probe rate */ - ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, - rix, &nrix); + ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); ath_rc_rate_set_series(rate_table, &rates[i++], txrc, try_per_rate, nrix, 0); @@ -870,8 +869,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, if (i + 1 == 4) try_per_rate = 4; - ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, - rix, &nrix); + ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, try_per_rate, nrix, 1); @@ -1156,8 +1154,8 @@ static void ath_rc_update_ht(struct ath_softc *sc, if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 && rate_table->info[tx_rate].ratekbps <= rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { - ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, - (u8)tx_rate, &ath_rc_priv->rate_max_phy); + ath_rc_get_lower_rix(rate_table, ath_rc_priv, + (u8)tx_rate, &ath_rc_priv->rate_max_phy); /* Don't probe for a little while. */ ath_rc_priv->probe_time = now_msec; -- cgit v1.2.2 From 4e6df85dacedbc68b551fdd8677f7df68639c181 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:01 -0400 Subject: ath9k: remove unused ath_rc_isvalid_txmask() Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index c8f800e6c299..b0e3702ca06a 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -454,13 +454,6 @@ static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; } -static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv, - u8 index) -{ - ASSERT(index <= ath_rc_priv->rate_table_size); - return ath_rc_priv->valid_rate_index[index]; -} - static inline int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv, -- cgit v1.2.2 From dfe80a3fd2199c31d0a2dc24044abaadb64c26c2 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:02 -0400 Subject: ath9k: remove ATH9K_MODE_11B This saves us 2733 bytes. text data bss dec hex filename 252265 3628 1584 257477 3edc5 ath9k-has-b-rate.ko 249905 3628 1584 255117 3e48d ath9k.ko Cc: Derek Smithies Cc: Chittajit Mitra Siged-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 1 - drivers/net/wireless/ath/ath9k/hw.h | 1 - drivers/net/wireless/ath/ath9k/rc.c | 23 ----------------------- 3 files changed, 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index cffb0789f669..a115c8ceabe3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3305,7 +3305,6 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) } if (eeval & AR5416_OPFLAGS_11G) { - set_bit(ATH9K_MODE_11B, pCap->wireless_modes); set_bit(ATH9K_MODE_11G, pCap->wireless_modes); if (ah->config.ht_enable) { if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9d0b31ad4603..5e40223259c8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -113,7 +113,6 @@ enum wireless_mode { ATH9K_MODE_11A = 0, - ATH9K_MODE_11B = 2, ATH9K_MODE_11G = 3, ATH9K_MODE_11NA_HT20 = 6, ATH9K_MODE_11NG_HT20 = 7, diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index b0e3702ca06a..112a0ec0df4f 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -380,27 +380,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = { 0, /* Phy rates allowed initially */ }; -static const struct ath_rate_table ar5416_11b_ratetable = { - 4, - { - { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0x1b, 0x00, (0x80|2), - 0, 0, 1, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1800, 0x1a, 0x04, (0x80|4), - 1, 1, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4300, 0x19, 0x04, (0x80|11), - 1, 2, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 7100, 0x18, 0x04, (0x80|22), - 1, 4, 100, 3, 0 }, - }, - 100, /* probe interval */ - 100, /* rssi reduce interval */ - 0, /* Phy rates allowed initially */ -}; - static inline int8_t median(int8_t a, int8_t b, int8_t c) { if (a >= b) { @@ -1702,8 +1681,6 @@ static struct rate_control_ops ath_rate_ops = { void ath_rate_attach(struct ath_softc *sc) { - sc->hw_rate_table[ATH9K_MODE_11B] = - &ar5416_11b_ratetable; sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; sc->hw_rate_table[ATH9K_MODE_11G] = -- cgit v1.2.2 From b9b6e15a9481441108ad2527db0187f729c88970 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:03 -0400 Subject: ath9k: remap ATH9K_MODE_* There are a lot of gaps here. Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 5e40223259c8..9a4570d7ecbe 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -113,14 +113,14 @@ enum wireless_mode { ATH9K_MODE_11A = 0, - ATH9K_MODE_11G = 3, - ATH9K_MODE_11NA_HT20 = 6, - ATH9K_MODE_11NG_HT20 = 7, - ATH9K_MODE_11NA_HT40PLUS = 8, - ATH9K_MODE_11NA_HT40MINUS = 9, - ATH9K_MODE_11NG_HT40PLUS = 10, - ATH9K_MODE_11NG_HT40MINUS = 11, - ATH9K_MODE_MAX + ATH9K_MODE_11G, + ATH9K_MODE_11NA_HT20, + ATH9K_MODE_11NG_HT20, + ATH9K_MODE_11NA_HT40PLUS, + ATH9K_MODE_11NA_HT40MINUS, + ATH9K_MODE_11NG_HT40PLUS, + ATH9K_MODE_11NG_HT40MINUS, + ATH9K_MODE_MAX, }; enum ath9k_hw_caps { -- cgit v1.2.2 From 201c3b414b4b759f399502b059189d7802bbfbb6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:04 -0400 Subject: ath9k: rename ath_rc_ratefind_ht() to ath_rc_get_highest_rix() The purpose is to find the highest rate we can use. Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 112a0ec0df4f..96d46d697e96 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -601,10 +601,11 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, return hi; } -static u8 ath_rc_ratefind_ht(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - int *is_probing) +/* Finds the highest rate index we can use */ +static u8 ath_rc_get_highest_rix(struct ath_softc *sc, + struct ath_rate_priv *ath_rc_priv, + const struct ath_rate_table *rate_table, + int *is_probing) { u32 dt, best_thruput, this_thruput, now_msec; u8 rate, next_rate, best_rate, maxindex, minindex; @@ -812,7 +813,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, try_per_rate = sc->hw->max_rate_tries; rate_table = sc->cur_rate_table; - rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe); + rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); nrix = rix; if (is_probe) { -- cgit v1.2.2 From 7682a76df8f4e875e4029d95b799c712ee740ddc Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:05 -0400 Subject: ath9k: remove unnecessary IEEE80211_TX_CTL_NO_ACK checks We check for this condition early on in our mac80211 get_rate() callback ath_get_rate(), so remove this check later down the path. Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 96d46d697e96..2c72901adbee 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -777,7 +777,6 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, * just CTS. Note that this is only done for OFDM/HT unicast frames. */ if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && - !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; @@ -882,9 +881,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, * * FIXME: Fix duration */ - if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && - (ieee80211_has_morefrags(fc) || - (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) { + if (ieee80211_has_morefrags(fc) || + (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { rates[1].count = rates[2].count = rates[3].count = 0; rates[1].idx = rates[2].idx = rates[3].idx = 0; rates[0].count = ATH_TXMAXTRY; -- cgit v1.2.2 From 943ab70f6aebfdc0005ef7e58ae982e9ec22224b Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:07 -0400 Subject: iwlwifi: use ieee80211_is_data(fc) iwl-agn-rs.c already uses this. Cc: Zhu Yi Cc: Reinette Chatre Cc: ipw3945-devel@lists.sourceforge.net Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 7 +++---- drivers/net/wireless/iwlwifi/iwl-sta.c | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index b23fd537f21f..2b776924d5e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -673,7 +673,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, s8 scale_action = 0; unsigned long flags; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc; + __le16 fc; u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; s8 max_rate_idx = -1; struct iwl_priv *priv = (struct iwl_priv *)priv_r; @@ -682,9 +682,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "enter\n"); /* Send management frames and NO_ACK data using lowest rate. */ - fc = le16_to_cpu(hdr->frame_control); - if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - info->flags & IEEE80211_TX_CTL_NO_ACK || + fc = hdr->frame_control; + if (!ieee80211_is_data(fc) || info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !priv_sta) { IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); info->control.rates[0].idx = rate_lowest_index(sband, sta); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 2addf735b193..afa1633602a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1044,11 +1044,10 @@ EXPORT_SYMBOL(iwl_rxon_add_station); int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { int sta_id; - u16 fc = le16_to_cpu(hdr->frame_control); + __le16 fc = hdr->frame_control; /* If this frame is broadcast or management, use broadcast station id */ - if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || - is_multicast_ether_addr(hdr->addr1)) + if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) return priv->hw_params.bcast_sta_id; switch (priv->iw_mode) { -- cgit v1.2.2 From 4c6d4f5c33fbe19b134c1af43af166fee79eb986 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 16 Jul 2009 10:05:41 -0700 Subject: mac80211: add helper for management / no-ack frame rate decision All current rate control algorithms agree to send management and no-ack frames at the lowest rate. They also agree to do this when sta and the private rate control data is NULL. We add a hlper to mac80211 for this and simplify the rate control algorithm code. Developers wishing to make enhancements to rate control algorithms are for broadcast/multicast can opt to not use this in their gate_rate() mac80211 callback. Cc: Zhu Yi Acked-by: Reinette Chatre Cc: ipw3945-devel@lists.sourceforge.net Cc: Gabor Juhos Acked-by: Felix Fietkau Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 14 +------------- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 13 +++---------- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 7 +------ 3 files changed, 5 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 2c72901adbee..630fcf46e0dd 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1518,23 +1518,11 @@ exit: static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) { - struct ieee80211_supported_band *sband = txrc->sband; - struct sk_buff *skb = txrc->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - __le16 fc = hdr->frame_control; - /* lowest rate for management and NO_ACK frames */ - if (!ieee80211_is_data(fc) || - tx_info->flags & IEEE80211_TX_CTL_NO_ACK || !sta) { - tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); - tx_info->control.rates[0].count = - (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ? - 1 : ATH_MGT_TXMAXTRY; + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } /* Find tx rate for unicast frames */ ath_rc_ratefind(sc, ath_rc_priv, txrc); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 2b776924d5e7..a16bd4147eac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -673,7 +673,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, s8 scale_action = 0; unsigned long flags; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc; u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; s8 max_rate_idx = -1; struct iwl_priv *priv = (struct iwl_priv *)priv_r; @@ -681,16 +680,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "enter\n"); - /* Send management frames and NO_ACK data using lowest rate. */ - fc = hdr->frame_control; - if (!ieee80211_is_data(fc) || info->flags & IEEE80211_TX_CTL_NO_ACK || - !sta || !priv_sta) { - IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); - info->control.rates[0].idx = rate_lowest_index(sband, sta); - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - info->control.rates[0].count = 1; + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } + + rate_mask = sta->supp_rates[sband->band]; /* get user max rate if set */ max_rate_idx = txrc->max_rate_idx; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3fea027f35d1..63280411fd58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2481,13 +2481,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, } /* Send management frames and NO_ACK data using lowest rate. */ - if (!ieee80211_is_data(hdr->frame_control) || - info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !lq_sta) { - info->control.rates[0].idx = rate_lowest_index(sband, sta); - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - info->control.rates[0].count = 1; + if (rate_control_send_low(sta, priv_sta, txrc)) return; - } rate_idx = lq_sta->last_txrate_idx; -- cgit v1.2.2 From e25739a171d7352168346dbab7f006e1f9275995 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:14:09 -0400 Subject: ath9k: remove rate control wraper After the cleanup we just use get_rate as a wrapper, skip the wrapper. Cc: Derek Smithies Cc: Chittajit Mitra Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 630fcf46e0dd..e66734c2cae1 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -786,10 +786,11 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, tx_info->control.rts_cts_rate_idx = cix; } -static void ath_rc_ratefind(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_rate_control *txrc) +static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, + struct ieee80211_tx_rate_control *txrc) { + struct ath_softc *sc = priv; + struct ath_rate_priv *ath_rc_priv = priv_sta; const struct ath_rate_table *rate_table; struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@ -799,6 +800,9 @@ static void ath_rc_ratefind(struct ath_softc *sc, u8 try_per_rate, i = 0, rix, nrix; int is_probe = 0; + if (rate_control_send_low(sta, priv_sta, txrc)) + return; + /* * For Multi Rate Retry we use a different number of * retry attempt counts. This ends up looking like this: @@ -1515,19 +1519,6 @@ exit: kfree(tx_info_priv); } -static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, - struct ieee80211_tx_rate_control *txrc) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - - if (rate_control_send_low(sta, priv_sta, txrc)) - return; - - /* Find tx rate for unicast frames */ - ath_rc_ratefind(sc, ath_rc_priv, txrc); -} - static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { -- cgit v1.2.2 From 39a4cafe1638bb21f335b210d037cd2cd8ce6c08 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 14 Jul 2009 20:14:10 -0400 Subject: ath9k: Remove dead code in rate control ath9k rate control is based on only PER (packet error rate), remove unused code which was intented to do rssi based rate selection. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 163 +----------------------------------- 1 file changed, 4 insertions(+), 159 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e66734c2cae1..a39b1a7d3775 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -607,47 +607,14 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, const struct ath_rate_table *rate_table, int *is_probing) { - u32 dt, best_thruput, this_thruput, now_msec; + u32 best_thruput, this_thruput, now_msec; u8 rate, next_rate, best_rate, maxindex, minindex; - int8_t rssi_last, rssi_reduce = 0, index = 0; - - *is_probing = 0; - - rssi_last = median(ath_rc_priv->rssi_last, - ath_rc_priv->rssi_last_prev, - ath_rc_priv->rssi_last_prev2); - - /* - * Age (reduce) last ack rssi based on how old it is. - * The bizarre numbers are so the delta is 160msec, - * meaning we divide by 16. - * 0msec <= dt <= 25msec: don't derate - * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB - * 185msec <= dt: derate by 10dB - */ + int8_t index = 0; now_msec = jiffies_to_msecs(jiffies); - dt = now_msec - ath_rc_priv->rssi_time; - - if (dt >= 185) - rssi_reduce = 10; - else if (dt >= 25) - rssi_reduce = (u8)((dt - 25) >> 4); - - /* Now reduce rssi_last by rssi_reduce */ - if (rssi_last < rssi_reduce) - rssi_last = 0; - else - rssi_last -= rssi_reduce; - - /* - * Now look up the rate in the rssi table and return it. - * If no rates match then we return 0 (lowest rate) - */ - + *is_probing = 0; best_thruput = 0; maxindex = ath_rc_priv->max_valid_rate-1; - minindex = 0; best_rate = minindex; @@ -687,7 +654,6 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, } rate = best_rate; - ath_rc_priv->rssi_last_lookup = rssi_last; /* * Must check the actual rate (ratekbps) to account for @@ -977,10 +943,6 @@ static bool ath_rc_update_per(struct ath_softc *sc, (nretry_to_per_lookup[retries] >> 3)); } - ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev; - ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last; - ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi; - ath_rc_priv->rssi_time = now_msec; /* * If we got at most one retry then increase the max rate if @@ -1024,18 +986,9 @@ static bool ath_rc_update_per(struct ath_softc *sc, /* * Don't update anything. We don't know if * this was because of collisions or poor signal. - * - * Later: if rssi_ack is close to - * ath_rc_priv->state[txRate].rssi_thres and we see lots - * of retries, then we could increase - * ath_rc_priv->state[txRate].rssi_thres. */ ath_rc_priv->hw_maxretry_pktcnt = 0; } else { - int32_t rssi_ackAvg; - int8_t rssi_thres; - int8_t rssi_ack_vmin; - /* * It worked with no retries. First ignore bogus (small) * rssi_ack values. @@ -1045,43 +998,9 @@ static bool ath_rc_update_per(struct ath_softc *sc, ath_rc_priv->hw_maxretry_pktcnt++; } - if (tx_info_priv->tx.ts_rssi < - rate_table->info[tx_rate].rssi_ack_validmin) - goto exit; - - /* Average the rssi */ - if (tx_rate != ath_rc_priv->rssi_sum_rate) { - ath_rc_priv->rssi_sum_rate = tx_rate; - ath_rc_priv->rssi_sum = - ath_rc_priv->rssi_sum_cnt = 0; - } - - ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi; - ath_rc_priv->rssi_sum_cnt++; - - if (ath_rc_priv->rssi_sum_cnt < 4) - goto exit; - - rssi_ackAvg = - (ath_rc_priv->rssi_sum + 2) / 4; - rssi_thres = - ath_rc_priv->state[tx_rate].rssi_thres; - rssi_ack_vmin = - rate_table->info[tx_rate].rssi_ack_validmin; - - ath_rc_priv->rssi_sum = - ath_rc_priv->rssi_sum_cnt = 0; - - /* Now reduce the current rssi threshold */ - if ((rssi_ackAvg < rssi_thres + 2) && - (rssi_thres > rssi_ack_vmin)) { - ath_rc_priv->state[tx_rate].rssi_thres--; - } - - state_change = true; } } -exit: + return state_change; } @@ -1093,11 +1012,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, struct ath_tx_info_priv *tx_info_priv, int tx_rate, int xretries, int retries) { -#define CHK_RSSI(rate) \ - ((ath_rc_priv->state[(rate)].rssi_thres + \ - rate_table->info[(rate)].rssi_ack_deltamin) > \ - ath_rc_priv->state[(rate)+1].rssi_thres) - u32 now_msec = jiffies_to_msecs(jiffies); int rate; u8 last_per; @@ -1108,13 +1022,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) return; - /* To compensate for some imbalance between ctrl and ext. channel */ - - if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) - tx_info_priv->tx.ts_rssi = - tx_info_priv->tx.ts_rssi < 3 ? 0 : - tx_info_priv->tx.ts_rssi - 3; - last_per = ath_rc_priv->state[tx_rate].per; /* Update PER first */ @@ -1136,51 +1043,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, ath_rc_priv->probe_time = now_msec; } - if (state_change) { - /* - * Make sure the rates above this have higher rssi thresholds. - * (Note: Monotonicity is kept within the OFDM rates and - * within the CCK rates. However, no adjustment is - * made to keep the rssi thresholds monotonically - * increasing between the CCK and OFDM rates.) - */ - for (rate = tx_rate; rate < size - 1; rate++) { - if (rate_table->info[rate+1].phy != - rate_table->info[tx_rate].phy) - break; - - if (CHK_RSSI(rate)) { - ath_rc_priv->state[rate+1].rssi_thres = - ath_rc_priv->state[rate].rssi_thres + - rate_table->info[rate].rssi_ack_deltamin; - } - } - - /* Make sure the rates below this have lower rssi thresholds. */ - for (rate = tx_rate - 1; rate >= 0; rate--) { - if (rate_table->info[rate].phy != - rate_table->info[tx_rate].phy) - break; - - if (CHK_RSSI(rate)) { - if (ath_rc_priv->state[rate+1].rssi_thres < - rate_table->info[rate].rssi_ack_deltamin) - ath_rc_priv->state[rate].rssi_thres = 0; - else { - ath_rc_priv->state[rate].rssi_thres = - ath_rc_priv->state[rate+1].rssi_thres - - rate_table->info[rate].rssi_ack_deltamin; - } - - if (ath_rc_priv->state[rate].rssi_thres < - rate_table->info[rate].rssi_ack_validmin) { - ath_rc_priv->state[rate].rssi_thres = - rate_table->info[rate].rssi_ack_validmin; - } - } - } - } - /* Make sure the rates below this have lower PER */ /* Monotonicity is kept only for rates below the current rate. */ if (ath_rc_priv->state[tx_rate].per < last_per) { @@ -1205,19 +1067,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, ath_rc_priv->state[rate].per; } - /* Every so often, we reduce the thresholds and - * PER (different for CCK and OFDM). */ - if (now_msec - ath_rc_priv->rssi_down_time >= - rate_table->rssi_reduce_interval) { - - for (rate = 0; rate < size; rate++) { - if (ath_rc_priv->state[rate].rssi_thres > - rate_table->info[rate].rssi_ack_validmin) - ath_rc_priv->state[rate].rssi_thres -= 1; - } - ath_rc_priv->rssi_down_time = now_msec; - } - /* Every so often, we reduce the thresholds * and PER (different for CCK and OFDM). */ if (now_msec - ath_rc_priv->per_down_time >= @@ -1233,7 +1082,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, ath_debug_stat_retries(sc, tx_rate, xretries, retries, ath_rc_priv->state[tx_rate].per); -#undef CHK_RSSI } static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, @@ -1369,8 +1217,6 @@ static void ath_rc_init(struct ath_softc *sc, /* Initialize thresholds according to the global rate table */ for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { - ath_rc_priv->state[i].rssi_thres = - rate_table->info[i].rssi_ack_validmin; ath_rc_priv->state[i].per = 0; } @@ -1631,7 +1477,6 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp return NULL; } - rate_priv->rssi_down_time = jiffies_to_msecs(jiffies); rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; return rate_priv; -- cgit v1.2.2 From ddf4a2db72c1073b31d0ad28911d137b1745cfca Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 14 Jul 2009 20:14:11 -0400 Subject: ath9k: Remove unused members from rate control structure Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 216 ++++++++++++++++++------------------ drivers/net/wireless/ath/ath9k/rc.h | 21 ---- 2 files changed, 108 insertions(+), 129 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a39b1a7d3775..731967c74a15 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -22,130 +22,130 @@ static const struct ath_rate_table ar5416_11na_ratetable = { { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 5400, 0x0b, 0x00, 12, - 0, 2, 1, 0, 0, 0, 0, 0 }, + 0, 0, 0, 0, 0, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 7800, 0x0f, 0x00, 18, - 0, 3, 1, 1, 1, 1, 1, 0 }, + 0, 1, 1, 1, 1, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 10000, 0x0a, 0x00, 24, - 2, 4, 2, 2, 2, 2, 2, 0 }, + 2, 2, 2, 2, 2, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 13900, 0x0e, 0x00, 36, - 2, 6, 2, 3, 3, 3, 3, 0 }, + 2, 3, 3, 3, 3, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 17300, 0x09, 0x00, 48, - 4, 10, 3, 4, 4, 4, 4, 0 }, + 4, 4, 4, 4, 4, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 23000, 0x0d, 0x00, 72, - 4, 14, 3, 5, 5, 5, 5, 0 }, + 4, 5, 5, 5, 5, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 27400, 0x08, 0x00, 96, - 4, 20, 3, 6, 6, 6, 6, 0 }, + 4, 6, 6, 6, 6, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 29300, 0x0c, 0x00, 108, - 4, 23, 3, 7, 7, 7, 7, 0 }, + 4, 7, 7, 7, 7, 0 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ 6400, 0x80, 0x00, 0, - 0, 2, 3, 8, 24, 8, 24, 3216 }, + 0, 8, 24, 8, 24, 3216 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ 12700, 0x81, 0x00, 1, - 2, 4, 3, 9, 25, 9, 25, 6434 }, + 2, 9, 25, 9, 25, 6434 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ 18800, 0x82, 0x00, 2, - 2, 6, 3, 10, 26, 10, 26, 9650 }, + 2, 10, 26, 10, 26, 9650 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ 25000, 0x83, 0x00, 3, - 4, 10, 3, 11, 27, 11, 27, 12868 }, + 4, 11, 27, 11, 27, 12868 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ 36700, 0x84, 0x00, 4, - 4, 14, 3, 12, 28, 12, 28, 19304 }, + 4, 12, 28, 12, 28, 19304 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ 48100, 0x85, 0x00, 5, - 4, 20, 3, 13, 29, 13, 29, 25740 }, + 4, 13, 29, 13, 29, 25740 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ 53500, 0x86, 0x00, 6, - 4, 23, 3, 14, 30, 14, 30, 28956 }, + 4, 14, 30, 14, 30, 28956 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ 59000, 0x87, 0x00, 7, - 4, 25, 3, 15, 31, 15, 32, 32180 }, + 4, 15, 31, 15, 32, 32180 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ 12700, 0x88, 0x00, - 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, + 8, 3, 16, 33, 16, 33, 6430 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ 24800, 0x89, 0x00, 9, - 2, 4, 3, 17, 34, 17, 34, 12860 }, + 2, 17, 34, 17, 34, 12860 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ 36600, 0x8a, 0x00, 10, - 2, 6, 3, 18, 35, 18, 35, 19300 }, + 2, 18, 35, 18, 35, 19300 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ 48100, 0x8b, 0x00, 11, - 4, 10, 3, 19, 36, 19, 36, 25736 }, + 4, 19, 36, 19, 36, 25736 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ 69500, 0x8c, 0x00, 12, - 4, 14, 3, 20, 37, 20, 37, 38600 }, + 4, 20, 37, 20, 37, 38600 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ 89500, 0x8d, 0x00, 13, - 4, 20, 3, 21, 38, 21, 38, 51472 }, + 4, 21, 38, 21, 38, 51472 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ 98900, 0x8e, 0x00, 14, - 4, 23, 3, 22, 39, 22, 39, 57890 }, + 4, 22, 39, 22, 39, 57890 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ 108300, 0x8f, 0x00, 15, - 4, 25, 3, 23, 40, 23, 41, 64320 }, + 4, 23, 40, 23, 41, 64320 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ 13200, 0x80, 0x00, 0, - 0, 2, 3, 8, 24, 24, 24, 6684 }, + 0, 8, 24, 24, 24, 6684 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ 25900, 0x81, 0x00, 1, - 2, 4, 3, 9, 25, 25, 25, 13368 }, + 2, 9, 25, 25, 25, 13368 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ 38600, 0x82, 0x00, 2, - 2, 6, 3, 10, 26, 26, 26, 20052 }, + 2, 10, 26, 26, 26, 20052 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ 49800, 0x83, 0x00, 3, - 4, 10, 3, 11, 27, 27, 27, 26738 }, + 4, 11, 27, 27, 27, 26738 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ 72200, 0x84, 0x00, 4, - 4, 14, 3, 12, 28, 28, 28, 40104 }, + 4, 12, 28, 28, 28, 40104 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ 92900, 0x85, 0x00, 5, - 4, 20, 3, 13, 29, 29, 29, 53476 }, + 4, 13, 29, 29, 29, 53476 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ 102700, 0x86, 0x00, 6, - 4, 23, 3, 14, 30, 30, 30, 60156 }, + 4, 14, 30, 30, 30, 60156 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ 112000, 0x87, 0x00, 7, - 4, 25, 3, 15, 31, 32, 32, 66840 }, + 4, 15, 31, 32, 32, 66840 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ 122000, 0x87, 0x00, 7, - 4, 25, 3, 15, 31, 32, 32, 74200 }, + 4, 15, 31, 32, 32, 74200 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ 25800, 0x88, 0x00, 8, - 0, 2, 3, 16, 33, 33, 33, 13360 }, + 0, 16, 33, 33, 33, 13360 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ 49800, 0x89, 0x00, 9, - 2, 4, 3, 17, 34, 34, 34, 26720 }, + 2, 17, 34, 34, 34, 26720 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ 71900, 0x8a, 0x00, 10, - 2, 6, 3, 18, 35, 35, 35, 40080 }, + 2, 18, 35, 35, 35, 40080 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ 92500, 0x8b, 0x00, 11, - 4, 10, 3, 19, 36, 36, 36, 53440 }, + 4, 19, 36, 36, 36, 53440 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ 130300, 0x8c, 0x00, 12, - 4, 14, 3, 20, 37, 37, 37, 80160 }, + 4, 20, 37, 37, 37, 80160 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ 162800, 0x8d, 0x00, 13, - 4, 20, 3, 21, 38, 38, 38, 106880 }, + 4, 21, 38, 38, 38, 106880 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ 178200, 0x8e, 0x00, 14, - 4, 23, 3, 22, 39, 39, 39, 120240 }, + 4, 22, 39, 39, 39, 120240 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ 192100, 0x8f, 0x00, 15, - 4, 25, 3, 23, 40, 41, 41, 133600 }, + 4, 23, 40, 41, 41, 133600 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ 207000, 0x8f, 0x00, 15, - 4, 25, 3, 23, 40, 41, 41, 148400 }, + 4, 23, 40, 41, 41, 148400 }, }, 50, /* probe interval */ 50, /* rssi reduce interval */ @@ -160,142 +160,142 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { { { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ 900, 0x1b, 0x00, 2, - 0, 0, 1, 0, 0, 0, 0, 0 }, + 0, 0, 0, 0, 0, 0 }, { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ 1900, 0x1a, 0x04, 4, - 1, 1, 1, 1, 1, 1, 1, 0 }, + 1, 1, 1, 1, 1, 0 }, { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ 4900, 0x19, 0x04, 11, - 2, 2, 2, 2, 2, 2, 2, 0 }, + 2, 2, 2, 2, 2, 0 }, { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ 8100, 0x18, 0x04, 22, - 3, 3, 2, 3, 3, 3, 3, 0 }, + 3, 3, 3, 3, 3, 0 }, { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 5400, 0x0b, 0x00, 12, - 4, 2, 1, 4, 4, 4, 4, 0 }, + 4, 4, 4, 4, 4, 0 }, { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 7800, 0x0f, 0x00, 18, - 4, 3, 1, 5, 5, 5, 5, 0 }, + 4, 5, 5, 5, 5, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 10100, 0x0a, 0x00, 24, - 6, 4, 1, 6, 6, 6, 6, 0 }, + 6, 6, 6, 6, 6, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 14100, 0x0e, 0x00, 36, - 6, 6, 2, 7, 7, 7, 7, 0 }, + 6, 7, 7, 7, 7, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 17700, 0x09, 0x00, 48, - 8, 10, 3, 8, 8, 8, 8, 0 }, + 8, 8, 8, 8, 8, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 23700, 0x0d, 0x00, 72, - 8, 14, 3, 9, 9, 9, 9, 0 }, + 8, 9, 9, 9, 9, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 27400, 0x08, 0x00, 96, - 8, 20, 3, 10, 10, 10, 10, 0 }, + 8, 10, 10, 10, 10, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 30900, 0x0c, 0x00, 108, - 8, 23, 3, 11, 11, 11, 11, 0 }, + 8, 11, 11, 11, 11, 0 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ 6400, 0x80, 0x00, 0, - 4, 2, 3, 12, 28, 12, 28, 3216 }, + 4, 12, 28, 12, 28, 3216 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ 12700, 0x81, 0x00, 1, - 6, 4, 3, 13, 29, 13, 29, 6434 }, + 6, 13, 29, 13, 29, 6434 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ 18800, 0x82, 0x00, 2, - 6, 6, 3, 14, 30, 14, 30, 9650 }, + 6, 14, 30, 14, 30, 9650 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ 25000, 0x83, 0x00, 3, - 8, 10, 3, 15, 31, 15, 31, 12868 }, + 8, 15, 31, 15, 31, 12868 }, { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ 36700, 0x84, 0x00, 4, - 8, 14, 3, 16, 32, 16, 32, 19304 }, + 8, 16, 32, 16, 32, 19304 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ 48100, 0x85, 0x00, 5, - 8, 20, 3, 17, 33, 17, 33, 25740 }, + 8, 17, 33, 17, 33, 25740 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ 53500, 0x86, 0x00, 6, - 8, 23, 3, 18, 34, 18, 34, 28956 }, + 8, 18, 34, 18, 34, 28956 }, { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ 59000, 0x87, 0x00, 7, - 8, 25, 3, 19, 35, 19, 36, 32180 }, + 8, 19, 35, 19, 36, 32180 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ 12700, 0x88, 0x00, 8, - 4, 2, 3, 20, 37, 20, 37, 6430 }, + 4, 20, 37, 20, 37, 6430 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ 24800, 0x89, 0x00, 9, - 6, 4, 3, 21, 38, 21, 38, 12860 }, + 6, 21, 38, 21, 38, 12860 }, { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ 36600, 0x8a, 0x00, 10, - 6, 6, 3, 22, 39, 22, 39, 19300 }, + 6, 22, 39, 22, 39, 19300 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ 48100, 0x8b, 0x00, 11, - 8, 10, 3, 23, 40, 23, 40, 25736 }, + 8, 23, 40, 23, 40, 25736 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ 69500, 0x8c, 0x00, 12, - 8, 14, 3, 24, 41, 24, 41, 38600 }, + 8, 24, 41, 24, 41, 38600 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ 89500, 0x8d, 0x00, 13, - 8, 20, 3, 25, 42, 25, 42, 51472 }, + 8, 25, 42, 25, 42, 51472 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ 98900, 0x8e, 0x00, 14, - 8, 23, 3, 26, 43, 26, 44, 57890 }, + 8, 26, 43, 26, 44, 57890 }, { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ 108300, 0x8f, 0x00, 15, - 8, 25, 3, 27, 44, 27, 45, 64320 }, + 8, 27, 44, 27, 45, 64320 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ 13200, 0x80, 0x00, 0, - 8, 2, 3, 12, 28, 28, 28, 6684 }, + 8, 12, 28, 28, 28, 6684 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ 25900, 0x81, 0x00, 1, - 8, 4, 3, 13, 29, 29, 29, 13368 }, + 8, 13, 29, 29, 29, 13368 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ 38600, 0x82, 0x00, 2, - 8, 6, 3, 14, 30, 30, 30, 20052 }, + 8, 14, 30, 30, 30, 20052 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ 49800, 0x83, 0x00, 3, - 8, 10, 3, 15, 31, 31, 31, 26738 }, + 8, 15, 31, 31, 31, 26738 }, { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ 72200, 0x84, 0x00, 4, - 8, 14, 3, 16, 32, 32, 32, 40104 }, + 8, 16, 32, 32, 32, 40104 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ 92900, 0x85, 0x00, 5, - 8, 20, 3, 17, 33, 33, 33, 53476 }, + 8, 17, 33, 33, 33, 53476 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ 102700, 0x86, 0x00, 6, - 8, 23, 3, 18, 34, 34, 34, 60156 }, + 8, 18, 34, 34, 34, 60156 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ 112000, 0x87, 0x00, 7, - 8, 23, 3, 19, 35, 36, 36, 66840 }, + 8, 19, 35, 36, 36, 66840 }, { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ 122000, 0x87, 0x00, 7, - 8, 25, 3, 19, 35, 36, 36, 74200 }, + 8, 19, 35, 36, 36, 74200 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ 25800, 0x88, 0x00, 8, - 8, 2, 3, 20, 37, 37, 37, 13360 }, + 8, 20, 37, 37, 37, 13360 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ 49800, 0x89, 0x00, 9, - 8, 4, 3, 21, 38, 38, 38, 26720 }, + 8, 21, 38, 38, 38, 26720 }, { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ 71900, 0x8a, 0x00, 10, - 8, 6, 3, 22, 39, 39, 39, 40080 }, + 8, 22, 39, 39, 39, 40080 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ 92500, 0x8b, 0x00, 11, - 8, 10, 3, 23, 40, 40, 40, 53440 }, + 8, 23, 40, 40, 40, 53440 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ 130300, 0x8c, 0x00, 12, - 8, 14, 3, 24, 41, 41, 41, 80160 }, + 8, 24, 41, 41, 41, 80160 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ 162800, 0x8d, 0x00, 13, - 8, 20, 3, 25, 42, 42, 42, 106880 }, + 8, 25, 42, 42, 42, 106880 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ 178200, 0x8e, 0x00, 14, - 8, 23, 3, 26, 43, 43, 43, 120240 }, + 8, 26, 43, 43, 43, 120240 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ 192100, 0x8f, 0x00, 15, - 8, 23, 3, 27, 44, 45, 45, 133600 }, + 8, 27, 44, 45, 45, 133600 }, { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ 207000, 0x8f, 0x00, 15, - 8, 25, 3, 27, 44, 45, 45, 148400 }, + 8, 27, 44, 45, 45, 148400 }, }, 50, /* probe interval */ 50, /* rssi reduce interval */ @@ -307,28 +307,28 @@ static const struct ath_rate_table ar5416_11a_ratetable = { { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 5400, 0x0b, 0x00, (0x80|12), - 0, 2, 1, 0, 0 }, + 0, 0, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 7800, 0x0f, 0x00, 18, - 0, 3, 1, 1, 0 }, + 0, 1, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 10000, 0x0a, 0x00, (0x80|24), - 2, 4, 2, 2, 0 }, + 2, 2, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 13900, 0x0e, 0x00, 36, - 2, 6, 2, 3, 0 }, + 2, 3, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 17300, 0x09, 0x00, (0x80|48), - 4, 10, 3, 4, 0 }, + 4, 4, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 23000, 0x0d, 0x00, 72, - 4, 14, 3, 5, 0 }, + 4, 5, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 27400, 0x08, 0x00, 96, - 4, 19, 3, 6, 0 }, + 4, 6, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 29300, 0x0c, 0x00, 108, - 4, 23, 3, 7, 0 }, + 4, 7, 0 }, }, 50, /* probe interval */ 50, /* rssi reduce interval */ @@ -340,40 +340,40 @@ static const struct ath_rate_table ar5416_11g_ratetable = { { { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ 900, 0x1b, 0x00, 2, - 0, 0, 1, 0, 0 }, + 0, 0, 0 }, { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ 1900, 0x1a, 0x04, 4, - 1, 1, 1, 1, 0 }, + 1, 1, 0 }, { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ 4900, 0x19, 0x04, 11, - 2, 2, 2, 2, 0 }, + 2, 2, 0 }, { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ 8100, 0x18, 0x04, 22, - 3, 3, 2, 3, 0 }, + 3, 3, 0 }, { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 5400, 0x0b, 0x00, 12, - 4, 2, 1, 4, 0 }, + 4, 4, 0 }, { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 7800, 0x0f, 0x00, 18, - 4, 3, 1, 5, 0 }, + 4, 5, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 10000, 0x0a, 0x00, 24, - 6, 4, 1, 6, 0 }, + 6, 6, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 13900, 0x0e, 0x00, 36, - 6, 6, 2, 7, 0 }, + 6, 7, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 17300, 0x09, 0x00, 48, - 8, 10, 3, 8, 0 }, + 8, 8, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 23000, 0x0d, 0x00, 72, - 8, 14, 3, 9, 0 }, + 8, 9, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 27400, 0x08, 0x00, 96, - 8, 19, 3, 10, 0 }, + 8, 10, 0 }, { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 29300, 0x0c, 0x00, 108, - 8, 23, 3, 11, 0 }, + 8, 11, 0 }, }, 50, /* probe interval */ 50, /* rssi reduce interval */ diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index e3abd76103fd..6797df0b196d 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -112,8 +112,6 @@ struct ath_rate_table { u8 short_preamble; u8 dot11rate; u8 ctrl_rate; - int8_t rssi_ack_validmin; - int8_t rssi_ack_deltamin; u8 base_index; u8 cw40index; u8 sgi_index; @@ -126,7 +124,6 @@ struct ath_rate_table { }; struct ath_tx_ratectrl_state { - int8_t rssi_thres; /* required rssi for this rate (dB) */ u8 per; /* recent estimate of packet error rate (%) */ }; @@ -138,16 +135,7 @@ struct ath_rateset { /** * struct ath_rate_priv - Rate Control priv data * @state: RC state - * @rssi_last: last ACK rssi - * @rssi_last_lookup: last ACK rssi used for lookup - * @rssi_last_prev: previous last ACK rssi - * @rssi_last_prev2: 2nd previous last ACK rssi - * @rssi_sum_cnt: count of rssi_sum for averaging - * @rssi_sum_rate: rate that we are averaging - * @rssi_sum: running sum of rssi for averaging * @probe_rate: rate we are probing at - * @rssi_time: msec timestamp for last ack rssi - * @rssi_down_time: msec timestamp for last down step * @probe_time: msec timestamp for last probe * @hw_maxretry_pktcnt: num of packets since we got HW max retry error * @max_valid_rate: maximum number of valid rate @@ -161,13 +149,6 @@ struct ath_rateset { * @neg_ht_rates: Negotiated HT rates */ struct ath_rate_priv { - int8_t rssi_last; - int8_t rssi_last_lookup; - int8_t rssi_last_prev; - int8_t rssi_last_prev2; - int32_t rssi_sum_cnt; - int32_t rssi_sum_rate; - int32_t rssi_sum; u8 rate_table_size; u8 probe_rate; u8 hw_maxretry_pktcnt; @@ -177,8 +158,6 @@ struct ath_rate_priv { u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; u8 rate_max_phy; - u32 rssi_time; - u32 rssi_down_time; u32 probe_time; u32 per_down_time; u32 probe_interval; -- cgit v1.2.2 From c41304653e120749dae8b04332b92ffb5f4dbbfd Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 14 Jul 2009 20:14:12 -0400 Subject: ath9k: Use probe interval instead of rssi reduce interval Get rid of rssi reduce interval. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 6 +----- drivers/net/wireless/ath/ath9k/rc.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 731967c74a15..a97dd7b6b706 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -148,7 +148,6 @@ static const struct ath_rate_table ar5416_11na_ratetable = { 4, 23, 40, 41, 41, 148400 }, }, 50, /* probe interval */ - 50, /* rssi reduce interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ }; @@ -298,7 +297,6 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { 8, 27, 44, 45, 45, 148400 }, }, 50, /* probe interval */ - 50, /* rssi reduce interval */ WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ }; @@ -331,7 +329,6 @@ static const struct ath_rate_table ar5416_11a_ratetable = { 4, 7, 0 }, }, 50, /* probe interval */ - 50, /* rssi reduce interval */ 0, /* Phy rates allowed initially */ }; @@ -376,7 +373,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = { 8, 11, 0 }, }, 50, /* probe interval */ - 50, /* rssi reduce interval */ 0, /* Phy rates allowed initially */ }; @@ -1070,7 +1066,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, /* Every so often, we reduce the thresholds * and PER (different for CCK and OFDM). */ if (now_msec - ath_rc_priv->per_down_time >= - rate_table->rssi_reduce_interval) { + rate_table->probe_interval) { for (rate = 0; rate < size; rate++) { ath_rc_priv->state[rate].per = 7 * ath_rc_priv->state[rate].per / 8; diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 6797df0b196d..c794d6c82ad4 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -119,7 +119,6 @@ struct ath_rate_table { u32 max_4ms_framelen; } info[RATE_TABLE_SIZE]; u32 probe_interval; - u32 rssi_reduce_interval; u8 initial_ratemax; }; -- cgit v1.2.2 From 922bac602255d4557c289cabba7857c5be332d34 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 14 Jul 2009 20:14:13 -0400 Subject: ath9k: Nuke struct ath_tx_ratectrl_state Move its only member (u8 per) to struct ath_rate_priv. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 50 ++++++++++++++++++------------------- drivers/net/wireless/ath/ath9k/rc.h | 7 ++---- 2 files changed, 27 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a97dd7b6b706..a07efa22551e 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -636,7 +636,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, * 10-15 and we would be worse off then staying * at the current rate. */ - per_thres = ath_rc_priv->state[rate].per; + per_thres = ath_rc_priv->per[rate]; if (per_thres < 12) per_thres = 12; @@ -881,13 +881,13 @@ static bool ath_rc_update_per(struct ath_softc *sc, 100 * 9 / 10 }; - last_per = ath_rc_priv->state[tx_rate].per; + last_per = ath_rc_priv->per[tx_rate]; if (xretries) { if (xretries == 1) { - ath_rc_priv->state[tx_rate].per += 30; - if (ath_rc_priv->state[tx_rate].per > 100) - ath_rc_priv->state[tx_rate].per = 100; + ath_rc_priv->per[tx_rate] += 30; + if (ath_rc_priv->per[tx_rate] > 100) + ath_rc_priv->per[tx_rate] = 100; } else { /* xretries == 2 */ count = ARRAY_SIZE(nretry_to_per_lookup); @@ -895,7 +895,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, retries = count - 1; /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ - ath_rc_priv->state[tx_rate].per = + ath_rc_priv->per[tx_rate] = (u8)(last_per - (last_per >> 3) + (100 >> 3)); } @@ -931,10 +931,10 @@ static bool ath_rc_update_per(struct ath_softc *sc, n_frames = tx_info_priv->n_frames * (retries + 1); cur_per = (100 * n_bad_frames / n_frames) >> 3; new_per = (u8)(last_per - (last_per >> 3) + cur_per); - ath_rc_priv->state[tx_rate].per = new_per; + ath_rc_priv->per[tx_rate] = new_per; } } else { - ath_rc_priv->state[tx_rate].per = + ath_rc_priv->per[tx_rate] = (u8)(last_per - (last_per >> 3) + (nretry_to_per_lookup[retries] >> 3)); } @@ -962,8 +962,8 @@ static bool ath_rc_update_per(struct ath_softc *sc, ath_rc_priv->probe_rate; probe_rate = ath_rc_priv->probe_rate; - if (ath_rc_priv->state[probe_rate].per > 30) - ath_rc_priv->state[probe_rate].per = 20; + if (ath_rc_priv->per[probe_rate] > 30) + ath_rc_priv->per[probe_rate] = 20; ath_rc_priv->probe_rate = 0; @@ -1018,7 +1018,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) return; - last_per = ath_rc_priv->state[tx_rate].per; + last_per = ath_rc_priv->per[tx_rate]; /* Update PER first */ state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, @@ -1029,7 +1029,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, * If this rate looks bad (high PER) then stop using it for * a while (except if we are probing). */ - if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 && + if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 && rate_table->info[tx_rate].ratekbps <= rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { ath_rc_get_lower_rix(rate_table, ath_rc_priv, @@ -1041,26 +1041,26 @@ static void ath_rc_update_ht(struct ath_softc *sc, /* Make sure the rates below this have lower PER */ /* Monotonicity is kept only for rates below the current rate. */ - if (ath_rc_priv->state[tx_rate].per < last_per) { + if (ath_rc_priv->per[tx_rate] < last_per) { for (rate = tx_rate - 1; rate >= 0; rate--) { if (rate_table->info[rate].phy != rate_table->info[tx_rate].phy) break; - if (ath_rc_priv->state[rate].per > - ath_rc_priv->state[rate+1].per) { - ath_rc_priv->state[rate].per = - ath_rc_priv->state[rate+1].per; + if (ath_rc_priv->per[rate] > + ath_rc_priv->per[rate+1]) { + ath_rc_priv->per[rate] = + ath_rc_priv->per[rate+1]; } } } /* Maintain monotonicity for rates above the current rate */ for (rate = tx_rate; rate < size - 1; rate++) { - if (ath_rc_priv->state[rate+1].per < - ath_rc_priv->state[rate].per) - ath_rc_priv->state[rate+1].per = - ath_rc_priv->state[rate].per; + if (ath_rc_priv->per[rate+1] < + ath_rc_priv->per[rate]) + ath_rc_priv->per[rate+1] = + ath_rc_priv->per[rate]; } /* Every so often, we reduce the thresholds @@ -1068,15 +1068,15 @@ static void ath_rc_update_ht(struct ath_softc *sc, if (now_msec - ath_rc_priv->per_down_time >= rate_table->probe_interval) { for (rate = 0; rate < size; rate++) { - ath_rc_priv->state[rate].per = - 7 * ath_rc_priv->state[rate].per / 8; + ath_rc_priv->per[rate] = + 7 * ath_rc_priv->per[rate] / 8; } ath_rc_priv->per_down_time = now_msec; } ath_debug_stat_retries(sc, tx_rate, xretries, retries, - ath_rc_priv->state[tx_rate].per); + ath_rc_priv->per[tx_rate]); } @@ -1213,7 +1213,7 @@ static void ath_rc_init(struct ath_softc *sc, /* Initialize thresholds according to the global rate table */ for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { - ath_rc_priv->state[i].per = 0; + ath_rc_priv->per[i] = 0; } /* Determine the valid rates */ diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index c794d6c82ad4..fa21a628ddd0 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -122,10 +122,6 @@ struct ath_rate_table { u8 initial_ratemax; }; -struct ath_tx_ratectrl_state { - u8 per; /* recent estimate of packet error rate (%) */ -}; - struct ath_rateset { u8 rs_nrates; u8 rs_rates[ATH_RATE_MAX]; @@ -141,6 +137,7 @@ struct ath_rateset { * @per_down_time: msec timestamp for last PER down step * @valid_phy_ratecnt: valid rate count * @rate_max_phy: phy index for the max rate + * @per: PER for every valid rate in % * @probe_interval: interval for ratectrl to probe for other rates * @prev_data_rix: rate idx of last data frame * @ht_cap: HT capabilities @@ -157,12 +154,12 @@ struct ath_rate_priv { u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; u8 rate_max_phy; + u8 per[RATE_TABLE_SIZE]; u32 probe_time; u32 per_down_time; u32 probe_interval; u32 prev_data_rix; u32 tx_triglevel_max; - struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE]; struct ath_rateset neg_rates; struct ath_rateset neg_ht_rates; struct ath_rate_softc *asc; -- cgit v1.2.2 From a59b5a5e684652eec035c869ab8911a1689c8f53 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Tue, 14 Jul 2009 20:17:07 -0400 Subject: ath9k: Manipulate and report the correct RSSI RSSI reported by the RX descriptor requires little manipulation. Manipulate and report the correct RSSI to the stack. This will fix the improper signal levels reported by iwconfig iw dev wlanX station dump. Also the Link Quality reported seems to be varying (falls to zero also sometimes) when iperf is run from STA to AP. Also use the default noise floor for now as the one reported during the caliberation seems to be wrong. The Signal and Link Quality before this patch (taken while TX is in progress from STA to AP) 09:59:13.285428037 Link Quality=29/70 Signal level=-81 dBm 09:59:13.410660084 Link Quality=20/70 Signal level=-90 dBm 09:59:13.586864392 Link Quality=21/70 Signal level=-89 dBm 09:59:13.710296281 Link Quality=21/70 Signal level=-89 dBm 09:59:13.821683064 Link Quality=25/70 Signal level=-85 dBm 09:59:13.933402989 Link Quality=24/70 Signal level=-86 dBm 09:59:14.045839276 Link Quality=26/70 Signal level=-84 dBm 09:59:14.193926673 Link Quality=23/70 Signal level=-87 dBm 09:59:14.306230262 Link Quality=31/70 Signal level=-79 dBm 09:59:14.419459667 Link Quality=26/70 Signal level=-84 dBm 09:59:14.530711167 Link Quality=37/70 Signal level=-73 dBm 09:59:14.642593962 Link Quality=29/70 Signal level=-81 dBm 09:59:14.754361169 Link Quality=21/70 Signal level=-89 dBm 09:59:14.866217355 Link Quality=21/70 Signal level=-89 dBm 09:59:14.976963623 Link Quality=28/70 Signal level=-82 dBm 09:59:15.089149809 Link Quality=26/70 Signal level=-84 dBm 09:59:15.205039887 Link Quality=27/70 Signal level=-83 dBm 09:59:15.316368003 Link Quality=23/70 Signal level=-87 dBm 09:59:15.427684036 Link Quality=36/70 Signal level=-74 dBm 09:59:15.539756380 Link Quality=21/70 Signal level=-89 dBm 09:59:15.650549093 Link Quality=22/70 Signal level=-88 dBm 09:59:15.761171672 Link Quality=32/70 Signal level=-78 dBm 09:59:15.872793750 Link Quality=23/70 Signal level=-87 dBm 09:59:15.984421694 Link Quality=22/70 Signal level=-88 dBm 09:59:16.097315093 Link Quality=21/70 Signal level=-89 dBm The link quality and signal level after this patch (take while TX is in progress from STA to AP) 17:21:25.627848091 Link Quality=65/70 Signal level=-45 dBm 17:21:25.762805607 Link Quality=65/70 Signal level=-45 dBm 17:21:25.875521888 Link Quality=66/70 Signal level=-44 dBm 17:21:25.987468448 Link Quality=66/70 Signal level=-44 dBm 17:21:26.100628151 Link Quality=66/70 Signal level=-44 dBm 17:21:26.213129671 Link Quality=66/70 Signal level=-44 dBm 17:21:26.324923070 Link Quality=65/70 Signal level=-45 dBm 17:21:26.436831357 Link Quality=65/70 Signal level=-45 dBm 17:21:26.610356973 Link Quality=65/70 Signal level=-45 dBm 17:21:26.723340047 Link Quality=65/70 Signal level=-45 dBm 17:21:26.835715293 Link Quality=64/70 Signal level=-46 dBm 17:21:26.949542748 Link Quality=64/70 Signal level=-46 dBm 17:21:27.062261613 Link Quality=65/70 Signal level=-45 dBm 17:21:27.174511563 Link Quality=64/70 Signal level=-46 dBm 17:21:27.287616232 Link Quality=64/70 Signal level=-46 dBm 17:21:27.400598119 Link Quality=64/70 Signal level=-46 dBm 17:21:27.511381404 Link Quality=64/70 Signal level=-46 dBm 17:21:27.624530421 Link Quality=65/70 Signal level=-45 dBm 17:21:27.737807109 Link Quality=64/70 Signal level=-46 dBm 17:21:27.850861352 Link Quality=65/70 Signal level=-45 dBm 17:21:27.963369436 Link Quality=64/70 Signal level=-46 dBm 17:21:28.076582289 Link Quality=64/70 Signal level=-46 dBm Signed-off-by: Senthil Balasubramanian Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 16 ++++++++++++++++ drivers/net/wireless/ath/ath9k/calib.c | 13 ++++++++++--- drivers/net/wireless/ath/ath9k/calib.h | 4 +++- drivers/net/wireless/ath/ath9k/main.c | 1 + drivers/net/wireless/ath/ath9k/recv.c | 25 ++++++++++++++++++++++++- 5 files changed, 54 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 3afd7ee41a63..544599b826c1 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -290,12 +290,28 @@ struct ath_tx_control { #define ATH_TX_XRETRY 0x02 #define ATH_TX_BAR 0x04 +#define ATH_RSSI_LPF_LEN 10 +#define RSSI_LPF_THRESHOLD -20 +#define ATH9K_RSSI_BAD 0x80 +#define ATH_RSSI_EP_MULTIPLIER (1<<7) +#define ATH_EP_MUL(x, mul) ((x) * (mul)) +#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) +#define ATH_LPF_RSSI(x, y, len) \ + ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y)) +#define ATH_RSSI_LPF(x, y) do { \ + if ((y) >= RSSI_LPF_THRESHOLD) \ + x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ +} while (0) +#define ATH_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) + struct ath_node { struct ath_softc *an_sc; struct ath_atx_tid tid[WME_NUM_TID]; struct ath_atx_ac ac[WME_NUM_AC]; u16 maxampdu; u8 mpdudensity; + int last_rssi; }; struct ath_tx { diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index a32d7e7fecbe..1f0c5fe4a68b 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -691,15 +691,22 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) { int i, j; + s16 noise_floor; + + if (AR_SREV_9280(ah)) + noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; + else if (AR_SREV_9285(ah)) + noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; + else + noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; for (i = 0; i < NUM_NF_READINGS; i++) { ah->nfCalHist[i].currIndex = 0; - ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE; + ah->nfCalHist[i].privNF = noise_floor; ah->nfCalHist[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { - ah->nfCalHist[i].nfCalBuffer[j] = - AR_PHY_CCA_MAX_GOOD_VALUE; + ah->nfCalHist[i].nfCalBuffer[j] = noise_floor; } } } diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index fe5367f14148..547e697b9055 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -25,7 +25,9 @@ extern const struct ath9k_percal_data adc_dc_cal_multi_sample; extern const struct ath9k_percal_data adc_dc_cal_single_sample; extern const struct ath9k_percal_data adc_init_dc_cal; -#define AR_PHY_CCA_MAX_GOOD_VALUE -85 +#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 +#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 +#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 #define AR_PHY_CCA_MAX_HIGH_VALUE -62 #define AR_PHY_CCA_MIN_BAD_VALUE -140 #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 19df7882d0d3..2ad718489c0d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -465,6 +465,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + sta->ht_cap.ampdu_factor); an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); + an->last_rssi = ATH_RSSI_DUMMY_MARKER; } } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index b3da81db453b..61edfab20ffc 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -145,6 +145,10 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, u8 ratecode; __le16 fc; struct ieee80211_hw *hw; + struct ieee80211_sta *sta; + struct ath_node *an; + int last_rssi = ATH_RSSI_DUMMY_MARKER; + hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; @@ -229,11 +233,30 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, } } + rcu_read_lock(); + sta = ieee80211_find_sta(sc->hw, hdr->addr2); + if (sta) { + an = (struct ath_node *) sta->drv_priv; + if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD && + !ds->ds_rxstat.rs_moreaggr) + ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi); + last_rssi = an->last_rssi; + } + rcu_read_unlock(); + + if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) + ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi, + ATH_RSSI_EP_MULTIPLIER); + if (ds->ds_rxstat.rs_rssi < 0) + ds->ds_rxstat.rs_rssi = 0; + else if (ds->ds_rxstat.rs_rssi > 127) + ds->ds_rxstat.rs_rssi = 127; + rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); rx_status->band = hw->conf.channel->band; rx_status->freq = hw->conf.channel->center_freq; rx_status->noise = sc->ani.noise_floor; - rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; + rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + ds->ds_rxstat.rs_rssi; rx_status->antenna = ds->ds_rxstat.rs_antenna; /* -- cgit v1.2.2 From dd8b15b027d96f7097ae9dbaebd822a114a03c34 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Tue, 14 Jul 2009 20:17:08 -0400 Subject: ath9k: RX stucks during heavy traffic in HT40 mode. Running iperf along with p2p traffic on both TX and RX side then stop one side, then stop the other side, then start it up again, eventually the STA gets into a mode that it can not pass data at all. A hardware workaround for invalid RSSI can make FIFO write pointer to jump over read pointer, causing RX data corruption and repeated DMA. Both TX and RX works fine when the workaround is disabled. To replace the original hardware work around, software looks for frames with post delimiter CRC error and mark the RSSI invalid so that the upperlayer will not use the RSSI associated with this frame. So disable the hardware workaround by updating the appropriate registers. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.c | 20 ++++++++++++- drivers/net/wireless/ath/ath9k/initvals.h | 47 ++++++++++++++++--------------- drivers/net/wireless/ath/ath9k/mac.c | 30 +++++++++++++++----- 3 files changed, 67 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index d82a0f97e6f5..df41ed5fd7c4 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -1208,6 +1208,19 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, pModal->xatten2Margin[0]); REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); + + /* Set the block 1 value to block 0 value */ + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[0]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[0]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, + pModal->xatten2Db[0]); } REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, @@ -1215,6 +1228,11 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); + REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); + if (AR_SREV_9285_11(ah)) REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); } @@ -1239,7 +1257,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); /* Initialize Ant Diversity settings from EEPROM */ - if (pModal->version == 3) { + if (pModal->version >= 3) { ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf); ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf); regVal = REG_READ(ah, 0x99ac); diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index e2f0a34b79a1..f67a2a96cc5c 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h @@ -2782,7 +2782,7 @@ static const u32 ar9280Common_9280_2[][2] = { { 0x00008338, 0x00ff0000 }, { 0x0000833c, 0x00000000 }, { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00581043 }, + { 0x00008344, 0x00481043 }, { 0x00009808, 0x00000000 }, { 0x0000980c, 0xafa68e30 }, { 0x00009810, 0xfd14e000 }, @@ -3439,7 +3439,7 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { {0x00004044, 0x00000000 }, }; -/* AR9285 */ +/* AR9285 Revsion 10*/ static const u_int32_t ar9285Modes_9285[][6] = { { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -3955,7 +3955,7 @@ static const u_int32_t ar9285Common_9285[][2] = { { 0x00008338, 0x00000000 }, { 0x0000833c, 0x00000000 }, { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00581043 }, + { 0x00008344, 0x00481043 }, { 0x00009808, 0x00000000 }, { 0x0000980c, 0xafe68e30 }, { 0x00009810, 0xfd14e000 }, @@ -4121,8 +4121,9 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { {0x00004044, 0x00000000 }, }; -/* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */ +/* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */ static const u_int32_t ar9285Modes_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -4139,6 +4140,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, @@ -4419,6 +4421,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, @@ -4618,7 +4621,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { { 0x00008338, 0x00ff0000 }, { 0x0000833c, 0x00000000 }, { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00581043 }, + { 0x00008344, 0x00481043 }, { 0x00009808, 0x00000000 }, { 0x0000980c, 0xafe68e30 }, { 0x00009810, 0xfd14e000 }, @@ -4752,18 +4755,18 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, @@ -4776,13 +4779,13 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, - { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, - { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, - { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, - { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, + { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, + { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, + { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, + { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, }; static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 8ae4ec21667b..6f923e318727 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -825,13 +825,29 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; - ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); - ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); - ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); - ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); - ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); - ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); - ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); + if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { + ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD; + ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD; + } else { + ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); + ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, + AR_RxRSSIAnt00); + ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, + AR_RxRSSIAnt01); + ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, + AR_RxRSSIAnt02); + ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, + AR_RxRSSIAnt10); + ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, + AR_RxRSSIAnt11); + ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, + AR_RxRSSIAnt12); + } if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); else -- cgit v1.2.2 From 164ace38536849966ffa377b1b1132993a5a375d Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Tue, 14 Jul 2009 20:17:09 -0400 Subject: ath9k: Fix TX hang issue with Atheros chipsets The hardware doesn't generate interrupts in some cases and so work around this by monitoring the TX status periodically and reset the chip if required. This behavior of the hardware not generating the TX interrupts can be noticed through ath9k debugfs interrupt statistics when heavy traffic is being sent from STA to AP. One can easily see this behavior when the STA is transmitting at a higher rates. The interrupt statistics in the debugfs interface clearly shows that only RX interrupts alone being generated and TX being stuck. TX should be monitored through a timer and reset the chip only when frames are queued to the hardware but TX interrupts are not generated for the same even after one second. Also, we shouldn't remove holding descriptor from AC queue if it happens to be the only descriptor and schedule TX aggregation regarless of queue depth as it improves scheduling of AMPDUs from software to hardware queue. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 +++ drivers/net/wireless/ath/ath9k/main.c | 3 ++ drivers/net/wireless/ath/ath9k/xmit.c | 57 +++++++++++++++++++++++++--------- 3 files changed, 50 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 544599b826c1..20bf4a7f896d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -225,6 +225,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) +#define ATH_TX_COMPLETE_POLL_INT 1000 + enum ATH_AGGR_STATUS { ATH_AGGR_DONE, ATH_AGGR_BAW_CLOSED, @@ -240,6 +242,7 @@ struct ath_txq { u8 axq_aggr_depth; u32 axq_totalqueued; bool stopped; + bool axq_tx_inprogress; struct ath_buf *axq_linkbuf; /* first desc of the last descriptor that contains CTS */ @@ -605,6 +608,7 @@ struct ath_softc { #endif struct ath_bus_ops *bus_ops; struct ath_beacon_config cur_beacon_conf; + struct delayed_work tx_complete_work; }; struct ath_wiphy { diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2ad718489c0d..46f4a692c8d1 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1259,6 +1259,7 @@ void ath_detach(struct ath_softc *sc) ath_deinit_leds(sc); cancel_work_sync(&sc->chan_work); cancel_delayed_work_sync(&sc->wiphy_work); + cancel_delayed_work_sync(&sc->tx_complete_work); for (i = 0; i < sc->num_sec_wiphy; i++) { struct ath_wiphy *aphy = sc->sec_wiphy[i]; @@ -1979,6 +1980,8 @@ static int ath9k_start(struct ieee80211_hw *hw) ieee80211_wake_queues(hw); + queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 0); + mutex_unlock: mutex_unlock(&sc->mutex); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 5de9878d2c12..a3bc4310a67c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -857,6 +857,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) txq->axq_aggr_depth = 0; txq->axq_totalqueued = 0; txq->axq_linkbuf = NULL; + txq->axq_tx_inprogress = false; sc->tx.txqsetup |= 1<tx.txq[qnum]; @@ -1023,6 +1024,10 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); } + spin_lock_bh(&txq->axq_lock); + txq->axq_tx_inprogress = false; + spin_unlock_bh(&txq->axq_lock); + /* flush any pending frames if aggregation is enabled */ if (sc->sc_flags & SC_OP_TXAGGR) { if (!retry_tx) { @@ -1103,8 +1108,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) if (tid->paused) continue; - if ((txq->axq_depth % 2) == 0) - ath_tx_sched_aggr(sc, txq, tid); + ath_tx_sched_aggr(sc, txq, tid); /* * add tid to round-robin queue if more frames @@ -1947,19 +1951,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (bf->bf_stale) { bf_held = bf; if (list_is_last(&bf_held->list, &txq->axq_q)) { - txq->axq_link = NULL; - txq->axq_linkbuf = NULL; spin_unlock_bh(&txq->axq_lock); - - /* - * The holding descriptor is the last - * descriptor in queue. It's safe to remove - * the last holding descriptor in BH context. - */ - spin_lock_bh(&sc->tx.txbuflock); - list_move_tail(&bf_held->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - break; } else { bf = list_entry(bf_held->list.next, @@ -1996,6 +1988,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) txq->axq_aggr_depth--; txok = (ds->ds_txstat.ts_status == 0); + txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); if (bf_held) { @@ -2029,6 +2022,40 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) } } +void ath_tx_complete_poll_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + tx_complete_work.work); + struct ath_txq *txq; + int i; + bool needreset = false; + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) { + txq = &sc->tx.txq[i]; + spin_lock_bh(&txq->axq_lock); + if (txq->axq_depth) { + if (txq->axq_tx_inprogress) { + needreset = true; + spin_unlock_bh(&txq->axq_lock); + break; + } else { + txq->axq_tx_inprogress = true; + } + } + spin_unlock_bh(&txq->axq_lock); + } + + if (needreset) { + DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n"); + ath_reset(sc, false); + } + + queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, + msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); +} + + void ath_tx_tasklet(struct ath_softc *sc) { @@ -2069,6 +2096,8 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) goto err; } + INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); + err: if (error != 0) ath_tx_cleanup(sc); -- cgit v1.2.2 From 8e7f98b5690fc295e3a39b99aeed475d28c60c90 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 14 Jul 2009 20:17:10 -0400 Subject: ath9k: Remove bogus assert in ath_clone_txbuf() oops, this one should be part of the original patch "ath9k: downgrade assert in ath_clone_txbuf()" Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index a3bc4310a67c..24663ce10ef8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -242,7 +242,6 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) spin_unlock_bh(&sc->tx.txbuflock); return NULL; } - ASSERT(!list_empty((&sc->tx.txbuf))); tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); list_del(&tbf->list); spin_unlock_bh(&sc->tx.txbuflock); -- cgit v1.2.2 From c41d92dc9d9a1afcec0095c32698ea7deff01098 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 14 Jul 2009 20:17:11 -0400 Subject: ath9k: Handle tx desc shortage more appropriately Update tx BA window and complete the frame as failed one if we can't clone the holding descriptor due to unavailability of descriptors. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 24663ce10ef8..4ff155e8ee59 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -382,8 +382,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *tbf; tbf = ath_clone_txbuf(sc, bf_last); - if (!tbf) + /* + * Update tx baw and complete the frame with + * failed status if we run out of tx buf + */ + if (!tbf) { + spin_lock_bh(&txq->axq_lock); + ath_tx_update_baw(sc, tid, + bf->bf_seqno); + spin_unlock_bh(&txq->axq_lock); + + bf->bf_state.bf_type |= BUF_XRETRY; + ath_tx_rc_status(bf, ds, nbad, + 0, false); + ath_tx_complete_buf(sc, bf, &bf_head, + 0, 0); break; + } + ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); list_add_tail(&tbf->list, &bf_head); } else { -- cgit v1.2.2 From ebaa24534ef54a8f665558536dbef3a761a9b841 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 14 Jul 2009 20:17:12 -0400 Subject: ath9k: Remove pointless ath9k_ps_restore() in ath_detach() Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 46f4a692c8d1..90cecce8d5ff 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1286,7 +1286,6 @@ void ath_detach(struct ath_softc *sc) ath9k_hw_detach(sc->sc_ah); ath9k_exit_debug(sc); - ath9k_ps_restore(sc); } static int ath9k_reg_notifier(struct wiphy *wiphy, -- cgit v1.2.2 From 04717ccd80e5acc500239222684fcf8d2c759a84 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 14 Jul 2009 20:17:13 -0400 Subject: ath9k: serialize ath9k_hw_setpower calls Because ath9k_setpower is called from various contexts, we have to protect it against concurrent calls. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/hw.c | 15 ++++++++++++++- drivers/net/wireless/ath/ath9k/main.c | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 20bf4a7f896d..b37eb592b524 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -559,6 +559,7 @@ struct ath_softc { spinlock_t sc_resetlock; spinlock_t sc_serial_rw; spinlock_t ani_lock; + spinlock_t sc_pm_lock; struct mutex mutex; u8 curbssid[ETH_ALEN]; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a115c8ceabe3..6740a6b98a62 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2728,7 +2728,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) return true; } -bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) +static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, + enum ath9k_power_mode mode) { int status = true, setChip = true; static const char *modes[] = { @@ -2762,6 +2763,18 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) return status; } +bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&ah->ah_sc->sc_pm_lock, flags); + ret = ath9k_hw_setpower_nolock(ah, mode); + spin_unlock_irqrestore(&ah->ah_sc->sc_pm_lock, flags); + + return ret; +} + /* * Helper for ASPM support. * diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 90cecce8d5ff..d14f8c9cef68 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1316,6 +1316,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->ani_lock); + spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, -- cgit v1.2.2 From 0bc0798b7605664c3ab8d577b398dc7ae0b2e58c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 14 Jul 2009 20:17:14 -0400 Subject: ath9k: uninline ath9k_ps_{wakeup,restore} functions Uninline these functions before we add functional changes to them. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 23 ++--------------------- drivers/net/wireless/ath/ath9k/hw.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b37eb592b524..8b38c0a5d7e6 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -674,27 +674,8 @@ static inline int ath_ahb_init(void) { return 0; }; static inline void ath_ahb_exit(void) {}; #endif -static inline void ath9k_ps_wakeup(struct ath_softc *sc) -{ - if (atomic_inc_return(&sc->ps_usecount) == 1) - if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { - sc->sc_ah->restore_mode = sc->sc_ah->power_mode; - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - } -} - -static inline void ath9k_ps_restore(struct ath_softc *sc) -{ - if (atomic_dec_and_test(&sc->ps_usecount)) - if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && - !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK))) - ath9k_hw_setpower(sc->sc_ah, - sc->sc_ah->restore_mode); -} - +void ath9k_ps_wakeup(struct ath_softc *sc); +void ath9k_ps_restore(struct ath_softc *sc); void ath9k_set_bssid_mask(struct ieee80211_hw *hw); int ath9k_wiphy_add(struct ath_softc *sc); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6740a6b98a62..df278fd807b8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2775,6 +2775,27 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) return ret; } +void ath9k_ps_wakeup(struct ath_softc *sc) +{ + if (atomic_inc_return(&sc->ps_usecount) == 1) + if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { + sc->sc_ah->restore_mode = sc->sc_ah->power_mode; + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + } +} + +void ath9k_ps_restore(struct ath_softc *sc) +{ + if (atomic_dec_and_test(&sc->ps_usecount)) + if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && + !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | + SC_OP_WAIT_FOR_CAB | + SC_OP_WAIT_FOR_PSPOLL_DATA | + SC_OP_WAIT_FOR_TX_ACK))) + ath9k_hw_setpower(sc->sc_ah, + sc->sc_ah->restore_mode); +} + /* * Helper for ASPM support. * -- cgit v1.2.2 From 709ade9eb8ef06e03526115408e2fc93a9feabbd Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 14 Jul 2009 20:17:15 -0400 Subject: ath9k: serialize ath9k_ps_{wakeup,restore} calls These functions are changing the power mode of the chip, but this may have unpredictable effects, if another code are trying to set the power mode via 'ath9k_hw_setpower' in the same time from another context. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/hw.c | 42 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8b38c0a5d7e6..157681241733 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -576,7 +576,7 @@ struct ath_softc { u32 keymax; DECLARE_BITMAP(keymap, ATH_KEYMAX); u8 splitmic; - atomic_t ps_usecount; + unsigned long ps_usecount; enum ath9k_int imask; enum ath9k_ht_extprotspacing ht_extprotspacing; enum ath9k_ht_macmode tx_chan_width; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index df278fd807b8..b9d1a13ba164 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2777,23 +2777,39 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) void ath9k_ps_wakeup(struct ath_softc *sc) { - if (atomic_inc_return(&sc->ps_usecount) == 1) - if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { - sc->sc_ah->restore_mode = sc->sc_ah->power_mode; - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - } + unsigned long flags; + + spin_lock_irqsave(&sc->sc_pm_lock, flags); + if (++sc->ps_usecount != 1) + goto unlock; + + if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { + sc->sc_ah->restore_mode = sc->sc_ah->power_mode; + ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE); + } + + unlock: + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); } void ath9k_ps_restore(struct ath_softc *sc) { - if (atomic_dec_and_test(&sc->ps_usecount)) - if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && - !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK))) - ath9k_hw_setpower(sc->sc_ah, - sc->sc_ah->restore_mode); + unsigned long flags; + + spin_lock_irqsave(&sc->sc_pm_lock, flags); + if (--sc->ps_usecount != 0) + goto unlock; + + if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && + !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | + SC_OP_WAIT_FOR_CAB | + SC_OP_WAIT_FOR_PSPOLL_DATA | + SC_OP_WAIT_FOR_TX_ACK))) + ath9k_hw_setpower_nolock(sc->sc_ah, + sc->sc_ah->restore_mode); + + unlock: + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); } /* -- cgit v1.2.2 From 64839170be296e6348fbaf83fd103711978669b9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 14 Jul 2009 20:22:53 -0400 Subject: ath9k: disable radio when all devices are marked idle This uses the new configuration changes indicated up by mac80211 when all interfaces are marked idle. We need to do a little more work as we have our own set of virtual wiphys within ath9k. Only when all virtual wiphys are inactive do we allow an idle state change for a wiphy to trigger disabling the radio. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 24 ++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/virtual.c | 17 +++++++++++++++++ 3 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 157681241733..751885a5df47 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -691,6 +691,7 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, struct ath_wiphy *selected); bool ath9k_wiphy_scanning(struct ath_softc *sc); void ath9k_wiphy_work(struct work_struct *work); +bool ath9k_all_wiphys_idle(struct ath_softc *sc); void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d14f8c9cef68..254e78786eee 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2260,9 +2260,28 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ath_softc *sc = aphy->sc; struct ieee80211_conf *conf = &hw->conf; struct ath_hw *ah = sc->sc_ah; + bool all_wiphys_idle = false, disable_radio = false; mutex_lock(&sc->mutex); + /* Leave this as the first check */ + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + + spin_lock_bh(&sc->wiphy_lock); + all_wiphys_idle = ath9k_all_wiphys_idle(sc); + spin_unlock_bh(&sc->wiphy_lock); + + if (conf->flags & IEEE80211_CONF_IDLE){ + if (all_wiphys_idle) + disable_radio = true; + } + else if (all_wiphys_idle) { + ath_radio_enable(sc); + DPRINTF(sc, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); + } + } + if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { if (!(ah->caps.hw_caps & @@ -2330,6 +2349,11 @@ skip_chan_change: if (changed & IEEE80211_CONF_CHANGE_POWER) sc->config.txpowlimit = 2 * conf->power_level; + if (disable_radio) { + DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n"); + ath_radio_disable(sc); + } + mutex_unlock(&sc->mutex); return 0; diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 1ff429b027d7..e1d419e02b4a 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -660,3 +660,20 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, sc->wiphy_scheduler_int); } + +/* caller must hold wiphy_lock */ +bool ath9k_all_wiphys_idle(struct ath_softc *sc) +{ + unsigned int i; + if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { + return false; + } + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + if (!aphy) + continue; + if (aphy->state != ATH_WIPHY_INACTIVE) + return false; + } + return true; +} -- cgit v1.2.2 From 04dc882d601ec6fae5dfcb47c43f7af343e9a135 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 15 Jul 2009 08:51:17 +0530 Subject: ath9k: Add AR9287 based chipsets' register information. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 93 ++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 52605246679f..8302aeb62e5d 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -574,6 +574,7 @@ #define AR_D_GBL_IFS_SIFS 0x1030 #define AR_D_GBL_IFS_SIFS_M 0x0000FFFF +#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB #define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF #define AR_D_TXBLK_BASE 0x1038 @@ -589,10 +590,12 @@ #define AR_D_GBL_IFS_SLOT 0x1070 #define AR_D_GBL_IFS_SLOT_M 0x0000FFFF #define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 +#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420 #define AR_D_GBL_IFS_EIFS 0x10b0 #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 +#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB #define AR_D_GBL_IFS_MISC 0x10f0 #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 @@ -738,6 +741,9 @@ #define AR_SREV_REVISION_9285_10 0 #define AR_SREV_REVISION_9285_11 1 #define AR_SREV_REVISION_9285_12 2 +#define AR_SREV_VERSION_9287 0x180 +#define AR_SREV_REVISION_9287_10 0 +#define AR_SREV_REVISION_9287_11 1 #define AR_SREV_5416(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -794,6 +800,21 @@ (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ AR_SREV_REVISION_9285_12))) +#define AR_SREV_9287(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287)) +#define AR_SREV_9287_10_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287)) +#define AR_SREV_9287_10(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10)) +#define AR_SREV_9287_11(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11)) +#define AR_SREV_9287_11_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) + #define AR_RADIO_SREV_MAJOR 0xf0 #define AR_RAD5133_SREV_MAJOR 0xc0 #define AR_RAD2133_SREV_MAJOR 0xd0 @@ -809,6 +830,9 @@ #define AR_AHB_PAGE_SIZE_1K 0x00000000 #define AR_AHB_PAGE_SIZE_2K 0x00000008 #define AR_AHB_PAGE_SIZE_4K 0x00000010 +#define AR_AHB_CUSTOM_BURST_EN 0x000000C0 +#define AR_AHB_CUSTOM_BURST_EN_S 6 +#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3 #define AR_INTR_RTC_IRQ 0x00000001 #define AR_INTR_MAC_IRQ 0x00000002 @@ -885,6 +909,7 @@ enum { #define AR_NUM_GPIO 14 #define AR928X_NUM_GPIO 10 #define AR9285_NUM_GPIO 12 +#define AR9287_NUM_GPIO 11 #define AR_GPIO_IN_OUT 0x4048 #define AR_GPIO_IN_VAL 0x0FFFC000 @@ -893,6 +918,8 @@ enum { #define AR928X_GPIO_IN_VAL_S 10 #define AR9285_GPIO_IN_VAL 0x00FFF000 #define AR9285_GPIO_IN_VAL_S 12 +#define AR9287_GPIO_IN_VAL 0x003FF800 +#define AR9287_GPIO_IN_VAL_S 11 #define AR_GPIO_OE_OUT 0x404c #define AR_GPIO_OE_OUT_DRV 0x3 @@ -1154,6 +1181,33 @@ enum { #define AR9285_AN_TOP4 0x7870 #define AR9285_AN_TOP4_DEFAULT 0x10142c00 +#define AR9287_AN_RF2G3_CH0 0x7808 +#define AR9287_AN_RF2G3_CH1 0x785c +#define AR9287_AN_RF2G3_DB1 0xE0000000 +#define AR9287_AN_RF2G3_DB1_S 29 +#define AR9287_AN_RF2G3_DB2 0x1C000000 +#define AR9287_AN_RF2G3_DB2_S 26 +#define AR9287_AN_RF2G3_OB_CCK 0x03800000 +#define AR9287_AN_RF2G3_OB_CCK_S 23 +#define AR9287_AN_RF2G3_OB_PSK 0x00700000 +#define AR9287_AN_RF2G3_OB_PSK_S 20 +#define AR9287_AN_RF2G3_OB_QAM 0x000E0000 +#define AR9287_AN_RF2G3_OB_QAM_S 17 +#define AR9287_AN_RF2G3_OB_PAL_OFF 0x0001C000 +#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14 + +#define AR9287_AN_TXPC0 0x7898 +#define AR9287_AN_TXPC0_TXPCMODE 0x0000C000 +#define AR9287_AN_TXPC0_TXPCMODE_S 14 +#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0 +#define AR9287_AN_TXPC0_TXPCMODE_TEST 1 +#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2 +#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3 + +#define AR9287_AN_TOP2 0x78b4 +#define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000 +#define AR9287_AN_TOP2_XPABIAS_LVL_S 30 + #define AR_STA_ID0 0x8000 #define AR_STA_ID1 0x8004 #define AR_STA_ID1_SADH_MASK 0x0000FFFF @@ -1188,6 +1242,7 @@ enum { #define AR_TIME_OUT_ACK_S 0 #define AR_TIME_OUT_CTS 0x3FFF0000 #define AR_TIME_OUT_CTS_S 16 +#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56 #define AR_RSSI_THR 0x8018 #define AR_RSSI_THR_MASK 0x000000FF @@ -1203,6 +1258,7 @@ enum { #define AR_USEC_TX_LAT_S 14 #define AR_USEC_RX_LAT 0x1F800000 #define AR_USEC_RX_LAT_S 23 +#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074 #define AR_RESET_TSF 0x8020 #define AR_RESET_TSF_ONCE 0x01000000 @@ -1468,6 +1524,10 @@ enum { #define AR_SLP_MIB_CLEAR 0x00000001 #define AR_SLP_MIB_PENDING 0x00000002 +#define AR_MAC_PCU_LOGIC_ANALYZER 0x8264 +#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000 + + #define AR_2040_MODE 0x8318 #define AR_2040_JOINED_RX_CLEAR 0x00000001 @@ -1485,6 +1545,39 @@ enum { #define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 #define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 +#define AR_PCU_MISC_MODE2_RESERVED 0x00000038 +#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040 +#define AR_PCU_MISC_MODE2_CFP_IGNORE 0x00000080 +#define AR_PCU_MISC_MODE2_MGMT_QOS 0x0000FF00 +#define AR_PCU_MISC_MODE2_MGMT_QOS_S 8 +#define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DURATION 0x00010000 +#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000 +#define AR_PCU_MISC_MODE2_HWWAR1 0x00100000 +#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000 +#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000 + +#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358 +#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400 +#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 + + +#define AR_AES_MUTE_MASK0 0x805c +#define AR_AES_MUTE_MASK0_FC 0x0000FFFF +#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 +#define AR_AES_MUTE_MASK0_QOS_S 16 + +#define AR_AES_MUTE_MASK1 0x8060 +#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF +#define AR_AES_MUTE_MASK1_SEQ_S 0 +#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 +#define AR_AES_MUTE_MASK1_FC_MGMT_S 16 + +#define AR_RATE_DURATION_0 0x8700 +#define AR_RATE_DURATION_31 0x87CC +#define AR_RATE_DURATION_32 0x8780 +#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2)) + + #define AR_KEYTABLE_0 0x8800 #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) #define AR_KEY_CACHE_SIZE 128 -- cgit v1.2.2 From e91d83346ad9b30f44469c92b982206dcd7dcaf0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 Jul 2009 17:21:41 +0200 Subject: wireless: remove print_mac uses Use %pM instead, and also remove stray variables declared with DECLARE_MAC_BUF. Signed-off-by: Johannes Berg Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/main.c | 1 - drivers/net/wireless/b43/main.c | 4 +--- drivers/net/wireless/libertas/assoc.c | 10 +++------- drivers/net/wireless/mac80211_hwsim.c | 2 -- drivers/net/wireless/mwl8k.c | 6 ++---- drivers/net/wireless/rt2x00/rt2800usb.c | 4 +--- drivers/net/wireless/wl12xx/wl1251_main.c | 5 ++--- 7 files changed, 9 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index cfe6fc78067a..c7287a883a48 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2628,7 +2628,6 @@ static int ar9170_read_eeprom(struct ar9170 *ar) { #define RW 8 /* number of words to read at once */ #define RB (sizeof(u32) * RW) - DECLARE_MAC_BUF(mbuf); u8 *eeprom = (void *)&ar->eeprom; u8 *addr = ar->eeprom.mac_address; __le32 offsets[RW]; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e71c8d9cd706..3f4360ad0e4e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -938,7 +938,6 @@ static void b43_clear_keys(struct b43_wldev *dev) static void b43_dump_keymemory(struct b43_wldev *dev) { unsigned int i, index, offset; - DECLARE_MAC_BUF(macbuf); u8 mac[ETH_ALEN]; u16 algo; u32 rcmta0; @@ -973,8 +972,7 @@ static void b43_dump_keymemory(struct b43_wldev *dev) ((index - 4) * 2) + 1); *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); - printk(" MAC: %s", - print_mac(macbuf, mac)); + printk(" MAC: %pM", mac); } else printk(" DEFAULT KEY"); printk("\n"); diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index fbf26499c9a9..385b50f4b105 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -129,7 +129,6 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth { struct cmd_ds_802_11_authenticate cmd; int ret = -1; - DECLARE_MAC_BUF(mac); lbs_deb_enter(LBS_DEB_JOIN); @@ -138,8 +137,7 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth cmd.authtype = iw_auth_to_ieee_auth(auth); - lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", - print_mac(mac, bssid), cmd.authtype); + lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype); ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); @@ -342,8 +340,6 @@ static int lbs_associate(struct lbs_private *priv, /* Firmware v9+ indicate authentication suites as a TLV */ if (priv->fwrelease >= 0x09000000) { - DECLARE_MAC_BUF(mac); - auth = (struct mrvl_ie_auth_type *) pos; auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); auth->header.len = cpu_to_le16(2); @@ -351,8 +347,8 @@ static int lbs_associate(struct lbs_private *priv, auth->auth = cpu_to_le16(tmpauth); pos += sizeof(auth->header) + 2; - lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", - print_mac(mac, bss->bssid), priv->secinfo.auth_mode); + lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", + bss->bssid, priv->secinfo.auth_mode); } /* WPA/WPA2 IEs */ diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 78431abc8b40..930f5c7da4a6 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -837,7 +837,6 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) { struct mac80211_hwsim_data *data = dat; struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - DECLARE_MAC_BUF(buf); struct sk_buff *skb; struct ieee80211_pspoll *pspoll; @@ -867,7 +866,6 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, struct ieee80211_vif *vif, int ps) { struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - DECLARE_MAC_BUF(buf); struct sk_buff *skb; struct ieee80211_hdr *hdr; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b9eded88c322..4f725473fb73 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2271,7 +2271,6 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, struct mwl8k_cmd_update_sta_db *cmd; struct peer_capability_info *peer_info; struct ieee80211_rate *bitrates = mv_vif->legacy_rates; - DECLARE_MAC_BUF(mac); int rc; __u8 count, *rates; @@ -3480,7 +3479,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, { struct ieee80211_hw *hw; struct mwl8k_priv *priv; - DECLARE_MAC_BUF(mac); int rc; int i; u8 *fw; @@ -3669,8 +3667,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, MWL8K_DESC); printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n", priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]); - printk(KERN_INFO "%s: MAC Address: %s\n", priv->name, - print_mac(mac, hw->wiphy->perm_addr)); + printk(KERN_INFO "%s: MAC Address: %pM\n", priv->name, + hw->wiphy->perm_addr); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 66e001c392b0..f35b3d6649c8 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -2220,10 +2220,8 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - DECLARE_MAC_BUF(macbuf); - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); + EEPROM(rt2x00dev, "MAC: %pM\n", mac); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 106b0f265192..509cbef5e271 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -435,11 +435,10 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct wl1251 *wl = hw->priv; - DECLARE_MAC_BUF(mac); int ret = 0; - wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s", - conf->type, print_mac(mac, conf->mac_addr)); + wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", + conf->type, conf->mac_addr); mutex_lock(&wl->mutex); -- cgit v1.2.2 From ea9edaf6bc0e3f3a7bd167d9ba369276a30c9953 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 15 Jul 2009 22:49:27 -0500 Subject: hostap_cs: Enable shared interrupts The hostap_cs driver is programmed for exclusive rather that shared interrupts. Signed-off-by: Larry Finger Reported-and-Tested-by: Jack Schneider Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 633740277352..ad8eab4a639b 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -666,7 +666,8 @@ static int prism2_config(struct pcmcia_device *link) * irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) { - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | + IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = prism2_interrupt; link->irq.Instance = dev; -- cgit v1.2.2 From 1cc589b9e7d95888bb8cc806c210d8ab5371d40f Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:06 +0800 Subject: iwmc3200wifi: fix UMAC INIT_COMPLETE notification handling The patch fixes the missing UMAC iwm_umac_wifi_in_hdr header in the UMAC INIT_COMPLETE (iwm_umac_notif_init_complete) notification. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 1 - drivers/net/wireless/iwmc3200wifi/umac.h | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 3909477fb3bf..59ef69ca3ca7 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -102,7 +102,6 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, error = (struct iwm_umac_notif_error *)buf; fw_err = &error->err; - IWM_ERR(iwm, "%cMAC FW ERROR:\n", (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index 0af2a3c76281..c5a14ae3160a 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h @@ -615,6 +615,7 @@ struct iwm_umac_notif_alive { } __attribute__ ((packed)); struct iwm_umac_notif_init_complete { + struct iwm_umac_wifi_in_hdr hdr; __le16 status; __le16 reserved; } __attribute__ ((packed)); @@ -643,6 +644,11 @@ struct iwm_fw_error_hdr { __le32 umac_status; __le32 lmac_status; __le32 sdio_status; + __le32 dbm_sample_ctrl; + __le32 dbm_buf_base; + __le32 dbm_buf_end; + __le32 dbm_buf_write_ptr; + __le32 dbm_buf_cycle_cnt; } __attribute__ ((packed)); struct iwm_umac_notif_error { -- cgit v1.2.2 From 3a0e4851c97328ee455a57cb3e4097bb43934a87 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:07 +0800 Subject: iwmc3200wifi: hardware does not support IP checksum The iwmc3200wifi hardware doesn't support IP checksum. So mark the skb->ip_summed to CHECKSUM_NONE instead of CHECKSUM_UNNECESSARY. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 59ef69ca3ca7..9fb498b514e1 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1359,7 +1359,7 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, skb->dev = iwm_to_ndev(iwm); skb->protocol = eth_type_trans(skb, ndev); - skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->ip_summed = CHECKSUM_NONE; memset(skb->cb, 0, sizeof(skb->cb)); ndev->stats.rx_packets++; -- cgit v1.2.2 From 49b7772776359b8306ce740bfc52d32b344adc83 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:08 +0800 Subject: iwmc3200wifi: set cipher_suites before registering wiphy We need to specify all the cipher suites we supported. Otherwise cfg80211_validate_key_settings() will fail when we are setting keys. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 54bebba8e27e..0aa389564c71 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -558,6 +558,13 @@ static struct cfg80211_ops iwm_cfg80211_ops = { .set_power_mgmt = iwm_cfg80211_set_power_mgmt, }; +static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) { int ret = 0; @@ -600,6 +607,9 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + ret = wiphy_register(wdev->wiphy); if (ret < 0) { dev_err(dev, "Couldn't register wiphy device\n"); -- cgit v1.2.2 From 4fdd81f5f2e6fc55b67938f09b3495d679428cd7 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:09 +0800 Subject: iwmc3200wifi: use correct debug level This patch uses TX and RX instead of NTF debug levels in some hot paths. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 9fb498b514e1..218933b8800b 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -218,17 +218,17 @@ static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf, (buf + sizeof(struct iwm_umac_wifi_in_hdr)); hdr = (struct iwm_umac_wifi_in_hdr *)buf; - IWM_DBG_NTF(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); - - IWM_DBG_NTF(iwm, DBG, "Seqnum: %d\n", - le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); - IWM_DBG_NTF(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); - IWM_DBG_NTF(iwm, DBG, "\tRetry cnt: %d\n", - le16_to_cpu(tx_resp->retry_cnt)); - IWM_DBG_NTF(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); - IWM_DBG_NTF(iwm, DBG, "\tByte cnt: %d\n", - le16_to_cpu(tx_resp->byte_cnt)); - IWM_DBG_NTF(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); + IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); + + IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n", + le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); + IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); + IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n", + le16_to_cpu(tx_resp->retry_cnt)); + IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); + IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n", + le16_to_cpu(tx_resp->byte_cnt)); + IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); return 0; } @@ -418,8 +418,8 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, if (IS_ERR(ticket_node)) return PTR_ERR(ticket_node); - IWM_DBG_NTF(iwm, DBG, "TICKET RELEASE(%d)\n", - ticket->id); + IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n", + ticket->id); list_add_tail(&ticket_node->node, &iwm->rx_tickets); /* @@ -454,15 +454,15 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, u16 id, buf_offset; u32 packet_size; - IWM_DBG_NTF(iwm, DBG, "\n"); + IWM_DBG_RX(iwm, DBG, "\n"); wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); buf_offset = sizeof(struct iwm_umac_wifi_in_hdr); packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr); - IWM_DBG_NTF(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", - wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); + IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", + wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id); IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size); -- cgit v1.2.2 From 9967d46aa5ba065650d3352ab5d906f56ba17648 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 16 Jul 2009 17:34:10 +0800 Subject: iwmc3200wifi: cfg80211 managed mode port This patch ports iwmc3200wifi to the cfg80211 managed mode API. Signed-off-by: Samuel Ortiz Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 195 ++++++++++++++++ drivers/net/wireless/iwmc3200wifi/rx.c | 16 +- drivers/net/wireless/iwmc3200wifi/wext.c | 320 +++------------------------ 3 files changed, 239 insertions(+), 292 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 0aa389564c71..ee4031764389 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -305,6 +305,25 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, return iwm_reset_profile(iwm); } +int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + + if (memcmp(mac, iwm->bssid, ETH_ALEN)) + return -ENOENT; + + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = iwm->rate * 10; + + if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = iwm->wstats.qual.level; + } + + return 0; +} + int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) { @@ -500,6 +519,179 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) return 0; } +static int iwm_set_auth_type(struct iwm_priv *iwm, + enum nl80211_auth_type sme_auth_type) +{ + u8 *auth_type = &iwm->umac_profile->sec.auth_type; + + switch (sme_auth_type) { + case NL80211_AUTHTYPE_AUTOMATIC: + case NL80211_AUTHTYPE_OPEN_SYSTEM: + IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n"); + *auth_type = UMAC_AUTH_TYPE_OPEN; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + if (iwm->umac_profile->sec.flags & + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { + IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n"); + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; + } else { + IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n"); + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; + } + + break; + default: + IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type); + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) +{ + if (!wpa_version) { + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; + return 0; + } + + if (wpa_version & NL80211_WPA_VERSION_2) + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; + + if (wpa_version & NL80211_WPA_VERSION_1) + iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK; + + return 0; +} + +static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) +{ + u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : + &iwm->umac_profile->sec.mcast_cipher; + + if (!cipher) { + *profile_cipher = UMAC_CIPHER_TYPE_NONE; + return 0; + } + + switch (cipher) { + case IW_AUTH_CIPHER_NONE: + *profile_cipher = UMAC_CIPHER_TYPE_NONE; + break; + case WLAN_CIPHER_SUITE_WEP40: + *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; + break; + case WLAN_CIPHER_SUITE_WEP104: + *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; + break; + case WLAN_CIPHER_SUITE_TKIP: + *profile_cipher = UMAC_CIPHER_TYPE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + *profile_cipher = UMAC_CIPHER_TYPE_CCMP; + break; + default: + IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt) +{ + u8 *auth_type = &iwm->umac_profile->sec.auth_type; + + IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); + + if (key_mgt == WLAN_AKM_SUITE_8021X) + *auth_type = UMAC_AUTH_TYPE_8021X; + else if (key_mgt == WLAN_AKM_SUITE_PSK) { + if (iwm->umac_profile->sec.flags & + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; + else + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; + } else { + IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); + return -EINVAL; + } + + return 0; +} + + +static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + struct ieee80211_channel *chan = sme->channel; + int ret; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return -EIO; + + if (!sme->ssid) + return -EINVAL; + + if (chan) + iwm->channel = + ieee80211_frequency_to_channel(chan->center_freq); + + iwm->umac_profile->ssid.ssid_len = sme->ssid_len; + memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len); + + if (sme->bssid) { + IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid); + memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN); + iwm->umac_profile->bss_num = 1; + } else { + memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); + iwm->umac_profile->bss_num = 0; + } + + ret = iwm_set_auth_type(iwm, sme->auth_type); + if (ret < 0) + return ret; + + ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); + if (ret < 0) + return ret; + + if (sme->crypto.n_ciphers_pairwise) { + ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0], + true); + if (ret < 0) + return ret; + } + + ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false); + if (ret < 0) + return ret; + + if (sme->crypto.n_akm_suites) { + ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]); + if (ret < 0) + return ret; + } + + return iwm_send_mlme_profile(iwm); +} + +static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); + + if (iwm->umac_profile_active) + return iwm_invalidate_mlme_profile(iwm); + + return 0; +} + static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, enum tx_power_setting type, int dbm) { @@ -549,8 +741,11 @@ static struct cfg80211_ops iwm_cfg80211_ops = { .get_key = iwm_cfg80211_get_key, .del_key = iwm_cfg80211_del_key, .set_default_key = iwm_cfg80211_set_default_key, + .get_station = iwm_cfg80211_get_station, .scan = iwm_cfg80211_scan, .set_wiphy_params = iwm_cfg80211_set_wiphy_params, + .connect = iwm_cfg80211_connect, + .disconnect = iwm_cfg80211_disconnect, .join_ibss = iwm_cfg80211_join_ibss, .leave_ibss = iwm_cfg80211_leave_ibss, .set_tx_power = iwm_cfg80211_set_txpower, diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 218933b8800b..82b572a6fc0b 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -503,13 +503,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, { struct iwm_umac_notif_assoc_complete *complete = (struct iwm_umac_notif_assoc_complete *)buf; - union iwreq_data wrqu; IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", complete->bssid, complete->status); - memset(&wrqu, 0, sizeof(wrqu)); - clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); switch (le32_to_cpu(complete->status)) { @@ -520,7 +517,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm_link_on(iwm); - memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN); + cfg80211_connect_result(iwm_to_ndev(iwm), + complete->bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_SUCCESS, GFP_KERNEL); break; case UMAC_ASSOC_COMPLETE_FAILURE: clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); @@ -528,6 +528,11 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm->channel = 0; iwm_link_off(iwm); + + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); default: break; } @@ -537,9 +542,6 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, return 0; } - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL); - return 0; } diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 2e7eaf96cf93..c3c90d5963bf 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -21,31 +21,11 @@ * */ -#include -#include #include -#include -#include #include -#include #include "iwm.h" -#include "umac.h" #include "commands.h" -#include "debug.h" - -static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - struct iw_statistics *wstats = &iwm->wstats; - - if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { - memset(wstats, 0, sizeof(struct iw_statistics)); - wstats->qual.updated = IW_QUAL_ALL_INVALID; - } - - return wstats; -} static int iwm_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, @@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_device *dev, { struct iwm_priv *iwm = ndev_to_iwm(dev); - if (freq->flags == IW_FREQ_AUTO) - return 0; - - /* frequency/channel can only be set in IBSS mode */ - if (iwm->conf.mode != UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: + return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); + default: return -EOPNOTSUPP; - - return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); + } } static int iwm_wext_giwfreq(struct net_device *dev, @@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_device *dev, { struct iwm_priv *iwm = ndev_to_iwm(dev); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); - - freq->e = 0; - freq->m = iwm->channel; - - return 0; + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); + default: + return -EOPNOTSUPP; + } } static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) { struct iwm_priv *iwm = ndev_to_iwm(dev); - int ret; - - IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - if (is_zero_ether_addr(ap_addr->sa_data) || - is_broadcast_ether_addr(ap_addr->sa_data)) { - IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n", - iwm->umac_profile->bssid[0]); - memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); - iwm->umac_profile->bss_num = 0; - } else { - IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n", - ap_addr->sa_data); - memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data, - ETH_ALEN); - iwm->umac_profile->bss_num = 1; - } - - if (iwm->umac_profile_active) { - int i; - - if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN)) - return 0; - - /* - * If we're clearing the BSSID, and we're associated, - * we have to clear the keys as they're no longer valid. - */ - if (is_zero_ether_addr(ap_addr->sa_data)) { - for (i = 0; i < IWM_NUM_KEYS; i++) - iwm->keys[i].key_len = 0; - } - - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); + default: + return -EOPNOTSUPP; } - - if (iwm->umac_profile->ssid.ssid_len) - return iwm_send_mlme_profile(iwm); - - return 0; } static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, @@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, case UMAC_MODE_IBSS: return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); case UMAC_MODE_BSS: - if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN); - } else - memset(&ap_addr->sa_data, 0, ETH_ALEN); - break; + return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); default: return -EOPNOTSUPP; } - - return 0; } static int iwm_wext_siwessid(struct net_device *dev, @@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_device *dev, struct iw_point *data, char *ssid) { struct iwm_priv *iwm = ndev_to_iwm(dev); - size_t len = data->length; - int ret; - - IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - if (len > 0 && ssid[len - 1] == '\0') - len--; - - if (iwm->umac_profile_active) { - if (iwm->umac_profile->ssid.ssid_len == len && - !memcmp(iwm->umac_profile->ssid.ssid, ssid, len)) - return 0; - - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); + default: + return -EOPNOTSUPP; } - - iwm->umac_profile->ssid.ssid_len = len; - memcpy(iwm->umac_profile->ssid.ssid, ssid, len); - - return iwm_send_mlme_profile(iwm); } static int iwm_wext_giwessid(struct net_device *dev, @@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_device *dev, { struct iwm_priv *iwm = ndev_to_iwm(dev); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - data->length = iwm->umac_profile->ssid.ssid_len; - if (data->length) { - memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length); - data->flags = 1; - } else - data->flags = 0; - - return 0; -} - -static int iwm_wext_giwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rate, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - rate->value = iwm->rate * 1000000; - - return 0; -} - -static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) -{ - if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; - else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK; - else - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; - - return 0; -} - -static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) -{ - u8 *auth_type = &iwm->umac_profile->sec.auth_type; - - IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); - - if (key_mgt == IW_AUTH_KEY_MGMT_802_1X) - *auth_type = UMAC_AUTH_TYPE_8021X; - else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) { - if (iwm->umac_profile->sec.flags & - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; - else - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; - } else { - IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); - return -EINVAL; - } - - return 0; -} - -static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast) -{ - u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : - &iwm->umac_profile->sec.mcast_cipher; - - switch (cipher) { - case IW_AUTH_CIPHER_NONE: - *profile_cipher = UMAC_CIPHER_TYPE_NONE; - break; - case IW_AUTH_CIPHER_WEP40: - *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; - break; - case IW_AUTH_CIPHER_TKIP: - *profile_cipher = UMAC_CIPHER_TYPE_TKIP; - break; - case IW_AUTH_CIPHER_CCMP: - *profile_cipher = UMAC_CIPHER_TYPE_CCMP; - break; - case IW_AUTH_CIPHER_WEP104: - *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; - break; - default: - IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); - return -ENOTSUPP; - } - - return 0; -} - -static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg) -{ - u8 *auth_type = &iwm->umac_profile->sec.auth_type; - - IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg); - - switch (auth_alg) { - case IW_AUTH_ALG_OPEN_SYSTEM: - *auth_type = UMAC_AUTH_TYPE_OPEN; - break; - case IW_AUTH_ALG_SHARED_KEY: - if (iwm->umac_profile->sec.flags & - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { - if (*auth_type == UMAC_AUTH_TYPE_8021X) - return -EINVAL; - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; - } else { - IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n"); - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; - } - break; - case IW_AUTH_ALG_LEAP: - default: - IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg); - return -ENOTSUPP; - } - - return 0; -} - -static int iwm_wext_siwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - int ret; - - if ((data->flags) & - (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT | - IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) { - /* We need to invalidate the current profile */ - if (iwm->umac_profile_active) { - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } - } - } - - switch (data->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - return iwm_set_wpa_version(iwm, data->value); - break; - case IW_AUTH_CIPHER_PAIRWISE: - return iwm_set_cipher(iwm, data->value, 1); - break; - case IW_AUTH_CIPHER_GROUP: - return iwm_set_cipher(iwm, data->value, 0); - break; - case IW_AUTH_KEY_MGMT: - return iwm_set_key_mgt(iwm, data->value); - break; - case IW_AUTH_80211_AUTH_ALG: - return iwm_set_auth_alg(iwm, data->value); - break; + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); default: - return -ENOTSUPP; + return -EOPNOTSUPP; } - - return 0; -} - -static int iwm_wext_giwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - return 0; } static const iw_handler iwm_handlers[] = @@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] = (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* SIOCSIWRATE */ - (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */ + (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ @@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] = (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWGENIE */ + (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */ - (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */ + (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ + (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ (iw_handler) NULL, /* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ @@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] = const struct iw_handler_def iwm_iw_handler_def = { .num_standard = ARRAY_SIZE(iwm_handlers), .standard = (iw_handler *) iwm_handlers, - .get_wireless_stats = iwm_get_wireless_stats, + .get_wireless_stats = cfg80211_wireless_stats, }; -- cgit v1.2.2 From 0e371f1a0c0acd4abfa052b01e7b1f4a71ef6590 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:11 +0800 Subject: iwmc3200wifi: remove setting WEP keys before setting essid support The recent cfg80211 "rework key operation" patch from Johannes Berg makes sure keys are set only after the connection has been established. So we can remove the setting WEP keys before essid support from the driver. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index ee4031764389..0372658bac99 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -203,32 +203,6 @@ static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, return ret; } - /* - * The WEP keys can be set before or after setting the essid. - * We need to handle both cases by simply pushing the keys after - * we send the profile. - * If the profile is not set yet (i.e. we're pushing keys before - * the essid), we set the cipher appropriately. - * If the profile is set, we havent associated yet because our - * cipher was incorrectly set. So we invalidate and send the - * profile again. - */ - if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || - key->cipher == WLAN_CIPHER_SUITE_WEP104) { - u8 *ucast_cipher = &iwm->umac_profile->sec.ucast_cipher; - u8 *mcast_cipher = &iwm->umac_profile->sec.mcast_cipher; - - IWM_DBG_WEXT(iwm, DBG, "WEP key\n"); - - if (key->cipher == WLAN_CIPHER_SUITE_WEP40) - *ucast_cipher = *mcast_cipher = UMAC_CIPHER_TYPE_WEP_40; - if (key->cipher == WLAN_CIPHER_SUITE_WEP104) - *ucast_cipher = *mcast_cipher = - UMAC_CIPHER_TYPE_WEP_104; - - return iwm_reset_profile(iwm); - } - return iwm_set_key(iwm, 0, key); } -- cgit v1.2.2 From b6c321718e1376b1a55afc63cce090a2c4573417 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:12 +0800 Subject: iwmc3200wifi: make iwm_send_wifi_if_cmd return 0 on success We used to return the result of wait_event_interruptible_timeout() which is the remaining timeout on success. But this information is not used by any of its callers. So we just return 0 on success. This fixed a erroneous return value bug for iwm_set_key(). Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 0d35afefb61c..e6be29704a1d 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -87,8 +87,7 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), 3 * HZ); - if (!ret) - ret = -EBUSY; + return ret ? 0 : -EBUSY; } return ret; @@ -480,8 +479,10 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, target_cmd.eop = 1; ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); - if (ret < 0) + if (ret < 0) { IWM_ERR(iwm, "Couldn't send READ command\n"); + return ret; + } /* When succeding, the send_target routine returns the seq number */ seq_num = ret; @@ -501,7 +502,7 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, kfree(cmd); - return ret; + return 0; } int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) @@ -511,7 +512,7 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR), mac_align, sizeof(mac_align)); - if (ret < 0) + if (ret) return ret; if (is_valid_ether_addr(mac_align)) @@ -714,7 +715,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) ret = iwm_send_wifi_if_cmd(iwm, &key_remove, sizeof(struct iwm_umac_key_remove), 1); - if (ret < 0) + if (ret) return ret; iwm->keys[key_idx].key_len = 0; @@ -736,7 +737,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) sizeof(struct iwm_umac_wifi_if)); ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1); - if (ret < 0) { + if (ret) { IWM_ERR(iwm, "Send profile command failed\n"); return ret; } @@ -752,12 +753,12 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) 3 * HZ); ret = iwm_set_key(iwm, 0, key); - if (ret < 0) + if (ret) return ret; if (iwm->default_key == i) { ret = iwm_set_tx_key(iwm, i); - if (ret < 0) + if (ret) return ret; } } @@ -778,15 +779,13 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) invalid.reason = WLAN_REASON_UNSPECIFIED; ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); - if (ret < 0) + if (ret) return ret; ret = wait_event_interruptible_timeout(iwm->mlme_queue, (iwm->umac_profile_active == 0), 2 * HZ); - if (!ret) - return -EBUSY; - return 0; + return ret ? 0 : -EBUSY; } int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) @@ -869,7 +868,7 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, } ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0); - if (ret < 0) { + if (ret) { IWM_ERR(iwm, "Couldn't send scan request\n"); return ret; } -- cgit v1.2.2 From 6e5db0a8454b44bf88fa74cf437a507ec08f436d Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:13 +0800 Subject: iwmc3200wifi: remove key caches in driver cfg80211 now guarantees keys are set after connecting. We can remove the key cache code from the driver now. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 43 +--------------------------- drivers/net/wireless/iwmc3200wifi/commands.c | 29 +------------------ 2 files changed, 2 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 0372658bac99..3f5a08fa401f 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -158,34 +158,6 @@ static int iwm_key_init(struct iwm_key *key, u8 key_index, return 0; } -static int iwm_reset_profile(struct iwm_priv *iwm) -{ - int ret; - - if (!iwm->umac_profile_active) - return 0; - - /* - * If there is a current active profile, but no - * default key, it's not worth trying to associate again. - */ - if (iwm->default_key < 0) - return 0; - - /* - * Here we have an active profile, but a key setting changed. - * We thus have to invalidate the current profile, and push the - * new one. Keys will be pushed when association takes place. - */ - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } - - return iwm_send_mlme_profile(iwm); -} - static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, const u8 *mac_addr, struct key_params *params) @@ -245,10 +217,6 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, if (key_index == iwm->default_key) iwm->default_key = -1; - /* If the interface is down, we just cache this */ - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return 0; - return iwm_set_key(iwm, 1, key); } @@ -257,7 +225,6 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, u8 key_index) { struct iwm_priv *iwm = ndev_to_iwm(ndev); - int ret; IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); @@ -268,15 +235,7 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, iwm->default_key = key_index; - /* If the interface is down, we just cache this */ - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return 0; - - ret = iwm_set_tx_key(iwm, key_index); - if (ret < 0) - return ret; - - return iwm_reset_profile(iwm); + return iwm_set_tx_key(iwm, key_index); } int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index e6be29704a1d..0d6637005f42 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -584,12 +584,6 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; - /* - * We check if our current profile is valid. - * If not, we dont push the key, we just cache them, - * so that with the next siwsessid call, the keys - * will be actually pushed. - */ if (!remove) { ret = iwm_check_profile(iwm); if (ret < 0) @@ -727,7 +721,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) int iwm_send_mlme_profile(struct iwm_priv *iwm) { - int ret, i; + int ret; struct iwm_umac_profile profile; memcpy(&profile, iwm->umac_profile, sizeof(profile)); @@ -742,27 +736,6 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) return ret; } - for (i = 0; i < IWM_NUM_KEYS; i++) - if (iwm->keys[i].key_len) { - struct iwm_key *key = &iwm->keys[i]; - - /* Wait for the profile before sending the keys */ - wait_event_interruptible_timeout(iwm->mlme_queue, - (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) || - test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)), - 3 * HZ); - - ret = iwm_set_key(iwm, 0, key); - if (ret) - return ret; - - if (iwm->default_key == i) { - ret = iwm_set_tx_key(iwm, i); - if (ret) - return ret; - } - } - return 0; } -- cgit v1.2.2 From 12f49a79cd32d97a11f864a7b67660438ee3e6c8 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 16 Jul 2009 20:03:17 +0200 Subject: p54: remove useless code This patch removes some useless checks in recv/xmit code. Acked-by: Larry Finger Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 01eadb1683fa..416400c4ad03 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -87,9 +87,6 @@ static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) u32 target_addr = priv->rx_start; u16 len = priv->headroom + skb->len + priv->tailroom + 3; - if (unlikely(WARN_ON(!skb || !priv))) - return -EINVAL; - info = IEEE80211_SKB_CB(skb); range = (void *) info->rate_driver_data; len = (range->extra_len + len) & ~0x3; @@ -111,11 +108,6 @@ static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) range = (void *) info->rate_driver_data; hole_size = range->start_addr - last_addr; - if (!entry->next) { - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - return -ENOSPC; - } - if (!target_skb && hole_size >= len) { target_skb = entry->prev; hole_size -= len; @@ -153,9 +145,6 @@ static void p54_tx_pending(struct p54_common *priv) struct sk_buff *skb; int ret; - if (unlikely(WARN_ON(!priv))) - return ; - skb = skb_dequeue(&priv->tx_pending); if (unlikely(!skb)) return ; @@ -219,7 +208,7 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv, static void p54_tx_qos_accounting_free(struct p54_common *priv, struct sk_buff *skb) { - if (skb && IS_DATA_FRAME(skb)) { + if (IS_DATA_FRAME(skb)) { struct p54_hdr *hdr = (void *) skb->data; struct p54_tx_data *data = (void *) hdr->data; unsigned long flags; @@ -266,9 +255,6 @@ static struct sk_buff *p54_find_and_unlink_skb(struct p54_common *priv, void p54_tx(struct p54_common *priv, struct sk_buff *skb) { - if (unlikely(WARN_ON(!priv))) - return ; - skb_queue_tail(&priv->tx_pending, skb); p54_tx_pending(priv); } -- cgit v1.2.2 From 46df10ae44b4488176bae16da0b31541eb0f8f48 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 16 Jul 2009 20:03:47 +0200 Subject: p54: fix beaconing related firmware crash This patch fixes a firmware crash which can be provoked by changing operation mode. Acked-by: Larry Finger Signed-off-by: Christian Lamparter Tested-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/lmac.h | 4 ++++ drivers/net/wireless/p54/main.c | 31 +++++++++++++++++++------------ drivers/net/wireless/p54/p54.h | 1 + drivers/net/wireless/p54/txrx.c | 22 ++++++++++++++-------- 4 files changed, 38 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h index af35cfcd4fe3..04b63ec80fa4 100644 --- a/drivers/net/wireless/p54/lmac.h +++ b/drivers/net/wireless/p54/lmac.h @@ -98,6 +98,10 @@ struct p54_hdr { (!((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \ flags) & cpu_to_le16(P54_HDR_FLAG_CONTROL))) +#define GET_HW_QUEUE(skb) \ + (((struct p54_tx_data *)((struct p54_hdr *) \ + skb->data)->data)->hw_queue) + /* * shared interface ID definitions * The interface ID is a unique identification of a specific interface. diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index f19add2c3cac..955f6d7ec16a 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -130,7 +130,6 @@ static int p54_beacon_update(struct p54_common *priv, struct ieee80211_vif *vif) { struct sk_buff *beacon; - __le32 old_beacon_req_id; int ret; beacon = ieee80211_beacon_get(priv->hw, vif); @@ -140,15 +139,16 @@ static int p54_beacon_update(struct p54_common *priv, if (ret) return ret; - old_beacon_req_id = priv->beacon_req_id; - priv->beacon_req_id = GET_REQ_ID(beacon); - - ret = p54_tx_80211(priv->hw, beacon); - if (ret) { - priv->beacon_req_id = old_beacon_req_id; - return -ENOSPC; - } - + /* + * During operation, the firmware takes care of beaconing. + * The driver only needs to upload a new beacon template, once + * the template was changed by the stack or userspace. + * + * LMAC API 3.2.2 also specifies that the driver does not need + * to cancel the old beacon template by hand, instead the firmware + * will release the previous one through the feedback mechanism. + */ + WARN_ON(p54_tx_80211(priv->hw, beacon)); priv->tsf_high32 = 0; priv->tsf_low32 = 0; @@ -253,9 +253,14 @@ static void p54_remove_interface(struct ieee80211_hw *dev, mutex_lock(&priv->conf_mutex); priv->vif = NULL; - if (priv->beacon_req_id) { + + /* + * LMAC API 3.2.2 states that any active beacon template must be + * canceled by the driver before attempting a mode transition. + */ + if (le32_to_cpu(priv->beacon_req_id) != 0) { p54_tx_cancel(priv, priv->beacon_req_id); - priv->beacon_req_id = cpu_to_le32(0); + wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ); } priv->mode = NL80211_IFTYPE_MONITOR; memset(priv->mac_addr, 0, ETH_ALEN); @@ -544,6 +549,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) BIT(NL80211_IFTYPE_MESH_POINT); dev->channel_change_time = 1000; /* TODO: find actual value */ + priv->beacon_req_id = cpu_to_le32(0); priv->tx_stats[P54_QUEUE_BEACON].limit = 1; priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; priv->tx_stats[P54_QUEUE_MGMT].limit = 3; @@ -567,6 +573,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) mutex_init(&priv->conf_mutex); mutex_init(&priv->eeprom_mutex); init_completion(&priv->eeprom_comp); + init_completion(&priv->beacon_comp); INIT_DELAYED_WORK(&priv->work, p54_work); return dev; diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 584b1560aff0..1afc39410e85 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -211,6 +211,7 @@ struct p54_common { u16 aid; bool powersave_override; __le32 beacon_req_id; + struct completion beacon_comp; /* cryptographic engine information */ u8 privacy_caps; diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 416400c4ad03..0d589d68e547 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -134,9 +134,13 @@ static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) range = (void *) info->rate_driver_data; range->start_addr = target_addr; range->end_addr = target_addr + len; + data->req_id = cpu_to_le32(target_addr + priv->headroom); + if (IS_DATA_FRAME(skb) && + unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) + priv->beacon_req_id = data->req_id; + __skb_queue_after(&priv->tx_queue, target_skb, skb); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - data->req_id = cpu_to_le32(target_addr + priv->headroom); return 0; } @@ -209,13 +213,19 @@ static void p54_tx_qos_accounting_free(struct p54_common *priv, struct sk_buff *skb) { if (IS_DATA_FRAME(skb)) { - struct p54_hdr *hdr = (void *) skb->data; - struct p54_tx_data *data = (void *) hdr->data; unsigned long flags; spin_lock_irqsave(&priv->tx_stats_lock, flags); - priv->tx_stats[data->hw_queue].len--; + priv->tx_stats[GET_HW_QUEUE(skb)].len--; spin_unlock_irqrestore(&priv->tx_stats_lock, flags); + + if (unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) { + if (priv->beacon_req_id == GET_REQ_ID(skb)) { + /* this is the active beacon set anymore */ + priv->beacon_req_id = 0; + } + complete(&priv->beacon_comp); + } } p54_wake_queues(priv); } @@ -403,10 +413,6 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) * and we don't want to confuse the mac80211 stack. */ if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) { - if (entry_data->hw_queue == P54_QUEUE_BEACON && - hdr->req_id == priv->beacon_req_id) - priv->beacon_req_id = cpu_to_le32(0); - dev_kfree_skb_any(entry); return ; } -- cgit v1.2.2 From 436b37c59416d0d8e21430f7980857fc932eb1e6 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 16 Jul 2009 20:05:41 +0200 Subject: p54: fix a fw crash caused by statistic feedback This patch fixes a bug which crawled into the tree with the split-up changes. The memory-manager wasn't aware of the statistic feedback extra_len space requirements and happily placed following frames into the allegedly free spots. Thanks fly out to Larry Finger for taking the time to test all (permutations of) patches and theories all day long. Acked-by: Larry Finger Signed-off-by: Christian Lamparter Tested-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/fwio.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 349375f4a14b..21f19018fab5 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -686,6 +686,8 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len, int p54_fetch_statistics(struct p54_common *priv) { + struct ieee80211_tx_info *txinfo; + struct p54_tx_info *p54info; struct sk_buff *skb; skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, @@ -694,6 +696,20 @@ int p54_fetch_statistics(struct p54_common *priv) if (!skb) return -ENOMEM; + /* + * The statistic feedback causes some extra headaches here, if it + * is not to crash/corrupt the firmware data structures. + * + * Unlike all other Control Get OIDs we can not use helpers like + * skb_put to reserve the space for the data we're requesting. + * Instead the extra frame length -which will hold the results later- + * will only be told to the p54_assign_address, so that following + * frames won't be placed into the allegedly empty area. + */ + txinfo = IEEE80211_SKB_CB(skb); + p54info = (void *) txinfo->rate_driver_data; + p54info->extra_len = sizeof(struct p54_statistics); + p54_tx(priv, skb); return 0; } -- cgit v1.2.2 From 02c06e4abc0680afd31bf481a803541556757fb6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:14 -0700 Subject: iwlagn: modify digital SVR for 1000 On 1000, there are two Switching Voltage Regulators (SVR). The first one apply digital voltage level (1.32V) for PCIe block and core. We need to use this regulator to solve a stability issue related to noisy DC2DC line in the silicon. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-prph.h | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 85e8bac499a7..3f9da6e47108 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -239,6 +239,13 @@ static void iwl5000_nic_config(struct iwl_priv *priv) APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); + if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_1000) { + /* Setting digital SVR for 1000 card to 1.32V */ + iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, + APMG_SVR_DIGITAL_VOLTAGE_1_32, + ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); + } + spin_unlock_irqrestore(&priv->lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 3b9cac3fd216..d393e8f02102 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -80,6 +80,8 @@ #define APMG_RFKILL_REG (APMG_BASE + 0x0014) #define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c) #define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020) +#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058) +#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C) #define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200) #define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800) @@ -91,7 +93,8 @@ #define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) #define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ #define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) - +#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ +#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) -- cgit v1.2.2 From 244294e83f7637e31bbf64060301904860a32051 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:15 -0700 Subject: iwlwifi: fix rx signal quality reporting in dmesg Fix quality incorrectly reported as signal strength value. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 66fe365dd08a..fc7edd1d34dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1065,7 +1065,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, iwl_dbg_report_frame(priv, rx_start, len, header, 1); #endif IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", - rx_status.signal, rx_status.noise, rx_status.signal, + rx_status.signal, rx_status.noise, rx_status.qual, (unsigned long long)rx_status.mactime); /* -- cgit v1.2.2 From cc0f555d511a5fe9d4519334c8f674a1dbab9e3a Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Fri, 17 Jul 2009 09:30:16 -0700 Subject: iwlwifi: Handle new firmware file with ucode build number in header Adding new API version to account for change to ucode file format. New header includes the build number of the ucode. This build number is the SVN revision thus allowing for exact correlation to the code that generated it. The header adds the build number so that older ucode images can also be enhanced to include the build in the future. some cleanup in iwl_read_ucode needed to ensure old header not used and reduce unnecessary references through pointer with the data is already in heap variable. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 40 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-4965.c | 39 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-5000.c | 51 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 5 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 55 +++++++++++++++++------------ drivers/net/wireless/iwlwifi/iwl-core.h | 12 +++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 31 +++++++++++----- drivers/net/wireless/iwlwifi/iwl3945-base.c | 45 ++++++++++++----------- 8 files changed, 224 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 1227ed2960fb..14a47c0a1583 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2786,11 +2786,50 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) return 0; } +#define IWL3945_UCODE_GET(item) \ +static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\ + u32 api_ver) \ +{ \ + return le32_to_cpu(ucode->u.v1.item); \ +} + +static u32 iwl3945_ucode_get_header_size(u32 api_ver) +{ + return UCODE_HEADER_SIZE(1); +} +static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + return 0; +} +static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + return (u8 *) ucode->u.v1.data; +} + +IWL3945_UCODE_GET(inst_size); +IWL3945_UCODE_GET(data_size); +IWL3945_UCODE_GET(init_size); +IWL3945_UCODE_GET(init_data_size); +IWL3945_UCODE_GET(boot_size); + static struct iwl_hcmd_ops iwl3945_hcmd = { .rxon_assoc = iwl3945_send_rxon_assoc, .commit_rxon = iwl3945_commit_rxon, }; +static struct iwl_ucode_ops iwl3945_ucode = { + .get_header_size = iwl3945_ucode_get_header_size, + .get_build = iwl3945_ucode_get_build, + .get_inst_size = iwl3945_ucode_get_inst_size, + .get_data_size = iwl3945_ucode_get_data_size, + .get_init_size = iwl3945_ucode_get_init_size, + .get_init_data_size = iwl3945_ucode_get_init_data_size, + .get_boot_size = iwl3945_ucode_get_boot_size, + .get_data = iwl3945_ucode_get_data, +}; + static struct iwl_lib_ops iwl3945_lib = { .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl3945_hw_txq_free_tfd, @@ -2831,6 +2870,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { }; static struct iwl_ops iwl3945_ops = { + .ucode = &iwl3945_ucode, .lib = &iwl3945_lib, .hcmd = &iwl3945_hcmd, .utils = &iwl3945_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index edbb0bfd8cb7..f4eb683aa2d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2221,12 +2221,50 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->txpower_work); } +#define IWL4965_UCODE_GET(item) \ +static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\ + u32 api_ver) \ +{ \ + return le32_to_cpu(ucode->u.v1.item); \ +} + +static u32 iwl4965_ucode_get_header_size(u32 api_ver) +{ + return UCODE_HEADER_SIZE(1); +} +static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + return 0; +} +static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + return (u8 *) ucode->u.v1.data; +} + +IWL4965_UCODE_GET(inst_size); +IWL4965_UCODE_GET(data_size); +IWL4965_UCODE_GET(init_size); +IWL4965_UCODE_GET(init_data_size); +IWL4965_UCODE_GET(boot_size); + static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, }; +static struct iwl_ucode_ops iwl4965_ucode = { + .get_header_size = iwl4965_ucode_get_header_size, + .get_build = iwl4965_ucode_get_build, + .get_inst_size = iwl4965_ucode_get_inst_size, + .get_data_size = iwl4965_ucode_get_data_size, + .get_init_size = iwl4965_ucode_get_init_size, + .get_init_data_size = iwl4965_ucode_get_init_data_size, + .get_boot_size = iwl4965_ucode_get_boot_size, + .get_data = iwl4965_ucode_get_data, +}; static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .get_hcmd_size = iwl4965_get_hcmd_size, .build_addsta_hcmd = iwl4965_build_addsta_hcmd, @@ -2287,6 +2325,7 @@ static struct iwl_lib_ops iwl4965_lib = { }; static struct iwl_ops iwl4965_ops = { + .ucode = &iwl4965_ucode, .lib = &iwl4965_lib, .hcmd = &iwl4965_hcmd, .utils = &iwl4965_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 3f9da6e47108..74103cfcaceb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1456,6 +1456,44 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, return max_rssi - agc - IWL49_RSSI_OFFSET; } +#define IWL5000_UCODE_GET(item) \ +static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ + u32 api_ver) \ +{ \ + if (api_ver <= 2) \ + return le32_to_cpu(ucode->u.v1.item); \ + return le32_to_cpu(ucode->u.v2.item); \ +} + +static u32 iwl5000_ucode_get_header_size(u32 api_ver) +{ + if (api_ver <= 2) + return UCODE_HEADER_SIZE(1); + return UCODE_HEADER_SIZE(2); +} + +static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + if (api_ver <= 2) + return 0; + return le32_to_cpu(ucode->u.v2.build); +} + +static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode, + u32 api_ver) +{ + if (api_ver <= 2) + return (u8 *) ucode->u.v1.data; + return (u8 *) ucode->u.v2.data; +} + +IWL5000_UCODE_GET(inst_size); +IWL5000_UCODE_GET(data_size); +IWL5000_UCODE_GET(init_size); +IWL5000_UCODE_GET(init_data_size); +IWL5000_UCODE_GET(boot_size); + struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, @@ -1471,6 +1509,17 @@ struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .calc_rssi = iwl5000_calc_rssi, }; +struct iwl_ucode_ops iwl5000_ucode = { + .get_header_size = iwl5000_ucode_get_header_size, + .get_build = iwl5000_ucode_get_build, + .get_inst_size = iwl5000_ucode_get_inst_size, + .get_data_size = iwl5000_ucode_get_data_size, + .get_init_size = iwl5000_ucode_get_init_size, + .get_init_data_size = iwl5000_ucode_get_init_data_size, + .get_boot_size = iwl5000_ucode_get_boot_size, + .get_data = iwl5000_ucode_get_data, +}; + struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, @@ -1572,12 +1621,14 @@ static struct iwl_lib_ops iwl5150_lib = { }; struct iwl_ops iwl5000_ops = { + .ucode = &iwl5000_ucode, .lib = &iwl5000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, }; static struct iwl_ops iwl5150_ops = { + .ucode = &iwl5000_ucode, .lib = &iwl5150_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index bd438d8acf55..26c5d4a60d17 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -46,8 +46,8 @@ #include "iwl-5000-hw.h" /* Highest firmware API version supported */ -#define IWL6000_UCODE_API_MAX 2 -#define IWL6050_UCODE_API_MAX 2 +#define IWL6000_UCODE_API_MAX 3 +#define IWL6050_UCODE_API_MAX 3 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 1 @@ -69,6 +69,7 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { }; static struct iwl_ops iwl6000_ops = { + .ucode = &iwl5000_ucode, .lib = &iwl5000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl6000_hcmd_utils, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ad5002211ab4..6b874dab4120 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1284,7 +1284,7 @@ static void iwl_nic_start(struct iwl_priv *priv) */ static int iwl_read_ucode(struct iwl_priv *priv) { - struct iwl_ucode *ucode; + struct iwl_ucode_header *ucode; int ret = -EINVAL, index; const struct firmware *ucode_raw; const char *name_pre = priv->cfg->fw_name_pre; @@ -1293,7 +1293,8 @@ static int iwl_read_ucode(struct iwl_priv *priv) char buf[25]; u8 *src; size_t len; - u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size; + u32 api_ver, build; + u32 inst_size, data_size, init_size, init_data_size, boot_size; /* Ask kernel firmware_class module to get the boot firmware off disk. * request_firmware() is synchronous, file is in memory on return. */ @@ -1323,23 +1324,26 @@ static int iwl_read_ucode(struct iwl_priv *priv) if (ret < 0) goto error; - /* Make sure that we got at least our header! */ - if (ucode_raw->size < sizeof(*ucode)) { + /* Make sure that we got at least the v1 header! */ + if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { IWL_ERR(priv, "File size way too small!\n"); ret = -EINVAL; goto err_release; } /* Data from ucode file: header followed by uCode images */ - ucode = (void *)ucode_raw->data; + ucode = (struct iwl_ucode_header *)ucode_raw->data; priv->ucode_ver = le32_to_cpu(ucode->ver); api_ver = IWL_UCODE_API(priv->ucode_ver); - inst_size = le32_to_cpu(ucode->inst_size); - data_size = le32_to_cpu(ucode->data_size); - init_size = le32_to_cpu(ucode->init_size); - init_data_size = le32_to_cpu(ucode->init_data_size); - boot_size = le32_to_cpu(ucode->boot_size); + build = priv->cfg->ops->ucode->get_build(ucode, api_ver); + inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); + data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); + init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); + init_data_size = + priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); + boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); + src = priv->cfg->ops->ucode->get_data(ucode, api_ver); /* api_ver should match the api version forming part of the * firmware filename ... but we don't check for that and only rely @@ -1365,6 +1369,9 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_UCODE_API(priv->ucode_ver), IWL_UCODE_SERIAL(priv->ucode_ver)); + if (build) + IWL_DEBUG_INFO(priv, "Build %u\n", build); + IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", priv->ucode_ver); IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", @@ -1379,12 +1386,14 @@ static int iwl_read_ucode(struct iwl_priv *priv) boot_size); /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size < sizeof(*ucode) + + if (ucode_raw->size != + priv->cfg->ops->ucode->get_header_size(api_ver) + inst_size + data_size + init_size + init_data_size + boot_size) { - IWL_DEBUG_INFO(priv, "uCode file size %d too small\n", - (int)ucode_raw->size); + IWL_DEBUG_INFO(priv, + "uCode file size %d does not match expected size\n", + (int)ucode_raw->size); ret = -EINVAL; goto err_release; } @@ -1464,42 +1473,42 @@ static int iwl_read_ucode(struct iwl_priv *priv) /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ - src = &ucode->data[0]; - len = priv->ucode_code.len; + len = inst_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); memcpy(priv->ucode_code.v_addr, src, len); + src += len; + IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); /* Runtime data (2nd block) * NOTE: Copy into backup buffer will be done in iwl_up() */ - src = &ucode->data[inst_size]; - len = priv->ucode_data.len; + len = data_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); memcpy(priv->ucode_data.v_addr, src, len); memcpy(priv->ucode_data_backup.v_addr, src, len); + src += len; /* Initialization instructions (3rd block) */ if (init_size) { - src = &ucode->data[inst_size + data_size]; - len = priv->ucode_init.len; + len = init_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", len); memcpy(priv->ucode_init.v_addr, src, len); + src += len; } /* Initialization data (4th block) */ if (init_data_size) { - src = &ucode->data[inst_size + data_size + init_size]; - len = priv->ucode_init_data.len; + len = init_data_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", len); memcpy(priv->ucode_init_data.v_addr, src, len); + src += len; } /* Bootstrap instructions (5th block) */ - src = &ucode->data[inst_size + data_size + init_size + init_data_size]; - len = priv->ucode_boot.len; + len = boot_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); memcpy(priv->ucode_boot.v_addr, src, len); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 640c4644a165..c844fab95abb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -116,6 +116,17 @@ struct iwl_temp_ops { void (*set_ct_kill)(struct iwl_priv *priv); }; +struct iwl_ucode_ops { + u32 (*get_header_size)(u32); + u32 (*get_build)(const struct iwl_ucode_header *, u32); + u32 (*get_inst_size)(const struct iwl_ucode_header *, u32); + u32 (*get_data_size)(const struct iwl_ucode_header *, u32); + u32 (*get_init_size)(const struct iwl_ucode_header *, u32); + u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32); + u32 (*get_boot_size)(const struct iwl_ucode_header *, u32); + u8 * (*get_data)(const struct iwl_ucode_header *, u32); +}; + struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); @@ -171,6 +182,7 @@ struct iwl_lib_ops { }; struct iwl_ops { + const struct iwl_ucode_ops *ucode; const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b989d5c08d34..f4afd0c3265f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -66,6 +66,7 @@ extern struct iwl_cfg iwl1000_bgn_cfg; /* shared structures from iwl-5000.c */ extern struct iwl_mod_params iwl50_mod_params; extern struct iwl_ops iwl5000_ops; +extern struct iwl_ucode_ops iwl5000_ucode; extern struct iwl_lib_ops iwl5000_lib; extern struct iwl_hcmd_ops iwl5000_hcmd; extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; @@ -525,15 +526,29 @@ struct fw_desc { }; /* uCode file layout */ -struct iwl_ucode { - __le32 ver; /* major/minor/API/serial */ - __le32 inst_size; /* bytes of runtime instructions */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of initialization instructions */ - __le32 init_data_size; /* bytes of initialization data */ - __le32 boot_size; /* bytes of bootstrap instructions */ - u8 data[0]; /* data in same order as "size" elements */ +struct iwl_ucode_header { + __le32 ver; /* major/minor/API/serial */ + union { + struct { + __le32 inst_size; /* bytes of runtime code */ + __le32 data_size; /* bytes of runtime data */ + __le32 init_size; /* bytes of init code */ + __le32 init_data_size; /* bytes of init data */ + __le32 boot_size; /* bytes of bootstrap code */ + u8 data[0]; /* in same order as sizes */ + } v1; + struct { + __le32 build; /* build number */ + __le32 inst_size; /* bytes of runtime code */ + __le32 data_size; /* bytes of runtime data */ + __le32 init_size; /* bytes of init code */ + __le32 init_data_size; /* bytes of init data */ + __le32 boot_size; /* bytes of bootstrap code */ + u8 data[0]; /* in same order as sizes */ + } v2; + } u; }; +#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28) struct iwl4965_ibss_seq { u8 mac[ETH_ALEN]; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c9b3ea927144..bd6a067b4881 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2041,7 +2041,7 @@ static void iwl3945_nic_start(struct iwl_priv *priv) */ static int iwl3945_read_ucode(struct iwl_priv *priv) { - struct iwl_ucode *ucode; + const struct iwl_ucode_header *ucode; int ret = -EINVAL, index; const struct firmware *ucode_raw; /* firmware file name contains uCode/driver compatibility version */ @@ -2082,22 +2082,24 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) goto error; /* Make sure that we got at least our header! */ - if (ucode_raw->size < sizeof(*ucode)) { + if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { IWL_ERR(priv, "File size way too small!\n"); ret = -EINVAL; goto err_release; } /* Data from ucode file: header followed by uCode images */ - ucode = (void *)ucode_raw->data; + ucode = (struct iwl_ucode_header *)ucode_raw->data; priv->ucode_ver = le32_to_cpu(ucode->ver); api_ver = IWL_UCODE_API(priv->ucode_ver); - inst_size = le32_to_cpu(ucode->inst_size); - data_size = le32_to_cpu(ucode->data_size); - init_size = le32_to_cpu(ucode->init_size); - init_data_size = le32_to_cpu(ucode->init_data_size); - boot_size = le32_to_cpu(ucode->boot_size); + inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); + data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); + init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); + init_data_size = + priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); + boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); + src = priv->cfg->ops->ucode->get_data(ucode, api_ver); /* api_ver should match the api version forming part of the * firmware filename ... but we don't check for that and only rely @@ -2138,12 +2140,13 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size < sizeof(*ucode) + + if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) + inst_size + data_size + init_size + init_data_size + boot_size) { - IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n", - ucode_raw->size); + IWL_DEBUG_INFO(priv, + "uCode file size %zd does not match expected size\n", + ucode_raw->size); ret = -EINVAL; goto err_release; } @@ -2226,44 +2229,44 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) /* Copy images into buffers for card's bus-master reads ... */ /* Runtime instructions (first block of data in file) */ - src = &ucode->data[0]; - len = priv->ucode_code.len; + len = inst_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %zd\n", len); memcpy(priv->ucode_code.v_addr, src, len); + src += len; + IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); /* Runtime data (2nd block) * NOTE: Copy into backup buffer will be done in iwl3945_up() */ - src = &ucode->data[inst_size]; - len = priv->ucode_data.len; + len = data_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %zd\n", len); memcpy(priv->ucode_data.v_addr, src, len); memcpy(priv->ucode_data_backup.v_addr, src, len); + src += len; /* Initialization instructions (3rd block) */ if (init_size) { - src = &ucode->data[inst_size + data_size]; - len = priv->ucode_init.len; + len = init_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %zd\n", len); memcpy(priv->ucode_init.v_addr, src, len); + src += len; } /* Initialization data (4th block) */ if (init_data_size) { - src = &ucode->data[inst_size + data_size + init_size]; - len = priv->ucode_init_data.len; + len = init_data_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %zd\n", len); memcpy(priv->ucode_init_data.v_addr, src, len); + src += len; } /* Bootstrap instructions (5th block) */ - src = &ucode->data[inst_size + data_size + init_size + init_data_size]; - len = priv->ucode_boot.len; + len = boot_size; IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %zd\n", len); memcpy(priv->ucode_boot.v_addr, src, len); -- cgit v1.2.2 From 5e215169f466e48561e40d1fa142f02e0e44a3d0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:17 -0700 Subject: iwlwifi: make led functions generic Led functions are generic for all the devices except 3945, so remove the reference to 4965 Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-led.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 5e64252f80f6..36d88a045043 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -104,7 +104,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) } /* Set led pattern command */ -static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, +static int iwl_led_pattern(struct iwl_priv *priv, int led_id, unsigned int idx) { struct iwl_led_cmd led_cmd = { @@ -121,7 +121,7 @@ static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, } /* Set led register off */ -static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) +static int iwl_led_on_reg(struct iwl_priv *priv, int led_id) { IWL_DEBUG_LED(priv, "led on %d\n", led_id); iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); @@ -130,7 +130,7 @@ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) #if 0 /* Set led on command */ -static int iwl4965_led_on(struct iwl_priv *priv, int led_id) +static int iwl_led_on(struct iwl_priv *priv, int led_id) { struct iwl_led_cmd led_cmd = { .id = led_id, @@ -142,7 +142,7 @@ static int iwl4965_led_on(struct iwl_priv *priv, int led_id) } /* Set led off command */ -int iwl4965_led_off(struct iwl_priv *priv, int led_id) +int iwl_led_off(struct iwl_priv *priv, int led_id) { struct iwl_led_cmd led_cmd = { .id = led_id, @@ -157,7 +157,7 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id) /* Set led register off */ -static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) +static int iwl_led_off_reg(struct iwl_priv *priv, int led_id) { IWL_DEBUG_LED(priv, "LED Reg off\n"); iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); @@ -171,7 +171,7 @@ static int iwl_led_associate(struct iwl_priv *priv, int led_id) { IWL_DEBUG_LED(priv, "Associated\n"); priv->allow_blinking = 1; - return iwl4965_led_on_reg(priv, led_id); + return iwl_led_on_reg(priv, led_id); } static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) { @@ -314,7 +314,7 @@ void iwl_leds_background(struct iwl_priv *priv) priv->last_blink_time = 0; if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { priv->last_blink_rate = IWL_SOLID_BLINK_IDX; - iwl4965_led_pattern(priv, IWL_LED_LINK, + iwl_led_pattern(priv, IWL_LED_LINK, IWL_SOLID_BLINK_IDX); } return; @@ -328,7 +328,7 @@ void iwl_leds_background(struct iwl_priv *priv) /* call only if blink rate change */ if (blink_idx != priv->last_blink_rate) - iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx); + iwl_led_pattern(priv, IWL_LED_LINK, blink_idx); priv->last_blink_time = jiffies; priv->last_blink_rate = blink_idx; @@ -351,8 +351,8 @@ int iwl_leds_register(struct iwl_priv *priv) sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", wiphy_name(priv->hw->wiphy)); - priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg; - priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg; + priv->led[IWL_LED_TRG_RADIO].led_on = iwl_led_on_reg; + priv->led[IWL_LED_TRG_RADIO].led_off = iwl_led_off_reg; priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], @@ -386,7 +386,7 @@ int iwl_leds_register(struct iwl_priv *priv) priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; - priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern; + priv->led[IWL_LED_TRG_RX].led_pattern = iwl_led_pattern; if (ret) goto exit_fail; @@ -401,7 +401,7 @@ int iwl_leds_register(struct iwl_priv *priv) priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; - priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; + priv->led[IWL_LED_TRG_TX].led_pattern = iwl_led_pattern; if (ret) goto exit_fail; -- cgit v1.2.2 From 2d1bb9e58c2b13df13741d1efe1129cf1098405d Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 17 Jul 2009 09:30:18 -0700 Subject: iwlagn: do not send key clear commands when rfkill enabled Do all key clearing except sending sommands to device when rfkill enabled. When rfkill enabled the interface is brought down and will be brought back up correctly after rfkill is enabled again. Same change is not needed for iwl3945 as it ignores return code when sending key clearing command to device. This fixes http://bugzilla.kernel.org/show_bug.cgi?id=13742 Signed-off-by: Reinette Chatre Tested-by: Frans Pop Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index afa1633602a7..7fd806d33a67 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -566,6 +566,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, unsigned long flags; spin_lock_irqsave(&priv->sta_lock, flags); + IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", + keyconf->keyidx); if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) IWL_ERR(priv, "index %d not used in uCode key table.\n", @@ -573,6 +575,11 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, priv->default_wep_key--; memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); + if (iwl_is_rfkill(priv)) { + IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); + spin_unlock_irqrestore(&priv->sta_lock, flags); + return 0; + } ret = iwl_send_static_wepkey_cmd(priv, 1); IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret); @@ -853,6 +860,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + if (iwl_is_rfkill(priv)) { + IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n"); + spin_unlock_irqrestore(&priv->sta_lock, flags); + return 0; + } ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; -- cgit v1.2.2 From a283c0116b0cc5e82327e50ad4d05f6d4d42c603 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:19 -0700 Subject: iwlwifi: add led debugfs function Adding debugfs file to show current led blinking rate /sys/kernel/debug/ieee80211/phy0/iwlagn/data/led Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 36 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 1555676fc519..e4a4dbd20c98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -83,6 +83,9 @@ struct iwl_debugfs { struct dentry *file_status; struct dentry *file_interrupt; struct dentry *file_qos; +#ifdef CONFIG_IWLWIFI_LEDS + struct dentry *file_led; +#endif } dbgfs_data_files; struct dir_rf_files { struct dentry *file_disable_sensitivity; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0b9e824b67c2..0ab3463aa07e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -591,6 +591,33 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, return ret; } +#ifdef CONFIG_IWLWIFI_LEDS +static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char buf[256]; + const size_t bufsz = sizeof(buf); + ssize_t ret; + + pos += scnprintf(buf + pos, bufsz - pos, + "allow blinking: %s\n", + (priv->allow_blinking) ? "True" : "False"); + if (priv->allow_blinking) { + pos += scnprintf(buf + pos, bufsz - pos, + "Led blinking rate: %u\n", + priv->last_blink_rate); + pos += scnprintf(buf + pos, bufsz - pos, + "Last blink time: %lu\n", + priv->last_blink_time); + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; +} +#endif + DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(nvm); @@ -601,6 +628,9 @@ DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(status); DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_FILE_OPS(qos); +#ifdef CONFIG_IWLWIFI_LEDS +DEBUGFS_READ_FILE_OPS(led); +#endif /* * Create the debugfs files and directories @@ -638,6 +668,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(status, data); DEBUGFS_ADD_FILE(interrupt, data); DEBUGFS_ADD_FILE(qos, data); +#ifdef CONFIG_IWLWIFI_LEDS + DEBUGFS_ADD_FILE(led, data); +#endif DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, &priv->disable_chain_noise_cal); @@ -673,6 +706,9 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); +#ifdef CONFIG_IWLWIFI_LEDS + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); +#endif DEBUGFS_REMOVE(priv->dbgfs->dir_data); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); -- cgit v1.2.2 From e5108d075c705ed3336163d9ead2b8fe629f680d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:20 -0700 Subject: iwlwifi: Led blinking counting both tx and rx For controlling led blinking, counting both tx and rx data traffic; this will be able to handle traffic in either direction Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-led.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 36d88a045043..8c8115293b3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -54,7 +54,7 @@ static const char *led_type_str[] = { static const struct { - u16 tpt; + u16 tpt; /* Mb/s */ u8 on_time; u8 off_time; } blink_tbl[] = @@ -264,13 +264,15 @@ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, /* - * calculate blink rate according to last 2 sec Tx/Rx activities + * calculate blink rate according to last second Tx/Rx activities */ static int iwl_get_blink_rate(struct iwl_priv *priv) { int i; - u64 current_tpt = priv->tx_stats[2].bytes; - /* FIXME: + priv->rx_stats[2].bytes; */ + /* count both tx and rx traffic to be able to + * handle traffic in either direction + */ + u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes; s64 tpt = current_tpt - priv->led_tpt; if (tpt < 0) /* wraparound */ -- cgit v1.2.2 From b23a0524a38b146f85be44ae0d71abd2a710f4ab Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:21 -0700 Subject: iwlwifi: checking unknown HW type When deciding NVM type, if the HW type is unknown, report error and exit with -ENOENT. This check should prevent incorrect behavior by assuming the wrong NVM type. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 7d7554a2f341..51eed7226669 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -159,6 +159,9 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv) /* OTP only valid for CP/PP and after */ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { + case CSR_HW_REV_TYPE_NONE: + IWL_ERR(priv, "Unknown hardware type\n"); + return -ENOENT; case CSR_HW_REV_TYPE_3945: case CSR_HW_REV_TYPE_4965: case CSR_HW_REV_TYPE_5300: @@ -266,7 +269,8 @@ int iwl_eeprom_init(struct iwl_priv *priv) u32 otpgp; priv->nvm_device_type = iwlcore_get_nvm_type(priv); - + if (priv->nvm_device_type == -ENOENT) + return -ENOENT; /* allocate eeprom */ if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) priv->cfg->eeprom_size = -- cgit v1.2.2 From cce53aa347c1e023d967b1cb1aa393c725aedba5 Mon Sep 17 00:00:00 2001 From: Jay Sternberg Date: Fri, 17 Jul 2009 09:30:22 -0700 Subject: iwlwifi: update 1000 series API version to match firmware firmware file now contains build number so API needs to be updated. Signed-off-by: Jay Sternberg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 7da52f1cc1d6..a899be914ebf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -46,7 +46,7 @@ #include "iwl-5000-hw.h" /* Highest firmware API version supported */ -#define IWL1000_UCODE_API_MAX 2 +#define IWL1000_UCODE_API_MAX 3 /* Lowest firmware API version supported */ #define IWL1000_UCODE_API_MIN 1 -- cgit v1.2.2 From 34a66de628b5dcc4a93129610ccd24814935e8cd Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:23 -0700 Subject: iwlwifi: uCode Alive notification with timeout Wait for REPLY_ALIVE notification from init and runtime uCode. based on the type of REPLY_ALIVE, different status bit will be set to wake up the queue: STATUS_INIT_UCODE_ALIVE for init uCode STATUS_RT_UCODE_ALIVE for runtime uCode. If timeout, attempt to download the failing uCode image again. This can only be done for the init ucode images of all iwlagn devices and the runtime ucode image of the 5000 series and up. If there is a problem with the 4965 runtime ucode coming up we restart the interface and thus trigger a new download of the init ucode also. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 26 ++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn.c | 50 +++++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 39 +++++++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ 5 files changed, 109 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index f4eb683aa2d5..272409c80619 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -146,7 +146,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Begin load bsm\n"); - priv->ucode_type = UCODE_RT; + priv->ucode_type = UCODE_INIT; /* make sure bootstrap program is no larger than BSM's SRAM size */ if (len > IWL49_MAX_BSM_SIZE) @@ -256,6 +256,8 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) */ static void iwl4965_init_alive_start(struct iwl_priv *priv) { + int ret; + /* Check alive response for "valid" sign from uCode */ if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { /* We had an error bringing up the hardware, so take it @@ -287,6 +289,28 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); goto restart; } + priv->ucode_type = UCODE_RT; + if (test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) { + IWL_WARN(priv, "Runtime uCode already alive? " + "Waiting for alive anyway\n"); + clear_bit(STATUS_RT_UCODE_ALIVE, &priv->status); + } + ret = wait_event_interruptible_timeout( + priv->wait_command_queue, + test_bit(STATUS_RT_UCODE_ALIVE, &priv->status), + UCODE_ALIVE_TIMEOUT); + if (!ret) { + /* FIXME: if STATUS_RT_UCODE_ALIVE timeout + * go back to restart the download Init uCode again + * this might cause to trap in the restart loop + */ + priv->ucode_type = UCODE_NONE; + if (!test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) { + IWL_ERR(priv, "Runtime timeout after %dms\n", + jiffies_to_msecs(UCODE_ALIVE_TIMEOUT)); + goto restart; + } + } return; restart: diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6b874dab4120..f61f653a1b72 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -533,12 +533,16 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv, if (palive->ver_subtype == INITIALIZE_SUBTYPE) { IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); + set_bit(STATUS_INIT_UCODE_ALIVE, &priv->status); + wake_up_interruptible(&priv->wait_command_queue); memcpy(&priv->card_alive_init, &pkt->u.alive_frame, sizeof(struct iwl_init_alive_resp)); pwork = &priv->init_alive_start; } else { IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); + set_bit(STATUS_RT_UCODE_ALIVE, &priv->status); + wake_up_interruptible(&priv->wait_command_queue); memcpy(&priv->card_alive, &pkt->u.alive_frame, sizeof(struct iwl_alive_resp)); pwork = &priv->alive_start; @@ -1782,6 +1786,7 @@ static int __iwl_up(struct iwl_priv *priv) { int i; int ret; + unsigned long status; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); @@ -1859,6 +1864,51 @@ static int __iwl_up(struct iwl_priv *priv) /* start card; "initialize" will load runtime ucode */ iwl_nic_start(priv); + /* Just finish download Init or Runtime uCode image to device + * now we wait here for uCode send REPLY_ALIVE notification + * to indicate uCode is ready. + * 1) For Init uCode image, all iwlagn devices should wait here + * on STATUS_INIT_UCODE_ALIVE status bit; if timeout before + * receive the REPLY_ALIVE notification, go back and try to + * download the Init uCode image again. + * 2) For Runtime uCode image, all iwlagn devices except 4965 + * wait here on STATUS_RT_UCODE_ALIVE status bit; if + * timeout before receive the REPLY_ALIVE notification, go back + * and download the Runtime uCode image again. + * 3) For 4965 Runtime uCode, it will not go through this path, + * need to wait for STATUS_RT_UCODE_ALIVE status bit in + * iwl4965_init_alive_start() function; if timeout, need to + * restart and download Init uCode image. + */ + if (priv->ucode_type == UCODE_INIT) + status = STATUS_INIT_UCODE_ALIVE; + else + status = STATUS_RT_UCODE_ALIVE; + if (test_bit(status, &priv->status)) { + IWL_WARN(priv, + "%s uCode already alive? " + "Waiting for alive anyway\n", + (status == STATUS_INIT_UCODE_ALIVE) + ? "INIT" : "Runtime"); + clear_bit(status, &priv->status); + } + ret = wait_event_interruptible_timeout( + priv->wait_command_queue, + test_bit(status, &priv->status), + UCODE_ALIVE_TIMEOUT); + if (!ret) { + if (!test_bit(status, &priv->status)) { + priv->ucode_type = + (status == STATUS_INIT_UCODE_ALIVE) + ? UCODE_NONE : UCODE_INIT; + IWL_ERR(priv, + "%s timeout after %dms\n", + (status == STATUS_INIT_UCODE_ALIVE) + ? "INIT" : "Runtime", + jiffies_to_msecs(UCODE_ALIVE_TIMEOUT)); + continue; + } + } IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b82480a51782..8655e092fca7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1341,10 +1341,17 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 desc, time, count, base, data1; u32 blink1, blink2, ilink1, ilink2; - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); - else + switch (priv->ucode_type) { + case UCODE_RT: base = le32_to_cpu(priv->card_alive.error_event_table_ptr); + break; + case UCODE_INIT: + base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); + break; + default: + IWL_ERR(priv, "uCode image not available\n"); + return; + } if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); @@ -1396,10 +1403,17 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, if (num_events == 0) return; - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else + switch (priv->ucode_type) { + case UCODE_RT: base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + break; + case UCODE_INIT: + base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); + break; + default: + IWL_ERR(priv, "uCode image not available\n"); + return; + } if (mode == 0) event_size = 2 * sizeof(u32); @@ -1436,10 +1450,17 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) u32 next_entry; /* index of next entry to be written by uCode */ u32 size; /* # entries that we'll print */ - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else + switch (priv->ucode_type) { + case UCODE_RT: base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + break; + case UCODE_INIT: + base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); + break; + default: + IWL_ERR(priv, "uCode image not available\n"); + return; + } if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c844fab95abb..a697b843863b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -512,6 +512,8 @@ void iwlcore_free_geos(struct iwl_priv *priv); #define STATUS_POWER_PMI 16 #define STATUS_FW_ERROR 17 #define STATUS_MODE_PENDING 18 +#define STATUS_INIT_UCODE_ALIVE 19 +#define STATUS_RT_UCODE_ALIVE 20 static inline int iwl_is_ready(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f4afd0c3265f..926df3ae2416 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -772,6 +772,8 @@ struct iwl_calib_result { size_t buf_len; }; +#define UCODE_ALIVE_TIMEOUT (5 * HZ) + enum ucode_type { UCODE_NONE = 0, UCODE_INIT, -- cgit v1.2.2 From a562a9dda7f47e7cac58d80bf1ffe441feca510e Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 17 Jul 2009 09:30:24 -0700 Subject: iwlwifi: make debug level more user friendly * Deprecate the "debug50" module parameter used to obtain 5000 series and up debugging. Replace it with "debug" module parameter to match with original driver and be consistent between them. The "debug50" module parameter can still be used, except that the module parameter is not writable in keeping with its previous state. We currently just mark it as "deprecated" and do not have it in the feature-removal-schedule. Some more cleanup of module parameters needs to be done and can then be entered together. * Only make "debug" module parameters visible if the driver is compiled with CONFIG_IWLWIFI_DEBUG. This will eliminate a lot of confusion where users think they have set debug flags but yet cannot see any debug output. * Make module parameters writable. This eliminates the need for the "debug_level" sysfs file, which can now also be deprecated and added to feature-removal-schedule. This file is in significant use though with many iwlwifi documents and text referring users to it. We can thus not take its removal lightly and keep it around. With iwlcore shared between iwlagn and iwl3945 we really do not need debug module parameters for each but can instead have one debug module parameter for the iwlcore module. The same issue is here as with the sysfs file - a lot of iwlwifi documentation and text (like bug reports) rely on iwlagn and iwl3945 having this module parameter, so changing this to a module parameter of iwlcore will have significant impact and we do not do this for that reason. One consequence of this patch is that if a user is running a system with both 3945 and later hardware then the setting of the one module parameter will affect the value of the other. The likelihood of this seems low - and even if this setup is present it does not seem like an issue for both modules to run with the same debug level. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-agn.c | 31 +++++++++++++++++++---------- drivers/net/wireless/iwlwifi/iwl-core.c | 11 ++++++---- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-debug.h | 12 +++++------ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-rx.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 25 +++++++++++++---------- 12 files changed, 55 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 14a47c0a1583..8ee403cd9b99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -502,14 +502,14 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, } } if (print_dump) - iwl_print_hex_dump(priv, IWL_DL_RX, data, length); + iwl_print_hex_dump(IWL_DL_RX, data, length); } static void iwl3945_dbg_report_frame(struct iwl_priv *priv, struct iwl_rx_packet *pkt, struct ieee80211_hdr *header, int group100) { - if (priv->debug_level & IWL_DL_RX) + if (iwl_debug_level & IWL_DL_RX) _iwl3945_dbg_report_frame(priv, pkt, header, group100); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 272409c80619..c30a1b960576 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2376,8 +2376,6 @@ module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); -module_param_named(debug, iwl4965_mod_params.debug, uint, 0444); -MODULE_PARM_DESC(debug, "debug output mask"); module_param_named( disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 74103cfcaceb..702db07fa382 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1745,8 +1745,6 @@ MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); MODULE_PARM_DESC(swcrypto50, "using software crypto engine (default 0 [hardware])\n"); -module_param_named(debug50, iwl50_mod_params.debug, uint, 0444); -MODULE_PARM_DESC(debug50, "50XX debug output mask"); module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f61f653a1b72..ff4a546f1e6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -904,7 +904,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & IWL_DL_ISR) { + if (iwl_debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -939,7 +939,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) } #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & (IWL_DL_ISR)) { + if (iwl_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " @@ -1053,7 +1053,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) iwl_enable_interrupts(priv); #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & (IWL_DL_ISR)) { + if (iwl_debug_level & (IWL_DL_ISR)) { inta = iwl_read32(priv, CSR_INT); inta_mask = iwl_read32(priv, CSR_INT_MASK); inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); @@ -1084,7 +1084,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) inta = priv->inta; #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & IWL_DL_ISR) { + if (iwl_debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", @@ -1112,7 +1112,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) } #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & (IWL_DL_ISR)) { + if (iwl_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " @@ -2456,14 +2456,16 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, * used for controlling the debug level. * * See the level definitions in iwl for details. + * + * FIXME This file can be deprecated as the module parameter is + * writable and users can thus also change the debug level + * using the /sys/module/iwl3945/parameters/debug file. */ static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%08X\n", priv->debug_level); + return sprintf(buf, "0x%08X\n", iwl_debug_level); } static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, @@ -2477,7 +2479,7 @@ static ssize_t store_debug_level(struct device *d, if (ret) IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); else - priv->debug_level = val; + iwl_debug_level = val; return strnlen(buf, count); } @@ -2829,7 +2831,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. */ if (cfg->mod_params->disable_hw_scan) { - if (cfg->mod_params->debug & IWL_DL_INFO) + if (iwl_debug_level & IWL_DL_INFO) dev_printk(KERN_DEBUG, &(pdev->dev), "Disabling hw_scan\n"); iwl_hw_ops.hw_scan = NULL; @@ -2851,7 +2853,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->inta_mask = CSR_INI_SET_MASK; #ifdef CONFIG_IWLWIFI_DEBUG - priv->debug_level = priv->cfg->mod_params->debug; atomic_set(&priv->restrict_refcnt, 0); #endif @@ -3211,3 +3212,11 @@ static void __exit iwl_exit(void) module_exit(iwl_exit); module_init(iwl_init); + +#ifdef CONFIG_IWLWIFI_DEBUG +module_param_named(debug50, iwl_debug_level, uint, 0444); +MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); +module_param_named(debug, iwl_debug_level, uint, 0644); +MODULE_PARM_DESC(debug, "debug output mask"); +#endif + diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8655e092fca7..976004f6c7dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -59,6 +59,9 @@ MODULE_LICENSE("GPL"); IWL_RATE_##pp##M_INDEX, \ IWL_RATE_##np##M_INDEX } +u32 iwl_debug_level; +EXPORT_SYMBOL(iwl_debug_level); + static irqreturn_t iwl_isr(int irq, void *data); /* @@ -1275,7 +1278,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) struct iwl_rxon_cmd *rxon = &priv->staging_rxon; IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); - iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); + iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", @@ -1505,7 +1508,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) clear_bit(STATUS_HCMD_ACTIVE, &priv->status); #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & IWL_DL_FW_ERRORS) { + if (iwl_debug_level & IWL_DL_FW_ERRORS) { iwl_dump_nic_error_log(priv); iwl_dump_nic_event_log(priv); iwl_print_rx_config_cmd(priv); @@ -2004,7 +2007,7 @@ static irqreturn_t iwl_isr(int irq, void *data) } #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & (IWL_DL_ISR)) { + if (iwl_debug_level & (IWL_DL_ISR)) { inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); @@ -2311,7 +2314,7 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); - iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); + iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); } EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a697b843863b..f82ec9e4da03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -190,7 +190,6 @@ struct iwl_ops { struct iwl_mod_params { int sw_crypto; /* def: 0 = using hardware encryption */ - u32 debug; /* def: 0 = minimal debug log messages */ int disable_hw_scan; /* def: 0 = use h/w scan */ int num_of_queues; /* def: HW dependent */ int num_of_ampdu_queues;/* def: HW dependent */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index e4a4dbd20c98..9faf0c2ff608 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -30,6 +30,7 @@ #define __iwl_debug_h__ struct iwl_priv; +extern u32 iwl_debug_level; #define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) #define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) @@ -45,7 +46,7 @@ do { \ #ifdef CONFIG_IWLWIFI_DEBUG #define IWL_DEBUG(__priv, level, fmt, args...) \ do { \ - if (__priv->debug_level & (level)) \ + if (iwl_debug_level & (level)) \ dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ @@ -53,15 +54,15 @@ do { \ #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ do { \ - if ((__priv->debug_level & (level)) && net_ratelimit()) \ + if ((iwl_debug_level & (level)) && net_ratelimit()) \ dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ } while (0) -#define iwl_print_hex_dump(priv, level, p, len) \ +#define iwl_print_hex_dump(level, p, len) \ do { \ - if (priv->debug_level & level) \ + if (iwl_debug_level & level) \ print_hex_dump(KERN_DEBUG, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) @@ -103,8 +104,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv); #else #define IWL_DEBUG(__priv, level, fmt, args...) #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) -static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, - void *p, u32 len) +static inline void iwl_print_hex_dump(int level, void *p, u32 len) {} #endif /* CONFIG_IWLWIFI_DEBUG */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 926df3ae2416..0751891f4ab7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1111,7 +1111,6 @@ struct iwl_priv { #ifdef CONFIG_IWLWIFI_DEBUG /* debugging info */ - u32 debug_level; u32 framecnt_to_us; atomic_t restrict_refcnt; #ifdef CONFIG_IWLWIFI_DEBUGFS diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index fc7edd1d34dc..5d5f2153f445 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -646,7 +646,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv, u32 tsf_low; int rssi; - if (likely(!(priv->debug_level & IWL_DL_RX))) + if (likely(!(iwl_debug_level & IWL_DL_RX))) return; /* MAC header */ @@ -742,7 +742,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv, } } if (print_dump) - iwl_print_hex_dump(priv, IWL_DL_RX, header, length); + iwl_print_hex_dump(IWL_DL_RX, header, length); } #endif @@ -1061,7 +1061,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, /* Set "1" to report good data frames in groups of 100 */ #ifdef CONFIG_IWLWIFI_DEBUG - if (unlikely(priv->debug_level & IWL_DL_RX)) + if (unlikely(iwl_debug_level & IWL_DL_RX)) iwl_dbg_report_frame(priv, rx_start, len, header, 1); #endif IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7fd806d33a67..cbe4e26d053f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1093,7 +1093,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) IWL_DEBUG_DROP(priv, "Station %pM not in station map. " "Defaulting to broadcast...\n", hdr->addr1); - iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); + iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); return priv->hw_params.bcast_sta_id; default: diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7073069a61a9..ef7e6bdb0671 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -869,8 +869,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", le16_to_cpu(out_cmd->hdr.sequence)); IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); + iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); + iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); /* Set up entry for this TFD in Tx byte-count array */ if (info->flags & IEEE80211_TX_CTL_AMPDU) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bd6a067b4881..221a875b0161 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -612,8 +612,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", le16_to_cpu(out_cmd->hdr.sequence)); IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags)); - iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr, + iwl_print_hex_dump(IWL_DL_TX, tx, sizeof(*tx)); + iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx->hdr, ieee80211_hdrlen(fc)); /* @@ -1644,7 +1644,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & IWL_DL_ISR) { + if (iwl_debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -1679,7 +1679,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) } #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & (IWL_DL_ISR)) { + if (iwl_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " @@ -1758,7 +1758,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) iwl_enable_interrupts(priv); #ifdef CONFIG_IWLWIFI_DEBUG - if (priv->debug_level & (IWL_DL_ISR)) { + if (iwl_debug_level & (IWL_DL_ISR)) { inta = iwl_read32(priv, CSR_INT); inta_mask = iwl_read32(priv, CSR_INT_MASK); inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); @@ -3308,13 +3308,15 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * used for controlling the debug level. * * See the level definitions in iwl for details. + * + * FIXME This file can be deprecated as the module parameter is + * writable and users can thus also change the debug level + * using the /sys/module/iwl3945/parameters/debug file. */ static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%08X\n", priv->debug_level); + return sprintf(buf, "0x%08X\n", iwl_debug_level); } static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, @@ -3328,7 +3330,7 @@ static ssize_t store_debug_level(struct device *d, if (ret) IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf); else - priv->debug_level = val; + iwl_debug_level = val; return strnlen(buf, count); } @@ -3966,7 +3968,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->inta_mask = CSR_INI_SET_MASK; #ifdef CONFIG_IWLWIFI_DEBUG - priv->debug_level = iwl3945_mod_params.debug; atomic_set(&priv->restrict_refcnt, 0); #endif @@ -4262,8 +4263,10 @@ MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); MODULE_PARM_DESC(swcrypto, "using software crypto (default 1 [software])\n"); -module_param_named(debug, iwl3945_mod_params.debug, uint, 0444); +#ifdef CONFIG_IWLWIFI_DEBUG +module_param_named(debug, iwl_debug_level, uint, 0644); MODULE_PARM_DESC(debug, "debug output mask"); +#endif module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); -- cgit v1.2.2 From 58dba728b1b727cb3d95a1f76ca4e88a1e628ee1 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 17 Jul 2009 09:30:25 -0700 Subject: iwlwifi: clarify hardware error message When a hardware error is detected we need to be clear about that and not create impression that the microcode is able to deal with it. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ff4a546f1e6d..b7ac4ee794c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -923,7 +923,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); + IWL_ERR(priv, "Hardware error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); @@ -1096,7 +1096,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); + IWL_ERR(priv, "Hardware error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 221a875b0161..8891d6e3a0fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1663,7 +1663,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); + IWL_ERR(priv, "Hardware error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); -- cgit v1.2.2 From 4c423a2b0cc3c85137988962e6ba3f01baef0b4e Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 17 Jul 2009 09:30:26 -0700 Subject: iwlwifi: inform user about rfkill state changes rfkill state changes are mostly available through debug messages. These are significant enough to always make user aware of so we turn them into warnings. Also insert a missing newline in some rfkill related debug message. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b7ac4ee794c0..44c7f236a7a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -964,7 +964,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; - IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", + IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); priv->isr_stats.rfkill++; @@ -1137,7 +1137,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; - IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", + IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); priv->isr_stats.rfkill++; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index ef7e6bdb0671..0912987af603 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -940,7 +940,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) !(cmd->meta.flags & CMD_SIZE_HUGE)); if (iwl_is_rfkill(priv)) { - IWL_DEBUG_INFO(priv, "Not sending command - RF KILL"); + IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n"); return -EIO; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8891d6e3a0fa..2cc7e30d7743 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -926,7 +926,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); unsigned long status = priv->status; - IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", + IWL_WARN(priv, "Card state received: HW:%s SW:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", (flags & SW_CARD_DISABLED) ? "Kill" : "On"); -- cgit v1.2.2 From 30a12a8fbbd530b016277dd2ab65246b516540a8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 17 Jul 2009 09:30:27 -0700 Subject: iwlwifi: change iwl_enable/disable_interrupts to "inline" iwl_enable_interrupts is being called inside the interrupt, change from function call to inline Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 25 ------------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- drivers/net/wireless/iwlwifi/iwl-helpers.h | 21 +++++++++++++++++++++ 3 files changed, 21 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 976004f6c7dc..6aea02644809 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1749,31 +1749,6 @@ void iwl_uninit_drv(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_uninit_drv); - -void iwl_disable_interrupts(struct iwl_priv *priv) -{ - clear_bit(STATUS_INT_ENABLED, &priv->status); - - /* disable interrupts from uCode/NIC to host */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* acknowledge/clear/reset any interrupts still pending - * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(priv, CSR_INT, 0xffffffff); - iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); - IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); -} -EXPORT_SYMBOL(iwl_disable_interrupts); - -void iwl_enable_interrupts(struct iwl_priv *priv) -{ - IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); - set_bit(STATUS_INT_ENABLED, &priv->status); - iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); -} -EXPORT_SYMBOL(iwl_enable_interrupts); - - #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) /* Free dram table */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f82ec9e4da03..614ec7cc5b31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -458,8 +458,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, /***************************************************** * PCI * *****************************************************/ -void iwl_disable_interrupts(struct iwl_priv *priv); -void iwl_enable_interrupts(struct iwl_priv *priv); irqreturn_t iwl_isr_legacy(int irq, void *data); int iwl_reset_ict(struct iwl_priv *priv); void iwl_disable_ict(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index a1328c3c81ae..bd0b12efb5c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -145,4 +145,25 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue) #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue +static inline void iwl_disable_interrupts(struct iwl_priv *priv) +{ + clear_bit(STATUS_INT_ENABLED, &priv->status); + + /* disable interrupts from uCode/NIC to host */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* acknowledge/clear/reset any interrupts still pending + * from uCode or flow handler (Rx/Tx DMA) */ + iwl_write32(priv, CSR_INT, 0xffffffff); + iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); + IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); +} + +static inline void iwl_enable_interrupts(struct iwl_priv *priv) +{ + IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); + set_bit(STATUS_INT_ENABLED, &priv->status); + iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); +} + #endif /* __iwl_helpers_h__ */ -- cgit v1.2.2 From 4951348109c334f2b839816bd161522d089cb782 Mon Sep 17 00:00:00 2001 From: Luis Correia Date: Fri, 17 Jul 2009 21:39:19 +0200 Subject: rt2x00: Comment spellchecking Fix a bunch of spelling errors in the rt2x00 drivers Signed-off-by: Luis Correia Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500usb.h | 2 +- drivers/net/wireless/rt2x00/rt2800usb.c | 4 ++-- drivers/net/wireless/rt2x00/rt2800usb.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 4 ++-- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- drivers/net/wireless/rt2x00/rt2x00crypto.c | 2 +- drivers/net/wireless/rt2x00/rt2x00link.c | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00queue.h | 10 +++++----- drivers/net/wireless/rt2x00/rt2x00reg.h | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/rt2x00/rt73usb.h | 4 ++-- 15 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index ec3b004ddc3c..ccd644104ad1 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -928,7 +928,7 @@ #define RXD_W7_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to mac80211 value + * Macros for converting txpower from EEPROM to mac80211 value * and from mac80211 value to register value. * NOTE: Logics in rt2400pci for txpower are reversed * compared to the other rt2x00 drivers. A higher txpower diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index ce2f065c7486..54d37957883c 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1218,7 +1218,7 @@ #define RXD_W10_DROP FIELD32(0x00000001) /* - * Macro's for converting txpower from EEPROM to mac80211 value + * Macros for converting txpower from EEPROM to mac80211 value * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 5bc46fe72179..b01edca42583 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -831,7 +831,7 @@ #define RXD_W3_EIV FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to mac80211 value + * Macros for converting txpower from EEPROM to mac80211 value * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index f35b3d6649c8..9efb41710508 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1910,7 +1910,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, /* * Before the radio can be enabled, the device first has * to be woken up. After that it needs a bit of time - * to be fully awake and the radio can be enabled. + * to be fully awake and then the radio can be enabled. */ rt2800usb_set_state(rt2x00dev, STATE_AWAKE); msleep(1); @@ -1918,7 +1918,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, break; case STATE_RADIO_OFF: /* - * After the radio has been disablee, the device should + * After the radio has been disabled, the device should * be put to sleep for powersaving. */ rt2800usb_disable_radio(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 61a8be61d3f5..2d9dc3783361 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -1921,7 +1921,7 @@ struct mac_iveiv_entry { #define RXWI_W3_SNR1 FIELD32(0x0000ff00) /* - * Macro's for converting txpower from EEPROM to mac80211 value + * Macros for converting txpower from EEPROM to mac80211 value * and from mac80211 value to register value. */ #define MIN_G_TXPOWER 0 diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4c76c8d93cb5..cbec91ef6f76 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -245,7 +245,7 @@ struct link_ant { struct antenna_setup active; /* - * RSSI information for the different antenna's. + * RSSI information for the different antennas. * These statistics are used to determine when * to switch antenna when using software diversity. * @@ -633,7 +633,7 @@ struct rt2x00_dev { * The structure stored in here depends on the * system bus (PCI or USB). * When accessing this variable, the rt2x00dev_{pci,usb} - * macro's should be used for correct typecasting. + * macros should be used for correct typecasting. */ struct device *dev; diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 3e019a12df2e..c6e0bcf78e9e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -132,7 +132,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Failsafe: Make sure we are not sending the * ANTENNA_SW_DIVERSITY state to the driver. - * If that happes fallback to hardware default, + * If that happens, fallback to hardware defaults, * or our own default. * The calls to rt2x00lib_config_antenna_check() * might have caused that we restore back to the already diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index c54eda3c2db0..30fbd3bbe08b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -129,7 +129,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc) /* Pull buffer to correct size */ skb_pull(skb, txdesc->iv_len); - /* IV/EIV data has officially be stripped */ + /* IV/EIV data has officially been stripped */ skbdesc->flags |= SKBDESC_IV_STRIPPED; } diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index eb9b981b9139..32570758e67c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -158,7 +158,7 @@ static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) /* * During the last period we have sampled the RSSI - * from both antenna's. It now is time to determine + * from both antennas. It now is time to determine * which antenna demonstrated the best performance. * When we are already on the antenna with the best * performance, then there really is nothing for us diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3425984a55c7..9d31c23b92fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -341,7 +341,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) int status; /* - * Mac80211 might be calling this function while we are trying + * mac80211 might be calling this function while we are trying * to remove the device or perhaps suspending it. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) @@ -587,7 +587,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, int update_bssid = 0; /* - * Mac80211 might be calling this function while we are trying + * mac80211 might be calling this function while we are trying * to remove the device or perhaps suspending it. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index b5e06347c8a7..47d175a13790 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -29,7 +29,7 @@ #include /** - * DOC: Entrie frame size + * DOC: Entry frame size * * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes, * for USB devices this restriction does not apply, but the value of @@ -45,13 +45,13 @@ /** * DOC: Number of entries per queue * - * Under normal load without fragmentation 12 entries are sufficient + * Under normal load without fragmentation, 12 entries are sufficient * without the queue being filled up to the maximum. When using fragmentation - * and the queue threshold code we need to add some additional margins to + * and the queue threshold code, we need to add some additional margins to * make sure the queue will never (or only under extreme load) fill up * completely. - * Since we don't use preallocated DMA having a large number of queue entries - * will have only minimal impact on the memory requirements for the queue. + * Since we don't use preallocated DMA, having a large number of queue entries + * will have minimal impact on the memory requirements for the queue. */ #define RX_ENTRIES 24 #define TX_ENTRIES 24 diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 861322d97fce..983e52e127a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -176,8 +176,8 @@ struct rt2x00_field32 { #define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x)) /* - * Macro's to find first set bit in a variable. - * These macro's behaves the same as the __ffs() function with + * Macros to find first set bit in a variable. + * These macros behave the same as the __ffs() functions but * the most important difference that this is done during * compile-time rather then run-time. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b435c140cb96..fb95b8cc4fe9 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2312,7 +2312,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) } /* - * Determine number of antenna's. + * Determine number of antennas. */ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 6c71f77c8165..93eb699165cc 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1476,7 +1476,7 @@ struct hw_pairwise_ta_entry { #define RXD_W15_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to mac80211 value + * Macros for converting txpower from EEPROM to mac80211 value * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index c8016f65b4bd..81fe0be51c42 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -809,7 +809,7 @@ struct hw_pairwise_ta_entry { /* * EEPROM antenna. - * ANTENNA_NUM: Number of antenna's. + * ANTENNA_NUM: Number of antennas. * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only. @@ -1058,7 +1058,7 @@ struct hw_pairwise_ta_entry { #define RXD_W5_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to mac80211 value + * Macros for converting txpower from EEPROM to mac80211 value * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 -- cgit v1.2.2 From da3c821f549419e09b4b64f07d99f52174daae6d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 19 Jul 2009 15:00:39 +0200 Subject: wl12xx: fix spelling Changes (comments and debug output): * couldnt -> couldn't * frmware -> firmware * recevied -> received Signed-off-by: Stefan Weil Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_acx.c | 4 ++-- drivers/net/wireless/wl12xx/wl1251_ops.c | 4 ++-- drivers/net/wireless/wl12xx/wl1251_rx.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index 5a8d21c3192d..a46c92a29526 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c @@ -84,7 +84,7 @@ int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id) ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY, default_key, sizeof(*default_key)); if (ret < 0) { - wl1251_error("Couldnt set default key"); + wl1251_error("Couldn't set default key"); goto out; } @@ -231,7 +231,7 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl) ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, feature, sizeof(*feature)); if (ret < 0) { - wl1251_error("Couldnt set HW encryption"); + wl1251_error("Couldn't set HW encryption"); goto out; } diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.c b/drivers/net/wireless/wl12xx/wl1251_ops.c index 96a45f595297..e7b9aab3682f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ops.c +++ b/drivers/net/wireless/wl12xx/wl1251_ops.c @@ -423,7 +423,7 @@ static void wl1251_irq_work(struct work_struct *work) wl->rx_counter = wl1251_mem_read32(wl, wl->data_path->rx_control_addr); - /* We handle a frmware bug here */ + /* We handle a firmware bug here */ switch ((wl->rx_counter - wl->rx_handled) & 0xf) { case 0: wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); @@ -575,7 +575,7 @@ static int wl1251_hw_init_data_path_config(struct wl1251 *wl) wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), GFP_KERNEL); if (!wl->data_path) { - wl1251_error("Couldnt allocate data path parameters"); + wl1251_error("Couldn't allocate data path parameters"); return -ENOMEM; } diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h index 81156b9c4758..563a3fde40fb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.h +++ b/drivers/net/wireless/wl12xx/wl1251_rx.h @@ -88,7 +88,7 @@ struct wl1251_rx_descriptor { u8 type; /* - * Recevied Rate: + * Received Rate: * 0x0A - 1MBPS * 0x14 - 2MBPS * 0x37 - 5_5MBPS -- cgit v1.2.2 From 1b7e528b2e39bfed37228eedaaf0665196d8ddc9 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sun, 21 Jun 2009 00:02:14 +0200 Subject: ath9k: wake up the chip for TSF reset If we are in NETWORK SLEEP state, AR_SLP32_TSF_WRITE_STATUS limit always exceeds in 'ath9k_hw_reset_tsf', because reading of the AR_SLP3 register always return with the magic 0xdeadbeef value. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b9d1a13ba164..98537698be22 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3842,6 +3842,7 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah) { int count; + ath9k_ps_wakeup(ah->ah_sc); count = 0; while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { count++; @@ -3853,6 +3854,7 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah) udelay(10); } REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); + ath9k_ps_restore(ah->ah_sc); } bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) -- cgit v1.2.2 From f9b604f6c24ad161e9c9e30a138d5899724225c8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sun, 21 Jun 2009 00:02:15 +0200 Subject: ath9k: make use ath9k_hw_wait int ath9k_hw_reset_tsf We have a dedicated function for this kind of checks, use that instead of duplicating the code. Changes-licensed-under: ISC Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 17 +++++------------ drivers/net/wireless/ath/ath9k/hw.h | 1 + 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 98537698be22..605803ae9ed8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3840,19 +3840,12 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) void ath9k_hw_reset_tsf(struct ath_hw *ah) { - int count; - ath9k_ps_wakeup(ah->ah_sc); - count = 0; - while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { - count++; - if (count > 10) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); - break; - } - udelay(10); - } + if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, + AH_TSF_WRITE_TIMEOUT)) + DPRINTF(ah->ah_sc, ATH_DBG_RESET, + "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); + REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); ath9k_ps_restore(ah->ah_sc); } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9a4570d7ecbe..28bffdb365a2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -95,6 +95,7 @@ #define MAX_RATE_POWER 63 #define AH_WAIT_TIMEOUT 100000 /* (us) */ +#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ #define AH_TIME_QUANTUM 10 #define AR_KEYTABLE_SIZE 128 #define POWER_UP_TIME 200000 -- cgit v1.2.2 From 9ab56078e638efb75ac4ccd27c7196cdfed2e6c8 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 13 Jul 2009 00:10:07 +0200 Subject: arlan: inverted logic? Inverted logic Signed-off-by: Roel Kluin Signed-off-by: John W. Linville --- drivers/net/wireless/arlan-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c index d479f4735aaa..f96c634e2d35 100644 --- a/drivers/net/wireless/arlan-main.c +++ b/drivers/net/wireless/arlan-main.c @@ -1022,7 +1022,7 @@ static int arlan_mac_addr(struct net_device *dev, void *p) ARLAN_DEBUG_ENTRY("arlan_mac_addr"); return -EINVAL; - if (!netif_running(dev)) + if (netif_running(dev)) return -EBUSY; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -- cgit v1.2.2 From e6a3f551bc236010c4d4d99e626e150e98a4c3e6 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 19 Jul 2009 21:53:14 -0500 Subject: p54: Eliminate unnecessary initialization In two places, variables are unnecessilarly initialized to NULL. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/eeprom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 549ef2d19cd7..0efe67deedee 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -529,7 +529,7 @@ static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src, int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) { struct p54_common *priv = dev->priv; - struct eeprom_pda_wrap *wrap = NULL; + struct eeprom_pda_wrap *wrap; struct pda_entry *entry; unsigned int data_len, entry_len; void *tmp; @@ -722,7 +722,7 @@ int p54_read_eeprom(struct ieee80211_hw *dev) struct p54_common *priv = dev->priv; size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize; int ret = -ENOMEM; - void *eeprom = NULL; + void *eeprom; maxblocksize = EEPROM_READBACK_LEN; if (priv->fw_var >= 0x509) -- cgit v1.2.2 From b68518fcbc6e0fe8c06a218cd2b92f62f3730cf9 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 20 Jul 2009 11:47:45 +0800 Subject: iwmc3200wifi: use cfg80211_connect_result to send req/resp IE cfg80211_connect_result() let us specify associate request and response IEs as parameters after we are connected. We use this capability instead of doing it ourselves with WEXT. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/iwm.h | 5 +++++ drivers/net/wireless/iwmc3200wifi/main.c | 7 +++++++ drivers/net/wireless/iwmc3200wifi/rx.c | 36 ++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 79d9d89d47ae..2175a481d2f4 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -281,6 +281,11 @@ struct iwm_priv { struct work_struct reset_worker; struct mutex mutex; + u8 *req_ie; + int req_ie_len; + u8 *resp_ie; + int resp_ie_len; + char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); }; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 484f110151b7..cf2574442b57 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -497,6 +497,13 @@ void iwm_link_off(struct iwm_priv *iwm) memset(wstats, 0, sizeof(struct iw_statistics)); wstats->qual.updated = IW_QUAL_ALL_INVALID; + kfree(iwm->req_ie); + iwm->req_ie = NULL; + iwm->req_ie_len = 0; + kfree(iwm->resp_ie); + iwm->resp_ie = NULL; + iwm->resp_ie_len = 0; + del_timer_sync(&iwm->watchdog); } diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 82b572a6fc0b..6743391a45be 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -519,7 +519,8 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, - NULL, 0, NULL, 0, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, WLAN_STATUS_SUCCESS, GFP_KERNEL); break; case UMAC_ASSOC_COMPLETE_FAILURE: @@ -771,37 +772,46 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, struct iwm_wifi_cmd *cmd) { struct iwm_umac_notif_mgt_frame *mgt_frame = - (struct iwm_umac_notif_mgt_frame *)buf; + (struct iwm_umac_notif_mgt_frame *)buf; struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; u8 *ie; - unsigned int event; - union iwreq_data wrqu; IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, le16_to_cpu(mgt_frame->len)); if (ieee80211_is_assoc_req(mgt->frame_control)) { ie = mgt->u.assoc_req.variable;; - event = IWEVASSOCREQIE; + iwm->req_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->req_ie); + iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, + iwm->req_ie_len, GFP_KERNEL); } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { ie = mgt->u.reassoc_req.variable;; - event = IWEVASSOCREQIE; + iwm->req_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->req_ie); + iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, + iwm->req_ie_len, GFP_KERNEL); } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { ie = mgt->u.assoc_resp.variable;; - event = IWEVASSOCRESPIE; + iwm->resp_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->resp_ie); + iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, + iwm->resp_ie_len, GFP_KERNEL); } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { ie = mgt->u.reassoc_resp.variable;; - event = IWEVASSOCRESPIE; + iwm->resp_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->resp_ie); + iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, + iwm->resp_ie_len, GFP_KERNEL); } else { IWM_ERR(iwm, "Unsupported management frame"); return 0; } - wrqu.data.length = le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); - - IWM_HEXDUMP(iwm, DBG, MLME, "EVT: ", ie, wrqu.data.length); - wireless_send_event(iwm_to_ndev(iwm), event, &wrqu, ie); - return 0; } -- cgit v1.2.2 From 9c7c0cdd24e64f9aed39453a1bffc3b3fd16ef99 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 20 Jul 2009 11:47:46 +0800 Subject: iwmc3200wifi: fix cfg80211_connect_result is called in IBSS Avoid calling cfg80211_connect_result() in IBSS mode. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 6743391a45be..86079a187eef 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -517,6 +517,9 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm_link_on(iwm); + if (iwm->conf.mode == UMAC_MODE_IBSS) + goto ibss; + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, iwm->req_ie, iwm->req_ie_len, @@ -530,6 +533,9 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm_link_off(iwm); + if (iwm->conf.mode == UMAC_MODE_IBSS) + goto ibss; + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, @@ -538,11 +544,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, break; } - if (iwm->conf.mode == UMAC_MODE_IBSS) { - cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); - return 0; - } + return 0; + ibss: + cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); return 0; } -- cgit v1.2.2 From 971ad01169398170976951d3a9479a29d231c734 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 20 Jul 2009 11:47:47 +0800 Subject: iwmc3200wifi: fix a use-after-free bug The patch fixes a use-after-free bug for cmd->seq_num; Reported-by: Dan Carpenter Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/hal.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index ee127fe4f43f..c430418248b4 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c @@ -105,9 +105,9 @@ #include "umac.h" #include "debug.h" -static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, - struct iwm_nonwifi_cmd *cmd, - struct iwm_udma_nonwifi_cmd *udma_cmd) +static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, + struct iwm_nonwifi_cmd *cmd, + struct iwm_udma_nonwifi_cmd *udma_cmd) { INIT_LIST_HEAD(&cmd->pending); @@ -118,7 +118,7 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, cmd->seq_num = iwm->nonwifi_seq_num; udma_cmd->seq_num = cpu_to_le16(cmd->seq_num); - cmd->seq_num = iwm->nonwifi_seq_num++; + iwm->nonwifi_seq_num++; iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX; if (udma_cmd->resp) @@ -130,6 +130,8 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, cmd->buf.len = 0; memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); + + return cmd->seq_num; } u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm) @@ -369,7 +371,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, const void *payload) { struct iwm_nonwifi_cmd *cmd; - int ret; + int ret, seq_num; cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL); if (!cmd) { @@ -377,7 +379,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, return -ENOMEM; } - iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); + seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE || cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) { @@ -393,7 +395,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, if (ret < 0) return ret; - return cmd->seq_num; + return seq_num; } static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr, -- cgit v1.2.2 From f974cfdd8112a081fb1a402bf77835f28f37fcad Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Mon, 20 Jul 2009 08:00:30 -0400 Subject: ath5k: fix values for bus error bits in ISR2 The new values are taken from the recently open sourced Atheros HAL. Correctness is also confirmed by the users with access to Atheros documentation. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/reg.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 6809b54a2ad7..debad07d9900 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -339,9 +339,9 @@ #define AR5K_SISR2 0x008c /* Register Address [5211+] */ #define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ #define AR5K_SISR2_QCU_TXURN_S 0 -#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */ -#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */ +#define AR5K_SISR2_MCABT 0x00010000 /* Master Cycle Abort */ +#define AR5K_SISR2_SSERR 0x00020000 /* Signaled System Error */ +#define AR5K_SISR2_DPERR 0x00040000 /* Bus parity error */ #define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ #define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ @@ -430,9 +430,9 @@ #define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ #define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ #define AR5K_SIMR2_QCU_TXURN_S 0 -#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */ -#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */ +#define AR5K_SIMR2_MCABT 0x00010000 /* Master Cycle Abort */ +#define AR5K_SIMR2_SSERR 0x00020000 /* Signaled System Error */ +#define AR5K_SIMR2_DPERR 0x00040000 /* Bus parity error */ #define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ #define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ -- cgit v1.2.2 From f298c282a5233126ffe6385c02a9e79f695bed0f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 21 Jul 2009 14:25:53 +0300 Subject: wl1251: remove accidentally added wl1251_netlink.c Commit "wl1251: add wl1251 prefix to all 1251 files" accidentally added wl1251_netlink.c which contains a private netlink interface. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_netlink.c | 679 --------------------------- 1 file changed, 679 deletions(-) delete mode 100644 drivers/net/wireless/wl12xx/wl1251_netlink.c (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/wl1251_netlink.c b/drivers/net/wireless/wl12xx/wl1251_netlink.c deleted file mode 100644 index 67d3d5a3b519..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_netlink.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * 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 program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#include "wl1251_netlink.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "wl1251.h" -#include "wl1251_spi.h" -#include "wl1251_acx.h" - -/* FIXME: this should be changed as soon as user space catches up */ -#define WL1251_NL_NAME "wl1251" -#define WL1251_NL_VERSION 1 - -#define WL1251_MAX_TEST_LENGTH 1024 -#define WL1251_MAX_NVS_LENGTH 1024 - -enum wl1251_nl_commands { - WL1251_NL_CMD_UNSPEC, - WL1251_NL_CMD_TEST, - WL1251_NL_CMD_INTERROGATE, - WL1251_NL_CMD_CONFIGURE, - WL1251_NL_CMD_PHY_REG_READ, - WL1251_NL_CMD_NVS_PUSH, - WL1251_NL_CMD_REG_WRITE, - WL1251_NL_CMD_REG_READ, - WL1251_NL_CMD_SET_PLT_MODE, - - __WL1251_NL_CMD_AFTER_LAST -}; -#define WL1251_NL_CMD_MAX (__WL1251_NL_CMD_AFTER_LAST - 1) - -enum wl1251_nl_attrs { - WL1251_NL_ATTR_UNSPEC, - WL1251_NL_ATTR_IFNAME, - WL1251_NL_ATTR_CMD_TEST_PARAM, - WL1251_NL_ATTR_CMD_TEST_ANSWER, - WL1251_NL_ATTR_CMD_IE, - WL1251_NL_ATTR_CMD_IE_LEN, - WL1251_NL_ATTR_CMD_IE_BUFFER, - WL1251_NL_ATTR_CMD_IE_ANSWER, - WL1251_NL_ATTR_REG_ADDR, - WL1251_NL_ATTR_REG_VAL, - WL1251_NL_ATTR_NVS_BUFFER, - WL1251_NL_ATTR_NVS_LEN, - WL1251_NL_ATTR_PLT_MODE, - - __WL1251_NL_ATTR_AFTER_LAST -}; -#define WL1251_NL_ATTR_MAX (__WL1251_NL_ATTR_AFTER_LAST - 1) - -static struct genl_family wl1251_nl_family = { - .id = GENL_ID_GENERATE, - .name = WL1251_NL_NAME, - .hdrsize = 0, - .version = WL1251_NL_VERSION, - .maxattr = WL1251_NL_ATTR_MAX, -}; - -static struct net_device *ifname_to_netdev(struct net *net, - struct genl_info *info) -{ - char *ifname; - - if (!info->attrs[WL1251_NL_ATTR_IFNAME]) - return NULL; - - ifname = nla_data(info->attrs[WL1251_NL_ATTR_IFNAME]); - - wl1251_debug(DEBUG_NETLINK, "Looking for %s", ifname); - - return dev_get_by_name(net, ifname); -} - -static struct wl1251 *ifname_to_wl1251(struct net *net, struct genl_info *info) -{ - struct net_device *netdev; - struct wireless_dev *wdev; - struct wiphy *wiphy; - struct ieee80211_hw *hw; - - netdev = ifname_to_netdev(net, info); - if (netdev == NULL) { - wl1251_error("Wrong interface"); - return NULL; - } - - wdev = netdev->ieee80211_ptr; - if (wdev == NULL) { - wl1251_error("ieee80211_ptr is NULL"); - return NULL; - } - - wiphy = wdev->wiphy; - if (wiphy == NULL) { - wl1251_error("wiphy is NULL"); - return NULL; - } - - hw = wiphy_priv(wiphy); - if (hw == NULL) { - wl1251_error("hw is NULL"); - return NULL; - } - - dev_put(netdev); - - return hw->priv; -} - -static int wl1251_nl_test_cmd(struct sk_buff *skb, struct genl_info *info) -{ - struct wl1251 *wl; - struct wl1251_command *cmd; - char *buf; - int buf_len, ret, cmd_len; - u8 answer; - - if (!info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]) - return -EINVAL; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - return -EINVAL; - } - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - buf = nla_data(info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]); - buf_len = nla_len(info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]); - answer = nla_get_u8(info->attrs[WL1251_NL_ATTR_CMD_TEST_ANSWER]); - - cmd->header.id = CMD_TEST; - memcpy(cmd->parameters, buf, buf_len); - cmd_len = sizeof(struct wl1251_cmd_header) + buf_len; - - mutex_lock(&wl->mutex); - ret = wl1251_cmd_test(wl, cmd, cmd_len, answer); - mutex_unlock(&wl->mutex); - - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto out; - } - - if (answer) { - struct sk_buff *msg; - void *hdr; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) { - ret = -ENOMEM; - goto out; - } - - hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, - &wl1251_nl_family, 0, WL1251_NL_CMD_TEST); - if (IS_ERR(hdr)) { - ret = PTR_ERR(hdr); - goto nla_put_failure; - } - - NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, - nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); - NLA_PUT(msg, WL1251_NL_ATTR_CMD_TEST_ANSWER, - sizeof(*cmd), cmd); - - ret = genlmsg_end(msg, hdr); - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto nla_put_failure; - } - - wl1251_debug(DEBUG_NETLINK, "TEST cmd sent, answer"); - ret = genlmsg_reply(msg, info); - goto out; - - nla_put_failure: - nlmsg_free(msg); - } else - wl1251_debug(DEBUG_NETLINK, "TEST cmd sent"); - -out: - kfree(cmd); - return ret; -} - -static int wl1251_nl_interrogate(struct sk_buff *skb, struct genl_info *info) -{ - struct wl1251 *wl; - struct sk_buff *msg; - int ret = -ENOBUFS, cmd_ie, cmd_ie_len; - struct wl1251_command *cmd; - void *hdr; - - if (!info->attrs[WL1251_NL_ATTR_CMD_IE]) - return -EINVAL; - - if (!info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]) - return -EINVAL; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - ret = -EINVAL; - goto nla_put_failure; - } - - /* acx id */ - cmd_ie = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE]); - - /* maximum length of acx, including all headers */ - cmd_ie_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]); - - wl1251_debug(DEBUG_NETLINK, "Getting IE 0x%x (len %d)", - cmd_ie, cmd_ie_len); - - mutex_lock(&wl->mutex); - ret = wl1251_cmd_interrogate(wl, cmd_ie, cmd, cmd_ie_len); - mutex_unlock(&wl->mutex); - - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto nla_put_failure; - } - - hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, - &wl1251_nl_family, 0, WL1251_NL_CMD_INTERROGATE); - if (IS_ERR(hdr)) { - ret = PTR_ERR(hdr); - goto nla_put_failure; - } - - NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, - nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); - NLA_PUT(msg, WL1251_NL_ATTR_CMD_IE_ANSWER, cmd_ie_len, cmd); - - ret = genlmsg_end(msg, hdr); - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto nla_put_failure; - } - - kfree(cmd); - return genlmsg_reply(msg, info); - - nla_put_failure: - kfree(cmd); - nlmsg_free(msg); - - return ret; -} - -static int wl1251_nl_configure(struct sk_buff *skb, struct genl_info *info) -{ - int ret = 0, cmd_ie_len, acx_len; - struct acx_header *acx = NULL; - struct sk_buff *msg; - struct wl1251 *wl; - void *cmd_ie; - u16 *id; - - if (!info->attrs[WL1251_NL_ATTR_CMD_IE_BUFFER]) - return -EINVAL; - - if (!info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]) - return -EINVAL; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - ret = -EINVAL; - goto nla_put_failure; - } - - /* contains the acx header but not the cmd header */ - cmd_ie = nla_data(info->attrs[WL1251_NL_ATTR_CMD_IE_BUFFER]); - - cmd_ie_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]); - - /* acx id is in the first two bytes */ - id = cmd_ie; - - /* need to add acx_header before cmd_ie, so create a new command */ - acx_len = sizeof(struct acx_header) + cmd_ie_len; - acx = kzalloc(acx_len, GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto nla_put_failure; - } - - /* copy the acx header and the payload */ - memcpy(&acx->id, cmd_ie, cmd_ie_len); - - mutex_lock(&wl->mutex); - ret = wl1251_cmd_configure(wl, *id, acx, acx_len); - mutex_unlock(&wl->mutex); - - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto nla_put_failure; - } - - wl1251_debug(DEBUG_NETLINK, "CONFIGURE cmd sent"); - - nla_put_failure: - kfree(acx); - nlmsg_free(msg); - - return ret; -} - -static int wl1251_nl_phy_reg_read(struct sk_buff *skb, struct genl_info *info) -{ - struct wl1251 *wl; - struct sk_buff *msg; - u32 reg_addr, *reg_value = NULL; - int ret = 0; - void *hdr; - - if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) - return -EINVAL; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - ret = -EINVAL; - goto nla_put_failure; - } - - reg_value = kmalloc(sizeof(*reg_value), GFP_KERNEL); - if (!reg_value) { - ret = -ENOMEM; - goto nla_put_failure; - } - - reg_addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); - - wl1251_debug(DEBUG_NETLINK, "Reading PHY reg 0x%x", reg_addr); - - mutex_lock(&wl->mutex); - ret = wl1251_cmd_read_memory(wl, reg_addr, reg_value, - sizeof(*reg_value)); - mutex_unlock(&wl->mutex); - - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto nla_put_failure; - } - - - hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, - &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); - if (IS_ERR(hdr)) { - ret = PTR_ERR(hdr); - goto nla_put_failure; - } - - NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, - nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); - - NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, *reg_value); - - ret = genlmsg_end(msg, hdr); - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto nla_put_failure; - } - - kfree(reg_value); - - return genlmsg_reply(msg, info); - - nla_put_failure: - nlmsg_free(msg); - kfree(reg_value); - - return ret; -} - -static int wl1251_nl_nvs_push(struct sk_buff *skb, struct genl_info *info) -{ - struct wl1251 *wl; - int ret = 0; - - if (!info->attrs[WL1251_NL_ATTR_NVS_BUFFER]) - return -EINVAL; - - if (!info->attrs[WL1251_NL_ATTR_NVS_LEN]) - return -EINVAL; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - return -EINVAL; - } - - mutex_lock(&wl->mutex); - wl->nvs_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_NVS_LEN]); - if (wl->nvs_len % 4) { - wl1251_error("NVS size is not multiple of 32: %d", wl->nvs_len); - ret = -EILSEQ; - goto out; - } - - /* If we already have an NVS, we should free it */ - kfree(wl->nvs); - - wl->nvs = kzalloc(wl->nvs_len, GFP_KERNEL); - if (wl->nvs == NULL) { - wl1251_error("Can't allocate NVS"); - ret = -ENOMEM; - goto out; - } - - memcpy(wl->nvs, - nla_data(info->attrs[WL1251_NL_ATTR_NVS_BUFFER]), - wl->nvs_len); - - wl1251_debug(DEBUG_NETLINK, "got NVS from userspace, %d bytes", - wl->nvs_len); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -static int wl1251_nl_reg_read(struct sk_buff *skb, struct genl_info *info) -{ - struct wl1251 *wl; - u32 addr, val; - int ret = 0; - struct sk_buff *msg; - void *hdr; - - if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) - return -EINVAL; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - return -EINVAL; - } - - addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); - - mutex_lock(&wl->mutex); - val = wl1251_reg_read32(wl, addr); - mutex_unlock(&wl->mutex); - - hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, - &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); - if (IS_ERR(hdr)) { - ret = PTR_ERR(hdr); - goto nla_put_failure; - } - - NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, - nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); - - NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, val); - - ret = genlmsg_end(msg, hdr); - if (ret < 0) { - wl1251_error("%s() failed", __func__); - goto nla_put_failure; - } - - return genlmsg_reply(msg, info); - - nla_put_failure: - nlmsg_free(msg); - - return ret; -} - -static int wl1251_nl_reg_write(struct sk_buff *skb, struct genl_info *info) -{ - struct wl1251 *wl; - u32 addr, val; - - if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) - return -EINVAL; - - if (!info->attrs[WL1251_NL_ATTR_REG_VAL]) - return -EINVAL; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - return -EINVAL; - } - - addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); - val = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_VAL]); - - mutex_lock(&wl->mutex); - wl1251_reg_write32(wl, addr, val); - mutex_unlock(&wl->mutex); - - return 0; -} - -static int wl1251_nl_set_plt_mode(struct sk_buff *skb, struct genl_info *info) -{ - struct wl1251 *wl; - u32 val; - int ret; - - if (!info->attrs[WL1251_NL_ATTR_PLT_MODE]) - return -EINVAL; - - wl = ifname_to_wl1251(&init_net, info); - if (wl == NULL) { - wl1251_error("wl1251 not found"); - return -EINVAL; - } - - val = nla_get_u32(info->attrs[WL1251_NL_ATTR_PLT_MODE]); - - switch (val) { - case 0: - ret = wl1251_plt_stop(wl); - break; - case 1: - ret = wl1251_plt_start(wl); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static struct nla_policy wl1251_nl_policy[WL1251_NL_ATTR_MAX + 1] = { - [WL1251_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING, - .len = IFNAMSIZ-1 }, - [WL1251_NL_ATTR_CMD_TEST_PARAM] = { .type = NLA_BINARY, - .len = WL1251_MAX_TEST_LENGTH }, - [WL1251_NL_ATTR_CMD_TEST_ANSWER] = { .type = NLA_U8 }, - [WL1251_NL_ATTR_CMD_IE] = { .type = NLA_U32 }, - [WL1251_NL_ATTR_CMD_IE_LEN] = { .type = NLA_U32 }, - [WL1251_NL_ATTR_CMD_IE_BUFFER] = { .type = NLA_BINARY, - .len = WL1251_MAX_TEST_LENGTH }, - [WL1251_NL_ATTR_CMD_IE_ANSWER] = { .type = NLA_BINARY, - .len = WL1251_MAX_TEST_LENGTH }, - [WL1251_NL_ATTR_REG_ADDR] = { .type = NLA_U32 }, - [WL1251_NL_ATTR_REG_VAL] = { .type = NLA_U32 }, - [WL1251_NL_ATTR_NVS_BUFFER] = { .type = NLA_BINARY, - .len = WL1251_MAX_NVS_LENGTH }, - [WL1251_NL_ATTR_NVS_LEN] = { .type = NLA_U32 }, - [WL1251_NL_ATTR_PLT_MODE] = { .type = NLA_U32 }, -}; - -static struct genl_ops wl1251_nl_ops[] = { - { - .cmd = WL1251_NL_CMD_TEST, - .doit = wl1251_nl_test_cmd, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = WL1251_NL_CMD_INTERROGATE, - .doit = wl1251_nl_interrogate, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = WL1251_NL_CMD_CONFIGURE, - .doit = wl1251_nl_configure, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = WL1251_NL_CMD_PHY_REG_READ, - .doit = wl1251_nl_phy_reg_read, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = WL1251_NL_CMD_NVS_PUSH, - .doit = wl1251_nl_nvs_push, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = WL1251_NL_CMD_REG_WRITE, - .doit = wl1251_nl_reg_write, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = WL1251_NL_CMD_REG_READ, - .doit = wl1251_nl_reg_read, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = WL1251_NL_CMD_SET_PLT_MODE, - .doit = wl1251_nl_set_plt_mode, - .policy = wl1251_nl_policy, - .flags = GENL_ADMIN_PERM, - }, -}; - -int wl1251_nl_register(void) -{ - int err, i; - - err = genl_register_family(&wl1251_nl_family); - if (err) - return err; - - for (i = 0; i < ARRAY_SIZE(wl1251_nl_ops); i++) { - err = genl_register_ops(&wl1251_nl_family, &wl1251_nl_ops[i]); - if (err) - goto err_out; - } - return 0; - err_out: - genl_unregister_family(&wl1251_nl_family); - return err; -} - -void wl1251_nl_unregister(void) -{ - genl_unregister_family(&wl1251_nl_family); -} -- cgit v1.2.2 From 270b7588b376968d4db3af01e6d9907814c45552 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 21 Jul 2009 14:26:01 +0300 Subject: wl1251: remove wl1251_plt_start/stop() This Production Line Testing code is currently unused and can be removed. It can be reintroduced when nl80211 test mode implemented for the driver. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 54 ------------------------------- 1 file changed, 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 509cbef5e271..da4c688c46af 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -246,60 +246,6 @@ out: mutex_unlock(&wl->mutex); } -int wl1251_plt_start(struct wl1251 *wl) -{ - int ret; - - mutex_lock(&wl->mutex); - - wl1251_notice("power up"); - - if (wl->state != WL1251_STATE_OFF) { - wl1251_error("cannot go into PLT state because not " - "in off state: %d", wl->state); - return -EBUSY; - } - - wl->state = WL1251_STATE_PLT; - - ret = wl1251_chip_wakeup(wl); - if (ret < 0) - return ret; - - ret = wl->chip.op_boot(wl); - if (ret < 0) - return ret; - - wl1251_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); - - ret = wl->chip.op_plt_init(wl); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_plt_stop(struct wl1251 *wl) -{ - mutex_lock(&wl->mutex); - - wl1251_notice("power down"); - - if (wl->state != WL1251_STATE_PLT) { - wl1251_error("cannot power down because not in PLT " - "state: %d", wl->state); - return -EBUSY; - } - - wl1251_disable_interrupts(wl); - wl1251_power_off(wl); - - wl->state = WL1251_STATE_OFF; - - return 0; -} - - static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl1251 *wl = hw->priv; -- cgit v1.2.2 From 95a2b2ef82dc0bd10475c02e9d1fc7c93e708d03 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 21 Jul 2009 21:03:10 -0400 Subject: ath9k: do not stop the queues in driver stop mac80211 will have disabled the queues for us when needed. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 254e78786eee..3436295e0509 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2101,8 +2101,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) mutex_lock(&sc->mutex); - ieee80211_stop_queues(hw); - if (ath9k_wiphy_started(sc)) { mutex_unlock(&sc->mutex); return; /* another wiphy still in use */ -- cgit v1.2.2 From ccc78ec5d463e6c99f4a384be52b31222ffe2e21 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 21 Jul 2009 21:03:42 -0400 Subject: adm8211: remove uneeded code during suspend/resume mac80211 drivers do not need to stop the software queues or call their own stop() callback upon suspend as we do it for drivers. Equally drivers don't have to call their own start() or start the queues as mac80211 will do it for us. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index ecc93834533f..5695911bc602 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1964,14 +1964,6 @@ static void __devexit adm8211_remove(struct pci_dev *pdev) #ifdef CONFIG_PM static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) { - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct adm8211_priv *priv = dev->priv; - - if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) { - ieee80211_stop_queues(dev); - adm8211_stop(dev); - } - pci_save_state(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; @@ -1979,17 +1971,8 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) static int adm8211_resume(struct pci_dev *pdev) { - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct adm8211_priv *priv = dev->priv; - pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - - if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) { - adm8211_start(dev); - ieee80211_wake_queues(dev); - } - return 0; } #endif /* CONFIG_PM */ -- cgit v1.2.2