diff --git a/Kbuild b/Kbuild new file mode 100644 index 0000000..a7a7301 --- /dev/null +++ b/Kbuild @@ -0,0 +1,10 @@ +obj-m += vendor-reset.o + +include $(src)/src/Makefile +include $(src)/src/amd/Makefile + +ccflags-y += \ + -I$(src)/include -g +ldflags-$(CONFIG_DEBUG) += -g + +subdir-y += userspace/ \ No newline at end of file diff --git a/Makefile b/Makefile index 5218135..8aea118 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,3 @@ -obj-m := vendor-reset.o -vendor-reset-y := src/vendor-reset.o - -vendor-reset-y += src/amd/vega10.o -vendor-reset-y += src/amd/vega20.o -vendor-reset-y += src/amd/navi10.o - - -ccflags-y := -I$(src)/src -ccflags-y += -I$(src)/include - USER := $(shell whoami) KVER ?= $(shell uname -r) KDIR ?= /lib/modules/$(KVER)/build @@ -23,7 +12,7 @@ userspace: gcc userspace/vendor-reset.c -Wall -Werror -g -Og -o userspace/vendor-reset load: all - grep -q '^vendor-reset' /proc/modules && sudo rmmod vendor-reset || true + grep -q '^vendor_reset' /proc/modules && sudo rmmod vendor_reset || true sudo insmod ./vendor-reset.ko -.PHONY: userspace +.PHONY: userspace load diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..6b8aff8 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,2 @@ +vendor-reset-y += src/vendor-reset.o +ccflags-y += -I$(src)/src \ No newline at end of file diff --git a/src/amd/Makefile b/src/amd/Makefile new file mode 100644 index 0000000..176d9d9 --- /dev/null +++ b/src/amd/Makefile @@ -0,0 +1,5 @@ +vendor-reset-y += \ + src/amd/common.o \ + src/amd/vega10.o \ + src/amd/vega20.o \ + src/amd/navi10.o \ No newline at end of file diff --git a/src/amd/common.c b/src/amd/common.c new file mode 100644 index 0000000..85ac437 --- /dev/null +++ b/src/amd/common.c @@ -0,0 +1,46 @@ +#include +#include +#include "vendor-reset-dev.h" +#include "common.h" + +int amd_common_pre_reset(struct vendor_reset_dev *dev) +{ + struct amd_vendor_private *priv; + struct pci_dev *pdev = dev->pdev; + + priv = kzalloc(sizeof *priv, GFP_KERNEL); + if (!priv) + return -ENOMEM; + + dev->vendor_private = priv; + + spin_lock_init(&priv->pcie_lock); + + pci_set_power_state(pdev, PCI_D0); + pci_clear_master(pdev); + pci_save_state(pdev); + priv->saved_state = pci_store_saved_state(pdev); + pci_read_config_word(pdev, PCI_COMMAND, &priv->cfg); + pci_write_config_word(pdev, PCI_COMMAND, priv->cfg | PCI_COMMAND_MEMORY | PCI_COMMAND_INTX_DISABLE); + + return 0; +} + +int amd_common_post_reset(struct vendor_reset_dev *dev) +{ + struct amd_vendor_private *priv = amd_private(dev); + struct pci_dev *pdev = dev->pdev; + + if (priv->saved_state) + { + pci_load_and_free_saved_state(pdev, &priv->saved_state); + pci_restore_state(pdev); + } + pci_write_config_word(pdev, PCI_COMMAND, priv->cfg); + + /* don't try to go to low power if reset failed */ + if (!dev->reset_ret) + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} diff --git a/src/amd/common.h b/src/amd/common.h new file mode 100644 index 0000000..7ffa13c --- /dev/null +++ b/src/amd/common.h @@ -0,0 +1,87 @@ +/* +Vendor Reset - Vendor Specific Reset +Copyright (C) 2020 Geoffrey McRae + +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 +*/ + +#ifndef __VENDOR_RESET_COMMON_H__ +#define __VENDOR_RESET_COMMON_H__ + +#include "vendor-reset-dev.h" + +#define RREG32(reg) \ + ({ \ + u32 out; \ + if ((reg) < mmio_size) \ + out = readl(mmio + (reg)); \ + else \ + { \ + writel((reg), mmio + mmMM_INDEX); \ + out = readl(mmio + mmMM_DATA); \ + } \ + out; \ + }) + +#define WREG32(reg, v) \ + do \ + { \ + if ((reg) < mmio_size) \ + writel(v, mmio + (reg)); \ + else \ + { \ + writel((reg), mmio + mmMM_INDEX); \ + writel(v, mmio + mmMM_DATA); \ + } \ + } while (0) + +#define WREG32_PCIE(reg, v) \ + do \ + { \ + unsigned long __flags; \ + spin_lock_irqsave(&pcie_lock, __flags); \ + WREG32(mmPCIE_INDEX2, reg); \ + (void)RREG32(mmPCIE_INDEX2); \ + WREG32(mmPCIE_DATA2, v); \ + (void)RREG32(mmPCIE_DATA2); \ + spin_unlock_irqrestore(&pcie_lock, __flags); \ + } while (0) + +#define RREG32_PCIE(reg) \ + ({ \ + unsigned long __flags; \ + u32 __tmp_read; \ + spin_lock_irqsave(&pcie_lock, __flags); \ + WREG32(mmPCIE_INDEX2, reg); \ + (void)RREG32(mmPCIE_INDEX2); \ + __tmp_read = RREG32(mmPCIE_DATA2); \ + spin_unlock_irqrestore(&pcie_lock, __flags); \ + __tmp_read; \ + }) + +struct amd_vendor_private +{ + u16 cfg; + + struct pci_saved_state *saved_state; + + spinlock_t pcie_lock; +}; + +#define amd_private(vdev) ((struct amd_vendor_private *)(vdev->vendor_private)) + +int amd_common_pre_reset(struct vendor_reset_dev *); +int amd_common_post_reset(struct vendor_reset_dev *); + +#endif \ No newline at end of file diff --git a/src/amd/navi10.c b/src/amd/navi10.c index 194f877..cb95883 100644 --- a/src/amd/navi10.c +++ b/src/amd/navi10.c @@ -18,7 +18,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "vendor-reset-dev.h" -static int amd_navi10_reset(struct pci_dev * dev) +static int amd_navi10_reset(struct vendor_reset_dev *dev) { return 0; } diff --git a/src/amd/soc15_common.h b/src/amd/soc15_common.h new file mode 100644 index 0000000..a5c00ab --- /dev/null +++ b/src/amd/soc15_common.h @@ -0,0 +1,135 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __SOC15_COMMON_H__ +#define __SOC15_COMMON_H__ + +/* Register Access Macros */ +#define SOC15_REG_OFFSET(ip, inst, reg) (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + +#define WREG32_FIELD15(ip, idx, reg, field, val) \ + WREG32(adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg, \ + (RREG32(adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg) \ + & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field)) + +#define RREG32_SOC15(ip, inst, reg) \ + RREG32(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + +#define RREG32_SOC15_NO_KIQ(ip, inst, reg) \ + RREG32_NO_KIQ(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + +#define RREG32_SOC15_OFFSET(ip, inst, reg, offset) \ + RREG32((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset) + +#define WREG32_SOC15(ip, inst, reg, value) \ + WREG32((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg), value) + +#define WREG32_SOC15_NO_KIQ(ip, inst, reg, value) \ + WREG32_NO_KIQ((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg), value) + +#define WREG32_SOC15_OFFSET(ip, inst, reg, offset, value) \ + WREG32((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset, value) + +#define SOC15_WAIT_ON_RREG(ip, inst, reg, expected_value, mask) \ +({ int ret = 0; \ + do { \ + uint32_t old_ = 0; \ + uint32_t tmp_ = RREG32(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg); \ + uint32_t loop = adev->usec_timeout; \ + ret = 0; \ + while ((tmp_ & (mask)) != (expected_value)) { \ + if (old_ != tmp_) { \ + loop = adev->usec_timeout; \ + old_ = tmp_; \ + } else \ + udelay(1); \ + tmp_ = RREG32(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg); \ + loop--; \ + if (!loop) { \ + DRM_WARN("Register(%d) [%s] failed to reach value 0x%08x != 0x%08x\n", \ + inst, #reg, (unsigned)expected_value, (unsigned)(tmp_ & (mask))); \ + ret = -ETIMEDOUT; \ + break; \ + } \ + } \ + } while (0); \ + ret; \ +}) + +#define WREG32_RLC(reg, value) \ + do { \ + if (amdgpu_sriov_fullaccess(adev)) { \ + uint32_t i = 0; \ + uint32_t retries = 50000; \ + uint32_t r0 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0; \ + uint32_t r1 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1; \ + uint32_t spare_int = adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT; \ + WREG32(r0, value); \ + WREG32(r1, (reg | 0x80000000)); \ + WREG32(spare_int, 0x1); \ + for (i = 0; i < retries; i++) { \ + u32 tmp = RREG32(r1); \ + if (!(tmp & 0x80000000)) \ + break; \ + udelay(10); \ + } \ + if (i >= retries) \ + pr_err("timeout: rlcg program reg:0x%05x failed !\n", reg); \ + } else { \ + WREG32(reg, value); \ + } \ + } while (0) + +#define WREG32_SOC15_RLC_SHADOW(ip, inst, reg, value) \ + do { \ + uint32_t target_reg = adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg;\ + if (amdgpu_sriov_fullaccess(adev)) { \ + uint32_t r2 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG2; \ + uint32_t r3 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG3; \ + uint32_t grbm_cntl = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_CNTL_BASE_IDX] + mmGRBM_GFX_CNTL; \ + uint32_t grbm_idx = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_INDEX_BASE_IDX] + mmGRBM_GFX_INDEX; \ + if (target_reg == grbm_cntl) \ + WREG32(r2, value); \ + else if (target_reg == grbm_idx) \ + WREG32(r3, value); \ + WREG32(target_reg, value); \ + } else { \ + WREG32(target_reg, value); \ + } \ + } while (0) + +#define WREG32_SOC15_RLC(ip, inst, reg, value) \ + do { \ + uint32_t target_reg = adev->reg_offset[GC_HWIP][0][reg##_BASE_IDX] + reg;\ + WREG32_RLC(target_reg, value); \ + } while (0) + +#define WREG32_FIELD15_RLC(ip, idx, reg, field, val) \ + WREG32_RLC((adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg), \ + (RREG32(adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg) \ + & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field)) + +#define WREG32_SOC15_OFFSET_RLC(ip, inst, reg, offset, value) \ + WREG32_RLC(((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset), value) + +#endif diff --git a/src/amd/vega10.c b/src/amd/vega10.c index c576992..5ab7816 100644 --- a/src/amd/vega10.c +++ b/src/amd/vega10.c @@ -16,14 +16,18 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "soc15_common.h" #include "vendor-reset-dev.h" +#include "common.h" -static int amd_vega10_reset(struct pci_dev * dev) +static int amd_vega10_reset(struct vendor_reset_dev *dev) { - return 0; + + return 0; } -const struct vendor_reset_ops amd_vega10_ops = -{ - .reset = amd_vega10_reset +const struct vendor_reset_ops amd_vega10_ops = { + .pre_reset = amd_common_pre_reset, + .reset = amd_vega10_reset, + .post_reset = amd_common_post_reset, }; diff --git a/src/amd/vega20.c b/src/amd/vega20.c index 17d61c5..4a945f6 100644 --- a/src/amd/vega20.c +++ b/src/amd/vega20.c @@ -18,7 +18,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "vendor-reset-dev.h" -static int amd_vega20_reset(struct pci_dev * dev) +static int amd_vega20_reset(struct vendor_reset_dev *dev) { return 0; } diff --git a/src/device-db.h b/src/device-db.h index 02224a1..ecfeeac 100644 --- a/src/device-db.h +++ b/src/device-db.h @@ -18,42 +18,42 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "amd/amd.h" -static struct vendor_reset_device vendor_reset_devices[] = -{ - /* AMD Vega 10 */ - { PCI_VENDOR_ID_ATI, 0x6860, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x6861, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x6862, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x6863, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x6864, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x6867, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x6868, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x6869, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x686a, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x686b, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x686c, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x686d, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x686e, &amd_vega10_ops }, - { PCI_VENDOR_ID_ATI, 0x686f, &amd_vega10_ops }, +static struct vendor_reset_cfg vendor_reset_devices[] = + { + /* AMD Vega 10 */ + {PCI_VENDOR_ID_ATI, 0x6860, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x6861, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x6862, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x6863, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x6864, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x6867, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x6868, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x6869, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x686a, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x686b, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x686c, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x686d, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x686e, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x686f, &amd_vega10_ops}, + {PCI_VENDOR_ID_ATI, 0x687f, &amd_vega10_ops}, - /* AMD Vega 20 */ - { PCI_VENDOR_ID_ATI, 0x66a0, &amd_vega20_ops }, - { PCI_VENDOR_ID_ATI, 0x66a1, &amd_vega20_ops }, - { PCI_VENDOR_ID_ATI, 0x66a2, &amd_vega20_ops }, - { PCI_VENDOR_ID_ATI, 0x66a3, &amd_vega20_ops }, - { PCI_VENDOR_ID_ATI, 0x66a4, &amd_vega20_ops }, - { PCI_VENDOR_ID_ATI, 0x66a7, &amd_vega20_ops }, - { PCI_VENDOR_ID_ATI, 0x66af, &amd_vega20_ops }, + /* AMD Vega 20 */ + {PCI_VENDOR_ID_ATI, 0x66a0, &amd_vega20_ops}, + {PCI_VENDOR_ID_ATI, 0x66a1, &amd_vega20_ops}, + {PCI_VENDOR_ID_ATI, 0x66a2, &amd_vega20_ops}, + {PCI_VENDOR_ID_ATI, 0x66a3, &amd_vega20_ops}, + {PCI_VENDOR_ID_ATI, 0x66a4, &amd_vega20_ops}, + {PCI_VENDOR_ID_ATI, 0x66a7, &amd_vega20_ops}, + {PCI_VENDOR_ID_ATI, 0x66af, &amd_vega20_ops}, - /* AMD Navi 10 */ - { PCI_VENDOR_ID_ATI, 0x7310, &amd_navi10_ops }, - { PCI_VENDOR_ID_ATI, 0x7312, &amd_navi10_ops }, - { PCI_VENDOR_ID_ATI, 0x7318, &amd_navi10_ops }, - { PCI_VENDOR_ID_ATI, 0x7319, &amd_navi10_ops }, - { PCI_VENDOR_ID_ATI, 0x731a, &amd_navi10_ops }, - { PCI_VENDOR_ID_ATI, 0x731b, &amd_navi10_ops }, - { PCI_VENDOR_ID_ATI, 0x731e, &amd_navi10_ops }, - { PCI_VENDOR_ID_ATI, 0x731f, &amd_navi10_ops }, + /* AMD Navi 10 */ + {PCI_VENDOR_ID_ATI, 0x7310, &amd_navi10_ops}, + {PCI_VENDOR_ID_ATI, 0x7312, &amd_navi10_ops}, + {PCI_VENDOR_ID_ATI, 0x7318, &amd_navi10_ops}, + {PCI_VENDOR_ID_ATI, 0x7319, &amd_navi10_ops}, + {PCI_VENDOR_ID_ATI, 0x731a, &amd_navi10_ops}, + {PCI_VENDOR_ID_ATI, 0x731b, &amd_navi10_ops}, + {PCI_VENDOR_ID_ATI, 0x731e, &amd_navi10_ops}, + {PCI_VENDOR_ID_ATI, 0x731f, &amd_navi10_ops}, - { 0 } -}; + {0}}; diff --git a/src/vendor-reset-dev.h b/src/vendor-reset-dev.h index 1445daf..24b9f0f 100644 --- a/src/vendor-reset-dev.h +++ b/src/vendor-reset-dev.h @@ -23,13 +23,26 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include -struct vendor_reset_ops +struct vendor_reset_dev { - /* the reset method for the device at the specified address */ - int (*reset)(struct pci_dev *dev); + struct pci_dev *pdev; + + int reset_ret; + + void *vendor_private; }; -struct vendor_reset_device +struct vendor_reset_ops +{ + /* any pre-reset ops to do, i.e., common code between devices */ + int (*pre_reset)(struct vendor_reset_dev *); + /* the reset method for the device at the specified address */ + int (*reset)(struct vendor_reset_dev *); + /* any post-reset ops to do, i.e., common code between devices */ + int (*post_reset)(struct vendor_reset_dev *); +}; + +struct vendor_reset_cfg { /* the vendor ID */ unsigned int vendor; diff --git a/src/vendor-reset.c b/src/vendor-reset.c index c78e8aa..9d15232 100644 --- a/src/vendor-reset.c +++ b/src/vendor-reset.c @@ -32,9 +32,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg) { struct vendor_reset_ioctl dev; - struct vendor_reset_device *entry = vendor_reset_devices; + struct vendor_reset_cfg *entry = vendor_reset_devices; struct pci_dev * pcidev; int ret; + struct vendor_reset_dev vdev; if (copy_from_user(&dev, (void __user *)arg, sizeof(dev))) return -EFAULT; @@ -43,6 +44,8 @@ static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg) if (!pcidev) return -ENODEV; + pci_printk(KERN_INFO, pcidev, "Found device\n"); + for(entry = vendor_reset_devices; entry->vendor; ++entry) { if (entry->vendor != pcidev->vendor) @@ -59,7 +62,38 @@ static long vendor_reset_ioctl_reset(struct file * filp, unsigned long arg) goto err; } - ret = entry->ops->reset(pcidev); + vdev.pdev = pcidev; + + /* we probably always want to lock the device */ + if (!pci_cfg_access_trylock(pcidev)) + goto err; + else + { + if (!device_trylock(&pcidev->dev)) + { + pci_cfg_access_unlock(pcidev); + goto err; + } + } + + if (entry->ops->pre_reset) + { + ret = entry->ops->pre_reset(&vdev); + if (ret) + 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); + +unlock: + device_unlock(&pcidev->dev); + pci_cfg_access_unlock(pcidev); err: pci_dev_put(pcidev); diff --git a/userspace/Makefile b/userspace/Makefile new file mode 100644 index 0000000..1c3e3fe --- /dev/null +++ b/userspace/Makefile @@ -0,0 +1,3 @@ +userccflags += -I$(src)/../include +userprogs-always-y += vendor-reset +vendor-reset-objs += vendor-reset.o \ No newline at end of file diff --git a/userspace/vendor-reset b/userspace/vendor-reset deleted file mode 100755 index a90b65f..0000000 Binary files a/userspace/vendor-reset and /dev/null differ diff --git a/userspace/vendor-reset.c b/userspace/vendor-reset.c index 0ea500e..bafb5d6 100644 --- a/userspace/vendor-reset.c +++ b/userspace/vendor-reset.c @@ -16,12 +16,12 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../include/vendor-reset.h" #include #include #include #include #include +#include "vendor-reset.h" int main(int argc, char * argv[]) {