[RFC 4/4] ath10k: introduce basic tdls functionality

Michal Kazior michal.kazior at tieto.com
Tue Feb 3 04:49:22 PST 2015


On 3 February 2015 at 11:41, Marek Puzyniak <marek.puzyniak at tieto.com> wrote:
[...]
> +static int ath10k_enable_tdls(struct ath10k *ar, u32 vdev_id, bool enable)

Function in mac.c should have a `ath10k_mac_` prefix.

> +{
> +       int ret;
> +       enum wmi_tdls_state state = WMI_TDLS_DISABLE;
> +
> +       lockdep_assert_held(&ar->conf_mutex);
> +
> +       if (enable)
> +               state = WMI_TDLS_ENABLE_ACTIVE;
> +
> +       ret = ath10k_wmi_update_fw_tdls_state(ar, vdev_id, state);

Anyway I see little point in having this wrapper function just to call
wmi function?


[...]
> +static int ath10k_tdls_peer_update(struct ath10k *ar, u32 vdev_id,
> +                                  struct ieee80211_sta *sta,
> +                                  enum wmi_tdls_peer_state state)

The ath10k_mac_ prefix is missing: ath10k_mac_tdls_peer_update().


> +{
> +       int ret;
> +       struct wmi_tdls_peer_update_cmd_arg arg;
> +       struct wmi_tdls_peer_capab_arg cap;
> +       struct wmi_channel_arg chan_arg;

I would `xxx = {}` to make these are zero-ed. Right now you pass
uninitialized vars from the stack..


> +       int i;
> +
> +       lockdep_assert_held(&ar->conf_mutex);
> +
> +       arg.vdev_id = vdev_id;
> +       arg.peer_state = state;
> +       ether_addr_copy(arg.addr, sta->addr);
> +
> +       cap.peer_max_sp = sta->max_sp;
> +       cap.peer_uapsd_queues = sta->uapsd_queues;
> +       cap.peer_curr_operclass = 0;
> +       cap.self_curr_operclass = 0;
> +       cap.peer_chan_len = 0;
> +       cap.peer_operclass_len = 0;
> +       cap.is_peer_responder = 0;
> +       cap.buff_sta_support = 0;
> +       cap.off_chan_support = 0;
> +       cap.pref_offchan_num = 0;
> +       cap.pref_offchan_bw = 0;

Once you `= {}` it's probably redundant to zero each structure member like that.


[...]
> @@ -4462,6 +4553,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
>                 if (ret)
>                         ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n",
>                                     sta->addr, arvif->vdev_id, ret);
> +               if (sta->tdls)
> +                       ath10k_enable_tdls(ar, arvif->vdev_id, false);

What if you have 2 TDLS peers? If you disconnect the first one you'll
disable TDLS on the entire vdev while the other peer is still
connected. I don't think that's desired.

Perhaps the per-vdev TDLS command can be called in
add_interface()/remove_interface()? If that's not possible I guess you
could use ieee80211_iterate_stations_atomic() to look if there's still
at least one TDLS peer present.


>
>                 ath10k_mac_dec_num_stations(arvif);
>         } else if (old_state == IEEE80211_STA_AUTH &&
> @@ -4479,9 +4572,28 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
>                         ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n",
>                                     sta->addr, arvif->vdev_id, ret);
>         } else if (old_state == IEEE80211_STA_ASSOC &&
> -                  new_state == IEEE80211_STA_AUTH &&
> -                  (vif->type == NL80211_IFTYPE_AP ||
> -                   vif->type == NL80211_IFTYPE_ADHOC)) {
> +                  new_state == IEEE80211_STA_AUTHORIZED &&
> +                  sta->tdls) {
> +               /*
> +                * Tdls station authorized.
> +                */
> +               ath10k_dbg(ar, ATH10K_DBG_MAC, "mac tdls sta %pM authorized\n",
> +                          sta->addr);
> +
> +               ret = ath10k_station_assoc(ar, vif, sta, false);
> +               if (ret)
> +                       ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n",
> +                                   sta->addr, arvif->vdev_id, ret);

It's meaningless to call tdls_peer_update() if assoc failed. From
practical standpoint fw is probably dead at that point and subsequent
commands will timeout. You can `goto exit`.


[...]
> +static struct sk_buff *
> +ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
> +                                          enum wmi_tdls_state state)
> +{
> +       struct wmi_tdls_set_state_cmd *cmd;
> +       struct wmi_tlv *tlv;
> +       struct sk_buff *skb;
> +       void *ptr;
> +       size_t len;
> +       /* Set to options from wmi_tlv_tdls_options,
> +        * for now none of then are enabled.

Typo: s/then/them/


> +        */
> +       u32 options = 0;
> +
> +       len = sizeof(*tlv) + sizeof(*cmd);
> +       skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));

Why not use `len` for alloc_skb()?


[...]
> +static struct sk_buff *
> +ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar,
> +                                      struct wmi_tdls_peer_update_cmd_arg *arg,
> +                                      struct wmi_tdls_peer_capab_arg *cap,
> +                                      struct wmi_channel_arg *chan_arg)

Could be const struct on these _args.


[...]
> diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
> index 5f0fe84..8c219f0 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
> +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
> @@ -1516,6 +1516,58 @@ struct wmi_tlv_p2p_noa_ev {
>         __le32 vdev_id;
>  } __packed;
>
> +/* TDLS Options */
> +enum wmi_tlv_tdls_options {
> +       WMI_TLV_TDLS_OFFCHAN_EN = BIT(0), /* TDLS Off Channel support */
> +       WMI_TLV_TDLS_BUFFER_STA_EN = BIT(1), /* TDLS Buffer STA support */
> +       WMI_TLV_TDLS_SLEEP_STA_EN = BIT(2), /* TDLS Sleep STA support */

These comments seem redundant and don't introduce any extra info..


Michał



More information about the ath10k mailing list