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); |
|