* [RFC][PATCH] iwlwifi using mac80211_leds
@ 2007-10-17 18:00 Ian Schram
2007-10-17 23:21 ` [ipw3945-devel] " Tomas Winkler
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Ian Schram @ 2007-10-17 18:00 UTC (permalink / raw)
To: wireless; +Cc: Ipw3945-devel
Here's my naive attempt to implement the mac80211_leds, since the addition of the associated led to wireless2.6
it works rather well for me. The patch below Is only for the 3945 but it should work for 4965 too afaik by just
copy pasting the changes in iwl3945-bace.c to iwl4965-base.c. But I can't test that and this way the email is clearer.
I am aware of two problems
- when unloading the module it prints a few warnings to dmesg because a send command failing
- when loading/unloading the module a few times. it will no longer connect. reloading mac80211 module fixes this
I expect there to be problems with the locking
- it's basically this way it doesn't crash for me spinlocking what can be spinlocked
But anyways, if for no other reason than your viewing pleasure ;-)
Signed-of-by: Ian Schram <ischram@telenet.be>
---
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 25cfc6c..8e8f835 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -126,3 +126,9 @@ config IWL3945
inserted in and remvoed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called iwl3945.ko.
+config IWLWIFI_LEDS
+ bool "IWLWIFI leds"
+ depends IWLWIFI && MAC80211_LEDS
+ default y
+ ---help---
+ This options enables the wireless led.
diff --git a/drivers/net/wireless/iwlwifi/iwl-leds.h b/drivers/net/wireless/iwlwifi/iwl-leds.h
new file mode 100644
index 0000000..07a55f0
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-leds.h
@@ -0,0 +1,20 @@
+#ifndef __iwl_leds_h__
+#define __iwl_leds_h__
+
+
+#include <linux/leds.h>
+
+
+#define IWL_LED_ACTIVITY (0<<1)
+#define IWL_LED_LINK (1<<1)
+#define IWL_LED_INTERVAL __constant_cpu_to_le32(1000)
+#define IWL_LED_ACTIVITY_PERIOD msecs_to_jiffies(500)
+#define IWL_LED_MAX_NAME_LEN 31
+
+struct iwl_led {
+ char name[IWL_LED_MAX_NAME_LEN + 1];
+ struct led_classdev cdev;
+};
+
+
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-priv.h b/drivers/net/wireless/iwlwifi/iwl-priv.h
index 6b490d0..bdaeb80 100644
--- a/drivers/net/wireless/iwlwifi/iwl-priv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-priv.h
@@ -127,11 +128,14 @@ struct iwl_priv {
struct iwl_init_alive_resp card_alive_init;
struct iwl_alive_resp card_alive;
-#ifdef LED
- /* LED related variables */
- struct iwl_activity_blink activity;
- unsigned long led_packets;
- int led_state;
+
+#ifdef CONFIG_IWLWIFI_LEDS
+ u8 led_state;
+ unsigned int rxtxpackets;
+ atomic_t ledtimer;
+ struct iwl_led tx_led;
+ struct iwl_led rx_led;
+ struct iwl_led assoc_led;
#endif
u16 active_rate;
@@ -274,6 +278,7 @@ struct iwl_priv {
struct delayed_work gather_stats;
struct delayed_work scan_check;
struct delayed_work post_associate;
+ struct delayed_work update_led;
#define IWL_DEFAULT_TX_POWER 0x0F
s8 user_txpower_limit;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index b601455..72317a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6065,6 +6065,171 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->restart);
}
+#ifdef CONFIG_IWLWIFI_LEDS
+static int iwl_led_cmd_callback(struct iwl_priv *priv,
+ struct iwl_cmd *cmd, struct sk_buff *skb)
+{
+ return 1;
+}
+
+static void iwl_bg_led_update(struct work_struct *data)
+{
+ struct iwl_priv *priv =
+ container_of(data, struct iwl_priv, update_led.work);
+ struct iwl_led_cmd led_cmd = {
+ .id = IWL_LED_ACTIVITY,
+ .interval = IWL_LED_INTERVAL,
+ };
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_LEDS_CMD,
+ .len = sizeof(struct iwl_led_cmd),
+ .data = &led_cmd,
+ .meta.flags = CMD_ASYNC,
+ .meta.u.callback = iwl_led_cmd_callback,
+ };
+ u8 on;
+ unsigned long flags;
+
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->rxtxpackets){
+ on = 1 + 250 / priv->rxtxpackets;
+ priv->rxtxpackets = 0;
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+
+ if (on == priv->led_state)
+ goto exit_unlock;
+
+ led_cmd.on = led_cmd.off = on;
+ priv->led_state = on;
+
+ }
+ else {
+
+ atomic_set(&priv->ledtimer, 0);
+ led_cmd.on = led_cmd.off = 0;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ iwl_send_cmd(priv, &cmd);
+
+ return;
+
+exit_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwl_led_set_rx(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ rx_led.cdev);
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!atomic_xchg(&priv->ledtimer, 1))
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+ priv->rxtxpackets++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+}
+
+static void iwl_led_set_tx(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ tx_led.cdev);
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!atomic_xchg(&priv->ledtimer, 1))
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+
+ priv->rxtxpackets++;
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwl_led_set_assoc(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ assoc_led.cdev);
+ struct iwl_led_cmd led_cmd = {
+ .id = IWL_LED_LINK,
+ .interval = IWL_LED_INTERVAL,
+ };
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_LEDS_CMD,
+ .len = sizeof(struct iwl_led_cmd),
+ .data = &led_cmd,
+ .meta.flags = CMD_ASYNC,
+ .meta.u.callback = iwl_led_cmd_callback
+ };
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ switch(value)
+ {
+ case LED_OFF:
+ led_cmd.off = 0;
+ led_cmd.on = 0;
+ break;
+ case LED_HALF:
+ case LED_FULL:
+ led_cmd.off = 0;
+ led_cmd.on = 40;
+ }
+ iwl_send_cmd(priv, &cmd);
+}
+
+
+static int iwl_register_led(struct iwl_priv *priv, struct iwl_led *led, char *ledname,
+ char *triggername, void (*callback)
+ (struct led_classdev *, enum led_brightness))
+{
+ snprintf(led->name, sizeof(led->name), ledname,
+ wiphy_name(priv->hw->wiphy));
+ led->cdev.name = led->name;
+ led->cdev.brightness_set = callback;
+ led->cdev.default_trigger = triggername;
+
+ return led_classdev_register(&priv->pci_dev->dev, &led->cdev);
+}
+
+static void iwl_register_leds(struct iwl_priv *priv)
+{
+ iwl_register_led(priv, &priv->tx_led, "iwl-%s:tx",
+ ieee80211_get_tx_led_name(priv->hw),
+ iwl_led_set_tx);
+ iwl_register_led(priv, &priv->rx_led, "iwl-%s:rx",
+ ieee80211_get_rx_led_name(priv->hw),
+ iwl_led_set_rx);
+ iwl_register_led(priv, &priv->assoc_led, "iwl-%s:asoc",
+ ieee80211_get_assoc_led_name(priv->hw),
+ iwl_led_set_assoc);
+}
+
+static void iwl_unregister_leds(struct iwl_priv *priv)
+{
+ led_classdev_unregister(&priv->tx_led.cdev);
+ led_classdev_unregister(&priv->rx_led.cdev);
+ led_classdev_unregister(&priv->assoc_led.cdev);
+}
+#endif
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
@@ -6140,6 +6140,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
if (iwl_is_rfkill(priv))
return;
+#ifdef CONFIG_IWLWIFI_LEDS
+ atomic_set(&priv->ledtimer, 0);
+#endif
if (!priv->mac80211_registered) {
/* Unlock so any user space entry points can call back into
* the driver without a deadlock... */
@@ -6158,6 +6161,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
priv->mac80211_registered = 1;
iwl_reset_channel_flag(priv);
+#ifdef CONFIG_IWLWIFI_LEDS
+ iwl_register_leds(priv);
+#endif
} else
ieee80211_start_queues(priv->hw);
@@ -6217,6 +6223,10 @@ static void __iwl_down(struct iwl_priv *priv)
if (!exit_pending)
set_bit(STATUS_EXIT_PENDING, &priv->status);
+#ifdef CONFIG_IWLWIFI_LEDS
+ /* Prevent the led callbacks from rescheduling the update_led timer */
+ atomic_set(&priv->ledtimer, 1);
+#endif
iwl_clear_stations_table(priv);
/* Unblock any waiting calls */
@@ -8198,7 +8208,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
-
+ INIT_DELAYED_WORK(&priv->update_led, iwl_bg_led_update);
iwl_hw_setup_deferred_work(priv);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
@@ -8209,6 +8219,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
iwl_hw_cancel_deferred_work(priv);
+ cancel_delayed_work(&priv->update_led);
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
cancel_delayed_work(&priv->post_associate);
@@ -8531,6 +8542,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
iwl_clear_stations_table(priv);
if (priv->mac80211_registered) {
+#ifdef CONFIG_IWLWIFI_LEDS
+ iwl_unregister_leds(priv);
+#endif
ieee80211_unregister_hw(priv->hw);
iwl_rate_control_unregister(priv->hw);
}
diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h
index e0b97c3..ce5d489 100644
--- a/drivers/net/wireless/iwlwifi/iwlwifi.h
+++ b/drivers/net/wireless/iwlwifi/iwlwifi.h
@@ -55,6 +55,9 @@ extern struct pci_device_id iwl_hw_card_ids[];
#include "iwl-prph.h"
+#ifdef CONFIG_IWLWIFI_LEDS
+#include "iwl-leds.h"
+#endif
/*
* Driver implementation data structures, constants, inline
* functions
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-17 18:00 [RFC][PATCH] iwlwifi using mac80211_leds Ian Schram
@ 2007-10-17 23:21 ` Tomas Winkler
2007-10-18 1:45 ` Ian Schram
2007-10-23 6:11 ` Jerone Young
2007-10-24 0:34 ` Ian Schram
2 siblings, 1 reply; 13+ messages in thread
From: Tomas Winkler @ 2007-10-17 23:21 UTC (permalink / raw)
To: Ian Schram; +Cc: wireless, Ipw3945-devel
I'm not familiar with the led framework but as far as I see this is
not how the LEDs work in iwl. You don't run it upon each packet just
define blinking pattern with on off and period timers. It is too
expensive to send the LED command for each packet.
Usually you would change the pattern pattern as the throughput changes.
On 10/17/07, Ian Schram <ischram@telenet.be> wrote:
> Here's my naive attempt to implement the mac80211_leds, since the addition of the associated led to wireless2.6
> it works rather well for me. The patch below Is only for the 3945 but it should work for 4965 too afaik by just
> copy pasting the changes in iwl3945-bace.c to iwl4965-base.c. But I can't test that and this way the email is clearer.
>
> I am aware of two problems
> - when unloading the module it prints a few warnings to dmesg because a send command failing
> - when loading/unloading the module a few times. it will no longer connect. reloading mac80211 module fixes this
>
> I expect there to be problems with the locking
> - it's basically this way it doesn't crash for me spinlocking what can be spinlocked
>
> But anyways, if for no other reason than your viewing pleasure ;-)
>
> Signed-of-by: Ian Schram <ischram@telenet.be>
> ---
> diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
> index 25cfc6c..8e8f835 100644
> --- a/drivers/net/wireless/iwlwifi/Kconfig
> +++ b/drivers/net/wireless/iwlwifi/Kconfig
> @@ -126,3 +126,9 @@ config IWL3945
> inserted in and remvoed from the running kernel whenever you want),
> say M here and read <file:Documentation/modules.txt>. The module
> will be called iwl3945.ko.
> +config IWLWIFI_LEDS
> + bool "IWLWIFI leds"
> + depends IWLWIFI && MAC80211_LEDS
> + default y
> + ---help---
> + This options enables the wireless led.
> diff --git a/drivers/net/wireless/iwlwifi/iwl-leds.h b/drivers/net/wireless/iwlwifi/iwl-leds.h
> new file mode 100644
> index 0000000..07a55f0
> --- /dev/null
> +++ b/drivers/net/wireless/iwlwifi/iwl-leds.h
> @@ -0,0 +1,20 @@
> +#ifndef __iwl_leds_h__
> +#define __iwl_leds_h__
> +
> +
> +#include <linux/leds.h>
> +
> +
> +#define IWL_LED_ACTIVITY (0<<1)
> +#define IWL_LED_LINK (1<<1)
> +#define IWL_LED_INTERVAL __constant_cpu_to_le32(1000)
> +#define IWL_LED_ACTIVITY_PERIOD msecs_to_jiffies(500)
> +#define IWL_LED_MAX_NAME_LEN 31
> +
> +struct iwl_led {
> + char name[IWL_LED_MAX_NAME_LEN + 1];
> + struct led_classdev cdev;
> +};
> +
> +
> +#endif
> diff --git a/drivers/net/wireless/iwlwifi/iwl-priv.h b/drivers/net/wireless/iwlwifi/iwl-priv.h
> index 6b490d0..bdaeb80 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-priv.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-priv.h
> @@ -127,11 +128,14 @@ struct iwl_priv {
> struct iwl_init_alive_resp card_alive_init;
> struct iwl_alive_resp card_alive;
>
> -#ifdef LED
> - /* LED related variables */
> - struct iwl_activity_blink activity;
> - unsigned long led_packets;
> - int led_state;
> +
> +#ifdef CONFIG_IWLWIFI_LEDS
> + u8 led_state;
> + unsigned int rxtxpackets;
> + atomic_t ledtimer;
> + struct iwl_led tx_led;
> + struct iwl_led rx_led;
> + struct iwl_led assoc_led;
> #endif
>
> u16 active_rate;
> @@ -274,6 +278,7 @@ struct iwl_priv {
> struct delayed_work gather_stats;
> struct delayed_work scan_check;
> struct delayed_work post_associate;
> + struct delayed_work update_led;
>
> #define IWL_DEFAULT_TX_POWER 0x0F
> s8 user_txpower_limit;
> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> index b601455..72317a3 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -6065,6 +6065,171 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
> queue_work(priv->workqueue, &priv->restart);
> }
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> +static int iwl_led_cmd_callback(struct iwl_priv *priv,
> + struct iwl_cmd *cmd, struct sk_buff *skb)
> +{
> + return 1;
> +}
> +
> +static void iwl_bg_led_update(struct work_struct *data)
> +{
> + struct iwl_priv *priv =
> + container_of(data, struct iwl_priv, update_led.work);
> + struct iwl_led_cmd led_cmd = {
> + .id = IWL_LED_ACTIVITY,
> + .interval = IWL_LED_INTERVAL,
> + };
> + struct iwl_host_cmd cmd = {
> + .id = REPLY_LEDS_CMD,
> + .len = sizeof(struct iwl_led_cmd),
> + .data = &led_cmd,
> + .meta.flags = CMD_ASYNC,
> + .meta.u.callback = iwl_led_cmd_callback,
> + };
> + u8 on;
> + unsigned long flags;
> +
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + spin_lock_irqsave(&priv->lock, flags);
> +
> + if (priv->rxtxpackets){
> + on = 1 + 250 / priv->rxtxpackets;
> + priv->rxtxpackets = 0;
> + queue_delayed_work(priv->workqueue, &priv->update_led,
> + IWL_LED_ACTIVITY_PERIOD);
> +
> + if (on == priv->led_state)
> + goto exit_unlock;
> +
> + led_cmd.on = led_cmd.off = on;
> + priv->led_state = on;
> +
> + }
> + else {
> +
> + atomic_set(&priv->ledtimer, 0);
> + led_cmd.on = led_cmd.off = 0;
> + }
> +
> + spin_unlock_irqrestore(&priv->lock, flags);
> + iwl_send_cmd(priv, &cmd);
> +
> + return;
> +
> +exit_unlock:
> + spin_unlock_irqrestore(&priv->lock, flags);
> +}
> +
> +static void iwl_led_set_rx(struct led_classdev *led_cdev,
> + enum led_brightness value)
> +{
> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
> + rx_led.cdev);
> + unsigned long flags;
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + spin_lock_irqsave(&priv->lock, flags);
> + if (!atomic_xchg(&priv->ledtimer, 1))
> + queue_delayed_work(priv->workqueue, &priv->update_led,
> + IWL_LED_ACTIVITY_PERIOD);
> + priv->rxtxpackets++;
> + spin_unlock_irqrestore(&priv->lock, flags);
> +
> +}
> +
> +static void iwl_led_set_tx(struct led_classdev *led_cdev,
> + enum led_brightness value)
> +{
> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
> + tx_led.cdev);
> + unsigned long flags;
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + spin_lock_irqsave(&priv->lock, flags);
> + if (!atomic_xchg(&priv->ledtimer, 1))
> + queue_delayed_work(priv->workqueue, &priv->update_led,
> + IWL_LED_ACTIVITY_PERIOD);
> +
> + priv->rxtxpackets++;
> + spin_unlock_irqrestore(&priv->lock, flags);
> +}
> +
> +static void iwl_led_set_assoc(struct led_classdev *led_cdev,
> + enum led_brightness value)
> +{
> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
> + assoc_led.cdev);
> + struct iwl_led_cmd led_cmd = {
> + .id = IWL_LED_LINK,
> + .interval = IWL_LED_INTERVAL,
> + };
> + struct iwl_host_cmd cmd = {
> + .id = REPLY_LEDS_CMD,
> + .len = sizeof(struct iwl_led_cmd),
> + .data = &led_cmd,
> + .meta.flags = CMD_ASYNC,
> + .meta.u.callback = iwl_led_cmd_callback
> + };
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + switch(value)
> + {
> + case LED_OFF:
> + led_cmd.off = 0;
> + led_cmd.on = 0;
> + break;
> + case LED_HALF:
> + case LED_FULL:
> + led_cmd.off = 0;
> + led_cmd.on = 40;
> + }
> + iwl_send_cmd(priv, &cmd);
> +}
> +
> +
> +static int iwl_register_led(struct iwl_priv *priv, struct iwl_led *led, char *ledname,
> + char *triggername, void (*callback)
> + (struct led_classdev *, enum led_brightness))
> +{
> + snprintf(led->name, sizeof(led->name), ledname,
> + wiphy_name(priv->hw->wiphy));
> + led->cdev.name = led->name;
> + led->cdev.brightness_set = callback;
> + led->cdev.default_trigger = triggername;
> +
> + return led_classdev_register(&priv->pci_dev->dev, &led->cdev);
> +}
> +
> +static void iwl_register_leds(struct iwl_priv *priv)
> +{
> + iwl_register_led(priv, &priv->tx_led, "iwl-%s:tx",
> + ieee80211_get_tx_led_name(priv->hw),
> + iwl_led_set_tx);
> + iwl_register_led(priv, &priv->rx_led, "iwl-%s:rx",
> + ieee80211_get_rx_led_name(priv->hw),
> + iwl_led_set_rx);
> + iwl_register_led(priv, &priv->assoc_led, "iwl-%s:asoc",
> + ieee80211_get_assoc_led_name(priv->hw),
> + iwl_led_set_assoc);
> +}
> +
> +static void iwl_unregister_leds(struct iwl_priv *priv)
> +{
> + led_classdev_unregister(&priv->tx_led.cdev);
> + led_classdev_unregister(&priv->rx_led.cdev);
> + led_classdev_unregister(&priv->assoc_led.cdev);
> +}
> +#endif
>
> /**
> * iwl_alive_start - called after REPLY_ALIVE notification received
> @@ -6140,6 +6140,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
> if (iwl_is_rfkill(priv))
> return;
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> + atomic_set(&priv->ledtimer, 0);
> +#endif
> if (!priv->mac80211_registered) {
> /* Unlock so any user space entry points can call back into
> * the driver without a deadlock... */
> @@ -6158,6 +6161,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
> priv->mac80211_registered = 1;
>
> iwl_reset_channel_flag(priv);
> +#ifdef CONFIG_IWLWIFI_LEDS
> + iwl_register_leds(priv);
> +#endif
> } else
> ieee80211_start_queues(priv->hw);
>
> @@ -6217,6 +6223,10 @@ static void __iwl_down(struct iwl_priv *priv)
> if (!exit_pending)
> set_bit(STATUS_EXIT_PENDING, &priv->status);
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> + /* Prevent the led callbacks from rescheduling the update_led timer */
> + atomic_set(&priv->ledtimer, 1);
> +#endif
> iwl_clear_stations_table(priv);
>
> /* Unblock any waiting calls */
> @@ -8198,7 +8208,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
> INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
> INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
> INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
> -
> + INIT_DELAYED_WORK(&priv->update_led, iwl_bg_led_update);
> iwl_hw_setup_deferred_work(priv);
>
> tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
> @@ -8209,6 +8219,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
> {
> iwl_hw_cancel_deferred_work(priv);
>
> + cancel_delayed_work(&priv->update_led);
> cancel_delayed_work(&priv->scan_check);
> cancel_delayed_work(&priv->alive_start);
> cancel_delayed_work(&priv->post_associate);
> @@ -8531,6 +8542,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
> iwl_clear_stations_table(priv);
>
> if (priv->mac80211_registered) {
> +#ifdef CONFIG_IWLWIFI_LEDS
> + iwl_unregister_leds(priv);
> +#endif
> ieee80211_unregister_hw(priv->hw);
> iwl_rate_control_unregister(priv->hw);
> }
> diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h
> index e0b97c3..ce5d489 100644
> --- a/drivers/net/wireless/iwlwifi/iwlwifi.h
> +++ b/drivers/net/wireless/iwlwifi/iwlwifi.h
> @@ -55,6 +55,9 @@ extern struct pci_device_id iwl_hw_card_ids[];
>
> #include "iwl-prph.h"
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> +#include "iwl-leds.h"
> +#endif
> /*
> * Driver implementation data structures, constants, inline
> * functions
>
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >> http://get.splunk.com/
> _______________________________________________
> Ipw3945-devel mailing list
> Ipw3945-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/ipw3945-devel
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-17 23:21 ` [ipw3945-devel] " Tomas Winkler
@ 2007-10-18 1:45 ` Ian Schram
0 siblings, 0 replies; 13+ messages in thread
From: Ian Schram @ 2007-10-18 1:45 UTC (permalink / raw)
To: Tomas Winkler; +Cc: wireless, Ipw3945-devel
I do *not* send a led command on each packet. (Unless i made a horrible coding error that I do not see)
I send a led command when on every association event. But that's only when
we actually associate. or hw/sw rfkill is activated, or deassociated.
The leds for activity: keep a counter, which counts how many times the led is triggered from mac80211
right now this is a multiple of the #packets. A delayed work will run every 500 ms and translate this
amount of packets into a blinking rate for the led. When no packets are transeived, the delayed work
will not be scheduled until new packets are transeived. This is quite similar to how the leds work in
ipwraw, and ipw3945, only there the amount of byters were counted in the rx and tx path, which
was then converted to a blinking rate. This information is not available within the led framework,
hence i used the amount of led events and translate that into a blinking rate.
I did manage to listen to your comments on my previous patch ;-)
Actually i believe this to be a crossection of what mac80211_leds expects, and how ipw used to
do it.
Ian
Tomas Winkler wrote:
> I'm not familiar with the led framework but as far as I see this is
> not how the LEDs work in iwl. You don't run it upon each packet just
> define blinking pattern with on off and period timers. It is too
> expensive to send the LED command for each packet.
> Usually you would change the pattern pattern as the throughput changes.
>
>
> On 10/17/07, Ian Schram <ischram@telenet.be> wrote:
>> Here's my naive attempt to implement the mac80211_leds, since the addition of the associated led to wireless2.6
>> it works rather well for me. The patch below Is only for the 3945 but it should work for 4965 too afaik by just
>> copy pasting the changes in iwl3945-bace.c to iwl4965-base.c. But I can't test that and this way the email is clearer.
>>
>> I am aware of two problems
>> - when unloading the module it prints a few warnings to dmesg because a send command failing
>> - when loading/unloading the module a few times. it will no longer connect. reloading mac80211 module fixes this
>>
>> I expect there to be problems with the locking
>> - it's basically this way it doesn't crash for me spinlocking what can be spinlocked
>>
>> But anyways, if for no other reason than your viewing pleasure ;-)
>>
>> Signed-of-by: Ian Schram <ischram@telenet.be>
>> ---
>> diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
>> index 25cfc6c..8e8f835 100644
>> --- a/drivers/net/wireless/iwlwifi/Kconfig
>> +++ b/drivers/net/wireless/iwlwifi/Kconfig
>> @@ -126,3 +126,9 @@ config IWL3945
>> inserted in and remvoed from the running kernel whenever you want),
>> say M here and read <file:Documentation/modules.txt>. The module
>> will be called iwl3945.ko.
>> +config IWLWIFI_LEDS
>> + bool "IWLWIFI leds"
>> + depends IWLWIFI && MAC80211_LEDS
>> + default y
>> + ---help---
>> + This options enables the wireless led.
>> diff --git a/drivers/net/wireless/iwlwifi/iwl-leds.h b/drivers/net/wireless/iwlwifi/iwl-leds.h
>> new file mode 100644
>> index 0000000..07a55f0
>> --- /dev/null
>> +++ b/drivers/net/wireless/iwlwifi/iwl-leds.h
>> @@ -0,0 +1,20 @@
>> +#ifndef __iwl_leds_h__
>> +#define __iwl_leds_h__
>> +
>> +
>> +#include <linux/leds.h>
>> +
>> +
>> +#define IWL_LED_ACTIVITY (0<<1)
>> +#define IWL_LED_LINK (1<<1)
>> +#define IWL_LED_INTERVAL __constant_cpu_to_le32(1000)
>> +#define IWL_LED_ACTIVITY_PERIOD msecs_to_jiffies(500)
>> +#define IWL_LED_MAX_NAME_LEN 31
>> +
>> +struct iwl_led {
>> + char name[IWL_LED_MAX_NAME_LEN + 1];
>> + struct led_classdev cdev;
>> +};
>> +
>> +
>> +#endif
>> diff --git a/drivers/net/wireless/iwlwifi/iwl-priv.h b/drivers/net/wireless/iwlwifi/iwl-priv.h
>> index 6b490d0..bdaeb80 100644
>> --- a/drivers/net/wireless/iwlwifi/iwl-priv.h
>> +++ b/drivers/net/wireless/iwlwifi/iwl-priv.h
>> @@ -127,11 +128,14 @@ struct iwl_priv {
>> struct iwl_init_alive_resp card_alive_init;
>> struct iwl_alive_resp card_alive;
>>
>> -#ifdef LED
>> - /* LED related variables */
>> - struct iwl_activity_blink activity;
>> - unsigned long led_packets;
>> - int led_state;
>> +
>> +#ifdef CONFIG_IWLWIFI_LEDS
>> + u8 led_state;
>> + unsigned int rxtxpackets;
>> + atomic_t ledtimer;
>> + struct iwl_led tx_led;
>> + struct iwl_led rx_led;
>> + struct iwl_led assoc_led;
>> #endif
>>
>> u16 active_rate;
>> @@ -274,6 +278,7 @@ struct iwl_priv {
>> struct delayed_work gather_stats;
>> struct delayed_work scan_check;
>> struct delayed_work post_associate;
>> + struct delayed_work update_led;
>>
>> #define IWL_DEFAULT_TX_POWER 0x0F
>> s8 user_txpower_limit;
>> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
>> index b601455..72317a3 100644
>> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
>> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
>> @@ -6065,6 +6065,171 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
>> queue_work(priv->workqueue, &priv->restart);
>> }
>>
>> +#ifdef CONFIG_IWLWIFI_LEDS
>> +static int iwl_led_cmd_callback(struct iwl_priv *priv,
>> + struct iwl_cmd *cmd, struct sk_buff *skb)
>> +{
>> + return 1;
>> +}
>> +
>> +static void iwl_bg_led_update(struct work_struct *data)
>> +{
>> + struct iwl_priv *priv =
>> + container_of(data, struct iwl_priv, update_led.work);
>> + struct iwl_led_cmd led_cmd = {
>> + .id = IWL_LED_ACTIVITY,
>> + .interval = IWL_LED_INTERVAL,
>> + };
>> + struct iwl_host_cmd cmd = {
>> + .id = REPLY_LEDS_CMD,
>> + .len = sizeof(struct iwl_led_cmd),
>> + .data = &led_cmd,
>> + .meta.flags = CMD_ASYNC,
>> + .meta.u.callback = iwl_led_cmd_callback,
>> + };
>> + u8 on;
>> + unsigned long flags;
>> +
>> +
>> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
>> + return;
>> +
>> + spin_lock_irqsave(&priv->lock, flags);
>> +
>> + if (priv->rxtxpackets){
>> + on = 1 + 250 / priv->rxtxpackets;
>> + priv->rxtxpackets = 0;
>> + queue_delayed_work(priv->workqueue, &priv->update_led,
>> + IWL_LED_ACTIVITY_PERIOD);
>> +
>> + if (on == priv->led_state)
>> + goto exit_unlock;
>> +
>> + led_cmd.on = led_cmd.off = on;
>> + priv->led_state = on;
>> +
>> + }
>> + else {
>> +
>> + atomic_set(&priv->ledtimer, 0);
>> + led_cmd.on = led_cmd.off = 0;
>> + }
>> +
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> + iwl_send_cmd(priv, &cmd);
>> +
>> + return;
>> +
>> +exit_unlock:
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> +}
>> +
>> +static void iwl_led_set_rx(struct led_classdev *led_cdev,
>> + enum led_brightness value)
>> +{
>> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
>> + rx_led.cdev);
>> + unsigned long flags;
>> +
>> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
>> + return;
>> +
>> + spin_lock_irqsave(&priv->lock, flags);
>> + if (!atomic_xchg(&priv->ledtimer, 1))
>> + queue_delayed_work(priv->workqueue, &priv->update_led,
>> + IWL_LED_ACTIVITY_PERIOD);
>> + priv->rxtxpackets++;
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> +
>> +}
>> +
>> +static void iwl_led_set_tx(struct led_classdev *led_cdev,
>> + enum led_brightness value)
>> +{
>> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
>> + tx_led.cdev);
>> + unsigned long flags;
>> +
>> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
>> + return;
>> +
>> + spin_lock_irqsave(&priv->lock, flags);
>> + if (!atomic_xchg(&priv->ledtimer, 1))
>> + queue_delayed_work(priv->workqueue, &priv->update_led,
>> + IWL_LED_ACTIVITY_PERIOD);
>> +
>> + priv->rxtxpackets++;
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> +}
>> +
>> +static void iwl_led_set_assoc(struct led_classdev *led_cdev,
>> + enum led_brightness value)
>> +{
>> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
>> + assoc_led.cdev);
>> + struct iwl_led_cmd led_cmd = {
>> + .id = IWL_LED_LINK,
>> + .interval = IWL_LED_INTERVAL,
>> + };
>> + struct iwl_host_cmd cmd = {
>> + .id = REPLY_LEDS_CMD,
>> + .len = sizeof(struct iwl_led_cmd),
>> + .data = &led_cmd,
>> + .meta.flags = CMD_ASYNC,
>> + .meta.u.callback = iwl_led_cmd_callback
>> + };
>> +
>> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
>> + return;
>> +
>> + switch(value)
>> + {
>> + case LED_OFF:
>> + led_cmd.off = 0;
>> + led_cmd.on = 0;
>> + break;
>> + case LED_HALF:
>> + case LED_FULL:
>> + led_cmd.off = 0;
>> + led_cmd.on = 40;
>> + }
>> + iwl_send_cmd(priv, &cmd);
>> +}
>> +
>> +
>> +static int iwl_register_led(struct iwl_priv *priv, struct iwl_led *led, char *ledname,
>> + char *triggername, void (*callback)
>> + (struct led_classdev *, enum led_brightness))
>> +{
>> + snprintf(led->name, sizeof(led->name), ledname,
>> + wiphy_name(priv->hw->wiphy));
>> + led->cdev.name = led->name;
>> + led->cdev.brightness_set = callback;
>> + led->cdev.default_trigger = triggername;
>> +
>> + return led_classdev_register(&priv->pci_dev->dev, &led->cdev);
>> +}
>> +
>> +static void iwl_register_leds(struct iwl_priv *priv)
>> +{
>> + iwl_register_led(priv, &priv->tx_led, "iwl-%s:tx",
>> + ieee80211_get_tx_led_name(priv->hw),
>> + iwl_led_set_tx);
>> + iwl_register_led(priv, &priv->rx_led, "iwl-%s:rx",
>> + ieee80211_get_rx_led_name(priv->hw),
>> + iwl_led_set_rx);
>> + iwl_register_led(priv, &priv->assoc_led, "iwl-%s:asoc",
>> + ieee80211_get_assoc_led_name(priv->hw),
>> + iwl_led_set_assoc);
>> +}
>> +
>> +static void iwl_unregister_leds(struct iwl_priv *priv)
>> +{
>> + led_classdev_unregister(&priv->tx_led.cdev);
>> + led_classdev_unregister(&priv->rx_led.cdev);
>> + led_classdev_unregister(&priv->assoc_led.cdev);
>> +}
>> +#endif
>>
>> /**
>> * iwl_alive_start - called after REPLY_ALIVE notification received
>> @@ -6140,6 +6140,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
>> if (iwl_is_rfkill(priv))
>> return;
>>
>> +#ifdef CONFIG_IWLWIFI_LEDS
>> + atomic_set(&priv->ledtimer, 0);
>> +#endif
>> if (!priv->mac80211_registered) {
>> /* Unlock so any user space entry points can call back into
>> * the driver without a deadlock... */
>> @@ -6158,6 +6161,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
>> priv->mac80211_registered = 1;
>>
>> iwl_reset_channel_flag(priv);
>> +#ifdef CONFIG_IWLWIFI_LEDS
>> + iwl_register_leds(priv);
>> +#endif
>> } else
>> ieee80211_start_queues(priv->hw);
>>
>> @@ -6217,6 +6223,10 @@ static void __iwl_down(struct iwl_priv *priv)
>> if (!exit_pending)
>> set_bit(STATUS_EXIT_PENDING, &priv->status);
>>
>> +#ifdef CONFIG_IWLWIFI_LEDS
>> + /* Prevent the led callbacks from rescheduling the update_led timer */
>> + atomic_set(&priv->ledtimer, 1);
>> +#endif
>> iwl_clear_stations_table(priv);
>>
>> /* Unblock any waiting calls */
>> @@ -8198,7 +8208,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
>> INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
>> INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
>> INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
>> -
>> + INIT_DELAYED_WORK(&priv->update_led, iwl_bg_led_update);
>> iwl_hw_setup_deferred_work(priv);
>>
>> tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
>> @@ -8209,6 +8219,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
>> {
>> iwl_hw_cancel_deferred_work(priv);
>>
>> + cancel_delayed_work(&priv->update_led);
>> cancel_delayed_work(&priv->scan_check);
>> cancel_delayed_work(&priv->alive_start);
>> cancel_delayed_work(&priv->post_associate);
>> @@ -8531,6 +8542,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
>> iwl_clear_stations_table(priv);
>>
>> if (priv->mac80211_registered) {
>> +#ifdef CONFIG_IWLWIFI_LEDS
>> + iwl_unregister_leds(priv);
>> +#endif
>> ieee80211_unregister_hw(priv->hw);
>> iwl_rate_control_unregister(priv->hw);
>> }
>> diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h
>> index e0b97c3..ce5d489 100644
>> --- a/drivers/net/wireless/iwlwifi/iwlwifi.h
>> +++ b/drivers/net/wireless/iwlwifi/iwlwifi.h
>> @@ -55,6 +55,9 @@ extern struct pci_device_id iwl_hw_card_ids[];
>>
>> #include "iwl-prph.h"
>>
>> +#ifdef CONFIG_IWLWIFI_LEDS
>> +#include "iwl-leds.h"
>> +#endif
>> /*
>> * Driver implementation data structures, constants, inline
>> * functions
>>
>>
>>
>> -------------------------------------------------------------------------
>> This SF.net email is sponsored by: Splunk Inc.
>> Still grepping through log files to find problems? Stop.
>> Now Search log events and configuration files using AJAX and a browser.
>> Download your FREE copy of Splunk now >> http://get.splunk.com/
>> _______________________________________________
>> Ipw3945-devel mailing list
>> Ipw3945-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/ipw3945-devel
>>
>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-17 18:00 [RFC][PATCH] iwlwifi using mac80211_leds Ian Schram
2007-10-17 23:21 ` [ipw3945-devel] " Tomas Winkler
@ 2007-10-23 6:11 ` Jerone Young
2007-10-23 6:15 ` Zhu Yi
2007-10-24 0:34 ` Ian Schram
2 siblings, 1 reply; 13+ messages in thread
From: Jerone Young @ 2007-10-23 6:11 UTC (permalink / raw)
To: Ian Schram; +Cc: wireless, Ipw3945-devel
Is this patch acceptable for everyone?
It would be nice to finally have the wireless led indicator working.
If this patch is ok .. I'll put out a patch for the iwl4965 and test
it. I think since a lot of the major functionality is now in the
driver (great job guys!) it's about time to kill these small user
issues.
On 10/17/07, Ian Schram <ischram@telenet.be> wrote:
> Here's my naive attempt to implement the mac80211_leds, since the addition of the associated led to wireless2.6
> it works rather well for me. The patch below Is only for the 3945 but it should work for 4965 too afaik by just
> copy pasting the changes in iwl3945-bace.c to iwl4965-base.c. But I can't test that and this way the email is clearer.
>
> I am aware of two problems
> - when unloading the module it prints a few warnings to dmesg because a send command failing
> - when loading/unloading the module a few times. it will no longer connect. reloading mac80211 module fixes this
>
> I expect there to be problems with the locking
> - it's basically this way it doesn't crash for me spinlocking what can be spinlocked
>
> But anyways, if for no other reason than your viewing pleasure ;-)
>
> Signed-of-by: Ian Schram <ischram@telenet.be>
> ---
> diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
> index 25cfc6c..8e8f835 100644
> --- a/drivers/net/wireless/iwlwifi/Kconfig
> +++ b/drivers/net/wireless/iwlwifi/Kconfig
> @@ -126,3 +126,9 @@ config IWL3945
> inserted in and remvoed from the running kernel whenever you want),
> say M here and read <file:Documentation/modules.txt>. The module
> will be called iwl3945.ko.
> +config IWLWIFI_LEDS
> + bool "IWLWIFI leds"
> + depends IWLWIFI && MAC80211_LEDS
> + default y
> + ---help---
> + This options enables the wireless led.
> diff --git a/drivers/net/wireless/iwlwifi/iwl-leds.h b/drivers/net/wireless/iwlwifi/iwl-leds.h
> new file mode 100644
> index 0000000..07a55f0
> --- /dev/null
> +++ b/drivers/net/wireless/iwlwifi/iwl-leds.h
> @@ -0,0 +1,20 @@
> +#ifndef __iwl_leds_h__
> +#define __iwl_leds_h__
> +
> +
> +#include <linux/leds.h>
> +
> +
> +#define IWL_LED_ACTIVITY (0<<1)
> +#define IWL_LED_LINK (1<<1)
> +#define IWL_LED_INTERVAL __constant_cpu_to_le32(1000)
> +#define IWL_LED_ACTIVITY_PERIOD msecs_to_jiffies(500)
> +#define IWL_LED_MAX_NAME_LEN 31
> +
> +struct iwl_led {
> + char name[IWL_LED_MAX_NAME_LEN + 1];
> + struct led_classdev cdev;
> +};
> +
> +
> +#endif
> diff --git a/drivers/net/wireless/iwlwifi/iwl-priv.h b/drivers/net/wireless/iwlwifi/iwl-priv.h
> index 6b490d0..bdaeb80 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-priv.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-priv.h
> @@ -127,11 +128,14 @@ struct iwl_priv {
> struct iwl_init_alive_resp card_alive_init;
> struct iwl_alive_resp card_alive;
>
> -#ifdef LED
> - /* LED related variables */
> - struct iwl_activity_blink activity;
> - unsigned long led_packets;
> - int led_state;
> +
> +#ifdef CONFIG_IWLWIFI_LEDS
> + u8 led_state;
> + unsigned int rxtxpackets;
> + atomic_t ledtimer;
> + struct iwl_led tx_led;
> + struct iwl_led rx_led;
> + struct iwl_led assoc_led;
> #endif
>
> u16 active_rate;
> @@ -274,6 +278,7 @@ struct iwl_priv {
> struct delayed_work gather_stats;
> struct delayed_work scan_check;
> struct delayed_work post_associate;
> + struct delayed_work update_led;
>
> #define IWL_DEFAULT_TX_POWER 0x0F
> s8 user_txpower_limit;
> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> index b601455..72317a3 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -6065,6 +6065,171 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
> queue_work(priv->workqueue, &priv->restart);
> }
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> +static int iwl_led_cmd_callback(struct iwl_priv *priv,
> + struct iwl_cmd *cmd, struct sk_buff *skb)
> +{
> + return 1;
> +}
> +
> +static void iwl_bg_led_update(struct work_struct *data)
> +{
> + struct iwl_priv *priv =
> + container_of(data, struct iwl_priv, update_led.work);
> + struct iwl_led_cmd led_cmd = {
> + .id = IWL_LED_ACTIVITY,
> + .interval = IWL_LED_INTERVAL,
> + };
> + struct iwl_host_cmd cmd = {
> + .id = REPLY_LEDS_CMD,
> + .len = sizeof(struct iwl_led_cmd),
> + .data = &led_cmd,
> + .meta.flags = CMD_ASYNC,
> + .meta.u.callback = iwl_led_cmd_callback,
> + };
> + u8 on;
> + unsigned long flags;
> +
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + spin_lock_irqsave(&priv->lock, flags);
> +
> + if (priv->rxtxpackets){
> + on = 1 + 250 / priv->rxtxpackets;
> + priv->rxtxpackets = 0;
> + queue_delayed_work(priv->workqueue, &priv->update_led,
> + IWL_LED_ACTIVITY_PERIOD);
> +
> + if (on == priv->led_state)
> + goto exit_unlock;
> +
> + led_cmd.on = led_cmd.off = on;
> + priv->led_state = on;
> +
> + }
> + else {
> +
> + atomic_set(&priv->ledtimer, 0);
> + led_cmd.on = led_cmd.off = 0;
> + }
> +
> + spin_unlock_irqrestore(&priv->lock, flags);
> + iwl_send_cmd(priv, &cmd);
> +
> + return;
> +
> +exit_unlock:
> + spin_unlock_irqrestore(&priv->lock, flags);
> +}
> +
> +static void iwl_led_set_rx(struct led_classdev *led_cdev,
> + enum led_brightness value)
> +{
> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
> + rx_led.cdev);
> + unsigned long flags;
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + spin_lock_irqsave(&priv->lock, flags);
> + if (!atomic_xchg(&priv->ledtimer, 1))
> + queue_delayed_work(priv->workqueue, &priv->update_led,
> + IWL_LED_ACTIVITY_PERIOD);
> + priv->rxtxpackets++;
> + spin_unlock_irqrestore(&priv->lock, flags);
> +
> +}
> +
> +static void iwl_led_set_tx(struct led_classdev *led_cdev,
> + enum led_brightness value)
> +{
> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
> + tx_led.cdev);
> + unsigned long flags;
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + spin_lock_irqsave(&priv->lock, flags);
> + if (!atomic_xchg(&priv->ledtimer, 1))
> + queue_delayed_work(priv->workqueue, &priv->update_led,
> + IWL_LED_ACTIVITY_PERIOD);
> +
> + priv->rxtxpackets++;
> + spin_unlock_irqrestore(&priv->lock, flags);
> +}
> +
> +static void iwl_led_set_assoc(struct led_classdev *led_cdev,
> + enum led_brightness value)
> +{
> + struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
> + assoc_led.cdev);
> + struct iwl_led_cmd led_cmd = {
> + .id = IWL_LED_LINK,
> + .interval = IWL_LED_INTERVAL,
> + };
> + struct iwl_host_cmd cmd = {
> + .id = REPLY_LEDS_CMD,
> + .len = sizeof(struct iwl_led_cmd),
> + .data = &led_cmd,
> + .meta.flags = CMD_ASYNC,
> + .meta.u.callback = iwl_led_cmd_callback
> + };
> +
> + if (test_bit(STATUS_EXIT_PENDING, &priv->status))
> + return;
> +
> + switch(value)
> + {
> + case LED_OFF:
> + led_cmd.off = 0;
> + led_cmd.on = 0;
> + break;
> + case LED_HALF:
> + case LED_FULL:
> + led_cmd.off = 0;
> + led_cmd.on = 40;
> + }
> + iwl_send_cmd(priv, &cmd);
> +}
> +
> +
> +static int iwl_register_led(struct iwl_priv *priv, struct iwl_led *led, char *ledname,
> + char *triggername, void (*callback)
> + (struct led_classdev *, enum led_brightness))
> +{
> + snprintf(led->name, sizeof(led->name), ledname,
> + wiphy_name(priv->hw->wiphy));
> + led->cdev.name = led->name;
> + led->cdev.brightness_set = callback;
> + led->cdev.default_trigger = triggername;
> +
> + return led_classdev_register(&priv->pci_dev->dev, &led->cdev);
> +}
> +
> +static void iwl_register_leds(struct iwl_priv *priv)
> +{
> + iwl_register_led(priv, &priv->tx_led, "iwl-%s:tx",
> + ieee80211_get_tx_led_name(priv->hw),
> + iwl_led_set_tx);
> + iwl_register_led(priv, &priv->rx_led, "iwl-%s:rx",
> + ieee80211_get_rx_led_name(priv->hw),
> + iwl_led_set_rx);
> + iwl_register_led(priv, &priv->assoc_led, "iwl-%s:asoc",
> + ieee80211_get_assoc_led_name(priv->hw),
> + iwl_led_set_assoc);
> +}
> +
> +static void iwl_unregister_leds(struct iwl_priv *priv)
> +{
> + led_classdev_unregister(&priv->tx_led.cdev);
> + led_classdev_unregister(&priv->rx_led.cdev);
> + led_classdev_unregister(&priv->assoc_led.cdev);
> +}
> +#endif
>
> /**
> * iwl_alive_start - called after REPLY_ALIVE notification received
> @@ -6140,6 +6140,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
> if (iwl_is_rfkill(priv))
> return;
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> + atomic_set(&priv->ledtimer, 0);
> +#endif
> if (!priv->mac80211_registered) {
> /* Unlock so any user space entry points can call back into
> * the driver without a deadlock... */
> @@ -6158,6 +6161,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
> priv->mac80211_registered = 1;
>
> iwl_reset_channel_flag(priv);
> +#ifdef CONFIG_IWLWIFI_LEDS
> + iwl_register_leds(priv);
> +#endif
> } else
> ieee80211_start_queues(priv->hw);
>
> @@ -6217,6 +6223,10 @@ static void __iwl_down(struct iwl_priv *priv)
> if (!exit_pending)
> set_bit(STATUS_EXIT_PENDING, &priv->status);
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> + /* Prevent the led callbacks from rescheduling the update_led timer */
> + atomic_set(&priv->ledtimer, 1);
> +#endif
> iwl_clear_stations_table(priv);
>
> /* Unblock any waiting calls */
> @@ -8198,7 +8208,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
> INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
> INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
> INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
> -
> + INIT_DELAYED_WORK(&priv->update_led, iwl_bg_led_update);
> iwl_hw_setup_deferred_work(priv);
>
> tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
> @@ -8209,6 +8219,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
> {
> iwl_hw_cancel_deferred_work(priv);
>
> + cancel_delayed_work(&priv->update_led);
> cancel_delayed_work(&priv->scan_check);
> cancel_delayed_work(&priv->alive_start);
> cancel_delayed_work(&priv->post_associate);
> @@ -8531,6 +8542,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
> iwl_clear_stations_table(priv);
>
> if (priv->mac80211_registered) {
> +#ifdef CONFIG_IWLWIFI_LEDS
> + iwl_unregister_leds(priv);
> +#endif
> ieee80211_unregister_hw(priv->hw);
> iwl_rate_control_unregister(priv->hw);
> }
> diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h
> index e0b97c3..ce5d489 100644
> --- a/drivers/net/wireless/iwlwifi/iwlwifi.h
> +++ b/drivers/net/wireless/iwlwifi/iwlwifi.h
> @@ -55,6 +55,9 @@ extern struct pci_device_id iwl_hw_card_ids[];
>
> #include "iwl-prph.h"
>
> +#ifdef CONFIG_IWLWIFI_LEDS
> +#include "iwl-leds.h"
> +#endif
> /*
> * Driver implementation data structures, constants, inline
> * functions
>
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >> http://get.splunk.com/
> _______________________________________________
> Ipw3945-devel mailing list
> Ipw3945-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/ipw3945-devel
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-23 6:11 ` Jerone Young
@ 2007-10-23 6:15 ` Zhu Yi
2007-10-23 10:46 ` Norbert Preining
0 siblings, 1 reply; 13+ messages in thread
From: Zhu Yi @ 2007-10-23 6:15 UTC (permalink / raw)
To: Jerone Young; +Cc: Ian Schram, wireless, Ipw3945-devel
On Tue, 2007-10-23 at 01:11 -0500, Jerone Young wrote:
> Is this patch acceptable for everyone?
> It would be nice to finally have the wireless led indicator working.
> If this patch is ok .. I'll put out a patch for the iwl4965 and test
> it. I think since a lot of the major functionality is now in the
> driver (great job guys!) it's about time to kill these small user
Sorry, I haven't have enough time to review this patch these days. Will
try to do it next week. But any test are always welcome!
Thanks,
-yi
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-23 6:15 ` Zhu Yi
@ 2007-10-23 10:46 ` Norbert Preining
2007-10-23 11:41 ` Ian Schram
0 siblings, 1 reply; 13+ messages in thread
From: Norbert Preining @ 2007-10-23 10:46 UTC (permalink / raw)
To: linux-wireless
Zhu Yi <yi.zhu@...> writes:
aven't have enough time to review this patch these days. Will
> try to do it next week. But any test are always welcome!
I would like to, is there a way to patch this into the git sources?
I am running 2.6.23 with latest iwlwifi git sources.
I patched the git sources and started compiling with -DCONFIG_IWLWIFI_LEDS=y but
the compile boiled out with:
/src/wlan/iwlwifi/foo/compatible/iwl3945-base.c:6218: error: implicit
declaration of function 'ieee80211_get_assoc_led_name'
(and some more warnings).
Is there anything I can do to test it?
Best wishes
Norbert
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-23 10:46 ` Norbert Preining
@ 2007-10-23 11:41 ` Ian Schram
2007-10-23 11:43 ` Norbert Preining
0 siblings, 1 reply; 13+ messages in thread
From: Ian Schram @ 2007-10-23 11:41 UTC (permalink / raw)
To: Norbert Preining; +Cc: linux-wireless, ipw3945-devel
Norbert Preining wrote:
> Zhu Yi <yi.zhu@...> writes:
> aven't have enough time to review this patch these days. Will
>> try to do it next week. But any test are always welcome!
>
> I would like to, is there a way to patch this into the git sources?
the intellinuxwireless.org gits? to make it work it would require an update
of the mac80211 package, and compatibility with older kernels is probably
pretty nasty.
>
> I am running 2.6.23 with latest iwlwifi git sources.
>
> I patched the git sources and started compiling with -DCONFIG_IWLWIFI_LEDS=y but
> the compile boiled out with:
> /src/wlan/iwlwifi/foo/compatible/iwl3945-base.c:6218: error: implicit
> declaration of function 'ieee80211_get_assoc_led_name'
> (and some more warnings).
>
the association led is only in the very latest git sources, i'm guessing only
wireless-2.6 for now.
(also i have learned that i forgot to ifdef the INIT_DELAYED_WORK, I must really try to
beat this inability of sending a patch right the first time round)
i bet an iwl_is_ready(priv) call in the delayed work wouldn't hurt either,
anyway. It works for me feel free to improve it. Or wait until one of
seasoned developers, has no higher priority items on their list.
> Is there anything I can do to test it?
>
> Best wishes
>
> Norbert
>
I'll try to send a patch a bit later today to fix a few of the outstanding issues.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-23 11:41 ` Ian Schram
@ 2007-10-23 11:43 ` Norbert Preining
2007-10-23 12:36 ` maximilian attems
0 siblings, 1 reply; 13+ messages in thread
From: Norbert Preining @ 2007-10-23 11:43 UTC (permalink / raw)
To: Ian Schram; +Cc: linux-wireless, ipw3945-devel
On Di, 23 Okt 2007, Ian Schram wrote:
> > I would like to, is there a way to patch this into the git sources?
> the intellinuxwireless.org gits? to make it work it would require an update
Sorry for being unclear, I meant the iwlwifi git sources (so currently
the 1.1.18 one).
> of the mac80211 package, and compatibility with older kernels is probably
> pretty nasty.
Ah, ok, so I would have to use the mac80211.git source, too.
> the association led is only in the very latest git sources, i'm guessing only
> wireless-2.6 for now.
Ok, so 2.6.23-mm1 should do the trick, am I right?
> I'll try to send a patch a bit later today to fix a few of the outstanding issues.
Thanks.
Best wishes
Norbert
-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at> Vienna University of Technology
Debian Developer <preining@debian.org> Debian TeX Group
gpg DSA: 0x09C5B094 fp: 14DF 2E6C 0307 BE6D AD76 A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
EWELME (n.)
The smile bestowed on you by an air hostess.
--- Douglas Adams, The Meaning of Liff
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-23 11:43 ` Norbert Preining
@ 2007-10-23 12:36 ` maximilian attems
0 siblings, 0 replies; 13+ messages in thread
From: maximilian attems @ 2007-10-23 12:36 UTC (permalink / raw)
To: Norbert Preining; +Cc: Ian Schram, linux-wireless, ipw3945-devel
On Tue, Oct 23, 2007 at 01:43:18PM +0200, Norbert Preining wrote:
> Ok, so 2.6.23-mm1 should do the trick, am I right?
>
current git maybe better :P
but if you are lazy we have backports in 2.6.23 trunk snapshots
-> http://wiki.debian.org/DebianKernel
--
maks
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-17 18:00 [RFC][PATCH] iwlwifi using mac80211_leds Ian Schram
2007-10-17 23:21 ` [ipw3945-devel] " Tomas Winkler
2007-10-23 6:11 ` Jerone Young
@ 2007-10-24 0:34 ` Ian Schram
2007-10-25 13:09 ` Norbert Preining
2007-11-08 6:10 ` Norbert Preining
2 siblings, 2 replies; 13+ messages in thread
From: Ian Schram @ 2007-10-24 0:34 UTC (permalink / raw)
To: wireless; +Cc: Ipw3945-devel
This is the second version of this patch with a few several bugfixes,
please test this one instead. I also included a 4965 part to the patch
so people can just test it. The code there has never been executed so
you adventurous (and responsible ;-)) if you try it on your machine.
It shouldn't print any warnings anymore when unloading the driver.
I'm still to new to kernel code to fully understand the locking, so that's
probably not entirely right. But basically it works for me ..
Signed-of-by: Ian Schram<ischram@telenet.be>
---
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 25cfc6c..8e8f835 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -126,3 +126,9 @@ config IWL3945
inserted in and remvoed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called iwl3945.ko.
+config IWLWIFI_LEDS
+ bool "IWLWIFI leds"
+ depends IWLWIFI && MAC80211_LEDS
+ default y
+ ---help---
+ This options enables the wireless led.
diff --git a/drivers/net/wireless/iwlwifi/iwl-priv.h b/drivers/net/wireless/iwlwifi/iwl-priv.h
index 6b490d0..ad05513 100644
--- a/drivers/net/wireless/iwlwifi/iwl-priv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-priv.h
@@ -127,11 +127,14 @@ struct iwl_priv {
struct iwl_init_alive_resp card_alive_init;
struct iwl_alive_resp card_alive;
-#ifdef LED
- /* LED related variables */
- struct iwl_activity_blink activity;
- unsigned long led_packets;
- int led_state;
+
+#ifdef CONFIG_IWLWIFI_LEDS
+ u8 led_state;
+ unsigned int rxtxpackets;
+ atomic_t ledtimer;
+ struct iwl_led tx_led;
+ struct iwl_led rx_led;
+ struct iwl_led assoc_led;
#endif
u16 active_rate;
@@ -274,6 +277,7 @@ struct iwl_priv {
struct delayed_work gather_stats;
struct delayed_work scan_check;
struct delayed_work post_associate;
+ struct delayed_work update_led;
#define IWL_DEFAULT_TX_POWER 0x0F
s8 user_txpower_limit;
diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h
index 432ce88..06a2839 100644
--- a/drivers/net/wireless/iwlwifi/iwlwifi.h
+++ b/drivers/net/wireless/iwlwifi/iwlwifi.h
@@ -50,6 +50,9 @@ extern struct pci_device_id iwl_hw_card_ids[];
#include "iwl-prph.h"
+#ifdef CONFIG_IWLWIFI_LEDS
+#include "iwl-leds.h"
+#endif
/*
* Driver implementation data structures, constants, inline
* functions
diff --git a/drivers/net/wireless/iwlwifi/iwl-leds.h b/drivers/net/wireless/iwlwifi/iwl-leds.h
new file mode 100644
index 0000000..07a55f0
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-leds.h
@@ -0,0 +1,20 @@
+#ifndef __iwl_leds_h__
+#define __iwl_leds_h__
+
+
+#include <linux/leds.h>
+
+
+#define IWL_LED_ACTIVITY (0<<1)
+#define IWL_LED_LINK (1<<1)
+#define IWL_LED_INTERVAL __constant_cpu_to_le32(1000)
+#define IWL_LED_ACTIVITY_PERIOD msecs_to_jiffies(500)
+#define IWL_LED_MAX_NAME_LEN 31
+
+struct iwl_led {
+ char name[IWL_LED_MAX_NAME_LEN + 1];
+ struct led_classdev cdev;
+};
+
+
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 05e1135..4835ee0 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6073,6 +6073,173 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->restart);
}
+#ifdef CONFIG_IWLWIFI_LEDS
+static int iwl_led_cmd_callback(struct iwl_priv *priv,
+ struct iwl_cmd *cmd, struct sk_buff *skb)
+{
+ return 1;
+}
+
+static void iwl_bg_led_update(struct work_struct *data)
+{
+ struct iwl_priv *priv =
+ container_of(data, struct iwl_priv, update_led.work);
+ struct iwl_led_cmd led_cmd = {
+ .id = IWL_LED_ACTIVITY,
+ .interval = IWL_LED_INTERVAL,
+ };
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_LEDS_CMD,
+ .len = sizeof(struct iwl_led_cmd),
+ .data = &led_cmd,
+ .meta.flags = CMD_ASYNC,
+ .meta.u.callback = iwl_led_cmd_callback,
+ };
+ u8 on;
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->rxtxpackets) {
+ on = 25 + 230 / (1 + (priv->rxtxpackets >> 2));
+ priv->rxtxpackets = 0;
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+
+ if (on == priv->led_state)
+ goto exit_unlock;
+
+ led_cmd.on = led_cmd.off = on;
+ priv->led_state = on;
+
+ }
+ else {
+ atomic_set(&priv->ledtimer, 0);
+ led_cmd.on = led_cmd.off = 0;
+ priv->led_state = 0;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ iwl_send_cmd(priv, &cmd);
+
+ return;
+
+exit_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwl_led_set_rx(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ rx_led.cdev);
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rxtxpackets += 2;
+ if (!atomic_xchg(&priv->ledtimer, 1))
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+}
+
+static void iwl_led_set_tx(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ tx_led.cdev);
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rxtxpackets++;
+ if (!atomic_xchg(&priv->ledtimer, 1))
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwl_led_set_assoc(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ assoc_led.cdev);
+ struct iwl_led_cmd led_cmd = {
+ .id = IWL_LED_LINK,
+ .interval = IWL_LED_INTERVAL,
+ };
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_LEDS_CMD,
+ .len = sizeof(struct iwl_led_cmd),
+ .data = &led_cmd,
+ .meta.flags = CMD_ASYNC,
+ .meta.u.callback = iwl_led_cmd_callback
+ };
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ switch(value)
+ {
+ case LED_OFF:
+ led_cmd.off = 0;
+ led_cmd.on = 0;
+ break;
+ case LED_HALF:
+ case LED_FULL:
+ led_cmd.off = 0;
+ led_cmd.on = 40;
+ }
+ iwl_send_cmd(priv, &cmd);
+}
+
+
+static int iwl_register_led(struct iwl_priv *priv, struct iwl_led *led, char *ledname,
+ char *triggername, void (*callback)
+ (struct led_classdev *, enum led_brightness))
+{
+ snprintf(led->name, sizeof(led->name), ledname,
+ wiphy_name(priv->hw->wiphy));
+ led->cdev.name = led->name;
+ led->cdev.brightness_set = callback;
+ led->cdev.default_trigger = triggername;
+
+ return led_classdev_register(&priv->pci_dev->dev, &led->cdev);
+}
+
+static void iwl_register_leds(struct iwl_priv *priv)
+{
+ iwl_register_led(priv, &priv->tx_led, "iwl-%s:tx",
+ ieee80211_get_tx_led_name(priv->hw),
+ iwl_led_set_tx);
+ iwl_register_led(priv, &priv->rx_led, "iwl-%s:rx",
+ ieee80211_get_rx_led_name(priv->hw),
+ iwl_led_set_rx);
+ iwl_register_led(priv, &priv->assoc_led, "iwl-%s:asoc",
+ ieee80211_get_assoc_led_name(priv->hw),
+ iwl_led_set_assoc);
+}
+
+static void iwl_unregister_leds(struct iwl_priv *priv)
+{
+ led_classdev_unregister(&priv->tx_led.cdev);
+ led_classdev_unregister(&priv->rx_led.cdev);
+ led_classdev_unregister(&priv->assoc_led.cdev);
+}
+#endif
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
@@ -6148,6 +6315,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
if (iwl_is_rfkill(priv))
return;
+#ifdef CONFIG_IWLWIFI_LEDS
+ atomic_set(&priv->ledtimer, 0);
+#endif
if (!priv->mac80211_registered) {
/* Unlock so any user space entry points can call back into
* the driver without a deadlock... */
@@ -6166,6 +6336,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
priv->mac80211_registered = 1;
iwl_reset_channel_flag(priv);
+#ifdef CONFIG_IWLWIFI_LEDS
+ iwl_register_leds(priv);
+#endif
} else
ieee80211_start_queues(priv->hw);
@@ -8206,7 +8379,9 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
-
+#ifdef CONFIG_IWLWIFI_LEDS
+ INIT_DELAYED_WORK(&priv->update_led, iwl_bg_led_update);
+#endif
iwl_hw_setup_deferred_work(priv);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
@@ -8217,6 +8392,9 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
iwl_hw_cancel_deferred_work(priv);
+#ifdef CONFIG_IWLWIFI_LEDS
+ cancel_delayed_work(&priv->update_led);
+#endif
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
cancel_delayed_work(&priv->post_associate);
@@ -8539,6 +8717,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
iwl_clear_stations_table(priv);
if (priv->mac80211_registered) {
+#ifdef CONFIG_IWLWIFI_LEDS
+ iwl_unregister_leds(priv);
+#endif
ieee80211_unregister_hw(priv->hw);
iwl_rate_control_unregister(priv->hw);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 90561bb..3d02e28 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -6449,6 +6449,174 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->restart);
}
+#ifdef CONFIG_IWLWIFI_LEDS
+static int iwl_led_cmd_callback(struct iwl_priv *priv,
+ struct iwl_cmd *cmd, struct sk_buff *skb)
+{
+ return 1;
+}
+
+static void iwl_bg_led_update(struct work_struct *data)
+{
+ struct iwl_priv *priv =
+ container_of(data, struct iwl_priv, update_led.work);
+ struct iwl_led_cmd led_cmd = {
+ .id = IWL_LED_ACTIVITY,
+ .interval = IWL_LED_INTERVAL,
+ };
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_LEDS_CMD,
+ .len = sizeof(struct iwl_led_cmd),
+ .data = &led_cmd,
+ .meta.flags = CMD_ASYNC,
+ .meta.u.callback = iwl_led_cmd_callback,
+ };
+ u8 on;
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->rxtxpackets) {
+ on = 25 + 230 / (1 + (priv->rxtxpackets >> 2));
+ priv->rxtxpackets = 0;
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+
+ if (on == priv->led_state)
+ goto exit_unlock;
+
+ led_cmd.on = led_cmd.off = on;
+ priv->led_state = on;
+
+ }
+ else {
+ atomic_set(&priv->ledtimer, 0);
+ led_cmd.on = led_cmd.off = 0;
+ priv->led_state = 0;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ iwl_send_cmd(priv, &cmd);
+
+ return;
+
+exit_unlock:
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwl_led_set_rx(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ rx_led.cdev);
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rxtxpackets += 2;
+ if (!atomic_xchg(&priv->ledtimer, 1))
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+}
+
+static void iwl_led_set_tx(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ tx_led.cdev);
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rxtxpackets++;
+ if (!atomic_xchg(&priv->ledtimer, 1))
+ queue_delayed_work(priv->workqueue, &priv->update_led,
+ IWL_LED_ACTIVITY_PERIOD);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwl_led_set_assoc(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv,
+ assoc_led.cdev);
+ struct iwl_led_cmd led_cmd = {
+ .id = IWL_LED_LINK,
+ .interval = IWL_LED_INTERVAL,
+ };
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_LEDS_CMD,
+ .len = sizeof(struct iwl_led_cmd),
+ .data = &led_cmd,
+ .meta.flags = CMD_ASYNC,
+ .meta.u.callback = iwl_led_cmd_callback
+ };
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+ !test_bit(STATUS_READY, &priv->status))
+ return;
+
+ switch(value)
+ {
+ case LED_OFF:
+ led_cmd.off = 0;
+ led_cmd.on = 0;
+ break;
+ case LED_HALF:
+ case LED_FULL:
+ led_cmd.off = 0;
+ led_cmd.on = 40;
+ }
+ iwl_send_cmd(priv, &cmd);
+}
+
+
+static int iwl_register_led(struct iwl_priv *priv, struct iwl_led *led, char *ledname,
+ char *triggername, void (*callback)
+ (struct led_classdev *, enum led_brightness))
+{
+ snprintf(led->name, sizeof(led->name), ledname,
+ wiphy_name(priv->hw->wiphy));
+ led->cdev.name = led->name;
+ led->cdev.brightness_set = callback;
+ led->cdev.default_trigger = triggername;
+
+ return led_classdev_register(&priv->pci_dev->dev, &led->cdev);
+}
+
+static void iwl_register_leds(struct iwl_priv *priv)
+{
+ iwl_register_led(priv, &priv->tx_led, "iwl-%s:tx",
+ ieee80211_get_tx_led_name(priv->hw),
+ iwl_led_set_tx);
+ iwl_register_led(priv, &priv->rx_led, "iwl-%s:rx",
+ ieee80211_get_rx_led_name(priv->hw),
+ iwl_led_set_rx);
+ iwl_register_led(priv, &priv->assoc_led, "iwl-%s:asoc",
+ ieee80211_get_assoc_led_name(priv->hw),
+ iwl_led_set_assoc);
+}
+
+static void iwl_unregister_leds(struct iwl_priv *priv)
+{
+ led_classdev_unregister(&priv->tx_led.cdev);
+ led_classdev_unregister(&priv->rx_led.cdev);
+ led_classdev_unregister(&priv->assoc_led.cdev);
+}
+#endif
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
@@ -6504,6 +6672,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
if (iwl_is_rfkill(priv))
return;
+#ifdef CONFIG_IWLWIFI_LEDS
+ atomic_set(&priv->ledtimer, 0);
+#endif
if (!priv->mac80211_registered) {
/* Unlock so any user space entry points can call back into
* the driver without a deadlock... */
@@ -6522,6 +6693,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
priv->mac80211_registered = 1;
iwl_reset_channel_flag(priv);
+#ifdef CONFIG_IWLWIFI_LEDS
+ iwl_register_leds(priv);
+#endif
} else
ieee80211_start_queues(priv->hw);
@@ -8801,7 +8975,9 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
-
+#ifdef CONFIG_IWLWIFI_LEDS
+ INIT_DELAYED_WORK(&priv->update_led, iwl_bg_led_update);
+#endif
iwl_hw_setup_deferred_work(priv);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
@@ -8812,6 +8988,9 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
iwl_hw_cancel_deferred_work(priv);
+#ifdef CONFIG_IWLWIFI_LEDS
+ cancel_delayed_work(&priv->update_led);
+#endif
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
cancel_delayed_work(&priv->post_associate);
@@ -9135,6 +9314,9 @@ static void iwl_pci_remove(struct pci_dev *pdev)
iwl_clear_stations_table(priv);
if (priv->mac80211_registered) {
+#ifdef CONFIG_IWLWIFI_LEDS
+ iwl_unregister_leds(priv);
+#endif
ieee80211_unregister_hw(priv->hw);
iwl_rate_control_unregister(priv->hw);
}
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-24 0:34 ` Ian Schram
@ 2007-10-25 13:09 ` Norbert Preining
2007-11-08 6:10 ` Norbert Preining
1 sibling, 0 replies; 13+ messages in thread
From: Norbert Preining @ 2007-10-25 13:09 UTC (permalink / raw)
To: Ian Schram; +Cc: wireless, Ipw3945-devel
On Mi, 24 Okt 2007, Ian Schram wrote:
> This is the second version of this patch with a few several bugfixes,
> please test this one instead. I also included a 4965 part to the patch
Hmm, patching onto 2.6.24-rc1 does work without problems, but
configuring not:
scripts/kconfig/conf -o arch/i386/Kconfig
drivers/net/wireless/iwlwifi/Kconfig:131: invalid option
make[1]: *** [oldconfig] Error 1
Must be this part:
> --- a/drivers/net/wireless/iwlwifi/Kconfig
> +++ b/drivers/net/wireless/iwlwifi/Kconfig
> @@ -126,3 +126,9 @@ config IWL3945
> inserted in and remvoed from the running kernel whenever you want),
> say M here and read <file:Documentation/modules.txt>. The module
> will be called iwl3945.ko.
> +config IWLWIFI_LEDS
> + bool "IWLWIFI leds"
> + depends IWLWIFI && MAC80211_LEDS
> + default y
> + ---help---
> + This options enables the wireless led.
I though all necessary changes are in -rc1 already, what else do I need?
Best wishes
Norbert
-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at> Vienna University of Technology
Debian Developer <preining@debian.org> Debian TeX Group
gpg DSA: 0x09C5B094 fp: 14DF 2E6C 0307 BE6D AD76 A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
Aaaargggh...'
These two words are usually coupled together in the Old
Pink Dog Bar.
--- Ford in a spot of bother.
--- Douglas Adams, The Hitchhikers Guide to the Galaxy
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
@ 2007-10-27 0:22 Ian Schram
0 siblings, 0 replies; 13+ messages in thread
From: Ian Schram @ 2007-10-27 0:22 UTC (permalink / raw)
To: Tomas Winkler; +Cc: ipw3945-devel, wireless
Tomas Winkler wrote:
> > On 10/17/07, Ian Schram <ischram@telenet.be> wrote:
>> >> I do *not* send a led command on each packet. (Unless i made a ho=
rrible
>> >> coding error that I do not see)
>> >>
>> >> I send a led command when on every association event. But that's =
only when
>> >> we actually associate. or hw/sw rfkill is activated, or deassocia=
ted.
>> >>
>> >> The leds for activity: keep a counter, which counts how many time=
s the led
>> >> is triggered from mac80211
>> >> right now this is a multiple of the #packets. A delayed work will=
run
>> >> every 500 ms and translate this
>> >> amount of packets into a blinking rate for the led. When no packe=
ts are
>> >> transeived, the delayed work
>> >> will not be scheduled until new packets are transeived.
> >
> >
> > When no packets are transmitted correct behaviour is steady light=
on.
> >
> > This is quite similar to how the leds work in
>> >> ipwraw, and ipw3945, only there the amount of byters were counted=
in the
>> >> rx and tx path, which
>> >> was then converted to a blinking rate. This information is not av=
ailable
>> >> within the led framework,
>> >> hence i used the amount of led events and translate that into a b=
linking
>> >> rate.
> >
All these comments are on the activity led code. This code is the bulk
of the patch, and proably isn't the nicest solution to the problem.
I could send a stripped down patch, that only registers the association=
led trigger.
This is something that is a lot easier the mac80211_leds way.
This basic functionality of the led being on when associated, is still =
a nice
gimmick imho. Second only to the firmware filename it's the comment i m=
ost
frequently read in irc.. but perhaps i have tunnel vision.
> >
> > I think we can figure out how to do it correctly we already have th=
rouput
> > masurement incorporated in.
> > Second I=B4m not sure that the wrokqueueu is really necessary. I th=
ink that
> > the command can be issued right away.
if i'm not mistaking ratescale has this data, and that there is no prob=
lem
collecting this data from the rx/tx paths. for activity, this is probab=
ly more
efficient and accurate. I just choose to do this the mac80211 way too
>> >>
>> >> I did manage to listen to your comments on my previous patch ;-)
> >
> >
> > I=B4ve just recalled I wrote already once email as this one :) . Y=
eah I
> > didn=B4t read code carefully enough.
> >
> > Actually i believe this to be a crossection of what mac80211_leds e=
xpects,
>> >> and how ipw used to
>> >> do it.
>> >>
>> >> Ian
>> >>
Ian
-
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [ipw3945-devel] [RFC][PATCH] iwlwifi using mac80211_leds
2007-10-24 0:34 ` Ian Schram
2007-10-25 13:09 ` Norbert Preining
@ 2007-11-08 6:10 ` Norbert Preining
1 sibling, 0 replies; 13+ messages in thread
From: Norbert Preining @ 2007-11-08 6:10 UTC (permalink / raw)
To: Ian Schram; +Cc: wireless, Ipw3945-devel
On Mi, 24 Okt 2007, Ian Schram wrote:
> This is the second version of this patch with a few several bugfixes,
> please test this one instead. I also included a 4965 part to the patch
Works nicely with 2.6.24-rc2. Finally the led of my laptop is orange
again. Thanks.
Needed only a simple Kconfig fix.
Best wishes
Norbert
-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at> Vienna University of Technology
Debian Developer <preining@debian.org> Debian TeX Group
gpg DSA: 0x09C5B094 fp: 14DF 2E6C 0307 BE6D AD76 A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
TOTTERIDGE (n.)
The ridiculous two-inch hunch that people adopt when arriving late for
the theatre in the vain and futile hope that it will minimise either
the embarrassment of the lack of visibility for the rest of the
audience. c.f. hickling.
--- Douglas Adams, The Meaning of Liff
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2007-11-08 6:10 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-17 18:00 [RFC][PATCH] iwlwifi using mac80211_leds Ian Schram
2007-10-17 23:21 ` [ipw3945-devel] " Tomas Winkler
2007-10-18 1:45 ` Ian Schram
2007-10-23 6:11 ` Jerone Young
2007-10-23 6:15 ` Zhu Yi
2007-10-23 10:46 ` Norbert Preining
2007-10-23 11:41 ` Ian Schram
2007-10-23 11:43 ` Norbert Preining
2007-10-23 12:36 ` maximilian attems
2007-10-24 0:34 ` Ian Schram
2007-10-25 13:09 ` Norbert Preining
2007-11-08 6:10 ` Norbert Preining
-- strict thread matches above, loose matches on Subject: below --
2007-10-27 0:22 Ian Schram
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).