@@ -129,14 +129,13 @@ static struct iosapic {
129
129
char __iomem * addr ; /* base address of IOSAPIC */
130
130
unsigned int gsi_base ; /* first GSI assigned to this IOSAPIC */
131
131
unsigned short num_rte ; /* number of RTE in this IOSAPIC */
132
+ int rtes_inuse ; /* # of RTEs in use on this IOSAPIC */
132
133
#ifdef CONFIG_NUMA
133
134
unsigned short node ; /* numa node association via pxm */
134
135
#endif
135
136
} iosapic_lists [NR_IOSAPICS ];
136
137
137
- static int num_iosapic ;
138
-
139
- static unsigned char pcat_compat __initdata ; /* 8259 compatibility flag */
138
+ static unsigned char pcat_compat __devinitdata ; /* 8259 compatibility flag */
140
139
141
140
static int iosapic_kmalloc_ok ;
142
141
static LIST_HEAD (free_rte_list );
@@ -149,7 +148,7 @@ find_iosapic (unsigned int gsi)
149
148
{
150
149
int i ;
151
150
152
- for (i = 0 ; i < num_iosapic ; i ++ ) {
151
+ for (i = 0 ; i < NR_IOSAPICS ; i ++ ) {
153
152
if ((unsigned ) (gsi - iosapic_lists [i ].gsi_base ) < iosapic_lists [i ].num_rte )
154
153
return i ;
155
154
}
@@ -598,6 +597,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
598
597
rte -> refcnt ++ ;
599
598
list_add_tail (& rte -> rte_list , & iosapic_intr_info [vector ].rtes );
600
599
iosapic_intr_info [vector ].count ++ ;
600
+ iosapic_lists [index ].rtes_inuse ++ ;
601
601
}
602
602
else if (vector_is_shared (vector )) {
603
603
struct iosapic_intr_info * info = & iosapic_intr_info [vector ];
778
778
iosapic_unregister_intr (unsigned int gsi )
779
779
{
780
780
unsigned long flags ;
781
- int irq , vector ;
781
+ int irq , vector , index ;
782
782
irq_desc_t * idesc ;
783
783
u32 low32 ;
784
784
unsigned long trigger , polarity ;
@@ -819,6 +819,9 @@ iosapic_unregister_intr (unsigned int gsi)
819
819
list_del (& rte -> rte_list );
820
820
iosapic_intr_info [vector ].count -- ;
821
821
iosapic_free_rte (rte );
822
+ index = find_iosapic (gsi );
823
+ iosapic_lists [index ].rtes_inuse -- ;
824
+ WARN_ON (iosapic_lists [index ].rtes_inuse < 0 );
822
825
823
826
trigger = iosapic_intr_info [vector ].trigger ;
824
827
polarity = iosapic_intr_info [vector ].polarity ;
@@ -952,30 +955,86 @@ iosapic_system_init (int system_pcat_compat)
952
955
}
953
956
}
954
957
955
- void __init
958
+ static inline int
959
+ iosapic_alloc (void )
960
+ {
961
+ int index ;
962
+
963
+ for (index = 0 ; index < NR_IOSAPICS ; index ++ )
964
+ if (!iosapic_lists [index ].addr )
965
+ return index ;
966
+
967
+ printk (KERN_WARNING "%s: failed to allocate iosapic\n" , __FUNCTION__ );
968
+ return -1 ;
969
+ }
970
+
971
+ static inline void
972
+ iosapic_free (int index )
973
+ {
974
+ memset (& iosapic_lists [index ], 0 , sizeof (iosapic_lists [0 ]));
975
+ }
976
+
977
+ static inline int
978
+ iosapic_check_gsi_range (unsigned int gsi_base , unsigned int ver )
979
+ {
980
+ int index ;
981
+ unsigned int gsi_end , base , end ;
982
+
983
+ /* check gsi range */
984
+ gsi_end = gsi_base + ((ver >> 16 ) & 0xff );
985
+ for (index = 0 ; index < NR_IOSAPICS ; index ++ ) {
986
+ if (!iosapic_lists [index ].addr )
987
+ continue ;
988
+
989
+ base = iosapic_lists [index ].gsi_base ;
990
+ end = base + iosapic_lists [index ].num_rte - 1 ;
991
+
992
+ if (gsi_base < base && gsi_end < base )
993
+ continue ;/* OK */
994
+
995
+ if (gsi_base > end && gsi_end > end )
996
+ continue ; /* OK */
997
+
998
+ return - EBUSY ;
999
+ }
1000
+ return 0 ;
1001
+ }
1002
+
1003
+ int __devinit
956
1004
iosapic_init (unsigned long phys_addr , unsigned int gsi_base )
957
1005
{
958
- int num_rte ;
1006
+ int num_rte , err , index ;
959
1007
unsigned int isa_irq , ver ;
960
1008
char __iomem * addr ;
1009
+ unsigned long flags ;
1010
+
1011
+ spin_lock_irqsave (& iosapic_lock , flags );
1012
+ {
1013
+ addr = ioremap (phys_addr , 0 );
1014
+ ver = iosapic_version (addr );
961
1015
962
- addr = ioremap (phys_addr , 0 );
963
- ver = iosapic_version (addr );
1016
+ if ((err = iosapic_check_gsi_range (gsi_base , ver ))) {
1017
+ iounmap (addr );
1018
+ spin_unlock_irqrestore (& iosapic_lock , flags );
1019
+ return err ;
1020
+ }
964
1021
965
- /*
966
- * The MAX_REDIR register holds the highest input pin
967
- * number (starting from 0).
968
- * We add 1 so that we can use it for number of pins (= RTEs)
969
- */
970
- num_rte = ((ver >> 16 ) & 0xff ) + 1 ;
1022
+ /*
1023
+ * The MAX_REDIR register holds the highest input pin
1024
+ * number (starting from 0).
1025
+ * We add 1 so that we can use it for number of pins (= RTEs)
1026
+ */
1027
+ num_rte = ((ver >> 16 ) & 0xff ) + 1 ;
971
1028
972
- iosapic_lists [num_iosapic ].addr = addr ;
973
- iosapic_lists [num_iosapic ].gsi_base = gsi_base ;
974
- iosapic_lists [num_iosapic ].num_rte = num_rte ;
1029
+ index = iosapic_alloc ();
1030
+ iosapic_lists [index ].addr = addr ;
1031
+ iosapic_lists [index ].gsi_base = gsi_base ;
1032
+ iosapic_lists [index ].num_rte = num_rte ;
975
1033
#ifdef CONFIG_NUMA
976
- iosapic_lists [num_iosapic ].node = MAX_NUMNODES ;
1034
+ iosapic_lists [index ].node = MAX_NUMNODES ;
977
1035
#endif
978
- num_iosapic ++ ;
1036
+ }
1037
+ spin_unlock_irqrestore (& iosapic_lock , flags );
979
1038
980
1039
if ((gsi_base == 0 ) && pcat_compat ) {
981
1040
/*
@@ -986,10 +1045,43 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
986
1045
for (isa_irq = 0 ; isa_irq < 16 ; ++ isa_irq )
987
1046
iosapic_override_isa_irq (isa_irq , isa_irq , IOSAPIC_POL_HIGH , IOSAPIC_EDGE );
988
1047
}
1048
+ return 0 ;
1049
+ }
1050
+
1051
+ #ifdef CONFIG_HOTPLUG
1052
+ int
1053
+ iosapic_remove (unsigned int gsi_base )
1054
+ {
1055
+ int index , err = 0 ;
1056
+ unsigned long flags ;
1057
+
1058
+ spin_lock_irqsave (& iosapic_lock , flags );
1059
+ {
1060
+ index = find_iosapic (gsi_base );
1061
+ if (index < 0 ) {
1062
+ printk (KERN_WARNING "%s: No IOSAPIC for GSI base %u\n" ,
1063
+ __FUNCTION__ , gsi_base );
1064
+ goto out ;
1065
+ }
1066
+
1067
+ if (iosapic_lists [index ].rtes_inuse ) {
1068
+ err = - EBUSY ;
1069
+ printk (KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n" ,
1070
+ __FUNCTION__ , gsi_base );
1071
+ goto out ;
1072
+ }
1073
+
1074
+ iounmap (iosapic_lists [index ].addr );
1075
+ iosapic_free (index );
1076
+ }
1077
+ out :
1078
+ spin_unlock_irqrestore (& iosapic_lock , flags );
1079
+ return err ;
989
1080
}
1081
+ #endif /* CONFIG_HOTPLUG */
990
1082
991
1083
#ifdef CONFIG_NUMA
992
- void __init
1084
+ void __devinit
993
1085
map_iosapic_to_node (unsigned int gsi_base , int node )
994
1086
{
995
1087
int index ;
0 commit comments