1*eb3ae0aaSThomas 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 16812eb4683SFrank Haverkamp * 16912eb4683SFrank Haverkamp * pci_reset_function() will recover the device and ensure that the 17012eb4683SFrank Haverkamp * registers are accessible again when it completes with success. If 17112eb4683SFrank Haverkamp * not, the card will stay dead and registers will be unaccessible 17212eb4683SFrank Haverkamp * still. 17312eb4683SFrank Haverkamp */ 17412eb4683SFrank Haverkamp static int genwqe_bus_reset(struct genwqe_dev *cd) 17512eb4683SFrank Haverkamp { 176f03774bdSJohannes Thumshirn int rc = 0; 17712eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 17812eb4683SFrank Haverkamp void __iomem *mmio; 17912eb4683SFrank Haverkamp 18012eb4683SFrank Haverkamp if (cd->err_inject & GENWQE_INJECT_BUS_RESET_FAILURE) 18112eb4683SFrank Haverkamp return -EIO; 18212eb4683SFrank Haverkamp 18312eb4683SFrank Haverkamp mmio = cd->mmio; 18412eb4683SFrank Haverkamp cd->mmio = NULL; 18512eb4683SFrank Haverkamp pci_iounmap(pci_dev, mmio); 18612eb4683SFrank Haverkamp 187f03774bdSJohannes Thumshirn pci_release_mem_regions(pci_dev); 18812eb4683SFrank Haverkamp 18912eb4683SFrank Haverkamp /* 19012eb4683SFrank Haverkamp * Firmware/BIOS might change memory mapping during bus reset. 19112eb4683SFrank Haverkamp * Settings like enable bus-mastering, ... are backuped and 19212eb4683SFrank Haverkamp * restored by the pci_reset_function(). 19312eb4683SFrank Haverkamp */ 19412eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, "[%s] pci_reset function ...\n", __func__); 19512eb4683SFrank Haverkamp rc = pci_reset_function(pci_dev); 19612eb4683SFrank Haverkamp if (rc) { 19712eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 19812eb4683SFrank Haverkamp "[%s] err: failed reset func (rc %d)\n", __func__, rc); 19912eb4683SFrank Haverkamp return rc; 20012eb4683SFrank Haverkamp } 20112eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, "[%s] done with rc=%d\n", __func__, rc); 20212eb4683SFrank Haverkamp 20312eb4683SFrank Haverkamp /* 20412eb4683SFrank Haverkamp * Here is the right spot to clear the register read 20512eb4683SFrank Haverkamp * failure. pci_bus_reset() does this job in real systems. 20612eb4683SFrank Haverkamp */ 20712eb4683SFrank Haverkamp cd->err_inject &= ~(GENWQE_INJECT_HARDWARE_FAILURE | 20812eb4683SFrank Haverkamp GENWQE_INJECT_GFIR_FATAL | 20912eb4683SFrank Haverkamp GENWQE_INJECT_GFIR_INFO); 21012eb4683SFrank Haverkamp 211f03774bdSJohannes Thumshirn rc = pci_request_mem_regions(pci_dev, genwqe_driver_name); 21212eb4683SFrank Haverkamp if (rc) { 21312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 21412eb4683SFrank Haverkamp "[%s] err: request bars failed (%d)\n", __func__, rc); 21512eb4683SFrank Haverkamp return -EIO; 21612eb4683SFrank Haverkamp } 21712eb4683SFrank Haverkamp 21812eb4683SFrank Haverkamp cd->mmio = pci_iomap(pci_dev, 0, 0); 21912eb4683SFrank Haverkamp if (cd->mmio == NULL) { 22012eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 22112eb4683SFrank Haverkamp "[%s] err: mapping BAR0 failed\n", __func__); 22212eb4683SFrank Haverkamp return -ENOMEM; 22312eb4683SFrank Haverkamp } 22412eb4683SFrank Haverkamp return 0; 22512eb4683SFrank Haverkamp } 22612eb4683SFrank Haverkamp 22712eb4683SFrank Haverkamp /* 22812eb4683SFrank Haverkamp * Hardware circumvention section. Certain bitstreams in our test-lab 22912eb4683SFrank Haverkamp * had different kinds of problems. Here is where we adjust those 23012eb4683SFrank Haverkamp * bitstreams to function will with this version of our device driver. 23112eb4683SFrank Haverkamp * 23212eb4683SFrank Haverkamp * Thise circumventions are applied to the physical function only. 23312eb4683SFrank Haverkamp * The magical numbers below are identifying development/manufacturing 23412eb4683SFrank Haverkamp * versions of the bitstream used on the card. 23512eb4683SFrank Haverkamp * 23612eb4683SFrank Haverkamp * Turn off error reporting for old/manufacturing images. 23712eb4683SFrank Haverkamp */ 23812eb4683SFrank Haverkamp 23912eb4683SFrank Haverkamp bool genwqe_need_err_masking(struct genwqe_dev *cd) 24012eb4683SFrank Haverkamp { 24112eb4683SFrank Haverkamp return (cd->slu_unitcfg & 0xFFFF0ull) < 0x32170ull; 24212eb4683SFrank Haverkamp } 24312eb4683SFrank Haverkamp 24412eb4683SFrank Haverkamp static void genwqe_tweak_hardware(struct genwqe_dev *cd) 24512eb4683SFrank Haverkamp { 24612eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 24712eb4683SFrank Haverkamp 24812eb4683SFrank Haverkamp /* Mask FIRs for development images */ 24912eb4683SFrank Haverkamp if (((cd->slu_unitcfg & 0xFFFF0ull) >= 0x32000ull) && 25012eb4683SFrank Haverkamp ((cd->slu_unitcfg & 0xFFFF0ull) <= 0x33250ull)) { 25112eb4683SFrank Haverkamp dev_warn(&pci_dev->dev, 25212eb4683SFrank Haverkamp "FIRs masked due to bitstream %016llx.%016llx\n", 25312eb4683SFrank Haverkamp cd->slu_unitcfg, cd->app_unitcfg); 25412eb4683SFrank Haverkamp 25512eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_APP_SEC_LEM_DEBUG_OVR, 25612eb4683SFrank Haverkamp 0xFFFFFFFFFFFFFFFFull); 25712eb4683SFrank Haverkamp 25812eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_APP_ERR_ACT_MASK, 25912eb4683SFrank Haverkamp 0x0000000000000000ull); 26012eb4683SFrank Haverkamp } 26112eb4683SFrank Haverkamp } 26212eb4683SFrank Haverkamp 26312eb4683SFrank Haverkamp /** 26412eb4683SFrank Haverkamp * genwqe_recovery_on_fatal_gfir_required() - Version depended actions 26512eb4683SFrank Haverkamp * 26612eb4683SFrank Haverkamp * Bitstreams older than 2013-02-17 have a bug where fatal GFIRs must 26712eb4683SFrank Haverkamp * be ignored. This is e.g. true for the bitstream we gave to the card 26812eb4683SFrank Haverkamp * manufacturer, but also for some old bitstreams we released to our 26912eb4683SFrank Haverkamp * test-lab. 27012eb4683SFrank Haverkamp */ 27112eb4683SFrank Haverkamp int genwqe_recovery_on_fatal_gfir_required(struct genwqe_dev *cd) 27212eb4683SFrank Haverkamp { 27312eb4683SFrank Haverkamp return (cd->slu_unitcfg & 0xFFFF0ull) >= 0x32170ull; 27412eb4683SFrank Haverkamp } 27512eb4683SFrank Haverkamp 27612eb4683SFrank Haverkamp int genwqe_flash_readback_fails(struct genwqe_dev *cd) 27712eb4683SFrank Haverkamp { 27812eb4683SFrank Haverkamp return (cd->slu_unitcfg & 0xFFFF0ull) < 0x32170ull; 27912eb4683SFrank Haverkamp } 28012eb4683SFrank Haverkamp 28112eb4683SFrank Haverkamp /** 28212eb4683SFrank Haverkamp * genwqe_T_psec() - Calculate PF/VF timeout register content 28312eb4683SFrank Haverkamp * 28412eb4683SFrank Haverkamp * Note: From a design perspective it turned out to be a bad idea to 28512eb4683SFrank Haverkamp * use codes here to specifiy the frequency/speed values. An old 28612eb4683SFrank Haverkamp * driver cannot understand new codes and is therefore always a 28712eb4683SFrank Haverkamp * problem. Better is to measure out the value or put the 28812eb4683SFrank Haverkamp * speed/frequency directly into a register which is always a valid 28912eb4683SFrank Haverkamp * value for old as well as for new software. 29012eb4683SFrank Haverkamp */ 29112eb4683SFrank Haverkamp /* T = 1/f */ 29212eb4683SFrank Haverkamp static int genwqe_T_psec(struct genwqe_dev *cd) 29312eb4683SFrank Haverkamp { 29412eb4683SFrank Haverkamp u16 speed; /* 1/f -> 250, 200, 166, 175 */ 29512eb4683SFrank Haverkamp static const int T[] = { 4000, 5000, 6000, 5714 }; 29612eb4683SFrank Haverkamp 29712eb4683SFrank Haverkamp speed = (u16)((cd->slu_unitcfg >> 28) & 0x0full); 29812eb4683SFrank Haverkamp if (speed >= ARRAY_SIZE(T)) 29912eb4683SFrank Haverkamp return -1; /* illegal value */ 30012eb4683SFrank Haverkamp 30112eb4683SFrank Haverkamp return T[speed]; 30212eb4683SFrank Haverkamp } 30312eb4683SFrank Haverkamp 30412eb4683SFrank Haverkamp /** 30512eb4683SFrank Haverkamp * genwqe_setup_pf_jtimer() - Setup PF hardware timeouts for DDCB execution 30612eb4683SFrank Haverkamp * 30712eb4683SFrank Haverkamp * Do this _after_ card_reset() is called. Otherwise the values will 30812eb4683SFrank Haverkamp * vanish. The settings need to be done when the queues are inactive. 30912eb4683SFrank Haverkamp * 31012eb4683SFrank Haverkamp * The max. timeout value is 2^(10+x) * T (6ns for 166MHz) * 15/16. 31112eb4683SFrank Haverkamp * The min. timeout value is 2^(10+x) * T (6ns for 166MHz) * 14/16. 31212eb4683SFrank Haverkamp */ 31312eb4683SFrank Haverkamp static bool genwqe_setup_pf_jtimer(struct genwqe_dev *cd) 31412eb4683SFrank Haverkamp { 31512eb4683SFrank Haverkamp u32 T = genwqe_T_psec(cd); 31612eb4683SFrank Haverkamp u64 x; 31712eb4683SFrank Haverkamp 3189d14e766SGuilherme G. Piccoli if (GENWQE_PF_JOBTIMEOUT_MSEC == 0) 31912eb4683SFrank Haverkamp return false; 32012eb4683SFrank Haverkamp 32112eb4683SFrank Haverkamp /* PF: large value needed, flash update 2sec per block */ 3229d14e766SGuilherme G. Piccoli x = ilog2(GENWQE_PF_JOBTIMEOUT_MSEC * 32312eb4683SFrank Haverkamp 16000000000uL/(T * 15)) - 10; 32412eb4683SFrank Haverkamp 32512eb4683SFrank Haverkamp genwqe_write_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 32612eb4683SFrank Haverkamp 0xff00 | (x & 0xff), 0); 32712eb4683SFrank Haverkamp return true; 32812eb4683SFrank Haverkamp } 32912eb4683SFrank Haverkamp 33012eb4683SFrank Haverkamp /** 33112eb4683SFrank Haverkamp * genwqe_setup_vf_jtimer() - Setup VF hardware timeouts for DDCB execution 33212eb4683SFrank Haverkamp */ 33312eb4683SFrank Haverkamp static bool genwqe_setup_vf_jtimer(struct genwqe_dev *cd) 33412eb4683SFrank Haverkamp { 33512eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 33612eb4683SFrank Haverkamp unsigned int vf; 33712eb4683SFrank Haverkamp u32 T = genwqe_T_psec(cd); 33812eb4683SFrank Haverkamp u64 x; 33995a8825cSFrank Haverkamp int totalvfs; 34012eb4683SFrank Haverkamp 34195a8825cSFrank Haverkamp totalvfs = pci_sriov_get_totalvfs(pci_dev); 34295a8825cSFrank Haverkamp if (totalvfs <= 0) 34395a8825cSFrank Haverkamp return false; 34495a8825cSFrank Haverkamp 34595a8825cSFrank Haverkamp for (vf = 0; vf < totalvfs; vf++) { 34612eb4683SFrank Haverkamp 34712eb4683SFrank Haverkamp if (cd->vf_jobtimeout_msec[vf] == 0) 34812eb4683SFrank Haverkamp continue; 34912eb4683SFrank Haverkamp 35012eb4683SFrank Haverkamp x = ilog2(cd->vf_jobtimeout_msec[vf] * 35112eb4683SFrank Haverkamp 16000000000uL/(T * 15)) - 10; 35212eb4683SFrank Haverkamp 35312eb4683SFrank Haverkamp genwqe_write_vreg(cd, IO_SLC_VF_APPJOB_TIMEOUT, 35412eb4683SFrank Haverkamp 0xff00 | (x & 0xff), vf + 1); 35512eb4683SFrank Haverkamp } 35612eb4683SFrank Haverkamp return true; 35712eb4683SFrank Haverkamp } 35812eb4683SFrank Haverkamp 35912eb4683SFrank Haverkamp static int genwqe_ffdc_buffs_alloc(struct genwqe_dev *cd) 36012eb4683SFrank Haverkamp { 36112eb4683SFrank Haverkamp unsigned int type, e = 0; 36212eb4683SFrank Haverkamp 36312eb4683SFrank Haverkamp for (type = 0; type < GENWQE_DBG_UNITS; type++) { 36412eb4683SFrank Haverkamp switch (type) { 36512eb4683SFrank Haverkamp case GENWQE_DBG_UNIT0: 36612eb4683SFrank Haverkamp e = genwqe_ffdc_buff_size(cd, 0); 36712eb4683SFrank Haverkamp break; 36812eb4683SFrank Haverkamp case GENWQE_DBG_UNIT1: 36912eb4683SFrank Haverkamp e = genwqe_ffdc_buff_size(cd, 1); 37012eb4683SFrank Haverkamp break; 37112eb4683SFrank Haverkamp case GENWQE_DBG_UNIT2: 37212eb4683SFrank Haverkamp e = genwqe_ffdc_buff_size(cd, 2); 37312eb4683SFrank Haverkamp break; 37412eb4683SFrank Haverkamp case GENWQE_DBG_REGS: 37512eb4683SFrank Haverkamp e = GENWQE_FFDC_REGS; 37612eb4683SFrank Haverkamp break; 37712eb4683SFrank Haverkamp } 37812eb4683SFrank Haverkamp 37912eb4683SFrank Haverkamp /* currently support only the debug units mentioned here */ 38012eb4683SFrank Haverkamp cd->ffdc[type].entries = e; 381d9c11d45SFrank Haverkamp cd->ffdc[type].regs = 382d9c11d45SFrank Haverkamp kmalloc_array(e, sizeof(struct genwqe_reg), 38312eb4683SFrank Haverkamp GFP_KERNEL); 38412eb4683SFrank Haverkamp /* 38512eb4683SFrank Haverkamp * regs == NULL is ok, the using code treats this as no regs, 38612eb4683SFrank Haverkamp * Printing warning is ok in this case. 38712eb4683SFrank Haverkamp */ 38812eb4683SFrank Haverkamp } 38912eb4683SFrank Haverkamp return 0; 39012eb4683SFrank Haverkamp } 39112eb4683SFrank Haverkamp 39212eb4683SFrank Haverkamp static void genwqe_ffdc_buffs_free(struct genwqe_dev *cd) 39312eb4683SFrank Haverkamp { 39412eb4683SFrank Haverkamp unsigned int type; 39512eb4683SFrank Haverkamp 39612eb4683SFrank Haverkamp for (type = 0; type < GENWQE_DBG_UNITS; type++) { 39712eb4683SFrank Haverkamp kfree(cd->ffdc[type].regs); 39812eb4683SFrank Haverkamp cd->ffdc[type].regs = NULL; 39912eb4683SFrank Haverkamp } 40012eb4683SFrank Haverkamp } 40112eb4683SFrank Haverkamp 40212eb4683SFrank Haverkamp static int genwqe_read_ids(struct genwqe_dev *cd) 40312eb4683SFrank Haverkamp { 40412eb4683SFrank Haverkamp int err = 0; 40512eb4683SFrank Haverkamp int slu_id; 40612eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 40712eb4683SFrank Haverkamp 40812eb4683SFrank Haverkamp cd->slu_unitcfg = __genwqe_readq(cd, IO_SLU_UNITCFG); 40912eb4683SFrank Haverkamp if (cd->slu_unitcfg == IO_ILLEGAL_VALUE) { 41012eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 41112eb4683SFrank Haverkamp "err: SLUID=%016llx\n", cd->slu_unitcfg); 41212eb4683SFrank Haverkamp err = -EIO; 41312eb4683SFrank Haverkamp goto out_err; 41412eb4683SFrank Haverkamp } 41512eb4683SFrank Haverkamp 41612eb4683SFrank Haverkamp slu_id = genwqe_get_slu_id(cd); 41712eb4683SFrank Haverkamp if (slu_id < GENWQE_SLU_ARCH_REQ || slu_id == 0xff) { 41812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 41912eb4683SFrank Haverkamp "err: incompatible SLU Architecture %u\n", slu_id); 42012eb4683SFrank Haverkamp err = -ENOENT; 42112eb4683SFrank Haverkamp goto out_err; 42212eb4683SFrank Haverkamp } 42312eb4683SFrank Haverkamp 42412eb4683SFrank Haverkamp cd->app_unitcfg = __genwqe_readq(cd, IO_APP_UNITCFG); 42512eb4683SFrank Haverkamp if (cd->app_unitcfg == IO_ILLEGAL_VALUE) { 42612eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 42712eb4683SFrank Haverkamp "err: APPID=%016llx\n", cd->app_unitcfg); 42812eb4683SFrank Haverkamp err = -EIO; 42912eb4683SFrank Haverkamp goto out_err; 43012eb4683SFrank Haverkamp } 43112eb4683SFrank Haverkamp genwqe_read_app_id(cd, cd->app_name, sizeof(cd->app_name)); 43212eb4683SFrank Haverkamp 43312eb4683SFrank Haverkamp /* 43412eb4683SFrank Haverkamp * Is access to all registers possible? If we are a VF the 43512eb4683SFrank Haverkamp * answer is obvious. If we run fully virtualized, we need to 43612eb4683SFrank Haverkamp * check if we can access all registers. If we do not have 43712eb4683SFrank Haverkamp * full access we will cause an UR and some informational FIRs 43812eb4683SFrank Haverkamp * in the PF, but that should not harm. 43912eb4683SFrank Haverkamp */ 44012eb4683SFrank Haverkamp if (pci_dev->is_virtfn) 44112eb4683SFrank Haverkamp cd->is_privileged = 0; 44212eb4683SFrank Haverkamp else 44312eb4683SFrank Haverkamp cd->is_privileged = (__genwqe_readq(cd, IO_SLU_BITSTREAM) 44412eb4683SFrank Haverkamp != IO_ILLEGAL_VALUE); 44512eb4683SFrank Haverkamp 44612eb4683SFrank Haverkamp out_err: 44712eb4683SFrank Haverkamp return err; 44812eb4683SFrank Haverkamp } 44912eb4683SFrank Haverkamp 45012eb4683SFrank Haverkamp static int genwqe_start(struct genwqe_dev *cd) 45112eb4683SFrank Haverkamp { 45212eb4683SFrank Haverkamp int err; 45312eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 45412eb4683SFrank Haverkamp 45512eb4683SFrank Haverkamp err = genwqe_read_ids(cd); 45612eb4683SFrank Haverkamp if (err) 45712eb4683SFrank Haverkamp return err; 45812eb4683SFrank Haverkamp 45912eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { 46012eb4683SFrank Haverkamp /* do this after the tweaks. alloc fail is acceptable */ 46112eb4683SFrank Haverkamp genwqe_ffdc_buffs_alloc(cd); 46212eb4683SFrank Haverkamp genwqe_stop_traps(cd); 46312eb4683SFrank Haverkamp 46412eb4683SFrank Haverkamp /* Collect registers e.g. FIRs, UNITIDs, traces ... */ 46512eb4683SFrank Haverkamp genwqe_read_ffdc_regs(cd, cd->ffdc[GENWQE_DBG_REGS].regs, 46612eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_REGS].entries, 0); 46712eb4683SFrank Haverkamp 46812eb4683SFrank Haverkamp genwqe_ffdc_buff_read(cd, GENWQE_DBG_UNIT0, 46912eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT0].regs, 47012eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT0].entries); 47112eb4683SFrank Haverkamp 47212eb4683SFrank Haverkamp genwqe_ffdc_buff_read(cd, GENWQE_DBG_UNIT1, 47312eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT1].regs, 47412eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT1].entries); 47512eb4683SFrank Haverkamp 47612eb4683SFrank Haverkamp genwqe_ffdc_buff_read(cd, GENWQE_DBG_UNIT2, 47712eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT2].regs, 47812eb4683SFrank Haverkamp cd->ffdc[GENWQE_DBG_UNIT2].entries); 47912eb4683SFrank Haverkamp 48012eb4683SFrank Haverkamp genwqe_start_traps(cd); 48112eb4683SFrank Haverkamp 48212eb4683SFrank Haverkamp if (cd->card_state == GENWQE_CARD_FATAL_ERROR) { 48312eb4683SFrank Haverkamp dev_warn(&pci_dev->dev, 48412eb4683SFrank Haverkamp "[%s] chip reload/recovery!\n", __func__); 48512eb4683SFrank Haverkamp 48612eb4683SFrank Haverkamp /* 48712eb4683SFrank Haverkamp * Stealth Mode: Reload chip on either hot 48812eb4683SFrank Haverkamp * reset or PERST. 48912eb4683SFrank Haverkamp */ 49012eb4683SFrank Haverkamp cd->softreset = 0x7Cull; 49112eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, 49212eb4683SFrank Haverkamp cd->softreset); 49312eb4683SFrank Haverkamp 49412eb4683SFrank Haverkamp err = genwqe_bus_reset(cd); 49512eb4683SFrank Haverkamp if (err != 0) { 49612eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 49712eb4683SFrank Haverkamp "[%s] err: bus reset failed!\n", 49812eb4683SFrank Haverkamp __func__); 49912eb4683SFrank Haverkamp goto out; 50012eb4683SFrank Haverkamp } 50112eb4683SFrank Haverkamp 50212eb4683SFrank Haverkamp /* 50312eb4683SFrank Haverkamp * Re-read the IDs because 50412eb4683SFrank Haverkamp * it could happen that the bitstream load 50512eb4683SFrank Haverkamp * failed! 50612eb4683SFrank Haverkamp */ 50712eb4683SFrank Haverkamp err = genwqe_read_ids(cd); 50812eb4683SFrank Haverkamp if (err) 50912eb4683SFrank Haverkamp goto out; 51012eb4683SFrank Haverkamp } 51112eb4683SFrank Haverkamp } 51212eb4683SFrank Haverkamp 51312eb4683SFrank Haverkamp err = genwqe_setup_service_layer(cd); /* does a reset to the card */ 51412eb4683SFrank Haverkamp if (err != 0) { 51512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 51612eb4683SFrank Haverkamp "[%s] err: could not setup servicelayer!\n", __func__); 51712eb4683SFrank Haverkamp err = -ENODEV; 51812eb4683SFrank Haverkamp goto out; 51912eb4683SFrank Haverkamp } 52012eb4683SFrank Haverkamp 52112eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { /* code is running _after_ reset */ 52212eb4683SFrank Haverkamp genwqe_tweak_hardware(cd); 52312eb4683SFrank Haverkamp 52412eb4683SFrank Haverkamp genwqe_setup_pf_jtimer(cd); 52512eb4683SFrank Haverkamp genwqe_setup_vf_jtimer(cd); 52612eb4683SFrank Haverkamp } 52712eb4683SFrank Haverkamp 52812eb4683SFrank Haverkamp err = genwqe_device_create(cd); 52912eb4683SFrank Haverkamp if (err < 0) { 53012eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 53112eb4683SFrank Haverkamp "err: chdev init failed! (err=%d)\n", err); 53212eb4683SFrank Haverkamp goto out_release_service_layer; 53312eb4683SFrank Haverkamp } 53412eb4683SFrank Haverkamp return 0; 53512eb4683SFrank Haverkamp 53612eb4683SFrank Haverkamp out_release_service_layer: 53712eb4683SFrank Haverkamp genwqe_release_service_layer(cd); 53812eb4683SFrank Haverkamp out: 53912eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) 54012eb4683SFrank Haverkamp genwqe_ffdc_buffs_free(cd); 54112eb4683SFrank Haverkamp return -EIO; 54212eb4683SFrank Haverkamp } 54312eb4683SFrank Haverkamp 54412eb4683SFrank Haverkamp /** 54512eb4683SFrank Haverkamp * genwqe_stop() - Stop card operation 54612eb4683SFrank Haverkamp * 54712eb4683SFrank Haverkamp * Recovery notes: 54812eb4683SFrank Haverkamp * As long as genwqe_thread runs we might access registers during 54912eb4683SFrank Haverkamp * error data capture. Same is with the genwqe_health_thread. 55012eb4683SFrank Haverkamp * When genwqe_bus_reset() fails this function might called two times: 55112eb4683SFrank Haverkamp * first by the genwqe_health_thread() and later by genwqe_remove() to 55212eb4683SFrank Haverkamp * unbind the device. We must be able to survive that. 55312eb4683SFrank Haverkamp * 55412eb4683SFrank Haverkamp * This function must be robust enough to be called twice. 55512eb4683SFrank Haverkamp */ 55612eb4683SFrank Haverkamp static int genwqe_stop(struct genwqe_dev *cd) 55712eb4683SFrank Haverkamp { 55812eb4683SFrank Haverkamp genwqe_finish_queue(cd); /* no register access */ 55912eb4683SFrank Haverkamp genwqe_device_remove(cd); /* device removed, procs killed */ 56012eb4683SFrank Haverkamp genwqe_release_service_layer(cd); /* here genwqe_thread is stopped */ 56112eb4683SFrank Haverkamp 56212eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { 56312eb4683SFrank Haverkamp pci_disable_sriov(cd->pci_dev); /* access pci config space */ 56412eb4683SFrank Haverkamp genwqe_ffdc_buffs_free(cd); 56512eb4683SFrank Haverkamp } 56612eb4683SFrank Haverkamp 56712eb4683SFrank Haverkamp return 0; 56812eb4683SFrank Haverkamp } 56912eb4683SFrank Haverkamp 57012eb4683SFrank Haverkamp /** 57112eb4683SFrank Haverkamp * genwqe_recover_card() - Try to recover the card if it is possible 57212eb4683SFrank Haverkamp * 57312eb4683SFrank Haverkamp * If fatal_err is set no register access is possible anymore. It is 57412eb4683SFrank Haverkamp * likely that genwqe_start fails in that situation. Proper error 57512eb4683SFrank Haverkamp * handling is required in this case. 57612eb4683SFrank Haverkamp * 57712eb4683SFrank Haverkamp * genwqe_bus_reset() will cause the pci code to call genwqe_remove() 57812eb4683SFrank Haverkamp * and later genwqe_probe() for all virtual functions. 57912eb4683SFrank Haverkamp */ 58012eb4683SFrank Haverkamp static int genwqe_recover_card(struct genwqe_dev *cd, int fatal_err) 58112eb4683SFrank Haverkamp { 58212eb4683SFrank Haverkamp int rc; 58312eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 58412eb4683SFrank Haverkamp 58512eb4683SFrank Haverkamp genwqe_stop(cd); 58612eb4683SFrank Haverkamp 58712eb4683SFrank Haverkamp /* 58812eb4683SFrank Haverkamp * Make sure chip is not reloaded to maintain FFDC. Write SLU 58912eb4683SFrank Haverkamp * Reset Register, CPLDReset field to 0. 59012eb4683SFrank Haverkamp */ 59112eb4683SFrank Haverkamp if (!fatal_err) { 59212eb4683SFrank Haverkamp cd->softreset = 0x70ull; 59312eb4683SFrank Haverkamp __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, cd->softreset); 59412eb4683SFrank Haverkamp } 59512eb4683SFrank Haverkamp 59612eb4683SFrank Haverkamp rc = genwqe_bus_reset(cd); 59712eb4683SFrank Haverkamp if (rc != 0) { 59812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 59912eb4683SFrank Haverkamp "[%s] err: card recovery impossible!\n", __func__); 60012eb4683SFrank Haverkamp return rc; 60112eb4683SFrank Haverkamp } 60212eb4683SFrank Haverkamp 60312eb4683SFrank Haverkamp rc = genwqe_start(cd); 60412eb4683SFrank Haverkamp if (rc < 0) { 60512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 60612eb4683SFrank Haverkamp "[%s] err: failed to launch device!\n", __func__); 60712eb4683SFrank Haverkamp return rc; 60812eb4683SFrank Haverkamp } 60912eb4683SFrank Haverkamp return 0; 61012eb4683SFrank Haverkamp } 61112eb4683SFrank Haverkamp 61212eb4683SFrank Haverkamp static int genwqe_health_check_cond(struct genwqe_dev *cd, u64 *gfir) 61312eb4683SFrank Haverkamp { 61412eb4683SFrank Haverkamp *gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 61512eb4683SFrank Haverkamp return (*gfir & GFIR_ERR_TRIGGER) && 61612eb4683SFrank Haverkamp genwqe_recovery_on_fatal_gfir_required(cd); 61712eb4683SFrank Haverkamp } 61812eb4683SFrank Haverkamp 61912eb4683SFrank Haverkamp /** 62012eb4683SFrank Haverkamp * genwqe_fir_checking() - Check the fault isolation registers of the card 62112eb4683SFrank Haverkamp * 62212eb4683SFrank Haverkamp * If this code works ok, can be tried out with help of the genwqe_poke tool: 62312eb4683SFrank Haverkamp * sudo ./tools/genwqe_poke 0x8 0xfefefefefef 62412eb4683SFrank Haverkamp * 62512eb4683SFrank Haverkamp * Now the relevant FIRs/sFIRs should be printed out and the driver should 62612eb4683SFrank Haverkamp * invoke recovery (devices are removed and readded). 62712eb4683SFrank Haverkamp */ 62812eb4683SFrank Haverkamp static u64 genwqe_fir_checking(struct genwqe_dev *cd) 62912eb4683SFrank Haverkamp { 63012eb4683SFrank Haverkamp int j, iterations = 0; 63112eb4683SFrank Haverkamp u64 mask, fir, fec, uid, gfir, gfir_masked, sfir, sfec; 63212eb4683SFrank Haverkamp u32 fir_addr, fir_clr_addr, fec_addr, sfir_addr, sfec_addr; 63312eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 63412eb4683SFrank Haverkamp 63512eb4683SFrank Haverkamp healthMonitor: 63612eb4683SFrank Haverkamp iterations++; 63712eb4683SFrank Haverkamp if (iterations > 16) { 63812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* exit looping after %d times\n", 63912eb4683SFrank Haverkamp iterations); 64012eb4683SFrank Haverkamp goto fatal_error; 64112eb4683SFrank Haverkamp } 64212eb4683SFrank Haverkamp 64312eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 64412eb4683SFrank Haverkamp if (gfir != 0x0) 64512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* 0x%08x 0x%016llx\n", 64612eb4683SFrank Haverkamp IO_SLC_CFGREG_GFIR, gfir); 64712eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) 64812eb4683SFrank Haverkamp goto fatal_error; 64912eb4683SFrank Haverkamp 65012eb4683SFrank Haverkamp /* 65112eb4683SFrank Haverkamp * Avoid printing when to GFIR bit is on prevents contignous 65212eb4683SFrank Haverkamp * printout e.g. for the following bug: 65312eb4683SFrank Haverkamp * FIR set without a 2ndary FIR/FIR cannot be cleared 65412eb4683SFrank Haverkamp * Comment out the following if to get the prints: 65512eb4683SFrank Haverkamp */ 65612eb4683SFrank Haverkamp if (gfir == 0) 65712eb4683SFrank Haverkamp return 0; 65812eb4683SFrank Haverkamp 65912eb4683SFrank Haverkamp gfir_masked = gfir & GFIR_ERR_TRIGGER; /* fatal errors */ 66012eb4683SFrank Haverkamp 66112eb4683SFrank Haverkamp for (uid = 0; uid < GENWQE_MAX_UNITS; uid++) { /* 0..2 in zEDC */ 66212eb4683SFrank Haverkamp 66312eb4683SFrank Haverkamp /* read the primary FIR (pfir) */ 66412eb4683SFrank Haverkamp fir_addr = (uid << 24) + 0x08; 66512eb4683SFrank Haverkamp fir = __genwqe_readq(cd, fir_addr); 66612eb4683SFrank Haverkamp if (fir == 0x0) 66712eb4683SFrank Haverkamp continue; /* no error in this unit */ 66812eb4683SFrank Haverkamp 66912eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* 0x%08x 0x%016llx\n", fir_addr, fir); 67012eb4683SFrank Haverkamp if (fir == IO_ILLEGAL_VALUE) 67112eb4683SFrank Haverkamp goto fatal_error; 67212eb4683SFrank Haverkamp 67312eb4683SFrank Haverkamp /* read primary FEC */ 67412eb4683SFrank Haverkamp fec_addr = (uid << 24) + 0x18; 67512eb4683SFrank Haverkamp fec = __genwqe_readq(cd, fec_addr); 67612eb4683SFrank Haverkamp 67712eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "* 0x%08x 0x%016llx\n", fec_addr, fec); 67812eb4683SFrank Haverkamp if (fec == IO_ILLEGAL_VALUE) 67912eb4683SFrank Haverkamp goto fatal_error; 68012eb4683SFrank Haverkamp 68112eb4683SFrank Haverkamp for (j = 0, mask = 1ULL; j < 64; j++, mask <<= 1) { 68212eb4683SFrank Haverkamp 68312eb4683SFrank Haverkamp /* secondary fir empty, skip it */ 68412eb4683SFrank Haverkamp if ((fir & mask) == 0x0) 68512eb4683SFrank Haverkamp continue; 68612eb4683SFrank Haverkamp 68712eb4683SFrank Haverkamp sfir_addr = (uid << 24) + 0x100 + 0x08 * j; 68812eb4683SFrank Haverkamp sfir = __genwqe_readq(cd, sfir_addr); 68912eb4683SFrank Haverkamp 69012eb4683SFrank Haverkamp if (sfir == IO_ILLEGAL_VALUE) 69112eb4683SFrank Haverkamp goto fatal_error; 69212eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 69312eb4683SFrank Haverkamp "* 0x%08x 0x%016llx\n", sfir_addr, sfir); 69412eb4683SFrank Haverkamp 69512eb4683SFrank Haverkamp sfec_addr = (uid << 24) + 0x300 + 0x08 * j; 69612eb4683SFrank Haverkamp sfec = __genwqe_readq(cd, sfec_addr); 69712eb4683SFrank Haverkamp 69812eb4683SFrank Haverkamp if (sfec == IO_ILLEGAL_VALUE) 69912eb4683SFrank Haverkamp goto fatal_error; 70012eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 70112eb4683SFrank Haverkamp "* 0x%08x 0x%016llx\n", sfec_addr, sfec); 70212eb4683SFrank Haverkamp 70312eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 70412eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) 70512eb4683SFrank Haverkamp goto fatal_error; 70612eb4683SFrank Haverkamp 70712eb4683SFrank Haverkamp /* gfir turned on during routine! get out and 70812eb4683SFrank Haverkamp start over. */ 70912eb4683SFrank Haverkamp if ((gfir_masked == 0x0) && 71012eb4683SFrank Haverkamp (gfir & GFIR_ERR_TRIGGER)) { 71112eb4683SFrank Haverkamp goto healthMonitor; 71212eb4683SFrank Haverkamp } 71312eb4683SFrank Haverkamp 71412eb4683SFrank Haverkamp /* do not clear if we entered with a fatal gfir */ 71512eb4683SFrank Haverkamp if (gfir_masked == 0x0) { 71612eb4683SFrank Haverkamp 71712eb4683SFrank Haverkamp /* NEW clear by mask the logged bits */ 71812eb4683SFrank Haverkamp sfir_addr = (uid << 24) + 0x100 + 0x08 * j; 71912eb4683SFrank Haverkamp __genwqe_writeq(cd, sfir_addr, sfir); 72012eb4683SFrank Haverkamp 72112eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, 722d9c11d45SFrank Haverkamp "[HM] Clearing 2ndary FIR 0x%08x with 0x%016llx\n", 723d9c11d45SFrank Haverkamp sfir_addr, sfir); 72412eb4683SFrank Haverkamp 72512eb4683SFrank Haverkamp /* 72612eb4683SFrank Haverkamp * note, these cannot be error-Firs 72712eb4683SFrank Haverkamp * since gfir_masked is 0 after sfir 72812eb4683SFrank Haverkamp * was read. Also, it is safe to do 72912eb4683SFrank Haverkamp * this write if sfir=0. Still need to 73012eb4683SFrank Haverkamp * clear the primary. This just means 73112eb4683SFrank Haverkamp * there is no secondary FIR. 73212eb4683SFrank Haverkamp */ 73312eb4683SFrank Haverkamp 73412eb4683SFrank Haverkamp /* clear by mask the logged bit. */ 73512eb4683SFrank Haverkamp fir_clr_addr = (uid << 24) + 0x10; 73612eb4683SFrank Haverkamp __genwqe_writeq(cd, fir_clr_addr, mask); 73712eb4683SFrank Haverkamp 73812eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, 739d9c11d45SFrank Haverkamp "[HM] Clearing primary FIR 0x%08x with 0x%016llx\n", 740d9c11d45SFrank Haverkamp fir_clr_addr, mask); 74112eb4683SFrank Haverkamp } 74212eb4683SFrank Haverkamp } 74312eb4683SFrank Haverkamp } 74412eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 74512eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) 74612eb4683SFrank Haverkamp goto fatal_error; 74712eb4683SFrank Haverkamp 74812eb4683SFrank Haverkamp if ((gfir_masked == 0x0) && (gfir & GFIR_ERR_TRIGGER)) { 74912eb4683SFrank Haverkamp /* 75012eb4683SFrank Haverkamp * Check once more that it didn't go on after all the 75112eb4683SFrank Haverkamp * FIRS were cleared. 75212eb4683SFrank Haverkamp */ 75312eb4683SFrank Haverkamp dev_dbg(&pci_dev->dev, "ACK! Another FIR! Recursing %d!\n", 75412eb4683SFrank Haverkamp iterations); 75512eb4683SFrank Haverkamp goto healthMonitor; 75612eb4683SFrank Haverkamp } 75712eb4683SFrank Haverkamp return gfir_masked; 75812eb4683SFrank Haverkamp 75912eb4683SFrank Haverkamp fatal_error: 76012eb4683SFrank Haverkamp return IO_ILLEGAL_VALUE; 76112eb4683SFrank Haverkamp } 76212eb4683SFrank Haverkamp 76312eb4683SFrank Haverkamp /** 764c1f732adSKleber Sacilotto de Souza * genwqe_pci_fundamental_reset() - trigger a PCIe fundamental reset on the slot 765c1f732adSKleber Sacilotto de Souza * 766c1f732adSKleber Sacilotto de Souza * Note: pci_set_pcie_reset_state() is not implemented on all archs, so this 767c1f732adSKleber Sacilotto de Souza * reset method will not work in all cases. 768c1f732adSKleber Sacilotto de Souza * 769c1f732adSKleber Sacilotto de Souza * Return: 0 on success or error code from pci_set_pcie_reset_state() 770c1f732adSKleber Sacilotto de Souza */ 771c1f732adSKleber Sacilotto de Souza static int genwqe_pci_fundamental_reset(struct pci_dev *pci_dev) 772c1f732adSKleber Sacilotto de Souza { 773c1f732adSKleber Sacilotto de Souza int rc; 774c1f732adSKleber Sacilotto de Souza 775c1f732adSKleber Sacilotto de Souza /* 776c1f732adSKleber Sacilotto de Souza * lock pci config space access from userspace, 777c1f732adSKleber Sacilotto de Souza * save state and issue PCIe fundamental reset 778c1f732adSKleber Sacilotto de Souza */ 779c1f732adSKleber Sacilotto de Souza pci_cfg_access_lock(pci_dev); 780c1f732adSKleber Sacilotto de Souza pci_save_state(pci_dev); 781c1f732adSKleber Sacilotto de Souza rc = pci_set_pcie_reset_state(pci_dev, pcie_warm_reset); 782c1f732adSKleber Sacilotto de Souza if (!rc) { 783c1f732adSKleber Sacilotto de Souza /* keep PCIe reset asserted for 250ms */ 784c1f732adSKleber Sacilotto de Souza msleep(250); 785c1f732adSKleber Sacilotto de Souza pci_set_pcie_reset_state(pci_dev, pcie_deassert_reset); 786c1f732adSKleber Sacilotto de Souza /* Wait for 2s to reload flash and train the link */ 787c1f732adSKleber Sacilotto de Souza msleep(2000); 788c1f732adSKleber Sacilotto de Souza } 789c1f732adSKleber Sacilotto de Souza pci_restore_state(pci_dev); 790c1f732adSKleber Sacilotto de Souza pci_cfg_access_unlock(pci_dev); 791c1f732adSKleber Sacilotto de Souza return rc; 792c1f732adSKleber Sacilotto de Souza } 793c1f732adSKleber Sacilotto de Souza 79493b772b2SKleber Sacilotto de Souza 79593b772b2SKleber Sacilotto de Souza static int genwqe_platform_recovery(struct genwqe_dev *cd) 79693b772b2SKleber Sacilotto de Souza { 79793b772b2SKleber Sacilotto de Souza struct pci_dev *pci_dev = cd->pci_dev; 79893b772b2SKleber Sacilotto de Souza int rc; 79993b772b2SKleber Sacilotto de Souza 80093b772b2SKleber Sacilotto de Souza dev_info(&pci_dev->dev, 80193b772b2SKleber Sacilotto de Souza "[%s] resetting card for error recovery\n", __func__); 80293b772b2SKleber Sacilotto de Souza 80393b772b2SKleber Sacilotto de Souza /* Clear out error injection flags */ 80493b772b2SKleber Sacilotto de Souza cd->err_inject &= ~(GENWQE_INJECT_HARDWARE_FAILURE | 80593b772b2SKleber Sacilotto de Souza GENWQE_INJECT_GFIR_FATAL | 80693b772b2SKleber Sacilotto de Souza GENWQE_INJECT_GFIR_INFO); 80793b772b2SKleber Sacilotto de Souza 80893b772b2SKleber Sacilotto de Souza genwqe_stop(cd); 80993b772b2SKleber Sacilotto de Souza 81093b772b2SKleber Sacilotto de Souza /* Try recoverying the card with fundamental reset */ 81193b772b2SKleber Sacilotto de Souza rc = genwqe_pci_fundamental_reset(pci_dev); 81293b772b2SKleber Sacilotto de Souza if (!rc) { 81393b772b2SKleber Sacilotto de Souza rc = genwqe_start(cd); 81493b772b2SKleber Sacilotto de Souza if (!rc) 81593b772b2SKleber Sacilotto de Souza dev_info(&pci_dev->dev, 81693b772b2SKleber Sacilotto de Souza "[%s] card recovered\n", __func__); 81793b772b2SKleber Sacilotto de Souza else 81893b772b2SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 81993b772b2SKleber Sacilotto de Souza "[%s] err: cannot start card services! (err=%d)\n", 82093b772b2SKleber Sacilotto de Souza __func__, rc); 82193b772b2SKleber Sacilotto de Souza } else { 82293b772b2SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 82393b772b2SKleber Sacilotto de Souza "[%s] card reset failed\n", __func__); 82493b772b2SKleber Sacilotto de Souza } 82593b772b2SKleber Sacilotto de Souza 82693b772b2SKleber Sacilotto de Souza return rc; 82793b772b2SKleber Sacilotto de Souza } 82893b772b2SKleber Sacilotto de Souza 829c1f732adSKleber Sacilotto de Souza /* 830c1f732adSKleber Sacilotto de Souza * genwqe_reload_bistream() - reload card bitstream 831c1f732adSKleber Sacilotto de Souza * 832c1f732adSKleber Sacilotto de Souza * Set the appropriate register and call fundamental reset to reaload the card 833c1f732adSKleber Sacilotto de Souza * bitstream. 834c1f732adSKleber Sacilotto de Souza * 835c1f732adSKleber Sacilotto de Souza * Return: 0 on success, error code otherwise 836c1f732adSKleber Sacilotto de Souza */ 837c1f732adSKleber Sacilotto de Souza static int genwqe_reload_bistream(struct genwqe_dev *cd) 838c1f732adSKleber Sacilotto de Souza { 839c1f732adSKleber Sacilotto de Souza struct pci_dev *pci_dev = cd->pci_dev; 840c1f732adSKleber Sacilotto de Souza int rc; 841c1f732adSKleber Sacilotto de Souza 842c1f732adSKleber Sacilotto de Souza dev_info(&pci_dev->dev, 843c1f732adSKleber Sacilotto de Souza "[%s] resetting card for bitstream reload\n", 844c1f732adSKleber Sacilotto de Souza __func__); 845c1f732adSKleber Sacilotto de Souza 846c1f732adSKleber Sacilotto de Souza genwqe_stop(cd); 847c1f732adSKleber Sacilotto de Souza 848c1f732adSKleber Sacilotto de Souza /* 849c1f732adSKleber Sacilotto de Souza * Cause a CPLD reprogram with the 'next_bitstream' 850c1f732adSKleber Sacilotto de Souza * partition on PCIe hot or fundamental reset 851c1f732adSKleber Sacilotto de Souza */ 852c1f732adSKleber Sacilotto de Souza __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, 853c1f732adSKleber Sacilotto de Souza (cd->softreset & 0xcull) | 0x70ull); 854c1f732adSKleber Sacilotto de Souza 855c1f732adSKleber Sacilotto de Souza rc = genwqe_pci_fundamental_reset(pci_dev); 856c1f732adSKleber Sacilotto de Souza if (rc) { 857c1f732adSKleber Sacilotto de Souza /* 858c1f732adSKleber Sacilotto de Souza * A fundamental reset failure can be caused 859c1f732adSKleber Sacilotto de Souza * by lack of support on the arch, so we just 860c1f732adSKleber Sacilotto de Souza * log the error and try to start the card 861c1f732adSKleber Sacilotto de Souza * again. 862c1f732adSKleber Sacilotto de Souza */ 863c1f732adSKleber Sacilotto de Souza dev_err(&pci_dev->dev, 864c1f732adSKleber Sacilotto de Souza "[%s] err: failed to reset card for bitstream reload\n", 865c1f732adSKleber Sacilotto de Souza __func__); 866c1f732adSKleber Sacilotto de Souza } 867c1f732adSKleber Sacilotto de Souza 868c1f732adSKleber Sacilotto de Souza rc = genwqe_start(cd); 869c1f732adSKleber Sacilotto de Souza if (rc) { 870c1f732adSKleber Sacilotto de Souza dev_err(&pci_dev->dev, 871c1f732adSKleber Sacilotto de Souza "[%s] err: cannot start card services! (err=%d)\n", 872c1f732adSKleber Sacilotto de Souza __func__, rc); 873c1f732adSKleber Sacilotto de Souza return rc; 874c1f732adSKleber Sacilotto de Souza } 875c1f732adSKleber Sacilotto de Souza dev_info(&pci_dev->dev, 876c1f732adSKleber Sacilotto de Souza "[%s] card reloaded\n", __func__); 877c1f732adSKleber Sacilotto de Souza return 0; 878c1f732adSKleber Sacilotto de Souza } 879c1f732adSKleber Sacilotto de Souza 880c1f732adSKleber Sacilotto de Souza 881c1f732adSKleber Sacilotto de Souza /** 88212eb4683SFrank Haverkamp * genwqe_health_thread() - Health checking thread 88312eb4683SFrank Haverkamp * 88412eb4683SFrank Haverkamp * This thread is only started for the PF of the card. 88512eb4683SFrank Haverkamp * 88612eb4683SFrank Haverkamp * This thread monitors the health of the card. A critical situation 88712eb4683SFrank Haverkamp * is when we read registers which contain -1 (IO_ILLEGAL_VALUE). In 88812eb4683SFrank Haverkamp * this case we need to be recovered from outside. Writing to 88912eb4683SFrank Haverkamp * registers will very likely not work either. 89012eb4683SFrank Haverkamp * 89112eb4683SFrank Haverkamp * This thread must only exit if kthread_should_stop() becomes true. 89212eb4683SFrank Haverkamp * 89312eb4683SFrank Haverkamp * Condition for the health-thread to trigger: 89412eb4683SFrank Haverkamp * a) when a kthread_stop() request comes in or 89512eb4683SFrank Haverkamp * b) a critical GFIR occured 89612eb4683SFrank Haverkamp * 89712eb4683SFrank Haverkamp * Informational GFIRs are checked and potentially printed in 8989d14e766SGuilherme G. Piccoli * GENWQE_HEALTH_CHECK_INTERVAL seconds. 89912eb4683SFrank Haverkamp */ 90012eb4683SFrank Haverkamp static int genwqe_health_thread(void *data) 90112eb4683SFrank Haverkamp { 90212eb4683SFrank Haverkamp int rc, should_stop = 0; 90312eb4683SFrank Haverkamp struct genwqe_dev *cd = data; 90412eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 90512eb4683SFrank Haverkamp u64 gfir, gfir_masked, slu_unitcfg, app_unitcfg; 90612eb4683SFrank Haverkamp 90793b772b2SKleber Sacilotto de Souza health_thread_begin: 90812eb4683SFrank Haverkamp while (!kthread_should_stop()) { 90912eb4683SFrank Haverkamp rc = wait_event_interruptible_timeout(cd->health_waitq, 91012eb4683SFrank Haverkamp (genwqe_health_check_cond(cd, &gfir) || 91112eb4683SFrank Haverkamp (should_stop = kthread_should_stop())), 9129d14e766SGuilherme G. Piccoli GENWQE_HEALTH_CHECK_INTERVAL * HZ); 91312eb4683SFrank Haverkamp 91412eb4683SFrank Haverkamp if (should_stop) 91512eb4683SFrank Haverkamp break; 91612eb4683SFrank Haverkamp 91712eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) { 91812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 91912eb4683SFrank Haverkamp "[%s] GFIR=%016llx\n", __func__, gfir); 92012eb4683SFrank Haverkamp goto fatal_error; 92112eb4683SFrank Haverkamp } 92212eb4683SFrank Haverkamp 92312eb4683SFrank Haverkamp slu_unitcfg = __genwqe_readq(cd, IO_SLU_UNITCFG); 92412eb4683SFrank Haverkamp if (slu_unitcfg == IO_ILLEGAL_VALUE) { 92512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 92612eb4683SFrank Haverkamp "[%s] SLU_UNITCFG=%016llx\n", 92712eb4683SFrank Haverkamp __func__, slu_unitcfg); 92812eb4683SFrank Haverkamp goto fatal_error; 92912eb4683SFrank Haverkamp } 93012eb4683SFrank Haverkamp 93112eb4683SFrank Haverkamp app_unitcfg = __genwqe_readq(cd, IO_APP_UNITCFG); 93212eb4683SFrank Haverkamp if (app_unitcfg == IO_ILLEGAL_VALUE) { 93312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 93412eb4683SFrank Haverkamp "[%s] APP_UNITCFG=%016llx\n", 93512eb4683SFrank Haverkamp __func__, app_unitcfg); 93612eb4683SFrank Haverkamp goto fatal_error; 93712eb4683SFrank Haverkamp } 93812eb4683SFrank Haverkamp 93912eb4683SFrank Haverkamp gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); 94012eb4683SFrank Haverkamp if (gfir == IO_ILLEGAL_VALUE) { 94112eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 94212eb4683SFrank Haverkamp "[%s] %s: GFIR=%016llx\n", __func__, 94312eb4683SFrank Haverkamp (gfir & GFIR_ERR_TRIGGER) ? "err" : "info", 94412eb4683SFrank Haverkamp gfir); 94512eb4683SFrank Haverkamp goto fatal_error; 94612eb4683SFrank Haverkamp } 94712eb4683SFrank Haverkamp 94812eb4683SFrank Haverkamp gfir_masked = genwqe_fir_checking(cd); 94912eb4683SFrank Haverkamp if (gfir_masked == IO_ILLEGAL_VALUE) 95012eb4683SFrank Haverkamp goto fatal_error; 95112eb4683SFrank Haverkamp 95212eb4683SFrank Haverkamp /* 95312eb4683SFrank Haverkamp * GFIR ErrorTrigger bits set => reset the card! 95412eb4683SFrank Haverkamp * Never do this for old/manufacturing images! 95512eb4683SFrank Haverkamp */ 95612eb4683SFrank Haverkamp if ((gfir_masked) && !cd->skip_recovery && 95712eb4683SFrank Haverkamp genwqe_recovery_on_fatal_gfir_required(cd)) { 95812eb4683SFrank Haverkamp 95912eb4683SFrank Haverkamp cd->card_state = GENWQE_CARD_FATAL_ERROR; 96012eb4683SFrank Haverkamp 96112eb4683SFrank Haverkamp rc = genwqe_recover_card(cd, 0); 96212eb4683SFrank Haverkamp if (rc < 0) { 96312eb4683SFrank Haverkamp /* FIXME Card is unusable and needs unbind! */ 96412eb4683SFrank Haverkamp goto fatal_error; 96512eb4683SFrank Haverkamp } 96612eb4683SFrank Haverkamp } 96712eb4683SFrank Haverkamp 968c1f732adSKleber Sacilotto de Souza if (cd->card_state == GENWQE_CARD_RELOAD_BITSTREAM) { 969c1f732adSKleber Sacilotto de Souza /* Userspace requested card bitstream reload */ 970c1f732adSKleber Sacilotto de Souza rc = genwqe_reload_bistream(cd); 971c1f732adSKleber Sacilotto de Souza if (rc) 972c1f732adSKleber Sacilotto de Souza goto fatal_error; 973c1f732adSKleber Sacilotto de Souza } 974c1f732adSKleber Sacilotto de Souza 97512eb4683SFrank Haverkamp cd->last_gfir = gfir; 97612eb4683SFrank Haverkamp cond_resched(); 97712eb4683SFrank Haverkamp } 97812eb4683SFrank Haverkamp 97912eb4683SFrank Haverkamp return 0; 98012eb4683SFrank Haverkamp 98112eb4683SFrank Haverkamp fatal_error: 982fb145456SKleber Sacilotto de Souza if (cd->use_platform_recovery) { 983fb145456SKleber Sacilotto de Souza /* 984fb145456SKleber Sacilotto de Souza * Since we use raw accessors, EEH errors won't be detected 985fb145456SKleber Sacilotto de Souza * by the platform until we do a non-raw MMIO or config space 986fb145456SKleber Sacilotto de Souza * read 987fb145456SKleber Sacilotto de Souza */ 988fb145456SKleber Sacilotto de Souza readq(cd->mmio + IO_SLC_CFGREG_GFIR); 989fb145456SKleber Sacilotto de Souza 990fb145456SKleber Sacilotto de Souza /* We do nothing if the card is going over PCI recovery */ 991fb145456SKleber Sacilotto de Souza if (pci_channel_offline(pci_dev)) 992fb145456SKleber Sacilotto de Souza return -EIO; 99393b772b2SKleber Sacilotto de Souza 99493b772b2SKleber Sacilotto de Souza /* 99593b772b2SKleber Sacilotto de Souza * If it's supported by the platform, we try a fundamental reset 99693b772b2SKleber Sacilotto de Souza * to recover from a fatal error. Otherwise, we continue to wait 99793b772b2SKleber Sacilotto de Souza * for an external recovery procedure to take care of it. 99893b772b2SKleber Sacilotto de Souza */ 99993b772b2SKleber Sacilotto de Souza rc = genwqe_platform_recovery(cd); 100093b772b2SKleber Sacilotto de Souza if (!rc) 100193b772b2SKleber Sacilotto de Souza goto health_thread_begin; 1002fb145456SKleber Sacilotto de Souza } 1003fb145456SKleber Sacilotto de Souza 100412eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 100512eb4683SFrank Haverkamp "[%s] card unusable. Please trigger unbind!\n", __func__); 100612eb4683SFrank Haverkamp 100712eb4683SFrank Haverkamp /* Bring down logical devices to inform user space via udev remove. */ 100812eb4683SFrank Haverkamp cd->card_state = GENWQE_CARD_FATAL_ERROR; 100912eb4683SFrank Haverkamp genwqe_stop(cd); 101012eb4683SFrank Haverkamp 101112eb4683SFrank Haverkamp /* genwqe_bus_reset failed(). Now wait for genwqe_remove(). */ 101212eb4683SFrank Haverkamp while (!kthread_should_stop()) 101312eb4683SFrank Haverkamp cond_resched(); 101412eb4683SFrank Haverkamp 101512eb4683SFrank Haverkamp return -EIO; 101612eb4683SFrank Haverkamp } 101712eb4683SFrank Haverkamp 101812eb4683SFrank Haverkamp static int genwqe_health_check_start(struct genwqe_dev *cd) 101912eb4683SFrank Haverkamp { 102012eb4683SFrank Haverkamp int rc; 102112eb4683SFrank Haverkamp 10229d14e766SGuilherme G. Piccoli if (GENWQE_HEALTH_CHECK_INTERVAL <= 0) 102312eb4683SFrank Haverkamp return 0; /* valid for disabling the service */ 102412eb4683SFrank Haverkamp 102512eb4683SFrank Haverkamp /* moved before request_irq() */ 102612eb4683SFrank Haverkamp /* init_waitqueue_head(&cd->health_waitq); */ 102712eb4683SFrank Haverkamp 102812eb4683SFrank Haverkamp cd->health_thread = kthread_run(genwqe_health_thread, cd, 102912eb4683SFrank Haverkamp GENWQE_DEVNAME "%d_health", 103012eb4683SFrank Haverkamp cd->card_idx); 103112eb4683SFrank Haverkamp if (IS_ERR(cd->health_thread)) { 103212eb4683SFrank Haverkamp rc = PTR_ERR(cd->health_thread); 103312eb4683SFrank Haverkamp cd->health_thread = NULL; 103412eb4683SFrank Haverkamp return rc; 103512eb4683SFrank Haverkamp } 103612eb4683SFrank Haverkamp return 0; 103712eb4683SFrank Haverkamp } 103812eb4683SFrank Haverkamp 103912eb4683SFrank Haverkamp static int genwqe_health_thread_running(struct genwqe_dev *cd) 104012eb4683SFrank Haverkamp { 104112eb4683SFrank Haverkamp return cd->health_thread != NULL; 104212eb4683SFrank Haverkamp } 104312eb4683SFrank Haverkamp 104412eb4683SFrank Haverkamp static int genwqe_health_check_stop(struct genwqe_dev *cd) 104512eb4683SFrank Haverkamp { 104612eb4683SFrank Haverkamp int rc; 104712eb4683SFrank Haverkamp 104812eb4683SFrank Haverkamp if (!genwqe_health_thread_running(cd)) 104912eb4683SFrank Haverkamp return -EIO; 105012eb4683SFrank Haverkamp 105112eb4683SFrank Haverkamp rc = kthread_stop(cd->health_thread); 105212eb4683SFrank Haverkamp cd->health_thread = NULL; 105312eb4683SFrank Haverkamp return 0; 105412eb4683SFrank Haverkamp } 105512eb4683SFrank Haverkamp 105612eb4683SFrank Haverkamp /** 105712eb4683SFrank Haverkamp * genwqe_pci_setup() - Allocate PCIe related resources for our card 105812eb4683SFrank Haverkamp */ 105912eb4683SFrank Haverkamp static int genwqe_pci_setup(struct genwqe_dev *cd) 106012eb4683SFrank Haverkamp { 1061f03774bdSJohannes Thumshirn int err; 106212eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 106312eb4683SFrank Haverkamp 106412eb4683SFrank Haverkamp err = pci_enable_device_mem(pci_dev); 106512eb4683SFrank Haverkamp if (err) { 106612eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 106712eb4683SFrank Haverkamp "err: failed to enable pci memory (err=%d)\n", err); 106812eb4683SFrank Haverkamp goto err_out; 106912eb4683SFrank Haverkamp } 107012eb4683SFrank Haverkamp 107112eb4683SFrank Haverkamp /* Reserve PCI I/O and memory resources */ 1072f03774bdSJohannes Thumshirn err = pci_request_mem_regions(pci_dev, genwqe_driver_name); 107312eb4683SFrank Haverkamp if (err) { 107412eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 107512eb4683SFrank Haverkamp "[%s] err: request bars failed (%d)\n", __func__, err); 107612eb4683SFrank Haverkamp err = -EIO; 107712eb4683SFrank Haverkamp goto err_disable_device; 107812eb4683SFrank Haverkamp } 107912eb4683SFrank Haverkamp 108012eb4683SFrank Haverkamp /* check for 64-bit DMA address supported (DAC) */ 108112eb4683SFrank Haverkamp if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) { 108212eb4683SFrank Haverkamp err = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(64)); 108312eb4683SFrank Haverkamp if (err) { 108412eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 108512eb4683SFrank Haverkamp "err: DMA64 consistent mask error\n"); 108612eb4683SFrank Haverkamp err = -EIO; 108712eb4683SFrank Haverkamp goto out_release_resources; 108812eb4683SFrank Haverkamp } 108912eb4683SFrank Haverkamp /* check for 32-bit DMA address supported (SAC) */ 109012eb4683SFrank Haverkamp } else if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { 109112eb4683SFrank Haverkamp err = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(32)); 109212eb4683SFrank Haverkamp if (err) { 109312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 109412eb4683SFrank Haverkamp "err: DMA32 consistent mask error\n"); 109512eb4683SFrank Haverkamp err = -EIO; 109612eb4683SFrank Haverkamp goto out_release_resources; 109712eb4683SFrank Haverkamp } 109812eb4683SFrank Haverkamp } else { 109912eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 110012eb4683SFrank Haverkamp "err: neither DMA32 nor DMA64 supported\n"); 110112eb4683SFrank Haverkamp err = -EIO; 110212eb4683SFrank Haverkamp goto out_release_resources; 110312eb4683SFrank Haverkamp } 110412eb4683SFrank Haverkamp 110512eb4683SFrank Haverkamp pci_set_master(pci_dev); 110612eb4683SFrank Haverkamp pci_enable_pcie_error_reporting(pci_dev); 110712eb4683SFrank Haverkamp 1108fb145456SKleber Sacilotto de Souza /* EEH recovery requires PCIe fundamental reset */ 1109fb145456SKleber Sacilotto de Souza pci_dev->needs_freset = 1; 1110fb145456SKleber Sacilotto de Souza 111112eb4683SFrank Haverkamp /* request complete BAR-0 space (length = 0) */ 111212eb4683SFrank Haverkamp cd->mmio_len = pci_resource_len(pci_dev, 0); 111312eb4683SFrank Haverkamp cd->mmio = pci_iomap(pci_dev, 0, 0); 111412eb4683SFrank Haverkamp if (cd->mmio == NULL) { 111512eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 111612eb4683SFrank Haverkamp "[%s] err: mapping BAR0 failed\n", __func__); 111712eb4683SFrank Haverkamp err = -ENOMEM; 111812eb4683SFrank Haverkamp goto out_release_resources; 111912eb4683SFrank Haverkamp } 112012eb4683SFrank Haverkamp 112112eb4683SFrank Haverkamp cd->num_vfs = pci_sriov_get_totalvfs(pci_dev); 112295a8825cSFrank Haverkamp if (cd->num_vfs < 0) 112395a8825cSFrank Haverkamp cd->num_vfs = 0; 112412eb4683SFrank Haverkamp 112512eb4683SFrank Haverkamp err = genwqe_read_ids(cd); 112612eb4683SFrank Haverkamp if (err) 112712eb4683SFrank Haverkamp goto out_iounmap; 112812eb4683SFrank Haverkamp 112912eb4683SFrank Haverkamp return 0; 113012eb4683SFrank Haverkamp 113112eb4683SFrank Haverkamp out_iounmap: 113212eb4683SFrank Haverkamp pci_iounmap(pci_dev, cd->mmio); 113312eb4683SFrank Haverkamp out_release_resources: 1134f03774bdSJohannes Thumshirn pci_release_mem_regions(pci_dev); 113512eb4683SFrank Haverkamp err_disable_device: 113612eb4683SFrank Haverkamp pci_disable_device(pci_dev); 113712eb4683SFrank Haverkamp err_out: 113812eb4683SFrank Haverkamp return err; 113912eb4683SFrank Haverkamp } 114012eb4683SFrank Haverkamp 114112eb4683SFrank Haverkamp /** 114212eb4683SFrank Haverkamp * genwqe_pci_remove() - Free PCIe related resources for our card 114312eb4683SFrank Haverkamp */ 114412eb4683SFrank Haverkamp static void genwqe_pci_remove(struct genwqe_dev *cd) 114512eb4683SFrank Haverkamp { 114612eb4683SFrank Haverkamp struct pci_dev *pci_dev = cd->pci_dev; 114712eb4683SFrank Haverkamp 114812eb4683SFrank Haverkamp if (cd->mmio) 114912eb4683SFrank Haverkamp pci_iounmap(pci_dev, cd->mmio); 115012eb4683SFrank Haverkamp 1151f03774bdSJohannes Thumshirn pci_release_mem_regions(pci_dev); 115212eb4683SFrank Haverkamp pci_disable_device(pci_dev); 115312eb4683SFrank Haverkamp } 115412eb4683SFrank Haverkamp 115512eb4683SFrank Haverkamp /** 115612eb4683SFrank Haverkamp * genwqe_probe() - Device initialization 115712eb4683SFrank Haverkamp * @pdev: PCI device information struct 115812eb4683SFrank Haverkamp * 115912eb4683SFrank Haverkamp * Callable for multiple cards. This function is called on bind. 116012eb4683SFrank Haverkamp * 116112eb4683SFrank Haverkamp * Return: 0 if succeeded, < 0 when failed 116212eb4683SFrank Haverkamp */ 116312eb4683SFrank Haverkamp static int genwqe_probe(struct pci_dev *pci_dev, 116412eb4683SFrank Haverkamp const struct pci_device_id *id) 116512eb4683SFrank Haverkamp { 116612eb4683SFrank Haverkamp int err; 116712eb4683SFrank Haverkamp struct genwqe_dev *cd; 116812eb4683SFrank Haverkamp 116912eb4683SFrank Haverkamp genwqe_init_crc32(); 117012eb4683SFrank Haverkamp 117112eb4683SFrank Haverkamp cd = genwqe_dev_alloc(); 117212eb4683SFrank Haverkamp if (IS_ERR(cd)) { 117312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "err: could not alloc mem (err=%d)!\n", 117412eb4683SFrank Haverkamp (int)PTR_ERR(cd)); 117512eb4683SFrank Haverkamp return PTR_ERR(cd); 117612eb4683SFrank Haverkamp } 117712eb4683SFrank Haverkamp 117812eb4683SFrank Haverkamp dev_set_drvdata(&pci_dev->dev, cd); 117912eb4683SFrank Haverkamp cd->pci_dev = pci_dev; 118012eb4683SFrank Haverkamp 118112eb4683SFrank Haverkamp err = genwqe_pci_setup(cd); 118212eb4683SFrank Haverkamp if (err < 0) { 118312eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 118412eb4683SFrank Haverkamp "err: problems with PCI setup (err=%d)\n", err); 118512eb4683SFrank Haverkamp goto out_free_dev; 118612eb4683SFrank Haverkamp } 118712eb4683SFrank Haverkamp 118812eb4683SFrank Haverkamp err = genwqe_start(cd); 118912eb4683SFrank Haverkamp if (err < 0) { 119012eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 119112eb4683SFrank Haverkamp "err: cannot start card services! (err=%d)\n", err); 119212eb4683SFrank Haverkamp goto out_pci_remove; 119312eb4683SFrank Haverkamp } 119412eb4683SFrank Haverkamp 119512eb4683SFrank Haverkamp if (genwqe_is_privileged(cd)) { 119612eb4683SFrank Haverkamp err = genwqe_health_check_start(cd); 119712eb4683SFrank Haverkamp if (err < 0) { 119812eb4683SFrank Haverkamp dev_err(&pci_dev->dev, 1199d9c11d45SFrank Haverkamp "err: cannot start health checking! (err=%d)\n", 1200d9c11d45SFrank Haverkamp err); 120112eb4683SFrank Haverkamp goto out_stop_services; 120212eb4683SFrank Haverkamp } 120312eb4683SFrank Haverkamp } 120412eb4683SFrank Haverkamp return 0; 120512eb4683SFrank Haverkamp 120612eb4683SFrank Haverkamp out_stop_services: 120712eb4683SFrank Haverkamp genwqe_stop(cd); 120812eb4683SFrank Haverkamp out_pci_remove: 120912eb4683SFrank Haverkamp genwqe_pci_remove(cd); 121012eb4683SFrank Haverkamp out_free_dev: 121112eb4683SFrank Haverkamp genwqe_dev_free(cd); 121212eb4683SFrank Haverkamp return err; 121312eb4683SFrank Haverkamp } 121412eb4683SFrank Haverkamp 121512eb4683SFrank Haverkamp /** 121612eb4683SFrank Haverkamp * genwqe_remove() - Called when device is removed (hot-plugable) 121712eb4683SFrank Haverkamp * 121812eb4683SFrank Haverkamp * Or when driver is unloaded respecitively when unbind is done. 121912eb4683SFrank Haverkamp */ 122012eb4683SFrank Haverkamp static void genwqe_remove(struct pci_dev *pci_dev) 122112eb4683SFrank Haverkamp { 122212eb4683SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); 122312eb4683SFrank Haverkamp 122412eb4683SFrank Haverkamp genwqe_health_check_stop(cd); 122512eb4683SFrank Haverkamp 122612eb4683SFrank Haverkamp /* 122712eb4683SFrank Haverkamp * genwqe_stop() must survive if it is called twice 122812eb4683SFrank Haverkamp * sequentially. This happens when the health thread calls it 122912eb4683SFrank Haverkamp * and fails on genwqe_bus_reset(). 123012eb4683SFrank Haverkamp */ 123112eb4683SFrank Haverkamp genwqe_stop(cd); 123212eb4683SFrank Haverkamp genwqe_pci_remove(cd); 123312eb4683SFrank Haverkamp genwqe_dev_free(cd); 123412eb4683SFrank Haverkamp } 123512eb4683SFrank Haverkamp 123612eb4683SFrank Haverkamp /* 123712eb4683SFrank Haverkamp * genwqe_err_error_detected() - Error detection callback 123812eb4683SFrank Haverkamp * 123912eb4683SFrank Haverkamp * This callback is called by the PCI subsystem whenever a PCI bus 124012eb4683SFrank Haverkamp * error is detected. 124112eb4683SFrank Haverkamp */ 124212eb4683SFrank Haverkamp static pci_ers_result_t genwqe_err_error_detected(struct pci_dev *pci_dev, 124312eb4683SFrank Haverkamp enum pci_channel_state state) 124412eb4683SFrank Haverkamp { 124512eb4683SFrank Haverkamp struct genwqe_dev *cd; 124612eb4683SFrank Haverkamp 124712eb4683SFrank Haverkamp dev_err(&pci_dev->dev, "[%s] state=%d\n", __func__, state); 124812eb4683SFrank Haverkamp 124912eb4683SFrank Haverkamp cd = dev_get_drvdata(&pci_dev->dev); 125012eb4683SFrank Haverkamp if (cd == NULL) 125112eb4683SFrank Haverkamp return PCI_ERS_RESULT_DISCONNECT; 1252fb145456SKleber Sacilotto de Souza 1253fb145456SKleber Sacilotto de Souza /* Stop the card */ 1254fb145456SKleber Sacilotto de Souza genwqe_health_check_stop(cd); 1255fb145456SKleber Sacilotto de Souza genwqe_stop(cd); 1256fb145456SKleber Sacilotto de Souza 1257fb145456SKleber Sacilotto de Souza /* 1258fb145456SKleber Sacilotto de Souza * On permanent failure, the PCI code will call device remove 1259fb145456SKleber Sacilotto de Souza * after the return of this function. 1260fb145456SKleber Sacilotto de Souza * genwqe_stop() can be called twice. 1261fb145456SKleber Sacilotto de Souza */ 1262fb145456SKleber Sacilotto de Souza if (state == pci_channel_io_perm_failure) { 1263fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_DISCONNECT; 1264fb145456SKleber Sacilotto de Souza } else { 1265fb145456SKleber Sacilotto de Souza genwqe_pci_remove(cd); 1266fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_NEED_RESET; 1267fb145456SKleber Sacilotto de Souza } 126812eb4683SFrank Haverkamp } 126912eb4683SFrank Haverkamp 1270fb145456SKleber Sacilotto de Souza static pci_ers_result_t genwqe_err_slot_reset(struct pci_dev *pci_dev) 1271fb145456SKleber Sacilotto de Souza { 1272fb145456SKleber Sacilotto de Souza int rc; 1273fb145456SKleber Sacilotto de Souza struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); 1274fb145456SKleber Sacilotto de Souza 1275fb145456SKleber Sacilotto de Souza rc = genwqe_pci_setup(cd); 1276fb145456SKleber Sacilotto de Souza if (!rc) { 1277fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_RECOVERED; 1278fb145456SKleber Sacilotto de Souza } else { 1279fb145456SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 1280fb145456SKleber Sacilotto de Souza "err: problems with PCI setup (err=%d)\n", rc); 1281fb145456SKleber Sacilotto de Souza return PCI_ERS_RESULT_DISCONNECT; 1282fb145456SKleber Sacilotto de Souza } 128312eb4683SFrank Haverkamp } 128412eb4683SFrank Haverkamp 128512eb4683SFrank Haverkamp static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev) 128612eb4683SFrank Haverkamp { 128712eb4683SFrank Haverkamp return PCI_ERS_RESULT_NONE; 128812eb4683SFrank Haverkamp } 128912eb4683SFrank Haverkamp 1290fb145456SKleber Sacilotto de Souza static void genwqe_err_resume(struct pci_dev *pci_dev) 129112eb4683SFrank Haverkamp { 1292fb145456SKleber Sacilotto de Souza int rc; 1293fb145456SKleber Sacilotto de Souza struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); 1294fb145456SKleber Sacilotto de Souza 1295fb145456SKleber Sacilotto de Souza rc = genwqe_start(cd); 1296fb145456SKleber Sacilotto de Souza if (!rc) { 1297fb145456SKleber Sacilotto de Souza rc = genwqe_health_check_start(cd); 1298fb145456SKleber Sacilotto de Souza if (rc) 1299fb145456SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 1300fb145456SKleber Sacilotto de Souza "err: cannot start health checking! (err=%d)\n", 1301fb145456SKleber Sacilotto de Souza rc); 1302fb145456SKleber Sacilotto de Souza } else { 1303fb145456SKleber Sacilotto de Souza dev_err(&pci_dev->dev, 1304fb145456SKleber Sacilotto de Souza "err: cannot start card services! (err=%d)\n", rc); 1305fb145456SKleber Sacilotto de Souza } 130612eb4683SFrank Haverkamp } 130712eb4683SFrank Haverkamp 130812eb4683SFrank Haverkamp static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs) 130912eb4683SFrank Haverkamp { 1310bc407dd3SFrank Haverkamp int rc; 131112eb4683SFrank Haverkamp struct genwqe_dev *cd = dev_get_drvdata(&dev->dev); 131212eb4683SFrank Haverkamp 131312eb4683SFrank Haverkamp if (numvfs > 0) { 131412eb4683SFrank Haverkamp genwqe_setup_vf_jtimer(cd); 1315bc407dd3SFrank Haverkamp rc = pci_enable_sriov(dev, numvfs); 1316bc407dd3SFrank Haverkamp if (rc < 0) 1317bc407dd3SFrank Haverkamp return rc; 131812eb4683SFrank Haverkamp return numvfs; 131912eb4683SFrank Haverkamp } 132012eb4683SFrank Haverkamp if (numvfs == 0) { 132112eb4683SFrank Haverkamp pci_disable_sriov(dev); 132212eb4683SFrank Haverkamp return 0; 132312eb4683SFrank Haverkamp } 132412eb4683SFrank Haverkamp return 0; 132512eb4683SFrank Haverkamp } 132612eb4683SFrank Haverkamp 132712eb4683SFrank Haverkamp static struct pci_error_handlers genwqe_err_handler = { 132812eb4683SFrank Haverkamp .error_detected = genwqe_err_error_detected, 132912eb4683SFrank Haverkamp .mmio_enabled = genwqe_err_result_none, 1330fb145456SKleber Sacilotto de Souza .slot_reset = genwqe_err_slot_reset, 133112eb4683SFrank Haverkamp .resume = genwqe_err_resume, 133212eb4683SFrank Haverkamp }; 133312eb4683SFrank Haverkamp 133412eb4683SFrank Haverkamp static struct pci_driver genwqe_driver = { 133512eb4683SFrank Haverkamp .name = genwqe_driver_name, 133612eb4683SFrank Haverkamp .id_table = genwqe_device_table, 133712eb4683SFrank Haverkamp .probe = genwqe_probe, 133812eb4683SFrank Haverkamp .remove = genwqe_remove, 133912eb4683SFrank Haverkamp .sriov_configure = genwqe_sriov_configure, 134012eb4683SFrank Haverkamp .err_handler = &genwqe_err_handler, 134112eb4683SFrank Haverkamp }; 134212eb4683SFrank Haverkamp 134312eb4683SFrank Haverkamp /** 13445ed22cebSFrank Haverkamp * genwqe_devnode() - Set default access mode for genwqe devices. 13455ed22cebSFrank Haverkamp * 13465ed22cebSFrank Haverkamp * Default mode should be rw for everybody. Do not change default 13475ed22cebSFrank Haverkamp * device name. 13485ed22cebSFrank Haverkamp */ 13495ed22cebSFrank Haverkamp static char *genwqe_devnode(struct device *dev, umode_t *mode) 13505ed22cebSFrank Haverkamp { 13515ed22cebSFrank Haverkamp if (mode) 13525ed22cebSFrank Haverkamp *mode = 0666; 13535ed22cebSFrank Haverkamp return NULL; 13545ed22cebSFrank Haverkamp } 13555ed22cebSFrank Haverkamp 13565ed22cebSFrank Haverkamp /** 135712eb4683SFrank Haverkamp * genwqe_init_module() - Driver registration and initialization 135812eb4683SFrank Haverkamp */ 135912eb4683SFrank Haverkamp static int __init genwqe_init_module(void) 136012eb4683SFrank Haverkamp { 136112eb4683SFrank Haverkamp int rc; 136212eb4683SFrank Haverkamp 136312eb4683SFrank Haverkamp class_genwqe = class_create(THIS_MODULE, GENWQE_DEVNAME); 136412eb4683SFrank Haverkamp if (IS_ERR(class_genwqe)) { 136512eb4683SFrank Haverkamp pr_err("[%s] create class failed\n", __func__); 136612eb4683SFrank Haverkamp return -ENOMEM; 136712eb4683SFrank Haverkamp } 136812eb4683SFrank Haverkamp 13695ed22cebSFrank Haverkamp class_genwqe->devnode = genwqe_devnode; 13705ed22cebSFrank Haverkamp 137112eb4683SFrank Haverkamp debugfs_genwqe = debugfs_create_dir(GENWQE_DEVNAME, NULL); 137212eb4683SFrank Haverkamp if (!debugfs_genwqe) { 137312eb4683SFrank Haverkamp rc = -ENOMEM; 137412eb4683SFrank Haverkamp goto err_out; 137512eb4683SFrank Haverkamp } 137612eb4683SFrank Haverkamp 137712eb4683SFrank Haverkamp rc = pci_register_driver(&genwqe_driver); 137812eb4683SFrank Haverkamp if (rc != 0) { 137912eb4683SFrank Haverkamp pr_err("[%s] pci_reg_driver (rc=%d)\n", __func__, rc); 138012eb4683SFrank Haverkamp goto err_out0; 138112eb4683SFrank Haverkamp } 138212eb4683SFrank Haverkamp 138312eb4683SFrank Haverkamp return rc; 138412eb4683SFrank Haverkamp 138512eb4683SFrank Haverkamp err_out0: 138612eb4683SFrank Haverkamp debugfs_remove(debugfs_genwqe); 138712eb4683SFrank Haverkamp err_out: 138812eb4683SFrank Haverkamp class_destroy(class_genwqe); 138912eb4683SFrank Haverkamp return rc; 139012eb4683SFrank Haverkamp } 139112eb4683SFrank Haverkamp 139212eb4683SFrank Haverkamp /** 139312eb4683SFrank Haverkamp * genwqe_exit_module() - Driver exit 139412eb4683SFrank Haverkamp */ 139512eb4683SFrank Haverkamp static void __exit genwqe_exit_module(void) 139612eb4683SFrank Haverkamp { 139712eb4683SFrank Haverkamp pci_unregister_driver(&genwqe_driver); 139812eb4683SFrank Haverkamp debugfs_remove(debugfs_genwqe); 139912eb4683SFrank Haverkamp class_destroy(class_genwqe); 140012eb4683SFrank Haverkamp } 140112eb4683SFrank Haverkamp 140212eb4683SFrank Haverkamp module_init(genwqe_init_module); 140312eb4683SFrank Haverkamp module_exit(genwqe_exit_module); 1404