static int intel_th_remove(struct device *dev) { struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver); struct intel_th_device *thdev = to_intel_th_device(dev); struct intel_th_device *hub = to_intel_th_device(dev->parent); int err; if (thdev->type == INTEL_TH_SWITCH) { err = device_for_each_child(dev, thdev, intel_th_child_remove); if (err) return err; } if (thdrv->attr_group) sysfs_remove_group(&thdev->dev.kobj, thdrv->attr_group); pm_runtime_get_sync(dev); thdrv->remove(thdev); if (intel_th_output_assigned(thdev)) { struct intel_th_driver *hubdrv = to_intel_th_driver(dev->parent->driver); if (hub->dev.driver) /* does not talk to hardware */ hubdrv->unassign(hub, thdev); } pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); return 0; }
static int intel_th_remove(struct device *dev) { struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver); struct intel_th_device *thdev = to_intel_th_device(dev); struct intel_th_device *hub = to_intel_th_device(dev->parent); int err; if (thdev->type == INTEL_TH_SWITCH) { err = device_for_each_child(dev, thdev, intel_th_child_remove); if (err) return err; } thdrv->remove(thdev); if (intel_th_output_assigned(thdev)) { struct intel_th_driver *hubdrv = to_intel_th_driver(dev->parent->driver); if (hub->dev.driver) hubdrv->unassign(hub, thdev); } return 0; }
static int intel_th_probe(struct device *dev) { struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver); struct intel_th_device *thdev = to_intel_th_device(dev); struct intel_th_driver *hubdrv; struct intel_th_device *hub = NULL; int ret; if (thdev->type == INTEL_TH_SWITCH) hub = thdev; else if (dev->parent) hub = to_intel_th_device(dev->parent); if (!hub || !hub->dev.driver) return -EPROBE_DEFER; hubdrv = to_intel_th_driver(hub->dev.driver); ret = thdrv->probe(to_intel_th_device(dev)); if (ret) return ret; if (thdev->type == INTEL_TH_OUTPUT && !intel_th_output_assigned(thdev)) ret = hubdrv->assign(hub, thdev); return ret; }
static ssize_t active_show(struct device *dev, struct device_attribute *attr, char *buf) { struct intel_th_device *thdev = to_intel_th_device(dev); return scnprintf(buf, PAGE_SIZE, "%d\n", thdev->output.active); }
static int intel_th_probe(struct device *dev) { struct intel_th_driver *thdrv = to_intel_th_driver(dev->driver); struct intel_th_device *thdev = to_intel_th_device(dev); struct intel_th_driver *hubdrv; struct intel_th_device *hub = NULL; int ret; if (thdev->type == INTEL_TH_SWITCH) hub = thdev; else if (dev->parent) hub = to_intel_th_device(dev->parent); if (!hub || !hub->dev.driver) return -EPROBE_DEFER; hubdrv = to_intel_th_driver(hub->dev.driver); pm_runtime_set_active(dev); pm_runtime_no_callbacks(dev); pm_runtime_enable(dev); ret = thdrv->probe(to_intel_th_device(dev)); if (ret) goto out_pm; if (thdrv->attr_group) { ret = sysfs_create_group(&thdev->dev.kobj, thdrv->attr_group); if (ret) goto out; } if (thdev->type == INTEL_TH_OUTPUT && !intel_th_output_assigned(thdev)) /* does not talk to hardware */ ret = hubdrv->assign(hub, thdev); out: if (ret) thdrv->remove(thdev); out_pm: if (ret) pm_runtime_disable(dev); return ret; }
static ssize_t port_show(struct device *dev, struct device_attribute *attr, char *buf) { struct intel_th_device *thdev = to_intel_th_device(dev); if (thdev->output.port >= 0) return scnprintf(buf, PAGE_SIZE, "%u\n", thdev->output.port); return scnprintf(buf, PAGE_SIZE, "unassigned\n"); }
static int intel_th_match(struct device *dev, struct device_driver *driver) { struct intel_th_driver *thdrv = to_intel_th_driver(driver); struct intel_th_device *thdev = to_intel_th_device(dev); if (thdev->type == INTEL_TH_SWITCH && (!thdrv->enable || !thdrv->disable)) return 0; return !strcmp(thdev->name, driver->name); }
static char *intel_th_output_devnode(struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid) { struct intel_th_device *thdev = to_intel_th_device(dev); char *node; if (thdev->id >= 0) node = kasprintf(GFP_KERNEL, "intel_th%d/%s%d", 0, thdev->name, thdev->id); else node = kasprintf(GFP_KERNEL, "intel_th%d/%s", 0, thdev->name); return node; }
static ssize_t active_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct intel_th_device *thdev = to_intel_th_device(dev); unsigned long val; int ret; ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (!!val != thdev->output.active) { if (val) ret = intel_th_output_activate(thdev); else intel_th_output_deactivate(thdev); } return ret ? ret : size; }
static void intel_th_device_release(struct device *dev) { intel_th_device_free(to_intel_th_device(dev)); }