Loading drivers/net/wireless/ath/wil6210/cfg80211.c +3 −2 Original line number Diff line number Diff line Loading @@ -374,8 +374,9 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } /* scan on P2P_DEVICE is handled as p2p search */ if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { /* social scan on P2P_DEVICE is handled as p2p search */ if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE && wil_p2p_is_social_scan(request)) { wil->scan_request = request; wil->radio_wdev = wdev; rc = wil_p2p_search(wil, request); Loading drivers/net/wireless/ath/wil6210/debug.c +19 −3 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include "wil6210.h" #include "trace.h" void wil_err(struct wil6210_priv *wil, const char *fmt, ...) void __wil_err(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { Loading @@ -32,7 +32,7 @@ void wil_err(struct wil6210_priv *wil, const char *fmt, ...) va_end(args); } void wil_info(struct wil6210_priv *wil, const char *fmt, ...) void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { Loading @@ -47,7 +47,7 @@ void wil_info(struct wil6210_priv *wil, const char *fmt, ...) va_end(args); } void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) { if (net_ratelimit()) { struct net_device *ndev = wil_to_ndev(wil); Loading @@ -64,6 +64,22 @@ void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) } } void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) { struct va_format vaf; va_list args; if (!net_ratelimit()) return; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_dbg(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_dbg(&vaf); va_end(args); } void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...) { struct va_format vaf = { Loading drivers/net/wireless/ath/wil6210/debugfs.c +131 −10 Original line number Diff line number Diff line Loading @@ -165,6 +165,8 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, int rsize; uint i; wil_halp_vote(wil); wil_memcpy_fromio_32(&r, off, sizeof(r)); wil_mbox_ring_le2cpus(&r); /* Loading Loading @@ -241,6 +243,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, } out: seq_puts(s, "}\n"); wil_halp_unvote(wil); } static int wil_mbox_debugfs_show(struct seq_file *s, void *data) Loading Loading @@ -505,9 +508,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { enum { max_count = 4096 }; struct debugfs_blob_wrapper *blob = file->private_data; struct wil_blob_wrapper *wil_blob = file->private_data; loff_t pos = *ppos; size_t available = blob->size; size_t available = wil_blob->blob.size; void *buf; size_t ret; Loading @@ -526,8 +529,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + pos, count); wil_memcpy_fromio_halp_vote(wil_blob->wil, buf, (const volatile void __iomem *) wil_blob->blob.data + pos, count); ret = copy_to_user(user_buf, buf, count); kfree(buf); Loading @@ -550,9 +554,9 @@ static struct dentry *wil_debugfs_create_ioblob(const char *name, umode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob) struct wil_blob_wrapper *wil_blob) { return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob); } /*---reset---*/ Loading Loading @@ -843,7 +847,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, u16 cmdid; int rc, rc1; if (cmdlen <= 0) if (cmdlen < 0) return -EINVAL; wmi = kmalloc(len, GFP_KERNEL); Loading @@ -856,7 +860,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, return rc; } cmd = &wmi[1]; cmd = (cmdlen > 0) ? &wmi[1] : NULL; cmdid = le16_to_cpu(wmi->command_id); rc1 = wmi_send(wil, cmdid, cmd, cmdlen); Loading Loading @@ -1464,6 +1468,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) Loading @@ -1472,16 +1588,18 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, char name[32]; for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { struct debugfs_blob_wrapper *blob = &wil->blobs[i]; struct wil_blob_wrapper *wil_blob = &wil->blobs[i]; struct debugfs_blob_wrapper *blob = &wil_blob->blob; const struct fw_map *map = &fw_mapping[i]; if (!map->name) continue; wil_blob->wil = wil; blob->data = (void * __force)wil->csr + HOSTADDR(map->host); blob->size = map->to - map->from; snprintf(name, sizeof(name), "blob_%s", map->name); wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob); wil_debugfs_create_ioblob(name, S_IRUGO, dbg, wil_blob); } } Loading Loading @@ -1510,6 +1628,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, Loading Loading @@ -1572,6 +1692,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}, {}, }; Loading drivers/net/wireless/ath/wil6210/interrupt.c +72 −21 Original line number Diff line number Diff line Loading @@ -36,14 +36,18 @@ */ #define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) #define WIL6210_IRQ_DISABLE_NO_HALP (0xF7FFFFFFUL) #define WIL6210_IMC_RX (BIT_DMA_EP_RX_ICR_RX_DONE | \ BIT_DMA_EP_RX_ICR_RX_HTRSH) #define WIL6210_IMC_RX_NO_RX_HTRSH (WIL6210_IMC_RX & \ (~(BIT_DMA_EP_RX_ICR_RX_HTRSH))) #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) #define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \ #define WIL6210_IMC_MISC_NO_HALP (ISR_MISC_FW_READY | \ ISR_MISC_MBOX_EVT | \ ISR_MISC_FW_ERROR) #define WIL6210_IMC_MISC (WIL6210_IMC_MISC_NO_HALP | \ BIT_DMA_EP_MISC_ICR_HALP) #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ BIT_DMA_PSEUDO_CAUSE_TX | \ BIT_DMA_PSEUDO_CAUSE_MISC)) Loading @@ -51,6 +55,7 @@ #if defined(CONFIG_WIL6210_ISR_COR) /* configure to Clear-On-Read mode */ #define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) #define WIL_ICR_ICC_MISC_VALUE (0xF7FFFFFFUL) static inline void wil_icr_clear(u32 x, void __iomem *addr) { Loading @@ -58,6 +63,7 @@ static inline void wil_icr_clear(u32 x, void __iomem *addr) #else /* defined(CONFIG_WIL6210_ISR_COR) */ /* configure to Write-1-to-Clear mode */ #define WIL_ICR_ICC_VALUE (0UL) #define WIL_ICR_ICC_MISC_VALUE (0UL) static inline void wil_icr_clear(u32 x, void __iomem *addr) { Loading Loading @@ -86,10 +92,21 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil) WIL6210_IRQ_DISABLE); } static void wil6210_mask_irq_misc(struct wil6210_priv *wil) static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp) { wil_dbg_irq(wil, "%s: mask_halp(%s)\n", __func__, mask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), WIL6210_IRQ_DISABLE); mask_halp ? WIL6210_IRQ_DISABLE : WIL6210_IRQ_DISABLE_NO_HALP); } static void wil6210_mask_halp(struct wil6210_priv *wil) { wil_dbg_irq(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), BIT_DMA_EP_MISC_ICR_HALP); } static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) Loading @@ -109,14 +126,27 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil) void wil6210_unmask_irq_rx(struct wil6210_priv *wil) { bool unmask_rx_htrsh = test_bit(wil_status_fwconnected, wil->status); wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC), WIL6210_IMC_RX); unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); } static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) { wil_dbg_irq(wil, "%s: unmask_halp(%s)\n", __func__, unmask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), WIL6210_IMC_MISC); unmask_halp ? WIL6210_IMC_MISC : WIL6210_IMC_MISC_NO_HALP); } static void wil6210_unmask_halp(struct wil6210_priv *wil) { wil_dbg_irq(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), BIT_DMA_EP_MISC_ICR_HALP); } static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) Loading @@ -134,7 +164,7 @@ void wil_mask_irq(struct wil6210_priv *wil) wil6210_mask_irq_tx(wil); wil6210_mask_irq_rx(wil); wil6210_mask_irq_misc(wil); wil6210_mask_irq_misc(wil, true); wil6210_mask_irq_pseudo(wil); } Loading @@ -147,12 +177,12 @@ void wil_unmask_irq(struct wil6210_priv *wil) wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_VALUE); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_VALUE); WIL_ICR_ICC_MISC_VALUE); wil6210_unmask_irq_pseudo(wil); wil6210_unmask_irq_tx(wil); wil6210_unmask_irq_rx(wil); wil6210_unmask_irq_misc(wil); wil6210_unmask_irq_misc(wil, true); } void wil_configure_interrupt_moderation(struct wil6210_priv *wil) Loading Loading @@ -228,11 +258,8 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) */ if (likely(isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH))) { wil_dbg_irq(wil, "RX done\n"); if (unlikely(isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)) wil_err_ratelimited(wil, "Received \"Rx buffer is in risk of overflow\" interrupt\n"); wil_dbg_irq(wil, "RX done / RX_HTRSH received, ISR (0x%x)\n", isr); isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH); Loading Loading @@ -344,7 +371,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) return IRQ_NONE; } wil6210_mask_irq_misc(wil); wil6210_mask_irq_misc(wil, false); if (isr & ISR_MISC_FW_ERROR) { u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); Loading Loading @@ -372,12 +399,19 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) isr &= ~ISR_MISC_FW_READY; } if (isr & BIT_DMA_EP_MISC_ICR_HALP) { wil_dbg_irq(wil, "%s: HALP IRQ invoked\n", __func__); wil6210_mask_halp(wil); isr &= ~BIT_DMA_EP_MISC_ICR_HALP; complete(&wil->halp.comp); } wil->isr_misc = isr; if (isr) { return IRQ_WAKE_THREAD; } else { wil6210_unmask_irq_misc(wil); wil6210_unmask_irq_misc(wil, false); return IRQ_HANDLED; } } Loading Loading @@ -414,7 +448,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) wil->isr_misc = 0; wil6210_unmask_irq_misc(wil); wil6210_unmask_irq_misc(wil, false); return IRQ_HANDLED; } Loading Loading @@ -556,6 +590,23 @@ void wil6210_clear_irq(struct wil6210_priv *wil) wmb(); /* make sure write completed */ } void wil6210_set_halp(struct wil6210_priv *wil) { wil_dbg_misc(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS), BIT_DMA_EP_MISC_ICR_HALP); } void wil6210_clear_halp(struct wil6210_priv *wil) { wil_dbg_misc(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR), BIT_DMA_EP_MISC_ICR_HALP); wil6210_unmask_halp(wil); } int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi) { int rc; Loading drivers/net/wireless/ath/wil6210/main.c +92 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "wmi.h" #include "boot_loader.h" #define WAIT_FOR_HALP_VOTE_MS 100 bool debug_fw; /* = false; */ module_param(debug_fw, bool, S_IRUGO); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); Loading Loading @@ -132,6 +134,14 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, *d++ = __raw_readl(s++); } void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst, const volatile void __iomem *src, size_t count) { wil_halp_vote(wil); wil_memcpy_fromio_32(dst, src, count); wil_halp_unvote(wil); } void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count) { Loading @@ -142,6 +152,15 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, __raw_writel(*s++, d++); } void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil, volatile void __iomem *dst, const void *src, size_t count) { wil_halp_vote(wil); wil_memcpy_toio_32(dst, src, count); wil_halp_unvote(wil); } static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, u16 reason_code, bool from_event) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) Loading Loading @@ -194,6 +213,18 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) memset(&sta->stats, 0, sizeof(sta->stats)); } static bool wil_ap_is_connected(struct wil6210_priv *wil) { int i; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { if (wil->sta[i].status == wil_sta_connected) return true; } return false; } static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, u16 reason_code, bool from_event) { Loading Loading @@ -247,6 +278,11 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, } clear_bit(wil_status_fwconnecting, wil->status); break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: if (!wil_ap_is_connected(wil)) clear_bit(wil_status_fwconnected, wil->status); break; default: break; } Loading Loading @@ -457,9 +493,11 @@ int wil_priv_init(struct wil6210_priv *wil) mutex_init(&wil->wmi_mutex); mutex_init(&wil->probe_client_mutex); mutex_init(&wil->p2p_wdev_mutex); mutex_init(&wil->halp.lock); init_completion(&wil->wmi_ready); init_completion(&wil->wmi_call); init_completion(&wil->halp.comp); wil->bcast_vring = -1; setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); Loading Loading @@ -555,12 +593,11 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable) { wil_info(wil, "%s: enable=%d\n", __func__, enable); if (enable) { if (enable) wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); } else { else wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); } } static int wil_target_reset(struct wil6210_priv *wil) { Loading Loading @@ -804,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); Loading Loading @@ -871,6 +911,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); reinit_completion(&wil->halp.comp); if (load_fw) { wil_configure_interrupt_moderation(wil); Loading Loading @@ -1061,3 +1102,51 @@ int wil_find_cid(struct wil6210_priv *wil, const u8 *mac) return rc; } void wil_halp_vote(struct wil6210_priv *wil) { unsigned long rc; unsigned long to_jiffies = msecs_to_jiffies(WAIT_FOR_HALP_VOTE_MS); mutex_lock(&wil->halp.lock); wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); if (++wil->halp.ref_cnt == 1) { wil6210_set_halp(wil); rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); if (!rc) wil_err(wil, "%s: HALP vote timed out\n", __func__); else wil_dbg_misc(wil, "%s: HALP vote completed after %d ms\n", __func__, jiffies_to_msecs(to_jiffies - rc)); } wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); } void wil_halp_unvote(struct wil6210_priv *wil) { WARN_ON(wil->halp.ref_cnt == 0); mutex_lock(&wil->halp.lock); wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); if (--wil->halp.ref_cnt == 0) { wil6210_clear_halp(wil); wil_dbg_misc(wil, "%s: HALP unvote\n", __func__); } wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); } Loading
drivers/net/wireless/ath/wil6210/cfg80211.c +3 −2 Original line number Diff line number Diff line Loading @@ -374,8 +374,9 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } /* scan on P2P_DEVICE is handled as p2p search */ if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { /* social scan on P2P_DEVICE is handled as p2p search */ if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE && wil_p2p_is_social_scan(request)) { wil->scan_request = request; wil->radio_wdev = wdev; rc = wil_p2p_search(wil, request); Loading
drivers/net/wireless/ath/wil6210/debug.c +19 −3 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ #include "wil6210.h" #include "trace.h" void wil_err(struct wil6210_priv *wil, const char *fmt, ...) void __wil_err(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { Loading @@ -32,7 +32,7 @@ void wil_err(struct wil6210_priv *wil, const char *fmt, ...) va_end(args); } void wil_info(struct wil6210_priv *wil, const char *fmt, ...) void __wil_info(struct wil6210_priv *wil, const char *fmt, ...) { struct net_device *ndev = wil_to_ndev(wil); struct va_format vaf = { Loading @@ -47,7 +47,7 @@ void wil_info(struct wil6210_priv *wil, const char *fmt, ...) va_end(args); } void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) { if (net_ratelimit()) { struct net_device *ndev = wil_to_ndev(wil); Loading @@ -64,6 +64,22 @@ void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...) } } void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...) { struct va_format vaf; va_list args; if (!net_ratelimit()) return; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; netdev_dbg(wil_to_ndev(wil), "%pV", &vaf); trace_wil6210_log_dbg(&vaf); va_end(args); } void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...) { struct va_format vaf = { Loading
drivers/net/wireless/ath/wil6210/debugfs.c +131 −10 Original line number Diff line number Diff line Loading @@ -165,6 +165,8 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, int rsize; uint i; wil_halp_vote(wil); wil_memcpy_fromio_32(&r, off, sizeof(r)); wil_mbox_ring_le2cpus(&r); /* Loading Loading @@ -241,6 +243,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, } out: seq_puts(s, "}\n"); wil_halp_unvote(wil); } static int wil_mbox_debugfs_show(struct seq_file *s, void *data) Loading Loading @@ -505,9 +508,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { enum { max_count = 4096 }; struct debugfs_blob_wrapper *blob = file->private_data; struct wil_blob_wrapper *wil_blob = file->private_data; loff_t pos = *ppos; size_t available = blob->size; size_t available = wil_blob->blob.size; void *buf; size_t ret; Loading @@ -526,8 +529,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + pos, count); wil_memcpy_fromio_halp_vote(wil_blob->wil, buf, (const volatile void __iomem *) wil_blob->blob.data + pos, count); ret = copy_to_user(user_buf, buf, count); kfree(buf); Loading @@ -550,9 +554,9 @@ static struct dentry *wil_debugfs_create_ioblob(const char *name, umode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob) struct wil_blob_wrapper *wil_blob) { return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob); } /*---reset---*/ Loading Loading @@ -843,7 +847,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, u16 cmdid; int rc, rc1; if (cmdlen <= 0) if (cmdlen < 0) return -EINVAL; wmi = kmalloc(len, GFP_KERNEL); Loading @@ -856,7 +860,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, return rc; } cmd = &wmi[1]; cmd = (cmdlen > 0) ? &wmi[1] : NULL; cmdid = le16_to_cpu(wmi->command_id); rc1 = wmi_send(wil, cmdid, cmd, cmdlen); Loading Loading @@ -1464,6 +1468,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) Loading @@ -1472,16 +1588,18 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, char name[32]; for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { struct debugfs_blob_wrapper *blob = &wil->blobs[i]; struct wil_blob_wrapper *wil_blob = &wil->blobs[i]; struct debugfs_blob_wrapper *blob = &wil_blob->blob; const struct fw_map *map = &fw_mapping[i]; if (!map->name) continue; wil_blob->wil = wil; blob->data = (void * __force)wil->csr + HOSTADDR(map->host); blob->size = map->to - map->from; snprintf(name, sizeof(name), "blob_%s", map->name); wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob); wil_debugfs_create_ioblob(name, S_IRUGO, dbg, wil_blob); } } Loading Loading @@ -1510,6 +1628,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, Loading Loading @@ -1572,6 +1692,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}, {}, }; Loading
drivers/net/wireless/ath/wil6210/interrupt.c +72 −21 Original line number Diff line number Diff line Loading @@ -36,14 +36,18 @@ */ #define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) #define WIL6210_IRQ_DISABLE_NO_HALP (0xF7FFFFFFUL) #define WIL6210_IMC_RX (BIT_DMA_EP_RX_ICR_RX_DONE | \ BIT_DMA_EP_RX_ICR_RX_HTRSH) #define WIL6210_IMC_RX_NO_RX_HTRSH (WIL6210_IMC_RX & \ (~(BIT_DMA_EP_RX_ICR_RX_HTRSH))) #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) #define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \ #define WIL6210_IMC_MISC_NO_HALP (ISR_MISC_FW_READY | \ ISR_MISC_MBOX_EVT | \ ISR_MISC_FW_ERROR) #define WIL6210_IMC_MISC (WIL6210_IMC_MISC_NO_HALP | \ BIT_DMA_EP_MISC_ICR_HALP) #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ BIT_DMA_PSEUDO_CAUSE_TX | \ BIT_DMA_PSEUDO_CAUSE_MISC)) Loading @@ -51,6 +55,7 @@ #if defined(CONFIG_WIL6210_ISR_COR) /* configure to Clear-On-Read mode */ #define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) #define WIL_ICR_ICC_MISC_VALUE (0xF7FFFFFFUL) static inline void wil_icr_clear(u32 x, void __iomem *addr) { Loading @@ -58,6 +63,7 @@ static inline void wil_icr_clear(u32 x, void __iomem *addr) #else /* defined(CONFIG_WIL6210_ISR_COR) */ /* configure to Write-1-to-Clear mode */ #define WIL_ICR_ICC_VALUE (0UL) #define WIL_ICR_ICC_MISC_VALUE (0UL) static inline void wil_icr_clear(u32 x, void __iomem *addr) { Loading Loading @@ -86,10 +92,21 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil) WIL6210_IRQ_DISABLE); } static void wil6210_mask_irq_misc(struct wil6210_priv *wil) static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp) { wil_dbg_irq(wil, "%s: mask_halp(%s)\n", __func__, mask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), WIL6210_IRQ_DISABLE); mask_halp ? WIL6210_IRQ_DISABLE : WIL6210_IRQ_DISABLE_NO_HALP); } static void wil6210_mask_halp(struct wil6210_priv *wil) { wil_dbg_irq(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), BIT_DMA_EP_MISC_ICR_HALP); } static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) Loading @@ -109,14 +126,27 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil) void wil6210_unmask_irq_rx(struct wil6210_priv *wil) { bool unmask_rx_htrsh = test_bit(wil_status_fwconnected, wil->status); wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC), WIL6210_IMC_RX); unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH); } static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) { wil_dbg_irq(wil, "%s: unmask_halp(%s)\n", __func__, unmask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), WIL6210_IMC_MISC); unmask_halp ? WIL6210_IMC_MISC : WIL6210_IMC_MISC_NO_HALP); } static void wil6210_unmask_halp(struct wil6210_priv *wil) { wil_dbg_irq(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), BIT_DMA_EP_MISC_ICR_HALP); } static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) Loading @@ -134,7 +164,7 @@ void wil_mask_irq(struct wil6210_priv *wil) wil6210_mask_irq_tx(wil); wil6210_mask_irq_rx(wil); wil6210_mask_irq_misc(wil); wil6210_mask_irq_misc(wil, true); wil6210_mask_irq_pseudo(wil); } Loading @@ -147,12 +177,12 @@ void wil_unmask_irq(struct wil6210_priv *wil) wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_VALUE); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_VALUE); WIL_ICR_ICC_MISC_VALUE); wil6210_unmask_irq_pseudo(wil); wil6210_unmask_irq_tx(wil); wil6210_unmask_irq_rx(wil); wil6210_unmask_irq_misc(wil); wil6210_unmask_irq_misc(wil, true); } void wil_configure_interrupt_moderation(struct wil6210_priv *wil) Loading Loading @@ -228,11 +258,8 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) */ if (likely(isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH))) { wil_dbg_irq(wil, "RX done\n"); if (unlikely(isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)) wil_err_ratelimited(wil, "Received \"Rx buffer is in risk of overflow\" interrupt\n"); wil_dbg_irq(wil, "RX done / RX_HTRSH received, ISR (0x%x)\n", isr); isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH); Loading Loading @@ -344,7 +371,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) return IRQ_NONE; } wil6210_mask_irq_misc(wil); wil6210_mask_irq_misc(wil, false); if (isr & ISR_MISC_FW_ERROR) { u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); Loading Loading @@ -372,12 +399,19 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) isr &= ~ISR_MISC_FW_READY; } if (isr & BIT_DMA_EP_MISC_ICR_HALP) { wil_dbg_irq(wil, "%s: HALP IRQ invoked\n", __func__); wil6210_mask_halp(wil); isr &= ~BIT_DMA_EP_MISC_ICR_HALP; complete(&wil->halp.comp); } wil->isr_misc = isr; if (isr) { return IRQ_WAKE_THREAD; } else { wil6210_unmask_irq_misc(wil); wil6210_unmask_irq_misc(wil, false); return IRQ_HANDLED; } } Loading Loading @@ -414,7 +448,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) wil->isr_misc = 0; wil6210_unmask_irq_misc(wil); wil6210_unmask_irq_misc(wil, false); return IRQ_HANDLED; } Loading Loading @@ -556,6 +590,23 @@ void wil6210_clear_irq(struct wil6210_priv *wil) wmb(); /* make sure write completed */ } void wil6210_set_halp(struct wil6210_priv *wil) { wil_dbg_misc(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS), BIT_DMA_EP_MISC_ICR_HALP); } void wil6210_clear_halp(struct wil6210_priv *wil) { wil_dbg_misc(wil, "%s()\n", __func__); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR), BIT_DMA_EP_MISC_ICR_HALP); wil6210_unmask_halp(wil); } int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi) { int rc; Loading
drivers/net/wireless/ath/wil6210/main.c +92 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include "wmi.h" #include "boot_loader.h" #define WAIT_FOR_HALP_VOTE_MS 100 bool debug_fw; /* = false; */ module_param(debug_fw, bool, S_IRUGO); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); Loading Loading @@ -132,6 +134,14 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, *d++ = __raw_readl(s++); } void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst, const volatile void __iomem *src, size_t count) { wil_halp_vote(wil); wil_memcpy_fromio_32(dst, src, count); wil_halp_unvote(wil); } void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, size_t count) { Loading @@ -142,6 +152,15 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, __raw_writel(*s++, d++); } void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil, volatile void __iomem *dst, const void *src, size_t count) { wil_halp_vote(wil); wil_memcpy_toio_32(dst, src, count); wil_halp_unvote(wil); } static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, u16 reason_code, bool from_event) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) Loading Loading @@ -194,6 +213,18 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) memset(&sta->stats, 0, sizeof(sta->stats)); } static bool wil_ap_is_connected(struct wil6210_priv *wil) { int i; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { if (wil->sta[i].status == wil_sta_connected) return true; } return false; } static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, u16 reason_code, bool from_event) { Loading Loading @@ -247,6 +278,11 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, } clear_bit(wil_status_fwconnecting, wil->status); break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: if (!wil_ap_is_connected(wil)) clear_bit(wil_status_fwconnected, wil->status); break; default: break; } Loading Loading @@ -457,9 +493,11 @@ int wil_priv_init(struct wil6210_priv *wil) mutex_init(&wil->wmi_mutex); mutex_init(&wil->probe_client_mutex); mutex_init(&wil->p2p_wdev_mutex); mutex_init(&wil->halp.lock); init_completion(&wil->wmi_ready); init_completion(&wil->wmi_call); init_completion(&wil->halp.comp); wil->bcast_vring = -1; setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); Loading Loading @@ -555,12 +593,11 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable) { wil_info(wil, "%s: enable=%d\n", __func__, enable); if (enable) { if (enable) wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); } else { else wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); } } static int wil_target_reset(struct wil6210_priv *wil) { Loading Loading @@ -804,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); Loading Loading @@ -871,6 +911,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); reinit_completion(&wil->halp.comp); if (load_fw) { wil_configure_interrupt_moderation(wil); Loading Loading @@ -1061,3 +1102,51 @@ int wil_find_cid(struct wil6210_priv *wil, const u8 *mac) return rc; } void wil_halp_vote(struct wil6210_priv *wil) { unsigned long rc; unsigned long to_jiffies = msecs_to_jiffies(WAIT_FOR_HALP_VOTE_MS); mutex_lock(&wil->halp.lock); wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); if (++wil->halp.ref_cnt == 1) { wil6210_set_halp(wil); rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); if (!rc) wil_err(wil, "%s: HALP vote timed out\n", __func__); else wil_dbg_misc(wil, "%s: HALP vote completed after %d ms\n", __func__, jiffies_to_msecs(to_jiffies - rc)); } wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); } void wil_halp_unvote(struct wil6210_priv *wil) { WARN_ON(wil->halp.ref_cnt == 0); mutex_lock(&wil->halp.lock); wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); if (--wil->halp.ref_cnt == 0) { wil6210_clear_halp(wil); wil_dbg_misc(wil, "%s: HALP unvote\n", __func__); } wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); }