diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-05-11 14:24:55 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-05-11 14:24:55 -0400 |
commit | cc755896a4274f11283bca32d1d658203844057a (patch) | |
tree | 218970ece71df99f686b9416b7fd88b921690ebb /drivers/net/wireless/rtl818x | |
parent | d250fe91ae129bff0968e685cc9c466d3a5e3482 (diff) | |
parent | 9459d59fbf0bc82ff4c804679fa8bc22788eca63 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/ath/ar9170/main.c
Diffstat (limited to 'drivers/net/wireless/rtl818x')
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180_dev.c | 96 |
2 files changed, 95 insertions, 12 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index de3844fe06d8..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 | ||
58 | struct rtl8180_vif { | ||
59 | struct ieee80211_hw *dev; | ||
60 | |||
61 | /* beaconing */ | ||
62 | struct delayed_work beacon_work; | ||
63 | bool enable_beacon; | ||
64 | }; | ||
65 | |||
58 | struct rtl8180_priv { | 66 | struct rtl8180_priv { |
59 | /* common between rtl818x drivers */ | 67 | /* common between rtl818x drivers */ |
60 | struct rtl818x_csr __iomem *map; | 68 | struct rtl818x_csr __iomem *map; |
@@ -78,6 +86,9 @@ struct rtl8180_priv { | |||
78 | u32 anaparam; | 86 | u32 anaparam; |
79 | u16 rfparam; | 87 | u16 rfparam; |
80 | u8 csthreshold; | 88 | u8 csthreshold; |
89 | |||
90 | /* sequence # */ | ||
91 | u16 seqno; | ||
81 | }; | 92 | }; |
82 | 93 | ||
83 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); | 94 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 21307f2412b8..515817de2905 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -234,6 +234,7 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | |||
234 | static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | 234 | static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
235 | { | 235 | { |
236 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 236 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
237 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
237 | struct rtl8180_priv *priv = dev->priv; | 238 | struct rtl8180_priv *priv = dev->priv; |
238 | struct rtl8180_tx_ring *ring; | 239 | struct rtl8180_tx_ring *ring; |
239 | struct rtl8180_tx_desc *entry; | 240 | struct rtl8180_tx_desc *entry; |
@@ -285,6 +286,14 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
285 | } | 286 | } |
286 | 287 | ||
287 | spin_lock_irqsave(&priv->lock, flags); | 288 | spin_lock_irqsave(&priv->lock, flags); |
289 | |||
290 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
291 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
292 | priv->seqno += 0x10; | ||
293 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
294 | hdr->seq_ctrl |= cpu_to_le16(priv->seqno); | ||
295 | } | ||
296 | |||
288 | idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; | 297 | idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; |
289 | entry = &ring->desc[idx]; | 298 | entry = &ring->desc[idx]; |
290 | 299 | ||
@@ -299,6 +308,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
299 | __skb_queue_tail(&ring->queue, skb); | 308 | __skb_queue_tail(&ring->queue, skb); |
300 | if (ring->entries - skb_queue_len(&ring->queue) < 2) | 309 | if (ring->entries - skb_queue_len(&ring->queue) < 2) |
301 | ieee80211_stop_queue(dev, prio); | 310 | ieee80211_stop_queue(dev, prio); |
311 | |||
302 | spin_unlock_irqrestore(&priv->lock, flags); | 312 | spin_unlock_irqrestore(&priv->lock, flags); |
303 | 313 | ||
304 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); | 314 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); |
@@ -653,10 +663,59 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
653 | rtl8180_free_tx_ring(dev, i); | 663 | rtl8180_free_tx_ring(dev, i); |
654 | } | 664 | } |
655 | 665 | ||
666 | static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) | ||
667 | { | ||
668 | struct rtl8180_priv *priv = dev->priv; | ||
669 | |||
670 | return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | | ||
671 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; | ||
672 | } | ||
673 | |||
674 | void rtl8180_beacon_work(struct work_struct *work) | ||
675 | { | ||
676 | struct rtl8180_vif *vif_priv = | ||
677 | container_of(work, struct rtl8180_vif, beacon_work.work); | ||
678 | struct ieee80211_vif *vif = | ||
679 | container_of((void *)vif_priv, struct ieee80211_vif, drv_priv); | ||
680 | struct ieee80211_hw *dev = vif_priv->dev; | ||
681 | struct ieee80211_mgmt *mgmt; | ||
682 | struct sk_buff *skb; | ||
683 | int err = 0; | ||
684 | |||
685 | /* don't overflow the tx ring */ | ||
686 | if (ieee80211_queue_stopped(dev, 0)) | ||
687 | goto resched; | ||
688 | |||
689 | /* grab a fresh beacon */ | ||
690 | skb = ieee80211_beacon_get(dev, vif); | ||
691 | |||
692 | /* | ||
693 | * update beacon timestamp w/ TSF value | ||
694 | * TODO: make hardware update beacon timestamp | ||
695 | */ | ||
696 | mgmt = (struct ieee80211_mgmt *)skb->data; | ||
697 | mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev)); | ||
698 | |||
699 | /* TODO: use actual beacon queue */ | ||
700 | skb_set_queue_mapping(skb, 0); | ||
701 | |||
702 | err = rtl8180_tx(dev, skb); | ||
703 | WARN_ON(err); | ||
704 | |||
705 | resched: | ||
706 | /* | ||
707 | * schedule next beacon | ||
708 | * TODO: use hardware support for beacon timing | ||
709 | */ | ||
710 | schedule_delayed_work(&vif_priv->beacon_work, | ||
711 | usecs_to_jiffies(1024 * vif->bss_conf.beacon_int)); | ||
712 | } | ||
713 | |||
656 | static int rtl8180_add_interface(struct ieee80211_hw *dev, | 714 | static int rtl8180_add_interface(struct ieee80211_hw *dev, |
657 | struct ieee80211_vif *vif) | 715 | struct ieee80211_vif *vif) |
658 | { | 716 | { |
659 | struct rtl8180_priv *priv = dev->priv; | 717 | struct rtl8180_priv *priv = dev->priv; |
718 | struct rtl8180_vif *vif_priv; | ||
660 | 719 | ||
661 | /* | 720 | /* |
662 | * We only support one active interface at a time. | 721 | * We only support one active interface at a time. |
@@ -666,6 +725,7 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, | |||
666 | 725 | ||
667 | switch (vif->type) { | 726 | switch (vif->type) { |
668 | case NL80211_IFTYPE_STATION: | 727 | case NL80211_IFTYPE_STATION: |
728 | case NL80211_IFTYPE_ADHOC: | ||
669 | break; | 729 | break; |
670 | default: | 730 | default: |
671 | return -EOPNOTSUPP; | 731 | return -EOPNOTSUPP; |
@@ -673,6 +733,12 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, | |||
673 | 733 | ||
674 | priv->vif = vif; | 734 | priv->vif = vif; |
675 | 735 | ||
736 | /* Initialize driver private area */ | ||
737 | vif_priv = (struct rtl8180_vif *)&vif->drv_priv; | ||
738 | vif_priv->dev = dev; | ||
739 | INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8180_beacon_work); | ||
740 | vif_priv->enable_beacon = false; | ||
741 | |||
676 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 742 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
677 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], | 743 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], |
678 | le32_to_cpu(*(__le32 *)vif->addr)); | 744 | le32_to_cpu(*(__le32 *)vif->addr)); |
@@ -706,8 +772,11 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
706 | u32 changed) | 772 | u32 changed) |
707 | { | 773 | { |
708 | struct rtl8180_priv *priv = dev->priv; | 774 | struct rtl8180_priv *priv = dev->priv; |
775 | struct rtl8180_vif *vif_priv; | ||
709 | int i; | 776 | int i; |
710 | 777 | ||
778 | vif_priv = (struct rtl8180_vif *)&vif->drv_priv; | ||
779 | |||
711 | if (changed & BSS_CHANGED_BSSID) { | 780 | if (changed & BSS_CHANGED_BSSID) { |
712 | for (i = 0; i < ETH_ALEN; i++) | 781 | for (i = 0; i < ETH_ALEN; i++) |
713 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], | 782 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], |
@@ -722,7 +791,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
722 | } | 791 | } |
723 | 792 | ||
724 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) | 793 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) |
725 | priv->rf->conf_erp(dev, info); | 794 | priv->rf->conf_erp(dev, info); |
795 | |||
796 | if (changed & BSS_CHANGED_BEACON_ENABLED) | ||
797 | vif_priv->enable_beacon = info->enable_beacon; | ||
798 | |||
799 | if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) { | ||
800 | cancel_delayed_work_sync(&vif_priv->beacon_work); | ||
801 | if (vif_priv->enable_beacon) | ||
802 | schedule_work(&vif_priv->beacon_work.work); | ||
803 | } | ||
726 | } | 804 | } |
727 | 805 | ||
728 | static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, | 806 | static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, |
@@ -763,14 +841,6 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, | |||
763 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); | 841 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); |
764 | } | 842 | } |
765 | 843 | ||
766 | static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) | ||
767 | { | ||
768 | struct rtl8180_priv *priv = dev->priv; | ||
769 | |||
770 | return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | | ||
771 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; | ||
772 | } | ||
773 | |||
774 | static const struct ieee80211_ops rtl8180_ops = { | 844 | static const struct ieee80211_ops rtl8180_ops = { |
775 | .tx = rtl8180_tx, | 845 | .tx = rtl8180_tx, |
776 | .start = rtl8180_start, | 846 | .start = rtl8180_start, |
@@ -857,8 +927,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
857 | goto err_free_reg; | 927 | goto err_free_reg; |
858 | } | 928 | } |
859 | 929 | ||
860 | if ((err = pci_set_dma_mask(pdev, 0xFFFFFF00ULL)) || | 930 | if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) || |
861 | (err = pci_set_consistent_dma_mask(pdev, 0xFFFFFF00ULL))) { | 931 | (err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))) { |
862 | printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", | 932 | printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", |
863 | pci_name(pdev)); | 933 | pci_name(pdev)); |
864 | goto err_free_reg; | 934 | goto err_free_reg; |
@@ -907,7 +977,9 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
907 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 977 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
908 | IEEE80211_HW_RX_INCLUDES_FCS | | 978 | IEEE80211_HW_RX_INCLUDES_FCS | |
909 | IEEE80211_HW_SIGNAL_UNSPEC; | 979 | IEEE80211_HW_SIGNAL_UNSPEC; |
910 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 980 | dev->vif_data_size = sizeof(struct rtl8180_vif); |
981 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
982 | BIT(NL80211_IFTYPE_ADHOC); | ||
911 | dev->queues = 1; | 983 | dev->queues = 1; |
912 | dev->max_signal = 65; | 984 | dev->max_signal = 65; |
913 | 985 | ||