* [PATCHv3 NEXT 1/7] qlcnic: fix aer for virtual func
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
Virtual function are not privilge to initialize firmware.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index bf6d87a..4ecbf41 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2733,7 +2733,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
if (qlcnic_api_lock(adapter))
return -EINVAL;
- if (first_func) {
+ if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
adapter->need_fw_reset = 1;
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 2/7] qlcnic: device state management fixes for virtual func
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
o NPAR state should be set to operationl by Mangement function only.
o NPAR state should be set to non operational before device reset.
o VF function should wait for NPAR state to be operational.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_hdr.h | 5 +-
drivers/net/qlcnic/qlcnic_main.c | 80 +++++++++++++++++++++++---------------
2 files changed, 51 insertions(+), 34 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h
index 15fc320..bd346d9 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/qlcnic/qlcnic_hdr.h
@@ -718,8 +718,9 @@ enum {
#define QLCNIC_DEV_FAILED 0x6
#define QLCNIC_DEV_QUISCENT 0x7
-#define QLCNIC_DEV_NPAR_NOT_RDY 0
-#define QLCNIC_DEV_NPAR_RDY 1
+#define QLCNIC_DEV_NPAR_NON_OPER 0 /* NON Operational */
+#define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */
+#define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */
#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) &= (1 << (FN * 4)))
#define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4)))
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 4ecbf41..70c4b6b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2398,7 +2398,7 @@ qlcnic_fwinit_work(struct work_struct *work)
{
struct qlcnic_adapter *adapter = container_of(work,
struct qlcnic_adapter, fw_work.work);
- u32 dev_state = 0xf, npar_state;
+ u32 dev_state = 0xf;
if (qlcnic_api_lock(adapter))
goto err_ret;
@@ -2412,16 +2412,8 @@ qlcnic_fwinit_work(struct work_struct *work)
}
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
- npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
- if (npar_state == QLCNIC_DEV_NPAR_RDY) {
- qlcnic_api_unlock(adapter);
- goto wait_npar;
- } else {
- qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
- FW_POLL_DELAY);
- qlcnic_api_unlock(adapter);
- return;
- }
+ qlcnic_api_unlock(adapter);
+ goto wait_npar;
}
if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
@@ -2470,20 +2462,17 @@ wait_npar:
QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
switch (dev_state) {
- case QLCNIC_DEV_QUISCENT:
- case QLCNIC_DEV_NEED_QUISCENT:
- case QLCNIC_DEV_NEED_RESET:
- qlcnic_schedule_work(adapter,
- qlcnic_fwinit_work, FW_POLL_DELAY);
- return;
- case QLCNIC_DEV_FAILED:
- break;
-
- default:
+ case QLCNIC_DEV_READY:
if (!adapter->nic_ops->start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
return;
}
+ case QLCNIC_DEV_FAILED:
+ break;
+ default:
+ qlcnic_schedule_work(adapter,
+ qlcnic_fwinit_work, FW_POLL_DELAY);
+ return;
}
err_ret:
@@ -2530,6 +2519,22 @@ err_ret:
}
+/*Transit NPAR state to NON Operational */
+static void
+qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
+{
+ u32 state;
+
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ if (state == QLCNIC_DEV_NPAR_NON_OPER)
+ return;
+
+ if (qlcnic_api_lock(adapter))
+ return;
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+ qlcnic_api_unlock(adapter);
+}
+
/*Transit to RESET state from READY state only */
static void
qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
@@ -2548,6 +2553,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
qlcnic_idc_debug_info(adapter, 0);
}
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
qlcnic_api_unlock(adapter);
}
@@ -2555,21 +2561,14 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
static void
qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
- u32 state;
-
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ adapter->op_mode != QLCNIC_MGMT_FUNC)
return;
if (qlcnic_api_lock(adapter))
return;
- state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
-
- if (state != QLCNIC_DEV_NPAR_RDY) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
- QLCNIC_DEV_NPAR_RDY);
- QLCDB(adapter, DRV, "NPAR READY state set\n");
- }
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
+ QLCDB(adapter, DRV, "NPAR operational state set\n");
qlcnic_api_unlock(adapter);
}
@@ -2631,8 +2630,11 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT)
+ if (state == QLCNIC_DEV_NEED_RESET ||
+ state == QLCNIC_DEV_NEED_QUISCENT) {
+ qlcnic_set_npar_non_operational(adapter);
adapter->need_fw_reset = 1;
+ }
heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
if (heartbit != adapter->heartbit) {
@@ -2822,11 +2824,25 @@ static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{
int err;
+ u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
+ u32 npar_state;
err = qlcnic_can_start_firmware(adapter);
if (err)
return err;
+ npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
+ msleep(1000);
+ npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ }
+
+ if (!npar_opt_timeo) {
+ dev_err(&adapter->pdev->dev,
+ "Waiting for NPAR state to opertional timeout\n");
+ return -EIO;
+ }
+
qlcnic_check_options(adapter);
adapter->need_fw_reset = 0;
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 3/7] qlcnic: fix for setting function modes
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Rajesh Borundia
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
function modes was not working with CNA device, in CNA mode
other function(FCOE) can be enabled before nic.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 70c4b6b..06ffd76 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -543,8 +543,6 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
ret = qlcnic_api_lock(adapter);
if (ret)
goto err_lock;
- if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func))
- goto err_npar;
if (qlcnic_config_npars) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
@@ -562,7 +560,6 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
adapter->ahw.pci_func));
}
writel(data, priv_op);
-err_npar:
qlcnic_api_unlock(adapter);
err_lock:
return ret;
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXTv3 0/3]qlcnic: enhancement and fixes
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
I have fixed link status message by using netdev_info().
After updating net-next, same patches applied cleanly. Last commit I see
on qlcnic driver is "e88db3bd46801a9c2cd0ac5e46122d47c285faec".
Sending series of v3 patches, apply it on net-next.
-Amit
^ permalink raw reply
* [PATCHv3 NEXT 4/7] qlcnic: add eswitch statistics support
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
Adding eswitch statistics support. User can get
whole eswitch stats or stats of func belong to that eswitch.
Added:
o command to get statistics of eswitch and function.
o sysfs support to export eswitch and func statatistics.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 31 +++++++++
drivers/net/qlcnic/qlcnic_ctx.c | 125 ++++++++++++++++++++++++++++++++++++
drivers/net/qlcnic/qlcnic_main.c | 132 +++++++++++++++++++++++++++++++++++++-
3 files changed, 287 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 9703893..7f4e11b 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -555,6 +555,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026
#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027
#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028
+#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a
#define QLCNIC_RCODE_SUCCESS 0
#define QLCNIC_RCODE_TIMEOUT 17
@@ -1126,6 +1127,31 @@ struct qlcnic_esw_func_cfg {
u8 reserved;
};
+#define QLCNIC_STATS_VERSION 1
+#define QLCNIC_STATS_PORT 1
+#define QLCNIC_STATS_ESWITCH 2
+#define QLCNIC_QUERY_RX_COUNTER 0
+#define QLCNIC_QUERY_TX_COUNTER 1
+struct __qlcnic_esw_statistics {
+ __le16 context_id;
+ __le16 version;
+ __le16 size;
+ __le16 unused;
+ __le64 unicast_frames;
+ __le64 multicast_frames;
+ __le64 broadcast_frames;
+ __le64 dropped_frames;
+ __le64 errors;
+ __le64 local_frames;
+ __le64 numbytes;
+ __le64 rsvd[3];
+};
+
+struct qlcnic_esw_statistics {
+ struct __qlcnic_esw_statistics rx;
+ struct __qlcnic_esw_statistics tx;
+};
+
int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val);
int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val);
@@ -1252,6 +1278,11 @@ int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8);
int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8,
u8, u8, u16);
int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
+int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
+ struct __qlcnic_esw_statistics *);
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
+ struct __qlcnic_esw_statistics *);
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
extern int qlcnic_config_tso;
/*
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cc5d861..57c9b09 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -983,3 +983,128 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id,
return err;
}
+
+int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+ size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
+ dma_addr_t stats_dma_t;
+ void *stats_addr;
+ u32 arg1;
+ int err;
+
+ if (esw_stats == NULL)
+ return -ENOMEM;
+
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
+ func != adapter->ahw.pci_func) {
+ dev_err(&adapter->pdev->dev,
+ "Not privilege to query stats for func=%d", func);
+ return -EIO;
+ }
+
+ stats_addr = pci_alloc_consistent(adapter->pdev, stats_size,
+ &stats_dma_t);
+ if (!stats_addr) {
+ dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(stats_addr, 0, stats_size);
+
+ arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
+ arg1 |= rx_tx << 15 | stats_size << 16;
+
+ err = qlcnic_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ adapter->fw_hal_version,
+ arg1,
+ MSD(stats_dma_t),
+ LSD(stats_dma_t),
+ QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+
+ if (!err)
+ memcpy(esw_stats, stats_addr, stats_size);
+
+ pci_free_consistent(adapter->pdev, stats_size, stats_addr,
+ stats_dma_t);
+ return err;
+}
+
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+ struct __qlcnic_esw_statistics port_stats;
+ u8 i;
+ int ret = -EIO;
+
+ if (esw_stats == NULL)
+ return -ENOMEM;
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return -EIO;
+ if (adapter->npars == NULL)
+ return -EIO;
+
+ memset(esw_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+ esw_stats->context_id = eswitch;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].phy_port != eswitch)
+ continue;
+
+ memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+ if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+ continue;
+
+ esw_stats->size = port_stats.size;
+ esw_stats->version = port_stats.version;
+ esw_stats->unicast_frames += port_stats.unicast_frames;
+ esw_stats->multicast_frames += port_stats.multicast_frames;
+ esw_stats->broadcast_frames += port_stats.broadcast_frames;
+ esw_stats->dropped_frames += port_stats.dropped_frames;
+ esw_stats->errors += port_stats.errors;
+ esw_stats->local_frames += port_stats.local_frames;
+ esw_stats->numbytes += port_stats.numbytes;
+
+ ret = 0;
+ }
+ return ret;
+}
+
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
+ const u8 port, const u8 rx_tx)
+{
+
+ u32 arg1;
+
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return -EIO;
+
+ if (func_esw == QLCNIC_STATS_PORT) {
+ if (port >= QLCNIC_MAX_PCI_FUNC)
+ goto err_ret;
+ } else if (func_esw == QLCNIC_STATS_ESWITCH) {
+ if (port >= QLCNIC_NIU_MAX_XG_PORTS)
+ goto err_ret;
+ } else {
+ goto err_ret;
+ }
+
+ if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
+ goto err_ret;
+
+ arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
+ arg1 |= BIT_14 | rx_tx << 15;
+
+ return qlcnic_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ adapter->fw_hal_version,
+ arg1,
+ 0,
+ 0,
+ QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+
+err_ret:
+ dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d"
+ "rx_ctx=%d\n", func_esw, port, rx_tx);
+ return -EIO;
+}
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 06ffd76..a30bde5 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -3378,6 +3378,115 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
}
static ssize_t
+qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics port_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&port_stats, 0, size);
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &port_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &port_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &port_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics esw_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&esw_stats, 0, size);
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &esw_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &esw_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &esw_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
{
@@ -3426,6 +3535,20 @@ static struct bin_attribute bin_attr_pci_config = {
.write = NULL,
};
+static struct bin_attribute bin_attr_port_stats = {
+ .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_port_stats,
+ .write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+ .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_esw_stats,
+ .write = qlcnic_sysfs_clear_esw_stats,
+};
+
static struct bin_attribute bin_attr_esw_config = {
.attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
.size = 0,
@@ -3465,6 +3588,9 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ if (device_create_bin_file(dev, &bin_attr_port_stats))
+ dev_info(dev, "failed to create port stats sysfs entry");
+
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
if (device_create_file(dev, &dev_attr_diag_mode))
@@ -3484,7 +3610,8 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
dev_info(dev, "failed to create esw config sysfs entry");
if (device_create_bin_file(dev, &bin_attr_pm_config))
dev_info(dev, "failed to create pm config sysfs entry");
-
+ if (device_create_bin_file(dev, &bin_attr_esw_stats))
+ dev_info(dev, "failed to create eswitch stats sysfs entry");
}
static void
@@ -3492,6 +3619,8 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ device_remove_bin_file(dev, &bin_attr_port_stats);
+
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
device_remove_file(dev, &dev_attr_diag_mode);
@@ -3504,6 +3633,7 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
device_remove_bin_file(dev, &bin_attr_npar_config);
device_remove_bin_file(dev, &bin_attr_esw_config);
device_remove_bin_file(dev, &bin_attr_pm_config);
+ device_remove_bin_file(dev, &bin_attr_esw_stats);
}
#ifdef CONFIG_INET
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 7/7] qlcnic: turn off lro when rxcsum is disabled.
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sucheta Chakraborty
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
o Also dont allow lro to be turn on, if rx csum is disabled
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 1 +
drivers/net/qlcnic/qlcnic_ethtool.c | 23 +++++++++++++++++++++++
drivers/net/qlcnic/qlcnic_main.c | 2 +-
3 files changed, 25 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 7f4e11b..f6b887d 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -894,6 +894,7 @@ struct qlcnic_mac_req {
#define QLCNIC_MSI_ENABLED 0x02
#define QLCNIC_MSIX_ENABLED 0x04
#define QLCNIC_LRO_ENABLED 0x08
+#define QLCNIC_LRO_DISABLED 0x00
#define QLCNIC_BRIDGE_ENABLED 0X10
#define QLCNIC_DIAG_ENABLED 0x20
#define QLCNIC_ESWITCH_ENABLED 0x40
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 3d4655d..e38fc3d 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -818,7 +818,21 @@ static u32 qlcnic_get_rx_csum(struct net_device *dev)
static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+ if (!!data) {
+ adapter->rx_csum = !!data;
+ return 0;
+ }
+
+ if (adapter->flags & QLCNIC_LRO_ENABLED) {
+ if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED))
+ return -EIO;
+
+ dev->features &= ~NETIF_F_LRO;
+ qlcnic_send_lro_cleanup(adapter);
+ }
adapter->rx_csum = !!data;
+ dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n");
return 0;
}
@@ -1001,6 +1015,15 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
return -EINVAL;
+ if (!adapter->rx_csum) {
+ dev_info(&adapter->pdev->dev, "rx csum is off, "
+ "cannot toggle lro\n");
+ return -EINVAL;
+ }
+
+ if ((data & ETH_FLAG_LRO) && (adapter->flags & QLCNIC_LRO_ENABLED))
+ return 0;
+
if (data & ETH_FLAG_LRO) {
hw_lro = QLCNIC_LRO_ENABLED;
netdev->features |= NETIF_F_LRO;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index bf4077a..abd7cd6 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -995,7 +995,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_config_intr_coalesce(adapter);
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ if (netdev->features & NETIF_F_LRO)
qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
qlcnic_napi_enable(adapter);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 5/7] qlcnic: fix link status message
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sony Chacko
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
Display interface name with netdev_info() for link status message.
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index a30bde5..bf4077a 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1944,14 +1944,14 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
struct net_device *netdev = adapter->netdev;
if (adapter->ahw.linkup && !linkup) {
- dev_info(&netdev->dev, "NIC Link is down\n");
+ netdev_info(netdev, "NIC Link is down\n");
adapter->ahw.linkup = 0;
if (netif_running(netdev)) {
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
} else if (!adapter->ahw.linkup && linkup) {
- dev_info(&netdev->dev, "NIC Link is up\n");
+ netdev_info(netdev, "NIC Link is up\n");
adapter->ahw.linkup = 1;
if (netif_running(netdev)) {
netif_carrier_on(netdev);
--
1.6.0.2
^ permalink raw reply related
* [PATCHv3 NEXT 6/7] qlcnic: fix link diag test
From: Amit Kumar Salecha @ 2010-08-17 10:34 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sony Chacko
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
From: Sony Chacko <sony.chacko@qlogic.com>
o Give sufficient time for all makes of PHY modules
to establish the link after loopback test.
o Perform online test before offline test.
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ethtool.c | 17 ++++++++---------
drivers/net/qlcnic/qlcnic_hw.c | 1 +
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 9328d59..3d4655d 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -747,6 +747,14 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
{
memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
+ data[0] = qlcnic_reg_test(dev);
+ if (data[0])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
+ data[1] = (u64) qlcnic_test_link(dev);
+ if (data[1])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
data[2] = qlcnic_irq_test(dev);
if (data[2])
@@ -757,15 +765,6 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
eth_test->flags |= ETH_TEST_FL_FAILED;
}
-
- data[0] = qlcnic_reg_test(dev);
- if (data[0])
- eth_test->flags |= ETH_TEST_FL_FAILED;
-
- /* link test */
- data[1] = (u64) qlcnic_test_link(dev);
- if (data[1])
- eth_test->flags |= ETH_TEST_FL_FAILED;
}
static void
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index e08c8b0..9d40ce0 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -1245,4 +1245,5 @@ void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter)
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
qlcnic_nic_set_promisc(adapter, mode);
+ msleep(1000);
}
--
1.6.0.2
^ permalink raw reply related
* Re: [PATCH 1/5] ptp: Added a brand new class driver for ptp clocks.
From: Richard Cochran @ 2010-08-17 10:52 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Rodolfo Giometti,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Krzysztof Halasa
In-Reply-To: <201008170925.55592.arnd-r2nGTMty4D4@public.gmane.org>
On Tue, Aug 17, 2010 at 09:25:55AM +0000, Arnd Bergmann wrote:
> Another difference is that we generally use ioctl for devices that can
> be enumerated, while syscalls are for system services that are not tied to
> a specific device. This argument works both ways for PTP IMHO: On the one
> hand you want to have a reliable clock that you can use without knowing
> where it comes from, on the other you might have multiple PTP sources that
> you need to differentiate.
Yes, I agree. In normal use, there will be only one PTP clock in a
system. However, for research purposes, it would be nice to have more
than one.
I've been looking at offering the PTP clock as a posix clock, and it
is not as hard as I first thought. The PTP clock or clocks just have
to be registered as one of the posix_clocks[MAX_CLOCKS] in
posix-timers.c.
My suggestion would be to reserve three clock ids in time.h,
CLOCK_PTP0, CLOCK_PTP1, and CLOCK_PTP2. The first one would be the
same as CLOCK_REALTIME, for SW timestamping, and the other two would
allow two different PTP clocks at the same time, for the research use
case.
Using the clock id will bring another advantage, since it will then be
possible for user space to specify the desired timestamp source for
SO_TIMESTAMPING.
Richard
^ permalink raw reply
* Re: [PATCH NEXTv3 0/3]qlcnic: enhancement and fixes
From: David Miller @ 2010-08-17 11:00 UTC (permalink / raw)
To: amit.salecha; +Cc: netdev, ameen.rahman
In-Reply-To: <1282041265-32591-1-git-send-email-amit.salecha@qlogic.com>
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
Date: Tue, 17 Aug 2010 03:34:18 -0700
>
> I have fixed link status message by using netdev_info().
>
> After updating net-next, same patches applied cleanly. Last commit I see
> on qlcnic driver is "e88db3bd46801a9c2cd0ac5e46122d47c285faec".
>
> Sending series of v3 patches, apply it on net-next.
All applied, thank you.
^ permalink raw reply
* Re: BUG: IPv6 stops working after a while, needs ip ne del command to reset
From: Thomas Habets @ 2010-08-17 11:08 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Thomas Habets, linux-kernel, netdev
In-Reply-To: <1282024802.2487.687.camel@edumazet-laptop>
Aha! New development:
The Cisco router can't discover the address of the Linux box because Linux
doesn't seem to be listening to ff02::1 (all-nodes).
-----------
cisco#ping ff02::1
Output Interface: GigabitEthernet1/2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to FF02::1, timeout is 2 seconds:
Packet sent with a source address of
FE80::222:55FF:FE17:4B80%GigabitEthernet1/2
Request 0 timed out
Request 1 timed out
Request 2 timed out
Request 3 timed out
Request 4 timed out
Success rate is 0 percent (0/5)
0 multicast replies and 0 errors.
------------
If i set promisc mode on the interface (tcpdump without -p or "ip link set
promisc on eth0") it starts working (both normal ping and the above ping
from the Cisco to ff02::1). It continues working until I guess the
neighbor table on the cisco times out (leaving it overnight seems to
be enough idle time) or I manually do a "clear ipv6 neig".
So great news! I can reproduce it at will with no waiting time! Right
after rebooting the Linux box I run "clear ipv6 neighbors" and Linux can
no longer ping the router. Tested reproducing it immediately after reboot.
The Linux box itself can ping ff02::1%eth0 with no problem, and gets
replies from the fe80:: link-local of itself and the Cisco router.
So could this be that for some reason the NIC isn't listening
multicast MAC address 33:33:ff:5c:00:02 ?
Is there a way to see the list of addresses that get past the NIC? Or can
this perhaps be filtered after the NIC, but before tcpdump -p?
Since this now looks like a NIC thing, here's some info about eth0:
$ dmesg | grep eth0
[...]
tg3 0000:03:04.0: eth0: Tigon3 [partno(N/A) rev 9003] (PCIX:133MHz:64-bit)
MAC address 00:24:81:a3:44:24
tg3 0000:03:04.0: eth0: attached PHY is 5714 (10/100/1000Base-T Ethernet)
(WireSpeed[1])
tg3 0000:03:04.0: eth0: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[1] TSOcap[1]
tg3 0000:03:04.0: eth0: dma_rwctrl[76148000] dma_mask[40-bit]
[...]
$ sudo lspci -v -s 03:04.0
03:04.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5715
Gigabit Ethernet (rev a3)
Subsystem: Hewlett-Packard Company NC326i PCIe Dual Port Gigabit Server
Adapter
Flags: bus master, 66MHz, medium devsel, latency 64, IRQ 47
Memory at fdff0000 (64-bit, non-prefetchable) [size=64K]
Memory at fdfe0000 (64-bit, non-prefetchable) [size=64K]
Expansion ROM at <ignored> [disabled]
Capabilities: [40] PCI-X non-bridge device
Capabilities: [48] Power Management version 2
Capabilities: [50] Vital Product Data <?>
Capabilities: [58] Message Signalled Interrupts: Mask- 64bit+ Queue=0/3
Enable+
Kernel driver in use: tg3
Kernel modules: tg3
$ sudo ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:24:81:a3:44:24
inet addr:x.x.x.x Bcast:x.x.x.x
Mask:255.255.255.252
inet6 addr: 2a00:800:752:1::5c:2/112 Scope:Global
inet6 addr: fe80::224:81ff:fea3:4424/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:928 errors:0 dropped:0 overruns:0 frame:0
TX packets:834 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:142281 (138.9 KiB) TX bytes:154616 (150.9 KiB)
Interrupt:16
I have doublechecked iptables, ip6tables and arptables, and they are
either not compiled in the kernel or they are empty ACCEPT lists.
I have answered your questions below even if they may no longer be
applicable.
On Tue, 17 Aug 2010, Eric Dumazet wrote:
>> $ ip -6 ne sh
>> 2a00:800:752:1::5c:1 dev eth0 lladdr 00:22:55:17:4b:80 router STALE
>>
>> [try ping6 again, no reply]
>>
>> $ ip -6 ne sh
>> 2a00:800:752:1::5c:1 dev eth0 lladdr 00:22:55:17:4b:80 router DELAY
>>
>> [try ping6 again, no reply]
>>
>> $ ip -6 ne sh
>> 2a00:800:752:1::5c:1 dev eth0 lladdr 00:22:55:17:4b:80 router REACHABLE
>>
> This seems a bit different than previous mail. Apparently discovery now
> works ?
I didn't post the "ip -6 ne sh" immediately after ping attempt last time.
I'm not sure this changed since last time.
But the tcpdump output from last time seems to indicate that ND did work
then, at least in one direction, even if solicitation came from link-local
address and not the global address. The solicitation was answered, after
all (as seen in the tcpdump in in the original mail).
> Could you have a tcpdump on both sides ?
Not easily. The other end is a Cisco and a bit inconvenient to get to. I'm
going there tomorrow night, so I can hook up a cable and do a monitor
port then if needed.
---------
typedef struct me_s {
char name[] = { "Thomas Habets" };
char email[] = { "thomas@habets.pp.se" };
char kernel[] = { "Linux" };
char *pgpKey[] = { "http://www.habets.pp.se/pubkey.txt" };
char pgp[] = { "A8A3 D1DD 4AE0 8467 7FDE 0945 286A E90A AD48 E854" };
char coolcmd[] = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;
^ permalink raw reply
* Re: [PATCH 1/5] ptp: Added a brand new class driver for ptp clocks.
From: Arnd Bergmann @ 2010-08-17 11:36 UTC (permalink / raw)
To: Richard Cochran, john stultz
Cc: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Rodolfo Giometti,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Krzysztof Halasa
In-Reply-To: <20100817105232.GA9079-7KxsofuKt4IfAd9E5cN8NEzG7cXyKsk/@public.gmane.org>
On Tuesday 17 August 2010, Richard Cochran wrote:
> On Tue, Aug 17, 2010 at 09:25:55AM +0000, Arnd Bergmann wrote:
> > Another difference is that we generally use ioctl for devices that can
> > be enumerated, while syscalls are for system services that are not tied to
> > a specific device. This argument works both ways for PTP IMHO: On the one
> > hand you want to have a reliable clock that you can use without knowing
> > where it comes from, on the other you might have multiple PTP sources that
> > you need to differentiate.
>
> Yes, I agree. In normal use, there will be only one PTP clock in a
> system. However, for research purposes, it would be nice to have more
> than one.
>
> I've been looking at offering the PTP clock as a posix clock, and it
> is not as hard as I first thought. The PTP clock or clocks just have
> to be registered as one of the posix_clocks[MAX_CLOCKS] in
> posix-timers.c.
Ok sounds good.
> My suggestion would be to reserve three clock ids in time.h,
> CLOCK_PTP0, CLOCK_PTP1, and CLOCK_PTP2. The first one would be the
> same as CLOCK_REALTIME, for SW timestamping, and the other two would
> allow two different PTP clocks at the same time, for the research use
> case.
I don't think there is a point in making exactly two independent sources
available. The clockid_t space is not really limited, so we could define
an arbitrary range of ids for ptp sources that could be used simultaneously,
as long as we have space more more ids with a fixed number.
Would it be reasonable to assume that on a machine with a large number
of NICs, you'd want a separate ptp source for each of them for timestamping?
Or would you preferably define just one source in such a setup?
I think both could be done with the use of class device attributes in
sysfs for configuration. Maybe you can have one CLOCK_PTP value for one
global PTP source and use sysfs to configure which device that is.
If you also need simultaneous access to the specific clocks, you could
have run-time configured clockid numbers in a sysfs attribute for each
ptp class device.
> Using the clock id will bring another advantage, since it will then be
> possible for user space to specify the desired timestamp source for
> SO_TIMESTAMPING.
God point.
Arnd
^ permalink raw reply
* Re: RPS vs. hard-irq-context netif_rx()
From: Luca Tettamanti @ 2010-08-17 11:52 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1280495027.3710.13.camel@jlt3.sipsolutions.net>
> I got the following on a kvm instance I use for testing:
>
> [ 51.358803] WARNING: at kernel/lockdep.c:2327trace_hardirqs_on_caller+0x167/0x200()
> [ 51.360210] Hardware name: Bochs
> [ 51.360210] Modules linked in:
> [ 51.360210] Pid: 1546, comm: dhclient3 Tainted: G W 2.6.35-rc6-wl+ #588
> [ 51.360210] Call Trace:
> [ 51.360210] <IRQ> [<ffffffff8104e87f>] warn_slowpath_common+0x7f/0xc0
> [ 51.360210] [<ffffffff8104e8da>] warn_slowpath_null+0x1a/0x20
> [ 51.360210] [<ffffffff81087977>] trace_hardirqs_on_caller+0x167/0x200
> [ 51.360210] [<ffffffff81087a1d>] trace_hardirqs_on+0xd/0x10
> [ 51.360210] [<ffffffff81056ade>] local_bh_enable+0x9e/0x130
> [ 51.360210] [<ffffffff8139fa82>] netif_rx+0xc2/0x250
> [ 51.360210] [<ffffffff813146d7>] ei_receive+0x1b7/0x2c0
> [ 51.360210] [<ffffffff81314ca2>] __ei_interrupt+0x282/0x360
> [ 51.360210] [<ffffffff81314dce>] ei_interrupt+0xe/0x10
> [ 51.360210] [<ffffffff810abe85>] handle_IRQ_event+0x85/0x300
> [ 51.360210] [<ffffffff810aead5>] handle_level_irq+0x95/0x120
> [ 51.360210] [<ffffffff81005a12>] handle_irq+0x22/0x30
> [ 51.360210] [<ffffffff814394b3>] do_IRQ+0x73/0xf0
[...]
>So .. where's the bug? I'd point to CONFIG_RPS since it's newest.
Hello,
I just hit the same warning, with 2.6.36-rc1:
[ 228.001459] WARNING: at /home/kronos/src/linux-2.6.git/kernel/softirq.c:143 local_bh_enable+0x3c/0x9a()
[ 228.004096] Hardware name: F3Sa
[ 228.004175] Modules linked in: [...]
[ 228.015974] Pid: 2818, comm: irqbalance Not tainted 2.6.36-rc1 #274
[ 228.015974] Call Trace:
[ 228.015974] <IRQ> [<ffffffff81034b32>] warn_slowpath_common+0x80/0x98
[ 228.015974] [<ffffffff81034b5f>] warn_slowpath_null+0x15/0x17
[ 228.015974] [<ffffffff8103a009>] local_bh_enable+0x3c/0x9a
[ 228.015974] [<ffffffff8120dc16>] netif_rx+0x75/0x145
[ 228.015974] [<ffffffff8115162f>] ? unmap_single+0x4a/0x52
[ 228.015974] [<ffffffff811e7fcd>] atl1_intr+0x96c/0xa35
[ 228.015974] [<ffffffff8104edf4>] ? hrtimer_wakeup+0x0/0x21
[ 228.015974] [<ffffffff810707b2>] handle_IRQ_event+0x20/0x9a
[ 228.015974] [<ffffffff810723ba>] handle_edge_irq+0xf5/0x141
[ 228.015974] [<ffffffff81004d53>] handle_irq+0x83/0x8c
[ 228.015974] [<ffffffff81004332>] do_IRQ+0x5e/0xc4
[ 228.015974] [<ffffffff812843d3>] ret_from_intr+0x0/0xa
CONFIG_TREE_RCU=y
CONFIG_RPS=y
I never saw the warning with 2.6.35 and earlier kernels though.
Luca
^ permalink raw reply
* Re: [PATCH] net/sched: add ACT_CSUM action to update packets checksums
From: jamal @ 2010-08-17 12:36 UTC (permalink / raw)
To: Grégoire Baron; +Cc: netdev
In-Reply-To: <20100816230217.GA24125@n7mm.org>
On Tue, 2010-08-17 at 01:02 +0200, Grégoire Baron wrote:
> You're rigth. I will correct that, maybe using a macro which is
> specialised to get the protocol structure ...
> However, this macro could call a 'goto' instruction. Is it really a good
> idea? Tell me. Are you sure a function is appropriate?
Do you even need the goto fail? It seems you could short-circuit and
return 0 (at least thats what the goto seems to do)
But i really dont want to complicate this;
In the minimal i think you can make code like this
====
struct icmphdr *icmph;
+ int hl;
+ int ntkoff;
+
+ ntkoff = skb_network_offset(skb);
+
+ hl = ihl + sizeof(*icmph);
+
+ if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) ||
+ (skb_cloned(skb) &&
+ !skb_clone_writable(skb, hl + ntkoff) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ goto fail;
===
reusable - return 0 if fail else return 1 etc etc
BTW, another comment: icmp and igmp have unused parameter iph
passed to them - probably cut and paste.
cheers,
jamal
^ permalink raw reply
* IPv6 raw socket and recvfrom
From: Paul Rolland @ 2010-08-17 12:31 UTC (permalink / raw)
To: netdev
Hello,
I'd like someone to clarify the behavior I can expect from a RAW IPv6
socket _in Linux_ :
- Raw IPv4 sockets : recvfrom() payload contain all the IP header,
including src ip, dst ip, etc...
- Raw IPv6 sockets : so far, recvfrom returns me only the payload. I've
added the HDRINCL options, but it seems that this is a no-op in
IPv6-land.
I've reviewed RFC 3542, which states that I'm not to expect ip6 header, but
often "there is more than one way to do it", and I'd like to be sure I'm
not missing something obvious
Paul
PS : I'm not subscribed to netdev, so please answer directly...
^ permalink raw reply
* Re: IPv6 raw socket and recvfrom
From: Rémi Denis-Courmont @ 2010-08-17 13:08 UTC (permalink / raw)
To: Paul Rolland; +Cc: netdev
In-Reply-To: <20100817143120.7fad5186@tux.DEF.witbe.net>
On Tue, 17 Aug 2010 14:31:20 +0200, Paul Rolland <rol@as2917.net> wrote:
> I'd like someone to clarify the behavior I can expect from a RAW IPv6
> socket _in Linux_ :
> - Raw IPv4 sockets : recvfrom() payload contain all the IP header,
> including src ip, dst ip, etc...
>
> - Raw IPv6 sockets : so far, recvfrom returns me only the payload. I've
> added the HDRINCL options, but it seems that this is a no-op in
> IPv6-land.
Yes and no. You get the packet size from the return value of recvfrom().
You can also get the source address from the recvfrom() address parameter.
And you can additionally get the hop limit, destination address and type of
service as ancillary data with recvmsg(). Finally, you can have the kernel
verify the checksum field for you (and discard broken packets), and of
course the IP version. In the end, the only unknown field is the flow
information, for which there is no standardized API that I know.
> I've reviewed RFC 3542, which states that I'm not to expect ip6 header,
> but often "there is more than one way to do it", and I'd like to be sure
> I'm not missing something obvious
On Linux, you should use AF_PACKET sockets if you want to receive (or send)
raw packets including the network header. Alternatively, you can use
libpcap (which really is a wrapper around AF_PACKET anyway).
--
Rémi Denis-Courmont
http://www.remlab.net
http://fi.linkedin.com/in/remidenis
^ permalink raw reply
* Re: BUG: IPv6 stops working after a while, needs ip ne del command to reset
From: Eric Dumazet @ 2010-08-17 13:15 UTC (permalink / raw)
To: Thomas Habets; +Cc: linux-kernel, netdev
In-Reply-To: <alpine.DEB.1.10.1008171053230.21857@red.crap.retrofitta.se>
Le mardi 17 août 2010 à 13:08 +0200, Thomas Habets a écrit :
> Aha! New development:
>
> The Cisco router can't discover the address of the Linux box because Linux
> doesn't seem to be listening to ff02::1 (all-nodes).
>
> -----------
> cisco#ping ff02::1
> Output Interface: GigabitEthernet1/2
> Type escape sequence to abort.
> Sending 5, 100-byte ICMP Echos to FF02::1, timeout is 2 seconds:
> Packet sent with a source address of
> FE80::222:55FF:FE17:4B80%GigabitEthernet1/2
>
> Request 0 timed out
> Request 1 timed out
> Request 2 timed out
> Request 3 timed out
> Request 4 timed out
> Success rate is 0 percent (0/5)
> 0 multicast replies and 0 errors.
> ------------
>
> If i set promisc mode on the interface (tcpdump without -p or "ip link set
> promisc on eth0") it starts working (both normal ping and the above ping
> from the Cisco to ff02::1). It continues working until I guess the
> neighbor table on the cisco times out (leaving it overnight seems to
> be enough idle time) or I manually do a "clear ipv6 neig".
>
> So great news! I can reproduce it at will with no waiting time! Right
> after rebooting the Linux box I run "clear ipv6 neighbors" and Linux can
> no longer ping the router. Tested reproducing it immediately after reboot.
>
> The Linux box itself can ping ff02::1%eth0 with no problem, and gets
> replies from the fe80:: link-local of itself and the Cisco router.
>
> So could this be that for some reason the NIC isn't listening
> multicast MAC address 33:33:ff:5c:00:02 ?
>
That would be very surprising, but who knows...
Can you try : "ifconfig eth0 allmulti"
Maybe tg3 driver has a problem building the mulicast table for this 5715
> Is there a way to see the list of addresses that get past the NIC? Or can
> this perhaps be filtered after the NIC, but before tcpdump -p?
>
> Since this now looks like a NIC thing, here's some info about eth0:
>
> $ dmesg | grep eth0
> [...]
> tg3 0000:03:04.0: eth0: Tigon3 [partno(N/A) rev 9003] (PCIX:133MHz:64-bit)
> MAC address 00:24:81:a3:44:24
> tg3 0000:03:04.0: eth0: attached PHY is 5714 (10/100/1000Base-T Ethernet)
> (WireSpeed[1])
> tg3 0000:03:04.0: eth0: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[1] TSOcap[1]
> tg3 0000:03:04.0: eth0: dma_rwctrl[76148000] dma_mask[40-bit]
> [...]
>
> $ sudo lspci -v -s 03:04.0
> 03:04.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5715
> Gigabit Ethernet (rev a3)
> Subsystem: Hewlett-Packard Company NC326i PCIe Dual Port Gigabit Server
> Adapter
> Flags: bus master, 66MHz, medium devsel, latency 64, IRQ 47
> Memory at fdff0000 (64-bit, non-prefetchable) [size=64K]
> Memory at fdfe0000 (64-bit, non-prefetchable) [size=64K]
> Expansion ROM at <ignored> [disabled]
> Capabilities: [40] PCI-X non-bridge device
> Capabilities: [48] Power Management version 2
> Capabilities: [50] Vital Product Data <?>
> Capabilities: [58] Message Signalled Interrupts: Mask- 64bit+ Queue=0/3
> Enable+
> Kernel driver in use: tg3
> Kernel modules: tg3
>
> $ sudo ifconfig eth0
> eth0 Link encap:Ethernet HWaddr 00:24:81:a3:44:24
> inet addr:x.x.x.x Bcast:x.x.x.x
> Mask:255.255.255.252
> inet6 addr: 2a00:800:752:1::5c:2/112 Scope:Global
> inet6 addr: fe80::224:81ff:fea3:4424/64 Scope:Link
> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> RX packets:928 errors:0 dropped:0 overruns:0 frame:0
> TX packets:834 errors:0 dropped:0 overruns:0 carrier:0
> collisions:0 txqueuelen:1000
> RX bytes:142281 (138.9 KiB) TX bytes:154616 (150.9 KiB)
> Interrupt:16
>
> I have doublechecked iptables, ip6tables and arptables, and they are
> either not compiled in the kernel or they are empty ACCEPT lists.
If you let a "tcpdump" running with -p option, do you receive the packet
sent to ethernet dest 33:33:ff:5c:00:02 ?
If you can see it with tcpdump, then NIC gave the frame to us.
^ permalink raw reply
* Re: BUG: IPv6 stops working after a while, needs ip ne del command to reset
From: Thomas Habets @ 2010-08-17 14:09 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Thomas Habets, linux-kernel, netdev
In-Reply-To: <1282050920.2448.47.camel@edumazet-laptop>
On Tue, 17 Aug 2010, Eric Dumazet wrote:
> Can you try : "ifconfig eth0 allmulti"
That didn't help. "ifconfig eth0" and "ip l" shows that allmulti is now
set, but no other difference. Can't ping router, and router gets no answer
when pinging ff02::1. No message in dmesg saying allmulti isn't supported
or anything like that either.
> If you let a "tcpdump" running with -p option, do you receive the packet
> sent to ethernet dest 33:33:ff:5c:00:02 ?
No. Commented tcpdump output below.
> If you can see it with tcpdump, then NIC gave the frame to us.
Seems to be invisible unless I or tcpdump set promisc mode. But when
promisc mode is set I can immediately see the 33:33:ff:5c:00:02 packet
(ND solicitation) and I see that Linux is answering it.
Here's a tcpdump from the Linux host. It's slightliy trimmed to fit in
an email, but the full dump is at http://www.habets.pp.se/tmp/ipv6.pcap
$ sudo tcpdump -pnli eth0 -s0 -w ipv6.pcap ip6
[...]
$ tcpdump -nlr ipv6.pcap
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
[ here I run "clear ipv6 neighbors" on the Cisco router ]
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
[ ... more repeated echo requests, no reply ... ]
[ here i run "ip l set promisc on eth0" ]
2a00:800:752:1::5c:1 > ff02::1:ff5c:2: ICMP6, neighbor solicitation, who
has 2a00:800:752:1::5c:2
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6,neighbor advertisement,
tgt is 2a00:800:752:1::5c:2
2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
[ here I run "clear ipv6 neigbors" again ]
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
---------
typedef struct me_s {
char name[] = { "Thomas Habets" };
char email[] = { "thomas@habets.pp.se" };
char kernel[] = { "Linux" };
char *pgpKey[] = { "http://www.habets.pp.se/pubkey.txt" };
char pgp[] = { "A8A3 D1DD 4AE0 8467 7FDE 0945 286A E90A AD48 E854" };
char coolcmd[] = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;
^ permalink raw reply
* Re: BUG: IPv6 stops working after a while, needs ip ne del command to reset
From: Eric Dumazet @ 2010-08-17 14:34 UTC (permalink / raw)
To: Thomas Habets; +Cc: linux-kernel, netdev, Matt Carlson, Michael Chan
In-Reply-To: <alpine.DEB.1.10.1008171547090.21857@red.crap.retrofitta.se>
Le mardi 17 août 2010 à 16:09 +0200, Thomas Habets a écrit :
> On Tue, 17 Aug 2010, Eric Dumazet wrote:
> > Can you try : "ifconfig eth0 allmulti"
>
> That didn't help. "ifconfig eth0" and "ip l" shows that allmulti is now
> set, but no other difference. Can't ping router, and router gets no answer
> when pinging ff02::1. No message in dmesg saying allmulti isn't supported
> or anything like that either.
>
> > If you let a "tcpdump" running with -p option, do you receive the packet
> > sent to ethernet dest 33:33:ff:5c:00:02 ?
>
> No. Commented tcpdump output below.
>
> > If you can see it with tcpdump, then NIC gave the frame to us.
>
> Seems to be invisible unless I or tcpdump set promisc mode. But when
> promisc mode is set I can immediately see the 33:33:ff:5c:00:02 packet
> (ND solicitation) and I see that Linux is answering it.
>
> Here's a tcpdump from the Linux host. It's slightliy trimmed to fit in
> an email, but the full dump is at http://www.habets.pp.se/tmp/ipv6.pcap
>
> $ sudo tcpdump -pnli eth0 -s0 -w ipv6.pcap ip6
> [...]
>
> $ tcpdump -nlr ipv6.pcap
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
>
> [ here I run "clear ipv6 neighbors" on the Cisco router ]
>
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> [ ... more repeated echo requests, no reply ... ]
>
> [ here i run "ip l set promisc on eth0" ]
>
> 2a00:800:752:1::5c:1 > ff02::1:ff5c:2: ICMP6, neighbor solicitation, who
> has 2a00:800:752:1::5c:2
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6,neighbor advertisement,
> tgt is 2a00:800:752:1::5c:2
> 2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:1 > 2a00:800:752:1::5c:2: ICMP6, echo reply
>
> [ here I run "clear ipv6 neigbors" again ]
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
> 2a00:800:752:1::5c:2 > 2a00:800:752:1::5c:1: ICMP6, echo request
I suspect its time to ask broadcom guys some help :)
I have same adapter here (Hewlett-Packard Company NC326m PCIe Dual Port
Adapter) and could not reproduce the problem.
Try following patch to check tg3 receives correct multicast list (its OK
for me, seen on dmesg output)
[17162.120238] add mc_addr(ha->addr=33:33:00:00:00:01)
[17162.120270] add mc_addr(ha->addr=01:00:5e:00:00:01)
[17162.120298] add mc_addr(ha->addr=33:33:ff:87:96:ce)
[17162.120326] add mc_addr(ha->addr=33:33:ff:5c:00:02)
[17162.120355] filters=80000001 00000000 00400000 40000000
But if problem remains even with "ifconfig eth0 allmulti" I suspect a
NIC firmware problem. (allmulti set to 1 all the 128 bits of filters)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bc3af78..34510f5 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -9317,12 +9317,14 @@ static void __tg3_set_rx_mode(struct net_device *dev)
u32 crc;
netdev_for_each_mc_addr(ha, dev) {
+ pr_err("add mc_addr(ha->addr=%pM)\n", ha->addr);
crc = calc_crc(ha->addr, ETH_ALEN);
bit = ~crc & 0x7f;
regidx = (bit & 0x60) >> 5;
bit &= 0x1f;
mc_filter[regidx] |= (1 << bit);
}
+ pr_err("filters=%08X %08x %08x %08x\n", mc_filter[0], mc_filter[1], mc_filter[2], mc_filter[3]);
tw32(MAC_HASH_REG_0, mc_filter[0]);
tw32(MAC_HASH_REG_1, mc_filter[1]);
^ permalink raw reply related
* Re: [PATCHv3 NEXT 7/7] qlcnic: turn off lro when rxcsum is disabled.
From: Joe Perches @ 2010-08-17 14:48 UTC (permalink / raw)
To: Amit Kumar Salecha; +Cc: davem, netdev, ameen.rahman, Sucheta Chakraborty
In-Reply-To: <1282041265-32591-8-git-send-email-amit.salecha@qlogic.com>
On Tue, 2010-08-17 at 03:34 -0700, Amit Kumar Salecha wrote:
> From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Thanks all, 2 minor comments below.
> --- a/drivers/net/qlcnic/qlcnic_ethtool.c
> +++ b/drivers/net/qlcnic/qlcnic_ethtool.c
> @@ -818,7 +818,21 @@ static u32 qlcnic_get_rx_csum(struct net_device *dev)
> static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
[]
> dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n");
I think netdev_<level> should be used when a
struct net_device * is available.
netdev_info(dev, "disabling LRO as rx_csum is off\n");
> @@ -1001,6 +1015,15 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
[]
> + if (!adapter->rx_csum) {
> + dev_info(&adapter->pdev->dev, "rx csum is off, "
> + "cannot toggle lro\n");
netdev_info(netdev, "rx csum is off, cannot toggle LRO\n");
and please use consistent acronym case.
^ permalink raw reply
* Re: RPS vs. hard-irq-context netif_rx()
From: Eric Dumazet @ 2010-08-17 14:54 UTC (permalink / raw)
To: Luca Tettamanti; +Cc: netdev, Johannes Berg
In-Reply-To: <20100817115230.GA6510@nb-core2.darkstar.lan>
Le mardi 17 août 2010 à 13:52 +0200, Luca Tettamanti a écrit :
> > I got the following on a kvm instance I use for testing:
> >
> > [ 51.358803] WARNING: at kernel/lockdep.c:2327trace_hardirqs_on_caller+0x167/0x200()
> > [ 51.360210] Hardware name: Bochs
> > [ 51.360210] Modules linked in:
> > [ 51.360210] Pid: 1546, comm: dhclient3 Tainted: G W 2.6.35-rc6-wl+ #588
> > [ 51.360210] Call Trace:
> > [ 51.360210] <IRQ> [<ffffffff8104e87f>] warn_slowpath_common+0x7f/0xc0
> > [ 51.360210] [<ffffffff8104e8da>] warn_slowpath_null+0x1a/0x20
> > [ 51.360210] [<ffffffff81087977>] trace_hardirqs_on_caller+0x167/0x200
> > [ 51.360210] [<ffffffff81087a1d>] trace_hardirqs_on+0xd/0x10
> > [ 51.360210] [<ffffffff81056ade>] local_bh_enable+0x9e/0x130
> > [ 51.360210] [<ffffffff8139fa82>] netif_rx+0xc2/0x250
> > [ 51.360210] [<ffffffff813146d7>] ei_receive+0x1b7/0x2c0
> > [ 51.360210] [<ffffffff81314ca2>] __ei_interrupt+0x282/0x360
> > [ 51.360210] [<ffffffff81314dce>] ei_interrupt+0xe/0x10
> > [ 51.360210] [<ffffffff810abe85>] handle_IRQ_event+0x85/0x300
> > [ 51.360210] [<ffffffff810aead5>] handle_level_irq+0x95/0x120
> > [ 51.360210] [<ffffffff81005a12>] handle_irq+0x22/0x30
> > [ 51.360210] [<ffffffff814394b3>] do_IRQ+0x73/0xf0
> [...]
> >So .. where's the bug? I'd point to CONFIG_RPS since it's newest.
>
> Hello,
> I just hit the same warning, with 2.6.36-rc1:
>
> [ 228.001459] WARNING: at /home/kronos/src/linux-2.6.git/kernel/softirq.c:143 local_bh_enable+0x3c/0x9a()
> [ 228.004096] Hardware name: F3Sa
> [ 228.004175] Modules linked in: [...]
> [ 228.015974] Pid: 2818, comm: irqbalance Not tainted 2.6.36-rc1 #274
> [ 228.015974] Call Trace:
> [ 228.015974] <IRQ> [<ffffffff81034b32>] warn_slowpath_common+0x80/0x98
> [ 228.015974] [<ffffffff81034b5f>] warn_slowpath_null+0x15/0x17
> [ 228.015974] [<ffffffff8103a009>] local_bh_enable+0x3c/0x9a
> [ 228.015974] [<ffffffff8120dc16>] netif_rx+0x75/0x145
> [ 228.015974] [<ffffffff8115162f>] ? unmap_single+0x4a/0x52
> [ 228.015974] [<ffffffff811e7fcd>] atl1_intr+0x96c/0xa35
> [ 228.015974] [<ffffffff8104edf4>] ? hrtimer_wakeup+0x0/0x21
> [ 228.015974] [<ffffffff810707b2>] handle_IRQ_event+0x20/0x9a
> [ 228.015974] [<ffffffff810723ba>] handle_edge_irq+0xf5/0x141
> [ 228.015974] [<ffffffff81004d53>] handle_irq+0x83/0x8c
> [ 228.015974] [<ffffffff81004332>] do_IRQ+0x5e/0xc4
> [ 228.015974] [<ffffffff812843d3>] ret_from_intr+0x0/0xa
>
> CONFIG_TREE_RCU=y
> CONFIG_RPS=y
>
> I never saw the warning with 2.6.35 and earlier kernels though.
This is a known problem, related to netpoll
http://www.kerneltrap.com/mailarchive/linux-netdev/2010/8/10/6282780
^ permalink raw reply
* [PATCH] ehea: Fix synchronization between HW and SW send queue
From: Andre Detsch @ 2010-08-17 15:49 UTC (permalink / raw)
To: davem; +Cc: netdev, themann, brenohl
ehea: Fix synchronization between HW and SW send queue
When memory is added to / removed from a partition via the Memory DLPAR
mechanism, the eHEA driver has to do a couple of things to reflect the
memory change in its own IO address translation tables. This involves
stopping and restarting the HW queues.
During this operation, it is possible that HW and SW pointer into these
queues get out of sync. This results in a situation where packets that
are attached to a send queue are not transmitted immediately, but
delayed until further X packets have been put on the queue.
This patch detects such loss of synchronization, and resets the ehea
port when needed.
Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>
Signed-off-by: Andre Detsch <adetsch@br.ibm.com>
Index: net-next-2.6/drivers/net/ehea/ehea.h
===================================================================
--- net-next-2.6.orig/drivers/net/ehea/ehea.h 2010-08-17 11:34:26.090036724 -0400
+++ net-next-2.6/drivers/net/ehea/ehea.h 2010-08-17 11:36:33.800036535 -0400
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0105"
+#define DRV_VERSION "EHEA_0106"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
@@ -400,6 +400,7 @@
u32 poll_counter;
struct net_lro_mgr lro_mgr;
struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
+ int sq_restart_flag;
};
Index: net-next-2.6/drivers/net/ehea/ehea_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/ehea/ehea_main.c 2010-08-17 11:34:26.090036724 -0400
+++ net-next-2.6/drivers/net/ehea/ehea_main.c 2010-08-17 11:34:53.710036711 -0400
@@ -776,6 +776,53 @@
return processed;
}
+#define SWQE_RESTART_CHECK 0xdeadbeaff00d0000ull
+
+static void reset_sq_restart_flag(struct ehea_port *port)
+{
+ int i;
+
+ for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ struct ehea_port_res *pr = &port->port_res[i];
+ pr->sq_restart_flag = 0;
+ }
+}
+
+static void check_sqs(struct ehea_port *port)
+{
+ struct ehea_swqe *swqe;
+ int swqe_index;
+ int i, k;
+
+ for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ struct ehea_port_res *pr = &port->port_res[i];
+ k = 0;
+ swqe = ehea_get_swqe(pr->qp, &swqe_index);
+ memset(swqe, 0, SWQE_HEADER_SIZE);
+ atomic_dec(&pr->swqe_avail);
+
+ swqe->tx_control |= EHEA_SWQE_PURGE;
+ swqe->wr_id = SWQE_RESTART_CHECK;
+ swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
+ swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT;
+ swqe->immediate_data_length = 80;
+
+ ehea_post_swqe(pr->qp, swqe);
+
+ while (pr->sq_restart_flag == 0) {
+ msleep(5);
+ if (++k == 100) {
+ ehea_error("HW/SW queues out of sync");
+ ehea_schedule_port_reset(pr->port);
+ return;
+ }
+ }
+ }
+
+ return;
+}
+
+
static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
{
struct sk_buff *skb;
@@ -793,6 +840,13 @@
cqe_counter++;
rmb();
+
+ if (cqe->wr_id == SWQE_RESTART_CHECK) {
+ pr->sq_restart_flag = 1;
+ swqe_av++;
+ break;
+ }
+
if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
ehea_error("Bad send completion status=0x%04X",
cqe->status);
@@ -2675,8 +2729,10 @@
int k = 0;
while (atomic_read(&pr->swqe_avail) < swqe_max) {
msleep(5);
- if (++k == 20)
+ if (++k == 20) {
+ ehea_error("WARNING: sq not flushed completely");
break;
+ }
}
}
}
@@ -2917,6 +2973,7 @@
port_napi_disable(port);
mutex_unlock(&port->port_lock);
}
+ reset_sq_restart_flag(port);
}
/* Unregister old memory region */
@@ -2951,6 +3008,7 @@
mutex_lock(&port->port_lock);
port_napi_enable(port);
ret = ehea_restart_qps(dev);
+ check_sqs(port);
if (!ret)
netif_wake_queue(dev);
mutex_unlock(&port->port_lock);
^ permalink raw reply
* Re: BUG: IPv6 stops working after a while, needs ip ne del command to reset
From: Thomas Habets @ 2010-08-17 15:58 UTC (permalink / raw)
To: Eric Dumazet
Cc: Thomas Habets, linux-kernel, netdev, Matt Carlson, Michael Chan
In-Reply-To: <1282055659.2448.58.camel@edumazet-laptop>
On Tue, 17 Aug 2010, Eric Dumazet wrote:
> Try following patch to check tg3 receives correct multicast list (its OK
> for me, seen on dmesg output)
>
> [17162.120238] add mc_addr(ha->addr=33:33:00:00:00:01)
> [17162.120270] add mc_addr(ha->addr=01:00:5e:00:00:01)
> [17162.120298] add mc_addr(ha->addr=33:33:ff:87:96:ce)
> [17162.120326] add mc_addr(ha->addr=33:33:ff:5c:00:02)
> [17162.120355] filters=80000001 00000000 00400000 40000000
Right after boot:
$ dmesg | egrep 'eth0|^add mc|^filters='
tg3 0000:03:04.0: eth0: Tigon3 [partno(N/A) rev 9003] (PCIX:133MHz:64-bit)
MAC address 00:24:81:a3:44:24
tg3 0000:03:04.0: eth0: attached PHY is 5714 (10/100/1000Base-T Ethernet)
(WireSpeed[1])
tg3 0000:03:04.0: eth0: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[1] TSOcap[1]
tg3 0000:03:04.0: eth0: dma_rwctrl[76148000] dma_mask[40-bit]
add mc_addr(ha->addr=33:33:00:00:00:01)
filters=80000000 00000000 00000000 00000000
add mc_addr(ha->addr=33:33:00:00:00:01)
filters=80000000 00000000 00000000 00000000
add mc_addr(ha->addr=33:33:00:00:00:01)
filters=80000000 00000000 00000000 00000000
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
filters=80000000 00000000 00000000 40000000
ADDRCONF(NETDEV_UP): eth0: link is not ready
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
filters=80000000 00000000 00000000 40000000
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
filters=80000000 00000000 00000000 40000000
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
add mc_addr(ha->addr=33:33:ff:5c:00:02)
filters=80000001 00000000 00000000 40000000
tg3 0000:03:04.0: eth0: Link is up at 1000 Mbps, full duplex
tg3 0000:03:04.0: eth0: Flow control is off for TX and off for RX
ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
add mc_addr(ha->addr=33:33:ff:5c:00:02)
add mc_addr(ha->addr=33:33:ff:a3:44:24)
filters=80020001 00000000 00000000 40000000
eth0: no IPv6 routers present
[ ifconfig eth0 allmulti
(ip l and ifconfig say ALLMULTI is on)
]
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
add mc_addr(ha->addr=33:33:ff:5c:00:02)
add mc_addr(ha->addr=33:33:ff:a3:44:24)
filters=80020001 00000000 00000000 40000000
[
$ sudo ifconfig eth0 -allmulti
Warning: Interface eth0 still in ALLMULTI mode.
(ip l and ifconfig say ALLMULTI is now off)
]
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
add mc_addr(ha->addr=33:33:ff:5c:00:02)
add mc_addr(ha->addr=33:33:ff:a3:44:24)
filters=80020001 00000000 00000000 40000000
[ ifconfig eth0 allmulti
(same effect)
]
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
add mc_addr(ha->addr=33:33:ff:5c:00:02)
add mc_addr(ha->addr=33:33:ff:a3:44:24)
filters=80020001 00000000 00000000 40000000
[
$ sudo ifconfig eth0 -allmulti
Warning: Interface eth0 still in ALLMULTI mode.
(same effect)
]
add mc_addr(ha->addr=33:33:00:00:00:01)
add mc_addr(ha->addr=01:00:5e:00:00:01)
add mc_addr(ha->addr=33:33:ff:5c:00:02)
add mc_addr(ha->addr=33:33:ff:a3:44:24)
filters=80020001 00000000 00000000 40000000
> But if problem remains even with "ifconfig eth0 allmulti" I suspect a
> NIC firmware problem. (allmulti set to 1 all the 128 bits of filters)
If you expected more bits set in "filters" with allmulti than without it,
that doesn't seem to be the case.
Applied your patch to v2.6.35.
---------
typedef struct me_s {
char name[] = { "Thomas Habets" };
char email[] = { "thomas@habets.pp.se" };
char kernel[] = { "Linux" };
char *pgpKey[] = { "http://www.habets.pp.se/pubkey.txt" };
char pgp[] = { "A8A3 D1DD 4AE0 8467 7FDE 0945 286A E90A AD48 E854" };
char coolcmd[] = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;
^ permalink raw reply
* [PATCH] greth: Use return value of register_netdev
From: Tobias Klauser @ 2010-08-17 16:11 UTC (permalink / raw)
To: David S. Miller, Kristoffer Glembo, netdev; +Cc: kernel-janitors
Use the return value provided by register_netdev on error instead of
hard setting it to -ENOMEM.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
drivers/net/greth.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index f15c64f..fbeaf70 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -1547,10 +1547,10 @@ static int __devinit greth_of_probe(struct platform_device *ofdev, const struct
dev->netdev_ops = &greth_netdev_ops;
dev->ethtool_ops = &greth_ethtool_ops;
- if (register_netdev(dev)) {
+ err = register_netdev(dev);
+ if (err) {
if (netif_msg_probe(greth))
dev_err(greth->dev, "netdevice registration failed.\n");
- err = -ENOMEM;
goto error5;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH] greth: Use return value of register_netdev
From: Tobias Klauser @ 2010-08-17 16:12 UTC (permalink / raw)
To: David S. Miller, netdev; +Cc: kernel-janitors
Use the return value provided by register_netdev on error instead of
hard setting it to -ENOMEM.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
drivers/net/greth.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index f15c64f..fbeaf70 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -1547,10 +1547,10 @@ static int __devinit greth_of_probe(struct platform_device *ofdev, const struct
dev->netdev_ops = &greth_netdev_ops;
dev->ethtool_ops = &greth_ethtool_ops;
- if (register_netdev(dev)) {
+ err = register_netdev(dev);
+ if (err) {
if (netif_msg_probe(greth))
dev_err(greth->dev, "netdevice registration failed.\n");
- err = -ENOMEM;
goto error5;
}
--
1.7.0.4
^ 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