mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-06 14:48:06 +00:00
sparc64: enhance VIO device probing
- Allocate IRQs for VIO devices during probing. - Allow clients to specify if IRQs would be allocated for a given VIO device. - Cache the device handle of the root node of channel-devices sub-tree in Machine Description (MDESC). Signed-off-by: Jagannathan Raman <jag.raman@oracle.com> Reviewed-by: Liam Merwick <liam.merwick@oracle.com> Reviewed-by: Shannon Nelson <shannon.nelson@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
110f2264b3
commit
aa512d5ede
2 changed files with 42 additions and 16 deletions
|
@ -336,6 +336,10 @@ struct vio_dev {
|
||||||
unsigned int tx_irq;
|
unsigned int tx_irq;
|
||||||
unsigned int rx_irq;
|
unsigned int rx_irq;
|
||||||
u64 rx_ino;
|
u64 rx_ino;
|
||||||
|
u64 tx_ino;
|
||||||
|
|
||||||
|
/* Handle to the root of "channel-devices" sub-tree in MDESC */
|
||||||
|
u64 cdev_handle;
|
||||||
|
|
||||||
struct device dev;
|
struct device dev;
|
||||||
};
|
};
|
||||||
|
@ -349,6 +353,7 @@ struct vio_driver {
|
||||||
void (*shutdown)(struct vio_dev *dev);
|
void (*shutdown)(struct vio_dev *dev);
|
||||||
unsigned long driver_data;
|
unsigned long driver_data;
|
||||||
struct device_driver driver;
|
struct device_driver driver;
|
||||||
|
bool no_irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vio_version {
|
struct vio_version {
|
||||||
|
|
|
@ -70,15 +70,26 @@ static int vio_device_probe(struct device *dev)
|
||||||
struct vio_dev *vdev = to_vio_dev(dev);
|
struct vio_dev *vdev = to_vio_dev(dev);
|
||||||
struct vio_driver *drv = to_vio_driver(dev->driver);
|
struct vio_driver *drv = to_vio_driver(dev->driver);
|
||||||
const struct vio_device_id *id;
|
const struct vio_device_id *id;
|
||||||
int error = -ENODEV;
|
|
||||||
|
|
||||||
if (drv->probe) {
|
if (!drv->probe)
|
||||||
id = vio_match_device(drv->id_table, vdev);
|
return -ENODEV;
|
||||||
if (id)
|
|
||||||
error = drv->probe(vdev, id);
|
id = vio_match_device(drv->id_table, vdev);
|
||||||
|
if (!id)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* alloc irqs (unless the driver specified not to) */
|
||||||
|
if (!drv->no_irq) {
|
||||||
|
if (vdev->tx_irq == 0 && vdev->tx_ino != ~0UL)
|
||||||
|
vdev->tx_irq = sun4v_build_virq(vdev->cdev_handle,
|
||||||
|
vdev->tx_ino);
|
||||||
|
|
||||||
|
if (vdev->rx_irq == 0 && vdev->rx_ino != ~0UL)
|
||||||
|
vdev->rx_irq = sun4v_build_virq(vdev->cdev_handle,
|
||||||
|
vdev->rx_ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return drv->probe(vdev, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vio_device_remove(struct device *dev)
|
static int vio_device_remove(struct device *dev)
|
||||||
|
@ -86,8 +97,15 @@ static int vio_device_remove(struct device *dev)
|
||||||
struct vio_dev *vdev = to_vio_dev(dev);
|
struct vio_dev *vdev = to_vio_dev(dev);
|
||||||
struct vio_driver *drv = to_vio_driver(dev->driver);
|
struct vio_driver *drv = to_vio_driver(dev->driver);
|
||||||
|
|
||||||
if (drv->remove)
|
if (drv->remove) {
|
||||||
|
/*
|
||||||
|
* Ideally, we would remove/deallocate tx/rx virqs
|
||||||
|
* here - however, there are currently no support
|
||||||
|
* routines to do so at the moment. TBD
|
||||||
|
*/
|
||||||
|
|
||||||
return drv->remove(vdev);
|
return drv->remove(vdev);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -204,6 +222,9 @@ static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
|
||||||
{
|
{
|
||||||
u64 a;
|
u64 a;
|
||||||
|
|
||||||
|
vdev->tx_ino = ~0UL;
|
||||||
|
vdev->rx_ino = ~0UL;
|
||||||
|
vdev->channel_id = ~0UL;
|
||||||
mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
|
mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
|
||||||
const u64 *chan_id;
|
const u64 *chan_id;
|
||||||
const u64 *irq;
|
const u64 *irq;
|
||||||
|
@ -213,18 +234,18 @@ static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
|
||||||
|
|
||||||
irq = mdesc_get_property(hp, target, "tx-ino", NULL);
|
irq = mdesc_get_property(hp, target, "tx-ino", NULL);
|
||||||
if (irq)
|
if (irq)
|
||||||
vdev->tx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
|
vdev->tx_ino = *irq;
|
||||||
|
|
||||||
irq = mdesc_get_property(hp, target, "rx-ino", NULL);
|
irq = mdesc_get_property(hp, target, "rx-ino", NULL);
|
||||||
if (irq) {
|
if (irq)
|
||||||
vdev->rx_irq = sun4v_build_virq(cdev_cfg_handle, *irq);
|
|
||||||
vdev->rx_ino = *irq;
|
vdev->rx_ino = *irq;
|
||||||
}
|
|
||||||
|
|
||||||
chan_id = mdesc_get_property(hp, target, "id", NULL);
|
chan_id = mdesc_get_property(hp, target, "id", NULL);
|
||||||
if (chan_id)
|
if (chan_id)
|
||||||
vdev->channel_id = *chan_id;
|
vdev->channel_id = *chan_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vdev->cdev_handle = cdev_cfg_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vio_set_intr(unsigned long dev_ino, int state)
|
int vio_set_intr(unsigned long dev_ino, int state)
|
||||||
|
@ -287,9 +308,8 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
|
||||||
memset(vdev->compat, 0, sizeof(vdev->compat));
|
memset(vdev->compat, 0, sizeof(vdev->compat));
|
||||||
vdev->compat_len = clen;
|
vdev->compat_len = clen;
|
||||||
|
|
||||||
vdev->channel_id = ~0UL;
|
vdev->tx_irq = 0;
|
||||||
vdev->tx_irq = ~0;
|
vdev->rx_irq = 0;
|
||||||
vdev->rx_irq = ~0;
|
|
||||||
|
|
||||||
vio_fill_channel_info(hp, mp, vdev);
|
vio_fill_channel_info(hp, mp, vdev);
|
||||||
|
|
||||||
|
@ -327,13 +347,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
|
||||||
}
|
}
|
||||||
vdev->dp = dp;
|
vdev->dp = dp;
|
||||||
|
|
||||||
printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev));
|
|
||||||
|
|
||||||
/* node_name is NULL for the parent/channel-devices node */
|
/* node_name is NULL for the parent/channel-devices node */
|
||||||
if (node_name != NULL)
|
if (node_name != NULL)
|
||||||
(void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s",
|
(void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s",
|
||||||
node_name);
|
node_name);
|
||||||
|
|
||||||
|
pr_info("VIO: Adding device %s (tx_ino = %llx, rx_ino = %llx)\n",
|
||||||
|
dev_name(&vdev->dev), vdev->tx_ino, vdev->rx_ino);
|
||||||
|
|
||||||
err = device_register(&vdev->dev);
|
err = device_register(&vdev->dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
|
printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
|
||||||
|
|
Loading…
Add table
Reference in a new issue