aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtl818x
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-05-06 16:49:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-05-07 14:57:09 -0400
commitc809e86c11a64488acc85ddf12ece3c9b879ccb6 (patch)
treeb687b263154bc6e0cf84cc35f81bb782c5677192 /drivers/net/wireless/rtl818x
parent51e080deba57437459571f26a3c6f3db03324c4c (diff)
rtl8180: add software-based support for IBSS mode
Device documentation suggests that hardware support for beaconing is available. But I implemented software-based beacon generation as an experiment and it seems better to have that working now rather than waiting for something better to materialize. Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtl818x')
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180.h8
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c82
2 files changed, 80 insertions, 10 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h
index b92d678abc0c..4baf0cf0826f 100644
--- a/drivers/net/wireless/rtl818x/rtl8180.h
+++ b/drivers/net/wireless/rtl818x/rtl8180.h
@@ -55,6 +55,14 @@ struct rtl8180_tx_ring {
55 struct sk_buff_head queue; 55 struct sk_buff_head queue;
56}; 56};
57 57
58struct rtl8180_vif {
59 struct ieee80211_hw *dev;
60
61 /* beaconing */
62 struct delayed_work beacon_work;
63 bool enable_beacon;
64};
65
58struct rtl8180_priv { 66struct rtl8180_priv {
59 /* common between rtl818x drivers */ 67 /* common between rtl818x drivers */
60 struct rtl818x_csr __iomem *map; 68 struct rtl818x_csr __iomem *map;
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 3a214d7507a5..cbdc5cfec90c 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -662,10 +662,59 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
662 rtl8180_free_tx_ring(dev, i); 662 rtl8180_free_tx_ring(dev, i);
663} 663}
664 664
665static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
666{
667 struct rtl8180_priv *priv = dev->priv;
668
669 return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
670 (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
671}
672
673void rtl8180_beacon_work(struct work_struct *work)
674{
675 struct rtl8180_vif *vif_priv =
676 container_of(work, struct rtl8180_vif, beacon_work.work);
677 struct ieee80211_vif *vif =
678 container_of((void *)vif_priv, struct ieee80211_vif, drv_priv);
679 struct ieee80211_hw *dev = vif_priv->dev;
680 struct ieee80211_mgmt *mgmt;
681 struct sk_buff *skb;
682 int err = 0;
683
684 /* don't overflow the tx ring */
685 if (ieee80211_queue_stopped(dev, 0))
686 goto resched;
687
688 /* grab a fresh beacon */
689 skb = ieee80211_beacon_get(dev, vif);
690
691 /*
692 * update beacon timestamp w/ TSF value
693 * TODO: make hardware update beacon timestamp
694 */
695 mgmt = (struct ieee80211_mgmt *)skb->data;
696 mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev));
697
698 /* TODO: use actual beacon queue */
699 skb_set_queue_mapping(skb, 0);
700
701 err = rtl8180_tx(dev, skb);
702 WARN_ON(err);
703
704resched:
705 /*
706 * schedule next beacon
707 * TODO: use hardware support for beacon timing
708 */
709 schedule_delayed_work(&vif_priv->beacon_work,
710 usecs_to_jiffies(1024 * vif->bss_conf.beacon_int));
711}
712
665static int rtl8180_add_interface(struct ieee80211_hw *dev, 713static int rtl8180_add_interface(struct ieee80211_hw *dev,
666 struct ieee80211_vif *vif) 714 struct ieee80211_vif *vif)
667{ 715{
668 struct rtl8180_priv *priv = dev->priv; 716 struct rtl8180_priv *priv = dev->priv;
717 struct rtl8180_vif *vif_priv;
669 718
670 /* 719 /*
671 * We only support one active interface at a time. 720 * We only support one active interface at a time.
@@ -675,6 +724,7 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev,
675 724
676 switch (vif->type) { 725 switch (vif->type) {
677 case NL80211_IFTYPE_STATION: 726 case NL80211_IFTYPE_STATION:
727 case NL80211_IFTYPE_ADHOC:
678 break; 728 break;
679 default: 729 default:
680 return -EOPNOTSUPP; 730 return -EOPNOTSUPP;
@@ -682,6 +732,12 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev,
682 732
683 priv->vif = vif; 733 priv->vif = vif;
684 734
735 /* Initialize driver private area */
736 vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
737 vif_priv->dev = dev;
738 INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8180_beacon_work);
739 vif_priv->enable_beacon = false;
740
685 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); 741 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
686 rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], 742 rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
687 le32_to_cpu(*(__le32 *)vif->addr)); 743 le32_to_cpu(*(__le32 *)vif->addr));
@@ -715,8 +771,11 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
715 u32 changed) 771 u32 changed)
716{ 772{
717 struct rtl8180_priv *priv = dev->priv; 773 struct rtl8180_priv *priv = dev->priv;
774 struct rtl8180_vif *vif_priv;
718 int i; 775 int i;
719 776
777 vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
778
720 if (changed & BSS_CHANGED_BSSID) { 779 if (changed & BSS_CHANGED_BSSID) {
721 for (i = 0; i < ETH_ALEN; i++) 780 for (i = 0; i < ETH_ALEN; i++)
722 rtl818x_iowrite8(priv, &priv->map->BSSID[i], 781 rtl818x_iowrite8(priv, &priv->map->BSSID[i],
@@ -731,7 +790,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
731 } 790 }
732 791
733 if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) 792 if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
734 priv->rf->conf_erp(dev, info); 793 priv->rf->conf_erp(dev, info);
794
795 if (changed & BSS_CHANGED_BEACON_ENABLED)
796 vif_priv->enable_beacon = info->enable_beacon;
797
798 if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) {
799 cancel_delayed_work_sync(&vif_priv->beacon_work);
800 if (vif_priv->enable_beacon)
801 schedule_work(&vif_priv->beacon_work.work);
802 }
735} 803}
736 804
737static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, 805static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count,
@@ -772,14 +840,6 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev,
772 rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); 840 rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf);
773} 841}
774 842
775static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
776{
777 struct rtl8180_priv *priv = dev->priv;
778
779 return rtl818x_ioread32(priv, &priv->map->TSFT[0]) |
780 (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
781}
782
783static const struct ieee80211_ops rtl8180_ops = { 843static const struct ieee80211_ops rtl8180_ops = {
784 .tx = rtl8180_tx, 844 .tx = rtl8180_tx,
785 .start = rtl8180_start, 845 .start = rtl8180_start,
@@ -916,7 +976,9 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
916 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 976 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
917 IEEE80211_HW_RX_INCLUDES_FCS | 977 IEEE80211_HW_RX_INCLUDES_FCS |
918 IEEE80211_HW_SIGNAL_UNSPEC; 978 IEEE80211_HW_SIGNAL_UNSPEC;
919 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 979 dev->vif_data_size = sizeof(struct rtl8180_vif);
980 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
981 BIT(NL80211_IFTYPE_ADHOC);
920 dev->queues = 1; 982 dev->queues = 1;
921 dev->max_signal = 65; 983 dev->max_signal = 65;
922 984