aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2011-11-10 09:55:14 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-11 12:32:54 -0500
commit0b7a4c788fd08ffd147b266b7d0992f6f13ccdae (patch)
treee33e8ec6606aec0956b4b1aa01a7191795648984 /drivers/net
parenta69cd040d03711215c32f89683a025d28594d2b5 (diff)
iwlwifi: move more mac80211 callback function
Move more mac80211 related functions to _mac80211 file Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c304
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c308
3 files changed, 308 insertions, 315 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 989f9f3fdaf8..f7b00481a9fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1120,227 +1120,8 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
1120 &statistics_cmd); 1120 &statistics_cmd);
1121} 1121}
1122 1122
1123int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
1124 struct ieee80211_vif *vif, u16 queue,
1125 const struct ieee80211_tx_queue_params *params)
1126{
1127 struct iwl_priv *priv = hw->priv;
1128 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
1129 struct iwl_rxon_context *ctx = vif_priv->ctx;
1130 unsigned long flags;
1131 int q;
1132
1133 if (WARN_ON(!ctx))
1134 return -EINVAL;
1135
1136 IWL_DEBUG_MAC80211(priv, "enter\n");
1137
1138 if (!iwl_is_ready_rf(priv->shrd)) {
1139 IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
1140 return -EIO;
1141 }
1142
1143 if (queue >= AC_NUM) {
1144 IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
1145 return 0;
1146 }
1147
1148 q = AC_NUM - 1 - queue;
1149
1150 spin_lock_irqsave(&priv->shrd->lock, flags);
1151
1152 ctx->qos_data.def_qos_parm.ac[q].cw_min =
1153 cpu_to_le16(params->cw_min);
1154 ctx->qos_data.def_qos_parm.ac[q].cw_max =
1155 cpu_to_le16(params->cw_max);
1156 ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
1157 ctx->qos_data.def_qos_parm.ac[q].edca_txop =
1158 cpu_to_le16((params->txop * 32));
1159
1160 ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
1161
1162 spin_unlock_irqrestore(&priv->shrd->lock, flags);
1163
1164 IWL_DEBUG_MAC80211(priv, "leave\n");
1165 return 0;
1166}
1167
1168int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
1169{
1170 struct iwl_priv *priv = hw->priv;
1171
1172 return priv->ibss_manager == IWL_IBSS_MANAGER;
1173}
1174
1175static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
1176{
1177 iwl_connection_init_rx_config(priv, ctx);
1178
1179 iwlagn_set_rxon_chain(priv, ctx);
1180
1181 return iwlagn_commit_rxon(priv, ctx);
1182}
1183
1184static int iwl_setup_interface(struct iwl_priv *priv,
1185 struct iwl_rxon_context *ctx)
1186{
1187 struct ieee80211_vif *vif = ctx->vif;
1188 int err;
1189 1123
1190 lockdep_assert_held(&priv->shrd->mutex);
1191
1192 /*
1193 * This variable will be correct only when there's just
1194 * a single context, but all code using it is for hardware
1195 * that supports only one context.
1196 */
1197 priv->iw_mode = vif->type;
1198
1199 ctx->is_active = true;
1200
1201 err = iwl_set_mode(priv, ctx);
1202 if (err) {
1203 if (!ctx->always_active)
1204 ctx->is_active = false;
1205 return err;
1206 }
1207
1208 if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
1209 vif->type == NL80211_IFTYPE_ADHOC) {
1210 /*
1211 * pretend to have high BT traffic as long as we
1212 * are operating in IBSS mode, as this will cause
1213 * the rate scaling etc. to behave as intended.
1214 */
1215 priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
1216 }
1217
1218 return 0;
1219}
1220
1221int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
1222 struct ieee80211_vif *vif)
1223{
1224 struct iwl_priv *priv = hw->priv;
1225 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
1226 struct iwl_rxon_context *tmp, *ctx = NULL;
1227 int err;
1228 enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
1229 1124
1230 IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
1231 viftype, vif->addr);
1232
1233 cancel_delayed_work_sync(&priv->hw_roc_disable_work);
1234
1235 mutex_lock(&priv->shrd->mutex);
1236
1237 iwlagn_disable_roc(priv);
1238
1239 if (!iwl_is_ready_rf(priv->shrd)) {
1240 IWL_WARN(priv, "Try to add interface when device not ready\n");
1241 err = -EINVAL;
1242 goto out;
1243 }
1244
1245 for_each_context(priv, tmp) {
1246 u32 possible_modes =
1247 tmp->interface_modes | tmp->exclusive_interface_modes;
1248
1249 if (tmp->vif) {
1250 /* check if this busy context is exclusive */
1251 if (tmp->exclusive_interface_modes &
1252 BIT(tmp->vif->type)) {
1253 err = -EINVAL;
1254 goto out;
1255 }
1256 continue;
1257 }
1258
1259 if (!(possible_modes & BIT(viftype)))
1260 continue;
1261
1262 /* have maybe usable context w/o interface */
1263 ctx = tmp;
1264 break;
1265 }
1266
1267 if (!ctx) {
1268 err = -EOPNOTSUPP;
1269 goto out;
1270 }
1271
1272 vif_priv->ctx = ctx;
1273 ctx->vif = vif;
1274
1275 err = iwl_setup_interface(priv, ctx);
1276 if (!err)
1277 goto out;
1278
1279 ctx->vif = NULL;
1280 priv->iw_mode = NL80211_IFTYPE_STATION;
1281 out:
1282 mutex_unlock(&priv->shrd->mutex);
1283
1284 IWL_DEBUG_MAC80211(priv, "leave\n");
1285 return err;
1286}
1287
1288static void iwl_teardown_interface(struct iwl_priv *priv,
1289 struct ieee80211_vif *vif,
1290 bool mode_change)
1291{
1292 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1293
1294 lockdep_assert_held(&priv->shrd->mutex);
1295
1296 if (priv->scan_vif == vif) {
1297 iwl_scan_cancel_timeout(priv, 200);
1298 iwl_force_scan_end(priv);
1299 }
1300
1301 if (!mode_change) {
1302 iwl_set_mode(priv, ctx);
1303 if (!ctx->always_active)
1304 ctx->is_active = false;
1305 }
1306
1307 /*
1308 * When removing the IBSS interface, overwrite the
1309 * BT traffic load with the stored one from the last
1310 * notification, if any. If this is a device that
1311 * doesn't implement this, this has no effect since
1312 * both values are the same and zero.
1313 */
1314 if (vif->type == NL80211_IFTYPE_ADHOC)
1315 priv->bt_traffic_load = priv->last_bt_traffic_load;
1316}
1317
1318void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
1319 struct ieee80211_vif *vif)
1320{
1321 struct iwl_priv *priv = hw->priv;
1322 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1323
1324 IWL_DEBUG_MAC80211(priv, "enter\n");
1325
1326 mutex_lock(&priv->shrd->mutex);
1327
1328 if (WARN_ON(ctx->vif != vif)) {
1329 struct iwl_rxon_context *tmp;
1330 IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
1331 for_each_context(priv, tmp)
1332 IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
1333 tmp->ctxid, tmp, tmp->vif);
1334 }
1335 ctx->vif = NULL;
1336
1337 iwl_teardown_interface(priv, vif, false);
1338
1339 mutex_unlock(&priv->shrd->mutex);
1340
1341 IWL_DEBUG_MAC80211(priv, "leave\n");
1342
1343}
1344 1125
1345#ifdef CONFIG_IWLWIFI_DEBUGFS 1126#ifdef CONFIG_IWLWIFI_DEBUGFS
1346 1127
@@ -1647,91 +1428,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
1647 return 0; 1428 return 0;
1648} 1429}
1649 1430
1650int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
1651 struct ieee80211_vif *vif,
1652 enum nl80211_iftype newtype, bool newp2p)
1653{
1654 struct iwl_priv *priv = hw->priv;
1655 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1656 struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];
1657 struct iwl_rxon_context *tmp;
1658 enum nl80211_iftype newviftype = newtype;
1659 u32 interface_modes;
1660 int err;
1661
1662 IWL_DEBUG_MAC80211(priv, "enter\n");
1663
1664 newtype = ieee80211_iftype_p2p(newtype, newp2p);
1665
1666 mutex_lock(&priv->shrd->mutex);
1667
1668 if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
1669 /*
1670 * Huh? But wait ... this can maybe happen when
1671 * we're in the middle of a firmware restart!
1672 */
1673 err = -EBUSY;
1674 goto out;
1675 }
1676
1677 interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
1678
1679 if (!(interface_modes & BIT(newtype))) {
1680 err = -EBUSY;
1681 goto out;
1682 }
1683
1684 /*
1685 * Refuse a change that should be done by moving from the PAN
1686 * context to the BSS context instead, if the BSS context is
1687 * available and can support the new interface type.
1688 */
1689 if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif &&
1690 (bss_ctx->interface_modes & BIT(newtype) ||
1691 bss_ctx->exclusive_interface_modes & BIT(newtype))) {
1692 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
1693 err = -EBUSY;
1694 goto out;
1695 }
1696
1697 if (ctx->exclusive_interface_modes & BIT(newtype)) {
1698 for_each_context(priv, tmp) {
1699 if (ctx == tmp)
1700 continue;
1701
1702 if (!tmp->vif)
1703 continue;
1704
1705 /*
1706 * The current mode switch would be exclusive, but
1707 * another context is active ... refuse the switch.
1708 */
1709 err = -EBUSY;
1710 goto out;
1711 }
1712 }
1713
1714 /* success */
1715 iwl_teardown_interface(priv, vif, true);
1716 vif->type = newviftype;
1717 vif->p2p = newp2p;
1718 err = iwl_setup_interface(priv, ctx);
1719 WARN_ON(err);
1720 /*
1721 * We've switched internally, but submitting to the
1722 * device may have failed for some reason. Mask this
1723 * error, because otherwise mac80211 will not switch
1724 * (and set the interface type back) and we'll be
1725 * out of sync with it.
1726 */
1727 err = 0;
1728
1729 out:
1730 mutex_unlock(&priv->shrd->mutex);
1731 IWL_DEBUG_MAC80211(priv, "leave\n");
1732
1733 return err;
1734}
1735 1431
1736int iwl_cmd_echo_test(struct iwl_priv *priv) 1432int iwl_cmd_echo_test(struct iwl_priv *priv)
1737{ 1433{
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 137da3380704..ee3692adbad2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -237,10 +237,6 @@ struct iwl_cfg {
237 * L i b * 237 * L i b *
238 ***************************/ 238 ***************************/
239 239
240int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
241 struct ieee80211_vif *vif, u16 queue,
242 const struct ieee80211_tx_queue_params *params);
243int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw);
244void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, 240void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
245 int hw_decrypt); 241 int hw_decrypt);
246int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); 242int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@@ -260,13 +256,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
260void iwl_connection_init_rx_config(struct iwl_priv *priv, 256void iwl_connection_init_rx_config(struct iwl_priv *priv,
261 struct iwl_rxon_context *ctx); 257 struct iwl_rxon_context *ctx);
262void iwl_set_rate(struct iwl_priv *priv); 258void iwl_set_rate(struct iwl_priv *priv);
263int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
264 struct ieee80211_vif *vif);
265void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
266 struct ieee80211_vif *vif);
267int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
268 struct ieee80211_vif *vif,
269 enum nl80211_iftype newtype, bool newp2p);
270int iwl_cmd_echo_test(struct iwl_priv *priv); 259int iwl_cmd_echo_test(struct iwl_priv *priv);
271#ifdef CONFIG_IWLWIFI_DEBUGFS 260#ifdef CONFIG_IWLWIFI_DEBUGFS
272int iwl_alloc_traffic_mem(struct iwl_priv *priv); 261int iwl_alloc_traffic_mem(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index c06bfe40cf38..1b2dbb006adc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -1493,6 +1493,314 @@ static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
1493 return 0; 1493 return 0;
1494} 1494}
1495 1495
1496static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
1497 struct ieee80211_vif *vif, u16 queue,
1498 const struct ieee80211_tx_queue_params *params)
1499{
1500 struct iwl_priv *priv = hw->priv;
1501 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
1502 struct iwl_rxon_context *ctx = vif_priv->ctx;
1503 unsigned long flags;
1504 int q;
1505
1506 if (WARN_ON(!ctx))
1507 return -EINVAL;
1508
1509 IWL_DEBUG_MAC80211(priv, "enter\n");
1510
1511 if (!iwl_is_ready_rf(priv->shrd)) {
1512 IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
1513 return -EIO;
1514 }
1515
1516 if (queue >= AC_NUM) {
1517 IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
1518 return 0;
1519 }
1520
1521 q = AC_NUM - 1 - queue;
1522
1523 spin_lock_irqsave(&priv->shrd->lock, flags);
1524
1525 ctx->qos_data.def_qos_parm.ac[q].cw_min =
1526 cpu_to_le16(params->cw_min);
1527 ctx->qos_data.def_qos_parm.ac[q].cw_max =
1528 cpu_to_le16(params->cw_max);
1529 ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
1530 ctx->qos_data.def_qos_parm.ac[q].edca_txop =
1531 cpu_to_le16((params->txop * 32));
1532
1533 ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
1534
1535 spin_unlock_irqrestore(&priv->shrd->lock, flags);
1536
1537 IWL_DEBUG_MAC80211(priv, "leave\n");
1538 return 0;
1539}
1540
1541static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
1542{
1543 struct iwl_priv *priv = hw->priv;
1544
1545 return priv->ibss_manager == IWL_IBSS_MANAGER;
1546}
1547
1548static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
1549{
1550 iwl_connection_init_rx_config(priv, ctx);
1551
1552 iwlagn_set_rxon_chain(priv, ctx);
1553
1554 return iwlagn_commit_rxon(priv, ctx);
1555}
1556
1557static int iwl_setup_interface(struct iwl_priv *priv,
1558 struct iwl_rxon_context *ctx)
1559{
1560 struct ieee80211_vif *vif = ctx->vif;
1561 int err;
1562
1563 lockdep_assert_held(&priv->shrd->mutex);
1564
1565 /*
1566 * This variable will be correct only when there's just
1567 * a single context, but all code using it is for hardware
1568 * that supports only one context.
1569 */
1570 priv->iw_mode = vif->type;
1571
1572 ctx->is_active = true;
1573
1574 err = iwl_set_mode(priv, ctx);
1575 if (err) {
1576 if (!ctx->always_active)
1577 ctx->is_active = false;
1578 return err;
1579 }
1580
1581 if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
1582 vif->type == NL80211_IFTYPE_ADHOC) {
1583 /*
1584 * pretend to have high BT traffic as long as we
1585 * are operating in IBSS mode, as this will cause
1586 * the rate scaling etc. to behave as intended.
1587 */
1588 priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
1589 }
1590
1591 return 0;
1592}
1593
1594static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
1595 struct ieee80211_vif *vif)
1596{
1597 struct iwl_priv *priv = hw->priv;
1598 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
1599 struct iwl_rxon_context *tmp, *ctx = NULL;
1600 int err;
1601 enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
1602
1603 IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
1604 viftype, vif->addr);
1605
1606 cancel_delayed_work_sync(&priv->hw_roc_disable_work);
1607
1608 mutex_lock(&priv->shrd->mutex);
1609
1610 iwlagn_disable_roc(priv);
1611
1612 if (!iwl_is_ready_rf(priv->shrd)) {
1613 IWL_WARN(priv, "Try to add interface when device not ready\n");
1614 err = -EINVAL;
1615 goto out;
1616 }
1617
1618 for_each_context(priv, tmp) {
1619 u32 possible_modes =
1620 tmp->interface_modes | tmp->exclusive_interface_modes;
1621
1622 if (tmp->vif) {
1623 /* check if this busy context is exclusive */
1624 if (tmp->exclusive_interface_modes &
1625 BIT(tmp->vif->type)) {
1626 err = -EINVAL;
1627 goto out;
1628 }
1629 continue;
1630 }
1631
1632 if (!(possible_modes & BIT(viftype)))
1633 continue;
1634
1635 /* have maybe usable context w/o interface */
1636 ctx = tmp;
1637 break;
1638 }
1639
1640 if (!ctx) {
1641 err = -EOPNOTSUPP;
1642 goto out;
1643 }
1644
1645 vif_priv->ctx = ctx;
1646 ctx->vif = vif;
1647
1648 err = iwl_setup_interface(priv, ctx);
1649 if (!err)
1650 goto out;
1651
1652 ctx->vif = NULL;
1653 priv->iw_mode = NL80211_IFTYPE_STATION;
1654 out:
1655 mutex_unlock(&priv->shrd->mutex);
1656
1657 IWL_DEBUG_MAC80211(priv, "leave\n");
1658 return err;
1659}
1660
1661static void iwl_teardown_interface(struct iwl_priv *priv,
1662 struct ieee80211_vif *vif,
1663 bool mode_change)
1664{
1665 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1666
1667 lockdep_assert_held(&priv->shrd->mutex);
1668
1669 if (priv->scan_vif == vif) {
1670 iwl_scan_cancel_timeout(priv, 200);
1671 iwl_force_scan_end(priv);
1672 }
1673
1674 if (!mode_change) {
1675 iwl_set_mode(priv, ctx);
1676 if (!ctx->always_active)
1677 ctx->is_active = false;
1678 }
1679
1680 /*
1681 * When removing the IBSS interface, overwrite the
1682 * BT traffic load with the stored one from the last
1683 * notification, if any. If this is a device that
1684 * doesn't implement this, this has no effect since
1685 * both values are the same and zero.
1686 */
1687 if (vif->type == NL80211_IFTYPE_ADHOC)
1688 priv->bt_traffic_load = priv->last_bt_traffic_load;
1689}
1690
1691static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
1692 struct ieee80211_vif *vif)
1693{
1694 struct iwl_priv *priv = hw->priv;
1695 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1696
1697 IWL_DEBUG_MAC80211(priv, "enter\n");
1698
1699 mutex_lock(&priv->shrd->mutex);
1700
1701 if (WARN_ON(ctx->vif != vif)) {
1702 struct iwl_rxon_context *tmp;
1703 IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
1704 for_each_context(priv, tmp)
1705 IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
1706 tmp->ctxid, tmp, tmp->vif);
1707 }
1708 ctx->vif = NULL;
1709
1710 iwl_teardown_interface(priv, vif, false);
1711
1712 mutex_unlock(&priv->shrd->mutex);
1713
1714 IWL_DEBUG_MAC80211(priv, "leave\n");
1715
1716}
1717
1718static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
1719 struct ieee80211_vif *vif,
1720 enum nl80211_iftype newtype, bool newp2p)
1721{
1722 struct iwl_priv *priv = hw->priv;
1723 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
1724 struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];
1725 struct iwl_rxon_context *tmp;
1726 enum nl80211_iftype newviftype = newtype;
1727 u32 interface_modes;
1728 int err;
1729
1730 IWL_DEBUG_MAC80211(priv, "enter\n");
1731
1732 newtype = ieee80211_iftype_p2p(newtype, newp2p);
1733
1734 mutex_lock(&priv->shrd->mutex);
1735
1736 if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
1737 /*
1738 * Huh? But wait ... this can maybe happen when
1739 * we're in the middle of a firmware restart!
1740 */
1741 err = -EBUSY;
1742 goto out;
1743 }
1744
1745 interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
1746
1747 if (!(interface_modes & BIT(newtype))) {
1748 err = -EBUSY;
1749 goto out;
1750 }
1751
1752 /*
1753 * Refuse a change that should be done by moving from the PAN
1754 * context to the BSS context instead, if the BSS context is
1755 * available and can support the new interface type.
1756 */
1757 if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif &&
1758 (bss_ctx->interface_modes & BIT(newtype) ||
1759 bss_ctx->exclusive_interface_modes & BIT(newtype))) {
1760 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
1761 err = -EBUSY;
1762 goto out;
1763 }
1764
1765 if (ctx->exclusive_interface_modes & BIT(newtype)) {
1766 for_each_context(priv, tmp) {
1767 if (ctx == tmp)
1768 continue;
1769
1770 if (!tmp->vif)
1771 continue;
1772
1773 /*
1774 * The current mode switch would be exclusive, but
1775 * another context is active ... refuse the switch.
1776 */
1777 err = -EBUSY;
1778 goto out;
1779 }
1780 }
1781
1782 /* success */
1783 iwl_teardown_interface(priv, vif, true);
1784 vif->type = newviftype;
1785 vif->p2p = newp2p;
1786 err = iwl_setup_interface(priv, ctx);
1787 WARN_ON(err);
1788 /*
1789 * We've switched internally, but submitting to the
1790 * device may have failed for some reason. Mask this
1791 * error, because otherwise mac80211 will not switch
1792 * (and set the interface type back) and we'll be
1793 * out of sync with it.
1794 */
1795 err = 0;
1796
1797 out:
1798 mutex_unlock(&priv->shrd->mutex);
1799 IWL_DEBUG_MAC80211(priv, "leave\n");
1800
1801 return err;
1802}
1803
1496struct ieee80211_ops iwlagn_hw_ops = { 1804struct ieee80211_ops iwlagn_hw_ops = {
1497 .tx = iwlagn_mac_tx, 1805 .tx = iwlagn_mac_tx,
1498 .start = iwlagn_mac_start, 1806 .start = iwlagn_mac_start,