rtl8187: Fix wrong rfkill switch mask for some models
authorLarry Finger <Larry.Finger@lwfinger.net>
Sun, 6 Dec 2009 01:25:22 +0000 (19:25 -0600)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 7 Dec 2009 21:55:00 +0000 (16:55 -0500)
There are different bits used to convey the setting of the rfkill
switch to the driver. The current driver only supports one of these
possibilities. These changes were derived from the latest version
of the vendor driver.

This patch fixes the regression noted in kernel Bugzilla #14743.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Reported-and-tested-by: Antti Kaijanmäki <antti@kaijanmaki.net>
Tested-by: Hin-Tak Leung <hintak.leung@gmail.com>
Cc: Stable <stable@kernel.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rtl818x/rtl8187.h
drivers/net/wireless/rtl818x/rtl8187_dev.c
drivers/net/wireless/rtl818x/rtl8187_rfkill.c

index abb4907cf2960925feeaec25a146b13e7d28e5e2..b1a24de0b7b01a99f2186fb0a421a36e4969aade 100644 (file)
@@ -23,6 +23,7 @@
 #define RTL8187_EEPROM_TXPWR_CHAN_1    0x16    /* 3 channels */
 #define RTL8187_EEPROM_TXPWR_CHAN_6    0x1B    /* 2 channels */
 #define RTL8187_EEPROM_TXPWR_CHAN_4    0x3D    /* 2 channels */
+#define RTL8187_EEPROM_SELECT_GPIO     0x3B
 
 #define RTL8187_REQT_READ      0xC0
 #define RTL8187_REQT_WRITE     0x40
@@ -31,6 +32,9 @@
 
 #define RTL8187_MAX_RX         0x9C4
 
+#define RFKILL_MASK_8187_89_97 0x2
+#define RFKILL_MASK_8198       0x4
+
 struct rtl8187_rx_info {
        struct urb *urb;
        struct ieee80211_hw *dev;
@@ -122,6 +126,7 @@ struct rtl8187_priv {
        u8 noise;
        u8 slot_time;
        u8 aifsn[4];
+       u8 rfkill_mask;
        struct {
                __le64 buf;
                struct sk_buff_head queue;
index 76973b8c7099554f9a0e0bbef6fd3d6032d3321c..bc5726dd5fe49f5fc7582f4a94d6bce4402de7af 100644 (file)
@@ -1322,6 +1322,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
        struct ieee80211_channel *channel;
        const char *chip_name;
        u16 txpwr, reg;
+       u16 product_id = le16_to_cpu(udev->descriptor.idProduct);
        int err, i;
 
        dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
@@ -1481,6 +1482,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
                (*channel++).hw_value = txpwr & 0xFF;
                (*channel++).hw_value = txpwr >> 8;
        }
+       /* Handle the differing rfkill GPIO bit in different models */
+       priv->rfkill_mask = RFKILL_MASK_8187_89_97;
+       if (product_id == 0x8197 || product_id == 0x8198) {
+               eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, &reg);
+               if (reg & 0xFF00)
+                       priv->rfkill_mask = RFKILL_MASK_8198;
+       }
 
        /*
         * XXX: Once this driver supports anything that requires
@@ -1509,9 +1517,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
        mutex_init(&priv->conf_mutex);
        skb_queue_head_init(&priv->b_tx_status.queue);
 
-       printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
+       printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n",
               wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
-              chip_name, priv->asic_rev, priv->rf->name);
+              chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask);
 
 #ifdef CONFIG_RTL8187_LEDS
        eeprom_93cx6_read(&eeprom, 0x3F, &reg);
index cad8037ab2af3a4d136194dcdf3e322d65495ad6..03555e1e0cab29cb0d8b4698b71d994d3ec11296 100644 (file)
@@ -25,10 +25,10 @@ static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv)
        u8 gpio;
 
        gpio = rtl818x_ioread8(priv, &priv->map->GPIO0);
-       rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02);
+       rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask);
        gpio = rtl818x_ioread8(priv, &priv->map->GPIO1);
 
-       return gpio & 0x02;
+       return gpio & priv->rfkill_mask;
 }
 
 void rtl8187_rfkill_init(struct ieee80211_hw *hw)