Commit 459c51ad authored by Daniel Drake's avatar Daniel Drake Committed by David S. Miller
Browse files

zd1211rw: port to mac80211



This seems to be working smoothly now. Let's not hold back the mac80211
transition any further. This patch ports the existing driver from softmac
to mac80211.

Many thanks to everyone who helped out with the porting efforts.
Signed-off-by: default avatarDaniel Drake <dsd@gentoo.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0765af44
config ZD1211RW
tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
depends on USB && IEEE80211_SOFTMAC && WLAN_80211 && EXPERIMENTAL
select WIRELESS_EXT
depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
select FW_LOADER
---help---
This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless
chip, present in many USB-wireless adapters.
Device firmware is required alongside this driver. You can download the
firmware distribution from http://zd1211.ath.cx/get-firmware
Device firmware is required alongside this driver. You can download
the firmware distribution from http://zd1211.ath.cx/get-firmware
config ZD1211RW_DEBUG
bool "ZyDAS ZD1211 debugging"
......
obj-$(CONFIG_ZD1211RW) += zd1211rw.o
zd1211rw-objs := zd_chip.o zd_ieee80211.o \
zd_mac.o zd_netdev.o \
zd1211rw-objs := zd_chip.o zd_ieee80211.o zd_mac.o \
zd_rf_al2230.o zd_rf_rf2959.o \
zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o
......
......@@ -30,12 +30,12 @@
#include "zd_rf.h"
void zd_chip_init(struct zd_chip *chip,
struct net_device *netdev,
struct ieee80211_hw *hw,
struct usb_interface *intf)
{
memset(chip, 0, sizeof(*chip));
mutex_init(&chip->mutex);
zd_usb_init(&chip->usb, netdev, intf);
zd_usb_init(&chip->usb, hw, intf);
zd_rf_init(&chip->rf);
}
......@@ -50,7 +50,7 @@ void zd_chip_clear(struct zd_chip *chip)
static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
{
u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr;
u8 *addr = zd_mac_get_perm_addr(zd_chip_to_mac(chip));
return scnprintf(buffer, size, "%02x-%02x-%02x",
addr[0], addr[1], addr[2]);
}
......@@ -378,15 +378,18 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
};
DECLARE_MAC_BUF(mac);
reqs[0].value = (mac_addr[3] << 24)
| (mac_addr[2] << 16)
| (mac_addr[1] << 8)
| mac_addr[0];
reqs[1].value = (mac_addr[5] << 8)
| mac_addr[4];
dev_dbg_f(zd_chip_dev(chip),
"mac addr %s\n", print_mac(mac, mac_addr));
if (mac_addr) {
reqs[0].value = (mac_addr[3] << 24)
| (mac_addr[2] << 16)
| (mac_addr[1] << 8)
| mac_addr[0];
reqs[1].value = (mac_addr[5] << 8)
| mac_addr[4];
dev_dbg_f(zd_chip_dev(chip),
"mac addr %s\n", print_mac(mac, mac_addr));
} else {
dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
}
mutex_lock(&chip->mutex);
r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
......@@ -980,7 +983,7 @@ static int print_fw_version(struct zd_chip *chip)
return 0;
}
static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
static int set_mandatory_rates(struct zd_chip *chip, int mode)
{
u32 rates;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
......@@ -988,11 +991,11 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
* that the device is supporting. Until further notice we should try
* to support 802.11g also for full speed USB.
*/
switch (std) {
case IEEE80211B:
switch (mode) {
case MODE_IEEE80211B:
rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
break;
case IEEE80211G:
case MODE_IEEE80211G:
rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
break;
......@@ -1003,24 +1006,17 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
}
int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
u8 rts_rate, int preamble)
int preamble)
{
int rts_mod = ZD_RX_CCK;
u32 value = 0;
/* Modulation bit */
if (ZD_MODULATION_TYPE(rts_rate) == ZD_OFDM)
rts_mod = ZD_RX_OFDM;
dev_dbg_f(zd_chip_dev(chip), "rts_rate=%x preamble=%x\n",
rts_rate, preamble);
value |= ZD_PURE_RATE(rts_rate) << RTSCTS_SH_RTS_RATE;
value |= rts_mod << RTSCTS_SH_RTS_MOD_TYPE;
dev_dbg_f(zd_chip_dev(chip), "preamble=%x\n", preamble);
value |= preamble << RTSCTS_SH_RTS_PMB_TYPE;
value |= preamble << RTSCTS_SH_CTS_PMB_TYPE;
/* We always send 11M self-CTS messages, like the vendor driver. */
/* We always send 11M RTS/self-CTS messages, like the vendor driver. */
value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_RTS_RATE;
value |= ZD_RX_CCK << RTSCTS_SH_RTS_MOD_TYPE;
value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_CTS_RATE;
value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE;
......@@ -1109,7 +1105,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
* It might be discussed, whether we should suppport pure b mode for
* full speed USB.
*/
r = set_mandatory_rates(chip, IEEE80211G);
r = set_mandatory_rates(chip, MODE_IEEE80211G);
if (r)
goto out;
/* Disabling interrupts is certainly a smart thing here.
......@@ -1320,12 +1316,17 @@ out:
return r;
}
int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates)
int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
{
ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0);
dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates);
int r;
if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G))
return -EINVAL;
return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
mutex_lock(&chip->mutex);
r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
mutex_unlock(&chip->mutex);
return r;
}
static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size)
......@@ -1468,56 +1469,44 @@ u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
{
return (status->frame_status&ZD_RX_OFDM) ?
ofdm_qual_percent(status->signal_quality_ofdm,
zd_rate_from_ofdm_plcp_header(rx_frame),
zd_rate_from_ofdm_plcp_header(rx_frame),
size) :
cck_qual_percent(status->signal_quality_cck);
}
u8 zd_rx_strength_percent(u8 rssi)
{
int r = (rssi*100) / 41;
if (r > 100)
r = 100;
return (u8) r;
}
u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status)
/**
* zd_rx_rate - report zd-rate
* @rx_frame - received frame
* @rx_status - rx_status as given by the device
*
* This function converts the rate as encoded in the received packet to the
* zd-rate, we are using on other places in the driver.
*/
u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status)
{
static const u16 ofdm_rates[] = {
[ZD_OFDM_PLCP_RATE_6M] = 60,
[ZD_OFDM_PLCP_RATE_9M] = 90,
[ZD_OFDM_PLCP_RATE_12M] = 120,
[ZD_OFDM_PLCP_RATE_18M] = 180,
[ZD_OFDM_PLCP_RATE_24M] = 240,
[ZD_OFDM_PLCP_RATE_36M] = 360,
[ZD_OFDM_PLCP_RATE_48M] = 480,
[ZD_OFDM_PLCP_RATE_54M] = 540,
};
u16 rate;
u8 zd_rate;
if (status->frame_status & ZD_RX_OFDM) {
/* Deals with PLCP OFDM rate (not zd_rates) */
u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame);
rate = ofdm_rates[ofdm_rate & 0xf];
zd_rate = zd_rate_from_ofdm_plcp_header(rx_frame);
} else {
switch (zd_cck_plcp_header_signal(rx_frame)) {
case ZD_CCK_PLCP_SIGNAL_1M:
rate = 10;
zd_rate = ZD_CCK_RATE_1M;
break;
case ZD_CCK_PLCP_SIGNAL_2M:
rate = 20;
zd_rate = ZD_CCK_RATE_2M;
break;
case ZD_CCK_PLCP_SIGNAL_5M5:
rate = 55;
zd_rate = ZD_CCK_RATE_5_5M;
break;
case ZD_CCK_PLCP_SIGNAL_11M:
rate = 110;
zd_rate = ZD_CCK_RATE_11M;
break;
default:
rate = 0;
zd_rate = 0;
}
}
return rate;
return zd_rate;
}
int zd_chip_switch_radio_on(struct zd_chip *chip)
......@@ -1557,20 +1546,22 @@ void zd_chip_disable_int(struct zd_chip *chip)
mutex_unlock(&chip->mutex);
}
int zd_chip_enable_rx(struct zd_chip *chip)
int zd_chip_enable_rxtx(struct zd_chip *chip)
{
int r;
mutex_lock(&chip->mutex);
zd_usb_enable_tx(&chip->usb);
r = zd_usb_enable_rx(&chip->usb);
mutex_unlock(&chip->mutex);
return r;
}
void zd_chip_disable_rx(struct zd_chip *chip)
void zd_chip_disable_rxtx(struct zd_chip *chip)
{
mutex_lock(&chip->mutex);
zd_usb_disable_rx(&chip->usb);
zd_usb_disable_tx(&chip->usb);
mutex_unlock(&chip->mutex);
}
......
......@@ -433,9 +433,10 @@ enum {
#define CR_GROUP_HASH_P2 CTL_REG(0x0628)
#define CR_RX_TIMEOUT CTL_REG(0x062C)
/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
* device will use a rate in this table that is less than or equal to the rate
* of the incoming frame which prompted the response */
* of the incoming frame which prompted the response. */
#define CR_BASIC_RATE_TBL CTL_REG(0x0630)
#define CR_RATE_1M (1 << 0) /* 802.11b */
#define CR_RATE_2M (1 << 1) /* 802.11b */
......@@ -509,14 +510,37 @@ enum {
#define CR_UNDERRUN_CNT CTL_REG(0x0688)
#define CR_RX_FILTER CTL_REG(0x068c)
#define RX_FILTER_ASSOC_REQUEST (1 << 0)
#define RX_FILTER_ASSOC_RESPONSE (1 << 1)
#define RX_FILTER_REASSOC_REQUEST (1 << 2)
#define RX_FILTER_REASSOC_RESPONSE (1 << 3)
#define RX_FILTER_PROBE_REQUEST (1 << 4)
#define RX_FILTER_PROBE_RESPONSE (1 << 5)
/* bits 6 and 7 reserved */
#define RX_FILTER_BEACON (1 << 8)
#define RX_FILTER_ATIM (1 << 9)
#define RX_FILTER_DISASSOC (1 << 10)
#define RX_FILTER_AUTH (1 << 11)
#define AP_RX_FILTER 0x0400feff
#define STA_RX_FILTER 0x0000ffff
#define RX_FILTER_DEAUTH (1 << 12)
#define RX_FILTER_PSPOLL (1 << 26)
#define RX_FILTER_RTS (1 << 27)
#define RX_FILTER_CTS (1 << 28)
#define RX_FILTER_ACK (1 << 29)
#define RX_FILTER_CFEND (1 << 30)
#define RX_FILTER_CFACK (1 << 31)
/* Enable bits for all frames you are interested in. */
#define STA_RX_FILTER (RX_FILTER_ASSOC_REQUEST | RX_FILTER_ASSOC_RESPONSE | \
RX_FILTER_REASSOC_REQUEST | RX_FILTER_REASSOC_RESPONSE | \
RX_FILTER_PROBE_REQUEST | RX_FILTER_PROBE_RESPONSE | \
(0x3 << 6) /* vendor driver sets these reserved bits */ | \
RX_FILTER_BEACON | RX_FILTER_ATIM | RX_FILTER_DISASSOC | \
RX_FILTER_AUTH | RX_FILTER_DEAUTH | \
(0x7 << 13) /* vendor driver sets these reserved bits */ | \
RX_FILTER_PSPOLL | RX_FILTER_ACK) /* 0x2400ffff */
#define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
RX_FILTER_CFEND | RX_FILTER_CFACK)
/* Monitor mode sets filter to 0xfffff */
......@@ -730,7 +754,7 @@ static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf)
#define zd_chip_dev(chip) (&(chip)->usb.intf->dev)
void zd_chip_init(struct zd_chip *chip,
struct net_device *netdev,
struct ieee80211_hw *hw,
struct usb_interface *intf);
void zd_chip_clear(struct zd_chip *chip);
int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
......@@ -835,14 +859,12 @@ int zd_chip_switch_radio_on(struct zd_chip *chip);
int zd_chip_switch_radio_off(struct zd_chip *chip);
int zd_chip_enable_int(struct zd_chip *chip);
void zd_chip_disable_int(struct zd_chip *chip);
int zd_chip_enable_rx(struct zd_chip *chip);
void zd_chip_disable_rx(struct zd_chip *chip);
int zd_chip_enable_rxtx(struct zd_chip *chip);
void zd_chip_disable_rxtx(struct zd_chip *chip);
int zd_chip_enable_hwint(struct zd_chip *chip);
int zd_chip_disable_hwint(struct zd_chip *chip);
int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel);
int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
u8 rts_rate, int preamble);
int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, int preamble);
static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
{
......@@ -859,17 +881,7 @@ static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
}
int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates);
static inline int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
{
int r;
mutex_lock(&chip->mutex);
r = zd_chip_set_basic_rates_locked(chip, cr_rates);
mutex_unlock(&chip->mutex);
return r;
}
int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
int zd_chip_lock_phy_regs(struct zd_chip *chip);
int zd_chip_unlock_phy_regs(struct zd_chip *chip);
......@@ -893,9 +905,8 @@ struct rx_status;
u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
const struct rx_status *status);
u8 zd_rx_strength_percent(u8 rssi);
u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
struct zd_mc_hash {
u32 low;
......
......@@ -16,178 +16,85 @@
*/
/*
* A lot of this code is generic and should be moved into the upper layers
* at some point.
* In the long term, we'll probably find a better way of handling regulatory
* requirements outside of the driver.
*/
#include <linux/errno.h>
#include <linux/wireless.h>
#include <linux/kernel.h>
#include <net/ieee80211.h>
#include <net/mac80211.h>
#include "zd_def.h"
#include "zd_ieee80211.h"
#include "zd_mac.h"
struct channel_range {
u8 regdomain;
u8 start;
u8 end; /* exclusive (channel must be less than end) */
};
static const struct channel_range channel_ranges[] = {
[0] = { 0, 0},
[ZD_REGDOMAIN_FCC] = { 1, 12},
[ZD_REGDOMAIN_IC] = { 1, 12},
[ZD_REGDOMAIN_ETSI] = { 1, 14},
[ZD_REGDOMAIN_JAPAN] = { 1, 14},
[ZD_REGDOMAIN_SPAIN] = { 1, 14},
[ZD_REGDOMAIN_FRANCE] = { 1, 14},
{ ZD_REGDOMAIN_FCC, 1, 12 },
{ ZD_REGDOMAIN_IC, 1, 12 },
{ ZD_REGDOMAIN_ETSI, 1, 14 },
{ ZD_REGDOMAIN_JAPAN, 1, 14 },
{ ZD_REGDOMAIN_SPAIN, 1, 14 },
{ ZD_REGDOMAIN_FRANCE, 1, 14 },
/* Japan originally only had channel 14 available (see CHNL_ID 0x40 in
* 802.11). However, in 2001 the range was extended to include channels
* 1-13. The ZyDAS devices still use the old region code but are
* designed to allow the extra channel access in Japan. */
[ZD_REGDOMAIN_JAPAN_ADD] = { 1, 15},
{ ZD_REGDOMAIN_JAPAN_ADD, 1, 15 },
};
const struct channel_range *zd_channel_range(u8 regdomain)
{
if (regdomain >= ARRAY_SIZE(channel_ranges))
regdomain = 0;
return &channel_ranges[regdomain];
}
int zd_regdomain_supports_channel(u8 regdomain, u8 channel)
{
const struct channel_range *range = zd_channel_range(regdomain);
return range->start <= channel && channel < range->end;
}
int zd_regdomain_supported(u8 regdomain)
static const struct channel_range *zd_channel_range(u8 regdomain)
{
const struct channel_range *range = zd_channel_range(regdomain);
return range->start != 0;
}
/* Stores channel frequencies in MHz. */
static const u16 channel_frequencies[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447,
2452, 2457, 2462, 2467, 2472, 2484,
};
#define NUM_CHANNELS ARRAY_SIZE(channel_frequencies)
static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz)
{
u32 factor;
freq->e = 0;
if (mhz >= 1000000000U) {
pr_debug("zd1211 mhz %u to large\n", mhz);
freq->m = 0;
return -EINVAL;
}
factor = 1000;
while (mhz >= factor) {
freq->e += 1;
factor *= 10;
}
factor /= 1000U;
freq->m = mhz * (1000000U/factor) + hz/factor;
return 0;
}
int zd_channel_to_freq(struct iw_freq *freq, u8 channel)
{
if (channel > NUM_CHANNELS) {
freq->m = 0;
freq->e = 0;
return -EINVAL;
}
if (!channel) {
freq->m = 0;
freq->e = 0;
return -EINVAL;
int i;
for (i = 0; i < ARRAY_SIZE(channel_ranges); i++) {
const struct channel_range *range = &channel_ranges[i];
if (range->regdomain == regdomain)
return range;
}
return compute_freq(freq, channel_frequencies[channel-1], 0);
return NULL;
}
static int freq_to_mhz(const struct iw_freq *freq)
{
u32 factor;
int e;
/* Such high frequencies are not supported. */
if (freq->e > 6)
return -EINVAL;
factor = 1;
for (e = freq->e; e > 0; --e) {
factor *= 10;
}
factor = 1000000U / factor;
if (freq->m % factor) {
return -EINVAL;
}
return freq->m / factor;
}
#define CHAN_TO_IDX(chan) ((chan) - 1)
int zd_find_channel(u8 *channel, const struct iw_freq *freq)
static void unmask_bg_channels(struct ieee80211_hw *hw,
const struct channel_range *range,
struct ieee80211_hw_mode *mode)
{
int i, r;
u32 mhz;
if (freq->m < 1000) {
if (freq->m > NUM_CHANNELS || freq->m == 0)
return -EINVAL;
*channel = freq->m;
return 1;
}
r = freq_to_mhz(freq);
if (r < 0)
return r;
mhz = r;
u8 channel;
for (i = 0; i < NUM_CHANNELS; i++) {
if (mhz == channel_frequencies[i]) {
*channel = i+1;
return 1;
}
for (channel = range->start; channel < range->end; channel++) {
struct ieee80211_channel *chan =
&mode->channels[CHAN_TO_IDX(channel)];
chan->flag |= IEEE80211_CHAN_W_SCAN |
IEEE80211_CHAN_W_ACTIVE_SCAN |
IEEE80211_CHAN_W_IBSS;
}
return -EINVAL;
}
int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain)
void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain)
{
struct ieee80211_geo geo;
struct zd_mac *mac = zd_hw_mac(hw);
const struct channel_range *range;
int i;
u8 channel;
dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)),
"regdomain %#04x\n", regdomain);
dev_dbg(zd_mac_dev(mac), "regdomain %#02x\n", regdomain);
range = zd_channel_range(regdomain);
if (range->start == 0) {
dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)),
"zd1211 regdomain %#04x not supported\n",
regdomain);
return -EINVAL;
if (!range) {
/* The vendor driver overrides the regulatory domain and
* allowed channel registers and unconditionally restricts
* available channels to 1-11 everywhere. Match their
* questionable behaviour only for regdomains which we don't
* recognise. */
dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: "
"%#02x. Defaulting to FCC.\n", regdomain);
range = zd_channel_range(ZD_REGDOMAIN_FCC);
}
memset(&geo, 0, sizeof(geo));
for (i = 0, channel = range->start; channel < range->end; channel++) {
struct ieee80211_channel *chan = &geo.bg[i++];
chan->freq = channel_frequencies[channel - 1];
chan->channel = channel;
}
geo.bg_channels = i;
memcpy(geo.name, "XX ", 4);
ieee80211_set_geo(ieee, &geo);
return 0;
unmask_bg_channels(hw, range, &mac->modes[0]);
unmask_bg_channels(hw, range, &mac->modes[1]);
}
#ifndef _ZD_IEEE80211_H
#define _ZD_IEEE80211_H
#include <net/ieee80211.h>
#include <net/mac80211.h>