bool radar_required;
 };
 
-/**
- * enum plink_action - actions to perform in mesh peers
- *
- * @PLINK_ACTION_INVALID: action 0 is reserved
- * @PLINK_ACTION_OPEN: start mesh peer link establishment
- * @PLINK_ACTION_BLOCK: block traffic from this mesh peer
- */
-enum plink_actions {
-       PLINK_ACTION_INVALID,
-       PLINK_ACTION_OPEN,
-       PLINK_ACTION_BLOCK,
-};
-
 /**
  * enum station_parameters_apply_mask - station parameter values to apply
  * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
  * @STATION_PARAM_APPLY_CAPABILITY: apply new capability
+ * @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state
  *
  * Not all station parameters have in-band "no change" signalling,
  * for those that don't these flags will are used.
 enum station_parameters_apply_mask {
        STATION_PARAM_APPLY_UAPSD = BIT(0),
        STATION_PARAM_APPLY_CAPABILITY = BIT(1),
+       STATION_PARAM_APPLY_PLINK_STATE = BIT(2),
 };
 
 /**
 
  *     consisting of a nested array.
  *
  * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
- * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link.
+ * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link
+ *     (see &enum nl80211_plink_action).
  * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
  * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
  *     info given for %NL80211_CMD_GET_MPATH, nested attribute described at
        MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1
 };
 
+/**
+ * enum nl80211_plink_action - actions to perform in mesh peers
+ *
+ * @NL80211_PLINK_ACTION_NO_ACTION: perform no action
+ * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment
+ * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer
+ * @NUM_NL80211_PLINK_ACTIONS: number of possible actions
+ */
+enum plink_actions {
+       NL80211_PLINK_ACTION_NO_ACTION,
+       NL80211_PLINK_ACTION_OPEN,
+       NL80211_PLINK_ACTION_BLOCK,
+
+       NUM_NL80211_PLINK_ACTIONS,
+};
+
+
 #define NL80211_KCK_LEN                        16
 #define NL80211_KEK_LEN                        16
 #define NL80211_REPLAY_CTR_LEN         8
 
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
                u32 changed = 0;
-               if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) {
+               if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED &&
+                   (params->sta_modify_mask &
+                                       STATION_PARAM_APPLY_PLINK_STATE)) {
                        switch (params->plink_state) {
                        case NL80211_PLINK_ESTAB:
                                if (sta->plink_state != NL80211_PLINK_ESTAB)
                                /*  nothing  */
                                break;
                        }
+               } else if (params->sta_modify_mask &
+                                       STATION_PARAM_APPLY_PLINK_STATE) {
+                       return -EINVAL;
                } else {
                        switch (params->plink_action) {
-                       case PLINK_ACTION_OPEN:
+                       case NL80211_PLINK_ACTION_NO_ACTION:
+                               /* nothing */
+                               break;
+                       case NL80211_PLINK_ACTION_OPEN:
                                changed |= mesh_plink_open(sta);
                                break;
-                       case PLINK_ACTION_BLOCK:
+                       case NL80211_PLINK_ACTION_BLOCK:
                                changed |= mesh_plink_block(sta);
                                break;
                        }
 
        memset(¶ms, 0, sizeof(params));
 
        params.listen_interval = -1;
-       params.plink_state = -1;
 
        if (info->attrs[NL80211_ATTR_STA_AID])
                return -EINVAL;
        if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms))
                return -EINVAL;
 
-       if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
+       if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
                params.plink_action =
-                   nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+                       nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+               if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
+                       return -EINVAL;
+       }
 
-       if (info->attrs[NL80211_ATTR_STA_PLINK_STATE])
+       if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
                params.plink_state =
-                   nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
+                       nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
+               if (params.plink_state >= NUM_NL80211_PLINK_STATES)
+                       return -EINVAL;
+               params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
+       }
 
        if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) {
                enum nl80211_mesh_power_mode pm = nla_get_u32(
                        return -EINVAL;
                if (params.local_pm)
                        return -EINVAL;
+               if (params.sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
+                       return -EINVAL;
 
                /* TDLS can't be set, ... */
                if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
                        return -EINVAL;
                if (params.local_pm)
                        return -EINVAL;
+               if (params.sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
+                       return -EINVAL;
                /* reject any changes other than AUTHORIZED or WME (for TDLS) */
                if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
                                              BIT(NL80211_STA_FLAG_WME)))
                        return -EINVAL;
                if (params.local_pm)
                        return -EINVAL;
+               if (params.sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
+                       return -EINVAL;
                if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
                    info->attrs[NL80211_ATTR_VHT_CAPABILITY])
                        return -EINVAL;
                params.vht_capa =
                        nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 
-       if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
+       if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
                params.plink_action =
-                   nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+                       nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+               if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
+                       return -EINVAL;
+       }
 
        if (!rdev->ops->add_station)
                return -EOPNOTSUPP;