summary refs log tree commit diff
path: root/drivers/net/wireless/rtl818x
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-15 09:40:05 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-15 09:40:05 -0700
commit2ed0e21b30b53d3a94e204196e523e6c8f732b56 (patch)
treede2635426477d86338a9469ce09ba0626052288f /drivers/net/wireless/rtl818x
parent0fa213310cd8fa7a51071cdcf130e26fa56e9549 (diff)
parent9cbc1cb8cd46ce1f7645b9de249b2ce8460129bb (diff)
downloadlinux-2ed0e21b30b53d3a94e204196e523e6c8f732b56.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1244 commits)
  pkt_sched: Rename PSCHED_US2NS and PSCHED_NS2US
  ipv4: Fix fib_trie rebalancing
  Bluetooth: Fix issue with uninitialized nsh.type in DTL-1 driver
  Bluetooth: Fix Kconfig issue with RFKILL integration
  PIM-SM: namespace changes
  ipv4: update ARPD help text
  net: use a deferred timer in rt_check_expire
  ieee802154: fix kconfig bool/tristate muckup
  bonding: initialization rework
  bonding: use is_zero_ether_addr
  bonding: network device names are case sensative
  bonding: elminate bad refcount code
  bonding: fix style issues
  bonding: fix destructor
  bonding: remove bonding read/write semaphore
  bonding: initialize before registration
  bonding: bond_create always called with default parameters
  x_tables: Convert printk to pr_err
  netfilter: conntrack: optional reliable conntrack event delivery
  list_nulls: add hlist_nulls_add_head and hlist_nulls_del
  ...
Diffstat (limited to 'drivers/net/wireless/rtl818x')
-rw-r--r--drivers/net/wireless/rtl818x/Makefile2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c33
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h7
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c76
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.c218
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.h57
6 files changed, 334 insertions, 59 deletions
diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile
index c113b3e69046..37e3d4db0c40 100644
--- a/drivers/net/wireless/rtl818x/Makefile
+++ b/drivers/net/wireless/rtl818x/Makefile
@@ -1,5 +1,5 @@
 rtl8180-objs		:= rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
-rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o
+rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o
 
 obj-$(CONFIG_RTL8180)	+= rtl8180.o
 obj-$(CONFIG_RTL8187)	+= rtl8187.o
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 387c133ec0f2..7e65d7c31802 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -702,30 +702,26 @@ static int rtl8180_config(struct ieee80211_hw *dev, u32 changed)
 	return 0;
 }
 
-static int rtl8180_config_interface(struct ieee80211_hw *dev,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_if_conf *conf)
-{
-	struct rtl8180_priv *priv = dev->priv;
-	int i;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
-
-	if (is_valid_ether_addr(conf->bssid))
-		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
-	else
-		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
-
-	return 0;
-}
-
 static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *info,
 				     u32 changed)
 {
 	struct rtl8180_priv *priv = dev->priv;
+	int i;
+
+	if (changed & BSS_CHANGED_BSSID) {
+		for (i = 0; i < ETH_ALEN; i++)
+			rtl818x_iowrite8(priv, &priv->map->BSSID[i],
+					 info->bssid[i]);
+
+		if (is_valid_ether_addr(info->bssid))
+			rtl818x_iowrite8(priv, &priv->map->MSR,
+					 RTL818X_MSR_INFRA);
+		else
+			rtl818x_iowrite8(priv, &priv->map->MSR,
+					 RTL818X_MSR_NO_LINK);
+	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
 	        priv->rf->conf_erp(dev, info);
@@ -770,7 +766,6 @@ static const struct ieee80211_ops rtl8180_ops = {
 	.add_interface		= rtl8180_add_interface,
 	.remove_interface	= rtl8180_remove_interface,
 	.config			= rtl8180_config,
-	.config_interface	= rtl8180_config_interface,
 	.bss_info_changed	= rtl8180_bss_info_changed,
 	.configure_filter	= rtl8180_configure_filter,
 };
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index edeff82a4d06..c09bfefc70f3 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -16,6 +16,7 @@
 #define RTL8187_H
 
 #include "rtl818x.h"
+#include "rtl8187_leds.h"
 
 #define RTL8187_EEPROM_TXPWR_BASE	0x05
 #define RTL8187_EEPROM_MAC_ADDR		0x07
@@ -102,6 +103,12 @@ struct rtl8187_priv {
 	struct usb_anchor anchored;
 	struct delayed_work work;
 	struct ieee80211_hw *dev;
+#ifdef CONFIG_RTL8187_LEDS
+	struct rtl8187_led led_tx;
+	struct rtl8187_led led_rx;
+	struct delayed_work led_on;
+	struct delayed_work led_off;
+#endif
 	u16 txpwr_base;
 	u8 asic_rev;
 	u8 is_rtl8187b;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index d51ba0a88c23..294250e294dd 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -29,6 +29,9 @@
 
 #include "rtl8187.h"
 #include "rtl8187_rtl8225.h"
+#ifdef CONFIG_RTL8187_LEDS
+#include "rtl8187_leds.h"
+#endif
 
 MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
 MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
@@ -320,12 +323,7 @@ static void rtl8187_rx_cb(struct urb *urb)
 	unsigned long f;
 
 	spin_lock_irqsave(&priv->rx_queue.lock, f);
-	if (skb->next)
-		__skb_unlink(skb, &priv->rx_queue);
-	else {
-		spin_unlock_irqrestore(&priv->rx_queue.lock, f);
-		return;
-	}
+	__skb_unlink(skb, &priv->rx_queue);
 	spin_unlock_irqrestore(&priv->rx_queue.lock, f);
 	skb_put(skb, urb->actual_length);
 
@@ -736,10 +734,10 @@ static const u8 rtl8187b_reg_table[][3] = {
 	{0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0},
 	{0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0},
 	{0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0},
-	{0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0},
+	{0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2},
 
-	{0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0},
-	{0x8E, 0x08, 0}, {0x8F, 0x00, 0}
+	{0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0},
+	{0x8F, 0x00, 0}
 };
 
 static int rtl8187b_init_hw(struct ieee80211_hw *dev)
@@ -1089,32 +1087,6 @@ static int rtl8187_config(struct ieee80211_hw *dev, u32 changed)
 	return 0;
 }
 
-static int rtl8187_config_interface(struct ieee80211_hw *dev,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_if_conf *conf)
-{
-	struct rtl8187_priv *priv = dev->priv;
-	int i;
-	u8 reg;
-
-	mutex_lock(&priv->conf_mutex);
-	for (i = 0; i < ETH_ALEN; i++)
-		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
-
-	if (is_valid_ether_addr(conf->bssid)) {
-		reg = RTL818X_MSR_INFRA;
-		if (priv->is_rtl8187b)
-			reg |= RTL818X_MSR_ENEDCA;
-		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-	} else {
-		reg = RTL818X_MSR_NO_LINK;
-		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-	}
-
-	mutex_unlock(&priv->conf_mutex);
-	return 0;
-}
-
 /*
  * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for
  * example. Thus we have to use raw values for AC_*_PARAM register addresses.
@@ -1192,6 +1164,27 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
 				     u32 changed)
 {
 	struct rtl8187_priv *priv = dev->priv;
+	int i;
+	u8 reg;
+
+	if (changed & BSS_CHANGED_BSSID) {
+		mutex_lock(&priv->conf_mutex);
+		for (i = 0; i < ETH_ALEN; i++)
+			rtl818x_iowrite8(priv, &priv->map->BSSID[i],
+					 info->bssid[i]);
+
+		if (is_valid_ether_addr(info->bssid)) {
+			reg = RTL818X_MSR_INFRA;
+			if (priv->is_rtl8187b)
+				reg |= RTL818X_MSR_ENEDCA;
+			rtl818x_iowrite8(priv, &priv->map->MSR, reg);
+		} else {
+			reg = RTL818X_MSR_NO_LINK;
+			rtl818x_iowrite8(priv, &priv->map->MSR, reg);
+		}
+
+		mutex_unlock(&priv->conf_mutex);
+	}
 
 	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
 		rtl8187_conf_erp(priv, info->use_short_slot,
@@ -1273,7 +1266,6 @@ static const struct ieee80211_ops rtl8187_ops = {
 	.add_interface		= rtl8187_add_interface,
 	.remove_interface	= rtl8187_remove_interface,
 	.config			= rtl8187_config,
-	.config_interface	= rtl8187_config_interface,
 	.bss_info_changed	= rtl8187_bss_info_changed,
 	.configure_filter	= rtl8187_configure_filter,
 	.conf_tx		= rtl8187_conf_tx
@@ -1480,9 +1472,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
 		(*channel++).hw_value = txpwr >> 8;
 	}
 
-	if (priv->is_rtl8187b)
-		printk(KERN_WARNING "rtl8187: 8187B chip detected.\n");
-
 	/*
 	 * XXX: Once this driver supports anything that requires
 	 *	beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ.
@@ -1514,6 +1503,12 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
 	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
 	       chip_name, priv->asic_rev, priv->rf->name);
 
+#ifdef CONFIG_RTL8187_LEDS
+	eeprom_93cx6_read(&eeprom, 0x3F, &reg);
+	reg &= 0xFF;
+	rtl8187_leds_init(dev, reg);
+#endif
+
 	return 0;
 
  err_free_dmabuf:
@@ -1533,6 +1528,9 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
 	if (!dev)
 		return;
 
+#ifdef CONFIG_RTL8187_LEDS
+	rtl8187_leds_exit(dev);
+#endif
 	ieee80211_unregister_hw(dev);
 
 	priv = dev->priv;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
new file mode 100644
index 000000000000..b44253592243
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -0,0 +1,218 @@
+/*
+ * Linux LED driver for RTL8187
+ *
+ * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Based on the LED handling in the r8187 driver, which is:
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifdef CONFIG_RTL8187_LEDS
+
+#include <net/mac80211.h>
+#include <linux/usb.h>
+#include <linux/eeprom_93cx6.h>
+
+#include "rtl8187.h"
+#include "rtl8187_leds.h"
+
+static void led_turn_on(struct work_struct *work)
+{
+	/* As this routine does read/write operations on the hardware, it must
+	 * be run from a work queue.
+	 */
+	u8 reg;
+	struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
+				    led_on.work);
+	struct rtl8187_led *led = &priv->led_tx;
+
+	/* Don't change the LED, when the device is down. */
+	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+		return ;
+
+	/* Skip if the LED is not registered. */
+	if (!led->dev)
+		return;
+	mutex_lock(&priv->conf_mutex);
+	switch (led->ledpin) {
+	case LED_PIN_GPIO0:
+		rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
+		rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00);
+		break;
+	case LED_PIN_LED0:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_LED1:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_HW:
+	default:
+		break;
+	}
+	mutex_unlock(&priv->conf_mutex);
+}
+
+static void led_turn_off(struct work_struct *work)
+{
+	/* As this routine does read/write operations on the hardware, it must
+	 * be run from a work queue.
+	 */
+	u8 reg;
+	struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
+				    led_off.work);
+	struct rtl8187_led *led = &priv->led_tx;
+
+	/* Don't change the LED, when the device is down. */
+	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+		return ;
+
+	/* Skip if the LED is not registered. */
+	if (!led->dev)
+		return;
+	mutex_lock(&priv->conf_mutex);
+	switch (led->ledpin) {
+	case LED_PIN_GPIO0:
+		rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
+		rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01);
+		break;
+	case LED_PIN_LED0:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_LED1:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_HW:
+	default:
+		break;
+	}
+	mutex_unlock(&priv->conf_mutex);
+}
+
+/* Callback from the LED subsystem. */
+static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
+				   enum led_brightness brightness)
+{
+	struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
+					       led_dev);
+	struct ieee80211_hw *hw = led->dev;
+	struct rtl8187_priv *priv = hw->priv;
+
+	if (brightness == LED_OFF) {
+		queue_delayed_work(hw->workqueue, &priv->led_off, 0);
+		/* The LED is off for 1/20 sec so that it just blinks. */
+		queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20);
+	} else
+		queue_delayed_work(hw->workqueue, &priv->led_on, 0);
+}
+
+static int rtl8187_register_led(struct ieee80211_hw *dev,
+				struct rtl8187_led *led, const char *name,
+				const char *default_trigger, u8 ledpin)
+{
+	int err;
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (led->dev)
+		return -EEXIST;
+	if (!default_trigger)
+		return -EINVAL;
+	led->dev = dev;
+	led->ledpin = ledpin;
+	strncpy(led->name, name, sizeof(led->name));
+
+	led->led_dev.name = led->name;
+	led->led_dev.default_trigger = default_trigger;
+	led->led_dev.brightness_set = rtl8187_led_brightness_set;
+
+	err = led_classdev_register(&priv->udev->dev, &led->led_dev);
+	if (err) {
+		printk(KERN_INFO "LEDs: Failed to register %s\n", name);
+		led->dev = NULL;
+		return err;
+	}
+	return 0;
+}
+
+static void rtl8187_unregister_led(struct rtl8187_led *led)
+{
+	led_classdev_unregister(&led->led_dev);
+	led->dev = NULL;
+}
+
+void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	char name[RTL8187_LED_MAX_NAME_LEN + 1];
+	u8 ledpin;
+	int err;
+
+	/* According to the vendor driver, the LED operation depends on the
+	 * customer ID encoded in the EEPROM
+	 */
+	printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid);
+	switch (custid) {
+	case EEPROM_CID_RSVD0:
+	case EEPROM_CID_RSVD1:
+	case EEPROM_CID_SERCOMM_PS:
+	case EEPROM_CID_QMI:
+	case EEPROM_CID_DELL:
+	case EEPROM_CID_TOSHIBA:
+		ledpin = LED_PIN_GPIO0;
+		break;
+	case EEPROM_CID_ALPHA0:
+		ledpin = LED_PIN_LED0;
+		break;
+	case EEPROM_CID_HW:
+		ledpin = LED_PIN_HW;
+		break;
+	default:
+		ledpin = LED_PIN_GPIO0;
+	}
+
+	INIT_DELAYED_WORK(&priv->led_on, led_turn_on);
+	INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
+
+	snprintf(name, sizeof(name),
+		 "rtl8187-%s::tx", wiphy_name(dev->wiphy));
+	err = rtl8187_register_led(dev, &priv->led_tx, name,
+			 ieee80211_get_tx_led_name(dev), ledpin);
+	if (err)
+		goto error;
+	snprintf(name, sizeof(name),
+		 "rtl8187-%s::rx", wiphy_name(dev->wiphy));
+	err = rtl8187_register_led(dev, &priv->led_rx, name,
+			 ieee80211_get_rx_led_name(dev), ledpin);
+	if (!err) {
+		queue_delayed_work(dev->workqueue, &priv->led_on, 0);
+		return;
+	}
+	/* registration of RX LED failed - unregister TX */
+	rtl8187_unregister_led(&priv->led_tx);
+error:
+	/* If registration of either failed, cancel delayed work */
+	cancel_delayed_work_sync(&priv->led_off);
+	cancel_delayed_work_sync(&priv->led_on);
+}
+
+void rtl8187_leds_exit(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	rtl8187_unregister_led(&priv->led_tx);
+	/* turn the LED off before exiting */
+	queue_delayed_work(dev->workqueue, &priv->led_off, 0);
+	cancel_delayed_work_sync(&priv->led_off);
+	rtl8187_unregister_led(&priv->led_rx);
+}
+#endif /* def CONFIG_RTL8187_LED */
+
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h
new file mode 100644
index 000000000000..a0332027aead
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h
@@ -0,0 +1,57 @@
+/*
+ * Definitions for RTL8187 leds
+ *
+ * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Based on the LED handling in the r8187 driver, which is:
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL8187_LED_H
+#define RTL8187_LED_H
+
+#ifdef CONFIG_RTL8187_LEDS
+
+#define RTL8187_LED_MAX_NAME_LEN	21
+
+#include <linux/leds.h>
+#include <linux/types.h>
+
+enum {
+	LED_PIN_LED0,
+	LED_PIN_LED1,
+	LED_PIN_GPIO0,
+	LED_PIN_HW
+};
+
+enum {
+	EEPROM_CID_RSVD0 = 0x00,
+	EEPROM_CID_RSVD1 = 0xFF,
+	EEPROM_CID_ALPHA0 = 0x01,
+	EEPROM_CID_SERCOMM_PS = 0x02,
+	EEPROM_CID_HW = 0x03,
+	EEPROM_CID_TOSHIBA = 0x04,
+	EEPROM_CID_QMI = 0x07,
+	EEPROM_CID_DELL = 0x08
+};
+
+struct rtl8187_led {
+	struct ieee80211_hw *dev;
+	/* The LED class device */
+	struct led_classdev led_dev;
+	/* The pin/method used to control the led */
+	u8 ledpin;
+	/* The unique name string for this LED device. */
+	char name[RTL8187_LED_MAX_NAME_LEN + 1];
+};
+
+void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);
+void rtl8187_leds_exit(struct ieee80211_hw *dev);
+
+#endif /* def CONFIG_RTL8187_LED */
+
+#endif /* RTL8187_LED_H */