* [PATCH 06/17] sfc: SFT9001: Reset LED configuration correctly after blinking
From: Ben Hutchings @ 2009-11-24 2:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/tenxpress.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index 390b27b..19c78d2 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -83,9 +83,9 @@
#define PMA_PMD_LED_FLASH (3)
#define PMA_PMD_LED_MASK 3
/* All LEDs under hardware control */
-#define PMA_PMD_LED_FULL_AUTO (0)
+#define SFT9001_PMA_PMD_LED_DEFAULT 0
/* Green and Amber under hardware control, Red off */
-#define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
+#define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
#define PMA_PMD_SPEED_ENABLE_REG 49192
#define PMA_PMD_100TX_ADV_LBN 1
@@ -291,7 +291,7 @@ static int tenxpress_init(struct efx_nic *efx)
efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
1 << PMA_PMA_LED_ACTIVITY_LBN, true);
efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
- PMA_PMD_LED_DEFAULT);
+ SFX7101_PMA_PMD_LED_DEFAULT);
}
return 0;
@@ -624,7 +624,10 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink)
(PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN) |
(PMA_PMD_LED_FLASH << PMA_PMD_LED_LINK_LBN);
else
- reg = PMA_PMD_LED_DEFAULT;
+ if (efx->phy_type == PHY_TYPE_SFX7101)
+ reg = SFX7101_PMA_PMD_LED_DEFAULT;
+ else
+ reg = SFT9001_PMA_PMD_LED_DEFAULT;
efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
}
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 05/17] sfc: Record RX queue number on GRO path
From: Ben Hutchings @ 2009-11-24 2:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/rx.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 9e33391..9f22d15 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -473,6 +473,8 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
skb->ip_summed =
checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+ skb_record_rx_queue(skb, channel->channel);
+
gro_result = napi_gro_frags(napi);
} else {
struct sk_buff *skb = rx_buf->skb;
@@ -578,6 +580,8 @@ void __efx_rx_packet(struct efx_channel *channel,
* at the ethernet header */
rx_buf->skb->protocol = eth_type_trans(rx_buf->skb,
efx->net_dev);
+
+ skb_record_rx_queue(rx_buf->skb, channel->channel);
}
if (likely(checksummed || rx_buf->page)) {
@@ -593,8 +597,6 @@ void __efx_rx_packet(struct efx_channel *channel,
/* Set the SKB flags */
skb->ip_summed = CHECKSUM_NONE;
- skb_record_rx_queue(skb, channel->channel);
-
/* Pass the packet up */
netif_receive_skb(skb);
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 04/17] sfc: Move assertions and buffer cleanup earlier in efx_rx_packet_lro()
From: Ben Hutchings @ 2009-11-24 2:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
This removes the need to use a label and goto, and makes the two
branches mirror each other more closely.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/rx.c | 26 ++++++++++++++------------
1 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index c407352..9e33391 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -449,15 +449,19 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
/* Pass the skb/page into the LRO engine */
if (rx_buf->page) {
- struct sk_buff *skb = napi_get_frags(napi);
+ struct page *page = rx_buf->page;
+ struct sk_buff *skb;
+ EFX_BUG_ON_PARANOID(rx_buf->skb);
+ rx_buf->page = NULL;
+
+ skb = napi_get_frags(napi);
if (!skb) {
- put_page(rx_buf->page);
- gro_result = GRO_DROP;
- goto out;
+ put_page(page);
+ return;
}
- skb_shinfo(skb)->frags[0].page = rx_buf->page;
+ skb_shinfo(skb)->frags[0].page = page;
skb_shinfo(skb)->frags[0].page_offset =
efx_rx_buf_offset(rx_buf);
skb_shinfo(skb)->frags[0].size = rx_buf->len;
@@ -470,16 +474,14 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
gro_result = napi_gro_frags(napi);
-
-out:
- EFX_BUG_ON_PARANOID(rx_buf->skb);
- rx_buf->page = NULL;
} else {
- EFX_BUG_ON_PARANOID(!rx_buf->skb);
- EFX_BUG_ON_PARANOID(!checksummed);
+ struct sk_buff *skb = rx_buf->skb;
- gro_result = napi_gro_receive(napi, rx_buf->skb);
+ EFX_BUG_ON_PARANOID(!skb);
+ EFX_BUG_ON_PARANOID(!checksummed);
rx_buf->skb = NULL;
+
+ gro_result = napi_gro_receive(napi, skb);
}
if (gro_result == GRO_NORMAL) {
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 03/17] sfc: Remove ridiculously paranoid assertions
From: Ben Hutchings @ 2009-11-24 2:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/rx.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 32cfe40..c407352 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -586,9 +586,6 @@ void __efx_rx_packet(struct efx_channel *channel,
/* We now own the SKB */
skb = rx_buf->skb;
rx_buf->skb = NULL;
-
- EFX_BUG_ON_PARANOID(rx_buf->page);
- EFX_BUG_ON_PARANOID(rx_buf->skb);
EFX_BUG_ON_PARANOID(!skb);
/* Set the SKB flags */
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 02/17] sfc: Remove redundant gotos from __efx_rx_packet()
From: Ben Hutchings @ 2009-11-24 2:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
This function no longer has any common cleanup code.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/rx.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index a60c718..32cfe40 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -564,7 +564,7 @@ void __efx_rx_packet(struct efx_channel *channel,
if (unlikely(efx->loopback_selftest)) {
efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len);
efx_free_rx_buffer(efx, rx_buf);
- goto done;
+ return;
}
if (rx_buf->skb) {
@@ -580,7 +580,7 @@ void __efx_rx_packet(struct efx_channel *channel,
if (likely(checksummed || rx_buf->page)) {
efx_rx_packet_lro(channel, rx_buf, checksummed);
- goto done;
+ return;
}
/* We now own the SKB */
@@ -601,9 +601,6 @@ void __efx_rx_packet(struct efx_channel *channel,
/* Update allocation strategy method */
channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
-
-done:
- ;
}
void efx_rx_strategy(struct efx_channel *channel)
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH 01/17] sfc: Remove pointless abstraction of memory BAR number (2)
From: Ben Hutchings @ 2009-11-24 2:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Finish the job by removing the structure member.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/net_driver.h | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index bb3d258..bc6fb2b 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -848,7 +848,6 @@ static inline const char *efx_dev_name(struct efx_nic *efx)
/**
* struct efx_nic_type - Efx device type definition
- * @mem_bar: Memory BAR number
* @mem_map_size: Memory BAR mapped size
* @txd_ptr_tbl_base: TX descriptor ring base address
* @rxd_ptr_tbl_base: RX descriptor ring base address
@@ -863,7 +862,6 @@ static inline const char *efx_dev_name(struct efx_nic *efx)
* descriptors
*/
struct efx_nic_type {
- unsigned int mem_bar;
unsigned int mem_map_size;
unsigned int txd_ptr_tbl_base;
unsigned int rxd_ptr_tbl_base;
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* Re: macvlan: fix gso_max_size setting
From: Herbert Xu @ 2009-11-24 1:08 UTC (permalink / raw)
To: Patrick McHardy; +Cc: David Miller, netdev
In-Reply-To: <4B0B0DA1.7010403@trash.net>
On Mon, Nov 23, 2009 at 11:33:05PM +0100, Patrick McHardy wrote:
>
> Perhaps we should simply fall back to software in that case.
> Compile tested only.
Sure.
Since ixgbe appears to be the only driver in our entire tree
that has this limitation, I think it might make more sense to
move this special-case check into it and get it to do software
GSO just like tg3 does for a few other cases that the hardware
can't handle.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH 4/4] macvlan: export macvlan mode through netlink
From: Arnd Bergmann @ 2009-11-24 0:56 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Eric Dumazet, linux-kernel, netdev, David Miller,
Stephen Hemminger, Herbert Xu, Patrick Mullaney,
Eric W. Biederman, Edge Virtual Bridging, Anna Fischer, bridge,
virtualization, Jens Osterkamp, Gerhard Stenzel, Patrick McHardy,
Mark Smith, Arnd Bergmann
In-Reply-To: <1259024166-28158-1-git-send-email-arnd@arndb.de>
In order to support all three modes of macvlan at
runtime, extend the existing netlink protocol
to allow choosing the mode per macvlan slave
interface.
This depends on a matching patch to iproute2
in order to become accessible in user land.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/macvlan.c | 63 ++++++++++++++++++++++++++++++++++++++++++----
include/linux/if_link.h | 15 +++++++++++
2 files changed, 72 insertions(+), 6 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b840b3a..3db96b9 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -33,12 +33,6 @@
#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
-enum macvlan_mode {
- MACVLAN_MODE_PRIVATE = 1,
- MACVLAN_MODE_VEPA = 2,
- MACVLAN_MODE_BRIDGE = 4,
-};
-
struct macvlan_port {
struct net_device *dev;
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
@@ -600,6 +594,18 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
return -EADDRNOTAVAIL;
}
+
+ if (data && data[IFLA_MACVLAN_MODE]) {
+ u32 mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+ switch (mode) {
+ case MACVLAN_MODE_PRIVATE:
+ case MACVLAN_MODE_VEPA:
+ case MACVLAN_MODE_BRIDGE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
return 0;
}
@@ -664,6 +670,13 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
vlan->dev = dev;
vlan->port = port;
+ vlan->mode = MACVLAN_MODE_VEPA;
+ if (data && data[IFLA_MACVLAN_MODE]) {
+ u32 mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+
+ vlan->mode = mode;
+ }
+
err = register_netdevice(dev);
if (err < 0)
return err;
@@ -685,6 +698,39 @@ static void macvlan_dellink(struct net_device *dev, struct list_head *head)
macvlan_port_destroy(port->dev);
}
+static int macvlan_changelink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ if (data && data[IFLA_MACVLAN_MODE]) {
+ u32 mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+ vlan->mode = mode;
+ }
+
+ return 0;
+}
+
+static size_t macvlan_get_size(const struct net_device *dev)
+{
+ return nla_total_size(4);
+}
+
+static int macvlan_fill_info(struct sk_buff *skb,
+ const struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+
+ NLA_PUT_U32(skb, IFLA_MACVLAN_MODE, vlan->mode);
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
+ [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
+};
+
static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
.kind = "macvlan",
.priv_size = sizeof(struct macvlan_dev),
@@ -693,6 +739,11 @@ static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
.validate = macvlan_validate,
.newlink = macvlan_newlink,
.dellink = macvlan_dellink,
+ .maxtype = IFLA_MACVLAN_MAX,
+ .policy = macvlan_policy,
+ .changelink = macvlan_changelink,
+ .get_size = macvlan_get_size,
+ .fill_info = macvlan_fill_info,
};
static int macvlan_device_event(struct notifier_block *unused,
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 1d3b242..6674791 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -181,4 +181,19 @@ struct ifla_vlan_qos_mapping {
__u32 to;
};
+/* MACVLAN section */
+enum {
+ IFLA_MACVLAN_UNSPEC,
+ IFLA_MACVLAN_MODE,
+ __IFLA_MACVLAN_MAX,
+};
+
+#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
+
+enum macvlan_mode {
+ MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */
+ MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */
+ MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */
+};
+
#endif /* _LINUX_IF_LINK_H */
--
1.6.3.3
^ permalink raw reply related
* [PATCH 3/4] macvlan: implement bridge, VEPA and private mode
From: Arnd Bergmann @ 2009-11-24 0:56 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Herbert Xu, Eric Dumazet, Anna Fischer, netdev, bridge,
linux-kernel, virtualization, Mark Smith, Gerhard Stenzel,
Arnd Bergmann, Eric W. Biederman, Jens Osterkamp,
Patrick Mullaney, Stephen Hemminger, Edge Virtual Bridging,
David Miller
In-Reply-To: <1259024166-28158-1-git-send-email-arnd@arndb.de>
This allows each macvlan slave device to be in one
of three modes, depending on the use case:
MACVLAN_PRIVATE:
The device never communicates with any other device
on the same upper_dev. This even includes frames
coming back from a reflective relay, where supported
by the adjacent bridge.
MACVLAN_VEPA:
The new Virtual Ethernet Port Aggregator (VEPA) mode,
we assume that the adjacent bridge returns all frames
where both source and destination are local to the
macvlan port, i.e. the bridge is set up as a reflective
relay.
Broadcast frames coming in from the upper_dev get
flooded to all macvlan interfaces in VEPA mode.
We never deliver any frames locally.
MACVLAN_BRIDGE:
We provide the behavior of a simple bridge between
different macvlan interfaces on the same port. Frames
from one interface to another one get delivered directly
and are not sent out externally. Broadcast frames get
flooded to all other bridge ports and to the external
interface, but when they come back from a reflective
relay, we don't deliver them again.
Since we know all the MAC addresses, the macvlan bridge
mode does not require learning or STP like the bridge
module does.
Based on an earlier patch "macvlan: Reflect macvlan packets
meant for other macvlan devices" by Eric Biederman.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Eric Biederman <ebiederm@xmission.com>
---
drivers/net/macvlan.c | 75 +++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 67 insertions(+), 8 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index a0dea23..b840b3a 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -29,9 +29,16 @@
#include <linux/if_link.h>
#include <linux/if_macvlan.h>
#include <net/rtnetlink.h>
+#include <net/xfrm.h>
#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
+enum macvlan_mode {
+ MACVLAN_MODE_PRIVATE = 1,
+ MACVLAN_MODE_VEPA = 2,
+ MACVLAN_MODE_BRIDGE = 4,
+};
+
struct macvlan_port {
struct net_device *dev;
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
@@ -59,6 +66,7 @@ struct macvlan_dev {
struct macvlan_port *port;
struct net_device *lowerdev;
struct macvlan_rx_stats *rx_stats;
+ enum macvlan_mode mode;
};
@@ -129,11 +137,14 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, int length,
}
static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
- const struct ethhdr *eth)
+ const struct ethhdr *eth, int local)
{
if (!skb)
return NET_RX_DROP;
+ if (local)
+ return dev_forward_skb(dev, skb);
+
skb->dev = dev;
if (!compare_ether_addr_64bits(eth->h_dest,
dev->broadcast))
@@ -145,7 +156,9 @@ static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
}
static void macvlan_broadcast(struct sk_buff *skb,
- const struct macvlan_port *port)
+ const struct macvlan_port *port,
+ struct net_device *src,
+ enum macvlan_mode mode)
{
const struct ethhdr *eth = eth_hdr(skb);
const struct macvlan_dev *vlan;
@@ -159,8 +172,12 @@ static void macvlan_broadcast(struct sk_buff *skb,
for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
+ if ((vlan->dev == src) || !(vlan->mode & mode))
+ continue;
+
nskb = skb_clone(skb, GFP_ATOMIC);
- err = macvlan_broadcast_one(nskb, vlan->dev, eth);
+ err = macvlan_broadcast_one(nskb, vlan->dev, eth,
+ mode == MACVLAN_MODE_BRIDGE);
macvlan_count_rx(vlan, skb->len + ETH_HLEN,
likely(err == NET_RX_SUCCESS), 1);
}
@@ -173,6 +190,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
const struct ethhdr *eth = eth_hdr(skb);
const struct macvlan_port *port;
const struct macvlan_dev *vlan;
+ const struct macvlan_dev *src;
struct net_device *dev;
port = rcu_dereference(skb->dev->macvlan_port);
@@ -180,7 +198,20 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
return skb;
if (is_multicast_ether_addr(eth->h_dest)) {
- macvlan_broadcast(skb, port);
+ src = macvlan_hash_lookup(port, eth->h_source);
+ if (!src)
+ /* frame comes from an external address */
+ macvlan_broadcast(skb, port, NULL, MACVLAN_MODE_PRIVATE
+ | MACVLAN_MODE_VEPA | MACVLAN_MODE_BRIDGE);
+ else if (src->mode == MACVLAN_MODE_VEPA)
+ /* flood to everyone except source */
+ macvlan_broadcast(skb, port, src->dev,
+ MACVLAN_MODE_VEPA | MACVLAN_MODE_BRIDGE);
+ else if (src->mode == MACVLAN_MODE_BRIDGE)
+ /* flood only to VEPA ports, bridge ports
+ already saw the frame */
+ macvlan_broadcast(skb, port, src->dev,
+ MACVLAN_MODE_VEPA);
return skb;
}
@@ -203,18 +234,46 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
return NULL;
}
+static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ const struct macvlan_dev *vlan = netdev_priv(dev);
+ const struct macvlan_port *port = vlan->port;
+ const struct macvlan_dev *dest;
+
+ if (vlan->mode == MACVLAN_MODE_BRIDGE) {
+ const struct ethhdr *eth = (void *)skb->data;
+
+ /* send to other bridge ports directly */
+ if (is_multicast_ether_addr(eth->h_dest)) {
+ macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE);
+ goto xmit_world;
+ }
+
+ dest = macvlan_hash_lookup(port, eth->h_dest);
+ if (dest && dest->mode == MACVLAN_MODE_BRIDGE) {
+ int length = skb->len + ETH_HLEN;
+ int ret = dev_forward_skb(dest->dev, skb);
+ macvlan_count_rx(dest, length,
+ likely(ret == NET_RX_SUCCESS), 0);
+
+ return NET_XMIT_SUCCESS;
+ }
+ }
+
+xmit_world:
+ skb->dev = vlan->lowerdev;
+ return dev_queue_xmit(skb);
+}
+
static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
int i = skb_get_queue_mapping(skb);
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
- const struct macvlan_dev *vlan = netdev_priv(dev);
unsigned int len = skb->len;
int ret;
- skb->dev = vlan->lowerdev;
- ret = dev_queue_xmit(skb);
-
+ ret = macvlan_queue_xmit(skb, dev);
if (likely(ret == NET_XMIT_SUCCESS)) {
txq->tx_packets++;
txq->tx_bytes += len;
--
1.6.3.3
^ permalink raw reply related
* [PATCH 2/4] macvlan: cleanup rx statistics
From: Arnd Bergmann @ 2009-11-24 0:56 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Eric Dumazet, linux-kernel, netdev, David Miller,
Stephen Hemminger, Herbert Xu, Patrick Mullaney,
Eric W. Biederman, Edge Virtual Bridging, Anna Fischer, bridge,
virtualization, Jens Osterkamp, Gerhard Stenzel, Patrick McHardy,
Mark Smith, Arnd Bergmann
In-Reply-To: <1259024166-28158-1-git-send-email-arnd@arndb.de>
We have very similar code for rx statistics in
two places in the macvlan driver, with a third
one being added in the next patch.
Consolidate them into one function to improve
overall readability of the driver.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/macvlan.c | 63 +++++++++++++++++++++++++-----------------------
1 files changed, 33 insertions(+), 30 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index ae2b5c7..a0dea23 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -116,42 +116,53 @@ static int macvlan_addr_busy(const struct macvlan_port *port,
return 0;
}
+static inline void macvlan_count_rx(const struct macvlan_dev *vlan, int length,
+ int success, int multicast)
+{
+ struct macvlan_rx_stats *rx_stats;
+
+ rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
+ rx_stats->rx_packets += success != 0;
+ rx_stats->rx_bytes += success ? length : 0;
+ rx_stats->multicast += success && multicast;
+ rx_stats->rx_errors += !success;
+}
+
+static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
+ const struct ethhdr *eth)
+{
+ if (!skb)
+ return NET_RX_DROP;
+
+ skb->dev = dev;
+ if (!compare_ether_addr_64bits(eth->h_dest,
+ dev->broadcast))
+ skb->pkt_type = PACKET_BROADCAST;
+ else
+ skb->pkt_type = PACKET_MULTICAST;
+
+ return netif_rx(skb);
+}
+
static void macvlan_broadcast(struct sk_buff *skb,
const struct macvlan_port *port)
{
const struct ethhdr *eth = eth_hdr(skb);
const struct macvlan_dev *vlan;
struct hlist_node *n;
- struct net_device *dev;
struct sk_buff *nskb;
unsigned int i;
- struct macvlan_rx_stats *rx_stats;
+ int err;
if (skb->protocol == htons(ETH_P_PAUSE))
return;
for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
- dev = vlan->dev;
- rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
-
nskb = skb_clone(skb, GFP_ATOMIC);
- if (nskb == NULL) {
- rx_stats->rx_errors++;
- continue;
- }
-
- rx_stats->rx_bytes += skb->len + ETH_HLEN;
- rx_stats->rx_packets++;
- rx_stats->multicast++;
-
- nskb->dev = dev;
- if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast))
- nskb->pkt_type = PACKET_BROADCAST;
- else
- nskb->pkt_type = PACKET_MULTICAST;
-
- netif_rx(nskb);
+ err = macvlan_broadcast_one(nskb, vlan->dev, eth);
+ macvlan_count_rx(vlan, skb->len + ETH_HLEN,
+ likely(err == NET_RX_SUCCESS), 1);
}
}
}
@@ -163,7 +174,6 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
const struct macvlan_port *port;
const struct macvlan_dev *vlan;
struct net_device *dev;
- struct macvlan_rx_stats *rx_stats;
port = rcu_dereference(skb->dev->macvlan_port);
if (port == NULL)
@@ -183,15 +193,8 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
kfree_skb(skb);
return NULL;
}
- rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
skb = skb_share_check(skb, GFP_ATOMIC);
- if (skb == NULL) {
- rx_stats->rx_errors++;
- return NULL;
- }
-
- rx_stats->rx_bytes += skb->len + ETH_HLEN;
- rx_stats->rx_packets++;
+ macvlan_count_rx(vlan, skb->len + ETH_HLEN, likely(skb != NULL), 0);
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
--
1.6.3.3
^ permalink raw reply related
* [PATCH 1/4] veth: move loopback logic to common location
From: Arnd Bergmann @ 2009-11-24 0:56 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Eric Dumazet, linux-kernel, netdev, David Miller,
Stephen Hemminger, Herbert Xu, Patrick Mullaney,
Eric W. Biederman, Edge Virtual Bridging, Anna Fischer, bridge,
virtualization, Jens Osterkamp, Gerhard Stenzel, Patrick McHardy,
Mark Smith, Arnd Bergmann
In-Reply-To: <1259024166-28158-1-git-send-email-arnd@arndb.de>
The veth driver contains code to forward an skb
from the start_xmit function of one network
device into the receive path of another device.
Moving that code into a common location lets us
reuse the code for direct forwarding of data
between macvlan ports, and possibly in other
drivers.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/veth.c | 17 +++--------------
include/linux/netdevice.h | 2 ++
net/core/dev.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 2d657f2..6c4b5a2 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -155,8 +155,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
struct veth_net_stats *stats, *rcv_stats;
int length, cpu;
- skb_orphan(skb);
-
priv = netdev_priv(dev);
rcv = priv->peer;
rcv_priv = netdev_priv(rcv);
@@ -168,20 +166,12 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
if (!(rcv->flags & IFF_UP))
goto tx_drop;
- if (skb->len > (rcv->mtu + MTU_PAD))
- goto rx_drop;
-
- skb->tstamp.tv64 = 0;
- skb->pkt_type = PACKET_HOST;
- skb->protocol = eth_type_trans(skb, rcv);
if (dev->features & NETIF_F_NO_CSUM)
skb->ip_summed = rcv_priv->ip_summed;
- skb->mark = 0;
- secpath_reset(skb);
- nf_reset(skb);
-
- length = skb->len;
+ length = skb->len + ETH_HLEN;
+ if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
+ goto rx_drop;
stats->tx_bytes += length;
stats->tx_packets++;
@@ -189,7 +179,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
rcv_stats->rx_bytes += length;
rcv_stats->rx_packets++;
- netif_rx(skb);
return NETDEV_TX_OK;
tx_drop:
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 97873e3..9428793 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1562,6 +1562,8 @@ extern int dev_set_mac_address(struct net_device *,
extern int dev_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev,
struct netdev_queue *txq);
+extern int dev_forward_skb(struct net_device *dev,
+ struct sk_buff *skb);
extern int netdev_budget;
diff --git a/net/core/dev.c b/net/core/dev.c
index ccefa24..ba18e82 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -105,6 +105,7 @@
#include <net/dst.h>
#include <net/pkt_sched.h>
#include <net/checksum.h>
+#include <net/xfrm.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <linux/kmod.h>
@@ -1419,6 +1420,41 @@ static inline void net_timestamp(struct sk_buff *skb)
skb->tstamp.tv64 = 0;
}
+/**
+ * dev_forward_skb - loopback an skb to another netif
+ *
+ * @dev: destination network device
+ * @skb: buffer to forward
+ *
+ * return values:
+ * NET_RX_SUCCESS (no congestion)
+ * NET_RX_DROP (packet was dropped)
+ *
+ * dev_forward_skb can be used for injecting an skb from the
+ * start_xmit function of one device into the receive queue
+ * of another device.
+ */
+int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
+{
+ skb_orphan(skb);
+
+ if (!(dev->flags & IFF_UP))
+ return NET_RX_DROP;
+
+ if (skb->len > (dev->mtu + dev->hard_header_len))
+ return NET_RX_DROP;
+
+ skb_dst_drop(skb);
+ skb->tstamp.tv64 = 0;
+ skb->pkt_type = PACKET_HOST;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->mark = 0;
+ secpath_reset(skb);
+ nf_reset(skb);
+ return netif_rx(skb);
+}
+EXPORT_SYMBOL_GPL(dev_forward_skb);
+
/*
* Support routine. Sends outgoing frames to any network
* taps currently in use.
--
1.6.3.3
^ permalink raw reply related
* [PATCHv2 0/4] macvlan: add vepa and bridge mode
From: Arnd Bergmann @ 2009-11-24 0:56 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Eric Dumazet, linux-kernel, netdev, David Miller,
Stephen Hemminger, Herbert Xu, Patrick Mullaney,
Eric W. Biederman, Edge Virtual Bridging, Anna Fischer, bridge,
virtualization, Jens Osterkamp, Gerhard Stenzel, Patrick McHardy,
Mark Smith, Arnd Bergmann
Second version, all feedback so far addressed, thanks for the
help and interest!
The patch to iproute2 has not changed, so I'm not including
it this time. Patch 4/4 (the netlink interface) is basically
unchanged as well but included for completeness.
The other changes have moved forward a bit, to the point where
I find them a lot cleaner and am more confident in the code
being ready for inclusion. The implementation hardly resembles
Erics original patch now, so I've dropped his signed-off-by.
Please take a look and ack if you are happy so we can get it
into 2.6.33.
---
Version 1 description:
This is based on an earlier patch from Eric Biederman adding
forwarding between macvlans. I extended his approach to
allow the administrator to choose the mode for each macvlan,
and to implement a functional VEPA between macvlan.
Still missing from this is support for communication between
the lower device that the macvlans are based on. This would
be extremely useful but as others have found out before me
requires significant changes not only to macvlan but also
to the common transmit path.
I've tested VEPA operation with the hairpin support
added to the bridge driver by Anna Fischer.
Arnd <><
Arnd Bergmann (4):
veth: move loopback logic to common location
macvlan: cleanup rx statistics
macvlan: implement bridge, VEPA and private mode
macvlan: export macvlan mode through netlink
drivers/net/macvlan.c | 183 ++++++++++++++++++++++++++++++++++++---------
drivers/net/veth.c | 17 +----
include/linux/if_link.h | 15 ++++
include/linux/netdevice.h | 2 +
net/core/dev.c | 36 +++++++++
5 files changed, 204 insertions(+), 49 deletions(-)
^ permalink raw reply
* Re: icmp redirects problem
From: Alex Samad @ 2009-11-24 0:12 UTC (permalink / raw)
To: Jarek Poplawski; +Cc: netdev
In-Reply-To: <4B0B058E.3050906@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1965 bytes --]
On Mon, Nov 23, 2009 at 10:58:38PM +0100, Jarek Poplawski wrote:
> Alex Samad wrote, On 11/23/2009 05:31 AM:
>
[snip]
> >
> > laptop gets its ip from dchp server that make 192.168.11.1 the default
> > gateway and its 192.168.11.1 that sends out the icmp redirect.
>
> Btw, it seems you should fix your routing (by adding sydrt01's eth0
> the second ip or advertising 192.168.11.10 more) to avoid those
> redirects.
sorry I am lost on this statement, I can't add 192.168.11.10 to sydrt01
as it is not physically connected to the 192.168.10.0/24 any more, which
is why I had added the route on sydrt01 and which is why it send
icmp_rediercts.
I have updated the route table on each static machine, but the problem
is on the machines that get their ip via dhcp - I haven't looked at
pushing out route information via dhcp - I am not sure that it would
work in a mixed windows / linux environment.
what do you mean by advertising 192.168.11.10 more ?
>
> >
> > I had a quick look at the kernel tree for 2.6.31 (which is what I am
> > using).
>
> ...
>
> > Line 680
> > secure_redirects - BOOLEAN
> > 681 Accept ICMP redirect messages only for gateways,
> > 682 listed in default gateway list.
> > 683 secure_redirects for the interface will be enabled if at
> > least one of
> > 684 conf/{all,interface}/secure_redirects is set to TRUE,
> > 685 it will be disabled otherwise
> > 686 default TRUE
>
> Very helpful links. So, as you wrote "the documentation seems to suggest"
> something, and IMHO even if it doesn't, it's needlessly too concise
> considering your "lost time", and I'd suggest you sending a patch to fix
> this. (It seems it could "touch" shared_media, as well.)
Which is wrong the code or the documentation and which part the test or
the reliance on the shared_media or on the redirects flags
>
> Thanks,
> Jarek P.
>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: ixgbe question
From: David Miller @ 2009-11-23 23:44 UTC (permalink / raw)
To: peter.p.waskiewicz.jr; +Cc: eric.dumazet, robert, hawk, netdev
In-Reply-To: <Pine.WNT.4.64.0911231525180.10056@ppwaskie-MOBL2.amr.corp.intel.com>
From: "Waskiewicz Jr, Peter P" <peter.p.waskiewicz.jr@intel.com>
Date: Mon, 23 Nov 2009 15:28:18 -0800 (Pacific Standard Time)
> Do you know what version of irqbalance you're running, or if it's running
> at all?
Eric said he tried both with and without irqbalanced.
^ permalink raw reply
* Re: [PATCH] irq: Add node_affinity CPU masks for smarter irqbalance hints
From: Waskiewicz Jr, Peter P @ 2009-11-23 23:32 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Waskiewicz Jr, Peter P, Yong Zhang, linux-kernel@vger.kernel.org,
arjan@linux.jf.intel.com, davem@davemloft.net,
netdev@vger.kernel.org
In-Reply-To: <1258995923.4531.715.camel@laptop>
On Mon, 23 Nov 2009, Peter Zijlstra wrote:
> On Mon, 2009-11-23 at 01:36 -0800, Peter P Waskiewicz Jr wrote:
>
> > This mechanism isn't going to be used by any internal kernel mechanism
> > for determining interrupt placement or operation. It's purely something
> > that either a driver can modify, or external script (through /proc),
> > that irqbalance will make use of. If irqbalance isn't running, or the
> > current version of irqbalance doesn't support reading node_affinity,
> > then it won't affect the system's operation.
> >
> > If irqbalance does support it, it'll read whatever the supplied mask is,
> > and then will try and balance interrupts within that mask. It will bail
> > if the mask is invalid, or won't apply to the running system, just like
> > how putting a bogus mask into smp_affinity is ignored.
> >
> > If there's something I'm missing beyond this with the two suggestions
> > you've made (I looked into those two parameters and tried to draw
> > conclusions), please let me know.
>
> I don't see the point in adding it, if the driver wants to set a node
> cpu mask it can already do that using the regular smp affinity settings.
Unfortunately, a driver can't. The irq_set_affinity() function isn't
exported. I proposed a patch on netdev to export it, and then to tie down
an interrupt using IRQF_NOBALANCING, so irqbalance won't touch it. That
was rejected, since the driver is enforcing policy of the interrupt
balancing, not irqbalance.
I and Jesse Brandeburg had a meeting with Arjan about this. What we came
up with was this interface, so drivers can set what they'd like to see, if
irqbalance decides to honor it. That way interrupt affinity policies are
set only by irqbalance, but this interface gives us a mechanism to hint to
irqbalance what we'd like it to do.
Also, if you use the /proc interface to change smp_affinity on an
interrupt without any of these changes, irqbalance will override it on its
next poll interval. This also is not desirable.
Cheers,
-PJ
^ permalink raw reply
* Re: ixgbe question
From: Waskiewicz Jr, Peter P @ 2009-11-23 23:28 UTC (permalink / raw)
To: Eric Dumazet
Cc: robert@herjulf.net, Jesper Dangaard Brouer,
Waskiewicz Jr, Peter P, Linux Netdev List
In-Reply-To: <4B0ABF6D.9000103@gmail.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 2301 bytes --]
On Mon, 23 Nov 2009, Eric Dumazet wrote:
> robert@herjulf.net a écrit :
> > Eric Dumazet writes:
> >
> > > Jesper Dangaard Brouer a écrit :
> > >
> > > > How is your smp_affinity mask's set?
> > > >
> > > > grep . /proc/irq/*/fiber1-*/../smp_affinity
> > >
> >
> > Weird... set clone_skb to 1 to be sure and vary dst or something so
> > the HW classifier selects different queues and with proper RX affinty.
> >
> > You should see in /proc/net/softnet_stat something like:
> >
> > 012a7bb9 00000000 000000ae 00000000 00000000 00000000 00000000 00000000 00000000
> > 01288d4c 00000000 00000049 00000000 00000000 00000000 00000000 00000000 00000000
> > 0128fe28 00000000 00000043 00000000 00000000 00000000 00000000 00000000 00000000
> > 01295387 00000000 00000047 00000000 00000000 00000000 00000000 00000000 00000000
> > 0129a722 00000000 0000004a 00000000 00000000 00000000 00000000 00000000 00000000
> > 0128c5e4 00000000 00000046 00000000 00000000 00000000 00000000 00000000 00000000
> > 0128f718 00000000 00000043 00000000 00000000 00000000 00000000 00000000 00000000
> > 012993e3 00000000 0000004a 00000000 00000000 00000000 00000000 00000000 00000000
> >
>
> slone_skb set to 1, this changes nothing but slows down pktgen (obviously)
>
> Result: OK: 117614452(c117608705+d5746) nsec, 100000000 (60byte,0frags)
> 850235pps 408Mb/sec (408112800bps) errors: 0
>
> All RX processing of 16 RX queues done by CPU 1 only.
Ok, I was confused earlier. I thought you were saying that all packets
were headed into a single Rx queue. This is different.
Do you know what version of irqbalance you're running, or if it's running
at all? We've seen issues with irqbalance where it won't recognize the
ethernet device if the driver has been reloaded. In that case, it won't
balance the interrupts at all. If the default affinity was set to one
CPU, then well, you're screwed.
My suggestion in this case is after you reload ixgbe and start your tests,
see if it all goes to one CPU. If it does, then restart irqbalance
(service irqbalance restart - or just kill it and restart by hand). Then
start running your test, and in 10 seconds you should see the interrupts
move and spread out.
Let me know if this helps,
-PJ
^ permalink raw reply
* Re: [PATCH 1/1] Defer skb allocation for both mergeable buffers and big packets in virtio_net
From: Shirley Ma @ 2009-11-23 23:27 UTC (permalink / raw)
To: Rusty Russell
Cc: Eric Dumazet, Michael S. Tsirkin, Avi Kivity, netdev, kvm,
linux-kernel, Hollis Blanchard
In-Reply-To: <200911240854.24054.rusty@rustcorp.com.au>
On Tue, 2009-11-24 at 08:54 +1030, Rusty Russell wrote:
> #define BIG_PACKET_PAD (NET_SKB_PAD - sizeof(struct virtio_net_hdr) +
> NET_IP_ALIGN)
> struct big_packet_page {
> struct virtio_net_hdr hdr;
> char pad[BIG_PACKET_PAD];
> /* Actual packet data starts here */
> unsigned char data[PAGE_SIZE - BIG_PACKET_PAD - sizeof(struct
> virtio_net_hdr)];
> };
The padding was used for qemu userspace buffer copy, skb data is copied
from the page for size of GOOD_COPY_LEN, and skb data is reserved
NET_IP_ALIGN.
If we add paddings as above, userspace copy will starts NET_SKB_PAD +
NET_IP_ALIGN? I am little bit confused here.
> Then use this type as the template for registering the sg list for the
> big packet case.
>
> > > I think you can move the memcpy outside the if, like so:
> > >
> > > memcpy(&hdr, p, hdr_len);
> >
> > I didn't move it out, because num_buf = hdr->mhdr.num_buffers;
>
> Yes, that has to stay inside, but the memcpy can move out. It's just
> a bit
> neater to have more common code.
num_buf is assigned after memcpy so we couldn't move memcpy out.
Anyway I separated mergeable buffers and big packets in the new patch to
make it clear and it will be easy to modify when we drop big packets
support in the future.
Thanks
Shirley
^ permalink raw reply
* Diagnostic Monitoring Interface Monitoring (DOM) PATCH 2/5 for net-next-2.6
From: Robert Olsson @ 2009-11-23 22:51 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Robert Olsson
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index edd03b7..d2a729b 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -272,6 +272,53 @@ struct ethtool_stats {
__u64 data[0];
};
+/* Diagmostic Monitoring Interface Data -- DOM */
+struct ethtool_phy_diag {
+ __u32 cmd;
+ /* A0 page */
+ __u16 type;
+ __u16 wavelength;
+ /* A2 page */
+ __u16 alarm;
+ __u16 warning;
+ __s16 temp;
+ __u16 temp_slope;
+ __s16 temp_offset;
+ __u16 vcc;
+ __u16 vcc_slope;
+ __s16 vcc_offset;
+ __u16 tx_bias;
+ __u16 tx_bias_slope;
+ __s16 tx_bias_offset;
+ __u16 tx_pwr;
+ __u16 tx_pwr_slope;
+ __s16 tx_pwr_offset;
+ __u16 rx_pwr;
+ __u32 rx_pwr_cal[5];
+
+ /* Thresholds */
+ __s16 temp_alt;
+ __s16 temp_aht;
+ __s16 temp_wlt;
+ __s16 temp_wht;
+ __u16 vcc_alt;
+ __u16 vcc_aht;
+ __u16 vcc_wlt;
+ __u16 vcc_wht;
+ __u16 tx_bias_alt;
+ __u16 tx_bias_aht;
+ __u16 tx_bias_wlt;
+ __u16 tx_bias_wht;
+ __u16 tx_pwr_alt;
+ __u16 tx_pwr_aht;
+ __u16 tx_pwr_wlt;
+ __u16 tx_pwr_wht;
+ __u16 rx_pwr_alt;
+ __u16 rx_pwr_aht;
+ __u16 rx_pwr_wlt;
+ __u16 rx_pwr_wht;
+};
+
struct ethtool_perm_addr {
__u32 cmd; /* ETHTOOL_GPERMADDR */
__u32 size;
@@ -499,6 +546,7 @@ struct ethtool_ops {
int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
int (*flash_device)(struct net_device *, struct ethtool_flash *);
int (*reset)(struct net_device *, u32 *);
+ int (*get_phy_diag)(struct net_device *, struct ethtool_phy_diag*);
};
#endif /* __KERNEL__ */
@@ -557,6 +605,7 @@ struct ethtool_ops {
#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
#define ETHTOOL_RESET 0x00000034 /* Reset hardware */
+#define ETHTOOL_GPHYDIAG 0x00000035 /* Get PHY diagnostics */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index d8aee58..f4a1eae 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -893,6 +893,21 @@ static int ethtool_flash_device(struct net_device *dev, char __user *useraddr)
return dev->ethtool_ops->flash_device(dev, &efl);
}
+static int ethtool_phy_diag(struct net_device *dev, void __user *useraddr)
+{
+ struct ethtool_phy_diag pd;
+
+ if (!dev->ethtool_ops->get_phy_diag)
+ return -EOPNOTSUPP;
+
+ dev->ethtool_ops->get_phy_diag(dev, &pd); /* FIXME */
+
+ if (copy_to_user(useraddr, &pd, sizeof(pd)))
+ return -EFAULT;
+
+ return 0;
+}
+
/* The main entry point in this file. Called from net/core/dev.c */
int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -1112,6 +1127,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_RESET:
rc = ethtool_reset(dev, useraddr);
break;
+ case ETHTOOL_GPHYDIAG:
+ rc = ethtool_phy_diag(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
^ permalink raw reply related
* Re: linux-next: manual merge of the net tree with the net-current tree
From: Stephen Rothwell @ 2009-11-23 23:17 UTC (permalink / raw)
To: Amit Salecha
Cc: David Miller, netdev@vger.kernel.org, linux-next@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <99737F4847ED0A48AECC9F4A1974A4B80CFE956C25@MNEXMB2.qlogic.org>
[-- Attachment #1: Type: text/plain, Size: 285 bytes --]
Hi Amit,
On Mon, 23 Nov 2009 12:09:10 -0600 Amit Salecha <amit.salecha@qlogic.com> wrote:
>
> This merge looks ok and I have tested it.
Thanks for the confirmation.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Diagnostic Monitoring Interface Monitoring (DOM) PATCH 1/5 for net-next-2.6
From: Robert Olsson @ 2009-11-23 22:49 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Robert Olsson
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
diff --git a/Documentation/networking/dom.txt b/Documentation/networking/dom.txt
new file mode 100644
index 0000000..ff255b4
--- /dev/null
+++ b/Documentation/networking/dom.txt
@@ -0,0 +1,41 @@
+Diagnostic Monitoring Interface Monitoring also called DOM is a specification
+for optical transceivers to allow link and other diagnostics related to the
+transceiver's to standardized and communicated. For communication the I2C
+bus is used. The SFF specifications is available at ftp://ftp.seagate.com/
+Specification is generic and should work for many types of optical modules
+as GBIC, SFP, SFp+, XFP etc
+
+In short DOM spec adds a memory page where the diagnostics's is kept (address
+0xA2 bytes 66 to 105) but there are lot's of option's and variants. For example
+alarm and warnings are optional. See example below.
+
+Not all SFP's (SFP is for GIGE) have DOM support normally long range supports
+DOM. And of course your board and driver needs this support too.
+For SFP+ (10G) DOM is mandatory.
+
+Linux kernel support is via ethertool.
+
+include/net/dom.h # Basic definitions
+net/core/ethtool.c # adds ethtool_phy_diag()
+include/linux/ethtool.h # adds ETHTOOL_GPHYDIAG
+
+And drivers hooks exists currently in igb and ixgbe driver
+
+Usage example: ethtool -D eth5
+
+Ext-Calbr: Avr RX-Power: Alarm & Warn: RX_LOS: Wavelength: 1310 nm
+Alarms, warnings in beginning of line, Ie. AH = Alarm High, WL == Warn Low etc
+ Temp: 35.9 C Thresh: Lo: -12.0/-8.0 Hi: 103.0/110.0 C
+ Vcc: 3.33 V Thresh: Lo: 3.0/3.0 Hi: 3.7/4.0 V
+ Tx-Bias: 13.4 mA Thresh: Lo: 2.0/4.0 Hi: 70.0/84.0 mA
+ALWL TX-pwr: -5.9 dBm ( 0.26 mW) Thresh: Lo: -4.0/-2.0 Hi: 7.0/8.2 dBm
+AHWH RX-pwr: -5.0 dBm ( 0.31 mW) Thresh: Lo: -35.2/-28.0 Hi: -8.2/-6.0 dBm
+
+
+First line shows the options supported by the module. As we see this module
+supports Alarms and warnings as a consequence thresholds are printed. As example
+RX-pwr: -35.2 < no_alarm < -6.0 dBm and -28.0 < no_warning < -8.2 dBm. (dBm yields
+1 mW == 0 dBm)
+
+In the example above we see both warnings for both TX-pwr (low) and RX-Pwr high.
+The Rx side would need some attenuation.
diff --git a/include/net/dom.h b/include/net/dom.h
new file mode 100644
index 0000000..4c118a9
--- /dev/null
+++ b/include/net/dom.h
@@ -0,0 +1,109 @@
+#ifndef _LINUX_DOM_H
+#define _LINUX_DOM_H
+
+/*
+ Diagnostic Monitoring Interface for Optical Tranceivers
+ SFF-8472 v. 10.4 (Jan 2009)
+ ftp://ftp.seagate.com/sff/SFF-8472.PDF
+
+ Licensce GPL. Copyright Robert Olsson robert@herjulf.net
+*/
+
+#define DOM_A0_IDENTIFIER 0
+#define DOM_A0_WAVELENGTH 60
+#define DOM_A0_CC_BASE 63
+#define DOM_A0_DOM_TYPE 92
+
+/* DOM_TYPE codings in DOM_A0_DOM_TYPE */
+#define DOM_TYPE_LEGAGY_DOM (1<<7)
+#define DOM_TYPE_DOM (1<<6) /* Has DOM support */
+#define DOM_TYPE_INT_CAL (1<<5) /* Internally calibrated */
+#define DOM_TYPE_EXT_CAL (1<<4) /* Externally calibrated */
+#define DOM_TYPE_RX_PWR (1<<3) /* Received Power OMA=0, 1=average */
+#define DOM_TYPE_ADDR_CHNGE (1<<2) /* Address change required */
+
+#define DOM_A0_EO 93 /* Enhanced options */
+#define DOM_EO_AW (1<<7) /* Alarm & Warnings */
+#define DOM_EO_TX_DISABLE (1<<6)
+#define DOM_EO_TX_FAULT (1<<5)
+#define DOM_EO_RX_LOS (1<<4)
+#define DOM_EO_RATE_SELECT_MON (1<<3)
+#define DOM_EO_APP_SELECT (1<<2)
+#define DOM_EO_RATE_SELECT (1<<1)
+
+#define DOM_A0_CC_EXT 95
+
+#define DOM_A2_TEMP_AHT 0 /* Temp alarm high threshold */
+#define DOM_A2_TEMP_ALT 2
+#define DOM_A2_TEMP_WHT 4 /* Temp warning high threshold */
+#define DOM_A2_TEMP_WLT 6
+
+#define DOM_A2_VCC_AHT 8 /* VCC alarm high threshold */
+#define DOM_A2_VCC_ALT 10
+#define DOM_A2_VCC_WHT 12 /* VCC warning high threshold */
+#define DOM_A2_VCC_WLT 14
+
+#define DOM_A2_TX_BIAS_AHT 16 /* TX_BIAS alarm high threshold */
+#define DOM_A2_TX_BIAS_ALT 18
+#define DOM_A2_TX_BIAS_WHT 20 /* TX_BIAS warning high threshold */
+#define DOM_A2_TX_BIAS_WLT 22
+
+#define DOM_A2_TX_PWR_AHT 24 /* TX_PWR alarm high threshold */
+#define DOM_A2_TX_PWR_ALT 26
+#define DOM_A2_TX_PWR_WHT 28 /* TX_PWR warning high threshold */
+#define DOM_A2_TX_PWR_WLT 30
+
+#define DOM_A2_RX_PWR_AHT 32 /* RX_PWR alarm high threshold */
+#define DOM_A2_RX_PWR_ALT 34
+#define DOM_A2_RX_PWR_WHT 36 /* RX_PWR warning high threshold */
+#define DOM_A2_RX_PWR_WLT 38
+
+#define DOM_A2_RX_PWR_4 56 /* 4 bytes Calibration constants*/
+#define DOM_A2_RX_PWR_3 60 /* 4 bytes */
+#define DOM_A2_RX_PWR_2 64 /* 4 bytes */
+#define DOM_A2_RX_PWR_1 68 /* 4 bytes */
+#define DOM_A2_RX_PWR_0 72 /* 4 bytes */
+
+#define DOM_A2_TX_I_SLOPE 76 /* 2 bytes */
+#define DOM_A2_TX_I_OFFSET 78 /* 2 bytes */
+#define DOM_A2_TX_PWR_SLOPE 80 /* 2 bytes */
+#define DOM_A2_TX_PWR_OFFSET 82 /* 2 bytes */
+#define DOM_A2_TEMP_SLOPE 84 /* 2 bytes */
+#define DOM_A2_TEMP_OFFSET 86 /* 2 bytes */
+#define DOM_A2_VCC_SLOPE 88 /* 2 bytes */
+#define DOM_A2_VCC_OFFSET 90 /* 2 bytes */
+
+#define DOM_A2_CC_DMI 95
+#define DOM_A2_TEMP 96 /* 2 bytes */
+#define DOM_A2_VCC 98 /* 2 bytes */
+#define DOM_A2_TX_BIAS 100 /* 2 bytes */
+#define DOM_A2_TX_PWR 102 /* 2 bytes */
+#define DOM_A2_RX_PWR 104 /* 2 bytes */
+
+#define DOM_A2_ALARM 112 /* 2 bytes */
+#define DOM_TYPE_TEMP_AH (1<<7) /* Temp alarm high */
+#define DOM_TYPE_TEMP_AL (1<<6) /* low */
+#define DOM_TYPE_VCC_AH (1<<5)
+#define DOM_TYPE_VCC_AL (1<<4)
+#define DOM_TYPE_TX_BIAS_AH (1<<3)
+#define DOM_TYPE_TX_BIAS_AL (1<<2)
+#define DOM_TYPE_TX_PWR_AH (1<<1)
+#define DOM_TYPE_TX_PWR_AL (1<<0)
+/* Next byte 113 */
+#define DOM_TYPE_RX_PWR_AH (1<<7)
+#define DOM_TYPE_RX_PWR_AL (1<<6)
+
+#define DOM_A2_WARNING 116 /* 2 bytes */
+#define DOM_TYPE_TEMP_WH (1<<7) /* Temp warning high */
+#define DOM_TYPE_TEMP_WL (1<<6) /* low */
+#define DOM_TYPE_VCC_WH (1<<5)
+#define DOM_TYPE_VCC_WL (1<<4)
+#define DOM_TYPE_TX_BIAS_WH (1<<3)
+#define DOM_TYPE_TX_BIAS_WL (1<<2)
+#define DOM_TYPE_TX_PWR_WH (1<<1)
+#define DOM_TYPE_TX_PWR_WL (1<<0)
+/* Next byte 117 */
+#define DOM_TYPE_RX_PWR_WH (1<<7)
+#define DOM_TYPE_RX_PWR_WL (1<<6)
+
+#endif /* _LINUX_DOM_H */
^ permalink raw reply related
* Re: Diagnostic Monitoring Interface Monitoring (DOM) PATCH 4/5 for net-next-2.6
From: Joe Perches @ 2009-11-23 23:07 UTC (permalink / raw)
To: Robert Olsson; +Cc: David Miller, netdev
In-Reply-To: <19211.4849.284727.703717@gargle.gargle.HOWL>
On Mon, 2009-11-23 at 23:55 +0100, Robert Olsson wrote:
> Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Can you run ./scripts/checkpatch.pl on your patches please?
> + if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_SLOPE, &pd->temp_slope)))
> + goto out;
[etc...]
> + if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_OFFSET, &pd->tx_bias_offset)))
> + goto out;
perhaps this is clearer as:
if (read_phy_diag(hw, 0x1, reg, loc) ||
read_phy_diag(hw, 0x1, reg2, loc2) ||
...
read_phy_diag(hw, 0x1, regN, locN))
goto out;
^ permalink raw reply
* Diagnostic Monitoring Interface Monitoring (DOM) PATCH 5/5 for net-next-2.6
From: Robert Olsson @ 2009-11-23 22:58 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Robert Olsson
Ethtool support.
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Cheers
--ro
diff --git a/Makefile.am b/Makefile.am
index eac65fe..0988a6c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,5 @@
AM_CFLAGS = -Wall
+AM_LDLAGS = -lm
man_MANS = ethtool.8
EXTRA_DIST = LICENSE ethtool.8 ethtool.spec.in aclocal.m4 ChangeLog autogen.sh
diff --git a/ethtool-copy.h b/ethtool-copy.h
index 3ca4e2c..90ea1cb 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -266,6 +266,54 @@ struct ethtool_stats {
__u64 data[0];
};
+/* Diagmostic Monitoring Interface Data -- DOM */
+struct ethtool_phy_diag {
+ __u32 cmd;
+ /* A0 page */
+ __u16 type;
+ __u16 wavelength;
+ /* A2 page */
+ __u16 alarm;
+ __u16 warning;
+ __s16 temp;
+ __u16 temp_slope;
+ __s16 temp_offset;
+ __u16 vcc;
+ __u16 vcc_slope;
+ __s16 vcc_offset;
+ __u16 tx_bias;
+ __u16 tx_bias_slope;
+ __s16 tx_bias_offset;
+ __u16 tx_pwr;
+ __u16 tx_pwr_slope;
+ __s16 tx_pwr_offset;
+ __u16 rx_pwr;
+ __u32 rx_pwr_cal[5];
+
+ /* Thresholds */
+ __s16 temp_alt;
+ __s16 temp_aht;
+ __s16 temp_wlt;
+ __s16 temp_wht;
+ __u16 vcc_alt;
+ __u16 vcc_aht;
+ __u16 vcc_wlt;
+ __u16 vcc_wht;
+ __u16 tx_bias_alt;
+ __u16 tx_bias_aht;
+ __u16 tx_bias_wlt;
+ __u16 tx_bias_wht;
+ __u16 tx_pwr_alt;
+ __u16 tx_pwr_aht;
+ __u16 tx_pwr_wlt;
+ __u16 tx_pwr_wht;
+ __u16 rx_pwr_alt;
+ __u16 rx_pwr_aht;
+ __u16 rx_pwr_wlt;
+ __u16 rx_pwr_wht;
+};
+
+
struct ethtool_perm_addr {
__u32 cmd; /* ETHTOOL_GPERMADDR */
__u32 size;
diff --git a/ethtool-util.h b/ethtool-util.h
index 5572771..1a69426 100644
--- a/ethtool-util.h
+++ b/ethtool-util.h
@@ -9,7 +9,9 @@
typedef unsigned long long __u64;
typedef __uint32_t __u32; /* ditto */
typedef __uint16_t __u16; /* ditto */
+typedef __int16_t __s16; /* ditto */
typedef __uint8_t __u8; /* ditto */
+typedef __int8_t __s8; /* ditto */
/* historical: we used to use kernel-like types; remove these once cleaned */
typedef unsigned long long u64;
diff --git a/ethtool.c b/ethtool.c
index 0110682..caa9f6c 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -14,6 +14,7 @@
* amd8111e support by Reeja John <reeja.john@amd.com>
* long arguments by Andi Kleen.
* SMSC LAN911x support by Steve Glendinning <steve.glendinning@smsc.com>
+ * Diagnostic Monitoring Interface Support by Robert Olsson <robert@herjulf.net>
*
* TODO:
* * no-args => summary of each device (mii-tool style)
@@ -38,8 +39,9 @@
#include <errno.h>
#include <net/if.h>
#include <sys/utsname.h>
-
#include <linux/sockios.h>
+#include "dom.h"
+
#include "ethtool-util.h"
@@ -78,6 +80,7 @@ static int dump_rxfhash(int fhash, u64 val);
static int do_srxclass(int fd, struct ifreq *ifr);
static int do_grxclass(int fd, struct ifreq *ifr);
static int send_ioctl(int fd, struct ifreq *ifr);
+static int do_phy_diag(int fd, struct ifreq *ifr);
static enum {
MODE_HELP = -1,
@@ -101,6 +104,7 @@ static enum {
MODE_GSTATS,
MODE_GNFC,
MODE_SNFC,
+ MODE_PHY_DIAG
} mode = MODE_GSET;
static struct option {
@@ -184,6 +188,7 @@ static struct option {
{ "-t", "--test", MODE_TEST, "Execute adapter self test",
" [ online | offline ]\n" },
{ "-S", "--statistics", MODE_GSTATS, "Show adapter statistics" },
+ { "-D", "--phy_diag", MODE_PHY_DIAG, "Show PHY diagnostics" },
{ "-n", "--show-nfc", MODE_GNFC, "Show Rx network flow classification"
"options",
" [ rx-flow-hash tcp4|udp4|ah4|sctp4|"
@@ -496,7 +501,8 @@ static void parse_cmdline(int argc, char **argp)
(mode == MODE_GSTATS) ||
(mode == MODE_GNFC) ||
(mode == MODE_SNFC) ||
- (mode == MODE_PHYS_ID)) {
+ (mode == MODE_PHYS_ID) ||
+ (mode == MODE_PHY_DIAG)) {
devname = argp[i];
break;
}
@@ -1504,6 +1510,8 @@ static int doit(void)
return do_grxclass(fd, &ifr);
} else if (mode == MODE_SNFC) {
return do_srxclass(fd, &ifr);
+ } else if (mode == MODE_PHY_DIAG) {
+ return do_phy_diag(fd, &ifr);
}
return 69;
@@ -2403,6 +2411,287 @@ static int send_ioctl(int fd, struct ifreq *ifr)
return ioctl(fd, SIOCETHTOOL, ifr);
}
+static int do_phy_diag(int fd, struct ifreq *ifr)
+{
+ int err, ecal = 0, aw = 0;
+ double tmp, alt=0, aht=0, wlt=0, wht=0;
+ __u8 type, option, alarm[2], warn[2];
+
+
+ struct ethtool_phy_diag pd;
+
+ pd.cmd = ETHTOOL_GPHYDIAG;
+ ifr->ifr_data = (caddr_t)&pd;
+ err = ioctl(fd, SIOCETHTOOL, ifr);
+ if (err < 0) {
+ perror("Cannot get PHY diagnostics");
+ return 0;
+ }
+
+ type = pd.type >> 8;
+
+ if( ~(type) & DOM_TYPE_DOM || type & DOM_TYPE_LEGAGY_DOM) {
+ fprintf(stdout, "PHY Diagnostics not supported:\n");
+ return 0;
+ }
+
+ if(type & DOM_TYPE_INT_CAL)
+ fprintf(stdout, "Int-Calbr: ");
+
+ if(type & DOM_TYPE_EXT_CAL) {
+ fprintf(stdout, "Ext-Calbr: ");
+ ecal = 1;
+ }
+
+ if(type & DOM_TYPE_RX_PWR)
+ fprintf(stdout, "Avr RX-Power: ");
+ else
+ fprintf(stdout, "OMA RX-Power: ");
+
+ if(type & DOM_TYPE_ADDR_CHNGE)
+ fprintf(stdout,"Addr Change: ");
+
+ /* Check options */
+ option = pd.type & 0x00FF;
+
+ if(option & DOM_EO_AW) {
+ fprintf(stdout, "Alarm & Warn: ");
+ aw = 1;
+ }
+
+ if(option & DOM_EO_TX_DISABLE)
+ fprintf(stdout, "TX_DISABLE: ");
+
+ if(option & DOM_EO_TX_FAULT)
+ fprintf(stdout, "TX_FAULT: ");
+
+ if(option & DOM_EO_RX_LOS)
+ fprintf(stdout, "RX_LOS: ");
+
+ if(option & DOM_EO_RATE_SELECT_MON)
+ fprintf(stdout, "RATE_SELECT MON: ");
+
+ if(option & DOM_EO_APP_SELECT)
+ fprintf(stdout, "RATE_SELECT: ");
+
+ if(option & DOM_EO_RATE_SELECT)
+ fprintf(stdout, "RATE_SELECT: ");
+
+ if(aw) {
+ alarm[0] = pd.alarm >> 8;
+ alarm[1] = pd.alarm & 0x00FF;;
+
+ warn[0] = pd.warning >> 8;
+ warn[1] = pd.warning & 0x00FF;
+ }
+
+
+ fprintf(stdout, "\tWavelength: %d nm\n", pd.wavelength);
+
+ if(aw)
+ fprintf(stdout, "Alarms, warnings in beginning of line, Ie. AH = Alarm High, WL == Warn Low etc\n");
+
+
+#define ECAL(v, s, o) (( ((double) (s>>8)) + (s & 0xFF)) * (double) v + o)
+
+ /* Temp */
+
+ if (ecal) {
+ tmp = ECAL(pd.temp, pd.temp_slope, pd.temp_offset);
+ if(aw) {
+ alt = ECAL(pd.temp_alt, pd.temp_slope, pd.temp_offset);
+ aht = ECAL(pd.temp_aht, pd.temp_slope, pd.temp_offset);
+ wlt = ECAL(pd.temp_wlt, pd.temp_slope, pd.temp_offset);
+ wht = ECAL(pd.temp_wht, pd.temp_slope, pd.temp_offset);
+ }
+
+ }
+ else
+ tmp = (double) (pd.temp);
+
+ if(aw) {
+ if(alarm[0] & DOM_TYPE_TEMP_AH)
+ fprintf(stdout, "AH");
+
+ if(alarm[0] & DOM_TYPE_TEMP_AL)
+ fprintf(stdout, "AL");
+
+ if(warn[0] & DOM_TYPE_TEMP_WH)
+ fprintf(stdout, "WH");
+
+ if(warn[0] & DOM_TYPE_TEMP_WL)
+ fprintf(stdout, "WL");
+ }
+ fprintf(stdout, "\tTemp: %5.1f C", tmp/256);
+ if(aw)
+ fprintf(stdout, "\t\t\tThresh: Lo: %5.1f/%-5.1f Hi: %5.1f/%-5.1f C\n",
+ alt/256, wlt/256, wht/256, aht/256);
+ else
+ fprintf(stdout, "\n");
+
+
+
+ /* VCC */
+
+ if (ecal) {
+ tmp = ECAL(pd.vcc, pd.vcc_slope, pd.vcc_offset);
+ if(aw) {
+ alt = ECAL(pd.vcc_alt, pd.vcc_slope, pd.temp_offset);
+ aht = ECAL(pd.vcc_aht, pd.vcc_slope, pd.temp_offset);
+ wlt = ECAL(pd.vcc_wlt, pd.vcc_slope, pd.temp_offset);
+ wht = ECAL(pd.vcc_wht, pd.vcc_slope, pd.temp_offset);
+ }
+ }
+ else
+ tmp = (double) (pd.vcc);
+
+ fprintf(stdout, "\tVcc: %5.2f V\t", tmp/10000);
+ if(1)
+ fprintf(stdout, "\t\tThresh: Lo: %5.1f/%-5.1f Hi: %5.1f/%-5.1f V\n",
+ alt/10000, wlt/10000, wht/10000, aht/10000);
+
+ else
+ fprintf(stdout, "\n");
+
+
+ /* TX BIAS */
+
+ if (ecal) {
+ tmp = ECAL(pd.tx_bias, pd.tx_bias_slope, pd.tx_bias_offset);
+ if(aw) {
+ alt = ECAL(pd.tx_bias_alt, pd.tx_bias_slope, pd.temp_offset);
+ aht = ECAL(pd.tx_bias_aht, pd.tx_bias_slope, pd.temp_offset);
+ wlt = ECAL(pd.tx_bias_wlt, pd.tx_bias_slope, pd.temp_offset);
+ wht = ECAL(pd.tx_bias_wht, pd.tx_bias_slope, pd.temp_offset);
+ }
+ }
+ else
+ tmp = (double) (pd.tx_bias);
+
+ if(aw) {
+
+ if(alarm[0] & DOM_TYPE_TX_BIAS_AH)
+ fprintf(stdout, "AH");
+
+ if(alarm[0] & DOM_TYPE_TX_BIAS_AL)
+ fprintf(stdout, "AL");
+
+ if(warn[0] & DOM_TYPE_TX_BIAS_WH)
+ fprintf(stdout, "WH");
+
+ if(warn[0] & DOM_TYPE_TX_BIAS_WL)
+ fprintf(stdout, "WL");
+
+ }
+ fprintf(stdout, "\tTx-Bias: %5.1f mA\t", tmp/500);
+ if(aw)
+ fprintf(stdout, "\tThresh: Lo: %5.1f/%-5.1f Hi: %5.1f/%-5.1f mA\n",
+ alt/500, wlt/500, wht/500, aht/500);
+
+ else
+ fprintf(stdout, "\n");
+
+
+ /* TX PWR */
+
+ if (ecal) {
+ tmp = ECAL(pd.tx_pwr, pd.tx_pwr_slope, pd.tx_pwr_offset);
+ if(aw) {
+ alt = ECAL(pd.tx_pwr_alt, pd.tx_pwr_slope, pd.temp_offset);
+ aht = ECAL(pd.tx_pwr_aht, pd.tx_pwr_slope, pd.temp_offset);
+ wlt = ECAL(pd.tx_pwr_wlt, pd.tx_pwr_slope, pd.temp_offset);
+ wht = ECAL(pd.tx_pwr_wht, pd.tx_pwr_slope, pd.temp_offset);
+ }
+ }
+ else
+ tmp = (double) (pd.tx_pwr);
+ if(aw) {
+
+ if(alarm[0] & DOM_TYPE_TX_PWR_AH)
+ fprintf(stdout, "AH");
+
+ if(alarm[0] & DOM_TYPE_TX_PWR_AL)
+ fprintf(stdout, "AL");
+
+ if(warn[0] & DOM_TYPE_TX_PWR_WH)
+ fprintf(stdout, "WH");
+
+ if(warn[0] & DOM_TYPE_TX_PWR_WL)
+ fprintf(stdout, "WL");
+
+ }
+ tmp = tmp/10000;
+ fprintf(stdout, "\tTX-pwr: %5.1f dBm (%5.2f mW)", 10*log10(tmp), tmp);
+ if(aw) {
+ alt = alt/10000;
+ aht = aht/10000;
+ wlt = wlt/10000;
+ wht = wht/10000;
+ fprintf(stdout, "\tThresh: Lo: %5.1f/%-5.1f Hi: %5.1f/%-5.1f dBm\n",
+ 10*log10(alt), 10*log10(wlt), 10*log10(wht), 10*log10(aht));
+ }
+ else
+ fprintf(stdout, "\n");
+
+ /* RX PWR */
+ if (ecal) {
+ /* Note factors is in floast cast to avoid conversion */
+ float *f[5];
+ double s, o;
+
+ f[0] = (float *) &pd.rx_pwr_cal[0];
+ f[1] = (float *) &pd.rx_pwr_cal[1];
+ f[2] = (float *) &pd.rx_pwr_cal[2];
+ f[3] = (float *) &pd.rx_pwr_cal[3];
+ f[4] = (float *) &pd.rx_pwr_cal[4];
+ s = *f[4] + *f[3] + *f[2] + *f[1];
+ o = *f[0];
+
+ if(aw) {
+ tmp = pd.rx_pwr * s + o;
+ alt = pd.rx_pwr_alt * s + o;
+ aht = pd.rx_pwr_aht * s + o;
+ wlt = pd.rx_pwr_wlt * s + o;
+ wht = pd.rx_pwr_wht * s + o;
+ }
+ }
+ else
+ tmp = (double) (pd.rx_pwr);
+
+ if(aw) {
+
+ if(alarm[1] & DOM_TYPE_RX_PWR_AH)
+ fprintf(stdout, "AH");
+
+ if(alarm[1] & DOM_TYPE_RX_PWR_AL)
+ fprintf(stdout, "AL");
+
+ if(warn[1] & DOM_TYPE_RX_PWR_WH)
+ fprintf(stdout, "WH");
+
+ if(warn[1] & DOM_TYPE_RX_PWR_WL)
+ fprintf(stdout, "WL");
+
+ }
+ tmp = (double) (tmp)/10000;
+ fprintf(stdout, "\tRX-pwr: %5.1f dBm (%5.2f mW) ", 10*log10(tmp), tmp);
+
+ if(aw) {
+ alt = alt/10000;
+ aht = aht/10000;
+ wlt = wlt/10000;
+ wht = wht/10000;
+
+ fprintf(stdout, "\tThresh: Lo: %5.1f/%-5.1f Hi: %5.1f/%-5.1f dBm\n",
+ 10*log10(alt), 10*log10(wlt), 10*log10(wht), 10*log10(aht));
+ }
+ else
+ fprintf(stdout, "\n");
+
+ return 0;
+}
+
+
int main(int argc, char **argp, char **envp)
{
parse_cmdline(argc, argp);
^ permalink raw reply related
* Diagnostic Monitoring Interface Monitoring (DOM) PATCH 4/5 for net-next-2.6
From: Robert Olsson @ 2009-11-23 22:55 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Robert Olsson
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Untested.
--ro
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 026e94a..a5bdd65 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -34,9 +34,11 @@
#include <linux/ethtool.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
+#include <net/dom.h>
#include "ixgbe.h"
-
+#include "ixgbe_phy.h"
+#include "ixgbe_common.h"
#define IXGBE_ALL_RAR_ENTRIES 16
@@ -2031,6 +2033,206 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
}
+static s32 read_phy_diag(struct ixgbe_hw *hw, u8 page, u8 offset,
+ u16 *data)
+{
+ s32 status = 0;
+ u8 tmp [2];
+
+ status = ixgbe_read_i2c_byte_generic(hw, page, offset, &tmp[0]);
+ if(status != 0)
+ goto err;
+
+ status = ixgbe_read_i2c_byte_generic(hw, page, offset, &tmp[1]);
+ *data = (tmp[0]<<8) | tmp[1];
+err:
+ return status;
+}
+
+int ixgb_get_phy_diag(struct net_device *netdev, struct ethtool_phy_diag *pd)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u16 p1, p2;
+ int res;
+ u8 type, eo;
+
+ if((res = read_phy_diag(hw, 0x0, DOM_A0_DOM_TYPE, &pd->type)))
+ goto out;
+
+ type = pd->type >> 8;
+
+ if( ~(type) & DOM_TYPE_DOM || type & DOM_TYPE_LEGAGY_DOM)
+ goto out;
+
+ if( type& DOM_TYPE_DOM & DOM_TYPE_ADDR_CHNGE) {
+ hw_dbg(hw, "DOM module not supported (Address change)\n");
+ goto out;
+ }
+
+ eo = pd->type & 0xFF;
+ if((res = read_phy_diag(hw, 0x0, DOM_A0_WAVELENGTH, &pd->wavelength)))
+ goto out;
+
+ /* If supported. Read alarms and Warnings first*/
+ if( eo & DOM_EO_AW) {
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_ALARM, &pd->alarm)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_WARNING, &pd->warning)))
+ goto out;
+ }
+
+ /* Basic diag */
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP, &pd->temp)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_SLOPE, &pd->temp_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_OFFSET, &pd->temp_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC, &pd->vcc)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_SLOPE, &pd->vcc_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_OFFSET, &pd->vcc_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS, &pd->tx_bias)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_SLOPE, &pd->tx_bias_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_OFFSET, &pd->tx_bias_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR, &pd->tx_pwr)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_SLOPE, &pd->tx_pwr_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_OFFSET, &pd->tx_pwr_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR, &pd->rx_pwr)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[0] = (p1<<16) + p2;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[1] = (p1<<16) + p2;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[2] = (p1<<16) + p2;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[3] = (p1<<16) + p2;
+
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[4] = (p1<<16) + p2;
+
+ /* Thresholds for Alarms and Warnings */
+ if( !(eo & DOM_EO_AW))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_AHT, &pd->temp_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_ALT, &pd->temp_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WHT, &pd->temp_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WLT, &pd->temp_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_AHT, &pd->vcc_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_ALT, &pd->vcc_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WHT, &pd->vcc_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WLT, &pd->vcc_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_AHT, &pd->tx_bias_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_ALT, &pd->tx_bias_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WHT, &pd->tx_bias_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WLT, &pd->tx_bias_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_AHT, &pd->tx_pwr_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_ALT, &pd->tx_pwr_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WHT, &pd->tx_pwr_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WLT, &pd->tx_pwr_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_AHT, &pd->rx_pwr_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_ALT, &pd->rx_pwr_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WHT, &pd->rx_pwr_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WLT, &pd->rx_pwr_wlt)))
+ goto out;
+
+out:
+ return res;
+}
+
static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_settings = ixgbe_get_settings,
.set_settings = ixgbe_set_settings,
@@ -2066,5 +2268,6 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.set_coalesce = ixgbe_set_coalesce,
.get_flags = ethtool_op_get_flags,
.set_flags = ixgbe_set_flags,
+ .get_phy_diag = ixgb_get_phy_diag,
};
^ permalink raw reply related
* Diagnostic Monitoring Interface Monitoring (DOM) PATCH 3/5 for net-next-2.6
From: Robert Olsson @ 2009-11-23 22:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Robert Olsson
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index ac9d527..5d190ad 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -34,6 +34,7 @@
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/ethtool.h>
+#include <net/dom.h>
#include <linux/sched.h>
#include "igb.h"
@@ -2063,6 +2064,234 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
}
}
+static s32 read_phy_diag(struct e1000_hw *hw, u8 page, u8 offset,
+ u16 *data)
+{
+ u32 i, i2ccmd = 0;
+
+ if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
+ hw_dbg("DOM Register Address %u is out of range\n", offset);
+ return -E1000_ERR_PARAM;
+ }
+
+ /*
+ * Set up Op-code, Phy Address, and register address in the I2CCMD
+ * register. The MAC will take care of interfacing with the
+ * PHY to retrieve the desired data.
+ */
+
+ i2ccmd = (E1000_I2CCMD_OPCODE_READ) | (page << E1000_I2CCMD_PHY_ADDR_SHIFT) |
+ ( offset << E1000_I2CCMD_REG_ADDR_SHIFT);
+
+ wr32(E1000_I2CCMD, i2ccmd);
+
+ /* Poll the ready bit to see if the I2C read completed */
+ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+ udelay(50);
+ i2ccmd = rd32(E1000_I2CCMD);
+ //printk("DATA i2ccmd=0x%x\n", i2ccmd);
+ if (i2ccmd & E1000_I2CCMD_READY)
+ break;
+ }
+ if (!(i2ccmd & E1000_I2CCMD_READY)) {
+ hw_dbg("I2CCMD Read did not complete\n");
+ return -E1000_ERR_PHY;
+ }
+ if (i2ccmd & E1000_I2CCMD_ERROR) {
+ hw_dbg("I2CCMD Error bit set\n");
+ return -E1000_ERR_PHY;
+ }
+
+ /* Need to byte-swap the 16-bit value. */
+ *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
+ return 0;
+}
+
+int igb_get_phy_diag(struct net_device *netdev, struct ethtool_phy_diag *pd)
+{
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u16 p1, p2;
+ int res;
+ u8 type, eo;
+
+ if((res = read_phy_diag(hw, 0x0, DOM_A0_DOM_TYPE, &pd->type)))
+ goto out;
+
+ type = pd->type >> 8;
+
+ if( ~(type) & DOM_TYPE_DOM || type & DOM_TYPE_LEGAGY_DOM)
+ goto out;
+
+ if( type& DOM_TYPE_DOM & DOM_TYPE_ADDR_CHNGE) {
+ hw_dbg("DOM module not supported (Address change)\n");
+ goto out;
+ }
+
+ eo = pd->type & 0xFF;
+ if((res = read_phy_diag(hw, 0x0, DOM_A0_WAVELENGTH, &pd->wavelength)))
+ goto out;
+
+ /* If supported. Read alarms and Warnings first*/
+ if( eo & DOM_EO_AW) {
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_ALARM, &pd->alarm)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_WARNING, &pd->warning)))
+ goto out;
+ }
+
+ /* Basic diag */
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP, &pd->temp)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_SLOPE, &pd->temp_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_OFFSET, &pd->temp_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC, &pd->vcc)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_SLOPE, &pd->vcc_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_OFFSET, &pd->vcc_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS, &pd->tx_bias)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_SLOPE, &pd->tx_bias_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_I_OFFSET, &pd->tx_bias_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR, &pd->tx_pwr)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_SLOPE, &pd->tx_pwr_slope)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_OFFSET, &pd->tx_pwr_offset)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR, &pd->rx_pwr)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_0+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[0] = (p1<<16) + p2;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_1+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[1] = (p1<<16) + p2;
+
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_2+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[2] = (p1<<16) + p2;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_3+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[3] = (p1<<16) + p2;
+
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4, &p1)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_4+2, &p2)))
+ goto out;
+
+ pd->rx_pwr_cal[4] = (p1<<16) + p2;
+
+ /* Thresholds for Alarms and Warnings */
+ if( !(eo & DOM_EO_AW))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_AHT, &pd->temp_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_ALT, &pd->temp_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WHT, &pd->temp_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TEMP_WLT, &pd->temp_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_AHT, &pd->vcc_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_ALT, &pd->vcc_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WHT, &pd->vcc_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_VCC_WLT, &pd->vcc_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_AHT, &pd->tx_bias_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_ALT, &pd->tx_bias_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WHT, &pd->tx_bias_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_BIAS_WLT, &pd->tx_bias_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_AHT, &pd->tx_pwr_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_ALT, &pd->tx_pwr_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WHT, &pd->tx_pwr_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_TX_PWR_WLT, &pd->tx_pwr_wlt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_AHT, &pd->rx_pwr_aht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_ALT, &pd->rx_pwr_alt)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WHT, &pd->rx_pwr_wht)))
+ goto out;
+
+ if((res = read_phy_diag(hw, 0x1, DOM_A2_RX_PWR_WLT, &pd->rx_pwr_wlt)))
+ goto out;
+
+out:
+ return res;
+}
+
static const struct ethtool_ops igb_ethtool_ops = {
.get_settings = igb_get_settings,
.set_settings = igb_set_settings,
@@ -2097,6 +2326,7 @@ static const struct ethtool_ops igb_ethtool_ops = {
.get_ethtool_stats = igb_get_ethtool_stats,
.get_coalesce = igb_get_coalesce,
.set_coalesce = igb_set_coalesce,
+ .get_phy_diag = igb_get_phy_diag,
};
void igb_set_ethtool_ops(struct net_device *netdev)
^ permalink raw reply related
* Diagnostic Monitoring Interface Monitoring (DOM) PATCH 0/5 for net-next-2.6
From: Robert Olsson @ 2009-11-23 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, robert
Here are basic support to bring Diagnostic Monitoring Interface Monitoring (DOM)
to Linux this is more or less mandatory when building optical networks.
Optical modules as SFP, SFP+, XFP, GBIC etc holds transceiver and link diagnostic
data needed to monitor and troubleshoot optical links, Talks to networks cards
via the I2C-bus (DOM lives in memory page 0xA2).
In essential:
Usage example: ethtool -D eth5
Ext-Calbr: Avr RX-Power: Alarm & Warn: RX_LOS: Wavelength: 1310 nm
Alarms, warnings in beginning of line, Ie. AH = Alarm High, WL == Warn Low etc
Temp: 35.9 C Thresh: Lo: -12.0/-8.0 Hi: 103.0/110.0 C
Vcc: 3.33 V Thresh: Lo: 3.0/3.0 Hi: 3.7/4.0 V
Tx-Bias: 13.4 mA Thresh: Lo: 2.0/4.0 Hi: 70.0/84.0 mA
ALWL TX-pwr: -5.9 dBm ( 0.26 mW) Thresh: Lo: -4.0/-2.0 Hi: 7.0/8.2 dBm
AHWH RX-pwr: -5.0 dBm ( 0.31 mW) Thresh: Lo: -35.2/-28.0 Hi: -8.2/-6.0 dBm
Read more in Documentation/networking/dom.txt
It's tested with the igb driver, there is also a patch for the ixgbe driver but I
haven't any SFP+ with DOM support yet.
There are room for improvements an clean-ups.
Cheers
--ro
^ permalink raw reply
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