aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/scan.c
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2014-02-07 19:23:35 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-12 15:36:12 -0500
commit3b4d5c644204476265083a554dad56868b93b9dd (patch)
treeabce22bed52cd794d1b492f0cb96fee23357ded8 /drivers/net/wireless/mwifiex/scan.c
parentb8b3ecec91f106e2f26ac2e24dcda21f63336286 (diff)
mwifiex: separate out response buffer parsing code
This new function will be useful later for extended scan feature. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwifiex/scan.c')
-rw-r--r--drivers/net/wireless/mwifiex/scan.c309
1 files changed, 163 insertions, 146 deletions
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index b0be830aa342..28f0a38ff2d9 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1576,6 +1576,156 @@ done:
1576 return 0; 1576 return 0;
1577} 1577}
1578 1578
1579static int
1580mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1581 u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1582 bool ext_scan)
1583{
1584 struct mwifiex_adapter *adapter = priv->adapter;
1585 struct mwifiex_chan_freq_power *cfp;
1586 struct cfg80211_bss *bss;
1587 u8 bssid[ETH_ALEN];
1588 s32 rssi;
1589 const u8 *ie_buf;
1590 size_t ie_len;
1591 u16 channel = 0;
1592 u16 beacon_size = 0;
1593 u32 curr_bcn_bytes;
1594 u32 freq;
1595 u16 beacon_period;
1596 u16 cap_info_bitmap;
1597 u8 *current_ptr;
1598 u64 timestamp;
1599 struct mwifiex_fixed_bcn_param *bcn_param;
1600 struct mwifiex_bss_priv *bss_priv;
1601
1602 if (*bytes_left >= sizeof(beacon_size)) {
1603 /* Extract & convert beacon size from command buffer */
1604 memcpy(&beacon_size, *bss_info, sizeof(beacon_size));
1605 *bytes_left -= sizeof(beacon_size);
1606 *bss_info += sizeof(beacon_size);
1607 }
1608
1609 if (!beacon_size || beacon_size > *bytes_left) {
1610 *bss_info += *bytes_left;
1611 *bytes_left = 0;
1612 return -EFAULT;
1613 }
1614
1615 /* Initialize the current working beacon pointer for this BSS
1616 * iteration
1617 */
1618 current_ptr = *bss_info;
1619
1620 /* Advance the return beacon pointer past the current beacon */
1621 *bss_info += beacon_size;
1622 *bytes_left -= beacon_size;
1623
1624 curr_bcn_bytes = beacon_size;
1625
1626 /* First 5 fields are bssid, RSSI(for legacy scan only),
1627 * time stamp, beacon interval, and capability information
1628 */
1629 if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1630 sizeof(struct mwifiex_fixed_bcn_param)) {
1631 dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
1632 return -EFAULT;
1633 }
1634
1635 memcpy(bssid, current_ptr, ETH_ALEN);
1636 current_ptr += ETH_ALEN;
1637 curr_bcn_bytes -= ETH_ALEN;
1638
1639 if (!ext_scan) {
1640 rssi = (s32) *(u8 *)current_ptr;
1641 rssi = (-rssi) * 100; /* Convert dBm to mBm */
1642 current_ptr += sizeof(u8);
1643 curr_bcn_bytes -= sizeof(u8);
1644 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi);
1645 }
1646
1647 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1648 current_ptr += sizeof(*bcn_param);
1649 curr_bcn_bytes -= sizeof(*bcn_param);
1650
1651 timestamp = le64_to_cpu(bcn_param->timestamp);
1652 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1653
1654 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1655 dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1656 cap_info_bitmap);
1657
1658 /* Rest of the current buffer are IE's */
1659 ie_buf = current_ptr;
1660 ie_len = curr_bcn_bytes;
1661 dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n",
1662 curr_bcn_bytes);
1663
1664 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1665 u8 element_id, element_len;
1666
1667 element_id = *current_ptr;
1668 element_len = *(current_ptr + 1);
1669 if (curr_bcn_bytes < element_len +
1670 sizeof(struct ieee_types_header)) {
1671 dev_err(adapter->dev,
1672 "%s: bytes left < IE length\n", __func__);
1673 return -EFAULT;
1674 }
1675 if (element_id == WLAN_EID_DS_PARAMS) {
1676 channel = *(current_ptr +
1677 sizeof(struct ieee_types_header));
1678 break;
1679 }
1680
1681 current_ptr += element_len + sizeof(struct ieee_types_header);
1682 curr_bcn_bytes -= element_len +
1683 sizeof(struct ieee_types_header);
1684 }
1685
1686 if (channel) {
1687 struct ieee80211_channel *chan;
1688 u8 band;
1689
1690 /* Skip entry if on csa closed channel */
1691 if (channel == priv->csa_chan) {
1692 dev_dbg(adapter->dev,
1693 "Dropping entry on csa closed channel\n");
1694 return 0;
1695 }
1696
1697 band = BAND_G;
1698 if (radio_type)
1699 band = mwifiex_radio_type_to_band(*radio_type &
1700 (BIT(0) | BIT(1)));
1701
1702 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1703
1704 freq = cfp ? cfp->freq : 0;
1705
1706 chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
1707
1708 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1709 bss = cfg80211_inform_bss(priv->wdev->wiphy,
1710 chan, bssid, timestamp,
1711 cap_info_bitmap, beacon_period,
1712 ie_buf, ie_len, rssi, GFP_KERNEL);
1713 bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1714 bss_priv->band = band;
1715 bss_priv->fw_tsf = fw_tsf;
1716 if (priv->media_connected &&
1717 !memcmp(bssid, priv->curr_bss_params.bss_descriptor
1718 .mac_address, ETH_ALEN))
1719 mwifiex_update_curr_bss_params(priv, bss);
1720 cfg80211_put_bss(priv->wdev->wiphy, bss);
1721 }
1722 } else {
1723 dev_dbg(adapter->dev, "missing BSS channel IE\n");
1724 }
1725
1726 return 0;
1727}
1728
1579/* 1729/*
1580 * This function handles the command response of scan. 1730 * This function handles the command response of scan.
1581 * 1731 *
@@ -1609,12 +1759,12 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1609 u32 bytes_left; 1759 u32 bytes_left;
1610 u32 idx; 1760 u32 idx;
1611 u32 tlv_buf_size; 1761 u32 tlv_buf_size;
1612 struct mwifiex_chan_freq_power *cfp;
1613 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; 1762 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
1614 struct chan_band_param_set *chan_band; 1763 struct chan_band_param_set *chan_band;
1615 u8 is_bgscan_resp; 1764 u8 is_bgscan_resp;
1616 unsigned long flags; 1765 unsigned long flags;
1617 struct cfg80211_bss *bss; 1766 __le64 fw_tsf = 0;
1767 u8 *radio_type;
1618 1768
1619 is_bgscan_resp = (le16_to_cpu(resp->command) 1769 is_bgscan_resp = (le16_to_cpu(resp->command)
1620 == HostCmd_CMD_802_11_BG_SCAN_QUERY); 1770 == HostCmd_CMD_802_11_BG_SCAN_QUERY);
@@ -1676,107 +1826,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1676 &chan_band_tlv); 1826 &chan_band_tlv);
1677 1827
1678 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { 1828 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
1679 u8 bssid[ETH_ALEN];
1680 s32 rssi;
1681 const u8 *ie_buf;
1682 size_t ie_len;
1683 u16 channel = 0;
1684 __le64 fw_tsf = 0;
1685 u16 beacon_size = 0;
1686 u32 curr_bcn_bytes;
1687 u32 freq;
1688 u16 beacon_period;
1689 u16 cap_info_bitmap;
1690 u8 *current_ptr;
1691 u64 timestamp;
1692 struct mwifiex_fixed_bcn_param *bcn_param;
1693 struct mwifiex_bss_priv *bss_priv;
1694
1695 if (bytes_left >= sizeof(beacon_size)) {
1696 /* Extract & convert beacon size from command buffer */
1697 memcpy(&beacon_size, bss_info, sizeof(beacon_size));
1698 bytes_left -= sizeof(beacon_size);
1699 bss_info += sizeof(beacon_size);
1700 }
1701
1702 if (!beacon_size || beacon_size > bytes_left) {
1703 bss_info += bytes_left;
1704 bytes_left = 0;
1705 ret = -1;
1706 goto check_next_scan;
1707 }
1708
1709 /* Initialize the current working beacon pointer for this BSS
1710 * iteration */
1711 current_ptr = bss_info;
1712
1713 /* Advance the return beacon pointer past the current beacon */
1714 bss_info += beacon_size;
1715 bytes_left -= beacon_size;
1716
1717 curr_bcn_bytes = beacon_size;
1718
1719 /* First 5 fields are bssid, RSSI(for legacy scan only),
1720 * time stamp, beacon interval, and capability information
1721 */
1722 if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
1723 sizeof(struct mwifiex_fixed_bcn_param)) {
1724 dev_err(adapter->dev,
1725 "InterpretIE: not enough bytes left\n");
1726 continue;
1727 }
1728
1729 memcpy(bssid, current_ptr, ETH_ALEN);
1730 current_ptr += ETH_ALEN;
1731 curr_bcn_bytes -= ETH_ALEN;
1732
1733 rssi = (s32) *(u8 *)current_ptr;
1734 rssi = (-rssi) * 100; /* Convert dBm to mBm */
1735 current_ptr += sizeof(u8);
1736 curr_bcn_bytes -= sizeof(u8);
1737 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi);
1738
1739 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
1740 current_ptr += sizeof(*bcn_param);
1741 curr_bcn_bytes -= sizeof(*bcn_param);
1742
1743 timestamp = le64_to_cpu(bcn_param->timestamp);
1744 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1745
1746 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1747 dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1748 cap_info_bitmap);
1749
1750 /* Rest of the current buffer are IE's */
1751 ie_buf = current_ptr;
1752 ie_len = curr_bcn_bytes;
1753 dev_dbg(adapter->dev,
1754 "info: InterpretIE: IELength for this AP = %d\n",
1755 curr_bcn_bytes);
1756
1757 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1758 u8 element_id, element_len;
1759
1760 element_id = *current_ptr;
1761 element_len = *(current_ptr + 1);
1762 if (curr_bcn_bytes < element_len +
1763 sizeof(struct ieee_types_header)) {
1764 dev_err(priv->adapter->dev,
1765 "%s: bytes left < IE length\n",
1766 __func__);
1767 goto check_next_scan;
1768 }
1769 if (element_id == WLAN_EID_DS_PARAMS) {
1770 channel = *(current_ptr + sizeof(struct ieee_types_header));
1771 break;
1772 }
1773
1774 current_ptr += element_len +
1775 sizeof(struct ieee_types_header);
1776 curr_bcn_bytes -= element_len +
1777 sizeof(struct ieee_types_header);
1778 }
1779
1780 /* 1829 /*
1781 * If the TSF TLV was appended to the scan results, save this 1830 * If the TSF TLV was appended to the scan results, save this
1782 * entry's TSF value in the fw_tsf field. It is the firmware's 1831 * entry's TSF value in the fw_tsf field. It is the firmware's
@@ -1787,51 +1836,19 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1787 memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], 1836 memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
1788 sizeof(fw_tsf)); 1837 sizeof(fw_tsf));
1789 1838
1790 if (channel) { 1839 if (chan_band_tlv) {
1791 struct ieee80211_channel *chan; 1840 chan_band = &chan_band_tlv->chan_band_param[idx];
1792 u8 band; 1841 radio_type = &chan_band->radio_type;
1793
1794 /* Skip entry if on csa closed channel */
1795 if (channel == priv->csa_chan) {
1796 dev_dbg(adapter->dev,
1797 "Dropping entry on csa closed channel\n");
1798 continue;
1799 }
1800
1801 band = BAND_G;
1802 if (chan_band_tlv) {
1803 chan_band =
1804 &chan_band_tlv->chan_band_param[idx];
1805 band = mwifiex_radio_type_to_band(
1806 chan_band->radio_type
1807 & (BIT(0) | BIT(1)));
1808 }
1809
1810 cfp = mwifiex_get_cfp(priv, band, channel, 0);
1811
1812 freq = cfp ? cfp->freq : 0;
1813
1814 chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
1815
1816 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
1817 bss = cfg80211_inform_bss(priv->wdev->wiphy,
1818 chan, bssid, timestamp,
1819 cap_info_bitmap, beacon_period,
1820 ie_buf, ie_len, rssi, GFP_KERNEL);
1821 bss_priv = (struct mwifiex_bss_priv *)bss->priv;
1822 bss_priv->band = band;
1823 bss_priv->fw_tsf = le64_to_cpu(fw_tsf);
1824 if (priv->media_connected &&
1825 !memcmp(bssid,
1826 priv->curr_bss_params.bss_descriptor
1827 .mac_address, ETH_ALEN))
1828 mwifiex_update_curr_bss_params(priv,
1829 bss);
1830 cfg80211_put_bss(priv->wdev->wiphy, bss);
1831 }
1832 } else { 1842 } else {
1833 dev_dbg(adapter->dev, "missing BSS channel IE\n"); 1843 radio_type = NULL;
1834 } 1844 }
1845
1846 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
1847 &bytes_left,
1848 le64_to_cpu(fw_tsf),
1849 radio_type, false);
1850 if (ret)
1851 goto check_next_scan;
1835 } 1852 }
1836 1853
1837check_next_scan: 1854check_next_scan: