Commit afe3939e authored by David S. Miller's avatar David S. Miller

Merge branch 'sunvnet-driver-updates'

Shannon Nelson says:

====================
sunvnet driver updates

The sunvnet ldom virtual network driver was due for some updates and
a bugfix or two.  These patches address a few items left over from
last year's make-over.

v2:
 - changed memory barrier fix to use smp_wmb
 - put NETIF_F_SG back into the advertised ldmvsw hw_features

v3:
 - the sunvnet_common module doesn't need module_init or _exit

v4:
 - dropped the statistics patch
 - fixed up "default" tag for SUNVNET_COMMON
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bd08b532 bc221a34
...@@ -70,19 +70,23 @@ config CASSINI ...@@ -70,19 +70,23 @@ config CASSINI
<http://docs.oracle.com/cd/E19113-01/giga.ether.pci/817-4341-10/817-4341-10.pdf>. <http://docs.oracle.com/cd/E19113-01/giga.ether.pci/817-4341-10/817-4341-10.pdf>.
config SUNVNET_COMMON config SUNVNET_COMMON
bool tristate "Common routines to support Sun Virtual Networking"
depends on SUN_LDOMS depends on SUN_LDOMS
default y if SUN_LDOMS default m
config SUNVNET config SUNVNET
tristate "Sun Virtual Network support" tristate "Sun Virtual Network support"
default m
depends on SUN_LDOMS depends on SUN_LDOMS
depends on SUNVNET_COMMON
---help--- ---help---
Support for virtual network devices under Sun Logical Domains. Support for virtual network devices under Sun Logical Domains.
config LDMVSW config LDMVSW
tristate "Sun4v LDoms Virtual Switch support" tristate "Sun4v LDoms Virtual Switch support"
default m
depends on SUN_LDOMS depends on SUN_LDOMS
depends on SUNVNET_COMMON
---help--- ---help---
Support for virtual switch devices under Sun4v Logical Domains. Support for virtual switch devices under Sun4v Logical Domains.
This driver adds a network interface for every vsw-port node This driver adds a network interface for every vsw-port node
......
...@@ -41,11 +41,11 @@ ...@@ -41,11 +41,11 @@
static u8 vsw_port_hwaddr[ETH_ALEN] = {0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static u8 vsw_port_hwaddr[ETH_ALEN] = {0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#define DRV_MODULE_NAME "ldmvsw" #define DRV_MODULE_NAME "ldmvsw"
#define DRV_MODULE_VERSION "1.0" #define DRV_MODULE_VERSION "1.1"
#define DRV_MODULE_RELDATE "Jan 15, 2016" #define DRV_MODULE_RELDATE "February 3, 2017"
static char version[] = static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
MODULE_AUTHOR("Oracle"); MODULE_AUTHOR("Oracle");
MODULE_DESCRIPTION("Sun4v LDOM Virtual Switch Driver"); MODULE_DESCRIPTION("Sun4v LDOM Virtual Switch Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -234,8 +234,7 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[], ...@@ -234,8 +234,7 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
dev->ethtool_ops = &vsw_ethtool_ops; dev->ethtool_ops = &vsw_ethtool_ops;
dev->watchdog_timeo = VSW_TX_TIMEOUT; dev->watchdog_timeo = VSW_TX_TIMEOUT;
dev->hw_features = NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GSO_SOFTWARE | dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG;
NETIF_F_HW_CSUM | NETIF_F_SG;
dev->features = dev->hw_features; dev->features = dev->hw_features;
/* MTU range: 68 - 65535 */ /* MTU range: 68 - 65535 */
...@@ -259,11 +258,6 @@ static struct vio_driver_ops vsw_vio_ops = { ...@@ -259,11 +258,6 @@ static struct vio_driver_ops vsw_vio_ops = {
.handshake_complete = sunvnet_handshake_complete_common, .handshake_complete = sunvnet_handshake_complete_common,
}; };
static void print_version(void)
{
printk_once(KERN_INFO "%s", version);
}
static const char *remote_macaddr_prop = "remote-mac-address"; static const char *remote_macaddr_prop = "remote-mac-address";
static const char *id_prop = "id"; static const char *id_prop = "id";
...@@ -279,8 +273,6 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) ...@@ -279,8 +273,6 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
const u64 *port_id; const u64 *port_id;
u64 handle; u64 handle;
print_version();
hp = mdesc_grab(); hp = mdesc_grab();
rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len); rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
...@@ -327,7 +319,7 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) ...@@ -327,7 +319,7 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
port->vp = vp; port->vp = vp;
port->dev = dev; port->dev = dev;
port->switch_port = 1; port->switch_port = 1;
port->tso = true; port->tso = false; /* no tso in vsw, misbehaves in bridge */
port->tsolen = 0; port->tsolen = 0;
/* Mark the port as belonging to ldmvsw which directs the /* Mark the port as belonging to ldmvsw which directs the
...@@ -457,6 +449,7 @@ static struct vio_driver vsw_port_driver = { ...@@ -457,6 +449,7 @@ static struct vio_driver vsw_port_driver = {
static int __init vsw_init(void) static int __init vsw_init(void)
{ {
pr_info("%s\n", version);
return vio_register_driver(&vsw_port_driver); return vio_register_driver(&vsw_port_driver);
} }
......
...@@ -38,11 +38,11 @@ ...@@ -38,11 +38,11 @@
#define VNET_TX_TIMEOUT (5 * HZ) #define VNET_TX_TIMEOUT (5 * HZ)
#define DRV_MODULE_NAME "sunvnet" #define DRV_MODULE_NAME "sunvnet"
#define DRV_MODULE_VERSION "1.0" #define DRV_MODULE_VERSION "2.0"
#define DRV_MODULE_RELDATE "June 25, 2007" #define DRV_MODULE_RELDATE "February 3, 2017"
static char version[] = static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_DESCRIPTION("Sun LDOM virtual network driver"); MODULE_DESCRIPTION("Sun LDOM virtual network driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -303,11 +303,6 @@ static struct vio_driver_ops vnet_vio_ops = { ...@@ -303,11 +303,6 @@ static struct vio_driver_ops vnet_vio_ops = {
.handshake_complete = sunvnet_handshake_complete_common, .handshake_complete = sunvnet_handshake_complete_common,
}; };
static void print_version(void)
{
printk_once(KERN_INFO "%s", version);
}
const char *remote_macaddr_prop = "remote-mac-address"; const char *remote_macaddr_prop = "remote-mac-address";
static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
...@@ -319,8 +314,6 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) ...@@ -319,8 +314,6 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
const u64 *rmac; const u64 *rmac;
int len, i, err, switch_port; int len, i, err, switch_port;
print_version();
hp = mdesc_grab(); hp = mdesc_grab();
vp = vnet_find_parent(hp, vdev->mp, vdev); vp = vnet_find_parent(hp, vdev->mp, vdev);
...@@ -446,6 +439,7 @@ static struct vio_driver vnet_port_driver = { ...@@ -446,6 +439,7 @@ static struct vio_driver vnet_port_driver = {
static int __init vnet_init(void) static int __init vnet_init(void)
{ {
pr_info("%s\n", version);
return vio_register_driver(&vnet_port_driver); return vio_register_driver(&vnet_port_driver);
} }
......
...@@ -37,6 +37,11 @@ ...@@ -37,6 +37,11 @@
*/ */
#define VNET_MAX_RETRIES 10 #define VNET_MAX_RETRIES 10
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_DESCRIPTION("Sun LDOM virtual network support library");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.1");
static int __vnet_tx_trigger(struct vnet_port *port, u32 start); static int __vnet_tx_trigger(struct vnet_port *port, u32 start);
static void vnet_port_reset(struct vnet_port *port); static void vnet_port_reset(struct vnet_port *port);
...@@ -181,6 +186,7 @@ static int handle_attr_info(struct vio_driver_state *vio, ...@@ -181,6 +186,7 @@ static int handle_attr_info(struct vio_driver_state *vio,
} else { } else {
pkt->cflags &= ~VNET_LSO_IPV4_CAPAB; pkt->cflags &= ~VNET_LSO_IPV4_CAPAB;
pkt->ipv4_lso_maxlen = 0; pkt->ipv4_lso_maxlen = 0;
port->tsolen = 0;
} }
/* for version >= 1.6, ACK packet mode we support */ /* for version >= 1.6, ACK packet mode we support */
...@@ -714,12 +720,8 @@ static void maybe_tx_wakeup(struct vnet_port *port) ...@@ -714,12 +720,8 @@ static void maybe_tx_wakeup(struct vnet_port *port)
txq = netdev_get_tx_queue(VNET_PORT_TO_NET_DEVICE(port), txq = netdev_get_tx_queue(VNET_PORT_TO_NET_DEVICE(port),
port->q_index); port->q_index);
__netif_tx_lock(txq, smp_processor_id()); __netif_tx_lock(txq, smp_processor_id());
if (likely(netif_tx_queue_stopped(txq))) { if (likely(netif_tx_queue_stopped(txq)))
struct vio_dring_state *dr;
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
netif_tx_wake_queue(txq); netif_tx_wake_queue(txq);
}
__netif_tx_unlock(txq); __netif_tx_unlock(txq);
} }
...@@ -737,41 +739,37 @@ static int vnet_event_napi(struct vnet_port *port, int budget) ...@@ -737,41 +739,37 @@ static int vnet_event_napi(struct vnet_port *port, int budget)
struct vio_driver_state *vio = &port->vio; struct vio_driver_state *vio = &port->vio;
int tx_wakeup, err; int tx_wakeup, err;
int npkts = 0; int npkts = 0;
int event = (port->rx_event & LDC_EVENT_RESET);
/* we don't expect any other bits */
ldc_ctrl: BUG_ON(port->rx_event & ~(LDC_EVENT_DATA_READY |
if (unlikely(event == LDC_EVENT_RESET || LDC_EVENT_RESET |
event == LDC_EVENT_UP)) { LDC_EVENT_UP));
vio_link_state_change(vio, event);
/* RESET takes precedent over any other event */
if (event == LDC_EVENT_RESET) { if (port->rx_event & LDC_EVENT_RESET) {
vnet_port_reset(port); vio_link_state_change(vio, LDC_EVENT_RESET);
vio_port_up(vio); vnet_port_reset(port);
vio_port_up(vio);
/* If the device is running but its tx queue was
* stopped (due to flow control), restart it. /* If the device is running but its tx queue was
* This is necessary since vnet_port_reset() * stopped (due to flow control), restart it.
* clears the tx drings and thus we may never get * This is necessary since vnet_port_reset()
* back a VIO_TYPE_DATA ACK packet - which is * clears the tx drings and thus we may never get
* the normal mechanism to restart the tx queue. * back a VIO_TYPE_DATA ACK packet - which is
*/ * the normal mechanism to restart the tx queue.
if (netif_running(dev)) */
maybe_tx_wakeup(port); if (netif_running(dev))
} maybe_tx_wakeup(port);
port->rx_event = 0; port->rx_event = 0;
return 0; return 0;
} }
/* We may have multiple LDC events in rx_event. Unroll send_events() */
event = (port->rx_event & LDC_EVENT_UP);
port->rx_event &= ~(LDC_EVENT_RESET | LDC_EVENT_UP);
if (event == LDC_EVENT_UP)
goto ldc_ctrl;
event = port->rx_event;
if (!(event & LDC_EVENT_DATA_READY))
return 0;
/* we dont expect any other bits than RESET, UP, DATA_READY */ if (port->rx_event & LDC_EVENT_UP) {
BUG_ON(event != LDC_EVENT_DATA_READY); vio_link_state_change(vio, LDC_EVENT_UP);
port->rx_event = 0;
return 0;
}
err = 0; err = 0;
tx_wakeup = 0; tx_wakeup = 0;
...@@ -794,25 +792,25 @@ static int vnet_event_napi(struct vnet_port *port, int budget) ...@@ -794,25 +792,25 @@ static int vnet_event_napi(struct vnet_port *port, int budget)
pkt->start_idx = vio_dring_next(dr, pkt->start_idx = vio_dring_next(dr,
port->napi_stop_idx); port->napi_stop_idx);
pkt->end_idx = -1; pkt->end_idx = -1;
goto napi_resume; } else {
} err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf)); if (unlikely(err < 0)) {
if (unlikely(err < 0)) { if (err == -ECONNRESET)
if (err == -ECONNRESET) vio_conn_reset(vio);
vio_conn_reset(vio); break;
break; }
if (err == 0)
break;
viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
msgbuf.tag.type,
msgbuf.tag.stype,
msgbuf.tag.stype_env,
msgbuf.tag.sid);
err = vio_validate_sid(vio, &msgbuf.tag);
if (err < 0)
break;
} }
if (err == 0)
break;
viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
msgbuf.tag.type,
msgbuf.tag.stype,
msgbuf.tag.stype_env,
msgbuf.tag.sid);
err = vio_validate_sid(vio, &msgbuf.tag);
if (err < 0)
break;
napi_resume:
if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) { if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) { if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) {
if (!sunvnet_port_is_up_common(port)) { if (!sunvnet_port_is_up_common(port)) {
...@@ -1256,10 +1254,8 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, ...@@ -1256,10 +1254,8 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
rcu_read_lock(); rcu_read_lock();
port = vnet_tx_port(skb, dev); port = vnet_tx_port(skb, dev);
if (unlikely(!port)) { if (unlikely(!port))
rcu_read_unlock();
goto out_dropped; goto out_dropped;
}
if (skb_is_gso(skb) && skb->len > port->tsolen) { if (skb_is_gso(skb) && skb->len > port->tsolen) {
err = vnet_handle_offloads(port, skb, vnet_tx_port); err = vnet_handle_offloads(port, skb, vnet_tx_port);
...@@ -1284,7 +1280,6 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, ...@@ -1284,7 +1280,6 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
fl4.saddr = ip_hdr(skb)->saddr; fl4.saddr = ip_hdr(skb)->saddr;
rt = ip_route_output_key(dev_net(dev), &fl4); rt = ip_route_output_key(dev_net(dev), &fl4);
rcu_read_unlock();
if (!IS_ERR(rt)) { if (!IS_ERR(rt)) {
skb_dst_set(skb, &rt->dst); skb_dst_set(skb, &rt->dst);
icmp_send(skb, ICMP_DEST_UNREACH, icmp_send(skb, ICMP_DEST_UNREACH,
...@@ -1426,6 +1421,7 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, ...@@ -1426,6 +1421,7 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1); dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
if (unlikely(vnet_tx_dring_avail(dr) < 1)) { if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
netif_tx_stop_queue(txq); netif_tx_stop_queue(txq);
smp_rmb();
if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr)) if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
netif_tx_wake_queue(txq); netif_tx_wake_queue(txq);
} }
...@@ -1443,8 +1439,7 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, ...@@ -1443,8 +1439,7 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
jiffies + VNET_CLEAN_TIMEOUT); jiffies + VNET_CLEAN_TIMEOUT);
else if (port) else if (port)
del_timer(&port->clean_timer); del_timer(&port->clean_timer);
if (port) rcu_read_unlock();
rcu_read_unlock();
if (skb) if (skb)
dev_kfree_skb(skb); dev_kfree_skb(skb);
vnet_free_skbs(freeskbs); vnet_free_skbs(freeskbs);
...@@ -1641,7 +1636,7 @@ static void vnet_port_reset(struct vnet_port *port) ...@@ -1641,7 +1636,7 @@ static void vnet_port_reset(struct vnet_port *port)
del_timer(&port->clean_timer); del_timer(&port->clean_timer);
sunvnet_port_free_tx_bufs_common(port); sunvnet_port_free_tx_bufs_common(port);
port->rmtu = 0; port->rmtu = 0;
port->tso = true; port->tso = (port->vsw == 0); /* no tso in vsw, misbehaves in bridge */
port->tsolen = 0; port->tsolen = 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment