* Re: [PATCH] cfg80211: allow vendor commands to be sent to nan interface
From: Johannes Berg @ 2016-10-20 12:42 UTC (permalink / raw)
To: Arend Van Spriel, Luca Coelho
Cc: linux-wireless, Andrei Otcheretianski, Luca Coelho
In-Reply-To: <e7d135c6-e114-ffa5-a52f-3ee85c18641e@broadcom.com>
> Seeing this patch flying by, my itch became unbearable so I cooked up
> the patch below. Please consider this an RFC and let me know your
> thoughts.
Hah, I had this itch before, but didn't do anything about it yet :)
I like it though, care to submit it properly?
johannes
^ permalink raw reply
* Re: [PATCH] cfg80211: allow vendor commands to be sent to nan interface
From: Arend Van Spriel @ 2016-10-20 12:40 UTC (permalink / raw)
To: Luca Coelho, johannes; +Cc: linux-wireless, Andrei Otcheretianski, Luca Coelho
In-Reply-To: <20161019044747.15921-1-luca@coelho.fi>
On 19-10-2016 6:47, Luca Coelho wrote:
> From: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
>
> Allow vendor commands that require WIPHY_VENDOR_CMD_NEED_RUNNING flag, to
> be sent to NAN interface.
>
> Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
> ---
> net/wireless/nl80211.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index e48b9c3..fcf5b4f 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -11258,7 +11258,8 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
> if (wdev->netdev &&
> !netif_running(wdev->netdev))
> return -ENETDOWN;
> - if (!wdev->netdev && !wdev->p2p_started)
> + if (!wdev->netdev && !wdev->p2p_started &&
> + !wdev->nan_started)
> return -ENETDOWN;
Seeing this patch flying by, my itch became unbearable so I cooked up
the patch below. Please consider this an RFC and let me know your thoughts.
Regards,
Arend
---
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2bbbcc3..0010e5a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3781,8 +3781,8 @@ static inline struct wiphy *wiphy_new(const struct
cfg80211_ops *ops,
* @beacon_interval: beacon interval used on this device for transmitting
* beacons, 0 when not valid
* @address: The address for this device, valid only if @netdev is %NULL
- * @p2p_started: true if this is a P2P Device that has been started
- * @nan_started: true if this is a NAN interface that has been started
+ * @is_running: true if this is a non-netdev device that has been
started, eg.
+ * like the P2P Device.
* @cac_started: true if DFS channel availability check has been started
* @cac_start_time: timestamp (jiffies) when the dfs state was entered.
* @cac_time_ms: CAC time in ms
@@ -3814,7 +3814,7 @@ struct wireless_dev {
struct mutex mtx;
- bool use_4addr, p2p_started, nan_started;
+ bool use_4addr, is_running;
u8 address[ETH_ALEN] __aligned(sizeof(u16));
@@ -3871,6 +3871,13 @@ static inline u8 *wdev_address(struct
wireless_dev *wdev)
return wdev->address;
}
+static inline bool wdev_is_running(struct wireless_dev *wdev)
+{
+ if (wdev->netdev)
+ return netif_running(wdev->netdev);
+ return wdev->is_running;
+}
+
/**
* wdev_priv - return wiphy priv from wireless_dev
*
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f433f15..088ba44 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -210,11 +210,11 @@ void cfg80211_stop_p2p_device(struct
cfg80211_registered_device *rdev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
return;
- if (!wdev->p2p_started)
+ if (!wdev_is_running(wdev))
return;
rdev_stop_p2p_device(rdev, wdev);
- wdev->p2p_started = false;
+ wdev->is_running = false;
rdev->opencount--;
@@ -233,11 +233,11 @@ void cfg80211_stop_nan(struct
cfg80211_registered_device *rdev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
return;
- if (!wdev->nan_started)
+ if (!wdev_is_running(wdev))
return;
rdev_stop_nan(rdev, wdev);
- wdev->nan_started = false;
+ wdev->is_running = false;
rdev->opencount--;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fcf5b4f..e37801e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10528,7 +10528,7 @@ static int nl80211_start_p2p_device(struct
sk_buff *skb, struct genl_info *info)
if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
return -EOPNOTSUPP;
- if (wdev->p2p_started)
+ if (wdev_is_running(wdev))
return 0;
if (rfkill_blocked(rdev->rfkill))
@@ -10538,7 +10538,7 @@ static int nl80211_start_p2p_device(struct
sk_buff *skb, struct genl_info *info)
if (err)
return err;
- wdev->p2p_started = true;
+ wdev->is_running = true;
rdev->opencount++;
return 0;
@@ -10570,7 +10570,7 @@ static int nl80211_start_nan(struct sk_buff
*skb, struct genl_info *info)
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (wdev->nan_started)
+ if (!wdev_is_running(wdev))
return -EEXIST;
if (rfkill_blocked(rdev->rfkill))
@@ -10593,7 +10593,7 @@ static int nl80211_start_nan(struct sk_buff
*skb, struct genl_info *info)
if (err)
return err;
- wdev->nan_started = true;
+ wdev->is_running = true;
rdev->opencount++;
return 0;
@@ -10678,7 +10678,7 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (!wdev->nan_started)
+ if (!wdev_is_running(wdev))
return -ENOTCONN;
if (!info->attrs[NL80211_ATTR_NAN_FUNC])
@@ -10915,7 +10915,7 @@ static int nl80211_nan_del_func(struct sk_buff *skb,
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (!wdev->nan_started)
+ if (!wdev_is_running(wdev))
return -ENOTCONN;
if (!info->attrs[NL80211_ATTR_COOKIE])
@@ -10943,7 +10943,7 @@ static int nl80211_nan_change_config(struct
sk_buff *skb,
if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;
- if (!wdev->nan_started)
+ if (!wdev_is_running(wdev))
return -ENOTCONN;
if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
@@ -11255,11 +11255,7 @@ static int nl80211_vendor_cmd(struct sk_buff
*skb, struct genl_info *info)
return -EINVAL;
if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
- if (wdev->netdev &&
- !netif_running(wdev->netdev))
- return -ENETDOWN;
- if (!wdev->netdev && !wdev->p2p_started &&
- !wdev->nan_started)
+ if (!wdev_is_running(wdev))
return -ENETDOWN;
}
@@ -11422,10 +11418,7 @@ static int nl80211_vendor_cmd_dump(struct
sk_buff *skb,
return -EINVAL;
if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
- if (wdev->netdev &&
- !netif_running(wdev->netdev))
- return -ENETDOWN;
- if (!wdev->netdev && !wdev->p2p_started)
+ if (!wdev_is_running(wdev))
return -ENETDOWN;
}
}
@@ -11796,29 +11789,14 @@ static int nl80211_pre_doit(const struct
genl_ops *ops, struct sk_buff *skb,
info->user_ptr[1] = wdev;
}
- if (dev) {
- if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
- !netif_running(dev)) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
-
- dev_hold(dev);
- } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
- if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
- !wdev->p2p_started) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
- if (wdev->iftype == NL80211_IFTYPE_NAN &&
- !wdev->nan_started) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
+ if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
+ !wdev_is_running(wdev)) {
+ if (rtnl)
+ rtnl_unlock();
+ return -ENETDOWN;
}
+ if (dev)
+ dev_hold(dev);
info->user_ptr[0] = rdev;
}
^ permalink raw reply related
* [PATCH v2] staging: wilc1000: Remove unused function wilc_lock_timeout
From: Binoy Jayan @ 2016-10-20 9:36 UTC (permalink / raw)
To: Greg Kroah-Hartman, Aditya Shankar, Ganesh Krishna
Cc: Arnd Bergmann, linux-wireless, linux-kernel, Binoy Jayan
Semaphore are going away in the future, so remove the unused function
wilc_lock_timeout which calls a semaphore api but has no users.
Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
---
They following is a patch [v2] which removes semaphores from wilc1000.
Its part of a bigger effort to eliminate all semaphores
from the linux kernel.
Arnd, Thank you for reviewing. Removed the prototype as well.
drivers/staging/wilc1000/linux_wlan.c | 11 -----------
drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 -
2 files changed, 12 deletions(-)
diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c
index 6370a5e..470d59f 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -218,17 +218,6 @@ static void deinit_irq(struct net_device *dev)
}
}
-int wilc_lock_timeout(struct wilc *nic, void *vp, u32 timeout)
-{
- /* FIXME: replace with mutex_lock or wait_for_completion */
- int error = -1;
-
- if (vp)
- error = down_timeout(vp,
- msecs_to_jiffies(timeout));
- return error;
-}
-
void wilc_mac_indicate(struct wilc *wilc, int flag)
{
int status;
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index ec6b167..d431673 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -225,7 +225,6 @@ struct WILC_WFI_mon_priv {
void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
void wilc_mac_indicate(struct wilc *wilc, int flag);
-int wilc_lock_timeout(struct wilc *wilc, void *, u32 timeout);
void wilc_netdev_cleanup(struct wilc *wilc);
int wilc_netdev_init(struct wilc **wilc, struct device *, int io_type, int gpio,
const struct wilc_hif_func *ops);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* Re: [PATCH] staging: wilc1000: Remove unused function wilc_lock_timeout
From: Arnd Bergmann @ 2016-10-20 9:17 UTC (permalink / raw)
To: Binoy Jayan
Cc: Greg Kroah-Hartman, Aditya Shankar, Ganesh Krishna,
linux-wireless, linux-kernel
In-Reply-To: <1476953672-2198-1-git-send-email-binoy.jayan@linaro.org>
On Thursday, October 20, 2016 2:24:32 PM CEST Binoy Jayan wrote:
> Semaphore are going away in the future, so remove the unused function
> wilc_lock_timeout which calls a semaphore api but has no users.
>
> Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org>
> ---
>
> They following is a patch which removes semaphores from wilc1000.
> Its part of a bigger effort to eliminate all semaphores
> from the linux kernel.
Good catch!
> drivers/staging/wilc1000/linux_wlan.c | 11 -----------
> 1 file changed, 11 deletions(-)
>
> diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c
> index 6370a5e..470d59f 100644
> --- a/drivers/staging/wilc1000/linux_wlan.c
> +++ b/drivers/staging/wilc1000/linux_wlan.c
> @@ -218,17 +218,6 @@ static void deinit_irq(struct net_device *dev)
> }
> }
>
> -int wilc_lock_timeout(struct wilc *nic, void *vp, u32 timeout)
> -{
> - /* FIXME: replace with mutex_lock or wait_for_completion */
> - int error = -1;
> -
> - if (vp)
> - error = down_timeout(vp,
> - msecs_to_jiffies(timeout));
> - return error;
> -}
You need to remove the prototype from wilc_wfi_netdevice.h
as well. Once you do that, please add
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* [PATCH] staging: wilc1000: Remove unused function wilc_lock_timeout
From: Binoy Jayan @ 2016-10-20 8:54 UTC (permalink / raw)
To: Greg Kroah-Hartman, Aditya Shankar, Ganesh Krishna
Cc: Arnd Bergmann, linux-wireless, linux-kernel, Binoy Jayan
Semaphore are going away in the future, so remove the unused function
wilc_lock_timeout which calls a semaphore api but has no users.
Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org>
---
They following is a patch which removes semaphores from wilc1000.
Its part of a bigger effort to eliminate all semaphores
from the linux kernel.
drivers/staging/wilc1000/linux_wlan.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c
index 6370a5e..470d59f 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -218,17 +218,6 @@ static void deinit_irq(struct net_device *dev)
}
}
-int wilc_lock_timeout(struct wilc *nic, void *vp, u32 timeout)
-{
- /* FIXME: replace with mutex_lock or wait_for_completion */
- int error = -1;
-
- if (vp)
- error = down_timeout(vp,
- msecs_to_jiffies(timeout));
- return error;
-}
-
void wilc_mac_indicate(struct wilc *wilc, int flag)
{
int status;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* linux-wireless: realtek rtl8192cu user-space driver for Monitor Mode: about debug mechanism
From: Xuebing Wang @ 2016-10-20 7:38 UTC (permalink / raw)
To: Larry Finger, Chaoming Li, linux-wireless
Hi Larry, Chaoming and community,
I am trying to do user-space driver for Monitor Mode only for rtl8192cu.
My approach is:
1) Remove unnecessary functions from kernel driver, then verify kernel
driver works with Monitor Mode.
-- Purpose is to keep the code minimum.
2) Re-do the code at user-space by modelling kernel driver, e.g.
rtl92cu_hw_init()
My current status is that I can download rtl8192cu firmware
(rtl8192cufw_TMSC.bin). But, I can not read any WiFi frames from Bulk In
Endpoint (ep0). I guess there could be 2 possible issues:
a) I do not init rtl8192cu correctly.
b) Monitor Mode frames are ready in rtl8192cu adapter to be read out,
but I incorrectly read Bulk In Endpoint (at user-space).
As I am lack of a debug mechanism, is there a register in rtl8192cu
which shows there is data ready to be read out via Bulk In Endpoint and
I can read this register back?
I noticed rtl8192cu has an Interrupt Endpoint, what is this for?
Thanks.
xuebing
^ permalink raw reply
* [PATCH] staging: rtl8712: Free memory and return failure when kmalloc fails
From: Souptick Joarder @ 2016-10-20 6:59 UTC (permalink / raw)
To: linux-wireless; +Cc: Larry.Finger, gregkh, florian.c.schilhabel
This patch is added to free memory and return failure when kmalloc fails
Signed-off-by: Souptick joarder <jrdr.linux@gmail.com>
---
drivers/staging/rtl8712/os_intfs.c | 3 ++-
drivers/staging/rtl8712/rtl871x_cmd.c | 5 ++++-
drivers/staging/rtl8712/rtl871x_xmit.c | 5 ++++-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index cbe4de0..aab3141 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -313,7 +313,8 @@ u8 r8712_init_drv_sw(struct _adapter *padapter)
return _FAIL;
if (r8712_init_mlme_priv(padapter) == _FAIL)
return _FAIL;
- _r8712_init_xmit_priv(&padapter->xmitpriv, padapter);
+ if ((_r8712_init_xmit_priv(&padapter->xmitpriv, padapter)) != _SUCCESS)
+ return _FAIL;
_r8712_init_recv_priv(&padapter->recvpriv, padapter);
memset((unsigned char *)&padapter->securitypriv, 0,
sizeof(struct security_priv));
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index b7ee5e6..04638f1 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -72,8 +72,11 @@ static sint _init_cmd_priv(struct cmd_priv *pcmdpriv)
((addr_t)(pcmdpriv->cmd_allocated_buf) &
(CMDBUFF_ALIGN_SZ - 1));
pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC);
- if (!pcmdpriv->rsp_allocated_buf)
+ if (!pcmdpriv->rsp_allocated_buf) {
+ kfree(pcmdpriv->cmd_allocated_buf);
+ pcmdpriv->cmd_allocated_buf = NULL;
return _FAIL;
+ }
pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 -
((addr_t)(pcmdpriv->rsp_allocated_buf) & 3);
pcmdpriv->cmd_issued_cnt = 0;
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
index be38364..484d2f2 100644
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ b/drivers/staging/rtl8712/rtl871x_xmit.c
@@ -128,8 +128,11 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
_init_queue(&pxmitpriv->pending_xmitbuf_queue);
pxmitpriv->pallocated_xmitbuf = kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4,
GFP_ATOMIC);
- if (!pxmitpriv->pallocated_xmitbuf)
+ if (!pxmitpriv->pallocated_xmitbuf) {
+ kfree(pxmitpriv->pallocated_frame_buf);
+ pxmitpriv->pallocated_frame_buf = NULL;
return _FAIL;
+ }
pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 -
((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3);
pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
--
1.9.1
^ permalink raw reply related
* Re: Intel Wireless 7260 Microcode SW error detected
From: Luca Coelho @ 2016-10-20 3:59 UTC (permalink / raw)
To: Billes Tibor, linuxwifi
Cc: johannes.berg, emmanuel.grumbach, kvalo, linux-wireless, netdev
In-Reply-To: <41dbbe14-3098-551d-6c34-0a3654bafca9@gmx.com>
Hi Tibor,
On Sun, 2016-10-16 at 20:08 +0200, Billes Tibor wrote:
> I have Lenovo laptop with an Intel Wireless 7260 wifi module and the
> latest stable kernel 4.8.1. I was playing a movie from an sshfs mounted
> file system, when the movie just froze and my network stopped working.
> Dmesg said 'Microcode SW error detected'. Below is my full `dmesg -r`
> output. I probably will not be able to reproduce this behaviour, because
> it did not happen in the past, and it seems to work fine after reboot.
Can you file a bug in bugzilla so we can track this? It seems to be a
firmware problem that we'll have to investigate. We have instructions
on how to report here:
https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi/debugging
> Is there anything more that I can do to help you debug this?
It would be nice if you could enable firmware debugging so that, if
this happens again, we'll have the appropriate FW logs to investigate
it further. There are instructions on how to enable it in the
"Firmware Debugging" section of that wiki page.
Please make sure you read and understand the privacy aspects of
submitting firmware debugging data, as explained here:
https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi/debugging#privacy_aspects
> <3>[37750.190201] iwlwifi 0000:08:00.0: Microcode SW error detected.
> Restarting 0x2000000.
> <3>[37750.190206] iwlwifi 0000:08:00.0: CSR values:
> <3>[37750.190207] iwlwifi 0000:08:00.0: (2nd byte of CSR_INT_COALESCING
> is CSR_INT_PERIODIC_REG)
> <3>[37750.190212] iwlwifi 0000:08:00.0: CSR_HW_IF_CONFIG_REG: 0X40489204
> <3>[37750.190226] iwlwifi 0000:08:00.0: CSR_INT_COALESCING: 0X80000040
> <3>[37750.190239] iwlwifi 0000:08:00.0: CSR_INT: 0X00000000
> <3>[37750.190253] iwlwifi 0000:08:00.0: CSR_INT_MASK: 0X00000000
> <3>[37750.190267] iwlwifi 0000:08:00.0: CSR_FH_INT_STATUS: 0X00000000
> <3>[37750.190281] iwlwifi 0000:08:00.0: CSR_GPIO_IN: 0X00000000
> <3>[37750.190294] iwlwifi 0000:08:00.0: CSR_RESET: 0X00000000
> <3>[37750.190308] iwlwifi 0000:08:00.0: CSR_GP_CNTRL: 0X080403c5
> <3>[37750.190322] iwlwifi 0000:08:00.0: CSR_HW_REV: 0X00000144
> <3>[37750.190336] iwlwifi 0000:08:00.0: CSR_EEPROM_REG: 0X00000000
> <3>[37750.190350] iwlwifi 0000:08:00.0: CSR_EEPROM_GP: 0X80000000
> <3>[37750.190363] iwlwifi 0000:08:00.0: CSR_OTP_GP_REG: 0X803a0000
> <3>[37750.190377] iwlwifi 0000:08:00.0: CSR_GIO_REG: 0X001f0042
> <3>[37750.190391] iwlwifi 0000:08:00.0: CSR_GP_UCODE_REG: 0X00000000
> <3>[37750.190405] iwlwifi 0000:08:00.0: CSR_GP_DRIVER_REG: 0X00000000
> <3>[37750.190419] iwlwifi 0000:08:00.0: CSR_UCODE_DRV_GP1: 0X00000000
> <3>[37750.190432] iwlwifi 0000:08:00.0: CSR_UCODE_DRV_GP2: 0X00000000
> <3>[37750.190446] iwlwifi 0000:08:00.0: CSR_LED_REG: 0X00000060
> <3>[37750.190460] iwlwifi 0000:08:00.0: CSR_DRAM_INT_TBL_REG: 0X881530a3
> <3>[37750.190474] iwlwifi 0000:08:00.0: CSR_GIO_CHICKEN_BITS: 0X27800200
> <3>[37750.190488] iwlwifi 0000:08:00.0: CSR_ANA_PLL_CFG: 0Xd55555d5
> <3>[37750.190501] iwlwifi 0000:08:00.0: CSR_MONITOR_STATUS_REG: 0X3d0801bd
> <3>[37750.190515] iwlwifi 0000:08:00.0: CSR_HW_REV_WA_REG: 0X0001001a
> <3>[37750.190529] iwlwifi 0000:08:00.0: CSR_DBG_HPET_MEM_REG: 0Xffff0010
> <3>[37750.190530] iwlwifi 0000:08:00.0: FH register values:
> <3>[37750.190552] iwlwifi 0000:08:00.0: FH_RSCSR_CHNL0_STTS_WPTR_REG:
> 0X15005f00
> <3>[37750.190566] iwlwifi 0000:08:00.0: FH_RSCSR_CHNL0_RBDCB_BASE_REG:
> 0X015005e0
> <3>[37750.190580] iwlwifi 0000:08:00.0: FH_RSCSR_CHNL0_WPTR: 0X000000e8
> <3>[37750.190593] iwlwifi 0000:08:00.0: FH_MEM_RCSR_CHNL0_CONFIG_REG:
> 0X80801114
> <3>[37750.190607] iwlwifi 0000:08:00.0: FH_MEM_RSSR_SHARED_CTRL_REG:
> 0X000000fc
> <3>[37750.190621] iwlwifi 0000:08:00.0: FH_MEM_RSSR_RX_STATUS_REG:
> 0X07030000
> <3>[37750.190635] iwlwifi 0000:08:00.0:
> FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV: 0X00000000
> <3>[37750.190648] iwlwifi 0000:08:00.0: FH_TSSR_TX_STATUS_REG: 0X07ff0001
> <3>[37750.190662] iwlwifi 0000:08:00.0: FH_TSSR_TX_ERROR_REG: 0X00000000
> <3>[37750.190790] iwlwifi 0000:08:00.0: Start IWL Error Log Dump:
> <3>[37750.190791] iwlwifi 0000:08:00.0: Status: 0x00000000, count: 6
> <3>[37750.190793] iwlwifi 0000:08:00.0: Loaded firmware version: 16.242414.0
I recommend that you update your firmware to the latest version
(iwlwifi-7260-17.ucode) published in linux-firmware.git:
http://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git
While I'm not sure the issue you saw is solved by that, we do have lots
of other fixes in it that are worth the effort.
<3>[37750.190794] iwlwifi 0000:08:00.0: 0x0000307C | ADVANCED_SYSASSERT
I hadn't seen this for a while. This is something related to the TX
queues and could have many different causes...
Thanks for reporting!
--
Cheers,
Luca.
^ permalink raw reply
* Re: [char-misc-next 2/5] watchdog: mei_wdt: use module_mei_cl_driver macro
From: Guenter Roeck @ 2016-10-20 1:49 UTC (permalink / raw)
To: Tomas Winkler, Greg Kroah-Hartman, Aloisio Almeida Jr,
Samuel Ortiz, Wim Van Sebroeck
Cc: Alexander Usyskin, linux-kernel, linux-wireless, linux-watchdog
In-Reply-To: <1476884011-20645-3-git-send-email-tomas.winkler@intel.com>
On 10/19/2016 06:33 AM, Tomas Winkler wrote:
> Replace boilerplate driver registration with module_mei_cl_driver macro.
>
> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> drivers/watchdog/mei_wdt.c | 20 +-------------------
> 1 file changed, 1 insertion(+), 19 deletions(-)
>
> diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c
> index 630bd189f167..116be477c8fd 100644
> --- a/drivers/watchdog/mei_wdt.c
> +++ b/drivers/watchdog/mei_wdt.c
> @@ -699,25 +699,7 @@ static struct mei_cl_driver mei_wdt_driver = {
> .remove = mei_wdt_remove,
> };
>
> -static int __init mei_wdt_init(void)
> -{
> - int ret;
> -
> - ret = mei_cldev_driver_register(&mei_wdt_driver);
> - if (ret) {
> - pr_err(KBUILD_MODNAME ": module registration failed\n");
> - return ret;
> - }
> - return 0;
> -}
> -
> -static void __exit mei_wdt_exit(void)
> -{
> - mei_cldev_driver_unregister(&mei_wdt_driver);
> -}
> -
> -module_init(mei_wdt_init);
> -module_exit(mei_wdt_exit);
> +module_mei_cl_driver(mei_wdt_driver);
>
> MODULE_AUTHOR("Intel Corporation");
> MODULE_LICENSE("GPL");
>
^ permalink raw reply
* Re: crypto: aesni - add ccm(aes) algorithm implementation
From: Ben Greear @ 2016-10-19 16:39 UTC (permalink / raw)
To: linux-wireless; +Cc: Yauhen Kharuzhy
In-Reply-To: <1476895046-16549-1-git-send-email-greearb@candelatech.com>
On 10/19/2016 09:37 AM, greearb@candelatech.com wrote:
> From: Yauhen Kharuzhy <jekhor@gmail.com>
>
> Add ccm(aes) implementation from linux-wireless mailing list (see
> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/126679).
>
> This eliminates FPU context store/restore overhead existing in more
> general ccm_base(ctr(aes-aesni),aes-aesni) case in MAC calculation.
>
> Convert this patch to new AEAD API.
>
> Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
> Signed-off-by: Ben Greear <greearb@candelatech.com>
I've been using this patch or something similar for a while and it
significantly helps me with sw-crypt performance. One version or another
has been around the internet for some time, and I am not the originator
of this code, but would still be happy to see it upstream if someone
can review and bless it.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* crypto: aesni - add ccm(aes) algorithm implementation
From: greearb @ 2016-10-19 16:37 UTC (permalink / raw)
To: linux-wireless; +Cc: Yauhen Kharuzhy, Ben Greear
From: Yauhen Kharuzhy <jekhor@gmail.com>
Add ccm(aes) implementation from linux-wireless mailing list (see
http://permalink.gmane.org/gmane.linux.kernel.wireless.general/126679).
This eliminates FPU context store/restore overhead existing in more
general ccm_base(ctr(aes-aesni),aes-aesni) case in MAC calculation.
Convert this patch to new AEAD API.
Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
Signed-off-by: Ben Greear <greearb@candelatech.com>
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 5b7fa14..087a952 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -36,6 +36,7 @@
#include <asm/crypto/aes.h>
#include <crypto/ablk_helper.h>
#include <crypto/scatterwalk.h>
+#include <crypto/aead.h>
#include <crypto/internal/aead.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
@@ -529,6 +530,456 @@ static int ctr_crypt(struct blkcipher_desc *desc,
return err;
}
+
+static int __ccm_setkey(struct crypto_aead *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct crypto_aes_ctx *ctx = crypto_aead_ctx(tfm);
+
+ return aes_set_key_common(crypto_aead_tfm(tfm), ctx, in_key, key_len);
+}
+
+static int __ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
+{
+ if ((authsize & 1) || authsize < 4)
+ return -EINVAL;
+ return 0;
+}
+
+static int set_msg_len(u8 *block, unsigned int msglen, int csize)
+{
+ __be32 data;
+
+ memset(block, 0, csize);
+ block += csize;
+
+ if (csize >= 4)
+ csize = 4;
+ else if (msglen > (1 << (8 * csize)))
+ return -EOVERFLOW;
+
+ data = cpu_to_be32(msglen);
+ memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
+
+ return 0;
+}
+
+static int ccm_init_mac(struct aead_request *req, u8 maciv[], u32 msglen)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ __be32 *n = (__be32 *)&maciv[AES_BLOCK_SIZE - 8];
+ u32 l = req->iv[0] + 1;
+
+ /* verify that CCM dimension 'L' is set correctly in the IV */
+ if (l < 2 || l > 8)
+ return -EINVAL;
+
+ /* verify that msglen can in fact be represented in L bytes */
+ if (l < 4 && msglen >> (8 * l))
+ return -EOVERFLOW;
+
+ /*
+ * Even if the CCM spec allows L values of up to 8, the Linux cryptoapi
+ * uses a u32 type to represent msglen so the top 4 bytes are always 0.
+ */
+ n[0] = 0;
+ n[1] = cpu_to_be32(msglen);
+
+ memcpy(maciv, req->iv, AES_BLOCK_SIZE - l);
+
+ /*
+ * Meaning of byte 0 according to CCM spec (RFC 3610/NIST 800-38C)
+ * - bits 0..2 : max # of bytes required to represent msglen, minus 1
+ * (already set by caller)
+ * - bits 3..5 : size of auth tag (1 => 4 bytes, 2 => 6 bytes, etc)
+ * - bit 6 : indicates presence of authenticate-only data
+ */
+ maciv[0] |= (crypto_aead_authsize(aead) - 2) << 2;
+ if (req->assoclen)
+ maciv[0] |= 0x40;
+
+ memset(&req->iv[AES_BLOCK_SIZE - l], 0, l);
+ return set_msg_len(maciv + AES_BLOCK_SIZE - l, msglen, l);
+}
+
+static int compute_mac(struct crypto_aes_ctx *ctx, u8 mac[], u8 *data, int n,
+ unsigned int ilen, u8 *idata)
+{
+ unsigned int bs = AES_BLOCK_SIZE;
+ u8 *odata = mac;
+ int datalen, getlen;
+
+ datalen = n;
+
+ /* first time in here, block may be partially filled. */
+ getlen = bs - ilen;
+ if (datalen >= getlen) {
+ memcpy(idata + ilen, data, getlen);
+ crypto_xor(odata, idata, bs);
+
+ aesni_enc(ctx, odata, odata);
+ datalen -= getlen;
+ data += getlen;
+ ilen = 0;
+ }
+
+ /* now encrypt rest of data */
+ while (datalen >= bs) {
+ crypto_xor(odata, data, bs);
+
+ aesni_enc(ctx, odata, odata);
+
+ datalen -= bs;
+ data += bs;
+ }
+
+ /* check and see if there's leftover data that wasn't
+ * enough to fill a block.
+ */
+ if (datalen) {
+ memcpy(idata + ilen, data, datalen);
+ ilen += datalen;
+ }
+ return ilen;
+}
+
+static unsigned int get_data_to_compute(struct crypto_aes_ctx *ctx, u8 mac[],
+ u8 *idata, struct scatterlist *sg,
+ unsigned int len, unsigned int ilen)
+{
+ struct scatter_walk walk;
+ u8 *data_src;
+ int n;
+
+ scatterwalk_start(&walk, sg);
+
+ while (len) {
+ n = scatterwalk_clamp(&walk, len);
+ if (!n) {
+ scatterwalk_start(&walk, sg_next(walk.sg));
+ n = scatterwalk_clamp(&walk, len);
+ }
+ data_src = scatterwalk_map(&walk);
+
+ ilen = compute_mac(ctx, mac, data_src, n, ilen, idata);
+ len -= n;
+
+ scatterwalk_unmap(data_src);
+ scatterwalk_advance(&walk, n);
+ scatterwalk_done(&walk, 0, len);
+ }
+
+ /* any leftover needs padding and then encrypted */
+ if (ilen) {
+ int padlen;
+ u8 *odata = mac;
+
+ padlen = AES_BLOCK_SIZE - ilen;
+ memset(idata + ilen, 0, padlen);
+ crypto_xor(odata, idata, AES_BLOCK_SIZE);
+
+ aesni_enc(ctx, odata, odata);
+ ilen = 0;
+ }
+ return ilen;
+}
+
+static void ccm_calculate_auth_mac(struct aead_request *req,
+ struct crypto_aes_ctx *ctx, u8 mac[],
+ struct scatterlist *src,
+ unsigned int cryptlen)
+{
+ unsigned int ilen;
+ u8 idata[AES_BLOCK_SIZE];
+ u32 len = req->assoclen;
+
+ aesni_enc(ctx, mac, mac);
+
+ if (len) {
+ struct __packed {
+ __be16 l;
+ __be32 h;
+ } *ltag = (void *)idata;
+
+ /* prepend the AAD with a length tag */
+ if (len < 0xff00) {
+ ltag->l = cpu_to_be16(len);
+ ilen = 2;
+ } else {
+ ltag->l = cpu_to_be16(0xfffe);
+ ltag->h = cpu_to_be32(len);
+ ilen = 6;
+ }
+
+ ilen = get_data_to_compute(ctx, mac, idata,
+ req->src, req->assoclen,
+ ilen);
+ } else {
+ ilen = 0;
+ }
+
+ /* compute plaintext into mac */
+ if (cryptlen) {
+ ilen = get_data_to_compute(ctx, mac, idata,
+ src, cryptlen, ilen);
+ }
+}
+
+static int __ccm_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_aes_ctx *ctx = aes_ctx(crypto_aead_ctx(aead));
+ struct blkcipher_desc desc = { .info = req->iv };
+ struct blkcipher_walk walk;
+ struct scatterlist src[3], dst[3], *pdst, *sg;
+ u8 __aligned(8) mac[AES_BLOCK_SIZE];
+ u32 len = req->cryptlen;
+ int err;
+
+ err = ccm_init_mac(req, mac, len);
+ if (err)
+ return err;
+
+ sg_init_table(src, 3);
+ sg_set_buf(src, mac, sizeof(mac));
+ sg = scatterwalk_ffwd(src + 1, req->src, req->assoclen);
+ if (sg != src + 1)
+ sg_chain(src, 2, sg);
+
+ pdst = src;
+ if (req->src != req->dst) {
+ sg_init_table(dst, 3);
+ sg_set_buf(dst, mac, sizeof(mac));
+ sg = scatterwalk_ffwd(dst + 1, req->dst, req->assoclen);
+ if (sg != dst + 1)
+ sg_chain(dst, 2, sg);
+ pdst = dst;
+ }
+
+ ccm_calculate_auth_mac(req, ctx, mac, sg_next(src), len);
+
+ len += sizeof(mac);
+ blkcipher_walk_init(&walk, pdst, src, len);
+ err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
+ AES_BLOCK_SIZE);
+
+ while ((len = walk.nbytes) >= AES_BLOCK_SIZE) {
+ aesni_ctr_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+ len & AES_BLOCK_MASK, walk.iv);
+ len &= AES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(&desc, &walk, len);
+ }
+ if (walk.nbytes) {
+ ctr_crypt_final(ctx, &walk);
+ err = blkcipher_walk_done(&desc, &walk, 0);
+ }
+
+ if (err)
+ return err;
+
+ /* copy authtag to end of dst */
+ scatterwalk_map_and_copy(mac, sg_next(pdst), req->cryptlen,
+ crypto_aead_authsize(aead), 1);
+ return 0;
+}
+
+static int __ccm_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_aes_ctx *ctx = aes_ctx(crypto_aead_ctx(aead));
+ unsigned int authsize = crypto_aead_authsize(aead);
+ struct blkcipher_desc desc = { .info = req->iv };
+ struct blkcipher_walk walk;
+ struct scatterlist src[3], dst[3], *pdst, *sg;
+ u8 __aligned(8) authtag[AES_BLOCK_SIZE], mac[AES_BLOCK_SIZE];
+ u32 len;
+ int err;
+
+ if (req->cryptlen < authsize)
+ return -EINVAL;
+
+ err = ccm_init_mac(req, mac, req->cryptlen - authsize);
+ if (err)
+ return err;
+
+ sg_init_table(src, 3);
+ sg_set_buf(src, authtag, sizeof(authtag));
+ sg = scatterwalk_ffwd(src + 1, req->src, req->assoclen);
+ if (sg != src + 1)
+ sg_chain(src, 2, sg);
+
+ pdst = src;
+ if (req->src != req->dst) {
+ sg_init_table(dst, 3);
+ sg_set_buf(dst, authtag, sizeof(authtag));
+ sg = scatterwalk_ffwd(dst + 1, req->dst, req->assoclen);
+ if (sg != dst + 1)
+ sg_chain(dst, 2, sg);
+
+ pdst = dst;
+ }
+
+ scatterwalk_map_and_copy(authtag, sg_next(src),
+ req->cryptlen - authsize, authsize, 0);
+
+ blkcipher_walk_init(&walk, pdst, src,
+ req->cryptlen - authsize + sizeof(mac));
+ err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
+ AES_BLOCK_SIZE);
+
+ while ((len = walk.nbytes) >= AES_BLOCK_SIZE) {
+ aesni_ctr_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+ len & AES_BLOCK_MASK, walk.iv);
+ len &= AES_BLOCK_SIZE - 1;
+ err = blkcipher_walk_done(&desc, &walk, len);
+ }
+ if (walk.nbytes) {
+ ctr_crypt_final(ctx, &walk);
+ err = blkcipher_walk_done(&desc, &walk, 0);
+ }
+
+ ccm_calculate_auth_mac(req, ctx, mac, sg_next(pdst),
+ req->cryptlen - authsize);
+ if (err)
+ return err;
+
+ /* compare calculated auth tag with the stored one */
+ if (crypto_memneq(mac, authtag, authsize))
+ return -EBADMSG;
+ return 0;
+}
+
+struct ccm_async_ctx {
+ struct crypto_aes_ctx ctx;
+ struct crypto_aead *fallback;
+};
+
+static inline struct
+ccm_async_ctx *get_ccm_ctx(struct crypto_aead *aead)
+{
+ return (struct ccm_async_ctx *)
+ PTR_ALIGN((u8 *)
+ crypto_aead_ctx(aead), AESNI_ALIGN);
+}
+
+static int ccm_init(struct crypto_aead *tfm)
+{
+ struct crypto_aead *crypto_tfm;
+ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *)
+ PTR_ALIGN((u8 *)crypto_aead_ctx(tfm), AESNI_ALIGN);
+
+ crypto_tfm = crypto_alloc_aead("ccm(aes)", 0,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+ if (IS_ERR(crypto_tfm))
+ return PTR_ERR(crypto_tfm);
+
+ ctx->fallback = crypto_tfm;
+ return 0;
+}
+
+static void ccm_exit(struct crypto_aead *tfm)
+{
+ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *)
+ PTR_ALIGN((u8 *)crypto_aead_ctx(tfm), AESNI_ALIGN);
+
+ if (!IS_ERR_OR_NULL(ctx->fallback))
+ crypto_free_aead(ctx->fallback);
+}
+
+static int ccm_setkey(struct crypto_aead *aead, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *)
+ PTR_ALIGN((u8 *)crypto_aead_ctx(aead), AESNI_ALIGN);
+ int err;
+
+ err = __ccm_setkey(aead, in_key, key_len);
+ if (err)
+ return err;
+
+ /*
+ * Set the fallback transform to use the same request flags as
+ * the hardware transform.
+ */
+ ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ ctx->fallback->base.crt_flags |=
+ tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
+ return crypto_aead_setkey(ctx->fallback, in_key, key_len);
+}
+
+static int ccm_setauthsize(struct crypto_aead *aead, unsigned int authsize)
+{
+ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *)
+ PTR_ALIGN((u8 *)crypto_aead_ctx(aead), AESNI_ALIGN);
+ int err;
+
+ err = __ccm_setauthsize(aead, authsize);
+ if (err)
+ return err;
+
+ return crypto_aead_setauthsize(ctx->fallback, authsize);
+}
+
+static int ccm_encrypt(struct aead_request *req)
+{
+ int ret;
+
+ if (!irq_fpu_usable()) {
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct ccm_async_ctx *ctx = get_ccm_ctx(aead);
+ struct crypto_aead *fallback = ctx->fallback;
+
+ char aead_req_data[sizeof(struct aead_request) +
+ crypto_aead_reqsize(fallback)]
+ __aligned(__alignof__(struct aead_request));
+ struct aead_request *aead_req = (void *) aead_req_data;
+
+ memset(aead_req, 0, sizeof(aead_req_data));
+ aead_request_set_tfm(aead_req, fallback);
+ aead_request_set_ad(aead_req, req->assoclen);
+ aead_request_set_crypt(aead_req, req->src, req->dst,
+ req->cryptlen, req->iv);
+ aead_request_set_callback(aead_req, req->base.flags,
+ req->base.complete, req->base.data);
+ ret = crypto_aead_encrypt(aead_req);
+ } else {
+ kernel_fpu_begin();
+ ret = __ccm_encrypt(req);
+ kernel_fpu_end();
+ }
+ return ret;
+}
+
+static int ccm_decrypt(struct aead_request *req)
+{
+ int ret;
+
+ if (!irq_fpu_usable()) {
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct ccm_async_ctx *ctx = get_ccm_ctx(aead);
+ struct crypto_aead *fallback = ctx->fallback;
+
+ char aead_req_data[sizeof(struct aead_request) +
+ crypto_aead_reqsize(fallback)]
+ __aligned(__alignof__(struct aead_request));
+ struct aead_request *aead_req = (void *) aead_req_data;
+
+ memset(aead_req, 0, sizeof(aead_req_data));
+ aead_request_set_tfm(aead_req, fallback);
+ aead_request_set_ad(aead_req, req->assoclen);
+ aead_request_set_crypt(aead_req, req->src, req->dst,
+ req->cryptlen, req->iv);
+ aead_request_set_callback(aead_req, req->base.flags,
+ req->base.complete, req->base.data);
+ ret = crypto_aead_decrypt(aead_req);
+ } else {
+ kernel_fpu_begin();
+ ret = __ccm_decrypt(req);
+ kernel_fpu_end();
+ }
+ return ret;
+}
#endif
static int ablk_ecb_init(struct crypto_tfm *tfm)
@@ -1437,7 +1888,45 @@ static struct aead_alg aesni_aead_algs[] = { {
.cra_ctxsize = sizeof(struct cryptd_aead *),
.cra_module = THIS_MODULE,
},
-} };
+}, {
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .setkey = __ccm_setkey,
+ .setauthsize = __ccm_setauthsize,
+ .encrypt = __ccm_encrypt,
+ .decrypt = __ccm_decrypt,
+ .base = {
+ .cra_name = "__ccm-aes-aesni",
+ .cra_driver_name = "__driver-ccm-aes-aesni",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_INTERNAL,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx) +
+ AESNI_ALIGN - 1,
+ .cra_alignmask = 0,
+ .cra_module = THIS_MODULE,
+ },
+}, {
+ .base = {
+ .cra_name = "ccm(aes)",
+ .cra_driver_name = "ccm-aes-aesni",
+ .cra_priority = 700,
+ .cra_flags = CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = 1,
+ .cra_ctxsize = AESNI_ALIGN - 1 +
+ sizeof(struct ccm_async_ctx),
+ .cra_alignmask = 0,
+ .cra_module = THIS_MODULE,
+ },
+ .init = ccm_init,
+ .exit = ccm_exit,
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .setkey = ccm_setkey,
+ .setauthsize = ccm_setauthsize,
+ .encrypt = ccm_encrypt,
+ .decrypt = ccm_decrypt,
+}};
#else
static struct aead_alg aesni_aead_algs[0];
#endif
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index c727fb0..2a765ca 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1991,6 +1991,10 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "__driver-cbc-twofish-avx",
.test = alg_test_null,
}, {
+ .alg = "__driver-ccm-aes-aesni",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
.alg = "__driver-ecb-aes-aesni",
.test = alg_test_null,
.fips_allowed = 1,
^ permalink raw reply related
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Johannes Berg @ 2016-10-19 16:00 UTC (permalink / raw)
To: Ben Greear, Ard Biesheuvel
Cc: Herbert Xu, Andy Lutomirski, Sergey Senozhatsky,
<netdev@vger.kernel.org>, David S. Miller,
<linux-wireless@vger.kernel.org>,
linux-kernel@vger.kernel.org, Jouni Malinen
In-Reply-To: <5807984D.4050307@candelatech.com>
On Wed, 2016-10-19 at 08:59 -0700, Ben Greear wrote:
>
> Do you actually expect performance regressions? I'll be complaining
> if so, but will test first :)
I think we can expect this to use a bit more CPU time, but unless
you're very tight on that you probably shouldn't expect any throughput
difference.
johannes
^ permalink raw reply
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Ben Greear @ 2016-10-19 15:59 UTC (permalink / raw)
To: Ard Biesheuvel, Johannes Berg
Cc: Herbert Xu, Andy Lutomirski, Sergey Senozhatsky,
<netdev@vger.kernel.org>, David S. Miller,
<linux-wireless@vger.kernel.org>,
linux-kernel@vger.kernel.org, Jouni Malinen
In-Reply-To: <CAKv+Gu9CppR+AN5_RdDJ6ZBRr1EDDLB+nABPddyaj5TKb5=j_Q@mail.gmail.com>
On 10/19/2016 08:08 AM, Ard Biesheuvel wrote:
> On 19 October 2016 at 08:43, Johannes Berg <johannes@sipsolutions.net> wrote:
>> On Wed, 2016-10-19 at 11:31 +0800, Herbert Xu wrote:
>> We could probably make mac80211 do that too, but can we guarantee in-
>> order processing? Anyway, it's pretty low priority, maybe never
>> happening, since hardly anyone really uses "software" crypto, the wifi
>> devices mostly have it built in anyway.
>>
>
> Indeed. The code is now correct in terms of API requirements, so let's
> just wait for someone to complain about any performance regressions.
Do you actually expect performance regressions? I'll be complaining if
so, but will test first :)
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: sequence diagrams in rst documentation
From: Johannes Berg @ 2016-10-19 7:51 UTC (permalink / raw)
To: Jonathan Corbet; +Cc: linux-wireless, linux-doc
In-Reply-To: <20161018175236.75c8c4e2@lwn.net>
On Tue, 2016-10-18 at 17:52 -0600, Jonathan Corbet wrote:
> In summary, I think we can consider taking on a module if it's what
> we need to do the docs right. And if somebody agrees to maintain it!
> :)
:)
I think for the ones that we carry, they're probably specific?
> I've heard others say they would like better diagramming support. Do
> you think that, maybe, something like aafigure would do the trick?
>
> https://pythonhosted.org/sphinxcontrib-aafig/
>
> I've not actually played with it at all, but I like the idea that
> we'd have readable diagrams in the source docs as well...
Well, maybe. I agree having it readable in the source docs as well is
nice, but for sequence diagrams in particular, I don't think
+-------+ +-----------+
| Hello +-------->+ aafigure! |
+-------+ +-----------+
really beats
Hello -> aafigure!
by much. You could do some alignment even with the latter version, and
the above isn't even really a sequence diagram anyway :)
Some of the sequence diagrams may also be automatically generated from
runtime behaviour observation (e.g. tracing, we've actually done that),
and outputting the types of ascii boxes is much more difficult there.
For other types of diagrams this may be nice though.
Anyway, I guess we'll cross that bridge when we get to it. I'd like to
have these types of documentation, perhaps with a script to auto-
generate from tracing - such as script and visual display can even
serve as a debugging aid :)
johannes
^ permalink raw reply
* Re: [PATCH] crypto: ccm - avoid scatterlist for MAC encryption
From: Johannes Berg @ 2016-10-19 7:43 UTC (permalink / raw)
To: Herbert Xu, Ard Biesheuvel
Cc: Andy Lutomirski, Sergey Senozhatsky,
<netdev@vger.kernel.org>, David S. Miller,
<linux-wireless@vger.kernel.org>,
linux-kernel@vger.kernel.org, Jouni Malinen
In-Reply-To: <20161019033157.GA1457@gondor.apana.org.au>
On Wed, 2016-10-19 at 11:31 +0800, Herbert Xu wrote:
> On Mon, Oct 17, 2016 at 06:21:14PM +0100, Ard Biesheuvel wrote:
> >
> >
> > Annoyingly, all this complication with scatterlists etc is for
> > doing
> > asynchronous crypto via DMA capable crypto accelerators, and the
> > networking code (ipsec as well as mac80211, afaik) only allow
> > synchronous in the first place, given that they execute in softirq
> > context.
>
> I'm still thinking about the issue (in particular, whether we
> should continue to rely on the request context being SG-capable
> or allow it to be on the stack for AEAD).
:)
> But IPsec definitely supports async crypto. In fact it was the
> very first user of async crypto.
Yeah.
> mac80211 on the other hand is currently sync-only.
We could probably make mac80211 do that too, but can we guarantee in-
order processing? Anyway, it's pretty low priority, maybe never
happening, since hardly anyone really uses "software" crypto, the wifi
devices mostly have it built in anyway.
(One problem is that the skb->cb is already completely full, so we
can't stash away the AAD there)
johannes
^ permalink raw reply
* Re: [PATCH net-next 2/6] net: use core MTU range checking in wireless drivers
From: Johannes Berg @ 2016-10-19 7:38 UTC (permalink / raw)
To: Jarod Wilson, linux-kernel
Cc: netdev, linux-wireless, Maya Erez, Simon Kelley,
Stanislav Yakovlev
In-Reply-To: <20161019023333.15760-3-jarod@redhat.com>
On Tue, 2016-10-18 at 22:33 -0400, Jarod Wilson wrote:
> - set max_mtu in wil6210 driver
> - set max_mtu in atmel driver
> - set min/max_mtu in cisco airo driver, remove airo_change_mtu
> - set min/max_mtu in ipw2100/ipw2200 drivers, remove
> libipw_change_mtu
> - set min/max_mtu in p80211netdev, remove wlan_change_mtu
I guess we should do the same in net/mac80211/iface.c?
johannes
^ permalink raw reply
* [PATCH 06/10] iwlwifi: pcie: give a meaningful name to interrupt request
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Sharon Dvir, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Sharon Dvir <sharon.dvir@intel.com>
Instead of passing DRV_NAME pass a string that
represents the reason for the interrupt.
Signed-off-by: Sharon Dvir <sharon.dvir@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 29 ++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index ae95533..b10e363 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1598,6 +1598,29 @@ static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans)
}
}
+static const char *queue_name(struct device *dev,
+ struct iwl_trans_pcie *trans_p, int i)
+{
+ if (trans_p->shared_vec_mask) {
+ int vec = trans_p->shared_vec_mask &
+ IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
+
+ if (i == 0)
+ return DRV_NAME ": shared IRQ";
+
+ return devm_kasprintf(dev, GFP_KERNEL,
+ DRV_NAME ": queue %d", i + vec);
+ }
+ if (i == 0)
+ return DRV_NAME ": default queue";
+
+ if (i == trans_p->alloc_vecs - 1)
+ return DRV_NAME ": exception";
+
+ return devm_kasprintf(dev, GFP_KERNEL,
+ DRV_NAME ": queue %d", i);
+}
+
static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
struct iwl_trans_pcie *trans_pcie)
{
@@ -1606,6 +1629,10 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
for (i = 0; i < trans_pcie->alloc_vecs; i++) {
int ret;
struct msix_entry *msix_entry;
+ const char *qname = queue_name(&pdev->dev, trans_pcie, i);
+
+ if (!qname)
+ return -ENOMEM;
msix_entry = &trans_pcie->msix_entries[i];
ret = devm_request_threaded_irq(&pdev->dev,
@@ -1615,7 +1642,7 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
iwl_pcie_irq_msix_handler :
iwl_pcie_irq_rx_msix_handler,
IRQF_SHARED,
- DRV_NAME,
+ qname,
msix_entry);
if (ret) {
IWL_ERR(trans_pcie->trans,
--
2.9.3
^ permalink raw reply related
* [PATCH 10/10] iwlwifi: mvm: use dev_coredumpsg()
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Aviya Erenfeld, Johannes Berg, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Aviya Erenfeld <aviya.erenfeld@intel.com>
iwlmvm currently uses dev_coredumpm() to collect multiple
buffers, but this has the downside of pinning the module
until the coredump expires, if the data isn't read by any
userspace.
Avoid this by using the new dev_coredumpsg() method. We
still copy the data from the old way of generating it, but
neither hold on to vmalloc'ed data for a long time, nor do
we pin the module now.
Signed-off-by: Aviya Erenfeld <aviya.erenfeld@intel.com>
[rewrite commit message]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 100 +++++++++++++-----------
1 file changed, 55 insertions(+), 45 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index d89d0a1..2e8e3e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -70,49 +70,6 @@
#include "iwl-prph.h"
#include "iwl-csr.h"
-static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
- void *data, size_t datalen)
-{
- const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
- ssize_t bytes_read;
- ssize_t bytes_read_trans;
-
- if (offset < dump_ptrs->op_mode_len) {
- bytes_read = min_t(ssize_t, count,
- dump_ptrs->op_mode_len - offset);
- memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
- bytes_read);
- offset += bytes_read;
- count -= bytes_read;
-
- if (count == 0)
- return bytes_read;
- } else {
- bytes_read = 0;
- }
-
- if (!dump_ptrs->trans_ptr)
- return bytes_read;
-
- offset -= dump_ptrs->op_mode_len;
- bytes_read_trans = min_t(ssize_t, count,
- dump_ptrs->trans_ptr->len - offset);
- memcpy(buffer + bytes_read,
- (u8 *)dump_ptrs->trans_ptr->data + offset,
- bytes_read_trans);
-
- return bytes_read + bytes_read_trans;
-}
-
-static void iwl_mvm_free_coredump(void *data)
-{
- const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
-
- vfree(fw_error_dump->op_mode_ptr);
- vfree(fw_error_dump->trans_ptr);
- kfree(fw_error_dump);
-}
-
#define RADIO_REG_MAX_READ 0x2ad
static void iwl_mvm_read_radio_reg(struct iwl_mvm *mvm,
struct iwl_fw_error_dump_data **dump_data)
@@ -491,6 +448,43 @@ static u32 iwl_dump_prph(struct iwl_trans *trans,
return prph_len;
}
+/*
+ * alloc_sgtable - allocates scallerlist table in the given size,
+ * fills it with pages and returns it
+ * @size: the size (in bytes) of the table
+*/
+static struct scatterlist *alloc_sgtable(int size)
+{
+ int alloc_size, nents, i;
+ struct page *new_page;
+ struct scatterlist *iter;
+ struct scatterlist *table;
+
+ nents = DIV_ROUND_UP(size, PAGE_SIZE);
+ table = kcalloc(nents, sizeof(*table), GFP_KERNEL);
+ if (!table)
+ return NULL;
+ sg_init_table(table, nents);
+ iter = table;
+ for_each_sg(table, iter, sg_nents(table), i) {
+ new_page = alloc_page(GFP_KERNEL);
+ if (!new_page) {
+ /* release all previous allocated pages in the table */
+ iter = table;
+ for_each_sg(table, iter, sg_nents(table), i) {
+ new_page = sg_page(iter);
+ if (new_page)
+ __free_page(new_page);
+ }
+ return NULL;
+ }
+ alloc_size = min_t(int, size, PAGE_SIZE);
+ size -= PAGE_SIZE;
+ sg_set_page(iter, new_page, alloc_size, 0);
+ }
+ return table;
+}
+
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
{
struct iwl_fw_error_dump_file *dump_file;
@@ -499,6 +493,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_mem *dump_mem;
struct iwl_fw_error_dump_trigger_desc *dump_trig;
struct iwl_mvm_dump_ptrs *fw_error_dump;
+ struct scatterlist *sg_dump_data;
u32 sram_len, sram_ofs;
struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem =
mvm->fw->dbg_mem_tlv;
@@ -815,8 +810,23 @@ dump_trans_data:
file_len += fw_error_dump->trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len);
- dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
- GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
+ sg_dump_data = alloc_sgtable(file_len);
+ if (sg_dump_data) {
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump->op_mode_ptr,
+ fw_error_dump->op_mode_len, 0);
+ sg_pcopy_from_buffer(sg_dump_data,
+ sg_nents(sg_dump_data),
+ fw_error_dump->trans_ptr->data,
+ fw_error_dump->trans_ptr->len,
+ fw_error_dump->op_mode_len);
+ dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len,
+ GFP_KERNEL);
+ }
+ vfree(fw_error_dump->op_mode_ptr);
+ vfree(fw_error_dump->trans_ptr);
+ kfree(fw_error_dump);
out:
iwl_mvm_free_fw_dump_desc(mvm);
--
2.9.3
^ permalink raw reply related
* [PATCH 05/10] iwlwifi: mvm: use firmware station PM notification for AP_LINK_PS
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Johannes Berg, Emmanuel Grumbach, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Johannes Berg <johannes.berg@intel.com>
When using RSS on 9000 series devices, we can't rely on processing the
received frames for station powersave handling, since they could be
processed on different CPUs and out of order.
In order to still manage the powersave of stations, the firmware sends
a notification on sleep->wake, wake->sleep and - for U-APSD - frames
received with PM while already sleeping (with the TID.)
With this, the driver can set AP_LINK_PS, which is required for real
parallel RX. In addition, this requires checking for PS-Poll frames
and calling ieee80211_sta_pspoll() appropriately.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 +
drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 26 ++++++++
.../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 9 ++-
drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 70 ++++++++++++++++++++--
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 ++++
drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 1 +
9 files changed, 119 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
index ceec5ca..1ad0ec1 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
@@ -293,6 +293,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
* is supported.
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
+ * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
@@ -342,6 +343,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
+ IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
index acc5cd5..b530fa4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
@@ -474,4 +474,30 @@ struct iwl_mvm_internal_rxq_notif {
u8 data[];
} __packed;
+/**
+ * enum iwl_mvm_pm_event - type of station PM event
+ * @IWL_MVM_PM_EVENT_AWAKE: station woke up
+ * @IWL_MVM_PM_EVENT_ASLEEP: station went to sleep
+ * @IWL_MVM_PM_EVENT_UAPSD: station sent uAPSD trigger
+ * @IWL_MVM_PM_EVENT_PS_POLL: station sent PS-Poll
+ */
+enum iwl_mvm_pm_event {
+ IWL_MVM_PM_EVENT_AWAKE,
+ IWL_MVM_PM_EVENT_ASLEEP,
+ IWL_MVM_PM_EVENT_UAPSD,
+ IWL_MVM_PM_EVENT_PS_POLL,
+}; /* PEER_PM_NTFY_API_E_VER_1 */
+
+/**
+ * struct iwl_mvm_pm_state_notification - station PM state notification
+ * @sta_id: station ID of the station changing state
+ * @type: the new powersave state, see IWL_MVM_PM_EVENT_ above
+ */
+struct iwl_mvm_pm_state_notification {
+ u8 sta_id;
+ u8 type;
+ /* private: */
+ u16 reserved;
+} __packed; /* PEER_PM_NTFY_API_S_VER_1 */
+
#endif /* __fw_api_rx_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
index 6c8e3ca..3b5150e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -179,7 +179,7 @@ enum iwl_sta_key_flag {
* enum iwl_sta_modify_flag - indicate to the fw what flag are being changed
* @STA_MODIFY_QUEUE_REMOVAL: this command removes a queue
* @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx
- * @STA_MODIFY_TX_RATE: unused
+ * @STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_trigger_acs
* @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
* @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
* @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
@@ -189,7 +189,7 @@ enum iwl_sta_key_flag {
enum iwl_sta_modify_flag {
STA_MODIFY_QUEUE_REMOVAL = BIT(0),
STA_MODIFY_TID_DISABLE_TX = BIT(1),
- STA_MODIFY_TX_RATE = BIT(2),
+ STA_MODIFY_UAPSD_ACS = BIT(2),
STA_MODIFY_ADD_BA_TID = BIT(3),
STA_MODIFY_REMOVE_BA_TID = BIT(4),
STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5),
@@ -353,6 +353,8 @@ struct iwl_mvm_add_sta_cmd_v7 {
* @beamform_flags: beam forming controls
* @tfd_queue_msk: tfd queues used by this station
* @rx_ba_window: aggregation window size
+ * @scd_queue_bank: queue bank in used. Each bank contains 32 queues. 0 means
+ * that the queues used by this station are in the first 32.
*
* The device contains an internal table of per-station information, with info
* on security keys, aggregation parameters, and Tx rates for initial Tx
@@ -382,7 +384,8 @@ struct iwl_mvm_add_sta_cmd {
__le16 beamform_flags;
__le32 tfd_queue_msk;
__le16 rx_ba_window;
- __le16 reserved;
+ u8 scd_queue_bank;
+ u8 uapsd_trigger_acs;
} __packed; /* ADD_STA_CMD_API_S_VER_8 */
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index 9763369..ae12bad 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -332,6 +332,7 @@ enum iwl_data_path_subcmd_ids {
DQA_ENABLE_CMD = 0x0,
UPDATE_MU_GROUPS_CMD = 0x1,
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
+ STA_PM_NOTIF = 0xFD,
MU_GROUP_MGMT_NOTIF = 0xFE,
RX_QUEUES_NOTIFICATION = 0xFF,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 318efd8..9eeb2c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -445,6 +445,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
if (iwl_mvm_has_new_rx_api(mvm))
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF))
+ ieee80211_hw_set(hw, AP_LINK_PS);
if (mvm->trans->num_rx_queues > 1)
ieee80211_hw_set(hw, USES_RSS);
@@ -2318,10 +2320,9 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
tids, more_data, true);
}
-static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum sta_notify_cmd cmd,
- struct ieee80211_sta *sta)
+static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -2374,6 +2375,67 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
spin_unlock_bh(&mvmsta->lock);
}
+static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
+{
+ __iwl_mvm_mac_sta_notify(hw, cmd, sta);
+}
+
+void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_mvm_pm_state_notification *notif = (void *)pkt->data;
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+ bool sleeping = (notif->type != IWL_MVM_PM_EVENT_AWAKE);
+
+ if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
+ return;
+
+ rcu_read_lock();
+ sta = mvm->fw_id_to_mac_id[notif->sta_id];
+ if (WARN_ON(IS_ERR_OR_NULL(sta))) {
+ rcu_read_unlock();
+ return;
+ }
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ if (!mvmsta->vif ||
+ mvmsta->vif->type != NL80211_IFTYPE_AP) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (mvmsta->sleeping != sleeping) {
+ mvmsta->sleeping = sleeping;
+ __iwl_mvm_mac_sta_notify(mvm->hw,
+ sleeping ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE,
+ sta);
+ ieee80211_sta_ps_transition(sta, sleeping);
+ }
+
+ if (sleeping) {
+ switch (notif->type) {
+ case IWL_MVM_PM_EVENT_AWAKE:
+ case IWL_MVM_PM_EVENT_ASLEEP:
+ break;
+ case IWL_MVM_PM_EVENT_UAPSD:
+ ieee80211_sta_uapsd_trigger(sta, IEEE80211_NUM_TIDS);
+ break;
+ case IWL_MVM_PM_EVENT_PS_POLL:
+ ieee80211_sta_pspoll(sta);
+ break;
+ default:
+ break;
+ }
+ }
+
+ rcu_read_unlock();
+}
+
static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index d17cbf6..726ba48 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1418,6 +1418,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_window_status_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 05fe6dd..e86986f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -306,6 +306,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC),
RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF,
iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC),
+ RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF,
+ iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC),
};
#undef RX_HANDLER
#undef RX_HANDLER_GRP
@@ -452,6 +454,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
+ HCMD_NAME(STA_PM_NOTIF),
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
HCMD_NAME(RX_QUEUES_NOTIFICATION),
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 5ec1b96..82ee786 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -203,6 +203,19 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
add_sta_cmd.station_flags |=
cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
+ if (sta->wme) {
+ add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
+
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BK);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BE);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VI);
+ if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
+ add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VO);
+ }
+
status = ADD_STA_SUCCESS;
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
iwl_mvm_add_sta_cmd_size(mvm),
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index e068d53..b45c7b9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -436,6 +436,7 @@ struct iwl_mvm_sta {
bool disable_tx;
bool tlc_amsdu;
+ bool sleeping;
u8 agg_tids;
u8 sleep_tx_count;
u8 avg_energy;
--
2.9.3
^ permalink raw reply related
* [PATCH 07/10] iwlwifi: mvm: tell the firmware about the AID of the peer
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Emmanuel Grumbach, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
When a peer associates, the firmware will soon want to know
its AID to be able to compute the TIM IE by itself.
In DQA, the firmware has all the information it needs to
update the TIM internally. The only missing part is the
AID.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 82ee786..636c8b0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -202,6 +202,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
add_sta_cmd.station_flags |=
cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
+ add_sta_cmd.assoc_id = cpu_to_le16(sta->aid);
if (sta->wme) {
add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
--
2.9.3
^ permalink raw reply related
* [PATCH 01/10] iwlwifi: mvm: update txq metadata to current owner
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Liad Kaufman, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Liad Kaufman <liad.kaufman@intel.com>
When a TXQ's owner is changed, the FW is indeed notified, but
the driver doesn't update the current metadata to reflect the
owner change. Fix that.
Signed-off-by: Liad Kaufman <liad.kaufman@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index fc77188..a65030f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -875,12 +875,17 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd);
- if (ret)
+ if (ret) {
IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n",
queue, ret);
- else
- IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
- queue, tid);
+ return;
+ }
+
+ spin_lock_bh(&mvm->queue_info_lock);
+ mvm->queue_info[queue].txq_tid = tid;
+ spin_unlock_bh(&mvm->queue_info_lock);
+ IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
+ queue, tid);
}
static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
--
2.9.3
^ permalink raw reply related
* [PATCH 04/10] iwlwifi: mvm: fix dqa deferred frames marking
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Liad Kaufman, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Liad Kaufman <liad.kaufman@intel.com>
When a STA has deferred traffic to TX, an appropriate bit
is turned on in %deferred_tx_frames to indicate deferred
traffic. This marking is never turned off, resulting in
iterating over TIDs with no deferred traffic.
Although this didn't cause any failures/errors/bugs, there
is still no point of iterating over these TIDs when not
needed.
Signed-off-by: Liad Kaufman <liad.kaufman@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index c9dcb70..5ec1b96 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1015,6 +1015,7 @@ static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm,
local_bh_disable();
spin_lock(&mvmsta->lock);
skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx);
+ mvmsta->deferred_traffic_tid_map &= ~BIT(tid);
spin_unlock(&mvmsta->lock);
while ((skb = __skb_dequeue(&deferred_tx)))
--
2.9.3
^ permalink raw reply related
* [PATCH 03/10] iwlwifi: mvm: support MONITOR vif in DQA mode
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Liad Kaufman, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Liad Kaufman <liad.kaufman@intel.com>
In DQA mode the TXQs are allocated on demand, so make
sure the sniffer STA tfd_queue_msk isn't set.
Signed-off-by: Liad Kaufman <liad.kaufman@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 6b962d6..9a91203 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -899,9 +899,11 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
- for (i = 0; i < IEEE80211_NUM_ACS; i++)
- if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
- tfd_queue_msk |= BIT(vif->hw_queue[i]);
+ if (!iwl_mvm_is_dqa_supported(mvm)) {
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
+ tfd_queue_msk |= BIT(vif->hw_queue[i]);
+ }
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
MAC_FILTER_IN_CONTROL_AND_MGMT |
--
2.9.3
^ permalink raw reply related
* [PATCH 02/10] iwlwifi: mvm: fix reserved txq freeing
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Liad Kaufman, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Liad Kaufman <liad.kaufman@intel.com>
If a TXQ's marking as a reserved queue is removed,
when removing the STA the driver might try to access
out of bounds memory. Make sure the reserved queue
is freed only if it is still reserved.
Signed-off-by: Liad Kaufman <liad.kaufman@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index a65030f..c9dcb70 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1494,12 +1494,15 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
/* If DQA is supported - the queues can be disabled now */
- if (iwl_mvm_is_dqa_supported(mvm)) {
+ if (iwl_mvm_is_dqa_supported(mvm))
+ iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
+
+ /* If there is a TXQ still marked as reserved - free it */
+ if (iwl_mvm_is_dqa_supported(mvm) &&
+ mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
u8 reserved_txq = mvm_sta->reserved_queue;
enum iwl_mvm_queue_status *status;
- iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
-
/*
* If no traffic has gone through the reserved TXQ - it
* is still marked as IWL_MVM_QUEUE_RESERVED, and
--
2.9.3
^ permalink raw reply related
* [PATCH 08/10] iwlwifi: mvm: assign cab queue to the correct station
From: Luca Coelho @ 2016-10-19 10:07 UTC (permalink / raw)
To: linux-wireless; +Cc: kvalo, Sara Sharon, Luca Coelho
In-Reply-To: <20161019100755.23874-1-luca@coelho.fi>
From: Sara Sharon <sara.sharon@intel.com>
Currently when configuring the cab queue the scheduler is configured
without station id - which results in station id 0.
In DQA mode this causes firmware to assert later on when the actual
station 0 is added with an empty tfd_queue_mask.
Fix that by configuring the queue to the broadcast station.
This is a bit trickier since the queue should not be included in the
tfd_queue_mask of the ADD_STA since it is a multicast queue, and the
tfd_queue_mask is only unicast queue. As a result the queue should be
enabled only after the broadcast station is added.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 16 +++++++---------
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 16 ++++++++++++++++
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 9a91203..4a0874e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -499,23 +499,21 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (ret)
return ret;
+ /* If DQA is supported - queues will be enabled when needed */
+ if (iwl_mvm_is_dqa_supported(mvm))
+ return 0;
+
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
- if (!iwl_mvm_is_dqa_supported(mvm))
- iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
- IWL_MVM_OFFCHANNEL_QUEUE,
- IWL_MVM_TX_FIFO_VO, 0,
- wdg_timeout);
+ iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
+ IWL_MVM_OFFCHANNEL_QUEUE,
+ IWL_MVM_TX_FIFO_VO, 0, wdg_timeout);
break;
case NL80211_IFTYPE_AP:
iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue,
IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
/* fall through */
default:
- /* If DQA is supported - queues will be enabled when needed */
- if (iwl_mvm_is_dqa_supported(mvm))
- break;
-
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac],
vif->hw_queue[ac],
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 9eeb2c3..4f8c134 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2099,6 +2099,22 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (ret)
goto out_unbind;
+ /* enable the multicast queue, now that we have a station for it */
+ if (iwl_mvm_is_dqa_supported(mvm)) {
+ unsigned int wdg_timeout =
+ iwl_mvm_get_wd_timeout(mvm, vif, false, false);
+ struct iwl_trans_txq_scd_cfg cfg = {
+ .fifo = IWL_MVM_TX_FIFO_MCAST,
+ .sta_id = mvmvif->bcast_sta.sta_id,
+ .tid = IWL_MAX_TID_COUNT,
+ .aggregate = false,
+ .frame_limit = IWL_FRAME_LIMIT,
+ };
+
+ iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
+ &cfg, wdg_timeout);
+ }
+
/* must be set before quota calculations */
mvmvif->ap_ibss_active = true;
--
2.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox