xen/events: don't use chip_data for legacy IRQs

Since commit c330fb1ddc0a ("XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN data pointer which contains XEN specific information.")
Xen is using the chip_data pointer for storing IRQ specific data. When
running as a HVM domain this can result in problems for legacy IRQs, as
those might use chip_data for their own purposes.

Use a local array for this purpose in case of legacy IRQs, avoiding the
double use.

Cc: stable@vger.kernel.org
Fixes: c330fb1ddc0a ("XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN data pointer which contains XEN specific information.")
Signed-off-by: Juergen Gross <jgross@suse.com>
Tested-by: Stefan Bader <stefan.bader@canonical.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Link: https://lore.kernel.org/r/20200930091614.13660-1-jgross@suse.com
Signed-off-by: Juergen Gross <jgross@suse.com>

Changed files
+21 -8
drivers
xen
events
+21 -8
drivers/xen/events/events_base.c
··· 92 /* Xen will never allocate port zero for any purpose. */ 93 #define VALID_EVTCHN(chn) ((chn) != 0) 94 95 static struct irq_chip xen_dynamic_chip; 96 static struct irq_chip xen_percpu_chip; 97 static struct irq_chip xen_pirq_chip; ··· 158 /* Get info for IRQ */ 159 struct irq_info *info_for_irq(unsigned irq) 160 { 161 - return irq_get_chip_data(irq); 162 } 163 164 /* Constructors for packed IRQ information. */ ··· 390 info->type = IRQT_UNBOUND; 391 info->refcnt = -1; 392 393 - irq_set_chip_data(irq, info); 394 395 list_add_tail(&info->list, &xen_irq_list_head); 396 } ··· 439 440 static void xen_free_irq(unsigned irq) 441 { 442 - struct irq_info *info = irq_get_chip_data(irq); 443 444 if (WARN_ON(!info)) 445 return; 446 447 list_del(&info->list); 448 449 - irq_set_chip_data(irq, NULL); 450 451 WARN_ON(info->refcnt > 0); 452 ··· 616 static void __unbind_from_irq(unsigned int irq) 617 { 618 evtchn_port_t evtchn = evtchn_from_irq(irq); 619 - struct irq_info *info = irq_get_chip_data(irq); 620 621 if (info->refcnt > 0) { 622 info->refcnt--; ··· 1121 1122 void unbind_from_irqhandler(unsigned int irq, void *dev_id) 1123 { 1124 - struct irq_info *info = irq_get_chip_data(irq); 1125 1126 if (WARN_ON(!info)) 1127 return; ··· 1155 if (irq == -1) 1156 return -ENOENT; 1157 1158 - info = irq_get_chip_data(irq); 1159 1160 if (!info) 1161 return -ENOENT; ··· 1183 if (irq == -1) 1184 goto done; 1185 1186 - info = irq_get_chip_data(irq); 1187 1188 if (!info) 1189 goto done;
··· 92 /* Xen will never allocate port zero for any purpose. */ 93 #define VALID_EVTCHN(chn) ((chn) != 0) 94 95 + static struct irq_info *legacy_info_ptrs[NR_IRQS_LEGACY]; 96 + 97 static struct irq_chip xen_dynamic_chip; 98 static struct irq_chip xen_percpu_chip; 99 static struct irq_chip xen_pirq_chip; ··· 156 /* Get info for IRQ */ 157 struct irq_info *info_for_irq(unsigned irq) 158 { 159 + if (irq < nr_legacy_irqs()) 160 + return legacy_info_ptrs[irq]; 161 + else 162 + return irq_get_chip_data(irq); 163 + } 164 + 165 + static void set_info_for_irq(unsigned int irq, struct irq_info *info) 166 + { 167 + if (irq < nr_legacy_irqs()) 168 + legacy_info_ptrs[irq] = info; 169 + else 170 + irq_set_chip_data(irq, info); 171 } 172 173 /* Constructors for packed IRQ information. */ ··· 377 info->type = IRQT_UNBOUND; 378 info->refcnt = -1; 379 380 + set_info_for_irq(irq, info); 381 382 list_add_tail(&info->list, &xen_irq_list_head); 383 } ··· 426 427 static void xen_free_irq(unsigned irq) 428 { 429 + struct irq_info *info = info_for_irq(irq); 430 431 if (WARN_ON(!info)) 432 return; 433 434 list_del(&info->list); 435 436 + set_info_for_irq(irq, NULL); 437 438 WARN_ON(info->refcnt > 0); 439 ··· 603 static void __unbind_from_irq(unsigned int irq) 604 { 605 evtchn_port_t evtchn = evtchn_from_irq(irq); 606 + struct irq_info *info = info_for_irq(irq); 607 608 if (info->refcnt > 0) { 609 info->refcnt--; ··· 1108 1109 void unbind_from_irqhandler(unsigned int irq, void *dev_id) 1110 { 1111 + struct irq_info *info = info_for_irq(irq); 1112 1113 if (WARN_ON(!info)) 1114 return; ··· 1142 if (irq == -1) 1143 return -ENOENT; 1144 1145 + info = info_for_irq(irq); 1146 1147 if (!info) 1148 return -ENOENT; ··· 1170 if (irq == -1) 1171 goto done; 1172 1173 + info = info_for_irq(irq); 1174 1175 if (!info) 1176 goto done;