Sorry, this is the correct patch. Please test. :)
--
Ciao
Stefano
diff -u linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx.h wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx.h
--- linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx.h 2007-04-20 16:49:19.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx.h 2007-04-19 15:43:29.979032840 +0200
@@ -140,6 +140,7 @@
/* Chipcommon registers. */
#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04
+#define BCM43xx_CHIPCOMMON_CTL 0x28
#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0
#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4
#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8
@@ -153,6 +154,33 @@
/* SBTOPCI2 values. */
#define BCM43xx_SBTOPCI2_PREFETCH 0x4
#define BCM43xx_SBTOPCI2_BURST 0x8
+#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20
+
+/* PCI-E core registers. */
+#define BCM43xx_PCIECORE_REG_ADDR 0x0130
+#define BCM43xx_PCIECORE_REG_DATA 0x0134
+#define BCM43xx_PCIECORE_MDIO_CTL 0x0128
+#define BCM43xx_PCIECORE_MDIO_DATA 0x012C
+
+/* PCI-E registers. */
+#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004
+#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100
+
+/* PCI-E MDIO bits. */
+#define BCM43xx_PCIE_MDIO_ST 0x40000000
+#define BCM43xx_PCIE_MDIO_WT 0x10000000
+#define BCM43xx_PCIE_MDIO_DEV 22
+#define BCM43xx_PCIE_MDIO_REG 18
+#define BCM43xx_PCIE_MDIO_TA 0x00020000
+#define BCM43xx_PCIE_MDIO_TC 0x0100
+
+/* MDIO devices. */
+#define BCM43xx_MDIO_SERDES_RX 0x1F
+
+/* SERDES RX registers. */
+#define BCM43xx_SERDES_RXTIMER 0x2
+#define BCM43xx_SERDES_CDR 0x6
+#define BCM43xx_SERDES_CDR_BW 0x7
/* Chipcommon capabilities. */
#define BCM43xx_CAPABILITIES_PCTL 0x00040000
@@ -202,6 +230,7 @@
#define BCM43xx_COREID_USB20_HOST 0x819
#define BCM43xx_COREID_USB20_DEV 0x81a
#define BCM43xx_COREID_SDIO_HOST 0x81b
+#define BCM43xx_COREID_PCIE 0x820
/* Core Information Registers */
#define BCM43xx_CIR_BASE 0xf00
Only in wireless-dev/drivers/net/wireless/bcm43xx/: bcm43xx.mod.c
diff -u linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.c wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c
--- linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2007-04-20 16:49:19.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2007-04-20 12:03:18.668282968 +0200
@@ -130,6 +130,8 @@
{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4307 802.11b */
{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4311 802.11(a)/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4318 802.11b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4306 802.11b/g */
@@ -939,9 +941,9 @@
return 0;
}
-static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
+static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
{
- struct ieee80211_geo *geo;
+ struct ieee80211_geo geo;
struct ieee80211_channel *chan;
int have_a = 0, have_bg = 0;
int i;
@@ -949,10 +951,7 @@
struct bcm43xx_phyinfo *phy;
const char *iso_country;
- geo = kzalloc(sizeof(*geo), GFP_KERNEL);
- if (!geo)
- return -ENOMEM;
-
+ memset(&geo, 0, sizeof(geo));
for (i = 0; i < bcm->nr_80211_available; i++) {
phy = &(bcm->core_80211_ext[i].phy);
switch (phy->type) {
@@ -970,36 +969,31 @@
iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
if (have_a) {
- for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
- channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
- chan = &geo->a[i++];
+ for (i = 0, channel = 0; channel < 201; channel++) {
+ chan = &geo.a[i++];
chan->freq = bcm43xx_channel_to_freq_a(channel);
chan->channel = channel;
}
- geo->a_channels = i;
+ geo.a_channels = i;
}
if (have_bg) {
- for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
- channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) {
- chan = &geo->bg[i++];
+ for (i = 0, channel = 1; channel < 15; channel++) {
+ chan = &geo.bg[i++];
chan->freq = bcm43xx_channel_to_freq_bg(channel);
chan->channel = channel;
}
- geo->bg_channels = i;
+ geo.bg_channels = i;
}
- memcpy(geo->name, iso_country, 2);
+ memcpy(geo.name, iso_country, 2);
if (0 /*TODO: Outdoor use only */)
- geo->name[2] = 'O';
+ geo.name[2] = 'O';
else if (0 /*TODO: Indoor use only */)
- geo->name[2] = 'I';
+ geo.name[2] = 'I';
else
- geo->name[2] = ' ';
- geo->name[3] = '\0';
-
- ieee80211_set_geo(bcm->ieee, geo);
- kfree(geo);
+ geo.name[2] = ' ';
+ geo.name[3] = '\0';
- return 0;
+ ieee80211_set_geo(bcm->ieee, &geo);
}
/* DummyTransmission function, as documented on
@@ -1439,7 +1433,6 @@
if (err)
goto out;
sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
- sbtmstatelow &= ~0x20000000;
sbtmstatelow |= 0x20000000;
bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
err = bcm43xx_switch_core(bcm, old_core);
@@ -2573,8 +2566,8 @@
/* fetch sb_id_hi from core information registers */
sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
- core_id = (sb_id_hi & 0xFFF0) >> 4;
- core_rev = (sb_id_hi & 0xF);
+ core_id = (sb_id_hi & 0x8FF0) >> 4;
+ core_rev = (sb_id_hi & 0x7000) >> 8 | (sb_id_hi & 0xF);
core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
/* if present, chipcommon is always core 0; read the chipid from it */
@@ -2684,6 +2677,7 @@
core = NULL;
switch (core_id) {
case BCM43xx_COREID_PCI:
+ case BCM43xx_COREID_PCIE:
core = &bcm->core_pci;
if (core->available) {
printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
@@ -2722,12 +2716,12 @@
case 6:
case 7:
case 9:
+ case 10:
break;
default:
- printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
+ printk(KERN_WARNING PFX
+ "Unsupported 80211 core revision %u\n",
core_rev);
- err = -ENODEV;
- goto out;
}
bcm->nr_80211_available++;
bcm43xx_init_struct_phyinfo(&ext_80211->phy);
@@ -2839,16 +2833,11 @@
u32 sbimconfiglow;
u8 limit;
- if (bcm->chip_rev < 5) {
+ if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
- if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
- sbimconfiglow |= 0x32;
- else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
- sbimconfiglow |= 0x53;
- else
- assert(0);
+ sbimconfiglow |= 0x32;
bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
}
@@ -2965,22 +2954,65 @@
static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
{
- int err;
- struct bcm43xx_coreinfo *old_core;
+ int err = 0;
- old_core = bcm->current_core;
- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
- if (err)
- goto out;
+ if (bcm->core_chipcommon.available) {
+ err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ if (err)
+ goto out;
- bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+ bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+
+ /* this function is only called when a PCI core is mapped */
+ err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+ if (err)
+ goto out;
+ } else
+ bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
- bcm43xx_switch_core(bcm, old_core);
- assert(err == 0);
out:
return err;
}
+static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
+{
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+ return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
+}
+
+static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
+ u32 data)
+{
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
+}
+
+static int bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
+ u16 data)
+{
+ int i;
+
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
+ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
+ BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
+ (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
+ data);
+ udelay(10);
+
+ for (i = 0; i < 10; i++) {
+ if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
+ BCM43xx_PCIE_MDIO_TC)
+ return 0;
+ udelay(1000);
+ }
+ if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
+ BCM43xx_PCIE_MDIO_TC)
+ return 0;
+
+ printk(KERN_ERR PFX "Error: MDIO transaction failed\n");
+ return -EIO;
+}
+
/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
* To enable core 0, pass a core_mask of 1<<0
*/
@@ -3000,7 +3032,8 @@
if (err)
goto out;
- if (bcm->core_pci.rev < 6) {
+ if (bcm->current_core->rev < 6 ||
+ bcm->current_core->id == BCM43xx_COREID_PCI) {
value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
value |= (1 << backplane_flag_nr);
bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
@@ -3018,21 +3051,46 @@
}
}
- value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
- value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
- bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
-
- if (bcm->core_pci.rev < 5) {
- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
- value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
- & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
- value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
- & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
- err = bcm43xx_pcicore_commit_settings(bcm);
- assert(err == 0);
+ if (bcm->current_core->id == BCM43xx_COREID_PCI) {
+ value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+ value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+ bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+
+ if (bcm->current_core->rev < 5) {
+ value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+ value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+ & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+ value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+ & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+ bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+ err = bcm43xx_pcicore_commit_settings(bcm);
+ assert(err == 0);
+ } else if (bcm->current_core->rev >= 11) {
+ value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+ value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
+ bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+ }
+ } else {
+ if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
+ value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
+ value |= 0x8;
+ bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
+ value);
+ }
+ if (bcm->current_core->rev == 0) {
+ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+ BCM43xx_SERDES_RXTIMER, 0x8128);
+ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+ BCM43xx_SERDES_CDR, 0x0100);
+ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+ BCM43xx_SERDES_CDR_BW, 0x1466);
+ } else if (bcm->current_core->rev == 1) {
+ value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
+ value |= 0x40;
+ bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
+ value);
+ }
}
-
out_switch_back:
err = bcm43xx_switch_core(bcm, old_core);
out:
@@ -3350,7 +3408,7 @@
bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
break;
case BCM43xx_PHYTYPE_G:
- if (phy_rev > 7)
+ if (phy_rev > 8)
phy_rev_ok = 0;
bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
IEEE80211_CCK_MODULATION;
@@ -3487,17 +3545,16 @@
goto err_80211_unwind;
bcm43xx_wireless_core_disable(bcm);
}
- err = bcm43xx_geo_init(bcm);
- if (err)
- goto err_80211_unwind;
bcm43xx_pctl_set_crystal(bcm, 0);
/* Set the MAC address in the networking subsystem */
- if (is_valid_ether_addr(bcm->sprom.et1macaddr))
+ if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
else
memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
+ bcm43xx_geo_init(bcm);
+
snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
"Broadcom %04X", bcm->chip_id);
diff -u linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.h wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.h
--- linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.h 2007-04-20 16:49:19.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.h 2006-05-16 00:01:30.784127544 +0200
@@ -118,14 +118,12 @@
static inline
int bcm43xx_is_valid_channel_a(u8 channel)
{
- return (channel >= IEEE80211_52GHZ_MIN_CHANNEL
- && channel <= IEEE80211_52GHZ_MAX_CHANNEL);
+ return (channel <= 200);
}
static inline
int bcm43xx_is_valid_channel_bg(u8 channel)
{
- return (channel >= IEEE80211_24GHZ_MIN_CHANNEL
- && channel <= IEEE80211_24GHZ_MAX_CHANNEL);
+ return (channel >= 1 && channel <= 14);
}
static inline
int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
diff -u linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_phy.c wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
--- linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2007-04-20 16:49:19.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2006-05-16 00:01:30.785127392 +0200
@@ -1287,7 +1287,7 @@
if (radio->revision == 8)
bcm43xx_phy_write(bcm, 0x0805, 0x3230);
bcm43xx_phy_init_pctl(bcm);
- if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
+ if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) {
bcm43xx_phy_write(bcm, 0x0429,
bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
bcm43xx_phy_write(bcm, 0x04C3,
diff -u linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_power.c wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_power.c
--- linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_power.c 2007-04-20 16:49:19.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_power.c 2006-05-19 18:19:44.180844416 +0200
@@ -153,8 +153,6 @@
int err, maxfreq;
struct bcm43xx_coreinfo *old_core;
- if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
- return 0;
old_core = bcm->current_core;
err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
if (err == -ENODEV)
@@ -162,11 +160,25 @@
if (err)
goto out;
- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
- (maxfreq * 150 + 999999) / 1000000);
- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
- (maxfreq * 15 + 999999) / 1000000);
+ if (bcm->chip_id == 0x4321) {
+ if (bcm->chip_rev == 1)
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
+ if (bcm->chip_rev == 0)
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
+ }
+
+ if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
+ if (bcm->current_core->rev >= 10)
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
+ (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
+ & 0x0000FFFF) | 0x40000);
+
+ maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+ (maxfreq * 150 + 999999) / 1000000);
+ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+ (maxfreq * 15 + 999999) / 1000000);
+ }
err = bcm43xx_switch_core(bcm, old_core);
assert(err == 0);
diff -u linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_wx.c wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
--- linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2007-04-20 16:49:19.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2006-05-16 00:01:31.379037104 +0200
@@ -182,11 +182,8 @@
mode = BCM43xx_INITIAL_IWMODE;
bcm43xx_lock_mmio(bcm, flags);
- if (bcm->initialized) {
- if (bcm->ieee->iw_mode != mode)
- bcm43xx_set_iwmode(bcm, mode);
- } else
- bcm->ieee->iw_mode = mode;
+ if (bcm->ieee->iw_mode != mode)
+ bcm43xx_set_iwmode(bcm, mode);
bcm43xx_unlock_mmio(bcm, flags);
return 0;