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
<http://docs.oracle.com/cd/E19113-01/giga.ether.pci/817-4341-10/817-4341-10.pdf>.
config SUNVNET_COMMON
bool
tristate "Common routines to support Sun Virtual Networking"
depends on SUN_LDOMS
default y if SUN_LDOMS
default m
config SUNVNET
tristate "Sun Virtual Network support"
default m
depends on SUN_LDOMS
depends on SUNVNET_COMMON
---help---
Support for virtual network devices under Sun Logical Domains.
config LDMVSW
tristate "Sun4v LDoms Virtual Switch support"
default m
depends on SUN_LDOMS
depends on SUNVNET_COMMON
---help---
Support for virtual switch devices under Sun4v Logical Domains.
This driver adds a network interface for every vsw-port node
......
......@@ -41,11 +41,11 @@
static u8 vsw_port_hwaddr[ETH_ALEN] = {0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#define DRV_MODULE_NAME "ldmvsw"
#define DRV_MODULE_VERSION "1.0"
#define DRV_MODULE_RELDATE "Jan 15, 2016"
#define DRV_MODULE_VERSION "1.1"
#define DRV_MODULE_RELDATE "February 3, 2017"
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_DESCRIPTION("Sun4v LDOM Virtual Switch Driver");
MODULE_LICENSE("GPL");
......@@ -234,8 +234,7 @@ static struct net_device *vsw_alloc_netdev(u8 hwaddr[],
dev->ethtool_ops = &vsw_ethtool_ops;
dev->watchdog_timeo = VSW_TX_TIMEOUT;
dev->hw_features = NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GSO_SOFTWARE |
NETIF_F_HW_CSUM | NETIF_F_SG;
dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG;
dev->features = dev->hw_features;
/* MTU range: 68 - 65535 */
......@@ -259,11 +258,6 @@ static struct vio_driver_ops vsw_vio_ops = {
.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 *id_prop = "id";
......@@ -279,8 +273,6 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
const u64 *port_id;
u64 handle;
print_version();
hp = mdesc_grab();
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)
port->vp = vp;
port->dev = dev;
port->switch_port = 1;
port->tso = true;
port->tso = false; /* no tso in vsw, misbehaves in bridge */
port->tsolen = 0;
/* Mark the port as belonging to ldmvsw which directs the
......@@ -457,6 +449,7 @@ static struct vio_driver vsw_port_driver = {
static int __init vsw_init(void)
{
pr_info("%s\n", version);
return vio_register_driver(&vsw_port_driver);
}
......
......@@ -38,11 +38,11 @@
#define VNET_TX_TIMEOUT (5 * HZ)
#define DRV_MODULE_NAME "sunvnet"
#define DRV_MODULE_VERSION "1.0"
#define DRV_MODULE_RELDATE "June 25, 2007"
#define DRV_MODULE_VERSION "2.0"
#define DRV_MODULE_RELDATE "February 3, 2017"
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_DESCRIPTION("Sun LDOM virtual network driver");
MODULE_LICENSE("GPL");
......@@ -303,11 +303,6 @@ static struct vio_driver_ops vnet_vio_ops = {
.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";
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;
int len, i, err, switch_port;
print_version();
hp = mdesc_grab();
vp = vnet_find_parent(hp, vdev->mp, vdev);
......@@ -446,6 +439,7 @@ static struct vio_driver vnet_port_driver = {
static int __init vnet_init(void)
{
pr_info("%s\n", version);
return vio_register_driver(&vnet_port_driver);
}
......
......@@ -37,6 +37,11 @@
*/
#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 void vnet_port_reset(struct vnet_port *port);
......@@ -181,6 +186,7 @@ static int handle_attr_info(struct vio_driver_state *vio,
} else {
pkt->cflags &= ~VNET_LSO_IPV4_CAPAB;
pkt->ipv4_lso_maxlen = 0;
port->tsolen = 0;
}
/* for version >= 1.6, ACK packet mode we support */
......@@ -714,12 +720,8 @@ static void maybe_tx_wakeup(struct vnet_port *port)
txq = netdev_get_tx_queue(VNET_PORT_TO_NET_DEVICE(port),
port->q_index);
__netif_tx_lock(txq, smp_processor_id());
if (likely(netif_tx_queue_stopped(txq))) {
struct vio_dring_state *dr;
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
if (likely(netif_tx_queue_stopped(txq)))
netif_tx_wake_queue(txq);
}
__netif_tx_unlock(txq);
}
......@@ -737,41 +739,37 @@ static int vnet_event_napi(struct vnet_port *port, int budget)
struct vio_driver_state *vio = &port->vio;
int tx_wakeup, err;
int npkts = 0;
int event = (port->rx_event & LDC_EVENT_RESET);
ldc_ctrl:
if (unlikely(event == LDC_EVENT_RESET ||
event == LDC_EVENT_UP)) {
vio_link_state_change(vio, event);
if (event == LDC_EVENT_RESET) {
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.
* This is necessary since vnet_port_reset()
* clears the tx drings and thus we may never get
* 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);
}
/* we don't expect any other bits */
BUG_ON(port->rx_event & ~(LDC_EVENT_DATA_READY |
LDC_EVENT_RESET |
LDC_EVENT_UP));
/* RESET takes precedent over any other event */
if (port->rx_event & LDC_EVENT_RESET) {
vio_link_state_change(vio, LDC_EVENT_RESET);
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.
* This is necessary since vnet_port_reset()
* clears the tx drings and thus we may never get
* 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);
port->rx_event = 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 */
BUG_ON(event != LDC_EVENT_DATA_READY);
if (port->rx_event & LDC_EVENT_UP) {
vio_link_state_change(vio, LDC_EVENT_UP);
port->rx_event = 0;
return 0;
}
err = 0;
tx_wakeup = 0;
......@@ -794,25 +792,25 @@ static int vnet_event_napi(struct vnet_port *port, int budget)
pkt->start_idx = vio_dring_next(dr,
port->napi_stop_idx);
pkt->end_idx = -1;
goto napi_resume;
}
err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
if (unlikely(err < 0)) {
if (err == -ECONNRESET)
vio_conn_reset(vio);
break;
} else {
err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
if (unlikely(err < 0)) {
if (err == -ECONNRESET)
vio_conn_reset(vio);
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 (msgbuf.tag.stype == VIO_SUBTYPE_INFO) {
if (!sunvnet_port_is_up_common(port)) {
......@@ -1256,10 +1254,8 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
rcu_read_lock();
port = vnet_tx_port(skb, dev);
if (unlikely(!port)) {
rcu_read_unlock();
if (unlikely(!port))
goto out_dropped;
}
if (skb_is_gso(skb) && skb->len > port->tsolen) {
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,
fl4.saddr = ip_hdr(skb)->saddr;
rt = ip_route_output_key(dev_net(dev), &fl4);
rcu_read_unlock();
if (!IS_ERR(rt)) {
skb_dst_set(skb, &rt->dst);
icmp_send(skb, ICMP_DEST_UNREACH,
......@@ -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);
if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
netif_tx_stop_queue(txq);
smp_rmb();
if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
netif_tx_wake_queue(txq);
}
......@@ -1443,8 +1439,7 @@ int sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev,
jiffies + VNET_CLEAN_TIMEOUT);
else if (port)
del_timer(&port->clean_timer);
if (port)
rcu_read_unlock();
rcu_read_unlock();
if (skb)
dev_kfree_skb(skb);
vnet_free_skbs(freeskbs);
......@@ -1641,7 +1636,7 @@ static void vnet_port_reset(struct vnet_port *port)
del_timer(&port->clean_timer);
sunvnet_port_free_tx_bufs_common(port);
port->rmtu = 0;
port->tso = true;
port->tso = (port->vsw == 0); /* no tso in vsw, misbehaves in bridge */
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