As nobody still tested my patchset for PCI-E support and minor PCI fixes, I guess it could be easier if I would send an all-in-one patch against 2.6.17-rc4. Please test the attached patch (revised after Michael's coments) :)
-- Ciao Stefano
diff -u ./bcm43xx.h /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx.h --- ./bcm43xx.h 2007-04-19 15:43:29.979032840 +0200 +++ /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx.h 2007-04-20 16:49:19.000000000 +0200 @@ -140,7 +140,6 @@ /* 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 @@ -154,33 +153,6 @@ /* 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 @@ -230,7 +202,6 @@ #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 .: bcm43xx.mod.c diff -u ./bcm43xx_main.c /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.c --- ./bcm43xx_main.c 2007-04-20 12:03:18.668282968 +0200 +++ /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2007-04-20 16:49:19.000000000 +0200 @@ -130,8 +130,6 @@ { 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 */ @@ -941,9 +939,9 @@ return 0; } -static void bcm43xx_geo_init(struct bcm43xx_private *bcm) +static int 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; @@ -951,7 +949,10 @@ struct bcm43xx_phyinfo *phy; const char *iso_country; - memset(&geo, 0, sizeof(geo)); + geo = kzalloc(sizeof(*geo), GFP_KERNEL); + if (!geo) + return -ENOMEM; + for (i = 0; i < bcm->nr_80211_available; i++) { phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { @@ -969,31 +970,36 @@ iso_country = bcm43xx_locale_iso(bcm->sprom.locale); if (have_a) { - for (i = 0, channel = 0; channel < 201; channel++) { - chan = &geo.a[i++]; + for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL; + channel <= IEEE80211_52GHZ_MAX_CHANNEL; 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 = 1; channel < 15; channel++) { - chan = &geo.bg[i++]; + for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL; + channel <= IEEE80211_24GHZ_MAX_CHANNEL; 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'; + geo->name[2] = ' '; + geo->name[3] = '\0'; + + ieee80211_set_geo(bcm->ieee, geo); + kfree(geo); - ieee80211_set_geo(bcm->ieee, &geo); + return 0; } /* DummyTransmission function, as documented on @@ -1433,6 +1439,7 @@ 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); @@ -2566,8 +2573,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 & 0x8FF0) >> 4; - core_rev = (sb_id_hi & 0x7000) >> 8 | (sb_id_hi & 0xF); + core_id = (sb_id_hi & 0xFFF0) >> 4; + core_rev = (sb_id_hi & 0xF); core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; /* if present, chipcommon is always core 0; read the chipid from it */ @@ -2677,7 +2684,6 @@ 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"); @@ -2716,12 +2722,12 @@ case 6: case 7: case 9: - case 10: break; default: - printk(KERN_WARNING PFX - "Unsupported 80211 core revision %u\n", + printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n", core_rev); + err = -ENODEV; + goto out; } bcm->nr_80211_available++; bcm43xx_init_struct_phyinfo(&ext_80211->phy); @@ -2833,11 +2839,16 @@ u32 sbimconfiglow; u8 limit; - if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) { + if (bcm->chip_rev < 5) { sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - sbimconfiglow |= 0x32; + if (bcm->bustype == BCM43xx_BUSTYPE_PCI) + sbimconfiglow |= 0x32; + else if (bcm->bustype == BCM43xx_BUSTYPE_SB) + sbimconfiglow |= 0x53; + else + assert(0); bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); } @@ -2954,65 +2965,22 @@ static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) { - int err = 0; - - if (bcm->core_chipcommon.available) { - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err) - goto out; + int err; + struct bcm43xx_coreinfo *old_core; - bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err) + goto out; - /* 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_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 */ @@ -3032,8 +3000,7 @@ if (err) goto out; - if (bcm->current_core->rev < 6 || - bcm->current_core->id == BCM43xx_COREID_PCI) { + if (bcm->core_pci.rev < 6) { value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); value |= (1 << backplane_flag_nr); bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); @@ -3051,46 +3018,21 @@ } } - 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); - } + 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); } + out_switch_back: err = bcm43xx_switch_core(bcm, old_core); out: @@ -3408,7 +3350,7 @@ bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; break; case BCM43xx_PHYTYPE_G: - if (phy_rev > 8) + if (phy_rev > 7) phy_rev_ok = 0; bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION; @@ -3545,16 +3487,17 @@ 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 (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) + if (is_valid_ether_addr(bcm->sprom.et1macaddr)) 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 ./bcm43xx_main.h /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.h --- ./bcm43xx_main.h 2006-05-16 00:01:30.784127544 +0200 +++ /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_main.h 2007-04-20 16:49:19.000000000 +0200 @@ -118,12 +118,14 @@ static inline int bcm43xx_is_valid_channel_a(u8 channel) { - return (channel <= 200); + return (channel >= IEEE80211_52GHZ_MIN_CHANNEL + && channel <= IEEE80211_52GHZ_MAX_CHANNEL); } static inline int bcm43xx_is_valid_channel_bg(u8 channel) { - return (channel >= 1 && channel <= 14); + return (channel >= IEEE80211_24GHZ_MIN_CHANNEL + && channel <= IEEE80211_24GHZ_MAX_CHANNEL); } static inline int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, diff -u ./bcm43xx_phy.c /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_phy.c --- ./bcm43xx_phy.c 2006-05-16 00:01:30.785127392 +0200 +++ /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2007-04-20 16:49:19.000000000 +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 ./bcm43xx_power.c /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_power.c --- ./bcm43xx_power.c 2006-05-19 18:19:44.180844416 +0200 +++ /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_power.c 2007-04-20 16:49:19.000000000 +0200 @@ -153,6 +153,8 @@ 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) @@ -160,25 +162,11 @@ if (err) goto out; - 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); - } + 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 ./bcm43xx_wx.c /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_wx.c --- ./bcm43xx_wx.c 2006-05-16 00:01:31.379037104 +0200 +++ /usr/src/linux-2.6.17-rc4/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2007-04-20 16:49:19.000000000 +0200 @@ -182,8 +182,11 @@ mode = BCM43xx_INITIAL_IWMODE; bcm43xx_lock_mmio(bcm, flags); - if (bcm->ieee->iw_mode != mode) - bcm43xx_set_iwmode(bcm, mode); + if (bcm->initialized) { + if (bcm->ieee->iw_mode != mode) + bcm43xx_set_iwmode(bcm, mode); + } else + bcm->ieee->iw_mode = mode; bcm43xx_unlock_mmio(bcm, flags); return 0;