summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <gordon.w.ross@gmail.com>2016-10-29 11:48:56 -0400
committerGordon Ross <gordon.w.ross@gmail.com>2016-11-22 22:55:15 -0500
commitba92f03d1b2495fc0d7bd801c949bab716eaf7f5 (patch)
treee87e9d9b63ae6532d9b3be17dbf9101649b215bd
parent02167e5266a5aecd4fcf8ab713e88c8a91efd314 (diff)
downloadillumos-gfx-drm-ba92f03d1b2495fc0d7bd801c949bab716eaf7f5.tar.gz
Fix device names and links
need to mask off the "type" part; minor is just the low 6 bits. The links use the same minor numbers.
-rw-r--r--usr/src/cmd/devfsadm/drm_link_i386.c92
-rw-r--r--usr/src/uts/common/io/drm/drm_stub.c12
2 files changed, 75 insertions, 29 deletions
diff --git a/usr/src/cmd/devfsadm/drm_link_i386.c b/usr/src/cmd/devfsadm/drm_link_i386.c
index ab29ab7..5a3e6fe 100644
--- a/usr/src/cmd/devfsadm/drm_link_i386.c
+++ b/usr/src/cmd/devfsadm/drm_link_i386.c
@@ -22,6 +22,7 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Joyent, Inc. All rights reserved.
+ * Copyright 2016 Gordon W. Ross
*/
#include <regex.h>
@@ -33,8 +34,9 @@
#include <ctype.h>
/*
- * Note: separate from misc_link_i386.c because this will later
- * move to the gfx-drm gate.
+ * Handles device links for agp and drm drivers.
+ * Note that misc_link.c (in ON gate) handles minor "gfx"
+ * which gets linked as /dev/fbs/gfx0 -> ...:gfx0
*/
static int agp_process(di_minor_t minor, di_node_t node);
@@ -98,8 +100,9 @@ static devfsadm_enumerate_t cpugart_rules[1] =
{ "^agp$/^cpugart([0-9]+)$", 1, MATCH_ALL };
static devfsadm_enumerate_t agpmaster_rules[1] =
{ "^agp$/^agpmaster([0-9]+)$", 1, MATCH_ALL };
+
static devfsadm_enumerate_t drm_rules[1] =
- { "^dri$/^card([0-9]+)$", 1, MATCH_ALL };
+ { "^dri$/^([a-z]+D?)([0-9]+)$", 2, MATCH_MINOR };
/*
@@ -118,7 +121,7 @@ static devfsadm_remove_t drm_remove_cbt[] = {
{ "agp", "^agp/cpugart[0-9]+$", RM_POST,
ILEVEL_0, devfsadm_rm_all
},
- { "drm", "^dri/card[0-9]+$", RM_POST,
+ { "drm", "^dri/[a-z]D?[0-9]+$", RM_POST,
ILEVEL_0, devfsadm_rm_all
},
};
@@ -253,9 +256,16 @@ static int
drm_node(di_minor_t minor, di_node_t node)
{
char *minor_nm, *drv_nm;
- char *devfspath;
- char *I_path, *p_path, *buf;
- char *name = "card";
+ char *devfspath = NULL;
+ char *I_path = NULL;
+ char *p_path = NULL;
+ char *buf = NULL;
+ char *name = NULL;
+ char *unit;
+ int len;
+
+ devfsadm_print(debug_mid, "drm_node: node=%s type=%s\n",
+ di_node_name(node), di_minor_nodetype(minor));
minor_nm = di_minor_name(minor);
drv_nm = di_driver_name(node);
@@ -263,8 +273,8 @@ drm_node(di_minor_t minor, di_node_t node)
return (DEVFSADM_CONTINUE);
}
- devfsadm_print(debug_mid, "drm_node: minor=%s node=%s type=%s\n",
- minor_nm, di_node_name(node), di_minor_nodetype(minor));
+ devfsadm_print(debug_mid, "drm_node: dev_nm=%s minor_nm=%s\n",
+ drv_nm, minor_nm);
devfspath = di_devfs_path(node);
if (devfspath == NULL) {
@@ -272,47 +282,81 @@ drm_node(di_minor_t minor, di_node_t node)
return (DEVFSADM_CONTINUE);
}
- I_path = (char *)malloc(PATH_MAX);
+ /*
+ * Want the minor name without trailing digits.
+ * Also find the unit suffix in minor_nm.
+ */
+ name = strdup(minor_nm);
+ if (name == NULL) {
+ devfsadm_print(debug_mid, "drm_node: malloc failed\n");
+ goto out;
+ }
+ len = strlen(name);
+ while (len > 2 && isdigit(name[len-1]))
+ len--;
+ name[len] = '\0';
+ unit = &minor_nm[len];
+ devfsadm_print(debug_mid, "drm_node: trimmed minor %s, unit: %s\n",
+ name, unit);
+ I_path = (char *)malloc(PATH_MAX);
if (I_path == NULL) {
- di_devfs_path_free(devfspath);
devfsadm_print(debug_mid, "drm_node: malloc failed\n");
- return (DEVFSADM_CONTINUE);
+ goto out;
}
p_path = (char *)malloc(PATH_MAX);
-
if (p_path == NULL) {
devfsadm_print(debug_mid, "drm_node: malloc failed\n");
- di_devfs_path_free(devfspath);
- free(I_path);
- return (DEVFSADM_CONTINUE);
+ goto out;
}
(void) strlcpy(p_path, devfspath, PATH_MAX);
(void) strlcat(p_path, ":", PATH_MAX);
(void) strlcat(p_path, minor_nm, PATH_MAX);
- di_devfs_path_free(devfspath);
devfsadm_print(debug_mid, "drm_node: p_path %s\n", p_path);
if (devfsadm_enumerate_int(p_path, 0, &buf, drm_rules, 1)) {
- free(p_path);
devfsadm_print(debug_mid, "drm_node: exit/coninue\n");
- return (DEVFSADM_CONTINUE);
+ goto out;
}
- (void) snprintf(I_path, PATH_MAX, "dri/%s%s", name, buf);
- devfsadm_print(debug_mid, "drm_node: p_path=%s buf=%s\n",
- p_path, buf);
+ /*
+ * See xf86drm.c drmOpenDevice() and xf86drm.h DRM_DEV_NAME etc.
+ * Basically, we need the links to look like this:
+ * /dev/dri/card0 -> /devices/pci@0,0/display@2:drm0
+ * /dev/dri/controlD0 -> /devices/pci@0,0/display@2:controlD0
+ * /dev/dri/renderD0 -> /devices/pci@0,0/display@2:renderD0
+ * Most just use the full minor name as the link name,
+ * but "card0" points to ...:drm0 so special case that.
+ */
+ if (strcmp(name, "drm") == 0) {
+ strcpy(name, "card");
+ }
- free(buf);
+ /*
+ * The counter value in buf seems to be wrong. It gives us
+ * zero as expected in this case:
+ * dri/card0 -> .../display@2:drm0
+ * but it gives us "1" in this case:
+ * dri/controlD1 -> .../display@2:controlD0
+ * Work aound: ignore the counter value enum put in "buf"
+ * and just use the unit number from the minor name.
+ */
+ (void) snprintf(I_path, PATH_MAX, "dri/%s%s", name, unit);
devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
(void) devfsadm_mklink(I_path, node, minor, 0);
+out:
+ free(buf);
+
free(p_path);
free(I_path);
+ free(name);
+ if (devfspath != NULL)
+ di_devfs_path_free(devfspath);
- return (0);
+ return (DEVFSADM_CONTINUE);
}
diff --git a/usr/src/uts/common/io/drm/drm_stub.c b/usr/src/uts/common/io/drm/drm_stub.c
index 5663336..d5228dd 100644
--- a/usr/src/uts/common/io/drm/drm_stub.c
+++ b/usr/src/uts/common/io/drm/drm_stub.c
@@ -310,6 +310,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
struct drm_minor *new_minor;
int ret;
int minor_id;
+ int minor_unit;
DRM_DEBUG("\n");
@@ -330,16 +331,17 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
(void) idr_replace(&drm_minors_idr, new_minor, minor_id);
+ minor_unit = minor_id & DRM_MINOR_ID_LIMIT_LEGACY; /* 63 */
if (type == DRM_MINOR_LEGACY)
- (void) sprintf(new_minor->name, "drm%d", new_minor->index);
+ (void) sprintf(new_minor->name, "drm%d", minor_unit);
else if (type == DRM_MINOR_CONTROL)
- (void) sprintf(new_minor->name, "controlD%d", new_minor->index);
+ (void) sprintf(new_minor->name, "controlD%d", minor_unit);
else if (type == DRM_MINOR_RENDER)
- (void) sprintf(new_minor->name, "renderD%d", new_minor->index);
+ (void) sprintf(new_minor->name, "renderD%d", minor_unit);
else if (type == DRM_MINOR_VGATEXT)
- (void) sprintf(new_minor->name, "gfx%d", new_minor->index - DRM_MINOR_ID_BASE_VGATEXT);
+ (void) sprintf(new_minor->name, "gfx%d", minor_unit);
else if (type == DRM_MINOR_AGPMASTER)
- (void) sprintf(new_minor->name, "agpmaster%d", new_minor->index - DRM_MINOR_ID_BASE_AGPMASTER);
+ (void) sprintf(new_minor->name, "agpmaster%d", minor_unit);
idr_init(&new_minor->clone_idr);