aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanoharan@atheros.com>2010-12-08 09:08:55 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-13 15:23:27 -0500
commit6b3b991dbdb66a65a2167abbd9503e519fa999f3 (patch)
tree1f352177d49c7b1a5ecdad559bc5a0ce39334582
parenta7ffac9591a2a0ee74c431396ae475a8d0caa51e (diff)
ath9k: Add change_interface callback
Add support to change interface type without bringing down the interface. Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c90
1 files changed, 69 insertions, 21 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index ef87637e4245..ca35aaa7aec6 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1428,13 +1428,78 @@ out:
1428 return ret; 1428 return ret;
1429} 1429}
1430 1430
1431static void ath9k_reclaim_beacon(struct ath_softc *sc,
1432 struct ieee80211_vif *vif)
1433{
1434 struct ath_vif *avp = (void *)vif->drv_priv;
1435
1436 /* Disable SWBA interrupt */
1437 sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
1438 ath9k_ps_wakeup(sc);
1439 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1440 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
1441 tasklet_kill(&sc->bcon_tasklet);
1442 ath9k_ps_restore(sc);
1443
1444 ath_beacon_return(sc, avp);
1445 sc->sc_flags &= ~SC_OP_BEACONS;
1446
1447 if (sc->nbcnvifs > 0) {
1448 /* Re-enable beaconing */
1449 sc->sc_ah->imask |= ATH9K_INT_SWBA;
1450 ath9k_ps_wakeup(sc);
1451 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1452 ath9k_ps_restore(sc);
1453 }
1454}
1455
1456static int ath9k_change_interface(struct ieee80211_hw *hw,
1457 struct ieee80211_vif *vif,
1458 enum nl80211_iftype new_type,
1459 bool p2p)
1460{
1461 struct ath_wiphy *aphy = hw->priv;
1462 struct ath_softc *sc = aphy->sc;
1463 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1464
1465 ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
1466 mutex_lock(&sc->mutex);
1467
1468 switch (new_type) {
1469 case NL80211_IFTYPE_AP:
1470 case NL80211_IFTYPE_ADHOC:
1471 if (sc->nbcnvifs >= ATH_BCBUF) {
1472 ath_err(common, "No beacon slot available\n");
1473 return -ENOBUFS;
1474 }
1475 break;
1476 case NL80211_IFTYPE_STATION:
1477 /* Stop ANI */
1478 sc->sc_flags &= ~SC_OP_ANI_RUN;
1479 del_timer_sync(&common->ani.timer);
1480 if ((vif->type == NL80211_IFTYPE_AP) ||
1481 (vif->type == NL80211_IFTYPE_ADHOC))
1482 ath9k_reclaim_beacon(sc, vif);
1483 break;
1484 default:
1485 ath_err(common, "Interface type %d not yet supported\n",
1486 vif->type);
1487 mutex_unlock(&sc->mutex);
1488 return -ENOTSUPP;
1489 }
1490 vif->type = new_type;
1491 vif->p2p = p2p;
1492
1493 mutex_unlock(&sc->mutex);
1494 return 0;
1495}
1496
1431static void ath9k_remove_interface(struct ieee80211_hw *hw, 1497static void ath9k_remove_interface(struct ieee80211_hw *hw,
1432 struct ieee80211_vif *vif) 1498 struct ieee80211_vif *vif)
1433{ 1499{
1434 struct ath_wiphy *aphy = hw->priv; 1500 struct ath_wiphy *aphy = hw->priv;
1435 struct ath_softc *sc = aphy->sc; 1501 struct ath_softc *sc = aphy->sc;
1436 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1502 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1437 struct ath_vif *avp = (void *)vif->drv_priv;
1438 1503
1439 ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); 1504 ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
1440 1505
@@ -1447,26 +1512,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
1447 /* Reclaim beacon resources */ 1512 /* Reclaim beacon resources */
1448 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || 1513 if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
1449 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || 1514 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
1450 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { 1515 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
1451 /* Disable SWBA interrupt */ 1516 ath9k_reclaim_beacon(sc, vif);
1452 sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
1453 ath9k_ps_wakeup(sc);
1454 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1455 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
1456 ath9k_ps_restore(sc);
1457 tasklet_kill(&sc->bcon_tasklet);
1458 }
1459
1460 ath_beacon_return(sc, avp);
1461 sc->sc_flags &= ~SC_OP_BEACONS;
1462
1463 if (sc->nbcnvifs) {
1464 /* Re-enable SWBA interrupt */
1465 sc->sc_ah->imask |= ATH9K_INT_SWBA;
1466 ath9k_ps_wakeup(sc);
1467 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1468 ath9k_ps_restore(sc);
1469 }
1470 1517
1471 sc->nvifs--; 1518 sc->nvifs--;
1472 1519
@@ -2111,6 +2158,7 @@ struct ieee80211_ops ath9k_ops = {
2111 .start = ath9k_start, 2158 .start = ath9k_start,
2112 .stop = ath9k_stop, 2159 .stop = ath9k_stop,
2113 .add_interface = ath9k_add_interface, 2160 .add_interface = ath9k_add_interface,
2161 .change_interface = ath9k_change_interface,
2114 .remove_interface = ath9k_remove_interface, 2162 .remove_interface = ath9k_remove_interface,
2115 .config = ath9k_config, 2163 .config = ath9k_config,
2116 .configure_filter = ath9k_configure_filter, 2164 .configure_filter = ath9k_configure_filter,