Commit 133189a4 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-john' of git://git.sipsolutions.net/mac80211-next

parents f761b694 0f6b3f59
...@@ -567,6 +567,26 @@ struct ieee80211s_hdr { ...@@ -567,6 +567,26 @@ struct ieee80211s_hdr {
#define MESH_FLAGS_AE 0x3 #define MESH_FLAGS_AE 0x3
#define MESH_FLAGS_PS_DEEP 0x4 #define MESH_FLAGS_PS_DEEP 0x4
/**
* enum ieee80211_preq_flags - mesh PREQ element flags
*
* @IEEE80211_PREQ_PROACTIVE_PREP_FLAG: proactive PREP subfield
*/
enum ieee80211_preq_flags {
IEEE80211_PREQ_PROACTIVE_PREP_FLAG = 1<<2,
};
/**
* enum ieee80211_preq_target_flags - mesh PREQ element per target flags
*
* @IEEE80211_PREQ_TO_FLAG: target only subfield
* @IEEE80211_PREQ_USN_FLAG: unknown target HWMP sequence number subfield
*/
enum ieee80211_preq_target_flags {
IEEE80211_PREQ_TO_FLAG = 1<<0,
IEEE80211_PREQ_USN_FLAG = 1<<2,
};
/** /**
* struct ieee80211_quiet_ie * struct ieee80211_quiet_ie
* *
...@@ -1443,7 +1463,7 @@ enum ieee80211_tdls_actioncode { ...@@ -1443,7 +1463,7 @@ enum ieee80211_tdls_actioncode {
* *
* @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method * @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method
* @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method * @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method
* that will be specified in a vendor specific information element * that will be specified in a vendor specific information element
*/ */
enum { enum {
IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1, IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1,
...@@ -1455,7 +1475,7 @@ enum { ...@@ -1455,7 +1475,7 @@ enum {
* *
* @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol * @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol
* @IEEE80211_PATH_PROTOCOL_VENDOR: a vendor specific protocol that will * @IEEE80211_PATH_PROTOCOL_VENDOR: a vendor specific protocol that will
* be specified in a vendor specific information element * be specified in a vendor specific information element
*/ */
enum { enum {
IEEE80211_PATH_PROTOCOL_HWMP = 1, IEEE80211_PATH_PROTOCOL_HWMP = 1,
...@@ -1467,13 +1487,35 @@ enum { ...@@ -1467,13 +1487,35 @@ enum {
* *
* @IEEE80211_PATH_METRIC_AIRTIME: the default path selection metric * @IEEE80211_PATH_METRIC_AIRTIME: the default path selection metric
* @IEEE80211_PATH_METRIC_VENDOR: a vendor specific metric that will be * @IEEE80211_PATH_METRIC_VENDOR: a vendor specific metric that will be
* specified in a vendor specific information element * specified in a vendor specific information element
*/ */
enum { enum {
IEEE80211_PATH_METRIC_AIRTIME = 1, IEEE80211_PATH_METRIC_AIRTIME = 1,
IEEE80211_PATH_METRIC_VENDOR = 255, IEEE80211_PATH_METRIC_VENDOR = 255,
}; };
/**
* enum ieee80211_root_mode_identifier - root mesh STA mode identifier
*
* These attribute are used by dot11MeshHWMPRootMode to set root mesh STA mode
*
* @IEEE80211_ROOTMODE_NO_ROOT: the mesh STA is not a root mesh STA (default)
* @IEEE80211_ROOTMODE_ROOT: the mesh STA is a root mesh STA if greater than
* this value
* @IEEE80211_PROACTIVE_PREQ_NO_PREP: the mesh STA is a root mesh STA supports
* the proactive PREQ with proactive PREP subfield set to 0
* @IEEE80211_PROACTIVE_PREQ_WITH_PREP: the mesh STA is a root mesh STA
* supports the proactive PREQ with proactive PREP subfield set to 1
* @IEEE80211_PROACTIVE_RANN: the mesh STA is a root mesh STA supports
* the proactive RANN
*/
enum ieee80211_root_mode_identifier {
IEEE80211_ROOTMODE_NO_ROOT = 0,
IEEE80211_ROOTMODE_ROOT = 1,
IEEE80211_PROACTIVE_PREQ_NO_PREP = 2,
IEEE80211_PROACTIVE_PREQ_WITH_PREP = 3,
IEEE80211_PROACTIVE_RANN = 4,
};
/* /*
* IEEE 802.11-2007 7.3.2.9 Country information element * IEEE 802.11-2007 7.3.2.9 Country information element
...@@ -1589,6 +1631,8 @@ enum ieee80211_sa_query_action { ...@@ -1589,6 +1631,8 @@ enum ieee80211_sa_query_action {
#define WLAN_OUI_WFA 0x506f9a #define WLAN_OUI_WFA 0x506f9a
#define WLAN_OUI_TYPE_WFA_P2P 9 #define WLAN_OUI_TYPE_WFA_P2P 9
#define WLAN_OUI_MICROSOFT 0x0050f2
#define WLAN_OUI_TYPE_MICROSOFT_WPA 1
/* /*
* WMM/802.11e Tspec Element * WMM/802.11e Tspec Element
......
This diff is collapsed.
...@@ -627,10 +627,10 @@ struct sta_bss_parameters { ...@@ -627,10 +627,10 @@ struct sta_bss_parameters {
* @llid: mesh local link id * @llid: mesh local link id
* @plid: mesh peer link id * @plid: mesh peer link id
* @plink_state: mesh peer link state * @plink_state: mesh peer link state
* @signal: the signal strength, type depends on the wiphy's signal_type * @signal: The signal strength, type depends on the wiphy's signal_type.
NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @signal_avg: avg signal strength, type depends on the wiphy's signal_type * @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @txrate: current unicast bitrate from this station * @txrate: current unicast bitrate from this station
* @rxrate: current unicast bitrate to this station * @rxrate: current unicast bitrate to this station
* @rx_packets: packets received from this station * @rx_packets: packets received from this station
...@@ -790,43 +790,95 @@ struct bss_parameters { ...@@ -790,43 +790,95 @@ struct bss_parameters {
int ht_opmode; int ht_opmode;
}; };
/* /**
* struct mesh_config - 802.11s mesh configuration * struct mesh_config - 802.11s mesh configuration
* *
* These parameters can be changed while the mesh is active. * These parameters can be changed while the mesh is active.
*
* @dot11MeshRetryTimeout: the initial retry timeout in millisecond units used
* by the Mesh Peering Open message
* @dot11MeshConfirmTimeout: the initial retry timeout in millisecond units
* used by the Mesh Peering Open message
* @dot11MeshHoldingTimeout: the confirm timeout in millisecond units used by
* the mesh peering management to close a mesh peering
* @dot11MeshMaxPeerLinks: the maximum number of peer links allowed on this
* mesh interface
* @dot11MeshMaxRetries: the maximum number of peer link open retries that can
* be sent to establish a new peer link instance in a mesh
* @dot11MeshTTL: the value of TTL field set at a source mesh STA
* @element_ttl: the value of TTL field set at a mesh STA for path selection
* elements
* @auto_open_plinks: whether we should automatically open peer links when we
* detect compatible mesh peers
* @dot11MeshNbrOffsetMaxNeighbor: the maximum number of neighbors to
* synchronize to for 11s default synchronization method
* @dot11MeshHWMPmaxPREQretries: the number of action frames containing a PREQ
* that an originator mesh STA can send to a particular path target
* @path_refresh_time: how frequently to refresh mesh paths in milliseconds
* @min_discovery_timeout: the minimum length of time to wait until giving up on
* a path discovery in milliseconds
* @dot11MeshHWMPactivePathTimeout: the time (in TUs) for which mesh STAs
* receiving a PREQ shall consider the forwarding information from the
* root to be valid. (TU = time unit)
* @dot11MeshHWMPpreqMinInterval: the minimum interval of time (in TUs) during
* which a mesh STA can send only one action frame containing a PREQ
* element
* @dot11MeshHWMPperrMinInterval: the minimum interval of time (in TUs) during
* which a mesh STA can send only one Action frame containing a PERR
* element
* @dot11MeshHWMPnetDiameterTraversalTime: the interval of time (in TUs) that
* it takes for an HWMP information element to propagate across the mesh
* @dot11MeshHWMPRootMode: the configuration of a mesh STA as root mesh STA
* @dot11MeshHWMPRannInterval: the interval of time (in TUs) between root
* announcements are transmitted
* @dot11MeshGateAnnouncementProtocol: whether to advertise that this mesh
* station has access to a broader network beyond the MBSS. (This is
* missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol set to true
* only means that the station will announce others it's a mesh gate, but
* not necessarily using the gate announcement protocol. Still keeping the
* same nomenclature to be in sync with the spec)
* @dot11MeshForwarding: whether the Mesh STA is forwarding or non-forwarding
* entity (default is TRUE - forwarding entity)
* @rssi_threshold: the threshold for average signal strength of candidate
* station to establish a peer link
* @ht_opmode: mesh HT protection mode
*
* @dot11MeshHWMPactivePathToRootTimeout: The time (in TUs) for which mesh STAs
* receiving a proactive PREQ shall consider the forwarding information to
* the root mesh STA to be valid.
*
* @dot11MeshHWMProotInterval: The interval of time (in TUs) between proactive
* PREQs are transmitted.
* @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs)
* during which a mesh STA can send only one Action frame containing
* a PREQ element for root path confirmation.
*/ */
struct mesh_config { struct mesh_config {
/* Timeouts in ms */
/* Mesh plink management parameters */
u16 dot11MeshRetryTimeout; u16 dot11MeshRetryTimeout;
u16 dot11MeshConfirmTimeout; u16 dot11MeshConfirmTimeout;
u16 dot11MeshHoldingTimeout; u16 dot11MeshHoldingTimeout;
u16 dot11MeshMaxPeerLinks; u16 dot11MeshMaxPeerLinks;
u8 dot11MeshMaxRetries; u8 dot11MeshMaxRetries;
u8 dot11MeshTTL; u8 dot11MeshTTL;
/* ttl used in path selection information elements */ u8 element_ttl;
u8 element_ttl;
bool auto_open_plinks; bool auto_open_plinks;
/* neighbor offset synchronization */
u32 dot11MeshNbrOffsetMaxNeighbor; u32 dot11MeshNbrOffsetMaxNeighbor;
/* HWMP parameters */ u8 dot11MeshHWMPmaxPREQretries;
u8 dot11MeshHWMPmaxPREQretries;
u32 path_refresh_time; u32 path_refresh_time;
u16 min_discovery_timeout; u16 min_discovery_timeout;
u32 dot11MeshHWMPactivePathTimeout; u32 dot11MeshHWMPactivePathTimeout;
u16 dot11MeshHWMPpreqMinInterval; u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPperrMinInterval; u16 dot11MeshHWMPperrMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime; u16 dot11MeshHWMPnetDiameterTraversalTime;
u8 dot11MeshHWMPRootMode; u8 dot11MeshHWMPRootMode;
u16 dot11MeshHWMPRannInterval; u16 dot11MeshHWMPRannInterval;
/* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol bool dot11MeshGateAnnouncementProtocol;
* set to true only means that the station will announce others it's a
* mesh gate, but not necessarily using the gate announcement protocol.
* Still keeping the same nomenclature to be in sync with the spec. */
bool dot11MeshGateAnnouncementProtocol;
bool dot11MeshForwarding; bool dot11MeshForwarding;
s32 rssi_threshold; s32 rssi_threshold;
u16 ht_opmode; u16 ht_opmode;
u32 dot11MeshHWMPactivePathToRootTimeout;
u16 dot11MeshHWMProotInterval;
u16 dot11MeshHWMPconfirmationInterval;
}; };
/** /**
......
...@@ -689,7 +689,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy, ...@@ -689,7 +689,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
case CHAN_MODE_HOPPING: case CHAN_MODE_HOPPING:
return -EBUSY; return -EBUSY;
case CHAN_MODE_FIXED: case CHAN_MODE_FIXED:
if (local->oper_channel != chan) if (local->oper_channel != chan ||
(!sdata && local->_oper_channel_type != channel_type))
return -EBUSY; return -EBUSY;
if (!sdata && local->_oper_channel_type == channel_type) if (!sdata && local->_oper_channel_type == channel_type)
return 0; return 0;
...@@ -1529,7 +1530,7 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, ...@@ -1529,7 +1530,7 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
conf->dot11MeshTTL = nconf->dot11MeshTTL; conf->dot11MeshTTL = nconf->dot11MeshTTL;
if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
conf->dot11MeshTTL = nconf->element_ttl; conf->element_ttl = nconf->element_ttl;
if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
conf->auto_open_plinks = nconf->auto_open_plinks; conf->auto_open_plinks = nconf->auto_open_plinks;
if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask))
...@@ -1564,17 +1565,16 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, ...@@ -1564,17 +1565,16 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
* announcements, so require this ifmsh to also be a root node * announcements, so require this ifmsh to also be a root node
* */ * */
if (nconf->dot11MeshGateAnnouncementProtocol && if (nconf->dot11MeshGateAnnouncementProtocol &&
!conf->dot11MeshHWMPRootMode) { !(conf->dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)) {
conf->dot11MeshHWMPRootMode = 1; conf->dot11MeshHWMPRootMode = IEEE80211_PROACTIVE_RANN;
ieee80211_mesh_root_setup(ifmsh); ieee80211_mesh_root_setup(ifmsh);
} }
conf->dot11MeshGateAnnouncementProtocol = conf->dot11MeshGateAnnouncementProtocol =
nconf->dot11MeshGateAnnouncementProtocol; nconf->dot11MeshGateAnnouncementProtocol;
} }
if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) { if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask))
conf->dot11MeshHWMPRannInterval = conf->dot11MeshHWMPRannInterval =
nconf->dot11MeshHWMPRannInterval; nconf->dot11MeshHWMPRannInterval;
}
if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask)) if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
conf->dot11MeshForwarding = nconf->dot11MeshForwarding; conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) { if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
...@@ -1590,6 +1590,15 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, ...@@ -1590,6 +1590,15 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode; sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
} }
if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))
conf->dot11MeshHWMPactivePathToRootTimeout =
nconf->dot11MeshHWMPactivePathToRootTimeout;
if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask))
conf->dot11MeshHWMProotInterval =
nconf->dot11MeshHWMProotInterval;
if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask))
conf->dot11MeshHWMPconfirmationInterval =
nconf->dot11MeshHWMPconfirmationInterval;
return 0; return 0;
} }
...@@ -2309,6 +2318,21 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, ...@@ -2309,6 +2318,21 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
struct ieee80211_roc_work *dep, *tmp2;
list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) {
if (!mgmt_tx && (unsigned long)dep != cookie)
continue;
else if (mgmt_tx && dep->mgmt_tx_cookie != cookie)
continue;
/* found dependent item -- just remove it */
list_del(&dep->list);
mutex_unlock(&local->mtx);
ieee80211_roc_notify_destroy(dep);
return 0;
}
if (!mgmt_tx && (unsigned long)roc != cookie) if (!mgmt_tx && (unsigned long)roc != cookie)
continue; continue;
else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
...@@ -2323,6 +2347,13 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, ...@@ -2323,6 +2347,13 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
return -ENOENT; return -ENOENT;
} }
/*
* We found the item to cancel, so do that. Note that it
* may have dependents, which we also cancel (and send
* the expired signal for.) Not doing so would be quite
* tricky here, but we may need to fix it later.
*/
if (local->ops->remain_on_channel) { if (local->ops->remain_on_channel) {
if (found->started) { if (found->started) {
ret = drv_cancel_remain_on_channel(local); ret = drv_cancel_remain_on_channel(local);
...@@ -2334,8 +2365,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, ...@@ -2334,8 +2365,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
list_del(&found->list); list_del(&found->list);
ieee80211_run_deferred_scan(local); if (found->started)
ieee80211_start_next_roc(local); ieee80211_start_next_roc(local);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
ieee80211_roc_notify_destroy(found); ieee80211_roc_notify_destroy(found);
...@@ -2489,16 +2520,30 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, ...@@ -2489,16 +2520,30 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
u16 frame_type, bool reg) u16 frame_type, bool reg)
{ {
struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) switch (frame_type) {
return; case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH:
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
if (reg) if (reg)
local->probe_req_reg++; ifibss->auth_frame_registrations++;
else else
local->probe_req_reg--; ifibss->auth_frame_registrations--;
}
break;
case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
if (reg)
local->probe_req_reg++;
else
local->probe_req_reg--;
ieee80211_queue_work(&local->hw, &local->reconfig_filter); ieee80211_queue_work(&local->hw, &local->reconfig_filter);
break;
default:
break;
}
} }
static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
......
...@@ -468,48 +468,54 @@ IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); ...@@ -468,48 +468,54 @@ IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
IEEE80211_IF_FILE(dropped_frames_congestion, IEEE80211_IF_FILE(dropped_frames_congestion,
u.mesh.mshstats.dropped_frames_congestion, DEC); u.mesh.mshstats.dropped_frames_congestion, DEC);
IEEE80211_IF_FILE(dropped_frames_no_route, IEEE80211_IF_FILE(dropped_frames_no_route,
u.mesh.mshstats.dropped_frames_no_route, DEC); u.mesh.mshstats.dropped_frames_no_route, DEC);
IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
/* Mesh parameters */ /* Mesh parameters */
IEEE80211_IF_FILE(dot11MeshMaxRetries, IEEE80211_IF_FILE(dot11MeshMaxRetries,
u.mesh.mshcfg.dot11MeshMaxRetries, DEC); u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
IEEE80211_IF_FILE(dot11MeshRetryTimeout, IEEE80211_IF_FILE(dot11MeshRetryTimeout,
u.mesh.mshcfg.dot11MeshRetryTimeout, DEC); u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshConfirmTimeout, IEEE80211_IF_FILE(dot11MeshConfirmTimeout,
u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC); u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshHoldingTimeout, IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC); u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC); IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC); IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC);
IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC); IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
IEEE80211_IF_FILE(dot11MeshMaxPeerLinks, IEEE80211_IF_FILE(dot11MeshMaxPeerLinks,
u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC); u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout, IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC); u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval, IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC); u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval, IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval,
u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC); u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime, IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC); u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries, IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC); u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
IEEE80211_IF_FILE(path_refresh_time, IEEE80211_IF_FILE(path_refresh_time,
u.mesh.mshcfg.path_refresh_time, DEC); u.mesh.mshcfg.path_refresh_time, DEC);
IEEE80211_IF_FILE(min_discovery_timeout, IEEE80211_IF_FILE(min_discovery_timeout,
u.mesh.mshcfg.min_discovery_timeout, DEC); u.mesh.mshcfg.min_discovery_timeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRootMode, IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC); IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPactivePathToRootTimeout,
u.mesh.mshcfg.dot11MeshHWMPactivePathToRootTimeout, DEC);
IEEE80211_IF_FILE(dot11MeshHWMProotInterval,
u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC);
IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval,
u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC);
#endif #endif
#define DEBUGFS_ADD_MODE(name, mode) \ #define DEBUGFS_ADD_MODE(name, mode) \
...@@ -611,6 +617,9 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) ...@@ -611,6 +617,9 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
MESHPARAMS_ADD(rssi_threshold); MESHPARAMS_ADD(rssi_threshold);
MESHPARAMS_ADD(ht_opmode); MESHPARAMS_ADD(ht_opmode);
MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout);
MESHPARAMS_ADD(dot11MeshHWMProotInterval);
MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval);
#undef MESHPARAMS_ADD #undef MESHPARAMS_ADD
} }
#endif #endif
......
...@@ -279,7 +279,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, ...@@ -279,7 +279,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
/* If it fails, maybe we raced another insertion? */ /* If it fails, maybe we raced another insertion? */
if (sta_info_insert_rcu(sta)) if (sta_info_insert_rcu(sta))
return sta_info_get(sdata, addr); return sta_info_get(sdata, addr);
if (auth) { if (auth && !sdata->u.ibss.auth_frame_registrations) {
ibss_vdbg("TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", ibss_vdbg("TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n",
sdata->vif.addr, sdata->u.ibss.bssid, addr); sdata->vif.addr, sdata->u.ibss.bssid, addr);
ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0, ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, NULL, 0,
......
...@@ -55,11 +55,14 @@ struct ieee80211_local; ...@@ -55,11 +55,14 @@ struct ieee80211_local;
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) #define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) #define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
/*
* Some APs experience problems when working with U-APSD. Decrease the
* probability of that happening by using legacy mode for all ACs but VO.
* The AP that caused us trouble was a Cisco 4410N. It ignores our
* setting, and always treats non-VO ACs as legacy.
*/
#define IEEE80211_DEFAULT_UAPSD_QUEUES \ #define IEEE80211_DEFAULT_UAPSD_QUEUES \
(IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \ IEEE80211_WMM_IE_STA_QOSINFO_AC_VO
IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \
IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | \
IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
#define IEEE80211_DEFAULT_MAX_SP_LEN \ #define IEEE80211_DEFAULT_MAX_SP_LEN \
IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
...@@ -508,6 +511,7 @@ struct ieee80211_if_ibss { ...@@ -508,6 +511,7 @@ struct ieee80211_if_ibss {
bool privacy; bool privacy;
bool control_port; bool control_port;
unsigned int auth_frame_registrations;
u8 bssid[ETH_ALEN] __aligned(2); u8 bssid[ETH_ALEN] __aligned(2);
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
...@@ -677,6 +681,9 @@ struct ieee80211_sub_if_data { ...@@ -677,6 +681,9 @@ struct ieee80211_sub_if_data {
/* TID bitmap for NoAck policy */ /* TID bitmap for NoAck policy */
u16 noack_map; u16 noack_map;
/* bit field of ACM bits (BIT(802.1D tag)) */
u8 wmm_acm;
struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key __rcu *default_unicast_key; struct ieee80211_key __rcu *default_unicast_key;
struct ieee80211_key __rcu *default_multicast_key; struct ieee80211_key __rcu *default_multicast_key;
...@@ -881,6 +888,9 @@ struct ieee80211_local { ...@@ -881,6 +888,9 @@ struct ieee80211_local {
/* device is started */ /* device is started */
bool started; bool started;
/* device is during a HW reconfig */
bool in_reconfig;
/* wowlan is enabled -- don't reconfig on resume */ /* wowlan is enabled -- don't reconfig on resume */
bool wowlan; bool wowlan;
...@@ -1019,7 +1029,6 @@ struct ieee80211_local { ...@@ -1019,7 +1029,6 @@ struct ieee80211_local {
int total_ps_buffered; /* total number of all buffered unicast and int total_ps_buffered; /* total number of all buffered unicast and
* multicast packets for power saving stations * multicast packets for power saving stations
*/ */
unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
bool pspolling; bool pspolling;
bool offchannel_ps_enabled; bool offchannel_ps_enabled;
......
...@@ -808,7 +808,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, ...@@ -808,7 +808,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
return ieee80211_select_queue_80211(local, skb, hdr); return ieee80211_select_queue_80211(sdata, skb, hdr);
} }
static const struct net_device_ops ieee80211_monitorif_ops = { static const struct net_device_ops ieee80211_monitorif_ops = {
......
...@@ -345,6 +345,13 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) ...@@ -345,6 +345,13 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
ieee80211_stop_queues_by_reason(hw, ieee80211_stop_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND); IEEE80211_QUEUE_STOP_REASON_SUSPEND);
/*
* Stop all Rx during the reconfig. We don't want state changes
* or driver callbacks while this is in progress.
*/
local->in_reconfig = true;
barrier();
schedule_work(&local->restart_work); schedule_work(&local->restart_work);
} }
EXPORT_SYMBOL(ieee80211_restart_hw); EXPORT_SYMBOL(ieee80211_restart_hw);
...@@ -455,7 +462,9 @@ static const struct ieee80211_txrx_stypes ...@@ -455,7 +462,9 @@ static const struct ieee80211_txrx_stypes
ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_ADHOC] = { [NL80211_IFTYPE_ADHOC] = {
.tx = 0xffff, .tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4), .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
BIT(IEEE80211_STYPE_AUTH >> 4) |
BIT(IEEE80211_STYPE_DEAUTH >> 4),
}, },
[NL80211_IFTYPE_STATION] = { [NL80211_IFTYPE_STATION] = {
.tx = 0xffff, .tx = 0xffff,
......
...@@ -443,7 +443,7 @@ static void ieee80211_mesh_path_root_timer(unsigned long data) ...@@ -443,7 +443,7 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
{ {
if (ifmsh->mshcfg.dot11MeshHWMPRootMode) if (ifmsh->mshcfg.dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)
set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
else { else {
clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
...@@ -541,11 +541,17 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, ...@@ -541,11 +541,17 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 interval;
mesh_path_tx_root_frame(sdata); mesh_path_tx_root_frame(sdata);
if (ifmsh->mshcfg.dot11MeshHWMPRootMode == IEEE80211_PROACTIVE_RANN)
interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
else
interval = ifmsh->mshcfg.dot11MeshHWMProotInterval;
mod_timer(&ifmsh->mesh_path_root_timer, mod_timer(&ifmsh->mesh_path_root_timer,
round_jiffies(TU_TO_EXP_TIME( round_jiffies(TU_TO_EXP_TIME(interval)));
ifmsh->mshcfg.dot11MeshHWMPRannInterval)));
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -104,6 +104,7 @@ enum mesh_deferred_task_flags { ...@@ -104,6 +104,7 @@ enum mesh_deferred_task_flags {
* an mpath to a hash bucket on a path table. * an mpath to a hash bucket on a path table.
* @rann_snd_addr: the RANN sender address * @rann_snd_addr: the RANN sender address
* @rann_metric: the aggregated path metric towards the root node * @rann_metric: the aggregated path metric towards the root node
* @last_preq_to_root: Timestamp of last PREQ sent to root
* @is_root: the destination station of this path is a root node * @is_root: the destination station of this path is a root node
* @is_gate: the destination station of this path is a mesh gate * @is_gate: the destination station of this path is a mesh gate
* *
...@@ -131,6 +132,7 @@ struct mesh_path { ...@@ -131,6 +132,7 @@ struct mesh_path {
spinlock_t state_lock; spinlock_t state_lock;
u8 rann_snd_addr[ETH_ALEN]; u8 rann_snd_addr[ETH_ALEN];
u32 rann_metric; u32 rann_metric;
unsigned long last_preq_to_root;
bool is_root; bool is_root;
bool is_gate; bool is_gate;
}; };
...@@ -245,7 +247,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); ...@@ -245,7 +247,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void); void ieee80211s_init(void);
void ieee80211s_update_metric(struct ieee80211_local *local, void ieee80211s_update_metric(struct ieee80211_local *local,
struct sta_info *stainfo, struct sk_buff *skb); struct sta_info *sta, struct sk_buff *skb);
void ieee80211s_stop(void); void ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
......
...@@ -98,6 +98,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) ...@@ -98,6 +98,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries) #define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
#define disc_timeout_jiff(s) \ #define disc_timeout_jiff(s) \
msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout) msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
#define root_path_confirmation_jiffies(s) \
msecs_to_jiffies(sdata->u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval)
enum mpath_frame_type { enum mpath_frame_type {
MPATH_PREQ = 0, MPATH_PREQ = 0,
...@@ -303,7 +305,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, ...@@ -303,7 +305,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
} }
void ieee80211s_update_metric(struct ieee80211_local *local, void ieee80211s_update_metric(struct ieee80211_local *local,
struct sta_info *stainfo, struct sk_buff *skb) struct sta_info *sta, struct sk_buff *skb)
{ {
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
...@@ -315,15 +317,14 @@ void ieee80211s_update_metric(struct ieee80211_local *local, ...@@ -315,15 +317,14 @@ void ieee80211s_update_metric(struct ieee80211_local *local,
failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK); failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
/* moving average, scaled to 100 */ /* moving average, scaled to 100 */
stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed); sta->fail_avg = ((80 * sta->fail_avg + 5) / 100 + 20 * failed);
if (stainfo->fail_avg > 95) if (sta->fail_avg > 95)
mesh_plink_broken(stainfo); mesh_plink_broken(sta);
} }
static u32 airtime_link_metric_get(struct ieee80211_local *local, static u32 airtime_link_metric_get(struct ieee80211_local *local,
struct sta_info *sta) struct sta_info *sta)
{ {
struct ieee80211_supported_band *sband;
struct rate_info rinfo; struct rate_info rinfo;
/* This should be adjusted for each device */ /* This should be adjusted for each device */
int device_constant = 1 << ARITH_SHIFT; int device_constant = 1 << ARITH_SHIFT;
...@@ -333,8 +334,6 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, ...@@ -333,8 +334,6 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
u32 tx_time, estimated_retx; u32 tx_time, estimated_retx;
u64 result; u64 result;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
if (sta->fail_avg >= 100) if (sta->fail_avg >= 100)
return MAX_METRIC; return MAX_METRIC;
...@@ -519,10 +518,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -519,10 +518,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
struct mesh_path *mpath = NULL; struct mesh_path *mpath = NULL;
u8 *target_addr, *orig_addr; u8 *target_addr, *orig_addr;
const u8 *da; const u8 *da;
u8 target_flags, ttl; u8 target_flags, ttl, flags;
u32 orig_sn, target_sn, lifetime; u32 orig_sn, target_sn, lifetime, orig_metric;
bool reply = false; bool reply = false;
bool forward = true; bool forward = true;
bool root_is_gate;
/* Update target SN, if present */ /* Update target SN, if present */
target_addr = PREQ_IE_TARGET_ADDR(preq_elem); target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
...@@ -530,6 +530,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -530,6 +530,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
target_sn = PREQ_IE_TARGET_SN(preq_elem); target_sn = PREQ_IE_TARGET_SN(preq_elem);
orig_sn = PREQ_IE_ORIG_SN(preq_elem); orig_sn = PREQ_IE_ORIG_SN(preq_elem);
target_flags = PREQ_IE_TARGET_F(preq_elem); target_flags = PREQ_IE_TARGET_F(preq_elem);
orig_metric = metric;
/* Proactive PREQ gate announcements */
flags = PREQ_IE_FLAGS(preq_elem);
root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
mhwmp_dbg("received PREQ from %pM", orig_addr); mhwmp_dbg("received PREQ from %pM", orig_addr);
...@@ -544,6 +548,22 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -544,6 +548,22 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
target_sn = ++ifmsh->sn; target_sn = ++ifmsh->sn;
ifmsh->last_sn_update = jiffies; ifmsh->last_sn_update = jiffies;
} }
} else if (is_broadcast_ether_addr(target_addr) &&
(target_flags & IEEE80211_PREQ_TO_FLAG)) {
rcu_read_lock();
mpath = mesh_path_lookup(orig_addr, sdata);
if (mpath) {
if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
reply = true;
target_addr = sdata->vif.addr;
target_sn = ++ifmsh->sn;
metric = 0;
ifmsh->last_sn_update = jiffies;
}
if (root_is_gate)
mesh_path_add_gate(mpath);
}
rcu_read_unlock();
} else { } else {
rcu_read_lock(); rcu_read_lock();
mpath = mesh_path_lookup(target_addr, sdata); mpath = mesh_path_lookup(target_addr, sdata);
...@@ -576,13 +596,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -576,13 +596,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
cpu_to_le32(target_sn), mgmt->sa, 0, ttl, cpu_to_le32(target_sn), mgmt->sa, 0, ttl,
cpu_to_le32(lifetime), cpu_to_le32(metric), cpu_to_le32(lifetime), cpu_to_le32(metric),
0, sdata); 0, sdata);
} else } else {
ifmsh->mshstats.dropped_frames_ttl++; ifmsh->mshstats.dropped_frames_ttl++;
}
} }
if (forward && ifmsh->mshcfg.dot11MeshForwarding) { if (forward && ifmsh->mshcfg.dot11MeshForwarding) {
u32 preq_id; u32 preq_id;
u8 hopcount, flags; u8 hopcount;
ttl = PREQ_IE_TTL(preq_elem); ttl = PREQ_IE_TTL(preq_elem);
lifetime = PREQ_IE_LIFETIME(preq_elem); lifetime = PREQ_IE_LIFETIME(preq_elem);
...@@ -592,11 +613,17 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -592,11 +613,17 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
} }
mhwmp_dbg("forwarding the PREQ from %pM", orig_addr); mhwmp_dbg("forwarding the PREQ from %pM", orig_addr);
--ttl; --ttl;
flags = PREQ_IE_FLAGS(preq_elem);
preq_id = PREQ_IE_PREQ_ID(preq_elem); preq_id = PREQ_IE_PREQ_ID(preq_elem);
hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
da = (mpath && mpath->is_root) ? da = (mpath && mpath->is_root) ?
mpath->rann_snd_addr : broadcast_addr; mpath->rann_snd_addr : broadcast_addr;
if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
target_sn = PREQ_IE_TARGET_SN(preq_elem);
metric = orig_metric;
}
mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
cpu_to_le32(orig_sn), target_flags, target_addr, cpu_to_le32(orig_sn), target_flags, target_addr,
cpu_to_le32(target_sn), da, cpu_to_le32(target_sn), da,
...@@ -744,11 +771,6 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -744,11 +771,6 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
bool root_is_gate; bool root_is_gate;
ttl = rann->rann_ttl; ttl = rann->rann_ttl;
if (ttl <= 1) {
ifmsh->mshstats.dropped_frames_ttl++;
return;
}
ttl--;
flags = rann->rann_flags; flags = rann->rann_flags;
root_is_gate = !!(flags & RANN_FLAG_IS_GATE); root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
orig_addr = rann->rann_addr; orig_addr = rann->rann_addr;
...@@ -785,34 +807,49 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, ...@@ -785,34 +807,49 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
} }
} }
if (!(SN_LT(mpath->sn, orig_sn)) &&
!(mpath->sn == orig_sn && metric < mpath->rann_metric)) {
rcu_read_unlock();
return;
}
if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) || if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
time_after(jiffies, mpath->exp_time - 1*HZ)) && (time_after(jiffies, mpath->last_preq_to_root +
!(mpath->flags & MESH_PATH_FIXED)) { root_path_confirmation_jiffies(sdata)) ||
time_before(jiffies, mpath->last_preq_to_root))) &&
!(mpath->flags & MESH_PATH_FIXED) && (ttl != 0)) {
mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name, mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
orig_addr); orig_addr);
mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
mpath->last_preq_to_root = jiffies;
}
mpath->sn = orig_sn;
mpath->rann_metric = metric + metric_txsta;
mpath->is_root = true;
/* Recording RANNs sender address to send individually
* addressed PREQs destined for root mesh STA */
memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
if (root_is_gate)
mesh_path_add_gate(mpath);
if (ttl <= 1) {
ifmsh->mshstats.dropped_frames_ttl++;
rcu_read_unlock();
return;
} }
ttl--;
if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn && if (ifmsh->mshcfg.dot11MeshForwarding) {
metric < mpath->rann_metric)) && ifmsh->mshcfg.dot11MeshForwarding) {
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn), cpu_to_le32(orig_sn),
0, NULL, 0, broadcast_addr, 0, NULL, 0, broadcast_addr,
hopcount, ttl, cpu_to_le32(interval), hopcount, ttl, cpu_to_le32(interval),
cpu_to_le32(metric + metric_txsta), cpu_to_le32(metric + metric_txsta),
0, sdata); 0, sdata);
mpath->sn = orig_sn;
mpath->rann_metric = metric + metric_txsta;
/* Recording RANNs sender address to send individually
* addressed PREQs destined for root mesh STA */
memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN);
} }
mpath->is_root = true;
if (root_is_gate)
mesh_path_add_gate(mpath);
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -1157,13 +1194,34 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) ...@@ -1157,13 +1194,34 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval;
u8 flags; u8 flags, target_flags = 0;
flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol) flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol)
? RANN_FLAG_IS_GATE : 0; ? RANN_FLAG_IS_GATE : 0;
mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) {
case IEEE80211_PROACTIVE_RANN:
mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn), cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr, 0, NULL, 0, broadcast_addr,
0, sdata->u.mesh.mshcfg.element_ttl, 0, ifmsh->mshcfg.element_ttl,
cpu_to_le32(interval), 0, 0, sdata); cpu_to_le32(interval), 0, 0, sdata);
break;
case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
case IEEE80211_PROACTIVE_PREQ_NO_PREP:
interval = ifmsh->mshcfg.dot11MeshHWMPactivePathToRootTimeout;
target_flags |= IEEE80211_PREQ_TO_FLAG |
IEEE80211_PREQ_USN_FLAG;
mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn), target_flags,
(u8 *) broadcast_addr, 0, broadcast_addr,
0, ifmsh->mshcfg.element_ttl,
cpu_to_le32(interval),
0, cpu_to_le32(ifmsh->preq_id++), sdata);
break;
default:
mhwmp_dbg("Proactive mechanism not supported");
return;
}
} }
...@@ -1141,7 +1141,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, ...@@ -1141,7 +1141,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
local->wmm_acm = 0; sdata->wmm_acm = 0;
for (; left >= 4; left -= 4, pos += 4) { for (; left >= 4; left -= 4, pos += 4) {
int aci = (pos[0] >> 5) & 0x03; int aci = (pos[0] >> 5) & 0x03;
int acm = (pos[0] >> 4) & 0x01; int acm = (pos[0] >> 4) & 0x01;
...@@ -1152,21 +1152,21 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, ...@@ -1152,21 +1152,21 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
case 1: /* AC_BK */ case 1: /* AC_BK */
queue = 3; queue = 3;
if (acm) if (acm)
local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
uapsd = true; uapsd = true;
break; break;
case 2: /* AC_VI */ case 2: /* AC_VI */
queue = 1; queue = 1;
if (acm) if (acm)
local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
uapsd = true; uapsd = true;
break; break;
case 3: /* AC_VO */ case 3: /* AC_VO */
queue = 0; queue = 0;
if (acm) if (acm)
local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
uapsd = true; uapsd = true;
break; break;
...@@ -1174,7 +1174,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, ...@@ -1174,7 +1174,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
default: default:
queue = 2; queue = 2;
if (acm) if (acm)
local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
uapsd = true; uapsd = true;
break; break;
...@@ -1275,7 +1275,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ...@@ -1275,7 +1275,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
bss_info_changed |= BSS_CHANGED_BEACON_INT; bss_info_changed |= BSS_CHANGED_BEACON_INT;
bss_info_changed |= ieee80211_handle_bss_capability(sdata, bss_info_changed |= ieee80211_handle_bss_capability(sdata,
cbss->capability, bss->has_erp_value, bss->erp_value); bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int));
...@@ -3012,7 +3012,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, ...@@ -3012,7 +3012,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss *bss = (void *)cbss->priv; struct ieee80211_bss *bss = (void *)cbss->priv;
struct sta_info *sta; struct sta_info *sta = NULL;
bool have_sta = false; bool have_sta = false;
int err; int err;
int ht_cfreq; int ht_cfreq;
...@@ -3102,7 +3102,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, ...@@ -3102,7 +3102,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
local->oper_channel = cbss->channel; local->oper_channel = cbss->channel;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
if (!have_sta) { if (sta) {
u32 rates = 0, basic_rates = 0; u32 rates = 0, basic_rates = 0;
bool have_higher_than_11mbit; bool have_higher_than_11mbit;
int min_rate = INT_MAX, min_rate_index = -1; int min_rate = INT_MAX, min_rate_index = -1;
......
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
* because we *may* be doing work on-operating channel, and want our * because we *may* be doing work on-operating channel, and want our
* hardware unconditionally awake, but still let the AP send us normal frames. * hardware unconditionally awake, but still let the AP send us normal frames.
*/ */
static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
bool tell_ap)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
...@@ -47,8 +46,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, ...@@ -47,8 +46,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
} }
if (tell_ap && (!local->offchannel_ps_enabled || if (!local->offchannel_ps_enabled ||
!(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
/* /*
* If power save was enabled, no need to send a nullfunc * If power save was enabled, no need to send a nullfunc
* frame because AP knows that we are sleeping. But if the * frame because AP knows that we are sleeping. But if the
...@@ -133,7 +132,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, ...@@ -133,7 +132,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
if (offchannel_ps_enable && if (offchannel_ps_enable &&
(sdata->vif.type == NL80211_IFTYPE_STATION) && (sdata->vif.type == NL80211_IFTYPE_STATION) &&
sdata->u.mgd.associated) sdata->u.mgd.associated)
ieee80211_offchannel_ps_enable(sdata, true); ieee80211_offchannel_ps_enable(sdata);
} }
} }
mutex_unlock(&local->iflist_mtx); mutex_unlock(&local->iflist_mtx);
...@@ -263,6 +262,9 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) ...@@ -263,6 +262,9 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
list); list);
if (WARN_ON_ONCE(roc->started))
return;
if (local->ops->remain_on_channel) { if (local->ops->remain_on_channel) {
int ret, duration = roc->duration; int ret, duration = roc->duration;
...@@ -378,8 +380,8 @@ void ieee80211_sw_roc_work(struct work_struct *work) ...@@ -378,8 +380,8 @@ void ieee80211_sw_roc_work(struct work_struct *work)
ieee80211_recalc_idle(local); ieee80211_recalc_idle(local);
ieee80211_start_next_roc(local); if (roc->started)
ieee80211_run_deferred_scan(local); ieee80211_start_next_roc(local);
} }
out_unlock: out_unlock:
...@@ -410,9 +412,6 @@ static void ieee80211_hw_roc_done(struct work_struct *work) ...@@ -410,9 +412,6 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
/* if there's another roc, start it now */ /* if there's another roc, start it now */
ieee80211_start_next_roc(local); ieee80211_start_next_roc(local);
/* or scan maybe */
ieee80211_run_deferred_scan(local);
out_unlock: out_unlock:
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
} }
...@@ -455,7 +454,6 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) ...@@ -455,7 +454,6 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
} }
ieee80211_start_next_roc(local); ieee80211_start_next_roc(local);
ieee80211_run_deferred_scan(local);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
list_for_each_entry_safe(roc, tmp, &tmp_list, list) { list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
......
...@@ -78,6 +78,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) ...@@ -78,6 +78,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
if (err < 0) { if (err < 0) {
local->quiescing = false; local->quiescing = false;
local->wowlan = false; local->wowlan = false;
if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta,
&local->sta_list, list) {
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
}
mutex_unlock(&local->sta_mtx);
}
ieee80211_wake_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
return err; return err;
} else if (err > 0) { } else if (err > 0) {
WARN_ON(err != 1); WARN_ON(err != 1);
......
...@@ -1935,7 +1935,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) ...@@ -1935,7 +1935,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
ether_addr_equal(sdata->vif.addr, hdr->addr3)) ether_addr_equal(sdata->vif.addr, hdr->addr3))
return RX_CONTINUE; return RX_CONTINUE;
q = ieee80211_select_queue_80211(local, skb, hdr); q = ieee80211_select_queue_80211(sdata, skb, hdr);
if (ieee80211_queue_stopped(&local->hw, q)) { if (ieee80211_queue_stopped(&local->hw, q)) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
return RX_DROP_MONITOR; return RX_DROP_MONITOR;
...@@ -3027,6 +3027,10 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -3027,6 +3027,10 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (unlikely(local->quiescing || local->suspended)) if (unlikely(local->quiescing || local->suspended))
goto drop; goto drop;
/* We might be during a HW reconfig, prevent Rx for the same reason */
if (unlikely(local->in_reconfig))
goto drop;
/* /*
* The same happens when we're not even started, * The same happens when we're not even started,
* but that's worth a warning. * but that's worth a warning.
......
...@@ -1411,6 +1411,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -1411,6 +1411,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (ieee80211_sdata_running(sdata)) if (ieee80211_sdata_running(sdata))
ieee80211_enable_keys(sdata); ieee80211_enable_keys(sdata);
local->in_reconfig = false;
barrier();
wake_up: wake_up:
/* /*
* Clear the WLAN_STA_BLOCK_BA flag so new aggregation * Clear the WLAN_STA_BLOCK_BA flag so new aggregation
......
...@@ -52,11 +52,11 @@ static int wme_downgrade_ac(struct sk_buff *skb) ...@@ -52,11 +52,11 @@ static int wme_downgrade_ac(struct sk_buff *skb)
} }
} }
static u16 ieee80211_downgrade_queue(struct ieee80211_local *local, static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb) struct sk_buff *skb)
{ {
/* in case we are a client verify acm is not set for this ac */ /* in case we are a client verify acm is not set for this ac */
while (unlikely(local->wmm_acm & BIT(skb->priority))) { while (unlikely(sdata->wmm_acm & BIT(skb->priority))) {
if (wme_downgrade_ac(skb)) { if (wme_downgrade_ac(skb)) {
/* /*
* This should not really happen. The AP has marked all * This should not really happen. The AP has marked all
...@@ -73,10 +73,11 @@ static u16 ieee80211_downgrade_queue(struct ieee80211_local *local, ...@@ -73,10 +73,11 @@ static u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
} }
/* Indicate which queue to use for this fully formed 802.11 frame */ /* Indicate which queue to use for this fully formed 802.11 frame */
u16 ieee80211_select_queue_80211(struct ieee80211_local *local, u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_hdr *hdr) struct ieee80211_hdr *hdr)
{ {
struct ieee80211_local *local = sdata->local;
u8 *p; u8 *p;
if (local->hw.queues < IEEE80211_NUM_ACS) if (local->hw.queues < IEEE80211_NUM_ACS)
...@@ -94,7 +95,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_local *local, ...@@ -94,7 +95,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_local *local,
p = ieee80211_get_qos_ctl(hdr); p = ieee80211_get_qos_ctl(hdr);
skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
return ieee80211_downgrade_queue(local, skb); return ieee80211_downgrade_queue(sdata, skb);
} }
/* Indicate which queue to use. */ /* Indicate which queue to use. */
...@@ -156,7 +157,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, ...@@ -156,7 +157,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
* data frame has */ * data frame has */
skb->priority = cfg80211_classify8021d(skb); skb->priority = cfg80211_classify8021d(skb);
return ieee80211_downgrade_queue(local, skb); return ieee80211_downgrade_queue(sdata, skb);
} }
void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
extern const int ieee802_1d_to_ac[8]; extern const int ieee802_1d_to_ac[8];
u16 ieee80211_select_queue_80211(struct ieee80211_local *local, u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_hdr *hdr); struct ieee80211_hdr *hdr);
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
......
...@@ -96,69 +96,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) ...@@ -96,69 +96,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy; return &rdev->wiphy;
} }
/* requires cfg80211_mutex to be held! */
struct cfg80211_registered_device *
__cfg80211_rdev_from_info(struct genl_info *info)
{
int ifindex;
struct cfg80211_registered_device *bywiphyidx = NULL, *byifidx = NULL;
struct net_device *dev;
int err = -EINVAL;
assert_cfg80211_lock();
if (info->attrs[NL80211_ATTR_WIPHY]) {
bywiphyidx = cfg80211_rdev_by_wiphy_idx(
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
err = -ENODEV;
}
if (info->attrs[NL80211_ATTR_IFINDEX]) {
ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
dev = dev_get_by_index(genl_info_net(info), ifindex);
if (dev) {
if (dev->ieee80211_ptr)
byifidx =
wiphy_to_dev(dev->ieee80211_ptr->wiphy);
dev_put(dev);
}
err = -ENODEV;
}
if (bywiphyidx && byifidx) {
if (bywiphyidx != byifidx)
return ERR_PTR(-EINVAL);
else
return bywiphyidx; /* == byifidx */
}
if (bywiphyidx)
return bywiphyidx;
if (byifidx)
return byifidx;
return ERR_PTR(err);
}
struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
mutex_lock(&cfg80211_mutex);
rdev = __cfg80211_rdev_from_info(info);
/* if it is not an error we grab the lock on
* it to assure it won't be going away while
* we operate on it */
if (!IS_ERR(rdev))
mutex_lock(&rdev->mtx);
mutex_unlock(&cfg80211_mutex);
return rdev;
}
struct cfg80211_registered_device * struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{ {
......
...@@ -159,32 +159,6 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) ...@@ -159,32 +159,6 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy); int get_wiphy_idx(struct wiphy *wiphy);
struct cfg80211_registered_device *
__cfg80211_rdev_from_info(struct genl_info *info);
/*
* This function returns a pointer to the driver
* that the genl_info item that is passed refers to.
* If successful, it returns non-NULL and also locks
* the driver's mutex!
*
* This means that you need to call cfg80211_unlock_rdev()
* before being allowed to acquire &cfg80211_mutex!
*
* This is necessary because we need to lock the global
* mutex to get an item off the list safely, and then
* we lock the rdev mutex so it doesn't go away under us.
*
* We don't want to keep cfg80211_mutex locked
* for all the time in order to allow requests on
* other interfaces to go through at the same time.
*
* The result of this can be a PTR_ERR and hence must
* be checked with IS_ERR() for errors.
*/
extern struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct genl_info *info);
/* requires cfg80211_rdev_mutex to be held! */ /* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
#define MESH_PATH_TIMEOUT 5000 #define MESH_PATH_TIMEOUT 5000
#define MESH_RANN_INTERVAL 5000 #define MESH_RANN_INTERVAL 5000
#define MESH_PATH_TO_ROOT_TIMEOUT 6000
#define MESH_ROOT_INTERVAL 5000
#define MESH_ROOT_CONFIRMATION_INTERVAL 2000
/* /*
* Minimum interval between two consecutive PREQs originated by the same * Minimum interval between two consecutive PREQs originated by the same
...@@ -62,6 +65,9 @@ const struct mesh_config default_mesh_config = { ...@@ -62,6 +65,9 @@ const struct mesh_config default_mesh_config = {
.dot11MeshForwarding = true, .dot11MeshForwarding = true,
.rssi_threshold = MESH_RSSI_THRESHOLD, .rssi_threshold = MESH_RSSI_THRESHOLD,
.ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED, .ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED,
.dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT,
.dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL,
.dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL,
}; };
const struct mesh_setup default_mesh_setup = { const struct mesh_setup default_mesh_setup = {
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment