aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00dev.c
diff options
context:
space:
mode:
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