aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00dev.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-02-03 09:49:59 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:19:28 -0500
commit6bb40dd13b458beb55f5c60dba1cb28e814bd640 (patch)
tree9b2aaa0de4a4d72a7afc3550b08572083b111c57 /drivers/net/wireless/rt2x00/rt2x00dev.c
parent9404ef34e4747228717d6e22ce3827ed366ccf41 (diff)
rt2x00: Add per-interface structure
Rework the interface handling. Delete the interface structure and replace it with a per-interface structure. This changes the way rt2x00 handles the active interface drastically. Copy ieee80211_bss_conf to the this rt2x00_intf structure during the bss_info_changed() callback function. This will allow us to reference it later, and removes the requirement for the device flag SHORT_PREAMBLE flag which is interface specific. Drivers receive the option to give the maximum number of virtual interfaces the device can handle. Virtual interface support: rt2400pci: 1 sta or 1 ap, * monitor interfaces rt2500pci: 1 sta or 1 ap, * monitor interfaces rt2500usb: 1 sta or 1 ap, * monitor interfaces rt61pci: 1 sta or 4 ap, * monitor interfaces rt73usb: 1 sta or 4 ap, * monitor interfaces At the moment none of the drivers support AP and STA interfaces simultaneously, this is a hardware limitation so future support will be very unlikely. Each interface structure receives its dedicated beacon entry, with this we can easily work with beaconing while multiple master mode interfaces are currently active. The configuration handlers for the MAC, BSSID and type are often called together since they all belong to the interface configuration. Merge the 3 configuration calls and cleanup the API between rt2x00lib and the drivers. While we are cleaning up the interface configuration anyway, we might as well clean up the configuration handler as well. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c154
1 files changed, 109 insertions, 45 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index bc07c56f89b3..014c307c270c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -136,12 +136,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
136 /* 136 /*
137 * Stop all scheduled work. 137 * Stop all scheduled work.
138 */ 138 */
139 if (work_pending(&rt2x00dev->beacon_work)) 139 if (work_pending(&rt2x00dev->intf_work))
140 cancel_work_sync(&rt2x00dev->beacon_work); 140 cancel_work_sync(&rt2x00dev->intf_work);
141 if (work_pending(&rt2x00dev->filter_work)) 141 if (work_pending(&rt2x00dev->filter_work))
142 cancel_work_sync(&rt2x00dev->filter_work); 142 cancel_work_sync(&rt2x00dev->filter_work);
143 if (work_pending(&rt2x00dev->config_work))
144 cancel_work_sync(&rt2x00dev->config_work);
145 143
146 /* 144 /*
147 * Stop the TX queues. 145 * Stop the TX queues.
@@ -173,7 +171,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
173 * When we are enabling the RX, we should also start the link tuner. 171 * When we are enabling the RX, we should also start the link tuner.
174 */ 172 */
175 if (state == STATE_RADIO_RX_ON && 173 if (state == STATE_RADIO_RX_ON &&
176 is_interface_present(&rt2x00dev->interface)) 174 (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count))
177 rt2x00lib_start_link_tuner(rt2x00dev); 175 rt2x00lib_start_link_tuner(rt2x00dev);
178} 176}
179 177
@@ -401,10 +399,10 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
401 unsigned int filter = rt2x00dev->packet_filter; 399 unsigned int filter = rt2x00dev->packet_filter;
402 400
403 /* 401 /*
404 * Since we had stored the filter inside interface.filter, 402 * Since we had stored the filter inside rt2x00dev->packet_filter,
405 * we should now clear that field. Otherwise the driver will 403 * we should now clear that field. Otherwise the driver will
406 * assume nothing has changed (*total_flags will be compared 404 * assume nothing has changed (*total_flags will be compared
407 * to interface.filter to determine if any action is required). 405 * to rt2x00dev->packet_filter to determine if any action is required).
408 */ 406 */
409 rt2x00dev->packet_filter = 0; 407 rt2x00dev->packet_filter = 0;
410 408
@@ -412,41 +410,72 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
412 filter, &filter, 0, NULL); 410 filter, &filter, 0, NULL);
413} 411}
414 412
415static void rt2x00lib_configuration_scheduled(struct work_struct *work) 413static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
414 struct ieee80211_vif *vif)
416{ 415{
417 struct rt2x00_dev *rt2x00dev = 416 struct rt2x00_dev *rt2x00dev = data;
418 container_of(work, struct rt2x00_dev, config_work); 417 struct rt2x00_intf *intf = vif_to_intf(vif);
419 struct ieee80211_bss_conf bss_conf; 418 struct sk_buff *skb;
419 struct ieee80211_tx_control control;
420 struct ieee80211_bss_conf conf;
421 int delayed_flags;
422
423 /*
424 * Copy all data we need during this action under the protection
425 * of a spinlock. Otherwise race conditions might occur which results
426 * into an invalid configuration.
427 */
428 spin_lock(&intf->lock);
429
430 memcpy(&conf, &intf->conf, sizeof(conf));
431 delayed_flags = intf->delayed_flags;
432 intf->delayed_flags = 0;
433
434 spin_unlock(&intf->lock);
435
436 if (delayed_flags & DELAYED_UPDATE_BEACON) {
437 skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
438 if (skb) {
439 rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
440 &control);
441 dev_kfree_skb(skb);
442 }
443 }
444
445 if (delayed_flags & DELAYED_CONFIG_PREAMBLE)
446 rt2x00lib_config_preamble(rt2x00dev, intf,
447 intf->conf.use_short_preamble);
448}
420 449
421 bss_conf.use_short_preamble = 450static void rt2x00lib_intf_scheduled(struct work_struct *work)
422 test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); 451{
452 struct rt2x00_dev *rt2x00dev =
453 container_of(work, struct rt2x00_dev, intf_work);
423 454
424 /* 455 /*
425 * FIXME: shouldn't invoke it this way because all other contents 456 * Iterate over each interface and perform the
426 * of bss_conf is invalid. 457 * requested configurations.
427 */ 458 */
428 rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id, 459 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
429 &bss_conf, BSS_CHANGED_ERP_PREAMBLE); 460 rt2x00lib_intf_scheduled_iter,
461 rt2x00dev);
430} 462}
431 463
432/* 464/*
433 * Interrupt context handlers. 465 * Interrupt context handlers.
434 */ 466 */
435static void rt2x00lib_beacondone_scheduled(struct work_struct *work) 467static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
468 struct ieee80211_vif *vif)
436{ 469{
437 struct rt2x00_dev *rt2x00dev = 470 struct rt2x00_intf *intf = vif_to_intf(vif);
438 container_of(work, struct rt2x00_dev, beacon_work);
439 struct ieee80211_tx_control control;
440 struct sk_buff *skb;
441 471
442 skb = ieee80211_beacon_get(rt2x00dev->hw, 472 if (vif->type != IEEE80211_IF_TYPE_AP &&
443 rt2x00dev->interface.id, &control); 473 vif->type != IEEE80211_IF_TYPE_IBSS)
444 if (!skb)
445 return; 474 return;
446 475
447 rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, &control); 476 spin_lock(&intf->lock);
448 477 intf->delayed_flags |= DELAYED_UPDATE_BEACON;
449 dev_kfree_skb(skb); 478 spin_unlock(&intf->lock);
450} 479}
451 480
452void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) 481void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
@@ -454,7 +483,11 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
454 if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) 483 if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
455 return; 484 return;
456 485
457 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work); 486 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
487 rt2x00lib_beacondone_iter,
488 rt2x00dev);
489
490 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
458} 491}
459EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); 492EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
460 493
@@ -1037,6 +1070,10 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
1037 return retval; 1070 return retval;
1038 } 1071 }
1039 1072
1073 rt2x00dev->intf_ap_count = 0;
1074 rt2x00dev->intf_sta_count = 0;
1075 rt2x00dev->intf_associated = 0;
1076
1040 __set_bit(DEVICE_STARTED, &rt2x00dev->flags); 1077 __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
1041 1078
1042 return 0; 1079 return 0;
@@ -1053,6 +1090,10 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
1053 */ 1090 */
1054 rt2x00lib_disable_radio(rt2x00dev); 1091 rt2x00lib_disable_radio(rt2x00dev);
1055 1092
1093 rt2x00dev->intf_ap_count = 0;
1094 rt2x00dev->intf_sta_count = 0;
1095 rt2x00dev->intf_associated = 0;
1096
1056 __clear_bit(DEVICE_STARTED, &rt2x00dev->flags); 1097 __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
1057} 1098}
1058 1099
@@ -1064,6 +1105,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
1064 int retval = -ENOMEM; 1105 int retval = -ENOMEM;
1065 1106
1066 /* 1107 /*
1108 * Make room for rt2x00_intf inside the per-interface
1109 * structure ieee80211_vif.
1110 */
1111 rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
1112
1113 /*
1067 * Let the driver probe the device to detect the capabilities. 1114 * Let the driver probe the device to detect the capabilities.
1068 */ 1115 */
1069 retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev); 1116 retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);
@@ -1075,17 +1122,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
1075 /* 1122 /*
1076 * Initialize configuration work. 1123 * Initialize configuration work.
1077 */ 1124 */
1078 INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled); 1125 INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
1079 INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); 1126 INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
1080 INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled);
1081 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); 1127 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
1082 1128
1083 /* 1129 /*
1084 * Reset current working type.
1085 */
1086 rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
1087
1088 /*
1089 * Allocate queue array. 1130 * Allocate queue array.
1090 */ 1131 */
1091 retval = rt2x00queue_allocate(rt2x00dev); 1132 retval = rt2x00queue_allocate(rt2x00dev);
@@ -1203,9 +1244,30 @@ exit:
1203} 1244}
1204EXPORT_SYMBOL_GPL(rt2x00lib_suspend); 1245EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
1205 1246
1247static void rt2x00lib_resume_intf(void *data, u8 *mac,
1248 struct ieee80211_vif *vif)
1249{
1250 struct rt2x00_dev *rt2x00dev = data;
1251 struct rt2x00_intf *intf = vif_to_intf(vif);
1252
1253 spin_lock(&intf->lock);
1254
1255 rt2x00lib_config_intf(rt2x00dev, intf,
1256 vif->type, intf->mac, intf->bssid);
1257
1258
1259 /*
1260 * Master or Ad-hoc mode require a new beacon update.
1261 */
1262 if (vif->type == IEEE80211_IF_TYPE_AP ||
1263 vif->type == IEEE80211_IF_TYPE_IBSS)
1264 intf->delayed_flags |= DELAYED_UPDATE_BEACON;
1265
1266 spin_unlock(&intf->lock);
1267}
1268
1206int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) 1269int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
1207{ 1270{
1208 struct interface *intf = &rt2x00dev->interface;
1209 int retval; 1271 int retval;
1210 1272
1211 NOTICE(rt2x00dev, "Waking up.\n"); 1273 NOTICE(rt2x00dev, "Waking up.\n");
@@ -1235,9 +1297,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
1235 if (!rt2x00dev->hw->conf.radio_enabled) 1297 if (!rt2x00dev->hw->conf.radio_enabled)
1236 rt2x00lib_disable_radio(rt2x00dev); 1298 rt2x00lib_disable_radio(rt2x00dev);
1237 1299
1238 rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); 1300 /*
1239 rt2x00lib_config_bssid(rt2x00dev, intf->bssid); 1301 * Iterator over each active interface to
1240 rt2x00lib_config_type(rt2x00dev, intf->type); 1302 * reconfigure the hardware.
1303 */
1304 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
1305 rt2x00lib_resume_intf, rt2x00dev);
1241 1306
1242 /* 1307 /*
1243 * We are ready again to receive requests from mac80211. 1308 * We are ready again to receive requests from mac80211.
@@ -1253,12 +1318,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
1253 ieee80211_start_queues(rt2x00dev->hw); 1318 ieee80211_start_queues(rt2x00dev->hw);
1254 1319
1255 /* 1320 /*
1256 * When in Master or Ad-hoc mode, 1321 * During interface iteration we might have changed the
1257 * restart Beacon transmitting by faking a beacondone event. 1322 * delayed_flags, time to handles the event by calling
1323 * the work handler directly.
1258 */ 1324 */
1259 if (intf->type == IEEE80211_IF_TYPE_AP || 1325 rt2x00lib_intf_scheduled(&rt2x00dev->intf_work);
1260 intf->type == IEEE80211_IF_TYPE_IBSS)
1261 rt2x00lib_beacondone(rt2x00dev);
1262 1326
1263 return 0; 1327 return 0;
1264 1328