1  // SPDX-License-Identifier: GPL-2.0
2  /* vio.c: Virtual I/O channel devices probing infrastructure.
3   *
4   *    Copyright (c) 2003-2005 IBM Corp.
5   *     Dave Engebretsen engebret@us.ibm.com
6   *     Santiago Leon santil@us.ibm.com
7   *     Hollis Blanchard <hollisb@us.ibm.com>
8   *     Stephen Rothwell
9   *
10   * Adapted to sparc64 by David S. Miller davem@davemloft.net
11   */
12  
13  #include <linux/kernel.h>
14  #include <linux/slab.h>
15  #include <linux/irq.h>
16  #include <linux/export.h>
17  #include <linux/init.h>
18  
19  #include <asm/mdesc.h>
20  #include <asm/vio.h>
21  
vio_match_device(const struct vio_device_id * matches,const struct vio_dev * dev)22  static const struct vio_device_id *vio_match_device(
23  	const struct vio_device_id *matches,
24  	const struct vio_dev *dev)
25  {
26  	const char *type, *compat;
27  	int len;
28  
29  	type = dev->type;
30  	compat = dev->compat;
31  	len = dev->compat_len;
32  
33  	while (matches->type[0] || matches->compat[0]) {
34  		int match = 1;
35  		if (matches->type[0])
36  			match &= !strcmp(matches->type, type);
37  
38  		if (matches->compat[0]) {
39  			match &= len &&
40  				of_find_in_proplist(compat, matches->compat, len);
41  		}
42  		if (match)
43  			return matches;
44  		matches++;
45  	}
46  	return NULL;
47  }
48  
vio_hotplug(struct device * dev,struct kobj_uevent_env * env)49  static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
50  {
51  	const struct vio_dev *vio_dev = to_vio_dev(dev);
52  
53  	add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, vio_dev->compat);
54  	return 0;
55  }
56  
vio_bus_match(struct device * dev,struct device_driver * drv)57  static int vio_bus_match(struct device *dev, struct device_driver *drv)
58  {
59  	struct vio_dev *vio_dev = to_vio_dev(dev);
60  	struct vio_driver *vio_drv = to_vio_driver(drv);
61  	const struct vio_device_id *matches = vio_drv->id_table;
62  
63  	if (!matches)
64  		return 0;
65  
66  	return vio_match_device(matches, vio_dev) != NULL;
67  }
68  
vio_device_probe(struct device * dev)69  static int vio_device_probe(struct device *dev)
70  {
71  	struct vio_dev *vdev = to_vio_dev(dev);
72  	struct vio_driver *drv = to_vio_driver(dev->driver);
73  	const struct vio_device_id *id;
74  
75  	if (!drv->probe)
76  		return -ENODEV;
77  
78  	id = vio_match_device(drv->id_table, vdev);
79  	if (!id)
80  		return -ENODEV;
81  
82  	/* alloc irqs (unless the driver specified not to) */
83  	if (!drv->no_irq) {
84  		if (vdev->tx_irq == 0 && vdev->tx_ino != ~0UL)
85  			vdev->tx_irq = sun4v_build_virq(vdev->cdev_handle,
86  							vdev->tx_ino);
87  
88  		if (vdev->rx_irq == 0 && vdev->rx_ino != ~0UL)
89  			vdev->rx_irq = sun4v_build_virq(vdev->cdev_handle,
90  							vdev->rx_ino);
91  	}
92  
93  	return drv->probe(vdev, id);
94  }
95  
vio_device_remove(struct device * dev)96  static void vio_device_remove(struct device *dev)
97  {
98  	struct vio_dev *vdev = to_vio_dev(dev);
99  	struct vio_driver *drv = to_vio_driver(dev->driver);
100  
101  	if (drv->remove) {
102  		/*
103  		 * Ideally, we would remove/deallocate tx/rx virqs
104  		 * here - however, there are currently no support
105  		 * routines to do so at the moment. TBD
106  		 */
107  
108  		drv->remove(vdev);
109  	}
110  }
111  
devspec_show(struct device * dev,struct device_attribute * attr,char * buf)112  static ssize_t devspec_show(struct device *dev,
113  		struct device_attribute *attr, char *buf)
114  {
115  	struct vio_dev *vdev = to_vio_dev(dev);
116  	const char *str = "none";
117  
118  	if (!strcmp(vdev->type, "vnet-port"))
119  		str = "vnet";
120  	else if (!strcmp(vdev->type, "vdc-port"))
121  		str = "vdisk";
122  
123  	return sprintf(buf, "%s\n", str);
124  }
125  static DEVICE_ATTR_RO(devspec);
126  
type_show(struct device * dev,struct device_attribute * attr,char * buf)127  static ssize_t type_show(struct device *dev,
128  		struct device_attribute *attr, char *buf)
129  {
130  	struct vio_dev *vdev = to_vio_dev(dev);
131  	return sprintf(buf, "%s\n", vdev->type);
132  }
133  static DEVICE_ATTR_RO(type);
134  
modalias_show(struct device * dev,struct device_attribute * attr,char * buf)135  static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
136  			     char *buf)
137  {
138  	const struct vio_dev *vdev = to_vio_dev(dev);
139  
140  	return sprintf(buf, "vio:T%sS%s\n", vdev->type, vdev->compat);
141  }
142  static DEVICE_ATTR_RO(modalias);
143  
144  static struct attribute *vio_dev_attrs[] = {
145  	&dev_attr_devspec.attr,
146  	&dev_attr_type.attr,
147  	&dev_attr_modalias.attr,
148  	NULL,
149   };
150  ATTRIBUTE_GROUPS(vio_dev);
151  
152  static struct bus_type vio_bus_type = {
153  	.name		= "vio",
154  	.dev_groups	= vio_dev_groups,
155  	.uevent         = vio_hotplug,
156  	.match		= vio_bus_match,
157  	.probe		= vio_device_probe,
158  	.remove		= vio_device_remove,
159  };
160  
__vio_register_driver(struct vio_driver * viodrv,struct module * owner,const char * mod_name)161  int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
162  			const char *mod_name)
163  {
164  	viodrv->driver.bus = &vio_bus_type;
165  	viodrv->driver.name = viodrv->name;
166  	viodrv->driver.owner = owner;
167  	viodrv->driver.mod_name = mod_name;
168  
169  	return driver_register(&viodrv->driver);
170  }
171  EXPORT_SYMBOL(__vio_register_driver);
172  
vio_unregister_driver(struct vio_driver * viodrv)173  void vio_unregister_driver(struct vio_driver *viodrv)
174  {
175  	driver_unregister(&viodrv->driver);
176  }
177  EXPORT_SYMBOL(vio_unregister_driver);
178  
vio_dev_release(struct device * dev)179  static void vio_dev_release(struct device *dev)
180  {
181  	kfree(to_vio_dev(dev));
182  }
183  
184  static ssize_t
show_pciobppath_attr(struct device * dev,struct device_attribute * attr,char * buf)185  show_pciobppath_attr(struct device *dev, struct device_attribute *attr,
186  		     char *buf)
187  {
188  	struct vio_dev *vdev;
189  	struct device_node *dp;
190  
191  	vdev = to_vio_dev(dev);
192  	dp = vdev->dp;
193  
194  	return scnprintf(buf, PAGE_SIZE, "%pOF\n", dp);
195  }
196  
197  static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH,
198  		   show_pciobppath_attr, NULL);
199  
200  static struct device_node *cdev_node;
201  
202  static struct vio_dev *root_vdev;
203  static u64 cdev_cfg_handle;
204  
vio_cfg_handle(struct mdesc_handle * hp,u64 node)205  static const u64 *vio_cfg_handle(struct mdesc_handle *hp, u64 node)
206  {
207  	const u64 *cfg_handle = NULL;
208  	u64 a;
209  
210  	mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
211  		u64 target;
212  
213  		target = mdesc_arc_target(hp, a);
214  		cfg_handle = mdesc_get_property(hp, target,
215  						"cfg-handle", NULL);
216  		if (cfg_handle)
217  			break;
218  	}
219  
220  	return cfg_handle;
221  }
222  
223  /**
224   * vio_vdev_node() - Find VDEV node in MD
225   * @hp:  Handle to the MD
226   * @vdev:  Pointer to VDEV
227   *
228   * Find the node in the current MD which matches the given vio_dev. This
229   * must be done dynamically since the node value can change if the MD
230   * is updated.
231   *
232   * NOTE: the MD must be locked, using mdesc_grab(), when calling this routine
233   *
234   * Return: The VDEV node in MDESC
235   */
vio_vdev_node(struct mdesc_handle * hp,struct vio_dev * vdev)236  u64 vio_vdev_node(struct mdesc_handle *hp, struct vio_dev *vdev)
237  {
238  	u64 node;
239  
240  	if (vdev == NULL)
241  		return MDESC_NODE_NULL;
242  
243  	node = mdesc_get_node(hp, (const char *)vdev->node_name,
244  			      &vdev->md_node_info);
245  
246  	return node;
247  }
248  EXPORT_SYMBOL(vio_vdev_node);
249  
vio_fill_channel_info(struct mdesc_handle * hp,u64 mp,struct vio_dev * vdev)250  static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp,
251  				  struct vio_dev *vdev)
252  {
253  	u64 a;
254  
255  	vdev->tx_ino = ~0UL;
256  	vdev->rx_ino = ~0UL;
257  	vdev->channel_id = ~0UL;
258  	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
259  		const u64 *chan_id;
260  		const u64 *irq;
261  		u64 target;
262  
263  		target = mdesc_arc_target(hp, a);
264  
265  		irq = mdesc_get_property(hp, target, "tx-ino", NULL);
266  		if (irq)
267  			vdev->tx_ino = *irq;
268  
269  		irq = mdesc_get_property(hp, target, "rx-ino", NULL);
270  		if (irq)
271  			vdev->rx_ino = *irq;
272  
273  		chan_id = mdesc_get_property(hp, target, "id", NULL);
274  		if (chan_id)
275  			vdev->channel_id = *chan_id;
276  	}
277  
278  	vdev->cdev_handle = cdev_cfg_handle;
279  }
280  
vio_set_intr(unsigned long dev_ino,int state)281  int vio_set_intr(unsigned long dev_ino, int state)
282  {
283  	int err;
284  
285  	err = sun4v_vintr_set_valid(cdev_cfg_handle, dev_ino, state);
286  	return err;
287  }
288  EXPORT_SYMBOL(vio_set_intr);
289  
vio_create_one(struct mdesc_handle * hp,u64 mp,const char * node_name,struct device * parent)290  static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
291  				      const char *node_name,
292  				      struct device *parent)
293  {
294  	const char *type, *compat;
295  	struct device_node *dp;
296  	struct vio_dev *vdev;
297  	int err, tlen, clen;
298  	const u64 *id, *cfg_handle;
299  
300  	type = mdesc_get_property(hp, mp, "device-type", &tlen);
301  	if (!type) {
302  		type = mdesc_get_property(hp, mp, "name", &tlen);
303  		if (!type) {
304  			type = mdesc_node_name(hp, mp);
305  			tlen = strlen(type) + 1;
306  		}
307  	}
308  	if (tlen > VIO_MAX_TYPE_LEN || strlen(type) >= VIO_MAX_TYPE_LEN) {
309  		printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
310  		       type);
311  		return NULL;
312  	}
313  
314  	id = mdesc_get_property(hp, mp, "id", NULL);
315  
316  	cfg_handle = vio_cfg_handle(hp, mp);
317  
318  	compat = mdesc_get_property(hp, mp, "device-type", &clen);
319  	if (!compat) {
320  		clen = 0;
321  	} else if (clen > VIO_MAX_COMPAT_LEN) {
322  		printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
323  		       clen, type);
324  		return NULL;
325  	}
326  
327  	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
328  	if (!vdev) {
329  		printk(KERN_ERR "VIO: Could not allocate vio_dev\n");
330  		return NULL;
331  	}
332  
333  	vdev->mp = mp;
334  	memcpy(vdev->type, type, tlen);
335  	if (compat)
336  		memcpy(vdev->compat, compat, clen);
337  	else
338  		memset(vdev->compat, 0, sizeof(vdev->compat));
339  	vdev->compat_len = clen;
340  
341  	vdev->port_id = ~0UL;
342  	vdev->tx_irq = 0;
343  	vdev->rx_irq = 0;
344  
345  	vio_fill_channel_info(hp, mp, vdev);
346  
347  	if (!id) {
348  		dev_set_name(&vdev->dev, "%s", type);
349  		vdev->dev_no = ~(u64)0;
350  	} else if (!cfg_handle) {
351  		dev_set_name(&vdev->dev, "%s-%llu", type, *id);
352  		vdev->dev_no = *id;
353  	} else {
354  		dev_set_name(&vdev->dev, "%s-%llu-%llu", type,
355  			     *cfg_handle, *id);
356  		vdev->dev_no = *cfg_handle;
357  		vdev->port_id = *id;
358  	}
359  
360  	vdev->dev.parent = parent;
361  	vdev->dev.bus = &vio_bus_type;
362  	vdev->dev.release = vio_dev_release;
363  
364  	if (parent == NULL) {
365  		dp = cdev_node;
366  	} else if (to_vio_dev(parent) == root_vdev) {
367  		for_each_child_of_node(cdev_node, dp) {
368  			if (of_node_is_type(dp, type))
369  				break;
370  		}
371  	} else {
372  		dp = to_vio_dev(parent)->dp;
373  	}
374  	vdev->dp = dp;
375  
376  	/*
377  	 * node_name is NULL for the parent/channel-devices node and
378  	 * the parent doesn't require the MD node info.
379  	 */
380  	if (node_name != NULL) {
381  		(void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s",
382  				node_name);
383  
384  		err = mdesc_get_node_info(hp, mp, node_name,
385  					  &vdev->md_node_info);
386  		if (err) {
387  			pr_err("VIO: Could not get MD node info %s, err=%d\n",
388  			       dev_name(&vdev->dev), err);
389  			kfree(vdev);
390  			return NULL;
391  		}
392  	}
393  
394  	pr_info("VIO: Adding device %s (tx_ino = %llx, rx_ino = %llx)\n",
395  		dev_name(&vdev->dev), vdev->tx_ino, vdev->rx_ino);
396  
397  	err = device_register(&vdev->dev);
398  	if (err) {
399  		printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
400  		       dev_name(&vdev->dev), err);
401  		put_device(&vdev->dev);
402  		return NULL;
403  	}
404  	if (vdev->dp)
405  		err = sysfs_create_file(&vdev->dev.kobj,
406  					&dev_attr_obppath.attr);
407  
408  	return vdev;
409  }
410  
vio_add(struct mdesc_handle * hp,u64 node,const char * node_name)411  static void vio_add(struct mdesc_handle *hp, u64 node,
412  		    const char *node_name)
413  {
414  	(void) vio_create_one(hp, node, node_name, &root_vdev->dev);
415  }
416  
417  struct vio_remove_node_data {
418  	struct mdesc_handle *hp;
419  	u64 node;
420  };
421  
vio_md_node_match(struct device * dev,void * arg)422  static int vio_md_node_match(struct device *dev, void *arg)
423  {
424  	struct vio_dev *vdev = to_vio_dev(dev);
425  	struct vio_remove_node_data *node_data;
426  	u64 node;
427  
428  	node_data = (struct vio_remove_node_data *)arg;
429  
430  	node = vio_vdev_node(node_data->hp, vdev);
431  
432  	if (node == node_data->node)
433  		return 1;
434  	else
435  		return 0;
436  }
437  
vio_remove(struct mdesc_handle * hp,u64 node,const char * node_name)438  static void vio_remove(struct mdesc_handle *hp, u64 node, const char *node_name)
439  {
440  	struct vio_remove_node_data node_data;
441  	struct device *dev;
442  
443  	node_data.hp = hp;
444  	node_data.node = node;
445  
446  	dev = device_find_child(&root_vdev->dev, (void *)&node_data,
447  				vio_md_node_match);
448  	if (dev) {
449  		printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev));
450  
451  		device_unregister(dev);
452  		put_device(dev);
453  	} else {
454  		pr_err("VIO: %s node not found in MDESC\n", node_name);
455  	}
456  }
457  
458  static struct mdesc_notifier_client vio_device_notifier = {
459  	.add		= vio_add,
460  	.remove		= vio_remove,
461  	.node_name	= "virtual-device-port",
462  };
463  
464  /* We are only interested in domain service ports under the
465   * "domain-services" node.  On control nodes there is another port
466   * under "openboot" that we should not mess with as aparently that is
467   * reserved exclusively for OBP use.
468   */
vio_add_ds(struct mdesc_handle * hp,u64 node,const char * node_name)469  static void vio_add_ds(struct mdesc_handle *hp, u64 node,
470  		       const char *node_name)
471  {
472  	int found;
473  	u64 a;
474  
475  	found = 0;
476  	mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
477  		u64 target = mdesc_arc_target(hp, a);
478  		const char *name = mdesc_node_name(hp, target);
479  
480  		if (!strcmp(name, "domain-services")) {
481  			found = 1;
482  			break;
483  		}
484  	}
485  
486  	if (found)
487  		(void) vio_create_one(hp, node, node_name, &root_vdev->dev);
488  }
489  
490  static struct mdesc_notifier_client vio_ds_notifier = {
491  	.add		= vio_add_ds,
492  	.remove		= vio_remove,
493  	.node_name	= "domain-services-port",
494  };
495  
496  static const char *channel_devices_node = "channel-devices";
497  static const char *channel_devices_compat = "SUNW,sun4v-channel-devices";
498  static const char *cfg_handle_prop = "cfg-handle";
499  
vio_init(void)500  static int __init vio_init(void)
501  {
502  	struct mdesc_handle *hp;
503  	const char *compat;
504  	const u64 *cfg_handle;
505  	int err, len;
506  	u64 root;
507  
508  	err = bus_register(&vio_bus_type);
509  	if (err) {
510  		printk(KERN_ERR "VIO: Could not register bus type err=%d\n",
511  		       err);
512  		return err;
513  	}
514  
515  	hp = mdesc_grab();
516  	if (!hp)
517  		return 0;
518  
519  	root = mdesc_node_by_name(hp, MDESC_NODE_NULL, channel_devices_node);
520  	if (root == MDESC_NODE_NULL) {
521  		printk(KERN_INFO "VIO: No channel-devices MDESC node.\n");
522  		mdesc_release(hp);
523  		return 0;
524  	}
525  
526  	cdev_node = of_find_node_by_name(NULL, "channel-devices");
527  	err = -ENODEV;
528  	if (!cdev_node) {
529  		printk(KERN_INFO "VIO: No channel-devices OBP node.\n");
530  		goto out_release;
531  	}
532  
533  	compat = mdesc_get_property(hp, root, "compatible", &len);
534  	if (!compat) {
535  		printk(KERN_ERR "VIO: Channel devices lacks compatible "
536  		       "property\n");
537  		goto out_release;
538  	}
539  	if (!of_find_in_proplist(compat, channel_devices_compat, len)) {
540  		printk(KERN_ERR "VIO: Channel devices node lacks (%s) "
541  		       "compat entry.\n", channel_devices_compat);
542  		goto out_release;
543  	}
544  
545  	cfg_handle = mdesc_get_property(hp, root, cfg_handle_prop, NULL);
546  	if (!cfg_handle) {
547  		printk(KERN_ERR "VIO: Channel devices lacks %s property\n",
548  		       cfg_handle_prop);
549  		goto out_release;
550  	}
551  
552  	cdev_cfg_handle = *cfg_handle;
553  
554  	root_vdev = vio_create_one(hp, root, NULL, NULL);
555  	err = -ENODEV;
556  	if (!root_vdev) {
557  		printk(KERN_ERR "VIO: Could not create root device.\n");
558  		goto out_release;
559  	}
560  
561  	mdesc_register_notifier(&vio_device_notifier);
562  	mdesc_register_notifier(&vio_ds_notifier);
563  
564  	mdesc_release(hp);
565  
566  	return err;
567  
568  out_release:
569  	mdesc_release(hp);
570  	return err;
571  }
572  
573  postcore_initcall(vio_init);
574