From 84e3196ff867c623056eea02c11a45e046490d89 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:53:29 +0100 Subject: rt2x00: Move link tuning into seperate file Move link and antenna tuning into a seperate file named rt2x00link.c, this makes the interface to the link tuner a lot cleaner. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 39ecf3b82ca1..19c068727a85 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -212,7 +212,7 @@ struct link_qual { * (WEIGHT_TX * tx_percentage) + * (WEIGHT_RX * rx_percentage)) / 100 * - * This value should then be checked to not be greated then 100. + * This value should then be checked to not be greater then 100. */ int rx_percentage; int rx_success; @@ -318,33 +318,6 @@ static inline int rt2x00_get_link_rssi(struct link *link) return DEFAULT_RSSI; } -static inline int rt2x00_get_link_ant_rssi(struct link *link) -{ - if (link->ant.rssi_ant && link->qual.rx_success) - return link->ant.rssi_ant; - return DEFAULT_RSSI; -} - -static inline void rt2x00_reset_link_ant_rssi(struct link *link) -{ - link->ant.rssi_ant = 0; -} - -static inline int rt2x00_get_link_ant_rssi_history(struct link *link, - enum antenna ant) -{ - if (link->ant.rssi_history[ant - ANTENNA_A]) - return link->ant.rssi_history[ant - ANTENNA_A]; - return DEFAULT_RSSI; -} - -static inline int rt2x00_update_ant_rssi(struct link *link, int rssi) -{ - int old_rssi = link->ant.rssi_history[link->ant.active.rx - ANTENNA_A]; - link->ant.rssi_history[link->ant.active.rx - ANTENNA_A] = rssi; - return old_rssi; -} - /* * Interface structure * Per interface configuration details, this structure -- cgit v1.2.3 From eb20b4e8a6998ca68d9ac0963ee36a1a36fe241d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:54:22 +0100 Subject: rt2x00: Reduce calls to bbp_read() The link_tuner() function will always call bbp_read() at the start of the function. Because this is an indirect register access has some costs attached to it (especially for USB hardware). We already store the value read from the register into the vgc_level value inside the link structure. Instead of reading from the register we can read that field directly and base the tuner on that value. This reduces the time the registers are locked with the csr_mutex and speeds up the link_tuner processing. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 27 ++++++++--------- drivers/net/wireless/rt2x00/rt2500pci.c | 50 +++++++++++++++---------------- drivers/net/wireless/rt2x00/rt2x00.h | 9 ++++-- drivers/net/wireless/rt2x00/rt61pci.c | 49 ++++++++++++++----------------- drivers/net/wireless/rt2x00/rt73usb.c | 52 +++++++++++++++------------------ 5 files changed, 92 insertions(+), 95 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 1afba42cc128..e87ad43e8e8d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -600,35 +600,36 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = bbp; } +static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); + rt2x00dev->link.vgc_level = vgc_level; + rt2x00dev->link.vgc_level_reg = vgc_level; +} + static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt2400pci_bbp_write(rt2x00dev, 13, 0x08); - rt2x00dev->link.vgc_level = 0x08; + rt2400pci_set_vgc(rt2x00dev, 0x08); } static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) { - u8 reg; + struct link *link = &rt2x00dev->link; /* * The link tuner should not run longer then 60 seconds, * and should run once every 2 seconds. */ - if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count & 1)) + if (link->count > 60 || !(link->count & 1)) return; /* * Base r13 link tuning on the false cca count. */ - rt2400pci_bbp_read(rt2x00dev, 13, ®); - - if (rt2x00dev->link.qual.false_cca > 512 && reg < 0x20) { - rt2400pci_bbp_write(rt2x00dev, 13, ++reg); - rt2x00dev->link.vgc_level = reg; - } else if (rt2x00dev->link.qual.false_cca < 100 && reg > 0x08) { - rt2400pci_bbp_write(rt2x00dev, 13, --reg); - rt2x00dev->link.vgc_level = reg; - } + if ((link->qual.false_cca > 512) && (link->vgc_level < 0x20)) + rt2400pci_set_vgc(rt2x00dev, ++link->vgc_level); + else if ((link->qual.false_cca < 100) && (link->vgc_level > 0x08)) + rt2400pci_set_vgc(rt2x00dev, --link->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index bf5e81162f25..5b98a74a2554 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -639,16 +639,23 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); } +static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + if (rt2x00dev->link.vgc_level_reg != vgc_level) { + rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); + rt2x00dev->link.vgc_level_reg = vgc_level; + } +} + static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt2500pci_bbp_write(rt2x00dev, 17, 0x48); - rt2x00dev->link.vgc_level = 0x48; + rt2500pci_set_vgc(rt2x00dev, 0x48); } static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) { - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u8 r17; + struct link *link = &rt2x00dev->link; + int rssi = rt2x00_get_link_rssi(link); /* * To prevent collisions with MAC ASIC on chipsets @@ -656,12 +663,9 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * seconds while being associated. */ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && - rt2x00dev->intf_associated && - rt2x00dev->link.count > 20) + rt2x00dev->intf_associated && link->count > 20) return; - rt2500pci_bbp_read(rt2x00dev, 17, &r17); - /* * Chipset versions C and lower should directly continue * to the dynamic CCA tuning. Chipset version D and higher @@ -677,11 +681,9 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * then corrupt the R17 tuning. To remidy this the tuning should * be stopped (While making sure the R17 value will not exceed limits) */ - if (rssi < -80 && rt2x00dev->link.count > 20) { - if (r17 >= 0x41) { - r17 = rt2x00dev->link.vgc_level; - rt2500pci_bbp_write(rt2x00dev, 17, r17); - } + if (rssi < -80 && link->count > 20) { + if (link->vgc_level_reg >= 0x41) + rt2500pci_set_vgc(rt2x00dev, link->vgc_level); return; } @@ -689,8 +691,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for short distance */ if (rssi >= -58) { - if (r17 != 0x50) - rt2500pci_bbp_write(rt2x00dev, 17, 0x50); + rt2500pci_set_vgc(rt2x00dev, 0x50); return; } @@ -698,8 +699,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special mid-R17 for middle distance */ if (rssi >= -74) { - if (r17 != 0x41) - rt2500pci_bbp_write(rt2x00dev, 17, 0x41); + rt2500pci_set_vgc(rt2x00dev, 0x41); return; } @@ -707,8 +707,8 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - if (r17 >= 0x41) { - rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->link.vgc_level); + if (link->vgc_level_reg >= 0x41) { + rt2500pci_set_vgc(rt2x00dev, link->vgc_level); return; } @@ -718,12 +718,12 @@ dynamic_cca_tune: * R17 is inside the dynamic tuning range, * start tuning the link based on the false cca counter. */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < 0x40) { - rt2500pci_bbp_write(rt2x00dev, 17, ++r17); - rt2x00dev->link.vgc_level = r17; - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > 0x32) { - rt2500pci_bbp_write(rt2x00dev, 17, --r17); - rt2x00dev->link.vgc_level = r17; + if (link->qual.false_cca > 512 && link->vgc_level_reg < 0x40) { + rt2500pci_set_vgc(rt2x00dev, ++link->vgc_level_reg); + link->vgc_level = link->vgc_level_reg; + } else if (link->qual.false_cca < 100 && link->vgc_level_reg > 0x32) { + rt2500pci_set_vgc(rt2x00dev, --link->vgc_level_reg); + link->vgc_level = link->vgc_level_reg; } } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 19c068727a85..8935f2c005ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -286,9 +286,14 @@ struct link { struct link_ant ant; /* - * Active VGC level + * Active VGC level (for false cca tuning) */ - int vgc_level; + u8 vgc_level; + + /* + * VGC level as configured in register + */ + u8 vgc_level_reg; /* * Work structure for scheduling periodic link tuning. diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c7ab744f0052..94523f7f0d88 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1046,21 +1046,27 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } +static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + if (rt2x00dev->link.vgc_level != vgc_level) { + rt61pci_bbp_write(rt2x00dev, 17, vgc_level); + rt2x00dev->link.vgc_level = vgc_level; + rt2x00dev->link.vgc_level_reg = vgc_level; + } +} + static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt61pci_bbp_write(rt2x00dev, 17, 0x20); - rt2x00dev->link.vgc_level = 0x20; + rt61pci_set_vgc(rt2x00dev, 0x20); } static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) { - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u8 r17; + struct link *link = &rt2x00dev->link; + int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; - rt61pci_bbp_read(rt2x00dev, 17, &r17); - /* * Determine r17 bounds. */ @@ -1091,8 +1097,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for very short distance */ if (rssi >= -35) { - if (r17 != 0x60) - rt61pci_bbp_write(rt2x00dev, 17, 0x60); + rt61pci_set_vgc(rt2x00dev, 0x60); return; } @@ -1100,8 +1105,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for short distance */ if (rssi >= -58) { - if (r17 != up_bound) - rt61pci_bbp_write(rt2x00dev, 17, up_bound); + rt61pci_set_vgc(rt2x00dev, up_bound); return; } @@ -1109,9 +1113,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for middle-short distance */ if (rssi >= -66) { - low_bound += 0x10; - if (r17 != low_bound) - rt61pci_bbp_write(rt2x00dev, 17, low_bound); + rt61pci_set_vgc(rt2x00dev, low_bound + 0x10); return; } @@ -1119,9 +1121,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special mid-R17 for middle distance */ if (rssi >= -74) { - low_bound += 0x08; - if (r17 != low_bound) - rt61pci_bbp_write(rt2x00dev, 17, low_bound); + rt61pci_set_vgc(rt2x00dev, low_bound + 0x08); return; } @@ -1133,8 +1133,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) if (low_bound > up_bound) up_bound = low_bound; - if (r17 > up_bound) { - rt61pci_bbp_write(rt2x00dev, 17, up_bound); + if (link->vgc_level > up_bound) { + rt61pci_set_vgc(rt2x00dev, up_bound); return; } @@ -1144,15 +1144,10 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { - if (++r17 > up_bound) - r17 = up_bound; - rt61pci_bbp_write(rt2x00dev, 17, r17); - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { - if (--r17 < low_bound) - r17 = low_bound; - rt61pci_bbp_write(rt2x00dev, 17, r17); - } + if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) + rt61pci_set_vgc(rt2x00dev, ++link->vgc_level); + else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) + rt61pci_set_vgc(rt2x00dev, --link->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ae3b31d0d511..b5443148d621 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -924,21 +924,27 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } +static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +{ + if (rt2x00dev->link.vgc_level != vgc_level) { + rt73usb_bbp_write(rt2x00dev, 17, vgc_level); + rt2x00dev->link.vgc_level = vgc_level; + rt2x00dev->link.vgc_level_reg = vgc_level; + } +} + static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev) { - rt73usb_bbp_write(rt2x00dev, 17, 0x20); - rt2x00dev->link.vgc_level = 0x20; + rt73usb_set_vgc(rt2x00dev, 0x20); } static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) { - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u8 r17; + struct link *link = &rt2x00dev->link; + int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; - rt73usb_bbp_read(rt2x00dev, 17, &r17); - /* * Determine r17 bounds. */ @@ -979,8 +985,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for very short distance */ if (rssi > -35) { - if (r17 != 0x60) - rt73usb_bbp_write(rt2x00dev, 17, 0x60); + rt73usb_set_vgc(rt2x00dev, 0x60); return; } @@ -988,8 +993,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for short distance */ if (rssi >= -58) { - if (r17 != up_bound) - rt73usb_bbp_write(rt2x00dev, 17, up_bound); + rt73usb_set_vgc(rt2x00dev, up_bound); return; } @@ -997,9 +1001,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special big-R17 for middle-short distance */ if (rssi >= -66) { - low_bound += 0x10; - if (r17 != low_bound) - rt73usb_bbp_write(rt2x00dev, 17, low_bound); + rt73usb_set_vgc(rt2x00dev, low_bound + 0x10); return; } @@ -1007,8 +1009,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special mid-R17 for middle distance */ if (rssi >= -74) { - if (r17 != (low_bound + 0x10)) - rt73usb_bbp_write(rt2x00dev, 17, low_bound + 0x08); + rt73usb_set_vgc(rt2x00dev, low_bound + 0x08); return; } @@ -1020,8 +1021,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) if (low_bound > up_bound) up_bound = low_bound; - if (r17 > up_bound) { - rt73usb_bbp_write(rt2x00dev, 17, up_bound); + if (link->vgc_level > up_bound) { + rt73usb_set_vgc(rt2x00dev, up_bound); return; } @@ -1031,17 +1032,12 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { - r17 += 4; - if (r17 > up_bound) - r17 = up_bound; - rt73usb_bbp_write(rt2x00dev, 17, r17); - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { - r17 -= 4; - if (r17 < low_bound) - r17 = low_bound; - rt73usb_bbp_write(rt2x00dev, 17, r17); - } + if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) + rt73usb_set_vgc(rt2x00dev, + min_t(u8, link->vgc_level + 4, up_bound)); + else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) + rt73usb_set_vgc(rt2x00dev, + max_t(u8, link->vgc_level - 4, low_bound)); } /* -- cgit v1.2.3 From 5352ff6510422d9a9bf13b7272f865eb53247f4d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:54:54 +0100 Subject: rt2x00: Restrict interface between rt2x00link and drivers Restrict drivers to only access link_qual structure during link tuning. The contents of these fields are for the drivers and all fields are allowed to be changed to values the driver considers correct. This means that some fields need to be moved outside of this structure to restrict access only to rt2x00link itself. This allows some code to be moved outside of the rt2x00.h header and into rt2x00link.c. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 27 +++--- drivers/net/wireless/rt2x00/rt2500pci.c | 50 +++++------ drivers/net/wireless/rt2x00/rt2500usb.c | 5 +- drivers/net/wireless/rt2x00/rt2x00.h | 99 ++++++++------------- drivers/net/wireless/rt2x00/rt2x00link.c | 145 ++++++++++++++++++++++--------- drivers/net/wireless/rt2x00/rt61pci.c | 49 ++++++----- drivers/net/wireless/rt2x00/rt73usb.c | 57 ++++++------ 7 files changed, 233 insertions(+), 199 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e87ad43e8e8d..9104113270d0 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -600,36 +600,37 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = bbp; } -static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); - rt2x00dev->link.vgc_level = vgc_level; - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; } -static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt2400pci_set_vgc(rt2x00dev, 0x08); + rt2400pci_set_vgc(rt2x00dev, qual, 0x08); } -static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - /* * The link tuner should not run longer then 60 seconds, * and should run once every 2 seconds. */ - if (link->count > 60 || !(link->count & 1)) + if (count > 60 || !(count & 1)) return; /* * Base r13 link tuning on the false cca count. */ - if ((link->qual.false_cca > 512) && (link->vgc_level < 0x20)) - rt2400pci_set_vgc(rt2x00dev, ++link->vgc_level); - else if ((link->qual.false_cca < 100) && (link->vgc_level > 0x08)) - rt2400pci_set_vgc(rt2x00dev, --link->vgc_level); + if ((qual->false_cca > 512) && (qual->vgc_level < 0x20)) + rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level); + else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08)) + rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 5b98a74a2554..fb86e2c55248 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -639,31 +639,31 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); } -static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { - if (rt2x00dev->link.vgc_level_reg != vgc_level) { + if (qual->vgc_level_reg != vgc_level) { rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level_reg = vgc_level; } } -static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt2500pci_set_vgc(rt2x00dev, 0x48); + rt2500pci_set_vgc(rt2x00dev, qual, 0x48); } -static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - int rssi = rt2x00_get_link_rssi(link); - /* * To prevent collisions with MAC ASIC on chipsets * up to version C the link tuning should halt after 20 * seconds while being associated. */ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && - rt2x00dev->intf_associated && link->count > 20) + rt2x00dev->intf_associated && count > 20) return; /* @@ -681,25 +681,25 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * then corrupt the R17 tuning. To remidy this the tuning should * be stopped (While making sure the R17 value will not exceed limits) */ - if (rssi < -80 && link->count > 20) { - if (link->vgc_level_reg >= 0x41) - rt2500pci_set_vgc(rt2x00dev, link->vgc_level); + if (qual->rssi < -80 && count > 20) { + if (qual->vgc_level_reg >= 0x41) + rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); return; } /* * Special big-R17 for short distance */ - if (rssi >= -58) { - rt2500pci_set_vgc(rt2x00dev, 0x50); + if (qual->rssi >= -58) { + rt2500pci_set_vgc(rt2x00dev, qual, 0x50); return; } /* * Special mid-R17 for middle distance */ - if (rssi >= -74) { - rt2500pci_set_vgc(rt2x00dev, 0x41); + if (qual->rssi >= -74) { + rt2500pci_set_vgc(rt2x00dev, qual, 0x41); return; } @@ -707,8 +707,8 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - if (link->vgc_level_reg >= 0x41) { - rt2500pci_set_vgc(rt2x00dev, link->vgc_level); + if (qual->vgc_level_reg >= 0x41) { + rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); return; } @@ -718,12 +718,12 @@ dynamic_cca_tune: * R17 is inside the dynamic tuning range, * start tuning the link based on the false cca counter. */ - if (link->qual.false_cca > 512 && link->vgc_level_reg < 0x40) { - rt2500pci_set_vgc(rt2x00dev, ++link->vgc_level_reg); - link->vgc_level = link->vgc_level_reg; - } else if (link->qual.false_cca < 100 && link->vgc_level_reg > 0x32) { - rt2500pci_set_vgc(rt2x00dev, --link->vgc_level_reg); - link->vgc_level = link->vgc_level_reg; + if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) { + rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg); + qual->vgc_level = qual->vgc_level_reg; + } else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) { + rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg); + qual->vgc_level = qual->vgc_level_reg; } } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 23cf585f03a4..557fcf2b30e4 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -698,7 +698,8 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); } -static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { u16 eeprom; u16 value; @@ -719,7 +720,7 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER); rt2500usb_bbp_write(rt2x00dev, 17, value); - rt2x00dev->link.vgc_level = value; + qual->vgc_level = value; } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8935f2c005ce..dea502234cf8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -177,52 +177,41 @@ struct antenna_setup { */ struct link_qual { /* - * Statistics required for Link tuning. - * For the average RSSI value we use the "Walking average" approach. - * When adding RSSI to the average value the following calculation - * is needed: - * - * avg_rssi = ((avg_rssi * 7) + rssi) / 8; + * Statistics required for Link tuning by driver + * The rssi value is provided by rt2x00lib during the + * link_tuner() callback function. + * The false_cca field is filled during the link_stats() + * callback function and could be used during the + * link_tuner() callback function. + */ + int rssi; + int false_cca; + + /* + * VGC levels + * Hardware driver will tune the VGC level during each call + * to the link_tuner() callback function. This vgc_level is + * is determined based on the link quality statistics like + * average RSSI and the false CCA count. * - * The advantage of this approach is that we only need 1 variable - * to store the average in (No need for a count and a total). - * But more importantly, normal average values will over time - * move less and less towards newly added values this results - * that with link tuning, the device can have a very good RSSI - * for a few minutes but when the device is moved away from the AP - * the average will not decrease fast enough to compensate. - * The walking average compensates this and will move towards - * the new values correctly allowing a effective link tuning. + * In some cases the drivers need to differentiate between + * the currently "desired" VGC level and the level configured + * in the hardware. The latter is important to reduce the + * number of BBP register reads to reduce register access + * overhead. For this reason we store both values here. */ - int avg_rssi; - int false_cca; + u8 vgc_level; + u8 vgc_level_reg; /* * Statistics required for Signal quality calculation. - * For calculating the Signal quality we have to determine - * the total number of success and failed RX and TX frames. - * After that we also use the average RSSI value to help - * determining the signal quality. - * For the calculation we will use the following algorithm: - * - * rssi_percentage = (avg_rssi * 100) / rssi_offset - * rx_percentage = (rx_success * 100) / rx_total - * tx_percentage = (tx_success * 100) / tx_total - * avg_signal = ((WEIGHT_RSSI * avg_rssi) + - * (WEIGHT_TX * tx_percentage) + - * (WEIGHT_RX * rx_percentage)) / 100 - * - * This value should then be checked to not be greater then 100. + * These fields might be changed during the link_stats() + * callback function. */ - int rx_percentage; int rx_success; int rx_failed; - int tx_percentage; int tx_success; int tx_failed; -#define WEIGHT_RSSI 20 -#define WEIGHT_RX 40 -#define WEIGHT_TX 40 }; /* @@ -286,14 +275,16 @@ struct link { struct link_ant ant; /* - * Active VGC level (for false cca tuning) + * Currently active average RSSI value */ - u8 vgc_level; + int avg_rssi; /* - * VGC level as configured in register + * Currently precalculated percentages of successful + * TX and RX frames. */ - u8 vgc_level_reg; + int rx_percentage; + int tx_percentage; /* * Work structure for scheduling periodic link tuning. @@ -301,28 +292,6 @@ struct link { struct delayed_work work; }; -/* - * Small helper macro to work with moving/walking averages. - */ -#define MOVING_AVERAGE(__avg, __val, __samples) \ - ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) ) - -/* - * When we lack RSSI information return something less then -80 to - * tell the driver to tune the device to maximum sensitivity. - */ -#define DEFAULT_RSSI ( -128 ) - -/* - * Link quality access functions. - */ -static inline int rt2x00_get_link_rssi(struct link *link) -{ - if (link->qual.avg_rssi && link->qual.rx_success) - return link->qual.avg_rssi; - return DEFAULT_RSSI; -} - /* * Interface structure * Per interface configuration details, this structure @@ -522,8 +491,10 @@ struct rt2x00lib_ops { int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev); void (*link_stats) (struct rt2x00_dev *rt2x00dev, struct link_qual *qual); - void (*reset_tuner) (struct rt2x00_dev *rt2x00dev); - void (*link_tuner) (struct rt2x00_dev *rt2x00dev); + void (*reset_tuner) (struct rt2x00_dev *rt2x00dev, + struct link_qual *qual); + void (*link_tuner) (struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count); /* * TX control handlers diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 0462d5ab6e97..ee08f1167f59 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -29,6 +29,71 @@ #include "rt2x00.h" #include "rt2x00lib.h" +/* + * When we lack RSSI information return something less then -80 to + * tell the driver to tune the device to maximum sensitivity. + */ +#define DEFAULT_RSSI -128 + +/* + * When no TX/RX percentage could be calculated due to lack of + * frames on the air, we fallback to a percentage of 50%. + * This will assure we will get at least get some decent value + * when the link tuner starts. + * The value will be dropped and overwritten with the correct (measured) + * value anyway during the first run of the link tuner. + */ +#define DEFAULT_PERCENTAGE 50 + +/* + * Small helper macro to work with moving/walking averages. + * When adding a value to the average value the following calculation + * is needed: + * + * avg_rssi = ((avg_rssi * 7) + rssi) / 8; + * + * The advantage of this approach is that we only need 1 variable + * to store the average in (No need for a count and a total). + * But more importantly, normal average values will over time + * move less and less towards newly added values this results + * that with link tuning, the device can have a very good RSSI + * for a few minutes but when the device is moved away from the AP + * the average will not decrease fast enough to compensate. + * The walking average compensates this and will move towards + * the new values correctly allowing a effective link tuning. + */ +#define MOVING_AVERAGE(__avg, __val, __samples) \ + ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) ) + +/* + * Small helper macro for percentage calculation + * This is a very simple macro with the only catch that it will + * produce a default value in case no total value was provided. + */ +#define PERCENTAGE(__value, __total) \ + ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) ) + +/* + * For calculating the Signal quality we have determined + * the total number of success and failed RX and TX frames. + * With the addition of the average RSSI value we can determine + * the link quality using the following algorithm: + * + * rssi_percentage = (avg_rssi * 100) / rssi_offset + * rx_percentage = (rx_success * 100) / rx_total + * tx_percentage = (tx_success * 100) / tx_total + * avg_signal = ((WEIGHT_RSSI * avg_rssi) + + * (WEIGHT_TX * tx_percentage) + + * (WEIGHT_RX * rx_percentage)) / 100 + * + * This value should then be checked to not be greater then 100. + * This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must + * sum up to 100 as well. + */ +#define WEIGHT_RSSI 20 +#define WEIGHT_RX 40 +#define WEIGHT_TX 40 + static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) { struct link_ant *ant = &rt2x00dev->link.ant; @@ -191,6 +256,7 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct rxdone_entry_desc *rxdesc) { + struct link *link = &rt2x00dev->link; struct link_qual *qual = &rt2x00dev->link.qual; struct link_ant *ant = &rt2x00dev->link.ant; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -215,9 +281,9 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, /* * Update global RSSI */ - if (qual->avg_rssi) - avg_rssi = MOVING_AVERAGE(qual->avg_rssi, rxdesc->rssi, 8); - qual->avg_rssi = avg_rssi; + if (link->avg_rssi) + avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8); + link->avg_rssi = avg_rssi; /* * Update antenna RSSI @@ -229,21 +295,13 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) { + struct link *link = &rt2x00dev->link; struct link_qual *qual = &rt2x00dev->link.qual; - if (qual->rx_failed || qual->rx_success) - qual->rx_percentage = - (qual->rx_success * 100) / - (qual->rx_failed + qual->rx_success); - else - qual->rx_percentage = 50; - - if (qual->tx_failed || qual->tx_success) - qual->tx_percentage = - (qual->tx_success * 100) / - (qual->tx_failed + qual->tx_success); - else - qual->tx_percentage = 50; + link->rx_percentage = + PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success); + link->tx_percentage = + PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success); qual->rx_success = 0; qual->rx_failed = 0; @@ -253,7 +311,7 @@ static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi) { - struct link_qual *qual = &rt2x00dev->link.qual; + struct link *link = &rt2x00dev->link; int rssi_percentage = 0; int signal; @@ -267,22 +325,22 @@ int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi) * Calculate the different percentages, * which will be used for the signal. */ - rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset; + rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset); /* * Add the individual percentages and use the WEIGHT * defines to calculate the current link signal. */ signal = ((WEIGHT_RSSI * rssi_percentage) + - (WEIGHT_TX * qual->tx_percentage) + - (WEIGHT_RX * qual->rx_percentage)) / 100; + (WEIGHT_TX * link->tx_percentage) + + (WEIGHT_RX * link->rx_percentage)) / 100; return max_t(int, signal, 100); } void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) { - struct link_qual *qual = &rt2x00dev->link.qual; + struct link *link = &rt2x00dev->link; /* * Link tuning should only be performed when @@ -293,26 +351,13 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count) return; - /* - * Clear all (possibly) pre-existing quality statistics. - */ - memset(qual, 0, sizeof(*qual)); - - /* - * The RX and TX percentage should start at 50% - * this will assure we will get at least get some - * decent value when the link tuner starts. - * The value will be dropped and overwritten with - * the correct (measured) value anyway during the - * first run of the link tuner. - */ - qual->rx_percentage = 50; - qual->tx_percentage = 50; + link->rx_percentage = DEFAULT_PERCENTAGE; + link->tx_percentage = DEFAULT_PERCENTAGE; rt2x00link_reset_tuner(rt2x00dev, false); queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) @@ -322,6 +367,8 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) { + struct link_qual *qual = &rt2x00dev->link.qual; + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return; @@ -334,12 +381,12 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) * first minute after being enabled. */ rt2x00dev->link.count = 0; - rt2x00dev->link.vgc_level = 0; + memset(qual, 0, sizeof(*qual)); /* * Reset the link tuner. */ - rt2x00dev->ops->lib->reset_tuner(rt2x00dev); + rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual); if (antenna) rt2x00link_antenna_reset(rt2x00dev); @@ -349,6 +396,7 @@ static void rt2x00link_tuner(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, link.work.work); + struct link *link = &rt2x00dev->link; struct link_qual *qual = &rt2x00dev->link.qual; /* @@ -364,12 +412,23 @@ static void rt2x00link_tuner(struct work_struct *work) rt2x00dev->ops->lib->link_stats(rt2x00dev, qual); rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed; + /* + * Update quality RSSI for link tuning, + * when we have received some frames and we managed to + * collect the RSSI data we could use this. Otherwise we + * must fallback to the default RSSI value. + */ + if (!link->avg_rssi || !qual->rx_success) + qual->rssi = DEFAULT_RSSI; + else + qual->rssi = link->avg_rssi; + /* * Only perform the link tuning when Link tuning * has been enabled (This could have been disabled from the EEPROM). */ if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) - rt2x00dev->ops->lib->link_tuner(rt2x00dev); + rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); /* * Precalculate a portion of the link signal which is @@ -380,7 +439,7 @@ static void rt2x00link_tuner(struct work_struct *work) /* * Send a signal to the led to update the led signal strength. */ - rt2x00leds_led_quality(rt2x00dev, qual->avg_rssi); + rt2x00leds_led_quality(rt2x00dev, link->avg_rssi); /* * Evaluate antenna setup, make this the last step since this could @@ -391,9 +450,9 @@ static void rt2x00link_tuner(struct work_struct *work) /* * Increase tuner counter, and reschedule the next link tuner run. */ - rt2x00dev->link.count++; + link->count++; queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_register(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 94523f7f0d88..ed829879c941 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1046,24 +1046,25 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } -static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { - if (rt2x00dev->link.vgc_level != vgc_level) { + if (qual->vgc_level != vgc_level) { rt61pci_bbp_write(rt2x00dev, 17, vgc_level); - rt2x00dev->link.vgc_level = vgc_level; - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; } } -static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt61pci_set_vgc(rt2x00dev, 0x20); + rt61pci_set_vgc(rt2x00dev, qual, 0x20); } -static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; @@ -1096,32 +1097,32 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Special big-R17 for very short distance */ - if (rssi >= -35) { - rt61pci_set_vgc(rt2x00dev, 0x60); + if (qual->rssi >= -35) { + rt61pci_set_vgc(rt2x00dev, qual, 0x60); return; } /* * Special big-R17 for short distance */ - if (rssi >= -58) { - rt61pci_set_vgc(rt2x00dev, up_bound); + if (qual->rssi >= -58) { + rt61pci_set_vgc(rt2x00dev, qual, up_bound); return; } /* * Special big-R17 for middle-short distance */ - if (rssi >= -66) { - rt61pci_set_vgc(rt2x00dev, low_bound + 0x10); + if (qual->rssi >= -66) { + rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x10); return; } /* * Special mid-R17 for middle distance */ - if (rssi >= -74) { - rt61pci_set_vgc(rt2x00dev, low_bound + 0x08); + if (qual->rssi >= -74) { + rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x08); return; } @@ -1129,12 +1130,12 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Special case: Change up_bound based on the rssi. * Lower up_bound when rssi is weaker then -74 dBm. */ - up_bound -= 2 * (-74 - rssi); + up_bound -= 2 * (-74 - qual->rssi); if (low_bound > up_bound) up_bound = low_bound; - if (link->vgc_level > up_bound) { - rt61pci_set_vgc(rt2x00dev, up_bound); + if (qual->vgc_level > up_bound) { + rt61pci_set_vgc(rt2x00dev, qual, up_bound); return; } @@ -1144,10 +1145,10 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) - rt61pci_set_vgc(rt2x00dev, ++link->vgc_level); - else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) - rt61pci_set_vgc(rt2x00dev, --link->vgc_level); + if ((qual->false_cca > 512) && (qual->vgc_level < up_bound)) + rt61pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level); + else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound)) + rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level); } /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b5443148d621..e99bcacfc191 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -924,24 +924,25 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); } -static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, u8 vgc_level) +static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) { - if (rt2x00dev->link.vgc_level != vgc_level) { + if (qual->vgc_level != vgc_level) { rt73usb_bbp_write(rt2x00dev, 17, vgc_level); - rt2x00dev->link.vgc_level = vgc_level; - rt2x00dev->link.vgc_level_reg = vgc_level; + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; } } -static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { - rt73usb_set_vgc(rt2x00dev, 0x20); + rt73usb_set_vgc(rt2x00dev, qual, 0x20); } -static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) +static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) { - struct link *link = &rt2x00dev->link; - int rssi = rt2x00_get_link_rssi(link); u8 up_bound; u8 low_bound; @@ -957,10 +958,10 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) up_bound += 0x10; } } else { - if (rssi > -82) { + if (qual->rssi > -82) { low_bound = 0x1c; up_bound = 0x40; - } else if (rssi > -84) { + } else if (qual->rssi > -84) { low_bound = 0x1c; up_bound = 0x20; } else { @@ -984,32 +985,32 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Special big-R17 for very short distance */ - if (rssi > -35) { - rt73usb_set_vgc(rt2x00dev, 0x60); + if (qual->rssi > -35) { + rt73usb_set_vgc(rt2x00dev, qual, 0x60); return; } /* * Special big-R17 for short distance */ - if (rssi >= -58) { - rt73usb_set_vgc(rt2x00dev, up_bound); + if (qual->rssi >= -58) { + rt73usb_set_vgc(rt2x00dev, qual, up_bound); return; } /* * Special big-R17 for middle-short distance */ - if (rssi >= -66) { - rt73usb_set_vgc(rt2x00dev, low_bound + 0x10); + if (qual->rssi >= -66) { + rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10); return; } /* * Special mid-R17 for middle distance */ - if (rssi >= -74) { - rt73usb_set_vgc(rt2x00dev, low_bound + 0x08); + if (qual->rssi >= -74) { + rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08); return; } @@ -1017,12 +1018,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Special case: Change up_bound based on the rssi. * Lower up_bound when rssi is weaker then -74 dBm. */ - up_bound -= 2 * (-74 - rssi); + up_bound -= 2 * (-74 - qual->rssi); if (low_bound > up_bound) up_bound = low_bound; - if (link->vgc_level > up_bound) { - rt73usb_set_vgc(rt2x00dev, up_bound); + if (qual->vgc_level > up_bound) { + rt73usb_set_vgc(rt2x00dev, qual, up_bound); return; } @@ -1032,12 +1033,12 @@ dynamic_cca_tune: * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - if ((link->qual.false_cca > 512) && (link->vgc_level < up_bound)) - rt73usb_set_vgc(rt2x00dev, - min_t(u8, link->vgc_level + 4, up_bound)); - else if ((link->qual.false_cca < 100) && (link->vgc_level > low_bound)) - rt73usb_set_vgc(rt2x00dev, - max_t(u8, link->vgc_level - 4, low_bound)); + if ((qual->false_cca > 512) && (qual->vgc_level < up_bound)) + rt73usb_set_vgc(rt2x00dev, qual, + min_t(u8, qual->vgc_level + 4, up_bound)); + else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound)) + rt73usb_set_vgc(rt2x00dev, qual, + max_t(u8, qual->vgc_level - 4, low_bound)); } /* -- cgit v1.2.3 From 3f787bd6d596ff56625f440910944ef6f937af8d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 10:56:36 +0100 Subject: rt2x00: Rename CONFIG_CRYPTO_COPY_IV CONFIG_CRYPTO_COPY_IV is a bad name since it is part of the driver requirements instead of a configuration option. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 01e5584d8f77..7b97160e2b5a 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1888,7 +1888,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); if (!modparam_nohwcrypt) { __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(CONFIG_CRYPTO_COPY_IV, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); } __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index dea502234cf8..1612a9cf4d7b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -586,6 +586,7 @@ enum rt2x00_flags { DRIVER_REQUIRE_ATIM_QUEUE, DRIVER_REQUIRE_SCHEDULED, DRIVER_REQUIRE_DMA, + DRIVER_REQUIRE_COPY_IV, /* * Driver features @@ -602,7 +603,6 @@ enum rt2x00_flags { CONFIG_EXTERNAL_LNA_BG, CONFIG_DOUBLE_ANTENNA, CONFIG_DISABLE_LINK_TUNING, - CONFIG_CRYPTO_COPY_IV, }; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 0709decec9c2..01125563aba3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -403,7 +403,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) */ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { - if (test_bit(CONFIG_CRYPTO_COPY_IV, &queue->rt2x00dev->flags)) + if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) rt2x00crypto_tx_copy_iv(skb, iv_len); else rt2x00crypto_tx_remove_iv(skb, iv_len); -- cgit v1.2.3 From 754be3098b22d1bea9620b40fe2f9f2286c55101 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 20 Dec 2008 11:00:49 +0100 Subject: rt2x00: Release rt2x00 2.3.0 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 1612a9cf4d7b..1ef3434a2bae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.2.3" +#define DRV_VERSION "2.3.0" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* -- cgit v1.2.3 From dc822b5db479dc0178d5c04cbb656dad0b6564fb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Dec 2008 12:55:09 +0100 Subject: mac80211: clean up set_key callback The set_key callback now seems rather odd, passing a MAC address instead of a station struct, and a local address instead of a vif struct. Change that. Signed-off-by: Johannes Berg Acked-by: Bob Copeland [ath5k] Acked-by: Ivo van Doorn [rt2x00] Acked-by: Christian Lamparter [p54] Tested-by: Kalle Valo [iwl3945] Tested-by: Samuel Ortiz [iwl3945] Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 9 ++--- drivers/net/wireless/ath5k/pcu.c | 2 +- drivers/net/wireless/ath9k/main.c | 18 ++++++---- drivers/net/wireless/b43/main.c | 13 +++++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 +++--- drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 ++++--- drivers/net/wireless/p54/p54common.c | 6 ++-- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 29 +++++++--------- include/net/mac80211.h | 20 +++++------ net/mac80211/key.c | 51 ++++++++++++++--------------- 11 files changed, 89 insertions(+), 83 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 8ef87356e083..88618645a7e4 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -232,7 +232,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, int mc_count, struct dev_mc_list *mclist); static int ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); static int ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); @@ -2991,8 +2991,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, static int ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct ath5k_softc *sc = hw->priv; int ret = 0; @@ -3015,7 +3015,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: - ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr); + ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, + sta ? sta->addr : NULL); if (ret) { ATH5K_ERR(sc, "can't set the key\n"); goto unlock; diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 75eb9f43c741..5b416ed65299 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -1139,7 +1139,7 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) /* MAC may be NULL if it's a broadcast key. In this case no need to * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ - if (unlikely(mac == NULL)) { + if (!mac) { low_id = 0xffffffff; high_id = 0xffff | AR5K_KEYTABLE_VALID; } else { diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 5cbda9245560..a4046a97c016 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -794,7 +794,7 @@ static int ath_reserve_key_cache_slot(struct ath_softc *sc) } static int ath_key_config(struct ath_softc *sc, - const u8 *addr, + struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct ath9k_keyval hk; @@ -828,7 +828,10 @@ static int ath_key_config(struct ath_softc *sc, } else if (key->keyidx) { struct ieee80211_vif *vif; - mac = addr; + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + vif = sc->sc_vaps[0]; if (vif->type != NL80211_IFTYPE_AP) { /* Only keyidx 0 should be used with unicast key, but @@ -837,7 +840,10 @@ static int ath_key_config(struct ath_softc *sc, } else return -EIO; } else { - mac = addr; + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + if (key->alg == ALG_TKIP) idx = ath_reserve_key_cache_slot_tkip(sc); else @@ -2320,8 +2326,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, static int ath9k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, - const u8 *addr, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct ath_softc *sc = hw->priv; @@ -2331,7 +2337,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, switch (cmd) { case SET_KEY: - ret = ath_key_config(sc, addr, key); + ret = ath_key_config(sc, sta, key); if (ret >= 0) { key->hw_key_idx = ret; /* push IV and Michael MIC generation to stack */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5ca55dcd0345..19ad5164fce7 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3476,8 +3476,8 @@ out_unlock_mutex: } static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -3542,9 +3542,14 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + if (WARN_ON(!sta)) { + err = -EOPNOTSUPP; + goto out_unlock; + } /* Pairwise key with an assigned MAC address. */ err = b43_key_write(dev, -1, algorithm, - key->key, key->keylen, addr, key); + key->key, key->keylen, + sta->addr, key); } else { /* Group key */ err = b43_key_write(dev, index, algorithm, @@ -3577,7 +3582,7 @@ out_unlock: b43dbg(wl, "%s hardware based encryption for keyidx: %d, " "mac: %pM\n", cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, - addr); + sta ? sta->addr : ""); b43_dump_keymemory(dev); } write_unlock(&wl->tx_lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f3f6dba7a673..dbfee28107a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3021,13 +3021,17 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, } static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; int ret = 0; u8 sta_id = IWL_INVALID_STATION; u8 is_default_wep_key = 0; + static const u8 bcast_addr[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; + static const u8 *addr; IWL_DEBUG_MAC80211("enter\n"); @@ -3036,9 +3040,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - if (is_zero_ether_addr(addr)) - /* only support pairwise keys */ - return -EOPNOTSUPP; + addr = sta ? sta->addr : bcast_addr; sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a176f42fd7cf..43cfc6ec5163 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6546,12 +6546,16 @@ out_unlock: } static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_addr, const u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; + const u8 *addr; int rc = 0; u8 sta_id; + static const u8 bcast_addr[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; IWL_DEBUG_MAC80211("enter\n"); @@ -6560,9 +6564,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - if (is_zero_ether_addr(addr)) - /* only support pairwise keys */ - return -EOPNOTSUPP; + addr = sta ? sta->addr : bcast_addr; sta_id = iwl3945_hw_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 8d2df5b6ecbf..0907e6f246e6 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2127,7 +2127,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, } static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct p54_common *priv = dev->priv; @@ -2191,8 +2191,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, rxkey->entry = key->keyidx; rxkey->key_id = key->keyidx; rxkey->key_type = algo; - if (address) - memcpy(rxkey->mac, address, ETH_ALEN); + if (sta) + memcpy(rxkey->mac, sta->addr, ETH_ALEN); else memset(rxkey->mac, ~0, ETH_ALEN); if (key->alg != ALG_TKIP) { diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 1ef3434a2bae..890c7216cf38 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -931,7 +931,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mc_list); #ifdef CONFIG_RT2X00_LIB_CRYPTO int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); #else #define rt2x00mac_set_key NULL diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index bf7755a21645..3e204406f44f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -502,15 +502,17 @@ static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) } int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_sta *sta; + struct rt2x00_intf *intf = vif_to_intf(vif); int (*set_key) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key); struct rt2x00lib_crypto crypto; + static const u8 bcast_addr[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; @@ -528,32 +530,25 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (rt2x00dev->intf_sta_count) crypto.bssidx = 0; else - crypto.bssidx = - local_address[5] & (rt2x00dev->ops->max_ap_intf - 1); + crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1); crypto.cipher = rt2x00crypto_key_to_cipher(key); if (crypto.cipher == CIPHER_NONE) return -EOPNOTSUPP; crypto.cmd = cmd; - crypto.address = address; + + if (sta) { + /* some drivers need the AID */ + crypto.aid = sta->aid; + crypto.address = sta->addr; + } else + crypto.address = bcast_addr; if (crypto.cipher == CIPHER_TKIP) memcpy_tkip(&crypto, &key->key[0], key->keylen); else memcpy(&crypto.key, &key->key[0], key->keylen); - - /* - * Discover the Association ID from mac80211. - * Some drivers need this information when updating the - * hardware key (either adding or removing). - */ - rcu_read_lock(); - sta = ieee80211_find_sta(hw, address); - if (sta) - crypto.aid = sta->aid; - rcu_read_unlock(); - /* * Each BSS has a maximum of 4 shared keys. * Shared key index values: diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ffcbd12775a4..9215b1ec90ec 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -715,8 +715,8 @@ enum ieee80211_key_flags { * - Temporal Encryption Key (128 bits) * - Temporal Authenticator Tx MIC Key (64 bits) * - Temporal Authenticator Rx MIC Key (64 bits) - * @icv_len: FIXME - * @iv_len: FIXME + * @icv_len: The ICV length for this key type + * @iv_len: The IV length for this key type */ struct ieee80211_key_conf { enum ieee80211_key_alg alg; @@ -1019,16 +1019,12 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * * The set_key() callback in the &struct ieee80211_ops for a given * device is called to enable hardware acceleration of encryption and - * decryption. The callback takes an @address parameter that will be - * the broadcast address for default keys, the other station's hardware - * address for individual keys or the zero address for keys that will - * be used only for transmission. + * decryption. The callback takes a @sta parameter that will be NULL + * for default keys or keys used for transmission only, or point to + * the station information for the peer for individual keys. * Multiple transmission keys with the same key index may be used when * VLANs are configured for an access point. * - * The @local_address parameter will always be set to our own address, - * this is only relevant if you support multiple local addresses. - * * When transmitting, the TX control data will use the @hw_key_idx * selected by the driver by modifying the &struct ieee80211_key_conf * pointed to by the @key parameter to the set_key() function. @@ -1233,8 +1229,8 @@ enum ieee80211_ampdu_mlme_action { * * @set_key: See the section "Hardware crypto acceleration" * This callback can sleep, and is only called between add_interface - * and remove_interface calls, i.e. while the interface with the - * given local_address is enabled. + * and remove_interface calls, i.e. while the given virtual interface + * is enabled. * * @update_tkip_key: See the section "Hardware crypto acceleration" * This callback will be called in the context of Rx. Called for drivers @@ -1311,7 +1307,7 @@ struct ieee80211_ops { int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set); int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, - const u8 *local_address, const u8 *address, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); void (*update_tkip_key)(struct ieee80211_hw *hw, struct ieee80211_key_conf *conf, const u8 *address, diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 999f7aa42326..b0a025c9b615 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -47,7 +47,6 @@ */ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -static const u8 zero_addr[ETH_ALEN]; /* key mutex: used to synchronise todo runners */ static DEFINE_MUTEX(key_mutex); @@ -108,29 +107,18 @@ static void assert_key_lock(void) WARN_ON(!mutex_is_locked(&key_mutex)); } -static const u8 *get_mac_for_key(struct ieee80211_key *key) +static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) { - const u8 *addr = bcast_addr; - - /* - * If we're an AP we won't ever receive frames with a non-WEP - * group key so we tell the driver that by using the zero MAC - * address to indicate a transmit-only key. - */ - if (key->conf.alg != ALG_WEP && - (key->sdata->vif.type == NL80211_IFTYPE_AP || - key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) - addr = zero_addr; - if (key->sta) - addr = key->sta->sta.addr; + return &key->sta->sta; - return addr; + return NULL; } static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) { - const u8 *addr; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_sta *sta; int ret; assert_key_lock(); @@ -139,11 +127,16 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (!key->local->ops->set_key) return; - addr = get_mac_for_key(key); + sta = get_sta_for_key(key); + + sdata = key->sdata; + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, - key->sdata->dev->dev_addr, addr, - &key->conf); + &sdata->vif, sta, &key->conf); if (!ret) { spin_lock(&todo_lock); @@ -155,12 +148,13 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) printk(KERN_ERR "mac80211-%s: failed to set key " "(%d, %pM) to hardware (%d)\n", wiphy_name(key->local->hw.wiphy), - key->conf.keyidx, addr, ret); + key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); } static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) { - const u8 *addr; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_sta *sta; int ret; assert_key_lock(); @@ -176,17 +170,22 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) } spin_unlock(&todo_lock); - addr = get_mac_for_key(key); + sta = get_sta_for_key(key); + sdata = key->sdata; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, - key->sdata->dev->dev_addr, addr, - &key->conf); + &sdata->vif, sta, &key->conf); if (ret) printk(KERN_ERR "mac80211-%s: failed to remove key " "(%d, %pM) from hardware (%d)\n", wiphy_name(key->local->hw.wiphy), - key->conf.keyidx, addr, ret); + key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); spin_lock(&todo_lock); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; -- cgit v1.2.3 From cca3e99861e883358ceb39ad17c9eaee082138a5 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 3 Jan 2009 19:56:02 +0100 Subject: rt2x00: Replace RFKILL with INPUT As discussed on linux-wireless rt2x00 does not offer a true RFKILL key, for that reason RFKILL support should be entirely removed. The key which is attached to the hardware should be treated as normal input device instead. Implement input_poll_dev support to poll the device frequently. When the key status has changed report it as a SW event. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 7 +- drivers/net/wireless/rt2x00/rt2x00.h | 5 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 122 +++++++++-------------------- 4 files changed, 46 insertions(+), 90 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 178b313293b4..bfc5d9cf716e 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -97,10 +97,11 @@ config RT2X00_LIB_CRYPTO config RT2X00_LIB_RFKILL boolean - default y if (RT2X00_LIB=y && RFKILL=y) || (RT2X00_LIB=m && RFKILL!=n) + default y if (RT2X00_LIB=y && INPUT=y) || (RT2X00_LIB=m && INPUT!=n) + select INPUT_POLLDEV -comment "rt2x00 rfkill support disabled due to modularized RFKILL and built-in rt2x00" - depends on RT2X00_LIB=y && RFKILL=m +comment "rt2x00 rfkill support disabled due to modularized INPUT and built-in rt2x00" + depends on RT2X00_LIB=y && INPUT=m config RT2X00_LIB_LEDS boolean diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 890c7216cf38..27c0f335f403 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -638,8 +639,8 @@ struct rt2x00_dev { unsigned long rfkill_state; #define RFKILL_STATE_ALLOCATED 1 #define RFKILL_STATE_REGISTERED 2 - struct rfkill *rfkill; - struct delayed_work rfkill_work; +#define RFKILL_STATE_BLOCKED 3 + struct input_polled_dev *rfkill_poll_dev; #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5e8df250e50d..92918f315ee5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -33,7 +33,7 @@ * Both the link tuner as the rfkill will be called once per second. */ #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) -#define RFKILL_POLL_INTERVAL ( round_jiffies_relative(HZ) ) +#define RFKILL_POLL_INTERVAL ( 1000 ) /* * rt2x00_rate: Per rate device information diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 3298cae1e12d..595efd05ce44 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -25,73 +25,30 @@ #include #include -#include #include "rt2x00.h" #include "rt2x00lib.h" -static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) +static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) { - struct rt2x00_dev *rt2x00dev = data; - int retval = 0; - - if (unlikely(!rt2x00dev)) - return 0; - - /* - * Only continue if there are enabled interfaces. - */ - if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - return 0; - - if (state == RFKILL_STATE_UNBLOCKED) { - INFO(rt2x00dev, "RFKILL event: enabling radio.\n"); - clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); - retval = rt2x00lib_enable_radio(rt2x00dev); - } else if (state == RFKILL_STATE_SOFT_BLOCKED) { - INFO(rt2x00dev, "RFKILL event: disabling radio.\n"); - set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); - rt2x00lib_disable_radio(rt2x00dev); - } else { - WARNING(rt2x00dev, "RFKILL event: unknown state %d.\n", state); - } - - return retval; -} - -static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) -{ - struct rt2x00_dev *rt2x00dev = data; - - /* - * rfkill_poll reports 1 when the key has been pressed and the - * radio should be blocked. - */ - *state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; - - return 0; -} - -static void rt2x00rfkill_poll(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, rfkill_work.work); - enum rfkill_state state; + struct rt2x00_dev *rt2x00dev = poll_dev->private; + int state, old_state; if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) || !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) return; /* - * Poll latest state and report it to rfkill who should sort - * out if the state should be toggled or not. + * Poll latest state, if the state is different then the previous state, + * we should generate an input event. */ - if (!rt2x00rfkill_get_state(rt2x00dev, &state)) - rfkill_force_state(rt2x00dev->rfkill, state); + state = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); + old_state = !!test_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); - queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); + if (old_state != state) { + input_report_switch(poll_dev->input, SW_RFKILL_ALL, state); + change_bit(RFKILL_STATE_BLOCKED, &rt2x00dev->rfkill_state); + } } void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) @@ -100,8 +57,8 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - if (rfkill_register(rt2x00dev->rfkill)) { - ERROR(rt2x00dev, "Failed to register rfkill handler.\n"); + if (input_register_polled_device(rt2x00dev->rfkill_poll_dev)) { + ERROR(rt2x00dev, "Failed to register polled device.\n"); return; } @@ -109,10 +66,10 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) /* * Force initial poll which will detect the initial device state, - * and correctly sends the signal to the rfkill layer about this + * and correctly sends the signal to the input layer about this * state. */ - rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work); + rt2x00rfkill_poll(rt2x00dev->rfkill_poll_dev); } void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) @@ -121,52 +78,49 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - cancel_delayed_work_sync(&rt2x00dev->rfkill_work); - - rfkill_unregister(rt2x00dev->rfkill); + input_unregister_polled_device(rt2x00dev->rfkill_poll_dev); __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); } void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) { - struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy); + struct input_polled_dev *poll_dev; if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) return; - rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN); - if (!rt2x00dev->rfkill) { - ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); + poll_dev = input_allocate_polled_device(); + if (!poll_dev) { + ERROR(rt2x00dev, "Failed to allocate polled device.\n"); return; } - __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); + poll_dev->private = rt2x00dev; + poll_dev->poll = rt2x00rfkill_poll; + poll_dev->poll_interval = RFKILL_POLL_INTERVAL; - rt2x00dev->rfkill->name = rt2x00dev->ops->name; - rt2x00dev->rfkill->data = rt2x00dev; - rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; - if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) { - rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; - rt2x00dev->rfkill->state = - rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; - } else { - rt2x00dev->rfkill->state = RFKILL_STATE_UNBLOCKED; - } + poll_dev->input->name = rt2x00dev->ops->name; + poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); + poll_dev->input->id.bustype = BUS_HOST; + poll_dev->input->id.vendor = 0x1814; + poll_dev->input->id.product = rt2x00dev->chip.rt; + poll_dev->input->id.version = rt2x00dev->chip.rev; + poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy); + poll_dev->input->evbit[0] = BIT(EV_SW); + poll_dev->input->swbit[0] = BIT(SW_RFKILL_ALL); - INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); + rt2x00dev->rfkill_poll_dev = poll_dev; - return; + __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); } void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) { - if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) + if (!__test_and_clear_bit(RFKILL_STATE_ALLOCATED, + &rt2x00dev->rfkill_state)) return; - cancel_delayed_work_sync(&rt2x00dev->rfkill_work); - - rfkill_free(rt2x00dev->rfkill); - rt2x00dev->rfkill = NULL; + input_free_polled_device(rt2x00dev->rfkill_poll_dev); + rt2x00dev->rfkill_poll_dev = NULL; } -- cgit v1.2.3 From 4e54c711b42c3cc8da8a3fdcde3407b86d67ebcc Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 17 Jan 2009 20:42:32 +0100 Subject: rt2x00: Update copyright year to 2009 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2400pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- drivers/net/wireless/rt2x00/rt2x00crypto.c | 2 +- drivers/net/wireless/rt2x00/rt2x00debug.c | 2 +- drivers/net/wireless/rt2x00/rt2x00debug.h | 2 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt2x00dump.h | 2 +- drivers/net/wireless/rt2x00/rt2x00firmware.c | 2 +- drivers/net/wireless/rt2x00/rt2x00leds.c | 2 +- drivers/net/wireless/rt2x00/rt2x00leds.h | 2 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- drivers/net/wireless/rt2x00/rt2x00link.c | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.h | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.h | 2 +- drivers/net/wireless/rt2x00/rt2x00reg.h | 2 +- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.h | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.h | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 76c6cb518f24..b0867a712858 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index 9aefda4ab3c2..72ac31c3cb75 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c1203e37a6fd..d2b36b1e9290 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index e135247f7f89..17a0c9c8c184 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 67dd84ce58b0..71de7868bb80 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index e1f714e82af0..afce0e0322c3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 27c0f335f403..cc56637e73b5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index ab139f2698b8..6b3bb0f661d5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index e9d3ddae2785..0b41845d9543 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index cc1940605349..dcdce7f746b5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h index a92104dfee9a..035cbc98c593 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.h +++ b/drivers/net/wireless/rt2x00/rt2x00debug.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 12331b15fe79..cd4447502d8b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 7169c222a486..fdedb5122928 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index bab05a56e7a0..2a7e8bc0016b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index a0cd35b6beb5..9b531e0ca0cd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h index 9df4a49bdcad..1046977e6a12 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.h +++ b/drivers/net/wireless/rt2x00/rt2x00leds.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 92918f315ee5..daf0def915dd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index ee08f1167f59..9223a6d1f1d0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3e204406f44f..71de8a7144f9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index d52b22b82d1f..e616c20d4a78 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 9c0a4d77bc1b..15a12487e04b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 67140e75608d..c86fb6471754 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 98209d2e93af..97e2ab08f080 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 93f8427055cf..9ddc2d07eef8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 53f64b76a8c1..b6d4c6700bf3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 0b29d767a258..c89d1520838c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 2bd4ac855f52..fe4523887bdf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 549480a963e9..8a8753e29308 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index cd86def8de53..2f97fee7a8de 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 849220236c7d..961f9f9352d8 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 204bbd5b7c59..834b28ce6cde 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify -- cgit v1.2.3 From 881d948c23442173a011f1adcfe4c95bf7f27515 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 21 Jan 2009 15:13:48 +0100 Subject: wireless: restrict to 32 legacy rates Since the standards only define 12 legacy rates, 32 is certainly a sane upper limit and we don't need to use u64 everywhere. Add sanity checking that no more than 32 rates are registered and change the variables to u32 throughout. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 +- drivers/net/wireless/b43legacy/main.c | 2 +- drivers/net/wireless/p54/p54.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- include/net/mac80211.h | 4 ++-- include/net/wireless.h | 2 +- net/mac80211/ieee80211_i.h | 6 +++--- net/mac80211/mesh.c | 2 +- net/mac80211/mesh.h | 2 +- net/mac80211/mesh_plink.c | 6 +++--- net/mac80211/mlme.c | 16 ++++++++-------- net/mac80211/util.c | 4 ++-- net/wireless/core.c | 12 +++++++++--- net/wireless/util.c | 2 +- 14 files changed, 35 insertions(+), 29 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8bb6659c0b3f..675a73a98072 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3398,7 +3398,7 @@ out_unlock_mutex: return err; } -static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates) +static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates) { struct ieee80211_supported_band *sband = dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)]; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index fb996c27a19b..879edc786713 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2650,7 +2650,7 @@ out_unlock_mutex: return err; } -static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u64 brates) +static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates) { struct ieee80211_supported_band *sband = dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 64492feca9b2..94c3acd1fcaf 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -144,7 +144,7 @@ struct p54_common { unsigned int output_power; u32 tsf_low32; u32 tsf_high32; - u64 basic_rate_mask; + u32 basic_rate_mask; u16 wakeup_timer; u16 aid; struct ieee80211_tx_queue_stats tx_stats[8]; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index cc56637e73b5..46918deceda1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -396,7 +396,7 @@ struct rt2x00lib_erp { int ack_timeout; int ack_consume_time; - u64 basic_rates; + u32 basic_rates; int slot_time; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ef42559694f1..c76484009baa 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -207,7 +207,7 @@ struct ieee80211_bss_conf { u16 beacon_int; u16 assoc_capability; u64 timestamp; - u64 basic_rates; + u32 basic_rates; struct ieee80211_bss_ht_conf ht; }; @@ -761,7 +761,7 @@ enum set_key_cmd { * sizeof(void *), size is determined in hw information. */ struct ieee80211_sta { - u64 supp_rates[IEEE80211_NUM_BANDS]; + u32 supp_rates[IEEE80211_NUM_BANDS]; u8 addr[ETH_ALEN]; u16 aid; struct ieee80211_sta_ht_cap ht_cap; diff --git a/include/net/wireless.h b/include/net/wireless.h index 9e73aae40c5d..6c5b08204232 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -367,7 +367,7 @@ ieee80211_get_channel(struct wiphy *wiphy, int freq) */ struct ieee80211_rate * ieee80211_get_response_rate(struct ieee80211_supported_band *sband, - u64 basic_rates, int bitrate); + u32 basic_rates, int bitrate); /** * regulatory_hint - driver hint to the wireless core a regulatory domain diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a8c72742a8b1..70366efc792e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -909,11 +909,11 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 *addr, u64 supp_rates); + u8 *bssid, u8 *addr, u32 supp_rates); int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); -u64 ieee80211_sta_get_rates(struct ieee80211_local *local, +u32 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, @@ -1026,7 +1026,7 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); -u64 ieee80211_mandatory_rates(struct ieee80211_local *local, +u32 ieee80211_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band); void ieee80211_dynamic_ps_enable_work(struct work_struct *work); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 82f568e94365..2d573f8470d0 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -476,7 +476,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee802_11_elems elems; struct ieee80211_channel *channel; - u64 supp_rates = 0; + u32 supp_rates = 0; size_t baselen; int freq; enum ieee80211_band band = rx_status->band; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index f1196f5c3efe..9e064ee98ee0 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -236,7 +236,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len); int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ -void mesh_neighbour_update(u8 *hw_addr, u64 rates, +void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, bool add); bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index c140a1b71a5e..a8bbdeca013a 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -93,7 +93,7 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) * on it in the lifecycle management section! */ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, - u8 *hw_addr, u64 rates) + u8 *hw_addr, u32 rates) { struct ieee80211_local *local = sdata->local; struct sta_info *sta; @@ -222,7 +222,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, return 0; } -void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata, +void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, bool peer_accepting_plinks) { struct ieee80211_local *local = sdata->local; @@ -447,7 +447,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_lock_bh(&sta->lock); } else if (!sta) { /* ftype == PLINK_OPEN */ - u64 rates; + u32 rates; if (!mesh_plink_free_count(sdata)) { mpl_dbg("Mesh plink error: no more free plinks\n"); rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b9e4b93089c4..9852da54f5e7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -73,7 +73,7 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) static int ieee80211_compatible_rates(struct ieee80211_bss *bss, struct ieee80211_supported_band *sband, - u64 *rates) + u32 *rates) { int i, j, count; *rates = 0; @@ -93,14 +93,14 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss, } /* also used by mesh code */ -u64 ieee80211_sta_get_rates(struct ieee80211_local *local, +u32 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band) { struct ieee80211_supported_band *sband; struct ieee80211_rate *bitrates; size_t num_rates; - u64 supp_rates; + u32 supp_rates; int i, j; sband = local->hw.wiphy->bands[band]; @@ -253,7 +253,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; - u64 rates = 0; + u32 rates = 0; size_t e_ies_len; if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { @@ -1282,7 +1282,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; - u64 rates, basic_rates; + u32 rates, basic_rates; u16 capab_info, status_code, aid; struct ieee802_11_elems elems; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; @@ -1639,7 +1639,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; struct ieee80211_channel *channel; u64 beacon_timestamp, rx_timestamp; - u64 supp_rates = 0; + u32 supp_rates = 0; enum ieee80211_band band = rx_status->band; if (elems->ds_params && elems->ds_params_len == 1) @@ -1660,7 +1660,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sta = sta_info_get(local, mgmt->sa); if (sta) { - u64 prev_rates; + u32 prev_rates; prev_rates = sta->sta.supp_rates[band]; /* make sure mandatory rates are always added */ @@ -2526,7 +2526,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) * must be callable in atomic context. */ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid,u8 *addr, u64 supp_rates) + u8 *bssid,u8 *addr, u32 supp_rates) { struct ieee80211_local *local = sdata->local; struct sta_info *sta; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3f559e3d0a7c..ede96c4fea2e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -731,12 +731,12 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) return ret; } -u64 ieee80211_mandatory_rates(struct ieee80211_local *local, +u32 ieee80211_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band) { struct ieee80211_supported_band *sband; struct ieee80211_rate *bitrates; - u64 mandatory_rates; + u32 mandatory_rates; enum ieee80211_rate_flags mandatory_flag; int i; diff --git a/net/wireless/core.c b/net/wireless/core.c index b96fc0c3f1c4..125226476089 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -273,10 +273,16 @@ int wiphy_register(struct wiphy *wiphy) sband->band = band; - if (!sband->n_channels || !sband->n_bitrates) { - WARN_ON(1); + if (WARN_ON(!sband->n_channels || !sband->n_bitrates)) + return -EINVAL; + + /* + * Since we use a u32 for rate bitmaps in + * ieee80211_get_response_rate, we cannot + * have more than 32 legacy rates. + */ + if (WARN_ON(sband->n_bitrates > 32)) return -EINVAL; - } for (i = 0; i < sband->n_channels; i++) { sband->channels[i].orig_flags = diff --git a/net/wireless/util.c b/net/wireless/util.c index e76cc28b0345..487cdd9bcffc 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -9,7 +9,7 @@ struct ieee80211_rate * ieee80211_get_response_rate(struct ieee80211_supported_band *sband, - u64 basic_rates, int bitrate) + u32 basic_rates, int bitrate) { struct ieee80211_rate *result = &sband->bitrates[0]; int i; -- cgit v1.2.3 From 6ba265e9cc764bc401cda284954cf2bdd4408c38 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 23 Jan 2009 17:03:06 +0100 Subject: rt2x00: rt2x00_rev() should return u32 The "rev" field in chipset definition is an u32, which means that rt2x00_rev() which returns that field should be of the same type. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 46918deceda1..2a9909dd551d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -868,7 +868,7 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) return (chipset->rf == chip); } -static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset) +static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) { return chipset->rev; } -- cgit v1.2.3 From 0712612741e1dccf10353c70ebe90ba8cc60d5fb Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 23 Jan 2009 17:04:05 +0100 Subject: rt2x00: Simplify suspend/resume handling With mac80211 handling all open interfaces during suspend and resume we can simplify suspend/resume within rt2x00lib. The only thing rt2x00 needs to do is free up memory during suspend and bring back the minimal required components during resume. 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 | 93 ++------------------------------- 2 files changed, 5 insertions(+), 89 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 2a9909dd551d..d0a825638188 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -575,7 +575,6 @@ enum rt2x00_flags { DEVICE_STATE_REGISTERED_HW, DEVICE_STATE_INITIALIZED, DEVICE_STATE_STARTED, - DEVICE_STATE_STARTED_SUSPEND, DEVICE_STATE_ENABLED_RADIO, DEVICE_STATE_DISABLED_RADIO_HW, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index cd4447502d8b..e1b40545a9be 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -881,23 +881,17 @@ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); #ifdef CONFIG_PM int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) { - int retval; - NOTICE(rt2x00dev, "Going to sleep.\n"); /* - * Only continue if mac80211 has open interfaces. + * Prevent mac80211 from accessing driver while suspended. */ - if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - goto exit; - - set_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags); + if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return 0; /* - * Disable radio. + * Cleanup as much as possible. */ - rt2x00lib_stop(rt2x00dev); rt2x00lib_uninitialize(rt2x00dev); /* @@ -906,7 +900,6 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) rt2x00leds_suspend(rt2x00dev); rt2x00debug_deregister(rt2x00dev); -exit: /* * Set device mode to sleep for power management, * on some hardware this call seems to consistently fail. @@ -918,8 +911,7 @@ exit: * the radio and the other components already disabled the * device is as good as disabled. */ - retval = rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP); - if (retval) + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP)) WARNING(rt2x00dev, "Device failed to enter sleep state, " "continue suspending.\n"); @@ -927,34 +919,8 @@ exit: } EXPORT_SYMBOL_GPL(rt2x00lib_suspend); -static void rt2x00lib_resume_intf(void *data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct rt2x00_dev *rt2x00dev = data; - struct rt2x00_intf *intf = vif_to_intf(vif); - - spin_lock(&intf->lock); - - rt2x00lib_config_intf(rt2x00dev, intf, - vif->type, intf->mac, intf->bssid); - - - /* - * AP, Ad-hoc, and Mesh Point mode require a new beacon update. - */ - if (vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_WDS) - intf->delayed_flags |= DELAYED_UPDATE_BEACON; - - spin_unlock(&intf->lock); -} - int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) { - int retval; - NOTICE(rt2x00dev, "Waking up.\n"); /* @@ -963,61 +929,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) rt2x00debug_register(rt2x00dev); rt2x00leds_resume(rt2x00dev); - /* - * Only continue if mac80211 had open interfaces. - */ - if (!test_and_clear_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags)) - return 0; - - /* - * Reinitialize device and all active interfaces. - */ - retval = rt2x00lib_start(rt2x00dev); - if (retval) - goto exit; - - /* - * Reconfigure device. - */ - retval = rt2x00mac_config(rt2x00dev->hw, ~0); - if (retval) - goto exit; - - /* - * Iterator over each active interface to - * reconfigure the hardware. - */ - ieee80211_iterate_active_interfaces(rt2x00dev->hw, - rt2x00lib_resume_intf, rt2x00dev); - /* * We are ready again to receive requests from mac80211. */ set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - /* - * It is possible that during that mac80211 has attempted - * to send frames while we were suspending or resuming. - * In that case we have disabled the TX queue and should - * now enable it again - */ - ieee80211_wake_queues(rt2x00dev->hw); - - /* - * During interface iteration we might have changed the - * delayed_flags, time to handles the event by calling - * the work handler directly. - */ - rt2x00lib_intf_scheduled(&rt2x00dev->intf_work); - return 0; - -exit: - rt2x00lib_stop(rt2x00dev); - rt2x00lib_uninitialize(rt2x00dev); - rt2x00debug_deregister(rt2x00dev); - - return retval; } EXPORT_SYMBOL_GPL(rt2x00lib_resume); #endif /* CONFIG_PM */ -- cgit v1.2.3 From a2c9b652a12a550d3d8509e9bae43bac396c5076 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 28 Jan 2009 00:32:33 +0100 Subject: rt2x00: Add kill_tx_queue callback function provide rt2x00lib the possibility to kill a particular TX queue. This can be useful when disabling the radio, but more importantly will allow beaconing to be disabled when mac80211 requests this (during scanning for example) Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 30 ++++++++------- drivers/net/wireless/rt2x00/rt2500pci.c | 30 ++++++++------- drivers/net/wireless/rt2x00/rt2500usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 2 + drivers/net/wireless/rt2x00/rt2x00dev.c | 5 ++- drivers/net/wireless/rt2x00/rt2x00lib.h | 13 ++++++- drivers/net/wireless/rt2x00/rt2x00mac.c | 6 ++- drivers/net/wireless/rt2x00/rt2x00queue.c | 19 +++++++++- drivers/net/wireless/rt2x00/rt2x00usb.c | 62 +++++++++++++++++++------------ drivers/net/wireless/rt2x00/rt2x00usb.h | 11 ++++++ drivers/net/wireless/rt2x00/rt61pci.c | 37 ++++++++++-------- drivers/net/wireless/rt2x00/rt73usb.c | 1 + 12 files changed, 145 insertions(+), 72 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4a2c0b971ca8..b0848259b455 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -934,21 +934,10 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); - /* - * Disable synchronisation. + * Disable power */ - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - - /* - * Cancel RX and TX. - */ - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); } static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -1145,6 +1134,20 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } +static void rt2400pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + u32 reg; + + if (qid == QID_BEACON) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); + } else { + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + } +} + /* * RX control handlers */ @@ -1606,6 +1609,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .write_beacon = rt2400pci_write_beacon, .kick_tx_queue = rt2400pci_kick_tx_queue, + .kill_tx_queue = rt2400pci_kill_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index b9104e28bc2e..eb82860c54f9 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1093,21 +1093,10 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); - /* - * Disable synchronisation. + * Disable power */ - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - - /* - * Cancel RX and TX. - */ - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); } static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -1303,6 +1292,20 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } +static void rt2500pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + u32 reg; + + if (qid == QID_BEACON) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); + } else { + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + } +} + /* * RX control handlers */ @@ -1905,6 +1908,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .write_beacon = rt2500pci_write_beacon, .kick_tx_queue = rt2500pci_kick_tx_queue, + .kill_tx_queue = rt2500pci_kill_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c526e737fcad..270691ac2361 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1935,6 +1935,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, + .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_shared_key = rt2500usb_config_key, .config_pairwise_key = rt2500usb_config_key, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d0a825638188..94fb571667fe 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -508,6 +508,8 @@ struct rt2x00lib_ops { int (*get_tx_data_len) (struct queue_entry *entry); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, const enum data_queue_qid queue); + void (*kill_tx_queue) (struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid queue); /* * RX control handlers diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e681d239d43c..05f94e21b423 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -83,9 +83,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) return; /* - * Stop the TX queues. + * Stop the TX queues in mac80211. */ ieee80211_stop_queues(rt2x00dev->hw); + rt2x00queue_stop_queues(rt2x00dev); /* * Disable RX. @@ -157,7 +158,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, return; if (delayed_flags & DELAYED_UPDATE_BEACON) - rt2x00queue_update_beacon(rt2x00dev, vif); + rt2x00queue_update_beacon(rt2x00dev, vif, true); if (delayed_flags & DELAYED_CONFIG_ERP) rt2x00lib_config_erp(rt2x00dev, intf, &conf); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 34efe4653549..a631613177d0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -123,9 +123,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware * @rt2x00dev: Pointer to &struct rt2x00_dev. * @vif: Interface for which the beacon should be updated. + * @enable_beacon: Enable beaconing */ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif); + struct ieee80211_vif *vif, + const bool enable_beacon); /** * rt2x00queue_index_inc - Index incrementation function @@ -138,6 +140,15 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, */ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); +/** + * rt2x00queue_stop_queues - Halt all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to stop + * any pending outgoing frames. + */ +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); + /** * rt2x00queue_init_queues - Initialize all data queues * @rt2x00dev: Pointer to &struct rt2x00_dev. diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 71de8a7144f9..c41a0b9e473d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -431,8 +431,10 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, /* * Update the beacon. */ - if (conf->changed & IEEE80211_IFCC_BEACON) - status = rt2x00queue_update_beacon(rt2x00dev, vif); + if (conf->changed & (IEEE80211_IFCC_BEACON | + IEEE80211_IFCC_BEACON_ENABLED)) + status = rt2x00queue_update_beacon(rt2x00dev, vif, + conf->enable_beacon); return status; } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index c86fb6471754..a5664bd8493e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -443,7 +443,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) } int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif, + const bool enable_beacon) { struct rt2x00_intf *intf = vif_to_intf(vif); struct skb_frame_desc *skbdesc; @@ -453,6 +454,11 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, if (unlikely(!intf->beacon)) return -ENOBUFS; + if (!enable_beacon) { + rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON); + return 0; + } + intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); if (!intf->beacon->skb) return -ENOMEM; @@ -501,6 +507,9 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, { int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + if (queue == QID_RX) + return rt2x00dev->rx; + if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx) return &rt2x00dev->tx[queue]; @@ -577,6 +586,14 @@ static void rt2x00queue_reset(struct data_queue *queue) spin_unlock_irqrestore(&queue->lock, irqflags); } +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + txall_queue_for_each(rt2x00dev, queue) + rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, queue->qid); +} + void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index c89d1520838c..7d50ca82375e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -296,6 +296,41 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); +void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); + struct queue_entry_priv_usb *entry_priv; + struct queue_entry_priv_usb_bcn *bcn_priv; + unsigned int i; + bool kill_guard; + + /* + * When killing the beacon queue, we must also kill + * the beacon guard byte. + */ + kill_guard = + (qid == QID_BEACON) && + (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)); + + /* + * Cancel all entries. + */ + for (i = 0; i < queue->limit; i++) { + entry_priv = queue->entries[i].priv_data; + usb_kill_urb(entry_priv->urb); + + /* + * Kill guardian urb (if required by driver). + */ + if (kill_guard) { + bcn_priv = queue->entries[i].priv_data; + usb_kill_urb(bcn_priv->guardian_urb); + } + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); + /* * RX data handlers. */ @@ -338,35 +373,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) */ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - struct queue_entry_priv_usb *entry_priv; - struct queue_entry_priv_usb_bcn *bcn_priv; - struct data_queue *queue; - unsigned int i; - rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, REGISTER_TIMEOUT); /* - * Cancel all queues. + * The USB version of kill_tx_queue also works + * on the RX queue. */ - queue_for_each(rt2x00dev, queue) { - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - usb_kill_urb(entry_priv->urb); - } - } - - /* - * Kill guardian urb (if required by driver). - */ - if (!test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) - return; - - for (i = 0; i < rt2x00dev->bcn->limit; i++) { - bcn_priv = rt2x00dev->bcn->entries[i].priv_data; - if (bcn_priv->guardian_urb) - usb_kill_urb(bcn_priv->guardian_urb); - } + rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_RX); } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index fe4523887bdf..bd2d59c85f1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -419,6 +419,17 @@ struct queue_entry_priv_usb_bcn { void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, const enum data_queue_qid qid); +/** + * rt2x00usb_kill_tx_queue - Kill data queue + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @qid: Data queue to kill + * + * This will walk through all entries of the queue and kill all + * previously kicked frames before they can be send. + */ +void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid); + /* * Device initialization handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index d81a8de9dc17..c7ad1b3d4765 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1696,24 +1696,10 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) { - u32 reg; - - rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); - - /* - * Disable synchronisation. - */ - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - /* - * Cancel RX and TX. + * Disable power */ - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, 1); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); } static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) @@ -1936,6 +1922,24 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); } +static void rt61pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid qid) +{ + u32 reg; + + if (qid == QID_BEACON) { + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); + return; + } + + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (qid == QID_AC_BE)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (qid == QID_AC_BK)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (qid == QID_AC_VI)); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (qid == QID_AC_VO)); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); +} + /* * RX control handlers */ @@ -2761,6 +2765,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .write_beacon = rt61pci_write_beacon, .kick_tx_queue = rt61pci_kick_tx_queue, + .kill_tx_queue = rt61pci_kill_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, .config_shared_key = rt61pci_config_shared_key, .config_pairwise_key = rt61pci_config_pairwise_key, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index f854551be75d..24e97b341cf8 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2293,6 +2293,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, + .kill_tx_queue = rt2x00usb_kill_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_shared_key = rt73usb_config_shared_key, .config_pairwise_key = rt73usb_config_pairwise_key, -- cgit v1.2.3 From 0cbe0064614ace61e08618948f82c6d525e75017 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 28 Jan 2009 00:33:47 +0100 Subject: rt2x00: Validate firmware in driver The get_firmware_crc() callback function isn't flexible enough when dealing with multiple firmware versions. It might in some cases be possible that the firmware file contains multiple CRC checksums. Create the check_firmware() callback function where the driver has complete freedom in how to validate the firmware. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 7 ++++--- drivers/net/wireless/rt2x00/rt2x00firmware.c | 27 +++++++++++++++++--------- drivers/net/wireless/rt2x00/rt2x00reg.h | 10 ++++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 29 +++++++++++++++++----------- drivers/net/wireless/rt2x00/rt73usb.c | 29 +++++++++++++++++----------- 5 files changed, 68 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 94fb571667fe..84bd6f19acb0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -468,9 +468,10 @@ struct rt2x00lib_ops { */ int (*probe_hw) (struct rt2x00_dev *rt2x00dev); char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev); - u16 (*get_firmware_crc) (const void *data, const size_t len); - int (*load_firmware) (struct rt2x00_dev *rt2x00dev, const void *data, - const size_t len); + int (*check_firmware) (struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len); + int (*load_firmware) (struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len); /* * Device initialization/deinitialization handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 2a7e8bc0016b..d2deea2f2679 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -35,7 +35,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) const struct firmware *fw; char *fw_name; int retval; - u16 crc; /* * Read correct firmware from harddisk. @@ -61,16 +60,26 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) return -ENOENT; } - crc = rt2x00dev->ops->lib->get_firmware_crc(fw->data, fw->size); - if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) { - ERROR(rt2x00dev, "Firmware checksum error.\n"); - retval = -ENOENT; - goto exit; - } - INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", fw->data[fw->size - 4], fw->data[fw->size - 3]); + retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); + switch (retval) { + case FW_OK: + break; + case FW_BAD_CRC: + ERROR(rt2x00dev, "Firmware checksum error.\n"); + goto exit; + case FW_BAD_LENGTH: + ERROR(rt2x00dev, + "Invalid firmware file length (len=%zu)\n", fw->size); + goto exit; + case FW_BAD_VERSION: + ERROR(rt2x00dev, + "Current firmware does not support detected chipset.\n"); + goto exit; + }; + rt2x00dev->fw = fw; return 0; @@ -78,7 +87,7 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) exit: release_firmware(fw); - return retval; + return -ENOENT; } int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 9ddc2d07eef8..861322d97fce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -134,6 +134,16 @@ enum rate_modulation { RATE_MODE_HT_GREENFIELD = 3, }; +/* + * Firmware validation error codes + */ +enum firmware_errors { + FW_OK, + FW_BAD_CRC, + FW_BAD_LENGTH, + FW_BAD_VERSION, +}; + /* * Register handlers. * We store the position of a register field inside a field structure, diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c7ad1b3d4765..0be147f364e7 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1176,34 +1176,41 @@ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) return fw_name; } -static u16 rt61pci_get_firmware_crc(const void *data, const size_t len) +static int rt61pci_check_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { + u16 fw_crc; u16 crc; /* - * Use the crc itu-t algorithm. + * Only support 8kb firmware files. + */ + if (len != 8192) + return FW_BAD_LENGTH; + + /* * The last 2 bytes in the firmware array are the crc checksum itself, * this means that we should never pass those 2 bytes to the crc * algorithm. */ + fw_crc = (data[len - 2] << 8 | data[len - 1]); + + /* + * Use the crc itu-t algorithm. + */ crc = crc_itu_t(0, data, len - 2); crc = crc_itu_t_byte(crc, 0); crc = crc_itu_t_byte(crc, 0); - return crc; + return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; } -static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, - const size_t len) +static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { int i; u32 reg; - if (len != 8192) { - ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len); - return -ENOENT; - } - /* * Wait for stable hardware. */ @@ -2750,7 +2757,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .irq_handler = rt61pci_interrupt, .probe_hw = rt61pci_probe_hw, .get_firmware_name = rt61pci_get_firmware_name, - .get_firmware_crc = rt61pci_get_firmware_crc, + .check_firmware = rt61pci_check_firmware, .load_firmware = rt61pci_load_firmware, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 24e97b341cf8..be791a43c054 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1061,35 +1061,42 @@ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) return FIRMWARE_RT2571; } -static u16 rt73usb_get_firmware_crc(const void *data, const size_t len) +static int rt73usb_check_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { + u16 fw_crc; u16 crc; /* - * Use the crc itu-t algorithm. + * Only support 2kb firmware files. + */ + if (len != 2048) + return FW_BAD_LENGTH; + + /* * The last 2 bytes in the firmware array are the crc checksum itself, * this means that we should never pass those 2 bytes to the crc * algorithm. */ + fw_crc = (data[len - 2] << 8 | data[len - 1]); + + /* + * Use the crc itu-t algorithm. + */ crc = crc_itu_t(0, data, len - 2); crc = crc_itu_t_byte(crc, 0); crc = crc_itu_t_byte(crc, 0); - return crc; + return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; } -static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, - const size_t len) +static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) { unsigned int i; int status; u32 reg; - if (len != 2048) { - ERROR(rt2x00dev, "Invalid firmware file length (len=%zu)\n", len); - return -ENOENT; - } - /* * Wait for stable hardware. */ @@ -2278,7 +2285,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .probe_hw = rt73usb_probe_hw, .get_firmware_name = rt73usb_get_firmware_name, - .get_firmware_crc = rt73usb_get_firmware_crc, + .check_firmware = rt73usb_check_firmware, .load_firmware = rt73usb_load_firmware, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, -- cgit v1.2.3