aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-09-09 17:33:45 -0700
committerDavid S. Miller <davem@davemloft.net>2009-09-09 17:33:45 -0700
commitea6a634ef7f0ab1d1f48ba0ad4f50e96d6065312 (patch)
treefbf291540b824183e0d9292906e9570fd344ebaa
parentfa1a9c681377c57e233038e50479e7d7a5cc3108 (diff)
parentb2e3abdc708f8c0eff194af25362fdb239abe241 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
-rw-r--r--Documentation/feature-removal-schedule.txt29
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/net/b44.c10
-rw-r--r--drivers/net/wireless/Kconfig57
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c420
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c23
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c30
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h1
-rw-r--r--drivers/net/wireless/ath/regd.h6
-rw-r--r--drivers/net/wireless/ath/regd_common.h6
-rw-r--r--drivers/net/wireless/b43/Kconfig4
-rw-r--r--drivers/net/wireless/b43/b43.h30
-rw-r--r--drivers/net/wireless/b43/debugfs.c67
-rw-r--r--drivers/net/wireless/b43/debugfs.h3
-rw-r--r--drivers/net/wireless/b43/dma.c31
-rw-r--r--drivers/net/wireless/b43/dma.h3
-rw-r--r--drivers/net/wireless/b43/main.c460
-rw-r--r--drivers/net/wireless/b43/main.h4
-rw-r--r--drivers/net/wireless/b43/phy_common.c1
-rw-r--r--drivers/net/wireless/b43/phy_common.h3
-rw-r--r--drivers/net/wireless/b43/phy_g.c7
-rw-r--r--drivers/net/wireless/b43/phy_g.h3
-rw-r--r--drivers/net/wireless/b43/pio.c71
-rw-r--r--drivers/net/wireless/b43/pio.h6
-rw-r--r--drivers/net/wireless/b43/sysfs.c3
-rw-r--r--drivers/net/wireless/b43/xmit.c10
-rw-r--r--drivers/net/wireless/b43legacy/main.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c2
-rw-r--r--drivers/ssb/Kconfig14
-rw-r--r--drivers/ssb/Makefile1
-rw-r--r--drivers/ssb/main.c64
-rw-r--r--drivers/ssb/scan.c11
-rw-r--r--drivers/ssb/sdio.c610
-rw-r--r--drivers/ssb/ssb_private.h40
-rw-r--r--include/linux/ssb/ssb.h25
-rw-r--r--net/wireless/Kconfig11
-rw-r--r--net/wireless/scan.c41
52 files changed, 1673 insertions, 539 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 09e031c5588..ad522e3d3d8 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -6,6 +6,35 @@ be removed from this file.
---------------------------
+What: PRISM54
+When: 2.6.34
+
+Why: prism54 FullMAC PCI / Cardbus devices used to be supported only by the
+ prism54 wireless driver. After Intersil stopped selling these
+ devices in preference for the newer more flexible SoftMAC devices
+ a SoftMAC device driver was required and prism54 did not support
+ them. The p54pci driver now exists and has been present in the kernel for
+ a while. This driver supports both SoftMAC devices and FullMAC devices.
+ The main difference between these devices was the amount of memory which
+ could be used for the firmware. The SoftMAC devices support a smaller
+ amount of memory. Because of this the SoftMAC firmware fits into FullMAC
+ devices's memory. p54pci supports not only PCI / Cardbus but also USB
+ and SPI. Since p54pci supports all devices prism54 supports
+ you will have a conflict. I'm not quite sure how distributions are
+ handling this conflict right now. prism54 was kept around due to
+ claims users may experience issues when using the SoftMAC driver.
+ Time has passed users have not reported issues. If you use prism54
+ and for whatever reason you cannot use p54pci please let us know!
+ E-mail us at: linux-wireless@vger.kernel.org
+
+ For more information see the p54 wiki page:
+
+ http://wireless.kernel.org/en/users/Drivers/p54
+
+Who: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+---------------------------
+
What: IRQF_SAMPLE_RANDOM
Check: IRQF_SAMPLE_RANDOM
When: July 2009
diff --git a/MAINTAINERS b/MAINTAINERS
index 0ab47e7fc2e..6e2e12fd9ef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -876,6 +876,7 @@ M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
M: Bob Copeland <me@bobcopeland.com>
L: linux-wireless@vger.kernel.org
L: ath5k-devel@lists.ath5k.org
+W: http://wireless.kernel.org/en/users/Drivers/ath5k
S: Maintained
F: drivers/net/wireless/ath/ath5k/
@@ -887,6 +888,7 @@ M: Vasanthakumar Thiagarajan <vasanth@atheros.com>
M: Senthil Balasubramanian <senthilkumar@atheros.com>
L: linux-wireless@vger.kernel.org
L: ath9k-devel@lists.ath9k.org
+W: http://wireless.kernel.org/en/users/Drivers/ath9k
S: Supported
F: drivers/net/wireless/ath/ath9k/
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 951735c9ec0..0189dcd36f3 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1303,10 +1303,13 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind)
& MDIO_CTRL_MAXF_MASK)));
break;
case SSB_BUSTYPE_PCI:
- case SSB_BUSTYPE_PCMCIA:
bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
(0x0d & MDIO_CTRL_MAXF_MASK)));
break;
+ case SSB_BUSTYPE_PCMCIA:
+ case SSB_BUSTYPE_SDIO:
+ WARN_ON(1); /* A device with this bus does not exist. */
+ break;
}
br32(bp, B44_MDIO_CTRL);
@@ -1764,10 +1767,13 @@ static void b44_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *inf
case SSB_BUSTYPE_PCI:
strlcpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
break;
- case SSB_BUSTYPE_PCMCIA:
case SSB_BUSTYPE_SSB:
strlcpy(info->bus_info, "SSB", sizeof(info->bus_info));
break;
+ case SSB_BUSTYPE_PCMCIA:
+ case SSB_BUSTYPE_SDIO:
+ WARN_ON(1); /* A device with this bus does not exist. */
+ break;
}
}
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index a8871a84d87..ad89d23968d 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -275,51 +275,26 @@ config PCMCIA_WL3501
micro support for ethtool.
config PRISM54
- tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus'
+ tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
depends on PCI && EXPERIMENTAL && WLAN_80211
select WIRELESS_EXT
select FW_LOADER
---help---
- Enable PCI and Cardbus support for the following chipset based cards:
-
- ISL3880 - Prism GT 802.11 b/g
- ISL3877 - Prism Indigo 802.11 a
- ISL3890 - Prism Duette 802.11 a/b/g
-
- For a complete list of supported cards visit <http://prism54.org>.
- Here is the latest confirmed list of supported cards:
-
- 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 (version 1)
- Allnet ALL0271 PCI Card
- Compex WL54G Cardbus Card
- Corega CG-WLCB54GT Cardbus Card
- D-Link Air Plus Xtreme G A1 Cardbus Card aka DWL-g650
- I-O Data WN-G54/CB Cardbus Card
- Kobishi XG-300 aka Z-Com Cardbus Card
- Netgear WG511 Cardbus Card
- Ovislink WL-5400PCI PCI Card
- Peabird WLG-PCI PCI Card
- Sitecom WL-100i Cardbus Card
- Sitecom WL-110i PCI Card
- SMC2802W - EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card
- SMC2835W - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
- SMC2835W-V2 - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
- Z-Com XG-900 PCI Card
- Zyxel G-100 Cardbus Card
-
- If you enable this you will need a firmware file as well.
- You will need to copy this to /usr/lib/hotplug/firmware/isl3890.
- You can get this non-GPL'd firmware file from the Prism54 project page:
- <http://prism54.org>
- You will also need the /etc/hotplug/firmware.agent script from
- a current hotplug package.
-
- Note: You need a motherboard with DMA support to use any of these cards
-
- If you want to compile the driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/kbuild/modules.txt>.
- The module will be called prism54.
+ This enables support for FullMAC PCI/Cardbus prism54 devices. This
+ driver is now deprecated in favor for the SoftMAC driver, p54pci.
+ p54pci supports FullMAC PCI/Cardbus devices as well. For details on
+ the scheduled removal of this driver on the kernel see the feature
+ removal schedule:
+
+ Documentation/feature-removal-schedule.txt
+
+ For more information refer to the p54 wiki:
+
+ http://wireless.kernel.org/en/users/Drivers/p54
+
+ Note: You need a motherboard with DMA support to use any of these cards
+
+ When built as module you get the module prism54
config USB_ZD1201
tristate "USB ZD1201 based Wireless device support"
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index df86f70cd81..b3e5cf3735b 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -396,6 +396,136 @@ static struct ar9170_phy_init ar5416_phy_init[] = {
{ 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
};
+/*
+ * look up a certain register in ar5416_phy_init[] and return the init. value
+ * for the band and bandwidth given. Return 0 if register address not found.
+ */
+static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz)
+{
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
+ if (ar5416_phy_init[i].reg != reg)
+ continue;
+
+ if (is_2ghz) {
+ if (is_40mhz)
+ return ar5416_phy_init[i]._2ghz_40;
+ else
+ return ar5416_phy_init[i]._2ghz_20;
+ } else {
+ if (is_40mhz)
+ return ar5416_phy_init[i]._5ghz_40;
+ else
+ return ar5416_phy_init[i]._5ghz_20;
+ }
+ }
+ return 0;
+}
+
+/*
+ * initialize some phy regs from eeprom values in modal_header[]
+ * acc. to band and bandwith
+ */
+static int ar9170_init_phy_from_eeprom(struct ar9170 *ar,
+ bool is_2ghz, bool is_40mhz)
+{
+ static const u8 xpd2pd[16] = {
+ 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2,
+ 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2
+ };
+ u32 defval, newval;
+ /* pointer to the modal_header acc. to band */
+ struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz];
+
+ ar9170_regwrite_begin(ar);
+
+ /* ant common control (index 0) */
+ newval = le32_to_cpu(m->antCtrlCommon);
+ ar9170_regwrite(0x1c5964, newval);
+
+ /* ant control chain 0 (index 1) */
+ newval = le32_to_cpu(m->antCtrlChain[0]);
+ ar9170_regwrite(0x1c5960, newval);
+
+ /* ant control chain 2 (index 2) */
+ newval = le32_to_cpu(m->antCtrlChain[1]);
+ ar9170_regwrite(0x1c7960, newval);
+
+ /* SwSettle (index 3) */
+ if (!is_40mhz) {
+ defval = ar9170_get_default_phy_reg_val(0x1c5844,
+ is_2ghz, is_40mhz);
+ newval = (defval & ~0x3f80) |
+ ((m->switchSettling & 0x7f) << 7);
+ ar9170_regwrite(0x1c5844, newval);
+ }
+
+ /* adcDesired, pdaDesired (index 4) */
+ defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz);
+ newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) |
+ ((u8)m->adcDesiredSize);
+ ar9170_regwrite(0x1c5850, newval);
+
+ /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */
+ defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz);
+ newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) |
+ (m->txFrameToXpaOn << 8) | m->txFrameToXpaOn;
+ ar9170_regwrite(0x1c5834, newval);
+
+ /* TxEndToRxOn (index 6) */
+ defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz);
+ newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16);
+ ar9170_regwrite(0x1c5828, newval);
+
+ /* thresh62 (index 7) */
+ defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz);
+ newval = (defval & ~0x7f000) | (m->thresh62 << 12);
+ ar9170_regwrite(0x1c8864, newval);
+
+ /* tx/rx attenuation chain 0 (index 8) */
+ defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz);
+ newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12);
+ ar9170_regwrite(0x1c5848, newval);
+
+ /* tx/rx attenuation chain 2 (index 9) */
+ defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz);
+ newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12);
+ ar9170_regwrite(0x1c7848, newval);
+
+ /* tx/rx margin chain 0 (index 10) */
+ defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz);
+ newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18);
+ /* bsw margin chain 0 for 5GHz only */
+ if (!is_2ghz)
+ newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10);
+ ar9170_regwrite(0x1c620c, newval);
+
+ /* tx/rx margin chain 2 (index 11) */
+ defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz);
+ newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18);
+ ar9170_regwrite(0x1c820c, newval);
+
+ /* iqCall, iqCallq chain 0 (index 12) */
+ defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz);
+ newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) |
+ ((u8)m->iqCalQCh[0] & 0x1f);
+ ar9170_regwrite(0x1c5920, newval);
+
+ /* iqCall, iqCallq chain 2 (index 13) */
+ defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz);
+ newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) |
+ ((u8)m->iqCalQCh[1] & 0x1f);
+ ar9170_regwrite(0x1c7920, newval);
+
+ /* xpd gain mask (index 14) */
+ defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz);
+ newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16);
+ ar9170_regwrite(0x1c6258, newval);
+ ar9170_regwrite_finish();
+
+ return ar9170_regwrite_result();
+}
+
int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
{
int i, err;
@@ -426,7 +556,9 @@ int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
if (err)
return err;
- /* XXX: use EEPROM data here! */
+ err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz);
+ if (err)
+ return err;
err = ar9170_init_power_cal(ar);
if (err)
@@ -987,6 +1119,282 @@ static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
#undef SHIFT
}
+static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ if (x <= x_array[i + 1])
+ break;
+
+ return ar9170_interpolate_u8(x,
+ x_array[i],
+ y_array[i],
+ x_array[i + 1],
+ y_array[i + 1]);
+}
+
+static int ar9170_set_freq_cal_data(struct ar9170 *ar,
+ struct ieee80211_channel *channel)
+{
+ u8 *cal_freq_pier;
+ u8 vpds[2][AR5416_PD_GAIN_ICEPTS];
+ u8 pwrs[2][AR5416_PD_GAIN_ICEPTS];
+ int chain, idx, i;
+ u8 f;
+
+ switch (channel->band) {
+ case IEEE80211_BAND_2GHZ:
+ f = channel->center_freq - 2300;
+ cal_freq_pier = ar->eeprom.cal_freq_pier_2G;
+ i = AR5416_NUM_2G_CAL_PIERS - 1;
+ break;
+
+ case IEEE80211_BAND_5GHZ:
+ f = (channel->center_freq - 4800) / 5;
+ cal_freq_pier = ar->eeprom.cal_freq_pier_5G;
+ i = AR5416_NUM_5G_CAL_PIERS - 1;
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ for (; i >= 0; i--) {
+ if (cal_freq_pier[i] != 0xff)
+ break;
+ }
+ if (i < 0)
+ return -EINVAL;
+
+ idx = ar9170_find_freq_idx(i, cal_freq_pier, f);
+
+ ar9170_regwrite_begin(ar);
+
+ for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) {
+ for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) {
+ struct ar9170_calibration_data_per_freq *cal_pier_data;
+ int j;
+
+ switch (channel->band) {
+ case IEEE80211_BAND_2GHZ:
+ cal_pier_data = &ar->eeprom.
+ cal_pier_data_2G[chain][idx];
+ break;
+
+ case IEEE80211_BAND_5GHZ:
+ cal_pier_data = &ar->eeprom.
+ cal_pier_data_5G[chain][idx];
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ for (j = 0; j < 2; j++) {
+ vpds[j][i] = ar9170_interpolate_u8(f,
+ cal_freq_pier[idx],
+ cal_pier_data->vpd_pdg[j][i],
+ cal_freq_pier[idx + 1],
+ cal_pier_data[1].vpd_pdg[j][i]);
+
+ pwrs[j][i] = ar9170_interpolate_u8(f,
+ cal_freq_pier[idx],
+ cal_pier_data->pwr_pdg[j][i],
+ cal_freq_pier[idx + 1],
+ cal_pier_data[1].pwr_pdg[j][i]) / 2;
+ }
+ }
+
+ for (i = 0; i < 76; i++) {
+ u32 phy_data;
+ u8 tmp;
+
+ if (i < 25) {
+ tmp = ar9170_interpolate_val(i, &pwrs[0][0],
+ &vpds[0][0]);
+ } else {
+ tmp = ar9170_interpolate_val(i - 12,
+ &pwrs[1][0],
+ &vpds[1][0]);
+ }
+
+ phy_data |= tmp << ((i & 3) << 3);
+ if ((i & 3) == 3) {
+ ar9170_regwrite(0x1c6280 + chain * 0x1000 +
+ (i & ~3), phy_data);
+ phy_data = 0;
+ }
+ }
+
+ for (i = 19; i < 32; i++)
+ ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2),
+ 0x0);
+ }
+
+ ar9170_regwrite_finish();
+ return ar9170_regwrite_result();
+}
+
+static u8 ar9170_get_max_edge_power(struct ar9170 *ar,
+ struct ar9170_calctl_edges edges[],
+ u32 freq)
+{
+/* TODO: move somewhere else */
+#define AR5416_MAX_RATE_POWER 63
+
+ int i;
+ u8 rc = AR5416_MAX_RATE_POWER;
+ u8 f;
+ if (freq < 3000)
+ f = freq - 2300;
+ else
+ f = (freq - 4800) / 5;
+
+ for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
+ if (edges[i].channel == 0xff)
+ break;
+ if (f == edges[i].channel) {
+ /* exact freq match */
+ rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS;
+ break;
+ }
+ if (i > 0 && f < edges[i].channel) {
+ if (f > edges[i-1].channel &&
+ edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
+ /* lower channel has the inband flag set */
+ rc = edges[i-1].power_flags &
+ ~AR9170_CALCTL_EDGE_FLAGS;
+ }
+ break;
+ }
+ }
+
+ if (i == AR5416_NUM_BAND_EDGES) {
+ if (f > edges[i-1].channel &&
+ edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
+ /* lower channel has the inband flag set */
+ rc = edges[i-1].power_flags &
+ ~AR9170_CALCTL_EDGE_FLAGS;
+ }
+ }
+ return rc;
+}
+
+/* calculate the conformance test limits and apply them to ar->power*
+ * (derived from otus hal/hpmain.c, line 3706 ff.)
+ */
+static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
+{
+ u8 ctl_grp; /* CTL group */
+ u8 ctl_idx; /* CTL index */
+ int i, j;
+ struct ctl_modes {
+ u8 ctl_mode;
+ u8 max_power;
+ u8 *pwr_cal_data;
+ int pwr_cal_len;
+ } *modes;
+
+ /* order is relevant in the mode_list_*: we fall back to the
+ * lower indices if any mode is missed in the EEPROM.
+ */
+ struct ctl_modes mode_list_2ghz[] = {
+ { CTL_11B, 0, ar->power_2G_cck, 4 },
+ { CTL_11G, 0, ar->power_2G_ofdm, 4 },
+ { CTL_2GHT20, 0, ar->power_2G_ht20, 8 },
+ { CTL_2GHT40, 0, ar->power_2G_ht40, 8 },
+ };
+ struct ctl_modes mode_list_5ghz[] = {
+ { CTL_11A, 0, ar->power_5G_leg, 4 },
+ { CTL_5GHT20, 0, ar->power_5G_ht20, 8 },
+ { CTL_5GHT40, 0, ar->power_5G_ht40, 8 },
+ };
+ int nr_modes;
+
+#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n])
+
+ /* TODO: investigate the differences between OTUS'
+ * hpreg.c::zfHpGetRegulatoryDomain() and
+ * ath/regd.c::ath_regd_get_band_ctl() -
+ * e.g. for FCC3_WORLD the OTUS procedure
+ * always returns CTL_FCC, while the one in ath/ delivers
+ * CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
+ */
+ ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
+ ar->hw->conf.channel->band);
+
+ /* ctl group not found - either invalid band (NO_CTL) or ww roaming */
+ if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
+ ctl_grp = CTL_FCC;
+
+ if (ctl_grp != CTL_FCC)
+ /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
+ return;
+
+ if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ modes = mode_list_2ghz;
+ nr_modes = ARRAY_SIZE(mode_list_2ghz);
+ } else {
+ modes = mode_list_5ghz;
+ nr_modes = ARRAY_SIZE(mode_list_5ghz);
+ }
+
+ for (i = 0; i < nr_modes; i++) {
+ u8 c = ctl_grp | modes[i].ctl_mode;
+ for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++)
+ if (c == ar->eeprom.ctl_index[ctl_idx])
+ break;
+ if (ctl_idx < AR5416_NUM_CTLS) {
+ int f_off = 0;
+
+ /* adjust freq for 40MHz */
+ if (modes[i].ctl_mode == CTL_2GHT40 ||
+ modes[i].ctl_mode == CTL_5GHT40) {
+ if (bw == AR9170_BW_40_BELOW)
+ f_off = -10;
+ else
+ f_off = 10;
+ }
+
+ modes[i].max_power =
+ ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1),
+ freq+f_off);
+
+ /* TODO: check if the regulatory max. power is
+ * controlled by cfg80211 for DFS
+ * (hpmain applies it to max_power itself for DFS freq)
+ */
+
+ } else {
+ /* Workaround in otus driver, hpmain.c, line 3906:
+ * if no data for 5GHT20 are found, take the
+ * legacy 5G value.
+ * We extend this here to fallback from any other *HT or
+ * 11G, too.
+ */
+ int k = i;
+
+ modes[i].max_power = AR5416_MAX_RATE_POWER;
+ while (k-- > 0) {
+ if (modes[k].max_power !=
+ AR5416_MAX_RATE_POWER) {
+ modes[i].max_power = modes[k].max_power;
+ break;
+ }
+ }
+ }
+
+ /* apply max power to pwr_cal_data (ar->power_*) */
+ for (j = 0; j < modes[i].pwr_cal_len; j++) {
+ modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j],
+ modes[i].max_power);
+ }
+ }
+#undef EDGES
+}
+
static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
{
struct ar9170_calibration_target_power_legacy *ctpl;
@@ -1089,6 +1497,12 @@ static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
ctph[idx + 1].power[n]);
}
+
+ /* calc. conformance test limits and apply to ar->power*[] */
+ ar9170_calc_ctl(ar, freq, bw);
+
+ /* TODO: (heavy clip) regulatory domain power level fine-tuning. */
+
/* set ACK/CTS TX power */
ar9170_regwrite_begin(ar);
@@ -1207,6 +1621,10 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
if (err)
return err;
+ err = ar9170_set_freq_cal_data(ar, channel);
+ if (err)
+ return err;
+
err = ar9170_set_power_cal(ar, channel->center_freq, bw);
if (err)
return err;
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 5618fc25d52..2ad7d0280f7 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -119,17 +119,15 @@ static int ath_ahb_probe(struct platform_device *pdev)
sc->bus_ops = &ath_ahb_bus_ops;
sc->irq = irq;
- ret = ath_init_device(AR5416_AR9100_DEVID, sc);
- if (ret != 0) {
- dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
- ret = -ENODEV;
+ ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize device\n");
goto err_free_hw;
}
ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
if (ret) {
- dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret);
- ret = -EIO;
+ dev_err(&pdev->dev, "request_irq failed\n");
goto err_detach;
}
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 1c68a9da22d..1d59f10f68d 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -658,7 +658,7 @@ extern struct ieee80211_ops ath9k_ops;
irqreturn_t ath_isr(int irq, void *dev);
void ath_cleanup(struct