Loading Documentation/feature-removal-schedule.txt +29 −0 Original line number Diff line number Diff line Loading @@ -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 Loading MAINTAINERS +2 −0 Original line number Diff line number Diff line Loading @@ -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/ Loading @@ -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/ Loading drivers/net/b44.c +8 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; } } Loading drivers/net/wireless/Kconfig +16 −41 Original line number Diff line number Diff line Loading @@ -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. 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 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. When built as module you get the module prism54 config USB_ZD1201 tristate "USB ZD1201 based Wireless device support" Loading drivers/net/wireless/ath/ar9170/phy.c +419 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading
Documentation/feature-removal-schedule.txt +29 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
MAINTAINERS +2 −0 Original line number Diff line number Diff line Loading @@ -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/ Loading @@ -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/ Loading
drivers/net/b44.c +8 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; } } Loading
drivers/net/wireless/Kconfig +16 −41 Original line number Diff line number Diff line Loading @@ -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. 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 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. When built as module you get the module prism54 config USB_ZD1201 tristate "USB ZD1201 based Wireless device support" Loading
drivers/net/wireless/ath/ar9170/phy.c +419 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading