diff options
author | David L Stevens <david.stevens@oracle.com> | 2014-07-25 10:30:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-28 20:29:53 -0400 |
commit | 8266f5fcf015101fbeb73cbc152c9d208c2baec0 (patch) | |
tree | 3508b7da82362d26fbd9c44b7eeedfd7dbcbed23 /drivers/net/ethernet/sun | |
parent | 8356f9768954e03494ce812f3985c665960ae3eb (diff) |
sunvnet: only use connected ports when sending
The sunvnet driver doesn't check whether or not a port is connected when
transmitting packets, which results in failures if a port fails to connect
(e.g., due to a version mismatch). The original code also assumes
unnecessarily that the first port is up and a switch, even though there is
a flag for switch ports.
This patch only matches a port if it is connected, and otherwise uses the
switch_port flag to send the packet to a switch port that is up.
Signed-off-by: David L Stevens <david.stevens@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sun')
-rw-r--r-- | drivers/net/ethernet/sun/sunvnet.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index fd411d6e19a2..d813bfb1a847 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c | |||
@@ -610,6 +610,13 @@ static int __vnet_tx_trigger(struct vnet_port *port) | |||
610 | return err; | 610 | return err; |
611 | } | 611 | } |
612 | 612 | ||
613 | static inline bool port_is_up(struct vnet_port *vnet) | ||
614 | { | ||
615 | struct vio_driver_state *vio = &vnet->vio; | ||
616 | |||
617 | return !!(vio->hs_state & VIO_HS_COMPLETE); | ||
618 | } | ||
619 | |||
613 | struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) | 620 | struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) |
614 | { | 621 | { |
615 | unsigned int hash = vnet_hashfn(skb->data); | 622 | unsigned int hash = vnet_hashfn(skb->data); |
@@ -617,14 +624,19 @@ struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) | |||
617 | struct vnet_port *port; | 624 | struct vnet_port *port; |
618 | 625 | ||
619 | hlist_for_each_entry(port, hp, hash) { | 626 | hlist_for_each_entry(port, hp, hash) { |
627 | if (!port_is_up(port)) | ||
628 | continue; | ||
620 | if (ether_addr_equal(port->raddr, skb->data)) | 629 | if (ether_addr_equal(port->raddr, skb->data)) |
621 | return port; | 630 | return port; |
622 | } | 631 | } |
623 | port = NULL; | 632 | list_for_each_entry(port, &vp->port_list, list) { |
624 | if (!list_empty(&vp->port_list)) | 633 | if (!port->switch_port) |
625 | port = list_entry(vp->port_list.next, struct vnet_port, list); | 634 | continue; |
626 | 635 | if (!port_is_up(port)) | |
627 | return port; | 636 | continue; |
637 | return port; | ||
638 | } | ||
639 | return NULL; | ||
628 | } | 640 | } |
629 | 641 | ||
630 | struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb) | 642 | struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb) |