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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'txgbe-irq_domain'

Jiawen Wu says:

====================
Implement irq_domain for TXGBE

Implement irq_domain for the MAC interrupt and handle the sub-irqs.

v3 -> v4:
- fix build error

v2 -> v3:
- use macro defines instead of magic number

v1 -> v2:
- move interrupt codes to txgbe_irq.c
- add txgbe-link-irq to msic irq domain
- remove functions that are not needed
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+337 -181
-2
drivers/net/ethernet/wangxun/libwx/wx_hw.c
··· 1958 1958 return -ENOMEM; 1959 1959 } 1960 1960 1961 - wx->msix_in_use = false; 1962 - 1963 1961 return 0; 1964 1962 } 1965 1963 EXPORT_SYMBOL(wx_sw_init);
+8 -12
drivers/net/ethernet/wangxun/libwx/wx_lib.c
··· 1614 1614 /* One for non-queue interrupts */ 1615 1615 nvecs += 1; 1616 1616 1617 - if (!wx->msix_in_use) { 1618 - wx->msix_entry = kcalloc(1, sizeof(struct msix_entry), 1619 - GFP_KERNEL); 1620 - if (!wx->msix_entry) { 1621 - kfree(wx->msix_q_entries); 1622 - wx->msix_q_entries = NULL; 1623 - return -ENOMEM; 1624 - } 1617 + wx->msix_entry = kcalloc(1, sizeof(struct msix_entry), 1618 + GFP_KERNEL); 1619 + if (!wx->msix_entry) { 1620 + kfree(wx->msix_q_entries); 1621 + wx->msix_q_entries = NULL; 1622 + return -ENOMEM; 1625 1623 } 1626 1624 1627 1625 nvecs = pci_alloc_irq_vectors_affinity(wx->pdev, nvecs, ··· 1929 1931 if (pdev->msix_enabled) { 1930 1932 kfree(wx->msix_q_entries); 1931 1933 wx->msix_q_entries = NULL; 1932 - if (!wx->msix_in_use) { 1933 - kfree(wx->msix_entry); 1934 - wx->msix_entry = NULL; 1935 - } 1934 + kfree(wx->msix_entry); 1935 + wx->msix_entry = NULL; 1936 1936 } 1937 1937 pci_free_irq_vectors(wx->pdev); 1938 1938 }
-1
drivers/net/ethernet/wangxun/libwx/wx_type.h
··· 1047 1047 unsigned int queues_per_pool; 1048 1048 struct msix_entry *msix_q_entries; 1049 1049 struct msix_entry *msix_entry; 1050 - bool msix_in_use; 1051 1050 struct wx_ring_feature ring_feature[RING_F_ARRAY_SIZE]; 1052 1051 1053 1052 /* misc interrupt status block */
+1
drivers/net/ethernet/wangxun/txgbe/Makefile
··· 9 9 txgbe-objs := txgbe_main.o \ 10 10 txgbe_hw.o \ 11 11 txgbe_phy.o \ 12 + txgbe_irq.o \ 12 13 txgbe_ethtool.o
+269
drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ 3 + 4 + #include <linux/irqdomain.h> 5 + #include <linux/pci.h> 6 + 7 + #include "../libwx/wx_type.h" 8 + #include "../libwx/wx_lib.h" 9 + #include "../libwx/wx_hw.h" 10 + #include "txgbe_type.h" 11 + #include "txgbe_phy.h" 12 + #include "txgbe_irq.h" 13 + 14 + /** 15 + * txgbe_irq_enable - Enable default interrupt generation settings 16 + * @wx: pointer to private structure 17 + * @queues: enable irqs for queues 18 + **/ 19 + void txgbe_irq_enable(struct wx *wx, bool queues) 20 + { 21 + wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK); 22 + 23 + /* unmask interrupt */ 24 + wx_intr_enable(wx, TXGBE_INTR_MISC); 25 + if (queues) 26 + wx_intr_enable(wx, TXGBE_INTR_QALL(wx)); 27 + } 28 + 29 + /** 30 + * txgbe_intr - msi/legacy mode Interrupt Handler 31 + * @irq: interrupt number 32 + * @data: pointer to a network interface device structure 33 + **/ 34 + static irqreturn_t txgbe_intr(int __always_unused irq, void *data) 35 + { 36 + struct wx_q_vector *q_vector; 37 + struct wx *wx = data; 38 + struct pci_dev *pdev; 39 + u32 eicr; 40 + 41 + q_vector = wx->q_vector[0]; 42 + pdev = wx->pdev; 43 + 44 + eicr = wx_misc_isb(wx, WX_ISB_VEC0); 45 + if (!eicr) { 46 + /* shared interrupt alert! 47 + * the interrupt that we masked before the ICR read. 48 + */ 49 + if (netif_running(wx->netdev)) 50 + txgbe_irq_enable(wx, true); 51 + return IRQ_NONE; /* Not our interrupt */ 52 + } 53 + wx->isb_mem[WX_ISB_VEC0] = 0; 54 + if (!(pdev->msi_enabled)) 55 + wr32(wx, WX_PX_INTA, 1); 56 + 57 + wx->isb_mem[WX_ISB_MISC] = 0; 58 + /* would disable interrupts here but it is auto disabled */ 59 + napi_schedule_irqoff(&q_vector->napi); 60 + 61 + /* re-enable link(maybe) and non-queue interrupts, no flush. 62 + * txgbe_poll will re-enable the queue interrupts 63 + */ 64 + if (netif_running(wx->netdev)) 65 + txgbe_irq_enable(wx, false); 66 + 67 + return IRQ_HANDLED; 68 + } 69 + 70 + /** 71 + * txgbe_request_msix_irqs - Initialize MSI-X interrupts 72 + * @wx: board private structure 73 + * 74 + * Allocate MSI-X vectors and request interrupts from the kernel. 75 + **/ 76 + static int txgbe_request_msix_irqs(struct wx *wx) 77 + { 78 + struct net_device *netdev = wx->netdev; 79 + int vector, err; 80 + 81 + for (vector = 0; vector < wx->num_q_vectors; vector++) { 82 + struct wx_q_vector *q_vector = wx->q_vector[vector]; 83 + struct msix_entry *entry = &wx->msix_q_entries[vector]; 84 + 85 + if (q_vector->tx.ring && q_vector->rx.ring) 86 + snprintf(q_vector->name, sizeof(q_vector->name) - 1, 87 + "%s-TxRx-%d", netdev->name, entry->entry); 88 + else 89 + /* skip this unused q_vector */ 90 + continue; 91 + 92 + err = request_irq(entry->vector, wx_msix_clean_rings, 0, 93 + q_vector->name, q_vector); 94 + if (err) { 95 + wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n", 96 + q_vector->name, err); 97 + goto free_queue_irqs; 98 + } 99 + } 100 + 101 + return 0; 102 + 103 + free_queue_irqs: 104 + while (vector) { 105 + vector--; 106 + free_irq(wx->msix_q_entries[vector].vector, 107 + wx->q_vector[vector]); 108 + } 109 + wx_reset_interrupt_capability(wx); 110 + return err; 111 + } 112 + 113 + /** 114 + * txgbe_request_irq - initialize interrupts 115 + * @wx: board private structure 116 + * 117 + * Attempt to configure interrupts using the best available 118 + * capabilities of the hardware and kernel. 119 + **/ 120 + int txgbe_request_irq(struct wx *wx) 121 + { 122 + struct net_device *netdev = wx->netdev; 123 + struct pci_dev *pdev = wx->pdev; 124 + int err; 125 + 126 + if (pdev->msix_enabled) 127 + err = txgbe_request_msix_irqs(wx); 128 + else if (pdev->msi_enabled) 129 + err = request_irq(wx->pdev->irq, &txgbe_intr, 0, 130 + netdev->name, wx); 131 + else 132 + err = request_irq(wx->pdev->irq, &txgbe_intr, IRQF_SHARED, 133 + netdev->name, wx); 134 + 135 + if (err) 136 + wx_err(wx, "request_irq failed, Error %d\n", err); 137 + 138 + return err; 139 + } 140 + 141 + static int txgbe_request_gpio_irq(struct txgbe *txgbe) 142 + { 143 + txgbe->gpio_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO); 144 + return request_threaded_irq(txgbe->gpio_irq, NULL, 145 + txgbe_gpio_irq_handler, 146 + IRQF_ONESHOT, "txgbe-gpio-irq", txgbe); 147 + } 148 + 149 + static int txgbe_request_link_irq(struct txgbe *txgbe) 150 + { 151 + txgbe->link_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK); 152 + return request_threaded_irq(txgbe->link_irq, NULL, 153 + txgbe_link_irq_handler, 154 + IRQF_ONESHOT, "txgbe-link-irq", txgbe); 155 + } 156 + 157 + static const struct irq_chip txgbe_irq_chip = { 158 + .name = "txgbe-misc-irq", 159 + }; 160 + 161 + static int txgbe_misc_irq_domain_map(struct irq_domain *d, 162 + unsigned int irq, 163 + irq_hw_number_t hwirq) 164 + { 165 + struct txgbe *txgbe = d->host_data; 166 + 167 + irq_set_chip_data(irq, txgbe); 168 + irq_set_chip(irq, &txgbe->misc.chip); 169 + irq_set_nested_thread(irq, true); 170 + irq_set_noprobe(irq); 171 + 172 + return 0; 173 + } 174 + 175 + static const struct irq_domain_ops txgbe_misc_irq_domain_ops = { 176 + .map = txgbe_misc_irq_domain_map, 177 + }; 178 + 179 + static irqreturn_t txgbe_misc_irq_handle(int irq, void *data) 180 + { 181 + struct txgbe *txgbe = data; 182 + struct wx *wx = txgbe->wx; 183 + unsigned int nhandled = 0; 184 + unsigned int sub_irq; 185 + u32 eicr; 186 + 187 + eicr = wx_misc_isb(wx, WX_ISB_MISC); 188 + if (eicr & TXGBE_PX_MISC_GPIO) { 189 + sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO); 190 + handle_nested_irq(sub_irq); 191 + nhandled++; 192 + } 193 + if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN | 194 + TXGBE_PX_MISC_ETH_AN)) { 195 + sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK); 196 + handle_nested_irq(sub_irq); 197 + nhandled++; 198 + } 199 + 200 + wx_intr_enable(wx, TXGBE_INTR_MISC); 201 + return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); 202 + } 203 + 204 + static void txgbe_del_irq_domain(struct txgbe *txgbe) 205 + { 206 + int hwirq, virq; 207 + 208 + for (hwirq = 0; hwirq < txgbe->misc.nirqs; hwirq++) { 209 + virq = irq_find_mapping(txgbe->misc.domain, hwirq); 210 + irq_dispose_mapping(virq); 211 + } 212 + 213 + irq_domain_remove(txgbe->misc.domain); 214 + } 215 + 216 + void txgbe_free_misc_irq(struct txgbe *txgbe) 217 + { 218 + free_irq(txgbe->gpio_irq, txgbe); 219 + free_irq(txgbe->link_irq, txgbe); 220 + free_irq(txgbe->misc.irq, txgbe); 221 + txgbe_del_irq_domain(txgbe); 222 + } 223 + 224 + int txgbe_setup_misc_irq(struct txgbe *txgbe) 225 + { 226 + struct wx *wx = txgbe->wx; 227 + int hwirq, err; 228 + 229 + txgbe->misc.nirqs = 2; 230 + txgbe->misc.domain = irq_domain_add_simple(NULL, txgbe->misc.nirqs, 0, 231 + &txgbe_misc_irq_domain_ops, txgbe); 232 + if (!txgbe->misc.domain) 233 + return -ENOMEM; 234 + 235 + for (hwirq = 0; hwirq < txgbe->misc.nirqs; hwirq++) 236 + irq_create_mapping(txgbe->misc.domain, hwirq); 237 + 238 + txgbe->misc.chip = txgbe_irq_chip; 239 + if (wx->pdev->msix_enabled) 240 + txgbe->misc.irq = wx->msix_entry->vector; 241 + else 242 + txgbe->misc.irq = wx->pdev->irq; 243 + 244 + err = request_threaded_irq(txgbe->misc.irq, NULL, 245 + txgbe_misc_irq_handle, 246 + IRQF_ONESHOT, 247 + wx->netdev->name, txgbe); 248 + if (err) 249 + goto del_misc_irq; 250 + 251 + err = txgbe_request_gpio_irq(txgbe); 252 + if (err) 253 + goto free_msic_irq; 254 + 255 + err = txgbe_request_link_irq(txgbe); 256 + if (err) 257 + goto free_gpio_irq; 258 + 259 + return 0; 260 + 261 + free_gpio_irq: 262 + free_irq(txgbe->gpio_irq, txgbe); 263 + free_msic_irq: 264 + free_irq(txgbe->misc.irq, txgbe); 265 + del_misc_irq: 266 + txgbe_del_irq_domain(txgbe); 267 + 268 + return err; 269 + }
+7
drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ 3 + 4 + void txgbe_irq_enable(struct wx *wx, bool queues); 5 + int txgbe_request_irq(struct wx *wx); 6 + void txgbe_free_misc_irq(struct txgbe *txgbe); 7 + int txgbe_setup_misc_irq(struct txgbe *txgbe);
+12 -128
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
··· 17 17 #include "txgbe_type.h" 18 18 #include "txgbe_hw.h" 19 19 #include "txgbe_phy.h" 20 + #include "txgbe_irq.h" 20 21 #include "txgbe_ethtool.h" 21 22 22 23 char txgbe_driver_name[] = "txgbe"; ··· 75 74 } 76 75 77 76 return physfns; 78 - } 79 - 80 - /** 81 - * txgbe_irq_enable - Enable default interrupt generation settings 82 - * @wx: pointer to private structure 83 - * @queues: enable irqs for queues 84 - **/ 85 - static void txgbe_irq_enable(struct wx *wx, bool queues) 86 - { 87 - wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK); 88 - 89 - /* unmask interrupt */ 90 - wx_intr_enable(wx, TXGBE_INTR_MISC); 91 - if (queues) 92 - wx_intr_enable(wx, TXGBE_INTR_QALL(wx)); 93 - } 94 - 95 - /** 96 - * txgbe_intr - msi/legacy mode Interrupt Handler 97 - * @irq: interrupt number 98 - * @data: pointer to a network interface device structure 99 - **/ 100 - static irqreturn_t txgbe_intr(int __always_unused irq, void *data) 101 - { 102 - struct wx_q_vector *q_vector; 103 - struct wx *wx = data; 104 - struct pci_dev *pdev; 105 - u32 eicr; 106 - 107 - q_vector = wx->q_vector[0]; 108 - pdev = wx->pdev; 109 - 110 - eicr = wx_misc_isb(wx, WX_ISB_VEC0); 111 - if (!eicr) { 112 - /* shared interrupt alert! 113 - * the interrupt that we masked before the ICR read. 114 - */ 115 - if (netif_running(wx->netdev)) 116 - txgbe_irq_enable(wx, true); 117 - return IRQ_NONE; /* Not our interrupt */ 118 - } 119 - wx->isb_mem[WX_ISB_VEC0] = 0; 120 - if (!(pdev->msi_enabled)) 121 - wr32(wx, WX_PX_INTA, 1); 122 - 123 - wx->isb_mem[WX_ISB_MISC] = 0; 124 - /* would disable interrupts here but it is auto disabled */ 125 - napi_schedule_irqoff(&q_vector->napi); 126 - 127 - /* re-enable link(maybe) and non-queue interrupts, no flush. 128 - * txgbe_poll will re-enable the queue interrupts 129 - */ 130 - if (netif_running(wx->netdev)) 131 - txgbe_irq_enable(wx, false); 132 - 133 - return IRQ_HANDLED; 134 - } 135 - 136 - /** 137 - * txgbe_request_msix_irqs - Initialize MSI-X interrupts 138 - * @wx: board private structure 139 - * 140 - * Allocate MSI-X vectors and request interrupts from the kernel. 141 - **/ 142 - static int txgbe_request_msix_irqs(struct wx *wx) 143 - { 144 - struct net_device *netdev = wx->netdev; 145 - int vector, err; 146 - 147 - for (vector = 0; vector < wx->num_q_vectors; vector++) { 148 - struct wx_q_vector *q_vector = wx->q_vector[vector]; 149 - struct msix_entry *entry = &wx->msix_q_entries[vector]; 150 - 151 - if (q_vector->tx.ring && q_vector->rx.ring) 152 - snprintf(q_vector->name, sizeof(q_vector->name) - 1, 153 - "%s-TxRx-%d", netdev->name, entry->entry); 154 - else 155 - /* skip this unused q_vector */ 156 - continue; 157 - 158 - err = request_irq(entry->vector, wx_msix_clean_rings, 0, 159 - q_vector->name, q_vector); 160 - if (err) { 161 - wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n", 162 - q_vector->name, err); 163 - goto free_queue_irqs; 164 - } 165 - } 166 - 167 - return 0; 168 - 169 - free_queue_irqs: 170 - while (vector) { 171 - vector--; 172 - free_irq(wx->msix_q_entries[vector].vector, 173 - wx->q_vector[vector]); 174 - } 175 - wx_reset_interrupt_capability(wx); 176 - return err; 177 - } 178 - 179 - /** 180 - * txgbe_request_irq - initialize interrupts 181 - * @wx: board private structure 182 - * 183 - * Attempt to configure interrupts using the best available 184 - * capabilities of the hardware and kernel. 185 - **/ 186 - static int txgbe_request_irq(struct wx *wx) 187 - { 188 - struct net_device *netdev = wx->netdev; 189 - struct pci_dev *pdev = wx->pdev; 190 - int err; 191 - 192 - if (pdev->msix_enabled) 193 - err = txgbe_request_msix_irqs(wx); 194 - else if (pdev->msi_enabled) 195 - err = request_irq(wx->pdev->irq, &txgbe_intr, 0, 196 - netdev->name, wx); 197 - else 198 - err = request_irq(wx->pdev->irq, &txgbe_intr, IRQF_SHARED, 199 - netdev->name, wx); 200 - 201 - if (err) 202 - wx_err(wx, "request_irq failed, Error %d\n", err); 203 - 204 - return err; 205 77 } 206 78 207 79 static void txgbe_up_complete(struct wx *wx) ··· 392 518 int txgbe_setup_tc(struct net_device *dev, u8 tc) 393 519 { 394 520 struct wx *wx = netdev_priv(dev); 521 + struct txgbe *txgbe = wx->priv; 395 522 396 523 /* Hardware has to reinitialize queues and interrupts to 397 524 * match packet buffer alignment. Unfortunately, the ··· 403 528 else 404 529 txgbe_reset(wx); 405 530 531 + txgbe_free_misc_irq(txgbe); 406 532 wx_clear_interrupt_scheme(wx); 407 533 408 534 if (tc) ··· 412 536 netdev_reset_tc(dev); 413 537 414 538 wx_init_interrupt_scheme(wx); 539 + txgbe_setup_misc_irq(txgbe); 415 540 416 541 if (netif_running(dev)) 417 542 txgbe_open(dev); ··· 628 751 txgbe->wx = wx; 629 752 wx->priv = txgbe; 630 753 631 - err = txgbe_init_phy(txgbe); 754 + err = txgbe_setup_misc_irq(txgbe); 632 755 if (err) 633 756 goto err_release_hw; 757 + 758 + err = txgbe_init_phy(txgbe); 759 + if (err) 760 + goto err_free_misc_irq; 634 761 635 762 err = register_netdev(netdev); 636 763 if (err) ··· 662 781 663 782 err_remove_phy: 664 783 txgbe_remove_phy(txgbe); 784 + err_free_misc_irq: 785 + txgbe_free_misc_irq(txgbe); 665 786 err_release_hw: 666 787 wx_clear_interrupt_scheme(wx); 667 788 wx_control_hw(wx, false); ··· 696 813 unregister_netdev(netdev); 697 814 698 815 txgbe_remove_phy(txgbe); 816 + txgbe_free_misc_irq(txgbe); 699 817 700 818 pci_release_selected_regions(pdev, 701 819 pci_select_bars(pdev, IORESOURCE_MEM));
+21 -38
drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
··· 292 292 return 0; 293 293 } 294 294 295 + irqreturn_t txgbe_link_irq_handler(int irq, void *data) 296 + { 297 + struct txgbe *txgbe = data; 298 + struct wx *wx = txgbe->wx; 299 + u32 status; 300 + bool up; 301 + 302 + status = rd32(wx, TXGBE_CFG_PORT_ST); 303 + up = !!(status & TXGBE_CFG_PORT_ST_LINK_UP); 304 + 305 + phylink_mac_change(wx->phylink, up); 306 + 307 + return IRQ_HANDLED; 308 + } 309 + 295 310 static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) 296 311 { 297 312 struct wx *wx = gpiochip_get_data(chip); ··· 452 437 } 453 438 454 439 static const struct irq_chip txgbe_gpio_irq_chip = { 455 - .name = "txgbe_gpio_irq", 440 + .name = "txgbe-gpio-irq", 456 441 .irq_ack = txgbe_gpio_irq_ack, 457 442 .irq_mask = txgbe_gpio_irq_mask, 458 443 .irq_unmask = txgbe_gpio_irq_unmask, ··· 461 446 GPIOCHIP_IRQ_RESOURCE_HELPERS, 462 447 }; 463 448 464 - static void txgbe_irq_handler(struct irq_desc *desc) 449 + irqreturn_t txgbe_gpio_irq_handler(int irq, void *data) 465 450 { 466 - struct irq_chip *chip = irq_desc_get_chip(desc); 467 - struct wx *wx = irq_desc_get_handler_data(desc); 468 - struct txgbe *txgbe = wx->priv; 451 + struct txgbe *txgbe = data; 452 + struct wx *wx = txgbe->wx; 469 453 irq_hw_number_t hwirq; 470 454 unsigned long gpioirq; 471 455 struct gpio_chip *gc; 472 456 unsigned long flags; 473 - u32 eicr; 474 - 475 - eicr = wx_misc_isb(wx, WX_ISB_MISC); 476 - 477 - chained_irq_enter(chip, desc); 478 457 479 458 gpioirq = rd32(wx, WX_GPIO_INTSTATUS); 480 459 ··· 477 468 int gpio = irq_find_mapping(gc->irq.domain, hwirq); 478 469 u32 irq_type = irq_get_trigger_type(gpio); 479 470 480 - generic_handle_domain_irq(gc->irq.domain, hwirq); 471 + handle_nested_irq(gpio); 481 472 482 473 if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { 483 474 raw_spin_lock_irqsave(&wx->gpio_lock, flags); ··· 486 477 } 487 478 } 488 479 489 - chained_irq_exit(chip, desc); 490 - 491 - if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN | 492 - TXGBE_PX_MISC_ETH_AN)) { 493 - u32 reg = rd32(wx, TXGBE_CFG_PORT_ST); 494 - 495 - phylink_mac_change(wx->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP)); 496 - } 497 - 498 - /* unmask interrupt */ 499 - wx_intr_enable(wx, TXGBE_INTR_MISC); 480 + return IRQ_HANDLED; 500 481 } 501 482 502 483 static int txgbe_gpio_init(struct txgbe *txgbe) ··· 523 524 524 525 girq = &gc->irq; 525 526 gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip); 526 - girq->parent_handler = txgbe_irq_handler; 527 - girq->parent_handler_data = wx; 528 - girq->num_parents = 1; 529 - girq->parents = devm_kcalloc(dev, girq->num_parents, 530 - sizeof(*girq->parents), GFP_KERNEL); 531 - if (!girq->parents) 532 - return -ENOMEM; 533 - 534 - /* now only suuported on MSI-X interrupt */ 535 - if (!wx->msix_entry) 536 - return -EPERM; 537 - 538 - girq->parents[0] = wx->msix_entry->vector; 539 527 girq->default_type = IRQ_TYPE_NONE; 540 528 girq->handler = handle_bad_irq; 541 529 ··· 740 754 goto err_unregister_i2c; 741 755 } 742 756 743 - wx->msix_in_use = true; 744 - 745 757 return 0; 746 758 747 759 err_unregister_i2c: ··· 772 788 phylink_destroy(txgbe->wx->phylink); 773 789 xpcs_destroy(txgbe->xpcs); 774 790 software_node_unregister_node_group(txgbe->nodes.group); 775 - txgbe->wx->msix_in_use = false; 776 791 }
+2
drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
··· 4 4 #ifndef _TXGBE_PHY_H_ 5 5 #define _TXGBE_PHY_H_ 6 6 7 + irqreturn_t txgbe_gpio_irq_handler(int irq, void *data); 8 + irqreturn_t txgbe_link_irq_handler(int irq, void *data); 7 9 int txgbe_init_phy(struct txgbe *txgbe); 8 10 void txgbe_remove_phy(struct txgbe *txgbe); 9 11
+17
drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
··· 5 5 #define _TXGBE_TYPE_H_ 6 6 7 7 #include <linux/property.h> 8 + #include <linux/irq.h> 8 9 9 10 /* Device IDs */ 10 11 #define TXGBE_DEV_ID_SP1000 0x1001 ··· 170 169 const struct software_node *group[SWNODE_MAX + 1]; 171 170 }; 172 171 172 + enum txgbe_misc_irqs { 173 + TXGBE_IRQ_GPIO = 0, 174 + TXGBE_IRQ_LINK, 175 + TXGBE_IRQ_MAX 176 + }; 177 + 178 + struct txgbe_irq { 179 + struct irq_chip chip; 180 + struct irq_domain *domain; 181 + int nirqs; 182 + int irq; 183 + }; 184 + 173 185 struct txgbe { 174 186 struct wx *wx; 175 187 struct txgbe_nodes nodes; 188 + struct txgbe_irq misc; 176 189 struct dw_xpcs *xpcs; 177 190 struct platform_device *sfp_dev; 178 191 struct platform_device *i2c_dev; 179 192 struct clk_lookup *clock; 180 193 struct clk *clk; 181 194 struct gpio_chip *gpio; 195 + unsigned int gpio_irq; 196 + unsigned int link_irq; 182 197 }; 183 198 184 199 #endif /* _TXGBE_TYPE_H_ */