Skip to content

Commit

Permalink
mac80211: Add HT helper functions
Browse files Browse the repository at this point in the history
Some refactoring for IBSS HT.

Move HT info and capability IEs building code into separate functions.

Add function to get the channel type from an HT info IE.

Signed-off-by: Alexander Simon <an.alexsimon@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Alexander Simon authored and John W. Linville committed Nov 8, 2011
1 parent 3b69a9c commit 42e7aa7
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 45 deletions.
8 changes: 8 additions & 0 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,12 @@ void ieee80211_recalc_smps(struct ieee80211_local *local);
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
const u8 *ids, int n_ids, size_t offset);
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
u16 cap);
u8 *ieee80211_ie_build_ht_info(u8 *pos,
struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type);

/* internal work items */
void ieee80211_work_init(struct ieee80211_local *local);
Expand Down Expand Up @@ -1361,6 +1367,8 @@ ieee80211_get_channel_mode(struct ieee80211_local *local,
bool ieee80211_set_channel_type(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
enum nl80211_channel_type chantype);
enum nl80211_channel_type
ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info);

#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
Expand Down
116 changes: 99 additions & 17 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,23 +811,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
offset = noffset;
}

if (sband->ht_cap.ht_supported) {
u16 cap = sband->ht_cap.cap;
__le16 tmp;

*pos++ = WLAN_EID_HT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_ht_cap);
memset(pos, 0, sizeof(struct ieee80211_ht_cap));
tmp = cpu_to_le16(cap);
memcpy(pos, &tmp, sizeof(u16));
pos += sizeof(u16);
*pos++ = sband->ht_cap.ampdu_factor |
(sband->ht_cap.ampdu_density <<
IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
pos += sizeof(sband->ht_cap.mcs);
pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
}
if (sband->ht_cap.ht_supported)
pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);

/*
* If adding more here, adjust code in main.c
Expand Down Expand Up @@ -1362,6 +1347,103 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
}
EXPORT_SYMBOL(ieee80211_disable_rssi_reports);

u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
u16 cap)
{
__le16 tmp;

*pos++ = WLAN_EID_HT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_ht_cap);
memset(pos, 0, sizeof(struct ieee80211_ht_cap));

/* capability flags */
tmp = cpu_to_le16(cap);
memcpy(pos, &tmp, sizeof(u16));
pos += sizeof(u16);

/* AMPDU parameters */
*pos++ = sband->ht_cap.ampdu_factor |
(sband->ht_cap.ampdu_density <<
IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);

/* MCS set */
memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
pos += sizeof(sband->ht_cap.mcs);

/* extended capabilities */
pos += sizeof(__le16);

/* BF capabilities */
pos += sizeof(__le32);

/* antenna selection */
pos += sizeof(u8);

return pos;
}

u8 *ieee80211_ie_build_ht_info(u8 *pos,
struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type)
{
struct ieee80211_ht_info *ht_info;
/* Build HT Information */
*pos++ = WLAN_EID_HT_INFORMATION;
*pos++ = sizeof(struct ieee80211_ht_info);
ht_info = (struct ieee80211_ht_info *)pos;
ht_info->control_chan =
ieee80211_frequency_to_channel(channel->center_freq);
switch (channel_type) {
case NL80211_CHAN_HT40MINUS:
ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
break;
case NL80211_CHAN_HT40PLUS:
ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
break;
case NL80211_CHAN_HT20:
default:
ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
break;
}
if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
ht_info->operation_mode = 0x0000;
ht_info->stbc_param = 0x0000;

/* It seems that Basic MCS set and Supported MCS set
are identical for the first 10 bytes */
memset(&ht_info->basic_set, 0, 16);
memcpy(&ht_info->basic_set, &ht_cap->mcs, 10);

return pos + sizeof(struct ieee80211_ht_info);
}

enum nl80211_channel_type
ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info)
{
enum nl80211_channel_type channel_type;

if (!ht_info)
return NL80211_CHAN_NO_HT;

switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_NONE:
channel_type = NL80211_CHAN_HT20;
break;
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
channel_type = NL80211_CHAN_HT40PLUS;
break;
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
channel_type = NL80211_CHAN_HT40MINUS;
break;
default:
channel_type = NL80211_CHAN_NO_HT;
}

return channel_type;
}

int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
Expand Down
29 changes: 1 addition & 28 deletions net/mac80211/work.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
u8 *pos;
u32 flags = channel->flags;
u16 cap = sband->ht_cap.cap;
__le16 tmp;

if (!sband->ht_cap.ht_supported)
return;
Expand Down Expand Up @@ -154,34 +153,8 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
}

/* reserve and fill IE */

pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
*pos++ = WLAN_EID_HT_CAPABILITY;
*pos++ = sizeof(struct ieee80211_ht_cap);
memset(pos, 0, sizeof(struct ieee80211_ht_cap));

/* capability flags */
tmp = cpu_to_le16(cap);
memcpy(pos, &tmp, sizeof(u16));
pos += sizeof(u16);

/* AMPDU parameters */
*pos++ = sband->ht_cap.ampdu_factor |
(sband->ht_cap.ampdu_density <<
IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);

/* MCS set */
memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
pos += sizeof(sband->ht_cap.mcs);

/* extended capabilities */
pos += sizeof(__le16);

/* BF capabilities */
pos += sizeof(__le32);

/* antenna selection */
pos += sizeof(u8);
ieee80211_ie_build_ht_cap(pos, sband, cap);
}

static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
Expand Down

0 comments on commit 42e7aa7

Please sign in to comment.