pci.c (169219) | pci.c (169221) |
---|---|
1/*- 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000, BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 13 unchanged lines hidden (view full) --- 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000, BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 13 unchanged lines hidden (view full) --- 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/sys/dev/pci/pci.c 169219 2007-05-02 16:21:18Z jhb $"); | 30__FBSDID("$FreeBSD: head/sys/dev/pci/pci.c 169221 2007-05-02 17:50:36Z jhb $"); |
31 32#include "opt_bus.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/malloc.h> 37#include <sys/module.h> 38#include <sys/linker.h> --- 57 unchanged lines hidden (view full) --- 96static void pci_read_extcap(device_t pcib, pcicfgregs *cfg); 97static uint32_t pci_read_vpd_reg(device_t pcib, pcicfgregs *cfg, 98 int reg); 99#if 0 100static void pci_write_vpd_reg(device_t pcib, pcicfgregs *cfg, 101 int reg, uint32_t data); 102#endif 103static void pci_read_vpd(device_t pcib, pcicfgregs *cfg); | 31 32#include "opt_bus.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/malloc.h> 37#include <sys/module.h> 38#include <sys/linker.h> --- 57 unchanged lines hidden (view full) --- 96static void pci_read_extcap(device_t pcib, pcicfgregs *cfg); 97static uint32_t pci_read_vpd_reg(device_t pcib, pcicfgregs *cfg, 98 int reg); 99#if 0 100static void pci_write_vpd_reg(device_t pcib, pcicfgregs *cfg, 101 int reg, uint32_t data); 102#endif 103static void pci_read_vpd(device_t pcib, pcicfgregs *cfg); |
104static void pci_disable_msi(device_t dev); 105static void pci_enable_msi(device_t dev, uint64_t address, 106 uint16_t data); 107static void pci_enable_msix(device_t dev, u_int index, 108 uint64_t address, uint32_t data); 109static void pci_mask_msix(device_t dev, u_int index); 110static void pci_unmask_msix(device_t dev, u_int index); |
|
104static int pci_msi_blacklisted(void); | 111static int pci_msi_blacklisted(void); |
112static void pci_resume_msi(device_t dev); 113static void pci_resume_msix(device_t dev); |
|
105 106static device_method_t pci_methods[] = { 107 /* Device interface */ 108 DEVMETHOD(device_probe, pci_probe), 109 DEVMETHOD(device_attach, pci_attach), 110 DEVMETHOD(device_detach, bus_generic_detach), 111 DEVMETHOD(device_shutdown, bus_generic_shutdown), 112 DEVMETHOD(device_suspend, pci_suspend), 113 DEVMETHOD(device_resume, pci_resume), 114 115 /* Bus interface */ 116 DEVMETHOD(bus_print_child, pci_print_child), 117 DEVMETHOD(bus_probe_nomatch, pci_probe_nomatch), 118 DEVMETHOD(bus_read_ivar, pci_read_ivar), 119 DEVMETHOD(bus_write_ivar, pci_write_ivar), 120 DEVMETHOD(bus_driver_added, pci_driver_added), | 114 115static device_method_t pci_methods[] = { 116 /* Device interface */ 117 DEVMETHOD(device_probe, pci_probe), 118 DEVMETHOD(device_attach, pci_attach), 119 DEVMETHOD(device_detach, bus_generic_detach), 120 DEVMETHOD(device_shutdown, bus_generic_shutdown), 121 DEVMETHOD(device_suspend, pci_suspend), 122 DEVMETHOD(device_resume, pci_resume), 123 124 /* Bus interface */ 125 DEVMETHOD(bus_print_child, pci_print_child), 126 DEVMETHOD(bus_probe_nomatch, pci_probe_nomatch), 127 DEVMETHOD(bus_read_ivar, pci_read_ivar), 128 DEVMETHOD(bus_write_ivar, pci_write_ivar), 129 DEVMETHOD(bus_driver_added, pci_driver_added), |
121 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 122 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), | 130 DEVMETHOD(bus_setup_intr, pci_setup_intr), 131 DEVMETHOD(bus_teardown_intr, pci_teardown_intr), |
123 124 DEVMETHOD(bus_get_resource_list,pci_get_resource_list), 125 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 126 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 127 DEVMETHOD(bus_delete_resource, pci_delete_resource), 128 DEVMETHOD(bus_alloc_resource, pci_alloc_resource), 129 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 130 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), --- 880 unchanged lines hidden (view full) --- 1011 */ 1012void 1013pci_enable_msix(device_t dev, u_int index, uint64_t address, uint32_t data) 1014{ 1015 struct pci_devinfo *dinfo = device_get_ivars(dev); 1016 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1017 uint32_t offset; 1018 | 132 133 DEVMETHOD(bus_get_resource_list,pci_get_resource_list), 134 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 135 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 136 DEVMETHOD(bus_delete_resource, pci_delete_resource), 137 DEVMETHOD(bus_alloc_resource, pci_alloc_resource), 138 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 139 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), --- 880 unchanged lines hidden (view full) --- 1020 */ 1021void 1022pci_enable_msix(device_t dev, u_int index, uint64_t address, uint32_t data) 1023{ 1024 struct pci_devinfo *dinfo = device_get_ivars(dev); 1025 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1026 uint32_t offset; 1027 |
1019 KASSERT(msix->msix_alloc > index, ("bogus index")); | 1028 KASSERT(msix->msix_table_len > index, ("bogus index")); |
1020 offset = msix->msix_table_offset + index * 16; 1021 bus_write_4(msix->msix_table_res, offset, address & 0xffffffff); 1022 bus_write_4(msix->msix_table_res, offset + 4, address >> 32); 1023 bus_write_4(msix->msix_table_res, offset + 8, data); 1024} 1025 1026void 1027pci_mask_msix(device_t dev, u_int index) --- 13 unchanged lines hidden (view full) --- 1041 1042void 1043pci_unmask_msix(device_t dev, u_int index) 1044{ 1045 struct pci_devinfo *dinfo = device_get_ivars(dev); 1046 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1047 uint32_t offset, val; 1048 | 1029 offset = msix->msix_table_offset + index * 16; 1030 bus_write_4(msix->msix_table_res, offset, address & 0xffffffff); 1031 bus_write_4(msix->msix_table_res, offset + 4, address >> 32); 1032 bus_write_4(msix->msix_table_res, offset + 8, data); 1033} 1034 1035void 1036pci_mask_msix(device_t dev, u_int index) --- 13 unchanged lines hidden (view full) --- 1050 1051void 1052pci_unmask_msix(device_t dev, u_int index) 1053{ 1054 struct pci_devinfo *dinfo = device_get_ivars(dev); 1055 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1056 uint32_t offset, val; 1057 |
1049 KASSERT(msix->msix_alloc > index, ("bogus index")); | 1058 KASSERT(msix->msix_table_len > index, ("bogus index")); |
1050 offset = msix->msix_table_offset + index * 16 + 12; 1051 val = bus_read_4(msix->msix_table_res, offset); 1052 if (val & PCIM_MSIX_VCTRL_MASK) { 1053 val &= ~PCIM_MSIX_VCTRL_MASK; 1054 bus_write_4(msix->msix_table_res, offset, val); 1055 } 1056} 1057 1058int 1059pci_pending_msix(device_t dev, u_int index) 1060{ 1061 struct pci_devinfo *dinfo = device_get_ivars(dev); 1062 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1063 uint32_t offset, bit; 1064 | 1059 offset = msix->msix_table_offset + index * 16 + 12; 1060 val = bus_read_4(msix->msix_table_res, offset); 1061 if (val & PCIM_MSIX_VCTRL_MASK) { 1062 val &= ~PCIM_MSIX_VCTRL_MASK; 1063 bus_write_4(msix->msix_table_res, offset, val); 1064 } 1065} 1066 1067int 1068pci_pending_msix(device_t dev, u_int index) 1069{ 1070 struct pci_devinfo *dinfo = device_get_ivars(dev); 1071 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1072 uint32_t offset, bit; 1073 |
1065 KASSERT(msix->msix_alloc > index, ("bogus index")); | 1074 KASSERT(msix->msix_table_len > index, ("bogus index")); |
1066 offset = msix->msix_pba_offset + (index / 32) * 4; 1067 bit = 1 << index % 32; 1068 return (bus_read_4(msix->msix_pba_res, offset) & bit); 1069} 1070 1071/* | 1075 offset = msix->msix_pba_offset + (index / 32) * 4; 1076 bit = 1 << index % 32; 1077 return (bus_read_4(msix->msix_pba_res, offset) & bit); 1078} 1079 1080/* |
1081 * Restore MSI-X registers and table during resume. If MSI-X is 1082 * enabled then walk the virtual table to restore the actual MSI-X 1083 * table. 1084 */ 1085static void 1086pci_resume_msix(device_t dev) 1087{ 1088 struct pci_devinfo *dinfo = device_get_ivars(dev); 1089 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1090 struct msix_table_entry *mte; 1091 struct msix_vector *mv; 1092 int i; 1093 1094 if (msix->msix_alloc > 0) { 1095 /* First, mask all vectors. */ 1096 for (i = 0; i < msix->msix_msgnum; i++) 1097 pci_mask_msix(dev, i); 1098 1099 /* Second, program any messages with at least one handler. */ 1100 for (i = 0; i < msix->msix_table_len; i++) { 1101 mte = &msix->msix_table[i]; 1102 if (mte->mte_vector == 0 || mte->mte_handlers == 0) 1103 continue; 1104 mv = &msix->msix_vectors[mte->mte_vector - 1]; 1105 pci_enable_msix(dev, i, mv->mv_address, mv->mv_data); 1106 pci_unmask_msix(dev, i); 1107 } 1108 } 1109 pci_write_config(dev, msix->msix_location + PCIR_MSIX_CTRL, 1110 msix->msix_ctrl, 2); 1111} 1112 1113/* |
|
1072 * Attempt to allocate *count MSI-X messages. The actual number allocated is 1073 * returned in *count. After this function returns, each message will be 1074 * available to the driver as SYS_RES_IRQ resources starting at rid 1. 1075 */ 1076int 1077pci_alloc_msix_method(device_t dev, device_t child, int *count) 1078{ 1079 struct pci_devinfo *dinfo = device_get_ivars(child); --- 40 unchanged lines hidden (view full) --- 1120 1121 if (bootverbose) 1122 device_printf(child, 1123 "attempting to allocate %d MSI-X vectors (%d supported)\n", 1124 *count, cfg->msix.msix_msgnum); 1125 max = min(*count, cfg->msix.msix_msgnum); 1126 for (i = 0; i < max; i++) { 1127 /* Allocate a message. */ | 1114 * Attempt to allocate *count MSI-X messages. The actual number allocated is 1115 * returned in *count. After this function returns, each message will be 1116 * available to the driver as SYS_RES_IRQ resources starting at rid 1. 1117 */ 1118int 1119pci_alloc_msix_method(device_t dev, device_t child, int *count) 1120{ 1121 struct pci_devinfo *dinfo = device_get_ivars(child); --- 40 unchanged lines hidden (view full) --- 1162 1163 if (bootverbose) 1164 device_printf(child, 1165 "attempting to allocate %d MSI-X vectors (%d supported)\n", 1166 *count, cfg->msix.msix_msgnum); 1167 max = min(*count, cfg->msix.msix_msgnum); 1168 for (i = 0; i < max; i++) { 1169 /* Allocate a message. */ |
1128 error = PCIB_ALLOC_MSIX(device_get_parent(dev), child, i, 1129 &irq); | 1170 error = PCIB_ALLOC_MSIX(device_get_parent(dev), child, &irq); |
1130 if (error) 1131 break; 1132 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i + 1, irq, 1133 irq, 1); 1134 } 1135 actual = i; 1136 1137 if (bootverbose) { --- 40 unchanged lines hidden (view full) --- 1178 printf(" for MSI-X\n"); 1179 } 1180 } 1181 1182 /* Mask all vectors. */ 1183 for (i = 0; i < cfg->msix.msix_msgnum; i++) 1184 pci_mask_msix(child, i); 1185 | 1171 if (error) 1172 break; 1173 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i + 1, irq, 1174 irq, 1); 1175 } 1176 actual = i; 1177 1178 if (bootverbose) { --- 40 unchanged lines hidden (view full) --- 1219 printf(" for MSI-X\n"); 1220 } 1221 } 1222 1223 /* Mask all vectors. */ 1224 for (i = 0; i < cfg->msix.msix_msgnum; i++) 1225 pci_mask_msix(child, i); 1226 |
1227 /* Allocate and initialize vector data and virtual table. */ 1228 cfg->msix.msix_vectors = malloc(sizeof(struct msix_vector) * actual, 1229 M_DEVBUF, M_WAITOK | M_ZERO); 1230 cfg->msix.msix_table = malloc(sizeof(struct msix_table_entry) * actual, 1231 M_DEVBUF, M_WAITOK | M_ZERO); 1232 for (i = 0; i < actual; i++) { 1233 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1); 1234 cfg->msix.msix_vectors[i].mv_irq = rle->start; 1235 cfg->msix.msix_table[i].mte_vector = i + 1; 1236 } 1237 |
|
1186 /* Update control register to enable MSI-X. */ 1187 cfg->msix.msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE; 1188 pci_write_config(child, cfg->msix.msix_location + PCIR_MSIX_CTRL, 1189 cfg->msix.msix_ctrl, 2); 1190 1191 /* Update counts of alloc'd messages. */ 1192 cfg->msix.msix_alloc = actual; | 1238 /* Update control register to enable MSI-X. */ 1239 cfg->msix.msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE; 1240 pci_write_config(child, cfg->msix.msix_location + PCIR_MSIX_CTRL, 1241 cfg->msix.msix_ctrl, 2); 1242 1243 /* Update counts of alloc'd messages. */ 1244 cfg->msix.msix_alloc = actual; |
1245 cfg->msix.msix_table_len = actual; |
|
1193 *count = actual; 1194 return (0); 1195} 1196 1197/* | 1246 *count = actual; 1247 return (0); 1248} 1249 1250/* |
1198 * By default, pci_alloc_msix() will assign the allocated IRQ resources to 1199 * the first N messages in the MSI-X table. However, device drivers may 1200 * want to use different layouts in the case that they do not allocate a 1201 * full table. This method allows the driver to specify what layout it 1202 * wants. It must be called after a successful pci_alloc_msix() but 1203 * before any of the associated SYS_RES_IRQ resources are allocated via 1204 * bus_alloc_resource(). The 'indices' array contains N (where N equals 1205 * the 'count' returned from pci_alloc_msix()) message indices. The 1206 * indices are 1-based (meaning the first message is at index 1). On 1207 * successful return, each of the messages in the 'indices' array will 1208 * have an associated SYS_RES_IRQ whose rid is equal to the index. Thus, 1209 * if indices contains { 2, 4 }, then upon successful return, the 'child' 1210 * device will have two SYS_RES_IRQ resources available at rids 2 and 4. | 1251 * By default, pci_alloc_msix() will assign the allocated IRQ 1252 * resources consecutively to the first N messages in the MSI-X table. 1253 * However, device drivers may want to use different layouts if they 1254 * either receive fewer messages than they asked for, or they wish to 1255 * populate the MSI-X table sparsely. This method allows the driver 1256 * to specify what layout it wants. It must be called after a 1257 * successful pci_alloc_msix() but before any of the associated 1258 * SYS_RES_IRQ resources are allocated via bus_alloc_resource(). 1259 * 1260 * The 'vectors' array contains 'count' message vectors. The array 1261 * maps directly to the MSI-X table in that index 0 in the array 1262 * specifies the vector for the first message in the MSI-X table, etc. 1263 * The vector value in each array index can either be 0 to indicate 1264 * that no vector should be assigned to a message slot, or it can be a 1265 * number from 1 to N (where N is the count returned from a 1266 * succcessful call to pci_alloc_msix()) to indicate which message 1267 * vector (IRQ) to be used for the corresponding message. 1268 * 1269 * On successful return, each message with a non-zero vector will have 1270 * an associated SYS_RES_IRQ whose rid is equal to the array index + 1271 * 1. Additionally, if any of the IRQs allocated via the previous 1272 * call to pci_alloc_msix() are not used in the mapping, those IRQs 1273 * will be freed back to the system automatically. 1274 * 1275 * For example, suppose a driver has a MSI-X table with 6 messages and 1276 * asks for 6 messages, but pci_alloc_msix() only returns a count of 1277 * 3. Call the three vectors allocated by pci_alloc_msix() A, B, and 1278 * C. After the call to pci_alloc_msix(), the device will be setup to 1279 * have an MSI-X table of ABC--- (where - means no vector assigned). 1280 * If the driver ten passes a vector array of { 1, 0, 1, 2, 0, 2 }, 1281 * then the MSI-X table will look like A-AB-B, and the 'C' vector will 1282 * be freed back to the system. This device will also have valid 1283 * SYS_RES_IRQ rids of 1, 3, 4, and 6. 1284 * 1285 * In any case, the SYS_RES_IRQ rid X will always map to the message 1286 * at MSI-X table index X - 1 and will only be valid if a vector is 1287 * assigned to that table entry. |
1211 */ 1212int | 1288 */ 1289int |
1213pci_remap_msix_method(device_t dev, device_t child, u_int *indices) | 1290pci_remap_msix_method(device_t dev, device_t child, int count, 1291 const u_int *vectors) |
1214{ 1215 struct pci_devinfo *dinfo = device_get_ivars(child); | 1292{ 1293 struct pci_devinfo *dinfo = device_get_ivars(child); |
1216 pcicfgregs *cfg = &dinfo->cfg; | 1294 struct pcicfg_msix *msix = &dinfo->cfg.msix; |
1217 struct resource_list_entry *rle; | 1295 struct resource_list_entry *rle; |
1218 int count, error, i, j, *irqs; | 1296 int i, irq, j, *used; |
1219 | 1297 |
1220 /* Sanity check the indices. */ 1221 for (i = 0; i < cfg->msix.msix_alloc; i++) 1222 if (indices[i] == 0 || indices[i] > cfg->msix.msix_msgnum) | 1298 /* 1299 * Have to have at least one message in the table but the 1300 * table can't be bigger than the actual MSI-X table in the 1301 * device. 1302 */ 1303 if (count == 0 || count > msix->msix_msgnum) 1304 return (EINVAL); 1305 1306 /* Sanity check the vectors. */ 1307 for (i = 0; i < count; i++) 1308 if (vectors[i] > msix->msix_alloc) |
1223 return (EINVAL); 1224 | 1309 return (EINVAL); 1310 |
1225 /* Check for duplicates. */ 1226 for (i = 0; i < cfg->msix.msix_alloc; i++) 1227 for (j = i + 1; j < cfg->msix.msix_alloc; j++) 1228 if (indices[i] == indices[j]) 1229 return (EINVAL); 1230 | 1311 /* 1312 * Make sure there aren't any holes in the vectors to be used. 1313 * It's a big pain to support it, and it doesn't really make 1314 * sense anyway. Also, at least one vector must be used. 1315 */ 1316 used = malloc(sizeof(int) * msix->msix_alloc, M_DEVBUF, M_WAITOK | 1317 M_ZERO); 1318 for (i = 0; i < count; i++) 1319 if (vectors[i] != 0) 1320 used[vectors[i] - 1] = 1; 1321 for (i = 0; i < msix->msix_alloc - 1; i++) 1322 if (used[i] == 0 && used[i + 1] == 1) { 1323 free(used, M_DEVBUF); 1324 return (EINVAL); 1325 } 1326 if (used[0] != 1) { 1327 free(used, M_DEVBUF); 1328 return (EINVAL); 1329 } 1330 |
1231 /* Make sure none of the resources are allocated. */ | 1331 /* Make sure none of the resources are allocated. */ |
1232 for (i = 1, count = 0; count < cfg->msix.msix_alloc; i++) { 1233 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i); 1234 if (rle == NULL) | 1332 for (i = 0; i < msix->msix_table_len; i++) { 1333 if (msix->msix_table[i].mte_vector == 0) |
1235 continue; | 1334 continue; |
1335 if (msix->msix_table[i].mte_handlers > 0) 1336 return (EBUSY); 1337 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1); 1338 KASSERT(rle != NULL, ("missing resource")); |
|
1236 if (rle->res != NULL) 1237 return (EBUSY); | 1339 if (rle->res != NULL) 1340 return (EBUSY); |
1238 count++; | |
1239 } 1240 | 1341 } 1342 |
1241 /* Save the IRQ values and free the existing resources. */ 1242 irqs = malloc(sizeof(int) * cfg->msix.msix_alloc, M_TEMP, M_WAITOK); 1243 for (i = 1, count = 0; count < cfg->msix.msix_alloc; i++) { 1244 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i); 1245 if (rle == NULL) | 1343 /* Free the existing resource list entries. */ 1344 for (i = 0; i < msix->msix_table_len; i++) { 1345 if (msix->msix_table[i].mte_vector == 0) |
1246 continue; | 1346 continue; |
1247 irqs[count] = rle->start; 1248 resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i); 1249 count++; | 1347 resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1); |
1250 } 1251 | 1348 } 1349 |
1252 /* Map the IRQ values to the new message indices and rids. */ 1253 for (i = 0; i < cfg->msix.msix_alloc; i++) { 1254 resource_list_add(&dinfo->resources, SYS_RES_IRQ, indices[i], 1255 irqs[i], irqs[i], 1); | 1350 /* 1351 * Build the new virtual table keeping track of which vectors are 1352 * used. 1353 */ 1354 free(msix->msix_table, M_DEVBUF); 1355 msix->msix_table = malloc(sizeof(struct msix_table_entry) * count, 1356 M_DEVBUF, M_WAITOK | M_ZERO); 1357 for (i = 0; i < count; i++) 1358 msix->msix_table[i].mte_vector = vectors[i]; 1359 msix->msix_table_len = count; |
1256 | 1360 |
1257 /* 1258 * The indices in the backend code (PCIB_* methods and the 1259 * MI helper routines for MD code such as pci_enable_msix()) 1260 * are all zero-based. However, the indices passed to this 1261 * function are 1-based so that the correspond 1:1 with the 1262 * SYS_RES_IRQ resource IDs. 1263 */ 1264 error = PCIB_REMAP_MSIX(device_get_parent(dev), child, 1265 indices[i] - 1, irqs[i]); 1266 KASSERT(error == 0, ("Failed to remap MSI-X message")); | 1361 /* Free any unused IRQs and resize the vectors array if necessary. */ 1362 j = msix->msix_alloc - 1; 1363 if (used[j] == 0) { 1364 struct msix_vector *vec; 1365 1366 while (used[j] == 0) { 1367 PCIB_RELEASE_MSIX(device_get_parent(dev), child, 1368 msix->msix_vectors[j].mv_irq); 1369 j--; 1370 } 1371 vec = malloc(sizeof(struct msix_vector) * (j + 1), M_DEVBUF, 1372 M_WAITOK); 1373 bcopy(msix->msix_vectors, vec, sizeof(struct msix_vector) * 1374 (j + 1)); 1375 free(msix->msix_vectors, M_DEVBUF); 1376 msix->msix_vectors = vec; 1377 msix->msix_alloc = j + 1; |
1267 } | 1378 } |
1379 free(used, M_DEVBUF); 1380 1381 /* Map the IRQs onto the rids. */ 1382 for (i = 0; i < count; i++) { 1383 if (vectors[i] == 0) 1384 continue; 1385 irq = msix->msix_vectors[vectors[i]].mv_irq; 1386 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i + 1, irq, 1387 irq, 1); 1388 } 1389 |
|
1268 if (bootverbose) { | 1390 if (bootverbose) { |
1269 if (cfg->msix.msix_alloc == 1) 1270 device_printf(child, 1271 "Remapped MSI-X IRQ to index %d\n", indices[0]); 1272 else { 1273 device_printf(child, "Remapped MSI-X IRQs to indices"); 1274 for (i = 0; i < cfg->msix.msix_alloc - 1; i++) 1275 printf(" %d,", indices[i]); 1276 printf(" %d\n", indices[cfg->msix.msix_alloc - 1]); | 1391 device_printf(child, "Remapped MSI-X IRQs as: "); 1392 for (i = 0; i < count; i++) { 1393 if (i != 0) 1394 printf(", "); 1395 if (vectors[i] == 0) 1396 printf("---"); 1397 else 1398 printf("%d", 1399 msix->msix_vectors[vectors[i]].mv_irq); |
1277 } | 1400 } |
1401 printf("\n"); |
|
1278 } | 1402 } |
1279 free(irqs, M_TEMP); | |
1280 1281 return (0); 1282} 1283 1284static int 1285pci_release_msix(device_t dev, device_t child) 1286{ 1287 struct pci_devinfo *dinfo = device_get_ivars(child); 1288 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1289 struct resource_list_entry *rle; | 1403 1404 return (0); 1405} 1406 1407static int 1408pci_release_msix(device_t dev, device_t child) 1409{ 1410 struct pci_devinfo *dinfo = device_get_ivars(child); 1411 struct pcicfg_msix *msix = &dinfo->cfg.msix; 1412 struct resource_list_entry *rle; |
1290 int count, i; | 1413 int i; |
1291 1292 /* Do we have any messages to release? */ 1293 if (msix->msix_alloc == 0) 1294 return (ENODEV); 1295 1296 /* Make sure none of the resources are allocated. */ | 1414 1415 /* Do we have any messages to release? */ 1416 if (msix->msix_alloc == 0) 1417 return (ENODEV); 1418 1419 /* Make sure none of the resources are allocated. */ |
1297 for (i = 1, count = 0; count < msix->msix_alloc; i++) { 1298 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i); 1299 if (rle == NULL) | 1420 for (i = 0; i < msix->msix_table_len; i++) { 1421 if (msix->msix_table[i].mte_vector == 0) |
1300 continue; | 1422 continue; |
1423 if (msix->msix_table[i].mte_handlers > 0) 1424 return (EBUSY); 1425 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1); 1426 KASSERT(rle != NULL, ("missing resource")); |
|
1301 if (rle->res != NULL) 1302 return (EBUSY); | 1427 if (rle->res != NULL) 1428 return (EBUSY); |
1303 count++; | |
1304 } 1305 1306 /* Update control register to disable MSI-X. */ 1307 msix->msix_ctrl &= ~PCIM_MSIXCTRL_MSIX_ENABLE; 1308 pci_write_config(child, msix->msix_location + PCIR_MSIX_CTRL, 1309 msix->msix_ctrl, 2); 1310 | 1429 } 1430 1431 /* Update control register to disable MSI-X. */ 1432 msix->msix_ctrl &= ~PCIM_MSIXCTRL_MSIX_ENABLE; 1433 pci_write_config(child, msix->msix_location + PCIR_MSIX_CTRL, 1434 msix->msix_ctrl, 2); 1435 |
1311 /* Release the messages. */ 1312 for (i = 1, count = 0; count < msix->msix_alloc; i++) { 1313 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i); 1314 if (rle == NULL) | 1436 /* Free the resource list entries. */ 1437 for (i = 0; i < msix->msix_table_len; i++) { 1438 if (msix->msix_table[i].mte_vector == 0) |
1315 continue; | 1439 continue; |
1316 PCIB_RELEASE_MSIX(device_get_parent(dev), child, 1317 rle->start); 1318 resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i); 1319 count++; | 1440 resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1); |
1320 } | 1441 } |
1442 free(msix->msix_table, M_DEVBUF); 1443 msix->msix_table_len = 0; |
|
1321 | 1444 |
1322 /* Update alloc count. */ | 1445 /* Release the IRQs. */ 1446 for (i = 0; i < msix->msix_alloc; i++) 1447 PCIB_RELEASE_MSIX(device_get_parent(dev), child, 1448 msix->msix_vectors[i].mv_irq); 1449 free(msix->msix_vectors, M_DEVBUF); |
1323 msix->msix_alloc = 0; 1324 return (0); 1325} 1326 1327/* 1328 * Return the max supported MSI-X messages this device supports. 1329 * Basically, assuming the MD code can alloc messages, this function 1330 * should return the maximum value that pci_alloc_msix() can return. --- 15 unchanged lines hidden (view full) --- 1346 */ 1347void 1348pci_enable_msi(device_t dev, uint64_t address, uint16_t data) 1349{ 1350 struct pci_devinfo *dinfo = device_get_ivars(dev); 1351 struct pcicfg_msi *msi = &dinfo->cfg.msi; 1352 1353 /* Write data and address values. */ | 1450 msix->msix_alloc = 0; 1451 return (0); 1452} 1453 1454/* 1455 * Return the max supported MSI-X messages this device supports. 1456 * Basically, assuming the MD code can alloc messages, this function 1457 * should return the maximum value that pci_alloc_msix() can return. --- 15 unchanged lines hidden (view full) --- 1473 */ 1474void 1475pci_enable_msi(device_t dev, uint64_t address, uint16_t data) 1476{ 1477 struct pci_devinfo *dinfo = device_get_ivars(dev); 1478 struct pcicfg_msi *msi = &dinfo->cfg.msi; 1479 1480 /* Write data and address values. */ |
1354 msi->msi_addr = address; 1355 msi->msi_data = data; | |
1356 pci_write_config(dev, msi->msi_location + PCIR_MSI_ADDR, 1357 address & 0xffffffff, 4); 1358 if (msi->msi_ctrl & PCIM_MSICTRL_64BIT) { 1359 pci_write_config(dev, msi->msi_location + PCIR_MSI_ADDR_HIGH, 1360 address >> 32, 4); 1361 pci_write_config(dev, msi->msi_location + PCIR_MSI_DATA_64BIT, 1362 data, 2); 1363 } else 1364 pci_write_config(dev, msi->msi_location + PCIR_MSI_DATA, data, 1365 2); 1366 1367 /* Enable MSI in the control register. */ 1368 msi->msi_ctrl |= PCIM_MSICTRL_MSI_ENABLE; 1369 pci_write_config(dev, msi->msi_location + PCIR_MSI_CTRL, msi->msi_ctrl, 1370 2); 1371} 1372 | 1481 pci_write_config(dev, msi->msi_location + PCIR_MSI_ADDR, 1482 address & 0xffffffff, 4); 1483 if (msi->msi_ctrl & PCIM_MSICTRL_64BIT) { 1484 pci_write_config(dev, msi->msi_location + PCIR_MSI_ADDR_HIGH, 1485 address >> 32, 4); 1486 pci_write_config(dev, msi->msi_location + PCIR_MSI_DATA_64BIT, 1487 data, 2); 1488 } else 1489 pci_write_config(dev, msi->msi_location + PCIR_MSI_DATA, data, 1490 2); 1491 1492 /* Enable MSI in the control register. */ 1493 msi->msi_ctrl |= PCIM_MSICTRL_MSI_ENABLE; 1494 pci_write_config(dev, msi->msi_location + PCIR_MSI_CTRL, msi->msi_ctrl, 1495 2); 1496} 1497 |
1498void 1499pci_disable_msi(device_t dev) 1500{ 1501 struct pci_devinfo *dinfo = device_get_ivars(dev); 1502 struct pcicfg_msi *msi = &dinfo->cfg.msi; 1503 1504 /* Disable MSI in the control register. */ 1505 msi->msi_ctrl &= ~PCIM_MSICTRL_MSI_ENABLE; 1506 pci_write_config(dev, msi->msi_location + PCIR_MSI_CTRL, msi->msi_ctrl, 1507 2); 1508} 1509 |
|
1373/* 1374 * Restore MSI registers during resume. If MSI is enabled then 1375 * restore the data and address registers in addition to the control 1376 * register. 1377 */ 1378static void 1379pci_resume_msi(device_t dev) 1380{ --- 15 unchanged lines hidden (view full) --- 1396 } else 1397 pci_write_config(dev, msi->msi_location + PCIR_MSI_DATA, 1398 data, 2); 1399 } 1400 pci_write_config(dev, msi->msi_location + PCIR_MSI_CTRL, msi->msi_ctrl, 1401 2); 1402} 1403 | 1510/* 1511 * Restore MSI registers during resume. If MSI is enabled then 1512 * restore the data and address registers in addition to the control 1513 * register. 1514 */ 1515static void 1516pci_resume_msi(device_t dev) 1517{ --- 15 unchanged lines hidden (view full) --- 1533 } else 1534 pci_write_config(dev, msi->msi_location + PCIR_MSI_DATA, 1535 data, 2); 1536 } 1537 pci_write_config(dev, msi->msi_location + PCIR_MSI_CTRL, msi->msi_ctrl, 1538 2); 1539} 1540 |
1541int 1542pci_remap_msi_irq(device_t dev, u_int irq) 1543{ 1544 struct pci_devinfo *dinfo = device_get_ivars(dev); 1545 pcicfgregs *cfg = &dinfo->cfg; 1546 struct resource_list_entry *rle; 1547 struct msix_table_entry *mte; 1548 struct msix_vector *mv; 1549 device_t bus; 1550 uint64_t addr; 1551 uint32_t data; 1552 int error, i, j; 1553 1554 bus = device_get_parent(dev); 1555 1556 /* 1557 * Handle MSI first. We try to find this IRQ among our list 1558 * of MSI IRQs. If we find it, we request updated address and 1559 * data registers and apply the results. 1560 */ 1561 if (cfg->msi.msi_alloc > 0) { 1562 1563 /* If we don't have any active handlers, nothing to do. */ 1564 if (cfg->msi.msi_handlers == 0) 1565 return (0); 1566 for (i = 0; i < cfg->msi.msi_alloc; i++) { 1567 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 1568 i + 1); 1569 if (rle->start == irq) { 1570 error = PCIB_MAP_MSI(device_get_parent(bus), 1571 dev, irq, &addr, &data); 1572 if (error) 1573 return (error); 1574 pci_disable_msi(dev); 1575 dinfo->cfg.msi.msi_addr = addr; 1576 dinfo->cfg.msi.msi_data = data; 1577 pci_enable_msi(dev, addr, data); 1578 return (0); 1579 } 1580 } 1581 return (ENOENT); 1582 } 1583 1584 /* 1585 * For MSI-X, we check to see if we have this IRQ. If we do, 1586 * we request the updated mapping info. If that works, we go 1587 * through all the slots that use this IRQ and update them. 1588 */ 1589 if (cfg->msix.msix_alloc > 0) { 1590 for (i = 0; i < cfg->msix.msix_alloc; i++) { 1591 mv = &cfg->msix.msix_vectors[i]; 1592 if (mv->mv_irq == irq) { 1593 error = PCIB_MAP_MSI(device_get_parent(bus), 1594 dev, irq, &addr, &data); 1595 if (error) 1596 return (error); 1597 mv->mv_address = addr; 1598 mv->mv_data = data; 1599 for (j = 0; j < cfg->msix.msix_table_len; j++) { 1600 mte = &cfg->msix.msix_table[j]; 1601 if (mte->mte_vector != i + 1) 1602 continue; 1603 if (mte->mte_handlers == 0) 1604 continue; 1605 pci_mask_msix(dev, j); 1606 pci_enable_msix(dev, j, addr, data); 1607 pci_unmask_msix(dev, j); 1608 } 1609 } 1610 } 1611 return (ENOENT); 1612 } 1613 1614 return (ENOENT); 1615} 1616 |
|
1404/* 1405 * Returns true if the specified device is blacklisted because MSI 1406 * doesn't work. 1407 */ 1408int 1409pci_msi_device_blacklisted(device_t dev) 1410{ 1411 struct pci_quirk *q; --- 148 unchanged lines hidden (view full) --- 1560 ctrl = cfg->msi.msi_ctrl; 1561 ctrl &= ~PCIM_MSICTRL_MME_MASK; 1562 ctrl |= (ffs(actual) - 1) << 4; 1563 cfg->msi.msi_ctrl = ctrl; 1564 pci_write_config(child, cfg->msi.msi_location + PCIR_MSI_CTRL, ctrl, 2); 1565 1566 /* Update counts of alloc'd messages. */ 1567 cfg->msi.msi_alloc = actual; | 1617/* 1618 * Returns true if the specified device is blacklisted because MSI 1619 * doesn't work. 1620 */ 1621int 1622pci_msi_device_blacklisted(device_t dev) 1623{ 1624 struct pci_quirk *q; --- 148 unchanged lines hidden (view full) --- 1773 ctrl = cfg->msi.msi_ctrl; 1774 ctrl &= ~PCIM_MSICTRL_MME_MASK; 1775 ctrl |= (ffs(actual) - 1) << 4; 1776 cfg->msi.msi_ctrl = ctrl; 1777 pci_write_config(child, cfg->msi.msi_location + PCIR_MSI_CTRL, ctrl, 2); 1778 1779 /* Update counts of alloc'd messages. */ 1780 cfg->msi.msi_alloc = actual; |
1781 cfg->msi.msi_handlers = 0; |
|
1568 *count = actual; 1569 return (0); 1570} 1571 1572/* Release the MSI messages associated with this device. */ 1573int 1574pci_release_msi_method(device_t dev, device_t child) 1575{ --- 8 unchanged lines hidden (view full) --- 1584 return (error); 1585 1586 /* Do we have any messages to release? */ 1587 if (msi->msi_alloc == 0) 1588 return (ENODEV); 1589 KASSERT(msi->msi_alloc <= 32, ("more than 32 alloc'd messages")); 1590 1591 /* Make sure none of the resources are allocated. */ | 1782 *count = actual; 1783 return (0); 1784} 1785 1786/* Release the MSI messages associated with this device. */ 1787int 1788pci_release_msi_method(device_t dev, device_t child) 1789{ --- 8 unchanged lines hidden (view full) --- 1798 return (error); 1799 1800 /* Do we have any messages to release? */ 1801 if (msi->msi_alloc == 0) 1802 return (ENODEV); 1803 KASSERT(msi->msi_alloc <= 32, ("more than 32 alloc'd messages")); 1804 1805 /* Make sure none of the resources are allocated. */ |
1806 if (msi->msi_handlers > 0) 1807 return (EBUSY); |
|
1592 for (i = 0; i < msi->msi_alloc; i++) { 1593 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1); 1594 KASSERT(rle != NULL, ("missing MSI resource")); 1595 if (rle->res != NULL) 1596 return (EBUSY); 1597 irqs[i] = rle->start; 1598 } 1599 | 1808 for (i = 0; i < msi->msi_alloc; i++) { 1809 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1); 1810 KASSERT(rle != NULL, ("missing MSI resource")); 1811 if (rle->res != NULL) 1812 return (EBUSY); 1813 irqs[i] = rle->start; 1814 } 1815 |
1600 /* Update control register with 0 count and disable MSI. */ 1601 msi->msi_ctrl &= ~(PCIM_MSICTRL_MME_MASK | PCIM_MSICTRL_MSI_ENABLE); | 1816 /* Update control register with 0 count. */ 1817 KASSERT(!(msi->msi_ctrl & PCIM_MSICTRL_MSI_ENABLE), 1818 ("%s: MSI still enabled", __func__)); 1819 msi->msi_ctrl &= ~PCIM_MSICTRL_MME_MASK; |
1602 pci_write_config(child, msi->msi_location + PCIR_MSI_CTRL, 1603 msi->msi_ctrl, 2); 1604 1605 /* Release the messages. */ 1606 PCIB_RELEASE_MSI(device_get_parent(dev), child, msi->msi_alloc, irqs); 1607 for (i = 0; i < msi->msi_alloc; i++) 1608 resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1); 1609 1610 /* Update alloc count. */ 1611 msi->msi_alloc = 0; | 1820 pci_write_config(child, msi->msi_location + PCIR_MSI_CTRL, 1821 msi->msi_ctrl, 2); 1822 1823 /* Release the messages. */ 1824 PCIB_RELEASE_MSI(device_get_parent(dev), child, msi->msi_alloc, irqs); 1825 for (i = 0; i < msi->msi_alloc; i++) 1826 resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1); 1827 1828 /* Update alloc count. */ 1829 msi->msi_alloc = 0; |
1830 msi->msi_addr = 0; 1831 msi->msi_data = 0; |
|
1612 return (0); 1613} 1614 1615/* 1616 * Return the max supported MSI messages this device supports. 1617 * Basically, assuming the MD code can alloc messages, this function 1618 * should return the maximum value that pci_alloc_msi() can return. 1619 * Thus, it is subject to the tunables, etc. --- 824 unchanged lines hidden (view full) --- 2444 pci_cfg_restore(child, dinfo); 2445 if (device_probe_and_attach(child) != 0) 2446 pci_cfg_save(child, dinfo, 1); 2447 } 2448 free(devlist, M_TEMP); 2449} 2450 2451int | 1832 return (0); 1833} 1834 1835/* 1836 * Return the max supported MSI messages this device supports. 1837 * Basically, assuming the MD code can alloc messages, this function 1838 * should return the maximum value that pci_alloc_msi() can return. 1839 * Thus, it is subject to the tunables, etc. --- 824 unchanged lines hidden (view full) --- 2664 pci_cfg_restore(child, dinfo); 2665 if (device_probe_and_attach(child) != 0) 2666 pci_cfg_save(child, dinfo, 1); 2667 } 2668 free(devlist, M_TEMP); 2669} 2670 2671int |
2672pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, 2673 driver_filter_t *filter, driver_intr_t *intr, void *arg, void **cookiep) 2674{ 2675 struct pci_devinfo *dinfo; 2676 struct msix_table_entry *mte; 2677 struct msix_vector *mv; 2678 uint64_t addr; 2679 uint32_t data; 2680 void *cookie; 2681 int error, rid; 2682 2683 error = bus_generic_setup_intr(dev, child, irq, flags, filter, intr, 2684 arg, &cookie); 2685 if (error) 2686 return (error); 2687 2688 /* 2689 * If this is a direct child, check to see if the interrupt is 2690 * MSI or MSI-X. If so, ask our parent to map the MSI and give 2691 * us the address and data register values. If we fail for some 2692 * reason, teardown the interrupt handler. 2693 */ 2694 rid = rman_get_rid(irq); 2695 if (device_get_parent(child) == dev && rid > 0) { 2696 dinfo = device_get_ivars(child); 2697 if (dinfo->cfg.msi.msi_alloc > 0) { 2698 if (dinfo->cfg.msi.msi_addr == 0) { 2699 KASSERT(dinfo->cfg.msi.msi_handlers == 0, 2700 ("MSI has handlers, but vectors not mapped")); 2701 error = PCIB_MAP_MSI(device_get_parent(dev), 2702 child, rman_get_start(irq), &addr, &data); 2703 if (error) 2704 goto bad; 2705 dinfo->cfg.msi.msi_addr = addr; 2706 dinfo->cfg.msi.msi_data = data; 2707 pci_enable_msi(child, addr, data); 2708 } 2709 dinfo->cfg.msi.msi_handlers++; 2710 } else { 2711 KASSERT(dinfo->cfg.msix.msix_alloc > 0, 2712 ("No MSI or MSI-X interrupts allocated")); 2713 KASSERT(rid <= dinfo->cfg.msix.msix_table_len, 2714 ("MSI-X index too high")); 2715 mte = &dinfo->cfg.msix.msix_table[rid - 1]; 2716 KASSERT(mte->mte_vector != 0, ("no message vector")); 2717 mv = &dinfo->cfg.msix.msix_vectors[mte->mte_vector - 1]; 2718 KASSERT(mv->mv_irq == rman_get_start(irq), 2719 ("IRQ mismatch")); 2720 if (mv->mv_address == 0) { 2721 KASSERT(mte->mte_handlers == 0, 2722 ("MSI-X table entry has handlers, but vector not mapped")); 2723 error = PCIB_MAP_MSI(device_get_parent(dev), 2724 child, rman_get_start(irq), &addr, &data); 2725 if (error) 2726 goto bad; 2727 mv->mv_address = addr; 2728 mv->mv_data = data; 2729 } 2730 if (mte->mte_handlers == 0) { 2731 pci_enable_msix(child, rid - 1, mv->mv_address, 2732 mv->mv_data); 2733 pci_unmask_msix(child, rid - 1); 2734 } 2735 mte->mte_handlers++; 2736 } 2737 bad: 2738 if (error) { 2739 (void)bus_generic_teardown_intr(dev, child, irq, 2740 cookie); 2741 return (error); 2742 } 2743 } 2744 *cookiep = cookie; 2745 return (0); 2746} 2747 2748int 2749pci_teardown_intr(device_t dev, device_t child, struct resource *irq, 2750 void *cookie) 2751{ 2752 struct msix_table_entry *mte; 2753 struct resource_list_entry *rle; 2754 struct pci_devinfo *dinfo; 2755 int error, rid; 2756 2757 /* 2758 * If this is a direct child, check to see if the interrupt is 2759 * MSI or MSI-X. If so, decrement the appropriate handlers 2760 * count and mask the MSI-X message, or disable MSI messages 2761 * if the count drops to 0. 2762 */ 2763 if (irq == NULL || !(rman_get_flags(irq) & RF_ACTIVE)) 2764 return (EINVAL); 2765 rid = rman_get_rid(irq); 2766 if (device_get_parent(child) == dev && rid > 0) { 2767 dinfo = device_get_ivars(child); 2768 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, rid); 2769 if (rle->res != irq) 2770 return (EINVAL); 2771 if (dinfo->cfg.msi.msi_alloc > 0) { 2772 KASSERT(rid <= dinfo->cfg.msi.msi_alloc, 2773 ("MSI-X index too high")); 2774 if (dinfo->cfg.msi.msi_handlers == 0) 2775 return (EINVAL); 2776 dinfo->cfg.msi.msi_handlers--; 2777 if (dinfo->cfg.msi.msi_handlers == 0) 2778 pci_disable_msi(child); 2779 } else { 2780 KASSERT(dinfo->cfg.msix.msix_alloc > 0, 2781 ("No MSI or MSI-X interrupts allocated")); 2782 KASSERT(rid <= dinfo->cfg.msix.msix_table_len, 2783 ("MSI-X index too high")); 2784 mte = &dinfo->cfg.msix.msix_table[rid - 1]; 2785 if (mte->mte_handlers == 0) 2786 return (EINVAL); 2787 mte->mte_handlers--; 2788 if (mte->mte_handlers == 0) 2789 pci_mask_msix(child, rid - 1); 2790 } 2791 } 2792 error = bus_generic_teardown_intr(dev, child, irq, cookie); 2793 if (device_get_parent(child) == dev && rid > 0) 2794 KASSERT(error == 0, 2795 ("%s: generic teardown failed for MSI/MSI-X", __func__)); 2796 return (error); 2797} 2798 2799int |
|
2452pci_print_child(device_t dev, device_t child) 2453{ 2454 struct pci_devinfo *dinfo; 2455 struct resource_list *rl; 2456 int retval = 0; 2457 2458 dinfo = device_get_ivars(child); 2459 rl = &dinfo->resources; --- 757 unchanged lines hidden (view full) --- 3217 pci_write_config(dev, PCIR_INTPIN, dinfo->cfg.intpin, 1); 3218 pci_write_config(dev, PCIR_MINGNT, dinfo->cfg.mingnt, 1); 3219 pci_write_config(dev, PCIR_MAXLAT, dinfo->cfg.maxlat, 1); 3220 pci_write_config(dev, PCIR_CACHELNSZ, dinfo->cfg.cachelnsz, 1); 3221 pci_write_config(dev, PCIR_LATTIMER, dinfo->cfg.lattimer, 1); 3222 pci_write_config(dev, PCIR_PROGIF, dinfo->cfg.progif, 1); 3223 pci_write_config(dev, PCIR_REVID, dinfo->cfg.revid, 1); 3224 | 2800pci_print_child(device_t dev, device_t child) 2801{ 2802 struct pci_devinfo *dinfo; 2803 struct resource_list *rl; 2804 int retval = 0; 2805 2806 dinfo = device_get_ivars(child); 2807 rl = &dinfo->resources; --- 757 unchanged lines hidden (view full) --- 3565 pci_write_config(dev, PCIR_INTPIN, dinfo->cfg.intpin, 1); 3566 pci_write_config(dev, PCIR_MINGNT, dinfo->cfg.mingnt, 1); 3567 pci_write_config(dev, PCIR_MAXLAT, dinfo->cfg.maxlat, 1); 3568 pci_write_config(dev, PCIR_CACHELNSZ, dinfo->cfg.cachelnsz, 1); 3569 pci_write_config(dev, PCIR_LATTIMER, dinfo->cfg.lattimer, 1); 3570 pci_write_config(dev, PCIR_PROGIF, dinfo->cfg.progif, 1); 3571 pci_write_config(dev, PCIR_REVID, dinfo->cfg.revid, 1); 3572 |
3225 /* 3226 * Restore MSI configuration if it is present. If MSI is enabled, 3227 * then restore the data and addr registers. 3228 */ | 3573 /* Restore MSI and MSI-X configurations if they are present. */ |
3229 if (dinfo->cfg.msi.msi_location != 0) 3230 pci_resume_msi(dev); | 3574 if (dinfo->cfg.msi.msi_location != 0) 3575 pci_resume_msi(dev); |
3576 if (dinfo->cfg.msix.msix_location != 0) 3577 pci_resume_msix(dev); |
|
3231} 3232 3233void 3234pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) 3235{ 3236 int i; 3237 uint32_t cls; 3238 int ps; --- 77 unchanged lines hidden --- | 3578} 3579 3580void 3581pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) 3582{ 3583 int i; 3584 uint32_t cls; 3585 int ps; --- 77 unchanged lines hidden --- |