summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2004-06-29 05:18:00 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-29 05:18:00 -0700
commitbb90dcc5e47661b395e1642a631434ceb993ab51 (patch)
tree7f3dc523f1a0a14e26611484d56893870b09711b
parent4575edd5da76ec5325f1f882d342845fcbbdc475 (diff)
[PATCH] ppc64: iseries_veth integration
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ppc64/kernel/vio.c22
-rw-r--r--drivers/net/iseries_veth.c104
-rw-r--r--drivers/net/iseries_veth.h2
-rw-r--r--include/asm-ppc64/iSeries/HvTypes.h1
4 files changed, 79 insertions, 50 deletions
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index f28b5d22288a..240e912aa1a8 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -26,7 +26,9 @@
#include <asm/vio.h>
#include <asm/hvcall.h>
#include <asm/iSeries/vio.h>
+#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/HvCallXm.h>
+#include <asm/iSeries/HvLpConfig.h>
#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
@@ -48,19 +50,11 @@ static struct vio_dev *__init vio_register_device_iseries(char *type,
static struct iommu_table veth_iommu_table;
static struct iommu_table vio_iommu_table;
-static struct vio_dev _veth_dev = {
- .iommu_table = &veth_iommu_table,
- .dev.bus = &vio_bus_type
-};
static struct vio_dev _vio_dev = {
.iommu_table = &vio_iommu_table,
.dev.bus = &vio_bus_type
};
-
-struct vio_dev *iSeries_veth_dev = &_veth_dev;
struct device *iSeries_vio_dev = &_vio_dev.dev;
-
-EXPORT_SYMBOL(iSeries_veth_dev);
EXPORT_SYMBOL(iSeries_vio_dev);
#define device_is_compatible(a, b) 1
@@ -227,6 +221,18 @@ static void probe_bus_pseries(void)
#ifdef CONFIG_PPC_ISERIES
static void probe_bus_iseries(void)
{
+ HvLpIndexMap vlan_map = HvLpConfig_getVirtualLanIndexMap();
+ struct vio_dev *viodev;
+ int i;
+
+ vlan_map = HvLpConfig_getVirtualLanIndexMap();
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+ if ((vlan_map & (0x8000 >> i)) == 0)
+ continue;
+ viodev = vio_register_device_iseries("vlan", i);
+ /* veth is special and has it own iommu_table */
+ viodev->iommu_table = &veth_iommu_table;
+ }
}
#endif
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 634cb049c600..e62ca7b1b5c2 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -81,8 +81,6 @@
#include "iseries_veth.h"
-extern struct vio_dev *iSeries_veth_dev;
-
MODULE_AUTHOR("Kyle Lucke <klucke@us.ibm.com>");
MODULE_DESCRIPTION("iSeries Virtual ethernet driver");
MODULE_LICENSE("GPL");
@@ -119,6 +117,7 @@ struct veth_msg {
int token;
unsigned long in_use;
struct sk_buff *skb;
+ struct device *dev;
};
struct veth_lpar_connection {
@@ -147,6 +146,7 @@ struct veth_lpar_connection {
};
struct veth_port {
+ struct device *dev;
struct net_device_stats stats;
u64 mac_addr;
HvLpIndexMap lpar_map;
@@ -843,7 +843,7 @@ static void veth_tx_timeout(struct net_device *dev)
spin_unlock_irqrestore(&port->pending_gate, flags);
}
-struct net_device * __init veth_probe_one(int vlan)
+static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
{
struct net_device *dev;
struct veth_port *port;
@@ -869,6 +869,7 @@ struct net_device * __init veth_probe_one(int vlan)
if (map & (0x8000 >> vlan))
port->lpar_map |= (1 << i);
}
+ port->dev = vdev;
dev->dev_addr[0] = 0x02;
dev->dev_addr[1] = 0x01;
@@ -893,6 +894,8 @@ struct net_device * __init veth_probe_one(int vlan)
dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000);
dev->tx_timeout = veth_tx_timeout;
+ SET_NETDEV_DEV(dev, vdev);
+
rc = register_netdev(dev);
if (rc != 0) {
veth_printk(KERN_ERR,
@@ -945,7 +948,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
}
dma_length = skb->len;
- dma_address = vio_map_single(iSeries_veth_dev, skb->data,
+ dma_address = dma_map_single(port->dev, skb->data,
dma_length, DMA_TO_DEVICE);
if (dma_mapping_error(dma_address))
@@ -954,6 +957,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
/* Is it really necessary to check the length and address
* fields of the first entry here? */
msg->skb = skb;
+ msg->dev = port->dev;
msg->data.addr[0] = dma_address;
msg->data.len[0] = dma_length;
msg->data.eofmask = 1 << VETH_EOF_SHIFT;
@@ -1059,7 +1063,7 @@ static void veth_recycle_msg(struct veth_lpar_connection *cnx,
dma_address = msg->data.addr[0];
dma_length = msg->data.len[0];
- vio_unmap_single(iSeries_veth_dev, dma_address, dma_length,
+ dma_unmap_single(msg->dev, dma_address, dma_length,
DMA_TO_DEVICE);
if (msg->skb) {
@@ -1327,6 +1331,58 @@ static void veth_timed_ack(unsigned long ptr)
spin_unlock_irqrestore(&cnx->lock, flags);
}
+static int veth_remove(struct vio_dev *vdev)
+{
+ int i = vdev->unit_address;
+ struct net_device *dev;
+
+ dev = veth_dev[i];
+ if (dev != NULL) {
+ veth_dev[i] = NULL;
+ unregister_netdev(dev);
+ free_netdev(dev);
+ }
+ return 0;
+}
+
+static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+{
+ int i = vdev->unit_address;
+ struct net_device *dev;
+
+ dev = veth_probe_one(i, &vdev->dev);
+ if (dev == NULL) {
+ veth_remove(vdev);
+ return 1;
+ }
+ veth_dev[i] = dev;
+
+ /* Start the state machine on each connection, to commence
+ * link negotiation */
+ for (i = 0; i < HVMAXARCHITECTEDLPS; i++)
+ if (veth_cnx[i])
+ veth_kick_statemachine(veth_cnx[i]);
+
+ return 0;
+}
+
+/**
+ * veth_device_table: Used by vio.c to match devices that we
+ * support.
+ */
+static struct vio_device_id veth_device_table[] __devinitdata = {
+ { "vlan", "" },
+ { NULL, NULL }
+};
+MODULE_DEVICE_TABLE(vio, veth_device_table);
+
+static struct vio_driver veth_driver = {
+ .name = "iseries_veth",
+ .id_table = veth_device_table,
+ .probe = veth_probe,
+ .remove = veth_remove
+};
+
/*
* Module initialization/cleanup
*/
@@ -1335,27 +1391,17 @@ void __exit veth_module_cleanup(void)
{
int i;
+ vio_unregister_driver(&veth_driver);
+
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
veth_destroy_connection(i);
HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan);
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; ++i) {
- struct net_device *dev = veth_dev[i];
-
- if (! dev)
- continue;
-
- veth_dev[i] = NULL;
- unregister_netdev(dev);
- free_netdev(dev);
- }
}
module_exit(veth_module_cleanup);
int __init veth_module_init(void)
{
- HvLpIndexMap vlan_map = HvLpConfig_getVirtualLanIndexMap();
int i;
int rc;
@@ -1369,31 +1415,9 @@ int __init veth_module_init(void)
}
}
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; ++i) {
- struct net_device *dev;
-
- if (! (vlan_map & (0x8000 >> i)))
- continue;
-
- dev = veth_probe_one(i);
-
- if (! dev) {
- veth_module_cleanup();
- return rc;
- }
-
- veth_dev[i] = dev;
- }
-
HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan,
&veth_handle_event);
- /* Start the state machine on each connection, to commence
- * link negotiation */
- for (i = 0; i < HVMAXARCHITECTEDLPS; i++)
- if (veth_cnx[i])
- veth_kick_statemachine(veth_cnx[i]);
-
- return 0;
+ return vio_register_driver(&veth_driver);
}
module_init(veth_module_init);
diff --git a/drivers/net/iseries_veth.h b/drivers/net/iseries_veth.h
index 078d898fcf04..d9370f79b83e 100644
--- a/drivers/net/iseries_veth.h
+++ b/drivers/net/iseries_veth.h
@@ -43,6 +43,4 @@ struct VethLpEvent {
};
-#define HVMAXARCHITECTEDVIRTUALLANS (16)
-
#endif /* _ISERIES_VETH_H */
diff --git a/include/asm-ppc64/iSeries/HvTypes.h b/include/asm-ppc64/iSeries/HvTypes.h
index bdaaa2c5dd59..c8eb2b958dbc 100644
--- a/include/asm-ppc64/iSeries/HvTypes.h
+++ b/include/asm-ppc64/iSeries/HvTypes.h
@@ -65,6 +65,7 @@ typedef u8 HvAgentId; // Hypervisor DevFn
#define HVMAXARCHITECTEDLPS 32
+#define HVMAXARCHITECTEDVIRTUALLANS 16
#define HVCHUNKSIZE 256 * 1024
#define HVPAGESIZE 4 * 1024
#define HVLPMINMEGSPRIMARY 256