diff --git a/include/vendor-reset.h b/include/vendor-reset-ioctl.h similarity index 100% rename from include/vendor-reset.h rename to include/vendor-reset-ioctl.h diff --git a/src/Makefile b/src/Makefile index 77771a4..de87fdd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,2 +1,7 @@ -vendor-reset-y += src/vendor-reset.o src/ftrace.o src/hooks.o -ccflags-y += -I$(src)/src \ No newline at end of file +vendor-reset-y += \ + src/vendor-reset.o \ + src/vendor-reset-dev.o\ + src/ftrace.o \ + src/hooks.o + +ccflags-y += -I$(src)/src diff --git a/src/amd/vega20.c b/src/amd/vega20.c index cb92059..0694a06 100644 --- a/src/amd/vega20.c +++ b/src/amd/vega20.c @@ -62,7 +62,6 @@ static int vega20_baco_set_state(struct amd_fake_dev *adev, enum BACO_STATE stat uint32_t data; vega20_baco_get_state(adev, &cur_state); - if (cur_state == state) return 0; diff --git a/src/hooks.c b/src/hooks.c index 5922ac1..c36793c 100644 --- a/src/hooks.c +++ b/src/hooks.c @@ -20,7 +20,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include "vendor-reset-dev.h" -#include "device-db.h" #include "ftrace.h" #include "hooks.h" @@ -30,38 +29,19 @@ static int hooked_pci_dev_specific_reset(struct pci_dev *dev, int probe) { int ret; struct vendor_reset_cfg *cfg; - struct vendor_reset_dev vdev = {0}; ret = orig_pci_dev_specific_reset(dev, probe); if (!ret || ret != -ENOTTY) return ret; - for (cfg = vendor_reset_devices; cfg->vendor; ++cfg) - if ((cfg->vendor == dev->vendor || cfg->vendor == PCI_ANY_ID) && (cfg->device == dev->device || cfg->device == PCI_ANY_ID)) - break; + cfg = vendor_reset_cfg_find(dev->vendor, dev->device); + if (!cfg) + return -ENOTTY; - if (cfg->vendor) - { - vdev.pdev = dev; - vdev.info = cfg->info; - - if (cfg->ops->pre_reset && (ret = cfg->ops->pre_reset(&vdev)) && ret) - return ret; - - ret = vdev.reset_ret = cfg->ops->reset(&vdev); - if (ret) - pr_warn("failed to reset device: %d\n", ret); - - if (cfg->ops->post_reset) - ret = cfg->ops->post_reset(&vdev); - - return ret; - } - - return -ENOTTY; + return vendor_reset_dev_locked(cfg, dev); } struct ftrace_hook fh_hooks[] = { HOOK("pci_dev_specific_reset", &orig_pci_dev_specific_reset, hooked_pci_dev_specific_reset), {0}, -}; \ No newline at end of file +}; diff --git a/src/vendor-reset-dev.c b/src/vendor-reset-dev.c new file mode 100644 index 0000000..344d681 --- /dev/null +++ b/src/vendor-reset-dev.c @@ -0,0 +1,71 @@ +/* +Vendor Reset - Vendor Specific Reset +Copyright (C) 2020 Geoffrey McRae +Copyright (C) 2020 Adam Madsen + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "vendor-reset-dev.h" +#include "device-db.h" + +struct vendor_reset_cfg * vendor_reset_cfg_find(unsigned int vendor, unsigned + int device) +{ + struct vendor_reset_cfg * cfg; + + for(cfg = vendor_reset_devices; cfg->vendor; ++cfg) + { + if (cfg->vendor != vendor) + continue; + + if (device == PCI_ANY_ID || device == cfg->device) + break; + } + + if (!cfg->vendor) + return NULL; + + return cfg; +} + +long vendor_reset_dev_locked(struct vendor_reset_cfg *cfg, struct pci_dev *dev) +{ + struct vendor_reset_dev vdev = + { + .pdev = dev, + .info = cfg->info + }; + int ret; + + if (cfg->ops->pre_reset) + { + ret = cfg->ops->pre_reset(&vdev); + if (ret) + return ret; + } + + /* expose return code to cleanup */ + ret = vdev.reset_ret = cfg->ops->reset(&vdev); + if (ret) + { + pci_warn(dev, "Failed to reset device\n"); + return ret; + } + + if (cfg->ops->post_reset) + ret = cfg->ops->post_reset(&vdev); + + return ret; +} diff --git a/src/vendor-reset-dev.h b/src/vendor-reset-dev.h index 3d11b24..1b4a2a8 100644 --- a/src/vendor-reset-dev.h +++ b/src/vendor-reset-dev.h @@ -20,8 +20,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA #ifndef _H_VENDOR_RESET_DEV #define _H_VENDOR_RESET_DEV -#define VENDOR_RESET_DEVICE_ALL ((unsigned int)-1) - #include struct vendor_reset_dev @@ -49,8 +47,7 @@ struct vendor_reset_cfg /* the vendor ID */ unsigned int vendor; - /* the device ID or VENDOR_RESET_DEVICE_ALL to match all devices for the - * vendor */ + /* the device ID or PCI_ANY_ID to match all devices for the vendor */ unsigned int device; /* the reset operations */ @@ -60,4 +57,11 @@ struct vendor_reset_cfg unsigned long info; }; +/* search the device table for the specified vendor and device id and return it */ +struct vendor_reset_cfg * vendor_reset_cfg_find(unsigned int vendor, unsigned + int device); + +/* perform the device reset */ +long vendor_reset_dev_locked(struct vendor_reset_cfg *cfg, struct pci_dev *dev); + #endif diff --git a/src/vendor-reset.c b/src/vendor-reset.c index 4a3def1..2181264 100644 --- a/src/vendor-reset.c +++ b/src/vendor-reset.c @@ -24,9 +24,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include "vendor-reset-dev.h" -#include "vendor-reset.h" - -#include "device-db.h" +#include "vendor-reset-ioctl.h" #include "ftrace.h" #include "hooks.h" @@ -41,10 +39,9 @@ module_param(install_hook, bool, 0); static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg) { struct vendor_reset_ioctl dev; - struct vendor_reset_cfg *entry = vendor_reset_devices; + struct vendor_reset_cfg *cfg; struct pci_dev * pcidev; int ret; - struct vendor_reset_dev vdev = {0}; if (copy_from_user(&dev, (void __user *)arg, sizeof(dev))) return -EFAULT; @@ -53,25 +50,13 @@ static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg) if (!pcidev) return -ENODEV; - for(entry = vendor_reset_devices; entry->vendor; ++entry) - { - if (entry->vendor != pcidev->vendor) - continue; - - if (entry->device == VENDOR_RESET_DEVICE_ALL || - entry->device == pcidev->device) - break; - } - - if (!entry->vendor) + cfg = vendor_reset_cfg_find(pcidev->vendor, pcidev->device); + if (!cfg) { ret = -EOPNOTSUPP; goto err; } - vdev.pdev = pcidev; - vdev.info = entry->info; - /* we probably always want to lock the device */ if (!pci_cfg_access_trylock(pcidev)) { @@ -79,36 +64,19 @@ static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg) ret = -EAGAIN; goto err; } - else - { - if (!device_trylock(&pcidev->dev)) - { - pci_warn(pcidev, "Could not acquire device lock\n"); - pci_cfg_access_unlock(pcidev); - ret = -EAGAIN; - goto err; - } - } - if (entry->ops->pre_reset) + if (!device_trylock(&pcidev->dev)) { - ret = entry->ops->pre_reset(&vdev); - if (ret) - goto unlock; + pci_warn(pcidev, "Could not acquire device lock\n"); + ret = -EAGAIN; + goto unlock; } - /* expose return code to cleanup */ - ret = vdev.reset_ret = entry->ops->reset(&vdev); - if (ret) - pci_warn(pcidev, "Failed to reset device\n"); - - if (entry->ops->post_reset) - ret = entry->ops->post_reset(&vdev); + ret = vendor_reset_dev_locked(cfg, pcidev); + device_unlock(&pcidev->dev); unlock: - device_unlock(&pcidev->dev); pci_cfg_access_unlock(pcidev); - err: pci_dev_put(pcidev); return ret; diff --git a/userspace/vendor-reset.c b/userspace/vendor-reset.c index 7120191..673e8fd 100644 --- a/userspace/vendor-reset.c +++ b/userspace/vendor-reset.c @@ -22,7 +22,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include -#include "vendor-reset.h" +#include "vendor-reset-ioctl.h" #include "ucommon.h" void help_(const char *prog);