1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_PCIEV_H 27 #define _SYS_PCIEV_H 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 typedef struct pcie_eh_data { 34 uint16_t minor_ver; /* Minor data packet version, added data */ 35 uint16_t major_ver; /* Major data packet version, struct change */ 36 uint16_t pci_err_status; /* pci status register */ 37 uint16_t pci_bdg_sec_stat; /* PCI secondary status reg */ 38 uint32_t pcix_status; /* pcix status register */ 39 uint16_t pcix_bdg_sec_stat; /* pcix bridge secondary status reg */ 40 uint32_t pcix_bdg_stat; /* pcix bridge status reg */ 41 uint16_t pcix_ecc_control_0; /* pcix ecc control status reg */ 42 uint16_t pcix_ecc_status_0; /* pcix ecc control status reg */ 43 uint32_t pcix_ecc_fst_addr_0; /* pcix ecc first address reg */ 44 uint32_t pcix_ecc_sec_addr_0; /* pcix ecc second address reg */ 45 uint32_t pcix_ecc_attr_0; /* pcix ecc attributes reg */ 46 uint16_t pcix_ecc_control_1; /* pcix ecc control status reg */ 47 uint16_t pcix_ecc_status_1; /* pcix ecc control status reg */ 48 uint32_t pcix_ecc_fst_addr_1; /* pcix ecc first address reg */ 49 uint32_t pcix_ecc_sec_addr_1; /* pcix ecc second address reg */ 50 uint32_t pcix_ecc_attr_1; /* pcix ecc attributes reg */ 51 uint16_t pcie_err_status; /* pcie device status register */ 52 uint32_t pcie_ue_status; /* pcie ue error status reg */ 53 uint32_t pcie_ue_hdr[4]; /* pcie ue header log */ 54 uint32_t pcie_ce_status; /* pcie ce error status reg */ 55 uint32_t pcie_sue_status; /* pcie bridge secondary ue status */ 56 uint32_t pcie_sue_hdr[4]; /* pcie bridge secondary ue hdr log */ 57 uint16_t pcie_rp_ctl; /* root port control register */ 58 uint32_t pcie_rp_err_status; /* pcie root port error status reg */ 59 uint32_t pcie_rp_err_cmd; /* pcie root port error cmd reg */ 60 uint16_t pcie_rp_ce_src_id; /* pcie root port ce sourpe id */ 61 uint16_t pcie_rp_ue_src_id; /* pcie root port ue sourpe id */ 62 } pcie_eh_data_t; 63 64 typedef struct pcie_domains { 65 uint_t domain_id; 66 uint_t cached_count; /* Reference Count of cached dom id list */ 67 uint_t faulty_count; /* Reference Count of faulty dom id list */ 68 struct pcie_domains *cached_next; /* Next on cached dom id list */ 69 struct pcie_domains *faulty_prev; /* Prev on faulty dom id list */ 70 struct pcie_domains *faulty_next; /* Next on faulty dom id list */ 71 } pcie_domains_t; 72 73 typedef struct pcie_req_id_list { 74 pcie_req_id_t bdf; 75 struct pcie_req_id_list *next; 76 } pcie_req_id_list_t; 77 78 typedef struct pcie_child_domains { 79 pcie_domains_t *ids; 80 pcie_req_id_list_t *bdfs; 81 } pcie_child_domains_t; 82 83 /* 84 * IOV data structure: 85 * This data strucutre is now statically allocated during bus_p 86 * initializing time. Do we need to have this data structure for 87 * non-root domains? If not, is there a way to differentiate root 88 * domain and non-root domain so that we do the initialization for 89 * root domain only? 90 */ 91 typedef struct pcie_domain { 92 /* 93 * Bridges: 94 * Cache the domain/channel id and bdfs of all it's children. 95 * 96 * Leaves: 97 * Cache just the domain/channel id of self. 98 * Bridges will contain 0 <= N <= NumChild 99 * 100 * Note: 101 * there is no lock to protect the access to 102 * pcie_domains_t data struture. Currently we don't see 103 * the need for lock. But we need to pay attention if there 104 * might be issues when hotplug is enabled. 105 */ 106 union { 107 pcie_child_domains_t ids; 108 pcie_domains_t id; 109 } domain; 110 111 /* 112 * Reference count of the domain type for this device and it's children. 113 * For leaf devices, fmadom + nfma + root = 1 114 * For bridges, the sum of the counts = number of LEAF children. 115 * 116 * All devices start with a count of 1 for either nfmadom or rootdom. 117 */ 118 uint_t fmadom_count; /* FMA channel capable domain */ 119 uint_t nfmadom_count; /* Non-FMA channel domain */ 120 uint_t rootdom_count; /* Root domain */ 121 122 /* flag if the affected dev will cause guest domains to panic */ 123 boolean_t nfma_panic; 124 } pcie_domain_t; 125 126 extern void pcie_domain_list_add(uint_t, pcie_domains_t **); 127 extern void pcie_domain_list_remove(uint_t, pcie_domains_t *); 128 extern void pcie_save_domain_id(pcie_domains_t *); 129 extern void pcie_init_dom(dev_info_t *); 130 extern void pcie_fini_dom(dev_info_t *); 131 132 #define PCIE_ASSIGNED_TO_FMA_DOM(bus_p) \ 133 (!PCIE_IS_BDG(bus_p) && PCIE_BUS2DOM(bus_p)->fmadom_count > 0) 134 #define PCIE_ASSIGNED_TO_NFMA_DOM(bus_p) \ 135 (!PCIE_IS_BDG(bus_p) && PCIE_BUS2DOM(bus_p)->nfmadom_count > 0) 136 #define PCIE_ASSIGNED_TO_ROOT_DOM(bus_p) \ 137 (PCIE_IS_BDG(bus_p) || PCIE_BUS2DOM(bus_p)->rootdom_count > 0) 138 #define PCIE_BDG_HAS_CHILDREN_FMA_DOM(bus_p) \ 139 (PCIE_IS_BDG(bus_p) && PCIE_BUS2DOM(bus_p)->fmadom_count > 0) 140 #define PCIE_BDG_HAS_CHILDREN_NFMA_DOM(bus_p) \ 141 (PCIE_IS_BDG(bus_p) && PCIE_BUS2DOM(bus_p)->nfmadom_count > 0) 142 #define PCIE_BDG_HAS_CHILDREN_ROOT_DOM(bus_p) \ 143 (PCIE_IS_BDG(bus_p) && PCIE_BUS2DOM(bus_p)->rootdom_count > 0) 144 #define PCIE_IS_ASSIGNED(bus_p) \ 145 (!PCIE_ASSIGNED_TO_ROOT_DOM(bus_p)) 146 #define PCIE_BDG_IS_UNASSIGNED(bus_p) \ 147 (PCIE_IS_BDG(bus_p) && \ 148 (!PCIE_BDG_HAS_CHILDREN_NFMA_DOM(bus_p)) && \ 149 (!PCIE_BDG_HAS_CHILDREN_FMA_DOM(bus_p))) 150 151 152 #define PCIE_IN_DOMAIN(bus_p, id) (pcie_in_domain((bus_p), (id))) 153 154 /* Following macros are only valid for leaf devices */ 155 #define PCIE_DOMAIN_ID_GET(bus_p) \ 156 ((uint_t)(PCIE_IS_ASSIGNED(bus_p) \ 157 ? PCIE_BUS2DOM(bus_p)->domain.id.domain_id : 0)) 158 #define PCIE_DOMAIN_ID_SET(bus_p, new_id) \ 159 if (!PCIE_IS_BDG(bus_p)) \ 160 PCIE_BUS2DOM(bus_p)->domain.id.domain_id = (uint_t)(new_id) 161 #define PCIE_DOMAIN_ID_INCR_REF_COUNT(bus_p) \ 162 if (!PCIE_IS_BDG(bus_p)) \ 163 PCIE_BUS2DOM(bus_p)->domain.id.cached_count = 1; 164 #define PCIE_DOMAIN_ID_DECR_REF_COUNT(bus_p) \ 165 if (!PCIE_IS_BDG(bus_p)) \ 166 PCIE_BUS2DOM(bus_p)->domain.id.cached_count = 0; 167 168 /* Following macros are only valid for bridges */ 169 #define PCIE_DOMAIN_LIST_GET(bus_p) \ 170 ((pcie_domains_t *)(PCIE_IS_BDG(bus_p) ? \ 171 PCIE_BUS2DOM(bus_p)->domain.ids.ids : NULL)) 172 #define PCIE_DOMAIN_LIST_ADD(bus_p, domain_id) \ 173 if (PCIE_IS_BDG(bus_p)) \ 174 pcie_domain_list_add(domain_id, \ 175 &PCIE_BUS2DOM(bus_p)->domain.ids.ids) 176 #define PCIE_DOMAIN_LIST_REMOVE(bus_p, domain_id) \ 177 if (PCIE_IS_BDG(bus_p)) \ 178 pcie_domain_list_remove(domain_id, \ 179 PCIE_BUS2DOM(bus_p)->domain.ids.ids) 180 181 #define PCIE_BDF_LIST_GET(bus_p) \ 182 ((pcie_req_id_list_t *)(PCIE_IS_BDG(bus_p) ? \ 183 PCIE_BUS2DOM(bus_p)->domain.ids.bdfs : NULL)) 184 #define PCIE_BDF_LIST_ADD(bus_p, bdf) \ 185 if (PCIE_IS_BDG(bus_p)) \ 186 pcie_bdf_list_add(bdf, &PCIE_BUS2DOM(bus_p)->domain.ids.bdfs) 187 #define PCIE_BDF_LIST_REMOVE(bus_p, bdf) \ 188 if (PCIE_IS_BDG(bus_p)) \ 189 pcie_bdf_list_remove(bdf, &PCIE_BUS2DOM(bus_p)->domain.ids.bdfs) 190 191 #ifdef __cplusplus 192 } 193 #endif 194 195 #endif /* _SYS_PCIEV_H */ 196