diff options
Diffstat (limited to 'drivers/net/wireless/p54common.c')
-rw-r--r-- | drivers/net/wireless/p54common.c | 80 |
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 | ||
777 | static 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 | |||
789 | static 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 | |||
777 | static int p54_add_interface(struct ieee80211_hw *dev, | 803 | static 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 | ||
834 | static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) | 847 | static 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 | ||
868 | static 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 | |||
854 | static int p54_conf_tx(struct ieee80211_hw *dev, int queue, | 887 | static 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 | ||
894 | static const struct ieee80211_ops p54_ops = { | 927 | static 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 |