Hi John, Please apply this to wireless-dev.
-- This patch adds AP mode support to the bcm43xx-d80211 driver. Initial patch from Alexander Tsvyashchenko. Thanks a lot! Signed-off-by: Michael Buesch <[EMAIL PROTECTED]> Cc: "Francois Barre" <[EMAIL PROTECTED]> Cc: "Alexander Tsvyashchenko" <[EMAIL PROTECTED]> Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c =================================================================== --- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c 2006-06-17 21:26:10.000000000 +0200 +++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c 2006-06-19 11:25:02.000000000 +0200 @@ -151,8 +151,10 @@ { u32 status; + assert(offset % 4 == 0); + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP)) + if (status & BCM43xx_SBF_XFER_REG_BYTESWAP) val = swab32(val); bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset); @@ -312,7 +314,7 @@ } } -void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) +static void bcm43xx_time_lock(struct bcm43xx_private *bcm) { u32 status; @@ -320,7 +322,19 @@ status |= BCM43xx_SBF_TIME_UPDATE; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); mmiowb(); +} + +static void bcm43xx_time_unlock(struct bcm43xx_private *bcm) +{ + u32 status; + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status &= ~BCM43xx_SBF_TIME_UPDATE; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); +} +static void bcm43xx_tsf_write_locked(struct bcm43xx_private *bcm, u64 tsf) +{ /* Be careful with the in-progress timer. * First zero out the low register, so we have a full * register-overflow duration to complete the operation. @@ -350,10 +364,13 @@ mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0); } +} - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status &= ~BCM43xx_SBF_TIME_UPDATE; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); +void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) +{ + bcm43xx_time_lock(bcm); + bcm43xx_tsf_write_locked(bcm, tsf); + bcm43xx_time_unlock(bcm); } static void bcm43xx_measure_channel_change_time(struct bcm43xx_private *bcm) @@ -415,10 +432,11 @@ static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) { static const u8 zero_addr[ETH_ALEN] = { 0 }; - const u8 *mac = NULL; - const u8 *bssid = NULL; + const u8 *mac; + const u8 *bssid; u8 mac_bssid[ETH_ALEN * 2]; int i; + u32 tmp; bssid = bcm->interface.bssid; if (!bssid) @@ -431,12 +449,13 @@ memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); /* Write our MAC address and BSSID to template ram */ - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i))); - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i))); - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); + for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) { + tmp = (u32)(mac_bssid[i + 0]); + tmp |= (u32)(mac_bssid[i + 1]) << 8; + tmp |= (u32)(mac_bssid[i + 2]) << 16; + tmp |= (u32)(mac_bssid[i + 3]) << 24; + bcm43xx_ram_write(bcm, 0x20 + i, tmp); + } } static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) @@ -460,49 +479,6 @@ bcm->short_slot = 0; } -/* FIXME: To get the MAC-filter working, we need to implement the - * following functions (and rename them :) - */ -#if 0 -static void bcm43xx_disassociate(struct bcm43xx_private *bcm) -{ - bcm43xx_mac_suspend(bcm); - bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); - - bcm43xx_ram_write(bcm, 0x0026, 0x0000); - bcm43xx_ram_write(bcm, 0x0028, 0x0000); - bcm43xx_ram_write(bcm, 0x007E, 0x0000); - bcm43xx_ram_write(bcm, 0x0080, 0x0000); - bcm43xx_ram_write(bcm, 0x047E, 0x0000); - bcm43xx_ram_write(bcm, 0x0480, 0x0000); - - if (bcm->current_core->rev < 3) { - bcm43xx_write16(bcm, 0x0610, 0x8000); - bcm43xx_write16(bcm, 0x060E, 0x0000); - } else - bcm43xx_write32(bcm, 0x0188, 0x80000000); - - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); - -#if 0 - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G && - ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate)) - bcm43xx_short_slot_timing_enable(bcm); -#endif - - bcm43xx_mac_enable(bcm); -} - -static void bcm43xx_associate(struct bcm43xx_private *bcm, - const u8 *mac) -{ - bcm43xx_mac_suspend(bcm); - bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac); - bcm43xx_write_mac_bssid_templates(bcm); - bcm43xx_mac_enable(bcm); -} -#endif - /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. * Returns the _previously_ enabled IRQ mask. */ @@ -758,12 +734,29 @@ return -ENODEV; } +#ifdef CONFIG_BCM947XX +static void bcm43xx_aton(const char *str, char *dest) +{ + int i = 0; + u16 *d = (u16 *)dest; + + for (;;) { + dest[i++] = (char)simple_strtoul(str, NULL, 16); + str += 2; + if (!*str++ || i == 6) + break; + } + for (i = 0; i < 3; i++) + d[i] = be16_to_cpu(d[i]); +} +#endif + static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) { u16 value; u16 *sprom; #ifdef CONFIG_BCM947XX - char *c; + const char *c; #endif sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), @@ -772,27 +765,46 @@ printk(KERN_ERR PFX "sprom_extract OOM\n"); return -ENOMEM; } -#ifdef CONFIG_BCM947XX - sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2")); - sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags")); - - if ((c = nvram_get("il0macaddr")) != NULL) - e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR])); - - if ((c = nvram_get("et1macaddr")) != NULL) - e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR])); - - sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0")); - sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1")); - sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2")); - sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0")); - sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1")); - sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2")); - - sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev")); -#else bcm43xx_sprom_read(bcm, sprom); + +#ifdef CONFIG_BCM947XX + /* In the case some settings are found in nvram, use them + * to override those read from sprom. + */ + c = nvram_get("boardflags2"); + if (c) + sprom[BCM43xx_SPROM_BOARDFLAGS2] = simple_strtoul(c, NULL, 0); + c = nvram_get("boardflags"); + if (c) + sprom[BCM43xx_SPROM_BOARDFLAGS] = simple_strtoul(c, NULL, 0); + c = nvram_get("il0macaddr"); + if (c) + bcm43xx_aton(c, (char *)&(sprom[BCM43xx_SPROM_IL0MACADDR])); + c = nvram_get("et1macaddr"); + if (c) + bcm43xx_aton(c, (char *)&(sprom[BCM43xx_SPROM_ET1MACADDR])); + c = nvram_get("pa0b0"); + if (c) + sprom[BCM43xx_SPROM_PA0B0] = simple_strtoul(c, NULL, 0); + c = nvram_get("pa0b1"); + if (c) + sprom[BCM43xx_SPROM_PA0B1] = simple_strtoul(c, NULL, 0); + c = nvram_get("pa0b2"); + if (c) + sprom[BCM43xx_SPROM_PA0B2] = simple_strtoul(c, NULL, 0); + c = nvram_get("pa1b0"); + if (c) + sprom[BCM43xx_SPROM_PA1B0] = simple_strtoul(c, NULL, 0); + c = nvram_get("pa1b1"); + if (c) + sprom[BCM43xx_SPROM_PA1B1] = simple_strtoul(c, NULL, 0); + c = nvram_get("pa1b2"); + if (c) + sprom[BCM43xx_SPROM_PA1B2] = simple_strtoul(c, NULL, 0); + c = nvram_get("boardrev"); + if (c) + sprom[BCM43xx_SPROM_BOARDREV] = simple_strtoul(c, NULL, 0); #endif /* boardflags2 */ @@ -914,21 +926,21 @@ u16 value = 0; u32 buffer[5] = { 0x00000000, - 0x0000D400, + 0x00D40000, 0x00000000, - 0x00000001, + 0x01000000, 0x00000000, }; switch (phy->type) { case BCM43xx_PHYTYPE_A: max_loop = 0x1E; - buffer[0] = 0xCC010200; + buffer[0] = 0x000201CC; break; case BCM43xx_PHYTYPE_B: case BCM43xx_PHYTYPE_G: max_loop = 0xFA; - buffer[0] = 0x6E840B00; + buffer[0] = 0x000B846E; break; default: assert(0); @@ -1521,48 +1533,274 @@ bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002); } +static void bcm43xx_write_template_common(struct bcm43xx_private *bcm, + const u8* data, u16 size, + u16 ram_offset, + u16 shm_size_offset, u8 rate) +{ + u32 i, tmp; + struct bcm43xx_plcp_hdr4 plcp; + + plcp.data = 0; + bcm43xx_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); + bcm43xx_ram_write(bcm, ram_offset, le32_to_cpu(plcp.data)); + ram_offset += sizeof(u32); + /* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet. + * So leave the first two bytes of the next write blank. + */ + tmp = (u32)(data[0]) << 16; + tmp |= (u32)(data[1]) << 24; + bcm43xx_ram_write(bcm, ram_offset, tmp); + ram_offset += sizeof(u32); + for (i = 2; i < size; i += sizeof(u32)) { + tmp = (u32)(data[i + 0]); + if (i + 1 < size) + tmp |= (u32)(data[i + 1]) << 8; + if (i + 2 < size) + tmp |= (u32)(data[i + 2]) << 16; + if (i + 3 < size) + tmp |= (u32)(data[i + 3]) << 24; + bcm43xx_ram_write(bcm, ram_offset + i - 2, tmp); + } + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, + size + sizeof(struct bcm43xx_plcp_hdr6)); +} + static void bcm43xx_write_beacon_template(struct bcm43xx_private *bcm, u16 ram_offset, - u16 shm_size_offset) + u16 shm_size_offset, u8 rate) { - u32 tmp; - u16 i, size; + int len; const u8 *data; + assert(bcm->cached_beacon); + len = min((size_t)bcm->cached_beacon->len, + 0x200 - sizeof(struct bcm43xx_plcp_hdr6)); data = (const u8 *)(bcm->cached_beacon->data); - size = min(bcm->cached_beacon->len, (unsigned int)17); + bcm43xx_write_template_common(bcm, data, + len, ram_offset, + shm_size_offset, rate); +} - for (i = 0; i < size; i += sizeof(u32)) { - tmp = (u32)((data + i)[0]); - tmp |= (u32)((data + i)[1]) << 8; - tmp |= (u32)((data + i)[2]) << 16; - tmp |= (u32)((data + i)[3]) << 24; - bcm43xx_ram_write(bcm, ram_offset + i, tmp); +static void bcm43xx_write_probe_resp_plcp(struct bcm43xx_private *bcm, + u16 shm_offset, u16 size, u8 rate) +{ + struct bcm43xx_plcp_hdr4 plcp; + u32 tmp; + u16 packet_time; + + plcp.data = 0; + bcm43xx_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); + /* + * 144 + 48 + 10 = preamble + PLCP + SIFS, + * taken from d80211 timings calculation. + * + * FIXME: long preamble assumed! + * + */ + packet_time = 202 + (size + FCS_LEN) * 16 / rate; + if ((size + FCS_LEN) * 16 % rate >= rate / 2) + ++packet_time; + + /* Write PLCP in two parts and timing for packet transfer */ + tmp = le32_to_cpu(plcp.data); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_offset, + tmp & 0xFFFF); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_offset + 2, + tmp >> 16); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_offset + 6, + packet_time); +} + +/* Instead of using custom probe response template, this function + * just patches custom beacon template by: + * 1) Changing packet type + * 2) Patching duration field + * 3) Stripping TIM + */ +static u8 * bcm43xx_generate_probe_resp(struct bcm43xx_private *bcm, + u16* dest_size, u8 rate) +{ + const u8 *src_data; + u8 *dest_data; + u16 src_size, elem_size, src_pos, dest_pos, tmp; + + assert(bcm->cached_beacon); + src_size = bcm->cached_beacon->len; + src_data = (const u8*)bcm->cached_beacon->data; + + if (unlikely(src_size < 0x24)) { + dprintk(KERN_ERR PFX "bcm43xx_generate_probe_resp: " + "invalid beacon\n"); + return NULL; + } + + dest_data = kmalloc(src_size, GFP_ATOMIC); + if (unlikely(!dest_data)) + return NULL; + + /* 0x24 is offset of first variable-len Information-Element + * in beacon frame. + */ + memcpy(dest_data, src_data, 0x24); + src_pos = dest_pos = 0x24; + for ( ; src_pos < src_size - 2; src_pos += elem_size) { + elem_size = src_data[src_pos + 1] + 2; + if (src_data[src_pos] != 0x05) { /* TIM */ + memcpy(dest_data + dest_pos, src_data + src_pos, + elem_size); + dest_pos += elem_size; + } + } + *dest_size = dest_pos; + + /* Set the frame control. */ + dest_data[0] = ((WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_PROBE_RESP << 4)); + dest_data[1] = 0; + + /* Set the duration field. + * + * 144 + 48 + 10 = preamble + PLCP + SIFS, + * taken from d80211 timings calculation. + * + * FIXME: long preamble assumed! + * + */ + tmp = 202 + (14 + FCS_LEN) * 16 / rate; + if ((14 + FCS_LEN) * 16 % rate >= rate / 2) + ++tmp; + + dest_data[2] = tmp & 0xFF; + dest_data[3] = (tmp >> 8) & 0xFF; + + return dest_data; +} + +static void bcm43xx_write_probe_resp_template(struct bcm43xx_private *bcm, + u16 ram_offset, + u16 shm_size_offset, u8 rate) +{ + u8* probe_resp_data; + u16 size; + + assert(bcm->cached_beacon); + size = bcm->cached_beacon->len; + probe_resp_data = bcm43xx_generate_probe_resp(bcm, &size, rate); + if (unlikely(!probe_resp_data)) + return; + + /* Looks like PLCP headers plus packet timings are stored for + * all possible basic rates + */ + bcm43xx_write_probe_resp_plcp(bcm, 0x31A, size, + BCM43xx_CCK_RATE_1MB); + bcm43xx_write_probe_resp_plcp(bcm, 0x32C, size, + BCM43xx_CCK_RATE_2MB); + bcm43xx_write_probe_resp_plcp(bcm, 0x33E, size, + BCM43xx_CCK_RATE_5MB); + bcm43xx_write_probe_resp_plcp(bcm, 0x350, size, + BCM43xx_CCK_RATE_11MB); + + size = min((size_t)size, + 0x200 - sizeof(struct bcm43xx_plcp_hdr6)); + bcm43xx_write_template_common(bcm, probe_resp_data, + size, ram_offset, + shm_size_offset, rate); + kfree(probe_resp_data); +} + +static int bcm43xx_refresh_cached_beacon(struct bcm43xx_private *bcm) +{ + struct ieee80211_tx_control control; + + if (bcm->cached_beacon) + kfree_skb(bcm->cached_beacon); + bcm->cached_beacon = ieee80211_beacon_get(bcm->net_dev, + bcm->interface.if_id, + &control); + if (unlikely(!bcm->cached_beacon)) + return -ENOMEM; + + return 0; +} + +static void bcm43xx_update_templates(struct bcm43xx_private *bcm) +{ + u32 status; + + assert(bcm->cached_beacon); + + bcm43xx_write_beacon_template(bcm, 0x68, 0x18, + BCM43xx_CCK_RATE_1MB); + bcm43xx_write_beacon_template(bcm, 0x468, 0x1A, + BCM43xx_CCK_RATE_1MB); + bcm43xx_write_probe_resp_template(bcm, 0x268, 0x4A, + BCM43xx_CCK_RATE_11MB); + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD); + status |= 0x03; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); +} + +static void bcm43xx_refresh_templates(struct bcm43xx_private *bcm) +{ + int err; + + err = bcm43xx_refresh_cached_beacon(bcm); + if (unlikely(err)) + return; + bcm43xx_update_templates(bcm); + kfree_skb(bcm->cached_beacon); + bcm->cached_beacon = NULL; +} + +static void bcm43xx_set_ssid(struct bcm43xx_private *bcm, + const u8 *ssid, u8 ssid_len) +{ + u32 tmp; + u16 i, len; + + len = min((u16)ssid_len, (u16)0x100); + for (i = 0; i < len; i += sizeof(u32)) { + tmp = (u32)(ssid[i + 0]); + if (i + 1 < len) + tmp |= (u32)(ssid[i + 1]) << 8; + if (i + 2 < len) + tmp |= (u32)(ssid[i + 2]) << 16; + if (i + 3 < len) + tmp |= (u32)(ssid[i + 3]) << 24; + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + 0x380 + i, tmp); + } + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + 0x48, len); +} + +static void bcm43xx_set_beacon_int(struct bcm43xx_private *bcm, u16 beacon_int) +{ + bcm43xx_time_lock(bcm); + if (bcm->current_core->rev >= 3) { + bcm43xx_write32(bcm, 0x188, (beacon_int << 16)); + } else { + bcm43xx_write16(bcm, 0x606, (beacon_int >> 6)); + bcm43xx_write16(bcm, 0x610, beacon_int); } - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size); + bcm43xx_time_unlock(bcm); } static void handle_irq_beacon(struct bcm43xx_private *bcm) { u32 status; + int err; bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON; status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD); if (!bcm->cached_beacon) { - struct ieee80211_tx_control control; - - /* No cached template available, yet. - * Request the 80211 subsystem to generate a new beacon - * frame and use it as template. - */ - bcm->cached_beacon = ieee80211_beacon_get(bcm->net_dev, - bcm->interface.if_id, - &control); - if (unlikely(!bcm->cached_beacon)) { - dprintkl(KERN_WARNING PFX "Could not generate beacon template.\n"); + err = bcm43xx_refresh_cached_beacon(bcm); + if (unlikely(err)) goto ack; - } } if ((status & 0x1) && (status & 0x2)) { @@ -1571,18 +1809,20 @@ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_BEACON); bcm->irq_savedstate |= BCM43xx_IRQ_BEACON; - if (likely(bcm->cached_beacon)) + if (bcm->cached_beacon) kfree_skb(bcm->cached_beacon); bcm->cached_beacon = NULL; return; } if (!(status & 0x1)) { - bcm43xx_write_beacon_template(bcm, 0x68, 0x18); + bcm43xx_write_beacon_template(bcm, 0x68, 0x18, + BCM43xx_CCK_RATE_1MB); status |= 0x1; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); } if (!(status & 0x2)) { - bcm43xx_write_beacon_template(bcm, 0x468, 0x1A); + bcm43xx_write_beacon_template(bcm, 0x468, 0x1A, + BCM43xx_CCK_RATE_1MB); status |= 0x2; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); } @@ -4114,6 +4354,17 @@ radio->power_level = conf->power_level; bcm43xx_phy_xmitpower(bcm); } + + if (conf->ssid_hidden) { + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + | BCM43xx_SBF_NO_SSID_BCAST); + } else { + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + & ~BCM43xx_SBF_NO_SSID_BCAST); + } + //FIXME: This does not seem to wake up: #if 0 if (conf->power_level == 0) { @@ -4128,6 +4379,11 @@ //TODO: phymode //TODO: antennas + if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP)) { + bcm43xx_set_beacon_int(bcm, conf->beacon_int); + bcm43xx_refresh_templates(bcm); + } + bcm43xx_unlock_irqonly(bcm, flags); return 0; @@ -4293,8 +4549,11 @@ bcm->interface.mac_addr = conf->mac_addr; bcm->interface.type = conf->type; } - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { bcm43xx_select_opmode(bcm); + if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP)) + bcm43xx_refresh_templates(bcm); + } err = 0; dprintk(KERN_INFO PFX "Virtual interface added " @@ -4343,6 +4602,11 @@ if (conf->type != IEEE80211_IF_TYPE_MNTR) { assert(bcm->interface.if_id == if_id); bcm->interface.bssid = conf->bssid; + if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP)) { + assert(conf->type == IEEE80211_IF_TYPE_AP); + bcm43xx_set_ssid(bcm, conf->ssid, conf->ssid_len); + bcm43xx_refresh_templates(bcm); + } } bcm43xx_unlock_irqsafe(bcm, flags); Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c =================================================================== --- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c 2006-06-13 21:06:01.000000000 +0200 +++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c 2006-06-18 18:43:12.000000000 +0200 @@ -112,14 +112,13 @@ return 0; } -static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, - const u16 octets, const u8 bitrate, - const int ofdm_modulation) +void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, + const u16 octets, const u8 bitrate) { __le32 *data = &(plcp->data); __u8 *raw = plcp->raw; - if (ofdm_modulation) { + if (bcm43xx_is_ofdm_rate(bitrate)) { *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate); assert(!(octets & 0xF000)); *data |= (octets << 5); @@ -224,11 +223,9 @@ flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + FCS_LEN, bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp), - flen, bitrate, - !bcm43xx_is_cck_rate(bitrate)); + flen, bitrate); bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp), - flen, fallback_bitrate, - !bcm43xx_is_cck_rate(fallback_bitrate)); + flen, fallback_bitrate); fctl = WLAN_FC_TYPE_CTRL << 2; fctl |= WLAN_FC_STYPE_RTS << 4; dur = le16_to_cpu(wlhdr->duration_id); @@ -332,10 +329,9 @@ } /* Generate the PLCP header and the fallback PLCP header. */ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), - plcp_fragment_len, - bitrate, ofdm_modulation); + plcp_fragment_len, bitrate); bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len, - fallback_bitrate, fallback_ofdm_modulation); + fallback_bitrate); /* Set the CONTROL field */ if (ofdm_modulation) Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h =================================================================== --- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h 2006-06-13 14:43:08.000000000 +0200 +++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h 2006-06-18 18:41:27.000000000 +0200 @@ -154,4 +154,7 @@ struct sk_buff *skb, struct bcm43xx_rxhdr *rxhdr); +void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, + const u16 octets, const u8 bitrate); + #endif /* BCM43xx_XMIT_H_ */ Index: wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h =================================================================== --- wireless-dev-dscapeports.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h 2006-06-13 14:43:08.000000000 +0200 +++ wireless-dev-dscapeports/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h 2006-06-18 18:41:03.000000000 +0200 @@ -33,24 +33,6 @@ #include "bcm43xx.h" -#ifdef CONFIG_BCM947XX -#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0) - -static inline void e_aton(char *str, char *dest) -{ - int i = 0; - u16 *d = (u16 *) dest; - - for (;;) { - dest[i++] = (char) simple_strtoul(str, NULL, 16); - str += 2; - if (!*str++ || i == 6) - break; - } - for (i = 0; i < 3; i++) - d[i] = cpu_to_be16(d[i]); -} -#endif #define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] #define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) @@ -143,6 +125,12 @@ rate == BCM43xx_CCK_RATE_11MB); } +static inline +int bcm43xx_is_ofdm_rate(int rate) +{ + return !bcm43xx_is_cck_rate(rate); +} + void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); -- Greetings Michael. - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html