[PATCH] wlcore: Set rx_status boottime_ns field on rx

2018-07-27 Thread Loic Poulain
When receiving a beacon or probe response, we should update the
boottime_ns field which is the timestamp the frame was received at.
(cf mac80211.h)

This fixes a scanning issue with Android since it relies on this
timestamp to determine when the AP has been seen for the last time
(via the nl80211 BSS_LAST_SEEN_BOOTTIME parameter).

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ti/wlcore/rx.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/rx.c 
b/drivers/net/wireless/ti/wlcore/rx.c
index 0f15696..078a494 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -59,7 +59,7 @@ static u32 wlcore_rx_get_align_buf_size(struct wl1271 *wl, 
u32 pkt_len)
 static void wl1271_rx_status(struct wl1271 *wl,
 struct wl1271_rx_descriptor *desc,
 struct ieee80211_rx_status *status,
-u8 beacon)
+u8 beacon, u8 probe_rsp)
 {
memset(status, 0, sizeof(struct ieee80211_rx_status));
 
@@ -106,6 +106,9 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
}
 
+   if (beacon || probe_rsp)
+   status->boottime_ns = ktime_get_boot_ns();
+
if (beacon)
wlcore_set_pending_regdomain_ch(wl, (u16)desc->channel,
status->band);
@@ -191,7 +194,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 
*data, u32 length,
if (ieee80211_is_data_present(hdr->frame_control))
is_data = 1;
 
-   wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
+   wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon,
+ieee80211_is_probe_resp(hdr->frame_control));
wlcore_hw_set_rx_csum(wl, desc, skb);
 
seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
-- 
2.7.4



[PATCH v2 1/3] wcn36xx: Fix WEP104 encryption type

2018-06-20 Thread Loic Poulain
This is an obvious copy & paste bug.

Signed-off-by: Loic Poulain 
---
 v2: non-empty commit message.

 drivers/net/wireless/ath/wcn36xx/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index aeb5e6e..4648a78 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -512,7 +512,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
break;
case WLAN_CIPHER_SUITE_WEP104:
-   vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
+   vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP104;
break;
case WLAN_CIPHER_SUITE_CCMP:
vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
-- 
2.7.4



[PATCH v2 2/3] wcn36xx: Track associated stations

2018-06-20 Thread Loic Poulain
Add list of associated stations(STA, AP, peer...) per vif.

Signed-off-by: Loic Poulain 
---
 v2: no change

 drivers/net/wireless/ath/wcn36xx/main.c| 5 +
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 4648a78..6fd0bf6 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -567,6 +567,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
key_conf->keyidx,
key_conf->keylen,
key);
+
if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
(WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
sta_priv->is_data_encrypted = true;
@@ -984,6 +985,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
mutex_lock(&wcn->conf_mutex);
 
vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
+   INIT_LIST_HEAD(&vif_priv->sta_list);
list_add(&vif_priv->list, &wcn->vif_list);
wcn36xx_smd_add_sta_self(wcn, vif);
 
@@ -1005,6 +1007,8 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, 
struct ieee80211_vif *vif,
 
spin_lock_init(&sta_priv->ampdu_lock);
sta_priv->vif = vif_priv;
+   list_add(&sta_priv->list, &vif_priv->sta_list);
+
/*
 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
 * at this stage AID is not available yet.
@@ -1032,6 +1036,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
 
mutex_lock(&wcn->conf_mutex);
 
+   list_del(&sta_priv->list);
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
sta_priv->vif = NULL;
 
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 11e7401..a58f313 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -129,6 +129,8 @@ struct wcn36xx_vif {
u8 self_sta_index;
u8 self_dpu_desc_index;
u8 self_ucast_dpu_sign;
+
+   struct list_head sta_list;
 };
 
 /**
@@ -154,6 +156,7 @@ struct wcn36xx_vif {
  * |__|_|___|
  */
 struct wcn36xx_sta {
+   struct list_head list;
struct wcn36xx_vif *vif;
u16 aid;
u16 tid;
-- 
2.7.4



[PATCH v2 3/3] wcn36xx: Fix WEP encryption

2018-06-20 Thread Loic Poulain
In case of WEP encryption, driver has to configure shared key for
associated station(s). Note that sta pointer is NULL in case of non
pairwise key, causing NULL pointer dereference with existing code
(sta_priv->is_data_encrypted). Fix this by using associated sta list
instead. This enables WEP support as client, WEP AP is non-functional.

Signed-off-by: Loic Poulain 
---
 v2: Commit reword, clarify Client/AP WEP status

 drivers/net/wireless/ath/wcn36xx/main.c | 19 +++
 drivers/net/wireless/ath/wcn36xx/smd.c  | 20 ++--
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 6fd0bf6..e38443e 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -493,7 +493,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
 {
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
+   struct wcn36xx_sta *sta_priv = sta ? wcn36xx_sta_to_priv(sta) : NULL;
int ret = 0;
u8 key[WLAN_MAX_KEY_LEN];
 
@@ -570,13 +570,16 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
 
if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
(WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
-   sta_priv->is_data_encrypted = true;
-   wcn36xx_smd_set_stakey(wcn,
-   vif_priv->encrypt_type,
-   key_conf->keyidx,
-   key_conf->keylen,
-   key,
-   get_sta_index(vif, sta_priv));
+   list_for_each_entry(sta_priv,
+   &vif_priv->sta_list, list) {
+   sta_priv->is_data_encrypted = true;
+   wcn36xx_smd_set_stakey(wcn,
+   vif_priv->encrypt_type,
+   key_conf->keyidx,
+   key_conf->keylen,
+   key,
+   get_sta_index(vif, sta_priv));
+   }
}
}
break;
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index b4dadf7..304a86c 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -1708,12 +1708,20 @@ int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
msg_body.set_sta_key_params.sta_index = sta_index;
msg_body.set_sta_key_params.enc_type = enc_type;
 
-   msg_body.set_sta_key_params.key[0].id = keyidx;
-   msg_body.set_sta_key_params.key[0].unicast = 1;
-   msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
-   msg_body.set_sta_key_params.key[0].pae_role = 0;
-   msg_body.set_sta_key_params.key[0].length = keylen;
-   memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
+   if (enc_type == WCN36XX_HAL_ED_WEP104 ||
+   enc_type == WCN36XX_HAL_ED_WEP40) {
+   /* Use bss key for wep (static) */
+   msg_body.set_sta_key_params.def_wep_idx = keyidx;
+   msg_body.set_sta_key_params.wep_type = 0;
+   } else {
+   msg_body.set_sta_key_params.key[0].id = keyidx;
+   msg_body.set_sta_key_params.key[0].unicast = 1;
+   msg_body.set_sta_key_params.key[0].direction = 
WCN36XX_HAL_TX_RX;
+   msg_body.set_sta_key_params.key[0].pae_role = 0;
+   msg_body.set_sta_key_params.key[0].length = keylen;
+   memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
+   }
+
msg_body.set_sta_key_params.single_tid_rc = 1;
 
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
-- 
2.7.4



[PATCH 3/3] wcn36xx: Fix WEP encryption

2018-05-28 Thread Loic Poulain
In case of WEP encryption, driver has to configure shared key for
associated station(s). Note that sta pointer is NULL in case of non
pairwise key, causing NULL pointer dereference with existing code
(sta_priv->is_data_encrypted). Fix this by using associated sta list
instead.

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/main.c | 19 +++
 drivers/net/wireless/ath/wcn36xx/smd.c  | 20 ++--
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 6fd0bf6..e38443e 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -493,7 +493,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
 {
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
+   struct wcn36xx_sta *sta_priv = sta ? wcn36xx_sta_to_priv(sta) : NULL;
int ret = 0;
u8 key[WLAN_MAX_KEY_LEN];
 
@@ -570,13 +570,16 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
 
if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
(WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
-   sta_priv->is_data_encrypted = true;
-   wcn36xx_smd_set_stakey(wcn,
-   vif_priv->encrypt_type,
-   key_conf->keyidx,
-   key_conf->keylen,
-   key,
-   get_sta_index(vif, sta_priv));
+   list_for_each_entry(sta_priv,
+   &vif_priv->sta_list, list) {
+   sta_priv->is_data_encrypted = true;
+   wcn36xx_smd_set_stakey(wcn,
+   vif_priv->encrypt_type,
+   key_conf->keyidx,
+   key_conf->keylen,
+   key,
+   get_sta_index(vif, sta_priv));
+   }
}
}
break;
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index b4dadf7..304a86c 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -1708,12 +1708,20 @@ int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
msg_body.set_sta_key_params.sta_index = sta_index;
msg_body.set_sta_key_params.enc_type = enc_type;
 
-   msg_body.set_sta_key_params.key[0].id = keyidx;
-   msg_body.set_sta_key_params.key[0].unicast = 1;
-   msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
-   msg_body.set_sta_key_params.key[0].pae_role = 0;
-   msg_body.set_sta_key_params.key[0].length = keylen;
-   memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
+   if (enc_type == WCN36XX_HAL_ED_WEP104 ||
+   enc_type == WCN36XX_HAL_ED_WEP40) {
+   /* Use bss key for wep (static) */
+   msg_body.set_sta_key_params.def_wep_idx = keyidx;
+   msg_body.set_sta_key_params.wep_type = 0;
+   } else {
+   msg_body.set_sta_key_params.key[0].id = keyidx;
+   msg_body.set_sta_key_params.key[0].unicast = 1;
+   msg_body.set_sta_key_params.key[0].direction = 
WCN36XX_HAL_TX_RX;
+   msg_body.set_sta_key_params.key[0].pae_role = 0;
+   msg_body.set_sta_key_params.key[0].length = keylen;
+   memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
+   }
+
msg_body.set_sta_key_params.single_tid_rc = 1;
 
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
-- 
2.7.4



[PATCH 2/3] wcn36xx: Track associated stations

2018-05-28 Thread Loic Poulain
Add list of associated stations(STA, AP, peer...) per vif.

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/main.c| 5 +
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 4648a78..6fd0bf6 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -567,6 +567,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
key_conf->keyidx,
key_conf->keylen,
key);
+
if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
(WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
sta_priv->is_data_encrypted = true;
@@ -984,6 +985,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
mutex_lock(&wcn->conf_mutex);
 
vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
+   INIT_LIST_HEAD(&vif_priv->sta_list);
list_add(&vif_priv->list, &wcn->vif_list);
wcn36xx_smd_add_sta_self(wcn, vif);
 
@@ -1005,6 +1007,8 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, 
struct ieee80211_vif *vif,
 
spin_lock_init(&sta_priv->ampdu_lock);
sta_priv->vif = vif_priv;
+   list_add(&sta_priv->list, &vif_priv->sta_list);
+
/*
 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
 * at this stage AID is not available yet.
@@ -1032,6 +1036,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
 
mutex_lock(&wcn->conf_mutex);
 
+   list_del(&sta_priv->list);
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
sta_priv->vif = NULL;
 
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 11e7401..a58f313 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -129,6 +129,8 @@ struct wcn36xx_vif {
u8 self_sta_index;
u8 self_dpu_desc_index;
u8 self_ucast_dpu_sign;
+
+   struct list_head sta_list;
 };
 
 /**
@@ -154,6 +156,7 @@ struct wcn36xx_vif {
  * |__|_|___|
  */
 struct wcn36xx_sta {
+   struct list_head list;
struct wcn36xx_vif *vif;
u16 aid;
u16 tid;
-- 
2.7.4



[PATCH 1/3] wcn36xx: Fix WEP104 encryption type

2018-05-28 Thread Loic Poulain
Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index aeb5e6e..4648a78 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -512,7 +512,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
break;
case WLAN_CIPHER_SUITE_WEP104:
-   vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
+   vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP104;
break;
case WLAN_CIPHER_SUITE_CCMP:
vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
-- 
2.7.4



Re: [PATCH 1/1 RFC] wcn36xx: fix buffer commit logic on TX path

2018-04-12 Thread Loic Poulain
On 11 April 2018 at 15:37, Daniel Mack  wrote:
> Hi Loic,
>
> On Wednesday, April 11, 2018 03:30 PM, Loic Poulain wrote:
>>> /* Move the head of the ring to the next empty descriptor */
>>> -ch->head_blk_ctl = ctl->next;
>>> +ch->head_blk_ctl = ctl_skb->next;
>>> +
>>> +   /* Commit all previous writes and set descriptors to VALID */
>>> +   wmb();
>>
>> Is this first memory barrier really needed? from what I understand, we
>> only need to ensure that the control descriptor is marked valid at the
>> end of the procedure and we don't really care about the paylod one.
>
> Well, without documentation or the firmware sources, that's just
> guesswork at this point. My assumption is only based on the weird
> comments and workarounds in the downstream driver.
>
> I added the second barrier to ensure that no descriptor is ever marked
> valid unless all other bits are definitely in sync.

Fair enough!


Re: [PATCH] wcn36xx: pass correct BSS index when deleting BSS keys

2018-04-12 Thread Loic Poulain
Hi Daniel,

> @@ -564,10 +565,13 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, 
> enum set_key_cmd cmd,
> break;
> case DISABLE_KEY:
> if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
> +   if (vif_priv->bss_index != 
> WCN36XX_HAL_BSS_INVALID_IDX)
> +   wcn36xx_smd_remove_bsskey(wcn,
> +   vif_priv->encrypt_type,
> +   vif_priv->bss_index,
> +   key_conf->keyidx);
> +
> vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
> -   wcn36xx_smd_remove_bsskey(wcn,
> -   vif_priv->encrypt_type,
> -   key_conf->keyidx);

Note that moving vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE after
key removal also fixes an issue I observed in AP mode:
wcn36xx: ERROR hal_remove_bsskey response failed err=6

Indeed, trying to remove a key with non-matching encrypt type fails,
keeping the right encrypt_type for removal fixes the issue.

Patch looks good.

Regards,
Loic


Re: [PATCH 1/1 RFC] wcn36xx: fix buffer commit logic on TX path

2018-04-11 Thread Loic Poulain
Hi Daniel,

> /* Move the head of the ring to the next empty descriptor */
> -ch->head_blk_ctl = ctl->next;
> +ch->head_blk_ctl = ctl_skb->next;
> +
> +   /* Commit all previous writes and set descriptors to VALID */
> +   wmb();

Is this first memory barrier really needed? from what I understand, we
only need to ensure that the control descriptor is marked valid at the
end of the procedure and we don't really care about the paylod one.

> +   desc_skb->ctrl = ch->ctrl_skb;
> +   wmb();
> +   desc_bd->ctrl = ch->ctrl_bd;
>
> /*
>  * When connected and trying to send data frame chip can be in sleep

Otherwise, patch makes sense.

Regards,
Loic


[PATCH] wcn36xx: Remove useless skb spinlock

2018-04-06 Thread Loic Poulain
Each DXE control block is associated to a specific channel.
The channel lock is always taken before accessing a control block.
There is no need to have an extra (useless) spinlock for the control
block skb.

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/dxe.c | 8 +---
 drivers/net/wireless/ath/wcn36xx/dxe.h | 1 -
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 2c3b899..4bb9630 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -78,7 +78,6 @@ static int wcn36xx_dxe_allocate_ctl_block(struct 
wcn36xx_dxe_ch *ch)
if (!cur_ctl)
goto out_fail;
 
-   spin_lock_init(&cur_ctl->skb_lock);
cur_ctl->ctl_blk_order = i;
if (i == 0) {
ch->head_blk_ctl = cur_ctl;
@@ -377,12 +376,11 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct 
wcn36xx_dxe_ch *ch)
/* Keep frame until TX status comes */
ieee80211_free_txskb(wcn->hw, ctl->skb);
}
-   spin_lock(&ctl->skb_lock);
+
if (wcn->queues_stopped) {
wcn->queues_stopped = false;
ieee80211_wake_queues(wcn->hw);
}
-   spin_unlock(&ctl->skb_lock);
 
ctl->skb = NULL;
}
@@ -654,8 +652,6 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
spin_lock_irqsave(&ch->lock, flags);
ctl = ch->head_blk_ctl;
 
-   spin_lock(&ctl->next->skb_lock);
-
/*
 * If skb is not null that means that we reached the tail of the ring
 * hence ring is full. Stop queues to let mac80211 back off until ring
@@ -664,11 +660,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
if (NULL != ctl->next->skb) {
ieee80211_stop_queues(wcn->hw);
wcn->queues_stopped = true;
-   spin_unlock(&ctl->next->skb_lock);
spin_unlock_irqrestore(&ch->lock, flags);
return -EBUSY;
}
-   spin_unlock(&ctl->next->skb_lock);
 
ctl->skb = NULL;
desc = ctl->desc;
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h 
b/drivers/net/wireless/ath/wcn36xx/dxe.h
index ce58096..31b81b7 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.h
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.h
@@ -422,7 +422,6 @@ struct wcn36xx_dxe_ctl {
unsigned intdesc_phy_addr;
int ctl_blk_order;
struct sk_buff  *skb;
-   spinlock_t  skb_lock;
void*bd_cpu_addr;
dma_addr_t  bd_phy_addr;
 };
-- 
2.7.4



[PATCH] wcn36xx: Add missing fall through comment in smd.c

2018-04-05 Thread Loic Poulain
This prevents GCC warning.

Reported-by: Dan Carpenter 
Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 7cc2928..7b79e0b 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2135,6 +2135,7 @@ static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, 
void *buf, size_t len)
switch (rsp->type) {
case WCN36XX_HAL_SCAN_IND_FAILED:
scan_info.aborted = true;
+   /* fall through */
case WCN36XX_HAL_SCAN_IND_COMPLETED:
mutex_lock(&wcn->scan_lock);
wcn->scan_req = NULL;
-- 
2.7.4



Re: [PATCH v2] wcn36xx: Disable 5GHz for wcn3610

2018-03-29 Thread Loic Poulain
Hi Ramon,

On 29 March 2018 at 09:32, Ramon Fried  wrote:

>> Should we document qcom,wcn3610 just like wcn3620 is:
>>
>> Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt: 
>>"qcom,wcn3620",
> IMHO the mentioned bindings is related to the PIL (peripheral image loaded) 
> which is just the firmware part and has
> nothing to do with wifi frontend(IRIS).
>

It seems that the RF is a subnode of the PIL node:

"= SUBNODES
A required subnode of the WCNSS PIL is used to describe the attached rf module
and its resource dependencies. It is described by the following properties:"

So we should add qcom,wcn3610 to the exiting list of 'compatible' rf modules.

Regards,
Loic


[PATCH] wcn36xx: Fix warning due to duplicate scan_completed notification

2018-02-15 Thread Loic Poulain
The wcn36xx_cancel_hw_scan method stops the hw scan and notify the
scan completion via ieee80211_scan_completed.
However, on scan offload cancellation, firmware sends a scan complete
indication, triggering a new call to ieee80211_scan_completed.
This leads to kernel warn since the scan has already been completed.

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/main.c | 9 +++--
 drivers/net/wireless/ath/wcn36xx/smd.c  | 2 ++
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index ab5be6d..fcc98d4 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -666,16 +666,13 @@ static void wcn36xx_cancel_hw_scan(struct ieee80211_hw 
*hw,
 {
struct wcn36xx *wcn = hw->priv;
 
-   if (!wcn36xx_smd_stop_hw_scan(wcn)) {
-   struct cfg80211_scan_info scan_info = { .aborted = true };
-
-   ieee80211_scan_completed(wcn->hw, &scan_info);
-   }
-
mutex_lock(&wcn->scan_lock);
wcn->scan_aborted = true;
mutex_unlock(&wcn->scan_lock);
 
+   /* ieee80211_scan_completed will be called on FW scan indication */
+   wcn36xx_smd_stop_hw_scan(wcn);
+
cancel_work_sync(&wcn->scan_work);
 }
 
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 2a4871c..7cc2928 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2138,6 +2138,8 @@ static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, 
void *buf, size_t len)
case WCN36XX_HAL_SCAN_IND_COMPLETED:
mutex_lock(&wcn->scan_lock);
wcn->scan_req = NULL;
+   if (wcn->scan_aborted)
+   scan_info.aborted = true;
mutex_unlock(&wcn->scan_lock);
ieee80211_scan_completed(wcn->hw, &scan_info);
break;
-- 
2.7.4



Re: [PATCH][next] wcn36xx: remove redundant assignment to msg_body.min_ch_time

2017-12-28 Thread Loic Poulain
Hi Colin, Bjorn,

On 26 December 2017 at 21:13, Bjorn Andersson
 wrote:
> On Tue 19 Dec 09:04 PST 2017, Colin King wrote:
>
>> From: Colin Ian King 
>>
>> msg_body.min_ch_time is being assigned twice; remove the redundant
>> first assignment.
>>
>> Detected by CoverityScan, CID#1463042 ("Unused Value")
>>
>
> Happy to see Coverity working for us :)
>
>
> This should have had a:
>
> Fixes: 2f3bef4b247e ("wcn36xx: Add hardware scan offload support")
>
>> Signed-off-by: Colin Ian King 
>> ---
>>  drivers/net/wireless/ath/wcn36xx/smd.c | 1 -
>>  1 file changed, 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
>> b/drivers/net/wireless/ath/wcn36xx/smd.c
>> index 2914618a0335..bab2eca5fcac 100644
>> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
>> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
>> @@ -625,7 +625,6 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, 
>> struct ieee80211_vif *vif,
>>   INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
>>
>>   msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
>> - msg_body.min_ch_time = 30;
>>   msg_body.min_ch_time = 100;
>
> But I strongly suspect the second line is supposed to be max_ch_time.
>
> @Loic, do you agree?

You're absolutely right.
Colin could you please update your patch accordingly?

Regards,
Loic


Re: [PATCH v2] wcn36xx: Fix dynamic power saving

2017-12-12 Thread Loic Poulain
Hi Kalle,

On 12 December 2017 at 13:40, Kalle Valo  wrote:
> Kalle Valo  writes:
>
>> Loic Poulain  writes:
>>
>>> Since driver does not report hardware dynamic power saving cap,
>>> this is up to the mac80211 to manage power saving timeout and
>>> state machine, using the ieee80211 config callback to report
>>> PS changes. This patch enables/disables PS mode according to
>>> the new configuration.
>>>
>>> Remove old behaviour enabling PS mode in a static way, this make
>>> the device unusable when power save is enabled since device is
>>> forced to PS regardless RX/TX traffic.
>>>
>>> Acked-by: Bjorn Andersson 
>>> Signed-off-by: Loic Poulain 
>>
>> A fixes line would be nice for backporters. I can add that but need the
>> commit id.
>
> Or maybe this actually isn't a regression? Then of course a fixes line
> is not needed.

Yes, not really a regression since the issue came with the driver
itself (8e84c258).

>
> Should I push this to v4.15 or v4.16, any preference?

4.15 would be great.

Thanks,
Loic


Re: [PATCH v2] wcn36xx: Fix dynamic power saving

2017-12-11 Thread Loic Poulain
Hi Ramon,

On 11 December 2017 at 16:41, Bjorn Andersson
 wrote:
> On Mon 11 Dec 07:34 PST 2017, Ramon Fried wrote:
>
>> On Mon, Dec 11, 2017 at 10:52:22AM +0200, Loic Poulain wrote:
>> > Since driver does not report hardware dynamic power saving cap,
>> > this is up to the mac80211 to manage power saving timeout and
>> > state machine, using the ieee80211 config callback to report
>> > PS changes. This patch enables/disables PS mode according to
>> > the new configuration.
>> >
>> > Remove old behaviour enabling PS mode in a static way, this make
>> > the device unusable when power save is enabled since device is
>> > forced to PS regardless RX/TX traffic.
>> >
>>
>> Hi.
>> I tried to see if this patch solves the ping delay once power save is
>> turned on and it appears it doesn't (log below).
>> I do see some change in the delay though in comparison to testing without 
>> the patch.
>> Bjorn, How did you test it ?

For me this is the expected behavior, when station is in PS mode, some
time is required
to leave PS, this is the cost for saving power. Since ping is every
second, station goes
back to PS between each ping due to dynamic PS timeout, this indeed
leads to some
latency... I obtain same kind of results pinging my mobile phone. Note
that the PS
timeout can be changed (100ms by default).

>>
>
> Without this patch I get ping times around a second and SSH is not
> usable, with this patch I see similar ping times as you, but SSH is
> usable.
>
> I have not been able to run iperf, because I keep hitting
> https://bugs.96boards.org/show_bug.cgi?id=663

Yes, improvement can be mainly observed with high traffic.

Regards,
Loic


Re: [PATCH] wcn36xx: Add hardware scan offload support

2017-12-11 Thread Loic Poulain
Hi Bjorn,

On 9 December 2017 at 01:34, Bjorn Andersson  wrote:
>
>> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
>> b/drivers/net/wireless/ath/wcn36xx/smd.c
> [..]
>> +static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t 
>> len)
>> +{
>> + struct wcn36xx_hal_scan_offload_ind *rsp = buf;
>> + struct cfg80211_scan_info scan_info = {};
>> +
>> + if (len != sizeof(*rsp)) {
>> + wcn36xx_warn("Corrupted delete scan indication\n");
>> + return -EIO;
>> + }
>> +
>> + wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)", rsp->type);
>> +
>> + switch (rsp->type) {
>> + case WCN36XX_HAL_SCAN_IND_FAILED:
>> + scan_info.aborted = true;
>> + case WCN36XX_HAL_SCAN_IND_COMPLETED:
>> + mutex_lock(&wcn->scan_lock);
>
> Grabbing this mutex with DEBUG_ATOMIC_SLEEP causes issues, but that's
> because the locking in ind_smd_work() is to excessive. Will reply with a
> fix for this.

Oops you're right, thanks for the patch.

Regards,
Loic


[PATCH v2] wcn36xx: Fix dynamic power saving

2017-12-11 Thread Loic Poulain
Since driver does not report hardware dynamic power saving cap,
this is up to the mac80211 to manage power saving timeout and
state machine, using the ieee80211 config callback to report
PS changes. This patch enables/disables PS mode according to
the new configuration.

Remove old behaviour enabling PS mode in a static way, this make
the device unusable when power save is enabled since device is
forced to PS regardless RX/TX traffic.

Acked-by: Bjorn Andersson 
Signed-off-by: Loic Poulain 
---
 v2: remove error msg on unbalanced bmps exit
 return -EALREADY if not in bmps mode

 drivers/net/wireless/ath/wcn36xx/main.c | 23 ---
 drivers/net/wireless/ath/wcn36xx/pmc.c  |  6 --
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index f0b4d43..436b8ea 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -384,6 +384,18 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 
changed)
}
}
 
+   if (changed & IEEE80211_CONF_CHANGE_PS) {
+   list_for_each_entry(tmp, &wcn->vif_list, list) {
+   vif = wcn36xx_priv_to_vif(tmp);
+   if (hw->conf.flags & IEEE80211_CONF_PS) {
+   if (vif->bss_conf.ps) /* ps allowed ? */
+   wcn36xx_pmc_enter_bmps_state(wcn, vif);
+   } else {
+   wcn36xx_pmc_exit_bmps_state(wcn, vif);
+   }
+   }
+   }
+
mutex_unlock(&wcn->conf_mutex);
 
return 0;
@@ -747,17 +759,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
vif_priv->dtim_period = bss_conf->dtim_period;
}
 
-   if (changed & BSS_CHANGED_PS) {
-   wcn36xx_dbg(WCN36XX_DBG_MAC,
-   "mac bss PS set %d\n",
-   bss_conf->ps);
-   if (bss_conf->ps) {
-   wcn36xx_pmc_enter_bmps_state(wcn, vif);
-   } else {
-   wcn36xx_pmc_exit_bmps_state(wcn, vif);
-   }
-   }
-
if (changed & BSS_CHANGED_BSSID) {
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
bss_conf->bssid);
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c 
b/drivers/net/wireless/ath/wcn36xx/pmc.c
index 589fe5f..1976b80 100644
--- a/drivers/net/wireless/ath/wcn36xx/pmc.c
+++ b/drivers/net/wireless/ath/wcn36xx/pmc.c
@@ -45,8 +45,10 @@ int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn,
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 
if (WCN36XX_BMPS != vif_priv->pw_state) {
-   wcn36xx_err("Not in BMPS mode, no need to exit from BMPS 
mode!\n");
-   return -EINVAL;
+   /* Unbalanced call or last BMPS enter failed */
+   wcn36xx_dbg(WCN36XX_DBG_PMC,
+   "Not in BMPS mode, no need to exit\n");
+   return -EALREADY;
}
wcn36xx_smd_exit_bmps(wcn, vif);
vif_priv->pw_state = WCN36XX_FULL_POWER;
-- 
2.7.4



Re: [PATCH] wcn36xx: Fix dynamic power saving

2017-12-11 Thread Loic Poulain
Hi Bjorn,

On 9 December 2017 at 01:45, Bjorn Andersson  wrote:
>>   }
>>   }
>>
>> + if (changed & IEEE80211_CONF_CHANGE_PS) {
>> + list_for_each_entry(tmp, &wcn->vif_list, list) {
>> + vif = wcn36xx_priv_to_vif(tmp);
>> + if (hw->conf.flags & IEEE80211_CONF_PS) {
>> + if (vif->bss_conf.ps) /* ps allowed ? */
>> + wcn36xx_pmc_enter_bmps_state(wcn, vif);
>> + } else {
>> + wcn36xx_pmc_exit_bmps_state(wcn, vif);
>
> During startup I get the error print from wcn36xx_pmc_exit_bmps_state()
> that we're not in BMPS state. There's no harm in this, but the error
> might concern people.
>
> How about we in addition to this, change the wcn36xx_err() to a
> wcn36xx_dbg(PMC...) ?

Thanks for reporting this, I assume mac80211 disable PS mode before enabling it
on timeout... It makes sense to avoid this error msg since balancing
is well managed
by this driver.

Regards,
Loic


[PATCH] wcn36xx: Fix dynamic power saving

2017-12-08 Thread Loic Poulain
Since driver does not report hardware dynamic power saving cap,
this is up to the mac80211 to manage power saving timeout and
state machine, using the ieee80211 config callback to report
PS changes. This patch enables/disables PS mode according to
the new configuration.

Remove old behaviour enabling PS mode in a static way, this make
the device unusable when power save is enabled since device is
forced to PS regardless RX/TX traffic.

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/main.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index f0b4d43..436b8ea 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -384,6 +384,18 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 
changed)
}
}
 
+   if (changed & IEEE80211_CONF_CHANGE_PS) {
+   list_for_each_entry(tmp, &wcn->vif_list, list) {
+   vif = wcn36xx_priv_to_vif(tmp);
+   if (hw->conf.flags & IEEE80211_CONF_PS) {
+   if (vif->bss_conf.ps) /* ps allowed ? */
+   wcn36xx_pmc_enter_bmps_state(wcn, vif);
+   } else {
+   wcn36xx_pmc_exit_bmps_state(wcn, vif);
+   }
+   }
+   }
+
mutex_unlock(&wcn->conf_mutex);
 
return 0;
@@ -747,17 +759,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
vif_priv->dtim_period = bss_conf->dtim_period;
}
 
-   if (changed & BSS_CHANGED_PS) {
-   wcn36xx_dbg(WCN36XX_DBG_MAC,
-   "mac bss PS set %d\n",
-   bss_conf->ps);
-   if (bss_conf->ps) {
-   wcn36xx_pmc_enter_bmps_state(wcn, vif);
-   } else {
-   wcn36xx_pmc_exit_bmps_state(wcn, vif);
-   }
-   }
-
if (changed & BSS_CHANGED_BSSID) {
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
bss_conf->bssid);
-- 
2.7.4



[PATCH] wcn36xx: Add hardware scan offload support

2017-12-08 Thread Loic Poulain
Current hw_scan implementation does not trigger offloaded
hardware scan and seems to only put the device in a kind of
listening mode (beacon/probe-response) for software scan.
Since no probe request are generated by the software, current
scanning method is similar to a passive scan.

This patch introduces support for 'true' hardware offloaded scan.
Hardware scan is configured and started via the start-scan-offload
firmware message. Once scan has been completed a scan indicator
message is received from firmware.

Moreover, this patch includes support for directed probe-request,
allowing connection with hidden APs. It also fixes scan issues with
band-steering AP which are not 'visible' with passive scan (due to
hidden ssid in beacons).

Let's keep the 'legacy' scanning method in case scan-offload is not
supported.

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/hal.h  | 107 ++--
 drivers/net/wireless/ath/wcn36xx/main.c |  16 -
 drivers/net/wireless/ath/wcn36xx/smd.c  | 120 
 drivers/net/wireless/ath/wcn36xx/smd.h  |   3 +
 4 files changed, 238 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index b765c64..1829635 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -348,6 +348,13 @@ enum wcn36xx_hal_host_msg_type {
WCN36XX_HAL_DHCP_START_IND = 189,
WCN36XX_HAL_DHCP_STOP_IND = 190,
 
+   /* Scan Offload(hw) APIs */
+   WCN36XX_HAL_START_SCAN_OFFLOAD_REQ = 204,
+   WCN36XX_HAL_START_SCAN_OFFLOAD_RSP = 205,
+   WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ = 206,
+   WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP = 207,
+   WCN36XX_HAL_SCAN_OFFLOAD_IND = 210,
+
WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
 
WCN36XX_HAL_PRINT_REG_INFO_IND = 259,
@@ -1115,6 +1122,101 @@ struct wcn36xx_hal_finish_scan_rsp_msg {
 
 } __packed;
 
+enum wcn36xx_hal_scan_type {
+   WCN36XX_HAL_SCAN_TYPE_PASSIVE = 0x00,
+   WCN36XX_HAL_SCAN_TYPE_ACTIVE = WCN36XX_HAL_MAX_ENUM_SIZE
+};
+
+struct wcn36xx_hal_mac_ssid {
+   u8 length;
+   u8 ssid[32];
+} __packed;
+
+struct wcn36xx_hal_start_scan_offload_req_msg {
+   struct wcn36xx_hal_msg_header header;
+
+   /* BSSIDs hot list */
+   u8 num_bssid;
+   u8 bssids[4][ETH_ALEN];
+
+   /* Directed probe-requests will be sent for listed SSIDs (max 10)*/
+   u8 num_ssid;
+   struct wcn36xx_hal_mac_ssid ssids[10];
+
+   /* Report AP with hidden ssid */
+   u8 scan_hidden;
+
+   /* Self MAC address */
+   u8 mac[ETH_ALEN];
+
+   /* BSS type */
+   enum wcn36xx_hal_bss_type bss_type;
+
+   /* Scan type */
+   enum wcn36xx_hal_scan_type scan_type;
+
+   /* Minimum scanning time on each channel (ms) */
+   u32 min_ch_time;
+
+   /* Maximum scanning time on each channel */
+   u32 max_ch_time;
+
+   /* Is a p2p search */
+   u8 p2p_search;
+
+   /* Channels to scan */
+   u8 num_channel;
+   u8 channels[80];
+
+   /* IE field */
+   u16 ie_len;
+   u8 ie[0];
+} __packed;
+
+struct wcn36xx_hal_start_scan_offload_rsp_msg {
+   struct wcn36xx_hal_msg_header header;
+
+   /* success or failure */
+   u32 status;
+} __packed;
+
+enum wcn36xx_hal_scan_offload_ind_type {
+   /* Scan has been started */
+   WCN36XX_HAL_SCAN_IND_STARTED = 0x01,
+   /* Scan has been completed */
+   WCN36XX_HAL_SCAN_IND_COMPLETED = 0x02,
+   /* Moved to foreign channel */
+   WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL = 0x08,
+   /* scan request has been dequeued */
+   WCN36XX_HAL_SCAN_IND_DEQUEUED = 0x10,
+   /* preempted by other high priority scan */
+   WCN36XX_HAL_SCAN_IND_PREEMPTED = 0x20,
+   /* scan start failed */
+   WCN36XX_HAL_SCAN_IND_FAILED = 0x40,
+/*scan restarted */
+   WCN36XX_HAL_SCAN_IND_RESTARTED = 0x80,
+   WCN36XX_HAL_SCAN_IND_MAX = WCN36XX_HAL_MAX_ENUM_SIZE
+};
+
+struct wcn36xx_hal_scan_offload_ind {
+   struct wcn36xx_hal_msg_header header;
+
+   u32 type;
+   u32 channel_mhz;
+   u32 scan_id;
+} __packed;
+
+struct wcn36xx_hal_stop_scan_offload_req_msg {
+   struct wcn36xx_hal_msg_header header;
+} __packed;
+
+struct wcn36xx_hal_stop_scan_offload_rsp_msg {
+   struct wcn36xx_hal_msg_header header;
+
+   /* success or failure */
+   u32 status;
+} __packed;
+
 enum wcn36xx_hal_rate_index {
HW_RATE_INDEX_1MBPS = 0x82,
HW_RATE_INDEX_2MBPS = 0x84,
@@ -1507,11 +1609,6 @@ struct wcn36xx_hal_edca_param_record {
u16 txop_limit;
 } __packed;
 
-struct wcn36xx_hal_mac_ssid {
-   u8 length;
-   u8 ssid[32];
-} __packed;
-
 /* Concurrency role. These are generic IDs that identify the various roles
  *  in the software system. */
 enum wcn36xx_hal_con_mode {
diff --git a/drivers/net/wir

[PATCH] wcn36xx: Disable 5GHz for wcn3620

2017-09-19 Thread Loic Poulain
wcn3620 can only operate on 2.4GHz band due to RF limitation.
If wcn36xx digital block is associated with an external IRIS
RF module, retrieve the id and disable 5GHz band in case of
wcn3620 id.

Signed-off-by: Loic Poulain 
---
 drivers/net/wireless/ath/wcn36xx/main.c| 12 +++-
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  6 ++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index a9220b4..c3bc248 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1089,7 +1089,8 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
BIT(NL80211_IFTYPE_MESH_POINT);
 
wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
-   wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
+   if (wcn->rf_id != RF_IRIS_WCN3620)
+   wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
 
wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
@@ -1119,6 +1120,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
  struct platform_device *pdev)
 {
struct device_node *mmio_node;
+   struct device_node *iris_node;
struct resource *res;
int index;
int ret;
@@ -1181,6 +1183,14 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
goto unmap_ccu;
}
 
+   /* External RF module */
+   iris_node = of_find_node_by_name(mmio_node, "iris");
+   if (iris_node) {
+   if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
+   wcn->rf_id = RF_IRIS_WCN3620;
+   of_node_put(iris_node);
+   }
+
of_node_put(mmio_node);
return 0;
 
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index b52b4da9..0643477 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -94,6 +94,9 @@ enum wcn36xx_ampdu_state {
 #define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags)
 #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power)
 
+#define RF_UNKNOWN 0x
+#define RF_IRIS_WCN36200x3620
+
 static inline void buff_to_be(u32 *buf, size_t len)
 {
int i;
@@ -238,6 +241,9 @@ struct wcn36xx {
 
struct sk_buff  *tx_ack_skb;
 
+   /* RF module */
+   unsignedrf_id;
+
 #ifdef CONFIG_WCN36XX_DEBUGFS
/* Debug file system entry */
struct wcn36xx_dfs_entrydfs;
-- 
2.7.4



Re: [PATCH 3/5] net: rfkill: gpio: Implement host wake up support

2014-10-09 Thread Loic Poulain

Thanks Heikki, I'll rework these patches accordingly.

Regards,
Loic

On 09/10/2014 09:38, Heikki Krogerus wrote:

On Wed, Oct 08, 2014 at 04:09:50PM +0200, Loic Poulain wrote:

Thanks, it sounds good to use a label instead of index.
However:
- DSD is only compatible with BIOS ACPI 5.1
- gpiod_get_index does not take care of con_id (label) parameter in case of
ACPI (acpi_find_gpio).
- gpiod_get calls gpiod_get_index with index 0.

Any patch ongoing to support con_id parameter with ACPI?

Yes. This is the latest version being review as we speak:
https://lkml.org/lkml/2014/10/6/530

It is really important you get your firmware fixed. We simply can not
rely on the order of the resources like GPIOs in the resource
templates. They may be different on every second
board/BIOS/configuration/whatever. It's even possible for a ACPI
device object to have two (or more) different resource templates
describing the same GPIOs in different order which are then selected
based on some magic condition, for example user selection in BIOS setup.

The existing hardware works with the drivers we have now, and it's not
possible to change the BIOS/system firmware on those so we just have
to live with them and rely on being able to pick the correct resources
based on index. But everything new _must_ use _DSD properties, and
ACPI 5.1 in general.

So basically your BIOS must produce the ACPI tables according to ACPI
5.1. If you are worried about support for ACPI 5.1 in kernel, don't
worry about it, it's almost ready. And in the meantime, _DSD is just
something kernel will ignore.


Cheers,



--
Intel Open Source Technology Center
http://oss.intel.com/

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/5] net: rfkill: gpio: Implement host wake up support

2014-10-08 Thread Loic Poulain

Thanks, it sounds good to use a label instead of index.
However:
- DSD is only compatible with BIOS ACPI 5.1
- gpiod_get_index does not take care of con_id (label) parameter in case 
of ACPI (acpi_find_gpio).

- gpiod_get calls gpiod_get_index with index 0.

Any patch ongoing to support con_id parameter with ACPI?

Regards,
Loic

On 08/10/2014 13:38, Heikki Krogerus wrote:

On Wed, Oct 08, 2014 at 10:34:38AM +0200, Loic Poulain wrote:

Some GPIO based rfkill devices can wake their host up from suspend by
toggling an input (from the host perspective) GPIO.
This patch adds a generic support for that feature by registering a
threaded interrupt routine and thus setting the corresponding GPIO as a
wake up source.

Signed-off-by: Loic Poulain 
---
  net/rfkill/rfkill-gpio.c | 49 
  1 file changed, 49 insertions(+)

To continue my previous answer, for this you could have the following
_DSD..

 Name (_DSD, Package ()
 {
 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 Package () {
 Package () {"host_wake-gpio", Package () {^BTH1, 0, 0, 0}},
 Package () {"reset-gpio", Package () {^BTH1, 1, 0, 0}},
 Package () {"shutdown-gpio", Package () {^BTH1, 2, 0, 0}},
 }
 })

And in the driver you can then request it without caring about the
index..

 ...
 gpio = devm_gpiod_get_index(dev, "host_wake", 3);
 if (!IS_ERR(gpio)) {
ret = gpiod_direction_input(gpio);
if (ret)
return ret;
rfkill->irq = gpiod_to_irq(gpio);
 ...


Actually, we could just use devm_gpiod_get instead of
devm_gpiod_get_index in this case.


Cheers,



--
Intel Open Source Technology Center
http://oss.intel.com/

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/5] net: rfkill: gpio: Configurable GPIO idx

2014-10-08 Thread Loic Poulain

Hi Johannes,

acpi_device_id driver_data field is defined as a kernel_ulong_t in 
mod_devicetable.h.


Regards,
Loic

On 08/10/2014 10:53, Johannes Berg wrote:

On Wed, 2014-10-08 at 10:34 +0200, Loic Poulain wrote:


+   { "BCM2E1A", (kernel_ulong_t)&acpi_default_bluetooth },

Shouldn't that be uintptr_t?

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
Intel Open Source Technology Center
http://oss.intel.com/

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/5] net: rfkill: gpio: Add BCM47521 ACPI ID

2014-10-08 Thread Loic Poulain
Add BCM47521 (GPS) to the ACPI table.
BCM47521 supports host wake.
HOST <---UART---> CONTROLLER
HOST <-- WAKE CONTROLLER (gpio res 0)
HOST ---ENABLE--> CONTROLLER (gpio res 1)

Signed-off-by: Loic Poulain 
---
 net/rfkill/rfkill-gpio.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 28d1cbf..da239ef 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -309,6 +309,14 @@ static struct rfkill_gpio_desc acpi_bluetooth_wake = {
.host_wake_idx = 2,
 };
 
+static struct rfkill_gpio_desc acpi_gps_wake = {
+   .type = RFKILL_TYPE_GPS,
+   .reset_idx = -1,
+   .shutdown_idx = 1,
+   .wake_idx = -1,
+   .host_wake_idx = 0,
+};
+
 static const struct acpi_device_id rfkill_acpi_match[] = {
{ "BCM2E1A", (kernel_ulong_t)&acpi_default_bluetooth },
{ "BCM2E39", (kernel_ulong_t)&acpi_default_bluetooth },
@@ -317,6 +325,7 @@ static const struct acpi_device_id rfkill_acpi_match[] = {
{ "OBDA8723", (kernel_ulong_t)&acpi_bluetooth_wake },
{ "BCM4752", (kernel_ulong_t)&acpi_default_gps },
{ "LNV4752", (kernel_ulong_t)&acpi_default_gps },
+   { "BCM47521", (kernel_ulong_t)&acpi_gps_wake },
{ },
 };
 MODULE_DEVICE_TABLE(acpi, rfkill_acpi_match);
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] net: rfkill: gpio: Add OBDA8723 ACPI ID

2014-10-08 Thread Loic Poulain
Add OBDA8723 (rtl8723) ACPI id.
rtl8723 bluetooth chip has the following interface:
HOST <---UART---> CONTROLLER
HOST --- WAKE---> CONTROLLER (gpio res 0)
HOST ---ENABLE--> CONTROLLER (gpio res 1)
HOST <---WAKE CONTROLLER (gpio res 2)

Signed-off-by: Loic Poulain 
---
 net/rfkill/rfkill-gpio.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 2f6aad1..28d1cbf 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -301,11 +301,20 @@ static struct rfkill_gpio_desc acpi_default_gps = {
.host_wake_idx = -1,
 };
 
+static struct rfkill_gpio_desc acpi_bluetooth_wake = {
+   .type = RFKILL_TYPE_BLUETOOTH,
+   .reset_idx = -1,
+   .shutdown_idx = 1,
+   .wake_idx = 0,
+   .host_wake_idx = 2,
+};
+
 static const struct acpi_device_id rfkill_acpi_match[] = {
{ "BCM2E1A", (kernel_ulong_t)&acpi_default_bluetooth },
{ "BCM2E39", (kernel_ulong_t)&acpi_default_bluetooth },
{ "BCM2E3D", (kernel_ulong_t)&acpi_default_bluetooth },
{ "BCM2E64", (kernel_ulong_t)&acpi_default_bluetooth },
+   { "OBDA8723", (kernel_ulong_t)&acpi_bluetooth_wake },
{ "BCM4752", (kernel_ulong_t)&acpi_default_gps },
{ "LNV4752", (kernel_ulong_t)&acpi_default_gps },
{ },
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] net: rfkill: gpio: Implement host wake up support

2014-10-08 Thread Loic Poulain
Some GPIO based rfkill devices can wake their host up from suspend by
toggling an input (from the host perspective) GPIO.
This patch adds a generic support for that feature by registering a
threaded interrupt routine and thus setting the corresponding GPIO as a
wake up source.

Signed-off-by: Loic Poulain 
---
 net/rfkill/rfkill-gpio.c | 49 
 1 file changed, 49 insertions(+)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 29369d6..2f6aad1 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -36,6 +37,8 @@ struct rfkill_gpio_data {
struct gpio_desc*shutdown_gpio;
struct gpio_desc*wake_gpio;
 
+   int host_wake_irq;
+
struct rfkill   *rfkill_dev;
struct clk  *clk;
 
@@ -48,6 +51,7 @@ struct rfkill_gpio_desc {
int reset_idx;
int shutdown_idx;
int wake_idx;
+   int host_wake_idx;
 };
 
 static int rfkill_gpio_set_power(void *data, bool blocked)
@@ -73,6 +77,15 @@ static const struct rfkill_ops rfkill_gpio_ops = {
.set_block = rfkill_gpio_set_power,
 };
 
+static irqreturn_t rfkill_gpio_host_wake(int irq, void *dev)
+{
+   struct rfkill_gpio_data *rfkill = dev;
+
+   pr_info("Host wake IRQ for %s\n", rfkill->name);
+
+   return IRQ_HANDLED;
+}
+
 static int rfkill_gpio_init(struct device *dev, struct rfkill_gpio_desc *desc)
 {
int ret;
@@ -125,6 +138,34 @@ static int rfkill_gpio_init(struct device *dev, struct 
rfkill_gpio_desc *desc)
}
}
 
+   rfkill->host_wake_irq = -1;
+
+   if (desc && (desc->host_wake_idx >= 0)) {
+   gpio = devm_gpiod_get_index(dev, "host_wake",
+   desc->host_wake_idx);
+   if (!IS_ERR(gpio)) {
+   int irqf = IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND |
+  IRQF_ONESHOT;
+
+   ret = gpiod_direction_input(gpio);
+   if (ret)
+   return ret;
+
+   rfkill->host_wake_irq = gpiod_to_irq(gpio);
+   ret = devm_request_threaded_irq(dev,
+   rfkill->host_wake_irq,
+   NULL,
+   rfkill_gpio_host_wake,
+   irqf, "host_wake",
+   rfkill);
+   if (ret)
+   return ret;
+
+   /* Wakeup IRQ, only used in suspend */
+   disable_irq(rfkill->host_wake_irq);
+   }
+   }
+
/* Make sure at-least one of the GPIO is defined */
if (!rfkill->reset_gpio && !rfkill->shutdown_gpio) {
dev_err(dev, "invalid platform data\n");
@@ -205,6 +246,9 @@ static int rfkill_gpio_suspend(struct device *dev)
if (!rfkill->clk_enabled)
return 0;
 
+   if (rfkill->host_wake_irq >= 0)
+   enable_irq(rfkill->host_wake_irq);
+
gpiod_set_value_cansleep(rfkill->wake_gpio, 0);
 
return 0;
@@ -219,6 +263,9 @@ static int rfkill_gpio_resume(struct device *dev)
if (!rfkill->clk_enabled)
return 0;
 
+   if (rfkill->host_wake_irq >= 0)
+   disable_irq(rfkill->host_wake_irq);
+
gpiod_set_value_cansleep(rfkill->wake_gpio, 1);
 
return 0;
@@ -243,6 +290,7 @@ static struct rfkill_gpio_desc acpi_default_bluetooth = {
.reset_idx = 0,
.shutdown_idx = 1,
.wake_idx = -1,
+   .host_wake_idx = -1,
 };
 
 static struct rfkill_gpio_desc acpi_default_gps = {
@@ -250,6 +298,7 @@ static struct rfkill_gpio_desc acpi_default_gps = {
.reset_idx = 0,
.shutdown_idx = 1,
.wake_idx = -1,
+   .host_wake_idx = -1,
 };
 
 static const struct acpi_device_id rfkill_acpi_match[] = {
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] net: rfkill: gpio: Implement PM hooks

2014-10-08 Thread Loic Poulain
GPIO based rfkill devices should also be put to sleep mode when the
system enters suspend. This patch introduces a wake gpio.

Signed-off-by: Loic Poulain 
---
 net/rfkill/rfkill-gpio.c | 48 
 1 file changed, 48 insertions(+)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 7982841..29369d6 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -34,6 +34,7 @@ struct rfkill_gpio_data {
enum rfkill_typetype;
struct gpio_desc*reset_gpio;
struct gpio_desc*shutdown_gpio;
+   struct gpio_desc*wake_gpio;
 
struct rfkill   *rfkill_dev;
struct clk  *clk;
@@ -46,6 +47,7 @@ struct rfkill_gpio_desc {
 
int reset_idx;
int shutdown_idx;
+   int wake_idx;
 };
 
 static int rfkill_gpio_set_power(void *data, bool blocked)
@@ -57,6 +59,7 @@ static int rfkill_gpio_set_power(void *data, bool blocked)
 
gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked);
gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked);
+   gpiod_set_value_cansleep(rfkill->wake_gpio, !blocked);
 
if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled)
clk_disable(rfkill->clk);
@@ -112,6 +115,16 @@ static int rfkill_gpio_init(struct device *dev, struct 
rfkill_gpio_desc *desc)
rfkill->shutdown_gpio = gpio;
}
 
+   if (desc && (desc->wake_idx >= 0)) {
+   gpio = devm_gpiod_get_index(dev, "wake", desc->wake_idx);
+   if (!IS_ERR(gpio)) {
+   ret = gpiod_direction_output(gpio, 0);
+   if (ret)
+   return ret;
+   rfkill->wake_gpio = gpio;
+   }
+   }
+
/* Make sure at-least one of the GPIO is defined */
if (!rfkill->reset_gpio && !rfkill->shutdown_gpio) {
dev_err(dev, "invalid platform data\n");
@@ -182,6 +195,38 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
return 0;
 }
 
+#ifdef CONFIG_PM
+static int rfkill_gpio_suspend(struct device *dev)
+{
+   struct rfkill_gpio_data *rfkill = dev_get_drvdata(dev);
+
+   dev_dbg(dev, "Suspend\n");
+
+   if (!rfkill->clk_enabled)
+   return 0;
+
+   gpiod_set_value_cansleep(rfkill->wake_gpio, 0);
+
+   return 0;
+}
+
+static int rfkill_gpio_resume(struct device *dev)
+{
+   struct rfkill_gpio_data *rfkill = dev_get_drvdata(dev);
+
+   dev_dbg(dev, "Resume\n");
+
+   if (!rfkill->clk_enabled)
+   return 0;
+
+   gpiod_set_value_cansleep(rfkill->wake_gpio, 1);
+
+   return 0;
+}
+#endif
+static SIMPLE_DEV_PM_OPS(rfkill_gpio_pm, rfkill_gpio_suspend,
+rfkill_gpio_resume);
+
 static int rfkill_gpio_remove(struct platform_device *pdev)
 {
struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev);
@@ -197,12 +242,14 @@ static struct rfkill_gpio_desc acpi_default_bluetooth = {
.type = RFKILL_TYPE_BLUETOOTH,
.reset_idx = 0,
.shutdown_idx = 1,
+   .wake_idx = -1,
 };
 
 static struct rfkill_gpio_desc acpi_default_gps = {
.type = RFKILL_TYPE_GPS,
.reset_idx = 0,
.shutdown_idx = 1,
+   .wake_idx = -1,
 };
 
 static const struct acpi_device_id rfkill_acpi_match[] = {
@@ -223,6 +270,7 @@ static struct platform_driver rfkill_gpio_driver = {
.driver = {
.name = "rfkill_gpio",
.owner = THIS_MODULE,
+   .pm = &rfkill_gpio_pm,
.acpi_match_table = ACPI_PTR(rfkill_acpi_match),
},
 };
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] net: rfkill: gpio: Configurable GPIO idx

2014-10-08 Thread Loic Poulain
Some devices don't match the current static gpio mapping:
-BCM4752 (GPS) uses gpio res 0 as host wake irq.
-OBDA8723 (Bluetooth) uses gpio res 0 as controller wake gpio
and res 2 as host wake irq.

To allow more flexibility, this patch introduces an index
map description.
By default, legacy config still used (reset: idx 0;
shutdown: idx 1).

Signed-off-by: Loic Poulain 
---
 net/rfkill/rfkill-gpio.c | 125 +--
 1 file changed, 88 insertions(+), 37 deletions(-)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 0f62326..7982841 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -41,6 +41,13 @@ struct rfkill_gpio_data {
boolclk_enabled;
 };
 
+struct rfkill_gpio_desc {
+   enum rfkill_typetype;
+
+   int reset_idx;
+   int shutdown_idx;
+};
+
 static int rfkill_gpio_set_power(void *data, bool blocked)
 {
struct rfkill_gpio_data *rfkill = data;
@@ -63,32 +70,89 @@ static const struct rfkill_ops rfkill_gpio_ops = {
.set_block = rfkill_gpio_set_power,
 };
 
+static int rfkill_gpio_init(struct device *dev, struct rfkill_gpio_desc *desc)
+{
+   int ret;
+   struct gpio_desc *gpio;
+   struct rfkill_gpio_data *rfkill = dev_get_drvdata(dev);
+
+   if (!rfkill->name) {
+   dev_err(dev, "invalid platform data\n");
+   return -EINVAL;
+   }
+
+   rfkill->clk = devm_clk_get(dev, NULL);
+
+   if (!desc)
+   gpio = devm_gpiod_get_index(dev, "reset", 0);
+   else if (desc->reset_idx >= 0)
+   gpio = devm_gpiod_get_index(dev, "reset", desc->reset_idx);
+   else
+   gpio = NULL;
+
+   if (gpio && !IS_ERR(gpio)) {
+   ret = gpiod_direction_output(gpio, 0);
+   if (ret)
+   return ret;
+   rfkill->reset_gpio = gpio;
+   }
+
+   if (!desc)
+   gpio = devm_gpiod_get_index(dev, "shutdown", 1);
+   else if (desc->shutdown_idx >= 0)
+   gpio = devm_gpiod_get_index(dev, "shutdown",
+   desc->shutdown_idx);
+   else
+   gpio = NULL;
+
+   if (gpio && !IS_ERR(gpio)) {
+   ret = gpiod_direction_output(gpio, 0);
+   if (ret)
+   return ret;
+   rfkill->shutdown_gpio = gpio;
+   }
+
+   /* Make sure at-least one of the GPIO is defined */
+   if (!rfkill->reset_gpio && !rfkill->shutdown_gpio) {
+   dev_err(dev, "invalid platform data\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int rfkill_gpio_acpi_probe(struct device *dev,
  struct rfkill_gpio_data *rfkill)
 {
const struct acpi_device_id *id;
+   struct rfkill_gpio_desc *desc;
 
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return -ENODEV;
 
+   desc = (struct rfkill_gpio_desc *)id->driver_data;
+   if (!desc)
+   return -ENODEV;
+
rfkill->name = dev_name(dev);
-   rfkill->type = (unsigned)id->driver_data;
+   rfkill->type = desc->type;
 
-   return 0;
+   return rfkill_gpio_init(dev, desc);
 }
 
 static int rfkill_gpio_probe(struct platform_device *pdev)
 {
struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
struct rfkill_gpio_data *rfkill;
-   struct gpio_desc *gpio;
int ret;
 
rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL);
if (!rfkill)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, rfkill);
+
if (ACPI_HANDLE(&pdev->dev)) {
ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill);
if (ret)
@@ -96,34 +160,11 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
} else if (pdata) {
rfkill->name = pdata->name;
rfkill->type = pdata->type;
-   } else {
-   return -ENODEV;
-   }
-
-   rfkill->clk = devm_clk_get(&pdev->dev, NULL);
-
-   gpio = devm_gpiod_get_index(&pdev->dev, "reset", 0);
-   if (!IS_ERR(gpio)) {
-   ret = gpiod_direction_output(gpio, 0);
+   ret = rfkill_gpio_init(&pdev->dev, NULL);
if (ret)
return ret;
-   rfkill->reset_gpio = gpio;
-   }
-
-   gpio = devm_gpiod_get_index(&pdev->dev, "shutdown", 1);
-   if (!IS_ERR(gpio)) {
-   ret = gpiod_direction_output(gpio, 0);
-   if (ret)
-   return ret;
-   rfkill

Re: [PATCH] net: rfkill: gpio: Fix clock status

2014-09-17 Thread Loic Poulain
If rfkill block/unblock are balanced, the following conditions are never 
true:

- if (!blocked && !rfkill->clk_enabled)
- if (blocked && rfkill->clk_enabled)

Then, clock is neither disabled nor enabled.
If clock is enabled by default, it does not cause any obvious issue.

Or maybe there's not much device with clock resource.

Regards,
Loic

On 17/09/2014 17:11, John W. Linville wrote:

On Tue, Sep 16, 2014 at 02:53:58PM +0200, Loic Poulain wrote:

Clock is disabled when the device is blocked.
So, clock_enabled is the logical negation of "blocked".

Signed-off-by: Loic Poulain 
---
  net/rfkill/rfkill-gpio.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 14c98e4..408e51f 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -54,7 +54,7 @@ static int rfkill_gpio_set_power(void *data, bool blocked)
if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled)
clk_disable(rfkill->clk);
  
-	rfkill->clk_enabled = blocked;

+   rfkill->clk_enabled = !blocked;
  
  	return 0;

  }

This looks like the right fix, but...the code has been that way for
a long time.  If this patch is correct, how has this gone undetected
for so long?

John


--
Intel Open Source Technology Center
http://oss.intel.com/

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] net: rfkill: gpio: Fix clock status

2014-09-16 Thread Loic Poulain
Clock is disabled when the device is blocked.
So, clock_enabled is the logical negation of "blocked".

Signed-off-by: Loic Poulain 
---
 net/rfkill/rfkill-gpio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 14c98e4..408e51f 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -54,7 +54,7 @@ static int rfkill_gpio_set_power(void *data, bool blocked)
if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled)
clk_disable(rfkill->clk);
 
-   rfkill->clk_enabled = blocked;
+   rfkill->clk_enabled = !blocked;
 
return 0;
 }
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Realtek GPIO chipset, for Baytrail?

2014-09-11 Thread Loic Poulain

Hi Bastien,

Your device is a child of 80860F0A (UART) which is driven by the 8250_dw 
driver.

OBDA8723 is the BT part of the realtek 8723 WiFi/BT combo chip.
acpi_platform should create a platform device from the ACPI desc.
Then, you can add the OBDA8723 acpi id to the rfkill-gpio platform 
driver (net/rfkill) which

seems to handle correctly the basic power management of this chip.

You need to use hciattach to attach the chip to the BT stack (with 
H5/3-wire proto).


Regards,
Loic

On 11/09/2014 17:06, Marcel Holtmann wrote:

Hi Bastien,


I have a tablet that seems to be using Realtek chips to do wireless
communications (hopefully, this time I won't be wrong[1]).

The device, under the gpio class in /sys, shows with a modalias of
"acpi:OBDA8723:" (that's on "O", not "0"). This seems to correspond to a
Realtek chipset (Larry tells me it matches the PCI ID of 0bda:8723 for
the RTL8723AE chipset).

It shows up under:
/sys/devices/platform/80860F0A:00/subsystem/devices

Does anyone have details on how this chipset is actually hooked up? Can
a portion of the existing RTL8723AE driver code be reused?

so after a little bit of digging, this seems to be the UART device for the 
Bluetooth chip. Can you try using 8250_dw.ko driver and see if it binds to it 
and you get a new serial port.

If I am correct then you have to run H:5 UART transport protocol to enable 
Bluetooth for this device.

Please double check that this ACPI tables really wrongly declare this as a 
Broadcom chip. This seems to be a firmware bug then. Unfortunately I think that 
for Broadcom you run H:4 UART transport protocol and for Realtek you have to 
run H:5 UART transport protocol. So no idea how to nicely differentiate these.

Regards

Marcel

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
Intel Open Source Technology Center
http://oss.intel.com/

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html