linux/arch/s390/pci/pci_event.c
<<
>>
Prefs
   1/*
   2 *  Copyright IBM Corp. 2012
   3 *
   4 *  Author(s):
   5 *    Jan Glauber <jang@linux.vnet.ibm.com>
   6 */
   7
   8#define KMSG_COMPONENT "zpci"
   9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  10
  11#include <linux/kernel.h>
  12#include <linux/pci.h>
  13#include <asm/pci_debug.h>
  14#include <asm/sclp.h>
  15
  16/* Content Code Description for PCI Function Error */
  17struct zpci_ccdf_err {
  18        u32 reserved1;
  19        u32 fh;                         /* function handle */
  20        u32 fid;                        /* function id */
  21        u32 ett         :  4;           /* expected table type */
  22        u32 mvn         : 12;           /* MSI vector number */
  23        u32 dmaas       :  8;           /* DMA address space */
  24        u32             :  6;
  25        u32 q           :  1;           /* event qualifier */
  26        u32 rw          :  1;           /* read/write */
  27        u64 faddr;                      /* failing address */
  28        u32 reserved3;
  29        u16 reserved4;
  30        u16 pec;                        /* PCI event code */
  31} __packed;
  32
  33/* Content Code Description for PCI Function Availability */
  34struct zpci_ccdf_avail {
  35        u32 reserved1;
  36        u32 fh;                         /* function handle */
  37        u32 fid;                        /* function id */
  38        u32 reserved2;
  39        u32 reserved3;
  40        u32 reserved4;
  41        u32 reserved5;
  42        u16 reserved6;
  43        u16 pec;                        /* PCI event code */
  44} __packed;
  45
  46static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
  47{
  48        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
  49        struct pci_dev *pdev = NULL;
  50
  51        zpci_err("error CCDF:\n");
  52        zpci_err_hex(ccdf, sizeof(*ccdf));
  53
  54        if (zdev)
  55                pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
  56
  57        pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
  58               pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
  59
  60        if (!pdev)
  61                return;
  62
  63        pdev->error_state = pci_channel_io_perm_failure;
  64        pci_dev_put(pdev);
  65}
  66
  67void zpci_event_error(void *data)
  68{
  69        if (zpci_is_enabled())
  70                __zpci_event_error(data);
  71}
  72
  73static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
  74{
  75        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
  76        struct pci_dev *pdev = NULL;
  77        int ret;
  78
  79        if (zdev)
  80                pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
  81
  82        pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
  83                pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
  84        zpci_err("avail CCDF:\n");
  85        zpci_err_hex(ccdf, sizeof(*ccdf));
  86
  87        switch (ccdf->pec) {
  88        case 0x0301: /* Reserved|Standby -> Configured */
  89                if (!zdev) {
  90                        ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
  91                        if (ret)
  92                                break;
  93                        zdev = get_zdev_by_fid(ccdf->fid);
  94                }
  95                if (!zdev || zdev->state != ZPCI_FN_STATE_STANDBY)
  96                        break;
  97                zdev->state = ZPCI_FN_STATE_CONFIGURED;
  98                zdev->fh = ccdf->fh;
  99                ret = zpci_enable_device(zdev);
 100                if (ret)
 101                        break;
 102                pci_lock_rescan_remove();
 103                pci_rescan_bus(zdev->bus);
 104                pci_unlock_rescan_remove();
 105                break;
 106        case 0x0302: /* Reserved -> Standby */
 107                if (!zdev)
 108                        clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
 109                break;
 110        case 0x0303: /* Deconfiguration requested */
 111                if (pdev)
 112                        pci_stop_and_remove_bus_device_locked(pdev);
 113
 114                ret = zpci_disable_device(zdev);
 115                if (ret)
 116                        break;
 117
 118                ret = sclp_pci_deconfigure(zdev->fid);
 119                zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
 120                if (!ret)
 121                        zdev->state = ZPCI_FN_STATE_STANDBY;
 122
 123                break;
 124        case 0x0304: /* Configured -> Standby */
 125                if (pdev) {
 126                        /* Give the driver a hint that the function is
 127                         * already unusable. */
 128                        pdev->error_state = pci_channel_io_perm_failure;
 129                        pci_stop_and_remove_bus_device_locked(pdev);
 130                }
 131
 132                zdev->fh = ccdf->fh;
 133                zpci_disable_device(zdev);
 134                zdev->state = ZPCI_FN_STATE_STANDBY;
 135                break;
 136        case 0x0306: /* 0x308 or 0x302 for multiple devices */
 137                clp_rescan_pci_devices();
 138                break;
 139        case 0x0308: /* Standby -> Reserved */
 140                if (!zdev)
 141                        break;
 142                pci_stop_root_bus(zdev->bus);
 143                pci_remove_root_bus(zdev->bus);
 144                break;
 145        default:
 146                break;
 147        }
 148        pci_dev_put(pdev);
 149}
 150
 151void zpci_event_availability(void *data)
 152{
 153        if (zpci_is_enabled())
 154                __zpci_event_availability(data);
 155}
 156