diff options
author | Arend van Spriel <arend@broadcom.com> | 2013-08-10 06:27:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-15 16:07:54 -0400 |
commit | 89c2f382fff4ec8adf04264925e07e951d0552ce (patch) | |
tree | a7c32d05ffb41fa7a0491f3ed2ab0fbbd60a25c4 | |
parent | 2ee8382fc6c763c76396a6aaff77a27089eed3aa (diff) |
brcmfmac: add support for manual TDLS operations
Implement the .tdls_oper() callback and indicate TDLS support
in the wiphy flags.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 57 |
2 files changed, 77 insertions, 1 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 665ef69e974b..ecabb04f33c3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
@@ -69,4 +69,25 @@ struct brcmf_fil_bss_enable_le { | |||
69 | __le32 enable; | 69 | __le32 enable; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | /** | ||
73 | * struct tdls_iovar - common structure for tdls iovars. | ||
74 | * | ||
75 | * @ea: ether address of peer station. | ||
76 | * @mode: mode value depending on specific tdls iovar. | ||
77 | * @chanspec: channel specification. | ||
78 | * @pad: unused (for future use). | ||
79 | */ | ||
80 | struct brcmf_tdls_iovar_le { | ||
81 | u8 ea[ETH_ALEN]; /* Station address */ | ||
82 | u8 mode; /* mode: depends on iovar */ | ||
83 | __le16 chanspec; | ||
84 | __le32 pad; /* future */ | ||
85 | }; | ||
86 | |||
87 | enum brcmf_tdls_manual_ep_ops { | ||
88 | BRCMF_TDLS_MANUAL_EP_CREATE = 1, | ||
89 | BRCMF_TDLS_MANUAL_EP_DELETE = 3, | ||
90 | BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6 | ||
91 | }; | ||
92 | |||
72 | #endif /* FWIL_TYPES_H_ */ | 93 | #endif /* FWIL_TYPES_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index c3dfea3f307d..0370e44cec11 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -4126,6 +4126,53 @@ static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy, | |||
4126 | clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); | 4126 | clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); |
4127 | } | 4127 | } |
4128 | 4128 | ||
4129 | static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper) | ||
4130 | { | ||
4131 | int ret; | ||
4132 | |||
4133 | switch (oper) { | ||
4134 | case NL80211_TDLS_DISCOVERY_REQ: | ||
4135 | ret = BRCMF_TDLS_MANUAL_EP_DISCOVERY; | ||
4136 | break; | ||
4137 | case NL80211_TDLS_SETUP: | ||
4138 | ret = BRCMF_TDLS_MANUAL_EP_CREATE; | ||
4139 | break; | ||
4140 | case NL80211_TDLS_TEARDOWN: | ||
4141 | ret = BRCMF_TDLS_MANUAL_EP_DELETE; | ||
4142 | break; | ||
4143 | default: | ||
4144 | brcmf_err("unsupported operation: %d\n", oper); | ||
4145 | ret = -EOPNOTSUPP; | ||
4146 | } | ||
4147 | return ret; | ||
4148 | } | ||
4149 | |||
4150 | static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, | ||
4151 | struct net_device *ndev, u8 *peer, | ||
4152 | enum nl80211_tdls_operation oper) | ||
4153 | { | ||
4154 | struct brcmf_if *ifp; | ||
4155 | struct brcmf_tdls_iovar_le info; | ||
4156 | int ret = 0; | ||
4157 | |||
4158 | ret = brcmf_convert_nl80211_tdls_oper(oper); | ||
4159 | if (ret < 0) | ||
4160 | return ret; | ||
4161 | |||
4162 | ifp = netdev_priv(ndev); | ||
4163 | memset(&info, 0, sizeof(info)); | ||
4164 | info.mode = (u8)ret; | ||
4165 | if (peer) | ||
4166 | memcpy(info.ea, peer, ETH_ALEN); | ||
4167 | |||
4168 | ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint", | ||
4169 | &info, sizeof(info)); | ||
4170 | if (ret < 0) | ||
4171 | brcmf_err("tdls_endpoint iovar failed: ret=%d\n", ret); | ||
4172 | |||
4173 | return ret; | ||
4174 | } | ||
4175 | |||
4129 | static struct cfg80211_ops wl_cfg80211_ops = { | 4176 | static struct cfg80211_ops wl_cfg80211_ops = { |
4130 | .add_virtual_intf = brcmf_cfg80211_add_iface, | 4177 | .add_virtual_intf = brcmf_cfg80211_add_iface, |
4131 | .del_virtual_intf = brcmf_cfg80211_del_iface, | 4178 | .del_virtual_intf = brcmf_cfg80211_del_iface, |
@@ -4164,6 +4211,7 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
4164 | .stop_p2p_device = brcmf_p2p_stop_device, | 4211 | .stop_p2p_device = brcmf_p2p_stop_device, |
4165 | .crit_proto_start = brcmf_cfg80211_crit_proto_start, | 4212 | .crit_proto_start = brcmf_cfg80211_crit_proto_start, |
4166 | .crit_proto_stop = brcmf_cfg80211_crit_proto_stop, | 4213 | .crit_proto_stop = brcmf_cfg80211_crit_proto_stop, |
4214 | .tdls_oper = brcmf_cfg80211_tdls_oper, | ||
4167 | CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode) | 4215 | CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode) |
4168 | }; | 4216 | }; |
4169 | 4217 | ||
@@ -4285,7 +4333,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4285 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | 4333 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); |
4286 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | | 4334 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | |
4287 | WIPHY_FLAG_OFFCHAN_TX | | 4335 | WIPHY_FLAG_OFFCHAN_TX | |
4288 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 4336 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
4337 | WIPHY_FLAG_SUPPORTS_TDLS; | ||
4289 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | 4338 | wiphy->mgmt_stypes = brcmf_txrx_stypes; |
4290 | wiphy->max_remain_on_channel_duration = 5000; | 4339 | wiphy->max_remain_on_channel_duration = 5000; |
4291 | brcmf_wiphy_pno_params(wiphy); | 4340 | brcmf_wiphy_pno_params(wiphy); |
@@ -4906,6 +4955,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
4906 | goto cfg80211_p2p_attach_out; | 4955 | goto cfg80211_p2p_attach_out; |
4907 | } | 4956 | } |
4908 | 4957 | ||
4958 | err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); | ||
4959 | if (err) { | ||
4960 | brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); | ||
4961 | wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS; | ||
4962 | } | ||
4963 | |||
4909 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, | 4964 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, |
4910 | &io_type); | 4965 | &io_type); |
4911 | if (err) { | 4966 | if (err) { |