|
@@ -597,6 +597,276 @@ static qdf_freq_t hdd_son_get_candidate_freq(struct wlan_objmgr_vdev *vdev)
|
|
|
return freq;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * hdd_son_phy_mode_to_vendor_phy_mode() - translate son phy mode to
|
|
|
+ * vendor_phy_mode
|
|
|
+ * @mode: son phy mode
|
|
|
+ *
|
|
|
+ * Return: qca_wlan_vendor_phy_mode
|
|
|
+ */
|
|
|
+static enum qca_wlan_vendor_phy_mode hdd_son_phy_mode_to_vendor_phy_mode(
|
|
|
+ enum ieee80211_phymode mode)
|
|
|
+{
|
|
|
+ enum qca_wlan_vendor_phy_mode vendor_mode;
|
|
|
+
|
|
|
+ switch (mode) {
|
|
|
+ case IEEE80211_MODE_AUTO:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11A:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11A;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11B:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11B;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11G:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11G;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NA_HT20:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NG_HT20:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NA_HT40PLUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NA_HT40MINUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NG_HT40PLUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NG_HT40MINUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NG_HT40:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11NA_HT40:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AC_VHT20:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AC_VHT40PLUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AC_VHT40MINUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AC_VHT40:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AC_VHT80:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AC_VHT160:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AC_VHT80_80:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AXA_HE20:
|
|
|
+ case IEEE80211_MODE_11AXG_HE20:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AXA_HE40PLUS:
|
|
|
+ case IEEE80211_MODE_11AXG_HE40PLUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AXA_HE40MINUS:
|
|
|
+ case IEEE80211_MODE_11AXG_HE40MINUS:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AXA_HE40:
|
|
|
+ case IEEE80211_MODE_11AXG_HE40:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AXA_HE80:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AXA_HE160:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160;
|
|
|
+ break;
|
|
|
+ case IEEE80211_MODE_11AXA_HE80_80:
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ hdd_err("Invalid config phy mode %d, set it as auto", mode);
|
|
|
+ vendor_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return vendor_mode;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_son_set_phymode() - set son phy mode
|
|
|
+ * @vdev: vdev
|
|
|
+ * @mode: son phy mode to set
|
|
|
+ *
|
|
|
+ * Return: 0 on success, negative errno on failure
|
|
|
+ */
|
|
|
+static int hdd_son_set_phymode(struct wlan_objmgr_vdev *vdev,
|
|
|
+ enum ieee80211_phymode mode)
|
|
|
+{
|
|
|
+ struct hdd_adapter *adapter;
|
|
|
+ enum qca_wlan_vendor_phy_mode vendor_phy_mode;
|
|
|
+
|
|
|
+ if (!vdev) {
|
|
|
+ hdd_err("null vdev");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
|
|
|
+ if (!adapter) {
|
|
|
+ hdd_err("null adapter");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ vendor_phy_mode = hdd_son_phy_mode_to_vendor_phy_mode(mode);
|
|
|
+
|
|
|
+ return hdd_set_phy_mode(adapter, vendor_phy_mode);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_phymode_chwidth_freq_to_son_phymode() - get son phymode from csr phymode
|
|
|
+ * chan width and freq
|
|
|
+ * @phymode: csr phymode
|
|
|
+ * @chwidth: chan width
|
|
|
+ * @freq: chan frequence
|
|
|
+ *
|
|
|
+ * Return: ieee80211_phymode
|
|
|
+ */
|
|
|
+static enum ieee80211_phymode hdd_phymode_chwidth_freq_to_son_phymode(
|
|
|
+ eCsrPhyMode phymode,
|
|
|
+ enum eSirMacHTChannelWidth chwidth,
|
|
|
+ qdf_freq_t freq)
|
|
|
+{
|
|
|
+ uint32_t band_2g = WLAN_REG_IS_24GHZ_CH_FREQ(freq);
|
|
|
+ enum ieee80211_phymode son_phymode;
|
|
|
+
|
|
|
+ switch (phymode) {
|
|
|
+ case eCSR_DOT11_MODE_abg:
|
|
|
+ case eCSR_DOT11_MODE_AUTO:
|
|
|
+ son_phymode = IEEE80211_MODE_AUTO;
|
|
|
+ break;
|
|
|
+ case eCSR_DOT11_MODE_11a:
|
|
|
+ son_phymode = IEEE80211_MODE_11A;
|
|
|
+ break;
|
|
|
+ case eCSR_DOT11_MODE_11b:
|
|
|
+ case eCSR_DOT11_MODE_11b_ONLY:
|
|
|
+ son_phymode = IEEE80211_MODE_11B;
|
|
|
+ break;
|
|
|
+ case eCSR_DOT11_MODE_11g:
|
|
|
+ case eCSR_DOT11_MODE_11g_ONLY:
|
|
|
+ son_phymode = IEEE80211_MODE_11G;
|
|
|
+ break;
|
|
|
+ case eCSR_DOT11_MODE_11n:
|
|
|
+ case eCSR_DOT11_MODE_11n_ONLY:
|
|
|
+ if (chwidth == eHT_CHANNEL_WIDTH_40MHZ) {
|
|
|
+ if (band_2g)
|
|
|
+ son_phymode = IEEE80211_MODE_11NG_HT40;
|
|
|
+ else
|
|
|
+ son_phymode = IEEE80211_MODE_11NA_HT40;
|
|
|
+ } else {
|
|
|
+ if (band_2g)
|
|
|
+ son_phymode = IEEE80211_MODE_11NG_HT20;
|
|
|
+ else
|
|
|
+ son_phymode = IEEE80211_MODE_11NA_HT20;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case eCSR_DOT11_MODE_11ac:
|
|
|
+ case eCSR_DOT11_MODE_11ac_ONLY:
|
|
|
+ if (chwidth == eHT_CHANNEL_WIDTH_160MHZ)
|
|
|
+ son_phymode = IEEE80211_MODE_11AC_VHT160;
|
|
|
+ else if (chwidth == eHT_CHANNEL_WIDTH_80P80MHZ)
|
|
|
+ son_phymode = IEEE80211_MODE_11AC_VHT80_80;
|
|
|
+ else if (chwidth == eHT_CHANNEL_WIDTH_80MHZ)
|
|
|
+ son_phymode = IEEE80211_MODE_11AC_VHT80;
|
|
|
+ else if (chwidth == eHT_CHANNEL_WIDTH_40MHZ)
|
|
|
+ son_phymode = IEEE80211_MODE_11AC_VHT40;
|
|
|
+ else
|
|
|
+ son_phymode = IEEE80211_MODE_11AC_VHT20;
|
|
|
+ break;
|
|
|
+ case eCSR_DOT11_MODE_11ax:
|
|
|
+ case eCSR_DOT11_MODE_11ax_ONLY:
|
|
|
+ if (chwidth == eHT_CHANNEL_WIDTH_160MHZ) {
|
|
|
+ son_phymode = IEEE80211_MODE_11AXA_HE160;
|
|
|
+ } else if (chwidth == eHT_CHANNEL_WIDTH_80P80MHZ) {
|
|
|
+ son_phymode = IEEE80211_MODE_11AXA_HE80_80;
|
|
|
+ } else if (chwidth == eHT_CHANNEL_WIDTH_80MHZ) {
|
|
|
+ son_phymode = IEEE80211_MODE_11AXA_HE80;
|
|
|
+ } else if (chwidth == eHT_CHANNEL_WIDTH_40MHZ) {
|
|
|
+ if (band_2g)
|
|
|
+ son_phymode = IEEE80211_MODE_11AXG_HE40;
|
|
|
+ else
|
|
|
+ son_phymode = IEEE80211_MODE_11AXA_HE40;
|
|
|
+ } else {
|
|
|
+ if (band_2g)
|
|
|
+ son_phymode = IEEE80211_MODE_11AXG_HE20;
|
|
|
+ else
|
|
|
+ son_phymode = IEEE80211_MODE_11AXA_HE20;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ son_phymode = IEEE80211_MODE_AUTO;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return son_phymode;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_son_get_phymode() - get son phy mode
|
|
|
+ * @vdev: vdev
|
|
|
+ *
|
|
|
+ * Return: enum ieee80211_phymode
|
|
|
+ */
|
|
|
+static enum ieee80211_phymode hdd_son_get_phymode(struct wlan_objmgr_vdev *vdev)
|
|
|
+{
|
|
|
+ enum eSirMacHTChannelWidth chwidth;
|
|
|
+ eCsrPhyMode phymode;
|
|
|
+ struct hdd_adapter *adapter;
|
|
|
+ qdf_freq_t freq;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+ struct hdd_context *hdd_ctx;
|
|
|
+
|
|
|
+ if (!vdev) {
|
|
|
+ hdd_err("null vdev");
|
|
|
+ return IEEE80211_MODE_AUTO;
|
|
|
+ }
|
|
|
+ adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
|
|
|
+ if (!adapter) {
|
|
|
+ hdd_err("null adapter");
|
|
|
+ return IEEE80211_MODE_AUTO;
|
|
|
+ }
|
|
|
+
|
|
|
+ pdev = wlan_vdev_get_pdev(vdev);
|
|
|
+ if (!pdev) {
|
|
|
+ hdd_err("null pdev");
|
|
|
+ return IEEE80211_MODE_AUTO;
|
|
|
+ }
|
|
|
+
|
|
|
+ freq = ucfg_son_get_operation_chan_freq_vdev_id(pdev, adapter->vdev_id);
|
|
|
+
|
|
|
+ chwidth = wma_cli_get_command(adapter->vdev_id, WMI_VDEV_PARAM_CHWIDTH,
|
|
|
+ VDEV_CMD);
|
|
|
+
|
|
|
+ if (chwidth < 0) {
|
|
|
+ hdd_err("Failed to get chwidth");
|
|
|
+ return IEEE80211_MODE_AUTO;
|
|
|
+ }
|
|
|
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
|
|
+ if (!hdd_ctx) {
|
|
|
+ hdd_err("null hdd ctx");
|
|
|
+ return IEEE80211_MODE_AUTO;
|
|
|
+ }
|
|
|
+ phymode = sme_get_phy_mode(hdd_ctx->mac_handle);
|
|
|
+
|
|
|
+ return hdd_phymode_chwidth_freq_to_son_phymode(phymode, chwidth, freq);
|
|
|
+}
|
|
|
+
|
|
|
void hdd_son_register_callbacks(struct hdd_context *hdd_ctx)
|
|
|
{
|
|
|
struct son_callbacks cb_obj = {0};
|
|
@@ -610,6 +880,8 @@ void hdd_son_register_callbacks(struct hdd_context *hdd_ctx)
|
|
|
cb_obj.os_if_set_country_code = hdd_son_set_country;
|
|
|
cb_obj.os_if_set_candidate_freq = hdd_son_set_candidate_freq;
|
|
|
cb_obj.os_if_get_candidate_freq = hdd_son_get_candidate_freq;
|
|
|
+ cb_obj.os_if_set_phymode = hdd_son_set_phymode;
|
|
|
+ cb_obj.os_if_get_phymode = hdd_son_get_phymode;
|
|
|
|
|
|
os_if_son_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj);
|
|
|
}
|