aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54common.c
diff options
context:
space:
mode:
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