Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 290282
b: refs/heads/master
c: d91e8ee
h: refs/heads/master
v: v3
  • Loading branch information
Raja Mani authored and Kalle Valo committed Jan 30, 2012
1 parent adfc69e commit b91440a
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e390af779dc671551800514d391928f5a798089a
refs/heads/master: d91e8eee046e0d4ae7a8a585616b5ce800f54568
231 changes: 189 additions & 42 deletions trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -1723,32 +1723,14 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
return 0;
}

static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
struct cfg80211_wowlan *wow, u32 *filter)
{
struct in_device *in_dev;
struct in_ifaddr *ifa;
struct ath6kl_vif *vif;
int ret, pos, left;
u32 filter = 0;
int ret, pos;
u8 mask[WOW_MASK_SIZE];
u16 i;
u8 mask[WOW_MASK_SIZE], index = 0;
__be32 ips[MAX_IP_ADDRS];

vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;

if (!ath6kl_cfg80211_ready(vif))
return -EIO;

if (!test_bit(CONNECTED, &vif->flags))
return -EINVAL;

/* Clear existing WOW patterns */
for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
WOW_LIST_ID, i);
/* Configure new WOW patterns */
/* Configure the patterns that we received from the user. */
for (i = 0; i < wow->n_patterns; i++) {

/*
Expand All @@ -1771,14 +1753,194 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
* matched from the first byte of received pkt in the firmware.
*/
ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
vif->fw_vif_idx, WOW_LIST_ID,
wow->patterns[i].pattern_len,
0 /* pattern offset */,
wow->patterns[i].pattern, mask);
vif->fw_vif_idx, WOW_LIST_ID,
wow->patterns[i].pattern_len,
0 /* pattern offset */,
wow->patterns[i].pattern, mask);
if (ret)
return ret;
}

if (wow->disconnect)
*filter |= WOW_FILTER_OPTION_NWK_DISASSOC;

if (wow->magic_pkt)
*filter |= WOW_FILTER_OPTION_MAGIC_PACKET;

if (wow->gtk_rekey_failure)
*filter |= WOW_FILTER_OPTION_GTK_ERROR;

if (wow->eap_identity_req)
*filter |= WOW_FILTER_OPTION_EAP_REQ;

if (wow->four_way_handshake)
*filter |= WOW_FILTER_OPTION_8021X_4WAYHS;

return 0;
}

static int ath6kl_wow_ap(struct ath6kl *ar, struct ath6kl_vif *vif)
{
static const u8 unicst_pattern[] = { 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08 };
static const u8 unicst_mask[] = { 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f };
u8 unicst_offset = 0;
static const u8 arp_pattern[] = { 0x08, 0x06 };
static const u8 arp_mask[] = { 0xff, 0xff };
u8 arp_offset = 20;
static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
u8 discvr_offset = 38;
static const u8 dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ };
static const u8 dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ };
u8 dhcp_offset = 0;
int ret;

/* Setup unicast IP, EAPOL-like and ARP pkt pattern */
ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
vif->fw_vif_idx, WOW_LIST_ID,
sizeof(unicst_pattern), unicst_offset,
unicst_pattern, unicst_mask);
if (ret) {
ath6kl_err("failed to add WOW unicast IP pattern\n");
return ret;
}

/* Setup all ARP pkt pattern */
ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
vif->fw_vif_idx, WOW_LIST_ID,
sizeof(arp_pattern), arp_offset,
arp_pattern, arp_mask);
if (ret) {
ath6kl_err("failed to add WOW ARP pattern\n");
return ret;
}

/*
* Setup multicast pattern for mDNS 224.0.0.251,
* SSDP 239.255.255.250 and LLMNR 224.0.0.252
*/
ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
vif->fw_vif_idx, WOW_LIST_ID,
sizeof(discvr_pattern), discvr_offset,
discvr_pattern, discvr_mask);
if (ret) {
ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
return ret;
}

/* Setup all DHCP broadcast pkt pattern */
ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
vif->fw_vif_idx, WOW_LIST_ID,
sizeof(dhcp_pattern), dhcp_offset,
dhcp_pattern, dhcp_mask);
if (ret) {
ath6kl_err("failed to add WOW DHCP broadcast pattern\n");
return ret;
}

return 0;
}

static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
{
struct net_device *ndev = vif->ndev;
static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
u8 discvr_offset = 38;
u8 mac_mask[ETH_ALEN];
int ret;

/* Setup unicast pkt pattern */
memset(mac_mask, 0xff, ETH_ALEN);
ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
vif->fw_vif_idx, WOW_LIST_ID,
ETH_ALEN, 0, ndev->dev_addr,
mac_mask);
if (ret) {
ath6kl_err("failed to add WOW unicast pattern\n");
return ret;
}

/*
* Setup multicast pattern for mDNS 224.0.0.251,
* SSDP 239.255.255.250 and LLMNR 224.0.0.252
*/
if ((ndev->flags & IFF_ALLMULTI) ||
(ndev->flags & IFF_MULTICAST && netdev_mc_count(ndev) > 0)) {
ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
vif->fw_vif_idx, WOW_LIST_ID,
sizeof(discvr_pattern), discvr_offset,
discvr_pattern, discvr_mask);
if (ret) {
ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR "
"pattern\n");
return ret;
}
}

return 0;
}

static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
{
struct in_device *in_dev;
struct in_ifaddr *ifa;
struct ath6kl_vif *vif;
int ret, left;
u32 filter = 0;
u16 i;
u8 index = 0;
__be32 ips[MAX_IP_ADDRS];

vif = ath6kl_vif_first(ar);
if (!vif)
return -EIO;

if (!ath6kl_cfg80211_ready(vif))
return -EIO;

if (!test_bit(CONNECTED, &vif->flags))
return -EINVAL;

if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
return -EINVAL;

/* Clear existing WOW patterns */
for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
WOW_LIST_ID, i);

/*
* Skip the default WOW pattern configuration
* if the driver receives any WOW patterns from
* the user.
*/
if (wow)
ret = ath6kl_wow_usr(ar, vif, wow, &filter);
else if (vif->nw_type == AP_NETWORK)
ret = ath6kl_wow_ap(ar, vif);
else
ret = ath6kl_wow_sta(ar, vif);

if (ret)
return ret;

/* Setup own IP addr for ARP agent. */
in_dev = __in_dev_get_rtnl(vif->ndev);
if (!in_dev)
Expand Down Expand Up @@ -1806,21 +1968,6 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
}

skip_arp:
if (wow->disconnect)
filter |= WOW_FILTER_OPTION_NWK_DISASSOC;

if (wow->magic_pkt)
filter |= WOW_FILTER_OPTION_MAGIC_PACKET;

if (wow->gtk_rekey_failure)
filter |= WOW_FILTER_OPTION_GTK_ERROR;

if (wow->eap_identity_req)
filter |= WOW_FILTER_OPTION_EAP_REQ;

if (wow->four_way_handshake)
filter |= WOW_FILTER_OPTION_8021X_4WAYHS;

ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
ATH6KL_WOW_MODE_ENABLE,
filter,
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/net/wireless/ath/ath6kl/wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2620,7 +2620,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,

int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u8 list_id, u8 filter_size,
u8 filter_offset, u8 *filter, u8 *mask)
u8 filter_offset, const u8 *filter,
const u8 *mask)
{
struct sk_buff *skb;
struct wmi_add_wow_pattern_cmd *cmd;
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/net/wireless/ath/ath6kl/wmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2461,7 +2461,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
u32 filter, u16 host_req_delay);
int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u8 list_id, u8 filter_size,
u8 filter_offset, u8 *filter, u8 *mask);
u8 filter_offset, const u8 *filter,
const u8 *mask);
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u16 list_id, u16 filter_id);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
Expand Down

0 comments on commit b91440a

Please sign in to comment.