* [PATCH net-next v2 3/9] qlcnic: Firmware dump collection when auto recovery is disabled.
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Pratik Pujar, himanshu.madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Pratik Pujar <pratik.pujar@qlogic.com>
o Allow collecting the firmware dump of halted firmware when auto
recovery is disabled.
Signed-off-by: Pratik Pujar <pratik.pujar@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 11 +++++++++++
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 7 ++++++-
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index f09e787..d303fab 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -818,6 +818,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_mailbox *mbx = ahw->mailbox;
int ret = 0;
+ u32 owner;
u32 val;
/* Perform NIC configuration based ready state entry actions */
@@ -846,6 +847,10 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
set_bit(__QLCNIC_RESETTING, &adapter->state);
qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
+ } else {
+ owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
+ if (ahw->pci_func == owner)
+ qlcnic_dump_fw(adapter);
}
return -EIO;
}
@@ -1058,6 +1063,12 @@ void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
qlcnic_83xx_periodic_tasks(adapter);
+ /* Do not reschedule if firmaware is in hanged state and auto
+ * recovery is disabled
+ */
+ if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset)
+ return;
+
/* Re-schedule the function */
if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 55e8b23..5195972 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -3353,6 +3353,8 @@ done:
static int
qlcnic_check_health(struct qlcnic_adapter *adapter)
{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump;
u32 state = 0, heartbeat;
u32 peg_status;
int err = 0;
@@ -3377,7 +3379,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
goto detach;
- if (adapter->ahw->reset_context && qlcnic_auto_fw_reset)
+ if (ahw->reset_context && qlcnic_auto_fw_reset)
qlcnic_reset_hw_context(adapter);
return 0;
@@ -3420,6 +3422,9 @@ detach:
qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
QLCDB(adapter, DRV, "fw recovery scheduled.\n");
+ } else if (!qlcnic_auto_fw_reset && fw_dump->enable &&
+ adapter->flags & QLCNIC_FW_RESET_OWNER) {
+ qlcnic_dump_fw(adapter);
}
return 1;
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 9/9] qlcnic: update version to 5.3.51
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Himanshu Madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 728bb88..0c2405d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -38,8 +38,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 50
-#define QLCNIC_LINUX_VERSIONID "5.3.50"
+#define _QLCNIC_LINUX_SUBVERSION 51
+#define QLCNIC_LINUX_VERSIONID "5.3.51"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 8/9] qlcnic: Skip unknown entry type while collecting firmware dump
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Shahed Shaikh, himanshu.madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Shahed Shaikh <shahed.shaikh@qlogic.com>
o Driver aborts the minidump collection operation when it finds
an unknown entry opcode. This patch skips unknown entry type
and resumes the minidump collection operation.
o Removed a comparision of collected dump size with expected dump size.
Size may differ when driver decides to skip an entry.
Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 41 ++++++++++------------
1 file changed, 19 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index 1551360..7763962 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -1187,41 +1187,38 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
}
if (ops_index == ops_cnt) {
- dev_info(&adapter->pdev->dev,
- "Invalid entry type %d, exiting dump\n",
+ dev_info(dev, "Skipping unknown entry opcode %d\n",
entry->hdr.type);
- goto error;
+ entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ entry_offset += entry->hdr.offset;
+ continue;
}
/* Collect dump for this entry */
dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
- if (!qlcnic_valid_dump_entry(&adapter->pdev->dev, entry, dump))
+ if (!qlcnic_valid_dump_entry(dev, entry, dump)) {
entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+ entry_offset += entry->hdr.offset;
+ continue;
+ }
+
buf_offset += entry->hdr.cap_size;
entry_offset += entry->hdr.offset;
buffer = fw_dump->data + buf_offset;
}
- if (dump_size != buf_offset) {
- dev_info(&adapter->pdev->dev,
- "Captured(%d) and expected size(%d) do not match\n",
- buf_offset, dump_size);
- goto error;
- } else {
- fw_dump->clr = 1;
- snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
- adapter->netdev->name);
- dev_info(&adapter->pdev->dev, "%s: Dump data, %d bytes captured\n",
- adapter->netdev->name, fw_dump->size);
- /* Send a udev event to notify availability of FW dump */
- kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
- return 0;
- }
-error:
+
+ fw_dump->clr = 1;
+ snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", adapter->netdev->name);
+ dev_info(dev, "%s: Dump data %d bytes captured, template header size %d bytes\n",
+ adapter->netdev->name, fw_dump->size, tmpl_hdr->size);
+ /* Send a udev event to notify availability of FW dump */
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, msg);
+
if (fw_dump->use_pex_dma)
dma_free_coherent(dev, QLC_PEX_DMA_READ_SIZE,
fw_dump->dma_buffer, fw_dump->phys_addr);
- vfree(fw_dump->data);
- return -EINVAL;
+
+ return 0;
}
void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter)
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 6/9] qlcnic: dcb code cleanup and refactoring.
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem
Cc: netdev, Dept_NX_Linux_NIC_Driver, Sucheta Chakraborty,
himanshu.madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
o Move dcb specific function definitions to dcb files.
o Move dcb specific variables to qlcnic_dcb structure.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 96 -----------
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 2 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 9 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c | 184 ++++++++++-----------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h | 109 ++++++++++--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 24 +--
.../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 9 +-
8 files changed, 207 insertions(+), 228 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index a3c4379..728bb88 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -961,8 +961,6 @@ struct qlcnic_ipaddr {
#define __QLCNIC_SRIOV_CAPABLE 11
#define __QLCNIC_MBX_POLL_ENABLE 12
#define __QLCNIC_DIAG_MODE 13
-#define __QLCNIC_DCB_STATE 14
-#define __QLCNIC_DCB_IN_AEN 15
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
@@ -2116,98 +2114,4 @@ static inline bool qlcnic_sriov_vf_check(struct qlcnic_adapter *adapter)
return status;
}
-
-static inline int qlcnic_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->get_hw_capability)
- return dcb->ops->get_hw_capability(adapter);
-
- return 0;
-}
-
-static inline void qlcnic_dcb_free(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->free)
- dcb->ops->free(adapter);
-}
-
-static inline int qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->attach)
- return dcb->ops->attach(adapter);
-
- return 0;
-}
-
-static inline int
-qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter, char *buf)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->query_hw_capability)
- return dcb->ops->query_hw_capability(adapter, buf);
-
- return 0;
-}
-
-static inline void qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->get_info)
- dcb->ops->get_info(adapter);
-}
-
-static inline int
-qlcnic_dcb_query_cee_param(struct qlcnic_adapter *adapter, char *buf, u8 type)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->query_cee_param)
- return dcb->ops->query_cee_param(adapter, buf, type);
-
- return 0;
-}
-
-static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->get_cee_cfg)
- return dcb->ops->get_cee_cfg(adapter);
-
- return 0;
-}
-
-static inline void
-qlcnic_dcb_register_aen(struct qlcnic_adapter *adapter, u8 flag)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->register_aen)
- dcb->ops->register_aen(adapter, flag);
-}
-
-static inline void qlcnic_dcb_handle_aen(struct qlcnic_adapter *adapter,
- void *msg)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->handle_aen)
- dcb->ops->handle_aen(adapter, msg);
-}
-
-static inline void qlcnic_dcb_init_dcbnl_ops(struct qlcnic_adapter *adapter)
-{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (dcb && dcb->ops->init_dcbnl_ops)
- dcb->ops->init_dcbnl_ops(adapter);
-}
#endif /* __QLCNIC_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 268fda6..a126bdf 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -902,7 +902,7 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
QLCNIC_MBX_RSP(event[0]));
break;
case QLCNIC_MBX_DCBX_CONFIG_CHANGE_EVENT:
- qlcnic_dcb_handle_aen(adapter, (void *)&event[1]);
+ qlcnic_dcb_aen_handler(adapter->dcb, (void *)&event[1]);
break;
default:
dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index d303fab..e2cd484 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -636,7 +636,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
if (adapter->portnum == 0)
qlcnic_set_drv_version(adapter);
- qlcnic_dcb_get_info(adapter);
+ qlcnic_dcb_get_info(adapter->dcb);
qlcnic_83xx_idc_attach_driver(adapter);
return 0;
@@ -2174,6 +2174,7 @@ static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter)
int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
+ struct qlcnic_dcb *dcb;
int err = 0;
ahw->msix_supported = !!qlcnic_use_msi_x;
@@ -2231,8 +2232,10 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
if (err)
goto disable_mbx_intr;
- if (adapter->dcb && qlcnic_dcb_attach(adapter))
- qlcnic_clear_dcb_ops(adapter);
+ dcb = adapter->dcb;
+
+ if (dcb && qlcnic_dcb_attach(dcb))
+ qlcnic_clear_dcb_ops(dcb);
/* Periodically monitor device status */
qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
index d62d5ce..86bca7c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
@@ -57,22 +57,22 @@ static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops;
static void qlcnic_dcb_aen_work(struct work_struct *);
static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *);
-static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_adapter *);
-static void __qlcnic_dcb_free(struct qlcnic_adapter *);
-static int __qlcnic_dcb_attach(struct qlcnic_adapter *);
-static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *);
-static void __qlcnic_dcb_get_info(struct qlcnic_adapter *);
-
-static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *);
-static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
-static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
-static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *, void *);
-
-static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *);
-static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8);
-static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *);
-static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *, bool);
-static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *, void *);
+static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *);
+static void __qlcnic_dcb_free(struct qlcnic_dcb *);
+static int __qlcnic_dcb_attach(struct qlcnic_dcb *);
+static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *, char *);
+static void __qlcnic_dcb_get_info(struct qlcnic_dcb *);
+
+static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *);
+static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
+static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
+static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
+
+static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *);
+static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
+static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
+static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *, bool);
+static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
struct qlcnic_dcb_capability {
bool tsa_capability;
@@ -180,7 +180,7 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
.query_cee_param = qlcnic_83xx_dcb_query_cee_param,
.get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg,
.register_aen = qlcnic_83xx_dcb_register_aen,
- .handle_aen = qlcnic_83xx_dcb_handle_aen,
+ .aen_handler = qlcnic_83xx_dcb_aen_handler,
};
static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
@@ -193,7 +193,7 @@ static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
.get_hw_capability = qlcnic_82xx_dcb_get_hw_capability,
.query_cee_param = qlcnic_82xx_dcb_query_cee_param,
.get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg,
- .handle_aen = qlcnic_82xx_dcb_handle_aen,
+ .aen_handler = qlcnic_82xx_dcb_aen_handler,
};
static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val)
@@ -242,10 +242,10 @@ static int qlcnic_dcb_prio_count(u8 up_tc_map)
return j;
}
-static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_adapter *adapter)
+static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *dcb)
{
- if (test_bit(__QLCNIC_DCB_STATE, &adapter->state))
- adapter->netdev->dcbnl_ops = &qlcnic_dcbnl_ops;
+ if (test_bit(QLCNIC_DCB_STATE, &dcb->state))
+ dcb->adapter->netdev->dcbnl_ops = &qlcnic_dcbnl_ops;
}
static void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
@@ -256,7 +256,7 @@ static void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
adapter->dcb->ops = &qlcnic_83xx_dcb_ops;
}
-int __qlcnic_register_dcb(struct qlcnic_adapter *adapter)
+int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
{
struct qlcnic_dcb *dcb;
@@ -267,20 +267,22 @@ int __qlcnic_register_dcb(struct qlcnic_adapter *adapter)
adapter->dcb = dcb;
dcb->adapter = adapter;
qlcnic_set_dcb_ops(adapter);
+ dcb->state = 0;
return 0;
}
-static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
+static void __qlcnic_dcb_free(struct qlcnic_dcb *dcb)
{
- struct qlcnic_dcb *dcb = adapter->dcb;
+ struct qlcnic_adapter *adapter;
if (!dcb)
return;
- qlcnic_dcb_register_aen(adapter, 0);
+ adapter = dcb->adapter;
+ qlcnic_dcb_register_aen(dcb, 0);
- while (test_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
+ while (test_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
usleep_range(10000, 11000);
cancel_delayed_work_sync(&dcb->aen_work);
@@ -298,23 +300,22 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter)
adapter->dcb = NULL;
}
-static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter)
+static void __qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
{
- qlcnic_dcb_get_hw_capability(adapter);
- qlcnic_dcb_get_cee_cfg(adapter);
- qlcnic_dcb_register_aen(adapter, 1);
+ qlcnic_dcb_get_hw_capability(dcb);
+ qlcnic_dcb_get_cee_cfg(dcb);
+ qlcnic_dcb_register_aen(dcb, 1);
}
-static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
+static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
{
- struct qlcnic_dcb *dcb = adapter->dcb;
int err = 0;
INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work);
dcb->wq = create_singlethread_workqueue("qlcnic-dcb");
if (!dcb->wq) {
- dev_err(&adapter->pdev->dev,
+ dev_err(&dcb->adapter->pdev->dev,
"DCB workqueue allocation failed. DCB will be disabled\n");
return -1;
}
@@ -331,7 +332,7 @@ static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter)
goto out_free_cfg;
}
- qlcnic_dcb_get_info(adapter);
+ qlcnic_dcb_get_info(dcb);
return 0;
out_free_cfg:
@@ -345,9 +346,9 @@ out_free_wq:
return err;
}
-static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter,
- char *buf)
+static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *dcb, char *buf)
{
+ struct qlcnic_adapter *adapter = dcb->adapter;
struct qlcnic_cmd_args cmd;
u32 mbx_out;
int err;
@@ -371,15 +372,15 @@ static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter,
return err;
}
-static int __qlcnic_dcb_get_capability(struct qlcnic_adapter *adapter, u32 *val)
+static int __qlcnic_dcb_get_capability(struct qlcnic_dcb *dcb, u32 *val)
{
- struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
+ struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
u32 mbx_out;
int err;
memset(cap, 0, sizeof(struct qlcnic_dcb_capability));
- err = qlcnic_dcb_query_hw_capability(adapter, (char *)val);
+ err = qlcnic_dcb_query_hw_capability(dcb, (char *)val);
if (err)
return err;
@@ -397,21 +398,21 @@ static int __qlcnic_dcb_get_capability(struct qlcnic_adapter *adapter, u32 *val)
if (cap->max_num_tc > QLC_DCB_MAX_TC ||
cap->max_ets_tc > cap->max_num_tc ||
cap->max_pfc_tc > cap->max_num_tc) {
- dev_err(&adapter->pdev->dev, "Invalid DCB configuration\n");
+ dev_err(&dcb->adapter->pdev->dev, "Invalid DCB configuration\n");
return -EINVAL;
}
return err;
}
-static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
+static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
{
- struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
+ struct qlcnic_dcb_cfg *cfg = dcb->cfg;
struct qlcnic_dcb_capability *cap;
u32 mbx_out;
int err;
- err = __qlcnic_dcb_get_capability(adapter, &mbx_out);
+ err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
if (err)
return err;
@@ -419,15 +420,16 @@ static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED;
if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
- set_bit(__QLCNIC_DCB_STATE, &adapter->state);
+ set_bit(QLCNIC_DCB_STATE, &dcb->state);
return err;
}
-static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *adapter,
+static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
char *buf, u8 type)
{
u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le);
+ struct qlcnic_adapter *adapter = dcb->adapter;
struct qlcnic_82xx_dcb_param_mbx_le *prsp_le;
struct device *dev = &adapter->pdev->dev;
dma_addr_t cardrsp_phys_addr;
@@ -447,8 +449,7 @@ static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *adapter,
return -EINVAL;
}
- addr = dma_alloc_coherent(&adapter->pdev->dev, size, &cardrsp_phys_addr,
- GFP_KERNEL);
+ addr = dma_alloc_coherent(dev, size, &cardrsp_phys_addr, GFP_KERNEL);
if (addr == NULL)
return -ENOMEM;
@@ -488,72 +489,67 @@ out:
qlcnic_free_mbx_args(&cmd);
out_free_rsp:
- dma_free_coherent(&adapter->pdev->dev, size, addr, cardrsp_phys_addr);
+ dma_free_coherent(dev, size, addr, cardrsp_phys_addr);
return err;
}
-static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
+static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
{
struct qlcnic_dcb_mbx_params *mbx;
int err;
- mbx = adapter->dcb->param;
+ mbx = dcb->param;
if (!mbx)
return 0;
- err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[0],
+ err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[0],
QLC_DCB_LOCAL_PARAM_FWID);
if (err)
return err;
- err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[1],
+ err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[1],
QLC_DCB_OPER_PARAM_FWID);
if (err)
return err;
- err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[2],
+ err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[2],
QLC_DCB_PEER_PARAM_FWID);
if (err)
return err;
mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP;
- qlcnic_dcb_data_cee_param_map(adapter);
+ qlcnic_dcb_data_cee_param_map(dcb->adapter);
return err;
}
static void qlcnic_dcb_aen_work(struct work_struct *work)
{
- struct qlcnic_adapter *adapter;
struct qlcnic_dcb *dcb;
dcb = container_of(work, struct qlcnic_dcb, aen_work.work);
- adapter = dcb->adapter;
- qlcnic_dcb_get_cee_cfg(adapter);
- clear_bit(__QLCNIC_DCB_IN_AEN, &adapter->state);
+ qlcnic_dcb_get_cee_cfg(dcb);
+ clear_bit(QLCNIC_DCB_AEN_MODE, &dcb->state);
}
-static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *adapter,
- void *data)
+static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
{
- struct qlcnic_dcb *dcb = adapter->dcb;
-
- if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
+ if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
return;
queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
}
-static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
+static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
{
- struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability;
+ struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
u32 mbx_out;
int err;
- err = __qlcnic_dcb_get_capability(adapter, &mbx_out);
+ err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
if (err)
return err;
@@ -565,14 +561,15 @@ static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter)
cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED;
if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
- set_bit(__QLCNIC_DCB_STATE, &adapter->state);
+ set_bit(QLCNIC_DCB_STATE, &dcb->state);
return err;
}
-static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *adapter,
+static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
char *buf, u8 idx)
{
+ struct qlcnic_adapter *adapter = dcb->adapter;
struct qlcnic_dcb_mbx_params mbx_out;
int err, i, j, k, max_app, size;
struct qlcnic_dcb_param *each;
@@ -632,24 +629,23 @@ out:
return err;
}
-static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter)
+static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
{
- struct qlcnic_dcb *dcb = adapter->dcb;
int err;
- err = qlcnic_dcb_query_cee_param(adapter, (char *)dcb->param, 0);
+ err = qlcnic_dcb_query_cee_param(dcb, (char *)dcb->param, 0);
if (err)
return err;
- qlcnic_dcb_data_cee_param_map(adapter);
+ qlcnic_dcb_data_cee_param_map(dcb->adapter);
return err;
}
-static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *adapter,
- bool flag)
+static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *dcb, bool flag)
{
u8 val = (flag ? QLCNIC_CMD_INIT_NIC_FUNC : QLCNIC_CMD_STOP_NIC_FUNC);
+ struct qlcnic_adapter *adapter = dcb->adapter;
struct qlcnic_cmd_args cmd;
int err;
@@ -669,19 +665,17 @@ static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *adapter,
return err;
}
-static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *adapter,
- void *data)
+static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
{
- struct qlcnic_dcb *dcb = adapter->dcb;
u32 *val = data;
- if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state))
+ if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
return;
if (*val & BIT_8)
- set_bit(__QLCNIC_DCB_STATE, &adapter->state);
+ set_bit(QLCNIC_DCB_STATE, &dcb->state);
else
- clear_bit(__QLCNIC_DCB_STATE, &adapter->state);
+ clear_bit(QLCNIC_DCB_STATE, &dcb->state);
queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
}
@@ -814,12 +808,12 @@ static u8 qlcnic_dcb_get_state(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- return test_bit(__QLCNIC_DCB_STATE, &adapter->state);
+ return test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state);
}
static void qlcnic_dcb_get_perm_hw_addr(struct net_device *netdev, u8 *addr)
{
- memcpy(addr, netdev->dev_addr, netdev->addr_len);
+ memcpy(addr, netdev->perm_addr, netdev->addr_len);
}
static void
@@ -834,7 +828,7 @@ qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio,
type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
*prio = *pgid = *bw_per = *up_tc_map = 0;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state) ||
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
!type->tc_param_valid)
return;
@@ -870,7 +864,7 @@ static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,
*bw_pct = 0;
type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state) ||
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
!type->tc_param_valid)
return;
@@ -896,7 +890,7 @@ static void qlcnic_dcb_get_pfc_cfg(struct net_device *netdev, int prio,
*setting = 0;
type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state) ||
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
!type->pfc_mode_enable)
return;
@@ -915,7 +909,7 @@ static u8 qlcnic_dcb_get_capability(struct net_device *netdev, int capid,
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 0;
switch (capid) {
@@ -944,7 +938,7 @@ static int qlcnic_dcb_get_num_tcs(struct net_device *netdev, int attr, u8 *num)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return -EINVAL;
switch (attr) {
@@ -967,7 +961,7 @@ static u8 qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
.protocol = id,
};
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 0;
return dcb_getapp(netdev, &app);
@@ -978,7 +972,7 @@ static u8 qlcnic_dcb_get_pfc_state(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_dcb *dcb = adapter->dcb;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &dcb->state))
return 0;
return dcb->cfg->type[QLC_DCB_OPER_IDX].pfc_mode_enable;
@@ -989,7 +983,7 @@ static u8 qlcnic_dcb_get_dcbx(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 0;
return cfg->capability.dcb_capability;
@@ -1000,7 +994,7 @@ static u8 qlcnic_dcb_get_feat_cfg(struct net_device *netdev, int fid, u8 *flag)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_dcb_cee *type;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 1;
type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
@@ -1055,7 +1049,7 @@ static int qlcnic_dcb_peer_app_info(struct net_device *netdev,
*app_count = 0;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 0;
peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
@@ -1076,7 +1070,7 @@ static int qlcnic_dcb_peer_app_table(struct net_device *netdev,
struct qlcnic_dcb_app *app;
int i, j;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 0;
peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
@@ -1101,7 +1095,7 @@ static int qlcnic_dcb_cee_peer_get_pg(struct net_device *netdev,
struct qlcnic_dcb_cee *peer;
u8 i, j, k, map;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 0;
peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
@@ -1136,7 +1130,7 @@ static int qlcnic_dcb_cee_peer_get_pfc(struct net_device *netdev,
pfc->pfc_en = 0;
- if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state))
+ if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
return 0;
peer = &cfg->type[QLC_DCB_PEER_IDX];
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
index b87ce9f..c04ae0c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
@@ -8,26 +8,29 @@
#ifndef __QLCNIC_DCBX_H
#define __QLCNIC_DCBX_H
-void qlcnic_clear_dcb_ops(struct qlcnic_adapter *);
+#define QLCNIC_DCB_STATE 0
+#define QLCNIC_DCB_AEN_MODE 1
#ifdef CONFIG_QLCNIC_DCB
-int __qlcnic_register_dcb(struct qlcnic_adapter *);
+int qlcnic_register_dcb(struct qlcnic_adapter *);
#else
-static inline int __qlcnic_register_dcb(struct qlcnic_adapter *adapter)
+static inline int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
{ return 0; }
#endif
+struct qlcnic_dcb;
+
struct qlcnic_dcb_ops {
- void (*init_dcbnl_ops) (struct qlcnic_adapter *);
- void (*free) (struct qlcnic_adapter *);
- int (*attach) (struct qlcnic_adapter *);
- int (*query_hw_capability) (struct qlcnic_adapter *, char *);
- int (*get_hw_capability) (struct qlcnic_adapter *);
- void (*get_info) (struct qlcnic_adapter *);
- int (*query_cee_param) (struct qlcnic_adapter *, char *, u8);
- int (*get_cee_cfg) (struct qlcnic_adapter *);
- int (*register_aen) (struct qlcnic_adapter *, bool);
- void (*handle_aen) (struct qlcnic_adapter *, void *);
+ int (*query_hw_capability) (struct qlcnic_dcb *, char *);
+ int (*get_hw_capability) (struct qlcnic_dcb *);
+ int (*query_cee_param) (struct qlcnic_dcb *, char *, u8);
+ void (*init_dcbnl_ops) (struct qlcnic_dcb *);
+ int (*register_aen) (struct qlcnic_dcb *, bool);
+ void (*aen_handler) (struct qlcnic_dcb *, void *);
+ int (*get_cee_cfg) (struct qlcnic_dcb *);
+ void (*get_info) (struct qlcnic_dcb *);
+ int (*attach) (struct qlcnic_dcb *);
+ void (*free) (struct qlcnic_dcb *);
};
struct qlcnic_dcb {
@@ -37,5 +40,85 @@ struct qlcnic_dcb {
struct workqueue_struct *wq;
struct qlcnic_dcb_ops *ops;
struct qlcnic_dcb_cfg *cfg;
+ unsigned long state;
};
+
+static inline void qlcnic_clear_dcb_ops(struct qlcnic_dcb *dcb)
+{
+ kfree(dcb);
+ dcb = NULL;
+}
+
+static inline int qlcnic_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
+{
+ if (dcb && dcb->ops->get_hw_capability)
+ return dcb->ops->get_hw_capability(dcb);
+
+ return 0;
+}
+
+static inline void qlcnic_dcb_free(struct qlcnic_dcb *dcb)
+{
+ if (dcb && dcb->ops->free)
+ dcb->ops->free(dcb);
+}
+
+static inline int qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
+{
+ if (dcb && dcb->ops->attach)
+ return dcb->ops->attach(dcb);
+
+ return 0;
+}
+
+static inline int
+qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *dcb, char *buf)
+{
+ if (dcb && dcb->ops->query_hw_capability)
+ return dcb->ops->query_hw_capability(dcb, buf);
+
+ return 0;
+}
+
+static inline void qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
+{
+ if (dcb && dcb->ops->get_info)
+ dcb->ops->get_info(dcb);
+}
+
+static inline int
+qlcnic_dcb_query_cee_param(struct qlcnic_dcb *dcb, char *buf, u8 type)
+{
+ if (dcb && dcb->ops->query_cee_param)
+ return dcb->ops->query_cee_param(dcb, buf, type);
+
+ return 0;
+}
+
+static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
+{
+ if (dcb && dcb->ops->get_cee_cfg)
+ return dcb->ops->get_cee_cfg(dcb);
+
+ return 0;
+}
+
+static inline void
+qlcnic_dcb_register_aen(struct qlcnic_dcb *dcb, u8 flag)
+{
+ if (dcb && dcb->ops->register_aen)
+ dcb->ops->register_aen(dcb, flag);
+}
+
+static inline void qlcnic_dcb_aen_handler(struct qlcnic_dcb *dcb, void *msg)
+{
+ if (dcb && dcb->ops->aen_handler)
+ dcb->ops->aen_handler(dcb, msg);
+}
+
+static inline void qlcnic_dcb_init_dcbnl_ops(struct qlcnic_dcb *dcb)
+{
+ if (dcb && dcb->ops->init_dcbnl_ops)
+ dcb->ops->init_dcbnl_ops(dcb);
+}
#endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 11b4bb8..897627d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -1011,7 +1011,7 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index,
}
break;
case QLCNIC_C2H_OPCODE_GET_DCB_AEN:
- qlcnic_dcb_handle_aen(adapter, (void *)&msg);
+ qlcnic_dcb_aen_handler(adapter->dcb, (void *)&msg);
break;
default:
break;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 725d76f..0274832 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2071,7 +2071,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
return err;
}
- qlcnic_dcb_init_dcbnl_ops(adapter);
+ qlcnic_dcb_init_dcbnl_ops(adapter->dcb);
return 0;
}
@@ -2166,17 +2166,6 @@ void qlcnic_set_drv_version(struct qlcnic_adapter *adapter)
qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd);
}
-static int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
-{
- return __qlcnic_register_dcb(adapter);
-}
-
-void qlcnic_clear_dcb_ops(struct qlcnic_adapter *adapter)
-{
- kfree(adapter->dcb);
- adapter->dcb = NULL;
-}
-
static int
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -2185,6 +2174,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct qlcnic_hardware_context *ahw;
int err, pci_using_dac = -1;
char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */
+ struct qlcnic_dcb *dcb;
if (pdev->is_virtfn)
return -ENODEV;
@@ -2305,8 +2295,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->flags |= QLCNIC_NEED_FLR;
- if (adapter->dcb && qlcnic_dcb_attach(adapter))
- qlcnic_clear_dcb_ops(adapter);
+ dcb = adapter->dcb;
+
+ if (dcb && qlcnic_dcb_attach(dcb))
+ qlcnic_clear_dcb_ops(dcb);
} else if (qlcnic_83xx_check(adapter)) {
adapter->max_drv_tx_rings = 1;
@@ -2451,7 +2443,7 @@ static void qlcnic_remove(struct pci_dev *pdev)
qlcnic_cancel_idc_work(adapter);
ahw = adapter->ahw;
- qlcnic_dcb_free(adapter);
+ qlcnic_dcb_free(adapter->dcb);
unregister_netdev(netdev);
qlcnic_sriov_cleanup(adapter);
@@ -3329,7 +3321,7 @@ qlcnic_attach_work(struct work_struct *work)
return;
}
attach:
- qlcnic_dcb_get_info(adapter);
+ qlcnic_dcb_get_info(adapter->dcb);
if (netif_running(netdev)) {
if (qlcnic_up(adapter, netdev))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index 392b9bd..8b96e29 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -500,6 +500,7 @@ static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter)
static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
int pci_using_dac)
{
+ struct qlcnic_dcb *dcb;
int err;
INIT_LIST_HEAD(&adapter->vf_mc_list);
@@ -533,8 +534,10 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
if (err)
goto err_out_send_channel_term;
- if (adapter->dcb && qlcnic_dcb_attach(adapter))
- qlcnic_clear_dcb_ops(adapter);
+ dcb = adapter->dcb;
+
+ if (dcb && qlcnic_dcb_attach(dcb))
+ qlcnic_clear_dcb_ops(dcb);
err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac);
if (err)
@@ -1577,7 +1580,7 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
if (err)
goto err_out_term_channel;
- qlcnic_dcb_get_info(adapter);
+ qlcnic_dcb_get_info(adapter->dcb);
return 0;
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 7/9] qlcnic: Validate Tx queue only for 82xx adapters.
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Himanshu Madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Himanshu Madhani <himanshu.madhani@qlogic.com>
o validate Tx queue only in case of adapters which supports
multi Tx queue.
This patch is to fix regression introduced in commit
aa4a1f7df7cbb98797c9f4edfde3c726e2b3841f
"qlcnic: Enable Tx queue changes using ethtool for 82xx Series adapter"
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 8 +-------
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 66355b7..b2a8805 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -691,7 +691,7 @@ static int qlcnic_set_channels(struct net_device *dev,
return err;
}
- if (channel->tx_count) {
+ if (qlcnic_82xx_check(adapter) && channel->tx_count) {
err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count);
if (err)
return err;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 0274832..830c15f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -3650,11 +3650,6 @@ int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, u32 txq)
u8 max_hw = QLCNIC_MAX_TX_RINGS;
u32 max_allowed;
- if (!qlcnic_82xx_check(adapter)) {
- netdev_err(netdev, "No Multi TX-Q support\n");
- return -EINVAL;
- }
-
if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n");
return -EINVAL;
@@ -3694,8 +3689,7 @@ int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
u8 max_hw = adapter->ahw->max_rx_ques;
u32 max_allowed;
- if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
- !qlcnic_use_msi) {
+ if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
netdev_err(netdev, "No RSS support in INT-x mode\n");
return -EINVAL;
}
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 5/9] qlcnic: Remove redundant eSwitch enable commands
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Sony Chacko, himanshu.madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
When more than one NIC physical functions are enabled on a port,
eSwitch on that port gets enabled automatically. Driver
need not explicitly enable the eSwitch.
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 2 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 23 ++++------------------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 13 ++++++------
3 files changed, 12 insertions(+), 26 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 2883b57..9f4e4c4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -629,7 +629,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *);
int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *,
struct qlcnic_info *, u8);
int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *);
-int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *, int);
+int qlcnic_83xx_set_port_eswitch_status(struct qlcnic_adapter *, int, int *);
void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *);
void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
index 63cdddf..97caf10 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
@@ -257,8 +257,8 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)
return 0;
}
-static int qlcnic_83xx_get_eswitch_port_info(struct qlcnic_adapter *adapter,
- int func, int *port_id)
+int qlcnic_83xx_set_port_eswitch_status(struct qlcnic_adapter *adapter,
+ int func, int *port_id)
{
struct qlcnic_info nic_info;
int err = 0;
@@ -274,23 +274,8 @@ static int qlcnic_83xx_get_eswitch_port_info(struct qlcnic_adapter *adapter,
else
err = -EIO;
- return err;
-}
-
-int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *adapter, int func)
-{
- int id, err = 0;
-
- err = qlcnic_83xx_get_eswitch_port_info(adapter, func, &id);
- if (err)
- return err;
-
- if (!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) {
- if (!qlcnic_enable_eswitch(adapter, id, 1))
- adapter->eswitch[id].flags |= QLCNIC_SWITCH_ENABLE;
- else
- err = -EIO;
- }
+ if (!err)
+ adapter->eswitch[*port_id].flags |= QLCNIC_SWITCH_ENABLE;
return err;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 5195972..725d76f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -819,7 +819,7 @@ static bool qlcnic_port_eswitch_cfg_capability(struct qlcnic_adapter *adapter)
int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
{
struct qlcnic_pci_info *pci_info;
- int i, ret = 0, j = 0;
+ int i, id = 0, ret = 0, j = 0;
u16 act_pci_func;
u8 pfn;
@@ -860,7 +860,8 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
continue;
if (qlcnic_port_eswitch_cfg_capability(adapter)) {
- if (!qlcnic_83xx_enable_port_eswitch(adapter, pfn))
+ if (!qlcnic_83xx_set_port_eswitch_status(adapter, pfn,
+ &id))
adapter->npars[j].eswitch_status = true;
else
continue;
@@ -879,12 +880,12 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
j++;
}
- if (qlcnic_82xx_check(adapter)) {
+ /* Update eSwitch status for adapters without per port eSwitch
+ * configuration capability
+ */
+ if (!qlcnic_port_eswitch_cfg_capability(adapter)) {
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
- } else if (!qlcnic_port_eswitch_cfg_capability(adapter)) {
- for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
- qlcnic_enable_eswitch(adapter, i, 1);
}
kfree(pci_info);
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 2/9] qlcnic: Enhance ethtool to display ring indices and interrupt mask
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Pratik Pujar, himanshu.madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Pratik Pujar <pratik.pujar@qlogic.com>
o Updated ethtool -d <ethX> option to display ring indices for Transmit(Tx),
Receive(Rx), and Status(St) rings.
o Updated ethtool -d <ethX> option to display ring interrupt mask for Transmit(Tx),
and Status(St) rings.
Signed-off-by: Pratik Pujar <pratik.pujar@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 8 ++--
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 54 ++++++++++++++++------
2 files changed, 44 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 66e94dc..c2df4ce 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -3267,12 +3267,12 @@ int qlcnic_83xx_reg_test(struct qlcnic_adapter *adapter)
return 0;
}
-int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
+inline int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
{
return (ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl) *
- sizeof(adapter->ahw->ext_reg_tbl)) +
- (ARRAY_SIZE(qlcnic_83xx_reg_tbl) +
- sizeof(adapter->ahw->reg_tbl));
+ sizeof(*adapter->ahw->ext_reg_tbl)) +
+ (ARRAY_SIZE(qlcnic_83xx_reg_tbl) *
+ sizeof(*adapter->ahw->reg_tbl));
}
int qlcnic_83xx_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index ebe4c86..66355b7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -187,8 +187,8 @@ static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
return -1;
}
-#define QLCNIC_RING_REGS_COUNT 20
-#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32))
+#define QLCNIC_TX_INTR_NOT_CONFIGURED 0X78563412
+
#define QLCNIC_MAX_EEPROM_LEN 1024
static const u32 diag_registers[] = {
@@ -219,7 +219,15 @@ static const u32 ext_diag_registers[] = {
};
#define QLCNIC_MGMT_API_VERSION 2
-#define QLCNIC_ETHTOOL_REGS_VER 3
+#define QLCNIC_ETHTOOL_REGS_VER 4
+
+static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
+{
+ int ring_regs_cnt = (adapter->max_drv_tx_rings * 5) +
+ (adapter->max_rds_rings * 2) +
+ (adapter->max_sds_rings * 3) + 5;
+ return ring_regs_cnt * sizeof(u32);
+}
static int qlcnic_get_regs_len(struct net_device *dev)
{
@@ -231,7 +239,9 @@ static int qlcnic_get_regs_len(struct net_device *dev)
else
len = sizeof(ext_diag_registers) + sizeof(diag_registers);
- return QLCNIC_RING_REGS_LEN + len + QLCNIC_DEV_INFO_SIZE + 1;
+ len += ((QLCNIC_DEV_INFO_SIZE + 2) * sizeof(u32));
+ len += qlcnic_get_ring_regs_len(adapter);
+ return len;
}
static int qlcnic_get_eeprom_len(struct net_device *dev)
@@ -493,6 +503,8 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
struct qlcnic_adapter *adapter = netdev_priv(dev);
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring;
+ struct qlcnic_host_rds_ring *rds_rings;
+ struct qlcnic_host_tx_ring *tx_ring;
u32 *regs_buff = p;
int ring, i = 0;
@@ -512,21 +524,35 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return;
- regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
-
- regs_buff[i++] = 1; /* No. of tx ring */
- regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
- regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer);
-
- regs_buff[i++] = 2; /* No. of rx ring */
- regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer);
- regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer);
+ /* Marker btw regs and TX ring count */
+ regs_buff[i++] = 0xFFEFCDAB;
+
+ regs_buff[i++] = adapter->max_drv_tx_rings; /* No. of TX ring */
+ for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
+ tx_ring = &adapter->tx_ring[ring];
+ regs_buff[i++] = le32_to_cpu(*(tx_ring->hw_consumer));
+ regs_buff[i++] = tx_ring->sw_consumer;
+ regs_buff[i++] = readl(tx_ring->crb_cmd_producer);
+ regs_buff[i++] = tx_ring->producer;
+ if (tx_ring->crb_intr_mask)
+ regs_buff[i++] = readl(tx_ring->crb_intr_mask);
+ else
+ regs_buff[i++] = QLCNIC_TX_INTR_NOT_CONFIGURED;
+ }
- regs_buff[i++] = adapter->max_sds_rings;
+ regs_buff[i++] = adapter->max_rds_rings; /* No. of RX ring */
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_rings = &recv_ctx->rds_rings[ring];
+ regs_buff[i++] = readl(rds_rings->crb_rcv_producer);
+ regs_buff[i++] = rds_rings->producer;
+ }
+ regs_buff[i++] = adapter->max_sds_rings; /* No. of SDS ring */
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &(recv_ctx->sds_rings[ring]);
regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
+ regs_buff[i++] = sds_ring->consumer;
+ regs_buff[i++] = readl(sds_ring->crb_intr_mask);
}
}
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 4/9] qlcnic: Update ethtool standard pause settings.
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Jitendra Kalsaria,
himanshu.madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Update ethtool standard pause parameter settings and display
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 18 +++++++++++++++---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 3 +++
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index c2df4ce..268fda6 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -3369,10 +3369,21 @@ void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *adapter,
}
config = ahw->port_config;
if (config & QLC_83XX_CFG_STD_PAUSE) {
- if (config & QLC_83XX_CFG_STD_TX_PAUSE)
+ switch (MSW(config)) {
+ case QLC_83XX_TX_PAUSE:
+ pause->tx_pause = 1;
+ break;
+ case QLC_83XX_RX_PAUSE:
+ pause->rx_pause = 1;
+ break;
+ case QLC_83XX_TX_RX_PAUSE:
+ default:
+ /* Backward compatibility for existing
+ * flash definitions
+ */
pause->tx_pause = 1;
- if (config & QLC_83XX_CFG_STD_RX_PAUSE)
pause->rx_pause = 1;
+ }
}
if (QLC_83XX_AUTONEG(config))
@@ -3415,7 +3426,8 @@ int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter,
ahw->port_config &= ~QLC_83XX_CFG_STD_RX_PAUSE;
ahw->port_config |= QLC_83XX_CFG_STD_TX_PAUSE;
} else if (!pause->rx_pause && !pause->tx_pause) {
- ahw->port_config &= ~QLC_83XX_CFG_STD_TX_RX_PAUSE;
+ ahw->port_config &= ~(QLC_83XX_CFG_STD_TX_RX_PAUSE |
+ QLC_83XX_CFG_STD_PAUSE);
}
status = qlcnic_83xx_set_port_config(adapter);
if (status) {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 533e150..2883b57 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -363,6 +363,9 @@ enum qlcnic_83xx_states {
#define QLC_83XX_LINK_EEE(data) ((data) & BIT_13)
#define QLC_83XX_DCBX(data) (((data) >> 28) & 7)
#define QLC_83XX_AUTONEG(data) ((data) & BIT_15)
+#define QLC_83XX_TX_PAUSE 0x10
+#define QLC_83XX_RX_PAUSE 0x20
+#define QLC_83XX_TX_RX_PAUSE 0x30
#define QLC_83XX_CFG_STD_PAUSE (1 << 5)
#define QLC_83XX_CFG_STD_TX_PAUSE (1 << 20)
#define QLC_83XX_CFG_STD_RX_PAUSE (2 << 20)
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 1/9] qlcnic: Print informational messages only once during driver load.
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem
Cc: netdev, Dept_NX_Linux_NIC_Driver, Sucheta Chakraborty,
himanshu.madhani
In-Reply-To: <cover.1381538863.git.himanshu.madhani@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 1 +
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 12 -----------
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 25 ++++++++++++++++++----
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 +
4 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 81bf836..a3c4379 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1199,6 +1199,7 @@ struct qlcnic_npar_info {
u8 promisc_mode;
u8 offload_flags;
u8 pci_func;
+ u8 mac[ETH_ALEN];
};
struct qlcnic_eswitch {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 3ca00e0..66e94dc 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -2321,19 +2321,7 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
i++;
memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
i = i + 3;
- if (ahw->op_mode == QLCNIC_MGMT_FUNC)
- dev_info(dev, "id = %d active = %d type = %d\n"
- "\tport = %d min bw = %d max bw = %d\n"
- "\tmac_addr = %pM\n", pci_info->id,
- pci_info->active, pci_info->type,
- pci_info->default_port,
- pci_info->tx_min_bw,
- pci_info->tx_max_bw, pci_info->mac);
}
- if (ahw->op_mode == QLCNIC_MGMT_FUNC)
- dev_info(dev, "Max functions = %d, active functions = %d\n",
- ahw->max_pci_func, ahw->act_pci_func);
-
} else {
dev_err(dev, "Failed to get PCI Info, error = %d\n", err);
err = -EIO;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
index 0248a4c..63cdddf 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
@@ -94,13 +94,30 @@ qlcnic_83xx_config_vnic_buff_descriptors(struct qlcnic_adapter *adapter)
**/
static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
{
- int err = -EIO;
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ struct device *dev = &adapter->pdev->dev;
+ struct qlcnic_npar_info *npar;
+ int i, err = -EIO;
qlcnic_83xx_get_minidump_template(adapter);
+
if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED)) {
if (qlcnic_init_pci_info(adapter))
return err;
+ npar = adapter->npars;
+
+ for (i = 0; i < ahw->act_pci_func; i++, npar++) {
+ dev_info(dev, "id = %d active = %d type = %d\n"
+ "\tport = %d min bw = %d max bw = %d\n"
+ "\tmac_addr = %pM\n", npar->pci_func,
+ npar->active, npar->type, npar->phy_port,
+ npar->min_bw, npar->max_bw, npar->mac);
+ }
+
+ dev_info(dev, "Max functions = %d, active functions = %d\n",
+ ahw->max_pci_func, ahw->act_pci_func);
+
if (qlcnic_83xx_set_vnic_opmode(adapter))
return err;
@@ -115,12 +132,12 @@ static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
return err;
qlcnic_83xx_config_vnic_buff_descriptors(adapter);
- adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
+ ahw->msix_supported = qlcnic_use_msi_x ? 1 : 0;
adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
qlcnic_83xx_enable_vnic_mode(adapter, 1);
- dev_info(&adapter->pdev->dev, "HAL Version: %d, Management function\n",
- adapter->ahw->fw_hal_version);
+ dev_info(dev, "HAL Version: %d, Management function\n",
+ ahw->fw_hal_version);
return 0;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index f07f2b0..55e8b23 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -875,6 +875,7 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
adapter->npars[j].min_bw = pci_info[i].tx_min_bw;
adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
+ memcpy(&adapter->npars[j].mac, &pci_info[i].mac, ETH_ALEN);
j++;
}
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next v2 0/9] qlcnic: fixes and ethtool enhancements.
From: Himanshu Madhani @ 2013-10-11 18:42 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept_NX_Linux_NIC_Driver, Himanshu Madhani
From: Himanshu Madhani <himanshu.madhani@qlogic.com>
This patch series contains
o patch to fix regression introduced by commit
aa4a1f7df7cbb98797c9f4edfde3c726e2b3841f.
o updates to ethtool for pause settings and enhance
register dump to display mask and ring indices.
o cleanup in DCB code and remove redundant eSwitch enablement command.
o fixed firmware dump collection logic to skip unknown entries.
Changes from v1 -> v2
o Dropped patch to register device if adapter is in FAILED state for more rework.
o Updated patch to display ring indices via ethtool per Ben Hutchings's comment.
o Update patch for DCB cleanup per Stephen Hemminger's comment.
Please apply to net-next.
Thanks,
Himanshu
Himanshu Madhani (2):
qlcnic: Validate Tx queue only for 82xx adapters.
qlcnic: update version to 5.3.51
Jitendra Kalsaria (1):
qlcnic: Update ethtool standard pause settings.
Pratik Pujar (2):
qlcnic: Enhance ethtool to display ring indices and interrupt mask
qlcnic: Firmware dump collection when auto recovery is disabled.
Shahed Shaikh (1):
qlcnic: Skip unknown entry type while collecting firmware dump
Sony Chacko (1):
qlcnic: Remove redundant eSwitch enable commands
Sucheta Chakraborty (2):
qlcnic: Print informational messages only once during driver load.
qlcnic: dcb code cleanup and refactoring.
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 101 +----------
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 40 ++---
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 5 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 20 ++-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 48 +++---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c | 184 ++++++++++-----------
drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h | 109 ++++++++++--
.../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 56 +++++--
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 53 +++---
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 41 +++--
.../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 9 +-
12 files changed, 344 insertions(+), 324 deletions(-)
--
1.8.1.4
^ permalink raw reply
* Re: [PATCH next 2/6] be2net: pass if_id for v1 and V2 versions of TX_CREATE cmd
From: David Miller @ 2013-10-11 19:02 UTC (permalink / raw)
To: Sathya.Perla; +Cc: netdev
In-Reply-To: <CF9D1877D81D214CB0CA0669EFAE020C26A275D8@CMEXMB1.ad.emulex.com>
From: Sathya Perla <Sathya.Perla@Emulex.Com>
Date: Thu, 10 Oct 2013 10:53:41 +0000
>> -----Original Message-----
>> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org] On Behalf
>>
>> From: Vasundhara Volam <vasundhara.volam@emulex.com>
>>
>> It is a required field for all TX_CREATE cmd versions > 0.
>> Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
>> Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
>
> David, Could you pls queue this patch for the stable tree.
I have a better idea, can you guys actually submit patches to the
proper destination?
If it's a bug fix, send it to 'net'. If it's not in 'net' I'm
not submitting it to -stable.
^ permalink raw reply
* Re: [PATCH 1/1] net: fix cipso packet validation when !NETLABEL
From: Paul Moore @ 2013-10-11 19:02 UTC (permalink / raw)
To: Seif Mazareeb
Cc: davem@davemloft.net, netdev@vger.kernel.org,
thomas.petazzoni@free-electrons.com, Dmitri Epshtein
In-Reply-To: <0DB595A2CB707F458400BE9663B6A72269C0047793@SC-VEXCH2.marvell.com>
On Friday, October 11, 2013 10:58:31 AM Seif Mazareeb wrote:
> When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function could
> loop forever in the main loop if opt[opt_iter +1] == 0, this will causing a
> kernel crash in an SMP system, since the CPU executing this function will
> stall /not respond to IPIs.
>
> This problem can be reproduced by running the IP Stack Integrity Checker
> (http://isic.sourceforge.net) using the following command on a Linux machine
> connected to DUT:
>
> "icmpsic -s rand -d <DUT IP address> -r 123456"
> wait (1-2 min)
>
> Signed-off-by: Seif Mazareeb <seif@marvell.com>
> ---
> include/net/cipso_ipv4.h | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
> index a7a683e..047f1f6 100644
> --- a/include/net/cipso_ipv4.h
> +++ b/include/net/cipso_ipv4.h
> @@ -306,6 +306,10 @@ static inline int cipso_v4_validate(const struct
> sk_buff *skb, err_offset = opt_iter + 1;
> goto out;
> }
> +
> + if (opt[opt_iter + 1] == 0)
> + break;
> +
> opt_iter += opt[opt_iter + 1];
> }
Thanks for finding and reporting this bug. Unfortunately, I don't think the
supplied patch is the best way to solve this. Since a length of zero is not
valid for any known CIPSO tag types (at least that I am aware of), we should
treat a zero length tag as an error, similar to how we treat tags with length
values that stretch beyond the option itself.
I'm thinking something like this:
static inline int cipso_v4_validate(const struct sk_buff *skb,
unsigned char **option)
{
unsigned char *opt = *option;
unsigned char err_offset = 0;
u8 opt_len = opt[1];
u8 opt_iter;
u8 tag_len;
if (opt_len < 8) {
err_offset = 1;
goto out;
}
if (get_unaligned_be32(&opt[2]) == 0) {
err_offset = 2;
goto out;
}
for (opt_iter = 6; opt_iter < opt_len;) {
tag_len = opt[opt_iter + 1];
if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
err_offset = opt_iter + 1;
goto out;
}
opt_iter += tag_len;
}
out:
*option = opt + err_offset;
return err_offset;
}
If you want to fixup your patch that would be appreciated, if not, please let
me know so I can submit the fix.
Thanks,
-Paul
--
paul moore
www.paul-moore.com
^ permalink raw reply
* Re: [PATCH RFC 0/2] xfrm: Remove ancient sleeping code
From: David Miller @ 2013-10-11 19:01 UTC (permalink / raw)
To: steffen.klassert; +Cc: netdev
In-Reply-To: <20131010063301.GO7660@secunet.com>
From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Thu, 10 Oct 2013 08:33:01 +0200
> Does anyone still rely on the ancient sleeping when the SA is in
> acquire state? It is disabled by default since more that five years,
> but can cause indefinite task hangs if enabled and the needed state
> does not get resolved.
>
> We now queue packets to the policy if the states are not yet resolved
> if we are in a code path that can not sleep. We could do this even in
> the case we can sleep. As a bonus, we can remove the FLOWI_FLAG_CAN_SLEEP
> flag because the only thing this flag does, is to notify xfrm that we are
> in a codepath that can sleep.
>
> The two RFC patches to remove the sleeping code are in reply to this
> mail. I'd add this to the ipsec-next tree if there are no objections.
The sleep path has the slight benefit that the TCP retransmit timers
for the initial SYN packet will not be started until the IPSEC rule
is resolved and the SYN actually goes out.
With the packet queue, if the IPSEC resolution is slow then we'll have
spurious SYN retransmits.
It makes no sense for TCP to keep queueing up SYNs if they will just
all get stuck in the packet queue. The first one is enough.
On the other hand we do want TCP to timeout, we do want the user to
be able to "Ctrl-C" (ie. send a SIGINT) during a connect, etc.
^ permalink raw reply
* Re: [PATCH] net: sh_eth: Correct fix for RX packet errors on R8A7740
From: David Miller @ 2013-10-11 18:58 UTC (permalink / raw)
To: horms+renesas; +Cc: netdev, linux-sh, magnus.damm, sergei.shtylyov, nh-ky
In-Reply-To: <1381384276-8077-2-git-send-email-horms+renesas@verge.net.au>
From: Simon Horman <horms+renesas@verge.net.au>
Date: Thu, 10 Oct 2013 14:51:16 +0900
> Nguyen Hong Ky posted a patch to correct RX packet errors on R8A7740 which
> was applied as 2c6221e4a5aab417 ("net: sh_eth: Fix RX packets errors on
> R8A7740"). Unfortunately sh_eth.c contains many similar instances
> of struct sh_eth_cpu_data and the patch was miss-applied, updating
> sh7734_data instead of r8a7740_data.
>
> This patch corrects this problem by.
> 1. Reverting the change to sh7734_data and;
> 2. Applying the change to r8a7740_data.
>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Applied, thanks Somon.
^ permalink raw reply
* Re: [PATCH 2/3] net: bpf jit: x86: optimize choose_load_func error path
From: David Miller @ 2013-10-11 18:56 UTC (permalink / raw)
To: murzin.v; +Cc: netdev, av1474, kaffeemonster, edumazet, mingo, tglx
In-Reply-To: <1381249910-17338-2-git-send-email-murzin.v@gmail.com>
From: Vladimir Murzin <murzin.v@gmail.com>
Date: Tue, 8 Oct 2013 20:31:49 +0400
> Macro CHOOSE_LOAD_FUNC returns handler for "any offset" if checks for K
> were not passed. At the same time handlers for "any offset" cases make
> the same checks against r_addr at run-time, that will always lead to
> bpf_error.
>
> Run-time checks are still necessary for indirect load operations, but
> error path for absolute and mesh loads are worth to optimize during bpf
> compile time.
>
> Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
>
> Cc: Jan Seiffert <kaffeemonster@googlemail.com>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: "David S. Miller" <davem@davemloft.net
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
>
> ---
> arch/x86/net/bpf_jit_comp.c | 15 +++++++++------
> 1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index 79c216a..28ac17f 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -123,7 +123,7 @@ static inline void bpf_flush_icache(void *start, void *end)
> }
>
> #define CHOOSE_LOAD_FUNC(K, func) \
> - ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
> + ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : NULL) : func##_positive_offset)
>
> /* Helper to find the offset of pkt_type in sk_buff
> * We want to make sure its still a 3bit field starting at a byte boundary.
> @@ -611,7 +611,13 @@ void bpf_jit_compile(struct sk_filter *fp)
> }
> case BPF_S_LD_W_ABS:
> func = CHOOSE_LOAD_FUNC(K, sk_load_word);
> -common_load: seen |= SEEN_DATAREF;
> +common_load:
> + if (!func) {
> + CLEAR_A();
> + EMIT_JMP(cleanup_addr - addrs[i]);
> + break;
> + }
> + seen |= SEEN_DATAREF;
> t_offset = func - (image + addrs[i]);
> EMIT1_off32(0xbe, K); /* mov imm32,%esi */
> EMIT1_off32(0xe8, t_offset); /* call */
> @@ -625,10 +631,7 @@ common_load: seen |= SEEN_DATAREF;
> case BPF_S_LDX_B_MSH:
> func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh);
> seen |= SEEN_DATAREF | SEEN_XREG;
> - t_offset = func - (image + addrs[i]);
> - EMIT1_off32(0xbe, K); /* mov imm32,%esi */
> - EMIT1_off32(0xe8, t_offset); /* call sk_load_byte_msh */
> - break;
> + goto common_load;
This second hunk will set SEEN_DATAREF even if common_load takes the
!func path, that is not the intention at all here.
There's a reason why these two code blocks aren't shared.
^ permalink raw reply
* Re: [PATCH net] vti: get rid of nf mark rule in prerouting
From: David Miller @ 2013-10-11 18:53 UTC (permalink / raw)
To: christophe.gouault; +Cc: netdev, amwang, saurabh
In-Reply-To: <1381245682-15523-1-git-send-email-christophe.gouault@6wind.com>
From: Christophe Gouault <christophe.gouault@6wind.com>
Date: Tue, 8 Oct 2013 17:21:22 +0200
> This patch fixes and improves the use of vti interfaces (while
> lightly changing the way of configuring them).
...
> Signed-off-by: Christophe Gouault <christophe.gouault@6wind.com>
> ---
> This is is both a fix and enhancement patch. However, there are 2 ways
> of fixing the inbound processing bug:
> - either keep the current configuration model (ikey + netfilter rule)
> and change the tunnel lookup method. This patch would then be reverted
> by the enhancement (this sounds counterproductive).
> - or directly change the configuration model (okey, no netfilter rule) and keep
> the current tunnel lookup method.
Ok, applied and queued up for -stable, thanks.
^ permalink raw reply
* [PATCH 2/2] ixgbe: enable l2 forwarding acceleration for macvlans
From: Neil Horman @ 2013-10-11 18:43 UTC (permalink / raw)
To: netdev; +Cc: john.fastabend, Andy Gospodarek, David Miller, Neil Horman
In-Reply-To: <1381517037-26007-1-git-send-email-nhorman@tuxdriver.com>
Now that l2 acceleration ops are in place from the prior patch, enable ixgbe to
take advantage of these operations. Allow it to allocate queues for a macvlan
so that when we transmit a frame, we can do the switching in hardware inside the
ixgbe card, rather than in software.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: john.fastabend@gmail.com
CC: Andy Gospodarek <andy@greyhouse.net>
CC: "David S. Miller" <davem@davemloft.net>
---
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 33 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 4 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_l2a.h | 54 ++++
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 15 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 388 ++++++++++++++++++-----
5 files changed, 400 insertions(+), 94 deletions(-)
create mode 100644 drivers/net/ethernet/intel/ixgbe/ixgbe_l2a.h
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 0ac6b11..e924efa 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -219,6 +219,17 @@ enum ixgbe_ring_state_t {
__IXGBE_RX_FCOE,
};
+struct ixgbe_fwd_adapter {
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+ struct net_device *netdev;
+ struct ixgbe_adapter *real_adapter;
+ unsigned int tx_base_queue;
+ unsigned int rx_base_queue;
+ struct net_device_stats net_stats;
+ int pool;
+ bool online;
+};
+
#define check_for_tx_hang(ring) \
test_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state)
#define set_check_for_tx_hang(ring) \
@@ -236,6 +247,7 @@ struct ixgbe_ring {
struct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */
struct net_device *netdev; /* netdev ring belongs to */
struct device *dev; /* device for DMA mapping */
+ struct ixgbe_fwd_adapter *l2_accel_priv;
void *desc; /* descriptor ring memory */
union {
struct ixgbe_tx_buffer *tx_buffer_info;
@@ -244,6 +256,7 @@ struct ixgbe_ring {
unsigned long last_rx_timestamp;
unsigned long state;
u8 __iomem *tail;
+ struct net_device *vmdq_netdev;
dma_addr_t dma; /* phys. address of descriptor ring */
unsigned int size; /* length in bytes */
@@ -288,11 +301,15 @@ enum ixgbe_ring_f_enum {
};
#define IXGBE_MAX_RSS_INDICES 16
-#define IXGBE_MAX_VMDQ_INDICES 64
+#define IXGBE_MAX_VMDQ_INDICES 32
#define IXGBE_MAX_FDIR_INDICES 63 /* based on q_vector limit */
#define IXGBE_MAX_FCOE_INDICES 8
#define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
#define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
+#define IXGBE_MAX_L2A_QUEUES 4
+#define IXGBE_MAX_L2A_QUEUES 4
+#define IXGBE_BAD_L2A_QUEUE 3
+
struct ixgbe_ring_feature {
u16 limit; /* upper limit on feature indices */
u16 indices; /* current value of indices */
@@ -738,6 +755,7 @@ struct ixgbe_adapter {
#endif /*CONFIG_DEBUG_FS*/
u8 default_up;
+ unsigned long fwd_bitmask; /* Bitmask indicating in use pools */
};
struct ixgbe_fdir_filter {
@@ -879,9 +897,14 @@ static inline void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter) {}
static inline void ixgbe_dbg_init(void) {}
static inline void ixgbe_dbg_exit(void) {}
#endif /* CONFIG_DEBUG_FS */
+static inline struct net_device *netdev_ring(const struct ixgbe_ring *ring)
+{
+ return ring->vmdq_netdev ? ring->vmdq_netdev : ring->netdev;
+}
+
static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring)
{
- return netdev_get_tx_queue(ring->netdev, ring->queue_index);
+ return netdev_get_tx_queue(netdev_ring(ring), ring->queue_index);
}
extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
@@ -915,4 +938,10 @@ extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
void ixgbe_sriov_reinit(struct ixgbe_adapter *adapter);
#endif
+int ixgbe_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd);
+int ixgbe_write_uc_addr_list(struct net_device *netdev);
+netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
+ struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *tx_ring);
+void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring);
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index e8649ab..277af14 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -150,8 +150,8 @@ static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = {
};
#define IXGBE_TEST_LEN sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN
-static int ixgbe_get_settings(struct net_device *netdev,
- struct ethtool_cmd *ecmd)
+int ixgbe_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_l2a.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_l2a.h
new file mode 100644
index 0000000..2f36584
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_l2a.h
@@ -0,0 +1,54 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2013 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+#include "ixgbe.h"
+
+
+static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
+ u64 qmask)
+{
+ u32 mask;
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
+ break;
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ mask = (qmask & 0xFFFFFFFF);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
+ mask = (qmask >> 32);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
+ break;
+ default:
+ break;
+ }
+ /* skip the flush */
+}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 90b4e10..e2dd635 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -500,7 +500,8 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)
#endif
/* only proceed if SR-IOV is enabled */
- if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+ if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
+ !(adapter->flags & IXGBE_FLAG_VMDQ_ENABLED))
return false;
/* Add starting offset to total pool count */
@@ -852,7 +853,11 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
/* apply Tx specific ring traits */
ring->count = adapter->tx_ring_count;
- ring->queue_index = txr_idx;
+ if (adapter->num_rx_pools > 1)
+ ring->queue_index =
+ txr_idx % adapter->num_rx_queues_per_pool;
+ else
+ ring->queue_index = txr_idx;
/* assign ring to adapter */
adapter->tx_ring[txr_idx] = ring;
@@ -895,7 +900,11 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
#endif /* IXGBE_FCOE */
/* apply Rx specific ring traits */
ring->count = adapter->rx_ring_count;
- ring->queue_index = rxr_idx;
+ if (adapter->num_rx_pools > 1)
+ ring->queue_index =
+ rxr_idx % adapter->num_rx_queues_per_pool;
+ else
+ ring->queue_index = rxr_idx;
/* assign ring to adapter */
adapter->rx_ring[rxr_idx] = ring;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 0ade0cd..582d30b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -52,6 +52,7 @@
#include "ixgbe_common.h"
#include "ixgbe_dcb_82599.h"
#include "ixgbe_sriov.h"
+#include "ixgbe_l2a.h"
char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
@@ -118,6 +119,8 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
};
MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
+netdev_tx_t ixgbe_fwd_xmit_frame(struct sk_buff *skb, void *priv);
+
#ifdef CONFIG_IXGBE_DCA
static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
void *p);
@@ -872,7 +875,8 @@ static u64 ixgbe_get_tx_completed(struct ixgbe_ring *ring)
static u64 ixgbe_get_tx_pending(struct ixgbe_ring *ring)
{
- struct ixgbe_adapter *adapter = netdev_priv(ring->netdev);
+ struct net_device *dev = ring->netdev;
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_hw *hw = &adapter->hw;
u32 head = IXGBE_READ_REG(hw, IXGBE_TDH(ring->reg_idx));
@@ -1055,7 +1059,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
tx_ring->next_to_use, i,
tx_ring->tx_buffer_info[i].time_stamp, jiffies);
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+ netif_stop_subqueue(netdev_ring(tx_ring), tx_ring->queue_index);
e_info(probe,
"tx hang %d detected on queue %d, resetting adapter\n",
@@ -1072,16 +1076,16 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
total_packets, total_bytes);
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
- if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
+ if (unlikely(total_packets && netif_carrier_ok(netdev_ring(tx_ring)) &&
(ixgbe_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
* sees the new next_to_clean.
*/
smp_mb();
- if (__netif_subqueue_stopped(tx_ring->netdev,
+ if (__netif_subqueue_stopped(netdev_ring(tx_ring),
tx_ring->queue_index)
&& !test_bit(__IXGBE_DOWN, &adapter->state)) {
- netif_wake_subqueue(tx_ring->netdev,
+ netif_wake_subqueue(netdev_ring(tx_ring),
tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue;
}
@@ -1226,7 +1230,7 @@ static inline void ixgbe_rx_hash(struct ixgbe_ring *ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- if (ring->netdev->features & NETIF_F_RXHASH)
+ if (netdev_ring(ring)->features & NETIF_F_RXHASH)
skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
}
@@ -1260,10 +1264,12 @@ static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
+ struct net_device *dev = netdev_ring(ring);
+
skb_checksum_none_assert(skb);
/* Rx csum disabled */
- if (!(ring->netdev->features & NETIF_F_RXCSUM))
+ if (!(dev->features & NETIF_F_RXCSUM))
return;
/* if IP and error */
@@ -1559,7 +1565,7 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- struct net_device *dev = rx_ring->netdev;
+ struct net_device *dev = netdev_ring(rx_ring);
ixgbe_update_rsc_stats(rx_ring, skb);
@@ -1739,7 +1745,7 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- struct net_device *netdev = rx_ring->netdev;
+ struct net_device *netdev = netdev_ring(rx_ring);
/* verify that the packet does not have any known errors */
if (unlikely(ixgbe_test_staterr(rx_desc,
@@ -1905,7 +1911,7 @@ static struct sk_buff *ixgbe_fetch_rx_buffer(struct ixgbe_ring *rx_ring,
#endif
/* allocate a skb to store the frags */
- skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+ skb = netdev_alloc_skb_ip_align(netdev_ring(rx_ring),
IXGBE_RX_HDR_SIZE);
if (unlikely(!skb)) {
rx_ring->rx_stats.alloc_rx_buff_failed++;
@@ -1986,6 +1992,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_adapter *adapter = q_vector->adapter;
int ddp_bytes;
unsigned int mss = 0;
+ struct net_device *netdev = netdev_ring(rx_ring);
#endif /* IXGBE_FCOE */
u16 cleaned_count = ixgbe_desc_unused(rx_ring);
@@ -1993,6 +2000,10 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
union ixgbe_adv_rx_desc *rx_desc;
struct sk_buff *skb;
+ if (rx_ring->l2_accel_priv) {
+ printk(KERN_CRIT "RECEIVING ON AN ACCELERATED QUEUE\n");
+ }
+
/* return some buffers to hardware, one at a time is too slow */
if (cleaned_count >= IXGBE_RX_BUFFER_WRITE) {
ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
@@ -2041,7 +2052,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
/* include DDPed FCoE data */
if (ddp_bytes > 0) {
if (!mss) {
- mss = rx_ring->netdev->mtu -
+ mss = netdev->mtu -
sizeof(struct fcoe_hdr) -
sizeof(struct fc_frame_header) -
sizeof(struct fcoe_crc_eof);
@@ -2455,58 +2466,6 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
}
}
-static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
- u64 qmask)
-{
- u32 mask;
- struct ixgbe_hw *hw = &adapter->hw;
-
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB:
- mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
- break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- mask = (qmask & 0xFFFFFFFF);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
- mask = (qmask >> 32);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
- break;
- default:
- break;
- }
- /* skip the flush */
-}
-
-static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
- u64 qmask)
-{
- u32 mask;
- struct ixgbe_hw *hw = &adapter->hw;
-
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB:
- mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
- IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
- break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- mask = (qmask & 0xFFFFFFFF);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
- mask = (qmask >> 32);
- if (mask)
- IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
- break;
- default:
- break;
- }
- /* skip the flush */
-}
-
/**
* ixgbe_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
@@ -2946,6 +2905,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring)
{
+ struct net_device *netdev = netdev_ring(ring);
struct ixgbe_hw *hw = &adapter->hw;
u64 tdba = ring->dma;
int wait_loop = 10;
@@ -3005,7 +2965,7 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
struct ixgbe_q_vector *q_vector = ring->q_vector;
if (q_vector)
- netif_set_xps_queue(adapter->netdev,
+ netif_set_xps_queue(netdev,
&q_vector->affinity_mask,
ring->queue_index);
}
@@ -3395,7 +3355,7 @@ static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
int rss_i = adapter->ring_feature[RING_F_RSS].indices;
- int p;
+ u16 pool;
/* PSRTYPE must be initialized in non 82598 adapters */
u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
@@ -3412,9 +3372,8 @@ static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
else if (rss_i > 1)
psrtype |= 1 << 29;
- for (p = 0; p < adapter->num_rx_pools; p++)
- IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(VMDQ_P(p)),
- psrtype);
+ for_each_set_bit(pool, &adapter->fwd_bitmask, 32)
+ IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(VMDQ_P(pool)), psrtype);
}
static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
@@ -3683,6 +3642,8 @@ static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter)
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
for (i = 0; i < adapter->num_rx_queues; i++) {
+ if (adapter->rx_ring[i]->vmdq_netdev)
+ continue;
j = adapter->rx_ring[i]->reg_idx;
vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
vlnctrl &= ~IXGBE_RXDCTL_VME;
@@ -3713,6 +3674,8 @@ static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter)
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
for (i = 0; i < adapter->num_rx_queues; i++) {
+ if (adapter->rx_ring[i]->vmdq_netdev)
+ continue;
j = adapter->rx_ring[i]->reg_idx;
vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
vlnctrl |= IXGBE_RXDCTL_VME;
@@ -3743,15 +3706,16 @@ static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
* 0 on no addresses written
* X on writing X addresses to the RAR table
**/
-static int ixgbe_write_uc_addr_list(struct net_device *netdev)
+int ixgbe_write_uc_addr_list(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
unsigned int rar_entries = hw->mac.num_rar_entries - 1;
int count = 0;
- /* In SR-IOV mode significantly less RAR entries are available */
- if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ /* In SR-IOV/VMDQ modes significantly less RAR entries are available */
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED ||
+ adapter->flags & IXGBE_FLAG_VMDQ_ENABLED)
rar_entries = IXGBE_MAX_PF_MACVLANS - 1;
/* return ENOMEM indicating insufficient memory for addresses */
@@ -3772,6 +3736,7 @@ static int ixgbe_write_uc_addr_list(struct net_device *netdev)
count++;
}
}
+
/* write the addresses in reverse order to avoid write combining */
for (; rar_entries > 0 ; rar_entries--)
hw->mac.ops.clear_rar(hw, rar_entries);
@@ -4133,6 +4098,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
ixgbe_configure_virtualization(adapter);
ixgbe_set_rx_mode(adapter->netdev);
+
ixgbe_restore_vlan(adapter);
switch (hw->mac.type) {
@@ -4459,7 +4425,7 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
* ixgbe_clean_rx_ring - Free Rx Buffers per Queue
* @rx_ring: ring to free buffers from
**/
-static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
+void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
{
struct device *dev = rx_ring->dev;
unsigned long size;
@@ -4838,6 +4804,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
return -EIO;
}
+ /* PF holds first pool slot */
+ set_bit(0, &adapter->fwd_bitmask);
set_bit(__IXGBE_DOWN, &adapter->state);
return 0;
@@ -5143,7 +5111,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
static int ixgbe_open(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- int err;
+ int err, queues;
/* disallow open during test */
if (test_bit(__IXGBE_TESTING, &adapter->state))
@@ -5168,16 +5136,22 @@ static int ixgbe_open(struct net_device *netdev)
goto err_req_irq;
/* Notify the stack of the actual queue counts. */
- err = netif_set_real_num_tx_queues(netdev,
- adapter->num_rx_pools > 1 ? 1 :
- adapter->num_tx_queues);
+ if (adapter->num_rx_pools > 1 &&
+ adapter->num_tx_queues > IXGBE_MAX_L2A_QUEUES)
+ queues = IXGBE_MAX_L2A_QUEUES;
+ else
+ queues = adapter->num_tx_queues;
+
+ err = netif_set_real_num_tx_queues(netdev, queues);
if (err)
goto err_set_queues;
-
- err = netif_set_real_num_rx_queues(netdev,
- adapter->num_rx_pools > 1 ? 1 :
- adapter->num_rx_queues);
+ if (adapter->num_rx_pools > 1 &&
+ adapter->num_rx_queues > IXGBE_MAX_L2A_QUEUES)
+ queues = IXGBE_MAX_L2A_QUEUES;
+ else
+ queues = adapter->num_rx_queues;
+ err = netif_set_real_num_rx_queues(netdev, queues);
if (err)
goto err_set_queues;
@@ -5215,7 +5189,6 @@ static int ixgbe_close(struct net_device *netdev)
struct ixgbe_adapter *adapter = netdev_priv(netdev);
ixgbe_ptp_stop(adapter);
-
ixgbe_down(adapter);
ixgbe_free_irq(adapter);
@@ -6576,7 +6549,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
{
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+ netif_stop_subqueue(netdev_ring(tx_ring), tx_ring->queue_index);
/* Herbert's original patch had:
* smp_mb__after_netif_stop_queue();
* but since that doesn't exist yet, just open code it. */
@@ -6588,7 +6561,7 @@ static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
return -EBUSY;
/* A reprieve! - use start_queue because it doesn't call schedule */
- netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
+ netif_start_subqueue(netdev_ring(tx_ring), tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue;
return 0;
}
@@ -6639,6 +6612,9 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
struct ixgbe_ring *tx_ring)
{
struct ixgbe_tx_buffer *first;
+#ifdef IXGBE_FCOE
+ struct net_device *dev;
+#endif
int tso;
u32 tx_flags = 0;
unsigned short f;
@@ -6730,9 +6706,10 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
first->protocol = protocol;
#ifdef IXGBE_FCOE
+ dev = netdev_ring(tx_ring);
/* setup tx offload for FCoE */
if ((protocol == __constant_htons(ETH_P_FCOE)) &&
- (tx_ring->netdev->features & (NETIF_F_FSO | NETIF_F_FCOE_CRC))) {
+ (dev->features & (NETIF_F_FSO | NETIF_F_FCOE_CRC))) {
tso = ixgbe_fso(tx_ring, first, &hdr_len);
if (tso < 0)
goto out_drop;
@@ -6767,8 +6744,9 @@ out_drop:
return NETDEV_TX_OK;
}
-static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
- struct net_device *netdev)
+static netdev_tx_t __ixgbe_xmit_frame(struct sk_buff *skb,
+ struct net_device *netdev,
+ struct ixgbe_ring *ring)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_ring *tx_ring;
@@ -6784,10 +6762,17 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
skb_set_tail_pointer(skb, 17);
}
- tx_ring = adapter->tx_ring[skb->queue_mapping];
+ tx_ring = ring ? ring : adapter->tx_ring[skb->queue_mapping];
+
return ixgbe_xmit_frame_ring(skb, adapter, tx_ring);
}
+static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
+ struct net_device*netdev)
+{
+ return __ixgbe_xmit_frame(skb, netdev, NULL);
+}
+
/**
* ixgbe_set_mac - Change the Ethernet Address of the NIC
* @netdev: network interface device structure
@@ -7057,6 +7042,7 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
*/
if (netif_running(dev))
ixgbe_close(dev);
+
ixgbe_clear_interrupt_scheme(adapter);
#ifdef CONFIG_IXGBE_DCB
@@ -7305,6 +7291,231 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode);
}
+static void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, u64 qmask)
+{
+ u32 mask;
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
+ break;
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ mask = (qmask & 0xFFFFFFFF);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
+ mask = (qmask >> 32);
+ if (mask)
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
+ break;
+ default:
+ break;
+ }
+}
+
+static void ixgbe_add_mac_filter(struct ixgbe_adapter *adapter,
+ u8 *addr, u16 pool)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ unsigned int entry;
+
+ entry = hw->mac.num_rar_entries - pool;
+ hw->mac.ops.set_rar(hw, entry, addr, VMDQ_P(pool), IXGBE_RAH_AV);
+}
+
+static void ixgbe_fwd_psrtype(struct ixgbe_fwd_adapter *vadapter)
+{
+ struct ixgbe_adapter *adapter = vadapter->real_adapter;
+ int rss_i = vadapter->netdev->real_num_rx_queues;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u16 pool = vadapter->pool;
+ u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
+ IXGBE_PSRTYPE_UDPHDR |
+ IXGBE_PSRTYPE_IPV4HDR |
+ IXGBE_PSRTYPE_L2HDR |
+ IXGBE_PSRTYPE_IPV6HDR;
+
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return;
+
+ if (rss_i > 3)
+ psrtype |= 2 << 29;
+ else if (rss_i > 1)
+ psrtype |= 1 << 29;
+
+ IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(VMDQ_P(pool)), psrtype);
+}
+
+static void ixgbe_enable_fwd_ring(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rx_ring,
+ struct ixgbe_fwd_adapter *accel)
+{
+ rx_ring->l2_accel_priv = accel;
+ ixgbe_configure_rx_ring(adapter, rx_ring);
+}
+
+
+static void ixgbe_disable_fwd_ring(struct ixgbe_fwd_adapter *vadapter,
+ struct ixgbe_ring *rx_ring)
+{
+ struct ixgbe_adapter *adapter = vadapter->real_adapter;
+ int index = rx_ring->queue_index + vadapter->rx_base_queue;
+
+ /* shutdown specific queue receive and wait for dma to settle */
+ ixgbe_disable_rx_queue(adapter, rx_ring);
+ usleep_range(10000, 20000);
+ ixgbe_irq_disable_queues(adapter, ((u64)1 << index));
+ ixgbe_clean_rx_ring(rx_ring);
+ rx_ring->l2_accel_priv = NULL;
+}
+
+int ixgbe_fwd_ring_up(struct net_device *vdev, struct ixgbe_fwd_adapter *accel)
+{
+ struct ixgbe_adapter *adapter = accel->real_adapter;
+ unsigned int rxbase = accel->pool * adapter->num_rx_queues_per_pool;
+ unsigned int txbase = accel->pool * adapter->num_rx_queues_per_pool;
+ int err, i;
+
+
+ accel->rx_base_queue = rxbase;
+ accel->tx_base_queue = txbase;
+
+ for (i = 0; i < vdev->num_rx_queues; i++)
+ ixgbe_disable_fwd_ring(accel, adapter->rx_ring[rxbase + i]);
+
+ for (i = 0; i < vdev->num_rx_queues; i++) {
+ adapter->rx_ring[rxbase + i]->vmdq_netdev = vdev;
+ ixgbe_enable_fwd_ring(adapter, adapter->rx_ring[rxbase + i], accel);
+ }
+
+ for (i = 0; i < vdev->num_tx_queues; i++)
+ adapter->tx_ring[txbase + i]->vmdq_netdev = vdev;
+
+ if (is_valid_ether_addr(vdev->dev_addr))
+ ixgbe_add_mac_filter(adapter, vdev->dev_addr, accel->pool);
+
+ err = netif_set_real_num_tx_queues(vdev, vdev->num_tx_queues);
+ if (err)
+ goto err_set_queues;
+ err = netif_set_real_num_rx_queues(vdev, vdev->num_rx_queues);
+ if (err)
+ goto err_set_queues;
+
+ ixgbe_fwd_psrtype(accel);
+ netif_tx_start_all_queues(vdev);
+ return 0;
+err_set_queues:
+ for (i = 0; i < vdev->num_rx_queues; i++)
+ ixgbe_disable_fwd_ring(accel, adapter->rx_ring[rxbase + i]);
+ return err;
+}
+
+int ixgbe_fwd_ring_down(struct net_device *vdev, struct ixgbe_fwd_adapter *accel)
+{
+ struct ixgbe_adapter *adapter = accel->real_adapter;
+ unsigned int rxbase = accel->rx_base_queue;
+ int i;
+
+ netif_tx_stop_all_queues(vdev);
+
+ for (i = 0; i < vdev->num_rx_queues; i++)
+ ixgbe_disable_fwd_ring(accel, adapter->rx_ring[rxbase + i]);
+
+ return 0;
+}
+
+static void* ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
+{
+ struct ixgbe_fwd_adapter *fwd_adapter = NULL;
+ struct ixgbe_adapter *adapter = netdev_priv(pdev);
+ int pool, vmdq_pool, base_queue;
+ int err;
+
+ /* Check for hardware restriction on number of rx/tx queues */
+ if (vdev->num_rx_queues != vdev->num_tx_queues ||
+ vdev->num_tx_queues > IXGBE_MAX_L2A_QUEUES ||
+ vdev->num_tx_queues == IXGBE_BAD_L2A_QUEUE) {
+ netdev_info(pdev, "%s: Supports RX/TX Queue counts 1,2, and 4\n",
+ pdev->name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (adapter->num_rx_pools > IXGBE_MAX_VMDQ_INDICES)
+ return ERR_PTR(-EBUSY);
+
+ fwd_adapter = kcalloc(1, sizeof(struct ixgbe_fwd_adapter), GFP_KERNEL);
+ if (!fwd_adapter)
+ return ERR_PTR(-ENOMEM);
+
+ pool = find_first_zero_bit(&adapter->fwd_bitmask, 32);
+ adapter->num_rx_pools++;
+ set_bit(pool, &adapter->fwd_bitmask);
+
+ /* Enable VMDq flag so device will be set in VM mode */
+ adapter->flags |= IXGBE_FLAG_VMDQ_ENABLED | IXGBE_FLAG_SRIOV_ENABLED;
+ adapter->ring_feature[RING_F_VMDQ].limit = adapter->num_rx_pools;
+ adapter->ring_feature[RING_F_VMDQ].offset = 0;
+ adapter->ring_feature[RING_F_RSS].limit = IXGBE_MAX_L2A_QUEUES;
+
+ /* Force reinit of ring allocation with VMDQ enabled */
+ ixgbe_setup_tc(pdev, netdev_get_num_tc(pdev));
+
+ /* Configure VSI adapter structure */
+ vmdq_pool = VMDQ_P(pool);
+ base_queue = vmdq_pool * adapter->num_rx_queues_per_pool;
+
+ netdev_dbg(pdev, "pool %i:%i queues %i:%i VSI bitmask %lx\n",
+ pool, adapter->num_rx_pools,
+ base_queue, base_queue + adapter->num_rx_queues_per_pool,
+ adapter->fwd_bitmask);
+
+ fwd_adapter->pool = pool;
+ fwd_adapter->netdev = vdev;
+ fwd_adapter->real_adapter = adapter;
+ fwd_adapter->rx_base_queue = base_queue;
+ fwd_adapter->tx_base_queue = base_queue;
+
+ err = ixgbe_fwd_ring_up(vdev, fwd_adapter);
+ if (!err) {
+ kfree(fwd_adapter);
+ return ERR_PTR(err);
+ }
+ return fwd_adapter;
+}
+
+static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
+{
+ struct ixgbe_fwd_adapter *fwd_adapter = priv;
+ struct ixgbe_adapter *adapter = fwd_adapter->real_adapter;
+
+ clear_bit(fwd_adapter->pool, &adapter->fwd_bitmask);
+ adapter->num_rx_pools--;
+
+ ixgbe_fwd_ring_down(fwd_adapter->netdev, fwd_adapter);
+
+ netdev_dbg(pdev, "pool %i:%i queues %i:%i VSI bitmask %lx\n",
+ fwd_adapter->pool, adapter->num_rx_pools,
+ fwd_adapter->rx_base_queue,
+ fwd_adapter->rx_base_queue + adapter->num_rx_queues_per_pool,
+ adapter->fwd_bitmask);
+}
+
+static netdev_tx_t ixgbe_fwd_xmit (struct sk_buff *skb,
+ struct net_device *dev,
+ void *priv)
+{
+ struct ixgbe_fwd_adapter *fwd_adapter = priv;
+ unsigned int queue;
+ struct ixgbe_ring *tx_ring;
+
+ queue = skb->queue_mapping + fwd_adapter->tx_base_queue;
+ tx_ring = fwd_adapter->real_adapter->tx_ring[queue];
+
+ return __ixgbe_xmit_frame(skb, dev, tx_ring);
+}
+
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
@@ -7349,6 +7560,9 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_fdb_add = ixgbe_ndo_fdb_add,
.ndo_bridge_setlink = ixgbe_ndo_bridge_setlink,
.ndo_bridge_getlink = ixgbe_ndo_bridge_getlink,
+ .ndo_dfwd_add_station = ixgbe_fwd_add,
+ .ndo_dfwd_del_station = ixgbe_fwd_del,
+ .ndo_dfwd_start_xmit = ixgbe_fwd_xmit,
};
/**
--
1.8.3.1
^ permalink raw reply related
* [PATCH 1/2] net: Add layer 2 hardware acceleration operations for macvlan devices
From: Neil Horman @ 2013-10-11 18:43 UTC (permalink / raw)
To: netdev; +Cc: john.fastabend, Andy Gospodarek, David Miller, Neil Horman
In-Reply-To: <1381517037-26007-1-git-send-email-nhorman@tuxdriver.com>
Add a operations structure that allows a network interface to export the fact
that it supports package forwarding in hardware between physical interfaces and
other mac layer devices assigned to it (such as macvlans). this operaions
structure can be used by virtual mac devices to bypass software switching so
that forwarding can be done in hardware more efficiently.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: john.fastabend@gmail.com
CC: Andy Gospodarek <andy@greyhouse.net>
CC: "David S. Miller" <davem@davemloft.net>
---
drivers/net/macvlan.c | 31 +++++++++++++++++++++++++++++++
include/linux/if_macvlan.h | 1 +
include/linux/netdev_features.h | 2 ++
include/linux/netdevice.h | 11 ++++++++++-
include/linux/skbuff.h | 4 ++--
net/core/dev.c | 18 +++++++++++++-----
net/core/ethtool.c | 1 +
net/sched/sch_generic.c | 2 +-
8 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 9bf46bd..c5a2718 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -297,7 +297,16 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
int ret;
const struct macvlan_dev *vlan = netdev_priv(dev);
+ if (vlan->fwd_priv) {
+ skb->dev = vlan->lowerdev;
+ ret = dev_hard_start_xmit(skb, skb->dev, NULL, vlan->fwd_priv);
+
+ if (likely(ret == NETDEV_TX_OK))
+ goto update_stats;
+ }
+
ret = macvlan_queue_xmit(skb, dev);
+update_stats:
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
struct macvlan_pcpu_stats *pcpu_stats;
@@ -347,6 +356,18 @@ static int macvlan_open(struct net_device *dev)
goto hash_add;
}
+ if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
+ vlan->fwd_priv = lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
+ /*
+ * If we get a NULL pointer back, or if we get an error
+ * then we should just fall through to the non accelerated path
+ */
+ if (IS_ERR_OR_NULL(vlan->fwd_priv))
+ vlan->fwd_priv = NULL;
+ else
+ return 0;
+ }
+
err = -EBUSY;
if (macvlan_addr_busy(vlan->port, dev->dev_addr))
goto out;
@@ -367,6 +388,10 @@ hash_add:
del_unicast:
dev_uc_del(lowerdev, dev->dev_addr);
out:
+ if (vlan->fwd_priv) {
+ lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev, vlan->fwd_priv);
+ vlan->fwd_priv = NULL;
+ }
return err;
}
@@ -391,6 +416,11 @@ static int macvlan_stop(struct net_device *dev)
hash_del:
macvlan_hash_del(vlan, !dev->dismantle);
+ if (vlan->fwd_priv) {
+ lowerdev->netdev_ops->ndo_dfwd_del_station(lowerdev, vlan->fwd_priv);
+ vlan->fwd_priv = NULL;
+ }
+
return 0;
}
@@ -801,6 +831,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
if (err < 0)
return err;
}
+
port = macvlan_port_get_rtnl(lowerdev);
/* Only 1 macvlan device can be created in passthru mode */
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index ddd33fd..c270285 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -61,6 +61,7 @@ struct macvlan_dev {
struct hlist_node hlist;
struct macvlan_port *port;
struct net_device *lowerdev;
+ void *fwd_priv;
struct macvlan_pcpu_stats __percpu *pcpu_stats;
DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index a2a89a5..9d1ee76 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -60,6 +60,7 @@ enum {
NETIF_F_HW_VLAN_STAG_TX_BIT, /* Transmit VLAN STAG HW acceleration */
NETIF_F_HW_VLAN_STAG_RX_BIT, /* Receive VLAN STAG HW acceleration */
NETIF_F_HW_VLAN_STAG_FILTER_BIT,/* Receive filtering on VLAN STAGs */
+ NETIF_F_HW_L2FW_DOFFLOAD_BIT, /* Allow L2 Forwarding in Hardware */
/*
* Add your fresh new feature above and remember to update
@@ -112,6 +113,7 @@ enum {
#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)
#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)
+#define NETIF_F_HW_L2FW_DOFFLOAD __NETIF_F(HW_L2FW_DOFFLOAD)
/* Features valid for ethtool to change */
/* = all defined minus driver/device-class-related */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3de49ac..0249179 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1097,6 +1097,13 @@ struct net_device_ops {
void (*ndo_del_vxlan_port)(struct net_device *dev,
sa_family_t sa_family,
__be16 port);
+
+ void* (*ndo_dfwd_add_station)(struct net_device *pdev,
+ struct net_device *vdev);
+ void (*ndo_dfwd_del_station)(struct net_device *pdev, void *priv);
+
+ netdev_tx_t (*ndo_dfwd_start_xmit) (struct sk_buff *skb,
+ struct net_device *dev, void *priv);
};
/*
@@ -1183,6 +1190,7 @@ struct net_device {
/* Management operations */
const struct net_device_ops *netdev_ops;
const struct ethtool_ops *ethtool_ops;
+ const struct forwarding_accel_ops *fwd_ops;
/* Hardware header description */
const struct header_ops *header_ops;
@@ -2383,7 +2391,8 @@ extern int dev_get_phys_port_id(struct net_device *dev,
struct netdev_phys_port_id *ppid);
extern int dev_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev,
- struct netdev_queue *txq);
+ struct netdev_queue *txq,
+ void *accel_priv);
extern int dev_forward_skb(struct net_device *dev,
struct sk_buff *skb);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 2ddb48d..1710fdb 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -426,9 +426,9 @@ struct sk_buff {
char cb[48] __aligned(8);
unsigned long _skb_refdst;
-#ifdef CONFIG_XFRM
+
struct sec_path *sp;
-#endif
+
unsigned int len,
data_len;
__u16 mac_len,
diff --git a/net/core/dev.c b/net/core/dev.c
index 5c713f2..ecad8c2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2536,7 +2536,7 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
}
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
- struct netdev_queue *txq)
+ struct netdev_queue *txq, void *accel_priv)
{
const struct net_device_ops *ops = dev->netdev_ops;
int rc = NETDEV_TX_OK;
@@ -2602,9 +2602,13 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
dev_queue_xmit_nit(skb, dev);
skb_len = skb->len;
- rc = ops->ndo_start_xmit(skb, dev);
+ if (accel_priv)
+ rc = ops->ndo_dfwd_start_xmit(skb, dev, accel_priv);
+ else
+ rc = ops->ndo_start_xmit(skb, dev);
+
trace_net_dev_xmit(skb, rc, dev, skb_len);
- if (rc == NETDEV_TX_OK)
+ if (rc == NETDEV_TX_OK && txq)
txq_trans_update(txq);
return rc;
}
@@ -2620,7 +2624,10 @@ gso:
dev_queue_xmit_nit(nskb, dev);
skb_len = nskb->len;
- rc = ops->ndo_start_xmit(nskb, dev);
+ if (accel_priv)
+ rc = ops->ndo_dfwd_start_xmit(nskb, dev, accel_priv);
+ else
+ rc = ops->ndo_start_xmit(nskb, dev);
trace_net_dev_xmit(nskb, rc, dev, skb_len);
if (unlikely(rc != NETDEV_TX_OK)) {
if (rc & ~NETDEV_TX_MASK)
@@ -2645,6 +2652,7 @@ out_kfree_skb:
out:
return rc;
}
+EXPORT_SYMBOL_GPL(dev_hard_start_xmit);
static void qdisc_pkt_len_init(struct sk_buff *skb)
{
@@ -2852,7 +2860,7 @@ int dev_queue_xmit(struct sk_buff *skb)
if (!netif_xmit_stopped(txq)) {
__this_cpu_inc(xmit_recursion);
- rc = dev_hard_start_xmit(skb, dev, txq);
+ rc = dev_hard_start_xmit(skb, dev, txq, NULL);
__this_cpu_dec(xmit_recursion);
if (dev_xmit_complete(rc)) {
HARD_TX_UNLOCK(dev, txq);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 78e9d92..9f0c599b 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -94,6 +94,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_LOOPBACK_BIT] = "loopback",
[NETIF_F_RXFCS_BIT] = "rx-fcs",
[NETIF_F_RXALL_BIT] = "rx-all",
+ [NETIF_F_HW_L2FW_DOFFLOAD_BIT] = "l2-fwd-offload",
};
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index e7121d2..8c44b1b 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -126,7 +126,7 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
HARD_TX_LOCK(dev, txq, smp_processor_id());
if (!netif_xmit_frozen_or_stopped(txq))
- ret = dev_hard_start_xmit(skb, dev, txq);
+ ret = dev_hard_start_xmit(skb, dev, txq, NULL);
HARD_TX_UNLOCK(dev, txq);
--
1.8.3.1
^ permalink raw reply related
* [RFC PATCH 0/2 v3] net: alternate proposal for using macvlans with forwarding acceleration
From: Neil Horman @ 2013-10-11 18:43 UTC (permalink / raw)
To: netdev; +Cc: john.fastabend, Andy Gospodarek, David Miller
In-Reply-To: <1380140209-24587-1-git-send-email-nhorman@tuxdriver.com>
Hey all-
heres the next, updated version of the vsi/macvlan integration that we've
been discussing.
Change notes:
* Moved the feature flag to netdev_features.h. No ethtool option for disabling
it yet, but its there now, and seems to fit fairly well. I was actually
thinking about your comment John, regarding the clumsiness in allowing sw and hw
accel vlans on the same lowerdev, and it just occured to me that we could use
the same flag on the macvlan device directly - i.e. if we found that a lowerdev
supported acceleration, then call ndo_dfwd_station_add, and, if successfull, set
the same feature flag in the macvlan device. Then we could use ethtool to
control the enabling/disabling of acceleration at the macvlan device directly.
Thoughts?
* Moved the acceleration net device methods back into net_device_ops. Looks
pretty good to me there.
* Restored the use of a separate xmit routine so we weren't subject to the
lowerdevs queue disciplines. I integrated its use with dev_hard_start_xmit, so
we could share the use of the linearization code, etc. Let me know what you
think.
Best
Neil
^ permalink raw reply
* Re: [PATCH] wimax: Use WARN(1,...) rather than printk followed by WARN_ON(1)
From: David Miller @ 2013-10-11 18:38 UTC (permalink / raw)
To: djduanjiong; +Cc: inaky.perez-gonzalez, linux-wimax, wimax, netdev, duanj.fnst
In-Reply-To: <1381192238-6486-1-git-send-email-duanj.fnst@cn.fujitsu.com>
From: djduanjiong@gmail.com
Date: Mon, 7 Oct 2013 17:30:38 -0700
> - list_for_each_entry(wimax_dev, &wimax_id_table, id_table_node) {
> - printk(KERN_ERR "BUG: %s wimax_dev %p ifindex %d not cleared\n",
> + list_for_each_entry(wimax_dev, &wimax_id_table, id_table_node)
> + WARN(1, KERN_ERR "BUG: %s wimax_dev %p ifindex %d not cleared\n",
> __func__, wimax_dev, wimax_dev->net_dev->ifindex);
You are changing the column where the openning parenthesis appears by
changing the printk() into a WARN(), therefore you have to adjust the
indentation of the next line such that the arguments start at the first
column after the openning parenthesis.
^ permalink raw reply
* Re: [PATCH net] netem: update backlog after drop
From: Eric Dumazet @ 2013-10-11 18:38 UTC (permalink / raw)
To: David Miller; +Cc: stephen, netdev
In-Reply-To: <20131011.143018.1801127237009991334.davem@davemloft.net>
On Fri, 2013-10-11 at 14:30 -0400, David Miller wrote:
> From: Stephen Hemminger <stephen@networkplumber.org>
> Date: Sun, 6 Oct 2013 15:15:33 -0700
>
> > When packet is dropped from rb-tree netem the backlog statistic should
> > also be updated.
> >
> > Reported-by: Сергеев Сергей <adron@yapic.net>
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> >
> > ---
> > Should be reviewed by Eric (he added the rb-tree stuff), and added to stable
> > as well.
>
> Eric please review this patch, thanks.
It somehow escaped from my radar ;)
Acked-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply
* Re: [PATCH net] netem: update backlog after drop
From: David Miller @ 2013-10-11 18:30 UTC (permalink / raw)
To: stephen; +Cc: eric.dumazet, netdev
In-Reply-To: <20131006151533.52988624@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Sun, 6 Oct 2013 15:15:33 -0700
> When packet is dropped from rb-tree netem the backlog statistic should
> also be updated.
>
> Reported-by: Сергеев Сергей <adron@yapic.net>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>
> ---
> Should be reviewed by Eric (he added the rb-tree stuff), and added to stable
> as well.
Eric please review this patch, thanks.
^ permalink raw reply
* Re: IPv6 kernel warning
From: dormando @ 2013-10-11 18:15 UTC (permalink / raw)
To: Yuchung Cheng
Cc: Michele Baldessari, Russell King - ARM Linux, netdev,
Neal Cardwell, Nandita Dukkipati
In-Reply-To: <alpine.DEB.2.02.1310091147340.5669@dtop>
On Wed, 9 Oct 2013, dormando wrote:
> > > >> >>
> > > >> >
> > > >> > Should I apply this and see if the warning stops?
> > Hi Dormando,
> >
> > Could you try this patch to make sure it fixes the warning (with
> > sysctl net.ipv4.early_retrans=3)?
>
> It's now running on one machine, with early_retrans=3. Will have to give
> it 24 hours to confirm.
>
Almost 48 hours, early_retrans=3, no warnings! (or crashes...)
Good catch :)
^ permalink raw reply
* Re: [PATCH net-next] openvswitch: fix vport-netdev unregister
From: Jesse Gross @ 2013-10-11 18:11 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Pravin Shelar, David S. Miller, Jiri Pirko, dev@openvswitch.org,
netdev
In-Reply-To: <CAMEtUuzf5UbZ_87DU+vSMbKzxLQgmuEfrf3NXQSz7vSF8LQTzw@mail.gmail.com>
On Thu, Oct 10, 2013 at 9:48 PM, Alexei Starovoitov <ast@plumgrid.com> wrote:
> On Thu, Oct 10, 2013 at 8:56 PM, Jesse Gross <jesse@nicira.com> wrote:
>> However, the check dev->reg_state in netdev_destroy() looks racy to
>> me, as it could already be in NETREG_UNREGISTERED even if we already
>> processed this device.
>
> you mean that netdev_destroy() will see reg_state == netreg_unregistered,
> while dp_device_event() didn't see reg_state == netreg_unregistering yet?
> or dp_device_event() saw it, proceeded to do unlink and
> netdev_destroy() ran in parallel?
> well, that's why reg_state == netreg_unregistering check in netdev_destroy()
> is done with rtnl_lock() held.
> reg_state cannot go into netreg_unregistered state skipping
> netreg_unregistering and notifier.
> therefore I don't think it's racy.
>
> In ovs_dp_notify_wq() you're checking for both unregistering and
> unregistered and that makes
> sense, since workq can run after unregistering notifier called and
> netdev_run_todo()
> already changed the state to unregistered.
> But here it's not the case.
ovs_dp_notify_wq() calls ovs_dp_detach_port(), which indirectly calls
netdev_destroy() so it seems like it actually is the same case to me.
^ permalink raw reply
* [PATCH 1/1] net: fix cipso packet validation when !NETLABEL
From: Seif Mazareeb @ 2013-10-11 17:58 UTC (permalink / raw)
To: davem@davemloft.net, paul@paul-moore.com, netdev@vger.kernel.org
Cc: thomas.petazzoni@free-electrons.com, Dmitri Epshtein
When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function could loop
forever in the main loop if opt[opt_iter +1] == 0, this will causing a kernel
crash in an SMP system, since the CPU executing this function will
stall /not respond to IPIs.
This problem can be reproduced by running the IP Stack Integrity Checker
(http://isic.sourceforge.net) using the following command on a Linux machine
connected to DUT:
"icmpsic -s rand -d <DUT IP address> -r 123456"
wait (1-2 min)
Signed-off-by: Seif Mazareeb <seif@marvell.com>
---
include/net/cipso_ipv4.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index a7a683e..047f1f6 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -306,6 +306,10 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
err_offset = opt_iter + 1;
goto out;
}
+
+ if (opt[opt_iter + 1] == 0)
+ break;
+
opt_iter += opt[opt_iter + 1];
}
--
1.8.1.2
^ 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