Deleted Added
full compact
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 ---