aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54common.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-17 01:29:23 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:57 -0400
commit4150c57212ad134765dd78c654a4b9906252b66d (patch)
treec37ab7a3f75532a623ed00339782d769514422d2 /drivers/net/wireless/p54common.c
parent070ac3a2651e3c1c4d277c5f1981517427c386a7 (diff)
[PATCH] mac80211: revamp interface and filter configuration
Drivers are currently supposed to keep track of monitor interfaces if they allow so-called "hard" monitor, and they are also supposed to keep track of multicast etc. This patch changes that, replaces the set_multicast_list() callback with a new configure_filter() callback that takes filter flags (FIF_*) instead of interface flags (IFF_*). For a driver, this means it should open the filter as much as necessary to get all frames requested by the filter flags. Accordingly, the filter flags are named "positively", e.g. FIF_ALLMULTI. Multicast filtering is a bit special in that drivers that have no multicast address filters need to allow multicast frames through when either the FIF_ALLMULTI flag is set or when the mc_count value is positive. At the same time, drivers are no longer notified about monitor interfaces at all, this means they now need to implement the start() and stop() callbacks and the new change_filter_flags() callback. Also, the start()/stop() ordering changed, start() is now called *before* any add_interface() as it really should be, and stop() after any remove_interface(). The patch also changes the behaviour of setting the bssid to multicast for scanning when IEEE80211_HW_NO_PROBE_FILTERING is set; the IEEE80211_HW_NO_PROBE_FILTERING flag is removed and the filter flag FIF_BCN_PRBRESP_PROMISC introduced. This is a lot more efficient for hardware like b43 that supports it and other hardware can still set the BSSID to all-ones. Driver modifications by Johannes Berg (b43 & iwlwifi), Michael Wu (rtl8187, adm8211, and p54), Larry Finger (b43legacy), and Ivo van Doorn (rt2x00). Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54common.c')
-rw-r--r--drivers/net/wireless/p54common.c80
1 files changed, 58 insertions, 22 deletions
diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c
index b05b5c5b4c04..9befd6cc7911 100644
--- a/drivers/net/wireless/p54common.c
+++ b/drivers/net/wireless/p54common.c
@@ -774,15 +774,39 @@ static void p54_set_vdcf(struct ieee80211_hw *dev)
774 priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0); 774 priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
775} 775}
776 776
777static int p54_start(struct ieee80211_hw *dev)
778{
779 struct p54_common *priv = dev->priv;
780 int err;
781
782 err = priv->open(dev);
783 if (!err)
784 priv->mode = IEEE80211_IF_TYPE_MNTR;
785
786 return err;
787}
788
789static void p54_stop(struct ieee80211_hw *dev)
790{
791 struct p54_common *priv = dev->priv;
792 struct sk_buff *skb;
793 while ((skb = skb_dequeue(&priv->tx_queue))) {
794 struct memrecord *range = (struct memrecord *)&skb->cb;
795 if (range->control)
796 kfree(range->control);
797 kfree_skb(skb);
798 }
799 priv->stop(dev);
800 priv->mode = IEEE80211_IF_TYPE_MGMT;
801}
802
777static int p54_add_interface(struct ieee80211_hw *dev, 803static int p54_add_interface(struct ieee80211_hw *dev,
778 struct ieee80211_if_init_conf *conf) 804 struct ieee80211_if_init_conf *conf)
779{ 805{
780 struct p54_common *priv = dev->priv; 806 struct p54_common *priv = dev->priv;
781 int err;
782 807
783 /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */ 808 if (priv->mode != IEEE80211_IF_TYPE_MNTR)
784 if (priv->mode != IEEE80211_IF_TYPE_MGMT) 809 return -EOPNOTSUPP;
785 return -1;
786 810
787 switch (conf->type) { 811 switch (conf->type) {
788 case IEEE80211_IF_TYPE_STA: 812 case IEEE80211_IF_TYPE_STA:
@@ -792,23 +816,18 @@ static int p54_add_interface(struct ieee80211_hw *dev,
792 return -EOPNOTSUPP; 816 return -EOPNOTSUPP;
793 } 817 }
794 818
795 priv->mac_addr = conf->mac_addr; 819 memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
796
797 err = priv->open(dev);
798 if (err) {
799 priv->mode = IEEE80211_IF_TYPE_MGMT;
800 skb_queue_purge(&priv->tx_queue);
801 return err;
802 }
803 820
804 p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642); 821 p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
805 p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642); 822 p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
806 p54_set_vdcf(dev);
807 823
808 switch (conf->type) { 824 switch (conf->type) {
809 case IEEE80211_IF_TYPE_STA: 825 case IEEE80211_IF_TYPE_STA:
810 p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0); 826 p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
811 break; 827 break;
828 default:
829 BUG(); /* impossible */
830 break;
812 } 831 }
813 832
814 p54_set_leds(dev, 1, 0, 0); 833 p54_set_leds(dev, 1, 0, 0);
@@ -820,15 +839,9 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
820 struct ieee80211_if_init_conf *conf) 839 struct ieee80211_if_init_conf *conf)
821{ 840{
822 struct p54_common *priv = dev->priv; 841 struct p54_common *priv = dev->priv;
823 struct sk_buff *skb; 842 priv->mode = IEEE80211_IF_TYPE_MNTR;
824 while ((skb = skb_dequeue(&priv->tx_queue))) { 843 memset(priv->mac_addr, 0, ETH_ALEN);
825 struct memrecord *range = (struct memrecord *)&skb->cb; 844 p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
826 if (range->control)
827 kfree(range->control);
828 kfree_skb(skb);
829 }
830 priv->mode = IEEE80211_IF_TYPE_MGMT;
831 priv->stop(dev);
832} 845}
833 846
834static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) 847static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
@@ -848,9 +861,29 @@ static int p54_config_interface(struct ieee80211_hw *dev, int if_id,
848 p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642); 861 p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
849 p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0); 862 p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
850 p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); 863 p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
864 memcpy(priv->bssid, conf->bssid, ETH_ALEN);
851 return 0; 865 return 0;
852} 866}
853 867
868static void p54_configure_filter(struct ieee80211_hw *dev,
869 unsigned int changed_flags,
870 unsigned int *total_flags,
871 int mc_count, struct dev_mc_list *mclist)
872{
873 struct p54_common *priv = dev->priv;
874
875 *total_flags &= FIF_BCN_PRBRESP_PROMISC;
876
877 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
878 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
879 p54_set_filter(dev, 0, priv->mac_addr,
880 NULL, 2, 0, 0, 0);
881 else
882 p54_set_filter(dev, 0, priv->mac_addr,
883 priv->bssid, 2, 0, 0, 0);
884 }
885}
886
854static int p54_conf_tx(struct ieee80211_hw *dev, int queue, 887static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
855 const struct ieee80211_tx_queue_params *params) 888 const struct ieee80211_tx_queue_params *params)
856{ 889{
@@ -893,10 +926,13 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev,
893 926
894static const struct ieee80211_ops p54_ops = { 927static const struct ieee80211_ops p54_ops = {
895 .tx = p54_tx, 928 .tx = p54_tx,
929 .start = p54_start,
930 .stop = p54_stop,
896 .add_interface = p54_add_interface, 931 .add_interface = p54_add_interface,
897 .remove_interface = p54_remove_interface, 932 .remove_interface = p54_remove_interface,
898 .config = p54_config, 933 .config = p54_config,
899 .config_interface = p54_config_interface, 934 .config_interface = p54_config_interface,
935 .configure_filter = p54_configure_filter,
900 .conf_tx = p54_conf_tx, 936 .conf_tx = p54_conf_tx,
901 .get_stats = p54_get_stats, 937 .get_stats = p54_get_stats,
902 .get_tx_stats = p54_get_tx_stats 938 .get_tx_stats = p54_get_tx_stats