@@ -94,7 +94,7 @@ static struct irq_chip gicv2m_msi_irq_chip = {
94
94
95
95
static struct msi_domain_info gicv2m_msi_domain_info = {
96
96
.flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
97
- MSI_FLAG_PCI_MSIX ),
97
+ MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI ),
98
98
.chip = & gicv2m_msi_irq_chip ,
99
99
};
100
100
@@ -155,32 +155,26 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
155
155
return 0 ;
156
156
}
157
157
158
- static void gicv2m_unalloc_msi (struct v2m_data * v2m , unsigned int hwirq )
158
+ static void gicv2m_unalloc_msi (struct v2m_data * v2m , unsigned int hwirq ,
159
+ int nr_irqs )
159
160
{
160
- int pos ;
161
-
162
- pos = hwirq - v2m -> spi_start ;
163
- if (pos < 0 || pos >= v2m -> nr_spis ) {
164
- pr_err ("Failed to teardown msi. Invalid hwirq %d\n" , hwirq );
165
- return ;
166
- }
167
-
168
161
spin_lock (& v2m_lock );
169
- __clear_bit (pos , v2m -> bm );
162
+ bitmap_release_region (v2m -> bm , hwirq - v2m -> spi_start ,
163
+ get_count_order (nr_irqs ));
170
164
spin_unlock (& v2m_lock );
171
165
}
172
166
173
167
static int gicv2m_irq_domain_alloc (struct irq_domain * domain , unsigned int virq ,
174
168
unsigned int nr_irqs , void * args )
175
169
{
176
170
struct v2m_data * v2m = NULL , * tmp ;
177
- int hwirq , offset , err = 0 ;
171
+ int hwirq , offset , i , err = 0 ;
178
172
179
173
spin_lock (& v2m_lock );
180
174
list_for_each_entry (tmp , & v2m_nodes , entry ) {
181
- offset = find_first_zero_bit (tmp -> bm , tmp -> nr_spis );
182
- if ( offset < tmp -> nr_spis ) {
183
- __set_bit (offset , tmp -> bm );
175
+ offset = bitmap_find_free_region (tmp -> bm , tmp -> nr_spis ,
176
+ get_count_order ( nr_irqs ));
177
+ if (offset >= 0 ) {
184
178
v2m = tmp ;
185
179
break ;
186
180
}
@@ -192,16 +186,21 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
192
186
193
187
hwirq = v2m -> spi_start + offset ;
194
188
195
- err = gicv2m_irq_gic_domain_alloc (domain , virq , hwirq );
196
- if (err ) {
197
- gicv2m_unalloc_msi (v2m , hwirq );
198
- return err ;
199
- }
189
+ for (i = 0 ; i < nr_irqs ; i ++ ) {
190
+ err = gicv2m_irq_gic_domain_alloc (domain , virq + i , hwirq + i );
191
+ if (err )
192
+ goto fail ;
200
193
201
- irq_domain_set_hwirq_and_chip (domain , virq , hwirq ,
202
- & gicv2m_irq_chip , v2m );
194
+ irq_domain_set_hwirq_and_chip (domain , virq + i , hwirq + i ,
195
+ & gicv2m_irq_chip , v2m );
196
+ }
203
197
204
198
return 0 ;
199
+
200
+ fail :
201
+ irq_domain_free_irqs_parent (domain , virq , nr_irqs );
202
+ gicv2m_unalloc_msi (v2m , hwirq , get_count_order (nr_irqs ));
203
+ return err ;
205
204
}
206
205
207
206
static void gicv2m_irq_domain_free (struct irq_domain * domain ,
@@ -210,8 +209,7 @@ static void gicv2m_irq_domain_free(struct irq_domain *domain,
210
209
struct irq_data * d = irq_domain_get_irq_data (domain , virq );
211
210
struct v2m_data * v2m = irq_data_get_irq_chip_data (d );
212
211
213
- BUG_ON (nr_irqs != 1 );
214
- gicv2m_unalloc_msi (v2m , d -> hwirq );
212
+ gicv2m_unalloc_msi (v2m , d -> hwirq , nr_irqs );
215
213
irq_domain_free_irqs_parent (domain , virq , nr_irqs );
216
214
}
217
215
0 commit comments