1 /* 2 * Copyright IBM Corp. 2012 3 * 4 * Author(s): 5 * Jan Glauber <jang@linux.vnet.ibm.com> 6 */ 7 8 #define COMPONENT "zPCI" 9 #define pr_fmt(fmt) COMPONENT ": " fmt 10 11 #include <linux/kernel.h> 12 #include <linux/pci.h> 13 14 /* Content Code Description for PCI Function Error */ 15 struct zpci_ccdf_err { 16 u32 reserved1; 17 u32 fh; /* function handle */ 18 u32 fid; /* function id */ 19 u32 ett : 4; /* expected table type */ 20 u32 mvn : 12; /* MSI vector number */ 21 u32 dmaas : 8; /* DMA address space */ 22 u32 : 6; 23 u32 q : 1; /* event qualifier */ 24 u32 rw : 1; /* read/write */ 25 u64 faddr; /* failing address */ 26 u32 reserved3; 27 u16 reserved4; 28 u16 pec; /* PCI event code */ 29 } __packed; 30 31 /* Content Code Description for PCI Function Availability */ 32 struct zpci_ccdf_avail { 33 u32 reserved1; 34 u32 fh; /* function handle */ 35 u32 fid; /* function id */ 36 u32 reserved2; 37 u32 reserved3; 38 u32 reserved4; 39 u32 reserved5; 40 u16 reserved6; 41 u16 pec; /* PCI event code */ 42 } __packed; 43 44 static void zpci_event_log_err(struct zpci_ccdf_err *ccdf) 45 { 46 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); 47 48 zpci_err("SEI error CCD:\n"); 49 zpci_err_hex(ccdf, sizeof(*ccdf)); 50 dev_err(&zdev->pdev->dev, "event code: 0x%x\n", ccdf->pec); 51 } 52 53 static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf) 54 { 55 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); 56 57 pr_err("%s%s: availability event: fh: 0x%x fid: 0x%x event code: 0x%x reason:", 58 (zdev) ? dev_driver_string(&zdev->pdev->dev) : "?", 59 (zdev) ? dev_name(&zdev->pdev->dev) : "?", 60 ccdf->fh, ccdf->fid, ccdf->pec); 61 print_hex_dump(KERN_CONT, "ccdf", DUMP_PREFIX_OFFSET, 62 16, 1, ccdf, sizeof(*ccdf), false); 63 64 switch (ccdf->pec) { 65 case 0x0301: 66 zpci_enable_device(zdev); 67 break; 68 case 0x0302: 69 clp_add_pci_device(ccdf->fid, ccdf->fh, 0); 70 break; 71 case 0x0306: 72 clp_rescan_pci_devices(); 73 break; 74 default: 75 break; 76 } 77 } 78 79 void zpci_event_error(void *data) 80 { 81 struct zpci_ccdf_err *ccdf = data; 82 struct zpci_dev *zdev; 83 84 zpci_event_log_err(ccdf); 85 zdev = get_zdev_by_fid(ccdf->fid); 86 if (!zdev) { 87 pr_err("Error event for unknown fid: %x", ccdf->fid); 88 return; 89 } 90 } 91 92 void zpci_event_availability(void *data) 93 { 94 zpci_event_log_avail(data); 95 } 96