>From Ivo van Doorn <[EMAIL PROTECTED]>
Move all settings depending on the current association into
a seperate interface structure.
Altough we only support 1 association type at a time,
we do support multiple monitor devices, keep track of the
number using the monitor_count field.
Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-22 23:17:54.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 14:54:53.000000000 +0200
@@ -411,7 +411,7 @@
rt2x00_set_field32(®, RXCSR0_DROP_TODS, 0);
rt2x00_set_field32(®, RXCSR0_DROP_CRC, 1);
- if (type == IEEE80211_IF_TYPE_MNTR) {
+ if (rt2x00pci->interface.monitor_count) {
rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 0);
@@ -426,7 +426,7 @@
/*
* Enable promisc mode when in monitor mode.
*/
- if (type == IEEE80211_IF_TYPE_MNTR)
+ if (rt2x00pci->interface.monitor_count)
rt2400pci_config_promisc(rt2x00pci, 1);
/*
@@ -445,7 +445,7 @@
/*
* Update working mode.
*/
- rt2x00pci->type = type;
+ rt2x00pci->interface.type = type;
}
static void rt2400pci_config_channel(struct rt2x00_pci *rt2x00pci,
@@ -897,7 +897,7 @@
memset(&beacon, 0x00, sizeof(beacon));
skb = ieee80211_beacon_get(ring->net_dev,
- rt2x00pci->interface_id, &beacon);
+ rt2x00pci->interface.id, &beacon);
if (!skb)
return;
@@ -1725,16 +1725,36 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return -ENOBUFS;
- rt2x00pci->interface_id = conf->if_id;
+ SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+ rt2x00_add_interface(&rt2x00pci->interface, conf);
+ /*
+ * Enable configuration.
+ */
+ rt2400pci_config_type(rt2x00pci, conf->type);
rt2400pci_config_mac_address(rt2x00pci, conf->mac_addr);
- SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+ /*
+ * In case of master mode, set the BSSID to our MAC.
+ */
+ if (conf->type == IEEE80211_IF_TYPE_AP) {
+ memcpy(&rt2x00pci->interface.bssid, conf->mac_addr, ETH_ALEN);
+ rt2400pci_config_bssid(rt2x00pci, conf->mac_addr);
+ }
+
+ /*
+ * Enable radio when this is the first
+ * interface that is brought up.
+ */
+ if (!GET_FLAG(rt2x00pci, DEVICE_ENABLED_RADIO))
+ return rt2400pci_enable_radio(rt2x00pci);
return 0;
}
@@ -1745,14 +1765,22 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (!GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ !GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return;
- rt2x00pci->interface_id = 0;
+ rt2x00_remove_interface(&rt2x00pci->interface, conf);
CLEAR_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+ /*
+ * Disable radio if this was the last interface
+ * that was working with this device.
+ */
+ if (!rt2x00pci->interface.monitor_count)
+ rt2400pci_disable_radio(rt2x00pci);
}
static void rt2400pci_config_update(void *data)
@@ -1818,15 +1846,20 @@
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- rt2400pci_config_type(rt2x00pci, conf->type);
-
/*
* When configuring monitor mode, we are done now.
+ * but if we are configuring another mode it must be
+ * equal to the interface that has been added.
*/
- if (rt2x00pci->type == IEEE80211_IF_TYPE_MNTR)
+ if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
+ else if (conf->type != rt2x00pci->interface.type)
+ return -EINVAL;
- rt2400pci_config_bssid(rt2x00pci, conf->bssid);
+ if (conf->bssid) {
+ memcpy(&rt2x00pci->interface.bssid, conf->bssid, ETH_ALEN);
+ rt2400pci_config_bssid(rt2x00pci, conf->bssid);
+ }
return 0;
}
@@ -1835,21 +1868,27 @@
unsigned short flags, int mc_count)
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
+ int update = 0;
+
+ if (GET_FLAG(rt2x00pci, INTERFACE_PROMISC)) {
+ if (!(flags & IFF_PROMISC)) {
+ rt2x00pci->interface.promisc = 0;
+ update = 1;
+ }
+ } else {
+ if (flags & IFF_PROMISC) {
+ rt2x00pci->interface.promisc = 1;
+ update = 1;
+ }
+ }
/*
* Monitor mode works with PROMISC mode forced on,
* so there is nothing to be done here.
*/
- if (rt2x00pci->type == IEEE80211_IF_TYPE_MNTR)
- return;
-
- if (GET_FLAG(rt2x00pci, INTERFACE_PROMISC)) {
- if (!(flags & IFF_PROMISC))
- rt2400pci_config_promisc(rt2x00pci, 0);
- } else {
- if (flags & IFF_PROMISC)
- rt2400pci_config_promisc(rt2x00pci, 1);
- }
+ if (update && !rt2x00pci->interface.monitor_count)
+ rt2400pci_config_promisc(rt2x00pci,
+ rt2x00pci->interface.promisc);
}
static void rt2400pci_scan(void *data)
@@ -2419,6 +2458,11 @@
INIT_WORK(&rt2x00pci->config_work, rt2400pci_config_update, rt2x00pci);
/*
+ * Reset current working type.
+ */
+ rt2x00pci->interface.type = -EINVAL;
+
+ /*
* Intialize scanning attributes.
*/
INIT_WORK(&rt2x00pci->scan_work, rt2400pci_scan, rt2x00pci);
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-22 23:18:04.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 14:55:00.000000000 +0200
@@ -411,7 +411,7 @@
rt2x00_set_field32(®, RXCSR0_DROP_TODS, 0);
rt2x00_set_field32(®, RXCSR0_DROP_CRC, 1);
- if (type == IEEE80211_IF_TYPE_MNTR) {
+ if (rt2x00pci->interface.monitor_count) {
rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0);
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 0);
@@ -429,7 +429,7 @@
/*
* Enable promisc mode when in monitor mode.
*/
- if (type == IEEE80211_IF_TYPE_MNTR)
+ if (rt2x00pci->interface.monitor_count)
rt2500pci_config_promisc(rt2x00pci, 1);
/*
@@ -448,7 +448,7 @@
/*
* Update working mode.
*/
- rt2x00pci->type = type;
+ rt2x00pci->interface.type = type;
}
static void rt2500pci_config_channel(struct rt2x00_pci *rt2x00pci,
@@ -976,7 +976,7 @@
memset(&beacon, 0x00, sizeof(beacon));
skb = ieee80211_beacon_get(ring->net_dev,
- rt2x00pci->interface_id, &beacon);
+ rt2x00pci->interface.id, &beacon);
if (!skb)
return;
@@ -1850,16 +1850,36 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return -ENOBUFS;
- rt2x00pci->interface_id = conf->if_id;
+ SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+ rt2x00_add_interface(&rt2x00pci->interface, conf);
+ /*
+ * Enable configuration.
+ */
+ rt2500pci_config_type(rt2x00pci, conf->type);
rt2500pci_config_mac_address(rt2x00pci, conf->mac_addr);
- SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+ /*
+ * In case of master mode, set the BSSID to our MAC.
+ */
+ if (conf->type == IEEE80211_IF_TYPE_AP) {
+ memcpy(&rt2x00pci->interface.bssid, conf->mac_addr, ETH_ALEN);
+ rt2500pci_config_bssid(rt2x00pci, conf->mac_addr);
+ }
+
+ /*
+ * Enable radio when this is the first
+ * interface that is brought up.
+ */
+ if (!GET_FLAG(rt2x00pci, DEVICE_ENABLED_RADIO))
+ return rt2500pci_enable_radio(rt2x00pci);
return 0;
}
@@ -1870,14 +1890,22 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (!GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ !GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return;
- rt2x00pci->interface_id = 0;
+ rt2x00_remove_interface(&rt2x00pci->interface, conf);
CLEAR_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+ /*
+ * Disable radio if this was the last interface
+ * that was working with this device.
+ */
+ if (!rt2x00pci->interface.monitor_count)
+ rt2500pci_disable_radio(rt2x00pci);
}
static void rt2500pci_config_update(void *data)
@@ -1943,15 +1971,20 @@
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- rt2500pci_config_type(rt2x00pci, conf->type);
-
/*
* When configuring monitor mode, we are done now.
+ * but if we are configuring another mode it must be
+ * equal to the interface that has been added.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
+ else if (conf->type != rt2x00pci->interface.type)
+ return -EINVAL;
- rt2500pci_config_bssid(rt2x00pci, conf->bssid);
+ if (conf->bssid) {
+ memcpy(&rt2x00pci->interface.bssid, conf->bssid, ETH_ALEN);
+ rt2500pci_config_bssid(rt2x00pci, conf->bssid);
+ }
return 0;
}
@@ -1960,21 +1993,27 @@
unsigned short flags, int mc_count)
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
+ int update = 0;
+
+ if (GET_FLAG(rt2x00pci, INTERFACE_PROMISC)) {
+ if (!(flags & IFF_PROMISC)) {
+ rt2x00pci->interface.promisc = 0;
+ update = 1;
+ }
+ } else {
+ if (flags & IFF_PROMISC) {
+ rt2x00pci->interface.promisc = 1;
+ update = 1;
+ }
+ }
/*
* Monitor mode works with PROMISC mode forced on,
* so there is nothing to be done here.
*/
- if (rt2x00pci->type == IEEE80211_IF_TYPE_MNTR)
- return;
-
- if (GET_FLAG(rt2x00pci, INTERFACE_PROMISC)) {
- if (!(flags & IFF_PROMISC))
- rt2500pci_config_promisc(rt2x00pci, 0);
- } else {
- if (flags & IFF_PROMISC)
- rt2500pci_config_promisc(rt2x00pci, 1);
- }
+ if (update && !rt2x00pci->interface.monitor_count)
+ rt2500pci_config_promisc(rt2x00pci,
+ rt2x00pci->interface.promisc);
}
static void rt2500pci_scan(void *data)
@@ -2722,6 +2761,11 @@
INIT_WORK(&rt2x00pci->config_work, rt2500pci_config_update, rt2x00pci);
/*
+ * Reset current working type.
+ */
+ rt2x00pci->interface.type = -EINVAL;
+
+ /*
* Intialize scanning attributes.
*/
INIT_WORK(&rt2x00pci->scan_work, rt2500pci_scan, rt2x00pci);
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-22 22:53:28.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 14:54:29.000000000 +0200
@@ -261,7 +261,7 @@
rt2x00_set_field16_nb(®, TXRX_CSR2_DROP_TODS, 0);
rt2x00_set_field16_nb(®, TXRX_CSR2_DROP_CRC, 1);
- if (type == IEEE80211_IF_TYPE_MNTR) {
+ if (rt2x00usb->interface.monitor_count) {
rt2x00_set_field16_nb(®, TXRX_CSR2_DROP_PHYSICAL, 0);
rt2x00_set_field16_nb(®, TXRX_CSR2_DROP_CONTROL, 0);
rt2x00_set_field16_nb(®, TXRX_CSR2_DROP_VERSION_ERROR, 0);
@@ -276,7 +276,7 @@
/*
* Enable promisc mode when in monitor mode.
*/
- if (type == IEEE80211_IF_TYPE_MNTR)
+ if (rt2x00usb->interface.monitor_count)
rt2500usb_config_promisc(rt2x00usb, 1);
/*
@@ -295,7 +295,7 @@
/*
* Update working mode.
*/
- rt2x00usb->type = type;
+ rt2x00usb->interface.type = type;
}
static void rt2500usb_config_channel(struct rt2x00_usb *rt2x00usb,
@@ -796,7 +796,7 @@
memset(&beacon, 0x00, sizeof(beacon));
skb = ieee80211_beacon_get(ring->net_dev,
- rt2x00usb->interface_id, &beacon);
+ rt2x00usb->interface.id, &beacon);
if (!skb)
return;
@@ -1510,16 +1510,36 @@
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
return -ENOBUFS;
- rt2x00usb->interface_id = conf->if_id;
+ SET_FLAG(rt2x00usb, INTERFACE_INITIALIZED);
+
+ rt2x00_add_interface(&rt2x00usb->interface, conf);
+ /*
+ * Enable configuration.
+ */
+ rt2500usb_config_type(rt2x00usb, conf->type);
rt2500usb_config_mac_address(rt2x00usb, conf->mac_addr);
- SET_FLAG(rt2x00usb, INTERFACE_INITIALIZED);
+ /*
+ * In case of master mode, set the BSSID to our MAC.
+ */
+ if (conf->type == IEEE80211_IF_TYPE_AP) {
+ memcpy(&rt2x00usb->interface.bssid, conf->mac_addr, ETH_ALEN);
+ rt2500usb_config_bssid(rt2x00usb, conf->mac_addr);
+ }
+
+ /*
+ * Enable radio when this is the first
+ * interface that is brought up.
+ */
+ if (!GET_FLAG(rt2x00usb, DEVICE_ENABLED_RADIO))
+ return rt2500usb_enable_radio(rt2x00usb);
return 0;
}
@@ -1530,14 +1550,22 @@
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (!GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ !GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
return;
- rt2x00usb->interface_id = 0;
+ rt2x00_remove_interface(&rt2x00usb->interface, conf);
CLEAR_FLAG(rt2x00usb, INTERFACE_INITIALIZED);
+
+ /*
+ * Disable radio if this was the last interface
+ * that was working with this device.
+ */
+ if (!rt2x00usb->interface.monitor_count)
+ rt2500usb_disable_radio(rt2x00usb);
}
static void rt2500usb_config_update(void *data)
@@ -1598,20 +1626,35 @@
return !queue_work(rt2x00usb->workqueue, &rt2x00usb->config_work);
}
+static void rt2500usb_interface_update(void *data)
+{
+ struct rt2x00_usb *rt2x00usb = data;
+
+ rt2500usb_config_bssid(rt2x00usb, &rt2x00usb->interface.bssid[0]);
+ rt2500usb_config_promisc(rt2x00usb, (rt2x00usb->interface.promisc ||
+ rt2x00usb->interface.monitor_count));
+}
+
static int rt2500usb_config_interface(struct net_device *net_dev, int if_id,
struct ieee80211_if_conf *conf)
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
- rt2500usb_config_type(rt2x00usb, conf->type);
-
/*
* When configuring monitor mode, we are done now.
+ * but if we are configuring another mode it must be
+ * equal to the interface that has been added.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
+ else if (conf->type != rt2x00usb->interface.type)
+ return -EINVAL;
- rt2500usb_config_bssid(rt2x00usb, conf->bssid);
+ if (conf->bssid) {
+ memcpy(&rt2x00usb->interface.bssid, conf->bssid, ETH_ALEN);
+ return !queue_work(rt2x00usb->workqueue,
+ &rt2x00usb->interface.work);
+ }
return 0;
}
@@ -1620,21 +1663,27 @@
unsigned short flags, int mc_count)
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ int update = 0;
+
+ if (GET_FLAG(rt2x00usb, INTERFACE_PROMISC)) {
+ if (!(flags & IFF_PROMISC)) {
+ rt2x00usb->interface.promisc = 0;
+ update = 1;
+ }
+ } else {
+ if (flags & IFF_PROMISC) {
+ rt2x00usb->interface.promisc = 1;
+ update = 1;
+ }
+ }
/*
* Monitor mode works with PROMISC mode forced on,
* so there is nothing to be done here.
*/
- if (rt2x00usb->type == IEEE80211_IF_TYPE_MNTR)
- return;
-
- if (GET_FLAG(rt2x00usb, INTERFACE_PROMISC)) {
- if (!(flags & IFF_PROMISC))
- rt2500usb_config_promisc(rt2x00usb, 0);
- } else {
- if (flags & IFF_PROMISC)
- rt2500usb_config_promisc(rt2x00usb, 1);
- }
+ if (update && !rt2x00usb->interface.monitor_count)
+ queue_work(rt2x00usb->workqueue,
+ &rt2x00usb->interface.work);
}
static void rt2500usb_scan(void *data)
@@ -2326,6 +2375,13 @@
* Initialize cofniguration work.
*/
INIT_WORK(&rt2x00usb->config_work, rt2500usb_config_update, rt2x00usb);
+ INIT_WORK(&rt2x00usb->interface.work,
+ rt2500usb_interface_update, rt2x00usb);
+
+ /*
+ * Reset current working type.
+ */
+ rt2x00usb->interface.type = -EINVAL;
/*
* Intialize scanning attributes.
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2x00.h
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2x00.h
2006-07-23 14:17:22.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2x00.h
2006-07-23 14:24:04.000000000 +0200
@@ -570,6 +570,90 @@
}
/*
+ * Interface structure
+ * Configuration details about the current interface.
+ */
+struct interface {
+ /*
+ * Interface identification. The value is assigned
+ * to us by the 80211 stack, and is used to request
+ * new beacons.
+ */
+ int id;
+
+ /*
+ * Current working type (IEEE80211_IF_TYPE_*).
+ * This excludes the type IEEE80211_IF_TYPE_MNTR
+ * since that is counted seperately in the monitor_count
+ * field.
+ */
+ int type;
+
+ /*
+ * BBSID of the AP to associate with.
+ */
+ u8 bssid[ETH_ALEN];
+
+ /*
+ * Store the promisc mode for the current interface.
+ * monitor mode always forces promisc mode to be enabled,
+ * so we need to store the promisc mode seperately.
+ */
+ short promisc;
+
+ /*
+ * Monitor mode count, the number of interfaces
+ * in monitor mode that that have been added.
+ */
+ short monitor_count;
+
+ /*
+ * Sequence number for software controled sequence counters.
+ */
+ u16 sequence;
+
+ /*
+ * Work structure in case interface configuration
+ * requires scheduling.
+ */
+ struct work_struct work;
+};
+
+static inline void rt2x00_add_interface(struct interface *intf,
+ struct ieee80211_if_init_conf *conf)
+{
+ /*
+ * We support muliple monitor mode interfaces.
+ * All we need to do is increase the monitor_count.
+ */
+ if (conf->type == IEEE80211_IF_TYPE_MNTR) {
+ intf->monitor_count++;
+ } else {
+ intf->id = conf->if_id;
+ intf->promisc = 0;
+ intf->sequence = 0;
+ }
+}
+
+static inline void rt2x00_remove_interface(struct interface *intf,
+ struct ieee80211_if_init_conf *conf)
+{
+ /*
+ * We support muliple monitor mode interfaces.
+ * All we need to do is decrease the monitor_count.
+ */
+ if (conf->type == IEEE80211_IF_TYPE_MNTR) {
+ intf->monitor_count--;
+ } else if (intf->type == conf->type) {
+ intf->id = 0;
+ intf->type = -EINVAL;
+ memset(&intf->bssid, 0x00, ETH_ALEN);
+ intf->promisc = 0;
+ intf->sequence = 0;
+ }
+}
+
+/*
* Scanning structure.
* Swithing channel during scanning will be put
* in a workqueue so we will be able to sleep
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
2006-07-22 23:04:01.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
2006-07-23 14:24:46.000000000 +0200
@@ -155,15 +155,9 @@
struct workqueue_struct *workqueue;
/*
- * Interface identication required for requesting beacons
- * from dscape stack.
+ * Interface we are connected with.
*/
- int interface_id;
-
- /*
- * Current working mode.
- */
- int type;
+ struct interface interface;
/*
* EEPROM bus width.
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
2006-07-22 23:04:13.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
2006-07-23 14:25:07.000000000 +0200
@@ -150,15 +150,9 @@
struct workqueue_struct *workqueue;
/*
- * Interface identication required for requesting beacons
- * from dscape stack.
+ * Interface we are connected with.
*/
- int interface_id;
-
- /*
- * Current working mode.
- */
- int type;
+ struct interface interface;
/*
* Frequency offset (for rt73usb).
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt61pci.c
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-22 23:19:03.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 14:55:07.000000000 +0200
@@ -442,7 +442,7 @@
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 0);
rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, 1);
- if (type == IEEE80211_IF_TYPE_MNTR) {
+ if (rt2x00pci->interface.monitor_count) {
rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 0);
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 0);
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 0);
@@ -460,7 +460,7 @@
/*
* Enable promisc mode when in monitor mode.
*/
- if (type == IEEE80211_IF_TYPE_MNTR)
+ if (rt2x00pci->interface.monitor_count)
rt61pci_config_promisc(rt2x00pci, 1);
/*
@@ -479,7 +479,7 @@
/*
* Update working mode.
*/
- rt2x00pci->type = type;
+ rt2x00pci->interface.type = type;
}
static void rt61pci_config_channel(struct rt2x00_pci *rt2x00pci,
@@ -1231,7 +1231,7 @@
memset(&beacon, 0x00, sizeof(beacon));
skb = ieee80211_beacon_get(ring->net_dev,
- rt2x00pci->interface_id, &beacon);
+ rt2x00pci->interface.id, &beacon);
if (!skb)
return;
@@ -2305,16 +2305,36 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return -ENOBUFS;
- rt2x00pci->interface_id = conf->if_id;
+ SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+ rt2x00_add_interface(&rt2x00pci->interface, conf);
+ /*
+ * Enable configuration.
+ */
+ rt61pci_config_type(rt2x00pci, conf->type);
rt61pci_config_mac_address(rt2x00pci, conf->mac_addr);
- SET_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+ /*
+ * In case of master mode, set the BSSID to our MAC.
+ */
+ if (conf->type == IEEE80211_IF_TYPE_AP) {
+ memcpy(&rt2x00pci->interface.bssid, conf->mac_addr, ETH_ALEN);
+ rt61pci_config_bssid(rt2x00pci, conf->mac_addr);
+ }
+
+ /*
+ * Enable radio when this is the first
+ * interface that is brought up.
+ */
+ if (!GET_FLAG(rt2x00pci, DEVICE_ENABLED_RADIO))
+ return rt61pci_enable_radio(rt2x00pci);
return 0;
}
@@ -2325,14 +2345,22 @@
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (!GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ !GET_FLAG(rt2x00pci, INTERFACE_INITIALIZED))
return;
- rt2x00pci->interface_id = 0;
+ rt2x00_remove_interface(&rt2x00pci->interface, conf);
CLEAR_FLAG(rt2x00pci, INTERFACE_INITIALIZED);
+
+ /*
+ * Disable radio if this was the last interface
+ * that was working with this device.
+ */
+ if (!rt2x00pci->interface.monitor_count)
+ rt61pci_disable_radio(rt2x00pci);
}
static void rt61pci_config_update(void *data)
@@ -2398,15 +2426,20 @@
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
- rt61pci_config_type(rt2x00pci, conf->type);
-
/*
* When configuring monitor mode, we are done now.
+ * but if we are configuring another mode it must be
+ * equal to the interface that has been added.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
+ else if (conf->type != rt2x00pci->interface.type)
+ return -EINVAL;
- rt61pci_config_bssid(rt2x00pci, conf->bssid);
+ if (conf->bssid) {
+ memcpy(&rt2x00pci->interface.bssid, conf->bssid, ETH_ALEN);
+ rt61pci_config_bssid(rt2x00pci, conf->bssid);
+ }
return 0;
}
@@ -2415,21 +2448,27 @@
unsigned short flags, int mc_count)
{
struct rt2x00_pci *rt2x00pci = ieee80211_dev_hw_data(net_dev);
+ int update = 0;
+
+ if (GET_FLAG(rt2x00pci, INTERFACE_PROMISC)) {
+ if (!(flags & IFF_PROMISC)) {
+ rt2x00pci->interface.promisc = 0;
+ update = 1;
+ }
+ } else {
+ if (flags & IFF_PROMISC) {
+ rt2x00pci->interface.promisc = 1;
+ update = 1;
+ }
+ }
/*
* Monitor mode works with PROMISC mode forced on,
* so there is nothing to be done here.
*/
- if (rt2x00pci->type == IEEE80211_IF_TYPE_MNTR)
- return;
-
- if (GET_FLAG(rt2x00pci, INTERFACE_PROMISC)) {
- if (!(flags & IFF_PROMISC))
- rt61pci_config_promisc(rt2x00pci, 0);
- } else {
- if (flags & IFF_PROMISC)
- rt61pci_config_promisc(rt2x00pci, 1);
- }
+ if (update && !rt2x00pci->interface.monitor_count)
+ rt61pci_config_promisc(rt2x00pci,
+ rt2x00pci->interface.promisc);
}
static void rt61pci_scan(void *data)
@@ -3263,6 +3302,11 @@
INIT_WORK(&rt2x00pci->config_work, rt61pci_config_update, rt2x00pci);
/*
+ * Reset current working type.
+ */
+ rt2x00pci->interface.type = -EINVAL;
+
+ /*
* Initialize scanning attributes.
*/
INIT_WORK(&rt2x00pci->scan_work, rt61pci_scan, rt2x00pci);
diff -rU3 wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt73usb.c
wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-style/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-22 23:18:51.000000000 +0200
+++ wireless-dev-interface/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 14:55:15.000000000 +0200
@@ -263,7 +263,7 @@
rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 0);
rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, 1);
- if (type == IEEE80211_IF_TYPE_MNTR) {
+ if (rt2x00usb->interface.monitor_count) {
rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 0);
rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 0);
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 0);
@@ -281,7 +281,7 @@
/*
* Enable promisc mode when in monitor mode.
*/
- if (type == IEEE80211_IF_TYPE_MNTR)
+ if (rt2x00usb->interface.monitor_count)
rt73usb_config_promisc(rt2x00usb, 1);
/*
@@ -296,6 +296,11 @@
else
rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC_MODE, 0);
rt2x00_register_write(rt2x00usb, TXRX_CSR9, reg);
+
+ /*
+ * Update working mode.
+ */
+ rt2x00usb->interface.type = type;
}
static void rt73usb_config_channel(struct rt2x00_usb *rt2x00usb,
@@ -959,7 +964,7 @@
memset(&beacon, 0x00, sizeof(beacon));
skb = ieee80211_beacon_get(ring->net_dev,
- rt2x00usb->interface_id, &beacon);
+ rt2x00usb->interface.id, &beacon);
if (!skb)
return;
@@ -1804,16 +1809,36 @@
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
return -ENOBUFS;
- rt2x00usb->interface_id = conf->if_id;
+ SET_FLAG(rt2x00usb, INTERFACE_INITIALIZED);
+
+ rt2x00_add_interface(&rt2x00usb->interface, conf);
+ /*
+ * Enable configuration.
+ */
+ rt73usb_config_type(rt2x00usb, conf->type);
rt73usb_config_mac_address(rt2x00usb, conf->mac_addr);
- SET_FLAG(rt2x00usb, INTERFACE_INITIALIZED);
+ /*
+ * In case of master mode, set the BSSID to our MAC.
+ */
+ if (conf->type == IEEE80211_IF_TYPE_AP) {
+ memcpy(&rt2x00usb->interface.bssid, conf->mac_addr, ETH_ALEN);
+ rt73usb_config_bssid(rt2x00usb, conf->mac_addr);
+ }
+
+ /*
+ * Enable radio when this is the first
+ * interface that is brought up.
+ */
+ if (!GET_FLAG(rt2x00usb, DEVICE_ENABLED_RADIO))
+ return rt73usb_enable_radio(rt2x00usb);
return 0;
}
@@ -1824,14 +1849,22 @@
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
/*
- * We only support 1 single working mode.
+ * We only support 1 non-monitor interface.
*/
- if (!GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
+ if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+ !GET_FLAG(rt2x00usb, INTERFACE_INITIALIZED))
return;
- rt2x00usb->interface_id = 0;
+ rt2x00_remove_interface(&rt2x00usb->interface, conf);
CLEAR_FLAG(rt2x00usb, INTERFACE_INITIALIZED);
+
+ /*
+ * Disable radio if this was the last interface
+ * that was working with this device.
+ */
+ if (!rt2x00usb->interface.monitor_count)
+ rt73usb_disable_radio(rt2x00usb);
}
static void rt73usb_config_update(void *data)
@@ -1895,20 +1928,35 @@
return !queue_work(rt2x00usb->workqueue, &rt2x00usb->config_work);
}
+static void rt73usb_interface_update(void *data)
+{
+ struct rt2x00_usb *rt2x00usb = data;
+
+ rt73usb_config_bssid(rt2x00usb, &rt2x00usb->interface.bssid[0]);
+ rt73usb_config_promisc(rt2x00usb, (rt2x00usb->interface.promisc ||
+ rt2x00usb->interface.monitor_count));
+}
+
static int rt73usb_config_interface(struct net_device *net_dev, int if_id,
struct ieee80211_if_conf *conf)
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
- rt73usb_config_type(rt2x00usb, conf->type);
-
/*
* When configuring monitor mode, we are done now.
+ * but if we are configuring another mode it must be
+ * equal to the interface that has been added.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
+ else if (conf->type != rt2x00usb->interface.type)
+ return -EINVAL;
- rt73usb_config_bssid(rt2x00usb, conf->bssid);
+ if (conf->bssid) {
+ memcpy(&rt2x00usb->interface.bssid, conf->bssid, ETH_ALEN);
+ return !queue_work(rt2x00usb->workqueue,
+ &rt2x00usb->interface.work);
+ }
return 0;
}
@@ -1917,21 +1965,27 @@
unsigned short flags, int mc_count)
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ int update = 0;
+
+ if (GET_FLAG(rt2x00usb, INTERFACE_PROMISC)) {
+ if (!(flags & IFF_PROMISC)) {
+ rt2x00usb->interface.promisc = 0;
+ update = 1;
+ }
+ } else {
+ if (flags & IFF_PROMISC) {
+ rt2x00usb->interface.promisc = 1;
+ update = 1;
+ }
+ }
/*
* Monitor mode works with PROMISC mode forced on,
* so there is nothing to be done here.
*/
- if (rt2x00usb->type == IEEE80211_IF_TYPE_MNTR)
- return;
-
- if (GET_FLAG(rt2x00usb, INTERFACE_PROMISC)) {
- if (!(flags & IFF_PROMISC))
- rt73usb_config_promisc(rt2x00usb, 0);
- } else {
- if (flags & IFF_PROMISC)
- rt73usb_config_promisc(rt2x00usb, 1);
- }
+ if (update && !rt2x00usb->interface.monitor_count)
+ queue_work(rt2x00usb->workqueue,
+ &rt2x00usb->interface.work);
}
static void rt73usb_scan(void *data)
@@ -2730,6 +2784,13 @@
* Initialize cofniguration work.
*/
INIT_WORK(&rt2x00usb->config_work, rt73usb_config_update, rt2x00usb);
+ INIT_WORK(&rt2x00usb->interface.work,
+ rt73usb_interface_update, rt2x00usb);
+
+ /*
+ * Reset current working type.
+ */
+ rt2x00usb->interface.type = -EINVAL;
/*
* Intialize scanning attributes.
-
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