diff options
Diffstat (limited to 'drivers/net/wireless/rtl818x/rtl8180/dev.c')
| -rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180/dev.c | 91 | 
1 files changed, 62 insertions, 29 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 2c1c02bafa10..026d912f516b 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -16,6 +16,7 @@   *   * based also on:   *  - portions of rtl8187se Linux staging driver, Copyright Realtek corp. + *    (available in drivers/staging/rtl8187se directory of Linux 3.14)   *  - other GPL, unpublished (until now), Linux driver code,   *    Copyright Larry Finger <Larry.Finger@lwfinger.net>   * @@ -63,7 +64,7 @@ MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>");  MODULE_DESCRIPTION("RTL8180 / RTL8185 / RTL8187SE PCI wireless driver");  MODULE_LICENSE("GPL"); -static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = { +static const struct pci_device_id rtl8180_table[] = {  	/* rtl8187se */  	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8199) }, @@ -209,7 +210,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)  	struct rtl8180_priv *priv = dev->priv;  	struct rtl818x_rx_cmd_desc *cmd_desc;  	unsigned int count = 32; -	u8 signal, agc, sq; +	u8 agc, sq, signal = 1;  	dma_addr_t mapping;  	while (count--) { @@ -222,12 +223,20 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)  			struct rtl8187se_rx_desc *desc = entry;  			flags = le32_to_cpu(desc->flags); +			/* if ownership flag is set, then we can trust the +			 * HW has written other fields. We must not trust +			 * other descriptor data read before we checked (read) +			 * the ownership flag +			 */ +			rmb();  			flags2 = le32_to_cpu(desc->flags2);  			tsft = le64_to_cpu(desc->tsft);  		} else {  			struct rtl8180_rx_desc *desc = entry;  			flags = le32_to_cpu(desc->flags); +			/* same as above */ +			rmb();  			flags2 = le32_to_cpu(desc->flags2);  			tsft = le64_to_cpu(desc->tsft);  		} @@ -266,18 +275,21 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)  			rx_status.rate_idx = (flags >> 20) & 0xF;  			agc = (flags2 >> 17) & 0x7F; -			if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { +			switch (priv->chip_family) { +			case RTL818X_CHIP_FAMILY_RTL8185:  				if (rx_status.rate_idx > 3) -					signal = 90 - clamp_t(u8, agc, 25, 90); +					signal = -clamp_t(u8, agc, 25, 90) - 9;  				else -					signal = 95 - clamp_t(u8, agc, 30, 95); -			} else if (priv->chip_family == -				   RTL818X_CHIP_FAMILY_RTL8180) { +					signal = -clamp_t(u8, agc, 30, 95); +				break; +			case RTL818X_CHIP_FAMILY_RTL8180:  				sq = flags2 & 0xff;  				signal = priv->rf->calc_rssi(agc, sq); -			} else { +				break; +			case RTL818X_CHIP_FAMILY_RTL8187SE:  				/* TODO: rtl8187se rssi */  				signal = 10; +				break;  			}  			rx_status.signal = signal;  			rx_status.freq = dev->conf.chandef.chan->center_freq; @@ -336,7 +348,6 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)  			info->flags |= IEEE80211_TX_STAT_ACK;  		info->status.rates[0].count = (flags & 0xFF) + 1; -		info->status.rates[1].idx = -1;  		ieee80211_tx_status_irqsafe(dev, skb);  		if (ring->entries - skb_queue_len(&ring->queue) == 2) @@ -528,9 +539,7 @@ static void rtl8180_tx(struct ieee80211_hw *dev,  	entry->plcp_len = cpu_to_le16(plcp_len);  	entry->tx_buf = cpu_to_le32(mapping); -	entry->flags2 = info->control.rates[1].idx >= 0 ? -		ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; -	entry->retry_limit = info->control.rates[0].count; +	entry->retry_limit = info->control.rates[0].count - 1;  	/* We must be sure that tx_flags is written last because the HW  	 * looks at it to check if the rest of data is valid or not @@ -852,7 +861,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)  	if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) {  		rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); -		rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); +		rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0);  	} else {  		rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); @@ -868,6 +877,16 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)  		reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);  		rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2));  		rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); +		/* fix eccessive IFS after CTS-to-self */ +		if (priv->map_pio) { +			u8 reg; + +			reg = rtl818x_ioread8(priv, &priv->map->PGSELECT); +			rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); +			rtl818x_iowrite8(priv, REG_ADDR1(0xff), 0x35); +			rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); +		} else +			rtl818x_iowrite8(priv, REG_ADDR1(0x1ff), 0x35);  	}  	if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { @@ -953,16 +972,13 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)  	else  		priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc); -	priv->rx_ring = pci_alloc_consistent(priv->pdev, -					     priv->rx_ring_sz * 32, -					     &priv->rx_ring_dma); - +	priv->rx_ring = pci_zalloc_consistent(priv->pdev, priv->rx_ring_sz * 32, +					      &priv->rx_ring_dma);  	if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {  		wiphy_err(dev->wiphy, "Cannot allocate RX ring\n");  		return -ENOMEM;  	} -	memset(priv->rx_ring, 0, priv->rx_ring_sz * 32);  	priv->rx_idx = 0;  	for (i = 0; i < 32; i++) { @@ -1021,14 +1037,14 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev,  	dma_addr_t dma;  	int i; -	ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); +	ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, +				     &dma);  	if (!ring || (unsigned long)ring & 0xFF) {  		wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n",  			  prio);  		return -ENOMEM;  	} -	memset(ring, 0, sizeof(*ring)*entries);  	priv->tx_ring[prio].desc = ring;  	priv->tx_ring[prio].dma = dma;  	priv->tx_ring[prio].idx = 0; @@ -1450,9 +1466,10 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,  	vif_priv = (struct rtl8180_vif *)&vif->drv_priv;  	if (changed & BSS_CHANGED_BSSID) { -		for (i = 0; i < ETH_ALEN; i++) -			rtl818x_iowrite8(priv, &priv->map->BSSID[i], -					 info->bssid[i]); +		rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->BSSID[0], +				  le16_to_cpu(*(__le16 *)info->bssid)); +		rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->BSSID[2], +				  le32_to_cpu(*(__le32 *)(info->bssid + 2)));  		if (is_valid_ether_addr(info->bssid)) {  			if (vif->type == NL80211_IFTYPE_ADHOC) @@ -1723,17 +1740,20 @@ static int rtl8180_probe(struct pci_dev *pdev,  	priv = dev->priv;  	priv->pdev = pdev; -	dev->max_rates = 2; +	dev->max_rates = 1;  	SET_IEEE80211_DEV(dev, &pdev->dev);  	pci_set_drvdata(pdev, dev); +	priv->map_pio = false;  	priv->map = pci_iomap(pdev, 1, mem_len); -	if (!priv->map) +	if (!priv->map) {  		priv->map = pci_iomap(pdev, 0, io_len); +		priv->map_pio = true; +	}  	if (!priv->map) { -		printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n", -		       pci_name(pdev)); +		dev_err(&pdev->dev, "Cannot map device memory/PIO\n"); +		err = -ENOMEM;  		goto err_free_dev;  	} @@ -1751,8 +1771,7 @@ static int rtl8180_probe(struct pci_dev *pdev,  	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;  	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | -		     IEEE80211_HW_RX_INCLUDES_FCS | -		     IEEE80211_HW_SIGNAL_UNSPEC; +		IEEE80211_HW_RX_INCLUDES_FCS;  	dev->vif_data_size = sizeof(struct rtl8180_vif);  	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |  					BIT(NL80211_IFTYPE_ADHOC); @@ -1783,12 +1802,19 @@ static int rtl8180_probe(struct pci_dev *pdev,  	case RTL818X_TX_CONF_RTL8187SE:  		chip_name = "RTL8187SE"; +		if (priv->map_pio) { +			dev_err(&pdev->dev, +				"MMIO failed. PIO not supported on RTL8187SE\n"); +			err = -ENOMEM; +			goto err_iounmap; +		}  		priv->chip_family = RTL818X_CHIP_FAMILY_RTL8187SE;  		break;  	default:  		printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n",  		       pci_name(pdev), reg >> 25); +		err = -ENODEV;  		goto err_iounmap;  	} @@ -1809,6 +1835,11 @@ static int rtl8180_probe(struct pci_dev *pdev,  		pci_try_set_mwi(pdev);  	} +	if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) +		dev->flags |= IEEE80211_HW_SIGNAL_DBM; +	else +		dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC; +  	rtl8180_eeprom_read(priv);  	switch (priv->rf_type) { @@ -1834,12 +1865,14 @@ static int rtl8180_probe(struct pci_dev *pdev,  	default:  		printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n",  		       pci_name(pdev), priv->rf_type); +		err = -ENODEV;  		goto err_iounmap;  	}  	if (!priv->rf) {  		printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n",  		       pci_name(pdev), rf_name); +		err = -ENODEV;  		goto err_iounmap;  	}  | 
