DRM KMS polling of connections providing errant EDID responses, or polling of "connectors" that have chips responding on DDC I2C bus address 0xA0/0xA1 with no actual physical connector nor EDID EEPROM, will create perpetual noise in dmesg and the system log every 10 seconds. Currently the user has apparently little recourse to silence these messages aside from replacing the offending cable, monitor, or graphics adapter. That recourse is impossible for an unused DVI-D "connector" of an internal graphics processor on a motherboard that provides no physical DVI-D connector. This change allows the root user to disable (and re-enable) DRM KMS connector polling on a per connector basis via sysfs, like so: # cat /sys/class/drm/card0/card0-DVI-D-1/polled [hotplug_detectable] connect disconnect # echo > /sys/class/drm/card0/card0-DVI-D-1/polled # cat /sys/class/drm/card0/card0-DVI-D-1/polled hotplug_detectable connect disconnect # echo " connect hotplug_detectable " > \ /sys/class/drm/card0/card0-DVI-D-1/polled # cat /sys/class/drm/card0/card0-DVI-D-1/polled [hotplug_detectable] [connect] disconnect # echo > /sys/class/drm/card0/card0-DVI-D-1/polled # cat /sys/class/drm/card0/card0-DVI-D-1/polled hotplug_detectable connect disconnect with the enabled poll types for the connector denoted in brackets: []. This allows the root user to silence DRM KMS log spam for locally known uncorrectable conditions. Signed-off-by Andy Walls <awalls@xxxxxxxxxxxxxxxx> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 86118a7..8e0807d 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -318,11 +318,80 @@ static ssize_t select_subconnector_show(struct device *device, drm_get_dvi_i_select_name((int)subconnector)); } +static const struct { + uint8_t mask; + const char *name; +} polled_bit_names[] = { + { DRM_CONNECTOR_POLL_HPD, "hotplug_detectable" }, + { DRM_CONNECTOR_POLL_CONNECT, "connect" }, + { DRM_CONNECTOR_POLL_DISCONNECT, "disconnect" }, +}; + +/* + * Return the decoded contents of connector->polled, using the names of the + * all the bit masks. Bits that are set, have their names enclosed in brackets. + */ +static ssize_t polled_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(dev); + char *tmp; + int i; + + tmp = buf; + for (i = 0; i < ARRAY_SIZE(polled_bit_names); i++) { + if (connector->polled & polled_bit_names[i].mask) + tmp += sprintf(tmp, "[%s] ", polled_bit_names[i].name); + else + tmp += sprintf(tmp, "%s ", polled_bit_names[i].name); + } + + if (tmp != buf) + *(tmp - 1) = '\n'; + return tmp - buf; +} + +/* + * Change the state of connector->polled, given input bit-mask name-strings + * that are separated by space or newline. + */ +static ssize_t polled_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct drm_connector *connector = to_drm_connector(dev); + const char *tmp; + int i; + uint8_t polled; + + /* Polling of this connector will cease, if no match is made below */ + polled = 0; + + /* Incrementally split and parse the input */ + while ((tmp = strsep((char **) &buf, " \n")) != NULL) { + + /* Don't waste effort on multiple adjacent separators */ + if (*tmp == '\0') + continue; + + /* Check for a match with a connector poll type name */ + for (i = 0; i < ARRAY_SIZE(polled_bit_names); i++) { + if (!strncasecmp(tmp, polled_bit_names[i].name, + strlen(polled_bit_names[i].name))) { + polled |= polled_bit_names[i].mask; + break; + } + } + } + connector->polled = polled; + return count; +} + static struct device_attribute connector_attrs[] = { __ATTR_RO(status), __ATTR_RO(enabled), __ATTR_RO(dpms), __ATTR_RO(modes), + __ATTR(polled, 0644, polled_show, polled_store), }; /* These attributes are for both DVI-I connectors and all types of tv-out. */ _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel