107 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2021 Intel Corporation. All rights rsvd. */3#include <linux/init.h>4#include <linux/kernel.h>5#include <linux/module.h>6#include <linux/device.h>7#include <linux/device/bus.h>8#include "idxd.h"9 10extern void device_driver_detach(struct device *dev);11 12#define DRIVER_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \13 struct driver_attribute driver_attr_##_name = \14 __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)15 16static ssize_t unbind_store(struct device_driver *drv, const char *buf, size_t count)17{18 const struct bus_type *bus = drv->bus;19 struct device *dev;20 int rc = -ENODEV;21 22 dev = bus_find_device_by_name(bus, NULL, buf);23 if (dev && dev->driver) {24 device_driver_detach(dev);25 rc = count;26 }27 28 return rc;29}30static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, 0200, NULL, unbind_store);31 32static ssize_t bind_store(struct device_driver *drv, const char *buf, size_t count)33{34 const struct bus_type *bus = drv->bus;35 struct device *dev;36 struct device_driver *alt_drv = NULL;37 int rc = -ENODEV;38 struct idxd_dev *idxd_dev;39 40 dev = bus_find_device_by_name(bus, NULL, buf);41 if (!dev || dev->driver || drv != &dsa_drv.drv)42 return -ENODEV;43 44 idxd_dev = confdev_to_idxd_dev(dev);45 if (is_idxd_dev(idxd_dev)) {46 alt_drv = driver_find("idxd", bus);47 } else if (is_idxd_wq_dev(idxd_dev)) {48 struct idxd_wq *wq = confdev_to_wq(dev);49 50 if (is_idxd_wq_kernel(wq))51 alt_drv = driver_find("dmaengine", bus);52 else if (is_idxd_wq_user(wq))53 alt_drv = driver_find("user", bus);54 }55 if (!alt_drv)56 return -ENODEV;57 58 rc = device_driver_attach(alt_drv, dev);59 if (rc < 0)60 return rc;61 62 return count;63}64static DRIVER_ATTR_IGNORE_LOCKDEP(bind, 0200, NULL, bind_store);65 66static struct attribute *dsa_drv_compat_attrs[] = {67 &driver_attr_bind.attr,68 &driver_attr_unbind.attr,69 NULL,70};71 72static const struct attribute_group dsa_drv_compat_attr_group = {73 .attrs = dsa_drv_compat_attrs,74};75 76static const struct attribute_group *dsa_drv_compat_groups[] = {77 &dsa_drv_compat_attr_group,78 NULL,79};80 81static int idxd_dsa_drv_probe(struct idxd_dev *idxd_dev)82{83 return -ENODEV;84}85 86static void idxd_dsa_drv_remove(struct idxd_dev *idxd_dev)87{88}89 90static enum idxd_dev_type dev_types[] = {91 IDXD_DEV_NONE,92};93 94struct idxd_device_driver dsa_drv = {95 .name = "dsa",96 .probe = idxd_dsa_drv_probe,97 .remove = idxd_dsa_drv_remove,98 .type = dev_types,99 .drv = {100 .suppress_bind_attrs = true,101 .groups = dsa_drv_compat_groups,102 },103};104 105module_idxd_driver(dsa_drv);106MODULE_IMPORT_NS(IDXD);107