* [PATCH 04/14] mlx4_en: performing CLOSE_PORT at the end of tear-down process
From: Yevgeny Petrilin @ 2010-08-24 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
All port's resources should be closed before we give the
CLOSE_PORT command to the firmware.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_netdev.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index c4ab0fc..068e572 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -704,9 +704,8 @@ void mlx4_en_stop_port(struct net_device *dev)
netif_tx_stop_all_queues(dev);
netif_tx_unlock_bh(dev);
- /* close port*/
+ /* Set port as not active */
priv->port_up = false;
- mlx4_CLOSE_PORT(mdev->dev, priv->port);
/* Unregister Mac address for the port */
mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
@@ -731,6 +730,9 @@ void mlx4_en_stop_port(struct net_device *dev)
msleep(1);
mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]);
}
+
+ /* close port*/
+ mlx4_CLOSE_PORT(mdev->dev, priv->port);
}
static void mlx4_en_restart(struct work_struct *work)
--
1.6.1.3
^ permalink raw reply related
* [PATCH 05/14] mlx4_en: Fixed MAX_TX_RINGS definition
From: Yevgeny Petrilin @ 2010-08-24 13:45 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
Defined as sum of default number of TX rings and number of
rings used for priority flow control mode.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/mlx4_en.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 4492109..f8f3ad3 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -61,7 +61,6 @@
#define MLX4_EN_PAGE_SHIFT 12
#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_TX_RINGS 16
#define MAX_RX_RINGS 16
#define TXBB_SIZE 64
#define HEADROOM (2048 / TXBB_SIZE + 1)
@@ -107,6 +106,7 @@ enum {
#define MLX4_EN_SMALL_PKT_SIZE 64
#define MLX4_EN_NUM_TX_RINGS 8
#define MLX4_EN_NUM_PPP_RINGS 8
+#define MAX_TX_RINGS (MLX4_EN_NUM_TX_RINGS + MLX4_EN_NUM_PPP_RINGS)
#define MLX4_EN_DEF_TX_RING_SIZE 512
#define MLX4_EN_DEF_RX_RING_SIZE 1024
--
1.6.1.3
^ permalink raw reply related
* [PATCH 06/14] mlx4_en: Reporting link state with KERN_INFO
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_netdev.c | 4 ++--
drivers/net/mlx4/mlx4_en.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 068e572..92fd1ff 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -528,10 +528,10 @@ static void mlx4_en_linkstate(struct work_struct *work)
* report to system log */
if (priv->last_link_state != linkstate) {
if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
- en_dbg(LINK, priv, "Link Down\n");
+ en_info(priv, "Link Down\n");
netif_carrier_off(priv->dev);
} else {
- en_dbg(LINK, priv, "Link Up\n");
+ en_info(priv, "Link Up\n");
netif_carrier_on(priv->dev);
}
}
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index f8f3ad3..747f04a 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -555,6 +555,8 @@ do { \
en_print(KERN_WARNING, priv, format, ##arg)
#define en_err(priv, format, arg...) \
en_print(KERN_ERR, priv, format, ##arg)
+#define en_info(priv, format, arg...) \
+ en_print(KERN_INFO, priv, format, ## arg)
#define mlx4_err(mdev, format, arg...) \
pr_err("%s %s: " format, DRV_NAME, \
--
1.6.1.3
^ permalink raw reply related
* [PATCH 07/14] mlx4_en: Validate port up prior to transmitting
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
We might try to use resources which were not activated.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_tx.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 580968f..3deabd1 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -612,6 +612,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
int lso_header_size;
void *fragptr;
+ if (!priv->port_up)
+ goto tx_drop;
+
real_size = get_real_size(skb, dev, &lso_header_size);
if (unlikely(!real_size))
goto tx_drop;
--
1.6.1.3
^ permalink raw reply related
* [PATCH 08/14] mlx4_en: Added self diagnostics test implementation
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
The selftest includes 5 features:
1. Interrupt test: Executing commands and receiving command completion
on all our interrupt vectors.
2. Link test: Verifying we are connected to valid link partner.
3. Speed test: Check that we negotiated link speed correctly.
4. Registers test: Activate HW health check command.
5. Loopback test: Send a packet on loopback interface and catch it on RX side.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/Makefile | 2 +-
drivers/net/mlx4/en_ethtool.c | 79 ++++++++++++------
drivers/net/mlx4/en_netdev.c | 2 +-
drivers/net/mlx4/en_port.c | 32 +++++++
drivers/net/mlx4/en_port.h | 14 +++
drivers/net/mlx4/en_rx.c | 20 +++++
drivers/net/mlx4/en_selftest.c | 179 ++++++++++++++++++++++++++++++++++++++++
drivers/net/mlx4/en_tx.c | 16 ++++
drivers/net/mlx4/eq.c | 44 ++++++++++
drivers/net/mlx4/fw.c | 3 +
drivers/net/mlx4/fw.h | 1 +
drivers/net/mlx4/main.c | 1 +
drivers/net/mlx4/mlx4_en.h | 19 ++++
include/linux/mlx4/cmd.h | 1 +
include/linux/mlx4/device.h | 2 +
15 files changed, 388 insertions(+), 27 deletions(-)
create mode 100644 drivers/net/mlx4/en_selftest.c
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index 1fd068e..d1aa45a 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -6,4 +6,4 @@ mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
obj-$(CONFIG_MLX4_EN) += mlx4_en.o
mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
- en_resources.o en_netdev.o
+ en_resources.o en_netdev.o en_selftest.o
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index b275238..49a7003 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -125,6 +125,14 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
#define NUM_MAIN_STATS 21
#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
+static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
+ "Interupt Test",
+ "Link Test",
+ "Speed Test",
+ "Register Test",
+ "Loopback Test",
+};
+
static u32 mlx4_en_get_msglevel(struct net_device *dev)
{
return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
@@ -146,10 +154,15 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- if (sset != ETH_SS_STATS)
+ switch (sset) {
+ case ETH_SS_STATS:
+ return NUM_ALL_STATS +
+ (priv->tx_ring_num + priv->rx_ring_num) * 2;
+ case ETH_SS_TEST:
+ return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2;
+ default:
return -EOPNOTSUPP;
-
- return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2;
+ }
}
static void mlx4_en_get_ethtool_stats(struct net_device *dev,
@@ -181,6 +194,12 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
}
+static void mlx4_en_self_test(struct net_device *dev,
+ struct ethtool_test *etest, u64 *buf)
+{
+ mlx4_en_ex_selftest(dev, &etest->flags, buf);
+}
+
static void mlx4_en_get_strings(struct net_device *dev,
uint32_t stringset, uint8_t *data)
{
@@ -188,30 +207,39 @@ static void mlx4_en_get_strings(struct net_device *dev,
int index = 0;
int i;
- if (stringset != ETH_SS_STATS)
- return;
-
- /* Add main counters */
- for (i = 0; i < NUM_MAIN_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
- for (i = 0; i < NUM_PORT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
+ switch (stringset) {
+ case ETH_SS_TEST:
+ for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
+ strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
+ if (priv->mdev->dev->caps.loopback_support)
+ for (; i < MLX4_EN_NUM_SELF_TEST; i++)
+ strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
+ break;
+
+ case ETH_SS_STATS:
+ /* Add main counters */
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
+ for (i = 0; i< NUM_PORT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[i + NUM_MAIN_STATS]);
- for (i = 0; i < priv->tx_ring_num; i++) {
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "tx%d_packets", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "tx%d_bytes", i);
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_packets", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_bytes", i);
- }
- for (i = 0; i < NUM_PKT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "tx%d_packets", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "tx%d_bytes", i);
+ }
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_packets", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_bytes", i);
+ }
+ for (i = 0; i< NUM_PKT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
+ break;
+ }
}
static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -441,6 +469,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_strings = mlx4_en_get_strings,
.get_sset_count = mlx4_en_get_sset_count,
.get_ethtool_stats = mlx4_en_get_ethtool_stats,
+ .self_test = mlx4_en_self_test,
.get_wol = mlx4_en_get_wol,
.get_msglevel = mlx4_en_get_msglevel,
.set_msglevel = mlx4_en_set_msglevel,
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 92fd1ff..7a1e697 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -109,7 +109,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
mutex_unlock(&mdev->state_lock);
}
-static u64 mlx4_en_mac_to_u64(u8 *addr)
+u64 mlx4_en_mac_to_u64(u8 *addr)
{
u64 mac = 0;
int i;
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index a29abe8..aa3ef2a 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -142,6 +142,38 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
return err;
}
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
+{
+ struct mlx4_en_query_port_context *qport_context;
+ struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
+ struct mlx4_en_port_state *state = &priv->port_state;
+ struct mlx4_cmd_mailbox *mailbox;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ memset(mailbox->buf, 0, sizeof(*qport_context));
+ err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
+ MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B);
+ if (err)
+ goto out;
+ qport_context = mailbox->buf;
+
+ /* This command is always accessed from Ethtool context
+ * already synchronized, no need in locking */
+ state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
+ if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) ==
+ MLX4_EN_1G_SPEED)
+ state->link_speed = 1000;
+ else
+ state->link_speed = 10000;
+ state->transciver = qport_context->transceiver;
+
+out:
+ mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+ return err;
+}
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
{
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index e6477f1..f6511aa 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -84,6 +84,20 @@ enum {
MLX4_MCAST_ENABLE = 2,
};
+struct mlx4_en_query_port_context {
+ u8 link_up;
+#define MLX4_EN_LINK_UP_MASK 0x80
+ u8 reserved;
+ __be16 mtu;
+ u8 reserved2;
+ u8 link_speed;
+#define MLX4_EN_SPEED_MASK 0x3
+#define MLX4_EN_1G_SPEED 0x2
+ u16 reserved3[5];
+ __be64 mac;
+ u8 transceiver;
+};
+
struct mlx4_en_stat_out_mbox {
/* Received frames with a length of 64 octets */
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 394da29..ae17baa 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -541,6 +541,21 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
return skb;
}
+static void validate_loopback(struct mlx4_en_priv *priv, struct sk_buff *skb)
+{
+ int i;
+ int offset = ETH_HLEN;
+
+ for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) {
+ if (*(skb->data + offset) != (unsigned char) (i & 0xff))
+ goto out_loopback;
+ }
+ /* Loopback found */
+ priv->loopback_ok = 1;
+
+out_loopback:
+ dev_kfree_skb_any(skb);
+}
int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
{
@@ -655,6 +670,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
goto next;
}
+ if (unlikely(priv->validate_loopback)) {
+ validate_loopback(priv, skb);
+ goto next;
+ }
+
skb->ip_summed = ip_summed;
skb->protocol = eth_type_trans(skb, dev);
skb_record_rx_queue(skb, cq->ring);
diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/mlx4/en_selftest.c
new file mode 100644
index 0000000..43357d3
--- /dev/null
+++ b/drivers/net/mlx4/en_selftest.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/mlx4/driver.h>
+
+#include "mlx4_en.h"
+
+
+static int mlx4_en_test_registers(struct mlx4_en_priv *priv)
+{
+ return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK,
+ MLX4_CMD_TIME_CLASS_A);
+}
+
+static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
+{
+ struct sk_buff *skb;
+ struct ethhdr *ethh;
+ unsigned char *packet;
+ unsigned int packet_size = MLX4_LOOPBACK_TEST_PAYLOAD;
+ unsigned int i;
+ int err;
+
+
+ /* build the pkt before xmit */
+ skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);
+ if (!skb) {
+ en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n");
+ return -ENOMEM;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr));
+ packet = (unsigned char *)skb_put(skb, packet_size);
+ memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);
+ memset(ethh->h_source, 0, ETH_ALEN);
+ ethh->h_proto = htons(ETH_P_ARP);
+ skb_set_mac_header(skb, 0);
+ for (i = 0; i < packet_size; ++i) /* fill our packet */
+ packet[i] = (unsigned char)(i & 0xff);
+
+ /* xmit the pkt */
+ err = mlx4_en_xmit(skb, priv->dev);
+ return err;
+}
+
+static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
+{
+ u32 loopback_ok = 0;
+ int i;
+
+
+ priv->loopback_ok = 0;
+ priv->validate_loopback = 1;
+
+ /* xmit */
+ if (mlx4_en_test_loopback_xmit(priv)) {
+ en_err(priv, "Transmitting loopback packet failed\n");
+ goto mlx4_en_test_loopback_exit;
+ }
+
+ /* polling for result */
+ for (i = 0; i < MLX4_EN_LOOPBACK_RETRIES; ++i) {
+ msleep(MLX4_EN_LOOPBACK_TIMEOUT);
+ if (priv->loopback_ok) {
+ loopback_ok = 1;
+ break;
+ }
+ }
+ if (!loopback_ok)
+ en_err(priv, "Loopback packet didn't arrive\n");
+
+mlx4_en_test_loopback_exit:
+
+ priv->validate_loopback = 0;
+ return (!loopback_ok);
+}
+
+
+static int mlx4_en_test_link(struct mlx4_en_priv *priv)
+{
+ if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+ return -ENOMEM;
+ if (priv->port_state.link_state == 1)
+ return 0;
+ else
+ return 1;
+}
+
+static int mlx4_en_test_speed(struct mlx4_en_priv *priv)
+{
+
+ if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+ return -ENOMEM;
+
+ /* The device currently only supports 10G speed */
+ if (priv->port_state.link_speed != SPEED_10000)
+ return priv->port_state.link_speed;
+ return 0;
+}
+
+
+void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_tx_ring *tx_ring;
+ int i, carrier_ok;
+
+ memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
+
+ if (*flags & ETH_TEST_FL_OFFLINE) {
+ /* disable the interface */
+ carrier_ok = netif_carrier_ok(dev);
+
+ netif_carrier_off(dev);
+retry_tx:
+ /* Wait untill all tx queues are empty.
+ * there should not be any additional incoming traffic
+ * since we turned the carrier off */
+ msleep(200);
+ for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) {
+ tx_ring = &priv->tx_ring[i];
+ if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb))
+ goto retry_tx;
+ }
+
+ if (priv->mdev->dev->caps.loopback_support){
+ buf[3] = mlx4_en_test_registers(priv);
+ buf[4] = mlx4_en_test_loopback(priv);
+ }
+
+ if (carrier_ok)
+ netif_carrier_on(dev);
+
+ }
+ buf[0] = mlx4_test_interrupts(mdev->dev);
+ buf[1] = mlx4_en_test_link(priv);
+ buf[2] = mlx4_en_test_speed(priv);
+
+ for (i = 0; i < MLX4_EN_NUM_SELF_TEST; i++) {
+ if (buf[i])
+ *flags |= ETH_TEST_FL_FAILED;
+ }
+}
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 3deabd1..b875f9c 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -600,6 +600,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
struct mlx4_wqe_data_seg *data;
struct skb_frag_struct *frag;
struct mlx4_en_tx_info *tx_info;
+ struct ethhdr *ethh;
+ u64 mac;
+ u32 mac_l, mac_h;
int tx_ind = 0;
int nr_txbb;
int desc_size;
@@ -679,6 +682,19 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
priv->port_stats.tx_chksum_offload++;
}
+ if (unlikely(priv->validate_loopback)) {
+ /* Copy dst mac address to wqe */
+ skb_reset_mac_header(skb);
+ ethh = eth_hdr(skb);
+ if (ethh && ethh->h_dest) {
+ mac = mlx4_en_mac_to_u64(ethh->h_dest);
+ mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
+ mac_l = (u32) (mac & 0xffffffff);
+ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
+ tx_desc->ctrl.imm = cpu_to_be32(mac_l);
+ }
+ }
+
/* Handle LSO (TSO) packets */
if (lso_header_size) {
/* Mark opcode as LSO */
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 6d7b2bf..552d0fc 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -699,3 +699,47 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
kfree(priv->eq_table.uar_map);
}
+
+/* A test that verifies that we can accept interrupts on all
+ * the irq vectors of the device.
+ * Interrupts are checked using the NOP command.
+ */
+int mlx4_test_interrupts(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int i;
+ int err;
+
+ err = mlx4_NOP(dev);
+ /* When not in MSI_X, there is only one irq to check */
+ if (!(dev->flags & MLX4_FLAG_MSI_X))
+ return err;
+
+ /* A loop over all completion vectors, for each vector we will check
+ * whether it works by mapping command completions to that vector
+ * and performing a NOP command
+ */
+ for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
+ /* Temporary use polling for command completions */
+ mlx4_cmd_use_polling(dev);
+
+ /* Map the new eq to handle all asyncronous events */
+ err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
+ priv->eq_table.eq[i].eqn);
+ if (err) {
+ mlx4_warn(dev, "Failed mapping eq for interrupt test\n");
+ mlx4_cmd_use_events(dev);
+ break;
+ }
+
+ /* Go back to using events */
+ mlx4_cmd_use_events(dev);
+ err = mlx4_NOP(dev);
+ }
+
+ /* Return to default */
+ mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
+ return err;
+}
+EXPORT_SYMBOL(mlx4_test_interrupts);
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 04f42ae..a87bf3c 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -178,6 +178,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b
#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f
+#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43
#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44
#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48
#define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49
@@ -268,6 +269,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_msg_sz = 1 << (field & 0x1f);
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
+ dev_cap->loopback_support = field & 0x1;
MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
dev_cap->reserved_uars = field >> 4;
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 526d7f3..2cc1ba5 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -74,6 +74,7 @@ struct mlx4_dev_cap {
u64 def_mac[MLX4_MAX_PORTS + 1];
u16 eth_mtu[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
+ int loopback_support;
u32 flags;
int reserved_uars;
int uar_size;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 5102ab1..7390cdb 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -221,6 +221,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.bmme_flags = dev_cap->bmme_flags;
dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
+ dev->caps.loopback_support = dev_cap->loopback_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
dev->caps.log_num_macs = log_num_mac;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 747f04a..bd39d81 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -45,6 +45,7 @@
#include <linux/mlx4/cq.h>
#include <linux/mlx4/srq.h>
#include <linux/mlx4/doorbell.h>
+#include <linux/mlx4/cmd.h>
#include "en_port.h"
@@ -139,10 +140,14 @@ enum {
#define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN)
#define HEADER_COPY_SIZE (128 - NET_IP_ALIGN)
+#define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETH_HLEN)
#define MLX4_EN_MIN_MTU 46
#define ETH_BCAST 0xffffffffffffULL
+#define MLX4_EN_LOOPBACK_RETRIES 5
+#define MLX4_EN_LOOPBACK_TIMEOUT 100
+
#ifdef MLX4_EN_PERF_STAT
/* Number of samples to 'average' */
#define AVG_SIZE 128
@@ -357,6 +362,12 @@ struct mlx4_en_rss_context {
__be32 rss_key[10];
};
+struct mlx4_en_port_state {
+ int link_state;
+ int link_speed;
+ int transciver;
+};
+
struct mlx4_en_pkt_stats {
unsigned long broadcast;
unsigned long rx_prio[8];
@@ -405,6 +416,7 @@ struct mlx4_en_priv {
struct vlan_group *vlgrp;
struct net_device_stats stats;
struct net_device_stats ret_stats;
+ struct mlx4_en_port_state port_state;
spinlock_t stats_lock;
unsigned long last_moder_packets;
@@ -423,6 +435,8 @@ struct mlx4_en_priv {
u16 sample_interval;
u16 adaptive_rx_coal;
u32 msg_enable;
+ u32 loopback_ok;
+ u32 validate_loopback;
struct mlx4_hwq_resources res;
int link_state;
@@ -531,6 +545,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
u8 promisc);
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
+
+#define MLX4_EN_NUM_SELF_TEST 5
+void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
+u64 mlx4_en_mac_to_u64(u8 *addr);
/*
* Globals
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 0f82293..78a1b96 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -56,6 +56,7 @@ enum {
MLX4_CMD_QUERY_HCA = 0xb,
MLX4_CMD_QUERY_PORT = 0x43,
MLX4_CMD_SENSE_PORT = 0x4d,
+ MLX4_CMD_HW_HEALTH_CHECK = 0x50,
MLX4_CMD_SET_PORT = 0xc,
MLX4_CMD_ACCESS_DDR = 0x2e,
MLX4_CMD_MAP_ICM = 0xffa,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 7a7f9c1..2cec587 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -229,6 +229,7 @@ struct mlx4_caps {
u32 bmme_flags;
u32 reserved_lkey;
u16 stat_rate_support;
+ int loopback_support;
u8 port_width_cap[MLX4_MAX_PORTS + 1];
int max_gso_sz;
int reserved_qps_cnt[MLX4_NUM_QP_REGION];
@@ -480,5 +481,6 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
u32 *lkey, u32 *rkey);
int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr);
int mlx4_SYNC_TPT(struct mlx4_dev *dev);
+int mlx4_test_interrupts(struct mlx4_dev *dev);
#endif /* MLX4_DEVICE_H */
--
1.6.1.3
^ permalink raw reply related
* [PATCH 09/14] mlx4_en: Fixing report in Ethtool get_settings
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
The report now based on query from FW, giving the correct tranciever type
and link speed.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_ethtool.c | 27 +++++++++++++++++++++++++--
drivers/net/mlx4/fw.c | 9 +++++++++
drivers/net/mlx4/fw.h | 4 ++++
drivers/net/mlx4/main.c | 4 ++++
include/linux/mlx4/device.h | 4 ++++
5 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 49a7003..13e20c6 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -244,16 +244,39 @@ static void mlx4_en_get_strings(struct net_device *dev,
static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int trans_type;
+
cmd->autoneg = AUTONEG_DISABLE;
cmd->supported = SUPPORTED_10000baseT_Full;
- cmd->advertising = ADVERTISED_1000baseT_Full;
+ cmd->advertising = ADVERTISED_10000baseT_Full;
+
+ if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+ return -ENOMEM;
+
+ trans_type = priv->port_state.transciver;
if (netif_carrier_ok(dev)) {
- cmd->speed = SPEED_10000;
+ cmd->speed = priv->port_state.link_speed;
cmd->duplex = DUPLEX_FULL;
} else {
cmd->speed = -1;
cmd->duplex = -1;
}
+
+ if (trans_type > 0 && trans_type <= 0xC) {
+ cmd->port = PORT_FIBRE;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->supported |= SUPPORTED_FIBRE;
+ cmd->advertising |= ADVERTISED_FIBRE;
+ } else if (trans_type == 0x80 || trans_type == 0) {
+ cmd->port = PORT_TP;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->supported |= SUPPORTED_TP;
+ cmd->advertising |= ADVERTISED_TP;
+ } else {
+ cmd->port = -1;
+ cmd->transceiver = -1;
+ }
return 0;
}
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index a87bf3c..515c634 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -141,6 +141,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
struct mlx4_cmd_mailbox *mailbox;
u32 *outbox;
u8 field;
+ u32 field32;
u16 size;
u16 stat_rate;
int err;
@@ -368,6 +369,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a
#define QUERY_PORT_MAX_VL_OFFSET 0x0b
#define QUERY_PORT_MAC_OFFSET 0x10
+#define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18
+#define QUERY_PORT_WAVELENGTH_OFFSET 0x1c
+#define QUERY_PORT_TRANS_CODE_OFFSET 0x20
for (i = 1; i <= dev_cap->num_ports; ++i) {
err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT,
@@ -391,6 +395,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->log_max_vlans[i] = field >> 4;
MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET);
MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET);
+ MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET);
+ dev_cap->trans_type[i] = field32 >> 24;
+ dev_cap->vendor_oui[i] = field32 & 0xffffff;
+ MLX4_GET(dev_cap->wavelength[i], outbox, QUERY_PORT_WAVELENGTH_OFFSET);
+ MLX4_GET(dev_cap->trans_code[i], outbox, QUERY_PORT_TRANS_CODE_OFFSET);
}
}
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 2cc1ba5..443e456 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -73,6 +73,10 @@ struct mlx4_dev_cap {
int max_pkeys[MLX4_MAX_PORTS + 1];
u64 def_mac[MLX4_MAX_PORTS + 1];
u16 eth_mtu[MLX4_MAX_PORTS + 1];
+ int trans_type[MLX4_MAX_PORTS + 1];
+ int vendor_oui[MLX4_MAX_PORTS + 1];
+ u16 wavelength[MLX4_MAX_PORTS + 1];
+ u64 trans_code[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
int loopback_support;
u32 flags;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 7390cdb..f4791fa 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -184,6 +184,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.eth_mtu_cap[i] = dev_cap->eth_mtu[i];
dev->caps.def_mac[i] = dev_cap->def_mac[i];
dev->caps.supported_type[i] = dev_cap->supported_port_types[i];
+ dev->caps.trans_type[i] = dev_cap->trans_type[i];
+ dev->caps.vendor_oui[i] = dev_cap->vendor_oui[i];
+ dev->caps.wavelength[i] = dev_cap->wavelength[i];
+ dev->caps.trans_code[i] = dev_cap->trans_code[i];
}
dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 2cec587..2a36a34 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -186,6 +186,10 @@ struct mlx4_caps {
int eth_mtu_cap[MLX4_MAX_PORTS + 1];
int gid_table_len[MLX4_MAX_PORTS + 1];
int pkey_table_len[MLX4_MAX_PORTS + 1];
+ int trans_type[MLX4_MAX_PORTS + 1];
+ int vendor_oui[MLX4_MAX_PORTS + 1];
+ int wavelength[MLX4_MAX_PORTS + 1];
+ u64 trans_code[MLX4_MAX_PORTS + 1];
int local_ca_ack_delay;
int num_uars;
int bf_reg_size;
--
1.6.1.3
^ permalink raw reply related
* [PATCH 10/14] mlx4_en: get/set ringsize uses actual ring size
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
In case that the rings were not fully filled, the report in Ethtool
should be according to the actual size that was filled.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_ethtool.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 13e20c6..acdcda8 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -394,8 +394,9 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
- if (rx_size == priv->prof->rx_ring_size &&
- tx_size == priv->prof->tx_ring_size)
+ if (rx_size == (priv->port_up ? priv->rx_ring[0].actual_size :
+ priv->rx_ring[0].size) &&
+ tx_size == priv->tx_ring[0].size)
return 0;
mutex_lock(&mdev->state_lock);
@@ -429,13 +430,13 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
struct ethtool_ringparam *param)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
memset(param, 0, sizeof(*param));
param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
- param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size;
- param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size;
+ param->rx_pending = priv->port_up ?
+ priv->rx_ring[0].actual_size : priv->rx_ring[0].size;
+ param->tx_pending = priv->tx_ring[0].size;
}
static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data)
--
1.6.1.3
^ permalink raw reply related
* [PATCH 11/14] mlx4_en: reconfiguring mac address.
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
When Mac address is removed from one port of the CX2 device, the other device
should reconfigure its Mac.
This fixes an issue with failover, when both ports have the same Mac address,
and one of the ports, is closed, the second one stops receiving traffic.
(bugzilla #1965 at bugs.openfabrics.org)
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_netdev.c | 6 ++++++
drivers/net/mlx4/mlx4_en.h | 1 +
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 7a1e697..2f8d705 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -513,6 +513,10 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
}
+ if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
+ queue_work(mdev->workqueue, &priv->mac_task);
+ mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
+ }
mutex_unlock(&mdev->state_lock);
}
@@ -653,6 +657,7 @@ int mlx4_en_start_port(struct net_device *dev)
en_err(priv, "Failed setting port mac\n");
goto tx_err;
}
+ mdev->mac_removed[priv->port] = 0;
/* Init port */
en_dbg(HW, priv, "Initializing port\n");
@@ -709,6 +714,7 @@ void mlx4_en_stop_port(struct net_device *dev)
/* Unregister Mac address for the port */
mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+ mdev->mac_removed[priv->port] = 1;
/* Free TX Rings */
for (i = 0; i < priv->tx_ring_num; i++) {
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index bd39d81..97c30ff 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -342,6 +342,7 @@ struct mlx4_en_dev {
struct mlx4_mr mr;
u32 priv_pdn;
spinlock_t uar_lock;
+ u8 mac_removed[MLX4_MAX_PORTS + 1];
};
--
1.6.1.3
^ permalink raw reply related
* [PATCH 12/14] mlx4_en: UDP RSS support
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
Adding capability for RSS for UDP traffic, hashing is done based on
IP addresses and UDP port number.
The support depends on HW/FW capabilities.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_main.c | 19 ++++++++++++-------
drivers/net/mlx4/en_rx.c | 8 ++++----
drivers/net/mlx4/fw.c | 3 +++
drivers/net/mlx4/fw.h | 1 +
drivers/net/mlx4/main.c | 1 +
drivers/net/mlx4/mlx4_en.h | 3 +++
include/linux/mlx4/device.h | 1 +
7 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 97934f1..2f25800 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -63,11 +63,12 @@ static const char mlx4_en_version[] =
*/
-/* Use a XOR rathern than Toeplitz hash function for RSS */
-MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS");
-
-/* RSS hash type mask - default to <saddr, daddr, sport, dport> */
-MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask");
+/* Enable RSS TCP traffic */
+MLX4_EN_PARM_INT(tcp_rss, 1,
+ "Enable RSS for incomming TCP traffic or disabled (0)");
+/* Enable RSS UDP traffic */
+MLX4_EN_PARM_INT(udp_rss, 1,
+ "Enable RSS for incomming UDP traffic or disabled (0)");
/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
@@ -107,8 +108,12 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
struct mlx4_en_profile *params = &mdev->profile;
int i;
- params->rss_xor = (rss_xor != 0);
- params->rss_mask = rss_mask & 0x1f;
+ params->tcp_rss = tcp_rss;
+ params->udp_rss = udp_rss;
+ if (params->udp_rss && !mdev->dev->caps.udp_rss) {
+ mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
+ params->udp_rss = 0;
+ }
params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
for (i = 1; i <= MLX4_MAX_PORTS; i++) {
params->prof[i].rx_pause = 1;
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index ae17baa..62604f5 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -859,8 +859,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
struct mlx4_qp_context context;
struct mlx4_en_rss_context *rss_context;
void *ptr;
- int rss_xor = mdev->profile.rss_xor;
- u8 rss_mask = mdev->profile.rss_mask;
+ u8 rss_mask = 0x3f;
int i, qpn;
int err = 0;
int good_qps = 0;
@@ -906,9 +905,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
- rss_context->hash_fn = rss_xor & 0x3;
- rss_context->flags = rss_mask << 2;
+ rss_context->flags = rss_mask;
+ if (priv->mdev->profile.udp_rss)
+ rss_context->base_qpn_udp = rss_context->default_qpn;
err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
&rss_map->indir_qp, &rss_map->indir_state);
if (err)
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 515c634..b716e1a 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -179,6 +179,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b
#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f
+#define QUERY_DEV_CAP_UDP_RSS_OFFSET 0x42
#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43
#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44
#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48
@@ -270,6 +271,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_msg_sz = 1 << (field & 0x1f);
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
+ dev_cap->udp_rss = field & 0x1;
MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
dev_cap->loopback_support = field & 0x1;
MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 443e456..65cc72e 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -78,6 +78,7 @@ struct mlx4_dev_cap {
u16 wavelength[MLX4_MAX_PORTS + 1];
u64 trans_code[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
+ int udp_rss;
int loopback_support;
u32 flags;
int reserved_uars;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index f4791fa..569fa3d 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -225,6 +225,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.bmme_flags = dev_cap->bmme_flags;
dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
+ dev->caps.udp_rss = dev_cap->udp_rss;
dev->caps.loopback_support = dev_cap->loopback_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 97c30ff..0662886 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -319,6 +319,8 @@ struct mlx4_en_port_profile {
struct mlx4_en_profile {
int rss_xor;
int num_lro;
+ int tcp_rss;
+ int udp_rss;
u8 rss_mask;
u32 active_ports;
u32 small_pkt_int;
@@ -361,6 +363,7 @@ struct mlx4_en_rss_context {
u8 hash_fn;
u8 flags;
__be32 rss_key[10];
+ __be32 base_qpn_udp;
};
struct mlx4_en_port_state {
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 2a36a34..7338654 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -233,6 +233,7 @@ struct mlx4_caps {
u32 bmme_flags;
u32 reserved_lkey;
u16 stat_rate_support;
+ int udp_rss;
int loopback_support;
u8 port_width_cap[MLX4_MAX_PORTS + 1];
int max_gso_sz;
--
1.6.1.3
^ permalink raw reply related
* [PATCH 13/14] mlx4_en: Moving to work with GRO
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/en_ethtool.c | 58 +---------------------------------
drivers/net/mlx4/en_main.c | 5 ---
drivers/net/mlx4/en_netdev.c | 3 +-
drivers/net/mlx4/en_rx.c | 68 ++++++++---------------------------------
drivers/net/mlx4/en_tx.c | 1 +
drivers/net/mlx4/mlx4_en.h | 6 ---
6 files changed, 17 insertions(+), 124 deletions(-)
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index acdcda8..01634a3 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -39,21 +39,6 @@
#include "en_port.h"
-static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
-{
- int i;
-
- priv->port_stats.lro_aggregated = 0;
- priv->port_stats.lro_flushed = 0;
- priv->port_stats.lro_no_desc = 0;
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
- priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
- priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
- }
-}
-
static void
mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
{
@@ -112,7 +97,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
"tx_heartbeat_errors", "tx_window_errors",
/* port statistics */
- "lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets",
+ "tso_packets",
"queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
"rx_csum_good", "rx_csum_none", "tx_chksum_offload",
@@ -122,7 +107,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
"tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5",
"tx_prio_6", "tx_prio_7",
};
-#define NUM_MAIN_STATS 21
+#define NUM_MAIN_STATS 18
#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
@@ -174,8 +159,6 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
spin_lock_bh(&priv->stats_lock);
- mlx4_en_update_lro_stats(priv);
-
for (i = 0; i < NUM_MAIN_STATS; i++)
data[index++] = ((unsigned long *) &priv->stats)[i];
for (i = 0; i < NUM_PORT_STATS; i++)
@@ -439,42 +422,6 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
param->tx_pending = priv->tx_ring[0].size;
}
-static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int rc = 0;
- int changed = 0;
-
- if (data & ~ETH_FLAG_LRO)
- return -EOPNOTSUPP;
-
- if (data & ETH_FLAG_LRO) {
- if (mdev->profile.num_lro == 0)
- return -EOPNOTSUPP;
- if (!(dev->features & NETIF_F_LRO))
- changed = 1;
- } else if (dev->features & NETIF_F_LRO) {
- changed = 1;
- }
-
- if (changed) {
- if (netif_running(dev)) {
- mutex_lock(&mdev->state_lock);
- mlx4_en_stop_port(dev);
- }
- dev->features ^= NETIF_F_LRO;
- if (netif_running(dev)) {
- rc = mlx4_en_start_port(dev);
- if (rc)
- en_err(priv, "Failed to restart port\n");
- mutex_unlock(&mdev->state_lock);
- }
- }
-
- return rc;
-}
-
const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_drvinfo = mlx4_en_get_drvinfo,
.get_settings = mlx4_en_get_settings,
@@ -504,7 +451,6 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_ringparam = mlx4_en_get_ringparam,
.set_ringparam = mlx4_en_set_ringparam,
.get_flags = ethtool_op_get_flags,
- .set_flags = mlx4_ethtool_op_set_flags,
};
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 2f25800..1439064 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -70,10 +70,6 @@ MLX4_EN_PARM_INT(tcp_rss, 1,
MLX4_EN_PARM_INT(udp_rss, 1,
"Enable RSS for incomming UDP traffic or disabled (0)");
-/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
-MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
- "Number of LRO sessions per ring or disabled (0)");
-
/* Priority pausing */
MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
" Per priority bit mask");
@@ -114,7 +110,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
params->udp_rss = 0;
}
- params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
for (i = 1; i <= MLX4_MAX_PORTS; i++) {
params->prof[i].rx_pause = 1;
params->prof[i].rx_ppp = pfcrx;
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 2f8d705..411bda5 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -1047,8 +1047,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->features |= NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- if (mdev->profile.num_lro)
- dev->features |= NETIF_F_LRO;
+ dev->features |= NETIF_F_GRO;
if (mdev->LSO_support) {
dev->features |= NETIF_F_TSO;
dev->features |= NETIF_F_TSO6;
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 62604f5..c4aad7f 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -42,18 +42,6 @@
#include "mlx4_en.h"
-static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
- void **ip_hdr, void **tcpudp_hdr,
- u64 *hdr_flags, void *priv)
-{
- *mac_hdr = page_address(frags->page) + frags->page_offset;
- *ip_hdr = *mac_hdr + ETH_HLEN;
- *tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr));
- *hdr_flags = LRO_IPV4 | LRO_TCP;
-
- return 0;
-}
-
static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
struct skb_frag_struct *skb_frags,
@@ -312,28 +300,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
}
ring->buf = ring->wqres.buf.direct.buf;
- /* Configure lro mngr */
- memset(&ring->lro, 0, sizeof(struct net_lro_mgr));
- ring->lro.dev = priv->dev;
- ring->lro.features = LRO_F_NAPI;
- ring->lro.frag_align_pad = NET_IP_ALIGN;
- ring->lro.ip_summed = CHECKSUM_UNNECESSARY;
- ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
- ring->lro.max_desc = mdev->profile.num_lro;
- ring->lro.max_aggr = MAX_SKB_FRAGS;
- ring->lro.lro_arr = kzalloc(mdev->profile.num_lro *
- sizeof(struct net_lro_desc),
- GFP_KERNEL);
- if (!ring->lro.lro_arr) {
- en_err(priv, "Failed to allocate lro array\n");
- goto err_map;
- }
- ring->lro.get_frag_header = mlx4_en_get_frag_header;
-
return 0;
-err_map:
- mlx4_en_unmap_buffer(&ring->wqres.buf);
err_hwq:
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
err_ring:
@@ -412,7 +380,6 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
{
struct mlx4_en_dev *mdev = priv->mdev;
- kfree(ring->lro.lro_arr);
mlx4_en_unmap_buffer(&ring->wqres.buf);
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
vfree(ring->rx_info);
@@ -563,7 +530,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
struct mlx4_cqe *cqe;
struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
struct skb_frag_struct *skb_frags;
- struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS];
struct mlx4_en_rx_desc *rx_desc;
struct sk_buff *skb;
int index;
@@ -623,37 +589,33 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
* - TCP/IP (v4)
* - without IP options
* - not an IP fragment */
- if (mlx4_en_can_lro(cqe->status) &&
- dev->features & NETIF_F_LRO) {
+ if (dev->features & NETIF_F_GRO) {
+ struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
nr = mlx4_en_complete_rx_desc(
priv, rx_desc,
- skb_frags, lro_frags,
+ skb_frags, skb_shinfo(gro_skb)->frags,
ring->page_alloc, length);
if (!nr)
goto next;
+ skb_shinfo(gro_skb)->nr_frags = nr;
+ gro_skb->len = length;
+ gro_skb->data_len = length;
+ gro_skb->truesize += length;
+ gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
+
if (priv->vlgrp && (cqe->vlan_my_qpn &
- cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) {
- lro_vlan_hwaccel_receive_frags(
- &ring->lro, lro_frags,
- length, length,
- priv->vlgrp,
- be16_to_cpu(cqe->sl_vid),
- NULL, 0);
- } else
- lro_receive_frags(&ring->lro,
- lro_frags,
- length,
- length,
- NULL, 0);
+ cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)))
+ vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid));
+ else
+ napi_gro_frags(&cq->napi);
goto next;
}
/* LRO not possible, complete processing here */
ip_summed = CHECKSUM_UNNECESSARY;
- INC_PERF_COUNTER(priv->pstats.lro_misses);
} else {
ip_summed = CHECKSUM_NONE;
priv->port_stats.rx_chksum_none++;
@@ -694,14 +656,10 @@ next:
if (++polled == budget) {
/* We are here because we reached the NAPI budget -
* flush only pending LRO sessions */
- lro_flush_all(&ring->lro);
goto out;
}
}
- /* If CQ is empty flush all LRO sessions unconditionally */
- lro_flush_all(&ring->lro);
-
out:
AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
mlx4_cq_set_ci(&cq->mcq);
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index b875f9c..98dd620 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -38,6 +38,7 @@
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/vmalloc.h>
+#include <linux/tcp.h>
#include "mlx4_en.h"
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 0662886..7d4ddb9 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -38,7 +38,6 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
-#include <linux/inet_lro.h>
#include <linux/mlx4/device.h>
#include <linux/mlx4/qp.h>
@@ -254,7 +253,6 @@ struct mlx4_en_rx_desc {
struct mlx4_en_rx_ring {
struct mlx4_hwq_resources wqres;
struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
- struct net_lro_mgr lro;
u32 size ; /* number of Rx descs*/
u32 actual_size;
u32 size_mask;
@@ -318,7 +316,6 @@ struct mlx4_en_port_profile {
struct mlx4_en_profile {
int rss_xor;
- int num_lro;
int tcp_rss;
int udp_rss;
u8 rss_mask;
@@ -380,9 +377,6 @@ struct mlx4_en_pkt_stats {
};
struct mlx4_en_port_stats {
- unsigned long lro_aggregated;
- unsigned long lro_flushed;
- unsigned long lro_no_desc;
unsigned long tso_packets;
unsigned long queue_stopped;
unsigned long wake_queue;
--
1.6.1.3
^ permalink raw reply related
* [PATCH 14/14] mlx4_en: updated driver version
From: Yevgeny Petrilin @ 2010-08-24 13:46 UTC (permalink / raw)
To: davem; +Cc: netdev, yevgenyp, eugenia
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
drivers/net/mlx4/mlx4_en.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 7d4ddb9..ce8e233 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -49,8 +49,8 @@
#include "en_port.h"
#define DRV_NAME "mlx4_en"
-#define DRV_VERSION "1.4.1.1"
-#define DRV_RELDATE "June 2009"
+#define DRV_VERSION "1.5.1.6"
+#define DRV_RELDATE "August 2010"
#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
--
1.6.1.3
^ permalink raw reply related
* Re: [PATCH] net: use skb_get_rxhash()
From: Changli Gao @ 2010-08-24 13:53 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S. Miller, netdev
In-Reply-To: <1282645262.2477.64.camel@edumazet-laptop>
On Tue, Aug 24, 2010 at 6:21 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le mardi 24 août 2010 à 17:52 +0800, Changli Gao a écrit :
>> Although it is rare the line contains skb->rxhash is executed:
>>
>> * The forwarded skbs should have the the rx queue recoreded.
>> * The local generated skbs should have non zero sk_hash in most of cases.
>>
>> when it is executed, a non zero rxhash will be better.
>>
>> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
>> ---
>> net/core/dev.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index 859e30f..ea041fd 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -2034,7 +2034,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
>> if (skb->sk && skb->sk->sk_hash)
>> hash = skb->sk->sk_hash;
>> else
>> - hash = (__force u16) skb->protocol ^ skb->rxhash;
>> + hash = (__force u16) skb->protocol ^ skb_get_rxhash(skb);
>> hash = jhash_1word(hash, hashrnd);
>>
>> return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
>> --
>
> Instead of adding hacks and growing kernel code (considering your
> previous patch), could we sit down and fix existing code, if really
> needed ?
>
> Spirit of existing code is that tcp/udp sockets have a sk_hash field,
> and this feeds skb->rxhash in transmit path.
>
> (check commit 87fd308c for an example of a fix)
>
Thanks. Got it. skb->rxhash should be only used when skb->sk is NULL,
and skb->rxhash should save the value copied from skb->sk->sk_hash at
that time.
if (skb->sk && skb->sk->sk_hash)
hash = skb->sk->sk_hash;
However, do we really need to check if skb->sk->sk_hash is zero? It is
a rare case, and this check may mislead someone to think a non zero
sk_hash means that sk_hash is set.
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* Re: [PATCH] net: use skb_get_rxhash()
From: Eric Dumazet @ 2010-08-24 14:09 UTC (permalink / raw)
To: Changli Gao; +Cc: David S. Miller, netdev
In-Reply-To: <AANLkTi=AkO0hUZ7o3uwX5zrxeiLi1TsLzu5QL=pUrAju@mail.gmail.com>
Le mardi 24 août 2010 à 21:53 +0800, Changli Gao a écrit :
> However, do we really need to check if skb->sk->sk_hash is zero? It is
> a rare case, and this check may mislead someone to think a non zero
> sk_hash means that sk_hash is set.
>
Not sure what you mean ;)
sk_hash is not always filled, only for some kind of sockets (tcp, udp)
^ permalink raw reply
* [PATCH net-next-2.6] typhoon: fix a race in typhoon_do_get_stats
From: Eric Dumazet @ 2010-08-24 14:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Its important to store 'final' values in counters,
not using them as temporary variables,
or this might break some SNMP applications.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/typhoon.c | 46 +++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 24 deletions(-)
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 2e50077..3f4681f 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -962,36 +962,34 @@ typhoon_do_get_stats(struct typhoon *tp)
* The extra status reported would be a good candidate for
* ethtool_ops->get_{strings,stats}()
*/
- stats->tx_packets = le32_to_cpu(s->txPackets);
- stats->tx_bytes = le64_to_cpu(s->txBytes);
- stats->tx_errors = le32_to_cpu(s->txCarrierLost);
- stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost);
- stats->collisions = le32_to_cpu(s->txMultipleCollisions);
- stats->rx_packets = le32_to_cpu(s->rxPacketsGood);
- stats->rx_bytes = le64_to_cpu(s->rxBytesGood);
- stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns);
+ stats->tx_packets = le32_to_cpu(s->txPackets) +
+ saved->tx_packets;
+ stats->tx_bytes = le64_to_cpu(s->txBytes) +
+ saved->tx_bytes;
+ stats->tx_errors = le32_to_cpu(s->txCarrierLost) +
+ saved->tx_errors;
+ stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost) +
+ saved->tx_carrier_errors;
+ stats->collisions = le32_to_cpu(s->txMultipleCollisions) +
+ saved->collisions;
+ stats->rx_packets = le32_to_cpu(s->rxPacketsGood) +
+ saved->rx_packets;
+ stats->rx_bytes = le64_to_cpu(s->rxBytesGood) +
+ saved->rx_bytes;
+ stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns) +
+ saved->rx_fifo_errors;
stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) +
- le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors);
- stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors);
- stats->rx_length_errors = le32_to_cpu(s->rxOversized);
+ le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors) +
+ saved->rx_errors;
+ stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors) +
+ saved->rx_crc_errors;
+ stats->rx_length_errors = le32_to_cpu(s->rxOversized) +
+ saved->rx_length_errors;
tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ?
SPEED_100 : SPEED_10;
tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ?
DUPLEX_FULL : DUPLEX_HALF;
- /* add in the saved statistics
- */
- stats->tx_packets += saved->tx_packets;
- stats->tx_bytes += saved->tx_bytes;
- stats->tx_errors += saved->tx_errors;
- stats->collisions += saved->collisions;
- stats->rx_packets += saved->rx_packets;
- stats->rx_bytes += saved->rx_bytes;
- stats->rx_fifo_errors += saved->rx_fifo_errors;
- stats->rx_errors += saved->rx_errors;
- stats->rx_crc_errors += saved->rx_crc_errors;
- stats->rx_length_errors += saved->rx_length_errors;
-
return 0;
}
^ permalink raw reply related
* Re: [PATCH] net: use skb_get_rxhash()
From: Changli Gao @ 2010-08-24 14:35 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S. Miller, netdev
In-Reply-To: <1282658991.2477.233.camel@edumazet-laptop>
On Tue, Aug 24, 2010 at 10:09 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le mardi 24 août 2010 à 21:53 +0800, Changli Gao a écrit :
>
>> However, do we really need to check if skb->sk->sk_hash is zero? It is
>> a rare case, and this check may mislead someone to think a non zero
>> sk_hash means that sk_hash is set.
>>
>
> Not sure what you mean ;)
>
> sk_hash is not always filled, only for some kind of sockets (tcp, udp)
>
Hmm, if so, I think maybe addr_fold(skb->sk) is enough and more common.
if (skb->sk)
hash = addr_fold(skb->sk);
else
hash = skb->rxhash; /* saved addr_fold(skb->sk) by skb_orphan_try()
previous */
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* [PATCH 1/5] drivers/net/irda: Eliminate memory leak
From: Julia Lawall @ 2010-08-24 14:38 UTC (permalink / raw)
To: Samuel Ortiz, netdev, linux-kernel, kernel-janitors
From: Julia Lawall <julia@diku.dk>
dev_alloc_skb allocates some memory, so that memory should be freed before
leaving the function in an error case.
Corrected some typos in a nearby comment as well.
A simplified version of the semantic match that finds this problem is:
(http://coccinelle.lip6.fr/)
// <smpl>
@r exists@
local idexpression x;
expression E;
identifier f1;
iterator I;
@@
x = dev_alloc_skb(...);
<... when != x
when != true (x == NULL || ...)
when != if (...) { <+...x...+> }
when != I (...) { <+...x...+> }
(
x == NULL
|
x == E
|
x->f1
)
...>
* return ...;
// </smpl>
Signed-off-by: Julia Lawall <julia@diku.dk>
---
drivers/net/irda/via-ircc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index b0a6cd8..67c0ad4 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -1182,12 +1182,13 @@ F01_E */
skb = dev_alloc_skb(len + 1 - 4);
/*
- * if frame size,data ptr,or skb ptr are wrong ,the get next
+ * if frame size, data ptr, or skb ptr are wrong, then get next
* entry.
*/
if ((skb == NULL) || (skb->data == NULL) ||
(self->rx_buff.data == NULL) || (len < 6)) {
self->netdev->stats.rx_dropped++;
+ kfree_skb(skb);
return TRUE;
}
skb_reserve(skb, 1);
^ permalink raw reply related
* [PATCH 5/5] net/netfilter/ipvs: Eliminate memory leak
From: Julia Lawall @ 2010-08-24 14:39 UTC (permalink / raw)
To: Wensong Zhang, Simon Horman, Julian Anastasov, Patrick McHardy,
David S. Miller, net
From: Julia Lawall <julia@diku.dk>
__ip_vs_service_get and __ip_vs_svc_fwm_get increment a reference count, so
that reference count should be decremented before leaving the function in an
error case.
A simplified version of the semantic match that finds this problem is:
(http://coccinelle.lip6.fr/)
// <smpl>
@r exists@
local idexpression x;
expression E;
identifier f1;
iterator I;
@@
x = __ip_vs_service_get(...);
<... when != x
when != true (x == NULL || ...)
when != if (...) { <+...x...+> }
when != I (...) { <+...x...+> }
(
x == NULL
|
x == E
|
x->f1
)
...>
* return ...;
// </smpl>
Signed-off-by: Julia Lawall <julia@diku.dk>
---
net/netfilter/ipvs/ip_vs_ctl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 0f0c079..f98169b 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2155,7 +2155,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
if (cmd != IP_VS_SO_SET_ADD
&& (svc == NULL || svc->protocol != usvc.protocol)) {
ret = -ESRCH;
- goto out_unlock;
+ goto out_drop_service;
}
switch (cmd) {
@@ -2189,6 +2189,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
ret = -EINVAL;
}
+out_drop_service:
if (svc)
ip_vs_service_put(svc);
^ permalink raw reply related
* Re: [PATCH] TCP_FAILFAST: a new socket option to timeout/abort a connection quicker
From: Arnd Hannemann @ 2010-08-24 14:58 UTC (permalink / raw)
To: Hagen Paul Pfeifer
Cc: Eric Dumazet, H.K. Jerry Chu, ilpo.jarvinen, davem, netdev
In-Reply-To: <423116d1d215b0fb3d1c966fb8167508@localhost>
Hi,
Am 24.08.2010 11:10, schrieb Hagen Paul Pfeifer:
>
> On Tue, 24 Aug 2010 10:04:37 +0200, Arnd Hannemann wrote:
>
>> Why not call it TCP_USERTIMEOUT?
>
>> Later you can also send it via the TCP user timeout option... (RFC5482)
>
>> Hmm... is the ms granularity really needed? Does it make sense to abort
>
>> a connection below a second?
>
>
>
> I am working on a patch for UTO, the lion share is already implemented. As
Nice, so did you come up with a name for the socket option yet?
> I can see this patch introduce a upper limit (max) where UTO on the other
>
> hand provides a lower limit (min). Therefore I am not sure if we should
>
> call this option TCP_USERTIMEOUT.
Hmm, is there really a difference? If an application specifies
a wanted timeout e.g. with USER_TIMEOUT, CHANGEABLE will
become false and the value would be announced via ADV_UTO.
The connection could be aborted locally after that time passed,
regardless of what the remote site thinks the timeout should be.
As I understand it U_LIMIT and L_LIMIT would only be there
for safety to disallow nonsensical values of USER_TIMEOUT.
Did I miss something?
Best regards,
Arnd
^ permalink raw reply
* Re: [PATCH net-next-2.6] typhoon: fix a race in typhoon_do_get_stats
From: David Dillow @ 2010-08-24 14:52 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1282659493.2477.241.camel@edumazet-laptop>
On Tue, 2010-08-24 at 16:18 +0200, Eric Dumazet wrote:
> Its important to store 'final' values in counters,
> not using them as temporary variables,
> or this might break some SNMP applications.
Acked-by: David Dillow <dave@thedillows.org>
^ permalink raw reply
* Re: [Bugme-new] [Bug 16626] New: Machine hangs with EIP at skb_copy_and_csum_dev
From: Eric Dumazet @ 2010-08-24 15:08 UTC (permalink / raw)
To: Plamen Petrov
Cc: Jarek Poplawski, Andrew Morton, netdev, bugzilla-daemon,
bugme-daemon
In-Reply-To: <4C73C8DF.4060601@fs.uni-ruse.bg>
Le mardi 24 août 2010 à 16:27 +0300, Plamen Petrov a écrit :
> The current status: if I enable GRO on the tg3 - the kernel oopses.
> It just takes a different amount of time to trigger: somewhere from
> 30 seconds to 30 minutes.
>
> The oopses looks the same, and here are the latest:
>
> [picture 13]
> http://picpaste.com/c8dbda8f5c15d9ce3e050dd7f245f5d0.jpg
>
> [picture 14]
> http://picpaste.com/646cca586b704c5b72d3cf9fa54c7344.jpg
>
> I was wondering which debug options could help us track this down?
>
Thanks, here is an updated patch (against linux-2.6)
diff --git a/net/core/dev.c b/net/core/dev.c
index 3721fbb..77c8eb7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1935,6 +1935,32 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
illegal_highdma(dev, skb))));
}
+int skb_csum_start_bug(const struct sk_buff *skb, int pos)
+{
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ long csstart;
+
+ csstart = skb->csum_start - skb_headroom(skb);
+ if (WARN_ON(csstart > skb_headlen(skb))) {
+ int i;
+
+ pr_err("%d: csum_start %u, offset %u, headroom %d, headlen %d, len %d\n",
+ pos, skb->csum_start, skb->csum_offset, skb_headroom(skb),
+ skb_headlen(skb), skb->len);
+ pr_err("nr_frags=%u gso_size=%u ",
+ skb_shinfo(skb)->nr_frags,
+ skb_shinfo(skb)->gso_size);
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ pr_err("frag_size=%u ", skb_shinfo(skb)->frags[i].size);
+ }
+ pr_err("\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
struct netdev_queue *txq)
{
@@ -1959,11 +1985,15 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
goto out_kfree_skb;
if (skb->next)
goto gso;
+ if (skb_csum_start_bug(skb, 10))
+ goto out_kfree_skb;
} else {
if (skb_needs_linearize(skb, dev) &&
__skb_linearize(skb))
goto out_kfree_skb;
+ if (skb_csum_start_bug(skb, 20))
+ goto out_kfree_skb;
/* If packet is not checksummed and device does not
* support checksumming for this protocol, complete
* checksumming here.
@@ -1974,10 +2004,16 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
if (!dev_can_checksum(dev, skb) &&
skb_checksum_help(skb))
goto out_kfree_skb;
+ if (skb_csum_start_bug(skb, 30))
+ goto out_kfree_skb;
}
}
- rc = ops->ndo_start_xmit(skb, dev);
+ if (skb_csum_start_bug(skb, 40)) {
+ kfree_skb(skb);
+ rc = NETDEV_TX_OK;
+ } else
+ rc = ops->ndo_start_xmit(skb, dev);
if (rc == NETDEV_TX_OK)
txq_trans_update(txq);
return rc;
@@ -1997,7 +2033,12 @@ gso:
if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
skb_dst_drop(nskb);
- rc = ops->ndo_start_xmit(nskb, dev);
+ if (skb_csum_start_bug(skb, 50)) {
+ kfree_skb(skb);
+ rc = NETDEV_TX_OK;
+ } else
+ rc = ops->ndo_start_xmit(nskb, dev);
+
if (unlikely(rc != NETDEV_TX_OK)) {
if (rc & ~NETDEV_TX_MASK)
goto out_kfree_gso_skb;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3a2513f..3d54a1b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1824,13 +1824,15 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
{
__wsum csum;
long csstart;
+ extern int skb_csum_start_bug(const struct sk_buff *skb, int pos);
if (skb->ip_summed == CHECKSUM_PARTIAL)
csstart = skb->csum_start - skb_headroom(skb);
else
csstart = skb_headlen(skb);
- BUG_ON(csstart > skb_headlen(skb));
+ if (skb_csum_start_bug(skb, 100))
+ return;
skb_copy_from_linear_data(skb, to, csstart);
^ permalink raw reply related
* [PATCH] caif-driver: add HAS_DMA dependency
From: Heiko Carstens @ 2010-08-24 15:14 UTC (permalink / raw)
To: David Miller; +Cc: Sjur Braendeland, Martin Schwidefsky, linux-kernel, netdev
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Fix this error on an s390 allyesconfig build:
linux-2.6/drivers/net/caif/caif_spi.c:98:
undefined reference to `dma_free_coherent'
Cc: Sjur Braendeland <sjur.brandeland@stericsson.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
---
drivers/net/caif/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -15,7 +15,7 @@ config CAIF_TTY
config CAIF_SPI_SLAVE
tristate "CAIF SPI transport driver for slave interface"
- depends on CAIF
+ depends on CAIF && HAS_DMA
default n
---help---
The CAIF Link layer SPI Protocol driver for Slave SPI interface.
^ permalink raw reply
* Re: RFC: MTU for serving NFS on Infiniband
From: Marc Aurele La France @ 2010-08-24 15:14 UTC (permalink / raw)
To: Stephen Hemminger
Cc: linux-kernel, netdev, David S. Miller, Alexey Kuznetsov,
Pekka Savola (ipv6), James Morris, Hideaki YOSHIFUJI,
Patrick McHardy
In-Reply-To: <20100823080543.319143e3@nehalam>
On Mon, 23 Aug 2010, Stephen Hemminger wrote:
> On Mon, 23 Aug 2010 08:44:37 -0600 (MDT)
> Marc Aurele La France <tsi@ualberta.ca> wrote:
>> In regrouping for my next tack at this, I noticed that all stack traces go
>> through ip_append_data(). This would be ipv6_append_data() in the IPv6 case.
>> A _very_ rough draft that would have ip_append_data() temporarily drop down
>> to a smaller fake MTU follows ...
> Why doesn't NFS generate page size fragments? Does Infiniband or your
> device not support this? Any thing that requires higher order allocation
> is going to unstable under load. Let's fix the cause not the apply bandaid
> solution to the symptom.
>From what I can tell, IP fragmentation is done centrally.
The MTU is a device attribute, yes. But, here, it is ip_append_data(),
not NFS nor the device driver, whose responsibility it is to break up the
payload into fragments, either by itself or using any facility supported
by the adapter. What I'm saying is that there's no reason to require all
fragments, except the last, to be MTU-sized. The RFCs I've looked at
allow them to be shorter which can be used to advantage when MTU-sized
fragments cannot be allocated in a memory fragmentation scenario, instead
of reporting an error.
Marc.
+----------------------------------+----------------------------------+
| Marc Aurele La France | work: 1-780-492-9310 |
| Academic Information and | fax: 1-780-492-1729 |
| Communications Technologies | email: tsi@ualberta.ca |
| 352 General Services Building +----------------------------------+
| University of Alberta | |
| Edmonton, Alberta | Standard disclaimers apply |
| T6G 2H1 | |
| CANADA | |
+----------------------------------+----------------------------------+
^ permalink raw reply
* [PATCH net-next-2.6] be2net: get rid of be_get_stats()
From: Eric Dumazet @ 2010-08-24 15:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Somnath K, Ajit Khaparde
drivers can avoid implementing ndo_get_stats method if using netdevice
stats structure.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/benet/be_main.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 74e146f..b89bae0 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -365,11 +365,6 @@ static void be_rx_eqd_update(struct be_adapter *adapter)
rx_eq->cur_eqd = eqd;
}
-static struct net_device_stats *be_get_stats(struct net_device *dev)
-{
- return &dev->stats;
-}
-
static u32 be_calc_rate(u64 bytes, unsigned long ticks)
{
u64 rate = bytes;
@@ -2399,7 +2394,6 @@ static struct net_device_ops be_netdev_ops = {
.ndo_open = be_open,
.ndo_stop = be_close,
.ndo_start_xmit = be_xmit,
- .ndo_get_stats = be_get_stats,
.ndo_set_rx_mode = be_set_multicast_list,
.ndo_set_mac_address = be_mac_addr_set,
.ndo_change_mtu = be_change_mtu,
^ permalink raw reply related
* [PATCH net-next-2.6] ethoc: get rid of ethoc_stats()
From: Eric Dumazet @ 2010-08-24 15:22 UTC (permalink / raw)
To: David Miller; +Cc: netdev
drivers can avoid implementing ndo_get_stats method if using netdevice
stats structure.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/ethoc.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 6d653c4..c5a2fe0 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -806,11 +806,6 @@ static void ethoc_tx_timeout(struct net_device *dev)
ethoc_interrupt(dev->irq, dev);
}
-static struct net_device_stats *ethoc_stats(struct net_device *dev)
-{
- return &dev->stats;
-}
-
static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ethoc *priv = netdev_priv(dev);
@@ -863,7 +858,6 @@ static const struct net_device_ops ethoc_netdev_ops = {
.ndo_set_multicast_list = ethoc_set_multicast_list,
.ndo_change_mtu = ethoc_change_mtu,
.ndo_tx_timeout = ethoc_tx_timeout,
- .ndo_get_stats = ethoc_stats,
.ndo_start_xmit = ethoc_start_xmit,
};
^ permalink raw reply related
* [PATCH net-next-2.6] bcm63xx_enet: use netdev stats
From: Eric Dumazet @ 2010-08-24 15:53 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Maxime Bizon, Florian Fainelli
Use integrated net_device stats instead of a private one
Get rid of bcm_enet_get_stats()
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/bcm63xx_enet.c | 60 +++++++++++++++--------------------
drivers/net/bcm63xx_enet.h | 1
2 files changed, 27 insertions(+), 34 deletions(-)
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index 0d2c5da..e2f70c3 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -293,22 +293,22 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
/* if the packet does not have start of packet _and_
* end of packet flag set, then just recycle it */
if ((len_stat & DMADESC_ESOP_MASK) != DMADESC_ESOP_MASK) {
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
continue;
}
/* recycle packet if it's marked as bad */
if (unlikely(len_stat & DMADESC_ERR_MASK)) {
- priv->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (len_stat & DMADESC_OVSIZE_MASK)
- priv->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
if (len_stat & DMADESC_CRC_MASK)
- priv->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (len_stat & DMADESC_UNDER_MASK)
- priv->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (len_stat & DMADESC_OV_MASK)
- priv->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
continue;
}
@@ -324,7 +324,7 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
nskb = netdev_alloc_skb_ip_align(dev, len);
if (!nskb) {
/* forget packet, just rearm desc */
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
continue;
}
@@ -342,8 +342,8 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, dev);
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
netif_receive_skb(skb);
} while (--budget > 0);
@@ -403,7 +403,7 @@ static int bcm_enet_tx_reclaim(struct net_device *dev, int force)
spin_unlock(&priv->tx_lock);
if (desc->len_stat & DMADESC_UNDER_MASK)
- priv->stats.tx_errors++;
+ dev->stats.tx_errors++;
dev_kfree_skb(skb);
released++;
@@ -563,8 +563,8 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!priv->tx_desc_count)
netif_stop_queue(dev);
- priv->stats.tx_bytes += skb->len;
- priv->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ dev->stats.tx_packets++;
ret = NETDEV_TX_OK;
out_unlock:
@@ -1141,17 +1141,6 @@ static int bcm_enet_stop(struct net_device *dev)
}
/*
- * core request to return device rx/tx stats
- */
-static struct net_device_stats *bcm_enet_get_stats(struct net_device *dev)
-{
- struct bcm_enet_priv *priv;
-
- priv = netdev_priv(dev);
- return &priv->stats;
-}
-
-/*
* ethtool callbacks
*/
struct bcm_enet_stats {
@@ -1163,16 +1152,18 @@ struct bcm_enet_stats {
#define GEN_STAT(m) sizeof(((struct bcm_enet_priv *)0)->m), \
offsetof(struct bcm_enet_priv, m)
+#define DEV_STAT(m) sizeof(((struct net_device_stats *)0)->m), \
+ offsetof(struct net_device_stats, m)
static const struct bcm_enet_stats bcm_enet_gstrings_stats[] = {
- { "rx_packets", GEN_STAT(stats.rx_packets), -1 },
- { "tx_packets", GEN_STAT(stats.tx_packets), -1 },
- { "rx_bytes", GEN_STAT(stats.rx_bytes), -1 },
- { "tx_bytes", GEN_STAT(stats.tx_bytes), -1 },
- { "rx_errors", GEN_STAT(stats.rx_errors), -1 },
- { "tx_errors", GEN_STAT(stats.tx_errors), -1 },
- { "rx_dropped", GEN_STAT(stats.rx_dropped), -1 },
- { "tx_dropped", GEN_STAT(stats.tx_dropped), -1 },
+ { "rx_packets", DEV_STAT(rx_packets), -1 },
+ { "tx_packets", DEV_STAT(tx_packets), -1 },
+ { "rx_bytes", DEV_STAT(rx_bytes), -1 },
+ { "tx_bytes", DEV_STAT(tx_bytes), -1 },
+ { "rx_errors", DEV_STAT(rx_errors), -1 },
+ { "tx_errors", DEV_STAT(tx_errors), -1 },
+ { "rx_dropped", DEV_STAT(rx_dropped), -1 },
+ { "tx_dropped", DEV_STAT(tx_dropped), -1 },
{ "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETH_MIB_RX_GD_OCTETS},
{ "rx_good_pkts", GEN_STAT(mib.rx_gd_pkts), ETH_MIB_RX_GD_PKTS },
@@ -1328,7 +1319,11 @@ static void bcm_enet_get_ethtool_stats(struct net_device *netdev,
char *p;
s = &bcm_enet_gstrings_stats[i];
- p = (char *)priv + s->stat_offset;
+ if (s->mib_reg == -1)
+ p = (char *)&netdev->stats;
+ else
+ p = (char *)priv;
+ p += s->stat_offset;
data[i] = (s->sizeof_stat == sizeof(u64)) ?
*(u64 *)p : *(u32 *)p;
}
@@ -1605,7 +1600,6 @@ static const struct net_device_ops bcm_enet_ops = {
.ndo_open = bcm_enet_open,
.ndo_stop = bcm_enet_stop,
.ndo_start_xmit = bcm_enet_start_xmit,
- .ndo_get_stats = bcm_enet_get_stats,
.ndo_set_mac_address = bcm_enet_set_mac_address,
.ndo_set_multicast_list = bcm_enet_set_multicast_list,
.ndo_do_ioctl = bcm_enet_ioctl,
diff --git a/drivers/net/bcm63xx_enet.h b/drivers/net/bcm63xx_enet.h
index bd3684d..0e3048b 100644
--- a/drivers/net/bcm63xx_enet.h
+++ b/drivers/net/bcm63xx_enet.h
@@ -274,7 +274,6 @@ struct bcm_enet_priv {
int pause_tx;
/* stats */
- struct net_device_stats stats;
struct bcm_enet_mib_counters mib;
/* after mib interrupt, mib registers update is done in this
^ 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