Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2 08/12] wil6210: missing length check in wil_cfg80211_mgmt_tx
From: Maya Erez @ 2017-11-01 19:23 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Lior David, linux-wireless, wil6210, Maya Erez
In-Reply-To: <1509564202-30078-1-git-send-email-qca_merez@qca.qualcomm.com>

From: Lior David <qca_liord@qca.qualcomm.com>

Add a length check in wil_cfg80211_mgmt_tx to detect unsigned integer
overflow.

Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
---
 drivers/net/wireless/ath/wil6210/cfg80211.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index c3d3c0c..771a534 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -901,7 +901,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 			 u64 *cookie)
 {
 	const u8 *buf = params->buf;
-	size_t len = params->len;
+	size_t len = params->len, total;
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	int rc;
 	bool tx_status = false;
@@ -926,7 +926,11 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	if (len < sizeof(struct ieee80211_hdr_3addr))
 		return -EINVAL;
 
-	cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
+	total = sizeof(*cmd) + len;
+	if (total < len)
+		return -EINVAL;
+
+	cmd = kmalloc(total, GFP_KERNEL);
 	if (!cmd) {
 		rc = -ENOMEM;
 		goto out;
@@ -936,7 +940,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	cmd->len = cpu_to_le16(len);
 	memcpy(cmd->payload, buf, len);
 
-	rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
+	rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, total,
 		      WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
 	if (rc == 0)
 		tx_status = !evt.evt.status;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 09/12] wil6210: get suspend reject reason and resume triggers from FW
From: Maya Erez @ 2017-11-01 19:23 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Lazar Alexei, linux-wireless, wil6210, Maya Erez
In-Reply-To: <1509564202-30078-1-git-send-email-qca_merez@qca.qualcomm.com>

From: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>

Upon receiving suspend reject, print reject reason.
Upon receiving resume event, print resume triggers.

Signed-off-by: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
---
 drivers/net/wireless/ath/wil6210/wmi.c | 46 +++++++++++++++++++++++++++++++---
 drivers/net/wireless/ath/wil6210/wmi.h | 17 ++++++++++---
 2 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index dd25f63..8ace618 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -2043,6 +2043,16 @@ void wmi_event_flush(struct wil6210_priv *wil)
 	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
 }
 
+static const char *suspend_status2name(u8 status)
+{
+	switch (status) {
+	case WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE:
+		return "LINK_NOT_IDLE";
+	default:
+		return "Untracked status";
+	}
+}
+
 int wmi_suspend(struct wil6210_priv *wil)
 {
 	int rc;
@@ -2058,7 +2068,7 @@ int wmi_suspend(struct wil6210_priv *wil)
 	wil->suspend_resp_rcvd = false;
 	wil->suspend_resp_comp = false;
 
-	reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED;
+	reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE;
 
 	rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd),
 		      WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
@@ -2090,8 +2100,9 @@ int wmi_suspend(struct wil6210_priv *wil)
 	}
 
 	wil_dbg_wmi(wil, "suspend_response_completed rcvd\n");
-	if (reply.evt.status == WMI_TRAFFIC_SUSPEND_REJECTED) {
-		wil_dbg_pm(wil, "device rejected the suspend\n");
+	if (reply.evt.status != WMI_TRAFFIC_SUSPEND_APPROVED) {
+		wil_dbg_pm(wil, "device rejected the suspend, %s\n",
+			   suspend_status2name(reply.evt.status));
 		wil->suspend_stats.rejected_by_device++;
 	}
 	rc = reply.evt.status;
@@ -2103,21 +2114,50 @@ int wmi_suspend(struct wil6210_priv *wil)
 	return rc;
 }
 
+static void resume_triggers2string(u32 triggers, char *string, int str_size)
+{
+	string[0] = '\0';
+
+	if (!triggers) {
+		strlcat(string, " UNKNOWN", str_size);
+		return;
+	}
+
+	if (triggers & WMI_RESUME_TRIGGER_HOST)
+		strlcat(string, " HOST", str_size);
+
+	if (triggers & WMI_RESUME_TRIGGER_UCAST_RX)
+		strlcat(string, " UCAST_RX", str_size);
+
+	if (triggers & WMI_RESUME_TRIGGER_BCAST_RX)
+		strlcat(string, " BCAST_RX", str_size);
+
+	if (triggers & WMI_RESUME_TRIGGER_WMI_EVT)
+		strlcat(string, " WMI_EVT", str_size);
+}
+
 int wmi_resume(struct wil6210_priv *wil)
 {
 	int rc;
+	char string[100];
 	struct {
 		struct wmi_cmd_hdr wmi;
 		struct wmi_traffic_resume_event evt;
 	} __packed reply;
 
 	reply.evt.status = WMI_TRAFFIC_RESUME_FAILED;
+	reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN;
 
 	rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0,
 		      WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
 		      WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
 	if (rc)
 		return rc;
+	resume_triggers2string(le32_to_cpu(reply.evt.resume_triggers), string,
+			       sizeof(string));
+	wil_dbg_pm(wil, "device resume %s, resume triggers:%s (0x%x)\n",
+		   reply.evt.status ? "failed" : "passed", string,
+		   le32_to_cpu(reply.evt.resume_triggers));
 
 	return reply.evt.status;
 }
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 5263ee7..d9e220a 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -2267,8 +2267,8 @@ struct wmi_link_maintain_cfg_read_done_event {
 } __packed;
 
 enum wmi_traffic_suspend_status {
-	WMI_TRAFFIC_SUSPEND_APPROVED	= 0x0,
-	WMI_TRAFFIC_SUSPEND_REJECTED	= 0x1,
+	WMI_TRAFFIC_SUSPEND_APPROVED			= 0x0,
+	WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE	= 0x1,
 };
 
 /* WMI_TRAFFIC_SUSPEND_EVENTID */
@@ -2282,10 +2282,21 @@ enum wmi_traffic_resume_status {
 	WMI_TRAFFIC_RESUME_FAILED	= 0x1,
 };
 
+enum wmi_resume_trigger {
+	WMI_RESUME_TRIGGER_UNKNOWN	= 0x0,
+	WMI_RESUME_TRIGGER_HOST		= 0x1,
+	WMI_RESUME_TRIGGER_UCAST_RX	= 0x2,
+	WMI_RESUME_TRIGGER_BCAST_RX	= 0x4,
+	WMI_RESUME_TRIGGER_WMI_EVT	= 0x8,
+};
+
 /* WMI_TRAFFIC_RESUME_EVENTID */
 struct wmi_traffic_resume_event {
-	/* enum wmi_traffic_resume_status_e */
+	/* enum wmi_traffic_resume_status */
 	u8 status;
+	u8 reserved[3];
+	/* enum wmi_resume_trigger bitmap */
+	__le32 resume_triggers;
 } __packed;
 
 /* Power Save command completion status codes */
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 10/12] wil6210: fix PCIe bus mastering in case of interface down
From: Maya Erez @ 2017-11-01 19:23 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Lazar Alexei, linux-wireless, wil6210, Maya Erez
In-Reply-To: <1509564202-30078-1-git-send-email-qca_merez@qca.qualcomm.com>

From: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>

In case of interface down, radio is turned off but PCIe mastering is
not cleared.
This can cause unexpected PCIe access to the shutdown device.
Fix this by clearing PCIe mastering also in case interface is down

Signed-off-by: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
---
 drivers/net/wireless/ath/wil6210/pcie_bus.c | 24 +++++++++++++++---------
 drivers/net/wireless/ath/wil6210/pm.c       | 10 ++--------
 drivers/net/wireless/ath/wil6210/wil6210.h  |  4 ++--
 3 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index b4de001..af062fc 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -385,6 +385,9 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
 	int rc = 0;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct wil6210_priv *wil = pci_get_drvdata(pdev);
+	struct net_device *ndev = wil_to_ndev(wil);
+	bool keep_radio_on = ndev->flags & IFF_UP &&
+			     wil->keep_radio_on_during_sleep;
 
 	wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
 
@@ -392,14 +395,14 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
 	if (rc)
 		goto out;
 
-	rc = wil_suspend(wil, is_runtime);
+	rc = wil_suspend(wil, is_runtime, keep_radio_on);
 	if (!rc) {
 		wil->suspend_stats.successful_suspends++;
 
-		/* If platform device supports keep_radio_on_during_sleep
-		 * it will control PCIe master
+		/* In case radio stays on, platform device will control
+		 * PCIe master
 		 */
-		if (!wil->keep_radio_on_during_sleep)
+		if (!keep_radio_on)
 			/* disable bus mastering */
 			pci_clear_master(pdev);
 	}
@@ -412,20 +415,23 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
 	int rc = 0;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct wil6210_priv *wil = pci_get_drvdata(pdev);
+	struct net_device *ndev = wil_to_ndev(wil);
+	bool keep_radio_on = ndev->flags & IFF_UP &&
+			     wil->keep_radio_on_during_sleep;
 
 	wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
 
-	/* If platform device supports keep_radio_on_during_sleep it will
-	 * control PCIe master
+	/* In case radio stays on, platform device will control
+	 * PCIe master
 	 */
-	if (!wil->keep_radio_on_during_sleep)
+	if (!keep_radio_on)
 		/* allow master */
 		pci_set_master(pdev);
-	rc = wil_resume(wil, is_runtime);
+	rc = wil_resume(wil, is_runtime, keep_radio_on);
 	if (rc) {
 		wil_err(wil, "device failed to resume (%d)\n", rc);
 		wil->suspend_stats.failed_resumes++;
-		if (!wil->keep_radio_on_during_sleep)
+		if (!keep_radio_on)
 			pci_clear_master(pdev);
 	} else {
 		wil->suspend_stats.successful_resumes++;
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 2ef2f34..ce4f546 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -300,12 +300,9 @@ static int wil_resume_radio_off(struct wil6210_priv *wil)
 	return rc;
 }
 
-int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
 {
 	int rc = 0;
-	struct net_device *ndev = wil_to_ndev(wil);
-	bool keep_radio_on = ndev->flags & IFF_UP &&
-			     wil->keep_radio_on_during_sleep;
 
 	wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
 
@@ -328,12 +325,9 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
 	return rc;
 }
 
-int wil_resume(struct wil6210_priv *wil, bool is_runtime)
+int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
 {
 	int rc = 0;
-	struct net_device *ndev = wil_to_ndev(wil);
-	bool keep_radio_on = ndev->flags & IFF_UP &&
-			     wil->keep_radio_on_during_sleep;
 	unsigned long long suspend_time_usec = 0;
 
 	wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 2521c7d..2441818 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -1018,8 +1018,8 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name,
 void wil_pm_runtime_put(struct wil6210_priv *wil);
 
 int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
-int wil_suspend(struct wil6210_priv *wil, bool is_runtime);
-int wil_resume(struct wil6210_priv *wil, bool is_runtime);
+int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on);
+int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on);
 bool wil_is_wmi_idle(struct wil6210_priv *wil);
 int wmi_resume(struct wil6210_priv *wil);
 int wmi_suspend(struct wil6210_priv *wil);
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 11/12] wil6210: remove suspend time statistics
From: Maya Erez @ 2017-11-01 19:23 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Lazar Alexei, linux-wireless, wil6210, Maya Erez
In-Reply-To: <1509564202-30078-1-git-send-email-qca_merez@qca.qualcomm.com>

From: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>

Currently suspend time statistics are showed through debugfs.
Remove time statistics in suspend state since the timing may
not be accurate in that state.

Signed-off-by: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
---
 drivers/net/wireless/ath/wil6210/debugfs.c | 17 ++---------------
 drivers/net/wireless/ath/wil6210/main.c    |  1 -
 drivers/net/wireless/ath/wil6210/pm.c      | 20 ++------------------
 drivers/net/wireless/ath/wil6210/wil6210.h |  5 -----
 4 files changed, 4 insertions(+), 39 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 06b9c56..edaab0f 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1632,8 +1632,6 @@ static ssize_t wil_write_suspend_stats(struct file *file,
 	struct wil6210_priv *wil = file->private_data;
 
 	memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
-	wil->suspend_stats.min_suspend_time = ULONG_MAX;
-	wil->suspend_stats.collection_start = ktime_get();
 
 	return len;
 }
@@ -1645,27 +1643,18 @@ static ssize_t wil_read_suspend_stats(struct file *file,
 	struct wil6210_priv *wil = file->private_data;
 	static char text[400];
 	int n;
-	unsigned long long stats_collection_time =
-		ktime_to_us(ktime_sub(ktime_get(),
-				      wil->suspend_stats.collection_start));
 
 	n = snprintf(text, sizeof(text),
 		     "Suspend statistics:\n"
 		     "successful suspends:%ld failed suspends:%ld\n"
 		     "successful resumes:%ld failed resumes:%ld\n"
-		     "rejected by host:%ld rejected by device:%ld\n"
-		     "total suspend time:%lld min suspend time:%lld\n"
-		     "max suspend time:%lld stats collection time: %lld\n",
+		     "rejected by host:%ld rejected by device:%ld\n",
 		     wil->suspend_stats.successful_suspends,
 		     wil->suspend_stats.failed_suspends,
 		     wil->suspend_stats.successful_resumes,
 		     wil->suspend_stats.failed_resumes,
 		     wil->suspend_stats.rejected_by_host,
-		     wil->suspend_stats.rejected_by_device,
-		     wil->suspend_stats.total_suspend_time,
-		     wil->suspend_stats.min_suspend_time,
-		     wil->suspend_stats.max_suspend_time,
-		     stats_collection_time);
+		     wil->suspend_stats.rejected_by_device);
 
 	n = min_t(int, n, sizeof(text));
 
@@ -1836,8 +1825,6 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
 
 	wil6210_debugfs_create_ITR_CNT(wil, dbg);
 
-	wil->suspend_stats.collection_start = ktime_get();
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index e92fd35..1b53cd3 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -579,7 +579,6 @@ int wil_priv_init(struct wil6210_priv *wil)
 	wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
 			      WMI_WAKEUP_TRIGGER_BCAST;
 	memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
-	wil->suspend_stats.min_suspend_time = ULONG_MAX;
 	wil->vring_idle_trsh = 16;
 
 	return 0;
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index ce4f546..48ec186 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -319,16 +319,12 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
 	wil_dbg_pm(wil, "suspend: %s => %d\n",
 		   is_runtime ? "runtime" : "system", rc);
 
-	if (!rc)
-		wil->suspend_stats.suspend_start_time = ktime_get();
-
 	return rc;
 }
 
 int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
 {
 	int rc = 0;
-	unsigned long long suspend_time_usec = 0;
 
 	wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
 
@@ -346,21 +342,9 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
 	else
 		rc = wil_resume_radio_off(wil);
 
-	if (rc)
-		goto out;
-
-	suspend_time_usec =
-		ktime_to_us(ktime_sub(ktime_get(),
-				      wil->suspend_stats.suspend_start_time));
-	wil->suspend_stats.total_suspend_time += suspend_time_usec;
-	if (suspend_time_usec < wil->suspend_stats.min_suspend_time)
-		wil->suspend_stats.min_suspend_time = suspend_time_usec;
-	if (suspend_time_usec > wil->suspend_stats.max_suspend_time)
-		wil->suspend_stats.max_suspend_time = suspend_time_usec;
-
 out:
-	wil_dbg_pm(wil, "resume: %s => %d, suspend time %lld usec\n",
-		   is_runtime ? "runtime" : "system", rc, suspend_time_usec);
+	wil_dbg_pm(wil, "resume: %s => %d\n", is_runtime ? "runtime" : "system",
+		   rc);
 	return rc;
 }
 
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 2441818..0ae2415 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -89,11 +89,6 @@ struct wil_suspend_stats {
 	unsigned long failed_resumes;
 	unsigned long rejected_by_device;
 	unsigned long rejected_by_host;
-	unsigned long long total_suspend_time;
-	unsigned long long min_suspend_time;
-	unsigned long long max_suspend_time;
-	ktime_t collection_start;
-	ktime_t suspend_start_time;
 };
 
 /* Calculate MAC buffer size for the firmware. It includes all overhead,
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 12/12] wil6210: update statistics for suspend
From: Maya Erez @ 2017-11-01 19:23 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Lazar Alexei, linux-wireless, wil6210, Maya Erez
In-Reply-To: <1509564202-30078-1-git-send-email-qca_merez@qca.qualcomm.com>

From: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>

Currently the statistics show how many successful/failed
suspend/resume operations the system had.
Update the statistics by splitting each successful/failed
suspend/resume operations to radio on/off.

Signed-off-by: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
---
 drivers/net/wireless/ath/wil6210/debugfs.c  | 47 ++++++++++++++++++++---------
 drivers/net/wireless/ath/wil6210/pcie_bus.c | 20 ++++++++----
 drivers/net/wireless/ath/wil6210/pm.c       |  8 +++--
 drivers/net/wireless/ath/wil6210/wil6210.h  | 11 +++++--
 4 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index edaab0f..4475937 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1641,24 +1641,41 @@ static ssize_t wil_read_suspend_stats(struct file *file,
 				      size_t count, loff_t *ppos)
 {
 	struct wil6210_priv *wil = file->private_data;
-	static char text[400];
-	int n;
+	char *text;
+	int n, ret, text_size = 500;
+
+	text = kmalloc(text_size, GFP_KERNEL);
+	if (!text)
+		return -ENOMEM;
 
-	n = snprintf(text, sizeof(text),
-		     "Suspend statistics:\n"
+	n = snprintf(text, text_size,
+		     "Radio on suspend statistics:\n"
 		     "successful suspends:%ld failed suspends:%ld\n"
 		     "successful resumes:%ld failed resumes:%ld\n"
-		     "rejected by host:%ld rejected by device:%ld\n",
-		     wil->suspend_stats.successful_suspends,
-		     wil->suspend_stats.failed_suspends,
-		     wil->suspend_stats.successful_resumes,
-		     wil->suspend_stats.failed_resumes,
-		     wil->suspend_stats.rejected_by_host,
-		     wil->suspend_stats.rejected_by_device);
-
-	n = min_t(int, n, sizeof(text));
-
-	return simple_read_from_buffer(user_buf, count, ppos, text, n);
+		     "rejected by device:%ld\n"
+		     "Radio off suspend statistics:\n"
+		     "successful suspends:%ld failed suspends:%ld\n"
+		     "successful resumes:%ld failed resumes:%ld\n"
+		     "General statistics:\n"
+		     "rejected by host:%ld\n",
+		     wil->suspend_stats.r_on.successful_suspends,
+		     wil->suspend_stats.r_on.failed_suspends,
+		     wil->suspend_stats.r_on.successful_resumes,
+		     wil->suspend_stats.r_on.failed_resumes,
+		     wil->suspend_stats.rejected_by_device,
+		     wil->suspend_stats.r_off.successful_suspends,
+		     wil->suspend_stats.r_off.failed_suspends,
+		     wil->suspend_stats.r_off.successful_resumes,
+		     wil->suspend_stats.r_off.failed_resumes,
+		     wil->suspend_stats.rejected_by_host);
+
+	n = min_t(int, n, text_size);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, text, n);
+
+	kfree(text);
+
+	return ret;
 }
 
 static const struct file_operations fops_suspend_stats = {
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index af062fc..53e8e60 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -397,14 +397,16 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
 
 	rc = wil_suspend(wil, is_runtime, keep_radio_on);
 	if (!rc) {
-		wil->suspend_stats.successful_suspends++;
-
 		/* In case radio stays on, platform device will control
 		 * PCIe master
 		 */
-		if (!keep_radio_on)
+		if (!keep_radio_on) {
 			/* disable bus mastering */
 			pci_clear_master(pdev);
+			wil->suspend_stats.r_off.successful_suspends++;
+		} else {
+			wil->suspend_stats.r_on.successful_suspends++;
+		}
 	}
 out:
 	return rc;
@@ -430,11 +432,17 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
 	rc = wil_resume(wil, is_runtime, keep_radio_on);
 	if (rc) {
 		wil_err(wil, "device failed to resume (%d)\n", rc);
-		wil->suspend_stats.failed_resumes++;
-		if (!keep_radio_on)
+		if (!keep_radio_on) {
 			pci_clear_master(pdev);
+			wil->suspend_stats.r_off.failed_resumes++;
+		} else {
+			wil->suspend_stats.r_on.failed_resumes++;
+		}
 	} else {
-		wil->suspend_stats.successful_resumes++;
+		if (keep_radio_on)
+			wil->suspend_stats.r_on.successful_resumes++;
+		else
+			wil->suspend_stats.r_off.successful_resumes++;
 	}
 
 	return rc;
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 48ec186..ec39ac7 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -179,7 +179,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
 					break;
 				wil_err(wil,
 					"TO waiting for idle RX, suspend failed\n");
-				wil->suspend_stats.failed_suspends++;
+				wil->suspend_stats.r_on.failed_suspends++;
 				goto resume_after_fail;
 			}
 			wil_dbg_ratelimited(wil, "rx vring is not empty -> NAPI\n");
@@ -195,7 +195,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
 	 */
 	if (!wil_is_wmi_idle(wil)) {
 		wil_err(wil, "suspend failed due to pending WMI events\n");
-		wil->suspend_stats.failed_suspends++;
+		wil->suspend_stats.r_on.failed_suspends++;
 		goto resume_after_fail;
 	}
 
@@ -209,7 +209,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
 		if (rc) {
 			wil_err(wil, "platform device failed to suspend (%d)\n",
 				rc);
-			wil->suspend_stats.failed_suspends++;
+			wil->suspend_stats.r_on.failed_suspends++;
 			wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
 			wil_unmask_irq(wil);
 			goto resume_after_fail;
@@ -256,6 +256,7 @@ static int wil_suspend_radio_off(struct wil6210_priv *wil)
 		rc = wil_down(wil);
 		if (rc) {
 			wil_err(wil, "wil_down : %d\n", rc);
+			wil->suspend_stats.r_off.failed_suspends++;
 			goto out;
 		}
 	}
@@ -268,6 +269,7 @@ static int wil_suspend_radio_off(struct wil6210_priv *wil)
 		rc = wil->platform_ops.suspend(wil->platform_handle, false);
 		if (rc) {
 			wil_enable_irq(wil);
+			wil->suspend_stats.r_off.failed_suspends++;
 			goto out;
 		}
 	}
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 0ae2415..54b96ae 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -82,12 +82,17 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
  */
 #define WIL_MAX_MPDU_OVERHEAD	(62)
 
-struct wil_suspend_stats {
+struct wil_suspend_count_stats {
 	unsigned long successful_suspends;
-	unsigned long failed_suspends;
 	unsigned long successful_resumes;
+	unsigned long failed_suspends;
 	unsigned long failed_resumes;
-	unsigned long rejected_by_device;
+};
+
+struct wil_suspend_stats {
+	struct wil_suspend_count_stats r_off;
+	struct wil_suspend_count_stats r_on;
+	unsigned long rejected_by_device; /* only radio on */
 	unsigned long rejected_by_host;
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH] ath10k: fix recent bandwidth conversion bug
From: Christian Lamparter @ 2017-11-01 20:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalle Valo

The commit "cfg80211: make RATE_INFO_BW_20 the default" changed
the index of RATE_INFO_BW_20, but the updates to ath10k missed
the special bandwidth calculation case in
ath10k_update_per_peer_tx_stats().

Fixes: 842be75c77cb ("cfg80211: make RATE_INFO_BW_20 the default")
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c | 23 +++++------------------
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index a3f5dc78353f..26b0d201a698 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -592,6 +592,9 @@ struct amsdu_subframe_hdr {
 
 #define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
 
+static const u8 ath10k_bw_to_mac80211[] = { RATE_INFO_BW_20, RATE_INFO_BW_40,
+	RATE_INFO_BW_80, RATE_INFO_BW_160 };
+
 static void ath10k_htt_rx_h_rates(struct ath10k *ar,
 				  struct ieee80211_rx_status *status,
 				  struct htt_rx_desc *rxd)
@@ -694,23 +697,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
 		if (sgi)
 			status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
 
-		switch (bw) {
-		/* 20MHZ */
-		case 0:
-			break;
-		/* 40MHZ */
-		case 1:
-			status->bw = RATE_INFO_BW_40;
-			break;
-		/* 80MHZ */
-		case 2:
-			status->bw = RATE_INFO_BW_80;
-			break;
-		case 3:
-			status->bw = RATE_INFO_BW_160;
-			break;
-		}
-
+		status->bw = ath10k_bw_to_mac80211[bw];
 		status->encoding = RX_ENC_VHT;
 		break;
 	default:
@@ -2297,7 +2284,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
 		arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
 
 	arsta->txrate.nss = txrate.nss;
-	arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
+	arsta->txrate.bw = ath10k_bw_to_mac80211[txrate.bw];
 }
 
 static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
-- 
2.15.0

^ permalink raw reply related

* Re: [PATCH] ath10k: fix recent bandwidth conversion bug
From: Sebastian Gottschall @ 2017-11-01 20:36 UTC (permalink / raw)
  To: Christian Lamparter, linux-wireless; +Cc: Kalle Valo
In-Reply-To: <20171101200157.27096-1-chunkeey@gmail.com>

true. good finding.

Am 01.11.2017 um 21:01 schrieb Christian Lamparter:
> The commit "cfg80211: make RATE_INFO_BW_20 the default" changed
> the index of RATE_INFO_BW_20, but the updates to ath10k missed
> the special bandwidth calculation case in
> ath10k_update_per_peer_tx_stats().
>
> Fixes: 842be75c77cb ("cfg80211: make RATE_INFO_BW_20 the default")
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
> ---
>   drivers/net/wireless/ath/ath10k/htt_rx.c | 23 +++++------------------
>   1 file changed, 5 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
> index a3f5dc78353f..26b0d201a698 100644
> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
> @@ -592,6 +592,9 @@ struct amsdu_subframe_hdr {
>   
>   #define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
>   
> +static const u8 ath10k_bw_to_mac80211[] = { RATE_INFO_BW_20, RATE_INFO_BW_40,
> +	RATE_INFO_BW_80, RATE_INFO_BW_160 };
> +
>   static void ath10k_htt_rx_h_rates(struct ath10k *ar,
>   				  struct ieee80211_rx_status *status,
>   				  struct htt_rx_desc *rxd)
> @@ -694,23 +697,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
>   		if (sgi)
>   			status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
>   
> -		switch (bw) {
> -		/* 20MHZ */
> -		case 0:
> -			break;
> -		/* 40MHZ */
> -		case 1:
> -			status->bw = RATE_INFO_BW_40;
> -			break;
> -		/* 80MHZ */
> -		case 2:
> -			status->bw = RATE_INFO_BW_80;
> -			break;
> -		case 3:
> -			status->bw = RATE_INFO_BW_160;
> -			break;
> -		}
> -
> +		status->bw = ath10k_bw_to_mac80211[bw];
>   		status->encoding = RX_ENC_VHT;
>   		break;
>   	default:
> @@ -2297,7 +2284,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
>   		arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
>   
>   	arsta->txrate.nss = txrate.nss;
> -	arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
> +	arsta->txrate.bw = ath10k_bw_to_mac80211[txrate.bw];
>   }
>   
>   static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,


-- 
Mit freundlichen Grüssen / Regards

Sebastian Gottschall / CTO

NewMedia-NET GmbH - DD-WRT
Firmensitz:  Stubenwaldallee 21a, 64625 Bensheim
Registergericht: Amtsgericht Darmstadt, HRB 25473
Geschäftsführer: Peter Steinhäuser, Christian Scheele
http://www.dd-wrt.com
email: s.gottschall@dd-wrt.com
Tel.: +496251-582650 / Fax: +496251-5826565

^ permalink raw reply

* Re: [PATCH] ath10k: fix recent bandwidth conversion bug
From: Sebastian Gottschall @ 2017-11-01 20:37 UTC (permalink / raw)
  To: Christian Lamparter, linux-wireless; +Cc: Kalle Valo
In-Reply-To: <20171101200157.27096-1-chunkeey@gmail.com>

a additional array bounds check would be good

Am 01.11.2017 um 21:01 schrieb Christian Lamparter:
> The commit "cfg80211: make RATE_INFO_BW_20 the default" changed
> the index of RATE_INFO_BW_20, but the updates to ath10k missed
> the special bandwidth calculation case in
> ath10k_update_per_peer_tx_stats().
>
> Fixes: 842be75c77cb ("cfg80211: make RATE_INFO_BW_20 the default")
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
> ---
>   drivers/net/wireless/ath/ath10k/htt_rx.c | 23 +++++------------------
>   1 file changed, 5 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
> index a3f5dc78353f..26b0d201a698 100644
> --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
> +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
> @@ -592,6 +592,9 @@ struct amsdu_subframe_hdr {
>   
>   #define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
>   
> +static const u8 ath10k_bw_to_mac80211[] = { RATE_INFO_BW_20, RATE_INFO_BW_40,
> +	RATE_INFO_BW_80, RATE_INFO_BW_160 };
> +
>   static void ath10k_htt_rx_h_rates(struct ath10k *ar,
>   				  struct ieee80211_rx_status *status,
>   				  struct htt_rx_desc *rxd)
> @@ -694,23 +697,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
>   		if (sgi)
>   			status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
>   
> -		switch (bw) {
> -		/* 20MHZ */
> -		case 0:
> -			break;
> -		/* 40MHZ */
> -		case 1:
> -			status->bw = RATE_INFO_BW_40;
> -			break;
> -		/* 80MHZ */
> -		case 2:
> -			status->bw = RATE_INFO_BW_80;
> -			break;
> -		case 3:
> -			status->bw = RATE_INFO_BW_160;
> -			break;
> -		}
> -
> +		status->bw = ath10k_bw_to_mac80211[bw];
>   		status->encoding = RX_ENC_VHT;
>   		break;
>   	default:
> @@ -2297,7 +2284,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
>   		arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
>   
>   	arsta->txrate.nss = txrate.nss;
> -	arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
> +	arsta->txrate.bw = ath10k_bw_to_mac80211[txrate.bw];
>   }
>   
>   static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,


-- 
Mit freundlichen Grüssen / Regards

Sebastian Gottschall / CTO

NewMedia-NET GmbH - DD-WRT
Firmensitz:  Stubenwaldallee 21a, 64625 Bensheim
Registergericht: Amtsgericht Darmstadt, HRB 25473
Geschäftsführer: Peter Steinhäuser, Christian Scheele
http://www.dd-wrt.com
email: s.gottschall@dd-wrt.com
Tel.: +496251-582650 / Fax: +496251-5826565

^ permalink raw reply

* Re: [PATCH 1/3] mwifiex: cleanup rx_pkt_lock usage in 11n_rxreorder.c
From: Brian Norris @ 2017-11-01 21:28 UTC (permalink / raw)
  To: Ganapathi Bhat
  Cc: linux-wireless, Cathy Luo, Xinming Hu, Zhiyuan Yang, James Cao,
	Mangesh Malusare, Douglas Anderson, Karthik Ananthapadmanabha
In-Reply-To: <1509442967-14149-2-git-send-email-gbhat@marvell.com>

Hi,

On Tue, Oct 31, 2017 at 03:12:45PM +0530, Ganapathi Bhat wrote:
> From: Karthik Ananthapadmanabha <karthida@marvell.com>
> 
> Fix the incorrect usage of rx_pkt_lock spinlock. Realsing the
> spinlock while the element is still in process is unsafe. The
> lock must be released only after the element processing is
> complete.
> 
> Signed-off-by: Karthik Ananthapadmanabha <karthida@marvell.com>
> Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
> ---
>  drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> index 1edcdda..0149c4a 100644
> --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> @@ -124,9 +124,10 @@ static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
>  			rx_tmp_ptr = tbl->rx_reorder_ptr[i];
>  			tbl->rx_reorder_ptr[i] = NULL;
>  		}
> -		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);

So, what is this lock protecting? Is it for protecting the packet
itself, or for protecting the ring buffer? As I read it, it's just the
latter, since once we've removed it from the ring buffer (and are about
to dispatch it up toward the networking layer), it's handled only by a
single context (or else, protected via some other common lock(s)).

If I'm correct above, then I think the current code here is actually
safe, since it holds the lock while removing from the ring buffer --
after it's removed from the ring, there's no way another thread can find
this payload, and so we can release the lock.

On a related note: I don't actually see the ring buffer *insertion*
being protected by this rx_pkt_lock, so is it really useful? See
mwifiex_11n_rx_reorder_pkt(). Perhaps the correct lock is actually
rx_reorder_tbl_lock()? Except that serves multiple purposes it seems...

Another thought: from what I can tell, all of these operations are
*only* performed on the main thread, so there's actually no concurrency
involved at all. So we also could probably drop this lock entirely...

I guess the real point is: can you explain better what you intend this
lock to do? Then we can review whether you're accomplishing your
intention, or whether we should improve the usage of this lock in some
other way, or perhaps even kill it entirely.

Thanks,
Brian

>  		if (rx_tmp_ptr)
>  			mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
> +
> +		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
>  	}
>  
>  	spin_lock_irqsave(&priv->rx_pkt_lock, flags);
> @@ -167,8 +168,8 @@ static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
>  		}
>  		rx_tmp_ptr = tbl->rx_reorder_ptr[i];
>  		tbl->rx_reorder_ptr[i] = NULL;
> -		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
>  		mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
> +		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
>  	}
>  
>  	spin_lock_irqsave(&priv->rx_pkt_lock, flags);
> -- 
> 1.9.1
> 

^ permalink raw reply

* [PATCH 1/3] staging: rtl8188eu: Revert part of "staging: rtl8188eu: fix comments with lines over 80 characters"
From: Hans de Goede @ 2017-11-02  9:30 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Hans de Goede, Larry Finger, linux-wireless, devel,
	Juliana Rodrigues

Commit 74e1e498e84e ("staging: rtl8188eu: fix comments with lines over 80
characters") not only changed comments but also changed an if check:

-if (pmlmepriv->cur_network.join_res != true) {
+if (!(pmlmepriv->cur_network.join_res)) {

This is not equivalent as join_res is an int and can have values such
as -2 and -3.

Note for the next time, please only make one type of changes in a single
clean-up commit.

Fixes: 74e1e498e84e ("staging: rtl8188eu: fix comments with lines over 80 ...")
Cc: Juliana Rodrigues <juliana.orod@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/staging/rtl8188eu/core/rtw_ap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 32a483769975..fa611455109a 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -754,7 +754,7 @@ static void start_bss_network(struct adapter *padapter, u8 *pbuf)
 	}
 
 	/* setting only at  first time */
-	if (!(pmlmepriv->cur_network.join_res)) {
+	if (pmlmepriv->cur_network.join_res != true) {
 		/* WEP Key will be set before this function, do not
 		 * clear CAM.
 		 */
-- 
2.14.2

^ permalink raw reply related

* [PATCH 2/3] staging: rtl8188eu: Fix bug introduced by convert timers to use timer_setup()
From: Hans de Goede @ 2017-11-02  9:30 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Hans de Goede, Larry Finger, linux-wireless, devel, Kees Cook
In-Reply-To: <20171102093013.10745-1-hdegoede@redhat.com>

Commit b7749656e946 ("staging: rtl8188eu: Convert timers to use
timer_setup()") introduces a copy and paste error which causes the
rtl8188eu driver to no longer function. This commit fixes this.

Fixes: b7749656e946 ("staging: rtl8188eu: Convert timers to use timer_setup()")
Cc: Kees Cook <keescook@chromium.org>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index d717046a6c2f..d73e9bdc80cc 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -4806,7 +4806,7 @@ void linked_status_chk(struct adapter *padapter)
 void survey_timer_hdl(struct timer_list *t)
 {
 	struct adapter *padapter = from_timer(padapter, t,
-					    mlmeextpriv.link_timer);
+					      mlmeextpriv.survey_timer);
 	struct cmd_obj	*ph2c;
 	struct sitesurvey_parm	*psurveyPara;
 	struct cmd_priv					*pcmdpriv = &padapter->cmdpriv;
-- 
2.14.2

^ permalink raw reply related

* [PATCH 3/3] staging: r8188eu: Revert 4 commits breaking ARP
From: Hans de Goede @ 2017-11-02  9:30 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Hans de Goede, Larry Finger, linux-wireless, devel, stable,
	Ivan Safonov
In-Reply-To: <20171102093013.10745-1-hdegoede@redhat.com>

Commit 2ba8444c97b1 ("staging:r8188eu: move IV/ICV trimming into
decrypt() and also place it after rtl88eu_mon_recv_hook()") breaks ARP.

After this commit ssh-ing to a laptop with r8188eu wifi no longer works
if the machine connecting has never communicated with the laptop before.
This is 100% reproducable using "arp -d <ipv4> && ssh <ipv4>" to ssh to
a laptop with r8188eu wifi.

This commit reverts 4 commits in total:

1. Commit 79650ffde38e ("staging:r8188eu: trim IV/ICV fields in
   validate_recv_data_frame()")
This commit depends on 2 of the other commits being reverted.

2. Commit 02b19b4c4920 ("staging:r8188eu: inline unprotect_frame() in
   mon_recv_decrypted_recv()")
The inline code is wrong the un-inlined version contains:
	if (skb->len < hdr_len + iv_len + icv_len)
		return;
	...
Where as the inline-ed code introduced by this commit does:
	if (skb->len < hdr_len + iv_len + icv_len) {
		...
Note the same check, but now to actually continue doing ... instead
of to not do it, so this commit is no good.

3. Commit d86e16da6a5d ("staging:r8188eu: use different mon_recv_decrypted()
   inside rtl88eu_mon_recv_hook() and rtl88eu_mon_xmit_hook().")
This commit introduced a 1:1 copy of a function so that one of the
2 copies can be modified in the 2 commits we're already reverting.

4. Commit 2ba8444c97b1 ("staging:r8188eu: move IV/ICV trimming into
   decrypt() and also place it after rtl88eu_mon_recv_hook()")
This is the commit actually breaking ARP.

Note this commit is a straight-forward squash of the revert of these
4 commits, without any changes.

Cc: stable@vger.kernel.org
Cc: Ivan Safonov <insafonov@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/staging/rtl8188eu/core/rtw_recv.c | 83 +++++++++++++++++++------------
 drivers/staging/rtl8188eu/os_dep/mon.c    | 34 ++-----------
 2 files changed, 55 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 2f0341689e2f..6506a1587df0 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -264,10 +264,12 @@ static int recvframe_chkmic(struct adapter *adapter,
 			}
 
 			/* icv_len included the mic code */
-			datalen = precvframe->pkt->len-prxattrib->hdrlen - 8;
+			datalen = precvframe->pkt->len-prxattrib->hdrlen -
+				  prxattrib->iv_len-prxattrib->icv_len-8;
 			pframe = precvframe->pkt->data;
-			payload = pframe+prxattrib->hdrlen;
+			payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
 
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len));
 			rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0],
 					   (unsigned char)prxattrib->priority); /* care the length of the data */
 
@@ -413,15 +415,9 @@ static struct recv_frame *decryptor(struct adapter *padapter,
 		default:
 			break;
 		}
-		if (res != _FAIL) {
-			memmove(precv_frame->pkt->data + precv_frame->attrib.iv_len, precv_frame->pkt->data, precv_frame->attrib.hdrlen);
-			skb_pull(precv_frame->pkt, precv_frame->attrib.iv_len);
-			skb_trim(precv_frame->pkt, precv_frame->pkt->len - precv_frame->attrib.icv_len);
-		}
 	} else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
-		   (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_)) {
-		psecuritypriv->hw_decrypted = true;
-	}
+		   (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_))
+			psecuritypriv->hw_decrypted = true;
 
 	if (res == _FAIL) {
 		rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
@@ -462,7 +458,7 @@ static struct recv_frame *portctrl(struct adapter *adapter,
 
 	if (auth_alg == 2) {
 		/* get ether_type */
-		ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
+		ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE + pfhdr->attrib.iv_len;
 		memcpy(&be_tmp, ptr, 2);
 		ether_type = ntohs(be_tmp);
 
@@ -1145,8 +1141,6 @@ static int validate_recv_data_frame(struct adapter *adapter,
 	}
 
 	if (pattrib->privacy) {
-		struct sk_buff *skb = precv_frame->pkt;
-
 		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("validate_recv_data_frame:pattrib->privacy=%x\n", pattrib->privacy));
 		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], IS_MCAST(pattrib->ra)));
 
@@ -1155,13 +1149,6 @@ static int validate_recv_data_frame(struct adapter *adapter,
 		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt=%d\n", pattrib->encrypt));
 
 		SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
-
-		if (pattrib->bdecrypted == 1 && pattrib->encrypt > 0) {
-			memmove(skb->data + pattrib->iv_len,
-				skb->data, pattrib->hdrlen);
-			skb_pull(skb, pattrib->iv_len);
-			skb_trim(skb, skb->len - pattrib->icv_len);
-		}
 	} else {
 		pattrib->encrypt = 0;
 		pattrib->iv_len = 0;
@@ -1281,7 +1268,6 @@ static int validate_recv_frame(struct adapter *adapter,
 	 * Hence forward the frame to the monitor anyway to preserve the order
 	 * in which frames were received.
 	 */
-
 	rtl88eu_mon_recv_hook(adapter->pmondev, precv_frame);
 
 exit:
@@ -1303,8 +1289,11 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
 	u8 *ptr = precvframe->pkt->data;
 	struct rx_pkt_attrib *pattrib = &precvframe->attrib;
 
-	psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen);
-	psnap_type = ptr+pattrib->hdrlen + SNAP_SIZE;
+	if (pattrib->encrypt)
+		skb_trim(precvframe->pkt, precvframe->pkt->len - pattrib->icv_len);
+
+	psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len);
+	psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
 	/* convert hdr + possible LLC headers into Ethernet header */
 	if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
 	     (!memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == false) &&
@@ -1317,9 +1306,12 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
 		bsnaphdr = false;
 	}
 
-	rmv_len = pattrib->hdrlen + (bsnaphdr ? SNAP_SIZE : 0);
+	rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);
 	len = precvframe->pkt->len - rmv_len;
 
+	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+		 ("\n===pattrib->hdrlen: %x,  pattrib->iv_len:%x===\n\n", pattrib->hdrlen,  pattrib->iv_len));
+
 	memcpy(&be_tmp, ptr+rmv_len, 2);
 	eth_type = ntohs(be_tmp); /* pattrib->ether_type */
 	pattrib->eth_type = eth_type;
@@ -1344,6 +1336,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
 					   struct __queue *defrag_q)
 {
 	struct list_head *plist, *phead;
+	u8 wlanhdr_offset;
 	u8	curfragnum;
 	struct recv_frame *pfhdr, *pnfhdr;
 	struct recv_frame *prframe, *pnextrframe;
@@ -1392,7 +1385,12 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
 		/* copy the 2nd~n fragment frame's payload to the first fragment */
 		/* get the 2nd~last fragment frame's payload */
 
-		skb_pull(pnextrframe->pkt, pnfhdr->attrib.hdrlen);
+		wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
+
+		skb_pull(pnextrframe->pkt, wlanhdr_offset);
+
+		/* append  to first fragment frame's tail (if privacy frame, pull the ICV) */
+		skb_trim(prframe->pkt, prframe->pkt->len - pfhdr->attrib.icv_len);
 
 		/* memcpy */
 		memcpy(skb_tail_pointer(pfhdr->pkt), pnfhdr->pkt->data,
@@ -1400,7 +1398,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
 
 		skb_put(prframe->pkt, pnfhdr->pkt->len);
 
-		pfhdr->attrib.icv_len = 0;
+		pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
 		plist = plist->next;
 	}
 
@@ -1526,6 +1524,11 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
 	nr_subframes = 0;
 	pattrib = &prframe->attrib;
 
+	skb_pull(prframe->pkt, prframe->attrib.hdrlen);
+
+	if (prframe->attrib.iv_len > 0)
+		skb_pull(prframe->pkt, prframe->attrib.iv_len);
+
 	a_len = prframe->pkt->len;
 
 	pdata = prframe->pkt->data;
@@ -1895,6 +1898,24 @@ static int process_recv_indicatepkts(struct adapter *padapter,
 	return retval;
 }
 
+static int recv_func_prehandle(struct adapter *padapter,
+			       struct recv_frame *rframe)
+{
+	int ret = _SUCCESS;
+	struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+
+	/* check the frame crtl field and decache */
+	ret = validate_recv_frame(padapter, rframe);
+	if (ret != _SUCCESS) {
+		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
+		rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
+		goto exit;
+	}
+
+exit:
+	return ret;
+}
+
 static int recv_func_posthandle(struct adapter *padapter,
 				struct recv_frame *prframe)
 {
@@ -1947,7 +1968,6 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
 	struct rx_pkt_attrib *prxattrib = &rframe->attrib;
 	struct security_priv *psecuritypriv = &padapter->securitypriv;
 	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
-	struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
 
 	/* check if need to handle uc_swdec_pending_queue*/
 	if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
@@ -1959,12 +1979,9 @@ static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
 		}
 	}
 
-	/* check the frame crtl field and decache */
-	ret = validate_recv_frame(padapter, rframe);
-	if (ret != _SUCCESS) {
-		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
-		rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
-	} else {
+	ret = recv_func_prehandle(padapter, rframe);
+
+	if (ret == _SUCCESS) {
 		/* check if need to enqueue into uc_swdec_pending_queue*/
 		if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
 		    !IS_MCAST(prxattrib->ra) && prxattrib->encrypt > 0 &&
diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c
index 37fd52d7364f..225c23fc69dc 100644
--- a/drivers/staging/rtl8188eu/os_dep/mon.c
+++ b/drivers/staging/rtl8188eu/os_dep/mon.c
@@ -66,34 +66,6 @@ static void mon_recv_decrypted(struct net_device *dev, const u8 *data,
 	netif_rx(skb);
 }
 
-static void mon_recv_decrypted_recv(struct net_device *dev, const u8 *data,
-				    int data_len)
-{
-	struct sk_buff *skb;
-	struct ieee80211_hdr *hdr;
-	int hdr_len;
-
-	skb = netdev_alloc_skb(dev, data_len);
-	if (!skb)
-		return;
-	memcpy(skb_put(skb, data_len), data, data_len);
-
-	/*
-	 * Frame data is not encrypted. Strip off protection so
-	 * userspace doesn't think that it is.
-	 */
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-
-	if (ieee80211_has_protected(hdr->frame_control))
-		hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-	skb->protocol = eth_type_trans(skb, dev);
-	netif_rx(skb);
-}
-
 static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
 			       int data_len)
 {
@@ -110,6 +82,7 @@ static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
 void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
 {
 	struct rx_pkt_attrib *attr;
+	int iv_len, icv_len;
 	int data_len;
 	u8 *data;
 
@@ -122,8 +95,11 @@ void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
 	data = frame->pkt->data;
 	data_len = frame->pkt->len;
 
+	/* Broadcast and multicast frames don't have attr->{iv,icv}_len set */
+	SET_ICE_IV_LEN(iv_len, icv_len, attr->encrypt);
+
 	if (attr->bdecrypted)
-		mon_recv_decrypted_recv(dev, data, data_len);
+		mon_recv_decrypted(dev, data, data_len, iv_len, icv_len);
 	else
 		mon_recv_encrypted(dev, data, data_len);
 }
-- 
2.14.2

^ permalink raw reply related

* RE: [EXT] Re: [PATCH 1/3] mwifiex: cleanup rx_pkt_lock usage in 11n_rxreorder.c
From: Ganapathi Bhat @ 2017-11-02 10:30 UTC (permalink / raw)
  To: Brian Norris
  Cc: linux-wireless@vger.kernel.org, Cathy Luo, Xinming Hu,
	Zhiyuan Yang, James Cao, Mangesh Malusare, Douglas Anderson,
	Karthik Doddayennegere Ananthapadmanabha
In-Reply-To: <20171101212853.GA89416@google.com>

Hi Brian,

> On Tue, Oct 31, 2017 at 03:12:45PM +0530, Ganapathi Bhat wrote:
> > From: Karthik Ananthapadmanabha <karthida@marvell.com>
> >
> > Fix the incorrect usage of rx_pkt_lock spinlock. Realsing the spinlock
> > while the element is still in process is unsafe. The lock must be
> > released only after the element processing is complete.
> >
> > Signed-off-by: Karthik Ananthapadmanabha <karthida@marvell.com>
> > Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
> > ---
> >  drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> > b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> > index 1edcdda..0149c4a 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
> > @@ -124,9 +124,10 @@ static int mwifiex_11n_dispatch_pkt(struct
> mwifiex_private *priv, void *payload)
> >                     rx_tmp_ptr = tbl->rx_reorder_ptr[i];
> >                     tbl->rx_reorder_ptr[i] = NULL;
> >             }
> > -           spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
>
> So, what is this lock protecting? Is it for protecting the packet itself, or for
> protecting the ring buffer?

This lock is protecting the ring buffer but with the current change, we are trying also to protect the packet too.

> As I read it, it's just the latter, since once we've
> removed it from the ring buffer (and are about to dispatch it up toward the
> networking layer), it's handled only by a single context (or else, protected via
> some other common lock(s)).
>
> If I'm correct above, then I think the current code here is actually safe, since
> it holds the lock while removing from the ring buffer -- after it's removed
> from the ring, there's no way another thread can find this payload, and so we
> can release the lock.

There are cases where the ring buffer is iterated by cfg80211 thread:
mwifiex_cfg80211_tdls_oper => mwifiex_tdls_oper => mwifiex_tdls_process_disable_link => mwifiex_11n_cleanup_reorder_tbl => mwifiex_del_rx_reorder_entry => mwifiex_11n_dispatch_pkt_until_start_win => {iterates the ring buffer}
So, at worst case we can have two threads (main & cfg80211) running mwifiex_11n_dispatch_pkt_until_start_win(), iterating the ring buffer.

>
> On a related note: I don't actually see the ring buffer *insertion* being
> protected by this rx_pkt_lock, so is it really useful? See
> mwifiex_11n_rx_reorder_pkt(). Perhaps the correct lock is actually
> rx_reorder_tbl_lock()? Except that serves multiple purposes it seems...

Right, ring buffer insertion is not protected.  I think we should be using both rx_reorder_tbl_lock(which is already present) and rx_pkt_lock(we need to add) during insertion (mwifiex_11n_rx_reorder_pkt()).

Also, we should be using rx_pkt_lock instead of rx_reorder_tbl_lock in mwifiex_11n_find_last_seq_num().
>
> Another thought: from what I can tell, all of these operations are
> *only* performed on the main thread, so there's actually no concurrency
> involved at all. So we also could probably drop this lock entirely...

Let us know your inputs on above observations.
>
> I guess the real point is: can you explain better what you intend this lock to
> do? Then we can review whether you're accomplishing your intention, or
> whether we should improve the usage of this lock in some other way, or
> perhaps even kill it entirely.
>
> Thanks,
> Brian
>
> >             if (rx_tmp_ptr)
> >                     mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
> > +
> > +           spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
> >     }
> >
> >     spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -167,8 +168,8 @@
> > static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void
> *payload)
> >             }
> >             rx_tmp_ptr = tbl->rx_reorder_ptr[i];
> >             tbl->rx_reorder_ptr[i] = NULL;
> > -           spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
> >             mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
> > +           spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
> >     }
> >
> >     spin_lock_irqsave(&priv->rx_pkt_lock, flags);
> > --
> > 1.9.1
> >

Regards,
Ganapathi

^ permalink raw reply

* Re: [PATCH V2 9/9] qtnfmac: pass all CONNECT cmd params to wireless card for processing
From: Sergey Matyukevich @ 2017-11-02 10:31 UTC (permalink / raw)
  To: igor.mitsyanko.os; +Cc: linux-wireless, vulyanov, johannes
In-Reply-To: <20171031010455.27772-10-igor.mitsyanko.os@quantenna.com>

> From: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
> 
> Specifically, following parameters are needed for wireless device
> configuration but were not available to it before:
> - HT/VHT capabilities and capabilities masks.
> - full channel info (not just IEEE number)
> - BSSID hint
> - previous BSSID for reassoc request
> 
> Move Management Frame Protection setting from common encr info
> structure into STA-specific .connect command parameters.
> 
> Make sure that all new qlink structure definitions are alignment-safe.
> 
> Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>

Reviewed-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>

for the whole patch set...

Regards,
Sergey

^ permalink raw reply

* [PATCH] ath10k: move pci suspend/resume functions
From: Arnd Bergmann @ 2017-11-02 11:08 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Arnd Bergmann, Ryan Hsu, Govind Singh, Srinivas Kandagatla,
	Ashok Raj Nagarajan, Ben Greear, Brian Norris, Colin Ian King,
	ath10k, linux-wireless, netdev, linux-kernel

The combination of two patches has led to a build failure:

drivers/net/wireless/ath/ath10k/pci.c: In function 'ath10k_pci_pm_suspend':
drivers/net/wireless/ath/ath10k/pci.c:3416:8: error: implicit declaration of function 'ath10k_pci_suspend'; did you mean 'ath10k_pci_pm_suspend'? [-Werror=implicit-function-declaration]
drivers/net/wireless/ath/ath10k/pci.c: In function 'ath10k_pci_pm_resume':
drivers/net/wireless/ath/ath10k/pci.c:3428:8: error: implicit declaration of function 'ath10k_pci_resume'; did you mean 'ath10k_pci_pm_resume'? [-Werror=implicit-function-declaration]

This moves the functions outside of the now incorrect #ifdef.

Fixes: 96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but disabled")
Fixes: 6af1de2e4ec4 ("ath10k: mark PM functions as __maybe_unused")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/wireless/ath/ath10k/pci.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index b18a9b690df4..6513edbd86e6 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -2585,6 +2585,13 @@ static int ath10k_pci_hif_suspend(struct ath10k *ar)
 	return 0;
 }
 
+static int ath10k_pci_hif_resume(struct ath10k *ar)
+{
+	/* Nothing to do; the important stuff is in the driver resume. */
+	return 0;
+}
+#endif
+
 static int ath10k_pci_suspend(struct ath10k *ar)
 {
 	/* The grace timer can still be counting down and ar->ps_awake be true.
@@ -2597,12 +2604,6 @@ static int ath10k_pci_suspend(struct ath10k *ar)
 	return 0;
 }
 
-static int ath10k_pci_hif_resume(struct ath10k *ar)
-{
-	/* Nothing to do; the important stuff is in the driver resume. */
-	return 0;
-}
-
 static int ath10k_pci_resume(struct ath10k *ar)
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -2627,7 +2628,6 @@ static int ath10k_pci_resume(struct ath10k *ar)
 
 	return ret;
 }
-#endif
 
 static bool ath10k_pci_validate_cal(void *data, size_t size)
 {
-- 
2.9.0

^ permalink raw reply related

* [PATCH] IW: Zero or Uninitialized value of keylen passing
From: Amit Khatri @ 2017-11-02 11:28 UTC (permalink / raw)
  To: johannes@sipsolutions.net, linux-wireless@vger.kernel.org
  Cc: Nitin Jhanwar, AMIT KUMAR JAISWAL
In-Reply-To: <CGME20171102112839epcms5p42b2f4fa5e261fb5ec26237a17fe08655@epcms5p4>

>From b755c8ee282abbd0008e9e7241c457662c90f2c3 Mon Sep 17 00:00:00 2001
From: Amit Khatri <amit.khatri@samsung.com>
Date: Thu, 2 Nov 2017 15:55:16 +0530
Subject: [PATCH] IW: Zero or Uninitialized value of keylen passing

In case of hexadeciaml keydata, keylen is not gettig updated
and passing in NLA_PUT(msg, NL80211_KEY_DATA, keylen, keydata)
as zero (becasue of local variable).

This patch initilalize keylen variable in case of hexkey data.

Signed-off-by: Amit Khatri <amit.khatri@samsung.com>
---
 util.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/util.c b/util.c
index 25d909a..1ec0791 100644
--- a/util.c
+++ b/util.c
@@ -427,12 +427,14 @@ int parse_keys(struct nl_msg *msg, char **argv, int argc)
 		switch (strlen(keydata)) {
 		case 10:
 			keydata = hex2bin(keydata, keybuf);
+			keylen = 5;
 		case 5:
 			NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC01);
 			keylen = 5;
 			break;
 		case 26:
 			keydata = hex2bin(keydata, keybuf);
+			keylen = 13;
 		case 13:
 			NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC05);
 			keylen = 13;
-- 
2.7.4

^ permalink raw reply related

* [PATCH] rsi: sdio: fix building without CONFIG_PM
From: Arnd Bergmann @ 2017-11-02 14:28 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Arnd Bergmann, Prameela Rani Garnepudi, Amitkumar Karwar,
	Karun Eagalapati, linux-wireless, netdev, linux-kernel

The addition of the WoWLAN support has caused a number of new
build errors when CONFIG_PM is disabled, including:

drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_wow_map_triggers':
drivers/net/wireless/rsi/rsi_91x_mac80211.c:1773:19: error: 'RSI_WOW_ANY' undeclared (first use in this function); did you mean 'RSI_WEP_KEY'?
drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_mac80211_attach':
drivers/net/wireless/rsi/rsi_91x_mac80211.c:1980:7: error: 'struct wiphy' has no member named 'wowlan'

This adds more #ifdef CONFIG_PM guards around the code that otherwise
fails to build and that we know is not used without CONFIG_PM.

Fixes: f3ac4e7394a1 ("rsi: sdio: add WOWLAN support for S3 suspend state")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/net/wireless/rsi/rsi_91x_mac80211.c | 4 +++-
 drivers/net/wireless/rsi/rsi_91x_mgmt.c     | 2 ++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 36c63e953f84..ba6405c7d92b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -1752,6 +1752,7 @@ static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw)
 	return 0;
 }
 
+#ifdef CONFIG_PM
 static const struct wiphy_wowlan_support rsi_wowlan_support = {
 	.flags = WIPHY_WOWLAN_ANY |
 		 WIPHY_WOWLAN_MAGIC_PKT |
@@ -1824,7 +1825,6 @@ int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan)
 }
 EXPORT_SYMBOL(rsi_config_wowlan);
 
-#ifdef CONFIG_PM
 static int rsi_mac80211_suspend(struct ieee80211_hw *hw,
 				struct cfg80211_wowlan *wowlan)
 {
@@ -1977,7 +1977,9 @@ int rsi_mac80211_attach(struct rsi_common *common)
 	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
 	wiphy->reg_notifier = rsi_reg_notify;
 
+#ifdef CONFIG_PM
 	wiphy->wowlan = &rsi_wowlan_support;
+#endif
 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
 
 	/* Wi-Fi direct parameters */
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index d38a09f15742..46c9d5470dfb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1597,6 +1597,7 @@ static int rsi_send_beacon(struct rsi_common *common)
 	return 0;
 }
 
+#ifdef CONFIG_PM
 int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
 			    u16 sleep_status)
 {
@@ -1630,6 +1631,7 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
 
 	return rsi_send_internal_mgmt_frame(common, skb);
 }
+#endif
 
 /**
  * rsi_handle_ta_confirm_type() - This function handles the confirm frames.
-- 
2.9.0

^ permalink raw reply related

* Re: [PATCH] rsi: sdio: fix building without CONFIG_PM
From: Kalle Valo @ 2017-11-02 14:57 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Prameela Rani Garnepudi, Amitkumar Karwar, Karun Eagalapati,
	linux-wireless, netdev, linux-kernel
In-Reply-To: <20171102142827.773188-1-arnd@arndb.de>

Arnd Bergmann <arnd@arndb.de> writes:

> The addition of the WoWLAN support has caused a number of new
> build errors when CONFIG_PM is disabled, including:
>
> drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_wow_map_triggers':
> drivers/net/wireless/rsi/rsi_91x_mac80211.c:1773:19: error: 'RSI_WOW_ANY' undeclared (first use in this function); did you mean 'RSI_WEP_KEY'?
> drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_mac80211_attach':
> drivers/net/wireless/rsi/rsi_91x_mac80211.c:1980:7: error: 'struct wiphy' has no member named 'wowlan'
>
> This adds more #ifdef CONFIG_PM guards around the code that otherwise
> fails to build and that we know is not used without CONFIG_PM.
>
> Fixes: f3ac4e7394a1 ("rsi: sdio: add WOWLAN support for S3 suspend state")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Amit already submitted two patches to fix this problem:

https://patchwork.kernel.org/patch/10036297/

https://patchwork.kernel.org/patch/10036299/

I applied them to my pending branch yesterday, and at least buildbot
seems to be happy, so I'm planning take apply those instead. Please let
me know if that's a problem.

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH] rsi: sdio: fix building without CONFIG_PM
From: Arnd Bergmann @ 2017-11-02 15:10 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Prameela Rani Garnepudi, Amitkumar Karwar, Karun Eagalapati,
	linux-wireless, Networking, Linux Kernel Mailing List
In-Reply-To: <87r2tglod5.fsf@codeaurora.org>

On Thu, Nov 2, 2017 at 3:57 PM, Kalle Valo <kvalo@codeaurora.org> wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
>
>> The addition of the WoWLAN support has caused a number of new
>> build errors when CONFIG_PM is disabled, including:
>>
>> drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_wow_map_triggers':
>> drivers/net/wireless/rsi/rsi_91x_mac80211.c:1773:19: error: 'RSI_WOW_ANY' undeclared (first use in this function); did you mean 'RSI_WEP_KEY'?
>> drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_mac80211_attach':
>> drivers/net/wireless/rsi/rsi_91x_mac80211.c:1980:7: error: 'struct wiphy' has no member named 'wowlan'
>>
>> This adds more #ifdef CONFIG_PM guards around the code that otherwise
>> fails to build and that we know is not used without CONFIG_PM.
>>
>> Fixes: f3ac4e7394a1 ("rsi: sdio: add WOWLAN support for S3 suspend state")
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>
> Amit already submitted two patches to fix this problem:
>
> https://patchwork.kernel.org/patch/10036297/
>
> https://patchwork.kernel.org/patch/10036299/
>
> I applied them to my pending branch yesterday, and at least buildbot
> seems to be happy, so I'm planning take apply those instead. Please let
> me know if that's a problem.

Looks good: the first patch is identical to mine, the second one appears to
be something I missed.

      Arnd

^ permalink raw reply

* Re: [PATCH] ath10k: move pci suspend/resume functions
From: Kalle Valo @ 2017-11-02 15:23 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Ryan Hsu, Govind Singh, Srinivas Kandagatla, Ashok Raj Nagarajan,
	Ben Greear, Brian Norris, Colin Ian King,
	ath10k@lists.infradead.org, linux-wireless@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20171102110903.2886660-1-arnd@arndb.de>

Arnd Bergmann <arnd@arndb.de> writes:

> The combination of two patches has led to a build failure:
>
> drivers/net/wireless/ath/ath10k/pci.c: In function 'ath10k_pci_pm_suspend=
':
> drivers/net/wireless/ath/ath10k/pci.c:3416:8: error: implicit declaration=
 of function 'ath10k_pci_suspend'; did you mean 'ath10k_pci_pm_suspend'? [-=
Werror=3Dimplicit-function-declaration]
> drivers/net/wireless/ath/ath10k/pci.c: In function 'ath10k_pci_pm_resume'=
:
> drivers/net/wireless/ath/ath10k/pci.c:3428:8: error: implicit declaration=
 of function 'ath10k_pci_resume'; did you mean 'ath10k_pci_pm_resume'? [-We=
rror=3Dimplicit-function-declaration]
>
> This moves the functions outside of the now incorrect #ifdef.
>
> Fixes: 96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is support=
ed but disabled")
> Fixes: 6af1de2e4ec4 ("ath10k: mark PM functions as __maybe_unused")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Brian has already fixed this, please check that:

https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=3Da=
th-next&id=3D20665a9076d48e9abd9a2db13d307f58f7ef6647

But apparently I forgot to merge ath-next to wireless-drivers-next, will
do that soon.

--=20
Kalle Valo=

^ permalink raw reply

* Re: [PATCH] rsi: sdio: fix building without CONFIG_PM
From: Kalle Valo @ 2017-11-02 15:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Prameela Rani Garnepudi, Amitkumar Karwar, Karun Eagalapati,
	linux-wireless, Networking, Linux Kernel Mailing List
In-Reply-To: <CAK8P3a0KkpkseMUy6ddYC2EbWKepKgRQG=U99SqVLG2yL8wW7w@mail.gmail.com>

Arnd Bergmann <arnd@arndb.de> writes:

> On Thu, Nov 2, 2017 at 3:57 PM, Kalle Valo <kvalo@codeaurora.org> wrote:
>> Arnd Bergmann <arnd@arndb.de> writes:
>>
>>> The addition of the WoWLAN support has caused a number of new
>>> build errors when CONFIG_PM is disabled, including:
>>>
>>> drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_wow_map_triggers':
>>> drivers/net/wireless/rsi/rsi_91x_mac80211.c:1773:19: error:
>>> 'RSI_WOW_ANY' undeclared (first use in this function); did you mean
>>> 'RSI_WEP_KEY'?
>>> drivers/net/wireless/rsi/rsi_91x_mac80211.c: In function 'rsi_mac80211_attach':
>>> drivers/net/wireless/rsi/rsi_91x_mac80211.c:1980:7: error: 'struct
>>> wiphy' has no member named 'wowlan'
>>>
>>> This adds more #ifdef CONFIG_PM guards around the code that otherwise
>>> fails to build and that we know is not used without CONFIG_PM.
>>>
>>> Fixes: f3ac4e7394a1 ("rsi: sdio: add WOWLAN support for S3 suspend state")
>>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>>
>> Amit already submitted two patches to fix this problem:
>>
>> https://patchwork.kernel.org/patch/10036297/
>>
>> https://patchwork.kernel.org/patch/10036299/
>>
>> I applied them to my pending branch yesterday, and at least buildbot
>> seems to be happy, so I'm planning take apply those instead. Please let
>> me know if that's a problem.
>
> Looks good: the first patch is identical to mine, the second one appears to
> be something I missed.

Good, thanks for checking.

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH] ath10k: move pci suspend/resume functions
From: Arnd Bergmann @ 2017-11-02 15:40 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Ryan Hsu, Govind Singh, Srinivas Kandagatla, Ashok Raj Nagarajan,
	Ben Greear, Brian Norris, Colin Ian King,
	ath10k@lists.infradead.org, linux-wireless@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <87mv44ln5v.fsf@qca.qualcomm.com>

On Thu, Nov 2, 2017 at 4:23 PM, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
>
>> The combination of two patches has led to a build failure:
>>
>> drivers/net/wireless/ath/ath10k/pci.c: In function 'ath10k_pci_pm_suspend':
>> drivers/net/wireless/ath/ath10k/pci.c:3416:8: error: implicit declaration of function 'ath10k_pci_suspend'; did you mean 'ath10k_pci_pm_suspend'? [-Werror=implicit-function-declaration]
>> drivers/net/wireless/ath/ath10k/pci.c: In function 'ath10k_pci_pm_resume':
>> drivers/net/wireless/ath/ath10k/pci.c:3428:8: error: implicit declaration of function 'ath10k_pci_resume'; did you mean 'ath10k_pci_pm_resume'? [-Werror=implicit-function-declaration]
>>
>> This moves the functions outside of the now incorrect #ifdef.
>>
>> Fixes: 96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but disabled")
>> Fixes: 6af1de2e4ec4 ("ath10k: mark PM functions as __maybe_unused")
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>
> Brian has already fixed this, please check that:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=ath-next&id=20665a9076d48e9abd9a2db13d307f58f7ef6647
>
> But apparently I forgot to merge ath-next to wireless-drivers-next, will
> do that soon.

Yes, Brian's version is better. I considered the same, but wasn't sure
it was safe.

      Arnd

^ permalink raw reply

* Re: [PATCH] ath10k: move pci suspend/resume functions
From: Brian Norris @ 2017-11-02 17:10 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Kalle Valo, Ryan Hsu, Govind Singh, Srinivas Kandagatla,
	Ashok Raj Nagarajan, Ben Greear, Colin Ian King,
	ath10k@lists.infradead.org, linux-wireless@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CAK8P3a2xkh19gocctXf4gv1Km_SaYJPbSC5QkkZ0WMQQAXp83Q@mail.gmail.com>

On Thu, Nov 02, 2017 at 04:40:57PM +0100, Arnd Bergmann wrote:
> On Thu, Nov 2, 2017 at 4:23 PM, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> > Brian has already fixed this, please check that:
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=ath-next&id=20665a9076d48e9abd9a2db13d307f58f7ef6647
> >
> > But apparently I forgot to merge ath-next to wireless-drivers-next, will
> > do that soon.
> 
> Yes, Brian's version is better. I considered the same, but wasn't sure
> it was safe.

Yes, it's safe. The code is still basically dead, since the mac80211 ops
get dropped with !CONFIG_PM (so no one calls the
*_hif_{suspend,resume}() functions), but at least we have fewer
#ifdef's.

Brian

^ permalink raw reply

* Re: [1/2] rsi: move rsi_sdio_reinit_device() out of CONFIG_PM
From: Kalle Valo @ 2017-11-02 17:38 UTC (permalink / raw)
  To: Amitkumar Karwar
  Cc: linux-wireless, Amitkumar Karwar, Prameela Rani Garnepudi
In-Reply-To: <1509538365-31532-1-git-send-email-amitkarwar@gmail.com>

Amitkumar Karwar <amitkarwar@gmail.com> wrote:

> From: Amitkumar Karwar <amit.karwar@redpinesignals.com>
> 
> This function is generic. It doesn't contain wowlan specific code.
> It should not be under CONFIG_PM. This patch resolves compilation
> errors observed when CONFIG_PM flag is disabled.
> 
> Reported-by: kbuild test robot <fengguang.wu@intel.com>
> Fixes: ef71ed0608c ("rsi: sdio: Add WOWLAN support for S5 shutdown state")
> Fixes: a24e35fcee0 ("rsi: sdio: Add WOWLAN support for S4 hibernate state")
> Fixes: e1ced6422a3 ("rsi: sdio: add WOWLAN support for S3 suspend state")
> Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>

2 patches applied to wireless-drivers-next.git, thanks.

39f1332c526c rsi: move rsi_sdio_reinit_device() out of CONFIG_PM
e6b3b2ed3d27 rsi: fix kbuild reported build errors with CONFIG_PM off

-- 
https://patchwork.kernel.org/patch/10036297/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply

* RE: [PATCH] mac80211: Update last_ack status for all except probing frames
From: Rajkumar Manoharan @ 2017-11-02 18:06 UTC (permalink / raw)
  To: Igor Mitsyanko, johannes@sipsolutions.net
  Cc: linux-wireless@vger.kernel.org, rmanohar@codeaurora.org
In-Reply-To: <46362ff1-acfb-701c-5f71-7d117d223e1a@quantenna.com>

PiBUbyBjbGFyaWZ5OiB3b3VsZG4ndCBpdCBicmVhayBob3N0YXBkJ3MgImluYWN0aXZpdHkgdGlt
ZW90IGtpY2stb3V0Ig0KPiBsb2dpYyBpbiBob3N0YXBkPyBBcyBob3N0YXBkIGdlbmVyYXRlcyBO
VUxMIGZyYW1lcyB0byBpZGxlIHN0YXRpb25zIHRvIHJlc2V0DQo+IHRoZWlyIGluYWN0aXZpdHkg
dGltZSwgb3RoZXJ3aXNlIGl0IHdpbGwgZGlzYXNzb2NpYXRlIGEgc3RhdGlvbiwgYWZ0ZXIgYW4N
Cj4gYXBfbWF4X2luYWN0aXZpdHkgcGVyaW9kLg0KDQpJZ29yLA0KDQpJIHZhbGlkYXRlZCBob3N0
cGFkIGluYWN0aXZpdHkgbW9uaXRvcmluZyB3aXRoIHRoaXMgY2hhbmdlIGFuZCBIb3N0YXBkIGlz
IHNlbmRpbmcNCk51bGxkYXRhIHBlcmlvZGljYWxseSBmb3IgaW5hY3RpdmUgc3RhdGlvbnMuIEhv
c3RhcGQgcmVzZXRzIHRpbWVyIGJhc2VkIG9uIHR4IGFjaw0Kc3RhdHVzIG9mIG51bGxkYXRhLiBT
byByZXRhaW5pbmcgYWN0dWFsIHN0YXRpb24gaW5hY3RpdmUgcGVyaW9kIHdpbGwgbm90IGJyZWFr
DQpob3N0YXBkIG1vbml0b3JpbmcuDQoNClBsZWFzZSByZXBvcnQgaWYgeW91IHNlZSBhbnkgaXNz
dWUgd2l0aCB0aGlzIGNoYW5nZS4gVGhhbmtzIGZvciB5b3VyIGZlZWRiYWNrLg0KDQotUmFqa3Vt
YXINCg0K

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox