Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/hpet: Move MSI support into hpet.c

This isn't really dependent on PCI MSI; it's just generic MSI which is now
supported by the generic x86_vector_domain. Move the HPET MSI support back
into hpet.c with the rest of the HPET support.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20201024213535.443185-11-dwmw2@infradead.org

authored by

David Woodhouse and committed by
Thomas Gleixner
3d7295eb f598181a

+112 -128
-11
arch/x86/include/asm/hpet.h
··· 74 74 extern unsigned int hpet_readl(unsigned int a); 75 75 extern void force_hpet_resume(void); 76 76 77 - struct irq_data; 78 - struct hpet_channel; 79 - struct irq_domain; 80 - 81 - extern void hpet_msi_unmask(struct irq_data *data); 82 - extern void hpet_msi_mask(struct irq_data *data); 83 - extern void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg); 84 - extern struct irq_domain *hpet_create_irq_domain(int hpet_id); 85 - extern int hpet_assign_irq(struct irq_domain *domain, 86 - struct hpet_channel *hc, int dev_num); 87 - 88 77 #ifdef CONFIG_HPET_EMULATE_RTC 89 78 90 79 #include <linux/interrupt.h>
-111
arch/x86/kernel/apic/msi.c
··· 340 340 irq_domain_free_irqs(irq, 1); 341 341 } 342 342 #endif 343 - 344 - /* 345 - * MSI message composition 346 - */ 347 - #ifdef CONFIG_HPET_TIMER 348 - static inline int hpet_dev_id(struct irq_domain *domain) 349 - { 350 - struct msi_domain_info *info = msi_get_domain_info(domain); 351 - 352 - return (int)(long)info->data; 353 - } 354 - 355 - static void hpet_msi_write_msg(struct irq_data *data, struct msi_msg *msg) 356 - { 357 - hpet_msi_write(irq_data_get_irq_handler_data(data), msg); 358 - } 359 - 360 - static struct irq_chip hpet_msi_controller __ro_after_init = { 361 - .name = "HPET-MSI", 362 - .irq_unmask = hpet_msi_unmask, 363 - .irq_mask = hpet_msi_mask, 364 - .irq_ack = irq_chip_ack_parent, 365 - .irq_set_affinity = msi_domain_set_affinity, 366 - .irq_retrigger = irq_chip_retrigger_hierarchy, 367 - .irq_write_msi_msg = hpet_msi_write_msg, 368 - .flags = IRQCHIP_SKIP_SET_WAKE, 369 - }; 370 - 371 - static int hpet_msi_init(struct irq_domain *domain, 372 - struct msi_domain_info *info, unsigned int virq, 373 - irq_hw_number_t hwirq, msi_alloc_info_t *arg) 374 - { 375 - irq_set_status_flags(virq, IRQ_MOVE_PCNTXT); 376 - irq_domain_set_info(domain, virq, arg->hwirq, info->chip, NULL, 377 - handle_edge_irq, arg->data, "edge"); 378 - 379 - return 0; 380 - } 381 - 382 - static void hpet_msi_free(struct irq_domain *domain, 383 - struct msi_domain_info *info, unsigned int virq) 384 - { 385 - irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT); 386 - } 387 - 388 - static struct msi_domain_ops hpet_msi_domain_ops = { 389 - .msi_init = hpet_msi_init, 390 - .msi_free = hpet_msi_free, 391 - }; 392 - 393 - static struct msi_domain_info hpet_msi_domain_info = { 394 - .ops = &hpet_msi_domain_ops, 395 - .chip = &hpet_msi_controller, 396 - .flags = MSI_FLAG_USE_DEF_DOM_OPS, 397 - }; 398 - 399 - struct irq_domain *hpet_create_irq_domain(int hpet_id) 400 - { 401 - struct msi_domain_info *domain_info; 402 - struct irq_domain *parent, *d; 403 - struct irq_alloc_info info; 404 - struct fwnode_handle *fn; 405 - 406 - if (x86_vector_domain == NULL) 407 - return NULL; 408 - 409 - domain_info = kzalloc(sizeof(*domain_info), GFP_KERNEL); 410 - if (!domain_info) 411 - return NULL; 412 - 413 - *domain_info = hpet_msi_domain_info; 414 - domain_info->data = (void *)(long)hpet_id; 415 - 416 - init_irq_alloc_info(&info, NULL); 417 - info.type = X86_IRQ_ALLOC_TYPE_HPET_GET_PARENT; 418 - info.devid = hpet_id; 419 - parent = irq_remapping_get_irq_domain(&info); 420 - if (parent == NULL) 421 - parent = x86_vector_domain; 422 - else 423 - hpet_msi_controller.name = "IR-HPET-MSI"; 424 - 425 - fn = irq_domain_alloc_named_id_fwnode(hpet_msi_controller.name, 426 - hpet_id); 427 - if (!fn) { 428 - kfree(domain_info); 429 - return NULL; 430 - } 431 - 432 - d = msi_create_irq_domain(fn, domain_info, parent); 433 - if (!d) { 434 - irq_domain_free_fwnode(fn); 435 - kfree(domain_info); 436 - } 437 - return d; 438 - } 439 - 440 - int hpet_assign_irq(struct irq_domain *domain, struct hpet_channel *hc, 441 - int dev_num) 442 - { 443 - struct irq_alloc_info info; 444 - 445 - init_irq_alloc_info(&info, NULL); 446 - info.type = X86_IRQ_ALLOC_TYPE_HPET; 447 - info.data = hc; 448 - info.devid = hpet_dev_id(domain); 449 - info.hwirq = dev_num; 450 - 451 - return irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, &info); 452 - } 453 - #endif
+112 -6
arch/x86/kernel/hpet.c
··· 7 7 #include <linux/cpu.h> 8 8 #include <linux/irq.h> 9 9 10 + #include <asm/irq_remapping.h> 10 11 #include <asm/hpet.h> 11 12 #include <asm/time.h> 12 13 ··· 51 50 u8 hpet_blockid; /* OS timer block num */ 52 51 bool hpet_msi_disable; 53 52 54 - #ifdef CONFIG_PCI_MSI 53 + #ifdef CONFIG_GENERIC_MSI_IRQ 55 54 static DEFINE_PER_CPU(struct hpet_channel *, cpu_hpet_channel); 56 55 static struct irq_domain *hpet_domain; 57 56 #endif ··· 468 467 /* 469 468 * HPET MSI Support 470 469 */ 471 - #ifdef CONFIG_PCI_MSI 472 - 473 - void hpet_msi_unmask(struct irq_data *data) 470 + #ifdef CONFIG_GENERIC_MSI_IRQ 471 + static void hpet_msi_unmask(struct irq_data *data) 474 472 { 475 473 struct hpet_channel *hc = irq_data_get_irq_handler_data(data); 476 474 unsigned int cfg; ··· 479 479 hpet_writel(cfg, HPET_Tn_CFG(hc->num)); 480 480 } 481 481 482 - void hpet_msi_mask(struct irq_data *data) 482 + static void hpet_msi_mask(struct irq_data *data) 483 483 { 484 484 struct hpet_channel *hc = irq_data_get_irq_handler_data(data); 485 485 unsigned int cfg; ··· 489 489 hpet_writel(cfg, HPET_Tn_CFG(hc->num)); 490 490 } 491 491 492 - void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg) 492 + static void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg) 493 493 { 494 494 hpet_writel(msg->data, HPET_Tn_ROUTE(hc->num)); 495 495 hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hc->num) + 4); 496 + } 497 + 498 + static void hpet_msi_write_msg(struct irq_data *data, struct msi_msg *msg) 499 + { 500 + hpet_msi_write(irq_data_get_irq_handler_data(data), msg); 501 + } 502 + 503 + static struct irq_chip hpet_msi_controller __ro_after_init = { 504 + .name = "HPET-MSI", 505 + .irq_unmask = hpet_msi_unmask, 506 + .irq_mask = hpet_msi_mask, 507 + .irq_ack = irq_chip_ack_parent, 508 + .irq_set_affinity = msi_domain_set_affinity, 509 + .irq_retrigger = irq_chip_retrigger_hierarchy, 510 + .irq_write_msi_msg = hpet_msi_write_msg, 511 + .flags = IRQCHIP_SKIP_SET_WAKE, 512 + }; 513 + 514 + static int hpet_msi_init(struct irq_domain *domain, 515 + struct msi_domain_info *info, unsigned int virq, 516 + irq_hw_number_t hwirq, msi_alloc_info_t *arg) 517 + { 518 + irq_set_status_flags(virq, IRQ_MOVE_PCNTXT); 519 + irq_domain_set_info(domain, virq, arg->hwirq, info->chip, NULL, 520 + handle_edge_irq, arg->data, "edge"); 521 + 522 + return 0; 523 + } 524 + 525 + static void hpet_msi_free(struct irq_domain *domain, 526 + struct msi_domain_info *info, unsigned int virq) 527 + { 528 + irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT); 529 + } 530 + 531 + static struct msi_domain_ops hpet_msi_domain_ops = { 532 + .msi_init = hpet_msi_init, 533 + .msi_free = hpet_msi_free, 534 + }; 535 + 536 + static struct msi_domain_info hpet_msi_domain_info = { 537 + .ops = &hpet_msi_domain_ops, 538 + .chip = &hpet_msi_controller, 539 + .flags = MSI_FLAG_USE_DEF_DOM_OPS, 540 + }; 541 + 542 + static struct irq_domain *hpet_create_irq_domain(int hpet_id) 543 + { 544 + struct msi_domain_info *domain_info; 545 + struct irq_domain *parent, *d; 546 + struct irq_alloc_info info; 547 + struct fwnode_handle *fn; 548 + 549 + if (x86_vector_domain == NULL) 550 + return NULL; 551 + 552 + domain_info = kzalloc(sizeof(*domain_info), GFP_KERNEL); 553 + if (!domain_info) 554 + return NULL; 555 + 556 + *domain_info = hpet_msi_domain_info; 557 + domain_info->data = (void *)(long)hpet_id; 558 + 559 + init_irq_alloc_info(&info, NULL); 560 + info.type = X86_IRQ_ALLOC_TYPE_HPET_GET_PARENT; 561 + info.devid = hpet_id; 562 + parent = irq_remapping_get_irq_domain(&info); 563 + if (parent == NULL) 564 + parent = x86_vector_domain; 565 + else 566 + hpet_msi_controller.name = "IR-HPET-MSI"; 567 + 568 + fn = irq_domain_alloc_named_id_fwnode(hpet_msi_controller.name, 569 + hpet_id); 570 + if (!fn) { 571 + kfree(domain_info); 572 + return NULL; 573 + } 574 + 575 + d = msi_create_irq_domain(fn, domain_info, parent); 576 + if (!d) { 577 + irq_domain_free_fwnode(fn); 578 + kfree(domain_info); 579 + } 580 + return d; 581 + } 582 + 583 + static inline int hpet_dev_id(struct irq_domain *domain) 584 + { 585 + struct msi_domain_info *info = msi_get_domain_info(domain); 586 + 587 + return (int)(long)info->data; 588 + } 589 + 590 + static int hpet_assign_irq(struct irq_domain *domain, struct hpet_channel *hc, 591 + int dev_num) 592 + { 593 + struct irq_alloc_info info; 594 + 595 + init_irq_alloc_info(&info, NULL); 596 + info.type = X86_IRQ_ALLOC_TYPE_HPET; 597 + info.data = hc; 598 + info.devid = hpet_dev_id(domain); 599 + info.hwirq = dev_num; 600 + 601 + return irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, &info); 496 602 } 497 603 498 604 static int hpet_clkevt_msi_resume(struct clock_event_device *evt)