Matt Andruff | 1 May 2006 13:34
Picon

Re: Bcm43xx-dev digest, Vol 1 #283 - 2 msgs

Is bcm4319 supported by this driver, I've recently seen it about but don't know of anyone that's running it.  Would like to know 'cause I help people on Ubuntu get up and running with this driver and would like to tell them one way or the other that this driver is good for them

On 5/1/06, bcm43xx-dev-request <at> berlios.de <bcm43xx-dev-request-tdrK/OAtAx2ELgA04lAiVw@public.gmane.org > wrote:
Send Bcm43xx-dev mailing list submissions to
         bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://lists.berlios.de/mailman/listinfo/bcm43xx-dev
or, via email, send a message with subject or body 'help' to
        bcm43xx-dev-request-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org

You can reach the person managing the list at
        bcm43xx-dev-admin-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Bcm43xx-dev digest..."


Today's Topics:

   1. Re: Problems with bcm4318 (Michael Buesch)
   2. Re: wireless-dev: warnings while removing bcm43xx-d80211 (Michael Buesch)

--__--__--

Message: 1
From: Michael Buesch < mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
To: Matej Cepl <ceplm-9Vj9tDbzfuSlVyrhU4qvOw@public.gmane.org>
Subject: Re: Problems with bcm4318
Date: Sun, 30 Apr 2006 12:30:55 +0200
Cc: bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org

--nextPart7911516.ekq4FvokeX
Content-Type: text/plain;
  charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

On Sunday 30 April 2006 06:33, Matej Cepl wrote:
> Hi,
>=20
> I have upgraded my kernel to 2.6.17-rc3 (on Debian/unstable) and=20
> found that native driver (THANKS!!!) works just on every other=20
> reboot. So, for example attached /var/log/messages contains=20
> couple of oopses and other problems.
>=20
> Can anybody help me to make my native driver working reliably or=20
> do I have to just have ndiswrapper as a backup and wait for the=20
> next version of kernel?

Wait for 2.6.18-rc

=2D-=20
Greetings Michael.

--nextPart7911516.ekq4FvokeX
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)

iD8DBQBEVJHflb09HEdWDKgRAjZ+AKC7TWRgNbrlB0vMbaDsVPg7ykYR4ACfSvm3
7jZu9uUTk5r+44QVmf1hcRA=
=T4f+
-----END PGP SIGNATURE-----

--nextPart7911516.ekq4FvokeX--

--__--__--

Message: 2
From: Michael Buesch < mb-fseUSCV1ubazQB+pC5nmwQ@public.gmane.org>
To: Jiri Benc <jbenc-AlSwsSmVLrQ@public.gmane.org>
Subject: Re: wireless-dev: warnings while removing bcm43xx-d80211
Date: Sun, 30 Apr 2006 14:49:45 +0200
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Broadcom Linux <bcm43xx-dev <at> berlios.de>,
   Johannes Berg < johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>

--nextPart10830473.4zreOQX36Q
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

On Sunday 30 April 2006 14:15, you wrote:
> Sat, 29 Apr 2006 13:00:25 +0200, Johannes Berg pise:
> > This didn't look too good to me, maybe someone can investigate?
> >=20
> > [24070.841580 ] Badness in remove_proc_entry at fs/proc/generic.c:732
> > [24070.841593] Call Trace:
> > [...]
>=20
> I know about this (also mentioned it at Wireless summit), I'm working on
> it.

Hm, seems like I did not listen to you. :P
How does this happen? I never saw it.

=2D-=20
Greetings Michael.

--nextPart10830473.4zreOQX36Q
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)

iD8DBQBEVLJqlb09HEdWDKgRAnjJAJ0TzInXS8N9iwlGl8ogCiyfg9wMBQCfWAiz
SUxbWi5ABndrzen0k9Rvy7M=
=cats
-----END PGP SIGNATURE-----

--nextPart10830473.4zreOQX36Q--


--__--__--

_______________________________________________
Bcm43xx-dev mailing list
Bcm43xx-dev-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
http://lists.berlios.de/mailman/listinfo/bcm43xx-dev


End of Bcm43xx-dev Digest



--
--Ultimate is my Mistress
Michael Buesch | 1 May 2006 21:35
Picon
Favicon

[PATCH] bcm43xx-d80211: proper implementation of virtual interface support

Hi,

Jiri, please review this patch for things that might look
strange to you. :)

--

This replaces the bcm43xx-d80211 virtual interfaces hack by
a correct implementation with support for monitor during oper.

Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-05-01 20:25:31.000000000 +0200
 <at>  <at>  -626,10 +626,34  <at>  <at> 
 	u8 algorithm;
 };

+struct bcm43xx_interface {
+	struct list_head list;
+	/* Interface type (IEEE80211_IF_TYPE_XXX). */
+	int type;
+	/* Opaque ID from the ieee80211 subsystem. Do not modify. */
+	int if_id;
+	/* MAC address for this interface. */
+	u8 *mac_addr;
+	/* BSSID (if any). */
+	u8 *bssid;
+};
+
+struct bcm43xx_interface_list {
+	/* Linked list of active interfaces. */
+	struct list_head list;
+	/* Shortcut pointer to the AP interface (if any). */
+	struct bcm43xx_interface *ap_if;
+
+	/* Usage counters of the internal operation modes. */
+	u16 opmode_ap;
+	u16 opmode_adhoc;
+	u16 opmode_monitor;
+	u16 opmode_promisc;
+};
+
 struct bcm43xx_private {
 	struct ieee80211_hw *ieee;
 	struct ieee80211_low_level_stats ieee_stats;
-	int iw_mode;

 	struct net_device *net_dev;
 	struct pci_dev *pci_dev;
 <at>  <at>  -653,6 +677,11  <at>  <at> 
 	    short_slot:1,		/* TRUE, if short slot timing is enabled. */
 	    firmware_norelease:1;	/* Do not release the firmware. Used on suspend. */

+	/* One physical device can have one or more virtual
+	 * interfaces. This stores and manages the virtual interfaces.
+	 */
+	struct bcm43xx_interface_list interfaces;
+	/* Various statistics about the physical device. */
 	struct bcm43xx_stats stats;

 	/* Bus type we are connected to.
 <at>  <at>  -716,8 +745,6  <at>  <at> 

 	/* Informational stuff. */
 	char nick[IW_ESSID_MAX_SIZE + 1];
-	u8 bssid[ETH_ALEN];
-	int interfaces;

 	/* encryption/decryption */
 	u16 security_offset;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-05-01
18:57:26.000000000 +0200
 <at>  <at>  -217,7 +217,7  <at>  <at> 
 				bcm43xx_led_blink_stop(led, 0);
 			continue;
 		case BCM43xx_LED_APTRANSFER:
-			if (bcm->iw_mode == IW_MODE_MASTER) {
+			if (bcm->interfaces.opmode_ap) {
 				if (transferring) {
 					interval = BCM43xx_LEDBLINK_FAST;
 					turn_on = 1;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-05-01
20:25:24.000000000 +0200
 <at>  <at>  -378,18 +378,30  <at>  <at> 
 static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
 				    u16 offset)
 {
-	const u8 zero_addr[ETH_ALEN] = { 0 };
+	static const u8 zero_addr[ETH_ALEN] = { 0 };

 	bcm43xx_macfilter_set(bcm, offset, zero_addr);
 }

 static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
 {
+	static const u8 zero_addr[ETH_ALEN] = { 0 };
+	struct bcm43xx_interface *iface;
 	const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
-	const u8 *bssid = bcm->bssid;
+	const u8 *bssid = NULL;
 	u8 mac_bssid[ETH_ALEN * 2];
 	int i;

+	list_for_each_entry(iface, &bcm->interfaces.list, list) {
+		if (iface->type != IEEE80211_IF_TYPE_MNTR &&
+		    iface->bssid) {
+			bssid = iface->bssid;
+			break;
+		}
+	}
+	if (!bssid)
+		bssid = zero_addr;
+
 	memcpy(mac_bssid, mac, ETH_ALEN);
 	memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);

 <at>  <at>  -1438,15 +1450,15  <at>  <at> 

 static void handle_irq_ps(struct bcm43xx_private *bcm)
 {
-	if (bcm->iw_mode == IW_MODE_MASTER) {
+	if (bcm->interfaces.opmode_ap) {
 		///TODO: PS TBTT
 	} else {
 		if (1/*FIXME: the last PSpoll frame was sent successfully */)
 			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
 	}
-	if (bcm->iw_mode == IW_MODE_ADHOC)
+	bcm->reg124_set_0x4 = 0;
+	if (bcm->interfaces.opmode_adhoc)
 		bcm->reg124_set_0x4 = 1;
-	//FIXME else set to false?
 }

 static void handle_irq_reg124(struct bcm43xx_private *bcm)
 <at>  <at>  -1456,7 +1468,6  <at>  <at> 
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
 			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
 			| 0x4);
-	//FIXME: reset reg124_set_0x4 to false?
 }

 static void handle_irq_pmq(struct bcm43xx_private *bcm)
 <at>  <at>  -1509,7 +1520,10  <at>  <at> 
 		 * Request the 80211 subsystem to generate a new beacon
 		 * frame and use it as template.
 		 */
-		bcm->cached_beacon = ieee80211_beacon_get(bcm->net_dev, 0, &control);
+		assert(bcm->interfaces.ap_if);
+		bcm->cached_beacon = ieee80211_beacon_get(bcm->net_dev,
+							  bcm->interfaces.ap_if->if_id,
+							  &control);
 		if (unlikely(!bcm->cached_beacon)) {
 			dprintkl(KERN_WARNING PFX "Could not generate beacon template.\n");
 			goto ack;
 <at>  <at>  -1603,7 +1617,7  <at>  <at> 
 	}

 	if (reason & BCM43xx_IRQ_BEACON) {
-		if (bcm->iw_mode == IW_MODE_MASTER)
+		if (bcm->interfaces.opmode_ap)
 			handle_irq_beacon(bcm);
 		bcmirq_handled(BCM43xx_IRQ_BEACON);
 	}
 <at>  <at>  -2147,55 +2161,35  <at>  <at> 
 	printkl(KERN_ERR PFX "MAC suspend failed\n");
 }

-void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
-			int iw_mode)
+static void bcm43xx_select_opmodes(struct bcm43xx_private *bcm)
 {
-	struct net_device *net_dev = bcm->net_dev;
 	u32 status;
 	u16 value;

-	bcm->iw_mode = iw_mode;
-	if (iw_mode == IW_MODE_MONITOR)
-		net_dev->type = ARPHRD_IEEE80211;
-	else
-		net_dev->type = ARPHRD_ETHER;
-
 	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-	/* Reset status to infrastructured mode */
-	status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
+	/* Reset status to default STA mode */
+	status &= ~BCM43xx_SBF_MODE_AP;
+	status &= ~BCM43xx_SBF_MODE_MONITOR;
 	status &= ~BCM43xx_SBF_MODE_PROMISC;
 	status |= BCM43xx_SBF_MODE_NOTADHOC;

+	if (bcm->interfaces.opmode_ap)
+		status |= BCM43xx_SBF_MODE_AP;
+	if (bcm->interfaces.opmode_adhoc)
+		status &= ~BCM43xx_SBF_MODE_NOTADHOC;
+	if (bcm->interfaces.opmode_monitor)
+		status |= BCM43xx_SBF_MODE_MONITOR;
+	if (bcm->interfaces.opmode_promisc)
+		status |= BCM43xx_SBF_MODE_PROMISC;
+
 /* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
 status |= BCM43xx_SBF_MODE_PROMISC;

-	switch (iw_mode) {
-	case IW_MODE_MONITOR:
-		status |= BCM43xx_SBF_MODE_MONITOR;
-		status |= BCM43xx_SBF_MODE_PROMISC;
-		break;
-	case IW_MODE_ADHOC:
-		status &= ~BCM43xx_SBF_MODE_NOTADHOC;
-		break;
-	case IW_MODE_MASTER:
-		status |= BCM43xx_SBF_MODE_AP;
-		break;
-	case IW_MODE_SECOND:
-	case IW_MODE_REPEAT:
-		TODO(); /* TODO */
-		break;
-	case IW_MODE_INFRA:
-		/* nothing to be done here... */
-		break;
-	default:
-		dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
-	}
-	if (net_dev->flags & IFF_PROMISC)
-		status |= BCM43xx_SBF_MODE_PROMISC;
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);

 	value = 0x0002;
-	if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
+	if (bcm->interfaces.opmode_adhoc == 0 &&
+	    bcm->interfaces.opmode_ap == 0) {
 		if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
 			value = 0x0064;
 		else
 <at>  <at>  -2291,7 +2285,7  <at>  <at> 
 	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);

 	/* Initially set the wireless operation mode. */
-	bcm43xx_set_iwmode(bcm, bcm->iw_mode);
+	bcm43xx_select_opmodes(bcm);

 	if (bcm->current_core->rev < 3) {
 		bcm43xx_write16(bcm, 0x060E, 0x0000);
 <at>  <at>  -2599,27 +2593,6  <at>  <at> 
 	return err;
 }

-static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
-{
-	const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
-	u8 *bssid = bcm->bssid;
-
-	switch (bcm->iw_mode) {
-	case IW_MODE_ADHOC:
-		random_ether_addr(bssid);
-		break;
-	case IW_MODE_MASTER:
-	case IW_MODE_INFRA:
-	case IW_MODE_REPEAT:
-	case IW_MODE_SECOND:
-	case IW_MODE_MONITOR:
-		memcpy(bssid, mac, ETH_ALEN);
-		break;
-	default:
-		assert(0);
-	}
-}
-
 static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
 				      u16 rate,
 				      int is_ofdm)
 <at>  <at>  -2746,7 +2719,6  <at>  <at> 
 	/* Maximum Contention Window */
 	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);

-	bcm43xx_gen_bssid(bcm);
 	bcm43xx_write_mac_bssid_templates(bcm);

 	if (bcm->current_core->rev >= 5)
 <at>  <at>  -4169,13 +4141,8  <at>  <at> 
 static int bcm43xx_net_open(struct net_device *net_dev)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	int res;

-	res = bcm43xx_init_board(bcm);
-	if (!res)
-		return res;
-	bcm43xx_set_iwmode(bcm, bcm->iw_mode);
-	return 0;
+	return bcm43xx_init_board(bcm);
 }

 static int bcm43xx_net_stop(struct net_device *net_dev)
 <at>  <at>  -4194,33 +4161,170  <at>  <at> 
 				 struct ieee80211_if_init_conf *conf)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int err = -ENOBUFS;
+	struct bcm43xx_interface *iface;

-	if (bcm->interfaces > 0)
-		return -ENOBUFS;
-	if (conf->type == IEEE80211_IF_TYPE_MNTR) {
-		bcm->iw_mode = IW_MODE_MONITOR;
-	} else {
-		if (memcmp(bcm->net_dev->dev_addr, conf->mac_addr, ETH_ALEN) != 0)
-			return -EADDRNOTAVAIL;
-		if (conf->type == IEEE80211_IF_TYPE_STA)
-			bcm->iw_mode = IW_MODE_INFRA;
-		else if (conf->type == IEEE80211_IF_TYPE_IBSS)
-			bcm->iw_mode = IW_MODE_ADHOC;
-		else if (conf->type == IEEE80211_IF_TYPE_AP)
-			bcm->iw_mode = IW_MODE_MASTER;
-		else
-			return -EOPNOTSUPP;
+	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
+	if (!iface)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&iface->list);
+	iface->type = conf->type;
+	iface->if_id = conf->if_id;
+	iface->mac_addr = conf->mac_addr;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	switch (conf->type) {
+	case IEEE80211_IF_TYPE_AP:
+		/* Cannot run more than one AP or concurrently
+		 * with IBSS mode.
+		 */
+		if (bcm->interfaces.opmode_ap)
+			break;
+		if (bcm->interfaces.opmode_adhoc)
+			break;
+		bcm->interfaces.opmode_ap++;
+		bcm->interfaces.ap_if = iface;
+		err = 0;
+		break;
+	case IEEE80211_IF_TYPE_STA:
+		/* Cannot run STA and AP or IBSS mode concurrently. */
+		if (bcm->interfaces.opmode_ap)
+			break;
+		if (bcm->interfaces.opmode_adhoc)
+			break;
+		err = 0;
+		break;
+	case IEEE80211_IF_TYPE_IBSS:
+		/* Cannot run more than one IBSS or concurrently
+		 * with AP mode.
+		 */
+		if (bcm->interfaces.opmode_ap)
+			break;
+		if (bcm->interfaces.opmode_adhoc)
+			break;
+		bcm->interfaces.opmode_adhoc++;
+		err = 0;
+		break;
+	case IEEE80211_IF_TYPE_MNTR:
+		bcm->interfaces.opmode_monitor++;
+		err = 0;
+		break;
+	case IEEE80211_IF_TYPE_WDS:
+		//TODO: Uhm..., well.
+		break;
+	default:
+		assert(0);
 	}
-	bcm->interfaces++;
-	return 0;
+	if (!err) {
+		list_add_tail(&iface->list, &bcm->interfaces.list);
+		if (bcm->initialized)
+			bcm43xx_select_opmodes(bcm);
+
+		dprintk(KERN_INFO PFX "Virtual interface added "
+				      "(type: 0x%08X, ID: %d, MAC: "
+				      BCM43xx_MACFMT ")\n",
+			conf->type, conf->if_id,
+			BCM43xx_MACARG(conf->mac_addr));
+	}
+
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	if (err)
+		kfree(iface);
+
+	return err;
 }

 static void bcm43xx_remove_interface(struct net_device *net_dev,
 				     struct ieee80211_if_init_conf *conf)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	struct bcm43xx_interface *iface, *tmp_iface;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	list_for_each_entry_safe(iface, tmp_iface, &bcm->interfaces.list, list) {
+		if (iface->if_id != conf->if_id)
+			continue;
+		assert(conf->type == iface->type);
+
+		switch (iface->type) {
+		case IEEE80211_IF_TYPE_AP:
+			bcm->interfaces.opmode_ap--;
+			assert(bcm->interfaces.opmode_ap == 0);
+			bcm->interfaces.ap_if = NULL;
+			break;
+		case IEEE80211_IF_TYPE_STA:
+			break;
+		case IEEE80211_IF_TYPE_IBSS:
+			bcm->interfaces.opmode_adhoc--;
+			assert(bcm->interfaces.opmode_adhoc == 0);
+			break;
+		case IEEE80211_IF_TYPE_MNTR:
+			assert(bcm->interfaces.opmode_monitor > 0);
+			bcm->interfaces.opmode_monitor--;
+			break;
+		case IEEE80211_IF_TYPE_WDS:
+			//TODO: Uhm..., well.
+			break;
+		default:
+			assert(0);
+		}
+		list_del(&iface->list);
+		kfree(iface);
+		if (bcm->initialized)
+			bcm43xx_select_opmodes(bcm);
+
+		dprintk(KERN_INFO PFX "Virtual interface removed "
+				      "(type: 0x%08X, ID: %d, MAC: "
+				      BCM43xx_MACFMT ")\n",
+			conf->type, conf->if_id,
+			BCM43xx_MACARG(conf->mac_addr));
+		break;
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static int bcm43xx_config_interface(struct net_device *net_dev,
+				    int if_id,
+				    struct ieee80211_if_conf *conf)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	struct bcm43xx_interface *iface;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	list_for_each_entry(iface, &bcm->interfaces.list, list) {
+		if (iface->if_id == if_id)
+			goto found;
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return -ENODEV;
+found:
+	iface->bssid = conf->bssid;
+	//TODO
+
+	return 0;
+}
+
+static void bcm43xx_set_multicast_list(struct net_device *net_dev,
+				       unsigned short netflags,
+				       int mc_count)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	u16 old_promisc;

-	bcm->interfaces--;
+	bcm43xx_lock_mmio(bcm, flags);
+	old_promisc = bcm->interfaces.opmode_promisc;
+	bcm->interfaces.opmode_promisc = !!(netflags & IFF_PROMISC);
+	if (bcm->interfaces.opmode_promisc != old_promisc) {
+		if (bcm->initialized)
+			bcm43xx_select_opmodes(bcm);
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
 }

 /* Initialization of struct net_device, just after allocation. */
 <at>  <at>  -4240,6 +4344,7  <at>  <at> 
 	int err;

 	bcm->ieee = ieee;
+	INIT_LIST_HEAD(&bcm->interfaces.list);
 	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
 	bcm->pci_dev = pci_dev;
 	bcm->net_dev = net_dev;
 <at>  <at>  -4294,6 +4399,8  <at>  <at> 
 	ieee->name = KBUILD_MODNAME;
 	ieee->host_gen_beacon = 1;
 	ieee->rx_includes_fcs = 1;
+	ieee->monitor_during_oper = 1;
+	ieee->channel_change_time = 20000;
 	ieee->tx = bcm43xx_net_hard_start_xmit;
 	ieee->open = bcm43xx_net_open;
 	ieee->stop = bcm43xx_net_stop;
 <at>  <at>  -4301,6 +4408,8  <at>  <at> 
 	ieee->remove_interface = bcm43xx_remove_interface;
 	ieee->reset = bcm43xx_net_reset;
 	ieee->config = bcm43xx_net_config;
+	ieee->config_interface = bcm43xx_config_interface;
+	ieee->set_multicast_list = bcm43xx_set_multicast_list;
 //TODO	ieee->set_key = bcm43xx_net_set_key;
 	ieee->get_stats = bcm43xx_net_get_stats;
 	ieee->queues = 1;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-05-01
18:56:17.000000000 +0200
 <at>  <at>  -94,7 +94,7  <at>  <at> 
 		bcm43xx_mac_suspend(bcm);
 		spin_lock(&phy->lock);
 	} else {
-		if (bcm->iw_mode != IW_MODE_MASTER)
+		if (bcm->interfaces.opmode_ap == 0)
 			bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
 	}
 	phy->is_locked = 1;
 <at>  <at>  -111,7 +111,7  <at>  <at> 
 			bcm43xx_mac_enable(bcm);
 		}
 	} else {
-		if (bcm->iw_mode != IW_MODE_MASTER)
+		if (bcm->interfaces.opmode_ap == 0)
 			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
 	}
 	phy->is_locked = 0;

--

-- 
Greetings Michael.
Michael Buesch | 1 May 2006 22:29
Picon
Favicon

[PATCH] bcm43xx: fix iwmode crash when down

This should go into 2.6.17, as it fixes a user exploitable crash.

--

This fixes a crash when
iwconfig ethX mode foo
is done before
ifconfig ethX up
or after
ifconfig ethX down

Index: linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
===================================================================
--- linux-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_wx.c	2006-04-22 17:47:03.000000000 +0200
+++ linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_wx.c	2006-05-01 22:10:18.000000000 +0200
 <at>  <at>  -182,8 +182,11  <at>  <at> 
 		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;

--

-- 
Greetings Michael.
Michael Buesch | 1 May 2006 22:43
Picon
Favicon

[PATCH] bcm43xx: fix iwmode crash when down

(Second attempt, now unmangled and with signed-off-by line, uh...)
This should go into 2.6.17, as it fixes a user exploitable crash.

--

This fixes a crash when
iwconfig ethX mode foo
is done before
ifconfig ethX up
or after
ifconfig ethX down

Signed-off-by: Michael Buesch <mb <at> bu3sch.de>

Index: linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
===================================================================
--- linux-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_wx.c	2006-04-22 17:47:03.000000000 +0200
+++ linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_wx.c	2006-05-01 22:10:18.000000000 +0200
 <at>  <at>  -182,8 +182,11  <at>  <at> 
 		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;

--

-- 
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo <at> vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Michael Buesch | 1 May 2006 23:10
Picon
Favicon

[PATCH] bcm43xx-d80211: remove sta_up script

Hi John,

This is not really a patch, because it is easier for you
to do it manually. :)

Please remove the file
scripts/bcm43xx-d80211-sta_up.sh
from the wireless-dev tree, as the d80211 user interface has
been fixed and it is not really needed anymore.

While you are at it, please also remove
Documentation/networking/bcm43xx-d80211-HOWTO.txt
Documentation/networking/bcm43xx-d80211.txt
as they are completely outdated and useless these days.

Thanks.

PS: If someone wants to update
Documentation/networking/bcm43xx.txt
please feel free to submit a patch.

--

-- 
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo <at> vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Daniel Drake | 2 May 2006 00:22
Picon
Favicon

test me: use softmac's suggested TX rate

Hi,

Anyone feel like testing the integration of initial softmac rate 
management with bcm43xx?

If so, first apply this patch to softmac:
http://marc.theaimsgroup.com/?l=linux-netdev&m=114651996213569&q=raw

Then apply the patch attached to this mail.

Have fun!
Daniel
Jiri Benc | 2 May 2006 13:20
Picon

Re: [PATCH] bcm43xx-d80211: proper implementation of virtual interface support

On Mon, 1 May 2006 21:35:00 +0200, Michael Buesch wrote:
> --- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-04-28
16:13:40.000000000 +0200
> +++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-05-01
20:25:31.000000000 +0200
>  <at>  <at>  -626,10 +626,34  <at>  <at> 
>  	u8 algorithm;
>  };
>  
> +struct bcm43xx_interface {
> +	struct list_head list;
> +	/* Interface type (IEEE80211_IF_TYPE_XXX). */
> +	int type;
> +	/* Opaque ID from the ieee80211 subsystem. Do not modify. */
> +	int if_id;
> +	/* MAC address for this interface. */
> +	u8 *mac_addr;
> +	/* BSSID (if any). */
> +	u8 *bssid;
> +};
> +
> +struct bcm43xx_interface_list {
> +	/* Linked list of active interfaces. */
> +	struct list_head list;
> +	/* Shortcut pointer to the AP interface (if any). */
> +	struct bcm43xx_interface *ap_if;
> +
> +	/* Usage counters of the internal operation modes. */
> +	u16 opmode_ap;
> +	u16 opmode_adhoc;
> +	u16 opmode_monitor;
> +	u16 opmode_promisc;
> +};
> +

This is unnecessary. AFAIK bcm43xx hardware doesn't support more than one
interface at a time (not counting monitor interfaces as those are somewhat
special). There is no need for the linked list.

Instead of those structures above, use something like this:

struct bcm43xx_interface {
	/* Interface type (IEEE80211_IF_TYPE_XXX). */
	int type;
	/* MAC address for this interface. */
	u8 *mac_addr;
	/* BSSID (if any). */
	u8 *bssid;
	/* Number of monitor interfaces. */
	int monitors;
	/* STA, IBSS, AP or WDS running? */
	int oper;
}

You need this structure just once per hw card.

In add_interface callback:
- If conf->type is MNTR:
	- If bcm43xx_interface->oper is FALSE and
	  bcm43xx_interface->monitors is 0, initialize the card.
	- If bcm43xx_interface->monitors is 0, switch the card to monitor
	  mode (enable promisc mode, enable receiving of control frames,
	  etc.)
	- Increase bcm43xx_interface->monitors.
- If conf->type != MNTR:
	- If bcm43xx_interface->oper is TRUE, return error.
	- Set bcm43xx_interface->oper to TRUE.
	- Set bcm43xx_interface->type to conf->type.
	- Set hw MAC address according to conf->mac_addr.
	- If bcm43xx_interface->monitors is 0, initialize the card.

In remove_interface callback:
- If conf->type is MNTR:
	- Decrease bcm43xx_interface->monitors.
	- If bcm43xx_interface->monitors is 0, switch the card from monitor
	  mode (disable promisc mode if not forced by set_multicast_list,
	  disable receiving of control frames, etc.)
	- If bcm43xx_interface->oper is FALSE and
	  bcm43xx_interface->monitors is 0, deinitialize the card.
- If conf->type != MNTR:
	- Set bcm43xx_interface->oper to FALSE.
	- If bcm43xx_interface->monitors is 0, deinitialize the card.

In config_interface callback:
- If conf->type is MNTR, please report a bug :-)
- Assume you are configuring the only interface you have running.

> [...]
> +	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
> +	if (!iface)
> +		return -ENOMEM;
> +	INIT_LIST_HEAD(&iface->list);
> +	iface->type = conf->type;
> +	iface->if_id = conf->if_id;
> +	iface->mac_addr = conf->mac_addr;
> +
> +	bcm43xx_lock_mmio(bcm, flags);
> +	switch (conf->type) {
> +	case IEEE80211_IF_TYPE_AP:
> +		/* Cannot run more than one AP or concurrently
> +		 * with IBSS mode.
> +		 */
> +		if (bcm->interfaces.opmode_ap)
> +			break;
> +		if (bcm->interfaces.opmode_adhoc)
> +			break;
> +		bcm->interfaces.opmode_ap++;
> +		bcm->interfaces.ap_if = iface;
> +		err = 0;
> +		break;
> +	case IEEE80211_IF_TYPE_STA:
> +		/* Cannot run STA and AP or IBSS mode concurrently. */
> +		if (bcm->interfaces.opmode_ap)
> +			break;
> +		if (bcm->interfaces.opmode_adhoc)
> +			break;
> +		err = 0;
> +		break;

"ifconfig ap up ; ifconfig sta up" will succeed, while
"ifconfig sta up ; ifconfig ap up" won't.

Also, you cannot allow multiple STA interfaces, unless you can configure the
card to ack frames destined to several MAC addresses.

Nevertheless, this is all addressed by the solution suggested above.

> +	case IEEE80211_IF_TYPE_IBSS:
> +		/* Cannot run more than one IBSS or concurrently
> +		 * with AP mode.
> +		 */
> +		if (bcm->interfaces.opmode_ap)
> +			break;
> +		if (bcm->interfaces.opmode_adhoc)
> +			break;
> +		bcm->interfaces.opmode_adhoc++;
> +		err = 0;
> +		break;
> +	case IEEE80211_IF_TYPE_MNTR:
> +		bcm->interfaces.opmode_monitor++;
> +		err = 0;
> +		break;
> +	case IEEE80211_IF_TYPE_WDS:
> +		//TODO: Uhm..., well.
> +		break;

Please return more appropriate error code (-EINVAL perhaps?).

> +	default:
> +		assert(0);
>  	}

Thanks,

--

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo <at> vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Michael Buesch | 3 May 2006 18:42
Picon
Favicon

[PATCH] bcm43xx-d80211: rewrite interface handling

Hi John,

Please apply to wireless-dev.

--

Rewrite the virtual interface handling.
With this monitor_during_oper is made possible.

Signed-off-by: Michael Buesch <mb <at> bu3sch.de>

Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-05-03 18:02:55.000000000 +0200
 <at>  <at>  -626,10 +626,32  <at>  <at> 
 	u8 algorithm;
 };

+struct bcm43xx_interface {
+	/* Opaque ID of the operating interface (!= monitor
+	 * interface) from the ieee80211 subsystem.
+	 * Do not modify.
+	 */
+	int if_id;
+	/* MAC address. */
+	u8 *mac_addr;
+	/* Current BSSID (if any). */
+	u8 *bssid;
+
+	/* Interface type. (IEEE80211_IF_TYPE_XXX) */
+	int type;
+	/* Counter of active monitor interfaces. */
+	int monitor;
+	/* Is the card operating in AP, STA or IBSS mode? */
+	unsigned int operating:1;
+	/* Promisc mode active?
+	 * Note that (monitor != 0) implies promisc.
+	 */
+	unsigned int promisc:1;
+};
+
 struct bcm43xx_private {
 	struct ieee80211_hw *ieee;
 	struct ieee80211_low_level_stats ieee_stats;
-	int iw_mode;

 	struct net_device *net_dev;
 	struct pci_dev *pci_dev;
 <at>  <at>  -653,6 +675,13  <at>  <at> 
 	    short_slot:1,		/* TRUE, if short slot timing is enabled. */
 	    firmware_norelease:1;	/* Do not release the firmware. Used on suspend. */

+	/* One physical device can have one operating interface
+	 * and a virtually infinite amount of monitoring interfaces.
+	 * This keeps track of the interfaces and the corresponding
+	 * hardware modes.
+	 */
+	struct bcm43xx_interface interface;
+	/* Various statistics about the physical device. */
 	struct bcm43xx_stats stats;

 	/* Bus type we are connected to.
 <at>  <at>  -716,8 +745,6  <at>  <at> 

 	/* Informational stuff. */
 	char nick[IW_ESSID_MAX_SIZE + 1];
-	u8 bssid[ETH_ALEN];
-	int interfaces;

 	/* encryption/decryption */
 	u16 security_offset;
 <at>  <at>  -854,6 +881,15  <at>  <at> 
 	return bcm;
 }

+/* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */
+static inline
+int bcm43xx_is_mode(struct bcm43xx_private *bcm, int type)
+{
+	if (type == IEEE80211_IF_TYPE_MNTR)
+		return !!bcm->interface.monitor;
+	return (bcm->interface.operating &&
+		bcm->interface.type == type);
+}

 static inline
 u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-05-03
18:00:46.000000000 +0200
 <at>  <at>  -217,7 +217,7  <at>  <at> 
 				bcm43xx_led_blink_stop(led, 0);
 			continue;
 		case BCM43xx_LED_APTRANSFER:
-			if (bcm->iw_mode == IW_MODE_MASTER) {
+			if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP)) {
 				if (transferring) {
 					interval = BCM43xx_LEDBLINK_FAST;
 					turn_on = 1;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-05-03
18:12:27.000000000 +0200
 <at>  <at>  -378,18 +378,26  <at>  <at> 
 static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
 				    u16 offset)
 {
-	const u8 zero_addr[ETH_ALEN] = { 0 };
+	static const u8 zero_addr[ETH_ALEN] = { 0 };

 	bcm43xx_macfilter_set(bcm, offset, zero_addr);
 }

 static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
 {
-	const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
-	const u8 *bssid = bcm->bssid;
+	static const u8 zero_addr[ETH_ALEN] = { 0 };
+	const u8 *mac = NULL;
+	const u8 *bssid = NULL;
 	u8 mac_bssid[ETH_ALEN * 2];
 	int i;

+	bssid = bcm->interface.bssid;
+	if (!bssid)
+		bssid = zero_addr;
+	mac = bcm->interface.mac_addr;
+	if (!mac)
+		mac = zero_addr;
+
 	memcpy(mac_bssid, mac, ETH_ALEN);
 	memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);

 <at>  <at>  -1438,15 +1446,15  <at>  <at> 

 static void handle_irq_ps(struct bcm43xx_private *bcm)
 {
-	if (bcm->iw_mode == IW_MODE_MASTER) {
+	if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP)) {
 		///TODO: PS TBTT
 	} else {
 		if (1/*FIXME: the last PSpoll frame was sent successfully */)
 			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
 	}
-	if (bcm->iw_mode == IW_MODE_ADHOC)
+	bcm->reg124_set_0x4 = 0;
+	if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_IBSS))
 		bcm->reg124_set_0x4 = 1;
-	//FIXME else set to false?
 }

 static void handle_irq_reg124(struct bcm43xx_private *bcm)
 <at>  <at>  -1456,7 +1464,6  <at>  <at> 
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
 			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
 			| 0x4);
-	//FIXME: reset reg124_set_0x4 to false?
 }

 static void handle_irq_pmq(struct bcm43xx_private *bcm)
 <at>  <at>  -1509,7 +1516,9  <at>  <at> 
 		 * Request the 80211 subsystem to generate a new beacon
 		 * frame and use it as template.
 		 */
-		bcm->cached_beacon = ieee80211_beacon_get(bcm->net_dev, 0, &control);
+		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");
 			goto ack;
 <at>  <at>  -1603,7 +1612,7  <at>  <at> 
 	}

 	if (reason & BCM43xx_IRQ_BEACON) {
-		if (bcm->iw_mode == IW_MODE_MASTER)
+		if (bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP))
 			handle_irq_beacon(bcm);
 		bcmirq_handled(BCM43xx_IRQ_BEACON);
 	}
 <at>  <at>  -2147,55 +2156,49  <at>  <at> 
 	printkl(KERN_ERR PFX "MAC suspend failed\n");
 }

-void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
-			int iw_mode)
+static void bcm43xx_select_opmode(struct bcm43xx_private *bcm)
 {
-	struct net_device *net_dev = bcm->net_dev;
 	u32 status;
 	u16 value;

-	bcm->iw_mode = iw_mode;
-	if (iw_mode == IW_MODE_MONITOR)
-		net_dev->type = ARPHRD_IEEE80211;
-	else
-		net_dev->type = ARPHRD_ETHER;
-
 	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-	/* Reset status to infrastructured mode */
-	status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
+	/* Reset status to default STA mode */
+	status &= ~BCM43xx_SBF_MODE_AP;
+	status &= ~BCM43xx_SBF_MODE_MONITOR;
 	status &= ~BCM43xx_SBF_MODE_PROMISC;
 	status |= BCM43xx_SBF_MODE_NOTADHOC;

-/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
-status |= BCM43xx_SBF_MODE_PROMISC;
-
-	switch (iw_mode) {
-	case IW_MODE_MONITOR:
+	if (bcm->interface.operating) {
+		switch (bcm->interface.type) {
+		case IEEE80211_IF_TYPE_AP:
+			status |= BCM43xx_SBF_MODE_AP;
+			break;
+		case IEEE80211_IF_TYPE_IBSS:
+			status &= ~BCM43xx_SBF_MODE_NOTADHOC;
+			break;
+		case IEEE80211_IF_TYPE_STA:
+		case IEEE80211_IF_TYPE_MNTR:
+		case IEEE80211_IF_TYPE_WDS:
+			break;
+		default:
+			assert(0);
+		}
+	}
+	if (bcm->interface.monitor) {
 		status |= BCM43xx_SBF_MODE_MONITOR;
 		status |= BCM43xx_SBF_MODE_PROMISC;
-		break;
-	case IW_MODE_ADHOC:
-		status &= ~BCM43xx_SBF_MODE_NOTADHOC;
-		break;
-	case IW_MODE_MASTER:
-		status |= BCM43xx_SBF_MODE_AP;
-		break;
-	case IW_MODE_SECOND:
-	case IW_MODE_REPEAT:
-		TODO(); /* TODO */
-		break;
-	case IW_MODE_INFRA:
-		/* nothing to be done here... */
-		break;
-	default:
-		dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
 	}
-	if (net_dev->flags & IFF_PROMISC)
+	if (bcm->interface.promisc)
 		status |= BCM43xx_SBF_MODE_PROMISC;
+
+/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
+status |= BCM43xx_SBF_MODE_PROMISC;
+
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);

 	value = 0x0002;
-	if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
+	if ((status & BCM43xx_SBF_MODE_NOTADHOC) &&
+	    !(status & BCM43xx_SBF_MODE_AP)) {
 		if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
 			value = 0x0064;
 		else
 <at>  <at>  -2291,7 +2294,7  <at>  <at> 
 	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);

 	/* Initially set the wireless operation mode. */
-	bcm43xx_set_iwmode(bcm, bcm->iw_mode);
+	bcm43xx_select_opmode(bcm);

 	if (bcm->current_core->rev < 3) {
 		bcm43xx_write16(bcm, 0x060E, 0x0000);
 <at>  <at>  -2599,27 +2602,6  <at>  <at> 
 	return err;
 }

-static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
-{
-	const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
-	u8 *bssid = bcm->bssid;
-
-	switch (bcm->iw_mode) {
-	case IW_MODE_ADHOC:
-		random_ether_addr(bssid);
-		break;
-	case IW_MODE_MASTER:
-	case IW_MODE_INFRA:
-	case IW_MODE_REPEAT:
-	case IW_MODE_SECOND:
-	case IW_MODE_MONITOR:
-		memcpy(bssid, mac, ETH_ALEN);
-		break;
-	default:
-		assert(0);
-	}
-}
-
 static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
 				      u16 rate,
 				      int is_ofdm)
 <at>  <at>  -2746,7 +2728,6  <at>  <at> 
 	/* Maximum Contention Window */
 	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);

-	bcm43xx_gen_bssid(bcm);
 	bcm43xx_write_mac_bssid_templates(bcm);

 	if (bcm->current_core->rev >= 5)
 <at>  <at>  -4169,13 +4150,8  <at>  <at> 
 static int bcm43xx_net_open(struct net_device *net_dev)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	int res;

-	res = bcm43xx_init_board(bcm);
-	if (!res)
-		return res;
-	bcm43xx_set_iwmode(bcm, bcm->iw_mode);
-	return 0;
+	return bcm43xx_init_board(bcm);
 }

 static int bcm43xx_net_stop(struct net_device *net_dev)
 <at>  <at>  -4194,33 +4170,91  <at>  <at> 
 				 struct ieee80211_if_init_conf *conf)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int err = -EOPNOTSUPP;
+
+	bcm43xx_lock_mmio(bcm, flags);

-	if (bcm->interfaces > 0)
-		return -ENOBUFS;
 	if (conf->type == IEEE80211_IF_TYPE_MNTR) {
-		bcm->iw_mode = IW_MODE_MONITOR;
+		bcm->interface.monitor++;
 	} else {
-		if (memcmp(bcm->net_dev->dev_addr, conf->mac_addr, ETH_ALEN) != 0)
-			return -EADDRNOTAVAIL;
-		if (conf->type == IEEE80211_IF_TYPE_STA)
-			bcm->iw_mode = IW_MODE_INFRA;
-		else if (conf->type == IEEE80211_IF_TYPE_IBSS)
-			bcm->iw_mode = IW_MODE_ADHOC;
-		else if (conf->type == IEEE80211_IF_TYPE_AP)
-			bcm->iw_mode = IW_MODE_MASTER;
-		else
-			return -EOPNOTSUPP;
+		if (bcm->interface.operating)
+			goto out_unlock;
+		bcm->interface.operating = 1;
+		bcm->interface.if_id = conf->if_id;
+		bcm->interface.mac_addr = conf->mac_addr;
+		bcm->interface.type = conf->type;
 	}
-	bcm->interfaces++;
-	return 0;
+	if (bcm->initialized)
+		bcm43xx_select_opmode(bcm);
+	err = 0;
+
+	dprintk(KERN_INFO PFX "Virtual interface added "
+			      "(type: 0x%08X, ID: %d, MAC: "
+			      BCM43xx_MACFMT ")\n",
+		conf->type, conf->if_id,
+		BCM43xx_MACARG(conf->mac_addr));
+
+out_unlock:
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return err;
 }

 static void bcm43xx_remove_interface(struct net_device *net_dev,
 				     struct ieee80211_if_init_conf *conf)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (conf->type == IEEE80211_IF_TYPE_MNTR) {
+		bcm->interface.monitor--;
+		assert(bcm->interface.monitor >= 0);
+	} else
+		bcm->interface.operating = 0;
+	if (bcm->initialized)
+		bcm43xx_select_opmode(bcm);
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	dprintk(KERN_INFO PFX "Virtual interface removed "
+			      "(type: 0x%08X, ID: %d, MAC: "
+			      BCM43xx_MACFMT ")\n",
+		conf->type, conf->if_id,
+		BCM43xx_MACARG(conf->mac_addr));
+}

-	bcm->interfaces--;
+static int bcm43xx_config_interface(struct net_device *net_dev,
+				    int if_id,
+				    struct ieee80211_if_conf *conf)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	bcm43xx_lock(bcm, flags);
+	if (conf->type != IEEE80211_IF_TYPE_MNTR) {
+		assert(bcm->interface.if_id == if_id);
+		bcm->interface.bssid = conf->bssid;
+	}
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static void bcm43xx_set_multicast_list(struct net_device *net_dev,
+				       unsigned short netflags,
+				       int mc_count)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (bcm->interface.promisc != !!(netflags & IFF_PROMISC)) {
+		bcm->interface.promisc = !!(netflags & IFF_PROMISC);
+		if (bcm->initialized)
+			bcm43xx_select_opmode(bcm);
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
 }

 /* Initialization of struct net_device, just after allocation. */
 <at>  <at>  -4294,6 +4328,8  <at>  <at> 
 	ieee->name = KBUILD_MODNAME;
 	ieee->host_gen_beacon = 1;
 	ieee->rx_includes_fcs = 1;
+	ieee->monitor_during_oper = 1;
+	ieee->channel_change_time = 20000;
 	ieee->tx = bcm43xx_net_hard_start_xmit;
 	ieee->open = bcm43xx_net_open;
 	ieee->stop = bcm43xx_net_stop;
 <at>  <at>  -4301,6 +4337,8  <at>  <at> 
 	ieee->remove_interface = bcm43xx_remove_interface;
 	ieee->reset = bcm43xx_net_reset;
 	ieee->config = bcm43xx_net_config;
+	ieee->config_interface = bcm43xx_config_interface;
+	ieee->set_multicast_list = bcm43xx_set_multicast_list;
 //TODO	ieee->set_key = bcm43xx_net_set_key;
 	ieee->get_stats = bcm43xx_net_get_stats;
 	ieee->queues = 1;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-04-28
16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-05-03
17:59:58.000000000 +0200
 <at>  <at>  -94,7 +94,7  <at>  <at> 
 		bcm43xx_mac_suspend(bcm);
 		spin_lock(&phy->lock);
 	} else {
-		if (bcm->iw_mode != IW_MODE_MASTER)
+		if (!bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP))
 			bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
 	}
 	phy->is_locked = 1;
 <at>  <at>  -111,7 +111,7  <at>  <at> 
 			bcm43xx_mac_enable(bcm);
 		}
 	} else {
-		if (bcm->iw_mode != IW_MODE_MASTER)
+		if (!bcm43xx_is_mode(bcm, IEEE80211_IF_TYPE_AP))
 			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
 	}
 	phy->is_locked = 0;

--

-- 
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo <at> vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Jiri Benc | 3 May 2006 19:44
Picon

Re: [PATCH] bcm43xx-d80211: rewrite interface handling

On Wed, 3 May 2006 18:42:04 +0200, Michael Buesch wrote:
> Rewrite the virtual interface handling.
> With this monitor_during_oper is made possible.
> 
> Signed-off-by: Michael Buesch <mb <at> bu3sch.de>

Acked-by: Jiri Benc <jbenc <at> suse.cz>

--

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo <at> vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Michael Buesch | 3 May 2006 21:05
Picon
Favicon

[PATCH] bcm43xx-d80211: measure the channel change time

Measure the channel change time with the
bcm43xx tsf timer and remove the guesswork constant. ;)

Tests on my 4306 show that the time comes damn
close to reality.

Signed-off-by: Michael Buesch <mb <at> bu3sch.de>

Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-05-03
18:12:27.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-05-03
20:51:24.000000000 +0200
 <at>  <at>  -354,6 +354,33  <at>  <at> 
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
 }

+static void bcm43xx_measure_channel_change_time(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio;
+	u64 start, stop;
+	unsigned long flags;
+	u8 oldchan, testchan;
+
+	/* We (ab)use the bcm43xx TSF timer to measure the time needed
+	 * to switch channels. This information is handed over to
+	 * the ieee80211 subsystem.
+	 * Time is measured in microseconds.
+	 */
+
+	bcm43xx_lock_mmio(bcm, flags);
+	radio = bcm43xx_current_radio(bcm);
+	oldchan = radio->channel;
+	testchan = (oldchan == 6) ? 7 : 6;
+	bcm43xx_tsf_read(bcm, &start);
+	bcm43xx_radio_selectchannel(bcm, testchan, 0);
+	bcm43xx_tsf_read(bcm, &stop);
+	bcm43xx_radio_selectchannel(bcm, oldchan, 0);
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	assert(stop > start);
+	bcm->ieee->channel_change_time = stop - start;
+}
+
 static
 void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
 			   u16 offset,
 <at>  <at>  -3706,6 +3733,7  <at>  <at> 
 	dprintk(KERN_INFO PFX "80211 cores initialized\n");
 	bcm43xx_setup_modes(bcm);
 	bcm43xx_security_init(bcm);
+	bcm43xx_measure_channel_change_time(bcm);
 	ieee80211_update_hw(bcm->net_dev, bcm->ieee);
 	ieee80211_netif_oper(bcm->net_dev, NETIF_ATTACH);
 	ieee80211_netif_oper(bcm->net_dev, NETIF_START);
 <at>  <at>  -4329,7 +4357,6  <at>  <at> 
 	ieee->host_gen_beacon = 1;
 	ieee->rx_includes_fcs = 1;
 	ieee->monitor_during_oper = 1;
-	ieee->channel_change_time = 20000;
 	ieee->tx = bcm43xx_net_hard_start_xmit;
 	ieee->open = bcm43xx_net_open;
 	ieee->stop = bcm43xx_net_stop;

--

-- 
Greetings Michael.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo <at> vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Gmane