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 #include <asm/pci_debug.h> 14 15 /* Content Code Description for PCI Function Error */ 16 struct zpci_ccdf_err { 17 u32 reserved1; 18 u32 fh; /* function handle */ 19 u32 fid; /* function id */ 20 u32 ett : 4; /* expected table type */ 21 u32 mvn : 12; /* MSI vector number */ 22 u32 dmaas : 8; /* DMA address space */ 23 u32 : 6; 24 u32 q : 1; /* event qualifier */ 25 u32 rw : 1; /* read/write */ 26 u64 faddr; /* failing address */ 27 u32 reserved3; 28 u16 reserved4; 29 u16 pec; /* PCI event code */ 30 } __packed; 31 32 /* Content Code Description for PCI Function Availability */ 33 struct zpci_ccdf_avail { 34 u32 reserved1; 35 u32 fh; /* function handle */ 36 u32 fid; /* function id */ 37 u32 reserved2; 38 u32 reserved3; 39 u32 reserved4; 40 u32 reserved5; 41 u16 reserved6; 42 u16 pec; /* PCI event code */ 43 } __packed; 44 45 static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf) 46 { 47 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); 48 struct pci_dev *pdev = zdev ? zdev->pdev : NULL; 49 50 pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n", 51 pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid); 52 zpci_err("avail CCDF:\n"); 53 zpci_err_hex(ccdf, sizeof(*ccdf)); 54 55 switch (ccdf->pec) { 56 case 0x0301: 57 zpci_enable_device(zdev); 58 break; 59 case 0x0302: 60 clp_add_pci_device(ccdf->fid, ccdf->fh, 0); 61 break; 62 case 0x0306: 63 clp_rescan_pci_devices(); 64 break; 65 default: 66 break; 67 } 68 } 69 70 void zpci_event_error(void *data) 71 { 72 struct zpci_ccdf_err *ccdf = data; 73 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); 74 75 zpci_err("error CCDF:\n"); 76 zpci_err_hex(ccdf, sizeof(*ccdf)); 77 78 if (!zdev) 79 return; 80 81 pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n", 82 pci_name(zdev->pdev), ccdf->pec, ccdf->fid); 83 } 84 85 void zpci_event_availability(void *data) 86 { 87 zpci_event_log_avail(data); 88 } 89