Merge ath-next from ath.git
[linux-2.6-microblaze.git] / drivers / net / wireless / ath / ath10k / wmi.c
index 7569db0..2a44d63 100644 (file)
@@ -1546,6 +1546,61 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
        .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
 };
 
+static const struct wmi_peer_flags_map wmi_peer_flags_map = {
+       .auth = WMI_PEER_AUTH,
+       .qos = WMI_PEER_QOS,
+       .need_ptk_4_way = WMI_PEER_NEED_PTK_4_WAY,
+       .need_gtk_2_way = WMI_PEER_NEED_GTK_2_WAY,
+       .apsd = WMI_PEER_APSD,
+       .ht = WMI_PEER_HT,
+       .bw40 = WMI_PEER_40MHZ,
+       .stbc = WMI_PEER_STBC,
+       .ldbc = WMI_PEER_LDPC,
+       .dyn_mimops = WMI_PEER_DYN_MIMOPS,
+       .static_mimops = WMI_PEER_STATIC_MIMOPS,
+       .spatial_mux = WMI_PEER_SPATIAL_MUX,
+       .vht = WMI_PEER_VHT,
+       .bw80 = WMI_PEER_80MHZ,
+       .vht_2g = WMI_PEER_VHT_2G,
+       .pmf = WMI_PEER_PMF,
+};
+
+static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
+       .auth = WMI_10X_PEER_AUTH,
+       .qos = WMI_10X_PEER_QOS,
+       .need_ptk_4_way = WMI_10X_PEER_NEED_PTK_4_WAY,
+       .need_gtk_2_way = WMI_10X_PEER_NEED_GTK_2_WAY,
+       .apsd = WMI_10X_PEER_APSD,
+       .ht = WMI_10X_PEER_HT,
+       .bw40 = WMI_10X_PEER_40MHZ,
+       .stbc = WMI_10X_PEER_STBC,
+       .ldbc = WMI_10X_PEER_LDPC,
+       .dyn_mimops = WMI_10X_PEER_DYN_MIMOPS,
+       .static_mimops = WMI_10X_PEER_STATIC_MIMOPS,
+       .spatial_mux = WMI_10X_PEER_SPATIAL_MUX,
+       .vht = WMI_10X_PEER_VHT,
+       .bw80 = WMI_10X_PEER_80MHZ,
+};
+
+static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
+       .auth = WMI_10_2_PEER_AUTH,
+       .qos = WMI_10_2_PEER_QOS,
+       .need_ptk_4_way = WMI_10_2_PEER_NEED_PTK_4_WAY,
+       .need_gtk_2_way = WMI_10_2_PEER_NEED_GTK_2_WAY,
+       .apsd = WMI_10_2_PEER_APSD,
+       .ht = WMI_10_2_PEER_HT,
+       .bw40 = WMI_10_2_PEER_40MHZ,
+       .stbc = WMI_10_2_PEER_STBC,
+       .ldbc = WMI_10_2_PEER_LDPC,
+       .dyn_mimops = WMI_10_2_PEER_DYN_MIMOPS,
+       .static_mimops = WMI_10_2_PEER_STATIC_MIMOPS,
+       .spatial_mux = WMI_10_2_PEER_SPATIAL_MUX,
+       .vht = WMI_10_2_PEER_VHT,
+       .bw80 = WMI_10_2_PEER_80MHZ,
+       .vht_2g = WMI_10_2_PEER_VHT_2G,
+       .pmf = WMI_10_2_PEER_PMF,
+};
+
 void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
                                const struct wmi_channel_arg *arg)
 {
@@ -1660,6 +1715,8 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
        struct ath10k *ar = arvif->ar;
        struct ath10k_skb_cb *cb;
        struct sk_buff *bcn;
+       bool dtim_zero;
+       bool deliver_cab;
        int ret;
 
        spin_lock_bh(&ar->data_lock);
@@ -1679,12 +1736,14 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
                arvif->beacon_state = ATH10K_BEACON_SENDING;
                spin_unlock_bh(&ar->data_lock);
 
+               dtim_zero = !!(cb->flags & ATH10K_SKB_F_DTIM_ZERO);
+               deliver_cab = !!(cb->flags & ATH10K_SKB_F_DELIVER_CAB);
                ret = ath10k_wmi_beacon_send_ref_nowait(arvif->ar,
                                                        arvif->vdev_id,
                                                        bcn->data, bcn->len,
                                                        cb->paddr,
-                                                       cb->bcn.dtim_zero,
-                                                       cb->bcn.deliver_cab);
+                                                       dtim_zero,
+                                                       deliver_cab);
 
                spin_lock_bh(&ar->data_lock);
 
@@ -1755,16 +1814,24 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
 static struct sk_buff *
 ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
 {
+       struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
+       struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
        struct wmi_mgmt_tx_cmd *cmd;
        struct ieee80211_hdr *hdr;
        struct sk_buff *skb;
        int len;
+       u32 vdev_id;
        u32 buf_len = msdu->len;
        u16 fc;
 
        hdr = (struct ieee80211_hdr *)msdu->data;
        fc = le16_to_cpu(hdr->frame_control);
 
+       if (cb->vif)
+               vdev_id = arvif->vdev_id;
+       else
+               vdev_id = 0;
+
        if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
                return ERR_PTR(-EINVAL);
 
@@ -1786,7 +1853,7 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
 
        cmd = (struct wmi_mgmt_tx_cmd *)skb->data;
 
-       cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(msdu)->vdev_id);
+       cmd->hdr.vdev_id = __cpu_to_le32(vdev_id);
        cmd->hdr.tx_rate = 0;
        cmd->hdr.tx_power = 0;
        cmd->hdr.buf_len = __cpu_to_le32(buf_len);
@@ -2204,22 +2271,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        ath10k_dbg(ar, ATH10K_DBG_MGMT,
                   "event mgmt rx status %08x\n", rx_status);
 
-       if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       if (rx_status & WMI_RX_STATUS_ERR_CRC) {
+       if ((test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) ||
+           (rx_status & (WMI_RX_STATUS_ERR_DECRYPT |
+           WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) {
                dev_kfree_skb(skb);
                return 0;
        }
@@ -3115,10 +3169,10 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
        memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
 
        if (tim->dtim_count == 0) {
-               ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
+               ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DTIM_ZERO;
 
                if (__le32_to_cpu(tim_info->tim_mcast) == 1)
-                       ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
+                       ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DELIVER_CAB;
        }
 
        ath10k_dbg(ar, ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
@@ -5061,6 +5115,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
        case WMI_10_4_UPDATE_STATS_EVENTID:
                ath10k_wmi_event_update_stats(ar, skb);
                break;
+       case WMI_10_4_PDEV_TEMPERATURE_EVENTID:
+               ath10k_wmi_event_temperature(ar, skb);
+               break;
        default:
                ath10k_warn(ar, "Unknown eventid: %d\n", id);
                break;
@@ -5431,8 +5488,11 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
        cmd = (struct wmi_init_cmd_10_2 *)buf->data;
 
        features = WMI_10_2_RX_BATCH_MODE;
-       if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
+
+       if (test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) &&
+           test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
                features |= WMI_10_2_COEX_GPIO;
+
        cmd->resource_config.feature_mask = __cpu_to_le32(features);
 
        memcpy(&cmd->resource_config.common, &config, sizeof(config));
@@ -6328,6 +6388,16 @@ ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf,
        cmd->info0 = __cpu_to_le32(info0);
 }
 
+static void
+ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf,
+                               const struct wmi_peer_assoc_complete_arg *arg)
+{
+       struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
+
+       ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
+       cmd->peer_bw_rxnss_override = 0;
+}
+
 static int
 ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg)
 {
@@ -6416,6 +6486,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar,
        return skb;
 }
 
+static struct sk_buff *
+ath10k_wmi_10_4_op_gen_peer_assoc(struct ath10k *ar,
+                                 const struct wmi_peer_assoc_complete_arg *arg)
+{
+       size_t len = sizeof(struct wmi_10_4_peer_assoc_complete_cmd);
+       struct sk_buff *skb;
+       int ret;
+
+       ret = ath10k_wmi_peer_assoc_check_arg(arg);
+       if (ret)
+               return ERR_PTR(ret);
+
+       skb = ath10k_wmi_alloc_skb(ar, len);
+       if (!skb)
+               return ERR_PTR(-ENOMEM);
+
+       ath10k_wmi_peer_assoc_fill_10_4(ar, skb->data, arg);
+
+       ath10k_dbg(ar, ATH10K_DBG_WMI,
+                  "wmi peer assoc vdev %d addr %pM (%s)\n",
+                  arg->vdev_id, arg->addr,
+                  arg->peer_reassoc ? "reassociate" : "new");
+       return skb;
+}
+
 static struct sk_buff *
 ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar)
 {
@@ -7536,6 +7631,7 @@ static const struct wmi_ops wmi_10_4_ops = {
        .gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
        .gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
        .gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
+       .gen_peer_assoc = ath10k_wmi_10_4_op_gen_peer_assoc,
        .gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
        .gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
        .gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
@@ -7555,8 +7651,8 @@ static const struct wmi_ops wmi_10_4_ops = {
        .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
 
        /* shared with 10.2 */
-       .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
        .gen_request_stats = ath10k_wmi_op_gen_request_stats,
+       .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
 };
 
 int ath10k_wmi_attach(struct ath10k *ar)
@@ -7567,30 +7663,35 @@ int ath10k_wmi_attach(struct ath10k *ar)
                ar->wmi.cmd = &wmi_10_4_cmd_map;
                ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_10_2_4:
                ar->wmi.cmd = &wmi_10_2_4_cmd_map;
                ar->wmi.ops = &wmi_10_2_4_ops;
                ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_10_2:
                ar->wmi.cmd = &wmi_10_2_cmd_map;
                ar->wmi.ops = &wmi_10_2_ops;
                ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_10_1:
                ar->wmi.cmd = &wmi_10x_cmd_map;
                ar->wmi.ops = &wmi_10_1_ops;
                ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_MAIN:
                ar->wmi.cmd = &wmi_cmd_map;
                ar->wmi.ops = &wmi_ops;
                ar->wmi.vdev_param = &wmi_vdev_param_map;
                ar->wmi.pdev_param = &wmi_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_TLV:
                ath10k_wmi_tlv_attach(ar);