diff mbox

[v2,7/7] wil6210: add support for device led configuration

Message ID 1461589078-29854-8-git-send-email-qca_merez@qca.qualcomm.com (mailing list archive)
State Accepted
Commit 21f6a4c5ccba672937704cf69500df0e9e56b56a
Delegated to: Kalle Valo
Headers show

Commit Message

Maya Erez April 25, 2016, 12:57 p.m. UTC
Add the ability to configure the device led to be used for notifying
the AP activity (60G device supports leds 0-2).
The host can also configure the blinking frequency of the led in
three states.

Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
---
 drivers/net/wireless/ath/wil6210/debugfs.c | 115 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/main.c    |   3 +
 drivers/net/wireless/ath/wil6210/wil6210.h |  25 +++++++
 drivers/net/wireless/ath/wil6210/wmi.c     |  77 +++++++++++++++++++
 drivers/net/wireless/ath/wil6210/wmi.h     |  61 +++++++++++++++
 5 files changed, 281 insertions(+)

Comments

Kalle Valo April 25, 2016, 6:56 p.m. UTC | #1
Maya Erez <qca_merez@qca.qualcomm.com> writes:

> Add the ability to configure the device led to be used for notifying
> the AP activity (60G device supports leds 0-2).
> The host can also configure the blinking frequency of the led in
> three states.

[...]

> +/* led_blink_time, write:
> + * "<blink_on_slow> <blink_off_slow> <blink_on_med> <blink_off_med> <blink_on_fast> <blink_off_fast>
> + */
> +static ssize_t wil_write_led_blink_time(struct file *file,
> +					const char __user *buf,
> +					size_t len, loff_t *ppos)
> +{
> +	int rc;
> +	char *kbuf = kmalloc(len + 1, GFP_KERNEL);
> +
> +	if (!kbuf)
> +		return -ENOMEM;
> +
> +	rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
> +	if (rc != len) {
> +		kfree(kbuf);
> +		return rc >= 0 ? -EIO : rc;
> +	}
> +
> +	kbuf[len] = '\0';
> +	rc = sscanf(kbuf, "%d %d %d %d %d %d",
> +		    &led_blink_time[WIL_LED_TIME_SLOW].on_ms,
> +		    &led_blink_time[WIL_LED_TIME_SLOW].off_ms,
> +		    &led_blink_time[WIL_LED_TIME_MED].on_ms,
> +		    &led_blink_time[WIL_LED_TIME_MED].off_ms,
> +		    &led_blink_time[WIL_LED_TIME_FAST].on_ms,
> +		    &led_blink_time[WIL_LED_TIME_FAST].off_ms);
> +	kfree(kbuf);
> +
> +	if (rc < 0)
> +		return rc;
> +	if (rc < 6)
> +		return -EINVAL;
> +
> +	return len;
> +}

Don't we already have a proper framework for leds? At least
include/linux/led.h and drivers/led/ makes me suspect that. I'm not
really fond of the idea reinventing the wheel, unless there's a really
good reason.
Maya Erez May 1, 2016, 7:06 a.m. UTC | #2
On 2016-04-25 21:56, Kalle Valo wrote:
> Maya Erez <qca_merez@qca.qualcomm.com> writes:
> 
>> Add the ability to configure the device led to be used for notifying
>> the AP activity (60G device supports leds 0-2).
>> The host can also configure the blinking frequency of the led in
>> three states.
> 
> [...]
> 
>> +/* led_blink_time, write:
>> + * "<blink_on_slow> <blink_off_slow> <blink_on_med> <blink_off_med>
> <blink_on_fast> <blink_off_fast>
>> + */
>> +static ssize_t wil_write_led_blink_time(struct file *file,
>> +					const char __user *buf,
>> +					size_t len, loff_t *ppos)
>> +{
>> +	int rc;
>> +	char *kbuf = kmalloc(len + 1, GFP_KERNEL);
>> +
>> +	if (!kbuf)
>> +		return -ENOMEM;
>> +
>> +	rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
>> +	if (rc != len) {
>> +		kfree(kbuf);
>> +		return rc >= 0 ? -EIO : rc;
>> +	}
>> +
>> +	kbuf[len] = '\0';
>> +	rc = sscanf(kbuf, "%d %d %d %d %d %d",
>> +		    &led_blink_time[WIL_LED_TIME_SLOW].on_ms,
>> +		    &led_blink_time[WIL_LED_TIME_SLOW].off_ms,
>> +		    &led_blink_time[WIL_LED_TIME_MED].on_ms,
>> +		    &led_blink_time[WIL_LED_TIME_MED].off_ms,
>> +		    &led_blink_time[WIL_LED_TIME_FAST].on_ms,
>> +		    &led_blink_time[WIL_LED_TIME_FAST].off_ms);
>> +	kfree(kbuf);
>> +
>> +	if (rc < 0)
>> +		return rc;
>> +	if (rc < 6)
>> +		return -EINVAL;
>> +
>> +	return len;
>> +}
> 
> Don't we already have a proper framework for leds? At least
> include/linux/led.h and drivers/led/ makes me suspect that. I'm not
> really fond of the idea reinventing the wheel, unless there's a really
> good reason.

The kernel led framework provides the host the ability to toggle a 
defined led,
but in our case the led toggling is fully offloaded to the device.
The host only configures the device with the led to activate and its 
parameters.
I agree that reusing an existing framework should be enforced when 
possible,
but as the WIL6210 host needs to align to the device led configuration
we cannot reuse the led kernel framework.
Kalle Valo May 11, 2016, 7:34 p.m. UTC | #3
merez@codeaurora.org writes:

> On 2016-04-25 21:56, Kalle Valo wrote:
>> Maya Erez <qca_merez@qca.qualcomm.com> writes:
>>
>>> Add the ability to configure the device led to be used for notifying
>>> the AP activity (60G device supports leds 0-2).
>>> The host can also configure the blinking frequency of the led in
>>> three states.
>>
>> [...]
>>
>>> +/* led_blink_time, write:
>>> + * "<blink_on_slow> <blink_off_slow> <blink_on_med> <blink_off_med>
>> <blink_on_fast> <blink_off_fast>
>>> + */
>>> +static ssize_t wil_write_led_blink_time(struct file *file,
>>> +					const char __user *buf,
>>> +					size_t len, loff_t *ppos)
>>> +{
>>> +	int rc;
>>> +	char *kbuf = kmalloc(len + 1, GFP_KERNEL);
>>> +
>>> +	if (!kbuf)
>>> +		return -ENOMEM;
>>> +
>>> +	rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
>>> +	if (rc != len) {
>>> +		kfree(kbuf);
>>> +		return rc >= 0 ? -EIO : rc;
>>> +	}
>>> +
>>> +	kbuf[len] = '\0';
>>> +	rc = sscanf(kbuf, "%d %d %d %d %d %d",
>>> +		    &led_blink_time[WIL_LED_TIME_SLOW].on_ms,
>>> +		    &led_blink_time[WIL_LED_TIME_SLOW].off_ms,
>>> +		    &led_blink_time[WIL_LED_TIME_MED].on_ms,
>>> +		    &led_blink_time[WIL_LED_TIME_MED].off_ms,
>>> +		    &led_blink_time[WIL_LED_TIME_FAST].on_ms,
>>> +		    &led_blink_time[WIL_LED_TIME_FAST].off_ms);
>>> +	kfree(kbuf);
>>> +
>>> +	if (rc < 0)
>>> +		return rc;
>>> +	if (rc < 6)
>>> +		return -EINVAL;
>>> +
>>> +	return len;
>>> +}
>>
>> Don't we already have a proper framework for leds? At least
>> include/linux/led.h and drivers/led/ makes me suspect that. I'm not
>> really fond of the idea reinventing the wheel, unless there's a really
>> good reason.
>
> The kernel led framework provides the host the ability to toggle a
> defined led, but in our case the led toggling is fully offloaded to
> the device. The host only configures the device with the led to
> activate and its parameters. I agree that reusing an existing
> framework should be enforced when possible, but as the WIL6210 host
> needs to align to the device led configuration we cannot reuse the led
> kernel framework.

Ok, thanks for checking. I'll apply the patch now.
Kalle Valo May 11, 2016, 7:46 p.m. UTC | #4
Maya Erez <qca_merez@qca.qualcomm.com> wrote:
> Add the ability to configure the device led to be used for notifying
> the AP activity (60G device supports leds 0-2).
> The host can also configure the blinking frequency of the led in
> three states.
> 
> Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>

Thanks, 1 patch applied to ath.git:

10d599ad84a1 wil6210: add support for device led configuration
diff mbox

Patch

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 5d8823d..a8098b4 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1441,6 +1441,118 @@  static const struct file_operations fops_sta = {
 	.llseek		= seq_lseek,
 };
 
+static ssize_t wil_read_file_led_cfg(struct file *file, char __user *user_buf,
+				     size_t count, loff_t *ppos)
+{
+	char buf[80];
+	int n;
+
+	n = snprintf(buf, sizeof(buf),
+		     "led_id is set to %d, echo 1 to enable, 0 to disable\n",
+		     led_id);
+
+	n = min_t(int, n, sizeof(buf));
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       buf, n);
+}
+
+static ssize_t wil_write_file_led_cfg(struct file *file,
+				      const char __user *buf_,
+				      size_t count, loff_t *ppos)
+{
+	struct wil6210_priv *wil = file->private_data;
+	int val;
+	int rc;
+
+	rc = kstrtoint_from_user(buf_, count, 0, &val);
+	if (rc) {
+		wil_err(wil, "Invalid argument\n");
+		return rc;
+	}
+
+	wil_info(wil, "%s led %d\n", val ? "Enabling" : "Disabling", led_id);
+	rc = wmi_led_cfg(wil, val);
+	if (rc) {
+		wil_info(wil, "%s led %d failed\n",
+			 val ? "Enabling" : "Disabling", led_id);
+		return rc;
+	}
+
+	return count;
+}
+
+static const struct file_operations fops_led_cfg = {
+	.read = wil_read_file_led_cfg,
+	.write = wil_write_file_led_cfg,
+	.open  = simple_open,
+};
+
+/* led_blink_time, write:
+ * "<blink_on_slow> <blink_off_slow> <blink_on_med> <blink_off_med> <blink_on_fast> <blink_off_fast>
+ */
+static ssize_t wil_write_led_blink_time(struct file *file,
+					const char __user *buf,
+					size_t len, loff_t *ppos)
+{
+	int rc;
+	char *kbuf = kmalloc(len + 1, GFP_KERNEL);
+
+	if (!kbuf)
+		return -ENOMEM;
+
+	rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
+	if (rc != len) {
+		kfree(kbuf);
+		return rc >= 0 ? -EIO : rc;
+	}
+
+	kbuf[len] = '\0';
+	rc = sscanf(kbuf, "%d %d %d %d %d %d",
+		    &led_blink_time[WIL_LED_TIME_SLOW].on_ms,
+		    &led_blink_time[WIL_LED_TIME_SLOW].off_ms,
+		    &led_blink_time[WIL_LED_TIME_MED].on_ms,
+		    &led_blink_time[WIL_LED_TIME_MED].off_ms,
+		    &led_blink_time[WIL_LED_TIME_FAST].on_ms,
+		    &led_blink_time[WIL_LED_TIME_FAST].off_ms);
+	kfree(kbuf);
+
+	if (rc < 0)
+		return rc;
+	if (rc < 6)
+		return -EINVAL;
+
+	return len;
+}
+
+static ssize_t wil_read_led_blink_time(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	static char text[400];
+
+	snprintf(text, sizeof(text),
+		 "To set led blink on/off time variables write:\n"
+		 "<blink_on_slow> <blink_off_slow> <blink_on_med> "
+		 "<blink_off_med> <blink_on_fast> <blink_off_fast>\n"
+		 "The current values are:\n"
+		 "%d %d %d %d %d %d\n",
+		 led_blink_time[WIL_LED_TIME_SLOW].on_ms,
+		 led_blink_time[WIL_LED_TIME_SLOW].off_ms,
+		 led_blink_time[WIL_LED_TIME_MED].on_ms,
+		 led_blink_time[WIL_LED_TIME_MED].off_ms,
+		 led_blink_time[WIL_LED_TIME_FAST].on_ms,
+		 led_blink_time[WIL_LED_TIME_FAST].off_ms);
+
+	return simple_read_from_buffer(user_buf, count, ppos, text,
+				       sizeof(text));
+}
+
+static const struct file_operations fops_led_blink_time = {
+	.read = wil_read_led_blink_time,
+	.write = wil_write_led_blink_time,
+	.open  = simple_open,
+};
+
 /*----------------*/
 static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
 				       struct dentry *dbg)
@@ -1489,6 +1601,8 @@  static const struct {
 	{"link",	S_IRUGO,		&fops_link},
 	{"info",	S_IRUGO,		&fops_info},
 	{"recovery",	S_IRUGO | S_IWUSR,	&fops_recovery},
+	{"led_cfg",	S_IRUGO | S_IWUSR,	&fops_led_cfg},
+	{"led_blink_time",	S_IRUGO | S_IWUSR,	&fops_led_blink_time},
 };
 
 static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1551,6 +1665,7 @@  static const struct dbg_off dbg_statics[] = {
 	{"mem_addr",	S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32},
 	{"vring_idle_trsh", S_IRUGO | S_IWUSR, (ulong)&vring_idle_trsh,
 	 doff_u32},
+	{"led_polarity", S_IRUGO | S_IWUSR, (ulong)&led_polarity, doff_u8},
 	{},
 };
 
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index f7ed651..8e31d75 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -841,6 +841,9 @@  int wil_reset(struct wil6210_priv *wil, bool load_fw)
 	wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
 	wil_bcast_fini(wil);
 
+	/* Disable device led before reset*/
+	wmi_led_cfg(wil, false);
+
 	/* prevent NAPI from being scheduled and prevent wmi commands */
 	mutex_lock(&wil->wmi_mutex);
 	bitmap_zero(wil->status, wil_status_last);
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 74bc2c5..aa09cbc 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -546,6 +546,30 @@  struct wil_blob_wrapper {
 	struct debugfs_blob_wrapper blob;
 };
 
+#define WIL_LED_MAX_ID			(2)
+#define WIL_LED_INVALID_ID		(0xF)
+#define WIL_LED_BLINK_ON_SLOW_MS	(300)
+#define WIL_LED_BLINK_OFF_SLOW_MS	(300)
+#define WIL_LED_BLINK_ON_MED_MS		(200)
+#define WIL_LED_BLINK_OFF_MED_MS	(200)
+#define WIL_LED_BLINK_ON_FAST_MS	(100)
+#define WIL_LED_BLINK_OFF_FAST_MS	(100)
+enum {
+	WIL_LED_TIME_SLOW = 0,
+	WIL_LED_TIME_MED,
+	WIL_LED_TIME_FAST,
+	WIL_LED_TIME_LAST,
+};
+
+struct blink_on_off_time {
+	u32 on_ms;
+	u32 off_ms;
+};
+
+extern struct blink_on_off_time led_blink_time[WIL_LED_TIME_LAST];
+extern u8 led_id;
+extern u8 led_polarity;
+
 struct wil6210_priv {
 	struct pci_dev *pdev;
 	struct wireless_dev *wdev;
@@ -834,6 +858,7 @@  int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
 int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 		  u8 chan, u8 hidden_ssid, u8 is_go);
 int wmi_pcp_stop(struct wil6210_priv *wil);
+int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
 void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
 			u16 reason_code, bool from_event);
 void wil_probe_client_flush(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index f83bde1..c9fef36 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -32,6 +32,11 @@  module_param(agg_wsize, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
 		 " 0 - use default; < 0 - don't auto-establish");
 
+u8 led_id = WIL_LED_INVALID_ID;
+module_param(led_id, byte, S_IRUGO);
+MODULE_PARM_DESC(led_id,
+		 " 60G device led enablement. Set the led ID (0-2) to enable");
+
 /**
  * WMI event receiving - theory of operations
  *
@@ -94,6 +99,14 @@  const struct fw_map fw_mapping[] = {
 	 */
 };
 
+struct blink_on_off_time led_blink_time[] = {
+	{WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS},
+	{WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS},
+	{WIL_LED_BLINK_ON_FAST_MS, WIL_LED_BLINK_OFF_FAST_MS},
+};
+
+u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
+
 /**
  * return AHB address for given firmware/ucode internal (linker) address
  * @x - internal address
@@ -971,6 +984,60 @@  int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
 	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
 }
 
+int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
+{
+	int rc = 0;
+	struct wmi_led_cfg_cmd cmd = {
+		.led_mode = enable,
+		.id = led_id,
+		.slow_blink_cfg.blink_on =
+			cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].on_ms),
+		.slow_blink_cfg.blink_off =
+			cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].off_ms),
+		.medium_blink_cfg.blink_on =
+			cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].on_ms),
+		.medium_blink_cfg.blink_off =
+			cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].off_ms),
+		.fast_blink_cfg.blink_on =
+			cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].on_ms),
+		.fast_blink_cfg.blink_off =
+			cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].off_ms),
+		.led_polarity = led_polarity,
+	};
+	struct {
+		struct wmi_cmd_hdr wmi;
+		struct wmi_led_cfg_done_event evt;
+	} __packed reply;
+
+	if (led_id == WIL_LED_INVALID_ID)
+		goto out;
+
+	if (led_id > WIL_LED_MAX_ID) {
+		wil_err(wil, "Invalid led id %d\n", led_id);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	wil_dbg_wmi(wil,
+		    "%s led %d\n",
+		    enable ? "enabling" : "disabling", led_id);
+
+	rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd),
+		      WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
+		      100);
+	if (rc)
+		goto out;
+
+	if (reply.evt.status) {
+		wil_err(wil, "led %d cfg failed with status %d\n",
+			led_id, le32_to_cpu(reply.evt.status));
+		rc = -EINVAL;
+	}
+
+out:
+	return rc;
+}
+
 int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 		  u8 chan, u8 hidden_ssid, u8 is_go)
 {
@@ -1013,11 +1080,21 @@  int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 	if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
 		rc = -EINVAL;
 
+	if (wmi_nettype != WMI_NETTYPE_P2P)
+		/* Don't fail due to error in the led configuration */
+		wmi_led_cfg(wil, true);
+
 	return rc;
 }
 
 int wmi_pcp_stop(struct wil6210_priv *wil)
 {
+	int rc;
+
+	rc = wmi_led_cfg(wil, false);
+	if (rc)
+		return rc;
+
 	return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
 			WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
 }
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 29865e0..685fe0d 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -129,6 +129,7 @@  enum wmi_command_id {
 	WMI_THERMAL_THROTTLING_GET_STATUS_CMDID	= 0x855,
 	WMI_OTP_READ_CMDID			= 0x856,
 	WMI_OTP_WRITE_CMDID			= 0x857,
+	WMI_LED_CFG_CMDID			= 0x858,
 	/* Performance monitoring commands */
 	WMI_BF_CTRL_CMDID			= 0x862,
 	WMI_NOTIFY_REQ_CMDID			= 0x863,
@@ -868,6 +869,7 @@  enum wmi_event_id {
 	WMI_RX_MGMT_PACKET_EVENTID		= 0x1840,
 	WMI_TX_MGMT_PACKET_EVENTID		= 0x1841,
 	WMI_OTP_READ_RESULT_EVENTID		= 0x1856,
+	WMI_LED_CFG_DONE_EVENTID		= 0x1858,
 	/* Performance monitoring events */
 	WMI_DATA_PORT_OPEN_EVENTID		= 0x1860,
 	WMI_WBE_LINK_DOWN_EVENTID		= 0x1861,
@@ -1349,4 +1351,63 @@  enum wmi_hidden_ssid {
 	WMI_HIDDEN_SSID_CLEAR		= 0xFE,
 };
 
+/* WMI_LED_CFG_CMDID
+ *
+ * Configure LED On\Off\Blinking operation
+ *
+ * Returned events:
+ * - WMI_LED_CFG_DONE_EVENTID
+ */
+enum led_mode {
+	LED_DISABLE	= 0x00,
+	LED_ENABLE	= 0x01,
+};
+
+/* The names of the led as
+ * described on HW schemes.
+ */
+enum wmi_led_id {
+	WMI_LED_WLAN	= 0x00,
+	WMI_LED_WPAN	= 0x01,
+	WMI_LED_WWAN	= 0x02,
+};
+
+/* Led polarity mode. */
+enum wmi_led_polarity {
+	LED_POLARITY_HIGH_ACTIVE	= 0x00,
+	LED_POLARITY_LOW_ACTIVE		= 0x01,
+};
+
+/* Combination of on and off
+ * creates the blinking period
+ */
+struct wmi_led_blink_mode {
+	__le32 blink_on;
+	__le32 blink_off;
+} __packed;
+
+/* WMI_LED_CFG_CMDID */
+struct wmi_led_cfg_cmd {
+	/* enum led_mode_e */
+	u8 led_mode;
+	/* enum wmi_led_id_e */
+	u8 id;
+	/* slow speed blinking combination */
+	struct wmi_led_blink_mode slow_blink_cfg;
+	/* medium speed blinking combination */
+	struct wmi_led_blink_mode medium_blink_cfg;
+	/* high speed blinking combination */
+	struct wmi_led_blink_mode fast_blink_cfg;
+	/* polarity of the led */
+	u8 led_polarity;
+	/* reserved */
+	u8 reserved;
+} __packed;
+
+/* WMI_LED_CFG_DONE_EVENTID */
+struct wmi_led_cfg_done_event {
+	/* led config status */
+	__le32 status;
+} __packed;
+
 #endif /* __WILOCITY_WMI_H__ */