aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2011-03-22 18:37:59 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-23 15:24:19 -0400
commit14c07b1358ede1664652bb9b28d9ace5fe6f7f92 (patch)
tree05fa72b9680e85923d938edd8e4963bbac0b629b /drivers/net/mlx4
parent1fb9876e9bf895ea4127ff17180f1b2ab37771b6 (diff)
mlx4: Wake on LAN support
The driver queries the FW for WOL support. Ethtool get/set_wol is implemented accordingly. Only magic packets are supported at the time. Signed-off-by: Igor Yarovinsky <igory@mellanox.co.il> Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/mlx4')
-rw-r--r--drivers/net/mlx4/en_ethtool.c62
-rw-r--r--drivers/net/mlx4/fw.c20
-rw-r--r--drivers/net/mlx4/fw.h1
-rw-r--r--drivers/net/mlx4/main.c1
-rw-r--r--drivers/net/mlx4/mlx4_en.h7
5 files changed, 89 insertions, 2 deletions
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 8cfe8586ed2d..c1f351f6ae57 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -131,8 +131,65 @@ static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
131static void mlx4_en_get_wol(struct net_device *netdev, 131static void mlx4_en_get_wol(struct net_device *netdev,
132 struct ethtool_wolinfo *wol) 132 struct ethtool_wolinfo *wol)
133{ 133{
134 wol->supported = 0; 134 struct mlx4_en_priv *priv = netdev_priv(netdev);
135 wol->wolopts = 0; 135 int err = 0;
136 u64 config = 0;
137
138 if (!priv->mdev->dev->caps.wol) {
139 wol->supported = 0;
140 wol->wolopts = 0;
141 return;
142 }
143
144 err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
145 if (err) {
146 en_err(priv, "Failed to get WoL information\n");
147 return;
148 }
149
150 if (config & MLX4_EN_WOL_MAGIC)
151 wol->supported = WAKE_MAGIC;
152 else
153 wol->supported = 0;
154
155 if (config & MLX4_EN_WOL_ENABLED)
156 wol->wolopts = WAKE_MAGIC;
157 else
158 wol->wolopts = 0;
159}
160
161static int mlx4_en_set_wol(struct net_device *netdev,
162 struct ethtool_wolinfo *wol)
163{
164 struct mlx4_en_priv *priv = netdev_priv(netdev);
165 u64 config = 0;
166 int err = 0;
167
168 if (!priv->mdev->dev->caps.wol)
169 return -EOPNOTSUPP;
170
171 if (wol->supported & ~WAKE_MAGIC)
172 return -EINVAL;
173
174 err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
175 if (err) {
176 en_err(priv, "Failed to get WoL info, unable to modify\n");
177 return err;
178 }
179
180 if (wol->wolopts & WAKE_MAGIC) {
181 config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
182 MLX4_EN_WOL_MAGIC;
183 } else {
184 config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
185 config |= MLX4_EN_WOL_DO_MODIFY;
186 }
187
188 err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
189 if (err)
190 en_err(priv, "Failed to set WoL information\n");
191
192 return err;
136} 193}
137 194
138static int mlx4_en_get_sset_count(struct net_device *dev, int sset) 195static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
@@ -442,6 +499,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
442 .get_ethtool_stats = mlx4_en_get_ethtool_stats, 499 .get_ethtool_stats = mlx4_en_get_ethtool_stats,
443 .self_test = mlx4_en_self_test, 500 .self_test = mlx4_en_self_test,
444 .get_wol = mlx4_en_get_wol, 501 .get_wol = mlx4_en_get_wol,
502 .set_wol = mlx4_en_set_wol,
445 .get_msglevel = mlx4_en_get_msglevel, 503 .get_msglevel = mlx4_en_get_msglevel,
446 .set_msglevel = mlx4_en_set_msglevel, 504 .set_msglevel = mlx4_en_set_msglevel,
447 .get_coalesce = mlx4_en_get_coalesce, 505 .get_coalesce = mlx4_en_get_coalesce,
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 5de1db897835..fd1c51b6197a 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -276,6 +276,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
276 dev_cap->udp_rss = field & 0x1; 276 dev_cap->udp_rss = field & 0x1;
277 MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET); 277 MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
278 dev_cap->loopback_support = field & 0x1; 278 dev_cap->loopback_support = field & 0x1;
279 dev_cap->wol = field & 0x40;
279 MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); 280 MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
280 MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); 281 MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
281 dev_cap->reserved_uars = field >> 4; 282 dev_cap->reserved_uars = field >> 4;
@@ -908,3 +909,22 @@ int mlx4_NOP(struct mlx4_dev *dev)
908 /* Input modifier of 0x1f means "finish as soon as possible." */ 909 /* Input modifier of 0x1f means "finish as soon as possible." */
909 return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100); 910 return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
910} 911}
912
913#define MLX4_WOL_SETUP_MODE (5 << 28)
914int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
915{
916 u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
917
918 return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
919 MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A);
920}
921EXPORT_SYMBOL_GPL(mlx4_wol_read);
922
923int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
924{
925 u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
926
927 return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
928 MLX4_CMD_TIME_CLASS_A);
929}
930EXPORT_SYMBOL_GPL(mlx4_wol_write);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 65cc72eb899d..f7b9cc2d1b2a 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -80,6 +80,7 @@ struct mlx4_dev_cap {
80 u16 stat_rate_support; 80 u16 stat_rate_support;
81 int udp_rss; 81 int udp_rss;
82 int loopback_support; 82 int loopback_support;
83 int wol;
83 u32 flags; 84 u32 flags;
84 int reserved_uars; 85 int reserved_uars;
85 int uar_size; 86 int uar_size;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 517ca34f5b37..42d4fb477870 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -227,6 +227,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
227 dev->caps.stat_rate_support = dev_cap->stat_rate_support; 227 dev->caps.stat_rate_support = dev_cap->stat_rate_support;
228 dev->caps.udp_rss = dev_cap->udp_rss; 228 dev->caps.udp_rss = dev_cap->udp_rss;
229 dev->caps.loopback_support = dev_cap->loopback_support; 229 dev->caps.loopback_support = dev_cap->loopback_support;
230 dev->caps.wol = dev_cap->wol;
230 dev->caps.max_gso_sz = dev_cap->max_gso_sz; 231 dev->caps.max_gso_sz = dev_cap->max_gso_sz;
231 232
232 dev->caps.log_num_macs = log_num_mac; 233 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 2db245fcd84b..07aea8d0beeb 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -479,6 +479,13 @@ struct mlx4_en_priv {
479 int mc_addrs_cnt; 479 int mc_addrs_cnt;
480 struct mlx4_en_stat_out_mbox hw_stats; 480 struct mlx4_en_stat_out_mbox hw_stats;
481 int vids[128]; 481 int vids[128];
482 bool wol;
483};
484
485enum mlx4_en_wol {
486 MLX4_EN_WOL_MAGIC = (1ULL << 61),
487 MLX4_EN_WOL_ENABLED = (1ULL << 62),
488 MLX4_EN_WOL_DO_MODIFY = (1ULL << 63),
482}; 489};
483 490
484 491