1eb3ae0aaSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 212eb4683SFrank Haverkamp /** 312eb4683SFrank Haverkamp * IBM Accelerator Family 'GenWQE' 412eb4683SFrank Haverkamp * 512eb4683SFrank Haverkamp * (C) Copyright IBM Corp. 2013 612eb4683SFrank Haverkamp * 712eb4683SFrank Haverkamp * Author: Frank Haverkamp <haver@linux.vnet.ibm.com> 812eb4683SFrank Haverkamp * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com> 926d8f6f1SFrank Haverkamp * Author: Michael Jung <mijung@gmx.net> 1012eb4683SFrank Haverkamp * Author: Michael Ruettger <michael@ibmra.de> 1112eb4683SFrank Haverkamp */ 1212eb4683SFrank Haverkamp 1312eb4683SFrank Haverkamp /* 1412eb4683SFrank Haverkamp * Module initialization and PCIe setup. Card health monitoring and 1512eb4683SFrank Haverkamp * recovery functionality. Character device creation and deletion are 1612eb4683SFrank Haverkamp * controlled from here. 1712eb4683SFrank Haverkamp */ 1812eb4683SFrank Haverkamp 1912eb4683SFrank Haverkamp #include <linux/types.h> 2012eb4683SFrank Haverkamp #include <linux/pci.h> 2112eb4683SFrank Haverkamp #include <linux/err.h> 2212eb4683SFrank Haverkamp #include <linux/aer.h> 2312eb4683SFrank Haverkamp #include <linux/string.h> 2412eb4683SFrank Haverkamp #include <linux/sched.h> 2512eb4683SFrank Haverkamp #include <linux/wait.h> 2612eb4683SFrank Haverkamp #include <linux/delay.h> 2712eb4683SFrank Haverkamp #include <linux/dma-mapping.h> 2812eb4683SFrank Haverkamp #include <linux/module.h> 2912eb4683SFrank Haverkamp #include <linux/notifier.h> 3012eb4683SFrank Haverkamp #include <linux/device.h> 3112eb4683SFrank Haverkamp #include <linux/log2.h> 3212eb4683SFrank Haverkamp 3312eb4683SFrank Haverkamp #include "card_base.h" 3412eb4683SFrank Haverkamp #include "card_ddcb.h" 3512eb4683SFrank Haverkamp 3612eb4683SFrank Haverkamp MODULE_AUTHOR("Frank Haverkamp <haver@linux.vnet.ibm.com>"); 3712eb4683SFrank Haverkamp MODULE_AUTHOR("Michael Ruettger <michael@ibmra.de>"); 3812eb4683SFrank Haverkamp MODULE_AUTHOR("Joerg-Stephan Vogt <jsvogt@de.ibm.com>"); 3926d8f6f1SFrank Haverkamp MODULE_AUTHOR("Michael Jung <mijung@gmx.net>"); 4012eb4683SFrank Haverkamp 4112eb4683SFrank Haverkamp MODULE_DESCRIPTION("GenWQE Card"); 4264df2ec5SFrank Haverkamp MODULE_VERSION(DRV_VERSION); 4312eb4683SFrank Haverkamp MODULE_LICENSE("GPL"); 4412eb4683SFrank Haverkamp 4512eb4683SFrank Haverkamp static char genwqe_driver_name[] = GENWQE_DEVNAME; 4612eb4683SFrank Haverkamp static struct class *class_genwqe; 4712eb4683SFrank Haverkamp static struct dentry *debugfs_genwqe; 4812eb4683SFrank Haverkamp static struct genwqe_dev *genwqe_devices[GENWQE_CARD_NO_MAX]; 4912eb4683SFrank Haverkamp 5012eb4683SFrank Haverkamp /* PCI structure for identifying device by PCI vendor and device ID */ 5132182cd3SGreg Kroah-Hartman static const struct pci_device_id genwqe_device_table[] = { 5212eb4683SFrank Haverkamp { .vendor = PCI_VENDOR_ID_IBM, 5312eb4683SFrank Haverkamp .device = PCI_DEVICE_GENWQE, 5412eb4683SFrank Haverkamp .subvendor = PCI_SUBVENDOR_ID_IBM, 5512eb4683SFrank Haverkamp .subdevice = PCI_SUBSYSTEM_ID_GENWQE5, 5612eb4683SFrank Haverkamp .class = (PCI_CLASSCODE_GENWQE5 << 8), 5712eb4683SFrank Haverkamp .class_mask = ~0, 5812eb4683SFrank Haverkamp .driver_data = 0 }, 5912eb4683SFrank Haverkamp 6012eb4683SFrank Haverkamp /* Initial SR-IOV bring-up image */ 6112eb4683SFrank Haverkamp { .vendor = PCI_VENDOR_ID_IBM, 6212eb4683SFrank Haverkamp .device = PCI_DEVICE_GENWQE, 6312eb4683SFrank Haverkamp .subvendor = PCI_SUBVENDOR_ID_IBM_SRIOV, 6412eb4683SFrank Haverkamp .subdevice = PCI_SUBSYSTEM_ID_GENWQE5_SRIOV, 6512eb4683SFrank Haverkamp .class = (PCI_CLASSCODE_GENWQE5_SRIOV << 8), 6612eb4683SFrank Haverkamp .class_mask = ~0, 6712eb4683SFrank Haverkamp .driver_data = 0 }, 6812eb4683SFrank Haverkamp 6912eb4683SFrank Haverkamp { .vendor = PCI_VENDOR_ID_IBM, /* VF Vendor ID */ 7012eb4683SFrank Haverkamp .device = 0x0000, /* VF Device ID */ 7112eb4683SFrank Haverkamp .subvendor = PCI_SUBVENDOR_ID_IBM_SRIOV, 7212eb4683SFrank Haverkamp .subdevice = PCI_SUBSYSTEM_ID_GENWQE5_SRIOV, 7312eb4683SFrank Haverkamp .class = (PCI_CLASSCODE_GENWQE5_SRIOV << 8), 7412eb4683SFrank Haverkamp .class_mask = ~0, 7512eb4683SFrank Haverkamp .driver_data = 0 }, 7612eb4683SFrank Haverkamp 7712eb4683SFrank Haverkamp /* Fixed up image */ 7812eb4683SFrank Haverkamp { .vendor = PCI_VENDOR_ID_IBM, 7912eb4683SFrank Haverkamp .device = PCI_DEVICE_GENWQE, 8012eb4683SFrank Haverkamp .subvendor = PCI_SUBVENDOR_ID_IBM_SRIOV, 8112eb4683SFrank Haverkamp .subdevice = PCI_SUBSYSTEM_ID_GENWQE5, 8212eb4683SFrank Haverkamp .class = (PCI_CLASSCODE_GENWQE5_SRIOV << 8), 8312eb4683SFrank Haverkamp .class_mask = ~0, 8412eb4683SFrank Haverkamp .driver_data = 0 }, 8512eb4683SFrank Haverkamp 8612eb4683SFrank Haverkamp { .vendor = PCI_VENDOR_ID_IBM, /* VF Vendor ID */ 8712eb4683SFrank Haverkamp .device = 0x0000, /* VF Device ID */ 8812eb4683SFrank Haverkamp .subvendor = PCI_SUBVENDOR_ID_IBM_SRIOV, 8912eb4683SFrank Haverkamp .subdevice = PCI_SUBSYSTEM_ID_GENWQE5, 9012eb4683SFrank Haverkamp .class = (PCI_CLASSCODE_GENWQE5_SRIOV << 8), 9112eb4683SFrank Haverkamp .class_mask = ~0, 9212eb4683SFrank Haverkamp .driver_data = 0 }, 9312eb4683SFrank Haverkamp 9412eb4683SFrank Haverkamp /* Even one more ... */ 9512eb4683SFrank Haverkamp { .vendor = PCI_VENDOR_ID_IBM, 9612eb4683SFrank Haverkamp .device = PCI_DEVICE_GENWQE, 9712eb4683SFrank Haverkamp .subvendor = PCI_SUBVENDOR_ID_IBM, 9812eb4683SFrank Haverkamp .subdevice = PCI_SUBSYSTEM_ID_GENWQE5_NEW, 9912eb4683SFrank Haverkamp .class = (PCI_CLASSCODE_GENWQE5 << 8), 10012eb4683SFrank Haverkamp .class_mask = ~0, 10112eb4683SFrank Haverkamp .driver_data = 0 }, 10212eb4683SFrank Haverkamp 10312eb4683SFrank Haverkamp { 0, } /* 0 terminated list. */ 10412eb4683SFrank Haverkamp }; 10512eb4683SFrank Haverkamp 10612eb4683SFrank Haverkamp MODULE_DEVICE_TABLE(pci, genwqe_device_table); 10712eb4683SFrank Haverkamp 10812eb4683SFrank Haverkamp /** 10912eb4683SFrank Haverkamp * genwqe_dev_alloc() - Create and prepare a new card descriptor 11012eb4683SFrank Haverkamp * 11112eb4683SFrank Haverkamp * Return: Pointer to card descriptor, or ERR_PTR(err) on error 11212eb4683SFrank Haverkamp */ 11312eb4683SFrank Haverkamp static struct genwqe_dev *genwqe_dev_alloc(void) 11412eb4683SFrank Haverkamp { 11512eb4683SFrank Haverkamp unsigned int i = 0, j; 11612eb4683SFrank Haverkamp struct genwqe_dev *cd; 11712eb4683SFrank Haverkamp 11812eb4683SFrank Haverkamp for (i = 0; i < GENWQE_CARD_NO_MAX; i++) { 11912eb4683SFrank Haverkamp if (genwqe_devices[i] == NULL) 12012eb4683SFrank Haverkamp break; 12112eb4683SFrank Haverkamp } 12212eb4683SFrank Haverkamp if (i >= GENWQE_CARD_NO_MAX) 12312eb4683SFrank Haverkamp return ERR_PTR(-ENODEV); 12412eb4683SFrank Haverkamp 12512eb4683SFrank Haverkamp cd = kzalloc(sizeof(struct genwqe_dev), GFP_KERNEL); 12612eb4683SFrank Haverkamp if (!cd) 12712eb4683SFrank Haverkamp return ERR_PTR(-ENOMEM); 12812eb4683SFrank Haverkamp 12912eb4683SFrank Haverkamp cd->card_idx = i; 13012eb4683SFrank Haverkamp cd->class_genwqe = class_genwqe; 13112eb4683SFrank Haverkamp cd->debugfs_genwqe = debugfs_genwqe; 13212eb4683SFrank Haverkamp 133fb145456SKleber Sacilotto de Souza /* 134fb145456SKleber Sacilotto de Souza * This comes from kernel config option and can be overritten via 135fb145456SKleber Sacilotto de Souza * debugfs. 136fb145456SKleber Sacilotto de Souza */ 137fb145456SKleber Sacilotto de Souza cd->use_platform_recovery = CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY; 138fb145456SKleber Sacilotto de Souza 13912eb4683SFrank Haverkamp init_waitqueue_head(&cd->queue_waitq); 14012eb4683SFrank Haverkamp 14112eb4683SFrank Haverkamp spin_lock_init(&cd->file_lock); 14212eb4683SFrank Haverkamp INIT_LIST_HEAD(&cd->file_list); 14312eb4683SFrank Haverkamp 14412eb4683SFrank Haverkamp cd->card_state = GENWQE_CARD_UNUSED; 14512eb4683SFrank Haverkamp spin_lock_init(&cd->print_lock); 14612eb4683SFrank Haverkamp 1479d14e766SGuilherme G. Piccoli cd->ddcb_software_timeout = GENWQE_DDCB_SOFTWARE_TIMEOUT; 1489d14e766SGuilherme G. Piccoli cd->kill_timeout = GENWQE_KILL_TIMEOUT; 14912eb4683SFrank Haverkamp 15012eb4683SFrank Haverkamp for (j = 0; j < GENWQE_MAX_VFS; j++) 1519d14e766SGuilherme G. Piccoli cd->vf_jobtimeout_msec[j] = GENWQE_VF_JOBTIMEOUT_MSEC; 15212eb4683SFrank Haverkamp 15312eb4683SFrank Haverkamp genwqe_devices[i] = cd; 15412eb4683SFrank Haverkamp return cd; 15512eb4683SFrank Haverkamp } 15612eb4683SFrank Haverkamp 15712eb4683SFrank Haverkamp static void genwqe_dev_free(struct genwqe_dev *cd) 15812eb4683SFrank Haverkamp { 15912eb4683SFrank Haverkamp if (!cd) 16012eb4683SFrank Haverkamp return; 16112eb4683SFrank Haverkamp 16212eb4683SFrank Haverkamp genwqe_devices[cd->card_idx] = NULL; 16312eb4683SFrank Haverkamp kfree(cd); 16412eb4683SFrank Haverkamp } 16512eb4683SFrank Haverkamp 16612eb4683SFrank Haverkamp /** 16712eb4683SFrank Haverkamp * genwqe_bus_reset() - Card recovery 168a562c0c3SLee Jones * @cd: GenWQE device information 16912eb4683SFrank Haverkamp * 17012eb4683SFrank Haverkamp * pci_reset_function() will recover the device and ensure that the 17112eb4683SFrank Haverkamp * registers are accessible again when it completes with success. If 17212eb4683SFrank Haverkamp * not, the card will stay dead and registers will be unaccessible 17312eb4683SFrank Haverkamp * still. 17412eb4683SFrank Haverkamp */ 17512eb4683SFrank Haverkamp static int genwqe_bus_reset(struct genwqe_dev *cd) 17612eb4683SFrank Haverkamp { 177f03774bdSJohannes Thumshirn int rc = 0; 17812eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 17912eb4683SFrank Haverkamp void __iomem *mmio; 18012eb4683SFrank Haverkamp 18112eb4683SFrank Haverkamp if (cd->err_inject & GENWQE_INJECT_BUS_RESET_FAILURE) 18212eb4683SFrank Haverkamp return -EIO; 18312eb4683SFrank Haverkamp 18412eb4683SFrank Haverkamp mmio = cd->mmio; 18512eb4683SFrank Haverkamp cd->mmio = NULL; 18612eb4683SFrank Haverkamp pci_iounmap(pci_dev, mmio); 18712eb4683SFrank Haverkamp 188f03774bdSJohannes Thumshirn pci_release_mem_regions(pci_dev); 18912eb4683SFrank Haverkamp 19012eb4683SFrank Haverkamp /* 19112eb4683SFrank Haverkamp * Firmware/BIOS might change memory mapping during bus reset. 19212eb4683SFrank Haverkamp * Settings like enable bus-mastering, ... are backuped and 19312eb4683SFrank Haverkamp * restored by the pci_reset_function(). 19412eb4683SFrank Haverkamp */ 19512eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, "[%s] pci_reset function ...\n", __func__); 19612eb4683SFrank Haverkamp rc = pci_reset_function(pci_dev); 19712eb4683SFrank Haverkamp if (rc) { 19812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 19912eb4683SFrank Haverkamp "[%s] err: failed reset func (rc %d)\n", __func__, rc); 20012eb4683SFrank Haverkamp return rc; 20112eb4683SFrank Haverkamp } 20212eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, "[%s] done with rc=%d\n", __func__, rc); 20312eb4683SFrank Haverkamp 20412eb4683SFrank Haverkamp /* 20512eb4683SFrank Haverkamp * Here is the right spot to clear the register read 20612eb4683SFrank Haverkamp * failure. pci_bus_reset() does this job in real systems. 20712eb4683SFrank Haverkamp */ 20812eb4683SFrank Haverkamp cd->err_inject &= ~(GENWQE_INJECT_HARDWARE_FAILURE | 20912eb4683SFrank Haverkamp GENWQE_INJECT_GFIR_FATAL | 21012eb4683SFrank Haverkamp GENWQE_INJECT_GFIR_INFO); 21112eb4683SFrank Haverkamp 212f03774bdSJohannes Thumshirn rc = pci_request_mem_regions(pci_dev, genwqe_driver_name); 21312eb4683SFrank Haverkamp if (rc) { 21412eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 21512eb4683SFrank Haverkamp "[%s] err: request bars failed (%d)\n", __func__, rc); 21612eb4683SFrank Haverkamp return -EIO; 21712eb4683SFrank Haverkamp } 21812eb4683SFrank Haverkamp 21912eb4683SFrank Haverkamp cd->mmio = pci_iomap(pci_dev, 0, 0); 22012eb4683SFrank Haverkamp if (cd->mmio == NULL) { 22112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 22212eb4683SFrank Haverkamp "[%s] err: mapping BAR0 failed\n", __func__); 22312eb4683SFrank Haverkamp return -ENOMEM; 22412eb4683SFrank Haverkamp } 22512eb4683SFrank Haverkamp return 0; 22612eb4683SFrank Haverkamp } 22712eb4683SFrank Haverkamp 22812eb4683SFrank Haverkamp /* 22912eb4683SFrank Haverkamp * Hardware circumvention section. Certain bitstreams in our test-lab 23012eb4683SFrank Haverkamp * had different kinds of problems. Here is where we adjust those 23112eb4683SFrank Haverkamp * bitstreams to function will with this version of our device driver. 23212eb4683SFrank Haverkamp * 23312eb4683SFrank Haverkamp * Thise circumventions are applied to the physical function only. 23412eb4683SFrank Haverkamp * The magical numbers below are identifying development/manufacturing 23512eb4683SFrank Haverkamp * versions of the bitstream used on the card. 23612eb4683SFrank Haverkamp * 23712eb4683SFrank Haverkamp * Turn off error reporting for old/manufacturing images. 23812eb4683SFrank Haverkamp */ 23912eb4683SFrank Haverkamp 24012eb4683SFrank Haverkamp bool genwqe_need_err_masking(struct genwqe_dev *cd) 24112eb4683SFrank Haverkamp { 24212eb4683SFrank Haverkamp return (cd->slu_unitcfg & 0xFFFF0ull) < 0x32170ull; 24312eb4683SFrank Haverkamp } 24412eb4683SFrank Haverkamp 24512eb4683SFrank Haverkamp static void genwqe_tweak_hardware(struct genwqe_dev *cd) 24612eb4683SFrank Haverkamp { 24712eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 24812eb4683SFrank Haverkamp 24912eb4683SFrank Haverkamp /* Mask FIRs for development images */ 25012eb4683SFrank Haverkamp if (((cd->slu_unitcfg & 0xFFFF0ull) >= 0x32000ull) && 25112eb4683SFrank Haverkamp ((cd->slu_unitcfg & 0xFFFF0ull) <= 0x33250ull)) { 25212eb4683SFrank Haverkamp dev_warn(&pci_dev->dev, 25312eb4683SFrank Haverkamp "FIRs masked due to bitstream %016llx.%016llx\n", 25412eb4683SFrank Haverkamp cd->slu_unitcfg, cd->app_unitcfg); 25512eb4683SFrank Haverkamp 25612eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_APP_SEC_LEM_DEBUG_OVR, 25712eb4683SFrank Haverkamp 0xFFFFFFFFFFFFFFFFull); 25812eb4683SFrank Haverkamp 25912eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_APP_ERR_ACT_MASK, 26012eb4683SFrank Haverkamp 0x0000000000000000ull); 26112eb4683SFrank Haverkamp } 26212eb4683SFrank Haverkamp } 26312eb4683SFrank Haverkamp 26412eb4683SFrank Haverkamp /** 26512eb4683SFrank Haverkamp * genwqe_recovery_on_fatal_gfir_required() - Version depended actions 266a562c0c3SLee Jones * @cd: GenWQE device information 26712eb4683SFrank Haverkamp * 26812eb4683SFrank Haverkamp * Bitstreams older than 2013-02-17 have a bug where fatal GFIRs must 26912eb4683SFrank Haverkamp * be ignored. This is e.g. true for the bitstream we gave to the card 27012eb4683SFrank Haverkamp * manufacturer, but also for some old bitstreams we released to our 27112eb4683SFrank Haverkamp * test-lab. 27212eb4683SFrank Haverkamp */ 27312eb4683SFrank Haverkamp int genwqe_recovery_on_fatal_gfir_required(struct genwqe_dev *cd) 27412eb4683SFrank Haverkamp { 27512eb4683SFrank Haverkamp return (cd->slu_unitcfg & 0xFFFF0ull) >= 0x32170ull; 27612eb4683SFrank Haverkamp } 27712eb4683SFrank Haverkamp 27812eb4683SFrank Haverkamp int genwqe_flash_readback_fails(struct genwqe_dev *cd) 27912eb4683SFrank Haverkamp { 28012eb4683SFrank Haverkamp return (cd->slu_unitcfg & 0xFFFF0ull) < 0x32170ull; 28112eb4683SFrank Haverkamp } 28212eb4683SFrank Haverkamp 28312eb4683SFrank Haverkamp /** 28412eb4683SFrank Haverkamp * genwqe_T_psec() - Calculate PF/VF timeout register content 285a562c0c3SLee Jones * @cd: GenWQE device information 28612eb4683SFrank Haverkamp * 28712eb4683SFrank Haverkamp * Note: From a design perspective it turned out to be a bad idea to 28812eb4683SFrank Haverkamp * use codes here to specifiy the frequency/speed values. An old 28912eb4683SFrank Haverkamp * driver cannot understand new codes and is therefore always a 29012eb4683SFrank Haverkamp * problem. Better is to measure out the value or put the 29112eb4683SFrank Haverkamp * speed/frequency directly into a register which is always a valid 29212eb4683SFrank Haverkamp * value for old as well as for new software. 29312eb4683SFrank Haverkamp */ 29412eb4683SFrank Haverkamp /* T = 1/f */ 29512eb4683SFrank Haverkamp static int genwqe_T_psec(struct genwqe_dev *cd) 29612eb4683SFrank Haverkamp { 29712eb4683SFrank Haverkamp u16 speed; /* 1/f -> 250, 200, 166, 175 */ 29812eb4683SFrank Haverkamp static const int T[] = { 4000, 5000, 6000, 5714 }; 29912eb4683SFrank Haverkamp 30012eb4683SFrank Haverkamp speed = (u16)((cd->slu_unitcfg >> 28) & 0x0full); 30112eb4683SFrank Haverkamp if (speed >= ARRAY_SIZE(T)) 30212eb4683SFrank Haverkamp return -1; /* illegal value */ 30312eb4683SFrank Haverkamp 30412eb4683SFrank Haverkamp return T[speed]; 30512eb4683SFrank Haverkamp } 30612eb4683SFrank Haverkamp 30712eb4683SFrank Haverkamp /** 30812eb4683SFrank Haverkamp * genwqe_setup_pf_jtimer() - Setup PF hardware timeouts for DDCB execution 309a562c0c3SLee Jones * @cd: GenWQE device information 31012eb4683SFrank Haverkamp * 31112eb4683SFrank Haverkamp * Do this _after_ card_reset() is called. Otherwise the values will 31212eb4683SFrank Haverkamp * vanish. The settings need to be done when the queues are inactive. 31312eb4683SFrank Haverkamp * 31412eb4683SFrank Haverkamp * The max. timeout value is 2^(10+x) * T (6ns for 166MHz) * 15/16. 31512eb4683SFrank Haverkamp * The min. timeout value is 2^(10+x) * T (6ns for 166MHz) * 14/16. 31612eb4683SFrank Haverkamp */ 31712eb4683SFrank Haverkamp static bool genwqe_setup_pf_jtimer(struct genwqe_dev *cd) 31812eb4683SFrank Haverkamp { 31912eb4683SFrank Haverkamp u32 T = genwqe_T_psec(cd); 32012eb4683SFrank Haverkamp u64 x; 32112eb4683SFrank Haverkamp 3229d14e766SGuilherme G. Piccoli if (GENWQE_PF_JOBTIMEOUT_MSEC == 0) 32312eb4683SFrank Haverkamp return false; 32412eb4683SFrank Haverkamp 32512eb4683SFrank Haverkamp /* PF: large value needed, flash update 2sec per block */ 3269d14e766SGuilherme G. Piccoli x = ilog2(GENWQE_PF_JOBTIMEOUT_MSEC * 32712eb4683SFrank Haverkamp 16000000000uL/(T * 15)) - 10; 32812eb4683SFrank Haverkamp 32912eb4683SFrank Haverkamp genwqe_write_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 33012eb4683SFrank Haverkamp 0xff00 | (x & 0xff), 0); 33112eb4683SFrank Haverkamp return true; 33212eb4683SFrank Haverkamp } 33312eb4683SFrank Haverkamp 33412eb4683SFrank Haverkamp /** 33512eb4683SFrank Haverkamp * genwqe_setup_vf_jtimer() - Setup VF hardware timeouts for DDCB execution 336a562c0c3SLee Jones * @cd: GenWQE device information 33712eb4683SFrank Haverkamp */ 33812eb4683SFrank Haverkamp static bool genwqe_setup_vf_jtimer(struct genwqe_dev *cd) 33912eb4683SFrank Haverkamp { 34012eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 34112eb4683SFrank Haverkamp unsigned int vf; 34212eb4683SFrank Haverkamp u32 T = genwqe_T_psec(cd); 34312eb4683SFrank Haverkamp u64 x; 34495a8825cSFrank Haverkamp int totalvfs; 34512eb4683SFrank Haverkamp 34695a8825cSFrank Haverkamp totalvfs = pci_sriov_get_totalvfs(pci_dev); 34795a8825cSFrank Haverkamp if (totalvfs <= 0) 34895a8825cSFrank Haverkamp return false; 34995a8825cSFrank Haverkamp 35095a8825cSFrank Haverkamp for (vf = 0; vf < totalvfs; vf++) { 35112eb4683SFrank Haverkamp 35212eb4683SFrank Haverkamp if (cd->vf_jobtimeout_msec[vf] == 0) 35312eb4683SFrank Haverkamp continue; 35412eb4683SFrank Haverkamp 35512eb4683SFrank Haverkamp x = ilog2(cd->vf_jobtimeout_msec[vf] * 35612eb4683SFrank Haverkamp 16000000000uL/(T * 15)) - 10; 35712eb4683SFrank Haverkamp 35812eb4683SFrank Haverkamp genwqe_write_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 35912eb4683SFrank Haverkamp 0xff00 | (x & 0xff), vf + 1); 36012eb4683SFrank Haverkamp } 36112eb4683SFrank Haverkamp return true; 36212eb4683SFrank Haverkamp } 36312eb4683SFrank Haverkamp 36412eb4683SFrank Haverkamp static int genwqe_ffdc_buffs_alloc(struct genwqe_dev *cd) 36512eb4683SFrank Haverkamp { 36612eb4683SFrank Haverkamp unsigned int type, e = 0; 36712eb4683SFrank Haverkamp 36812eb4683SFrank Haverkamp for (type = 0; type < GENWQE_DBG_UNITS; type++) { 36912eb4683SFrank Haverkamp switch (type) { 37012eb4683SFrank Haverkamp case GENWQE_DBG_UNIT0: 37112eb4683SFrank Haverkamp e = genwqe_ffdc_buff_size(cd, 0); 37212eb4683SFrank Haverkamp break; 37312eb4683SFrank Haverkamp case GENWQE_DBG_UNIT1: 37412eb4683SFrank Haverkamp e = genwqe_ffdc_buff_size(cd, 1); 37512eb4683SFrank Haverkamp break; 37612eb4683SFrank Haverkamp case GENWQE_DBG_UNIT2: 37712eb4683SFrank Haverkamp e = genwqe_ffdc_buff_size(cd, 2); 37812eb4683SFrank Haverkamp break; 37912eb4683SFrank Haverkamp case GENWQE_DBG_REGS: 38012eb4683SFrank Haverkamp e = GENWQE_FFDC_REGS; 38112eb4683SFrank Haverkamp break; 38212eb4683SFrank Haverkamp } 38312eb4683SFrank Haverkamp 38412eb4683SFrank Haverkamp /* currently support only the debug units mentioned here */ 38512eb4683SFrank Haverkamp cd->ffdc[type].entries = e; 386d9c11d45SFrank Haverkamp cd->ffdc[type].regs = 387d9c11d45SFrank Haverkamp kmalloc_array(e, sizeof(struct genwqe_reg), 38812eb4683SFrank Haverkamp GFP_KERNEL); 38912eb4683SFrank Haverkamp /* 39012eb4683SFrank Haverkamp * regs == NULL is ok, the using code treats this as no regs, 39112eb4683SFrank Haverkamp * Printing warning is ok in this case. 39212eb4683SFrank Haverkamp */ 39312eb4683SFrank Haverkamp } 39412eb4683SFrank Haverkamp return 0; 39512eb4683SFrank Haverkamp } 39612eb4683SFrank Haverkamp 39712eb4683SFrank Haverkamp static void genwqe_ffdc_buffs_free(struct genwqe_dev *cd) 39812eb4683SFrank Haverkamp { 39912eb4683SFrank Haverkamp unsigned int type; 40012eb4683SFrank Haverkamp 40112eb4683SFrank Haverkamp for (type = 0; type < GENWQE_DBG_UNITS; type++) { 40212eb4683SFrank Haverkamp kfree(cd->ffdc[type].regs); 40312eb4683SFrank Haverkamp cd->ffdc[type].regs = NULL; 40412eb4683SFrank Haverkamp } 40512eb4683SFrank Haverkamp } 40612eb4683SFrank Haverkamp 40712eb4683SFrank Haverkamp static int genwqe_read_ids(struct genwqe_dev *cd) 40812eb4683SFrank Haverkamp { 40912eb4683SFrank Haverkamp int err = 0; 41012eb4683SFrank Haverkamp int slu_id; 41112eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 41212eb4683SFrank Haverkamp 41312eb4683SFrank Haverkamp cd->slu_unitcfg = __genwqe_readq(cd, IO_SLU_UNITCFG); 41412eb4683SFrank Haverkamp if (cd->slu_unitcfg == IO_ILLEGAL_VALUE) { 41512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 41612eb4683SFrank Haverkamp "err: SLUID=%016llx\n", cd->slu_unitcfg); 41712eb4683SFrank Haverkamp err = -EIO; 41812eb4683SFrank Haverkamp goto out_err; 41912eb4683SFrank Haverkamp } 42012eb4683SFrank Haverkamp 42112eb4683SFrank Haverkamp slu_id = genwqe_get_slu_id(cd); 42212eb4683SFrank Haverkamp if (slu_id < GENWQE_SLU_ARCH_REQ || slu_id == 0xff) { 42312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 42412eb4683SFrank Haverkamp "err: incompatible SLU Architecture %u\n", slu_id); 42512eb4683SFrank Haverkamp err = -ENOENT; 42612eb4683SFrank Haverkamp goto out_err; 42712eb4683SFrank Haverkamp } 42812eb4683SFrank Haverkamp 42912eb4683SFrank Haverkamp cd->app_unitcfg = __genwqe_readq(cd, IO_APP_UNITCFG); 43012eb4683SFrank Haverkamp if (cd->app_unitcfg == IO_ILLEGAL_VALUE) { 43112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 43212eb4683SFrank Haverkamp "err: APPID=%016llx\n", cd->app_unitcfg); 43312eb4683SFrank Haverkamp err = -EIO; 43412eb4683SFrank Haverkamp goto out_err; 43512eb4683SFrank Haverkamp } 43612eb4683SFrank Haverkamp genwqe_read_app_id(cd, cd->app_name, sizeof(cd->app_name)); 43712eb4683SFrank Haverkamp 43812eb4683SFrank Haverkamp /* 43912eb4683SFrank Haverkamp * Is access to all registers possible? If we are a VF the 44012eb4683SFrank Haverkamp * answer is obvious. If we run fully virtualized, we need to 44112eb4683SFrank Haverkamp * check if we can access all registers. If we do not have 44212eb4683SFrank Haverkamp * full access we will cause an UR and some informational FIRs 44312eb4683SFrank Haverkamp * in the PF, but that should not harm. 44412eb4683SFrank Haverkamp */ 44512eb4683SFrank Haverkamp if (pci_dev->is_virtfn) 44612eb4683SFrank Haverkamp cd->is_privileged = 0; 44712eb4683SFrank Haverkamp else 44812eb4683SFrank Haverkamp cd->is_privileged = (__genwqe_readq(cd, IO_SLU_BITSTREAM) 44912eb4683SFrank Haverkamp != IO_ILLEGAL_VALUE); 45012eb4683SFrank Haverkamp 45112eb4683SFrank Haverkamp out_err: 45212eb4683SFrank Haverkamp return err; 45312eb4683SFrank Haverkamp } 45412eb4683SFrank Haverkamp 45512eb4683SFrank Haverkamp static int genwqe_start(struct genwqe_dev *cd) 45612eb4683SFrank Haverkamp { 45712eb4683SFrank Haverkamp int err; 45812eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 45912eb4683SFrank Haverkamp 46012eb4683SFrank Haverkamp err = genwqe_read_ids(cd); 46112eb4683SFrank Haverkamp if (err) 46212eb4683SFrank Haverkamp return err; 46312eb4683SFrank Haverkamp 46412eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { 46512eb4683SFrank Haverkamp /* do this after the tweaks. alloc fail is acceptable */ 46612eb4683SFrank Haverkamp genwqe_ffdc_buffs_alloc(cd); 46712eb4683SFrank Haverkamp genwqe_stop_traps(cd); 46812eb4683SFrank Haverkamp 46912eb4683SFrank Haverkamp /* Collect registers e.g. FIRs, UNITIDs, traces ... */ 47012eb4683SFrank Haverkamp genwqe_read_ffdc_regs(cd, cd->ffdc[GENWQE_DBG_REGS].regs, 47112eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_REGS].entries, 0); 47212eb4683SFrank Haverkamp 47312eb4683SFrank Haverkamp genwqe_ffdc_buff_read(cd, GENWQE_DBG_UNIT0, 47412eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT0].regs, 47512eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT0].entries); 47612eb4683SFrank Haverkamp 47712eb4683SFrank Haverkamp genwqe_ffdc_buff_read(cd, GENWQE_DBG_UNIT1, 47812eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT1].regs, 47912eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT1].entries); 48012eb4683SFrank Haverkamp 48112eb4683SFrank Haverkamp genwqe_ffdc_buff_read(cd, GENWQE_DBG_UNIT2, 48212eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT2].regs, 48312eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT2].entries); 48412eb4683SFrank Haverkamp 48512eb4683SFrank Haverkamp genwqe_start_traps(cd); 48612eb4683SFrank Haverkamp 48712eb4683SFrank Haverkamp if (cd->card_state == GENWQE_CARD_FATAL_ERROR) { 48812eb4683SFrank Haverkamp dev_warn(&pci_dev->dev, 48912eb4683SFrank Haverkamp "[%s] chip reload/recovery!\n", __func__); 49012eb4683SFrank Haverkamp 49112eb4683SFrank Haverkamp /* 49212eb4683SFrank Haverkamp * Stealth Mode: Reload chip on either hot 49312eb4683SFrank Haverkamp * reset or PERST. 49412eb4683SFrank Haverkamp */ 49512eb4683SFrank Haverkamp cd->softreset = 0x7Cull; 49612eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, 49712eb4683SFrank Haverkamp cd->softreset); 49812eb4683SFrank Haverkamp 49912eb4683SFrank Haverkamp err = genwqe_bus_reset(cd); 50012eb4683SFrank Haverkamp if (err != 0) { 50112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 50212eb4683SFrank Haverkamp "[%s] err: bus reset failed!\n", 50312eb4683SFrank Haverkamp __func__); 50412eb4683SFrank Haverkamp goto out; 50512eb4683SFrank Haverkamp } 50612eb4683SFrank Haverkamp 50712eb4683SFrank Haverkamp /* 50812eb4683SFrank Haverkamp * Re-read the IDs because 50912eb4683SFrank Haverkamp * it could happen that the bitstream load 51012eb4683SFrank Haverkamp * failed! 51112eb4683SFrank Haverkamp */ 51212eb4683SFrank Haverkamp err = genwqe_read_ids(cd); 51312eb4683SFrank Haverkamp if (err) 51412eb4683SFrank Haverkamp goto out; 51512eb4683SFrank Haverkamp } 51612eb4683SFrank Haverkamp } 51712eb4683SFrank Haverkamp 51812eb4683SFrank Haverkamp err = genwqe_setup_service_layer(cd); /* does a reset to the card */ 51912eb4683SFrank Haverkamp if (err != 0) { 52012eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 52112eb4683SFrank Haverkamp "[%s] err: could not setup servicelayer!\n", __func__); 52212eb4683SFrank Haverkamp err = -ENODEV; 52312eb4683SFrank Haverkamp goto out; 52412eb4683SFrank Haverkamp } 52512eb4683SFrank Haverkamp 52612eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { /* code is running _after_ reset */ 52712eb4683SFrank Haverkamp genwqe_tweak_hardware(cd); 52812eb4683SFrank Haverkamp 52912eb4683SFrank Haverkamp genwqe_setup_pf_jtimer(cd); 53012eb4683SFrank Haverkamp genwqe_setup_vf_jtimer(cd); 53112eb4683SFrank Haverkamp } 53212eb4683SFrank Haverkamp 53312eb4683SFrank Haverkamp err = genwqe_device_create(cd); 53412eb4683SFrank Haverkamp if (err < 0) { 53512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 53612eb4683SFrank Haverkamp "err: chdev init failed! (err=%d)\n", err); 53712eb4683SFrank Haverkamp goto out_release_service_layer; 53812eb4683SFrank Haverkamp } 53912eb4683SFrank Haverkamp return 0; 54012eb4683SFrank Haverkamp 54112eb4683SFrank Haverkamp out_release_service_layer: 54212eb4683SFrank Haverkamp genwqe_release_service_layer(cd); 54312eb4683SFrank Haverkamp out: 54412eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) 54512eb4683SFrank Haverkamp genwqe_ffdc_buffs_free(cd); 54612eb4683SFrank Haverkamp return -EIO; 54712eb4683SFrank Haverkamp } 54812eb4683SFrank Haverkamp 54912eb4683SFrank Haverkamp /** 55012eb4683SFrank Haverkamp * genwqe_stop() - Stop card operation 551a562c0c3SLee Jones * @cd: GenWQE device information 55212eb4683SFrank Haverkamp * 55312eb4683SFrank Haverkamp * Recovery notes: 55412eb4683SFrank Haverkamp * As long as genwqe_thread runs we might access registers during 55512eb4683SFrank Haverkamp * error data capture. Same is with the genwqe_health_thread. 55612eb4683SFrank Haverkamp * When genwqe_bus_reset() fails this function might called two times: 55712eb4683SFrank Haverkamp * first by the genwqe_health_thread() and later by genwqe_remove() to 55812eb4683SFrank Haverkamp * unbind the device. We must be able to survive that. 55912eb4683SFrank Haverkamp * 56012eb4683SFrank Haverkamp * This function must be robust enough to be called twice. 56112eb4683SFrank Haverkamp */ 56212eb4683SFrank Haverkamp static int genwqe_stop(struct genwqe_dev *cd) 56312eb4683SFrank Haverkamp { 56412eb4683SFrank Haverkamp genwqe_finish_queue(cd); /* no register access */ 56512eb4683SFrank Haverkamp genwqe_device_remove(cd); /* device removed, procs killed */ 56612eb4683SFrank Haverkamp genwqe_release_service_layer(cd); /* here genwqe_thread is stopped */ 56712eb4683SFrank Haverkamp 56812eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { 56912eb4683SFrank Haverkamp pci_disable_sriov(cd->pci_dev); /* access pci config space */ 57012eb4683SFrank Haverkamp genwqe_ffdc_buffs_free(cd); 57112eb4683SFrank Haverkamp } 57212eb4683SFrank Haverkamp 57312eb4683SFrank Haverkamp return 0; 57412eb4683SFrank Haverkamp } 57512eb4683SFrank Haverkamp 57612eb4683SFrank Haverkamp /** 57712eb4683SFrank Haverkamp * genwqe_recover_card() - Try to recover the card if it is possible 578f5721c7aSLee Jones * @cd: GenWQE device information 579f5721c7aSLee Jones * @fatal_err: Indicate whether to attempt soft reset 58012eb4683SFrank Haverkamp * 58112eb4683SFrank Haverkamp * If fatal_err is set no register access is possible anymore. It is 58212eb4683SFrank Haverkamp * likely that genwqe_start fails in that situation. Proper error 58312eb4683SFrank Haverkamp * handling is required in this case. 58412eb4683SFrank Haverkamp * 58512eb4683SFrank Haverkamp * genwqe_bus_reset() will cause the pci code to call genwqe_remove() 58612eb4683SFrank Haverkamp * and later genwqe_probe() for all virtual functions. 58712eb4683SFrank Haverkamp */ 58812eb4683SFrank Haverkamp static int genwqe_recover_card(struct genwqe_dev *cd, int fatal_err) 58912eb4683SFrank Haverkamp { 59012eb4683SFrank Haverkamp int rc; 59112eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 59212eb4683SFrank Haverkamp 59312eb4683SFrank Haverkamp genwqe_stop(cd); 59412eb4683SFrank Haverkamp 59512eb4683SFrank Haverkamp /* 59612eb4683SFrank Haverkamp * Make sure chip is not reloaded to maintain FFDC. Write SLU 59712eb4683SFrank Haverkamp * Reset Register, CPLDReset field to 0. 59812eb4683SFrank Haverkamp */ 59912eb4683SFrank Haverkamp if (!fatal_err) { 60012eb4683SFrank Haverkamp cd->softreset = 0x70ull; 60112eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, cd->softreset); 60212eb4683SFrank Haverkamp } 60312eb4683SFrank Haverkamp 60412eb4683SFrank Haverkamp rc = genwqe_bus_reset(cd); 60512eb4683SFrank Haverkamp if (rc != 0) { 60612eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 60712eb4683SFrank Haverkamp "[%s] err: card recovery impossible!\n", __func__); 60812eb4683SFrank Haverkamp return rc; 60912eb4683SFrank Haverkamp } 61012eb4683SFrank Haverkamp 61112eb4683SFrank Haverkamp rc = genwqe_start(cd); 61212eb4683SFrank Haverkamp if (rc < 0) { 61312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 61412eb4683SFrank Haverkamp "[%s] err: failed to launch device!\n", __func__); 61512eb4683SFrank Haverkamp return rc; 61612eb4683SFrank Haverkamp } 61712eb4683SFrank Haverkamp return 0; 61812eb4683SFrank Haverkamp } 61912eb4683SFrank Haverkamp 62012eb4683SFrank Haverkamp static int genwqe_health_check_cond(struct genwqe_dev *cd, u64 *gfir) 62112eb4683SFrank Haverkamp { 62212eb4683SFrank Haverkamp *gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 62312eb4683SFrank Haverkamp return (*gfir & GFIR_ERR_TRIGGER) && 62412eb4683SFrank Haverkamp genwqe_recovery_on_fatal_gfir_required(cd); 62512eb4683SFrank Haverkamp } 62612eb4683SFrank Haverkamp 62712eb4683SFrank Haverkamp /** 62812eb4683SFrank Haverkamp * genwqe_fir_checking() - Check the fault isolation registers of the card 629a562c0c3SLee Jones * @cd: GenWQE device information 63012eb4683SFrank Haverkamp * 63112eb4683SFrank Haverkamp * If this code works ok, can be tried out with help of the genwqe_poke tool: 63212eb4683SFrank Haverkamp * sudo ./tools/genwqe_poke 0x8 0xfefefefefef 63312eb4683SFrank Haverkamp * 63412eb4683SFrank Haverkamp * Now the relevant FIRs/sFIRs should be printed out and the driver should 63512eb4683SFrank Haverkamp * invoke recovery (devices are removed and readded). 63612eb4683SFrank Haverkamp */ 63712eb4683SFrank Haverkamp static u64 genwqe_fir_checking(struct genwqe_dev *cd) 63812eb4683SFrank Haverkamp { 63912eb4683SFrank Haverkamp int j, iterations = 0; 64012eb4683SFrank Haverkamp u64 mask, fir, fec, uid, gfir, gfir_masked, sfir, sfec; 64112eb4683SFrank Haverkamp u32 fir_addr, fir_clr_addr, fec_addr, sfir_addr, sfec_addr; 64212eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 64312eb4683SFrank Haverkamp 64412eb4683SFrank Haverkamp healthMonitor: 64512eb4683SFrank Haverkamp iterations++; 64612eb4683SFrank Haverkamp if (iterations > 16) { 64712eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* exit looping after %d times\n", 64812eb4683SFrank Haverkamp iterations); 64912eb4683SFrank Haverkamp goto fatal_error; 65012eb4683SFrank Haverkamp } 65112eb4683SFrank Haverkamp 65212eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 65312eb4683SFrank Haverkamp if (gfir != 0x0) 65412eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* 0x%08x 0x%016llx\n", 65512eb4683SFrank Haverkamp IO_SLC_CFGREG_GFIR, gfir); 65612eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) 65712eb4683SFrank Haverkamp goto fatal_error; 65812eb4683SFrank Haverkamp 65912eb4683SFrank Haverkamp /* 66012eb4683SFrank Haverkamp * Avoid printing when to GFIR bit is on prevents contignous 66112eb4683SFrank Haverkamp * printout e.g. for the following bug: 66212eb4683SFrank Haverkamp * FIR set without a 2ndary FIR/FIR cannot be cleared 66312eb4683SFrank Haverkamp * Comment out the following if to get the prints: 66412eb4683SFrank Haverkamp */ 66512eb4683SFrank Haverkamp if (gfir == 0) 66612eb4683SFrank Haverkamp return 0; 66712eb4683SFrank Haverkamp 66812eb4683SFrank Haverkamp gfir_masked = gfir & GFIR_ERR_TRIGGER; /* fatal errors */ 66912eb4683SFrank Haverkamp 67012eb4683SFrank Haverkamp for (uid = 0; uid < GENWQE_MAX_UNITS; uid++) { /* 0..2 in zEDC */ 67112eb4683SFrank Haverkamp 67212eb4683SFrank Haverkamp /* read the primary FIR (pfir) */ 67312eb4683SFrank Haverkamp fir_addr = (uid << 24) + 0x08; 67412eb4683SFrank Haverkamp fir = __genwqe_readq(cd, fir_addr); 67512eb4683SFrank Haverkamp if (fir == 0x0) 67612eb4683SFrank Haverkamp continue; /* no error in this unit */ 67712eb4683SFrank Haverkamp 67812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* 0x%08x 0x%016llx\n", fir_addr, fir); 67912eb4683SFrank Haverkamp if (fir == IO_ILLEGAL_VALUE) 68012eb4683SFrank Haverkamp goto fatal_error; 68112eb4683SFrank Haverkamp 68212eb4683SFrank Haverkamp /* read primary FEC */ 68312eb4683SFrank Haverkamp fec_addr = (uid << 24) + 0x18; 68412eb4683SFrank Haverkamp fec = __genwqe_readq(cd, fec_addr); 68512eb4683SFrank Haverkamp 68612eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* 0x%08x 0x%016llx\n", fec_addr, fec); 68712eb4683SFrank Haverkamp if (fec == IO_ILLEGAL_VALUE) 68812eb4683SFrank Haverkamp goto fatal_error; 68912eb4683SFrank Haverkamp 69012eb4683SFrank Haverkamp for (j = 0, mask = 1ULL; j < 64; j++, mask <<= 1) { 69112eb4683SFrank Haverkamp 69212eb4683SFrank Haverkamp /* secondary fir empty, skip it */ 69312eb4683SFrank Haverkamp if ((fir & mask) == 0x0) 69412eb4683SFrank Haverkamp continue; 69512eb4683SFrank Haverkamp 69612eb4683SFrank Haverkamp sfir_addr = (uid << 24) + 0x100 + 0x08 * j; 69712eb4683SFrank Haverkamp sfir = __genwqe_readq(cd, sfir_addr); 69812eb4683SFrank Haverkamp 69912eb4683SFrank Haverkamp if (sfir == IO_ILLEGAL_VALUE) 70012eb4683SFrank Haverkamp goto fatal_error; 70112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 70212eb4683SFrank Haverkamp "* 0x%08x 0x%016llx\n", sfir_addr, sfir); 70312eb4683SFrank Haverkamp 70412eb4683SFrank Haverkamp sfec_addr = (uid << 24) + 0x300 + 0x08 * j; 70512eb4683SFrank Haverkamp sfec = __genwqe_readq(cd, sfec_addr); 70612eb4683SFrank Haverkamp 70712eb4683SFrank Haverkamp if (sfec == IO_ILLEGAL_VALUE) 70812eb4683SFrank Haverkamp goto fatal_error; 70912eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 71012eb4683SFrank Haverkamp "* 0x%08x 0x%016llx\n", sfec_addr, sfec); 71112eb4683SFrank Haverkamp 71212eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 71312eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) 71412eb4683SFrank Haverkamp goto fatal_error; 71512eb4683SFrank Haverkamp 71612eb4683SFrank Haverkamp /* gfir turned on during routine! get out and 71712eb4683SFrank Haverkamp start over. */ 71812eb4683SFrank Haverkamp if ((gfir_masked == 0x0) && 71912eb4683SFrank Haverkamp (gfir & GFIR_ERR_TRIGGER)) { 72012eb4683SFrank Haverkamp goto healthMonitor; 72112eb4683SFrank Haverkamp } 72212eb4683SFrank Haverkamp 72312eb4683SFrank Haverkamp /* do not clear if we entered with a fatal gfir */ 72412eb4683SFrank Haverkamp if (gfir_masked == 0x0) { 72512eb4683SFrank Haverkamp 72612eb4683SFrank Haverkamp /* NEW clear by mask the logged bits */ 72712eb4683SFrank Haverkamp sfir_addr = (uid << 24) + 0x100 + 0x08 * j; 72812eb4683SFrank Haverkamp __genwqe_writeq(cd, sfir_addr, sfir); 72912eb4683SFrank Haverkamp 73012eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, 731d9c11d45SFrank Haverkamp "[HM] Clearing 2ndary FIR 0x%08x with 0x%016llx\n", 732d9c11d45SFrank Haverkamp sfir_addr, sfir); 73312eb4683SFrank Haverkamp 73412eb4683SFrank Haverkamp /* 73512eb4683SFrank Haverkamp * note, these cannot be error-Firs 73612eb4683SFrank Haverkamp * since gfir_masked is 0 after sfir 73712eb4683SFrank Haverkamp * was read. Also, it is safe to do 73812eb4683SFrank Haverkamp * this write if sfir=0. Still need to 73912eb4683SFrank Haverkamp * clear the primary. This just means 74012eb4683SFrank Haverkamp * there is no secondary FIR. 74112eb4683SFrank Haverkamp */ 74212eb4683SFrank Haverkamp 74312eb4683SFrank Haverkamp /* clear by mask the logged bit. */ 74412eb4683SFrank Haverkamp fir_clr_addr = (uid << 24) + 0x10; 74512eb4683SFrank Haverkamp __genwqe_writeq(cd, fir_clr_addr, mask); 74612eb4683SFrank Haverkamp 74712eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, 748d9c11d45SFrank Haverkamp "[HM] Clearing primary FIR 0x%08x with 0x%016llx\n", 749d9c11d45SFrank Haverkamp fir_clr_addr, mask); 75012eb4683SFrank Haverkamp } 75112eb4683SFrank Haverkamp } 75212eb4683SFrank Haverkamp } 75312eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 75412eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) 75512eb4683SFrank Haverkamp goto fatal_error; 75612eb4683SFrank Haverkamp 75712eb4683SFrank Haverkamp if ((gfir_masked == 0x0) && (gfir & GFIR_ERR_TRIGGER)) { 75812eb4683SFrank Haverkamp /* 75912eb4683SFrank Haverkamp * Check once more that it didn't go on after all the 76012eb4683SFrank Haverkamp * FIRS were cleared. 76112eb4683SFrank Haverkamp */ 76212eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, "ACK! Another FIR! Recursing %d!\n", 76312eb4683SFrank Haverkamp iterations); 76412eb4683SFrank Haverkamp goto healthMonitor; 76512eb4683SFrank Haverkamp } 76612eb4683SFrank Haverkamp return gfir_masked; 76712eb4683SFrank Haverkamp 76812eb4683SFrank Haverkamp fatal_error: 76912eb4683SFrank Haverkamp return IO_ILLEGAL_VALUE; 77012eb4683SFrank Haverkamp } 77112eb4683SFrank Haverkamp 77212eb4683SFrank Haverkamp /** 773c1f732adSKleber Sacilotto de Souza * genwqe_pci_fundamental_reset() - trigger a PCIe fundamental reset on the slot 774a562c0c3SLee Jones * @pci_dev: PCI device information struct 775c1f732adSKleber Sacilotto de Souza * 776c1f732adSKleber Sacilotto de Souza * Note: pci_set_pcie_reset_state() is not implemented on all archs, so this 777c1f732adSKleber Sacilotto de Souza * reset method will not work in all cases. 778c1f732adSKleber Sacilotto de Souza * 779c1f732adSKleber Sacilotto de Souza * Return: 0 on success or error code from pci_set_pcie_reset_state() 780c1f732adSKleber Sacilotto de Souza */ 781c1f732adSKleber Sacilotto de Souza static int genwqe_pci_fundamental_reset(struct pci_dev *pci_dev) 782c1f732adSKleber Sacilotto de Souza { 783c1f732adSKleber Sacilotto de Souza int rc; 784c1f732adSKleber Sacilotto de Souza 785c1f732adSKleber Sacilotto de Souza /* 786c1f732adSKleber Sacilotto de Souza * lock pci config space access from userspace, 787c1f732adSKleber Sacilotto de Souza * save state and issue PCIe fundamental reset 788c1f732adSKleber Sacilotto de Souza */ 789c1f732adSKleber Sacilotto de Souza pci_cfg_access_lock(pci_dev); 790c1f732adSKleber Sacilotto de Souza pci_save_state(pci_dev); 791c1f732adSKleber Sacilotto de Souza rc = pci_set_pcie_reset_state(pci_dev, pcie_warm_reset); 792c1f732adSKleber Sacilotto de Souza if (!rc) { 793c1f732adSKleber Sacilotto de Souza /* keep PCIe reset asserted for 250ms */ 794c1f732adSKleber Sacilotto de Souza msleep(250); 795c1f732adSKleber Sacilotto de Souza pci_set_pcie_reset_state(pci_dev, pcie_deassert_reset); 796c1f732adSKleber Sacilotto de Souza /* Wait for 2s to reload flash and train the link */ 797c1f732adSKleber Sacilotto de Souza msleep(2000); 798c1f732adSKleber Sacilotto de Souza } 799c1f732adSKleber Sacilotto de Souza pci_restore_state(pci_dev); 800c1f732adSKleber Sacilotto de Souza pci_cfg_access_unlock(pci_dev); 801c1f732adSKleber Sacilotto de Souza return rc; 802c1f732adSKleber Sacilotto de Souza } 803c1f732adSKleber Sacilotto de Souza 80493b772b2SKleber Sacilotto de Souza 80593b772b2SKleber Sacilotto de Souza static int genwqe_platform_recovery(struct genwqe_dev *cd) 80693b772b2SKleber Sacilotto de Souza { 80793b772b2SKleber Sacilotto de Souza struct pci_dev *pci_dev = cd->pci_dev; 80893b772b2SKleber Sacilotto de Souza int rc; 80993b772b2SKleber Sacilotto de Souza 81093b772b2SKleber Sacilotto de Souza dev_info(&pci_dev->dev, 81193b772b2SKleber Sacilotto de Souza "[%s] resetting card for error recovery\n", __func__); 81293b772b2SKleber Sacilotto de Souza 81393b772b2SKleber Sacilotto de Souza /* Clear out error injection flags */ 81493b772b2SKleber Sacilotto de Souza cd->err_inject &= ~(GENWQE_INJECT_HARDWARE_FAILURE | 81593b772b2SKleber Sacilotto de Souza GENWQE_INJECT_GFIR_FATAL | 81693b772b2SKleber Sacilotto de Souza GENWQE_INJECT_GFIR_INFO); 81793b772b2SKleber Sacilotto de Souza 81893b772b2SKleber Sacilotto de Souza genwqe_stop(cd); 81993b772b2SKleber Sacilotto de Souza 82093b772b2SKleber Sacilotto de Souza /* Try recoverying the card with fundamental reset */ 82193b772b2SKleber Sacilotto de Souza rc = genwqe_pci_fundamental_reset(pci_dev); 82293b772b2SKleber Sacilotto de Souza if (!rc) { 82393b772b2SKleber Sacilotto de Souza rc = genwqe_start(cd); 82493b772b2SKleber Sacilotto de Souza if (!rc) 82593b772b2SKleber Sacilotto de Souza dev_info(&pci_dev->dev, 82693b772b2SKleber Sacilotto de Souza "[%s] card recovered\n", __func__); 82793b772b2SKleber Sacilotto de Souza else 82893b772b2SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 82993b772b2SKleber Sacilotto de Souza "[%s] err: cannot start card services! (err=%d)\n", 83093b772b2SKleber Sacilotto de Souza __func__, rc); 83193b772b2SKleber Sacilotto de Souza } else { 83293b772b2SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 83393b772b2SKleber Sacilotto de Souza "[%s] card reset failed\n", __func__); 83493b772b2SKleber Sacilotto de Souza } 83593b772b2SKleber Sacilotto de Souza 83693b772b2SKleber Sacilotto de Souza return rc; 83793b772b2SKleber Sacilotto de Souza } 83893b772b2SKleber Sacilotto de Souza 839a562c0c3SLee Jones /** 840c1f732adSKleber Sacilotto de Souza * genwqe_reload_bistream() - reload card bitstream 841a562c0c3SLee Jones * @cd: GenWQE device information 842c1f732adSKleber Sacilotto de Souza * 843c1f732adSKleber Sacilotto de Souza * Set the appropriate register and call fundamental reset to reaload the card 844c1f732adSKleber Sacilotto de Souza * bitstream. 845c1f732adSKleber Sacilotto de Souza * 846c1f732adSKleber Sacilotto de Souza * Return: 0 on success, error code otherwise 847c1f732adSKleber Sacilotto de Souza */ 848c1f732adSKleber Sacilotto de Souza static int genwqe_reload_bistream(struct genwqe_dev *cd) 849c1f732adSKleber Sacilotto de Souza { 850c1f732adSKleber Sacilotto de Souza struct pci_dev *pci_dev = cd->pci_dev; 851c1f732adSKleber Sacilotto de Souza int rc; 852c1f732adSKleber Sacilotto de Souza 853c1f732adSKleber Sacilotto de Souza dev_info(&pci_dev->dev, 854c1f732adSKleber Sacilotto de Souza "[%s] resetting card for bitstream reload\n", 855c1f732adSKleber Sacilotto de Souza __func__); 856c1f732adSKleber Sacilotto de Souza 857c1f732adSKleber Sacilotto de Souza genwqe_stop(cd); 858c1f732adSKleber Sacilotto de Souza 859c1f732adSKleber Sacilotto de Souza /* 860c1f732adSKleber Sacilotto de Souza * Cause a CPLD reprogram with the 'next_bitstream' 861c1f732adSKleber Sacilotto de Souza * partition on PCIe hot or fundamental reset 862c1f732adSKleber Sacilotto de Souza */ 863c1f732adSKleber Sacilotto de Souza __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, 864c1f732adSKleber Sacilotto de Souza (cd->softreset & 0xcull) | 0x70ull); 865c1f732adSKleber Sacilotto de Souza 866c1f732adSKleber Sacilotto de Souza rc = genwqe_pci_fundamental_reset(pci_dev); 867c1f732adSKleber Sacilotto de Souza if (rc) { 868c1f732adSKleber Sacilotto de Souza /* 869c1f732adSKleber Sacilotto de Souza * A fundamental reset failure can be caused 870c1f732adSKleber Sacilotto de Souza * by lack of support on the arch, so we just 871c1f732adSKleber Sacilotto de Souza * log the error and try to start the card 872c1f732adSKleber Sacilotto de Souza * again. 873c1f732adSKleber Sacilotto de Souza */ 874c1f732adSKleber Sacilotto de Souza dev_err(&pci_dev->dev, 875c1f732adSKleber Sacilotto de Souza "[%s] err: failed to reset card for bitstream reload\n", 876c1f732adSKleber Sacilotto de Souza __func__); 877c1f732adSKleber Sacilotto de Souza } 878c1f732adSKleber Sacilotto de Souza 879c1f732adSKleber Sacilotto de Souza rc = genwqe_start(cd); 880c1f732adSKleber Sacilotto de Souza if (rc) { 881c1f732adSKleber Sacilotto de Souza dev_err(&pci_dev->dev, 882c1f732adSKleber Sacilotto de Souza "[%s] err: cannot start card services! (err=%d)\n", 883c1f732adSKleber Sacilotto de Souza __func__, rc); 884c1f732adSKleber Sacilotto de Souza return rc; 885c1f732adSKleber Sacilotto de Souza } 886c1f732adSKleber Sacilotto de Souza dev_info(&pci_dev->dev, 887c1f732adSKleber Sacilotto de Souza "[%s] card reloaded\n", __func__); 888c1f732adSKleber Sacilotto de Souza return 0; 889c1f732adSKleber Sacilotto de Souza } 890c1f732adSKleber Sacilotto de Souza 891c1f732adSKleber Sacilotto de Souza 892c1f732adSKleber Sacilotto de Souza /** 89312eb4683SFrank Haverkamp * genwqe_health_thread() - Health checking thread 894a562c0c3SLee Jones * @data: GenWQE device information 89512eb4683SFrank Haverkamp * 89612eb4683SFrank Haverkamp * This thread is only started for the PF of the card. 89712eb4683SFrank Haverkamp * 89812eb4683SFrank Haverkamp * This thread monitors the health of the card. A critical situation 89912eb4683SFrank Haverkamp * is when we read registers which contain -1 (IO_ILLEGAL_VALUE). In 90012eb4683SFrank Haverkamp * this case we need to be recovered from outside. Writing to 90112eb4683SFrank Haverkamp * registers will very likely not work either. 90212eb4683SFrank Haverkamp * 90312eb4683SFrank Haverkamp * This thread must only exit if kthread_should_stop() becomes true. 90412eb4683SFrank Haverkamp * 90512eb4683SFrank Haverkamp * Condition for the health-thread to trigger: 90612eb4683SFrank Haverkamp * a) when a kthread_stop() request comes in or 90712eb4683SFrank Haverkamp * b) a critical GFIR occured 90812eb4683SFrank Haverkamp * 90912eb4683SFrank Haverkamp * Informational GFIRs are checked and potentially printed in 9109d14e766SGuilherme G. Piccoli * GENWQE_HEALTH_CHECK_INTERVAL seconds. 91112eb4683SFrank Haverkamp */ 91212eb4683SFrank Haverkamp static int genwqe_health_thread(void *data) 91312eb4683SFrank Haverkamp { 91412eb4683SFrank Haverkamp int rc, should_stop = 0; 91512eb4683SFrank Haverkamp struct genwqe_dev *cd = data; 91612eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 91712eb4683SFrank Haverkamp u64 gfir, gfir_masked, slu_unitcfg, app_unitcfg; 91812eb4683SFrank Haverkamp 91993b772b2SKleber Sacilotto de Souza health_thread_begin: 92012eb4683SFrank Haverkamp while (!kthread_should_stop()) { 92112eb4683SFrank Haverkamp rc = wait_event_interruptible_timeout(cd->health_waitq, 92212eb4683SFrank Haverkamp (genwqe_health_check_cond(cd, &gfir) || 92312eb4683SFrank Haverkamp (should_stop = kthread_should_stop())), 9249d14e766SGuilherme G. Piccoli GENWQE_HEALTH_CHECK_INTERVAL * HZ); 92512eb4683SFrank Haverkamp 92612eb4683SFrank Haverkamp if (should_stop) 92712eb4683SFrank Haverkamp break; 92812eb4683SFrank Haverkamp 92912eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) { 93012eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 93112eb4683SFrank Haverkamp "[%s] GFIR=%016llx\n", __func__, gfir); 93212eb4683SFrank Haverkamp goto fatal_error; 93312eb4683SFrank Haverkamp } 93412eb4683SFrank Haverkamp 93512eb4683SFrank Haverkamp slu_unitcfg = __genwqe_readq(cd, IO_SLU_UNITCFG); 93612eb4683SFrank Haverkamp if (slu_unitcfg == IO_ILLEGAL_VALUE) { 93712eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 93812eb4683SFrank Haverkamp "[%s] SLU_UNITCFG=%016llx\n", 93912eb4683SFrank Haverkamp __func__, slu_unitcfg); 94012eb4683SFrank Haverkamp goto fatal_error; 94112eb4683SFrank Haverkamp } 94212eb4683SFrank Haverkamp 94312eb4683SFrank Haverkamp app_unitcfg = __genwqe_readq(cd, IO_APP_UNITCFG); 94412eb4683SFrank Haverkamp if (app_unitcfg == IO_ILLEGAL_VALUE) { 94512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 94612eb4683SFrank Haverkamp "[%s] APP_UNITCFG=%016llx\n", 94712eb4683SFrank Haverkamp __func__, app_unitcfg); 94812eb4683SFrank Haverkamp goto fatal_error; 94912eb4683SFrank Haverkamp } 95012eb4683SFrank Haverkamp 95112eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 95212eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) { 95312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 95412eb4683SFrank Haverkamp "[%s] %s: GFIR=%016llx\n", __func__, 95512eb4683SFrank Haverkamp (gfir & GFIR_ERR_TRIGGER) ? "err" : "info", 95612eb4683SFrank Haverkamp gfir); 95712eb4683SFrank Haverkamp goto fatal_error; 95812eb4683SFrank Haverkamp } 95912eb4683SFrank Haverkamp 96012eb4683SFrank Haverkamp gfir_masked = genwqe_fir_checking(cd); 96112eb4683SFrank Haverkamp if (gfir_masked == IO_ILLEGAL_VALUE) 96212eb4683SFrank Haverkamp goto fatal_error; 96312eb4683SFrank Haverkamp 96412eb4683SFrank Haverkamp /* 96512eb4683SFrank Haverkamp * GFIR ErrorTrigger bits set => reset the card! 96612eb4683SFrank Haverkamp * Never do this for old/manufacturing images! 96712eb4683SFrank Haverkamp */ 96812eb4683SFrank Haverkamp if ((gfir_masked) && !cd->skip_recovery && 96912eb4683SFrank Haverkamp genwqe_recovery_on_fatal_gfir_required(cd)) { 97012eb4683SFrank Haverkamp 97112eb4683SFrank Haverkamp cd->card_state = GENWQE_CARD_FATAL_ERROR; 97212eb4683SFrank Haverkamp 97312eb4683SFrank Haverkamp rc = genwqe_recover_card(cd, 0); 97412eb4683SFrank Haverkamp if (rc < 0) { 97512eb4683SFrank Haverkamp /* FIXME Card is unusable and needs unbind! */ 97612eb4683SFrank Haverkamp goto fatal_error; 97712eb4683SFrank Haverkamp } 97812eb4683SFrank Haverkamp } 97912eb4683SFrank Haverkamp 980c1f732adSKleber Sacilotto de Souza if (cd->card_state == GENWQE_CARD_RELOAD_BITSTREAM) { 981c1f732adSKleber Sacilotto de Souza /* Userspace requested card bitstream reload */ 982c1f732adSKleber Sacilotto de Souza rc = genwqe_reload_bistream(cd); 983c1f732adSKleber Sacilotto de Souza if (rc) 984c1f732adSKleber Sacilotto de Souza goto fatal_error; 985c1f732adSKleber Sacilotto de Souza } 986c1f732adSKleber Sacilotto de Souza 98712eb4683SFrank Haverkamp cd->last_gfir = gfir; 98812eb4683SFrank Haverkamp cond_resched(); 98912eb4683SFrank Haverkamp } 99012eb4683SFrank Haverkamp 99112eb4683SFrank Haverkamp return 0; 99212eb4683SFrank Haverkamp 99312eb4683SFrank Haverkamp fatal_error: 994fb145456SKleber Sacilotto de Souza if (cd->use_platform_recovery) { 995fb145456SKleber Sacilotto de Souza /* 996fb145456SKleber Sacilotto de Souza * Since we use raw accessors, EEH errors won't be detected 997fb145456SKleber Sacilotto de Souza * by the platform until we do a non-raw MMIO or config space 998fb145456SKleber Sacilotto de Souza * read 999fb145456SKleber Sacilotto de Souza */ 1000fb145456SKleber Sacilotto de Souza readq(cd->mmio + IO_SLC_CFGREG_GFIR); 1001fb145456SKleber Sacilotto de Souza 1002fb145456SKleber Sacilotto de Souza /* We do nothing if the card is going over PCI recovery */ 1003fb145456SKleber Sacilotto de Souza if (pci_channel_offline(pci_dev)) 1004fb145456SKleber Sacilotto de Souza return -EIO; 100593b772b2SKleber Sacilotto de Souza 100693b772b2SKleber Sacilotto de Souza /* 100793b772b2SKleber Sacilotto de Souza * If it's supported by the platform, we try a fundamental reset 100893b772b2SKleber Sacilotto de Souza * to recover from a fatal error. Otherwise, we continue to wait 100993b772b2SKleber Sacilotto de Souza * for an external recovery procedure to take care of it. 101093b772b2SKleber Sacilotto de Souza */ 101193b772b2SKleber Sacilotto de Souza rc = genwqe_platform_recovery(cd); 101293b772b2SKleber Sacilotto de Souza if (!rc) 101393b772b2SKleber Sacilotto de Souza goto health_thread_begin; 1014fb145456SKleber Sacilotto de Souza } 1015fb145456SKleber Sacilotto de Souza 101612eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 101712eb4683SFrank Haverkamp "[%s] card unusable. Please trigger unbind!\n", __func__); 101812eb4683SFrank Haverkamp 101912eb4683SFrank Haverkamp /* Bring down logical devices to inform user space via udev remove. */ 102012eb4683SFrank Haverkamp cd->card_state = GENWQE_CARD_FATAL_ERROR; 102112eb4683SFrank Haverkamp genwqe_stop(cd); 102212eb4683SFrank Haverkamp 102312eb4683SFrank Haverkamp /* genwqe_bus_reset failed(). Now wait for genwqe_remove(). */ 102412eb4683SFrank Haverkamp while (!kthread_should_stop()) 102512eb4683SFrank Haverkamp cond_resched(); 102612eb4683SFrank Haverkamp 102712eb4683SFrank Haverkamp return -EIO; 102812eb4683SFrank Haverkamp } 102912eb4683SFrank Haverkamp 103012eb4683SFrank Haverkamp static int genwqe_health_check_start(struct genwqe_dev *cd) 103112eb4683SFrank Haverkamp { 103212eb4683SFrank Haverkamp int rc; 103312eb4683SFrank Haverkamp 10349d14e766SGuilherme G. Piccoli if (GENWQE_HEALTH_CHECK_INTERVAL <= 0) 103512eb4683SFrank Haverkamp return 0; /* valid for disabling the service */ 103612eb4683SFrank Haverkamp 103712eb4683SFrank Haverkamp /* moved before request_irq() */ 103812eb4683SFrank Haverkamp /* init_waitqueue_head(&cd->health_waitq); */ 103912eb4683SFrank Haverkamp 104012eb4683SFrank Haverkamp cd->health_thread = kthread_run(genwqe_health_thread, cd, 104112eb4683SFrank Haverkamp GENWQE_DEVNAME "%d_health", 104212eb4683SFrank Haverkamp cd->card_idx); 104312eb4683SFrank Haverkamp if (IS_ERR(cd->health_thread)) { 104412eb4683SFrank Haverkamp rc = PTR_ERR(cd->health_thread); 104512eb4683SFrank Haverkamp cd->health_thread = NULL; 104612eb4683SFrank Haverkamp return rc; 104712eb4683SFrank Haverkamp } 104812eb4683SFrank Haverkamp return 0; 104912eb4683SFrank Haverkamp } 105012eb4683SFrank Haverkamp 105112eb4683SFrank Haverkamp static int genwqe_health_thread_running(struct genwqe_dev *cd) 105212eb4683SFrank Haverkamp { 105312eb4683SFrank Haverkamp return cd->health_thread != NULL; 105412eb4683SFrank Haverkamp } 105512eb4683SFrank Haverkamp 105612eb4683SFrank Haverkamp static int genwqe_health_check_stop(struct genwqe_dev *cd) 105712eb4683SFrank Haverkamp { 105812eb4683SFrank Haverkamp if (!genwqe_health_thread_running(cd)) 105912eb4683SFrank Haverkamp return -EIO; 106012eb4683SFrank Haverkamp 1061f33e92e5SLee Jones kthread_stop(cd->health_thread); 106212eb4683SFrank Haverkamp cd->health_thread = NULL; 106312eb4683SFrank Haverkamp return 0; 106412eb4683SFrank Haverkamp } 106512eb4683SFrank Haverkamp 106612eb4683SFrank Haverkamp /** 106712eb4683SFrank Haverkamp * genwqe_pci_setup() - Allocate PCIe related resources for our card 1068a562c0c3SLee Jones * @cd: GenWQE device information 106912eb4683SFrank Haverkamp */ 107012eb4683SFrank Haverkamp static int genwqe_pci_setup(struct genwqe_dev *cd) 107112eb4683SFrank Haverkamp { 1072f03774bdSJohannes Thumshirn int err; 107312eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 107412eb4683SFrank Haverkamp 107512eb4683SFrank Haverkamp err = pci_enable_device_mem(pci_dev); 107612eb4683SFrank Haverkamp if (err) { 107712eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 107812eb4683SFrank Haverkamp "err: failed to enable pci memory (err=%d)\n", err); 107912eb4683SFrank Haverkamp goto err_out; 108012eb4683SFrank Haverkamp } 108112eb4683SFrank Haverkamp 108212eb4683SFrank Haverkamp /* Reserve PCI I/O and memory resources */ 1083f03774bdSJohannes Thumshirn err = pci_request_mem_regions(pci_dev, genwqe_driver_name); 108412eb4683SFrank Haverkamp if (err) { 108512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 108612eb4683SFrank Haverkamp "[%s] err: request bars failed (%d)\n", __func__, err); 108712eb4683SFrank Haverkamp err = -EIO; 108812eb4683SFrank Haverkamp goto err_disable_device; 108912eb4683SFrank Haverkamp } 109012eb4683SFrank Haverkamp 109112eb4683SFrank Haverkamp /* check for 64-bit DMA address supported (DAC) */ 109212eb4683SFrank Haverkamp /* check for 32-bit DMA address supported (SAC) */ 1093*8d753db5SChristophe JAILLET if (dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)) && 1094505b0877SChristophe JAILLET dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32))) { 109512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 109612eb4683SFrank Haverkamp "err: neither DMA32 nor DMA64 supported\n"); 109712eb4683SFrank Haverkamp err = -EIO; 109812eb4683SFrank Haverkamp goto out_release_resources; 109912eb4683SFrank Haverkamp } 110012eb4683SFrank Haverkamp 110112eb4683SFrank Haverkamp pci_set_master(pci_dev); 110212eb4683SFrank Haverkamp pci_enable_pcie_error_reporting(pci_dev); 110312eb4683SFrank Haverkamp 1104fb145456SKleber Sacilotto de Souza /* EEH recovery requires PCIe fundamental reset */ 1105fb145456SKleber Sacilotto de Souza pci_dev->needs_freset = 1; 1106fb145456SKleber Sacilotto de Souza 110712eb4683SFrank Haverkamp /* request complete BAR-0 space (length = 0) */ 110812eb4683SFrank Haverkamp cd->mmio_len = pci_resource_len(pci_dev, 0); 110912eb4683SFrank Haverkamp cd->mmio = pci_iomap(pci_dev, 0, 0); 111012eb4683SFrank Haverkamp if (cd->mmio == NULL) { 111112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 111212eb4683SFrank Haverkamp "[%s] err: mapping BAR0 failed\n", __func__); 111312eb4683SFrank Haverkamp err = -ENOMEM; 111412eb4683SFrank Haverkamp goto out_release_resources; 111512eb4683SFrank Haverkamp } 111612eb4683SFrank Haverkamp 111712eb4683SFrank Haverkamp cd->num_vfs = pci_sriov_get_totalvfs(pci_dev); 111895a8825cSFrank Haverkamp if (cd->num_vfs < 0) 111995a8825cSFrank Haverkamp cd->num_vfs = 0; 112012eb4683SFrank Haverkamp 112112eb4683SFrank Haverkamp err = genwqe_read_ids(cd); 112212eb4683SFrank Haverkamp if (err) 112312eb4683SFrank Haverkamp goto out_iounmap; 112412eb4683SFrank Haverkamp 112512eb4683SFrank Haverkamp return 0; 112612eb4683SFrank Haverkamp 112712eb4683SFrank Haverkamp out_iounmap: 112812eb4683SFrank Haverkamp pci_iounmap(pci_dev, cd->mmio); 112912eb4683SFrank Haverkamp out_release_resources: 1130f03774bdSJohannes Thumshirn pci_release_mem_regions(pci_dev); 113112eb4683SFrank Haverkamp err_disable_device: 113212eb4683SFrank Haverkamp pci_disable_device(pci_dev); 113312eb4683SFrank Haverkamp err_out: 113412eb4683SFrank Haverkamp return err; 113512eb4683SFrank Haverkamp } 113612eb4683SFrank Haverkamp 113712eb4683SFrank Haverkamp /** 113812eb4683SFrank Haverkamp * genwqe_pci_remove() - Free PCIe related resources for our card 1139a562c0c3SLee Jones * @cd: GenWQE device information 114012eb4683SFrank Haverkamp */ 114112eb4683SFrank Haverkamp static void genwqe_pci_remove(struct genwqe_dev *cd) 114212eb4683SFrank Haverkamp { 114312eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 114412eb4683SFrank Haverkamp 114512eb4683SFrank Haverkamp if (cd->mmio) 114612eb4683SFrank Haverkamp pci_iounmap(pci_dev, cd->mmio); 114712eb4683SFrank Haverkamp 1148f03774bdSJohannes Thumshirn pci_release_mem_regions(pci_dev); 114912eb4683SFrank Haverkamp pci_disable_device(pci_dev); 115012eb4683SFrank Haverkamp } 115112eb4683SFrank Haverkamp 115212eb4683SFrank Haverkamp /** 115312eb4683SFrank Haverkamp * genwqe_probe() - Device initialization 1154a562c0c3SLee Jones * @pci_dev: PCI device information struct 1155a562c0c3SLee Jones * @id: PCI device ID 115612eb4683SFrank Haverkamp * 115712eb4683SFrank Haverkamp * Callable for multiple cards. This function is called on bind. 115812eb4683SFrank Haverkamp * 115912eb4683SFrank Haverkamp * Return: 0 if succeeded, < 0 when failed 116012eb4683SFrank Haverkamp */ 116112eb4683SFrank Haverkamp static int genwqe_probe(struct pci_dev *pci_dev, 116212eb4683SFrank Haverkamp const struct pci_device_id *id) 116312eb4683SFrank Haverkamp { 116412eb4683SFrank Haverkamp int err; 116512eb4683SFrank Haverkamp struct genwqe_dev *cd; 116612eb4683SFrank Haverkamp 116712eb4683SFrank Haverkamp genwqe_init_crc32(); 116812eb4683SFrank Haverkamp 116912eb4683SFrank Haverkamp cd = genwqe_dev_alloc(); 117012eb4683SFrank Haverkamp if (IS_ERR(cd)) { 117112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "err: could not alloc mem (err=%d)!\n", 117212eb4683SFrank Haverkamp (int)PTR_ERR(cd)); 117312eb4683SFrank Haverkamp return PTR_ERR(cd); 117412eb4683SFrank Haverkamp } 117512eb4683SFrank Haverkamp 117612eb4683SFrank Haverkamp dev_set_drvdata(&pci_dev->dev, cd); 117712eb4683SFrank Haverkamp cd->pci_dev = pci_dev; 117812eb4683SFrank Haverkamp 117912eb4683SFrank Haverkamp err = genwqe_pci_setup(cd); 118012eb4683SFrank Haverkamp if (err < 0) { 118112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 118212eb4683SFrank Haverkamp "err: problems with PCI setup (err=%d)\n", err); 118312eb4683SFrank Haverkamp goto out_free_dev; 118412eb4683SFrank Haverkamp } 118512eb4683SFrank Haverkamp 118612eb4683SFrank Haverkamp err = genwqe_start(cd); 118712eb4683SFrank Haverkamp if (err < 0) { 118812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 118912eb4683SFrank Haverkamp "err: cannot start card services! (err=%d)\n", err); 119012eb4683SFrank Haverkamp goto out_pci_remove; 119112eb4683SFrank Haverkamp } 119212eb4683SFrank Haverkamp 119312eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { 119412eb4683SFrank Haverkamp err = genwqe_health_check_start(cd); 119512eb4683SFrank Haverkamp if (err < 0) { 119612eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 1197d9c11d45SFrank Haverkamp "err: cannot start health checking! (err=%d)\n", 1198d9c11d45SFrank Haverkamp err); 119912eb4683SFrank Haverkamp goto out_stop_services; 120012eb4683SFrank Haverkamp } 120112eb4683SFrank Haverkamp } 120212eb4683SFrank Haverkamp return 0; 120312eb4683SFrank Haverkamp 120412eb4683SFrank Haverkamp out_stop_services: 120512eb4683SFrank Haverkamp genwqe_stop(cd); 120612eb4683SFrank Haverkamp out_pci_remove: 120712eb4683SFrank Haverkamp genwqe_pci_remove(cd); 120812eb4683SFrank Haverkamp out_free_dev: 120912eb4683SFrank Haverkamp genwqe_dev_free(cd); 121012eb4683SFrank Haverkamp return err; 121112eb4683SFrank Haverkamp } 121212eb4683SFrank Haverkamp 121312eb4683SFrank Haverkamp /** 121412eb4683SFrank Haverkamp * genwqe_remove() - Called when device is removed (hot-plugable) 1215a562c0c3SLee Jones * @pci_dev: PCI device information struct 121612eb4683SFrank Haverkamp * 121712eb4683SFrank Haverkamp * Or when driver is unloaded respecitively when unbind is done. 121812eb4683SFrank Haverkamp */ 121912eb4683SFrank Haverkamp static void genwqe_remove(struct pci_dev *pci_dev) 122012eb4683SFrank Haverkamp { 122112eb4683SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); 122212eb4683SFrank Haverkamp 122312eb4683SFrank Haverkamp genwqe_health_check_stop(cd); 122412eb4683SFrank Haverkamp 122512eb4683SFrank Haverkamp /* 122612eb4683SFrank Haverkamp * genwqe_stop() must survive if it is called twice 122712eb4683SFrank Haverkamp * sequentially. This happens when the health thread calls it 122812eb4683SFrank Haverkamp * and fails on genwqe_bus_reset(). 122912eb4683SFrank Haverkamp */ 123012eb4683SFrank Haverkamp genwqe_stop(cd); 123112eb4683SFrank Haverkamp genwqe_pci_remove(cd); 123212eb4683SFrank Haverkamp genwqe_dev_free(cd); 123312eb4683SFrank Haverkamp } 123412eb4683SFrank Haverkamp 1235a562c0c3SLee Jones /** 123612eb4683SFrank Haverkamp * genwqe_err_error_detected() - Error detection callback 1237a562c0c3SLee Jones * @pci_dev: PCI device information struct 1238a562c0c3SLee Jones * @state: PCI channel state 123912eb4683SFrank Haverkamp * 124012eb4683SFrank Haverkamp * This callback is called by the PCI subsystem whenever a PCI bus 124112eb4683SFrank Haverkamp * error is detected. 124212eb4683SFrank Haverkamp */ 124312eb4683SFrank Haverkamp static pci_ers_result_t genwqe_err_error_detected(struct pci_dev *pci_dev, 124416d79cd4SLuc Van Oostenryck pci_channel_state_t state) 124512eb4683SFrank Haverkamp { 124612eb4683SFrank Haverkamp struct genwqe_dev *cd; 124712eb4683SFrank Haverkamp 124812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "[%s] state=%d\n", __func__, state); 124912eb4683SFrank Haverkamp 125012eb4683SFrank Haverkamp cd = dev_get_drvdata(&pci_dev->dev); 125112eb4683SFrank Haverkamp if (cd == NULL) 125212eb4683SFrank Haverkamp return PCI_ERS_RESULT_DISCONNECT; 1253fb145456SKleber Sacilotto de Souza 1254fb145456SKleber Sacilotto de Souza /* Stop the card */ 1255fb145456SKleber Sacilotto de Souza genwqe_health_check_stop(cd); 1256fb145456SKleber Sacilotto de Souza genwqe_stop(cd); 1257fb145456SKleber Sacilotto de Souza 1258fb145456SKleber Sacilotto de Souza /* 1259fb145456SKleber Sacilotto de Souza * On permanent failure, the PCI code will call device remove 1260fb145456SKleber Sacilotto de Souza * after the return of this function. 1261fb145456SKleber Sacilotto de Souza * genwqe_stop() can be called twice. 1262fb145456SKleber Sacilotto de Souza */ 1263fb145456SKleber Sacilotto de Souza if (state == pci_channel_io_perm_failure) { 1264fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_DISCONNECT; 1265fb145456SKleber Sacilotto de Souza } else { 1266fb145456SKleber Sacilotto de Souza genwqe_pci_remove(cd); 1267fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_NEED_RESET; 1268fb145456SKleber Sacilotto de Souza } 126912eb4683SFrank Haverkamp } 127012eb4683SFrank Haverkamp 1271fb145456SKleber Sacilotto de Souza static pci_ers_result_t genwqe_err_slot_reset(struct pci_dev *pci_dev) 1272fb145456SKleber Sacilotto de Souza { 1273fb145456SKleber Sacilotto de Souza int rc; 1274fb145456SKleber Sacilotto de Souza struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); 1275fb145456SKleber Sacilotto de Souza 1276fb145456SKleber Sacilotto de Souza rc = genwqe_pci_setup(cd); 1277fb145456SKleber Sacilotto de Souza if (!rc) { 1278fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_RECOVERED; 1279fb145456SKleber Sacilotto de Souza } else { 1280fb145456SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 1281fb145456SKleber Sacilotto de Souza "err: problems with PCI setup (err=%d)\n", rc); 1282fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_DISCONNECT; 1283fb145456SKleber Sacilotto de Souza } 128412eb4683SFrank Haverkamp } 128512eb4683SFrank Haverkamp 128612eb4683SFrank Haverkamp static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev) 128712eb4683SFrank Haverkamp { 128812eb4683SFrank Haverkamp return PCI_ERS_RESULT_NONE; 128912eb4683SFrank Haverkamp } 129012eb4683SFrank Haverkamp 1291fb145456SKleber Sacilotto de Souza static void genwqe_err_resume(struct pci_dev *pci_dev) 129212eb4683SFrank Haverkamp { 1293fb145456SKleber Sacilotto de Souza int rc; 1294fb145456SKleber Sacilotto de Souza struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); 1295fb145456SKleber Sacilotto de Souza 1296fb145456SKleber Sacilotto de Souza rc = genwqe_start(cd); 1297fb145456SKleber Sacilotto de Souza if (!rc) { 1298fb145456SKleber Sacilotto de Souza rc = genwqe_health_check_start(cd); 1299fb145456SKleber Sacilotto de Souza if (rc) 1300fb145456SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 1301fb145456SKleber Sacilotto de Souza "err: cannot start health checking! (err=%d)\n", 1302fb145456SKleber Sacilotto de Souza rc); 1303fb145456SKleber Sacilotto de Souza } else { 1304fb145456SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 1305fb145456SKleber Sacilotto de Souza "err: cannot start card services! (err=%d)\n", rc); 1306fb145456SKleber Sacilotto de Souza } 130712eb4683SFrank Haverkamp } 130812eb4683SFrank Haverkamp 130912eb4683SFrank Haverkamp static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs) 131012eb4683SFrank Haverkamp { 1311bc407dd3SFrank Haverkamp int rc; 131212eb4683SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(&dev->dev); 131312eb4683SFrank Haverkamp 131412eb4683SFrank Haverkamp if (numvfs > 0) { 131512eb4683SFrank Haverkamp genwqe_setup_vf_jtimer(cd); 1316bc407dd3SFrank Haverkamp rc = pci_enable_sriov(dev, numvfs); 1317bc407dd3SFrank Haverkamp if (rc < 0) 1318bc407dd3SFrank Haverkamp return rc; 131912eb4683SFrank Haverkamp return numvfs; 132012eb4683SFrank Haverkamp } 132112eb4683SFrank Haverkamp if (numvfs == 0) { 132212eb4683SFrank Haverkamp pci_disable_sriov(dev); 132312eb4683SFrank Haverkamp return 0; 132412eb4683SFrank Haverkamp } 132512eb4683SFrank Haverkamp return 0; 132612eb4683SFrank Haverkamp } 132712eb4683SFrank Haverkamp 1328f0838790SRikard Falkeborn static const struct pci_error_handlers genwqe_err_handler = { 132912eb4683SFrank Haverkamp .error_detected = genwqe_err_error_detected, 133012eb4683SFrank Haverkamp .mmio_enabled = genwqe_err_result_none, 1331fb145456SKleber Sacilotto de Souza .slot_reset = genwqe_err_slot_reset, 133212eb4683SFrank Haverkamp .resume = genwqe_err_resume, 133312eb4683SFrank Haverkamp }; 133412eb4683SFrank Haverkamp 133512eb4683SFrank Haverkamp static struct pci_driver genwqe_driver = { 133612eb4683SFrank Haverkamp .name = genwqe_driver_name, 133712eb4683SFrank Haverkamp .id_table = genwqe_device_table, 133812eb4683SFrank Haverkamp .probe = genwqe_probe, 133912eb4683SFrank Haverkamp .remove = genwqe_remove, 134012eb4683SFrank Haverkamp .sriov_configure = genwqe_sriov_configure, 134112eb4683SFrank Haverkamp .err_handler = &genwqe_err_handler, 134212eb4683SFrank Haverkamp }; 134312eb4683SFrank Haverkamp 134412eb4683SFrank Haverkamp /** 13455ed22cebSFrank Haverkamp * genwqe_devnode() - Set default access mode for genwqe devices. 1346a562c0c3SLee Jones * @dev: Pointer to device (unused) 1347a562c0c3SLee Jones * @mode: Carrier to pass-back given mode (permissions) 13485ed22cebSFrank Haverkamp * 13495ed22cebSFrank Haverkamp * Default mode should be rw for everybody. Do not change default 13505ed22cebSFrank Haverkamp * device name. 13515ed22cebSFrank Haverkamp */ 13525ed22cebSFrank Haverkamp static char *genwqe_devnode(struct device *dev, umode_t *mode) 13535ed22cebSFrank Haverkamp { 13545ed22cebSFrank Haverkamp if (mode) 13555ed22cebSFrank Haverkamp *mode = 0666; 13565ed22cebSFrank Haverkamp return NULL; 13575ed22cebSFrank Haverkamp } 13585ed22cebSFrank Haverkamp 13595ed22cebSFrank Haverkamp /** 136012eb4683SFrank Haverkamp * genwqe_init_module() - Driver registration and initialization 136112eb4683SFrank Haverkamp */ 136212eb4683SFrank Haverkamp static int __init genwqe_init_module(void) 136312eb4683SFrank Haverkamp { 136412eb4683SFrank Haverkamp int rc; 136512eb4683SFrank Haverkamp 136612eb4683SFrank Haverkamp class_genwqe = class_create(THIS_MODULE, GENWQE_DEVNAME); 136712eb4683SFrank Haverkamp if (IS_ERR(class_genwqe)) { 136812eb4683SFrank Haverkamp pr_err("[%s] create class failed\n", __func__); 136912eb4683SFrank Haverkamp return -ENOMEM; 137012eb4683SFrank Haverkamp } 137112eb4683SFrank Haverkamp 13725ed22cebSFrank Haverkamp class_genwqe->devnode = genwqe_devnode; 13735ed22cebSFrank Haverkamp 137412eb4683SFrank Haverkamp debugfs_genwqe = debugfs_create_dir(GENWQE_DEVNAME, NULL); 137512eb4683SFrank Haverkamp 137612eb4683SFrank Haverkamp rc = pci_register_driver(&genwqe_driver); 137712eb4683SFrank Haverkamp if (rc != 0) { 137812eb4683SFrank Haverkamp pr_err("[%s] pci_reg_driver (rc=%d)\n", __func__, rc); 137912eb4683SFrank Haverkamp goto err_out0; 138012eb4683SFrank Haverkamp } 138112eb4683SFrank Haverkamp 138212eb4683SFrank Haverkamp return rc; 138312eb4683SFrank Haverkamp 138412eb4683SFrank Haverkamp err_out0: 138512eb4683SFrank Haverkamp debugfs_remove(debugfs_genwqe); 138612eb4683SFrank Haverkamp class_destroy(class_genwqe); 138712eb4683SFrank Haverkamp return rc; 138812eb4683SFrank Haverkamp } 138912eb4683SFrank Haverkamp 139012eb4683SFrank Haverkamp /** 139112eb4683SFrank Haverkamp * genwqe_exit_module() - Driver exit 139212eb4683SFrank Haverkamp */ 139312eb4683SFrank Haverkamp static void __exit genwqe_exit_module(void) 139412eb4683SFrank Haverkamp { 139512eb4683SFrank Haverkamp pci_unregister_driver(&genwqe_driver); 139612eb4683SFrank Haverkamp debugfs_remove(debugfs_genwqe); 139712eb4683SFrank Haverkamp class_destroy(class_genwqe); 139812eb4683SFrank Haverkamp } 139912eb4683SFrank Haverkamp 140012eb4683SFrank Haverkamp module_init(genwqe_init_module); 140112eb4683SFrank Haverkamp module_exit(genwqe_exit_module); 1402