Commit b6c7bafa authored by Bob Copeland's avatar Bob Copeland Committed by Kalle Valo

ath10k: implement mesh support

Add support for mesh to ath10k.  We simply use an AP virtual interface
in the firmware in order to enable beaconing without TSF adoption, and
use the raw (802.11) transmit mode.

Due to firmware limitations, the firmware must operate in raw
(non-native 802.11) mode.  As this is configured at firmware init time,
a new "rawmode" modparam is added, and mesh interfaces are available
only if rawmode=true.  The firmware must advertise support for rawmode;
tested successfully with firmware 10.2.4.70.6-2.

When the module is loaded with (newly implemented) modparam rawmode=1, it
will enable operating an open mesh STA via something like the following:

    ip link set wlan0 down
    iw dev wlan0 set type mp
    ip link set wlan0 up
    iw dev wlan0 set freq 5745 80 5775
    iw dev wlan0 mesh join mesh-vht
Signed-off-by: default avatarBob Copeland <me@bobcopeland.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent bc76c287
...@@ -34,16 +34,19 @@ unsigned int ath10k_debug_mask; ...@@ -34,16 +34,19 @@ unsigned int ath10k_debug_mask;
static unsigned int ath10k_cryptmode_param; static unsigned int ath10k_cryptmode_param;
static bool uart_print; static bool uart_print;
static bool skip_otp; static bool skip_otp;
static bool rawmode;
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644); module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
module_param(uart_print, bool, 0644); module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644); module_param(skip_otp, bool, 0644);
module_param(rawmode, bool, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging"); MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software"); MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
static const struct ath10k_hw_params ath10k_hw_params_list[] = { static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{ {
...@@ -1122,6 +1125,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ...@@ -1122,6 +1125,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT; ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT; ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
if (rawmode) {
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
ar->fw_features)) {
ath10k_err(ar, "rawmode = 1 requires support from firmware");
return -EINVAL;
}
set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
}
if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW; ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;
......
...@@ -4211,6 +4211,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, ...@@ -4211,6 +4211,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
arvif->vdev_type = WMI_VDEV_TYPE_IBSS; arvif->vdev_type = WMI_VDEV_TYPE_IBSS;
break; break;
case NL80211_IFTYPE_MESH_POINT:
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
ret = -EINVAL;
ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n");
goto err;
}
arvif->vdev_type = WMI_VDEV_TYPE_AP;
break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
arvif->vdev_type = WMI_VDEV_TYPE_AP; arvif->vdev_type = WMI_VDEV_TYPE_AP;
...@@ -4251,6 +4259,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, ...@@ -4251,6 +4259,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
* become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap. * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap.
*/ */
if (vif->type == NL80211_IFTYPE_ADHOC || if (vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_AP) { vif->type == NL80211_IFTYPE_AP) {
arvif->beacon_buf = dma_zalloc_coherent(ar->dev, arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
IEEE80211_MAX_FRAME_LEN, IEEE80211_MAX_FRAME_LEN,
...@@ -4590,6 +4599,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -4590,6 +4599,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
if (ret) if (ret)
ath10k_warn(ar, "failed to update beacon template: %d\n", ath10k_warn(ar, "failed to update beacon template: %d\n",
ret); ret);
if (ieee80211_vif_is_mesh(vif)) {
/* mesh doesn't use SSID but firmware needs it */
strncpy(arvif->u.ap.ssid, "mesh",
sizeof(arvif->u.ap.ssid));
arvif->u.ap.ssid_len = 4;
}
} }
if (changed & BSS_CHANGED_AP_PROBE_RESP) { if (changed & BSS_CHANGED_AP_PROBE_RESP) {
...@@ -5329,6 +5345,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ...@@ -5329,6 +5345,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_AUTH && } else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP || (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) { vif->type == NL80211_IFTYPE_ADHOC)) {
/* /*
* New association. * New association.
...@@ -5364,6 +5381,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ...@@ -5364,6 +5381,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_ASSOC && } else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_AUTH &&
(vif->type == NL80211_IFTYPE_AP || (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) { vif->type == NL80211_IFTYPE_ADHOC)) {
/* /*
* Disassociation. * Disassociation.
...@@ -6678,6 +6696,9 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = { ...@@ -6678,6 +6696,9 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
{ {
.max = 7, .max = 7,
.types = BIT(NL80211_IFTYPE_AP) .types = BIT(NL80211_IFTYPE_AP)
#ifdef CONFIG_MAC80211_MESH
| BIT(NL80211_IFTYPE_MESH_POINT)
#endif
}, },
}; };
...@@ -6685,6 +6706,9 @@ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { ...@@ -6685,6 +6706,9 @@ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
{ {
.max = 8, .max = 8,
.types = BIT(NL80211_IFTYPE_AP) .types = BIT(NL80211_IFTYPE_AP)
#ifdef CONFIG_MAC80211_MESH
| BIT(NL80211_IFTYPE_MESH_POINT)
#endif
}, },
}; };
...@@ -6722,6 +6746,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = { ...@@ -6722,6 +6746,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = {
{ {
.max = 2, .max = 2,
.types = BIT(NL80211_IFTYPE_AP) | .types = BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO), BIT(NL80211_IFTYPE_P2P_GO),
}, },
...@@ -6743,6 +6770,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_qcs_if_limit[] = { ...@@ -6743,6 +6770,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_qcs_if_limit[] = {
{ {
.max = 1, .max = 1,
.types = BIT(NL80211_IFTYPE_AP) | .types = BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_P2P_GO), BIT(NL80211_IFTYPE_P2P_GO),
}, },
{ {
...@@ -6809,6 +6839,9 @@ static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = { ...@@ -6809,6 +6839,9 @@ static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = {
{ {
.max = 16, .max = 16,
.types = BIT(NL80211_IFTYPE_AP) .types = BIT(NL80211_IFTYPE_AP)
#ifdef CONFIG_MAC80211_MESH
| BIT(NL80211_IFTYPE_MESH_POINT)
#endif
}, },
}; };
...@@ -7033,7 +7066,8 @@ int ath10k_mac_register(struct ath10k *ar) ...@@ -7033,7 +7066,8 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->interface_modes = ar->hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP); BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MESH_POINT);
ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment