Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F132964706
D38545.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
D38545.diff
View Options
diff --git a/sys/compat/linsysfs/linsysfs.h b/sys/compat/linsysfs/linsysfs.h
new file mode 100644
--- /dev/null
+++ b/sys/compat/linsysfs/linsysfs.h
@@ -0,0 +1,51 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2006 IronPort Systems
+ * All rights reserved.
+ * Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _COMPAT_LINSYSFS_LINSYSFS_H_
+#define _COMPAT_LINSYSFS_LINSYSFS_H_
+
+typedef struct pfs_node *linsysfs_bus_cb_t(device_t, device_t,
+ struct pfs_node *, struct pfs_node *);
+
+void linsysfs_bus_drm(struct pfs_node *, struct pfs_node *, device_t);
+
+int linsysfs_fill_data(PFS_FILL_ARGS);
+char *linsysfs_full_pfs_path(const struct pfs_node *);
+
+struct pfs_node *linsysfs_create_dir(struct pfs_node *, const char *,
+ pfs_attr_t, pfs_vis_t, pfs_destroy_t);
+struct pfs_node *linsysfs_create_file(struct pfs_node *, const char *,
+ pfs_fill_t, pfs_attr_t, pfs_vis_t,
+ pfs_destroy_t, int, void *);
+struct pfs_node *linsysfs_create_link(struct pfs_node *, const char *,
+ pfs_fill_t, pfs_attr_t, pfs_vis_t,
+ pfs_destroy_t, int, void *);
+struct pfs_node *linsysfs_find_pcinode(device_t);
+
+#endif /* _COMPAT_LINSYSFS_LINSYSFS_H_ */
diff --git a/sys/compat/linsysfs/linsysfs.c b/sys/compat/linsysfs/linsysfs.c
--- a/sys/compat/linsysfs/linsysfs.c
+++ b/sys/compat/linsysfs/linsysfs.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2006 IronPort Systems
* All rights reserved.
+ * Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,8 +34,10 @@
#include <sys/systm.h>
#include <sys/ctype.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mount.h>
+#include <sys/mutex.h>
#include <sys/sbuf.h>
#include <sys/smp.h>
#include <sys/socket.h>
@@ -53,20 +56,102 @@
#include <compat/linux/linux_util.h>
#include <fs/pseudofs/pseudofs.h>
-struct scsi_host_queue {
- TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
- char *path;
- char *name;
+#include <compat/linsysfs/linsysfs.h>
+
+static MALLOC_DEFINE(M_LINSYSFS, "linsysfs", "linsysfs");
+
+struct pci_nodes_queue {
+ TAILQ_ENTRY(pci_nodes_queue) pci_nodes_next;
+ device_t dev;
+ struct pfs_node *node;;
};
+TAILQ_HEAD(,pci_nodes_queue) pci_nodes_q;
-TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
+/* Mutex for pci_nodes_queue. */
+static struct mtx pci_nodes_mtx;
+MTX_SYSINIT(pci_nodes_mtx, &pci_nodes_mtx, "linsysfs", MTX_DEF);
-static int host_number = 0;
+/*
+ * Create pci device node.
+ */
+static struct pfs_node *
+linsysfs_create_pcidev_node(struct pfs_node *dir, struct pci_devinfo *dinfo,
+ pfs_attr_t attr, pfs_vis_t vis, pfs_destroy_t destroy, int flags,
+ device_t dev)
+{
+ char device[PCI_MAXNAMELEN + 1];
+ struct pci_nodes_queue *nq;
+ struct pfs_node *node;
+
+ nq = malloc(sizeof(*nq), M_LINSYSFS, M_WAITOK);
+
+ sprintf(device, "0000:%02x:%02x.%x",
+ dinfo->cfg.bus,
+ dinfo->cfg.slot,
+ dinfo->cfg.func);
+ node = pfs_create_dir(dir, device, attr, vis, destroy, flags);
+ node->pn_data = dev;
+ nq->node = node;
+ nq->dev= dev;
+ mtx_lock(&pci_nodes_mtx);
+ TAILQ_INSERT_TAIL(&pci_nodes_q, nq, pci_nodes_next);
+ mtx_unlock(&pci_nodes_mtx);
+ return (node);
+}
-static int
-atoi(const char *str)
+/*
+ * Locate a node by dev.
+ */
+struct pfs_node *
+linsysfs_find_pcinode(device_t dev)
{
- return (int)strtol(str, (char **)NULL, 10);
+ struct pci_nodes_queue *nq, *nq_tmp;
+
+ mtx_lock(&pci_nodes_mtx);
+ TAILQ_FOREACH_SAFE(nq, &pci_nodes_q, pci_nodes_next, nq_tmp) {
+ if (nq->dev == dev) {
+ mtx_unlock(&pci_nodes_mtx);
+ return (nq->node);
+ }
+ }
+ mtx_unlock(&pci_nodes_mtx);
+ return (NULL);
+}
+
+struct pfs_node *
+linsysfs_create_dir(struct pfs_node *parent, const char *name,
+ pfs_attr_t attr, pfs_vis_t vis, pfs_destroy_t destroy)
+{
+ struct pfs_node *node;
+
+ if (parent == NULL)
+ return (NULL);
+ node = pfs_create_dir(parent, name, attr, vis, destroy, 0);
+ return (node);
+}
+
+struct pfs_node *
+linsysfs_create_file(struct pfs_node *parent, const char *name,
+ pfs_fill_t fill, pfs_attr_t attr, pfs_vis_t vis, pfs_destroy_t destroy,
+ int flags, void *data)
+{
+ struct pfs_node *node;
+
+ node = pfs_create_file(parent, name, fill, attr, vis, destroy, flags);
+ node->pn_data = data;
+ return (node);
+}
+
+struct pfs_node *
+linsysfs_create_link(struct pfs_node *parent, const char *name,
+ pfs_fill_t fill, pfs_attr_t attr, pfs_vis_t vis, pfs_destroy_t destroy,
+ int flags, void *data)
+{
+ struct pfs_node *node;
+
+ node = pfs_create_link(parent, name, fill, attr, vis, destroy, flags);
+ node->pn_data = data;
+ return (node);
}
static int
@@ -215,22 +300,14 @@
static int
linsysfs_scsiname(PFS_FILL_ARGS)
{
- struct scsi_host_queue *scsi_host;
- int index;
+ device_t dev = pn->pn_data;
+ char *name;
- if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
- index = atoi(&pn->pn_parent->pn_name[4]);
- } else {
- sbuf_printf(sb, "unknown\n");
- return (0);
- }
- TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
- if (index-- == 0) {
- sbuf_printf(sb, "%s\n", scsi_host->name);
- return (0);
- }
- }
- sbuf_printf(sb, "unknown\n");
+ name = linux_driver_get_name_dev(dev);
+ if (name != NULL)
+ sbuf_printf(sb, "%s", name);
+ else
+ sbuf_printf(sb, "%s", device_get_nameunit(dev));
return (0);
}
@@ -240,26 +317,16 @@
static int
linsysfs_link_scsi_host(PFS_FILL_ARGS)
{
- struct scsi_host_queue *scsi_host;
- int index;
+ struct pfs_node *node = pn->pn_data;
+ char *path;
- if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
- index = atoi(&pn->pn_parent->pn_name[4]);
- } else {
- sbuf_printf(sb, "unknown\n");
- return (0);
- }
- TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
- if (index-- == 0) {
- sbuf_printf(sb, "../../../devices%s", scsi_host->path);
- return(0);
- }
- }
- sbuf_printf(sb, "unknown\n");
+ path = linsysfs_full_pfs_path(node);
+ sbuf_printf(sb, "../../../%s", path);
+ free(path, M_TEMP);
return (0);
}
-static int
+int
linsysfs_fill_data(PFS_FILL_ARGS)
{
sbuf_printf(sb, "%s", (char *)pn->pn_data);
@@ -346,25 +413,8 @@
return (0);
}
-/*
- * Filler function for drm uevent file
- */
-static int
-linsysfs_fill_uevent_drm(PFS_FILL_ARGS)
-{
- device_t dev;
- int unit;
-
- dev = (device_t)pn->pn_data;
- unit = device_get_unit(dev);
- sbuf_printf(sb,
- "MAJOR=226\nMINOR=%d\nDEVNAME=dri/card%d\nDEVTYPE=dri_minor\n",
- unit, unit);
- return (0);
-}
-
-static char *
-get_full_pfs_path(struct pfs_node *cur)
+char *
+linsysfs_full_pfs_path(const struct pfs_node *cur)
{
char *temp, *path;
@@ -383,183 +433,6 @@
return (path);
}
-/*
- * Filler function for symlink from drm char device to PCI device
- */
-static int
-linsysfs_fill_vgapci(PFS_FILL_ARGS)
-{
- char *path;
-
- path = get_full_pfs_path((struct pfs_node*)pn->pn_data);
- sbuf_printf(sb, "../../../%s", path);
- free(path, M_TEMP);
- return (0);
-}
-
-#undef PCI_DEV
-#define PCI_DEV "pci"
-#define DRMN_DEV "drmn"
-static int
-linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
- struct pfs_node *chardev, struct pfs_node *drm, char *path, char *prefix)
-{
- struct scsi_host_queue *scsi_host;
- struct pfs_node *sub_dir, *cur_file;
- int i, nchildren, error;
- device_t *children, parent;
- devclass_t devclass;
- const char *name = NULL;
- struct pci_devinfo *dinfo;
- char *device, *host, *new_path, *devname;
-
- new_path = path;
- devname = malloc(16, M_TEMP, M_WAITOK);
-
- parent = device_get_parent(dev);
- if (parent) {
- devclass = device_get_devclass(parent);
- if (devclass != NULL)
- name = devclass_get_name(devclass);
- if (name && strcmp(name, PCI_DEV) == 0) {
- dinfo = device_get_ivars(dev);
- if (dinfo) {
- device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
- new_path = malloc(MAXPATHLEN, M_TEMP,
- M_WAITOK);
- new_path[0] = '\000';
- strcpy(new_path, path);
- host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
- device[0] = '\000';
- sprintf(device, "%s:%02x:%02x.%x",
- prefix,
- dinfo->cfg.bus,
- dinfo->cfg.slot,
- dinfo->cfg.func);
- strcat(new_path, "/");
- strcat(new_path, device);
- dir = pfs_create_dir(dir, device,
- NULL, NULL, NULL, 0);
- cur_file = pfs_create_file(dir, "vendor",
- &linsysfs_fill_vendor, NULL, NULL, NULL,
- PFS_RD);
- cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "device",
- &linsysfs_fill_device, NULL, NULL, NULL,
- PFS_RD);
- cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir,
- "subsystem_vendor",
- &linsysfs_fill_subvendor, NULL, NULL, NULL,
- PFS_RD);
- cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir,
- "subsystem_device",
- &linsysfs_fill_subdevice, NULL, NULL, NULL,
- PFS_RD);
- cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "revision",
- &linsysfs_fill_revid, NULL, NULL, NULL,
- PFS_RD);
- cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "config",
- &linsysfs_fill_config, NULL, NULL, NULL,
- PFS_RD);
- cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "uevent",
- &linsysfs_fill_uevent_pci, NULL, NULL,
- NULL, PFS_RD);
- cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_link(dir, "subsystem",
- &linsysfs_fill_data, NULL, NULL, NULL, 0);
- /* libdrm just checks that the link ends in "/pci" */
- cur_file->pn_data = "/sys/bus/pci";
-
- if (dinfo->cfg.baseclass == PCIC_STORAGE) {
- /* DJA only make this if needed */
- sprintf(host, "host%d", host_number++);
- strcat(new_path, "/");
- strcat(new_path, host);
- pfs_create_dir(dir, host,
- NULL, NULL, NULL, 0);
- scsi_host = malloc(sizeof(
- struct scsi_host_queue),
- M_DEVBUF, M_NOWAIT);
- scsi_host->path = malloc(
- strlen(new_path) + 1,
- M_DEVBUF, M_NOWAIT);
- scsi_host->path[0] = '\000';
- bcopy(new_path, scsi_host->path,
- strlen(new_path) + 1);
- scsi_host->name = "unknown";
-
- sub_dir = pfs_create_dir(scsi, host,
- NULL, NULL, NULL, 0);
- pfs_create_link(sub_dir, "device",
- &linsysfs_link_scsi_host,
- NULL, NULL, NULL, 0);
- pfs_create_file(sub_dir, "proc_name",
- &linsysfs_scsiname,
- NULL, NULL, NULL, PFS_RD);
- scsi_host->name
- = linux_driver_get_name_dev(dev);
- TAILQ_INSERT_TAIL(&scsi_host_q,
- scsi_host, scsi_host_next);
- }
- free(device, M_TEMP);
- free(host, M_TEMP);
- }
- }
-
- devclass = device_get_devclass(dev);
- if (devclass != NULL)
- name = devclass_get_name(devclass);
- else
- name = NULL;
- if (name != NULL && strcmp(name, DRMN_DEV) == 0 &&
- device_get_unit(dev) >= 0) {
- dinfo = device_get_ivars(parent);
- if (dinfo != NULL && dinfo->cfg.baseclass == PCIC_DISPLAY) {
- pfs_create_dir(dir, "drm", NULL, NULL, NULL, 0);
- sprintf(devname, "226:%d",
- device_get_unit(dev));
- sub_dir = pfs_create_dir(chardev,
- devname, NULL, NULL, NULL, 0);
- cur_file = pfs_create_link(sub_dir,
- "device", &linsysfs_fill_vgapci, NULL,
- NULL, NULL, PFS_RD);
- cur_file->pn_data = (void*)dir;
- cur_file = pfs_create_file(sub_dir,
- "uevent", &linsysfs_fill_uevent_drm, NULL,
- NULL, NULL, PFS_RD);
- cur_file->pn_data = (void*)dev;
- sprintf(devname, "card%d",
- device_get_unit(dev));
- sub_dir = pfs_create_dir(drm,
- devname, NULL, NULL, NULL, 0);
- cur_file = pfs_create_link(sub_dir,
- "device", &linsysfs_fill_vgapci, NULL,
- NULL, NULL, PFS_RD);
- cur_file->pn_data = (void*)dir;
- }
- }
- }
-
- error = device_get_children(dev, &children, &nchildren);
- if (error == 0) {
- for (i = 0; i < nchildren; i++)
- if (children[i])
- linsysfs_run_bus(children[i], dir, scsi,
- chardev, drm, new_path, prefix);
- free(children, M_TEMP);
- }
- if (new_path != path)
- free(new_path, M_TEMP);
- free(devname, M_TEMP);
-
- return (1);
-}
-
/*
* Filler function for sys/devices/system/cpu/{online,possible,present}
*/
@@ -609,6 +482,143 @@
free(name, M_TEMP);
}
+#undef PCI_DEV
+#define PCI_DEV "pci"
+#define DRMN_DEV "drmn"
+/*
+ * Filler callback for sys/devices/pci0000:00.
+ */
+static struct pfs_node *
+linsysfs_pcibus_cb(device_t parent, device_t dev, struct pfs_node *pci,
+ struct pfs_node *dir)
+{
+ struct pci_devinfo *dinfo;
+ const char *classname;
+ devclass_t dc;
+
+ dinfo = NULL;
+ classname = NULL;
+ dc = device_get_devclass(parent);
+ if (dc != NULL)
+ classname = devclass_get_name(dc);
+ if (strcmp(classname, PCI_DEV) == 0)
+ dinfo = device_get_ivars(dev);
+
+ /* PCI tree. */
+ if (dinfo != NULL) {
+ pci = linsysfs_create_pcidev_node(pci, dinfo,
+ NULL, NULL, NULL, 0, dev);
+ linsysfs_create_file(pci, "vendor",
+ &linsysfs_fill_vendor, NULL, NULL, NULL, PFS_RD, dev);
+ linsysfs_create_file(pci, "device",
+ &linsysfs_fill_device, NULL, NULL, NULL, PFS_RD, dev);
+ linsysfs_create_file(pci, "subsystem_vendor",
+ &linsysfs_fill_subvendor, NULL, NULL, NULL, PFS_RD, dev);
+ linsysfs_create_file(pci, "subsystem_device",
+ &linsysfs_fill_subdevice, NULL, NULL, NULL, PFS_RD, dev);
+ linsysfs_create_file(pci, "revision",
+ &linsysfs_fill_revid, NULL, NULL, NULL, PFS_RD, dev);
+ linsysfs_create_file(pci, "config",
+ &linsysfs_fill_config, NULL, NULL, NULL, PFS_RD, dev);
+ linsysfs_create_file(pci, "uevent",
+ &linsysfs_fill_uevent_pci, NULL, NULL, NULL, PFS_RD, dev);
+ linsysfs_create_link(pci, "subsystem",
+ &linsysfs_fill_data, NULL, NULL, NULL, 0, "/sys/bus/pci");
+ /* TODO: libdrm just checks that the link ends in "/pci" */
+ }
+ /* vgapci/drmn childrens. */
+ if (strcmp(classname, DRMN_DEV) == 0)
+ linsysfs_bus_drm(pci, dir, dev);
+ return (pci);
+}
+
+/*
+ * Filler callback for scsi in sys/devices/pci0000:00.
+ */
+static struct pfs_node *
+linsysfs_scsi_cb(device_t parent, device_t dev, struct pfs_node *pci,
+ struct pfs_node *scsi)
+{
+ char host[PCI_MAXNAMELEN + 1];
+ struct pci_devinfo *dinfo;
+ const char *classname;
+ struct pfs_node *pdir, *sdir;
+ devclass_t dc;
+
+ dinfo = NULL;
+ classname = NULL;
+ dc = device_get_devclass(parent);
+ if (dc != NULL)
+ classname = devclass_get_name(dc);
+ if (strcmp(classname, PCI_DEV) == 0)
+ dinfo = device_get_ivars(dev);
+
+ if (dinfo != NULL &&
+ dinfo->cfg.baseclass == PCIC_STORAGE) {
+ /* DJA only make this if needed */
+ pdir = linsysfs_find_pcinode(dev);
+ KASSERT(pdir != NULL, ("Inconsistent dev %p node", dev));
+ if (pdir == NULL)
+ return (pci);
+ host[0] = '\000';
+ snprintf(host, sizeof(host), "host%d",
+ device_get_unit(dev));
+ sdir = linsysfs_create_dir(scsi, host, NULL, NULL, NULL);
+ pdir = linsysfs_create_dir(pdir, host, NULL, NULL, NULL);
+ linsysfs_create_link(sdir, "device",
+ &linsysfs_link_scsi_host, NULL, NULL, NULL, PFS_RD, pdir);
+ linsysfs_create_file(sdir, "proc_name",
+ &linsysfs_scsiname, NULL, NULL, NULL, PFS_RD, dev);
+ }
+ return (pci);
+}
+
+/*
+ * Traverse the device tree.
+ */
+static int
+linsysfs_bus_foreach(device_t dev, linsysfs_bus_cb_t cb,
+ struct pfs_node *pci, struct pfs_node *dir)
+{
+ device_t *ch, parent;
+ int n, count, error;
+
+ parent = device_get_parent(dev);
+ if (parent != NULL)
+ pci = (*cb)(parent, dev, pci, dir);
+ error = device_get_children(dev, &ch, &count);
+ if (error != 0)
+ return (error);
+ for (n = 0; n < count; n++) {
+ error = linsysfs_bus_foreach(ch[n], cb, pci, dir);
+ if (error != 0)
+ break;
+ }
+ free(ch, M_TEMP);
+ return (error);
+}
+
+/*
+ * Scan device tree starting from root.
+ */
+static int
+linsysfs_bus_scan(const char *root, linsysfs_bus_cb_t cb,
+ struct pfs_node *pci, struct pfs_node *dir)
+{
+ devclass_t dc;
+ device_t dev;
+ int error;
+
+ bus_topo_lock();
+ dc = devclass_find(root);
+ KASSERT(dc != NULL, ("Invalid %s class", root));
+ dev = devclass_get_device(dc, 0);
+ KASSERT(dev != NULL, ("Scan of %s failed", root));
+ error = linsysfs_bus_foreach(dev, cb, pci, dir);
+ bus_topo_unlock();
+ return (error);
+}
+
/*
* Constructor
*/
@@ -618,17 +628,14 @@
struct pfs_node *root;
struct pfs_node *class;
struct pfs_node *dir, *sys, *cpu;
- struct pfs_node *drm;
struct pfs_node *pci;
struct pfs_node *scsi;
struct pfs_node *net;
struct pfs_node *devdir, *chardev;
struct pfs_node *kernel;
- devclass_t devclass;
- device_t dev;
-
- TAILQ_INIT(&scsi_host_q);
+ int error;
+ TAILQ_INIT(&pci_nodes_q);
root = pi->pi_root;
/* /sys/bus/... */
@@ -637,7 +644,7 @@
/* /sys/class/... */
class = pfs_create_dir(root, "class", NULL, NULL, NULL, 0);
scsi = pfs_create_dir(class, "scsi_host", NULL, NULL, NULL, 0);
- drm = pfs_create_dir(class, "drm", NULL, NULL, NULL, 0);
+ pfs_create_dir(class, "drm", NULL, NULL, NULL, 0);
pfs_create_dir(class, "power_supply", NULL, NULL, NULL, 0);
/* /sys/class/net/.. */
@@ -651,14 +658,6 @@
dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0);
pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0);
- devclass = devclass_find("root");
- if (devclass == NULL) {
- return (0);
- }
-
- dev = devclass_get_device(devclass, 0);
- linsysfs_run_bus(dev, pci, scsi, chardev, drm, "/pci0000:00", "0000");
-
/* /sys/devices/system */
sys = pfs_create_dir(dir, "system", NULL, NULL, NULL, 0);
@@ -683,7 +682,12 @@
/* /sys/subsystem/... */
dir = pfs_create_dir(root, "subsystem", NULL, NULL, NULL, 0);
- return (0);
+ /* /sys/devices/pci0000:00 */
+ error = linsysfs_bus_scan("root", linsysfs_pcibus_cb, pci, chardev);
+ if (error == 0)
+ error = linsysfs_bus_scan("root", linsysfs_scsi_cb, pci, scsi);
+
+ return (error);
}
/*
@@ -692,14 +696,14 @@
static int
linsysfs_uninit(PFS_INIT_ARGS)
{
- struct scsi_host_queue *scsi_host, *scsi_host_tmp;
+ struct pci_nodes_queue *nq, *nq_tmp;
- TAILQ_FOREACH_SAFE(scsi_host, &scsi_host_q, scsi_host_next,
- scsi_host_tmp) {
- TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
- free(scsi_host->path, M_TEMP);
- free(scsi_host, M_TEMP);
+ mtx_lock(&pci_nodes_mtx);
+ TAILQ_FOREACH_SAFE(nq, &pci_nodes_q, pci_nodes_next, nq_tmp) {
+ TAILQ_REMOVE(&pci_nodes_q, nq, pci_nodes_next);
+ free(nq, M_LINSYSFS);
}
+ mtx_unlock(&pci_nodes_mtx);
return (0);
}
diff --git a/sys/compat/linsysfs/linsysfs_drm.c b/sys/compat/linsysfs/linsysfs_drm.c
new file mode 100644
--- /dev/null
+++ b/sys/compat/linsysfs/linsysfs_drm.c
@@ -0,0 +1,146 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sbuf.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <fs/pseudofs/pseudofs.h>
+
+#include <compat/linsysfs/linsysfs.h>
+#include <linux/device.h>
+
+/*
+ * Filler function for drm uevent file.
+ */
+static int
+linsysfs_drm_fill_uevent(PFS_FILL_ARGS)
+{
+ device_t bsddev = pn->pn_data;
+ struct device *dev;
+
+ /*
+ * XXX. bsddev can die, drm-kmod will delete it on unregister path.
+ */
+ dev = device_get_softc(bsddev);
+ if (dev == NULL)
+ return (-1);
+ return (sbuf_printf(sb,
+ "MAJOR=%d\nMINOR=%d\nDEVNAME=dri/%s\nDEVTYPE=drm_minor\n",
+ MAJOR(dev->devt), MINOR(dev->devt), dev_name(dev)));
+}
+
+/*
+ * Filler function for drm dev file.
+ */
+static int
+linsysfs_drm_fill_dev(PFS_FILL_ARGS)
+{
+ device_t bsddev = pn->pn_data;
+ struct device *dev;
+
+ /*
+ * XXX. bsddev can die, drm-kmod will delete it on unregister path.
+ */
+ dev = device_get_softc(bsddev);
+ if (dev == NULL)
+ return (-1);
+ return (sbuf_printf(sb, "%d:%d", MAJOR(dev->devt), MINOR(dev->devt)));
+}
+
+/*
+ * Filler function for symlink from drm/device to PCI device.
+ */
+static int
+linsysfs_drm_fill_vgapci(PFS_FILL_ARGS)
+{
+ struct pfs_node *node = pn->pn_data;
+ char *path;
+
+ path = linsysfs_full_pfs_path(node);
+ sbuf_printf(sb, "../../../../../%s", path);
+ free(path, M_TEMP);
+ return (0);
+}
+
+/*
+ * Filler function for symlink from dev/char to drm device.
+ */
+static int
+linsysfs_drm_fill_charlink(PFS_FILL_ARGS)
+{
+ struct pfs_node *node = pn->pn_data;
+ char *path;
+
+ path = linsysfs_full_pfs_path(node);
+ sbuf_printf(sb, "../../%s", path);
+ free(path, M_TEMP);
+ return (0);
+}
+
+/*
+ * Filler function for drm childrens.
+ */
+#define DRM_DEV "drm"
+void
+linsysfs_bus_drm(struct pfs_node *devdir, struct pfs_node *chardir,
+ device_t bsddev)
+{
+ const char *classname;
+ struct pfs_node *dir;
+ struct device *dev;
+ char charlink[16]; /* Major:Minor */
+
+ classname = devclass_get_name(device_get_devclass(bsddev));
+
+ if (strcmp(classname, DRM_DEV) == 0 &&
+ (dev = device_get_softc(bsddev)) != NULL) {
+ dir = pfs_find_node(devdir, DRM_DEV);
+ if (dir == NULL)
+ dir = linsysfs_create_dir(devdir, DRM_DEV,
+ NULL, NULL, NULL);
+ dir = linsysfs_create_dir(dir, dev_name(dev), NULL, NULL, NULL);
+ linsysfs_create_file(dir, "uevent",
+ &linsysfs_drm_fill_uevent, NULL, NULL, NULL, PFS_RD, bsddev);
+ linsysfs_create_link(dir, "device",
+ &linsysfs_drm_fill_vgapci, NULL, NULL, NULL, PFS_RD, devdir);
+ linsysfs_create_link(dir, "subsystem",
+ &linsysfs_fill_data, NULL, NULL, NULL, PFS_RD,
+ "/sys/class/drm");
+ snprintf(charlink, sizeof(charlink), "%d:%d",
+ MAJOR(dev->devt), MINOR(dev->devt));
+ linsysfs_create_link(chardir, charlink,
+ &linsysfs_drm_fill_charlink, NULL, NULL, NULL, PFS_RD, dir);
+ linsysfs_create_file(dir, "dev",
+ &linsysfs_drm_fill_dev, NULL, NULL, NULL, PFS_RD, bsddev);
+ linsysfs_create_dir(dir, "power", NULL, NULL, NULL);
+ }
+}
diff --git a/sys/modules/linsysfs/Makefile b/sys/modules/linsysfs/Makefile
--- a/sys/modules/linsysfs/Makefile
+++ b/sys/modules/linsysfs/Makefile
@@ -5,7 +5,9 @@
KMOD= linsysfs
SRCS= vnode_if.h \
device_if.h bus_if.h pci_if.h \
- linsysfs.c
+ linsysfs.c linsysfs_drm.c
+
+CFLAGS+= ${LINUXKPI_INCLUDES}
.if !defined(KERNBUILDDIR)
.warning Building Linuxulator outside of a kernel does not make sense
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Oct 22, 3:06 PM (5 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24058856
Default Alt Text
D38545.diff (24 KB)
Attached To
Mode
D38545: linsysfs: Reimplement bus scan code.
Attached
Detach File
Event Timeline
Log In to Comment