From bdcd81707973cf8aa9305337166f8ee842a050d4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Jul 2011 00:22:30 +0300 Subject: Add ath6kl cleaned up driver Last May we started working on cleaning up ath6kl driver which is currently in staging. The work has happened in a separate ath6kl-cleanup tree: http://git.kernel.org/?p=linux/kernel/git/kvalo/ath6kl-cleanup.git;a=summary After over 1100 (!) patches we have now reached a state where I would like to start discussing about pushing the driver to the wireless trees and replacing the staging driver. The driver is now a lot smaller and looks like a proper Linux driver. The size of the driver (measured with simple wc -l) dropped from 49 kLOC to 18 kLOC and the number of the .c and .h files dropped from 107 to 22. Most importantly the number of subdirectories reduced from 26 to zero :) There are two remaining checkpatch warnings in the driver which we decided to omit for now: drivers/net/wireless/ath/ath6kl/debug.c:31: WARNING: printk() should include KERN_ facility level drivers/net/wireless/ath/ath6kl/sdio.c:527: WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt The driver has endian annotations for all the hardware specific structures and there are no sparse errors. Unfortunately I don't have any big endian hardware to test that right now. We have been testing the driver both on x86 and arm platforms. The code is also compiled with sparc and parisc cross compilers. Notable missing features compared to the current staging driver are: o HCI over SDIO support o nl80211 testmode o firmware logging o suspend support Testmode, firmware logging and suspend support will be added soon. HCI over SDIO support will be more difficult as the HCI driver needs to share code with the wifi driver. This is something we need to research more. Also I want to point out the changes I did for signed endian support. As I wasn't able to find any support for signed endian annotations I decided to follow what NTFS has done and added my own. Grep for sle16 and sle32, especially from wmi.h. Various people have been working on the cleanup, the hall of fame based on number of patches is: 543 Vasanthakumar Thiagarajan 403 Raja Mani 252 Kalle Valo 16 Vivek Natarajan 12 Suraj Sumangala 3 Joe Perches 2 Jouni Malinen Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Raja Mani Signed-off-by: Vivek Natarajan Signed-off-by: Suraj Sumangala Signed-off-by: Joe Perches Signed-off-by: Jouni Malinen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/node.c | 238 +++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 drivers/net/wireless/ath/ath6kl/node.c (limited to 'drivers/net/wireless/ath/ath6kl/node.c') diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c new file mode 100644 index 000000000000..b0f9ba2e463c --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/node.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" +#include "wmi.h" +#include "debug.h" + +struct bss *wlan_node_alloc(int wh_size) +{ + struct bss *ni; + + ni = kzalloc(sizeof(struct bss), GFP_ATOMIC); + + if ((ni != NULL) && wh_size) { + ni->ni_buf = kmalloc(wh_size, GFP_ATOMIC); + if (ni->ni_buf == NULL) { + kfree(ni); + return NULL; + } + } + + return ni; +} + +void wlan_node_free(struct bss *ni) +{ + kfree(ni->ni_buf); + kfree(ni); +} + +void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni, + const u8 *mac_addr) +{ + int hash; + + memcpy(ni->ni_macaddr, mac_addr, ETH_ALEN); + hash = ATH6KL_NODE_HASH(mac_addr); + ni->ni_refcnt = 1; + + ni->ni_tstamp = jiffies_to_msecs(jiffies); + ni->ni_actcnt = WLAN_NODE_INACT_CNT; + + spin_lock_bh(&nt->nt_nodelock); + + /* insert at the end of the node list */ + ni->ni_list_next = NULL; + ni->ni_list_prev = nt->nt_node_last; + if (nt->nt_node_last != NULL) + nt->nt_node_last->ni_list_next = ni; + + nt->nt_node_last = ni; + if (nt->nt_node_first == NULL) + nt->nt_node_first = ni; + + /* insert into the hash list */ + ni->ni_hash_next = nt->nt_hash[hash]; + if (ni->ni_hash_next != NULL) + nt->nt_hash[hash]->ni_hash_prev = ni; + + ni->ni_hash_prev = NULL; + nt->nt_hash[hash] = ni; + + spin_unlock_bh(&nt->nt_nodelock); +} + +struct bss *wlan_find_node(struct ath6kl_node_table *nt, + const u8 *mac_addr) +{ + struct bss *ni, *found_ni = NULL; + int hash; + + spin_lock_bh(&nt->nt_nodelock); + + hash = ATH6KL_NODE_HASH(mac_addr); + for (ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { + if (memcmp(ni->ni_macaddr, mac_addr, ETH_ALEN) == 0) { + ni->ni_refcnt++; + found_ni = ni; + break; + } + } + + spin_unlock_bh(&nt->nt_nodelock); + + return found_ni; +} + +void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni) +{ + int hash; + + spin_lock_bh(&nt->nt_nodelock); + + if (ni->ni_list_prev == NULL) + /* fix list head */ + nt->nt_node_first = ni->ni_list_next; + else + ni->ni_list_prev->ni_list_next = ni->ni_list_next; + + if (ni->ni_list_next == NULL) + /* fix list tail */ + nt->nt_node_last = ni->ni_list_prev; + else + ni->ni_list_next->ni_list_prev = ni->ni_list_prev; + + if (ni->ni_hash_prev == NULL) { + /* first in list so fix the list head */ + hash = ATH6KL_NODE_HASH(ni->ni_macaddr); + nt->nt_hash[hash] = ni->ni_hash_next; + } else { + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; + } + + if (ni->ni_hash_next != NULL) + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; + + wlan_node_free(ni); + + spin_unlock_bh(&nt->nt_nodelock); +} + +static void wlan_node_dec_free(struct bss *ni) +{ + if ((ni->ni_refcnt--) == 1) + wlan_node_free(ni); +} + +void wlan_free_allnodes(struct ath6kl_node_table *nt) +{ + struct bss *ni; + + while ((ni = nt->nt_node_first) != NULL) + wlan_node_reclaim(nt, ni); +} + +void wlan_iterate_nodes(struct ath6kl_node_table *nt, + void (*f) (void *arg, struct bss *), void *arg) +{ + struct bss *ni; + + spin_lock_bh(&nt->nt_nodelock); + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + ni->ni_refcnt++; + (*f) (arg, ni); + wlan_node_dec_free(ni); + } + spin_unlock_bh(&nt->nt_nodelock); +} + +void wlan_node_table_init(void *wmi, struct ath6kl_node_table *nt) +{ + ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n", + (unsigned long)nt); + + memset(nt, 0, sizeof(struct ath6kl_node_table)); + + spin_lock_init(&nt->nt_nodelock); + + nt->nt_wmi = wmi; + nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC; +} + +void wlan_refresh_inactive_nodes(struct ath6kl_node_table *nt) +{ + struct bss *bss; + u8 my_bssid[ETH_ALEN]; + u32 now; + + ath6kl_wmi_get_current_bssid(nt->nt_wmi, my_bssid); + + now = jiffies_to_msecs(jiffies); + bss = nt->nt_node_first; + while (bss != NULL) { + /* refresh all nodes except the current bss */ + if (memcmp(my_bssid, bss->ni_macaddr, sizeof(my_bssid)) != 0) { + if (((now - bss->ni_tstamp) > nt->nt_node_age) + || --bss->ni_actcnt == 0) { + wlan_node_reclaim(nt, bss); + } + } + bss = bss->ni_list_next; + } +} + +void wlan_node_table_cleanup(struct ath6kl_node_table *nt) +{ + wlan_free_allnodes(nt); +} + +struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 * ssid, + u32 ssid_len, bool is_wpa2, bool match_ssid) +{ + struct bss *ni, *found_ni = NULL; + u8 *ie_ssid; + + spin_lock_bh(&nt->nt_nodelock); + + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { + + ie_ssid = ni->ni_cie.ie_ssid; + + if ((ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && + (memcmp(ssid, &ie_ssid[2], ssid_len) == 0)) { + + if (match_ssid || + (is_wpa2 && ni->ni_cie.ie_rsn != NULL) || + (!is_wpa2 && ni->ni_cie.ie_wpa != NULL)) { + ni->ni_refcnt++; + found_ni = ni; + break; + } + } + } + + spin_unlock_bh(&nt->nt_nodelock); + + return found_ni; +} + +void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni) +{ + spin_lock_bh(&nt->nt_nodelock); + wlan_node_dec_free(ni); + spin_unlock_bh(&nt->nt_nodelock); +} -- cgit v1.2.3 From e4c7ffcb9564dfed125e99daebc5fdce0b828626 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 21 Jul 2011 13:49:32 +0530 Subject: ath6kl: Cleanup parameters for wlan_refresh_inactive_nodes() And remove the reference to wmi in ath6kl_node_table. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/node.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/ath/ath6kl/node.c') diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c index b0f9ba2e463c..533588cb5a1c 100644 --- a/drivers/net/wireless/ath/ath6kl/node.c +++ b/drivers/net/wireless/ath/ath6kl/node.c @@ -169,17 +169,17 @@ void wlan_node_table_init(void *wmi, struct ath6kl_node_table *nt) spin_lock_init(&nt->nt_nodelock); - nt->nt_wmi = wmi; nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC; } -void wlan_refresh_inactive_nodes(struct ath6kl_node_table *nt) +void wlan_refresh_inactive_nodes(struct ath6kl *ar) { + struct ath6kl_node_table *nt = &ar->scan_table; struct bss *bss; u8 my_bssid[ETH_ALEN]; u32 now; - ath6kl_wmi_get_current_bssid(nt->nt_wmi, my_bssid); + ath6kl_wmi_get_current_bssid(ar->wmi, my_bssid); now = jiffies_to_msecs(jiffies); bss = nt->nt_node_first; -- cgit v1.2.3 From 46ff8d5978b7796e3757b9ad908361beb8fb160b Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 21 Jul 2011 14:13:53 +0530 Subject: ath6kl: Remove ath6kl_wmi_get_current_bssid() Use the bssid from ath6kl directly. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/node.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net/wireless/ath/ath6kl/node.c') diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c index 533588cb5a1c..961154193ef5 100644 --- a/drivers/net/wireless/ath/ath6kl/node.c +++ b/drivers/net/wireless/ath/ath6kl/node.c @@ -176,16 +176,13 @@ void wlan_refresh_inactive_nodes(struct ath6kl *ar) { struct ath6kl_node_table *nt = &ar->scan_table; struct bss *bss; - u8 my_bssid[ETH_ALEN]; u32 now; - ath6kl_wmi_get_current_bssid(ar->wmi, my_bssid); - now = jiffies_to_msecs(jiffies); bss = nt->nt_node_first; while (bss != NULL) { /* refresh all nodes except the current bss */ - if (memcmp(my_bssid, bss->ni_macaddr, sizeof(my_bssid)) != 0) { + if (memcmp(ar->bssid, bss->ni_macaddr, ETH_ALEN) != 0) { if (((now - bss->ni_tstamp) > nt->nt_node_age) || --bss->ni_actcnt == 0) { wlan_node_reclaim(nt, bss); -- cgit v1.2.3 From 9d0c6bcf46c3df4a5d011749c94d4f85dd98931d Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 21 Jul 2011 14:16:57 +0530 Subject: ath6kl: Cleanup parameters of wlan_node_table_init() Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath6kl/node.c') diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c index 961154193ef5..7c9fbde9dedd 100644 --- a/drivers/net/wireless/ath/ath6kl/node.c +++ b/drivers/net/wireless/ath/ath6kl/node.c @@ -160,7 +160,7 @@ void wlan_iterate_nodes(struct ath6kl_node_table *nt, spin_unlock_bh(&nt->nt_nodelock); } -void wlan_node_table_init(void *wmi, struct ath6kl_node_table *nt) +void wlan_node_table_init(struct ath6kl_node_table *nt) { ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n", (unsigned long)nt); -- cgit v1.2.3 From 8a8bc5a440a0b42cc8fc0d5a60c041e7ab5d76d1 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 21 Jul 2011 14:42:52 +0530 Subject: ath6kl: Use ath6kl_cfg80211_scan_node() directly instead of function pointer Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/node.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/ath/ath6kl/node.c') diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c index 7c9fbde9dedd..131205c610b9 100644 --- a/drivers/net/wireless/ath/ath6kl/node.c +++ b/drivers/net/wireless/ath/ath6kl/node.c @@ -146,15 +146,14 @@ void wlan_free_allnodes(struct ath6kl_node_table *nt) wlan_node_reclaim(nt, ni); } -void wlan_iterate_nodes(struct ath6kl_node_table *nt, - void (*f) (void *arg, struct bss *), void *arg) +void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg) { struct bss *ni; spin_lock_bh(&nt->nt_nodelock); for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { ni->ni_refcnt++; - (*f) (arg, ni); + ath6kl_cfg80211_scan_node(arg, ni); wlan_node_dec_free(ni); } spin_unlock_bh(&nt->nt_nodelock); -- cgit v1.2.3