wil6210: add support for device led configuration
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> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
41842dc1f0
commit
10d599ad84
|
@ -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},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in New Issue