diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2009-10-22 14:20:32 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-04 18:44:46 -0500 |
commit | a43c49a817f31ce1accc029239827b108319ecf9 (patch) | |
tree | 416a27b9f2af33b3f98173c6b189b0bbc47a71be /drivers | |
parent | 5dfd3e2c6fb69cf4295ec139107f4ebd3f7fbff0 (diff) |
mwl8k: add support for enabling hardware sniffer mode
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 75c9261abad8..94cbf93a8bf5 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -173,6 +173,7 @@ struct mwl8k_priv { | |||
173 | 173 | ||
174 | bool radio_on; | 174 | bool radio_on; |
175 | bool radio_short_preamble; | 175 | bool radio_short_preamble; |
176 | bool sniffer_enabled; | ||
176 | bool wmm_enabled; | 177 | bool wmm_enabled; |
177 | 178 | ||
178 | /* XXX need to convert this to handle multiple interfaces */ | 179 | /* XXX need to convert this to handle multiple interfaces */ |
@@ -2560,6 +2561,18 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2560 | if (conf->type != NL80211_IFTYPE_STATION) | 2561 | if (conf->type != NL80211_IFTYPE_STATION) |
2561 | return -EINVAL; | 2562 | return -EINVAL; |
2562 | 2563 | ||
2564 | /* | ||
2565 | * Reject interface creation if sniffer mode is active, as | ||
2566 | * STA operation is mutually exclusive with hardware sniffer | ||
2567 | * mode. | ||
2568 | */ | ||
2569 | if (priv->sniffer_enabled) { | ||
2570 | printk(KERN_INFO "%s: unable to create STA " | ||
2571 | "interface due to sniffer mode being enabled\n", | ||
2572 | wiphy_name(hw->wiphy)); | ||
2573 | return -EINVAL; | ||
2574 | } | ||
2575 | |||
2563 | /* Clean out driver private area */ | 2576 | /* Clean out driver private area */ |
2564 | mwl8k_vif = MWL8K_VIF(conf->vif); | 2577 | mwl8k_vif = MWL8K_VIF(conf->vif); |
2565 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); | 2578 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); |
@@ -2730,13 +2743,56 @@ static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, | |||
2730 | return (unsigned long)cmd; | 2743 | return (unsigned long)cmd; |
2731 | } | 2744 | } |
2732 | 2745 | ||
2746 | static int | ||
2747 | mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, | ||
2748 | unsigned int changed_flags, | ||
2749 | unsigned int *total_flags) | ||
2750 | { | ||
2751 | struct mwl8k_priv *priv = hw->priv; | ||
2752 | |||
2753 | /* | ||
2754 | * Hardware sniffer mode is mutually exclusive with STA | ||
2755 | * operation, so refuse to enable sniffer mode if a STA | ||
2756 | * interface is active. | ||
2757 | */ | ||
2758 | if (priv->vif != NULL) { | ||
2759 | if (net_ratelimit()) | ||
2760 | printk(KERN_INFO "%s: not enabling sniffer " | ||
2761 | "mode because STA interface is active\n", | ||
2762 | wiphy_name(hw->wiphy)); | ||
2763 | return 0; | ||
2764 | } | ||
2765 | |||
2766 | if (!priv->sniffer_enabled) { | ||
2767 | if (mwl8k_enable_sniffer(hw, 1)) | ||
2768 | return 0; | ||
2769 | priv->sniffer_enabled = true; | ||
2770 | } | ||
2771 | |||
2772 | *total_flags &= FIF_PROMISC_IN_BSS | FIF_ALLMULTI | | ||
2773 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL | | ||
2774 | FIF_OTHER_BSS; | ||
2775 | |||
2776 | return 1; | ||
2777 | } | ||
2778 | |||
2733 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, | 2779 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, |
2734 | unsigned int changed_flags, | 2780 | unsigned int changed_flags, |
2735 | unsigned int *total_flags, | 2781 | unsigned int *total_flags, |
2736 | u64 multicast) | 2782 | u64 multicast) |
2737 | { | 2783 | { |
2738 | struct mwl8k_priv *priv = hw->priv; | 2784 | struct mwl8k_priv *priv = hw->priv; |
2739 | struct mwl8k_cmd_pkt *cmd; | 2785 | struct mwl8k_cmd_pkt *cmd = (void *)(unsigned long)multicast; |
2786 | |||
2787 | /* | ||
2788 | * Enable hardware sniffer mode if FIF_CONTROL or | ||
2789 | * FIF_OTHER_BSS is requested. | ||
2790 | */ | ||
2791 | if (*total_flags & (FIF_CONTROL | FIF_OTHER_BSS) && | ||
2792 | mwl8k_configure_filter_sniffer(hw, changed_flags, total_flags)) { | ||
2793 | kfree(cmd); | ||
2794 | return; | ||
2795 | } | ||
2740 | 2796 | ||
2741 | /* Clear unsupported feature flags */ | 2797 | /* Clear unsupported feature flags */ |
2742 | *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; | 2798 | *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; |
@@ -2744,6 +2800,11 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
2744 | if (mwl8k_fw_lock(hw)) | 2800 | if (mwl8k_fw_lock(hw)) |
2745 | return; | 2801 | return; |
2746 | 2802 | ||
2803 | if (priv->sniffer_enabled) { | ||
2804 | mwl8k_enable_sniffer(hw, 0); | ||
2805 | priv->sniffer_enabled = false; | ||
2806 | } | ||
2807 | |||
2747 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | 2808 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { |
2748 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { | 2809 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { |
2749 | /* | 2810 | /* |
@@ -2769,8 +2830,6 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
2769 | } | 2830 | } |
2770 | } | 2831 | } |
2771 | 2832 | ||
2772 | cmd = (void *)(unsigned long)multicast; | ||
2773 | |||
2774 | /* | 2833 | /* |
2775 | * If FIF_ALLMULTI is being requested, throw away the command | 2834 | * If FIF_ALLMULTI is being requested, throw away the command |
2776 | * packet that ->prepare_multicast() built and replace it with | 2835 | * packet that ->prepare_multicast() built and replace it with |
@@ -2929,6 +2988,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
2929 | priv = hw->priv; | 2988 | priv = hw->priv; |
2930 | priv->hw = hw; | 2989 | priv->hw = hw; |
2931 | priv->pdev = pdev; | 2990 | priv->pdev = pdev; |
2991 | priv->sniffer_enabled = false; | ||
2932 | priv->wmm_enabled = false; | 2992 | priv->wmm_enabled = false; |
2933 | priv->pending_tx_pkts = 0; | 2993 | priv->pending_tx_pkts = 0; |
2934 | 2994 | ||