Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Mar 2011 00:54:01 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r220016 - in head/sys/ofed: drivers/net/mlx4 include/linux/mlx4
Message-ID:  <201103260054.p2Q0s1X7098684@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jeff
Date: Sat Mar 26 00:54:01 2011
New Revision: 220016
URL: http://svn.freebsd.org/changeset/base/220016

Log:
   - Implement wake-on-lan support in mlxen.

Modified:
  head/sys/ofed/drivers/net/mlx4/en_ethtool.c
  head/sys/ofed/drivers/net/mlx4/en_netdev.c
  head/sys/ofed/drivers/net/mlx4/fw.c
  head/sys/ofed/drivers/net/mlx4/fw.h
  head/sys/ofed/drivers/net/mlx4/main.c
  head/sys/ofed/drivers/net/mlx4/mlx4_en.h
  head/sys/ofed/include/linux/mlx4/device.h

Modified: head/sys/ofed/drivers/net/mlx4/en_ethtool.c
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/en_ethtool.c	Sat Mar 26 00:34:35 2011	(r220015)
+++ head/sys/ofed/drivers/net/mlx4/en_ethtool.c	Sat Mar 26 00:54:01 2011	(r220016)
@@ -494,6 +494,7 @@ const struct ethtool_ops mlx4_en_ethtool
 	.get_ethtool_stats = mlx4_en_get_ethtool_stats,
 	.self_test = mlx4_en_self_test,
 	.get_wol = mlx4_en_get_wol,
+	.set_wol = mlx4_en_set_wol,
 	.get_msglevel = mlx4_en_get_msglevel,
 	.set_msglevel = mlx4_en_set_msglevel,
 	.get_coalesce = mlx4_en_get_coalesce,

Modified: head/sys/ofed/drivers/net/mlx4/en_netdev.c
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/en_netdev.c	Sat Mar 26 00:34:35 2011	(r220015)
+++ head/sys/ofed/drivers/net/mlx4/en_netdev.c	Sat Mar 26 00:54:01 2011	(r220016)
@@ -532,6 +532,7 @@ int mlx4_en_start_port(struct net_device
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_en_cq *cq;
 	struct mlx4_en_tx_ring *tx_ring;
+	u64 config;
 	int rx_index = 0;
 	int tx_index = 0;
 	int err = 0;
@@ -662,6 +663,25 @@ int mlx4_en_start_port(struct net_device
 	else
 		priv->rx_csum = 0;
 
+	err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
+	if (err) {
+		en_err(priv, "Failed to get WoL info, unable to modify\n");
+		goto wol_err;
+	}
+	if (dev->if_capenable & IFCAP_WOL_MAGIC) {
+		config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
+		    MLX4_EN_WOL_MAGIC;
+	} else {
+		config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
+		config |= MLX4_EN_WOL_DO_MODIFY;
+	}
+
+	err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
+	if (err) {
+		en_err(priv, "Failed to set WoL information\n");
+		goto wol_err;
+	}
+
 	priv->port_up = true;
 
 	/* Populate multicast list */
@@ -676,6 +696,10 @@ int mlx4_en_start_port(struct net_device
 
 	return 0;
 
+wol_err:
+	/* close port*/
+	mlx4_CLOSE_PORT(mdev->dev, priv->port);
+
 mac_err:
 	mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
 tx_err:
@@ -1095,6 +1119,8 @@ static int mlx4_en_ioctl(struct ifnet *d
 			dev->if_capenable ^= IFCAP_VLAN_HWTAGGING;
 		if (mask & IFCAP_VLAN_HWFILTER)
 			dev->if_capenable ^= IFCAP_VLAN_HWFILTER;
+		if (mask & IFCAP_WOL_MAGIC)
+			dev->if_capenable ^= IFCAP_WOL_MAGIC;
 		if (dev->if_drv_flags & IFF_DRV_RUNNING)
 			mlx4_en_init(priv);
 		VLAN_CAPABILITIES(dev);
@@ -1534,14 +1560,23 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 	dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
 	dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
 	dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
-#if 0 /* Not yet */
-	dev->if_capabilities |= IFCAP_WOL;
-#endif
 	if (mdev->LSO_support)
 		dev->if_capabilities |= IFCAP_TSO | IFCAP_VLAN_HWTSO;
 	if (mdev->profile.num_lro)
 		dev->if_capabilities |= IFCAP_LRO;
 	dev->if_capenable = dev->if_capabilities;
+	/*
+	 * Setup wake-on-lan.
+	 */
+	if (priv->mdev->dev->caps.wol) {
+		u64 config;
+		if (mlx4_wol_read(priv->mdev->dev, &config, priv->port) == 0) {
+			if (config & MLX4_EN_WOL_MAGIC)
+				dev->if_capabilities |= IFCAP_WOL_MAGIC;
+			if (config & MLX4_EN_WOL_ENABLED)
+				dev->if_capenable |= IFCAP_WOL_MAGIC;
+		}
+	}
 
         /* Register for VLAN events */
 	priv->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,

Modified: head/sys/ofed/drivers/net/mlx4/fw.c
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/fw.c	Sat Mar 26 00:34:35 2011	(r220015)
+++ head/sys/ofed/drivers/net/mlx4/fw.c	Sat Mar 26 00:54:01 2011	(r220016)
@@ -289,6 +289,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *
 	dev_cap->udp_rss = field & 0x1;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
 	dev_cap->loopback_support = field & 0x1;
+	dev_cap->wol = field & 0x40;
 	MLX4_GET(tmp1, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
 	MLX4_GET(tmp2, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
 	dev_cap->flags = tmp2 | (u64)tmp1 << 32;
@@ -969,6 +970,25 @@ int mlx4_NOP(struct mlx4_dev *dev)
 	return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
 }
 
+#define MLX4_WOL_SETUP_MODE (5 << 28)
+int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
+{
+	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
+
+	return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
+			    MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A);
+}
+EXPORT_SYMBOL_GPL(mlx4_wol_read);
+
+int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
+{
+	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
+
+	return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
+					MLX4_CMD_TIME_CLASS_A);
+}
+EXPORT_SYMBOL_GPL(mlx4_wol_write);
+
 int mlx4_query_diag_counters(struct mlx4_dev *dev, int array_length,
 			     u8 op_modifier, u32 in_offset[], u32 counter_out[])
 {

Modified: head/sys/ofed/drivers/net/mlx4/fw.h
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/fw.h	Sat Mar 26 00:34:35 2011	(r220015)
+++ head/sys/ofed/drivers/net/mlx4/fw.h	Sat Mar 26 00:54:01 2011	(r220016)
@@ -80,6 +80,7 @@ struct mlx4_dev_cap {
 	u16 stat_rate_support;
 	int udp_rss;
 	int loopback_support;
+	int wol;
 	u64 flags;
 	int reserved_uars;
 	int uar_size;

Modified: head/sys/ofed/drivers/net/mlx4/main.c
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/main.c	Sat Mar 26 00:34:35 2011	(r220015)
+++ head/sys/ofed/drivers/net/mlx4/main.c	Sat Mar 26 00:54:01 2011	(r220016)
@@ -331,6 +331,7 @@ static int mlx4_dev_cap(struct mlx4_dev 
 	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.wol		     = dev_cap->wol;
 	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
 	dev->caps.reserved_xrcds     = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
 		dev_cap->reserved_xrcds : 0;

Modified: head/sys/ofed/drivers/net/mlx4/mlx4_en.h
==============================================================================
--- head/sys/ofed/drivers/net/mlx4/mlx4_en.h	Sat Mar 26 00:34:35 2011	(r220015)
+++ head/sys/ofed/drivers/net/mlx4/mlx4_en.h	Sat Mar 26 00:54:01 2011	(r220016)
@@ -164,7 +164,7 @@ enum {
 #define MLX4_EN_DEF_TX_RING_SIZE	512
 #define MLX4_EN_DEF_TX_QUEUE_SIZE	4096
 #define MLX4_EN_DEF_RX_RING_SIZE  	1024
-#define	MLX4_EN_MAX_RX_POLL		16
+#define	MLX4_EN_MAX_RX_POLL		1024
 
 /* Target number of bytes to coalesce with interrupt moderation */
 #define MLX4_EN_RX_COAL_TARGET	0x20000
@@ -537,6 +537,7 @@ struct mlx4_en_priv {
 	u16 num_frags;
 	u16 log_rx_info;
 	int ip_reasm;
+	bool wol;
 
 	struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS];
 	struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS];
@@ -561,6 +562,11 @@ struct mlx4_en_priv {
 	struct sysctl_ctx_list stat_ctx;
 };
 
+enum mlx4_en_wol {
+	MLX4_EN_WOL_MAGIC = (1ULL << 61),
+	MLX4_EN_WOL_ENABLED = (1ULL << 62),
+	MLX4_EN_WOL_DO_MODIFY = (1ULL << 63),
+};
 
 int mlx4_en_transmit(struct net_device *dev, struct mbuf *mb);
 void mlx4_en_qflush(struct net_device *dev);

Modified: head/sys/ofed/include/linux/mlx4/device.h
==============================================================================
--- head/sys/ofed/include/linux/mlx4/device.h	Sat Mar 26 00:34:35 2011	(r220015)
+++ head/sys/ofed/include/linux/mlx4/device.h	Sat Mar 26 00:54:01 2011	(r220016)
@@ -251,6 +251,7 @@ struct mlx4_caps {
 	u16			stat_rate_support;
 	int			udp_rss;
 	int			loopback_support;
+	int			wol;
 	u8			port_width_cap[MLX4_MAX_PORTS + 1];
 	int			max_gso_sz;
 	int                     reserved_qps_cnt[MLX4_NUM_QP_REGION];
@@ -535,6 +536,9 @@ int mlx4_mtt_init(struct mlx4_dev *dev, 
 		  struct mlx4_mtt *mtt);
 void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt);
 u64 mlx4_mtt_addr(struct mlx4_dev *dev, struct mlx4_mtt *mtt);
+int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port);
+int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port);
+
 
 int mlx4_mr_reserve_range(struct mlx4_dev *dev, int cnt, int align, u32 *base_mridx);
 void mlx4_mr_release_range(struct mlx4_dev *dev, u32 base_mridx, int cnt);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103260054.p2Q0s1X7098684>