]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/net/wireless/ath/carl9170/main.c
mac80211: inform the driver about update of dtim_period
[mirror_ubuntu-jammy-kernel.git] / drivers / net / wireless / ath / carl9170 / main.c
index 25a1e2f4f73862fb9bc26f6310d87bb3d51b6cf5..f293b3ff475628a389c1337df81d24cb3b3b5640 100644 (file)
@@ -358,8 +358,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
        ar->ps.last_action = jiffies;
        ar->ps.last_slept = jiffies;
        ar->erp_mode = CARL9170_ERP_AUTO;
-       ar->rx_software_decryption = false;
-       ar->disable_offload = false;
+
+       /* Set "disable hw crypto offload" whenever the module parameter
+        * nohwcrypt is true or if the firmware does not support it.
+        */
+       ar->disable_offload = modparam_nohwcrypt |
+               ar->fw.disable_offload_fw;
+       ar->rx_software_decryption = ar->disable_offload;
 
        for (i = 0; i < ar->hw->queues; i++) {
                ar->queue_stop_timeout[i] = jiffies;
@@ -565,12 +570,28 @@ static int carl9170_init_interface(struct ar9170 *ar,
 
        memcpy(common->macaddr, vif->addr, ETH_ALEN);
 
-       if (modparam_nohwcrypt ||
-           ((vif->type != NL80211_IFTYPE_STATION) &&
-            (vif->type != NL80211_IFTYPE_AP))) {
-               ar->rx_software_decryption = true;
-               ar->disable_offload = true;
-       }
+       /* We have to fall back to software crypto, whenever
+        * the user choose to participates in an IBSS. HW
+        * offload for IBSS RSN is not supported by this driver.
+        *
+        * NOTE: If the previous main interface has already
+        * disabled hw crypto offload, we have to keep this
+        * previous disable_offload setting as it was.
+        * Altough ideally, we should notify mac80211 and tell
+        * it to forget about any HW crypto offload for now.
+        */
+       ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) &&
+           (vif->type != NL80211_IFTYPE_AP));
+
+       /* While the driver supports HW offload in a single
+        * P2P client configuration, it doesn't support HW
+        * offload in the favourit, concurrent P2P GO+CLIENT
+        * configuration. Hence, HW offload will always be
+        * disabled for P2P.
+        */
+       ar->disable_offload |= vif->p2p;
+
+       ar->rx_software_decryption = ar->disable_offload;
 
        err = carl9170_set_operating_mode(ar);
        return err;
@@ -580,7 +601,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
                                     struct ieee80211_vif *vif)
 {
        struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
-       struct ieee80211_vif *main_vif;
+       struct ieee80211_vif *main_vif, *old_main = NULL;
        struct ar9170 *ar = hw->priv;
        int vif_id = -1, err = 0;
 
@@ -602,6 +623,15 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
                goto init;
        }
 
+       /* Because the AR9170 HW's MAC doesn't provide full support for
+        * multiple, independent interfaces [of different operation modes].
+        * We have to select ONE main interface [main mode of HW], but we
+        * can have multiple slaves [AKA: entry in the ACK-table].
+        *
+        * The first (from HEAD/TOP) interface in the ar->vif_list is
+        * always the main intf. All following intfs in this list
+        * are considered to be slave intfs.
+        */
        main_vif = carl9170_get_main_vif(ar);
 
        if (main_vif) {
@@ -610,6 +640,18 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
                        if (vif->type == NL80211_IFTYPE_STATION)
                                break;
 
+                       /* P2P GO [master] use-case
+                        * Because the P2P GO station is selected dynamically
+                        * by all participating peers of a WIFI Direct network,
+                        * the driver has be able to change the main interface
+                        * operating mode on the fly.
+                        */
+                       if (main_vif->p2p && vif->p2p &&
+                           vif->type == NL80211_IFTYPE_AP) {
+                               old_main = main_vif;
+                               break;
+                       }
+
                        err = -EBUSY;
                        rcu_read_unlock();
 
@@ -648,14 +690,41 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
        vif_priv->id = vif_id;
        vif_priv->enable_beacon = false;
        ar->vifs++;
-       list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
+       if (old_main) {
+               /* We end up in here, if the main interface is being replaced.
+                * Put the new main interface at the HEAD of the list and the
+                * previous inteface will automatically become second in line.
+                */
+               list_add_rcu(&vif_priv->list, &ar->vif_list);
+       } else {
+               /* Add new inteface. If the list is empty, it will become the
+                * main inteface, otherwise it will be slave.
+                */
+               list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
+       }
        rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif);
 
 init:
-       if (carl9170_get_main_vif(ar) == vif) {
+       main_vif = carl9170_get_main_vif(ar);
+
+       if (main_vif == vif) {
                rcu_assign_pointer(ar->beacon_iter, vif_priv);
                rcu_read_unlock();
 
+               if (old_main) {
+                       struct carl9170_vif_info *old_main_priv =
+                               (void *) old_main->drv_priv;
+                       /* downgrade old main intf to slave intf.
+                        * NOTE: We are no longer under rcu_read_lock.
+                        * But we are still holding ar->mutex, so the
+                        * vif data [id, addr] is safe.
+                        */
+                       err = carl9170_mod_virtual_mac(ar, old_main_priv->id,
+                                                      old_main->addr);
+                       if (err)
+                               goto unlock;
+               }
+
                err = carl9170_init_interface(ar, vif);
                if (err)
                        goto unlock;
@@ -1112,9 +1181,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        if (ar->disable_offload || !vif)
                return -EOPNOTSUPP;
 
-       /*
-        * We have to fall back to software encryption, whenever
-        * the user choose to participates in an IBSS or is connected
+       /* Fall back to software encryption whenever the driver is connected
         * to more than one network.
         *
         * This is very unfortunate, because some machines cannot handle
@@ -1263,7 +1330,7 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw,
                        return 0;
                }
 
-               for (i = 0; i < CARL9170_NUM_TID; i++)
+               for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++)
                        RCU_INIT_POINTER(sta_info->agg[i], NULL);
 
                sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
@@ -1287,7 +1354,7 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
                sta_info->ht_sta = false;
 
                rcu_read_lock();
-               for (i = 0; i < CARL9170_NUM_TID; i++) {
+               for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) {
                        struct carl9170_sta_tid *tid_info;
 
                        tid_info = rcu_dereference(sta_info->agg[i]);
@@ -1394,7 +1461,9 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
                break;
 
-       case IEEE80211_AMPDU_TX_STOP:
+       case IEEE80211_AMPDU_TX_STOP_CONT:
+       case IEEE80211_AMPDU_TX_STOP_FLUSH:
+       case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
                rcu_read_lock();
                tid_info = rcu_dereference(sta_info->agg[tid]);
                if (tid_info) {
@@ -1784,7 +1853,7 @@ void *carl9170_alloc(size_t priv_size)
                     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
                     IEEE80211_HW_SUPPORTS_PS |
                     IEEE80211_HW_PS_NULLFUNC_STACK |
-                    IEEE80211_HW_NEED_DTIM_PERIOD |
+                    IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
                     IEEE80211_HW_SIGNAL_DBM;
 
        if (!modparam_noht) {
@@ -1805,10 +1874,6 @@ void *carl9170_alloc(size_t priv_size)
        for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
                ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
 
-       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
-       /* As IBSS Encryption is software-based, IBSS RSN is supported. */
-       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
        return ar;
 
 err_nomem:
@@ -1916,13 +1981,13 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
        return 0;
 }
 
-static int carl9170_reg_notifier(struct wiphy *wiphy,
-                                struct regulatory_request *request)
+static void carl9170_reg_notifier(struct wiphy *wiphy,
+                                 struct regulatory_request *request)
 {
        struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
        struct ar9170 *ar = hw->priv;
 
-       return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
+       ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
 }
 
 int carl9170_register(struct ar9170 *ar)