0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/irq.h>
0016 #include <linux/export.h>
0017 #include <linux/init.h>
0018
0019 #include <asm/mdesc.h>
0020 #include <asm/vio.h>
0021
0022 static const struct vio_device_id *vio_match_device(
0023 const struct vio_device_id *matches,
0024 const struct vio_dev *dev)
0025 {
0026 const char *type, *compat;
0027 int len;
0028
0029 type = dev->type;
0030 compat = dev->compat;
0031 len = dev->compat_len;
0032
0033 while (matches->type[0] || matches->compat[0]) {
0034 int match = 1;
0035 if (matches->type[0])
0036 match &= !strcmp(matches->type, type);
0037
0038 if (matches->compat[0]) {
0039 match &= len &&
0040 of_find_in_proplist(compat, matches->compat, len);
0041 }
0042 if (match)
0043 return matches;
0044 matches++;
0045 }
0046 return NULL;
0047 }
0048
0049 static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
0050 {
0051 const struct vio_dev *vio_dev = to_vio_dev(dev);
0052
0053 add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, vio_dev->compat);
0054 return 0;
0055 }
0056
0057 static int vio_bus_match(struct device *dev, struct device_driver *drv)
0058 {
0059 struct vio_dev *vio_dev = to_vio_dev(dev);
0060 struct vio_driver *vio_drv = to_vio_driver(drv);
0061 const struct vio_device_id *matches = vio_drv->id_table;
0062
0063 if (!matches)
0064 return 0;
0065
0066 return vio_match_device(matches, vio_dev) != NULL;
0067 }
0068
0069 static int vio_device_probe(struct device *dev)
0070 {
0071 struct vio_dev *vdev = to_vio_dev(dev);
0072 struct vio_driver *drv = to_vio_driver(dev->driver);
0073 const struct vio_device_id *id;
0074
0075 if (!drv->probe)
0076 return -ENODEV;
0077
0078 id = vio_match_device(drv->id_table, vdev);
0079 if (!id)
0080 return -ENODEV;
0081
0082
0083 if (!drv->no_irq) {
0084 if (vdev->tx_irq == 0 && vdev->tx_ino != ~0UL)
0085 vdev->tx_irq = sun4v_build_virq(vdev->cdev_handle,
0086 vdev->tx_ino);
0087
0088 if (vdev->rx_irq == 0 && vdev->rx_ino != ~0UL)
0089 vdev->rx_irq = sun4v_build_virq(vdev->cdev_handle,
0090 vdev->rx_ino);
0091 }
0092
0093 return drv->probe(vdev, id);
0094 }
0095
0096 static void vio_device_remove(struct device *dev)
0097 {
0098 struct vio_dev *vdev = to_vio_dev(dev);
0099 struct vio_driver *drv = to_vio_driver(dev->driver);
0100
0101 if (drv->remove) {
0102
0103
0104
0105
0106
0107
0108 drv->remove(vdev);
0109 }
0110 }
0111
0112 static ssize_t devspec_show(struct device *dev,
0113 struct device_attribute *attr, char *buf)
0114 {
0115 struct vio_dev *vdev = to_vio_dev(dev);
0116 const char *str = "none";
0117
0118 if (!strcmp(vdev->type, "vnet-port"))
0119 str = "vnet";
0120 else if (!strcmp(vdev->type, "vdc-port"))
0121 str = "vdisk";
0122
0123 return sprintf(buf, "%s\n", str);
0124 }
0125 static DEVICE_ATTR_RO(devspec);
0126
0127 static ssize_t type_show(struct device *dev,
0128 struct device_attribute *attr, char *buf)
0129 {
0130 struct vio_dev *vdev = to_vio_dev(dev);
0131 return sprintf(buf, "%s\n", vdev->type);
0132 }
0133 static DEVICE_ATTR_RO(type);
0134
0135 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
0136 char *buf)
0137 {
0138 const struct vio_dev *vdev = to_vio_dev(dev);
0139
0140 return sprintf(buf, "vio:T%sS%s\n", vdev->type, vdev->compat);
0141 }
0142 static DEVICE_ATTR_RO(modalias);
0143
0144 static struct attribute *vio_dev_attrs[] = {
0145 &dev_attr_devspec.attr,
0146 &dev_attr_type.attr,
0147 &dev_attr_modalias.attr,
0148 NULL,
0149 };
0150 ATTRIBUTE_GROUPS(vio_dev);
0151
0152 static struct bus_type vio_bus_type = {
0153 .name = "vio",
0154 .dev_groups = vio_dev_groups,
0155 .uevent = vio_hotplug,
0156 .match = vio_bus_match,
0157 .probe = vio_device_probe,
0158 .remove = vio_device_remove,
0159 };
0160
0161 int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
0162 const char *mod_name)
0163 {
0164 viodrv->driver.bus = &vio_bus_type;
0165 viodrv->driver.name = viodrv->name;
0166 viodrv->driver.owner = owner;
0167 viodrv->driver.mod_name = mod_name;
0168
0169 return driver_register(&viodrv->driver);
0170 }
0171 EXPORT_SYMBOL(__vio_register_driver);
0172
0173 void vio_unregister_driver(struct vio_driver *viodrv)
0174 {
0175 driver_unregister(&viodrv->driver);
0176 }
0177 EXPORT_SYMBOL(vio_unregister_driver);
0178
0179 static void vio_dev_release(struct device *dev)
0180 {
0181 kfree(to_vio_dev(dev));
0182 }
0183
0184 static ssize_t
0185 show_pciobppath_attr(struct device *dev, struct device_attribute *attr,
0186 char *buf)
0187 {
0188 struct vio_dev *vdev;
0189 struct device_node *dp;
0190
0191 vdev = to_vio_dev(dev);
0192 dp = vdev->dp;
0193
0194 return scnprintf(buf, PAGE_SIZE, "%pOF\n", dp);
0195 }
0196
0197 static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH,
0198 show_pciobppath_attr, NULL);
0199
0200 static struct device_node *cdev_node;
0201
0202 static struct vio_dev *root_vdev;
0203 static u64 cdev_cfg_handle;
0204
0205 static const u64 *vio_cfg_handle(struct mdesc_handle *hp, u64 node)
0206 {
0207 const u64 *cfg_handle = NULL;
0208 u64 a;
0209
0210 mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
0211 u64 target;
0212
0213 target = mdesc_arc_target(hp, a);
0214 cfg_handle = mdesc_get_property(hp, target,
0215 "cfg-handle", NULL);
0216 if (cfg_handle)
0217 break;
0218 }
0219
0220 return cfg_handle;
0221 }
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 u64 vio_vdev_node(struct mdesc_handle *hp, struct vio_dev *vdev)
0237 {
0238 u64 node;
0239
0240 if (vdev == NULL)
0241 return MDESC_NODE_NULL;
0242
0243 node = mdesc_get_node(hp, (const char *)vdev->node_name,
0244 &vdev->md_node_info);
0245
0246 return node;
0247 }
0248 EXPORT_SYMBOL(vio_vdev_node);
0249
0250 static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
0251 struct vio_dev *vdev)
0252 {
0253 u64 a;
0254
0255 vdev->tx_ino = ~0UL;
0256 vdev->rx_ino = ~0UL;
0257 vdev->channel_id = ~0UL;
0258 mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
0259 const u64 *chan_id;
0260 const u64 *irq;
0261 u64 target;
0262
0263 target = mdesc_arc_target(hp, a);
0264
0265 irq = mdesc_get_property(hp, target, "tx-ino", NULL);
0266 if (irq)
0267 vdev->tx_ino = *irq;
0268
0269 irq = mdesc_get_property(hp, target, "rx-ino", NULL);
0270 if (irq)
0271 vdev->rx_ino = *irq;
0272
0273 chan_id = mdesc_get_property(hp, target, "id", NULL);
0274 if (chan_id)
0275 vdev->channel_id = *chan_id;
0276 }
0277
0278 vdev->cdev_handle = cdev_cfg_handle;
0279 }
0280
0281 int vio_set_intr(unsigned long dev_ino, int state)
0282 {
0283 int err;
0284
0285 err = sun4v_vintr_set_valid(cdev_cfg_handle, dev_ino, state);
0286 return err;
0287 }
0288 EXPORT_SYMBOL(vio_set_intr);
0289
0290 static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
0291 const char *node_name,
0292 struct device *parent)
0293 {
0294 const char *type, *compat;
0295 struct device_node *dp;
0296 struct vio_dev *vdev;
0297 int err, tlen, clen;
0298 const u64 *id, *cfg_handle;
0299
0300 type = mdesc_get_property(hp, mp, "device-type", &tlen);
0301 if (!type) {
0302 type = mdesc_get_property(hp, mp, "name", &tlen);
0303 if (!type) {
0304 type = mdesc_node_name(hp, mp);
0305 tlen = strlen(type) + 1;
0306 }
0307 }
0308 if (tlen > VIO_MAX_TYPE_LEN || strlen(type) >= VIO_MAX_TYPE_LEN) {
0309 printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
0310 type);
0311 return NULL;
0312 }
0313
0314 id = mdesc_get_property(hp, mp, "id", NULL);
0315
0316 cfg_handle = vio_cfg_handle(hp, mp);
0317
0318 compat = mdesc_get_property(hp, mp, "device-type", &clen);
0319 if (!compat) {
0320 clen = 0;
0321 } else if (clen > VIO_MAX_COMPAT_LEN) {
0322 printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
0323 clen, type);
0324 return NULL;
0325 }
0326
0327 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
0328 if (!vdev) {
0329 printk(KERN_ERR "VIO: Could not allocate vio_dev\n");
0330 return NULL;
0331 }
0332
0333 vdev->mp = mp;
0334 memcpy(vdev->type, type, tlen);
0335 if (compat)
0336 memcpy(vdev->compat, compat, clen);
0337 else
0338 memset(vdev->compat, 0, sizeof(vdev->compat));
0339 vdev->compat_len = clen;
0340
0341 vdev->port_id = ~0UL;
0342 vdev->tx_irq = 0;
0343 vdev->rx_irq = 0;
0344
0345 vio_fill_channel_info(hp, mp, vdev);
0346
0347 if (!id) {
0348 dev_set_name(&vdev->dev, "%s", type);
0349 vdev->dev_no = ~(u64)0;
0350 } else if (!cfg_handle) {
0351 dev_set_name(&vdev->dev, "%s-%llu", type, *id);
0352 vdev->dev_no = *id;
0353 } else {
0354 dev_set_name(&vdev->dev, "%s-%llu-%llu", type,
0355 *cfg_handle, *id);
0356 vdev->dev_no = *cfg_handle;
0357 vdev->port_id = *id;
0358 }
0359
0360 vdev->dev.parent = parent;
0361 vdev->dev.bus = &vio_bus_type;
0362 vdev->dev.release = vio_dev_release;
0363
0364 if (parent == NULL) {
0365 dp = cdev_node;
0366 } else if (to_vio_dev(parent) == root_vdev) {
0367 for_each_child_of_node(cdev_node, dp) {
0368 if (of_node_is_type(dp, type))
0369 break;
0370 }
0371 } else {
0372 dp = to_vio_dev(parent)->dp;
0373 }
0374 vdev->dp = dp;
0375
0376
0377
0378
0379
0380 if (node_name != NULL) {
0381 (void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s",
0382 node_name);
0383
0384 err = mdesc_get_node_info(hp, mp, node_name,
0385 &vdev->md_node_info);
0386 if (err) {
0387 pr_err("VIO: Could not get MD node info %s, err=%d\n",
0388 dev_name(&vdev->dev), err);
0389 kfree(vdev);
0390 return NULL;
0391 }
0392 }
0393
0394 pr_info("VIO: Adding device %s (tx_ino = %llx, rx_ino = %llx)\n",
0395 dev_name(&vdev->dev), vdev->tx_ino, vdev->rx_ino);
0396
0397 err = device_register(&vdev->dev);
0398 if (err) {
0399 printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
0400 dev_name(&vdev->dev), err);
0401 put_device(&vdev->dev);
0402 return NULL;
0403 }
0404 if (vdev->dp)
0405 err = sysfs_create_file(&vdev->dev.kobj,
0406 &dev_attr_obppath.attr);
0407
0408 return vdev;
0409 }
0410
0411 static void vio_add(struct mdesc_handle *hp, u64 node,
0412 const char *node_name)
0413 {
0414 (void) vio_create_one(hp, node, node_name, &root_vdev->dev);
0415 }
0416
0417 struct vio_remove_node_data {
0418 struct mdesc_handle *hp;
0419 u64 node;
0420 };
0421
0422 static int vio_md_node_match(struct device *dev, void *arg)
0423 {
0424 struct vio_dev *vdev = to_vio_dev(dev);
0425 struct vio_remove_node_data *node_data;
0426 u64 node;
0427
0428 node_data = (struct vio_remove_node_data *)arg;
0429
0430 node = vio_vdev_node(node_data->hp, vdev);
0431
0432 if (node == node_data->node)
0433 return 1;
0434 else
0435 return 0;
0436 }
0437
0438 static void vio_remove(struct mdesc_handle *hp, u64 node, const char *node_name)
0439 {
0440 struct vio_remove_node_data node_data;
0441 struct device *dev;
0442
0443 node_data.hp = hp;
0444 node_data.node = node;
0445
0446 dev = device_find_child(&root_vdev->dev, (void *)&node_data,
0447 vio_md_node_match);
0448 if (dev) {
0449 printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev));
0450
0451 device_unregister(dev);
0452 put_device(dev);
0453 } else {
0454 pr_err("VIO: %s node not found in MDESC\n", node_name);
0455 }
0456 }
0457
0458 static struct mdesc_notifier_client vio_device_notifier = {
0459 .add = vio_add,
0460 .remove = vio_remove,
0461 .node_name = "virtual-device-port",
0462 };
0463
0464
0465
0466
0467
0468
0469 static void vio_add_ds(struct mdesc_handle *hp, u64 node,
0470 const char *node_name)
0471 {
0472 int found;
0473 u64 a;
0474
0475 found = 0;
0476 mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
0477 u64 target = mdesc_arc_target(hp, a);
0478 const char *name = mdesc_node_name(hp, target);
0479
0480 if (!strcmp(name, "domain-services")) {
0481 found = 1;
0482 break;
0483 }
0484 }
0485
0486 if (found)
0487 (void) vio_create_one(hp, node, node_name, &root_vdev->dev);
0488 }
0489
0490 static struct mdesc_notifier_client vio_ds_notifier = {
0491 .add = vio_add_ds,
0492 .remove = vio_remove,
0493 .node_name = "domain-services-port",
0494 };
0495
0496 static const char *channel_devices_node = "channel-devices";
0497 static const char *channel_devices_compat = "SUNW,sun4v-channel-devices";
0498 static const char *cfg_handle_prop = "cfg-handle";
0499
0500 static int __init vio_init(void)
0501 {
0502 struct mdesc_handle *hp;
0503 const char *compat;
0504 const u64 *cfg_handle;
0505 int err, len;
0506 u64 root;
0507
0508 err = bus_register(&vio_bus_type);
0509 if (err) {
0510 printk(KERN_ERR "VIO: Could not register bus type err=%d\n",
0511 err);
0512 return err;
0513 }
0514
0515 hp = mdesc_grab();
0516 if (!hp)
0517 return 0;
0518
0519 root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node);
0520 if (root == MDESC_NODE_NULL) {
0521 printk(KERN_INFO "VIO: No channel-devices MDESC node.\n");
0522 mdesc_release(hp);
0523 return 0;
0524 }
0525
0526 cdev_node = of_find_node_by_name(NULL, "channel-devices");
0527 err = -ENODEV;
0528 if (!cdev_node) {
0529 printk(KERN_INFO "VIO: No channel-devices OBP node.\n");
0530 goto out_release;
0531 }
0532
0533 compat = mdesc_get_property(hp, root, "compatible", &len);
0534 if (!compat) {
0535 printk(KERN_ERR "VIO: Channel devices lacks compatible "
0536 "property\n");
0537 goto out_release;
0538 }
0539 if (!of_find_in_proplist(compat, channel_devices_compat, len)) {
0540 printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
0541 "compat entry.\n", channel_devices_compat);
0542 goto out_release;
0543 }
0544
0545 cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL);
0546 if (!cfg_handle) {
0547 printk(KERN_ERR "VIO: Channel devices lacks %s property\n",
0548 cfg_handle_prop);
0549 goto out_release;
0550 }
0551
0552 cdev_cfg_handle = *cfg_handle;
0553
0554 root_vdev = vio_create_one(hp, root, NULL, NULL);
0555 err = -ENODEV;
0556 if (!root_vdev) {
0557 printk(KERN_ERR "VIO: Could not create root device.\n");
0558 goto out_release;
0559 }
0560
0561 mdesc_register_notifier(&vio_device_notifier);
0562 mdesc_register_notifier(&vio_ds_notifier);
0563
0564 mdesc_release(hp);
0565
0566 return err;
0567
0568 out_release:
0569 mdesc_release(hp);
0570 return err;
0571 }
0572
0573 postcore_initcall(vio_init);