cfg80211 API for channels/bitrates, mac80211 and driver conversion

This patch creates new cfg80211 wiphy API for channel and bitrate
registration and converts mac80211 and drivers to the new API. The
old mac80211 API is completely ripped out. All drivers (except ath5k)
are updated to the new API, in many cases I expect that optimisations
can be done.

Along with the regulatory code I've also ripped out the
IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag, I believe it to be
unnecessary if the hardware simply gives us whatever channels it wants
to support and we then enable/disable them as required, which is pretty
much required for travelling.

Additionally, the patch adds proper "basic" rate handling for STA
mode interface, AP mode interface will have to have new API added
to allow userspace to set the basic rate set, currently it'll be
empty... However, the basic rate handling will need to be moved to
the BSS conf stuff.

I do expect there to be bugs in this, especially wrt. transmit
power handling where I'm basically clueless about how it should work.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 714a6ca..cd5fcc6 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -735,6 +735,7 @@
 config ATH5K
 	tristate "Atheros 5xxx wireless cards support"
 	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+	depends on BROKEN
 	---help---
 	  This module adds support for wireless adapters based on
 	  Atheros 5xxx chipset.
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 7979618..7d42182 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -48,6 +48,32 @@
 	{ 0 }
 };
 
+static struct ieee80211_rate adm8211_rates[] = {
+	{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */
+};
+
+static const struct ieee80211_channel adm8211_channels[] = {
+	{ .center_freq = 2412},
+	{ .center_freq = 2417},
+	{ .center_freq = 2422},
+	{ .center_freq = 2427},
+	{ .center_freq = 2432},
+	{ .center_freq = 2437},
+	{ .center_freq = 2442},
+	{ .center_freq = 2447},
+	{ .center_freq = 2452},
+	{ .center_freq = 2457},
+	{ .center_freq = 2462},
+	{ .center_freq = 2467},
+	{ .center_freq = 2472},
+	{ .center_freq = 2484},
+};
+
+
 static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom)
 {
 	struct adm8211_priv *priv = eeprom->data;
@@ -155,17 +181,17 @@
 	printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n",
 	       pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max);
 
-	priv->modes[0].num_channels = chan_range.max - chan_range.min + 1;
-	priv->modes[0].channels = priv->channels;
+	BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels));
 
-	memcpy(priv->channels, adm8211_channels, sizeof(adm8211_channels));
+	memcpy(priv->channels, adm8211_channels, sizeof(priv->channels));
+	priv->band.channels = priv->channels;
+	priv->band.n_channels = ARRAY_SIZE(adm8211_channels);
+	priv->band.bitrates = adm8211_rates;
+	priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates);
 
 	for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++)
-		if (i >= chan_range.min && i <= chan_range.max)
-			priv->channels[i - 1].flag =
-				IEEE80211_CHAN_W_SCAN |
-				IEEE80211_CHAN_W_ACTIVE_SCAN |
-				IEEE80211_CHAN_W_IBSS;
+		if (i < chan_range.min || i > chan_range.max)
+			priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED;
 
 	switch (priv->eeprom->specific_bbptype) {
 	case ADM8211_BBP_RFMD3000:
@@ -347,7 +373,6 @@
 	unsigned int pktlen;
 	struct sk_buff *skb, *newskb;
 	unsigned int limit = priv->rx_ring_size;
-	static const u8 rate_tbl[] = {10, 20, 55, 110, 220};
 	u8 rssi, rate;
 
 	while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) {
@@ -425,12 +450,10 @@
 			else
 				rx_status.ssi = 100 - rssi;
 
-			if (rate <= 4)
-				rx_status.rate = rate_tbl[rate];
+			rx_status.rate_idx = rate;
 
-			rx_status.channel = priv->channel;
-			rx_status.freq = adm8211_channels[priv->channel - 1].freq;
-			rx_status.phymode = MODE_IEEE80211B;
+			rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
+			rx_status.band = IEEE80211_BAND_2GHZ;
 
 			ieee80211_rx_irqsafe(dev, skb, &rx_status);
 		}
@@ -1054,7 +1077,7 @@
 	if (priv->pdev->revision != ADM8211_REV_BA) {
 		rate_buf[0] = ARRAY_SIZE(adm8211_rates);
 		for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++)
-			rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80;
+			rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80;
 	} else {
 		/* workaround for rev BA specific bug */
 		rate_buf[0] = 0x04;
@@ -1303,9 +1326,10 @@
 static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
 {
 	struct adm8211_priv *priv = dev->priv;
+	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
 
-	if (conf->channel != priv->channel) {
-		priv->channel = conf->channel;
+	if (channel != priv->channel) {
+		priv->channel = channel;
 		adm8211_rf_set_channel(dev, priv->channel);
 	}
 
@@ -1680,10 +1704,10 @@
 
 	if (control->tx_rate < 0) {
 		short_preamble = 1;
-		plcp_signal = -control->tx_rate;
+		plcp_signal = -control->tx_rate->bitrate;
 	} else {
 		short_preamble = 0;
-		plcp_signal = control->tx_rate;
+		plcp_signal = control->tx_rate->bitrate;
 	}
 
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -1880,18 +1904,11 @@
 	SET_IEEE80211_PERM_ADDR(dev, perm_addr);
 
 	dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
-	dev->flags = IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
-	/* IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
+	/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
 
 	dev->channel_change_time = 1000;
 	dev->max_rssi = 100;	/* FIXME: find better value */
 
-	priv->modes[0].mode = MODE_IEEE80211B;
-	/* channel info filled in by adm8211_read_eeprom */
-	memcpy(priv->rates, adm8211_rates, sizeof(adm8211_rates));
-	priv->modes[0].num_rates = ARRAY_SIZE(adm8211_rates);
-	priv->modes[0].rates = priv->rates;
-
 	dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
 
 	priv->retry_limit = 3;
@@ -1917,14 +1934,7 @@
 		goto err_free_desc;
 	}
 
-	priv->channel = priv->modes[0].channels[0].chan;
-
-	err = ieee80211_register_hwmode(dev, &priv->modes[0]);
-	if (err) {
-		printk(KERN_ERR "%s (adm8211): Can't register hwmode\n",
-		       pci_name(pdev));
-		goto err_free_desc;
-	}
+	priv->channel = 1;
 
 	err = ieee80211_register_hw(dev);
 	if (err) {
diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h
index ef326fe..8d7c564 100644
--- a/drivers/net/wireless/adm8211.h
+++ b/drivers/net/wireless/adm8211.h
@@ -534,61 +534,6 @@
 	u8	cis_data[0];		/* 0x80, 384 bytes */
 } __attribute__ ((packed));
 
-static const struct ieee80211_rate adm8211_rates[] = {
-	{ .rate = 10,
-	  .val = 10,
-	  .val2 = -10,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 20,
-	  .val = 20,
-	  .val2 = -20,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 55,
-	  .val = 55,
-	  .val2 = -55,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 110,
-	  .val = 110,
-	  .val2 = -110,
-	  .flags = IEEE80211_RATE_CCK_2 }
-};
-
-struct ieee80211_chan_range {
-	u8 min;
-	u8 max;
-};
-
-static const struct ieee80211_channel adm8211_channels[] = {
-	{ .chan = 1,
-	  .freq = 2412},
-	{ .chan = 2,
-	  .freq = 2417},
-	{ .chan = 3,
-	  .freq = 2422},
-	{ .chan = 4,
-	  .freq = 2427},
-	{ .chan = 5,
-	  .freq = 2432},
-	{ .chan = 6,
-	  .freq = 2437},
-	{ .chan = 7,
-	  .freq = 2442},
-	{ .chan = 8,
-	  .freq = 2447},
-	{ .chan = 9,
-	  .freq = 2452},
-	{ .chan = 10,
-	  .freq = 2457},
-	{ .chan = 11,
-	  .freq = 2462},
-	{ .chan = 12,
-	  .freq = 2467},
-	{ .chan = 13,
-	  .freq = 2472},
-	{ .chan = 14,
-	  .freq = 2484},
-};
-
 struct adm8211_priv {
 	struct pci_dev *pdev;
 	spinlock_t lock;
@@ -603,9 +548,8 @@
 	unsigned int cur_tx, dirty_tx, cur_rx;
 
 	struct ieee80211_low_level_stats stats;
-	struct ieee80211_hw_mode modes[1];
-	struct ieee80211_channel channels[ARRAY_SIZE(adm8211_channels)];
-	struct ieee80211_rate rates[ARRAY_SIZE(adm8211_rates)];
+	struct ieee80211_supported_band band;
+	struct ieee80211_channel channels[14];
 	int mode;
 
 	int channel;
@@ -643,6 +587,11 @@
 	} transceiver_type;
 };
 
+struct ieee80211_chan_range {
+	u8 min;
+	u8 max;
+};
+
 static const struct ieee80211_chan_range cranges[] = {
 	{1,  11},	/* FCC */
 	{1,  11},	/* IC */
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index f13346b..3e40323 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -468,10 +468,6 @@
 	u8 possible_phymodes;
 	/* GMODE bit enabled? */
 	bool gmode;
-	/* Possible ieee80211 subsystem hwmodes for this PHY.
-	 * Which mode is selected, depends on thr GMODE enabled bit */
-#define B43_MAX_PHYHWMODES	2
-	struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES];
 
 	/* Analog Type */
 	u8 analog;
@@ -727,7 +723,6 @@
 
 	bool bad_frames_preempt;	/* Use "Bad Frames Preemption" (default off) */
 	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
-	bool short_preamble;	/* TRUE, if short preamble is enabled. */
 	bool short_slot;	/* TRUE, if short slot timing is enabled. */
 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
 	bool suspend_in_progress;	/* TRUE, if we are in a suspend/resume cycle */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 51dfce1..017a041 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -96,25 +96,29 @@
  * data in there. This data is the same for all devices, so we don't
  * get concurrency issues */
 #define RATETAB_ENT(_rateid, _flags) \
-	{							\
-		.rate	= B43_RATE_TO_BASE100KBPS(_rateid),	\
-		.val	= (_rateid),				\
-		.val2	= (_rateid),				\
-		.flags	= (_flags),				\
+	{								\
+		.bitrate	= B43_RATE_TO_BASE100KBPS(_rateid),	\
+		.hw_value	= (_rateid),				\
+		.flags		= (_flags),				\
 	}
+
+/*
+ * NOTE: When changing this, sync with xmit.c's
+ *	 b43_plcp_get_bitrate_idx_* functions!
+ */
 static struct ieee80211_rate __b43_ratetable[] = {
-	RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK),
-	RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
-	RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
-	RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
-	RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
+	RATETAB_ENT(B43_CCK_RATE_1MB, 0),
+	RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43_OFDM_RATE_6MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_9MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_12MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_18MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_24MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_36MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_48MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_54MB, 0),
 };
 
 #define b43_a_ratetable		(__b43_ratetable + 4)
@@ -126,14 +130,8 @@
 
 #define CHANTAB_ENT(_chanid, _freq) \
 	{							\
-		.chan	= (_chanid),				\
-		.freq	= (_freq),				\
-		.val	= (_chanid),				\
-		.flag	= IEEE80211_CHAN_W_SCAN |		\
-			  IEEE80211_CHAN_W_ACTIVE_SCAN |	\
-			  IEEE80211_CHAN_W_IBSS,		\
-		.power_level	= 0xFF,				\
-		.antenna_max	= 0xFF,				\
+		.center_freq	= (_freq),			\
+		.hw_value	= (_chanid),			\
 	}
 static struct ieee80211_channel b43_2ghz_chantable[] = {
 	CHANTAB_ENT(1, 2412),
@@ -151,9 +149,8 @@
 	CHANTAB_ENT(13, 2472),
 	CHANTAB_ENT(14, 2484),
 };
-#define b43_2ghz_chantable_size	ARRAY_SIZE(b43_2ghz_chantable)
 
-#if 0
+#ifdef NOTYET
 static struct ieee80211_channel b43_5ghz_chantable[] = {
 	CHANTAB_ENT(36, 5180),
 	CHANTAB_ENT(40, 5200),
@@ -169,9 +166,22 @@
 	CHANTAB_ENT(161, 5805),
 	CHANTAB_ENT(165, 5825),
 };
-#define b43_5ghz_chantable_size	ARRAY_SIZE(b43_5ghz_chantable)
+
+static struct ieee80211_supported_band b43_band_5GHz = {
+	.channels = b43_5ghz_chantable,
+	.n_channels = ARRAY_SIZE(b43_5ghz_chantable),
+	.bitrates = b43_a_ratetable,
+	.n_bitrates = b43_a_ratetable_size,
+};
 #endif
 
+static struct ieee80211_supported_band b43_band_2GHz = {
+	.channels = b43_2ghz_chantable,
+	.n_channels = ARRAY_SIZE(b43_2ghz_chantable),
+	.bitrates = b43_g_ratetable,
+	.n_bitrates = b43_g_ratetable_size,
+};
+
 static void b43_wireless_core_exit(struct b43_wldev *dev);
 static int b43_wireless_core_init(struct b43_wldev *dev);
 static void b43_wireless_core_stop(struct b43_wldev *dev);
@@ -1222,17 +1232,18 @@
 }
 
 static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
-				      u16 shm_offset, u16 size, u8 rate)
+				      u16 shm_offset, u16 size,
+				      struct ieee80211_rate *rate)
 {
 	struct b43_plcp_hdr4 plcp;
 	u32 tmp;
 	__le16 dur;
 
 	plcp.data = 0;
-	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
+	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
 					       dev->wl->vif, size,
-					       B43_RATE_TO_BASE100KBPS(rate));
+					       rate);
 	/* Write PLCP in two parts and timing for packet transfer */
 	tmp = le32_to_cpu(plcp.data);
 	b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
@@ -1247,7 +1258,8 @@
  * 3) Stripping TIM
  */
 static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
-					  u16 *dest_size, u8 rate)
+					  u16 *dest_size,
+					  struct ieee80211_rate *rate)
 {
 	const u8 *src_data;
 	u8 *dest_data;
@@ -1292,7 +1304,7 @@
 					 IEEE80211_STYPE_PROBE_RESP);
 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
 					       dev->wl->vif, *dest_size,
-					       B43_RATE_TO_BASE100KBPS(rate));
+					       rate);
 	hdr->duration_id = dur;
 
 	return dest_data;
@@ -1300,7 +1312,8 @@
 
 static void b43_write_probe_resp_template(struct b43_wldev *dev,
 					  u16 ram_offset,
-					  u16 shm_size_offset, u8 rate)
+					  u16 shm_size_offset,
+					  struct ieee80211_rate *rate)
 {
 	const u8 *probe_resp_data;
 	u16 size;
@@ -1313,14 +1326,15 @@
 	/* Looks like PLCP headers plus packet timings are stored for
 	 * all possible basic rates
 	 */
-	b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB);
-	b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB);
-	b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB);
-	b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB);
+	b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
+	b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
+	b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
+	b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
 
 	size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
 	b43_write_template_common(dev, probe_resp_data,
-				  size, ram_offset, shm_size_offset, rate);
+				  size, ram_offset, shm_size_offset,
+				  rate->hw_value);
 	kfree(probe_resp_data);
 }
 
@@ -1388,7 +1402,7 @@
 			b43_write_beacon_template(dev, 0x68, 0x18,
 						  B43_CCK_RATE_1MB);
 			b43_write_probe_resp_template(dev, 0x268, 0x4A,
-						      B43_CCK_RATE_11MB);
+						      &__b43_ratetable[3]);
 			wl->beacon0_uploaded = 1;
 		}
 		cmd |= B43_MACCMD_BEACON0_VALID;
@@ -2830,14 +2844,11 @@
 	mutex_lock(&wl->mutex);
 
 	/* Switch the PHY mode (if necessary). */
-	switch (conf->phymode) {
-	case MODE_IEEE80211A:
+	switch (conf->channel->band) {
+	case IEEE80211_BAND_5GHZ:
 		new_phymode = B43_PHYMODE_A;
 		break;
-	case MODE_IEEE80211B:
-		new_phymode = B43_PHYMODE_B;
-		break;
-	case MODE_IEEE80211G:
+	case IEEE80211_BAND_2GHZ:
 		new_phymode = B43_PHYMODE_G;
 		break;
 	default:
@@ -2863,8 +2874,8 @@
 
 	/* Switch to the requested channel.
 	 * The firmware takes care of races with the TX handler. */
-	if (conf->channel_val != phy->channel)
-		b43_radio_selectchannel(dev, conf->channel_val, 0);
+	if (conf->channel->hw_value != phy->channel)
+		b43_radio_selectchannel(dev, conf->channel->hw_value, 0);
 
 	/* Enable/Disable ShortSlot timing. */
 	if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
@@ -3810,9 +3821,7 @@
 			   bool have_2ghz_phy, bool have_5ghz_phy)
 {
 	struct ieee80211_hw *hw = dev->wl->hw;
-	struct ieee80211_hw_mode *mode;
 	struct b43_phy *phy = &dev->phy;
-	int err;
 
 	/* XXX: This function will go away soon, when mac80211
 	 *      band stuff is rewritten. So this is just a hack.
@@ -3821,15 +3830,7 @@
 	 *      This assumption is OK, as any B, N or A PHY will already
 	 *      have died a horrible sanity check death earlier. */
 
-	mode = &phy->hwmodes[0];
-	mode->mode = MODE_IEEE80211G;
-	mode->num_channels = b43_2ghz_chantable_size;
-	mode->channels = b43_2ghz_chantable;
-	mode->num_rates = b43_g_ratetable_size;
-	mode->rates = b43_g_ratetable;
-	err = ieee80211_register_hwmode(hw, mode);
-	if (err)
-		return err;
+	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
 	phy->possible_phymodes |= B43_PHYMODE_G;
 
 	return 0;
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index f4faff6..275095b 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -47,29 +47,6 @@
 	return ret;
 }
 
-static int get_boolean(const char *buf, size_t count)
-{
-	if (count != 0) {
-		if (buf[0] == '1')
-			return 1;
-		if (buf[0] == '0')
-			return 0;
-		if (count >= 4 && memcmp(buf, "true", 4) == 0)
-			return 1;
-		if (count >= 5 && memcmp(buf, "false", 5) == 0)
-			return 0;
-		if (count >= 3 && memcmp(buf, "yes", 3) == 0)
-			return 1;
-		if (count >= 2 && memcmp(buf, "no", 2) == 0)
-			return 0;
-		if (count >= 2 && memcmp(buf, "on", 2) == 0)
-			return 1;
-		if (count >= 3 && memcmp(buf, "off", 3) == 0)
-			return 0;
-	}
-	return -EINVAL;
-}
-
 static ssize_t b43_attr_interfmode_show(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
@@ -155,82 +132,18 @@
 static DEVICE_ATTR(interference, 0644,
 		   b43_attr_interfmode_show, b43_attr_interfmode_store);
 
-static ssize_t b43_attr_preamble_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct b43_wldev *wldev = dev_to_b43_wldev(dev);
-	ssize_t count;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	mutex_lock(&wldev->wl->mutex);
-
-	if (wldev->short_preamble)
-		count =
-		    snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
-	else
-		count =
-		    snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
-
-	mutex_unlock(&wldev->wl->mutex);
-
-	return count;
-}
-
-static ssize_t b43_attr_preamble_store(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct b43_wldev *wldev = dev_to_b43_wldev(dev);
-	unsigned long flags;
-	int value;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	value = get_boolean(buf, count);
-	if (value < 0)
-		return value;
-	mutex_lock(&wldev->wl->mutex);
-	spin_lock_irqsave(&wldev->wl->irq_lock, flags);
-
-	wldev->short_preamble = !!value;
-
-	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
-	mutex_unlock(&wldev->wl->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(shortpreamble, 0644,
-		   b43_attr_preamble_show, b43_attr_preamble_store);
-
 int b43_sysfs_register(struct b43_wldev *wldev)
 {
 	struct device *dev = wldev->dev->dev;
-	int err;
 
 	B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
 
-	err = device_create_file(dev, &dev_attr_interference);
-	if (err)
-		goto out;
-	err = device_create_file(dev, &dev_attr_shortpreamble);
-	if (err)
-		goto err_remove_interfmode;
-
-      out:
-	return err;
-      err_remove_interfmode:
-	device_remove_file(dev, &dev_attr_interference);
-	goto out;
+	return device_create_file(dev, &dev_attr_interference);
 }
 
 void b43_sysfs_unregister(struct b43_wldev *wldev)
 {
 	struct device *dev = wldev->dev->dev;
 
-	device_remove_file(dev, &dev_attr_shortpreamble);
 	device_remove_file(dev, &dev_attr_interference);
 }
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 7caa26e..4014b6c 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -32,46 +32,48 @@
 #include "dma.h"
 
 
-/* Extract the bitrate out of a CCK PLCP header. */
-static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp)
+/* Extract the bitrate index out of a CCK PLCP header. */
+static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
 {
 	switch (plcp->raw[0]) {
 	case 0x0A:
-		return B43_CCK_RATE_1MB;
+		return 0;
 	case 0x14:
-		return B43_CCK_RATE_2MB;
+		return 1;
 	case 0x37:
-		return B43_CCK_RATE_5MB;
+		return 2;
 	case 0x6E:
-		return B43_CCK_RATE_11MB;
+		return 3;
 	}
 	B43_WARN_ON(1);
-	return 0;
+	return -1;
 }
 
-/* Extract the bitrate out of an OFDM PLCP header. */
-static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp)
+/* Extract the bitrate index out of an OFDM PLCP header. */
+static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
 {
+	int base = aphy ? 0 : 4;
+
 	switch (plcp->raw[0] & 0xF) {
 	case 0xB:
-		return B43_OFDM_RATE_6MB;
+		return base + 0;
 	case 0xF:
-		return B43_OFDM_RATE_9MB;
+		return base + 1;
 	case 0xA:
-		return B43_OFDM_RATE_12MB;
+		return base + 2;
 	case 0xE:
-		return B43_OFDM_RATE_18MB;
+		return base + 3;
 	case 0x9:
-		return B43_OFDM_RATE_24MB;
+		return base + 4;
 	case 0xD:
-		return B43_OFDM_RATE_36MB;
+		return base + 5;
 	case 0x8:
-		return B43_OFDM_RATE_48MB;
+		return base + 6;
 	case 0xC:
-		return B43_OFDM_RATE_54MB;
+		return base + 7;
 	}
 	B43_WARN_ON(1);
-	return 0;
+	return -1;
 }
 
 u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
@@ -191,6 +193,7 @@
 	    (const struct ieee80211_hdr *)fragment_data;
 	int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
 	u16 fctl = le16_to_cpu(wlhdr->frame_control);
+	struct ieee80211_rate *fbrate;
 	u8 rate, rate_fb;
 	int rate_ofdm, rate_fb_ofdm;
 	unsigned int plcp_fragment_len;
@@ -200,9 +203,11 @@
 
 	memset(txhdr, 0, sizeof(*txhdr));
 
-	rate = txctl->tx_rate;
+	WARN_ON(!txctl->tx_rate);
+	rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB;
 	rate_ofdm = b43_is_ofdm_rate(rate);
-	rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
+	fbrate = txctl->alt_retry_rate ? : txctl->tx_rate;
+	rate_fb = fbrate->hw_value;
 	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
 
 	if (rate_ofdm)
@@ -221,11 +226,10 @@
 		 * use the original dur_id field. */
 		txhdr->dur_fb = wlhdr->duration_id;
 	} else {
-		int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
 		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
 								 txctl->vif,
 								 fragment_len,
-								 fbrate_base100kbps);
+								 fbrate);
 	}
 
 	plcp_fragment_len = fragment_len + FCS_LEN;
@@ -287,7 +291,7 @@
 		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
 	else
 		phy_ctl |= B43_TXH_PHY_ENC_CCK;
-	if (dev->short_preamble)
+	if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
 		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
 
 	switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
@@ -332,7 +336,8 @@
 		int rts_rate_ofdm, rts_rate_fb_ofdm;
 		struct b43_plcp_hdr6 *plcp;
 
-		rts_rate = txctl->rts_cts_rate;
+		WARN_ON(!txctl->rts_cts_rate);
+		rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
 		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
 		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
 		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
@@ -506,6 +511,7 @@
 	u16 phystat0, phystat3, chanstat, mactime;
 	u32 macstat;
 	u16 chanid;
+	u16 phytype;
 	u8 jssi;
 	int padding;
 
@@ -518,6 +524,7 @@
 	macstat = le32_to_cpu(rxhdr->mac_status);
 	mactime = le16_to_cpu(rxhdr->mac_time);
 	chanstat = le16_to_cpu(rxhdr->channel);
+	phytype = chanstat & B43_RX_CHAN_PHYTYPE;
 
 	if (macstat & B43_RX_MAC_FCSERR)
 		dev->wl->ieee_stats.dot11FCSErrorCount++;
@@ -575,9 +582,10 @@
 	/* the next line looks wrong, but is what mac80211 wants */
 	status.signal = (jssi * 100) / B43_RX_MAX_SSI;
 	if (phystat0 & B43_RX_PHYST0_OFDM)
-		status.rate = b43_plcp_get_bitrate_ofdm(plcp);
+		status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
+						phytype == B43_PHYTYPE_A);
 	else
-		status.rate = b43_plcp_get_bitrate_cck(plcp);
+		status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
 	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
 
 	/*
@@ -601,29 +609,28 @@
 	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
 	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
 	case B43_PHYTYPE_A:
-		status.phymode = MODE_IEEE80211A;
+		status.band = IEEE80211_BAND_5GHZ;
 		B43_WARN_ON(1);
 		/* FIXME: We don't really know which value the "chanid" contains.
 		 *        So the following assignment might be wrong. */
-		status.channel = chanid;
-		status.freq = b43_channel_to_freq_5ghz(status.channel);
+		status.freq = b43_channel_to_freq_5ghz(chanid);
 		break;
 	case B43_PHYTYPE_G:
-		status.phymode = MODE_IEEE80211G;
+		status.band = IEEE80211_BAND_2GHZ;
 		/* chanid is the radio channel cookie value as used
 		 * to tune the radio. */
 		status.freq = chanid + 2400;
-		status.channel = b43_freq_to_channel_2ghz(status.freq);
 		break;
 	case B43_PHYTYPE_N:
-		status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/;
 		/* chanid is the SHM channel cookie. Which is the plain
 		 * channel number in b43. */
-		status.channel = chanid;
-		if (chanstat & B43_RX_CHAN_5GHZ)
-			status.freq = b43_freq_to_channel_5ghz(status.freq);
-		else
-			status.freq = b43_freq_to_channel_2ghz(status.freq);
+		if (chanstat & B43_RX_CHAN_5GHZ) {
+			status.band = IEEE80211_BAND_5GHZ;
+			status.freq = b43_freq_to_channel_5ghz(chanid);
+		} else {
+			status.band = IEEE80211_BAND_2GHZ;
+			status.freq = b43_freq_to_channel_2ghz(chanid);
+		}
 		break;
 	default:
 		B43_WARN_ON(1);
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 93d45b7..5f217d6 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -392,10 +392,6 @@
 	u8 possible_phymodes;
 	/* GMODE bit enabled in MACCTL? */
 	bool gmode;
-	/* Possible ieee80211 subsystem hwmodes for this PHY.
-	 * Which mode is selected, depends on thr GMODE enabled bit */
-#define B43legacy_MAX_PHYHWMODES	2
-	struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES];
 
 	/* Analog Type */
 	u8 analog;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c39de42..d2a72a2 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -95,28 +95,29 @@
  * data in there. This data is the same for all devices, so we don't
  * get concurrency issues */
 #define RATETAB_ENT(_rateid, _flags) \
-	{							\
-		.rate	= B43legacy_RATE_TO_100KBPS(_rateid),	\
-		.val	= (_rateid),				\
-		.val2	= (_rateid),				\
-		.flags	= (_flags),				\
+	{								\
+		.bitrate	= B43legacy_RATE_TO_100KBPS(_rateid),	\
+		.hw_value	= (_rateid),				\
+		.flags		= (_flags),				\
 	}
+/*
+ * NOTE: When changing this, sync with xmit.c's
+ *	 b43legacy_plcp_get_bitrate_idx_* functions!
+ */
 static struct ieee80211_rate __b43legacy_ratetable[] = {
-	RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK),
-	RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
-	RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
-	RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
-	RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
-	RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
+	RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
+	RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
 };
-#define b43legacy_a_ratetable		(__b43legacy_ratetable + 4)
-#define b43legacy_a_ratetable_size	8
 #define b43legacy_b_ratetable		(__b43legacy_ratetable + 0)
 #define b43legacy_b_ratetable_size	4
 #define b43legacy_g_ratetable		(__b43legacy_ratetable + 0)
@@ -124,14 +125,8 @@
 
 #define CHANTAB_ENT(_chanid, _freq) \
 	{							\
-		.chan	= (_chanid),				\
-		.freq	= (_freq),				\
-		.val	= (_chanid),				\
-		.flag	= IEEE80211_CHAN_W_SCAN |		\
-			  IEEE80211_CHAN_W_ACTIVE_SCAN |	\
-			  IEEE80211_CHAN_W_IBSS,		\
-		.power_level	= 0x0A,				\
-		.antenna_max	= 0xFF,				\
+		.center_freq	= (_freq),			\
+		.hw_value	= (_chanid),			\
 	}
 static struct ieee80211_channel b43legacy_bg_chantable[] = {
 	CHANTAB_ENT(1, 2412),
@@ -149,7 +144,20 @@
 	CHANTAB_ENT(13, 2472),
 	CHANTAB_ENT(14, 2484),
 };
-#define b43legacy_bg_chantable_size	ARRAY_SIZE(b43legacy_bg_chantable)
+
+static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
+	.channels = b43legacy_bg_chantable,
+	.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
+	.bitrates = b43legacy_b_ratetable,
+	.n_bitrates = b43legacy_b_ratetable_size,
+};
+
+static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
+	.channels = b43legacy_bg_chantable,
+	.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
+	.bitrates = b43legacy_g_ratetable,
+	.n_bitrates = b43legacy_g_ratetable_size,
+};
 
 static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
 static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
@@ -969,18 +977,18 @@
 
 static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
 					    u16 shm_offset, u16 size,
-					    u8 rate)
+					    struct ieee80211_rate *rate)
 {
 	struct b43legacy_plcp_hdr4 plcp;
 	u32 tmp;
 	__le16 dur;
 
 	plcp.data = 0;
-	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
+	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
 					       dev->wl->vif,
 					       size,
-					       B43legacy_RATE_TO_100KBPS(rate));
+					       rate);
 	/* Write PLCP in two parts and timing for packet transfer */
 	tmp = le32_to_cpu(plcp.data);
 	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
@@ -998,7 +1006,8 @@
  * 3) Stripping TIM
  */
 static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
-					 u16 *dest_size, u8 rate)
+					 u16 *dest_size,
+					 struct ieee80211_rate *rate)
 {
 	const u8 *src_data;
 	u8 *dest_data;
@@ -1046,7 +1055,7 @@
 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
 					       dev->wl->vif,
 					       *dest_size,
-					       B43legacy_RATE_TO_100KBPS(rate));
+					       rate);
 	hdr->duration_id = dur;
 
 	return dest_data;
@@ -1054,7 +1063,8 @@
 
 static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
 						u16 ram_offset,
-						u16 shm_size_offset, u8 rate)
+						u16 shm_size_offset,
+						struct ieee80211_rate *rate)
 {
 	u8 *probe_resp_data;
 	u16 size;
@@ -1069,19 +1079,19 @@
 	 * all possible basic rates
 	 */
 	b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
-					B43legacy_CCK_RATE_1MB);
+					&b43legacy_b_ratetable[0]);
 	b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
-					B43legacy_CCK_RATE_2MB);
+					&b43legacy_b_ratetable[1]);
 	b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
-					B43legacy_CCK_RATE_5MB);
+					&b43legacy_b_ratetable[2]);
 	b43legacy_write_probe_resp_plcp(dev, 0x350, size,
-					B43legacy_CCK_RATE_11MB);
+					&b43legacy_b_ratetable[3]);
 
 	size = min((size_t)size,
 		   0x200 - sizeof(struct b43legacy_plcp_hdr6));
 	b43legacy_write_template_common(dev, probe_resp_data,
 					size, ram_offset,
-					shm_size_offset, rate);
+					shm_size_offset, rate->bitrate);
 	kfree(probe_resp_data);
 }
 
@@ -1106,7 +1116,7 @@
 	b43legacy_write_beacon_template(dev, 0x468, 0x1A,
 					B43legacy_CCK_RATE_1MB);
 	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
-					    B43legacy_CCK_RATE_11MB);
+					    &b43legacy_b_ratetable[0]);
 
 	status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 	status |= 0x03;
@@ -2550,14 +2560,16 @@
 	antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
 
 	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	phy = &dev->phy;
 
 	/* Switch the PHY mode (if necessary). */
-	switch (conf->phymode) {
-	case MODE_IEEE80211B:
-		new_phymode = B43legacy_PHYMODE_B;
-		break;
-	case MODE_IEEE80211G:
-		new_phymode = B43legacy_PHYMODE_G;
+	switch (conf->channel->band) {
+	case IEEE80211_BAND_2GHZ:
+		if (phy->type == B43legacy_PHYTYPE_B)
+			new_phymode = B43legacy_PHYMODE_B;
+		else
+			new_phymode = B43legacy_PHYMODE_G;
 		break;
 	default:
 		B43legacy_WARN_ON(1);
@@ -2565,8 +2577,6 @@
 	err = b43legacy_switch_phymode(wl, new_phymode);
 	if (err)
 		goto out_unlock_mutex;
-	dev = wl->current_dev;
-	phy = &dev->phy;
 
 	/* Disable IRQs while reconfiguring the device.
 	 * This makes it possible to drop the spinlock throughout
@@ -2582,8 +2592,8 @@
 
 	/* Switch to the requested channel.
 	 * The firmware takes care of races with the TX handler. */
-	if (conf->channel_val != phy->channel)
-		b43legacy_radio_selectchannel(dev, conf->channel_val, 0);
+	if (conf->channel->hw_value != phy->channel)
+		b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
 
 	/* Enable/Disable ShortSlot timing. */
 	if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
@@ -3398,48 +3408,19 @@
 				 int have_gphy)
 {
 	struct ieee80211_hw *hw = dev->wl->hw;
-	struct ieee80211_hw_mode *mode;
 	struct b43legacy_phy *phy = &dev->phy;
-	int cnt = 0;
-	int err;
 
 	phy->possible_phymodes = 0;
-	for (; 1; cnt++) {
-		if (have_bphy) {
-			B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
-			mode = &phy->hwmodes[cnt];
+	if (have_bphy) {
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+			&b43legacy_band_2GHz_BPHY;
+		phy->possible_phymodes |= B43legacy_PHYMODE_B;
+	}
 
-			mode->mode = MODE_IEEE80211B;
-			mode->num_channels = b43legacy_bg_chantable_size;
-			mode->channels = b43legacy_bg_chantable;
-			mode->num_rates = b43legacy_b_ratetable_size;
-			mode->rates = b43legacy_b_ratetable;
-			err = ieee80211_register_hwmode(hw, mode);
-			if (err)
-				return err;
-
-			phy->possible_phymodes |= B43legacy_PHYMODE_B;
-			have_bphy = 0;
-			continue;
-		}
-		if (have_gphy) {
-			B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
-			mode = &phy->hwmodes[cnt];
-
-			mode->mode = MODE_IEEE80211G;
-			mode->num_channels = b43legacy_bg_chantable_size;
-			mode->channels = b43legacy_bg_chantable;
-			mode->num_rates = b43legacy_g_ratetable_size;
-			mode->rates = b43legacy_g_ratetable;
-			err = ieee80211_register_hwmode(hw, mode);
-			if (err)
-				return err;
-
-			phy->possible_phymodes |= B43legacy_PHYMODE_G;
-			have_gphy = 0;
-			continue;
-		}
-		break;
+	if (have_gphy) {
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+			&b43legacy_band_2GHz_GPHY;
+		phy->possible_phymodes |= B43legacy_PHYMODE_G;
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index d84408a..47e130e 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -37,45 +37,48 @@
 
 
 /* Extract the bitrate out of a CCK PLCP header. */
-static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp)
+static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
 {
 	switch (plcp->raw[0]) {
 	case 0x0A:
-		return B43legacy_CCK_RATE_1MB;
+		return 0;
 	case 0x14:
-		return B43legacy_CCK_RATE_2MB;
+		return 1;
 	case 0x37:
-		return B43legacy_CCK_RATE_5MB;
+		return 2;
 	case 0x6E:
-		return B43legacy_CCK_RATE_11MB;
+		return 3;
 	}
 	B43legacy_BUG_ON(1);
-	return 0;
+	return -1;
 }
 
 /* Extract the bitrate out of an OFDM PLCP header. */
-static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp)
+static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
+					      bool aphy)
 {
+	int base = aphy ? 0 : 4;
+
 	switch (plcp->raw[0] & 0xF) {
 	case 0xB:
-		return B43legacy_OFDM_RATE_6MB;
+		return base + 0;
 	case 0xF:
-		return B43legacy_OFDM_RATE_9MB;
+		return base + 1;
 	case 0xA:
-		return B43legacy_OFDM_RATE_12MB;
+		return base + 2;
 	case 0xE:
-		return B43legacy_OFDM_RATE_18MB;
+		return base + 3;
 	case 0x9:
-		return B43legacy_OFDM_RATE_24MB;
+		return base + 4;
 	case 0xD:
-		return B43legacy_OFDM_RATE_36MB;
+		return base + 5;
 	case 0x8:
-		return B43legacy_OFDM_RATE_48MB;
+		return base + 6;
 	case 0xC:
-		return B43legacy_OFDM_RATE_54MB;
+		return base + 7;
 	}
 	B43legacy_BUG_ON(1);
-	return 0;
+	return -1;
 }
 
 u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
@@ -192,7 +195,7 @@
 	int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
 	u16 fctl;
 	u8 rate;
-	u8 rate_fb;
+	struct ieee80211_rate *rate_fb;
 	int rate_ofdm;
 	int rate_fb_ofdm;
 	unsigned int plcp_fragment_len;
@@ -204,16 +207,16 @@
 
 	memset(txhdr, 0, sizeof(*txhdr));
 
-	rate = txctl->tx_rate;
+	rate = txctl->tx_rate->hw_value;
 	rate_ofdm = b43legacy_is_ofdm_rate(rate);
-	rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
-	rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb);
+	rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate;
+	rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
 
 	txhdr->mac_frame_ctl = wlhdr->frame_control;
 	memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
 
 	/* Calculate duration for fallback rate */
-	if ((rate_fb == rate) ||
+	if ((rate_fb->hw_value == rate) ||
 	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
 	    (wlhdr->duration_id == cpu_to_le16(0))) {
 		/* If the fallback rate equals the normal rate or the
@@ -221,11 +224,10 @@
 		 * use the original dur_id field. */
 		txhdr->dur_fb = wlhdr->duration_id;
 	} else {
-		int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
 		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
 							 txctl->vif,
 							 fragment_len,
-							 fbrate_base100kbps);
+							 rate_fb);
 	}
 
 	plcp_fragment_len = fragment_len + FCS_LEN;
@@ -266,7 +268,7 @@
 				    rate);
 	b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
 				    (&txhdr->plcp_fb), plcp_fragment_len,
-				    rate_fb);
+				    rate_fb->hw_value);
 
 	/* PHY TX Control word */
 	if (rate_ofdm)
@@ -310,7 +312,7 @@
 		int rts_rate_ofdm;
 		int rts_rate_fb_ofdm;
 
-		rts_rate = txctl->rts_cts_rate;
+		rts_rate = txctl->rts_cts_rate->hw_value;
 		rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
 		rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
 		rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
@@ -536,10 +538,11 @@
 				      (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
 	status.noise = dev->stats.link_noise;
 	status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
+	/* change to support A PHY */
 	if (phystat0 & B43legacy_RX_PHYST0_OFDM)
-		status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp);
+		status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
 	else
-		status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
+		status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
 	status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
 
 	/*
@@ -564,14 +567,9 @@
 		  B43legacy_RX_CHAN_ID_SHIFT;
 	switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
 	case B43legacy_PHYTYPE_B:
-		status.phymode = MODE_IEEE80211B;
-		status.freq = chanid + 2400;
-		status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
-		break;
 	case B43legacy_PHYTYPE_G:
-		status.phymode = MODE_IEEE80211G;
+		status.band = IEEE80211_BAND_2GHZ;
 		status.freq = chanid + 2400;
-		status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
 		break;
 	default:
 		b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 80d31ae..f018ce4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -100,14 +100,6 @@
 	{-89, IWL_RATE_6M_INDEX}
 };
 
-static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = {
-	{-86, IWL_RATE_11M_INDEX},
-	{-88, IWL_RATE_5M_INDEX},
-	{-90, IWL_RATE_2M_INDEX},
-	{-92, IWL_RATE_1M_INDEX}
-
-};
-
 static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
 	{-60, IWL_RATE_54M_INDEX},
 	{-64, IWL_RATE_48M_INDEX},
@@ -129,7 +121,7 @@
 #define IWL_RATE_MIN_SUCCESS_TH       8
 #define IWL_RATE_DECREASE_TH       1920
 
-static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
+static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
 {
 	u32 index = 0;
 	u32 table_size = 0;
@@ -138,21 +130,19 @@
 	if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
 		rssi = IWL_MIN_RSSI_VAL;
 
-	switch (mode) {
-	case MODE_IEEE80211G:
+	switch (band) {
+	case IEEE80211_BAND_2GHZ:
 		tpt_table = iwl3945_tpt_table_g;
 		table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
 		break;
 
-	case MODE_IEEE80211A:
+	case IEEE80211_BAND_5GHZ:
 		tpt_table = iwl3945_tpt_table_a;
 		table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
 		break;
 
 	default:
-	case MODE_IEEE80211B:
-		tpt_table = iwl3945_tpt_table_b;
-		table_size = ARRAY_SIZE(iwl3945_tpt_table_b);
+		BUG();
 		break;
 	}
 
@@ -340,17 +330,17 @@
 	 * after assoc.. */
 
 	for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
-		if (sta->supp_rates & (1 << i)) {
-			sta->txrate = i;
+		if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
+			sta->txrate_idx = i;
 			break;
 		}
 	}
 
-	sta->last_txrate = sta->txrate;
+	sta->last_txrate_idx = sta->txrate_idx;
 
-	/* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
-        if (local->hw.conf.phymode == MODE_IEEE80211A)
-                sta->last_txrate += IWL_FIRST_OFDM_RATE;
+	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
+	if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
+		sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
 
 	IWL_DEBUG_RATE("leave\n");
 }
@@ -429,17 +419,19 @@
 {
 	int next_rate = iwl3945_get_prev_ieee_rate(rate);
 
-	switch (priv->phymode) {
-	case MODE_IEEE80211A:
+	switch (priv->band) {
+	case IEEE80211_BAND_5GHZ:
 		if (rate == IWL_RATE_12M_INDEX)
 			next_rate = IWL_RATE_9M_INDEX;
 		else if (rate == IWL_RATE_6M_INDEX)
 			next_rate = IWL_RATE_6M_INDEX;
 		break;
+/* XXX cannot be invoked in current mac80211 so not a regression
 	case MODE_IEEE80211B:
 		if (rate == IWL_RATE_11M_INDEX_TABLE)
 			next_rate = IWL_RATE_5M_INDEX_TABLE;
 		break;
+ */
 	default:
 		break;
 	}
@@ -465,15 +457,17 @@
 	struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct iwl3945_rs_sta *rs_sta;
+	struct ieee80211_supported_band *sband;
+
+	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
 	IWL_DEBUG_RATE("enter\n");
 
 	retries = tx_resp->retry_count;
 
-	first_index = tx_resp->control.tx_rate;
+	first_index = &sband->bitrates[0] - tx_resp->control.tx_rate;
 	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
-		IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n",
-			       tx_resp->control.tx_rate, first_index);
+		IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
 		return;
 	}
 
@@ -561,14 +555,14 @@
 }
 
 static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
-				 u8 index, u16 rate_mask, int phymode)
+				 u8 index, u16 rate_mask, enum ieee80211_band band)
 {
 	u8 high = IWL_RATE_INVALID;
 	u8 low = IWL_RATE_INVALID;
 
 	/* 802.11A walks to the next literal adjacent rate in
 	 * the rate table */
-	if (unlikely(phymode == MODE_IEEE80211A)) {
+	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
 		int i;
 		u32 mask;
 
@@ -639,7 +633,8 @@
  *
  */
 static void rs_get_rate(void *priv_rate, struct net_device *dev,
-			struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+			struct ieee80211_supported_band *band,
+			struct sk_buff *skb,
 			struct rate_selection *sel)
 {
 	u8 low = IWL_RATE_INVALID;
@@ -672,16 +667,16 @@
 	    is_multicast_ether_addr(hdr->addr1) ||
 	    !sta || !sta->rate_ctrl_priv) {
 		IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
-		sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+		sel->rate = rate_lowest(local, band, sta);
 		if (sta)
 			sta_info_put(sta);
 		return;
 	}
 
-	rate_mask = sta->supp_rates;
-	index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
+	rate_mask = sta->supp_rates[band->band];
+	index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
 
-	if (priv->phymode == (u8) MODE_IEEE80211A)
+	if (priv->band == IEEE80211_BAND_5GHZ)
 		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
 
 	rs_sta = (void *)sta->rate_ctrl_priv;
@@ -732,7 +727,7 @@
 	current_tpt = window->average_tpt;
 
 	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
-					 local->hw.conf.phymode);
+					     band->band);
 	low = high_low & 0xff;
 	high = (high_low >> 8) & 0xff;
 
@@ -810,11 +805,11 @@
 
  out:
 
-	sta->last_txrate = index;
-	if (priv->phymode == (u8) MODE_IEEE80211A)
-		sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
+	sta->last_txrate_idx = index;
+	if (priv->band == IEEE80211_BAND_5GHZ)
+		sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
 	else
-		sta->txrate = sta->last_txrate;
+		sta->txrate_idx = sta->last_txrate_idx;
 
 	sta_info_put(sta);
 
@@ -945,8 +940,9 @@
 	spin_lock_irqsave(&rs_sta->lock, flags);
 
 	rs_sta->tgg = 0;
-	switch (priv->phymode) {
-	case MODE_IEEE80211G:
+	switch (priv->band) {
+	case IEEE80211_BAND_2GHZ:
+		/* TODO: this always does G, not a regression */
 		if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
 			rs_sta->tgg = 1;
 			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
@@ -954,14 +950,11 @@
 			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
 		break;
 
-	case MODE_IEEE80211A:
+	case IEEE80211_BAND_5GHZ:
 		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
 		break;
-
-	default:
-		IWL_WARNING("Invalid phymode.  Defaulting to 802.11b\n");
-	case MODE_IEEE80211B:
-		rs_sta->expected_tpt = iwl3945_expected_tpt_b;
+	case IEEE80211_NUM_BANDS:
+		BUG();
 		break;
 	}
 
@@ -974,8 +967,7 @@
 
 	IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);
 
-	rs_sta->start_rate =
-			iwl3945_get_rate_index_by_rssi(rssi, priv->phymode);
+	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
 
 	IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
 		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 8d4d91d..50d927b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -247,7 +247,7 @@
 	 * the information provided in the skb from the hardware */
 	s8 signal = stats->ssi;
 	s8 noise = 0;
-	int rate = stats->rate;
+	int rate = stats->rate_idx;
 	u64 tsf = stats->mactime;
 	__le16 phy_flags_hw = rx_hdr->phy_flags;
 
@@ -315,7 +315,6 @@
 					  IEEE80211_CHAN_2GHZ),
 			      &iwl3945_rt->rt_chbitmask);
 
-	rate = iwl3945_rate_index_from_plcp(rate);
 	if (rate == -1)
 		iwl3945_rt->rt_rate = 0;
 	else
@@ -387,11 +386,10 @@
 	struct ieee80211_rx_status stats = {
 		.mactime = le64_to_cpu(rx_end->timestamp),
 		.freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)),
-		.channel = le16_to_cpu(rx_hdr->channel),
-		.phymode = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-		MODE_IEEE80211G : MODE_IEEE80211A,
+		.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+		IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ,
 		.antenna = 0,
-		.rate = rx_hdr->rate,
+		.rate_idx = iwl3945_rate_index_from_plcp(rx_hdr->rate),
 		.flag = 0,
 	};
 	u8 network_packet;
@@ -450,8 +448,6 @@
 			stats.ssi, stats.noise, stats.signal,
 			rx_stats_sig_avg, rx_stats_noise_diff);
 
-	stats.freq = ieee80211chan2mhz(stats.channel);
-
 	/* can be covered by iwl3945_report_frame() in most cases */
 /*      IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */
 
@@ -464,8 +460,9 @@
 		IWL_DEBUG_STATS
 		    ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n",
 		     network_packet ? '*' : ' ',
-		     stats.channel, stats.ssi, stats.ssi,
-		     stats.ssi, stats.rate);
+		     le16_to_cpu(rx_hdr->channel),
+		     stats.ssi, stats.ssi,
+		     stats.ssi, stats.rate_idx);
 
 	if (iwl3945_debug_level & (IWL_DL_RX))
 		/* Set "1" to report good data frames in groups of 100 */
@@ -689,7 +686,7 @@
 			      struct ieee80211_hdr *hdr, int sta_id, int tx_id)
 {
 	unsigned long flags;
-	u16 rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
+	u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
 	u16 rate_mask;
 	int rate;
 	u8 rts_retry_limit;
@@ -1552,14 +1549,14 @@
 		.channel = priv->active_rxon.channel,
 	};
 
-	txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1;
+	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
 	ch_info = iwl3945_get_channel_info(priv,
-				       priv->phymode,
+				       priv->band,
 				       le16_to_cpu(priv->active_rxon.channel));
 	if (!ch_info) {
 		IWL_ERROR
 		    ("Failed to get channel info for channel %d [%d]\n",
-		     le16_to_cpu(priv->active_rxon.channel), priv->phymode);
+		     le16_to_cpu(priv->active_rxon.channel), priv->band);
 		return -EINVAL;
 	}
 
@@ -2241,8 +2238,8 @@
 		table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
 	}
 
-	switch (priv->phymode) {
-	case MODE_IEEE80211A:
+	switch (priv->band) {
+	case IEEE80211_BAND_5GHZ:
 		IWL_DEBUG_RATE("Select A mode rate scale\n");
 		/* If one of the following CCK rates is used,
 		 * have it fall back to the 6M OFDM rate */
@@ -2257,8 +2254,8 @@
 		    iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
 		break;
 
-	case MODE_IEEE80211B:
-		IWL_DEBUG_RATE("Select B mode rate scale\n");
+	case IEEE80211_BAND_2GHZ:
+		IWL_DEBUG_RATE("Select B/G mode rate scale\n");
 		/* If an OFDM rate is used, have it fall back to the
 		 * 1M CCK rates */
 		for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
@@ -2269,7 +2266,7 @@
 		break;
 
 	default:
-		IWL_DEBUG_RATE("Select G mode rate scale\n");
+		WARN_ON(1);
 		break;
 	}
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 1da14f9..1beb5b6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -195,7 +195,7 @@
 
 	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
 	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
-	u8 phymode;	  /* MODE_IEEE80211{A,B,G} */
+	enum ieee80211_band band;
 
 	/* Radio/DSP gain settings for each "normal" data Tx rate.
 	 * These include, in addition to RF and DSP gain, a few fields for
@@ -699,14 +699,14 @@
 	struct list_head free_frames;
 	int frames_count;
 
-	u8 phymode;
+	enum ieee80211_band band;
 	int alloc_rxb_skb;
 	bool add_radiotap;
 
 	void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
 				       struct iwl3945_rx_mem_buffer *rxb);
 
-	const struct ieee80211_hw_mode *modes;
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
 
 #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
 	/* spectrum measurement report caching */
@@ -937,13 +937,12 @@
 
 static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info)
 {
-	return ch_info->phymode == MODE_IEEE80211A;
+	return ch_info->band == IEEE80211_BAND_5GHZ;
 }
 
 static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info)
 {
-	return ((ch_info->phymode == MODE_IEEE80211B) ||
-		(ch_info->phymode == MODE_IEEE80211G));
+	return ch_info->band == IEEE80211_BAND_2GHZ;
 }
 
 static inline int is_channel_passive(const struct iwl3945_channel_info *ch)
@@ -967,7 +966,7 @@
 }
 
 extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
-	const struct iwl3945_priv *priv, int phymode, u16 channel);
+	const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
 
 /* Requires full declaration of iwl3945_priv before including */
 #include "iwl-3945-io.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 660671f..48a6a85 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -139,7 +139,7 @@
 	u8 valid_antenna;
 	u8 is_green;
 	u8 is_dup;
-	u8 phymode;
+	enum ieee80211_band band;
 	u8 ibss_sta_added;
 
 	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
@@ -563,7 +563,8 @@
  * fill "search" or "active" tx mode table.
  */
 static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
-				    int phymode, struct iwl4965_scale_tbl_info *tbl,
+				    enum ieee80211_band band,
+				    struct iwl4965_scale_tbl_info *tbl,
 				    int *rate_idx)
 {
 	int index;
@@ -588,7 +589,7 @@
 			tbl->lq_type = LQ_NONE;
 		else {
 
-			if (phymode == MODE_IEEE80211A)
+			if (band == IEEE80211_BAND_5GHZ)
 				tbl->lq_type = LQ_A;
 			else
 				tbl->lq_type = LQ_G;
@@ -766,7 +767,7 @@
 	if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
 		switch_to_legacy = 1;
 		scale_index = rs_ht_to_legacy[scale_index];
-		if (lq_sta->phymode == MODE_IEEE80211A)
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
 			tbl->lq_type = LQ_A;
 		else
 			tbl->lq_type = LQ_G;
@@ -784,7 +785,7 @@
 	/* Mask with station rate restriction */
 	if (is_legacy(tbl->lq_type)) {
 		/* supp_rates has no CCK bits in A mode */
-		if (lq_sta->phymode == (u8) MODE_IEEE80211A)
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
 			rate_mask  = (u16)(rate_mask &
 			   (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
 		else
@@ -883,9 +884,9 @@
 	search_win = (struct iwl4965_rate_scale_data *)
 	    &(search_tbl->win[0]);
 
-	tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
+	tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value;
 
-	rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
+	rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
 				  &tbl_type, &rs_index);
 	if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) {
 		IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n",
@@ -918,7 +919,7 @@
 		 * Each tx attempt steps one entry deeper in the rate table. */
 		tx_mcs.rate_n_flags =
 		    le32_to_cpu(table->rs_table[index].rate_n_flags);
-		rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
+		rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
 					  &tbl_type, &rs_index);
 
 		/* If type matches "search" table,
@@ -959,12 +960,12 @@
 	 * else look up the rate that was, finally, successful.
 	 */
 	if (!tx_resp->retry_count)
-		tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
+		tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value;
 	else
 		tx_mcs.rate_n_flags =
 			le32_to_cpu(table->rs_table[index].rate_n_flags);
 
-	rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
+	rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
 				  &tbl_type, &rs_index);
 
 	/* Update frame history window with "success" if Tx got ACKed ... */
@@ -1801,7 +1802,7 @@
 	is_green = lq_sta->is_green;
 
 	/* current tx rate */
-	index = sta->last_txrate;
+	index = sta->last_txrate_idx;
 
 	IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
 		       tbl->lq_type);
@@ -1814,7 +1815,7 @@
 
 	/* mask with station rate restriction */
 	if (is_legacy(tbl->lq_type)) {
-		if (lq_sta->phymode == (u8) MODE_IEEE80211A)
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
 			/* supp_rates has no CCK bits in A mode */
 			rate_scale_index_msk = (u16) (rate_mask &
 				(lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
@@ -2134,15 +2135,15 @@
 out:
 	rs_mcs_from_tbl(&tbl->current_rate, tbl, index, is_green);
 	i = index;
-	sta->last_txrate = i;
+	sta->last_txrate_idx = i;
 
-	/* sta->txrate is an index to A mode rates which start
+	/* sta->txrate_idx is an index to A mode rates which start
 	 * at IWL_FIRST_OFDM_RATE
 	 */
-	if (lq_sta->phymode == (u8) MODE_IEEE80211A)
-		sta->txrate = i - IWL_FIRST_OFDM_RATE;
+	if (lq_sta->band == IEEE80211_BAND_5GHZ)
+		sta->txrate_idx = i - IWL_FIRST_OFDM_RATE;
 	else
-		sta->txrate = i;
+		sta->txrate_idx = i;
 
 	return;
 }
@@ -2164,7 +2165,7 @@
 		goto out;
 
 	lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
-	i = sta->last_txrate;
+	i = sta->last_txrate_idx;
 
 	if ((lq_sta->lq.sta_id == 0xff) &&
 	    (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
@@ -2188,7 +2189,7 @@
 		mcs_rate.rate_n_flags |= RATE_MCS_CCK_MSK;
 
 	tbl->antenna_type = ANT_AUX;
-	rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx);
+	rs_get_tbl_info_from_mcs(&mcs_rate, priv->band, tbl, &rate_idx);
 	if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type))
 	    rs_toggle_antenna(&mcs_rate, tbl);
 
@@ -2202,7 +2203,8 @@
 }
 
 static void rs_get_rate(void *priv_rate, struct net_device *dev,
-			struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+			struct ieee80211_supported_band *sband,
+			struct sk_buff *skb,
 			struct rate_selection *sel)
 {
 
@@ -2224,14 +2226,14 @@
 	fc = le16_to_cpu(hdr->frame_control);
 	if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
 	    !sta || !sta->rate_ctrl_priv) {
-		sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+		sel->rate = rate_lowest(local, sband, sta);
 		if (sta)
 			sta_info_put(sta);
 		return;
 	}
 
 	lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
-	i = sta->last_txrate;
+	i = sta->last_txrate_idx;
 
 	if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
 	    !lq_sta->ibss_sta_added) {
@@ -2256,7 +2258,7 @@
 
  done:
 	if ((i < 0) || (i > IWL_RATE_COUNT)) {
-		sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+		sel->rate = rate_lowest(local, sband, sta);
 		return;
 	}
 	sta_info_put(sta);
@@ -2291,13 +2293,15 @@
 {
 	int i, j;
 	struct ieee80211_conf *conf = &local->hw.conf;
-	struct ieee80211_hw_mode *mode = local->oper_hw_mode;
+	struct ieee80211_supported_band *sband;
 	struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
 	struct iwl4965_lq_sta *lq_sta = priv_sta;
 
+	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
 	lq_sta->flush_timer = 0;
-	lq_sta->supp_rates = sta->supp_rates;
-	sta->txrate = 3;
+	lq_sta->supp_rates = sta->supp_rates[sband->band];
+	sta->txrate_idx = 3;
 	for (j = 0; j < LQ_SIZE; j++)
 		for (i = 0; i < IWL_RATE_COUNT; i++)
 			rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
@@ -2332,15 +2336,15 @@
 	}
 
 	/* Find highest tx rate supported by hardware and destination station */
-	for (i = 0; i < mode->num_rates; i++) {
-		if ((sta->supp_rates & BIT(i)) &&
-		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
-			sta->txrate = i;
-	}
-	sta->last_txrate = sta->txrate;
+	for (i = 0; i < sband->n_bitrates; i++)
+		if (sta->supp_rates[sband->band] & BIT(i))
+			sta->txrate_idx = i;
+
+	sta->last_txrate_idx = sta->txrate_idx;
+	/* WTF is with this bogus comment? A doesn't have cck rates */
 	/* For MODE_IEEE80211A, cck rates are at end of rate table */
-	if (local->hw.conf.phymode == MODE_IEEE80211A)
-		sta->last_txrate += IWL_FIRST_OFDM_RATE;
+	if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
+		sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
 
 	lq_sta->is_dup = 0;
 	lq_sta->valid_antenna = priv->valid_antenna;
@@ -2349,7 +2353,7 @@
 	lq_sta->active_rate = priv->active_rate;
 	lq_sta->active_rate &= ~(0x1000);
 	lq_sta->active_rate_basic = priv->active_rate_basic;
-	lq_sta->phymode = priv->phymode;
+	lq_sta->band = priv->band;
 #ifdef CONFIG_IWL4965_HT
 	/*
 	 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
@@ -2401,7 +2405,7 @@
 	rs_dbgfs_set_mcs(lq_sta, tx_mcs, index);
 
 	/* Interpret rate_n_flags */
-	rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode,
+	rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->band,
 				  &tbl_type, &rate_idx);
 
 	/* How many times should we repeat the initial rate? */
@@ -2455,7 +2459,7 @@
 			index++;
 		}
 
-		rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type,
+		rs_get_tbl_info_from_mcs(&new_rate, lq_sta->band, &tbl_type,
 						&rate_idx);
 
 		/* Indicate to uCode which entries might be MIMO.
@@ -2542,7 +2546,7 @@
 {
 	u32 base_rate;
 
-	if (lq_sta->phymode == (u8) MODE_IEEE80211A)
+	if (lq_sta->band == IEEE80211_BAND_5GHZ)
 		base_rate = 0x800D;
 	else
 		base_rate = 0x820A;
@@ -2802,7 +2806,7 @@
 
 	cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d "
 			 "active_search %d rate index %d\n", lq_type, antenna,
-			 lq_sta->search_better_tbl, sta->last_txrate);
+			 lq_sta->search_better_tbl, sta->last_txrate_idx);
 
 	sta_info_put(sta);
 	return cnt;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 0bded85..a894393 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -339,14 +339,15 @@
  *
  * Does not set up a command, or touch hardware.
  */
-int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel,
+int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv,
+			      enum ieee80211_band band, u16 channel,
 			      const struct iwl4965_eeprom_channel *eeprom_ch,
 			      u8 fat_extension_channel)
 {
 	struct iwl4965_channel_info *ch_info;
 
 	ch_info = (struct iwl4965_channel_info *)
-			iwl4965_get_channel_info(priv, phymode, channel);
+			iwl4965_get_channel_info(priv, band, channel);
 
 	if (!is_channel_valid(ch_info))
 		return -1;
@@ -1939,11 +1940,12 @@
 }
 
 static const struct iwl4965_channel_info *
-iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, u8 phymode, u16 channel)
+iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv,
+				 enum ieee80211_band band, u16 channel)
 {
 	const struct iwl4965_channel_info *ch_info;
 
-	ch_info = iwl4965_get_channel_info(priv, phymode, channel);
+	ch_info = iwl4965_get_channel_info(priv, band, channel);
 
 	if (!is_channel_valid(ch_info))
 		return NULL;
@@ -2392,7 +2394,7 @@
 
 	/* Get current (RXON) channel, band, width */
 	ch_info =
-		iwl4965_get_channel_txpower_info(priv, priv->phymode, channel);
+		iwl4965_get_channel_txpower_info(priv, priv->band, channel);
 
 	IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band,
 			  is_fat);
@@ -2619,8 +2621,7 @@
 		return -EAGAIN;
 	}
 
-	band = ((priv->phymode == MODE_IEEE80211B) ||
-		(priv->phymode == MODE_IEEE80211G));
+	band = priv->band == IEEE80211_BAND_2GHZ;
 
 	is_fat =  is_fat_channel(priv->active_rxon.flags);
 
@@ -2650,10 +2651,9 @@
 	struct iwl4965_channel_switch_cmd cmd = { 0 };
 	const struct iwl4965_channel_info *ch_info;
 
-	band = ((priv->phymode == MODE_IEEE80211B) ||
-		(priv->phymode == MODE_IEEE80211G));
+	band = priv->band == IEEE80211_BAND_2GHZ;
 
-	ch_info = iwl4965_get_channel_info(priv, priv->phymode, channel);
+	ch_info = iwl4965_get_channel_info(priv, priv->band, channel);
 
 	is_fat = is_fat_channel(priv->staging_rxon.flags);
 
@@ -2698,7 +2698,7 @@
 	u16 fc = le16_to_cpu(hdr->frame_control);
 	u8 rate_plcp;
 	u16 rate_flags = 0;
-	int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
+	int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
 
 	rate_plcp = iwl4965_rates[rate_idx].plcp;
 
@@ -3178,7 +3178,7 @@
 {
 	s8 signal = stats->ssi;
 	s8 noise = 0;
-	int rate = stats->rate;
+	int rate = stats->rate_idx;
 	u64 tsf = stats->mactime;
 	__le16 phy_flags_hw = rx_start->phy_flags;
 	struct iwl4965_rt_rx_hdr {
@@ -3246,7 +3246,6 @@
 					  IEEE80211_CHAN_2GHZ),
 			      &iwl4965_rt->rt_chbitmask);
 
-	rate = iwl4965_rate_index_from_plcp(rate);
 	if (rate == -1)
 		iwl4965_rt->rt_rate = 0;
 	else
@@ -3542,12 +3541,13 @@
 	u16 fc;
 	struct ieee80211_rx_status stats = {
 		.mactime = le64_to_cpu(rx_start->timestamp),
-		.channel = le16_to_cpu(rx_start->channel),
-		.phymode =
+		.freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)),
+		.band =
 			(rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-			MODE_IEEE80211G : MODE_IEEE80211A,
+			IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ,
 		.antenna = 0,
-		.rate = iwl4965_hw_get_rate(rx_start->rate_n_flags),
+		.rate_idx = iwl4965_hw_get_rate(
+				le32_to_cpu(rx_start->rate_n_flags)),
 		.flag = 0,
 	};
 	u8 network_packet;
@@ -3598,8 +3598,6 @@
 
 	priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
 
-	stats.freq = ieee80211chan2mhz(stats.channel);
-
 	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
 	stats.ssi = iwl4965_calc_rssi(rx_start);
 
@@ -4185,7 +4183,7 @@
 	 * all the way down to 1M in IEEE order, and then spin on 1M */
 	if (is_ap)
 		r = IWL_RATE_54M_INDEX;
-	else if (priv->phymode == MODE_IEEE80211A)
+	else if (priv->band == IEEE80211_BAND_5GHZ)
 		r = IWL_RATE_6M_INDEX;
 	else
 		r = IWL_RATE_1M_INDEX;
@@ -4218,12 +4216,13 @@
 
 #ifdef CONFIG_IWL4965_HT
 
-static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
+static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv,
+				       enum ieee80211_band band,
 				   u16 channel, u8 extension_chan_offset)
 {
 	const struct iwl4965_channel_info *ch_info;
 
-	ch_info = iwl4965_get_channel_info(priv, phymode, channel);
+	ch_info = iwl4965_get_channel_info(priv, band, channel);
 	if (!is_channel_valid(ch_info))
 		return 0;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index de5c1bf..cb8f7f2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -206,7 +206,7 @@
 
 	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
 	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
-	u8 phymode;	  /* MODE_IEEE80211{A,B,G} */
+	enum ieee80211_band band;
 
 	/* Radio/DSP gain settings for each "normal" data Tx rate.
 	 * These include, in addition to RF and DSP gain, a few fields for
@@ -764,7 +764,8 @@
 extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv);
 extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags,
 				     u8 force);
-extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode,
+extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv,
+				enum ieee80211_band band,
 				u16 channel,
 				const struct iwl4965_eeprom_channel *eeprom_ch,
 				u8 fat_extension_channel);
@@ -977,14 +978,14 @@
 	struct list_head free_frames;
 	int frames_count;
 
-	u8 phymode;
+	enum ieee80211_band band;
 	int alloc_rxb_skb;
 	bool add_radiotap;
 
 	void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv,
 				       struct iwl4965_rx_mem_buffer *rxb);
 
-	const struct ieee80211_hw_mode *modes;
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
 
 #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
 	/* spectrum measurement report caching */
@@ -1243,13 +1244,12 @@
 
 static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info)
 {
-	return ch_info->phymode == MODE_IEEE80211A;
+	return ch_info->band == IEEE80211_BAND_5GHZ;
 }
 
 static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info)
 {
-	return ((ch_info->phymode == MODE_IEEE80211B) ||
-		(ch_info->phymode == MODE_IEEE80211G));
+	return ch_info->band == IEEE80211_BAND_2GHZ;
 }
 
 static inline int is_channel_passive(const struct iwl4965_channel_info *ch)
@@ -1263,7 +1263,7 @@
 }
 
 extern const struct iwl4965_channel_info *iwl4965_get_channel_info(
-	const struct iwl4965_priv *priv, int phymode, u16 channel);
+	const struct iwl4965_priv *priv, enum ieee80211_band band, u16 channel);
 
 /* Requires full declaration of iwl4965_priv before including */
 #include "iwl-4965-io.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 40b71bc..57a1d70 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -116,16 +116,10 @@
 	return NULL;
 }
 
-static const struct ieee80211_hw_mode *iwl3945_get_hw_mode(
-		struct iwl3945_priv *priv, int mode)
+static const struct ieee80211_supported_band *iwl3945_get_band(
+		struct iwl3945_priv *priv, enum ieee80211_band band)
 {
-	int i;
-
-	for (i = 0; i < 3; i++)
-		if (priv->modes[i].mode == mode)
-			return &priv->modes[i];
-
-	return NULL;
+	return priv->hw->wiphy->bands[band];
 }
 
 static int iwl3945_is_empty_essid(const char *essid, int essid_len)
@@ -547,7 +541,7 @@
 	station->sta.sta.sta_id = index;
 	station->sta.station_flags = 0;
 
-	if (priv->phymode == MODE_IEEE80211A)
+	if (priv->band == IEEE80211_BAND_5GHZ)
 		rate = IWL_RATE_6M_PLCP;
 	else
 		rate =	IWL_RATE_1M_PLCP;
@@ -894,35 +888,37 @@
 
 /**
  * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON
- * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
- * @channel: Any channel valid for the requested phymode
+ * @band: 2.4 or 5 GHz band
+ * @channel: Any channel valid for the requested band
 
- * In addition to setting the staging RXON, priv->phymode is also set.
+ * In addition to setting the staging RXON, priv->band is also set.
  *
  * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
- * in the staging RXON flag structure based on the phymode
+ * in the staging RXON flag structure based on the band
  */
-static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel)
+static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv,
+				    enum ieee80211_band band,
+				    u16 channel)
 {
-	if (!iwl3945_get_channel_info(priv, phymode, channel)) {
+	if (!iwl3945_get_channel_info(priv, band, channel)) {
 		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
-			       channel, phymode);
+			       channel, band);
 		return -EINVAL;
 	}
 
 	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
-	    (priv->phymode == phymode))
+	    (priv->band == band))
 		return 0;
 
 	priv->staging_rxon.channel = cpu_to_le16(channel);
-	if (phymode == MODE_IEEE80211A)
+	if (band == IEEE80211_BAND_5GHZ)
 		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
 	else
 		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
 
-	priv->phymode = phymode;
+	priv->band = band;
 
-	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
+	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
 
 	return 0;
 }
@@ -1210,8 +1206,7 @@
 			return -EIO;
 		}
 
-	/* Init the hardware's rate fallback order based on the
-	 * phymode */
+	/* Init the hardware's rate fallback order based on the band */
 	rc = iwl3945_init_hw_rate_table(priv);
 	if (rc) {
 		IWL_ERROR("Error setting HW rate table: %02X\n", rc);
@@ -2461,9 +2456,10 @@
 	return 0;
 }
 
-static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode)
+static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
+					  enum ieee80211_band band)
 {
-	if (phymode == MODE_IEEE80211A) {
+	if (band == IEEE80211_BAND_5GHZ) {
 		priv->staging_rxon.flags &=
 		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
 		      | RXON_FLG_CCK_MSK);
@@ -2526,7 +2522,7 @@
 		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 #endif
 
-	ch_info = iwl3945_get_channel_info(priv, priv->phymode,
+	ch_info = iwl3945_get_channel_info(priv, priv->band,
 				       le16_to_cpu(priv->staging_rxon.channel));
 
 	if (!ch_info)
@@ -2542,11 +2538,11 @@
 
 	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
 	if (is_channel_a_band(ch_info))
-		priv->phymode = MODE_IEEE80211A;
+		priv->band = IEEE80211_BAND_5GHZ;
 	else
-		priv->phymode = MODE_IEEE80211G;
+		priv->band = IEEE80211_BAND_2GHZ;
 
-	iwl3945_set_flags_for_phymode(priv, priv->phymode);
+	iwl3945_set_flags_for_phymode(priv, priv->band);
 
 	priv->staging_rxon.ofdm_basic_rates =
 	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
@@ -2560,7 +2556,7 @@
 		const struct iwl3945_channel_info *ch_info;
 
 		ch_info = iwl3945_get_channel_info(priv,
-			priv->phymode,
+			priv->band,
 			le16_to_cpu(priv->staging_rxon.channel));
 
 		if (!ch_info || !is_channel_ibss(ch_info)) {
@@ -2792,7 +2788,7 @@
 		goto drop_unlock;
 	}
 
-	if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
+	if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
 		IWL_ERROR("ERROR: No TX rate available.\n");
 		goto drop_unlock;
 	}
@@ -2992,12 +2988,12 @@
 
 static void iwl3945_set_rate(struct iwl3945_priv *priv)
 {
-	const struct ieee80211_hw_mode *hw = NULL;
+	const struct ieee80211_supported_band *sband = NULL;
 	struct ieee80211_rate *rate;
 	int i;
 
-	hw = iwl3945_get_hw_mode(priv, priv->phymode);
-	if (!hw) {
+	sband = iwl3945_get_band(priv, priv->band);
+	if (!sband) {
 		IWL_ERROR("Failed to set rate: unable to get hw mode\n");
 		return;
 	}
@@ -3005,24 +3001,17 @@
 	priv->active_rate = 0;
 	priv->active_rate_basic = 0;
 
-	IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
-		       hw->mode == MODE_IEEE80211A ?
-		       'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
+	IWL_DEBUG_RATE("Setting rates for %s GHz\n",
+		       sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5");
 
-	for (i = 0; i < hw->num_rates; i++) {
-		rate = &(hw->rates[i]);
-		if ((rate->val < IWL_RATE_COUNT) &&
-		    (rate->flags & IEEE80211_RATE_SUPPORTED)) {
-			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
-				       rate->val, iwl3945_rates[rate->val].plcp,
-				       (rate->flags & IEEE80211_RATE_BASIC) ?
-				       "*" : "");
-			priv->active_rate |= (1 << rate->val);
-			if (rate->flags & IEEE80211_RATE_BASIC)
-				priv->active_rate_basic |= (1 << rate->val);
-		} else
-			IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
-				       rate->val, iwl3945_rates[rate->val].plcp);
+	for (i = 0; i < sband->n_bitrates; i++) {
+		rate = &sband->bitrates[i];
+		if ((rate->hw_value < IWL_RATE_COUNT) &&
+		    !(rate->flags & IEEE80211_CHAN_DISABLED)) {
+			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n",
+				       rate->hw_value, iwl3945_rates[rate->hw_value].plcp);
+			priv->active_rate |= (1 << rate->hw_value);
+		}
 	}
 
 	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
@@ -3436,8 +3425,6 @@
 	tx_status->flags =
 	    iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
 
-	tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate);
-
 	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
 			txq_id, iwl3945_get_tx_fail_reason(status), status,
 			tx_resp->rate, tx_resp->failure_frame);
@@ -5026,24 +5013,24 @@
  * Based on band and channel number.
  */
 const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
-						    int phymode, u16 channel)
+						    enum ieee80211_band band, u16 channel)
 {
 	int i;
 
-	switch (phymode) {
-	case MODE_IEEE80211A:
+	switch (band) {
+	case IEEE80211_BAND_5GHZ:
 		for (i = 14; i < priv->channel_count; i++) {
 			if (priv->channel_info[i].channel == channel)
 				return &priv->channel_info[i];
 		}
 		break;
 
-	case MODE_IEEE80211B:
-	case MODE_IEEE80211G:
+	case IEEE80211_BAND_2GHZ:
 		if (channel >= 1 && channel <= 14)
 			return &priv->channel_info[channel - 1];
 		break;
-
+	case IEEE80211_NUM_BANDS:
+		WARN_ON(1);
 	}
 
 	return NULL;
@@ -5106,8 +5093,8 @@
 		/* Loop through each band adding each of the channels */
 		for (ch = 0; ch < eeprom_ch_count; ch++) {
 			ch_info->channel = eeprom_ch_index[ch];
-			ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
-			    MODE_IEEE80211A;
+			ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
+			    IEEE80211_BAND_5GHZ;
 
 			/* permanently store EEPROM's channel regulatory flags
 			 *   and max power in channel info database. */
@@ -5203,18 +5190,20 @@
 #define IWL_PASSIVE_DWELL_BASE      (100)
 #define IWL_CHANNEL_TUNE_TIME       5
 
-static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode)
+static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
+						enum ieee80211_band band)
 {
-	if (phymode == MODE_IEEE80211A)
+	if (band == IEEE80211_BAND_5GHZ)
 		return IWL_ACTIVE_DWELL_TIME_52;
 	else
 		return IWL_ACTIVE_DWELL_TIME_24;
 }
 
-static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode)
+static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
+					  enum ieee80211_band band)
 {
-	u16 active = iwl3945_get_active_dwell_time(priv, phymode);
-	u16 passive = (phymode != MODE_IEEE80211A) ?
+	u16 active = iwl3945_get_active_dwell_time(priv, band);
+	u16 passive = (band == IEEE80211_BAND_2GHZ) ?
 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
 
@@ -5234,28 +5223,29 @@
 	return passive;
 }
 
-static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
+					 enum ieee80211_band band,
 				     u8 is_active, u8 direct_mask,
 				     struct iwl3945_scan_channel *scan_ch)
 {
 	const struct ieee80211_channel *channels = NULL;
-	const struct ieee80211_hw_mode *hw_mode;
+	const struct ieee80211_supported_band *sband;
 	const struct iwl3945_channel_info *ch_info;
 	u16 passive_dwell = 0;
 	u16 active_dwell = 0;
 	int added, i;
 
-	hw_mode = iwl3945_get_hw_mode(priv, phymode);
-	if (!hw_mode)
+	sband = iwl3945_get_band(priv, band);
+	if (!sband)
 		return 0;
 
-	channels = hw_mode->channels;
+	channels = sband->channels;
 
-	active_dwell = iwl3945_get_active_dwell_time(priv, phymode);
-	passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode);
+	active_dwell = iwl3945_get_active_dwell_time(priv, band);
+	passive_dwell = iwl3945_get_passive_dwell_time(priv, band);
 
-	for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
-		if (channels[i].chan ==
+	for (i = 0, added = 0; i < sband->n_channels; i++) {
+		if (channels[i].hw_value ==
 		    le16_to_cpu(priv->active_rxon.channel)) {
 			if (iwl3945_is_associated(priv)) {
 				IWL_DEBUG_SCAN
@@ -5266,9 +5256,9 @@
 		} else if (priv->only_active_channel)
 			continue;
 
-		scan_ch->channel = channels[i].chan;
+		scan_ch->channel = channels[i].hw_value;
 
-		ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel);
+		ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
 		if (!is_channel_valid(ch_info)) {
 			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
 				       scan_ch->channel);
@@ -5276,7 +5266,7 @@
 		}
 
 		if (!is_active || is_channel_passive(ch_info) ||
-		    !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
+		    (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
 			scan_ch->type = 0;	/* passive */
 		else
 			scan_ch->type = 1;	/* active */
@@ -5295,7 +5285,7 @@
 		/* scan_pwr_info->tpc.dsp_atten; */
 
 		/*scan_pwr_info->tpc.tx_gain; */
-		if (phymode == MODE_IEEE80211A)
+		if (band == IEEE80211_BAND_5GHZ)
 			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
 		else {
 			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
@@ -5319,41 +5309,23 @@
 	return added;
 }
 
-static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv)
-{
-	int i, j;
-	for (i = 0; i < 3; i++) {
-		struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
-		for (j = 0; j < hw_mode->num_channels; j++)
-			hw_mode->channels[j].flag = hw_mode->channels[j].val;
-	}
-}
-
 static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
 			      struct ieee80211_rate *rates)
 {
 	int i;
 
 	for (i = 0; i < IWL_RATE_COUNT; i++) {
-		rates[i].rate = iwl3945_rates[i].ieee * 5;
-		rates[i].val = i; /* Rate scaling will work on indexes */
-		rates[i].val2 = i;
-		rates[i].flags = IEEE80211_RATE_SUPPORTED;
-		/* Only OFDM have the bits-per-symbol set */
-		if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
-			rates[i].flags |= IEEE80211_RATE_OFDM;
-		else {
+		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
+		rates[i].hw_value = i; /* Rate scaling will work on indexes */
+		rates[i].hw_value_short = i;
+		rates[i].flags = 0;
+		if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
 			/*
-			 * If CCK 1M then set rate flag to CCK else CCK_2
-			 * which is CCK | PREAMBLE2
+			 * If CCK != 1M then set short preamble rate flag.
 			 */
 			rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
-				IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
+				0 : IEEE80211_RATE_SHORT_PREAMBLE;
 		}
-
-		/* Set up which ones are basic rates... */
-		if (IWL_BASIC_RATES_MASK & (1 << i))
-			rates[i].flags |= IEEE80211_RATE_BASIC;
 	}
 }
 
@@ -5363,67 +5335,41 @@
 static int iwl3945_init_geos(struct iwl3945_priv *priv)
 {
 	struct iwl3945_channel_info *ch;
-	struct ieee80211_hw_mode *modes;
+	struct ieee80211_supported_band *band;
 	struct ieee80211_channel *channels;
 	struct ieee80211_channel *geo_ch;
 	struct ieee80211_rate *rates;
 	int i = 0;
-	enum {
-		A = 0,
-		B = 1,
-		G = 2,
-	};
-	int mode_count = 3;
 
-	if (priv->modes) {
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
+	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
 		IWL_DEBUG_INFO("Geography modes already initialized.\n");
 		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 		return 0;
 	}
 
-	modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
-			GFP_KERNEL);
-	if (!modes)
-		return -ENOMEM;
-
 	channels = kzalloc(sizeof(struct ieee80211_channel) *
 			   priv->channel_count, GFP_KERNEL);
-	if (!channels) {
-		kfree(modes);
+	if (!channels)
 		return -ENOMEM;
-	}
 
 	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
 			GFP_KERNEL);
 	if (!rates) {
-		kfree(modes);
 		kfree(channels);
 		return -ENOMEM;
 	}
 
-	/* 0 = 802.11a
-	 * 1 = 802.11b
-	 * 2 = 802.11g
-	 */
-
 	/* 5.2GHz channels start after the 2.4GHz channels */
-	modes[A].mode = MODE_IEEE80211A;
-	modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
-	modes[A].rates = &rates[4];
-	modes[A].num_rates = 8;	/* just OFDM */
-	modes[A].num_channels = 0;
+	band = &priv->bands[IEEE80211_BAND_5GHZ];
+	band->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
+	band->bitrates = &rates[4];
+	band->n_bitrates = 8;	/* just OFDM */
 
-	modes[B].mode = MODE_IEEE80211B;
-	modes[B].channels = channels;
-	modes[B].rates = rates;
-	modes[B].num_rates = 4;	/* just CCK */
-	modes[B].num_channels = 0;
-
-	modes[G].mode = MODE_IEEE80211G;
-	modes[G].channels = channels;
-	modes[G].rates = rates;
-	modes[G].num_rates = 12;	/* OFDM & CCK */
-	modes[G].num_channels = 0;
+	band = &priv->bands[IEEE80211_BAND_2GHZ];
+	band->channels = channels;
+	band->bitrates = rates;
+	band->n_bitrates = 12;	/* OFDM & CCK */
 
 	priv->ieee_channels = channels;
 	priv->ieee_rates = rates;
@@ -5442,37 +5388,32 @@
 		}
 
 		if (is_channel_a_band(ch))
-			geo_ch = &modes[A].channels[modes[A].num_channels++];
-		else {
-			geo_ch = &modes[B].channels[modes[B].num_channels++];
-			modes[G].num_channels++;
-		}
+			geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++];
+		else
+			geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++];
 
-		geo_ch->freq = ieee80211chan2mhz(ch->channel);
-		geo_ch->chan = ch->channel;
-		geo_ch->power_level = ch->max_power_avg;
-		geo_ch->antenna_max = 0xff;
+		geo_ch->center_freq = ieee80211chan2mhz(ch->channel);
+		geo_ch->max_power = ch->max_power_avg;
+		geo_ch->max_antenna_gain = 0xff;
 
 		if (is_channel_valid(ch)) {
-			geo_ch->flag = IEEE80211_CHAN_W_SCAN;
-			if (ch->flags & EEPROM_CHANNEL_IBSS)
-				geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
+			if (!(ch->flags & EEPROM_CHANNEL_IBSS))
+				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
 
-			if (ch->flags & EEPROM_CHANNEL_ACTIVE)
-				geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
+			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
+				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
 
 			if (ch->flags & EEPROM_CHANNEL_RADAR)
-				geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
+				geo_ch->flags |= IEEE80211_CHAN_RADAR;
 
 			if (ch->max_power_avg > priv->max_channel_txpower_limit)
 				priv->max_channel_txpower_limit =
 				    ch->max_power_avg;
-		}
-
-		geo_ch->val = geo_ch->flag;
+		} else
+			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
 	}
 
-	if ((modes[A].num_channels == 0) && priv->is_abg) {
+	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) {
 		printk(KERN_INFO DRV_NAME
 		       ": Incorrectly detected BG card as ABG.  Please send "
 		       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
@@ -5482,24 +5423,12 @@
 
 	printk(KERN_INFO DRV_NAME
 	       ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-	       modes[G].num_channels, modes[A].num_channels);
+	       priv->bands[IEEE80211_BAND_2GHZ].n_channels,
+	       priv->bands[IEEE80211_BAND_5GHZ].n_channels);
 
-	/*
-	 * NOTE:  We register these in preference of order -- the
-	 * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
-	 * a phymode based on rates or AP capabilities but seems to
-	 * configure it purely on if the channel being configured
-	 * is supported by a mode -- and the first match is taken
-	 */
+	priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ];
+	priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ];
 
-	if (modes[G].num_channels)
-		ieee80211_register_hwmode(priv->hw, &modes[G]);
-	if (modes[B].num_channels)
-		ieee80211_register_hwmode(priv->hw, &modes[B]);
-	if (modes[A].num_channels)
-		ieee80211_register_hwmode(priv->hw, &modes[A]);
-
-	priv->modes = modes;
 	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 
 	return 0;
@@ -5510,7 +5439,6 @@
  */
 static void iwl3945_free_geos(struct iwl3945_priv *priv)
 {
-	kfree(priv->modes);
 	kfree(priv->ieee_channels);
 	kfree(priv->ieee_rates);
 	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
@@ -6519,7 +6447,7 @@
 	struct iwl3945_scan_cmd *scan;
 	struct ieee80211_conf *conf = NULL;
 	u8 direct_mask;
-	int phymode;
+	enum ieee80211_band band;
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -6651,13 +6579,13 @@
 		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
 		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
 		scan->good_CRC_th = 0;
-		phymode = MODE_IEEE80211G;
+		band = IEEE80211_BAND_2GHZ;
 		break;
 
 	case 1:
 		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
 		scan->good_CRC_th = IWL_GOOD_CRC_TH;
-		phymode = MODE_IEEE80211A;
+		band = IEEE80211_BAND_5GHZ;
 		break;
 
 	default:
@@ -6680,7 +6608,7 @@
 
 	scan->channel_count =
 		iwl3945_get_channels_for_scan(
-			priv, phymode, 1, /* active */
+			priv, band, 1, /* active */
 			direct_mask,
 			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
@@ -6825,7 +6753,7 @@
 		iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
 		iwl3945_add_station(priv, priv->bssid, 0, 0);
 		iwl3945_sync_sta(priv, IWL_STA_ID,
-				 (priv->phymode == MODE_IEEE80211A)?
+				 (priv->band == IEEE80211_BAND_5GHZ) ?
 				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
 				 CMD_ASYNC);
 		iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
@@ -7020,7 +6948,7 @@
 	}
 
 	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-		     ctl->tx_rate);
+		     ctl->tx_rate->bitrate);
 
 	if (iwl3945_tx_skb(priv, skb, ctl))
 		dev_kfree_skb_any(skb);
@@ -7079,7 +7007,7 @@
 	int ret = 0;
 
 	mutex_lock(&priv->mutex);
-	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
+	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
 
 	priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
 
@@ -7099,19 +7027,20 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel);
+	ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
+					   conf->channel->hw_value);
 	if (!is_channel_valid(ch_info)) {
 		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
-			       conf->channel, conf->phymode);
+			       conf->channel->hw_value, conf->channel->band);
 		IWL_DEBUG_MAC80211("leave - invalid channel\n");
 		spin_unlock_irqrestore(&priv->lock, flags);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel);
+	iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value);
 
-	iwl3945_set_flags_for_phymode(priv, conf->phymode);
+	iwl3945_set_flags_for_phymode(priv, conf->channel->band);
 
 	/* The list of supported rates and rate mask can be different
 	 * for each phymode; since the phymode may have changed, reset
@@ -7892,65 +7821,6 @@
 static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
 		   store_filter_flags);
 
-static ssize_t show_tune(struct device *d,
-			 struct device_attribute *attr, char *buf)
-{
-	struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-
-	return sprintf(buf, "0x%04X\n",
-		       (priv->phymode << 8) |
-			le16_to_cpu(priv->active_rxon.channel));
-}
-
-static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode);
-
-static ssize_t store_tune(struct device *d,
-			  struct device_attribute *attr,
-			  const char *buf, size_t count)
-{
-	struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-	char *p = (char *)buf;
-	u16 tune = simple_strtoul(p, &p, 0);
-	u8 phymode = (tune >> 8) & 0xff;
-	u16 channel = tune & 0xff;
-
-	IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
-
-	mutex_lock(&priv->mutex);
-	if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
-	    (priv->phymode != phymode)) {
-		const struct iwl3945_channel_info *ch_info;
-
-		ch_info = iwl3945_get_channel_info(priv, phymode, channel);
-		if (!ch_info) {
-			IWL_WARNING("Requested invalid phymode/channel "
-				    "combination: %d %d\n", phymode, channel);
-			mutex_unlock(&priv->mutex);
-			return -EINVAL;
-		}
-
-		/* Cancel any currently running scans... */
-		if (iwl3945_scan_cancel_timeout(priv, 100))
-			IWL_WARNING("Could not cancel scan.\n");
-		else {
-			IWL_DEBUG_INFO("Committing phymode and "
-				       "rxon.channel = %d %d\n",
-				       phymode, channel);
-
-			iwl3945_set_rxon_channel(priv, phymode, channel);
-			iwl3945_set_flags_for_phymode(priv, phymode);
-
-			iwl3945_set_rate(priv);
-			iwl3945_commit_rxon(priv);
-		}
-	}
-	mutex_unlock(&priv->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
-
 #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
 
 static ssize_t show_measurement(struct device *d,
@@ -8165,73 +8035,8 @@
 static ssize_t show_channels(struct device *d,
 			     struct device_attribute *attr, char *buf)
 {
-	struct iwl3945_priv *priv = dev_get_drvdata(d);
-	int len = 0, i;
-	struct ieee80211_channel *channels = NULL;
-	const struct ieee80211_hw_mode *hw_mode = NULL;
-	int count = 0;
-
-	if (!iwl3945_is_ready(priv))
-		return -EAGAIN;
-
-	hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G);
-	if (!hw_mode)
-		hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B);
-	if (hw_mode) {
-		channels = hw_mode->channels;
-		count = hw_mode->num_channels;
-	}
-
-	len +=
-	    sprintf(&buf[len],
-		    "Displaying %d channels in 2.4GHz band "
-		    "(802.11bg):\n", count);
-
-	for (i = 0; i < count; i++)
-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-			       channels[i].chan,
-			       channels[i].power_level,
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-			       " (IEEE 802.11h required)" : "",
-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-				|| (channels[i].
-				    flag &
-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-			       ", IBSS",
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-			       "active/passive" : "passive only");
-
-	hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A);
-	if (hw_mode) {
-		channels = hw_mode->channels;
-		count = hw_mode->num_channels;
-	} else {
-		channels = NULL;
-		count = 0;
-	}
-
-	len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
-		       "(802.11a):\n", count);
-
-	for (i = 0; i < count; i++)
-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-			       channels[i].chan,
-			       channels[i].power_level,
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-			       " (IEEE 802.11h required)" : "",
-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-				|| (channels[i].
-				    flag &
-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-			       ", IBSS",
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-			       "active/passive" : "passive only");
-
-	return len;
+	/* all this shit doesn't belong into sysfs anyway */
+	return 0;
 }
 
 static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
@@ -8411,7 +8216,6 @@
 	&dev_attr_statistics.attr,
 	&dev_attr_status.attr,
 	&dev_attr_temperature.attr,
-	&dev_attr_tune.attr,
 	&dev_attr_tx_power.attr,
 
 	NULL
@@ -8532,7 +8336,7 @@
 	priv->data_retry_limit = -1;
 	priv->ieee_channels = NULL;
 	priv->ieee_rates = NULL;
-	priv->phymode = -1;
+	priv->band = IEEE80211_BAND_2GHZ;
 
 	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 	if (!err)
@@ -8614,7 +8418,7 @@
 	priv->qos_data.qos_cap.val = 0;
 #endif /* CONFIG_IWL3945_QOS */
 
-	iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6);
+	iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
 	iwl3945_setup_deferred_work(priv);
 	iwl3945_setup_rx_handlers(priv);
 
@@ -8665,7 +8469,6 @@
 		IWL_ERROR("initializing geos failed: %d\n", err);
 		goto out_free_channel_map;
 	}
-	iwl3945_reset_channel_flag(priv);
 
 	iwl3945_rate_control_register(priv->hw);
 	err = ieee80211_register_hw(priv->hw);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 5f38fc5..6de969d 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -115,16 +115,10 @@
 	return NULL;
 }
 
-static const struct ieee80211_hw_mode *iwl4965_get_hw_mode(
-		struct iwl4965_priv *priv, int mode)
+static const struct ieee80211_supported_band *iwl4965_get_hw_mode(
+		struct iwl4965_priv *priv, enum ieee80211_band band)
 {
-	int i;
-
-	for (i = 0; i < 3; i++)
-		if (priv->modes[i].mode == mode)
-			return &priv->modes[i];
-
-	return NULL;
+	return priv->hw->wiphy->bands[band];
 }
 
 static int iwl4965_is_empty_essid(const char *essid, int essid_len)
@@ -937,28 +931,29 @@
  * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
  * in the staging RXON flag structure based on the phymode
  */
-static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode,
+static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv,
+				    enum ieee80211_band band,
 				 u16 channel)
 {
-	if (!iwl4965_get_channel_info(priv, phymode, channel)) {
+	if (!iwl4965_get_channel_info(priv, band, channel)) {
 		IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
-			       channel, phymode);
+			       channel, band);
 		return -EINVAL;
 	}
 
 	if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
-	    (priv->phymode == phymode))
+	    (priv->band == band))
 		return 0;
 
 	priv->staging_rxon.channel = cpu_to_le16(channel);
-	if (phymode == MODE_IEEE80211A)
+	if (band == IEEE80211_BAND_5GHZ)
 		priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
 	else
 		priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
 
-	priv->phymode = phymode;
+	priv->band = band;
 
-	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
+	IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
 
 	return 0;
 }
@@ -2571,9 +2566,10 @@
 	return 0;
 }
 
-static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode)
+static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv,
+					  enum ieee80211_band band)
 {
-	if (phymode == MODE_IEEE80211A) {
+	if (band == IEEE80211_BAND_5GHZ) {
 		priv->staging_rxon.flags &=
 		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
 		      | RXON_FLG_CCK_MSK);
@@ -2636,7 +2632,7 @@
 		priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 #endif
 
-	ch_info = iwl4965_get_channel_info(priv, priv->phymode,
+	ch_info = iwl4965_get_channel_info(priv, priv->band,
 				       le16_to_cpu(priv->staging_rxon.channel));
 
 	if (!ch_info)
@@ -2651,12 +2647,9 @@
 		ch_info = &priv->channel_info[0];
 
 	priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
-	if (is_channel_a_band(ch_info))
-		priv->phymode = MODE_IEEE80211A;
-	else
-		priv->phymode = MODE_IEEE80211G;
+	priv->band = ch_info->band;
 
-	iwl4965_set_flags_for_phymode(priv, priv->phymode);
+	iwl4965_set_flags_for_phymode(priv, priv->band);
 
 	priv->staging_rxon.ofdm_basic_rates =
 	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
@@ -2678,7 +2671,7 @@
 		const struct iwl4965_channel_info *ch_info;
 
 		ch_info = iwl4965_get_channel_info(priv,
-			priv->phymode,
+			priv->band,
 			le16_to_cpu(priv->staging_rxon.channel));
 
 		if (!ch_info || !is_channel_ibss(ch_info)) {
@@ -2918,7 +2911,7 @@
 		goto drop_unlock;
 	}
 
-	if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
+	if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
 		IWL_ERROR("ERROR: No TX rate available.\n");
 		goto drop_unlock;
 	}
@@ -3125,11 +3118,11 @@
 
 static void iwl4965_set_rate(struct iwl4965_priv *priv)
 {
-	const struct ieee80211_hw_mode *hw = NULL;
+	const struct ieee80211_supported_band *hw = NULL;
 	struct ieee80211_rate *rate;
 	int i;
 
-	hw = iwl4965_get_hw_mode(priv, priv->phymode);
+	hw = iwl4965_get_hw_mode(priv, priv->band);
 	if (!hw) {
 		IWL_ERROR("Failed to set rate: unable to get hw mode\n");
 		return;
@@ -3138,24 +3131,10 @@
 	priv->active_rate = 0;
 	priv->active_rate_basic = 0;
 
-	IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
-		       hw->mode == MODE_IEEE80211A ?
-		       'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
-
-	for (i = 0; i < hw->num_rates; i++) {
-		rate = &(hw->rates[i]);
-		if ((rate->val < IWL_RATE_COUNT) &&
-		    (rate->flags & IEEE80211_RATE_SUPPORTED)) {
-			IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
-				       rate->val, iwl4965_rates[rate->val].plcp,
-				       (rate->flags & IEEE80211_RATE_BASIC) ?
-				       "*" : "");
-			priv->active_rate |= (1 << rate->val);
-			if (rate->flags & IEEE80211_RATE_BASIC)
-				priv->active_rate_basic |= (1 << rate->val);
-		} else
-			IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
-				       rate->val, iwl4965_rates[rate->val].plcp);
+	for (i = 0; i < hw->n_bitrates; i++) {
+		rate = &(hw->bitrates[i]);
+		if (rate->hw_value < IWL_RATE_COUNT)
+			priv->active_rate |= (1 << rate->hw_value);
 	}
 
 	IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
@@ -3775,9 +3754,6 @@
 	tx_status->flags =
 	    iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
 
-	tx_status->control.tx_rate =
-		iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
-
 	IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
 		     "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
 		     status, le32_to_cpu(tx_resp->rate_n_flags),
@@ -5419,24 +5395,23 @@
  * Based on band and channel number.
  */
 const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv,
-						    int phymode, u16 channel)
+						    enum ieee80211_band band, u16 channel)
 {
 	int i;
 
-	switch (phymode) {
-	case MODE_IEEE80211A:
+	switch (band) {
+	case IEEE80211_BAND_5GHZ:
 		for (i = 14; i < priv->channel_count; i++) {
 			if (priv->channel_info[i].channel == channel)
 				return &priv->channel_info[i];
 		}
 		break;
-
-	case MODE_IEEE80211B:
-	case MODE_IEEE80211G:
+	case IEEE80211_BAND_2GHZ:
 		if (channel >= 1 && channel <= 14)
 			return &priv->channel_info[channel - 1];
 		break;
-
+	default:
+		BUG();
 	}
 
 	return NULL;
@@ -5499,8 +5474,8 @@
 		/* Loop through each band adding each of the channels */
 		for (ch = 0; ch < eeprom_ch_count; ch++) {
 			ch_info->channel = eeprom_ch_index[ch];
-			ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
-			    MODE_IEEE80211A;
+			ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
+			    IEEE80211_BAND_5GHZ;
 
 			/* permanently store EEPROM's channel regulatory flags
 			 *   and max power in channel info database. */
@@ -5559,14 +5534,14 @@
 
 	/* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
 	for (band = 6; band <= 7; band++) {
-		int phymode;
+		enum ieee80211_band ieeeband;
 		u8 fat_extension_chan;
 
 		iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
 					&eeprom_ch_info, &eeprom_ch_index);
 
 		/* EEPROM band 6 is 2.4, band 7 is 5 GHz */
-		phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A;
+		ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
 
 		/* Loop through each band adding each of the channels */
 		for (ch = 0; ch < eeprom_ch_count; ch++) {
@@ -5580,13 +5555,13 @@
 				fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
 
 			/* Set up driver's info for lower half */
-			iwl4965_set_fat_chan_info(priv, phymode,
+			iwl4965_set_fat_chan_info(priv, ieeeband,
 						  eeprom_ch_index[ch],
 						  &(eeprom_ch_info[ch]),
 						  fat_extension_chan);
 
 			/* Set up driver's info for upper half */
-			iwl4965_set_fat_chan_info(priv, phymode,
+			iwl4965_set_fat_chan_info(priv, ieeeband,
 						  (eeprom_ch_index[ch] + 4),
 						  &(eeprom_ch_info[ch]),
 						  HT_IE_EXT_CHANNEL_BELOW);
@@ -5628,18 +5603,20 @@
 #define IWL_PASSIVE_DWELL_BASE      (100)
 #define IWL_CHANNEL_TUNE_TIME       5
 
-static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, int phymode)
+static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv,
+						enum ieee80211_band band)
 {
-	if (phymode == MODE_IEEE80211A)
+	if (band == IEEE80211_BAND_5GHZ)
 		return IWL_ACTIVE_DWELL_TIME_52;
 	else
 		return IWL_ACTIVE_DWELL_TIME_24;
 }
 
-static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode)
+static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv,
+					  enum ieee80211_band band)
 {
-	u16 active = iwl4965_get_active_dwell_time(priv, phymode);
-	u16 passive = (phymode != MODE_IEEE80211A) ?
+	u16 active = iwl4965_get_active_dwell_time(priv, band);
+	u16 passive = (band != IEEE80211_BAND_5GHZ) ?
 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
 	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
 
@@ -5659,28 +5636,29 @@
 	return passive;
 }
 
-static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv,
+					 enum ieee80211_band band,
 				     u8 is_active, u8 direct_mask,
 				     struct iwl4965_scan_channel *scan_ch)
 {
 	const struct ieee80211_channel *channels = NULL;
-	const struct ieee80211_hw_mode *hw_mode;
+	const struct ieee80211_supported_band *sband;
 	const struct iwl4965_channel_info *ch_info;
 	u16 passive_dwell = 0;
 	u16 active_dwell = 0;
 	int added, i;
 
-	hw_mode = iwl4965_get_hw_mode(priv, phymode);
-	if (!hw_mode)
+	sband = iwl4965_get_hw_mode(priv, band);
+	if (!sband)
 		return 0;
 
-	channels = hw_mode->channels;
+	channels = sband->channels;
 
-	active_dwell = iwl4965_get_active_dwell_time(priv, phymode);
-	passive_dwell = iwl4965_get_passive_dwell_time(priv, phymode);
+	active_dwell = iwl4965_get_active_dwell_time(priv, band);
+	passive_dwell = iwl4965_get_passive_dwell_time(priv, band);
 
-	for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
-		if (channels[i].chan ==
+	for (i = 0, added = 0; i < sband->n_channels; i++) {
+		if (ieee80211_frequency_to_channel(channels[i].center_freq) ==
 		    le16_to_cpu(priv->active_rxon.channel)) {
 			if (iwl4965_is_associated(priv)) {
 				IWL_DEBUG_SCAN
@@ -5691,9 +5669,9 @@
 		} else if (priv->only_active_channel)
 			continue;
 
-		scan_ch->channel = channels[i].chan;
+		scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq);
 
-		ch_info = iwl4965_get_channel_info(priv, phymode,
+		ch_info = iwl4965_get_channel_info(priv, band,
 					 scan_ch->channel);
 		if (!is_channel_valid(ch_info)) {
 			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
@@ -5702,7 +5680,7 @@
 		}
 
 		if (!is_active || is_channel_passive(ch_info) ||
-		    !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
+		    (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
 			scan_ch->type = 0;	/* passive */
 		else
 			scan_ch->type = 1;	/* active */
@@ -5721,7 +5699,7 @@
 		/* scan_pwr_info->tpc.dsp_atten; */
 
 		/*scan_pwr_info->tpc.tx_gain; */
-		if (phymode == MODE_IEEE80211A)
+		if (band == IEEE80211_BAND_5GHZ)
 			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
 		else {
 			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
@@ -5745,41 +5723,23 @@
 	return added;
 }
 
-static void iwl4965_reset_channel_flag(struct iwl4965_priv *priv)
-{
-	int i, j;
-	for (i = 0; i < 3; i++) {
-		struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
-		for (j = 0; j < hw_mode->num_channels; j++)
-			hw_mode->channels[j].flag = hw_mode->channels[j].val;
-	}
-}
-
 static void iwl4965_init_hw_rates(struct iwl4965_priv *priv,
 			      struct ieee80211_rate *rates)
 {
 	int i;
 
 	for (i = 0; i < IWL_RATE_COUNT; i++) {
-		rates[i].rate = iwl4965_rates[i].ieee * 5;
-		rates[i].val = i; /* Rate scaling will work on indexes */
-		rates[i].val2 = i;
-		rates[i].flags = IEEE80211_RATE_SUPPORTED;
-		/* Only OFDM have the bits-per-symbol set */
-		if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
-			rates[i].flags |= IEEE80211_RATE_OFDM;
-		else {
+		rates[i].bitrate = iwl4965_rates[i].ieee * 5;
+		rates[i].hw_value = i; /* Rate scaling will work on indexes */
+		rates[i].hw_value_short = i;
+		rates[i].flags = 0;
+		if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
 			/*
-			 * If CCK 1M then set rate flag to CCK else CCK_2
-			 * which is CCK | PREAMBLE2
+			 * If CCK != 1M then set short preamble rate flag.
 			 */
 			rates[i].flags |= (iwl4965_rates[i].plcp == 10) ?
-				IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
+				0 : IEEE80211_RATE_SHORT_PREAMBLE;
 		}
-
-		/* Set up which ones are basic rates... */
-		if (IWL_BASIC_RATES_MASK & (1 << i))
-			rates[i].flags |= IEEE80211_RATE_BASIC;
 	}
 }
 
@@ -5789,74 +5749,47 @@
 static int iwl4965_init_geos(struct iwl4965_priv *priv)
 {
 	struct iwl4965_channel_info *ch;
-	struct ieee80211_hw_mode *modes;
+	struct ieee80211_supported_band *band;
 	struct ieee80211_channel *channels;
 	struct ieee80211_channel *geo_ch;
 	struct ieee80211_rate *rates;
 	int i = 0;
-	enum {
-		A = 0,
-		B = 1,
-		G = 2,
-	};
-	int mode_count = 3;
 
-	if (priv->modes) {
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
+	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
 		IWL_DEBUG_INFO("Geography modes already initialized.\n");
 		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 		return 0;
 	}
 
-	modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
-			GFP_KERNEL);
-	if (!modes)
-		return -ENOMEM;
-
 	channels = kzalloc(sizeof(struct ieee80211_channel) *
 			   priv->channel_count, GFP_KERNEL);
-	if (!channels) {
-		kfree(modes);
+	if (!channels)
 		return -ENOMEM;
-	}
 
 	rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
 			GFP_KERNEL);
 	if (!rates) {
-		kfree(modes);
 		kfree(channels);
 		return -ENOMEM;
 	}
 
-	/* 0 = 802.11a
-	 * 1 = 802.11b
-	 * 2 = 802.11g
-	 */
-
 	/* 5.2GHz channels start after the 2.4GHz channels */
-	modes[A].mode = MODE_IEEE80211A;
-	modes[A].channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)];
-	modes[A].rates = rates;
-	modes[A].num_rates = 8;	/* just OFDM */
-	modes[A].rates = &rates[4];
-	modes[A].num_channels = 0;
 #ifdef CONFIG_IWL4965_HT
 	iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A);
 #endif
-
-	modes[B].mode = MODE_IEEE80211B;
-	modes[B].channels = channels;
-	modes[B].rates = rates;
-	modes[B].num_rates = 4;	/* just CCK */
-	modes[B].num_channels = 0;
-
-	modes[G].mode = MODE_IEEE80211G;
-	modes[G].channels = channels;
-	modes[G].rates = rates;
-	modes[G].num_rates = 12;	/* OFDM & CCK */
-	modes[G].num_channels = 0;
 #ifdef CONFIG_IWL4965_HT
 	iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G);
 #endif
+	band = &priv->bands[IEEE80211_BAND_5GHZ];
+	band->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)];
+	band->bitrates = &rates[4];
+	band->n_bitrates = 8;	/* just OFDM */
+
+	band = &priv->bands[IEEE80211_BAND_2GHZ];
+	band->channels = channels;
+	band->bitrates = rates;
+	band->n_bitrates = 12;	/* OFDM & CCK */
 
 	priv->ieee_channels = channels;
 	priv->ieee_rates = rates;
@@ -5875,37 +5808,32 @@
 		}
 
 		if (is_channel_a_band(ch)) {
-			geo_ch = &modes[A].channels[modes[A].num_channels++];
-		} else {
-			geo_ch = &modes[B].channels[modes[B].num_channels++];
-			modes[G].num_channels++;
-		}
+			geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++];
+		} else
+			geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++];
 
-		geo_ch->freq = ieee80211chan2mhz(ch->channel);
-		geo_ch->chan = ch->channel;
-		geo_ch->power_level = ch->max_power_avg;
-		geo_ch->antenna_max = 0xff;
+		geo_ch->center_freq = ieee80211chan2mhz(ch->channel);
+		geo_ch->max_power = ch->max_power_avg;
+		geo_ch->max_antenna_gain = 0xff;
 
 		if (is_channel_valid(ch)) {
-			geo_ch->flag = IEEE80211_CHAN_W_SCAN;
-			if (ch->flags & EEPROM_CHANNEL_IBSS)
-				geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
+			if (!(ch->flags & EEPROM_CHANNEL_IBSS))
+				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
 
-			if (ch->flags & EEPROM_CHANNEL_ACTIVE)
-				geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
+			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
+				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
 
 			if (ch->flags & EEPROM_CHANNEL_RADAR)
-				geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
+				geo_ch->flags |= IEEE80211_CHAN_RADAR;
 
 			if (ch->max_power_avg > priv->max_channel_txpower_limit)
 				priv->max_channel_txpower_limit =
 				    ch->max_power_avg;
-		}
-
-		geo_ch->val = geo_ch->flag;
+		} else
+			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
 	}
 
-	if ((modes[A].num_channels == 0) && priv->is_abg) {
+	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) {
 		printk(KERN_INFO DRV_NAME
 		       ": Incorrectly detected BG card as ABG.  Please send "
 		       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
@@ -5915,24 +5843,12 @@
 
 	printk(KERN_INFO DRV_NAME
 	       ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-	       modes[G].num_channels, modes[A].num_channels);
+	       priv->bands[IEEE80211_BAND_2GHZ].n_channels,
+	       priv->bands[IEEE80211_BAND_5GHZ].n_channels);
 
-	/*
-	 * NOTE:  We register these in preference of order -- the
-	 * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
-	 * a phymode based on rates or AP capabilities but seems to
-	 * configure it purely on if the channel being configured
-	 * is supported by a mode -- and the first match is taken
-	 */
+	priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ];
+	priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ];
 
-	if (modes[G].num_channels)
-		ieee80211_register_hwmode(priv->hw, &modes[G]);
-	if (modes[B].num_channels)
-		ieee80211_register_hwmode(priv->hw, &modes[B]);
-	if (modes[A].num_channels)
-		ieee80211_register_hwmode(priv->hw, &modes[A]);
-
-	priv->modes = modes;
 	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
 
 	return 0;
@@ -5943,7 +5859,6 @@
  */
 static void iwl4965_free_geos(struct iwl4965_priv *priv)
 {
-	kfree(priv->modes);
 	kfree(priv->ieee_channels);
 	kfree(priv->ieee_rates);
 	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
@@ -6945,7 +6860,7 @@
 	struct iwl4965_scan_cmd *scan;
 	struct ieee80211_conf *conf = NULL;
 	u8 direct_mask;
-	int phymode;
+	enum ieee80211_band band;
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -7075,7 +6990,7 @@
 				RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
 
 		scan->good_CRC_th = 0;
-		phymode = MODE_IEEE80211G;
+		band = IEEE80211_BAND_2GHZ;
 		break;
 
 	case 1:
@@ -7083,7 +6998,7 @@
 				iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
 				RATE_MCS_ANT_B_MSK);
 		scan->good_CRC_th = IWL_GOOD_CRC_TH;
-		phymode = MODE_IEEE80211A;
+		band = IEEE80211_BAND_5GHZ;
 		break;
 
 	default:
@@ -7113,7 +7028,7 @@
 
 	scan->channel_count =
 		iwl4965_get_channels_for_scan(
-			priv, phymode, 1, /* active */
+			priv, band, 1, /* active */
 			direct_mask,
 			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
@@ -7463,7 +7378,7 @@
 	}
 
 	IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-		     ctl->tx_rate);
+		     ctl->tx_rate->bitrate);
 
 	if (iwl4965_tx_skb(priv, skb, ctl))
 		dev_kfree_skb_any(skb);
@@ -7522,7 +7437,7 @@
 	int ret = 0;
 
 	mutex_lock(&priv->mutex);
-	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
+	IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
 
 	priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
 
@@ -7542,10 +7457,9 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	ch_info = iwl4965_get_channel_info(priv, conf->phymode, conf->channel);
+	ch_info = iwl4965_get_channel_info(priv, conf->channel->band,
+			ieee80211_frequency_to_channel(conf->channel->center_freq));
 	if (!is_channel_valid(ch_info)) {
-		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
-			       conf->channel, conf->phymode);
 		IWL_DEBUG_MAC80211("leave - invalid channel\n");
 		spin_unlock_irqrestore(&priv->lock, flags);
 		ret = -EINVAL;
@@ -7564,12 +7478,13 @@
 		priv->staging_rxon.flags = 0;
 #endif /* CONFIG_IWL4965_HT */
 
-	iwl4965_set_rxon_channel(priv, conf->phymode, conf->channel);
+	iwl4965_set_rxon_channel(priv, conf->channel->band,
+		ieee80211_frequency_to_channel(conf->channel->center_freq));
 
-	iwl4965_set_flags_for_phymode(priv, conf->phymode);
+	iwl4965_set_flags_for_phymode(priv, conf->channel->band);
 
 	/* The list of supported rates and rate mask can be different
-	 * for each phymode; since the phymode may have changed, reset
+	 * for each band; since the band may have changed, reset
 	 * the rate mask to what mac80211 lists */
 	iwl4965_set_rate(priv);
 
@@ -7839,7 +7754,7 @@
 	}
 
 	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-		if (bss_conf->use_cts_prot && (priv->phymode != MODE_IEEE80211A))
+		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
 			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
 		else
 			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
@@ -8277,7 +8192,6 @@
 			u8 use_current_config)
 {
 	struct ieee80211_conf *conf = &hw->conf;
-	struct ieee80211_hw_mode *mode = conf->mode;
 
 	if (use_current_config) {
 		ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap);
@@ -8488,65 +8402,6 @@
 static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
 		   store_filter_flags);
 
-static ssize_t show_tune(struct device *d,
-			 struct device_attribute *attr, char *buf)
-{
-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-
-	return sprintf(buf, "0x%04X\n",
-		       (priv->phymode << 8) |
-			le16_to_cpu(priv->active_rxon.channel));
-}
-
-static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode);
-
-static ssize_t store_tune(struct device *d,
-			  struct device_attribute *attr,
-			  const char *buf, size_t count)
-{
-	struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-	char *p = (char *)buf;
-	u16 tune = simple_strtoul(p, &p, 0);
-	u8 phymode = (tune >> 8) & 0xff;
-	u16 channel = tune & 0xff;
-
-	IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
-
-	mutex_lock(&priv->mutex);
-	if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
-	    (priv->phymode != phymode)) {
-		const struct iwl4965_channel_info *ch_info;
-
-		ch_info = iwl4965_get_channel_info(priv, phymode, channel);
-		if (!ch_info) {
-			IWL_WARNING("Requested invalid phymode/channel "
-				    "combination: %d %d\n", phymode, channel);
-			mutex_unlock(&priv->mutex);
-			return -EINVAL;
-		}
-
-		/* Cancel any currently running scans... */
-		if (iwl4965_scan_cancel_timeout(priv, 100))
-			IWL_WARNING("Could not cancel scan.\n");
-		else {
-			IWL_DEBUG_INFO("Committing phymode and "
-				       "rxon.channel = %d %d\n",
-				       phymode, channel);
-
-			iwl4965_set_rxon_channel(priv, phymode, channel);
-			iwl4965_set_flags_for_phymode(priv, phymode);
-
-			iwl4965_set_rate(priv);
-			iwl4965_commit_rxon(priv);
-		}
-	}
-	mutex_unlock(&priv->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
-
 #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
 
 static ssize_t show_measurement(struct device *d,
@@ -8736,73 +8591,8 @@
 static ssize_t show_channels(struct device *d,
 			     struct device_attribute *attr, char *buf)
 {
-	struct iwl4965_priv *priv = dev_get_drvdata(d);
-	int len = 0, i;
-	struct ieee80211_channel *channels = NULL;
-	const struct ieee80211_hw_mode *hw_mode = NULL;
-	int count = 0;
-
-	if (!iwl4965_is_ready(priv))
-		return -EAGAIN;
-
-	hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211G);
-	if (!hw_mode)
-		hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211B);
-	if (hw_mode) {
-		channels = hw_mode->channels;
-		count = hw_mode->num_channels;
-	}
-
-	len +=
-	    sprintf(&buf[len],
-		    "Displaying %d channels in 2.4GHz band "
-		    "(802.11bg):\n", count);
-
-	for (i = 0; i < count; i++)
-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-			       channels[i].chan,
-			       channels[i].power_level,
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-			       " (IEEE 802.11h required)" : "",
-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-				|| (channels[i].
-				    flag &
-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-			       ", IBSS",
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-			       "active/passive" : "passive only");
-
-	hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211A);
-	if (hw_mode) {
-		channels = hw_mode->channels;
-		count = hw_mode->num_channels;
-	} else {
-		channels = NULL;
-		count = 0;
-	}
-
-	len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
-		       "(802.11a):\n", count);
-
-	for (i = 0; i < count; i++)
-		len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-			       channels[i].chan,
-			       channels[i].power_level,
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-			       " (IEEE 802.11h required)" : "",
-			       (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-				|| (channels[i].
-				    flag &
-				    IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-			       ", IBSS",
-			       channels[i].
-			       flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-			       "active/passive" : "passive only");
-
-	return len;
+	/* all this shit doesn't belong into sysfs anyway */
+	return 0;
 }
 
 static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
@@ -8981,7 +8771,6 @@
 	&dev_attr_statistics.attr,
 	&dev_attr_status.attr,
 	&dev_attr_temperature.attr,
-	&dev_attr_tune.attr,
 	&dev_attr_tx_power.attr,
 
 	NULL
@@ -9109,7 +8898,7 @@
 	priv->data_retry_limit = -1;
 	priv->ieee_channels = NULL;
 	priv->ieee_rates = NULL;
-	priv->phymode = -1;
+	priv->band = IEEE80211_BAND_2GHZ;
 
 	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 	if (!err)
@@ -9175,7 +8964,7 @@
 	priv->qos_data.qos_cap.val = 0;
 #endif /* CONFIG_IWL4965_QOS */
 
-	iwl4965_set_rxon_channel(priv, MODE_IEEE80211G, 6);
+	iwl4965_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
 	iwl4965_setup_deferred_work(priv);
 	iwl4965_setup_rx_handlers(priv);
 
@@ -9226,7 +9015,6 @@
 		IWL_ERROR("initializing geos failed: %d\n", err);
 		goto out_free_channel_map;
 	}
-	iwl4965_reset_channel_flag(priv);
 
 	iwl4965_rate_control_register(priv->hw);
 	err = ieee80211_register_hw(priv->hw);
diff --git a/drivers/net/wireless/p54.h b/drivers/net/wireless/p54.h
index 744c866..06d2c67 100644
--- a/drivers/net/wireless/p54.h
+++ b/drivers/net/wireless/p54.h
@@ -64,10 +64,6 @@
 	unsigned int tx_hdr_len;
 	void *cached_vdcf;
 	unsigned int fw_var;
-	/* FIXME: this channels/modes/rates stuff sucks */
-	struct ieee80211_channel channels[14];
-	struct ieee80211_rate rates[12];
-	struct ieee80211_hw_mode modes[2];
 	struct ieee80211_tx_queue_stats tx_stats;
 };
 
diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c
index 5cda49a..218ff77 100644
--- a/drivers/net/wireless/p54common.c
+++ b/drivers/net/wireless/p54common.c
@@ -27,6 +27,46 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("prism54common");
 
+static struct ieee80211_rate p54_rates[] = {
+	{ .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 60, .hw_value = 4, },
+	{ .bitrate = 90, .hw_value = 5, },
+	{ .bitrate = 120, .hw_value = 6, },
+	{ .bitrate = 180, .hw_value = 7, },
+	{ .bitrate = 240, .hw_value = 8, },
+	{ .bitrate = 360, .hw_value = 9, },
+	{ .bitrate = 480, .hw_value = 10, },
+	{ .bitrate = 540, .hw_value = 11, },
+};
+
+static struct ieee80211_channel p54_channels[] = {
+	{ .center_freq = 2412, .hw_value = 1, },
+	{ .center_freq = 2417, .hw_value = 2, },
+	{ .center_freq = 2422, .hw_value = 3, },
+	{ .center_freq = 2427, .hw_value = 4, },
+	{ .center_freq = 2432, .hw_value = 5, },
+	{ .center_freq = 2437, .hw_value = 6, },
+	{ .center_freq = 2442, .hw_value = 7, },
+	{ .center_freq = 2447, .hw_value = 8, },
+	{ .center_freq = 2452, .hw_value = 9, },
+	{ .center_freq = 2457, .hw_value = 10, },
+	{ .center_freq = 2462, .hw_value = 11, },
+	{ .center_freq = 2467, .hw_value = 12, },
+	{ .center_freq = 2472, .hw_value = 13, },
+	{ .center_freq = 2484, .hw_value = 14, },
+};
+
+struct ieee80211_supported_band band_2GHz = {
+	.channels = p54_channels,
+	.n_channels = ARRAY_SIZE(p54_channels),
+	.bitrates = p54_rates,
+	.n_bitrates = ARRAY_SIZE(p54_rates),
+};
+
+
 void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
 {
 	struct p54_common *priv = dev->priv;
@@ -308,10 +348,10 @@
 	u16 freq = le16_to_cpu(hdr->freq);
 
 	rx_status.ssi = hdr->rssi;
-	rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */
-	rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5;
+	/* XX correct? */
+	rx_status.rate_idx = hdr->rate & 0xf;
 	rx_status.freq = freq;
-	rx_status.phymode = MODE_IEEE80211G;
+	rx_status.band = IEEE80211_BAND_2GHZ;
 	rx_status.antenna = hdr->antenna;
 	rx_status.mactime = le64_to_cpu(hdr->timestamp);
 	rx_status.flag |= RX_FLAG_TSFT;
@@ -547,7 +587,9 @@
 	txhdr->padding2 = 0;
 
 	/* TODO: add support for alternate retry TX rates */
-	rate = control->tx_rate;
+	rate = control->tx_rate->hw_value;
+	if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
+		rate |= 0x10;
 	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
 		rate |= 0x40;
 	else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
@@ -849,7 +891,7 @@
 {
 	int ret;
 
-	ret = p54_set_freq(dev, cpu_to_le16(conf->freq));
+	ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
 	p54_set_vdcf(dev);
 	return ret;
 }
@@ -944,7 +986,6 @@
 {
 	struct ieee80211_hw *dev;
 	struct p54_common *priv;
-	int i;
 
 	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
 	if (!dev)
@@ -953,18 +994,7 @@
 	priv = dev->priv;
 	priv->mode = IEEE80211_IF_TYPE_INVALID;
 	skb_queue_head_init(&priv->tx_queue);
-	memcpy(priv->channels, p54_channels, sizeof(p54_channels));
-	memcpy(priv->rates, p54_rates, sizeof(p54_rates));
-	priv->modes[1].mode = MODE_IEEE80211B;
-	priv->modes[1].num_rates = 4;
-	priv->modes[1].rates = priv->rates;
-	priv->modes[1].num_channels = ARRAY_SIZE(p54_channels);
-	priv->modes[1].channels = priv->channels;
-	priv->modes[0].mode = MODE_IEEE80211G;
-	priv->modes[0].num_rates = ARRAY_SIZE(p54_rates);
-	priv->modes[0].rates = priv->rates;
-	priv->modes[0].num_channels = ARRAY_SIZE(p54_channels);
-	priv->modes[0].channels = priv->channels;
+	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
 		    IEEE80211_HW_RX_INCLUDES_FCS;
 	dev->channel_change_time = 1000;	/* TODO: find actual value */
@@ -986,14 +1016,6 @@
 
 	p54_init_vdcf(dev);
 
-	for (i = 0; i < 2; i++) {
-		if (ieee80211_register_hwmode(dev, &priv->modes[i])) {
-			kfree(priv->cached_vdcf);
-			ieee80211_free_hw(dev);
-			return NULL;
-		}
-	}
-
 	return dev;
 }
 EXPORT_SYMBOL_GPL(p54_init_common);
diff --git a/drivers/net/wireless/p54common.h b/drivers/net/wireless/p54common.h
index a721334..dc9f4ce 100644
--- a/drivers/net/wireless/p54common.h
+++ b/drivers/net/wireless/p54common.h
@@ -251,79 +251,4 @@
 	__le16 frameburst;
 } __attribute__ ((packed));
 
-static const struct ieee80211_rate p54_rates[] = {
-	{ .rate = 10,
-	  .val = 0,
-	  .val2 = 0x10,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 20,
-	  .val = 1,
-	  .val2 = 0x11,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 55,
-	  .val = 2,
-	  .val2 = 0x12,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 110,
-	  .val = 3,
-	  .val2 = 0x13,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 60,
-	  .val = 4,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 90,
-	  .val = 5,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 120,
-	  .val = 6,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 180,
-	  .val = 7,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 240,
-	  .val = 8,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 360,
-	  .val = 9,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 480,
-	  .val = 10,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 540,
-	  .val = 11,
-	  .flags = IEEE80211_RATE_OFDM },
-};
-
-// TODO: just generate this..
-static const struct ieee80211_channel p54_channels[] = {
-	{ .chan = 1,
-	  .freq = 2412},
-	{ .chan = 2,
-	  .freq = 2417},
-	{ .chan = 3,
-	  .freq = 2422},
-	{ .chan = 4,
-	  .freq = 2427},
-	{ .chan = 5,
-	  .freq = 2432},
-	{ .chan = 6,
-	  .freq = 2437},
-	{ .chan = 7,
-	  .freq = 2442},
-	{ .chan = 8,
-	  .freq = 2447},
-	{ .chan = 9,
-	  .freq = 2452},
-	{ .chan = 10,
-	  .freq = 2457},
-	{ .chan = 11,
-	  .freq = 2462},
-	{ .chan = 12,
-	  .freq = 2467},
-	{ .chan = 13,
-	  .freq = 2472},
-	{ .chan = 14,
-	  .freq = 2484}
-};
-
 #endif /* PRISM54COMMON_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index b0e4ea7..4fa762b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -390,6 +390,10 @@
 	return (struct rt2x00_intf *)vif->drv_priv;
 }
 
+#define HWMODE_B	0
+#define HWMODE_G	1
+#define HWMODE_A	2
+
 /*
  * Details about the supported modes, rates and channels
  * of a particular chipset. This is used by rt2x00lib
@@ -644,11 +648,8 @@
 	 * IEEE80211 control structure.
 	 */
 	struct ieee80211_hw *hw;
-	struct ieee80211_hw_mode *hwmodes;
-	unsigned int curr_hwmode;
-#define HWMODE_B	0
-#define HWMODE_G	1
-#define HWMODE_A	2
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+	enum ieee80211_band curr_band;
 
 	/*
 	 * rfkill structure for RF state switching support.
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 20231e0..9fba485 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -152,7 +152,7 @@
 		      struct ieee80211_conf *conf, const int force_config)
 {
 	struct rt2x00lib_conf libconf;
-	struct ieee80211_hw_mode *mode;
+	struct ieee80211_supported_band *band;
 	struct ieee80211_rate *rate;
 	struct antenna_setup *default_ant = &rt2x00dev->default_ant;
 	struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
@@ -172,9 +172,9 @@
 	 * Check which configuration options have been
 	 * updated and should be send to the device.
 	 */
-	if (rt2x00dev->rx_status.phymode != conf->phymode)
+	if (rt2x00dev->rx_status.band != conf->channel->band)
 		flags |= CONFIG_UPDATE_PHYMODE;
-	if (rt2x00dev->rx_status.channel != conf->channel)
+	if (rt2x00dev->rx_status.freq != conf->channel->center_freq)
 		flags |= CONFIG_UPDATE_CHANNEL;
 	if (rt2x00dev->tx_power != conf->power_level)
 		flags |= CONFIG_UPDATE_TXPOWER;
@@ -229,33 +229,31 @@
 	memset(&libconf, 0, sizeof(libconf));
 
 	if (flags & CONFIG_UPDATE_PHYMODE) {
-		switch (conf->phymode) {
-		case MODE_IEEE80211A:
+		switch (conf->channel->band) {
+		case IEEE80211_BAND_5GHZ:
 			libconf.phymode = HWMODE_A;
 			break;
-		case MODE_IEEE80211B:
-			libconf.phymode = HWMODE_B;
-			break;
-		case MODE_IEEE80211G:
+		case IEEE80211_BAND_2GHZ:
+			/* Uh oh. what about B? */
 			libconf.phymode = HWMODE_G;
 			break;
 		default:
 			ERROR(rt2x00dev,
 			      "Attempt to configure unsupported mode (%d)"
-			      "Defaulting to 802.11b", conf->phymode);
+			      "Defaulting to 802.11b", conf->channel->band);
 			libconf.phymode = HWMODE_B;
 		}
 
-		mode = &rt2x00dev->hwmodes[libconf.phymode];
-		rate = &mode->rates[mode->num_rates - 1];
+		band = &rt2x00dev->bands[conf->channel->band];
+		rate = &band->bitrates[band->n_bitrates - 1];
 
 		libconf.basic_rates =
-		    DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
+		    DEVICE_GET_RATE_FIELD(rate->hw_value, RATEMASK) & DEV_BASIC_RATEMASK;
 	}
 
 	if (flags & CONFIG_UPDATE_CHANNEL) {
 		memcpy(&libconf.rf,
-		       &rt2x00dev->spec.channels[conf->channel_val],
+		       &rt2x00dev->spec.channels[conf->channel->hw_value],
 		       sizeof(libconf.rf));
 	}
 
@@ -301,12 +299,11 @@
 		rt2x00lib_reset_link_tuner(rt2x00dev);
 
 	if (flags & CONFIG_UPDATE_PHYMODE) {
-		rt2x00dev->curr_hwmode = libconf.phymode;
-		rt2x00dev->rx_status.phymode = conf->phymode;
+		rt2x00dev->curr_band = conf->channel->band;
+		rt2x00dev->rx_status.band = conf->channel->band;
 	}
 
-	rt2x00dev->rx_status.freq = conf->freq;
-	rt2x00dev->rx_status.channel = conf->channel;
+	rt2x00dev->rx_status.freq = conf->channel->center_freq;
 	rt2x00dev->tx_power = conf->power_level;
 
 	if (flags & CONFIG_UPDATE_ANTENNA) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 0df8062..83a72ae 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -550,19 +550,19 @@
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
-	struct ieee80211_hw_mode *mode;
+	struct ieee80211_supported_band *sband;
 	struct ieee80211_rate *rate;
 	struct ieee80211_hdr *hdr;
 	unsigned int i;
-	int val = 0;
+	int val = 0, idx = -1;
 	u16 fc;
 
 	/*
 	 * Update RX statistics.
 	 */
-	mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
-	for (i = 0; i < mode->num_rates; i++) {
-		rate = &mode->rates[i];
+	sband = &rt2x00dev->bands[rt2x00dev->curr_band];
+	for (i = 0; i < sband->n_bitrates; i++) {
+		rate = &sband->bitrates[i];
 
 		/*
 		 * When frame was received with an OFDM bitrate,
@@ -570,12 +570,12 @@
 		 * a CCK bitrate the signal is the rate in 0.5kbit/s.
 		 */
 		if (!rxdesc->ofdm)
-			val = DEVICE_GET_RATE_FIELD(rate->val, RATE);
+			val = DEVICE_GET_RATE_FIELD(rate->hw_value, RATE);
 		else
-			val = DEVICE_GET_RATE_FIELD(rate->val, PLCP);
+			val = DEVICE_GET_RATE_FIELD(rate->hw_value, PLCP);
 
 		if (val == rxdesc->signal) {
-			val = rate->val;
+			idx = i;
 			break;
 		}
 	}
@@ -590,7 +590,7 @@
 
 	rt2x00dev->link.qual.rx_success++;
 
-	rx_status->rate = val;
+	rx_status->rate_idx = idx;
 	rx_status->signal =
 	    rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
 	rx_status->ssi = rxdesc->rssi;
@@ -639,7 +639,7 @@
 	frame_control = le16_to_cpu(ieee80211hdr->frame_control);
 	seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl);
 
-	tx_rate = control->tx_rate;
+	tx_rate = control->tx_rate->hw_value;
 
 	/*
 	 * Check whether this frame is to be acked
@@ -658,7 +658,7 @@
 		} else
 			__clear_bit(ENTRY_TXD_ACK, &txdesc.flags);
 		if (control->rts_cts_rate)
-			tx_rate = control->rts_cts_rate;
+			tx_rate = control->rts_cts_rate->hw_value;
 	}
 
 	/*
@@ -760,54 +760,45 @@
 			      const int channel, const int tx_power,
 			      const int value)
 {
-	entry->chan = channel;
 	if (channel <= 14)
-		entry->freq = 2407 + (5 * channel);
+		entry->center_freq = 2407 + (5 * channel);
 	else
-		entry->freq = 5000 + (5 * channel);
-	entry->val = value;
-	entry->flag =
-	    IEEE80211_CHAN_W_IBSS |
-	    IEEE80211_CHAN_W_ACTIVE_SCAN |
-	    IEEE80211_CHAN_W_SCAN;
-	entry->power_level = tx_power;
-	entry->antenna_max = 0xff;
+		entry->center_freq = 5000 + (5 * channel);
+	entry->hw_value = value;
+	entry->max_power = tx_power;
+	entry->max_antenna_gain = 0xff;
 }
 
 static void rt2x00lib_rate(struct ieee80211_rate *entry,
 			   const int rate, const int mask,
 			   const int plcp, const int flags)
 {
-	entry->rate = rate;
-	entry->val =
+	entry->bitrate = rate;
+	entry->hw_value =
 	    DEVICE_SET_RATE_FIELD(rate, RATE) |
 	    DEVICE_SET_RATE_FIELD(mask, RATEMASK) |
 	    DEVICE_SET_RATE_FIELD(plcp, PLCP);
 	entry->flags = flags;
-	entry->val2 = entry->val;
-	if (entry->flags & IEEE80211_RATE_PREAMBLE2)
-		entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
-	entry->min_rssi_ack = 0;
-	entry->min_rssi_ack_delta = 0;
+	entry->hw_value_short = entry->hw_value;
+	if (entry->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+		entry->hw_value_short |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
 }
 
 static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
 				    struct hw_mode_spec *spec)
 {
 	struct ieee80211_hw *hw = rt2x00dev->hw;
-	struct ieee80211_hw_mode *hwmodes;
+	struct ieee80211_supported_band *sbands;
 	struct ieee80211_channel *channels;
 	struct ieee80211_rate *rates;
 	unsigned int i;
 	unsigned char tx_power;
 
-	hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL);
-	if (!hwmodes)
-		goto exit;
+	sbands = &rt2x00dev->bands[0];
 
 	channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL);
 	if (!channels)
-		goto exit_free_modes;
+		return -ENOMEM;
 
 	rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL);
 	if (!rates)
@@ -817,31 +808,31 @@
 	 * Initialize Rate list.
 	 */
 	rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,
-		       0x00, IEEE80211_RATE_CCK);
+		       0x00, 0);
 	rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,
-		       0x01, IEEE80211_RATE_CCK_2);
+		       0x01, IEEE80211_RATE_SHORT_PREAMBLE);
 	rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,
-		       0x02, IEEE80211_RATE_CCK_2);
+		       0x02, IEEE80211_RATE_SHORT_PREAMBLE);
 	rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,
-		       0x03, IEEE80211_RATE_CCK_2);
+		       0x03, IEEE80211_RATE_SHORT_PREAMBLE);
 
 	if (spec->num_rates > 4) {
 		rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,
-			       0x0b, IEEE80211_RATE_OFDM);
+			       0x0b, 0);
 		rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,
-			       0x0f, IEEE80211_RATE_OFDM);
+			       0x0f, 0);
 		rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,
-			       0x0a, IEEE80211_RATE_OFDM);
+			       0x0a, 0);
 		rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,
-			       0x0e, IEEE80211_RATE_OFDM);
+			       0x0e, 0);
 		rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,
-			       0x09, IEEE80211_RATE_OFDM);
+			       0x09, 0);
 		rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,
-			       0x0d, IEEE80211_RATE_OFDM);
+			       0x0d, 0);
 		rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,
-			       0x08, IEEE80211_RATE_OFDM);
+			       0x08, 0);
 		rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,
-			       0x0c, IEEE80211_RATE_OFDM);
+			       0x0c, 0);
 	}
 
 	/*
@@ -862,27 +853,27 @@
 	/*
 	 * Intitialize 802.11b
 	 * Rates: CCK.
-	 * Channels: OFDM.
+	 * Channels: 2.4 GHz
 	 */
 	if (spec->num_modes > HWMODE_B) {
-		hwmodes[HWMODE_B].mode = MODE_IEEE80211B;
-		hwmodes[HWMODE_B].num_channels = 14;
-		hwmodes[HWMODE_B].num_rates = 4;
-		hwmodes[HWMODE_B].channels = channels;
-		hwmodes[HWMODE_B].rates = rates;
+		sbands[IEEE80211_BAND_2GHZ].n_channels = 14;
+		sbands[IEEE80211_BAND_2GHZ].n_bitrates = 4;
+		sbands[IEEE80211_BAND_2GHZ].channels = channels;
+		sbands[IEEE80211_BAND_2GHZ].bitrates = rates;
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
 	}
 
 	/*
 	 * Intitialize 802.11g
 	 * Rates: CCK, OFDM.
-	 * Channels: OFDM.
+	 * Channels: 2.4 GHz
 	 */
 	if (spec->num_modes > HWMODE_G) {
-		hwmodes[HWMODE_G].mode = MODE_IEEE80211G;
-		hwmodes[HWMODE_G].num_channels = 14;
-		hwmodes[HWMODE_G].num_rates = spec->num_rates;
-		hwmodes[HWMODE_G].channels = channels;
-		hwmodes[HWMODE_G].rates = rates;
+		sbands[IEEE80211_BAND_2GHZ].n_channels = 14;
+		sbands[IEEE80211_BAND_2GHZ].n_bitrates = spec->num_rates;
+		sbands[IEEE80211_BAND_2GHZ].channels = channels;
+		sbands[IEEE80211_BAND_2GHZ].bitrates = rates;
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
 	}
 
 	/*
@@ -891,39 +882,17 @@
 	 * Channels: OFDM, UNII, HiperLAN2.
 	 */
 	if (spec->num_modes > HWMODE_A) {
-		hwmodes[HWMODE_A].mode = MODE_IEEE80211A;
-		hwmodes[HWMODE_A].num_channels = spec->num_channels - 14;
-		hwmodes[HWMODE_A].num_rates = spec->num_rates - 4;
-		hwmodes[HWMODE_A].channels = &channels[14];
-		hwmodes[HWMODE_A].rates = &rates[4];
+		sbands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14;
+		sbands[IEEE80211_BAND_5GHZ].n_bitrates = spec->num_rates - 4;
+		sbands[IEEE80211_BAND_5GHZ].channels = &channels[14];
+		sbands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
+		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
 	}
 
-	if (spec->num_modes > HWMODE_G &&
-	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G]))
-		goto exit_free_rates;
-
-	if (spec->num_modes > HWMODE_B &&
-	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B]))
-		goto exit_free_rates;
-
-	if (spec->num_modes > HWMODE_A &&
-	    ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A]))
-		goto exit_free_rates;
-
-	rt2x00dev->hwmodes = hwmodes;
-
 	return 0;
 
-exit_free_rates:
-	kfree(rates);
-
-exit_free_channels:
+ exit_free_channels:
 	kfree(channels);
-
-exit_free_modes:
-	kfree(hwmodes);
-
-exit:
 	ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
 	return -ENOMEM;
 }
@@ -933,11 +902,11 @@
 	if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
 		ieee80211_unregister_hw(rt2x00dev->hw);
 
-	if (likely(rt2x00dev->hwmodes)) {
-		kfree(rt2x00dev->hwmodes->channels);
-		kfree(rt2x00dev->hwmodes->rates);
-		kfree(rt2x00dev->hwmodes);
-		rt2x00dev->hwmodes = NULL;
+	if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
+		kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+		kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
+		rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+		rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
 	}
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 59e87a1..1dd3051 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -426,12 +426,12 @@
 	case ANTENNA_HW_DIVERSITY:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-				  (rt2x00dev->curr_hwmode != HWMODE_A));
+				  (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
 		break;
 	case ANTENNA_A:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-		if (rt2x00dev->curr_hwmode == HWMODE_A)
+		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
 		else
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
@@ -446,7 +446,7 @@
 	case ANTENNA_B:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-		if (rt2x00dev->curr_hwmode == HWMODE_A)
+		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
 		else
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
@@ -602,7 +602,7 @@
 	unsigned int i;
 	u32 reg;
 
-	if (rt2x00dev->curr_hwmode == HWMODE_A) {
+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		sel = antenna_sel_a;
 		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
 	} else {
@@ -616,10 +616,9 @@
 	rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
 
 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
-			   (rt2x00dev->curr_hwmode == HWMODE_B ||
-			    rt2x00dev->curr_hwmode == HWMODE_G));
+			   rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
-			   (rt2x00dev->curr_hwmode == HWMODE_A));
+			   rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
 
 	rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
 
@@ -698,9 +697,9 @@
 
 	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
 	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
-			   (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+			   rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ);
 	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
-			   (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
+			   rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ);
 
 	arg0 = rt2x00dev->led_reg & 0xff;
 	arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
@@ -798,7 +797,7 @@
 	/*
 	 * Determine r17 bounds.
 	 */
-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+	if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) {
 		low_bound = 0x28;
 		up_bound = 0x48;
 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
@@ -1544,8 +1543,10 @@
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 5, &word);
+/* XXX: removed for now
 	rt2x00_set_field32(&word, TXD_W5_TX_POWER,
 			   TXPOWER_TO_DEV(control->power_level));
+ */
 	rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
 	rt2x00_desc_write(txd, 5, word);
 
@@ -1637,7 +1638,7 @@
 		return 0;
 	}
 
-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
 			offset += 14;
 
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 4b5bde8..9cbc879 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -439,13 +439,13 @@
 	case ANTENNA_HW_DIVERSITY:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
 		temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
-		       && (rt2x00dev->curr_hwmode != HWMODE_A);
+		       && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
 		break;
 	case ANTENNA_A:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-		if (rt2x00dev->curr_hwmode == HWMODE_A)
+		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
 		else
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
@@ -460,7 +460,7 @@
 	case ANTENNA_B:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-		if (rt2x00dev->curr_hwmode == HWMODE_A)
+		if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
 		else
 			rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
@@ -555,7 +555,7 @@
 	unsigned int i;
 	u32 reg;
 
-	if (rt2x00dev->curr_hwmode == HWMODE_A) {
+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		sel = antenna_sel_a;
 		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
 	} else {
@@ -569,10 +569,9 @@
 	rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
 
 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
-			   (rt2x00dev->curr_hwmode == HWMODE_B ||
-			    rt2x00dev->curr_hwmode == HWMODE_G));
+			   (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
 	rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
-			   (rt2x00dev->curr_hwmode == HWMODE_A));
+			   (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
 
 	rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
 
@@ -644,9 +643,9 @@
 
 	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
 	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
-			   (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+			   (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ));
 	rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
-			   (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
+			   (rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ));
 
 	rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
 				    rt2x00dev->led_reg, REGISTER_TIMEOUT);
@@ -736,7 +735,7 @@
 	/*
 	 * Determine r17 bounds.
 	 */
-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
 		low_bound = 0x28;
 		up_bound = 0x48;
 
@@ -1278,8 +1277,10 @@
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 5, &word);
+/* XXX: removed for now
 	rt2x00_set_field32(&word, TXD_W5_TX_POWER,
 			   TXPOWER_TO_DEV(control->power_level));
+ */
 	rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
 	rt2x00_desc_write(txd, 5, word);
 
@@ -1370,7 +1371,7 @@
 		return 0;
 	}
 
-	if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+	if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
 		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
 			if (lna == 3 || lna == 2)
 				offset += 10;
diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h
index 2cbfe3c..082a11f 100644
--- a/drivers/net/wireless/rtl8180.h
+++ b/drivers/net/wireless/rtl8180.h
@@ -102,7 +102,7 @@
 	struct rtl8180_tx_ring tx_ring[4];
 	struct ieee80211_channel channels[14];
 	struct ieee80211_rate rates[12];
-	struct ieee80211_hw_mode modes[2];
+	struct ieee80211_supported_band band;
 	struct pci_dev *pdev;
 	u32 rx_conf;
 
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index 5e9a8ac..d0928c9 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -49,6 +49,41 @@
 
 MODULE_DEVICE_TABLE(pci, rtl8180_table);
 
+static const struct ieee80211_rate rtl818x_rates[] = {
+	{ .bitrate = 10, .hw_value = 0, },
+	{ .bitrate = 20, .hw_value = 1, },
+	{ .bitrate = 55, .hw_value = 2, },
+	{ .bitrate = 110, .hw_value = 3, },
+	{ .bitrate = 60, .hw_value = 4, },
+	{ .bitrate = 90, .hw_value = 5, },
+	{ .bitrate = 120, .hw_value = 6, },
+	{ .bitrate = 180, .hw_value = 7, },
+	{ .bitrate = 240, .hw_value = 8, },
+	{ .bitrate = 360, .hw_value = 9, },
+	{ .bitrate = 480, .hw_value = 10, },
+	{ .bitrate = 540, .hw_value = 11, },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+	{ .center_freq = 2412 },
+	{ .center_freq = 2417 },
+	{ .center_freq = 2422 },
+	{ .center_freq = 2427 },
+	{ .center_freq = 2432 },
+	{ .center_freq = 2437 },
+	{ .center_freq = 2442 },
+	{ .center_freq = 2447 },
+	{ .center_freq = 2452 },
+	{ .center_freq = 2457 },
+	{ .center_freq = 2462 },
+	{ .center_freq = 2467 },
+	{ .center_freq = 2472 },
+	{ .center_freq = 2484 },
+};
+
+
+
+
 void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
 {
 	struct rtl8180_priv *priv = dev->priv;
@@ -99,10 +134,10 @@
 			/* TODO: improve signal/rssi reporting */
 			rx_status.signal = flags2 & 0xFF;
 			rx_status.ssi = (flags2 >> 8) & 0x7F;
-			rx_status.rate = (flags >> 20) & 0xF;
-			rx_status.freq = dev->conf.freq;
-			rx_status.channel = dev->conf.channel;
-			rx_status.phymode = dev->conf.phymode;
+			/* XXX: is this correct? */
+			rx_status.rate_idx = (flags >> 20) & 0xF;
+			rx_status.freq = dev->conf.channel->center_freq;
+			rx_status.band = dev->conf.channel->band;
 			rx_status.mactime = le64_to_cpu(entry->tsft);
 			rx_status.flag |= RX_FLAG_TSFT;
 			if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR)
@@ -223,8 +258,9 @@
 				 skb->len, PCI_DMA_TODEVICE);
 
 	tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
-		   RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) |
-		   (control->rts_cts_rate << 19) | skb->len;
+		   RTL8180_TX_DESC_FLAG_LS |
+		   (control->tx_rate->hw_value << 24) |
+		   (control->rts_cts_rate->hw_value << 19) | skb->len;
 
 	if (priv->r8185)
 		tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
@@ -246,9 +282,9 @@
 		unsigned int remainder;
 
 		plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
-					(control->rate->rate * 2) / 10);
+					(control->tx_rate->bitrate * 2) / 10);
 		remainder = (16 * (skb->len + 4)) %
-			    ((control->rate->rate * 2) / 10);
+			    ((control->tx_rate->bitrate * 2) / 10);
 		if (remainder > 0 && remainder <= 6)
 			plcp_len |= 1 << 15;
 	}
@@ -261,8 +297,8 @@
 	entry->plcp_len = cpu_to_le16(plcp_len);
 	entry->tx_buf = cpu_to_le32(mapping);
 	entry->frame_len = cpu_to_le32(skb->len);
-	entry->flags2 = control->alt_retry_rate != -1 ?
-			control->alt_retry_rate << 4 : 0;
+	entry->flags2 = control->alt_retry_rate != NULL ?
+			control->alt_retry_rate->bitrate << 4 : 0;
 	entry->retry_limit = control->retry_limit;
 	entry->flags = cpu_to_le32(tx_flags);
 	__skb_queue_tail(&ring->queue, skb);
@@ -838,19 +874,19 @@
 		goto err_free_dev;
 	}
 
+	BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
+	BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
+
 	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
 	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
-	priv->modes[0].mode = MODE_IEEE80211G;
-	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
-	priv->modes[0].rates = priv->rates;
-	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
-	priv->modes[0].channels = priv->channels;
-	priv->modes[1].mode = MODE_IEEE80211B;
-	priv->modes[1].num_rates = 4;
-	priv->modes[1].rates = priv->rates;
-	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
-	priv->modes[1].channels = priv->channels;
-	priv->mode = IEEE80211_IF_TYPE_INVALID;
+
+	priv->band.band = IEEE80211_BAND_2GHZ;
+	priv->band.channels = priv->channels;
+	priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->band.bitrates = priv->rates;
+	priv->band.n_bitrates = 4;
+	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		     IEEE80211_HW_RX_INCLUDES_FCS;
 	dev->queues = 1;
@@ -879,15 +915,10 @@
 
 	priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
 	if (priv->r8185) {
-		if ((err = ieee80211_register_hwmode(dev, &priv->modes[0])))
-			goto err_iounmap;
-
+		priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
 		pci_try_set_mwi(pdev);
 	}
 
-	if ((err = ieee80211_register_hwmode(dev, &priv->modes[1])))
-		goto err_iounmap;
-
 	eeprom.data = dev;
 	eeprom.register_read = rtl8180_eeprom_register_read;
 	eeprom.register_write = rtl8180_eeprom_register_write;
@@ -950,8 +981,8 @@
 	for (i = 0; i < 14; i += 2) {
 		u16 txpwr;
 		eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr);
-		priv->channels[i].val = txpwr & 0xFF;
-		priv->channels[i + 1].val = txpwr >> 8;
+		priv->channels[i].hw_value = txpwr & 0xFF;
+		priv->channels[i + 1].hw_value = txpwr >> 8;
 	}
 
 	/* OFDM TX power */
@@ -959,8 +990,8 @@
 		for (i = 0; i < 14; i += 2) {
 			u16 txpwr;
 			eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr);
-			priv->channels[i].val |= (txpwr & 0xFF) << 8;
-			priv->channels[i + 1].val |= txpwr & 0xFF00;
+			priv->channels[i].hw_value |= (txpwr & 0xFF) << 8;
+			priv->channels[i + 1].hw_value |= txpwr & 0xFF00;
 		}
 	}
 
diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c
index 8293e19..5d47935 100644
--- a/drivers/net/wireless/rtl8180_grf5101.c
+++ b/drivers/net/wireless/rtl8180_grf5101.c
@@ -73,8 +73,9 @@
 				   struct ieee80211_conf *conf)
 {
 	struct rtl8180_priv *priv = dev->priv;
-	u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
-	u32 chan = conf->channel - 1;
+	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+	u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
+	u32 chan = channel - 1;
 
 	/* set TX power */
 	write_grf5101(dev, 0x15, 0x0);
diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c
index 98fe9fd..a34dfd3 100644
--- a/drivers/net/wireless/rtl8180_max2820.c
+++ b/drivers/net/wireless/rtl8180_max2820.c
@@ -78,8 +78,9 @@
 				   struct ieee80211_conf *conf)
 {
 	struct rtl8180_priv *priv = dev->priv;
-	unsigned int chan_idx = conf ? conf->channel - 1 : 0;
-	u32 txpw = priv->channels[chan_idx].val & 0xFF;
+	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+	unsigned int chan_idx = channel - 1;
+	u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
 	u32 chan = max2820_chan[chan_idx];
 
 	/* While philips SA2400 drive the PA bias from
diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl8180_rtl8225.c
index ef3832b..cd22781 100644
--- a/drivers/net/wireless/rtl8180_rtl8225.c
+++ b/drivers/net/wireless/rtl8180_rtl8225.c
@@ -261,8 +261,8 @@
 	u32 reg;
 	int i;
 
-	cck_power = priv->channels[channel - 1].val & 0xFF;
-	ofdm_power = priv->channels[channel - 1].val >> 8;
+	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
+	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
 
 	cck_power = min(cck_power, (u8)35);
 	ofdm_power = min(ofdm_power, (u8)35);
@@ -476,8 +476,8 @@
 	const u8 *tmp;
 	int i;
 
-	cck_power = priv->channels[channel - 1].val & 0xFF;
-	ofdm_power = priv->channels[channel - 1].val >> 8;
+	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
+	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
 
 	if (channel == 14)
 		tmp = rtl8225z2_tx_power_cck_ch14;
@@ -716,13 +716,14 @@
 				   struct ieee80211_conf *conf)
 {
 	struct rtl8180_priv *priv = dev->priv;
+	int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
 
 	if (priv->rf->init == rtl8225_rf_init)
-		rtl8225_rf_set_tx_power(dev, conf->channel);
+		rtl8225_rf_set_tx_power(dev, chan);
 	else
-		rtl8225z2_rf_set_tx_power(dev, conf->channel);
+		rtl8225z2_rf_set_tx_power(dev, chan);
 
-	rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
+	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
 	msleep(10);
 
 	if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c
index e08ace7..0311b4e 100644
--- a/drivers/net/wireless/rtl8180_sa2400.c
+++ b/drivers/net/wireless/rtl8180_sa2400.c
@@ -80,8 +80,9 @@
 				  struct ieee80211_conf *conf)
 {
 	struct rtl8180_priv *priv = dev->priv;
-	u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
-	u32 chan = sa2400_chan[conf->channel - 1];
+	int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+	u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
+	u32 chan = sa2400_chan[channel - 1];
 
 	write_sa2400(dev, 7, txpw);
 
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index 8680a0b..076d88b 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -71,7 +71,7 @@
 	/* rtl8187 specific */
 	struct ieee80211_channel channels[14];
 	struct ieee80211_rate rates[12];
-	struct ieee80211_hw_mode modes[2];
+	struct ieee80211_supported_band band;
 	struct usb_device *udev;
 	u32 rx_conf;
 	u16 txpwr_base;
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index f445059..6ef6799 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -45,6 +45,38 @@
 
 MODULE_DEVICE_TABLE(usb, rtl8187_table);
 
+static const struct ieee80211_rate rtl818x_rates[] = {
+	{ .bitrate = 10, .hw_value = 0, },
+	{ .bitrate = 20, .hw_value = 1, },
+	{ .bitrate = 55, .hw_value = 2, },
+	{ .bitrate = 110, .hw_value = 3, },
+	{ .bitrate = 60, .hw_value = 4, },
+	{ .bitrate = 90, .hw_value = 5, },
+	{ .bitrate = 120, .hw_value = 6, },
+	{ .bitrate = 180, .hw_value = 7, },
+	{ .bitrate = 240, .hw_value = 8, },
+	{ .bitrate = 360, .hw_value = 9, },
+	{ .bitrate = 480, .hw_value = 10, },
+	{ .bitrate = 540, .hw_value = 11, },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+	{ .center_freq = 2412 },
+	{ .center_freq = 2417 },
+	{ .center_freq = 2422 },
+	{ .center_freq = 2427 },
+	{ .center_freq = 2432 },
+	{ .center_freq = 2437 },
+	{ .center_freq = 2442 },
+	{ .center_freq = 2447 },
+	{ .center_freq = 2452 },
+	{ .center_freq = 2457 },
+	{ .center_freq = 2462 },
+	{ .center_freq = 2467 },
+	{ .center_freq = 2472 },
+	{ .center_freq = 2484 },
+};
+
 static void rtl8187_iowrite_async_cb(struct urb *urb)
 {
 	kfree(urb->context);
@@ -146,8 +178,8 @@
 
 	flags = skb->len;
 	flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
-	flags |= control->rts_cts_rate << 19;
-	flags |= control->tx_rate << 24;
+	flags |= control->rts_cts_rate->hw_value << 19;
+	flags |= control->tx_rate->hw_value << 24;
 	if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data))
 		flags |= RTL8187_TX_FLAG_MORE_FRAG;
 	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
@@ -225,10 +257,9 @@
 	rx_status.antenna = (hdr->signal >> 7) & 1;
 	rx_status.signal = 64 - min(hdr->noise, (u8)64);
 	rx_status.ssi = signal;
-	rx_status.rate = rate;
-	rx_status.freq = dev->conf.freq;
-	rx_status.channel = dev->conf.channel;
-	rx_status.phymode = dev->conf.phymode;
+	rx_status.rate_idx = rate;
+	rx_status.freq = dev->conf.channel->center_freq;
+	rx_status.band = dev->conf.channel->band;
 	rx_status.mactime = le64_to_cpu(hdr->mac_time);
 	rx_status.flag |= RX_FLAG_TSFT;
 	if (flags & (1 << 13))
@@ -682,19 +713,22 @@
 	usb_get_dev(udev);
 
 	skb_queue_head_init(&priv->rx_queue);
+
+	BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
+	BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
+
 	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
 	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
 	priv->map = (struct rtl818x_csr *)0xFF00;
-	priv->modes[0].mode = MODE_IEEE80211G;
-	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
-	priv->modes[0].rates = priv->rates;
-	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
-	priv->modes[0].channels = priv->channels;
-	priv->modes[1].mode = MODE_IEEE80211B;
-	priv->modes[1].num_rates = 4;
-	priv->modes[1].rates = priv->rates;
-	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
-	priv->modes[1].channels = priv->channels;
+
+	priv->band.band = IEEE80211_BAND_2GHZ;
+	priv->band.channels = priv->channels;
+	priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->band.bitrates = priv->rates;
+	priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
+	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+
+
 	priv->mode = IEEE80211_IF_TYPE_MNTR;
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		     IEEE80211_HW_RX_INCLUDES_FCS;
@@ -703,10 +737,6 @@
 	dev->max_rssi = 65;
 	dev->max_signal = 64;
 
-	for (i = 0; i < 2; i++)
-		if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
-			goto err_free_dev;
-
 	eeprom.data = dev;
 	eeprom.register_read = rtl8187_eeprom_register_read;
 	eeprom.register_write = rtl8187_eeprom_register_write;
@@ -730,20 +760,20 @@
 	for (i = 0; i < 3; i++) {
 		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
 				  &txpwr);
-		(*channel++).val = txpwr & 0xFF;
-		(*channel++).val = txpwr >> 8;
+		(*channel++).hw_value = txpwr & 0xFF;
+		(*channel++).hw_value = txpwr >> 8;
 	}
 	for (i = 0; i < 2; i++) {
 		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
 				  &txpwr);
-		(*channel++).val = txpwr & 0xFF;
-		(*channel++).val = txpwr >> 8;
+		(*channel++).hw_value = txpwr & 0xFF;
+		(*channel++).hw_value = txpwr >> 8;
 	}
 	for (i = 0; i < 2; i++) {
 		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
 				  &txpwr);
-		(*channel++).val = txpwr & 0xFF;
-		(*channel++).val = txpwr >> 8;
+		(*channel++).hw_value = txpwr & 0xFF;
+		(*channel++).hw_value = txpwr >> 8;
 	}
 
 	eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
index b713de1..9146387 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -283,8 +283,8 @@
 	u32 reg;
 	int i;
 
-	cck_power = priv->channels[channel - 1].val & 0xF;
-	ofdm_power = priv->channels[channel - 1].val >> 4;
+	cck_power = priv->channels[channel - 1].hw_value & 0xF;
+	ofdm_power = priv->channels[channel - 1].hw_value >> 4;
 
 	cck_power = min(cck_power, (u8)11);
 	ofdm_power = min(ofdm_power, (u8)35);
@@ -500,8 +500,8 @@
 	u32 reg;
 	int i;
 
-	cck_power = priv->channels[channel - 1].val & 0xF;
-	ofdm_power = priv->channels[channel - 1].val >> 4;
+	cck_power = priv->channels[channel - 1].hw_value & 0xF;
+	ofdm_power = priv->channels[channel - 1].hw_value >> 4;
 
 	cck_power = min(cck_power, (u8)15);
 	cck_power += priv->txpwr_base & 0xF;
@@ -735,13 +735,14 @@
 				   struct ieee80211_conf *conf)
 {
 	struct rtl8187_priv *priv = dev->priv;
+	int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
 
 	if (priv->rf->init == rtl8225_rf_init)
-		rtl8225_rf_set_tx_power(dev, conf->channel);
+		rtl8225_rf_set_tx_power(dev, chan);
 	else
-		rtl8225z2_rf_set_tx_power(dev, conf->channel);
+		rtl8225z2_rf_set_tx_power(dev, chan);
 
-	rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
+	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
 	msleep(10);
 }
 
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
index 1e7d6f8..4f7d38f 100644
--- a/drivers/net/wireless/rtl818x.h
+++ b/drivers/net/wireless/rtl818x.h
@@ -175,74 +175,4 @@
 	void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
 };
 
-static const struct ieee80211_rate rtl818x_rates[] = {
-	{ .rate = 10,
-	  .val = 0,
-	  .flags = IEEE80211_RATE_CCK },
-	{ .rate = 20,
-	  .val = 1,
-	  .flags = IEEE80211_RATE_CCK },
-	{ .rate = 55,
-	  .val = 2,
-	  .flags = IEEE80211_RATE_CCK },
-	{ .rate = 110,
-	  .val = 3,
-	  .flags = IEEE80211_RATE_CCK },
-	{ .rate = 60,
-	  .val = 4,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 90,
-	  .val = 5,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 120,
-	  .val = 6,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 180,
-	  .val = 7,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 240,
-	  .val = 8,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 360,
-	  .val = 9,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 480,
-	  .val = 10,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 540,
-	  .val = 11,
-	  .flags = IEEE80211_RATE_OFDM },
-};
-
-static const struct ieee80211_channel rtl818x_channels[] = {
-	{ .chan = 1,
-	  .freq = 2412},
-	{ .chan = 2,
-	  .freq = 2417},
-	{ .chan = 3,
-	  .freq = 2422},
-	{ .chan = 4,
-	  .freq = 2427},
-	{ .chan = 5,
-	  .freq = 2432},
-	{ .chan = 6,
-	  .freq = 2437},
-	{ .chan = 7,
-	  .freq = 2442},
-	{ .chan = 8,
-	  .freq = 2447},
-	{ .chan = 9,
-	  .freq = 2452},
-	{ .chan = 10,
-	  .freq = 2457},
-	{ .chan = 11,
-	  .freq = 2462},
-	{ .chan = 12,
-	  .freq = 2467},
-	{ .chan = 13,
-	  .freq = 2472},
-	{ .chan = 14,
-	  .freq = 2484}
-};
-
 #endif /* RTL818X_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 99e5b03..e3fba6f 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -986,7 +986,7 @@
 	return 0;
 }
 
-static int set_mandatory_rates(struct zd_chip *chip, int mode)
+static int set_mandatory_rates(struct zd_chip *chip, int gmode)
 {
 	u32 rates;
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
@@ -994,17 +994,12 @@
 	 * that the device is supporting. Until further notice we should try
 	 * to support 802.11g also for full speed USB.
 	 */
-	switch (mode) {
-	case MODE_IEEE80211B:
+	if (!gmode)
 		rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
-		break;
-	case MODE_IEEE80211G:
+	else
 		rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
 			CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
-		break;
-	default:
-		return -EINVAL;
-	}
+
 	return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
 }
 
@@ -1108,7 +1103,7 @@
 	 * It might be discussed, whether we should suppport pure b mode for
 	 * full speed USB.
 	 */
-	r = set_mandatory_rates(chip, MODE_IEEE80211G);
+	r = set_mandatory_rates(chip, 1);
 	if (r)
 		goto out;
 	/* Disabling interrupts is certainly a smart thing here.
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
index 7c277ec..d8dc41e 100644
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
@@ -65,16 +65,14 @@
 
 static void unmask_bg_channels(struct ieee80211_hw *hw,
 	const struct channel_range *range,
-	struct ieee80211_hw_mode *mode)
+	struct ieee80211_supported_band *sband)
 {
 	u8 channel;
 
 	for (channel = range->start; channel < range->end; channel++) {
 		struct ieee80211_channel *chan =
-			&mode->channels[CHAN_TO_IDX(channel)];
-		chan->flag |= IEEE80211_CHAN_W_SCAN |
-			IEEE80211_CHAN_W_ACTIVE_SCAN |
-			IEEE80211_CHAN_W_IBSS;
+			&sband->channels[CHAN_TO_IDX(channel)];
+		chan->flags = 0;
 	}
 }
 
@@ -97,7 +95,6 @@
 		range = zd_channel_range(ZD_REGDOMAIN_FCC);
 	}
 
-	unmask_bg_channels(hw, range, &mac->modes[0]);
-	unmask_bg_channels(hw, range, &mac->modes[1]);
+	unmask_bg_channels(hw, range, &mac->band);
 }
 
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 76ef2d8..21b6534 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -34,76 +34,61 @@
 
 /* This table contains the hardware specific values for the modulation rates. */
 static const struct ieee80211_rate zd_rates[] = {
-	{ .rate = 10,
-	  .val = ZD_CCK_RATE_1M,
-	  .flags = IEEE80211_RATE_CCK },
-	{ .rate = 20,
-	  .val = ZD_CCK_RATE_2M,
-	  .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 55,
-	  .val = ZD_CCK_RATE_5_5M,
-	  .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 110,
-	  .val = ZD_CCK_RATE_11M,
-	  .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
-	  .flags = IEEE80211_RATE_CCK_2 },
-	{ .rate = 60,
-	  .val = ZD_OFDM_RATE_6M,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 90,
-	  .val = ZD_OFDM_RATE_9M,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 120,
-	  .val = ZD_OFDM_RATE_12M,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 180,
-	  .val = ZD_OFDM_RATE_18M,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 240,
-	  .val = ZD_OFDM_RATE_24M,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 360,
-	  .val = ZD_OFDM_RATE_36M,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 480,
-	  .val = ZD_OFDM_RATE_48M,
-	  .flags = IEEE80211_RATE_OFDM },
-	{ .rate = 540,
-	  .val = ZD_OFDM_RATE_54M,
-	  .flags = IEEE80211_RATE_OFDM },
+	{ .bitrate = 10,
+	  .hw_value = ZD_CCK_RATE_1M, },
+	{ .bitrate = 20,
+	  .hw_value = ZD_CCK_RATE_2M,
+	  .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 55,
+	  .hw_value = ZD_CCK_RATE_5_5M,
+	  .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 110,
+	  .hw_value = ZD_CCK_RATE_11M,
+	  .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 60,
+	  .hw_value = ZD_OFDM_RATE_6M,
+	  .flags = 0 },
+	{ .bitrate = 90,
+	  .hw_value = ZD_OFDM_RATE_9M,
+	  .flags = 0 },
+	{ .bitrate = 120,
+	  .hw_value = ZD_OFDM_RATE_12M,
+	  .flags = 0 },
+	{ .bitrate = 180,
+	  .hw_value = ZD_OFDM_RATE_18M,
+	  .flags = 0 },
+	{ .bitrate = 240,
+	  .hw_value = ZD_OFDM_RATE_24M,
+	  .flags = 0 },
+	{ .bitrate = 360,
+	  .hw_value = ZD_OFDM_RATE_36M,
+	  .flags = 0 },
+	{ .bitrate = 480,
+	  .hw_value = ZD_OFDM_RATE_48M,
+	  .flags = 0 },
+	{ .bitrate = 540,
+	  .hw_value = ZD_OFDM_RATE_54M,
+	  .flags = 0 },
 };
 
 static const struct ieee80211_channel zd_channels[] = {
-	{ .chan = 1,
-	  .freq = 2412},
-	{ .chan = 2,
-	  .freq = 2417},
-	{ .chan = 3,
-	  .freq = 2422},
-	{ .chan = 4,
-	  .freq = 2427},
-	{ .chan = 5,
-	  .freq = 2432},
-	{ .chan = 6,
-	  .freq = 2437},
-	{ .chan = 7,
-	  .freq = 2442},
-	{ .chan = 8,
-	  .freq = 2447},
-	{ .chan = 9,
-	  .freq = 2452},
-	{ .chan = 10,
-	  .freq = 2457},
-	{ .chan = 11,
-	  .freq = 2462},
-	{ .chan = 12,
-	  .freq = 2467},
-	{ .chan = 13,
-	  .freq = 2472},
-	{ .chan = 14,
-	  .freq = 2484}
+	{ .center_freq = 2412, .hw_value = 1 },
+	{ .center_freq = 2417, .hw_value = 2 },
+	{ .center_freq = 2422, .hw_value = 3 },
+	{ .center_freq = 2427, .hw_value = 4 },
+	{ .center_freq = 2432, .hw_value = 5 },
+	{ .center_freq = 2437, .hw_value = 6 },
+	{ .center_freq = 2442, .hw_value = 7 },
+	{ .center_freq = 2447, .hw_value = 8 },
+	{ .center_freq = 2452, .hw_value = 9 },
+	{ .center_freq = 2457, .hw_value = 10 },
+	{ .center_freq = 2462, .hw_value = 11 },
+	{ .center_freq = 2467, .hw_value = 12 },
+	{ .center_freq = 2472, .hw_value = 13 },
+	{ .center_freq = 2484, .hw_value = 14 },
 };
 
 static void housekeeping_init(struct zd_mac *mac);
@@ -503,7 +488,9 @@
 
 	ZD_ASSERT(frag_len <= 0xffff);
 
-	cs->modulation = control->tx_rate;
+	cs->modulation = control->tx_rate->hw_value;
+	if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
+		cs->modulation = control->tx_rate->hw_value_short;
 
 	cs->tx_length = cpu_to_le16(frag_len);
 
@@ -631,6 +618,8 @@
 	int bad_frame = 0;
 	u16 fc;
 	bool is_qos, is_4addr, need_padding;
+	int i;
+	u8 rate;
 
 	if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
 	             FCS_LEN + sizeof(struct rx_status))
@@ -660,14 +649,19 @@
 		}
 	}
 
-	stats.channel = _zd_chip_get_channel(&mac->chip);
-	stats.freq = zd_channels[stats.channel - 1].freq;
-	stats.phymode = MODE_IEEE80211G;
+	stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
+	stats.band = IEEE80211_BAND_2GHZ;
 	stats.ssi = status->signal_strength;
 	stats.signal = zd_rx_qual_percent(buffer,
 		                          length - sizeof(struct rx_status),
 		                          status);
-	stats.rate = zd_rx_rate(buffer, status);
+
+	rate = zd_rx_rate(buffer, status);
+
+	/* todo: return index in the big switches in zd_rx_rate instead */
+	for (i = 0; i < mac->band.n_bitrates; i++)
+		if (rate == mac->band.bitrates[i].hw_value)
+			stats.rate_idx = i;
 
 	length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
 	buffer += ZD_PLCP_HEADER_SIZE;
@@ -736,7 +730,7 @@
 static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
-	return zd_chip_set_channel(&mac->chip, conf->channel);
+	return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
 }
 
 static int zd_op_config_interface(struct ieee80211_hw *hw,
@@ -894,7 +888,6 @@
 {
 	struct zd_mac *mac;
 	struct ieee80211_hw *hw;
-	int i;
 
 	hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
 	if (!hw) {
@@ -912,19 +905,14 @@
 
 	memcpy(mac->channels, zd_channels, sizeof(zd_channels));
 	memcpy(mac->rates, zd_rates, sizeof(zd_rates));
-	mac->modes[0].mode = MODE_IEEE80211G;
-	mac->modes[0].num_rates = ARRAY_SIZE(zd_rates);
-	mac->modes[0].rates = mac->rates;
-	mac->modes[0].num_channels = ARRAY_SIZE(zd_channels);
-	mac->modes[0].channels = mac->channels;
-	mac->modes[1].mode = MODE_IEEE80211B;
-	mac->modes[1].num_rates = 4;
-	mac->modes[1].rates = mac->rates;
-	mac->modes[1].num_channels = ARRAY_SIZE(zd_channels);
-	mac->modes[1].channels = mac->channels;
+	mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
+	mac->band.bitrates = mac->rates;
+	mac->band.n_channels = ARRAY_SIZE(zd_channels);
+	mac->band.channels = mac->channels;
 
-	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		     IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
+	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
+
+	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS;
 	hw->max_rssi = 100;
 	hw->max_signal = 100;
 
@@ -933,14 +921,6 @@
 
 	skb_queue_head_init(&mac->ack_wait_queue);
 
-	for (i = 0; i < 2; i++) {
-		if (ieee80211_register_hwmode(hw, &mac->modes[i])) {
-			dev_dbg_f(&intf->dev, "cannot register hwmode\n");
-			ieee80211_free_hw(hw);
-			return NULL;
-		}
-	}
-
 	zd_chip_init(&mac->chip, hw, intf);
 	housekeeping_init(mac);
 	INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 2dde108..67dea97 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -185,7 +185,7 @@
 	struct sk_buff_head ack_wait_queue;
 	struct ieee80211_channel channels[14];
 	struct ieee80211_rate rates[12];
-	struct ieee80211_hw_mode modes[2];
+	struct ieee80211_supported_band band;
 
 	/* Short preamble (used for RTS/CTS) */
 	unsigned int short_preamble:1;