aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRaja Mani <rmani@qca.qualcomm.com>2012-01-30 06:43:10 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2012-01-30 14:22:55 -0500
commitd91e8eee046e0d4ae7a8a585616b5ce800f54568 (patch)
treef46dbb45d0b8d8e7f837e48c0926ffb470d381e0 /drivers
parente390af779dc671551800514d391928f5a798089a (diff)
ath6kl: Configure WOW patterns while going to wow_suspend
First preference is given to the user configured WOW patterns. If the user doesn't configure any patterns (for ex, via iw command), the default patterns will be configured based on the current mode (vif->nw_type) while going to WOW suspend. Summary of changes: * ath6kl_wow_ap() is added to configure the below default patterns when the system enters into WOW suspend in AP mode. + Unicast IP, EAPOL-like and ARP packet pattern + ARP packet pattern + mDNS/SSDP/LLMNR pattern + DHCP broadcast pattern * ath6kl_wow_sta() is added to configure the below default patterns when the system enters into WOW suspend in STA mode. + Unicast packet pattern + mDNS/SSDP/LLMNR pattern * Move the user provided WOW patterns configuration code from ath6kl_wow_suspend() to a separate function called ath6kl_wow_usr(). * Two argument variable's ('filter' and 'mask) data type in ath6kl_wmi_add_wow_pattern_cmd() are changed from 'u8 *' to 'const u8 *'. This is needed to make all pattern and mask arrays to be 'static const u8' in the caller function. * New conditional check is added to make sure user configured pattern count is within the limit (WOW_MAX_FILTERS_PER_LIST). Signed-off-by: Raja Mani <rmani@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c231
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c3
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h3
3 files changed, 193 insertions, 44 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index fed7b8077f5e..e676cfccedfe 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1723,32 +1723,14 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1723 return 0; 1723 return 0;
1724} 1724}
1725 1725
1726static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) 1726static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
1727 struct cfg80211_wowlan *wow, u32 *filter)
1727{ 1728{
1728 struct in_device *in_dev; 1729 int ret, pos;
1729 struct in_ifaddr *ifa; 1730 u8 mask[WOW_MASK_SIZE];
1730 struct ath6kl_vif *vif;
1731 int ret, pos, left;
1732 u32 filter = 0;
1733 u16 i; 1731 u16 i;
1734 u8 mask[WOW_MASK_SIZE], index = 0;
1735 __be32 ips[MAX_IP_ADDRS];
1736
1737 vif = ath6kl_vif_first(ar);
1738 if (!vif)
1739 return -EIO;
1740
1741 if (!ath6kl_cfg80211_ready(vif))
1742 return -EIO;
1743
1744 if (!test_bit(CONNECTED, &vif->flags))
1745 return -EINVAL;
1746 1732
1747 /* Clear existing WOW patterns */ 1733 /* Configure the patterns that we received from the user. */
1748 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
1749 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
1750 WOW_LIST_ID, i);
1751 /* Configure new WOW patterns */
1752 for (i = 0; i < wow->n_patterns; i++) { 1734 for (i = 0; i < wow->n_patterns; i++) {
1753 1735
1754 /* 1736 /*
@@ -1771,14 +1753,194 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1771 * matched from the first byte of received pkt in the firmware. 1753 * matched from the first byte of received pkt in the firmware.
1772 */ 1754 */
1773 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, 1755 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1774 vif->fw_vif_idx, WOW_LIST_ID, 1756 vif->fw_vif_idx, WOW_LIST_ID,
1775 wow->patterns[i].pattern_len, 1757 wow->patterns[i].pattern_len,
1776 0 /* pattern offset */, 1758 0 /* pattern offset */,
1777 wow->patterns[i].pattern, mask); 1759 wow->patterns[i].pattern, mask);
1778 if (ret) 1760 if (ret)
1779 return ret; 1761 return ret;
1780 } 1762 }
1781 1763
1764 if (wow->disconnect)
1765 *filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
1766
1767 if (wow->magic_pkt)
1768 *filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
1769
1770 if (wow->gtk_rekey_failure)
1771 *filter |= WOW_FILTER_OPTION_GTK_ERROR;
1772
1773 if (wow->eap_identity_req)
1774 *filter |= WOW_FILTER_OPTION_EAP_REQ;
1775
1776 if (wow->four_way_handshake)
1777 *filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
1778
1779 return 0;
1780}
1781
1782static int ath6kl_wow_ap(struct ath6kl *ar, struct ath6kl_vif *vif)
1783{
1784 static const u8 unicst_pattern[] = { 0x00, 0x00, 0x00,
1785 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1787 0x00, 0x08 };
1788 static const u8 unicst_mask[] = { 0x01, 0x00, 0x00,
1789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1791 0x00, 0x7f };
1792 u8 unicst_offset = 0;
1793 static const u8 arp_pattern[] = { 0x08, 0x06 };
1794 static const u8 arp_mask[] = { 0xff, 0xff };
1795 u8 arp_offset = 20;
1796 static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
1797 static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
1798 u8 discvr_offset = 38;
1799 static const u8 dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff,
1800 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
1802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1804 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ };
1805 static const u8 dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff,
1806 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
1808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1810 0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ };
1811 u8 dhcp_offset = 0;
1812 int ret;
1813
1814 /* Setup unicast IP, EAPOL-like and ARP pkt pattern */
1815 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1816 vif->fw_vif_idx, WOW_LIST_ID,
1817 sizeof(unicst_pattern), unicst_offset,
1818 unicst_pattern, unicst_mask);
1819 if (ret) {
1820 ath6kl_err("failed to add WOW unicast IP pattern\n");
1821 return ret;
1822 }
1823
1824 /* Setup all ARP pkt pattern */
1825 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1826 vif->fw_vif_idx, WOW_LIST_ID,
1827 sizeof(arp_pattern), arp_offset,
1828 arp_pattern, arp_mask);
1829 if (ret) {
1830 ath6kl_err("failed to add WOW ARP pattern\n");
1831 return ret;
1832 }
1833
1834 /*
1835 * Setup multicast pattern for mDNS 224.0.0.251,
1836 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
1837 */
1838 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1839 vif->fw_vif_idx, WOW_LIST_ID,
1840 sizeof(discvr_pattern), discvr_offset,
1841 discvr_pattern, discvr_mask);
1842 if (ret) {
1843 ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
1844 return ret;
1845 }
1846
1847 /* Setup all DHCP broadcast pkt pattern */
1848 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1849 vif->fw_vif_idx, WOW_LIST_ID,
1850 sizeof(dhcp_pattern), dhcp_offset,
1851 dhcp_pattern, dhcp_mask);
1852 if (ret) {
1853 ath6kl_err("failed to add WOW DHCP broadcast pattern\n");
1854 return ret;
1855 }
1856
1857 return 0;
1858}
1859
1860static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
1861{
1862 struct net_device *ndev = vif->ndev;
1863 static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
1864 static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
1865 u8 discvr_offset = 38;
1866 u8 mac_mask[ETH_ALEN];
1867 int ret;
1868
1869 /* Setup unicast pkt pattern */
1870 memset(mac_mask, 0xff, ETH_ALEN);
1871 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1872 vif->fw_vif_idx, WOW_LIST_ID,
1873 ETH_ALEN, 0, ndev->dev_addr,
1874 mac_mask);
1875 if (ret) {
1876 ath6kl_err("failed to add WOW unicast pattern\n");
1877 return ret;
1878 }
1879
1880 /*
1881 * Setup multicast pattern for mDNS 224.0.0.251,
1882 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
1883 */
1884 if ((ndev->flags & IFF_ALLMULTI) ||
1885 (ndev->flags & IFF_MULTICAST && netdev_mc_count(ndev) > 0)) {
1886 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1887 vif->fw_vif_idx, WOW_LIST_ID,
1888 sizeof(discvr_pattern), discvr_offset,
1889 discvr_pattern, discvr_mask);
1890 if (ret) {
1891 ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR "
1892 "pattern\n");
1893 return ret;
1894 }
1895 }
1896
1897 return 0;
1898}
1899
1900static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1901{
1902 struct in_device *in_dev;
1903 struct in_ifaddr *ifa;
1904 struct ath6kl_vif *vif;
1905 int ret, left;
1906 u32 filter = 0;
1907 u16 i;
1908 u8 index = 0;
1909 __be32 ips[MAX_IP_ADDRS];
1910
1911 vif = ath6kl_vif_first(ar);
1912 if (!vif)
1913 return -EIO;
1914
1915 if (!ath6kl_cfg80211_ready(vif))
1916 return -EIO;
1917
1918 if (!test_bit(CONNECTED, &vif->flags))
1919 return -EINVAL;
1920
1921 if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
1922 return -EINVAL;
1923
1924 /* Clear existing WOW patterns */
1925 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
1926 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
1927 WOW_LIST_ID, i);
1928
1929 /*
1930 * Skip the default WOW pattern configuration
1931 * if the driver receives any WOW patterns from
1932 * the user.
1933 */
1934 if (wow)
1935 ret = ath6kl_wow_usr(ar, vif, wow, &filter);
1936 else if (vif->nw_type == AP_NETWORK)
1937 ret = ath6kl_wow_ap(ar, vif);
1938 else
1939 ret = ath6kl_wow_sta(ar, vif);
1940
1941 if (ret)
1942 return ret;
1943
1782 /* Setup own IP addr for ARP agent. */ 1944 /* Setup own IP addr for ARP agent. */
1783 in_dev = __in_dev_get_rtnl(vif->ndev); 1945 in_dev = __in_dev_get_rtnl(vif->ndev);
1784 if (!in_dev) 1946 if (!in_dev)
@@ -1806,21 +1968,6 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1806 } 1968 }
1807 1969
1808skip_arp: 1970skip_arp:
1809 if (wow->disconnect)
1810 filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
1811
1812 if (wow->magic_pkt)
1813 filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
1814
1815 if (wow->gtk_rekey_failure)
1816 filter |= WOW_FILTER_OPTION_GTK_ERROR;
1817
1818 if (wow->eap_identity_req)
1819 filter |= WOW_FILTER_OPTION_EAP_REQ;
1820
1821 if (wow->four_way_handshake)
1822 filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
1823
1824 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, 1971 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
1825 ATH6KL_WOW_MODE_ENABLE, 1972 ATH6KL_WOW_MODE_ENABLE,
1826 filter, 1973 filter,
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 5d678bf372d3..9c8e4dfbfa0c 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2620,7 +2620,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
2620 2620
2621int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, 2621int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2622 u8 list_id, u8 filter_size, 2622 u8 list_id, u8 filter_size,
2623 u8 filter_offset, u8 *filter, u8 *mask) 2623 u8 filter_offset, const u8 *filter,
2624 const u8 *mask)
2624{ 2625{
2625 struct sk_buff *skb; 2626 struct sk_buff *skb;
2626 struct wmi_add_wow_pattern_cmd *cmd; 2627 struct wmi_add_wow_pattern_cmd *cmd;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 48e9d2641d69..85698ef2dd88 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -2461,7 +2461,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
2461 u32 filter, u16 host_req_delay); 2461 u32 filter, u16 host_req_delay);
2462int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, 2462int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2463 u8 list_id, u8 filter_size, 2463 u8 list_id, u8 filter_size,
2464 u8 filter_offset, u8 *filter, u8 *mask); 2464 u8 filter_offset, const u8 *filter,
2465 const u8 *mask);
2465int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, 2466int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2466 u16 list_id, u16 filter_id); 2467 u16 list_id, u16 filter_id);
2467int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); 2468int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);