Deleted Added
full compact
subr_intr.c (302408) subr_intr.c (308333)
1/*-
2 * Copyright (c) 2015-2016 Svatopluk Kraus
3 * Copyright (c) 2015-2016 Michal Meloun
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 12 unchanged lines hidden (view full) ---

21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2015-2016 Svatopluk Kraus
3 * Copyright (c) 2015-2016 Michal Meloun
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 12 unchanged lines hidden (view full) ---

21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: stable/11/sys/kern/subr_intr.c 301543 2016-06-07 09:03:27Z skra $");
29__FBSDID("$FreeBSD: stable/11/sys/kern/subr_intr.c 308333 2016-11-05 10:23:02Z mmel $");
30
31/*
32 * New-style Interrupt Framework
33 *
30
31/*
32 * New-style Interrupt Framework
33 *
34 * TODO: - to support IPI (PPI) enabling on other CPUs if already started
35 * - to complete things for removable PICs
34 * TODO: - add support for disconnected PICs.
35 * - to support IPI (PPI) enabling on other CPUs if already started.
36 * - to complete things for removable PICs.
36 */
37
38#include "opt_ddb.h"
39#include "opt_hwpmc_hooks.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>

--- 93 unchanged lines hidden (view full) ---

137
138/* Data for MI statistics reporting. */
139u_long intrcnt[INTRCNT_COUNT];
140char intrnames[INTRCNT_COUNT * INTRNAME_LEN];
141size_t sintrcnt = sizeof(intrcnt);
142size_t sintrnames = sizeof(intrnames);
143static u_int intrcnt_index;
144
37 */
38
39#include "opt_ddb.h"
40#include "opt_hwpmc_hooks.h"
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>

--- 93 unchanged lines hidden (view full) ---

138
139/* Data for MI statistics reporting. */
140u_long intrcnt[INTRCNT_COUNT];
141char intrnames[INTRCNT_COUNT * INTRNAME_LEN];
142size_t sintrcnt = sizeof(intrcnt);
143size_t sintrnames = sizeof(intrnames);
144static u_int intrcnt_index;
145
146static struct intr_irqsrc *intr_map_get_isrc(u_int res_id);
147static void intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc);
148static void intr_map_copy_map_data(u_int res_id, device_t *dev, intptr_t *xref,
149 struct intr_map_data **data);
150
145/*
146 * Interrupt framework initialization routine.
147 */
148static void
149intr_irq_init(void *dummy __unused)
150{
151
152 SLIST_INIT(&pic_list);

--- 256 unchanged lines hidden (view full) ---

409 return (EINVAL);
410
411 irq_sources[isrc->isrc_irq] = NULL;
412 isrc->isrc_irq = INTR_IRQ_INVALID; /* just to be safe */
413 return (0);
414}
415
416/*
151/*
152 * Interrupt framework initialization routine.
153 */
154static void
155intr_irq_init(void *dummy __unused)
156{
157
158 SLIST_INIT(&pic_list);

--- 256 unchanged lines hidden (view full) ---

415 return (EINVAL);
416
417 irq_sources[isrc->isrc_irq] = NULL;
418 isrc->isrc_irq = INTR_IRQ_INVALID; /* just to be safe */
419 return (0);
420}
421
422/*
417 * Lookup interrupt source by interrupt number (resource handle).
418 */
419static inline struct intr_irqsrc *
420isrc_lookup(u_int irq)
421{
422
423 if (irq < nitems(irq_sources))
424 return (irq_sources[irq]);
425 return (NULL);
426}
427
428/*
429 * Initialize interrupt source and register it into global interrupt table.
430 */
431int
432intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags,
433 const char *fmt, ...)
434{
435 int error;
436 va_list ap;

--- 457 unchanged lines hidden (view full) ---

894 }
895#endif
896 SLIST_INSERT_HEAD(&parent_pic->pic_children, newchild, pc_next);
897 mtx_unlock_spin(&parent_pic->pic_child_lock);
898
899 return (pic);
900}
901
423 * Initialize interrupt source and register it into global interrupt table.
424 */
425int
426intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags,
427 const char *fmt, ...)
428{
429 int error;
430 va_list ap;

--- 457 unchanged lines hidden (view full) ---

888 }
889#endif
890 SLIST_INSERT_HEAD(&parent_pic->pic_children, newchild, pc_next);
891 mtx_unlock_spin(&parent_pic->pic_child_lock);
892
893 return (pic);
894}
895
902int
903intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data,
904 u_int *irqp)
896static int
897intr_resolve_irq(device_t dev, intptr_t xref, struct intr_map_data *data,
898 struct intr_irqsrc **isrc)
905{
899{
906 int error;
907 struct intr_irqsrc *isrc;
908 struct intr_pic *pic;
900 struct intr_pic *pic;
901 struct intr_map_data_msi *msi;
909
910 if (data == NULL)
911 return (EINVAL);
912
913 pic = pic_lookup(dev, xref);
914 if (pic == NULL)
915 return (ESRCH);
916
902
903 if (data == NULL)
904 return (EINVAL);
905
906 pic = pic_lookup(dev, xref);
907 if (pic == NULL)
908 return (ESRCH);
909
917 KASSERT((pic->pic_flags & FLAG_PIC) != 0,
918 ("%s: Found a non-PIC controller: %s", __func__,
919 device_get_name(pic->pic_dev)));
910 switch (data->type) {
911 case INTR_MAP_DATA_MSI:
912 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
913 ("%s: Found a non-MSI controller: %s", __func__,
914 device_get_name(pic->pic_dev)));
915 msi = (struct intr_map_data_msi *)data;
916 *isrc = msi->isrc;
917 return (0);
920
918
921 error = PIC_MAP_INTR(pic->pic_dev, data, &isrc);
922 if (error == 0)
923 *irqp = isrc->isrc_irq;
924 return (error);
919 default:
920 KASSERT((pic->pic_flags & FLAG_PIC) != 0,
921 ("%s: Found a non-PIC controller: %s", __func__,
922 device_get_name(pic->pic_dev)));
923 return (PIC_MAP_INTR(pic->pic_dev, data, isrc));
924
925 }
925}
926
927int
926}
927
928int
928intr_alloc_irq(device_t dev, struct resource *res)
929intr_activate_irq(device_t dev, struct resource *res)
929{
930{
931 device_t map_dev;
932 intptr_t map_xref;
930 struct intr_map_data *data;
931 struct intr_irqsrc *isrc;
933 struct intr_map_data *data;
934 struct intr_irqsrc *isrc;
935 u_int res_id;
936 int error;
932
933 KASSERT(rman_get_start(res) == rman_get_end(res),
934 ("%s: more interrupts in resource", __func__));
935
937
938 KASSERT(rman_get_start(res) == rman_get_end(res),
939 ("%s: more interrupts in resource", __func__));
940
936 isrc = isrc_lookup(rman_get_start(res));
937 if (isrc == NULL)
938 return (EINVAL);
939
940 data = rman_get_virtual(res);
941 return (PIC_ALLOC_INTR(isrc->isrc_dev, isrc, res, data));
941 res_id = (u_int)rman_get_start(res);
942 if (intr_map_get_isrc(res_id) != NULL)
943 panic("Attempt to double activation of resource id: %u\n",
944 res_id);
945 intr_map_copy_map_data(res_id, &map_dev, &map_xref, &data);
946 error = intr_resolve_irq(map_dev, map_xref, data, &isrc);
947 if (error != 0) {
948 free(data, M_INTRNG);
949 /* XXX TODO DISCONECTED PICs */
950 /* if (error == EINVAL) return(0); */
951 return (error);
952 }
953 intr_map_set_isrc(res_id, isrc);
954 rman_set_virtual(res, data);
955 return (PIC_ACTIVATE_INTR(isrc->isrc_dev, isrc, res, data));
942}
943
944int
956}
957
958int
945intr_release_irq(device_t dev, struct resource *res)
959intr_deactivate_irq(device_t dev, struct resource *res)
946{
947 struct intr_map_data *data;
948 struct intr_irqsrc *isrc;
960{
961 struct intr_map_data *data;
962 struct intr_irqsrc *isrc;
963 u_int res_id;
964 int error;
949
950 KASSERT(rman_get_start(res) == rman_get_end(res),
951 ("%s: more interrupts in resource", __func__));
952
965
966 KASSERT(rman_get_start(res) == rman_get_end(res),
967 ("%s: more interrupts in resource", __func__));
968
953 isrc = isrc_lookup(rman_get_start(res));
969 res_id = (u_int)rman_get_start(res);
970 isrc = intr_map_get_isrc(res_id);
954 if (isrc == NULL)
971 if (isrc == NULL)
955 return (EINVAL);
972 panic("Attempt to deactivate non-active resource id: %u\n",
973 res_id);
956
957 data = rman_get_virtual(res);
974
975 data = rman_get_virtual(res);
958 return (PIC_RELEASE_INTR(isrc->isrc_dev, isrc, res, data));
976 error = PIC_DEACTIVATE_INTR(isrc->isrc_dev, isrc, res, data);
977 intr_map_set_isrc(res_id, NULL);
978 rman_set_virtual(res, NULL);
979 free(data, M_INTRNG);
980 return (error);
959}
960
961int
962intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt,
963 driver_intr_t hand, void *arg, int flags, void **cookiep)
964{
965 int error;
966 struct intr_map_data *data;
967 struct intr_irqsrc *isrc;
968 const char *name;
981}
982
983int
984intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt,
985 driver_intr_t hand, void *arg, int flags, void **cookiep)
986{
987 int error;
988 struct intr_map_data *data;
989 struct intr_irqsrc *isrc;
990 const char *name;
991 u_int res_id;
969
970 KASSERT(rman_get_start(res) == rman_get_end(res),
971 ("%s: more interrupts in resource", __func__));
972
992
993 KASSERT(rman_get_start(res) == rman_get_end(res),
994 ("%s: more interrupts in resource", __func__));
995
973 isrc = isrc_lookup(rman_get_start(res));
974 if (isrc == NULL)
996 res_id = (u_int)rman_get_start(res);
997 isrc = intr_map_get_isrc(res_id);
998 if (isrc == NULL) {
999 /* XXX TODO DISCONECTED PICs */
975 return (EINVAL);
1000 return (EINVAL);
1001 }
976
977 data = rman_get_virtual(res);
978 name = device_get_nameunit(dev);
979
980#ifdef INTR_SOLO
981 /*
982 * Standard handling is done through MI interrupt framework. However,
983 * some interrupts could request solely own special handling. This

--- 38 unchanged lines hidden (view full) ---

1022}
1023
1024int
1025intr_teardown_irq(device_t dev, struct resource *res, void *cookie)
1026{
1027 int error;
1028 struct intr_map_data *data;
1029 struct intr_irqsrc *isrc;
1002
1003 data = rman_get_virtual(res);
1004 name = device_get_nameunit(dev);
1005
1006#ifdef INTR_SOLO
1007 /*
1008 * Standard handling is done through MI interrupt framework. However,
1009 * some interrupts could request solely own special handling. This

--- 38 unchanged lines hidden (view full) ---

1048}
1049
1050int
1051intr_teardown_irq(device_t dev, struct resource *res, void *cookie)
1052{
1053 int error;
1054 struct intr_map_data *data;
1055 struct intr_irqsrc *isrc;
1056 u_int res_id;
1030
1031 KASSERT(rman_get_start(res) == rman_get_end(res),
1032 ("%s: more interrupts in resource", __func__));
1033
1057
1058 KASSERT(rman_get_start(res) == rman_get_end(res),
1059 ("%s: more interrupts in resource", __func__));
1060
1034 isrc = isrc_lookup(rman_get_start(res));
1061 res_id = (u_int)rman_get_start(res);
1062 isrc = intr_map_get_isrc(res_id);
1035 if (isrc == NULL || isrc->isrc_handlers == 0)
1036 return (EINVAL);
1037
1038 data = rman_get_virtual(res);
1039
1040#ifdef INTR_SOLO
1041 if (isrc->isrc_filter != NULL) {
1042 if (isrc != cookie)

--- 27 unchanged lines hidden (view full) ---

1070}
1071
1072int
1073intr_describe_irq(device_t dev, struct resource *res, void *cookie,
1074 const char *descr)
1075{
1076 int error;
1077 struct intr_irqsrc *isrc;
1063 if (isrc == NULL || isrc->isrc_handlers == 0)
1064 return (EINVAL);
1065
1066 data = rman_get_virtual(res);
1067
1068#ifdef INTR_SOLO
1069 if (isrc->isrc_filter != NULL) {
1070 if (isrc != cookie)

--- 27 unchanged lines hidden (view full) ---

1098}
1099
1100int
1101intr_describe_irq(device_t dev, struct resource *res, void *cookie,
1102 const char *descr)
1103{
1104 int error;
1105 struct intr_irqsrc *isrc;
1106 u_int res_id;
1078
1079 KASSERT(rman_get_start(res) == rman_get_end(res),
1080 ("%s: more interrupts in resource", __func__));
1081
1107
1108 KASSERT(rman_get_start(res) == rman_get_end(res),
1109 ("%s: more interrupts in resource", __func__));
1110
1082 isrc = isrc_lookup(rman_get_start(res));
1111 res_id = (u_int)rman_get_start(res);
1112 isrc = intr_map_get_isrc(res_id);
1083 if (isrc == NULL || isrc->isrc_handlers == 0)
1084 return (EINVAL);
1085#ifdef INTR_SOLO
1086 if (isrc->isrc_filter != NULL) {
1087 if (isrc != cookie)
1088 return (EINVAL);
1089
1090 mtx_lock(&isrc_table_lock);

--- 11 unchanged lines hidden (view full) ---

1102 return (error);
1103}
1104
1105#ifdef SMP
1106int
1107intr_bind_irq(device_t dev, struct resource *res, int cpu)
1108{
1109 struct intr_irqsrc *isrc;
1113 if (isrc == NULL || isrc->isrc_handlers == 0)
1114 return (EINVAL);
1115#ifdef INTR_SOLO
1116 if (isrc->isrc_filter != NULL) {
1117 if (isrc != cookie)
1118 return (EINVAL);
1119
1120 mtx_lock(&isrc_table_lock);

--- 11 unchanged lines hidden (view full) ---

1132 return (error);
1133}
1134
1135#ifdef SMP
1136int
1137intr_bind_irq(device_t dev, struct resource *res, int cpu)
1138{
1139 struct intr_irqsrc *isrc;
1140 u_int res_id;
1110
1111 KASSERT(rman_get_start(res) == rman_get_end(res),
1112 ("%s: more interrupts in resource", __func__));
1113
1141
1142 KASSERT(rman_get_start(res) == rman_get_end(res),
1143 ("%s: more interrupts in resource", __func__));
1144
1114 isrc = isrc_lookup(rman_get_start(res));
1145 res_id = (u_int)rman_get_start(res);
1146 isrc = intr_map_get_isrc(res_id);
1115 if (isrc == NULL || isrc->isrc_handlers == 0)
1116 return (EINVAL);
1117#ifdef INTR_SOLO
1118 if (isrc->isrc_filter != NULL)
1119 return (intr_isrc_assign_cpu(isrc, cpu));
1120#endif
1121 return (intr_event_bind(isrc->isrc_event, cpu));
1122}

--- 63 unchanged lines hidden (view full) ---

1186intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask)
1187{
1188
1189 return (PCPU_GET(cpuid));
1190}
1191#endif
1192
1193/*
1147 if (isrc == NULL || isrc->isrc_handlers == 0)
1148 return (EINVAL);
1149#ifdef INTR_SOLO
1150 if (isrc->isrc_filter != NULL)
1151 return (intr_isrc_assign_cpu(isrc, cpu));
1152#endif
1153 return (intr_event_bind(isrc->isrc_event, cpu));
1154}

--- 63 unchanged lines hidden (view full) ---

1218intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask)
1219{
1220
1221 return (PCPU_GET(cpuid));
1222}
1223#endif
1224
1225/*
1226 * Allocate memory for new intr_map_data structure.
1227 * Initialize common fields.
1228 */
1229struct intr_map_data *
1230intr_alloc_map_data(enum intr_map_data_type type, size_t len, int flags)
1231{
1232 struct intr_map_data *data;
1233
1234 data = malloc(len, M_INTRNG, flags);
1235 data->type = type;
1236 data->len = len;
1237 return (data);
1238}
1239
1240void intr_free_intr_map_data(struct intr_map_data *data)
1241{
1242
1243 free(data, M_INTRNG);
1244}
1245
1246
1247/*
1194 * Register a MSI/MSI-X interrupt controller
1195 */
1196int
1197intr_msi_register(device_t dev, intptr_t xref)
1198{
1199 struct intr_pic *pic;
1200
1201 if (dev == NULL)

--- 11 unchanged lines hidden (view full) ---

1213
1214int
1215intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count,
1216 int maxcount, int *irqs)
1217{
1218 struct intr_irqsrc **isrc;
1219 struct intr_pic *pic;
1220 device_t pdev;
1248 * Register a MSI/MSI-X interrupt controller
1249 */
1250int
1251intr_msi_register(device_t dev, intptr_t xref)
1252{
1253 struct intr_pic *pic;
1254
1255 if (dev == NULL)

--- 11 unchanged lines hidden (view full) ---

1267
1268int
1269intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count,
1270 int maxcount, int *irqs)
1271{
1272 struct intr_irqsrc **isrc;
1273 struct intr_pic *pic;
1274 device_t pdev;
1275 struct intr_map_data_msi *msi;
1221 int err, i;
1222
1223 pic = pic_lookup(NULL, xref);
1224 if (pic == NULL)
1225 return (ESRCH);
1226
1227 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1228 ("%s: Found a non-MSI controller: %s", __func__,
1229 device_get_name(pic->pic_dev)));
1230
1231 isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK);
1232 err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc);
1276 int err, i;
1277
1278 pic = pic_lookup(NULL, xref);
1279 if (pic == NULL)
1280 return (ESRCH);
1281
1282 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1283 ("%s: Found a non-MSI controller: %s", __func__,
1284 device_get_name(pic->pic_dev)));
1285
1286 isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK);
1287 err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc);
1233 if (err == 0) {
1234 for (i = 0; i < count; i++) {
1235 irqs[i] = isrc[i]->isrc_irq;
1236 }
1288 if (err != 0) {
1289 free(isrc, M_INTRNG);
1290 return (err);
1237 }
1238
1291 }
1292
1293 for (i = 0; i < count; i++) {
1294 msi = (struct intr_map_data_msi *)intr_alloc_map_data(
1295 INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO);
1296 msi-> isrc = isrc[i];
1297 irqs[i] = intr_map_irq(pic->pic_dev, xref,
1298 (struct intr_map_data *)msi);
1299
1300 }
1239 free(isrc, M_INTRNG);
1240
1241 return (err);
1242}
1243
1244int
1245intr_release_msi(device_t pci, device_t child, intptr_t xref, int count,
1246 int *irqs)

--- 7 unchanged lines hidden (view full) ---

1254 return (ESRCH);
1255
1256 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1257 ("%s: Found a non-MSI controller: %s", __func__,
1258 device_get_name(pic->pic_dev)));
1259
1260 isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK);
1261
1301 free(isrc, M_INTRNG);
1302
1303 return (err);
1304}
1305
1306int
1307intr_release_msi(device_t pci, device_t child, intptr_t xref, int count,
1308 int *irqs)

--- 7 unchanged lines hidden (view full) ---

1316 return (ESRCH);
1317
1318 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1319 ("%s: Found a non-MSI controller: %s", __func__,
1320 device_get_name(pic->pic_dev)));
1321
1322 isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK);
1323
1324 for (i = 0; i < count; i++)
1325 isrc[i] = intr_map_get_isrc(irqs[i]);
1326
1327 err = MSI_RELEASE_MSI(pic->pic_dev, child, count, isrc);
1328
1262 for (i = 0; i < count; i++) {
1329 for (i = 0; i < count; i++) {
1263 isrc[i] = isrc_lookup(irqs[i]);
1264 if (isrc == NULL) {
1265 free(isrc, M_INTRNG);
1266 return (EINVAL);
1267 }
1330 if (isrc[i] != NULL)
1331 intr_unmap_irq(irqs[i]);
1268 }
1269
1332 }
1333
1270 err = MSI_RELEASE_MSI(pic->pic_dev, child, count, isrc);
1271 free(isrc, M_INTRNG);
1272 return (err);
1273}
1274
1275int
1276intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq)
1277{
1278 struct intr_irqsrc *isrc;
1279 struct intr_pic *pic;
1280 device_t pdev;
1334 free(isrc, M_INTRNG);
1335 return (err);
1336}
1337
1338int
1339intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq)
1340{
1341 struct intr_irqsrc *isrc;
1342 struct intr_pic *pic;
1343 device_t pdev;
1344 struct intr_map_data_msi *msi;
1281 int err;
1282
1283 pic = pic_lookup(NULL, xref);
1284 if (pic == NULL)
1285 return (ESRCH);
1286
1287 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1288 ("%s: Found a non-MSI controller: %s", __func__,
1289 device_get_name(pic->pic_dev)));
1290
1345 int err;
1346
1347 pic = pic_lookup(NULL, xref);
1348 if (pic == NULL)
1349 return (ESRCH);
1350
1351 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1352 ("%s: Found a non-MSI controller: %s", __func__,
1353 device_get_name(pic->pic_dev)));
1354
1355
1291 err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc);
1292 if (err != 0)
1293 return (err);
1294
1356 err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc);
1357 if (err != 0)
1358 return (err);
1359
1295 *irq = isrc->isrc_irq;
1360 msi = (struct intr_map_data_msi *)intr_alloc_map_data(
1361 INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO);
1362 msi->isrc = isrc;
1363 *irq = intr_map_irq(pic->pic_dev, xref, (struct intr_map_data *)msi);
1296 return (0);
1297}
1298
1299int
1300intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq)
1301{
1302 struct intr_irqsrc *isrc;
1303 struct intr_pic *pic;
1304 int err;
1305
1306 pic = pic_lookup(NULL, xref);
1307 if (pic == NULL)
1308 return (ESRCH);
1309
1310 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1311 ("%s: Found a non-MSI controller: %s", __func__,
1312 device_get_name(pic->pic_dev)));
1313
1364 return (0);
1365}
1366
1367int
1368intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq)
1369{
1370 struct intr_irqsrc *isrc;
1371 struct intr_pic *pic;
1372 int err;
1373
1374 pic = pic_lookup(NULL, xref);
1375 if (pic == NULL)
1376 return (ESRCH);
1377
1378 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1379 ("%s: Found a non-MSI controller: %s", __func__,
1380 device_get_name(pic->pic_dev)));
1381
1314 isrc = isrc_lookup(irq);
1315 if (isrc == NULL)
1382 isrc = intr_map_get_isrc(irq);
1383 if (isrc == NULL) {
1384 intr_unmap_irq(irq);
1316 return (EINVAL);
1385 return (EINVAL);
1386 }
1317
1318 err = MSI_RELEASE_MSIX(pic->pic_dev, child, isrc);
1387
1388 err = MSI_RELEASE_MSIX(pic->pic_dev, child, isrc);
1389 intr_unmap_irq(irq);
1390
1319 return (err);
1320}
1321
1322int
1323intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq,
1324 uint64_t *addr, uint32_t *data)
1325{
1326 struct intr_irqsrc *isrc;
1327 struct intr_pic *pic;
1328 int err;
1329
1330 pic = pic_lookup(NULL, xref);
1331 if (pic == NULL)
1332 return (ESRCH);
1333
1334 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1335 ("%s: Found a non-MSI controller: %s", __func__,
1336 device_get_name(pic->pic_dev)));
1337
1391 return (err);
1392}
1393
1394int
1395intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq,
1396 uint64_t *addr, uint32_t *data)
1397{
1398 struct intr_irqsrc *isrc;
1399 struct intr_pic *pic;
1400 int err;
1401
1402 pic = pic_lookup(NULL, xref);
1403 if (pic == NULL)
1404 return (ESRCH);
1405
1406 KASSERT((pic->pic_flags & FLAG_MSI) != 0,
1407 ("%s: Found a non-MSI controller: %s", __func__,
1408 device_get_name(pic->pic_dev)));
1409
1338 isrc = isrc_lookup(irq);
1410 isrc = intr_map_get_isrc(irq);
1339 if (isrc == NULL)
1340 return (EINVAL);
1341
1342 err = MSI_MAP_MSI(pic->pic_dev, child, isrc, addr, data);
1343 return (err);
1344}
1345
1346

--- 38 unchanged lines hidden (view full) ---

1385 db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
1386 isrc->isrc_name, isrc->isrc_cpu.__bits[0],
1387 isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", num);
1388 irqsum += num;
1389 }
1390 db_printf("irq total %u\n", irqsum);
1391}
1392#endif
1411 if (isrc == NULL)
1412 return (EINVAL);
1413
1414 err = MSI_MAP_MSI(pic->pic_dev, child, isrc, addr, data);
1415 return (err);
1416}
1417
1418

--- 38 unchanged lines hidden (view full) ---

1457 db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
1458 isrc->isrc_name, isrc->isrc_cpu.__bits[0],
1459 isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", num);
1460 irqsum += num;
1461 }
1462 db_printf("irq total %u\n", irqsum);
1463}
1464#endif
1465
1466/*
1467 * Interrupt mapping table functions.
1468 *
1469 * Please, keep this part separately, it can be transformed to
1470 * extension of standard resources.
1471 */
1472struct intr_map_entry
1473{
1474 device_t dev;
1475 intptr_t xref;
1476 struct intr_map_data *map_data;
1477 struct intr_irqsrc *isrc;
1478 /* XXX TODO DISCONECTED PICs */
1479 /*int flags */
1480};
1481
1482/* XXX Convert irq_map[] to dynamicaly expandable one. */
1483static struct intr_map_entry *irq_map[2 * NIRQ];
1484static int irq_map_count = nitems(irq_map);
1485static int irq_map_first_free_idx;
1486static struct mtx irq_map_lock;
1487
1488static struct intr_irqsrc *
1489intr_map_get_isrc(u_int res_id)
1490{
1491 struct intr_irqsrc *isrc;
1492
1493 mtx_lock(&irq_map_lock);
1494 if ((res_id >= irq_map_count) || (irq_map[res_id] == NULL)) {
1495 mtx_unlock(&irq_map_lock);
1496 return (NULL);
1497 }
1498 isrc = irq_map[res_id]->isrc;
1499 mtx_unlock(&irq_map_lock);
1500 return (isrc);
1501}
1502
1503static void
1504intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc)
1505{
1506
1507 mtx_lock(&irq_map_lock);
1508 if ((res_id >= irq_map_count) || (irq_map[res_id] == NULL)) {
1509 mtx_unlock(&irq_map_lock);
1510 return;
1511 }
1512 irq_map[res_id]->isrc = isrc;
1513 mtx_unlock(&irq_map_lock);
1514}
1515
1516/*
1517 * Get a copy of intr_map_entry data
1518 */
1519static void
1520intr_map_copy_map_data(u_int res_id, device_t *map_dev, intptr_t *map_xref,
1521 struct intr_map_data **data)
1522{
1523 size_t len;
1524
1525 len = 0;
1526 mtx_lock(&irq_map_lock);
1527 if (res_id >= irq_map_count || irq_map[res_id] == NULL)
1528 panic("Attempt to copy invalid resource id: %u\n", res_id);
1529 if (irq_map[res_id]->map_data != NULL)
1530 len = irq_map[res_id]->map_data->len;
1531 mtx_unlock(&irq_map_lock);
1532
1533 if (len == 0)
1534 *data = NULL;
1535 else
1536 *data = malloc(len, M_INTRNG, M_WAITOK | M_ZERO);
1537 mtx_lock(&irq_map_lock);
1538 if (irq_map[res_id] == NULL)
1539 panic("Attempt to copy invalid resource id: %u\n", res_id);
1540 if (len != 0) {
1541 if (len != irq_map[res_id]->map_data->len)
1542 panic("Resource id: %u has changed.\n", res_id);
1543 memcpy(*data, irq_map[res_id]->map_data, len);
1544 }
1545 *map_dev = irq_map[res_id]->dev;
1546 *map_xref = irq_map[res_id]->xref;
1547 mtx_unlock(&irq_map_lock);
1548}
1549
1550
1551/*
1552 * Allocate and fill new entry in irq_map table.
1553 */
1554u_int
1555intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data)
1556{
1557 u_int i;
1558 struct intr_map_entry *entry;
1559
1560 /* Prepare new entry first. */
1561 entry = malloc(sizeof(*entry), M_INTRNG, M_WAITOK | M_ZERO);
1562
1563 entry->dev = dev;
1564 entry->xref = xref;
1565 entry->map_data = data;
1566 entry->isrc = NULL;
1567
1568 mtx_lock(&irq_map_lock);
1569 for (i = irq_map_first_free_idx; i < irq_map_count; i++) {
1570 if (irq_map[i] == NULL) {
1571 irq_map[i] = entry;
1572 irq_map_first_free_idx = i + 1;
1573 mtx_unlock(&irq_map_lock);
1574 return (i);
1575 }
1576 }
1577 mtx_unlock(&irq_map_lock);
1578
1579 /* XXX Expand irq_map table */
1580 panic("IRQ mapping table is full.");
1581}
1582
1583/*
1584 * Remove and free mapping entry.
1585 */
1586void
1587intr_unmap_irq(u_int res_id)
1588{
1589 struct intr_map_entry *entry;
1590
1591 mtx_lock(&irq_map_lock);
1592 if ((res_id >= irq_map_count) || (irq_map[res_id] == NULL))
1593 panic("Attempt to unmap invalid resource id: %u\n", res_id);
1594 entry = irq_map[res_id];
1595 irq_map[res_id] = NULL;
1596 irq_map_first_free_idx = res_id;
1597 mtx_unlock(&irq_map_lock);
1598 intr_free_intr_map_data(entry->map_data);
1599 free(entry, M_INTRNG);
1600}
1601
1602/*
1603 * Clone mapping entry.
1604 */
1605u_int
1606intr_map_clone_irq(u_int old_res_id)
1607{
1608 device_t map_dev;
1609 intptr_t map_xref;
1610 struct intr_map_data *data;
1611
1612 intr_map_copy_map_data(old_res_id, &map_dev, &map_xref, &data);
1613 return (intr_map_irq(map_dev, map_xref, data));
1614}
1615
1616static void
1617intr_map_init(void *dummy __unused)
1618{
1619
1620 mtx_init(&irq_map_lock, "intr map table", NULL, MTX_DEF);
1621}
1622SYSINIT(intr_map_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_map_init, NULL);