* [PATCH 5/7] net: wireless: wcn36xx: swallow two wcn3620 IND messages
From: Andy Green @ 2015-01-18 5:11 UTC (permalink / raw)
To: Kalle Valo, Eugene Krasnikov; +Cc: wcn36xx, linux-wireless, netdev
In-Reply-To: <20150118050741.31866.36490.stgit@114-36-241-182.dynamic.hinet.net>
WCN3620 can asynchronously send two new kinds of indication message,
since we can't handle them just accept them quietly.
Signed-off-by: Andy Green <andy.green@linaro.org>
---
drivers/net/wireless/ath/wcn36xx/smd.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 6398693..819741c 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2061,6 +2061,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
complete(&wcn->hal_rsp_compl);
break;
+ case WCN36XX_HAL_COEX_IND:
+ case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
@@ -2107,6 +2109,10 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
switch (msg_header->msg_type) {
+ case WCN36XX_HAL_COEX_IND:
+ break;
+ case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
+ break;
case WCN36XX_HAL_OTA_TX_COMPL_IND:
wcn36xx_smd_tx_compl_ind(wcn,
hal_ind_msg->msg,
^ permalink raw reply related
* [PATCH 6/7] net: wireless: wcn36xx: remove powersaving for wcn3620
From: Andy Green @ 2015-01-18 5:11 UTC (permalink / raw)
To: Kalle Valo, Eugene Krasnikov; +Cc: wcn36xx, linux-wireless, netdev
In-Reply-To: <20150118050741.31866.36490.stgit@114-36-241-182.dynamic.hinet.net>
WCN3620 powersaving mode is not stable. Disable it if we're
on a wcn3620 chip type.
Signed-off-by: Andy Green <andy.green@linaro.org>
---
drivers/net/wireless/ath/wcn36xx/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index c4178c7..569d45b 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -924,6 +924,10 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_TIMING_BEACON_ONLY;
+ /* 3620 powersaving currently unstable */
+ if (wcn->chip_version == WCN36XX_CHIP_3620)
+ wcn->hw->flags &= ~IEEE80211_HW_SUPPORTS_PS;
+
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_ADHOC) |
^ permalink raw reply related
* [PATCH 7/7] net: wireless: wcn36xx: handle new trigger_ba format
From: Andy Green @ 2015-01-18 5:11 UTC (permalink / raw)
To: Kalle Valo, Eugene Krasnikov; +Cc: wcn36xx, linux-wireless, netdev
In-Reply-To: <20150118050741.31866.36490.stgit@114-36-241-182.dynamic.hinet.net>
wcn3620 has a new message structure for the reply to trigger_ba
We don't know what to do with the candidate list he sends back,
but we can at least accept and ignore it nicely instead of dying.
Signed-off-by: Andy Green <andy.green@linaro.org>
---
drivers/net/wireless/ath/wcn36xx/smd.c | 28 ++++++++++++++++++++++++++--
drivers/net/wireless/ath/wcn36xx/smd.h | 9 +++++++++
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 819741c..dc24e1b 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -243,8 +243,31 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
rsp = (struct wcn36xx_fw_msg_status_rsp *)
(buf + sizeof(struct wcn36xx_hal_msg_header));
- if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
+ if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
+ pr_err("%s: bad status, len = %d\n", __func__, len);
+ return rsp->status;
+ }
+
+ return 0;
+}
+
+static int wcn36xx_smd_rsp_status_check_bav2(struct wcn36xx *wcn, void *buf,
+ size_t len)
+{
+ struct wcn36xx_fw_msg_status_rspv2 *rsp;
+
+ if (wcn->chip_version != WCN36XX_CHIP_3620)
+ return wcn36xx_smd_rsp_status_check(buf, len);
+
+ if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp))
+ return -EIO;
+
+ rsp = buf + sizeof(struct wcn36xx_hal_msg_header);
+
+ if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
+ pr_err("%s: bad status, len = %d\n", __func__, len);
return rsp->status;
+ }
return 0;
}
@@ -1884,7 +1907,8 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
wcn36xx_err("Sending hal_trigger_ba failed\n");
goto out;
}
- ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
+ ret = wcn36xx_smd_rsp_status_check_bav2(wcn, wcn->hal_buf,
+ wcn->hal_rsp_len);
if (ret) {
wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
goto out;
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 008d034..432d3b8 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -44,6 +44,15 @@ struct wcn36xx_fw_msg_status_rsp {
u32 status;
} __packed;
+/* wcn3620 returns this for tigger_ba */
+
+struct wcn36xx_fw_msg_status_rspv2 {
+ u8 bss_id[6];
+ u32 status __packed;
+ u16 count_following_candidates __packed;
+ /* candidate list follows */
+};
+
struct wcn36xx_hal_ind_msg {
struct list_head list;
u8 *msg;
^ permalink raw reply related
* [PATCH 0/2] net: wireless: wcn36xx: OOT platform reference patch for msm8916 / wcn36xx
From: Andy Green @ 2015-01-18 5:16 UTC (permalink / raw)
To: Kalle Valo, Eugene Krasnikov; +Cc: wcn36xx, linux-wireless, netdev
These patches are not intended for upstreaming. They are
included as a reference to show how to hook up wcn36xx to
msm platforms using the OOT PIL support needed.
The following series adds Eugene's OOT msm platform shim to
wcn36xx and modifies it to provide wcn36xx platform data
about chip type from Device Tree.
It's useful as an example for how to implement on msm
platforms that do not have all the necessary support
upstreamed yet.
This was tested on msm8916-QRD "phone" dev platform.
---
Andy Green (1):
net wireless wcn36xx adapt wcnss platform to select module by DT
Eugene Krasnikov (1):
net wireless wcn36xx add wcnss platform code
drivers/net/wireless/ath/wcn36xx/Makefile | 2
drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c | 360 ++++++++++++++++++++++++
2 files changed, 361 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
--
^ permalink raw reply
* [PATCH 1/2] net wireless wcn36xx add wcnss platform code
From: Andy Green @ 2015-01-18 5:16 UTC (permalink / raw)
To: Kalle Valo, Eugene Krasnikov; +Cc: wcn36xx, linux-wireless, netdev
In-Reply-To: <20150118051222.32019.32719.stgit@114-36-241-182.dynamic.hinet.net>
From: Eugene Krasnikov <k.eugene.e@gmail.com>
AG modified to remove regulator handling not needed on msm8916-qrd
Signed-off-by: Eugene Krasnikov <k.eugene.e@gmail.com>
Signed-off-by: Andy Green <andy.green@linaro.org>
---
drivers/net/wireless/ath/wcn36xx/Makefile | 2
drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c | 357 ++++++++++++++++++++++++
2 files changed, 358 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile
index 50c43b4..e889f2c 100644
--- a/drivers/net/wireless/ath/wcn36xx/Makefile
+++ b/drivers/net/wireless/ath/wcn36xx/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_WCN36XX) := wcn36xx.o
+obj-$(CONFIG_WCN36XX) := wcn36xx.o wcn36xx-msm.o
wcn36xx-y += main.o \
dxe.o \
txrx.o \
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c b/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
new file mode 100644
index 0000000..f6f6c83
--- /dev/null
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/completion.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <soc/qcom/smd.h>
+#include <soc/qcom/smsm.h>
+#include "wcn36xx.h"
+
+#include <soc/qcom/subsystem_restart.h>
+#include <soc/qcom/subsystem_notif.h>
+
+#define MAC_ADDR_0 "wlan/macaddr0"
+
+static void *pil;
+
+struct wcn36xx_msm {
+ struct wcn36xx_platform_ctrl_ops ctrl_ops;
+ struct platform_device *core;
+ void *drv_priv;
+ void (*rsp_cb)(void *drv_priv, void *buf, size_t len);
+ /* SMD related */
+ struct workqueue_struct *wq;
+ struct work_struct smd_work;
+ struct completion smd_compl;
+ smd_channel_t *smd_ch;
+ struct pinctrl *pinctrl;
+} wmsm;
+
+static int wcn36xx_msm_smsm_change_state(u32 clear_mask, u32 set_mask)
+{
+ return smsm_change_state(SMSM_APPS_STATE, clear_mask, set_mask);
+}
+
+static int wcn36xx_msm_get_hw_mac(u8 *addr)
+{
+ const struct firmware *addr_file = NULL;
+ int status;
+ u8 tmp[18];
+ static const u8 qcom_oui[3] = {0x00, 0x0A, 0xF5};
+ static const char *files = {MAC_ADDR_0};
+
+ status = request_firmware(&addr_file, files, &wmsm.core->dev);
+
+ if (status < 0) {
+ /* Assign a random mac with Qualcomm oui */
+ dev_err(&wmsm.core->dev, "Failed (%d) to read macaddress file %s, using a random address instead", status,
+ files);
+ memcpy(addr, qcom_oui, 3);
+ get_random_bytes(addr + 3, 3);
+ } else {
+ memset(tmp, 0, sizeof(tmp));
+ memcpy(tmp, addr_file->data, sizeof(tmp) - 1);
+ sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &addr[0],
+ &addr[1],
+ &addr[2],
+ &addr[3],
+ &addr[4],
+ &addr[5]);
+
+ release_firmware(addr_file);
+ }
+
+ return 0;
+}
+
+static int wcn36xx_msm_smd_send_and_wait(char *buf, size_t len)
+{
+ int avail;
+ int ret = 0;
+
+ avail = smd_write_avail(wmsm.smd_ch);
+
+ if (avail >= len) {
+ avail = smd_write(wmsm.smd_ch, buf, len);
+ if (avail != len) {
+ dev_err(&wmsm.core->dev,
+ "Cannot write to SMD channel\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+ } else {
+ dev_err(&wmsm.core->dev,
+ "SMD channel can accept only %d bytes\n", avail);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void wcn36xx_msm_smd_notify(void *data, unsigned event)
+{
+ struct wcn36xx_msm *wmsm_priv = (struct wcn36xx_msm *)data;
+
+ switch (event) {
+ case SMD_EVENT_OPEN:
+ complete(&wmsm_priv->smd_compl);
+ break;
+ case SMD_EVENT_DATA:
+ queue_work(wmsm_priv->wq, &wmsm_priv->smd_work);
+ break;
+ case SMD_EVENT_CLOSE:
+ break;
+ case SMD_EVENT_STATUS:
+ break;
+ case SMD_EVENT_REOPEN_READY:
+ break;
+ default:
+ dev_err(&wmsm_priv->core->dev,
+ "%s: SMD_EVENT (%d) not supported\n", __func__, event);
+ break;
+ }
+}
+
+static void wcn36xx_msm_smd_work(struct work_struct *work)
+{
+ int avail;
+ int msg_len;
+ void *msg;
+ int ret;
+ struct wcn36xx_msm *wmsm_priv =
+ container_of(work, struct wcn36xx_msm, smd_work);
+
+ while (1) {
+ msg_len = smd_cur_packet_size(wmsm_priv->smd_ch);
+ if (0 == msg_len) {
+ return;
+ }
+ avail = smd_read_avail(wmsm_priv->smd_ch);
+ if (avail < msg_len) {
+ return;
+ }
+ msg = kmalloc(msg_len, GFP_KERNEL);
+ if (NULL == msg) {
+ return;
+ }
+
+ ret = smd_read(wmsm_priv->smd_ch, msg, msg_len);
+ if (ret != msg_len) {
+ return;
+ }
+ wmsm_priv->rsp_cb(wmsm_priv->drv_priv, msg, msg_len);
+ kfree(msg);
+ }
+}
+
+int wcn36xx_msm_smd_open(void *drv_priv, void *rsp_cb)
+{
+ int ret, left;
+ wmsm.drv_priv = drv_priv;
+ wmsm.rsp_cb = rsp_cb;
+ INIT_WORK(&wmsm.smd_work, wcn36xx_msm_smd_work);
+ init_completion(&wmsm.smd_compl);
+
+ wmsm.wq = create_workqueue("wcn36xx_msm_smd_wq");
+ if (!wmsm.wq) {
+ dev_err(&wmsm.core->dev, "failed to allocate wq");
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ ret = smd_named_open_on_edge("WLAN_CTRL", SMD_APPS_WCNSS,
+ &wmsm.smd_ch, &wmsm, wcn36xx_msm_smd_notify);
+ if (ret) {
+ dev_err(&wmsm.core->dev,
+ "smd_named_open_on_edge failed: %d\n", ret);
+ return ret;
+ }
+
+ left = wait_for_completion_interruptible_timeout(&wmsm.smd_compl,
+ msecs_to_jiffies(HAL_MSG_TIMEOUT));
+ if (left <= 0) {
+ dev_err(&wmsm.core->dev,
+ "timeout waiting for smd open: %d\n", ret);
+ return left;
+ }
+
+ /* Not to receive INT until the whole buf from SMD is read */
+ smd_disable_read_intr(wmsm.smd_ch);
+
+ return 0;
+}
+
+void wcn36xx_msm_smd_close(void)
+{
+ smd_close(wmsm.smd_ch);
+ flush_workqueue(wmsm.wq);
+ destroy_workqueue(wmsm.wq);
+}
+
+int wcn36xx_msm_shutdown(const struct subsys_desc *desc, bool force_stop)
+{
+ return 0;
+}
+int wcn36xx_msm_powerup(const struct subsys_desc *desc)
+{
+ return 0;
+}
+
+static int wcn36xx_msm_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *wcnss_memory;
+ struct resource *tx_irq;
+ struct resource *rx_irq;
+ struct resource res[3];
+ struct pinctrl_state *ps;
+
+ wmsm.pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR_OR_NULL(wmsm.pinctrl))
+ return PTR_ERR(wmsm.pinctrl);
+
+ ps = pinctrl_lookup_state(wmsm.pinctrl, "wcnss_default");
+ if (IS_ERR_OR_NULL(ps))
+ return PTR_ERR(ps);
+
+ ret = pinctrl_select_state(wmsm.pinctrl, ps);
+ if (ret)
+ return ret;
+
+ if (IS_ERR_OR_NULL(pil))
+ pil = subsystem_get("wcnss");
+ if (IS_ERR_OR_NULL(pil))
+ return PTR_ERR(pil);
+
+ wmsm.core = platform_device_alloc("wcn36xx", -1);
+
+ //dev_err(&pdev->dev, "%s starting\n", __func__);
+
+ memset(res, 0x00, sizeof(res));
+ wmsm.ctrl_ops.open = wcn36xx_msm_smd_open;
+ wmsm.ctrl_ops.close = wcn36xx_msm_smd_close;
+ wmsm.ctrl_ops.tx = wcn36xx_msm_smd_send_and_wait;
+ wmsm.ctrl_ops.get_hw_mac = wcn36xx_msm_get_hw_mac;
+ wmsm.ctrl_ops.smsm_change_state = wcn36xx_msm_smsm_change_state;
+ wcnss_memory =
+ platform_get_resource_byname(pdev,
+ IORESOURCE_MEM,
+ "wcnss_mmio");
+ if (wcnss_memory == NULL) {
+ dev_err(&wmsm.core->dev,
+ "Failed to get wcnss wlan memory map.\n");
+ ret = -ENOMEM;
+ return ret;
+ }
+ memcpy(&res[0], wcnss_memory, sizeof(*wcnss_memory));
+
+ tx_irq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ,
+ "wcnss_wlantx_irq");
+ if (tx_irq == NULL) {
+ dev_err(&wmsm.core->dev, "Failed to get wcnss tx_irq");
+ ret = -ENOMEM;
+ return ret;
+ }
+ memcpy(&res[1], tx_irq, sizeof(*tx_irq));
+
+ rx_irq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ,
+ "wcnss_wlanrx_irq");
+ if (rx_irq == NULL) {
+ dev_err(&wmsm.core->dev, "Failed to get wcnss rx_irq");
+ ret = -ENOMEM;
+ return ret;
+ }
+ memcpy(&res[2], rx_irq, sizeof(*rx_irq));
+
+ platform_device_add_resources(wmsm.core, res, ARRAY_SIZE(res));
+
+ ret = platform_device_add_data(wmsm.core, &wmsm.ctrl_ops,
+ sizeof(wmsm.ctrl_ops));
+ if (ret) {
+ dev_err(&wmsm.core->dev, "Can't add platform data\n");
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ platform_device_add(wmsm.core);
+
+ dev_info(&pdev->dev, "%s initialized\n", __func__);
+
+ return 0;
+}
+static int wcn36xx_msm_remove(struct platform_device *pdev)
+{
+ struct pinctrl_state *ps;
+
+ platform_device_del(wmsm.core);
+ platform_device_put(wmsm.core);
+
+ if (wmsm.pinctrl) {
+ ps = pinctrl_lookup_state(wmsm.pinctrl, "wcnss_sleep");
+ if (IS_ERR_OR_NULL(ps))
+ return PTR_ERR(ps);
+
+ pinctrl_select_state(wmsm.pinctrl, ps);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id wcn36xx_msm_match_table[] = {
+ { .compatible = "qcom,wcn36xx" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wcn36xx_msm_match_table);
+
+static struct platform_driver wcn36xx_msm_driver = {
+ .probe = wcn36xx_msm_probe,
+ .remove = wcn36xx_msm_remove,
+ .driver = {
+ .name = "wcn36xx-msm",
+ .owner = THIS_MODULE,
+ .of_match_table = wcn36xx_msm_match_table,
+ },
+};
+
+static int __init wcn36xx_msm_init(void)
+{
+ return platform_driver_register(&wcn36xx_msm_driver);
+}
+module_init(wcn36xx_msm_init);
+
+static void __exit wcn36xx_msm_exit(void)
+{
+ platform_driver_unregister(&wcn36xx_msm_driver);
+ if (pil)
+ subsystem_put(pil);
+
+
+}
+module_exit(wcn36xx_msm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
+MODULE_FIRMWARE(MAC_ADDR_0);
+
^ permalink raw reply related
* [PATCH 2/2] net wireless wcn36xx adapt wcnss platform to select module by DT
From: Andy Green @ 2015-01-18 5:16 UTC (permalink / raw)
To: Kalle Valo, Eugene Krasnikov; +Cc: wcn36xx, linux-wireless, netdev
In-Reply-To: <20150118051222.32019.32719.stgit@114-36-241-182.dynamic.hinet.net>
Simplify the resource handling and use DT to indicate which chip type
we are dealing with
Signed-off-by: Andy Green <andy.green@linaro.org>
---
drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c | 101 ++++++++++++------------
1 file changed, 52 insertions(+), 49 deletions(-)
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c b/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
index f6f6c83..c9250e0 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c
@@ -42,7 +42,10 @@ struct wcn36xx_msm {
struct completion smd_compl;
smd_channel_t *smd_ch;
struct pinctrl *pinctrl;
-} wmsm;
+ enum wcn36xx_chip_type chip_type;
+};
+
+static struct wcn36xx_msm wmsm;
static int wcn36xx_msm_smsm_change_state(u32 clear_mask, u32 set_mask)
{
@@ -217,14 +220,47 @@ int wcn36xx_msm_powerup(const struct subsys_desc *desc)
return 0;
}
+static const struct of_device_id wcn36xx_msm_match_table[] = {
+ { .compatible = "qcom,wcn3660", .data = (void *)WCN36XX_CHIP_3660 },
+ { .compatible = "qcom,wcn3680", .data = (void *)WCN36XX_CHIP_3680 },
+ { .compatible = "qcom,wcn3620", .data = (void *)WCN36XX_CHIP_3620 },
+ { }
+};
+
+static int wcn36xx_msm_get_chip_type(void)
+{
+ return wmsm.chip_type;
+}
+
+static struct wcn36xx_msm wmsm = {
+ .ctrl_ops = {
+ .open = wcn36xx_msm_smd_open,
+ .close = wcn36xx_msm_smd_close,
+ .tx = wcn36xx_msm_smd_send_and_wait,
+ .get_hw_mac = wcn36xx_msm_get_hw_mac,
+ .smsm_change_state = wcn36xx_msm_smsm_change_state,
+ .get_chip_type = wcn36xx_msm_get_chip_type,
+ },
+};
+
static int wcn36xx_msm_probe(struct platform_device *pdev)
{
int ret;
- struct resource *wcnss_memory;
- struct resource *tx_irq;
- struct resource *rx_irq;
+ const struct of_device_id *of_id;
+ struct resource *r;
struct resource res[3];
struct pinctrl_state *ps;
+ static const char const *rnames[] = {
+ "wcnss_mmio", "wcnss_wlantx_irq", "wcnss_wlanrx_irq" };
+ static const int rtype[] = {
+ IORESOURCE_MEM, IORESOURCE_IRQ, IORESOURCE_IRQ };
+ int n;
+
+ of_id = of_match_node(wcn36xx_msm_match_table, pdev->dev.of_node);
+ if (!of_id)
+ return -EINVAL;
+
+ wmsm.chip_type = (enum wcn36xx_chip_type)of_id->data;
wmsm.pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR_OR_NULL(wmsm.pinctrl))
@@ -240,52 +276,23 @@ static int wcn36xx_msm_probe(struct platform_device *pdev)
if (IS_ERR_OR_NULL(pil))
pil = subsystem_get("wcnss");
- if (IS_ERR_OR_NULL(pil))
- return PTR_ERR(pil);
+ if (IS_ERR_OR_NULL(pil))
+ return PTR_ERR(pil);
wmsm.core = platform_device_alloc("wcn36xx", -1);
- //dev_err(&pdev->dev, "%s starting\n", __func__);
-
- memset(res, 0x00, sizeof(res));
- wmsm.ctrl_ops.open = wcn36xx_msm_smd_open;
- wmsm.ctrl_ops.close = wcn36xx_msm_smd_close;
- wmsm.ctrl_ops.tx = wcn36xx_msm_smd_send_and_wait;
- wmsm.ctrl_ops.get_hw_mac = wcn36xx_msm_get_hw_mac;
- wmsm.ctrl_ops.smsm_change_state = wcn36xx_msm_smsm_change_state;
- wcnss_memory =
- platform_get_resource_byname(pdev,
- IORESOURCE_MEM,
- "wcnss_mmio");
- if (wcnss_memory == NULL) {
- dev_err(&wmsm.core->dev,
- "Failed to get wcnss wlan memory map.\n");
- ret = -ENOMEM;
- return ret;
- }
- memcpy(&res[0], wcnss_memory, sizeof(*wcnss_memory));
-
- tx_irq = platform_get_resource_byname(pdev,
- IORESOURCE_IRQ,
- "wcnss_wlantx_irq");
- if (tx_irq == NULL) {
- dev_err(&wmsm.core->dev, "Failed to get wcnss tx_irq");
- ret = -ENOMEM;
- return ret;
- }
- memcpy(&res[1], tx_irq, sizeof(*tx_irq));
-
- rx_irq = platform_get_resource_byname(pdev,
- IORESOURCE_IRQ,
- "wcnss_wlanrx_irq");
- if (rx_irq == NULL) {
- dev_err(&wmsm.core->dev, "Failed to get wcnss rx_irq");
- ret = -ENOMEM;
- return ret;
+ for (n = 0; n < ARRAY_SIZE(rnames); n++) {
+ r = platform_get_resource_byname(pdev, rtype[n], rnames[n]);
+ if (!r) {
+ dev_err(&wmsm.core->dev,
+ "Missing resource %s'\n", rnames[n]);
+ ret = -ENOMEM;
+ return ret;
+ }
+ res[n] = *r;
}
- memcpy(&res[2], rx_irq, sizeof(*rx_irq));
- platform_device_add_resources(wmsm.core, res, ARRAY_SIZE(res));
+ platform_device_add_resources(wmsm.core, res, n);
ret = platform_device_add_data(wmsm.core, &wmsm.ctrl_ops,
sizeof(wmsm.ctrl_ops));
@@ -319,10 +326,6 @@ static int wcn36xx_msm_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id wcn36xx_msm_match_table[] = {
- { .compatible = "qcom,wcn36xx" },
- { }
-};
MODULE_DEVICE_TABLE(of, wcn36xx_msm_match_table);
static struct platform_driver wcn36xx_msm_driver = {
^ permalink raw reply related
* Re: [patch net-next 1/2] switchdev: introduce switchdev notifier
From: David Miller @ 2015-01-18 5:24 UTC (permalink / raw)
To: jiri; +Cc: netdev, jhs, sfeldma, stephen, linus.luessing, tgraf
In-Reply-To: <1421362177-10719-1-git-send-email-jiri@resnulli.us>
From: Jiri Pirko <jiri@resnulli.us>
Date: Thu, 15 Jan 2015 23:49:36 +0100
> This patch introduces new notifier for purposes of exposing events which happen
> on switch driver side. The consumers of the event messages are mainly involved
> masters, namely bridge and ovs.
>
> Suggested-by: Thomas Graf <tgraf@suug.ch>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Applied.
^ permalink raw reply
* Re: [patch net-next 2/2] net: replace br_fdb_external_learn_* calls with switchdev notifier events
From: David Miller @ 2015-01-18 5:24 UTC (permalink / raw)
To: jiri; +Cc: netdev, jhs, sfeldma, stephen, linus.luessing, tgraf
In-Reply-To: <1421362177-10719-2-git-send-email-jiri@resnulli.us>
From: Jiri Pirko <jiri@resnulli.us>
Date: Thu, 15 Jan 2015 23:49:37 +0100
> This patch benefits from newly introduced switchdev notifier and uses it
> to propagate fdb learn events from rocker driver to bridge. That avoids
> direct function calls and possible use by other listeners (ovs).
>
> Suggested-by: Thomas Graf <tgraf@suug.ch>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Applied.
^ permalink raw reply
* Re: pull request: bluetooth-next 2015-01-16
From: David Miller @ 2015-01-18 5:25 UTC (permalink / raw)
To: johan.hedberg; +Cc: netdev, linux-bluetooth
In-Reply-To: <20150116113301.GA3818@t440s.lan>
From: Johan Hedberg <johan.hedberg@gmail.com>
Date: Fri, 16 Jan 2015 13:33:01 +0200
> Here are some more bluetooth & ieee802154 patches intended for 3.20:
>
> - Refactoring & cleanups of ieee802154 & 6lowpan code
> - Various fixes to the btmrvl driver
> - Fixes for Bluetooth Low Energy Privacy feature handling
> - Added build-time sanity checks for sockaddr sizes
> - Fixes for Security Manager registration on LE-only controllers
> - Refactoring of broken inquiry mode handling to a generic quirk
>
> Please let me know if there are any issues pulling. Thanks.
Pulled, thanks Johan.
^ permalink raw reply
* Re: [PATCH net-next] tipc: fix socket list regression in new nl api
From: David Miller @ 2015-01-18 5:27 UTC (permalink / raw)
To: richard.alpe; +Cc: netdev, tipc-discussion
In-Reply-To: <1421407840-30726-1-git-send-email-richard.alpe@ericsson.com>
From: <richard.alpe@ericsson.com>
Date: Fri, 16 Jan 2015 12:30:40 +0100
> From: Richard Alpe <richard.alpe@ericsson.com>
>
> Commit 07f6c4bc (tipc: convert tipc reference table to use generic
> rhashtable) introduced a problem with port listing in the new netlink
> API. It broke the resume functionality resulting in a never ending
> loop. This was caused by starting with the first hash table every time
> subsequently never returning an empty skb (terminating).
>
> This patch fixes the resume mechanism by keeping a logical reference
> to the last hash table along with a logical reference to the socket
> (port) that didn't fit in the previous message.
>
> Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
> Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
> Reviewed-by: Ying Xue <ying.xue@windriver.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH 2/2] Drivers: Isdn: sc: Fixed coding style & spelling mistakes.
From: David Miller @ 2015-01-18 5:28 UTC (permalink / raw)
To: akash0x53s; +Cc: isdn, netdev, linux-kernel
In-Reply-To: <1421415762-21596-1-git-send-email-akash0x53s@gmail.com>
From: Akash Shende <akash0x53s@gmail.com>
Date: Fri, 16 Jan 2015 19:12:42 +0530
> Fix some spelling mistakes, coding style and don't assign value to static var.
>
> Signed-off-by: Akash Shende <akash0x53s@gmail.com>
Applied, thanks.
^ permalink raw reply
* Re: [net-next PATCH v3 1/1] atm: remove deprecated use of pci api
From: David Miller @ 2015-01-18 5:28 UTC (permalink / raw)
To: chas; +Cc: David.Laight, lambert.quentin, linux-atm-general, netdev,
linux-kernel
In-Reply-To: <20150116085721.56aa8075@thirdoffive.cmf.nrl.navy.mil>
From: chas williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
Date: Fri, 16 Jan 2015 08:57:21 -0500
> Signed-off-by: Chas Williams - CONTRACTOR <chas@cmf.nrl.navy.mil>
Applied, thanks Chas.
^ permalink raw reply
* Re: [PATCH] netlink: make nlmsg_end() and genlmsg_end() void
From: David Miller @ 2015-01-18 6:04 UTC (permalink / raw)
To: johannes; +Cc: netdev, johannes.berg
In-Reply-To: <1421442540-10244-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Fri, 16 Jan 2015 22:09:00 +0100
...
> Remove this, and make the functions void. This removes a bunch of dead
> code as described above. The patch adds lines because I did
>
> - return nlmsg_end(...);
> + nlmsg_end(...);
> + return 0;
>
> I could have preserved all the function's return values by returning
> skb->len, but instead I've audited all the places calling the affected
> functions and found that none cared. A few places actually compared
> the return value with <= 0 in dump functionality, but that could just
> be changed to < 0 with no change in behaviour, so I opted for the more
> efficient version.
>
> One instance of the error I've made numerous times now is also present
> in net/phonet/pn_netlink.c in the route_dumpit() function - it didn't
> check for <0 or <=0 and thus broke out of the loop every single time.
> I've preserved this since it will (I think) have caused the messages to
> userspace to be formatted differently with just a single message for
> every SKB returned to userspace. It's possible that this isn't needed
> for the tools that actually use this, but I don't even know what they
> are so couldn't test that changing this behaviour would be acceptable.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
I like this, applied, thanks Johannes.
You know, I would even be willing to apply a patch adjusting that phonet
case. So feel free to submit that.
^ permalink raw reply
* Re: [patch-net-next v3 1/2] net: ethernet: cpsw: unroll IRQ request loop
From: David Miller @ 2015-01-18 6:07 UTC (permalink / raw)
To: balbi; +Cc: tony, linux-omap, mugunthanvnm, netdev
In-Reply-To: <1421424672-19323-1-git-send-email-balbi@ti.com>
From: Felipe Balbi <balbi@ti.com>
Date: Fri, 16 Jan 2015 10:11:11 -0600
> This patch is in preparation for a nicer IRQ
> handling scheme where we use different IRQ
> handlers for each IRQ line (as it should be).
>
> Later, we will also drop IRQs offset 0 and 3
> because they are always disabled in this driver.
>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
Applied.
^ permalink raw reply
* Re: [patch-net-next v3 2/2] net: ethernet: cpsw: don't requests IRQs we don't use
From: David Miller @ 2015-01-18 6:07 UTC (permalink / raw)
To: balbi; +Cc: tony, linux-omap, mugunthanvnm, netdev
In-Reply-To: <1421424672-19323-2-git-send-email-balbi@ti.com>
From: Felipe Balbi <balbi@ti.com>
Date: Fri, 16 Jan 2015 10:11:12 -0600
> CPSW never uses RX_THRESHOLD or MISC interrupts. In
> fact, they are always kept masked in their appropriate
> IRQ Enable register.
>
> Instead of allocating an IRQ that never fires, it's best
> to remove that code altogether and let future patches
> implement it if anybody needs those.
>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
Applied.
^ permalink raw reply
* RE: [net-next v2 13/15] i40e: limit WoL and link settings to partition 1
From: Yuval Mintz @ 2015-01-18 6:10 UTC (permalink / raw)
To: Jeff Kirsher, David Miller
Cc: Shannon Nelson, netdev, nhorman@redhat.com, sassmann@redhat.com,
jogreene@redhat.com
In-Reply-To: <1421179093-10932-14-git-send-email-jeffrey.t.kirsher@intel.com>
>From: Shannon Nelson <shannon.nelson@intel.com>
>When in multi-function mode, e.g. Dell's NPAR, only partition 1
>of each MAC is allowed to set WoL, speed, and flow control.
Isn't it problematic? I mean, in bnx2x we address ~same issue -
but due to symmetry we prevent ALL interfaces from changing
the link configuration.
How can user be aware of this 'private' behavior? via system logs?
documentation?
How does it interact with Physical Device Assignment of the first
partition?
Cheers,
Yuval
^ permalink raw reply
* Re: [net-next PATCH v2 04/12] net: flow_table: create a set of common headers and actions
From: Scott Feldman @ 2015-01-18 6:34 UTC (permalink / raw)
To: John Fastabend
Cc: Thomas Graf, simon.horman@netronome.com, Netdev, gerlitz.or,
Jamal Hadi Salim, Andy Gospodarek, David S. Miller
In-Reply-To: <20150113213645.13874.24934.stgit@nitbit.x32>
On Tue, Jan 13, 2015 at 1:36 PM, John Fastabend
<john.fastabend@gmail.com> wrote:
> This adds common headers and actions that drivers can use.
>
> I have not yet moved the header graphs into the common header
> because I'm not entirely convinced its re-usable. The devices
> I have been looking at have different enough header graphs that
> they wouldn't be re-usable. However possibly many 40Gbp NICs
> for example could share a common header graph. When we get
> multiple implementations we can move this into the common file
> if it makes sense.
>
> And table structures seem to be unique enough that there is
> little value in putting each devices table layout into the
> common file so its left for device specific implementation.
>
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> ---
> include/linux/if_flow_common.h | 257 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 257 insertions(+)
> create mode 100644 include/linux/if_flow_common.h
>
> diff --git a/include/linux/if_flow_common.h b/include/linux/if_flow_common.h
> new file mode 100644
> index 0000000..d4dd749
> --- /dev/null
> +++ b/include/linux/if_flow_common.h
> @@ -0,0 +1,257 @@
> +#ifndef _IF_FLOW_COMMON_H_
> +#define _IF_FLOW_COMMON_H_
> +
> +#include <linux/if_flow.h>
> +
> +/* Common header definition this section provides a set of common or
> + * standard headers that device driver writers may use to simplify the
> + * driver creation. We do not want vendor or driver specific headers
> + * here though. Driver authors can keep these contained to their driver
> + *
> + * Driver authors may use unique IDs greater than HEADER_MAX_UID it is
> + * guaranteed to be larger than any unique IDs used here.
> + */
> +#define HEADER_MAX_UID 100
> +
> +enum net_flow_headers {
> + HEADER_UNSPEC,
> + HEADER_ETHERNET,
> + HEADER_VLAN,
> + HEADER_IPV4,
> +};
> +
> +enum net_flow_ethernet_fields_ids {
> + HEADER_ETHERNET_UNSPEC,
> + HEADER_ETHERNET_SRC_MAC,
> + HEADER_ETHERNET_DST_MAC,
> + HEADER_ETHERNET_ETHERTYPE,
> +};
> +
> +struct net_flow_field net_flow_ethernet_fields[] = {
> + { .name = "src_mac", .uid = HEADER_ETHERNET_SRC_MAC, .bitwidth = 48},
> + { .name = "dst_mac", .uid = HEADER_ETHERNET_DST_MAC, .bitwidth = 48},
> + { .name = "ethertype",
> + .uid = HEADER_ETHERNET_ETHERTYPE,
> + .bitwidth = 16},
> +};
All of these code chunks get repeated in each module that includes
if_flow_common.h, regardless if the module needs all of them.
Maybe #define would be better?
> +struct net_flow_field net_flow_ipv4_fields[14] = {
net_flow_ipv4_fields[]. more like this...
-scott
^ permalink raw reply
* Re: [net-next PATCH v2 06/12] net: rocker: add pipeline model for rocker switch
From: Scott Feldman @ 2015-01-18 6:39 UTC (permalink / raw)
To: John Fastabend
Cc: Thomas Graf, simon.horman@netronome.com, Netdev, gerlitz.or,
Jamal Hadi Salim, Andy Gospodarek, David S. Miller
In-Reply-To: <20150113213739.13874.37091.stgit@nitbit.x32>
On Tue, Jan 13, 2015 at 1:37 PM, John Fastabend
<john.fastabend@gmail.com> wrote:
> This adds rocker support for the net_flow_get_* operations. With this
> we can interrogate rocker.
>
> Here we see that for static configurations enabling the get operations
> is simply a matter of defining a pipeline model and returning the
> structures for the core infrastructure to encapsulate into netlink
> messages.
>
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> ---
> drivers/net/ethernet/rocker/rocker.c | 65 ++++
> drivers/net/ethernet/rocker/rocker_pipeline.h | 451 +++++++++++++++++++++++++
> 2 files changed, 516 insertions(+)
> create mode 100644 drivers/net/ethernet/rocker/rocker_pipeline.h
>
> diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
> index 2f398fa..d2ea451 100644
> --- a/drivers/net/ethernet/rocker/rocker.c
> +++ b/drivers/net/ethernet/rocker/rocker.c
> @@ -36,6 +36,7 @@
> #include <generated/utsrelease.h>
>
> #include "rocker.h"
> +#include "rocker_pipeline.h"
>
> static const char rocker_driver_name[] = "rocker";
>
> @@ -3781,6 +3782,56 @@ static int rocker_port_switch_port_stp_update(struct net_device *dev, u8 state)
> return rocker_port_stp_update(rocker_port, state);
> }
>
> +static void rocker_destroy_flow_tables(struct rocker_port *rocker_port)
> +{
> + int i;
> +
> + for (i = 0; rocker_table_list[i]; i++)
> + net_flow_destroy_cache(rocker_table_list[i]);
> +}
> +
> +static int rocker_init_flow_tables(struct rocker_port *rocker_port)
> +{
> + int i, err;
> +
> + for (i = 0; rocker_table_list[i]; i++) {
> + err = net_flow_init_cache(rocker_table_list[i]);
> + if (err) {
> + rocker_destroy_flow_tables(rocker_port);
> + return err;
> + }
> + }
> +
> + return 0;
> +}
Can these be moved up above drivers? They don't seem driver or device
specific. Call .ndo_flow_get_tbls to get table list.
> +
> +#ifdef CONFIG_NET_FLOW_TABLES
> +static struct net_flow_tbl **rocker_get_tables(struct net_device *d)
> +{
> + return rocker_table_list;
> +}
> +
> +static struct net_flow_hdr **rocker_get_headers(struct net_device *d)
> +{
> + return rocker_header_list;
> +}
> +
> +static struct net_flow_action **rocker_get_actions(struct net_device *d)
> +{
> + return rocker_action_list;
> +}
> +
> +static struct net_flow_tbl_node **rocker_get_tgraph(struct net_device *d)
> +{
> + return rocker_table_nodes;
> +}
> +
> +static struct net_flow_hdr_node **rocker_get_hgraph(struct net_device *d)
> +{
> + return rocker_header_nodes;
> +}
> +#endif
Do these need to be functions since they all just return static pointer lists?
> static const struct net_device_ops rocker_port_netdev_ops = {
> .ndo_open = rocker_port_open,
> .ndo_stop = rocker_port_stop,
> @@ -3795,6 +3846,13 @@ static const struct net_device_ops rocker_port_netdev_ops = {
> .ndo_bridge_getlink = rocker_port_bridge_getlink,
> .ndo_switch_parent_id_get = rocker_port_switch_parent_id_get,
> .ndo_switch_port_stp_update = rocker_port_switch_port_stp_update,
> +#ifdef CONFIG_NET_FLOW_TABLES
> + .ndo_flow_get_tbls = rocker_get_tables,
> + .ndo_flow_get_hdrs = rocker_get_headers,
> + .ndo_flow_get_actions = rocker_get_actions,
> + .ndo_flow_get_tbl_graph = rocker_get_tgraph,
> + .ndo_flow_get_hdr_graph = rocker_get_hgraph,
Please keep the rocker_port_xxx for .ndo_xxx naming convention.
> +#endif
> };
>
> /********************
> @@ -3960,6 +4018,7 @@ static void rocker_remove_ports(struct rocker *rocker)
> rocker_port = rocker->ports[i];
> rocker_port_ig_tbl(rocker_port, ROCKER_OP_FLAG_REMOVE);
> unregister_netdev(rocker_port->dev);
> + rocker_destroy_flow_tables(rocker_port);
> }
> kfree(rocker->ports);
> }
> @@ -4023,6 +4082,12 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
> goto err_port_ig_tbl;
> }
>
> + err = rocker_init_flow_tables(rocker_port);
> + if (err) {
> + dev_err(&pdev->dev, "install flow table failed\n");
s/table/tables/
> + goto err_port_ig_tbl;
Need to rocker_port_ig_tbl(rocker_port, ROCKER_OP_FLAG_REMOVE) to clean up.
-scott
^ permalink raw reply
* Re: [PATCH] net: rocker: Add basic netdev counters - v2
From: David Miller @ 2015-01-18 6:56 UTC (permalink / raw)
To: sfeldma; +Cc: dsahern, netdev, jiri
In-Reply-To: <CAE4R7bA3QG4LDvVQywDsRuJzJYv4mBq3=OXi2L=qGDfa4a8ykw@mail.gmail.com>
From: Scott Feldman <sfeldma@gmail.com>
Date: Fri, 16 Jan 2015 15:41:41 -0800
> On Fri, Jan 16, 2015 at 1:22 PM, David Ahern <dsahern@gmail.com> wrote:
>> Add packet and byte counters for RX and TX paths.
>>
>> $ ifconfig eth1
>> eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
>> inet6 fe80::5054:ff:fe12:3501 prefixlen 64 scopeid 0x20<link>
>> ether 52:54:00:12:35:01 txqueuelen 1000 (Ethernet)
>> RX packets 63 bytes 15813 (15.4 KiB)
>> RX errors 1 dropped 0 overruns 0 frame 0
>> TX packets 79 bytes 17991 (17.5 KiB)
>> TX errors 7 dropped 0 overruns 0 carrier 0 collisions 0
>>
>> Rx / Tx errors tested by injecting faults in qemu's hardware model for Rocker.
>>
>> v2:
>> - moved counter locations to avoid potential use after free per Florian's comment
>>
>> Signed-off-by: David Ahern <dsahern@gmail.com>
>> Cc: Scott Feldman <sfeldma@gmail.com>
>> Cc: Jiri Pirko <jiri@resnulli.us>
>
> Signed-off-by: Scott Feldman <sfeldma@gmail.com>
>
> Thanks David. I think this is good enough for first pass. Longer
> term, I'd like to see this replaced by stats read from device for each
> port.
Ok, applied, thanks everyone.
^ permalink raw reply
* Re: [PATCH v3 net-next 1/1] ip_tunnel: Create percpu gro_cell
From: David Miller @ 2015-01-18 6:57 UTC (permalink / raw)
To: kafai; +Cc: netdev, eric.dumazet, kernel-team
In-Reply-To: <1421431860-1960597-2-git-send-email-kafai@fb.com>
From: Martin KaFai Lau <kafai@fb.com>
Date: Fri, 16 Jan 2015 10:11:00 -0800
> In the ipip tunnel, the skb->queue_mapping is lost in ipip_rcv().
> All skb will be queued to the same cell->napi_skbs. The
> gro_cell_poll is pinned to one core under load. In production traffic,
> we also see severe rx_dropped in the tunl iface and it is probably due to
> this limit: skb_queue_len(&cell->napi_skbs) > netdev_max_backlog.
>
> This patch is trying to alloc_percpu(struct gro_cell) and schedule
> gro_cell_poll to process the skb in the same core.
>
> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH 2/7] net: wireless: wcn36xx: get chip type from platform ops
From: Pat Erley @ 2015-01-18 8:36 UTC (permalink / raw)
To: Andy Green, Kalle Valo, Eugene Krasnikov
Cc: wcn36xx-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20150118051049.31866.47265.stgit-FDDIDLfWL9/T9rR/E2HzMujRB4CPm7EUkgzjau31qRg@public.gmane.org>
On 01/17/2015 11:10 PM, Andy Green wrote:
> Autodetecting the chip type does not work well.
> Stop attempting to do it and require a platform op
> that tells us what the chip is.
>
> Signed-off-by: Andy Green <andy.green-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> drivers/net/wireless/ath/wcn36xx/main.c | 18 +++++-------------
> drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 +
> 2 files changed, 6 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
> index 7dd8873..c4178c7 100644
> --- a/drivers/net/wireless/ath/wcn36xx/main.c
> +++ b/drivers/net/wireless/ath/wcn36xx/main.c
> @@ -221,17 +221,6 @@ static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
> }
> }
>
> -static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
> -{
> - if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
> - wcn36xx_info("Chip is 3680\n");
> - wcn->chip_version = WCN36XX_CHIP_3680;
> - } else {
> - wcn36xx_info("Chip is 3660\n");
> - wcn->chip_version = WCN36XX_CHIP_3660;
> - }
> -}
> -
> static int wcn36xx_start(struct ieee80211_hw *hw)
> {
> struct wcn36xx *wcn = hw->priv;
> @@ -286,8 +275,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
> wcn36xx_feat_caps_info(wcn);
> }
>
> - wcn36xx_detect_chip_version(wcn);
> -
> /* DMA channel initialization */
> ret = wcn36xx_dxe_init(wcn);
> if (ret) {
> @@ -1023,6 +1010,11 @@ static int wcn36xx_probe(struct platform_device *pdev)
> wcn->hw = hw;
> wcn->dev = &pdev->dev;
> wcn->ctrl_ops = pdev->dev.platform_data;
> + if (!wcn->ctrl_ops->get_chip_type) {
> + dev_err(&pdev->dev, "Missing ops->get_chip_type\n");
> + return -EINVAL;
> + }
> + wcn->chip_version = wcn->ctrl_ops->get_chip_type();
>
> mutex_init(&wcn->hal_mutex);
>
> diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> index a5366b6..04793c6 100644
> --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> @@ -110,6 +110,7 @@ struct wcn36xx_platform_ctrl_ops {
> void (*close)(void);
> int (*tx)(char *buf, size_t len);
> int (*get_hw_mac)(u8 *addr);
> + int (*get_chip_type)(void);
> int (*smsm_change_state)(u32 clear_mask, u32 set_mask);
> };
>
(This all assumes this driver is currently actually being used)
Doesn't this change break any current users of wcn36xx? Couldn't you
just take the old wcn36xx_detect_chip_version and either add the check
for get_chip_type to the beginning and make it use it and return, or
fall back to the old 'broken' way?
Another alternative would be to update wcn36xx_detect_chip_version to
behave like you expect get_chip_type to, and make it the default and let
platforms override it.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH net-next] bridge: ability to disable forwarding on a port
From: roopa @ 2015-01-18 8:48 UTC (permalink / raw)
To: Arad, Ronen
Cc: stephen@networkplumber.org, davem@davemloft.net, jhs@mojatatu.com,
netdev@vger.kernel.org, sfeldma@gmail.com, jiri@resnulli.us,
tgraf@suug.ch, john.fastabend@gmail.com, vyasevic@redhat.com,
wkok@cumulusnetworks.com, gospo@cumulusnetworks.com
In-Reply-To: <E4CD12F19ABA0C4D8729E087A761DC3505DF57DB@ORSMSX101.amr.corp.intel.com>
On 1/17/15, 1:14 PM, Arad, Ronen wrote:
>
>> -----Original Message-----
>> From: roopa@cumulusnetworks.com [mailto:roopa@cumulusnetworks.com]
>> Sent: Friday, January 16, 2015 11:33 PM
>> To: stephen@networkplumber.org; davem@davemloft.net; jhs@mojatatu.com;
>> sfeldma@gmail.com; jiri@resnulli.us; Arad, Ronen; tgraf@suug.ch;
>> john.fastabend@gmail.com; vyasevic@redhat.com
>> Cc: netdev@vger.kernel.org; wkok@cumulusnetworks.com;
>> gospo@cumulusnetworks.com
>> Subject: [RFC PATCH net-next] bridge: ability to disable forwarding on a port
>>
>> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>>
>> On a Linux bridge with bridge forwarding offloaded to a switch ASIC,
>> there is a need to not re-forward the frames that come up to the
>> kernel in software.
>>
>> Typically these are broadcast or multicast packets forwarded by the
>> hardware to multiple destination ports including sending a copy of
>> the packet to the kernel (e.g. an arp broadcast).
>> The bridge driver will try to forward the packet again, resulting in
>> two copies of the same packet.
>>
>> These packets can also come up to the kernel for logging when they hit
>> a LOG acl in hardware.
>>
>> This patch makes forwarding a flag on the port similar to
>> learn and flood and drops the packet just before forwarding.
>> (The forwarding disable on a bridge is tested to work on our boxes.
>> The bridge port flag addition is only compile tested.
>> This will need to be further refined to cover cases where a non-switch port
>> is bridged to a switch port etc. We will submit more patches to cover
>> all cases if we agree on this approach).
>>
>> Other ways to solve the same problem could be to:
>> - use the offload feature flag on these switch ports to avoid the
>> re-forward:
>> https://www.marc.info/?l=linux-netdev&m=141820235010603&w=2
>>
>> - Or the switch driver can mark or set a flag in the skb, which the bridge
>> driver can use to avoid a re-forward.
>>
> The proposed patch does not go along with the offload feature flag.
> The premise of the offload feature flag is that offloading is driven by the
> switch port driver without user intervention. This patch requires different
> setting for BR_FLOOD in the software bridge port and the switch port driver.
Even with the offload feature flag, there are a few bridge port
attributes that can be set
from userspace which can be different for sw and hw. So, with this patch
I was
trying to see if making it similar to the other existing flags would be
better.
> The alternatives suggested (offload flag or skb flag) are better.
Glad to know your opinion.
>
> The proposed patch avoids re-forward but not without cost. For example in the
> case of unicast flood with local destination, the skb is cloned for each port
> before the forward avoidance in __br_forward. Is it acceptable overhead?
This patch places it in __br_forward to just make sure all the paths
including the netfilter
hook is traversed for these packets. And plus it was written with
minimal changes in mind.
We have not measured it but the extra overhead for these pkts that hit
the kernel has been negligible. But, I will look at the code to see if
it can be avoided.
Thanks,
Roopa
^ permalink raw reply
* Re: [RFC PATCH net-next] bridge: ability to disable forwarding on a port
From: roopa @ 2015-01-18 9:10 UTC (permalink / raw)
To: Scott Feldman
Cc: stephen@networkplumber.org, David S. Miller, Jamal Hadi Salim,
Jiří Pírko, Arad, Ronen, Thomas Graf,
john fastabend, vyasevic@redhat.com, Netdev, Wilson Kok,
Andy Gospodarek
In-Reply-To: <CAE4R7bBeNojtj3Zyd6+zSJFGRjG4vejBObnS1XUFAfJDZJZYow@mail.gmail.com>
On 1/17/15, 5:05 PM, Scott Feldman wrote:
> On Fri, Jan 16, 2015 at 11:32 PM, <roopa@cumulusnetworks.com> wrote:
>> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>>
>> On a Linux bridge with bridge forwarding offloaded to a switch ASIC,
>> there is a need to not re-forward the frames that come up to the
>> kernel in software.
>>
>> Typically these are broadcast or multicast packets forwarded by the
>> hardware to multiple destination ports including sending a copy of
>> the packet to the kernel (e.g. an arp broadcast).
>> The bridge driver will try to forward the packet again, resulting in
>> two copies of the same packet.
>>
>> These packets can also come up to the kernel for logging when they hit
>> a LOG acl in hardware.
>>
>> This patch makes forwarding a flag on the port similar to
>> learn and flood and drops the packet just before forwarding.
>> (The forwarding disable on a bridge is tested to work on our boxes.
>> The bridge port flag addition is only compile tested.
>> This will need to be further refined to cover cases where a non-switch port
>> is bridged to a switch port etc. We will submit more patches to cover
>> all cases if we agree on this approach).
> Good topic to bring up, thanks for proposing a patch. There is indeed
> duplicate pkts sent out in the case where both the bridge and the
> offloaded device are flooding these non-unicast pkts, such as ARP
> requests. We do have per-port control today over unicast flooding
> using BR_FLOOD (IFLA_BRPORT_UNICAST_FLOOD).
>
> As you point out, this doesn't solve the case for non-offloaded ports
> bridged with switch ports. If this port setting is enabled on an
> offloaded switch port, for example, the non-offloaded port can't get
> an ARP request resolved, if the MAC is behind the offloaded switch
> port. But do we care? Is there a use-case for this one, mixing
> offloaded and non-offloaded ports in a bridge?
Not sure. I don't know the use case, but I think I might have heard that
there could be a case
where a switch port could be bridged with a vm's port running on the
switch. (?)
>
>> Other ways to solve the same problem could be to:
>> - use the offload feature flag on these switch ports to avoid the
>> re-forward:
>> https://www.marc.info/?l=linux-netdev&m=141820235010603&w=2
>>
>> - Or the switch driver can mark or set a flag in the skb, which the bridge
>> driver can use to avoid a re-forward.
>>
>> Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com>
>> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
>> ---
>> include/linux/if_bridge.h | 3 ++-
>> include/uapi/linux/if_link.h | 1 +
>> net/bridge/br_forward.c | 13 +++++++++++++
>> net/bridge/br_if.c | 2 +-
>> net/bridge/br_netlink.c | 4 +++-
>> net/bridge/br_sysfs_if.c | 1 +
>> net/core/rtnetlink.c | 4 +++-
>> 7 files changed, 24 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
>> index 0a8ce76..c79f4eb 100644
>> --- a/include/linux/if_bridge.h
>> +++ b/include/linux/if_bridge.h
>> @@ -40,10 +40,11 @@ struct br_ip_list {
>> #define BR_ADMIN_COST BIT(4)
>> #define BR_LEARNING BIT(5)
>> #define BR_FLOOD BIT(6)
>> -#define BR_AUTO_MASK (BR_FLOOD | BR_LEARNING)
>> #define BR_PROMISC BIT(7)
>> #define BR_PROXYARP BIT(8)
>> #define BR_LEARNING_SYNC BIT(9)
>> +#define BR_FORWARD BIT(10)
> The name BR_FORWARD might confuse people thinking this is related to
> STP FORWARDING state.
yes, that thought crossed my mind too. I had BR_FORWARDING initially and
to make it sound less like
STP changed it to BR_FORWARD. :)
> We have BR_FLOOD for unknown unicast flooding.
> How about renaming BR_FLOOD to BR_FLOOD_UNICAST and add
> BR_FLOOD_BROADCAST? So you would have:
>
> IFLA_BRPORT_UNICAST_FLOOD BR_FLOOD_UNICAST /* flood
> unknown unicast traffic to port */
> IFLA_BRPORT_BROADCAST_FLOOD BR_FLOOD_BROADCAST /* flood
> bcast/mcast traffic to port */
That's a good idea. So, unknown unicast and broadcast will be covered
with that.
Am afraid there might be other packets, like the acl LOG packet hitting
the CPU/kernel (?)
I will check if there are others.
>
>> +#define BR_AUTO_MASK (BR_FLOOD | BR_LEARNING | BR_FORWARD)
>>
>> extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
>>
>> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
>> index f7d0d2d..d394625 100644
>> --- a/include/uapi/linux/if_link.h
>> +++ b/include/uapi/linux/if_link.h
>> @@ -246,6 +246,7 @@ enum {
>> IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */
>> IFLA_BRPORT_PROXYARP, /* proxy ARP */
>> IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */
>> + IFLA_BRPORT_FORWARD, /* enable forwarding on a device */
>> __IFLA_BRPORT_MAX
>> };
>> #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
>> diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
>> index f96933a..98c41c8 100644
>> --- a/net/bridge/br_forward.c
>> +++ b/net/bridge/br_forward.c
>> @@ -81,10 +81,23 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
>> br_forward_finish);
>> }
>>
>> +int br_hw_forward_finish(struct sk_buff *skb)
>> +{
>> + kfree_skb(skb);
>> +
>> + return 0;
>> +}
>> +
>> static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
>> {
>> struct net_device *indev;
>>
>> + if (!(to->flags & BR_FORWARD)) {
>> + NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, skb->dev, to->dev,
>> + br_hw_forward_finish);
>> + return;
>> + }
>> +
> Seems you should make the (flags & BR_FORWARD) check earlier, before
> skb cloning, in br_flood(), alongside the (flags & BR_FLOOD) check.
This patch strategically places it in __br_forward to catch all forwards
(due to floods or no floods ..with direct call to br_foward)
with minimal code changes in mind. Will see if the clone can be avoided.
>
> Also, the above code is skipping some vlan checks (br_handle_vlan).
The br_handle_vlan checks seemed not necessary for a packet getting dropped.
But, will check and fix if its needed while the packet traverses the
netfilter hook and before it gets dropped.
Thanks,
Roopa
^ permalink raw reply
* Re: [PATCH net-next] iproute2: bridge: support vlan range
From: roopa @ 2015-01-18 9:11 UTC (permalink / raw)
To: Scott Feldman; +Cc: Netdev, shemminger, vyasevic@redhat.com, Wilson Kok
In-Reply-To: <CAE4R7bA2VHepe8CCYuubH8teXMvRry10jnpsisYq+7Qv+gXzHQ@mail.gmail.com>
On 1/17/15, 5:35 PM, Scott Feldman wrote:
> On Thu, Jan 15, 2015 at 10:52 PM, <roopa@cumulusnetworks.com> wrote:
>> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>>
>> This patch adds vlan range support to bridge command
>> using the newly added vinfo flags BRIDGE_VLAN_INFO_RANGE_BEGIN and
>> BRIDGE_VLAN_INFO_RANGE_END.
>>
>> $bridge vlan show
>> port vlan ids
>> br0 1 PVID Egress Untagged
>>
>> dummy0 1 PVID Egress Untagged
>>
>> $bridge vlan add vid 10-15 dev dummy0
>> port vlan ids
>> br0 1 PVID Egress Untagged
>>
>> dummy0 1 PVID Egress Untagged
>> 10
>> 11
>> 12
>> 13
>> 14
>> 15
>>
>> $bridge vlan del vid 14 dev dummy0
>>
>> $bridge vlan show
>> port vlan ids
>> br0 1 PVID Egress Untagged
>>
>> dummy0 1 PVID Egress Untagged
>> 10
>> 11
>> 12
>> 13
>> 15
>>
>> $bridge vlan del vid 10-15 dev dummy0
>>
>> $bridge vlan show
>> port vlan ids
>> br0 1 PVID Egress Untagged
>>
>> dummy0 1 PVID Egress Untagged
>>
>> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
>> Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com>
>> ---
>> bridge/vlan.c | 46 ++++++++++++++++++++++++++++++++++++++-------
>> include/linux/if_bridge.h | 2 ++
>> 2 files changed, 41 insertions(+), 7 deletions(-)
>>
>> diff --git a/bridge/vlan.c b/bridge/vlan.c
>> index 3bd7b0d..90b3b6b 100644
>> --- a/bridge/vlan.c
>> +++ b/bridge/vlan.c
>> @@ -32,6 +32,7 @@ static int vlan_modify(int cmd, int argc, char **argv)
>> } req;
>> char *d = NULL;
>> short vid = -1;
>> + short vid_end = -1;
>> struct rtattr *afspec;
>> struct bridge_vlan_info vinfo;
>> unsigned short flags = 0;
>> @@ -49,8 +50,18 @@ static int vlan_modify(int cmd, int argc, char **argv)
>> NEXT_ARG();
>> d = *argv;
>> } else if (strcmp(*argv, "vid") == 0) {
>> + char *p;
>> NEXT_ARG();
>> - vid = atoi(*argv);
>> + p = strchr(*argv, '-');
>> + if (p) {
>> + *p = '\0';
>> + p++;
>> + vinfo.vid = atoi(*argv);
>> + vid_end = atoi(p);
> Is "vid 10-" same as "vid 10-0"?
correct ..
# bridge vlan add vid 10- dev dummy0
Invalid VLAN range "10-0"
>
> Is "vid -15" same as "vid 0-15"?
correct
# bridge vlan add vid -10 dev dummy0
root@net-next:~/iproute2# bridge vlan show
port vlan ids
br0 1 PVID Egress Untagged
dummy0 0 PVID
1
2
3
4
5
6
7
8
9
10
dummy1 1 PVID Egress Untagged
maybe vlan 0 should not be allowed. Will check
>
> What is "vid -"?
>
> Does the "-" char mess up shells? I don't know the answer; just asking.
No it does not :)
# bridge vlan add vid -
Device and VLAN ID are required arguments.
>
>> + vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN;
>> + } else {
>> + vinfo.vid = atoi(*argv);
>> + }
>> } else if (strcmp(*argv, "self") == 0) {
>> flags |= BRIDGE_FLAGS_SELF;
>> } else if (strcmp(*argv, "master") == 0) {
>> @@ -67,7 +78,7 @@ static int vlan_modify(int cmd, int argc, char **argv)
>> argc--; argv++;
>> }
>>
>> - if (d == NULL || vid == -1) {
>> + if (d == NULL || vinfo.vid == -1) {
> Where was vinfo.vid initialized to -1? Maybe use vid rather than
> vinfo.vid in the code above where parsing the arg, and continue using
> vid and vid_end until final put of vinfo.
>
There is already a "memset(&vinfo, 0, sizeof(vinfo));" in the code in
the beginning of the function.
And the code is already using vinfo for flags. That's the reason i
decided to use vinfo here.
Thanks,
Roopa
^ permalink raw reply
* [patch net-next] switchdev: fix typo in inline function definition
From: Jiri Pirko @ 2015-01-18 9:25 UTC (permalink / raw)
To: netdev; +Cc: davem, sfeldma
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
include/net/switchdev.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 201120e..205e636 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -69,7 +69,7 @@ static inline int unregister_netdev_switch_notifier(struct notifier_block *nb)
}
static inline int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
- struct netdev_switch_notifier_info *info);
+ struct netdev_switch_notifier_info *info)
{
return NOTIFY_DONE;
}
--
1.9.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox