diff options
Diffstat (limited to 'drivers/net/wireless/rtl818x/rtl8180_dev.c')
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180_dev.c | 115 |
1 files changed, 95 insertions, 20 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 2131a442831a..515817de2905 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -188,6 +188,7 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) | |||
188 | info->flags |= IEEE80211_TX_STAT_ACK; | 188 | info->flags |= IEEE80211_TX_STAT_ACK; |
189 | 189 | ||
190 | info->status.rates[0].count = (flags & 0xFF) + 1; | 190 | info->status.rates[0].count = (flags & 0xFF) + 1; |
191 | info->status.rates[1].idx = -1; | ||
191 | 192 | ||
192 | ieee80211_tx_status_irqsafe(dev, skb); | 193 | ieee80211_tx_status_irqsafe(dev, skb); |
193 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | 194 | if (ring->entries - skb_queue_len(&ring->queue) == 2) |
@@ -233,6 +234,7 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | |||
233 | 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) |
234 | { | 235 | { |
235 | 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; | ||
236 | struct rtl8180_priv *priv = dev->priv; | 238 | struct rtl8180_priv *priv = dev->priv; |
237 | struct rtl8180_tx_ring *ring; | 239 | struct rtl8180_tx_ring *ring; |
238 | struct rtl8180_tx_desc *entry; | 240 | struct rtl8180_tx_desc *entry; |
@@ -284,6 +286,14 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
284 | } | 286 | } |
285 | 287 | ||
286 | 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 | |||
287 | idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; | 297 | idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; |
288 | entry = &ring->desc[idx]; | 298 | entry = &ring->desc[idx]; |
289 | 299 | ||
@@ -297,7 +307,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
297 | entry->flags = cpu_to_le32(tx_flags); | 307 | entry->flags = cpu_to_le32(tx_flags); |
298 | __skb_queue_tail(&ring->queue, skb); | 308 | __skb_queue_tail(&ring->queue, skb); |
299 | if (ring->entries - skb_queue_len(&ring->queue) < 2) | 309 | if (ring->entries - skb_queue_len(&ring->queue) < 2) |
300 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); | 310 | ieee80211_stop_queue(dev, prio); |
311 | |||
301 | spin_unlock_irqrestore(&priv->lock, flags); | 312 | spin_unlock_irqrestore(&priv->lock, flags); |
302 | 313 | ||
303 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); | 314 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); |
@@ -652,10 +663,59 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
652 | rtl8180_free_tx_ring(dev, i); | 663 | rtl8180_free_tx_ring(dev, i); |
653 | } | 664 | } |
654 | 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 | |||
655 | static int rtl8180_add_interface(struct ieee80211_hw *dev, | 714 | static int rtl8180_add_interface(struct ieee80211_hw *dev, |
656 | struct ieee80211_vif *vif) | 715 | struct ieee80211_vif *vif) |
657 | { | 716 | { |
658 | struct rtl8180_priv *priv = dev->priv; | 717 | struct rtl8180_priv *priv = dev->priv; |
718 | struct rtl8180_vif *vif_priv; | ||
659 | 719 | ||
660 | /* | 720 | /* |
661 | * We only support one active interface at a time. | 721 | * We only support one active interface at a time. |
@@ -665,6 +725,7 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, | |||
665 | 725 | ||
666 | switch (vif->type) { | 726 | switch (vif->type) { |
667 | case NL80211_IFTYPE_STATION: | 727 | case NL80211_IFTYPE_STATION: |
728 | case NL80211_IFTYPE_ADHOC: | ||
668 | break; | 729 | break; |
669 | default: | 730 | default: |
670 | return -EOPNOTSUPP; | 731 | return -EOPNOTSUPP; |
@@ -672,6 +733,12 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, | |||
672 | 733 | ||
673 | priv->vif = vif; | 734 | priv->vif = vif; |
674 | 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 | |||
675 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 742 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
676 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], | 743 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], |
677 | le32_to_cpu(*(__le32 *)vif->addr)); | 744 | le32_to_cpu(*(__le32 *)vif->addr)); |
@@ -705,8 +772,11 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
705 | u32 changed) | 772 | u32 changed) |
706 | { | 773 | { |
707 | struct rtl8180_priv *priv = dev->priv; | 774 | struct rtl8180_priv *priv = dev->priv; |
775 | struct rtl8180_vif *vif_priv; | ||
708 | int i; | 776 | int i; |
709 | 777 | ||
778 | vif_priv = (struct rtl8180_vif *)&vif->drv_priv; | ||
779 | |||
710 | if (changed & BSS_CHANGED_BSSID) { | 780 | if (changed & BSS_CHANGED_BSSID) { |
711 | for (i = 0; i < ETH_ALEN; i++) | 781 | for (i = 0; i < ETH_ALEN; i++) |
712 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], | 782 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], |
@@ -721,13 +791,22 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
721 | } | 791 | } |
722 | 792 | ||
723 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) | 793 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) |
724 | 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 | } | ||
725 | } | 804 | } |
726 | 805 | ||
727 | static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, | 806 | static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, |
728 | struct dev_addr_list *mc_list) | 807 | struct netdev_hw_addr_list *mc_list) |
729 | { | 808 | { |
730 | return mc_count; | 809 | return netdev_hw_addr_list_count(mc_list); |
731 | } | 810 | } |
732 | 811 | ||
733 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, | 812 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, |
@@ -762,14 +841,6 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, | |||
762 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); | 841 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); |
763 | } | 842 | } |
764 | 843 | ||
765 | static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) | ||
766 | { | ||
767 | struct rtl8180_priv *priv = dev->priv; | ||
768 | |||
769 | return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | | ||
770 | (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; | ||
771 | } | ||
772 | |||
773 | static const struct ieee80211_ops rtl8180_ops = { | 844 | static const struct ieee80211_ops rtl8180_ops = { |
774 | .tx = rtl8180_tx, | 845 | .tx = rtl8180_tx, |
775 | .start = rtl8180_start, | 846 | .start = rtl8180_start, |
@@ -827,6 +898,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
827 | const char *chip_name, *rf_name = NULL; | 898 | const char *chip_name, *rf_name = NULL; |
828 | u32 reg; | 899 | u32 reg; |
829 | u16 eeprom_val; | 900 | u16 eeprom_val; |
901 | u8 mac_addr[ETH_ALEN]; | ||
830 | 902 | ||
831 | err = pci_enable_device(pdev); | 903 | err = pci_enable_device(pdev); |
832 | if (err) { | 904 | if (err) { |
@@ -855,8 +927,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
855 | goto err_free_reg; | 927 | goto err_free_reg; |
856 | } | 928 | } |
857 | 929 | ||
858 | if ((err = pci_set_dma_mask(pdev, 0xFFFFFF00ULL)) || | 930 | if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) || |
859 | (err = pci_set_consistent_dma_mask(pdev, 0xFFFFFF00ULL))) { | 931 | (err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))) { |
860 | printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", | 932 | printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", |
861 | pci_name(pdev)); | 933 | pci_name(pdev)); |
862 | goto err_free_reg; | 934 | goto err_free_reg; |
@@ -905,7 +977,9 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
905 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 977 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
906 | IEEE80211_HW_RX_INCLUDES_FCS | | 978 | IEEE80211_HW_RX_INCLUDES_FCS | |
907 | IEEE80211_HW_SIGNAL_UNSPEC; | 979 | IEEE80211_HW_SIGNAL_UNSPEC; |
908 | 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); | ||
909 | dev->queues = 1; | 983 | dev->queues = 1; |
910 | dev->max_signal = 65; | 984 | dev->max_signal = 65; |
911 | 985 | ||
@@ -987,12 +1061,13 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
987 | eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); | 1061 | eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); |
988 | } | 1062 | } |
989 | 1063 | ||
990 | eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)dev->wiphy->perm_addr, 3); | 1064 | eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)mac_addr, 3); |
991 | if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { | 1065 | if (!is_valid_ether_addr(mac_addr)) { |
992 | printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" | 1066 | printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" |
993 | " randomly generated MAC addr\n", pci_name(pdev)); | 1067 | " randomly generated MAC addr\n", pci_name(pdev)); |
994 | random_ether_addr(dev->wiphy->perm_addr); | 1068 | random_ether_addr(mac_addr); |
995 | } | 1069 | } |
1070 | SET_IEEE80211_PERM_ADDR(dev, mac_addr); | ||
996 | 1071 | ||
997 | /* CCK TX power */ | 1072 | /* CCK TX power */ |
998 | for (i = 0; i < 14; i += 2) { | 1073 | for (i = 0; i < 14; i += 2) { |
@@ -1024,7 +1099,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
1024 | } | 1099 | } |
1025 | 1100 | ||
1026 | printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n", | 1101 | printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n", |
1027 | wiphy_name(dev->wiphy), dev->wiphy->perm_addr, | 1102 | wiphy_name(dev->wiphy), mac_addr, |
1028 | chip_name, priv->rf->name); | 1103 | chip_name, priv->rf->name); |
1029 | 1104 | ||
1030 | return 0; | 1105 | return 0; |