|
5 | 5 | #include <linux/types.h> |
6 | 6 |
|
7 | 7 | #include "fbnic.h" |
| 8 | +#include "fbnic_netdev.h" |
8 | 9 | #include "fbnic_txrx.h" |
9 | 10 |
|
10 | 11 | static irqreturn_t fbnic_fw_msix_intr(int __always_unused irq, void *data) |
@@ -81,6 +82,70 @@ void fbnic_fw_disable_mbx(struct fbnic_dev *fbd) |
81 | 82 | fbnic_mbx_clean(fbd); |
82 | 83 | } |
83 | 84 |
|
| 85 | +static irqreturn_t fbnic_pcs_msix_intr(int __always_unused irq, void *data) |
| 86 | +{ |
| 87 | + struct fbnic_dev *fbd = data; |
| 88 | + struct fbnic_net *fbn; |
| 89 | + |
| 90 | + if (fbd->mac->pcs_get_link_event(fbd) == FBNIC_LINK_EVENT_NONE) { |
| 91 | + fbnic_wr32(fbd, FBNIC_INTR_MASK_CLEAR(0), |
| 92 | + 1u << FBNIC_PCS_MSIX_ENTRY); |
| 93 | + return IRQ_HANDLED; |
| 94 | + } |
| 95 | + |
| 96 | + fbn = netdev_priv(fbd->netdev); |
| 97 | + |
| 98 | + phylink_pcs_change(&fbn->phylink_pcs, false); |
| 99 | + |
| 100 | + return IRQ_HANDLED; |
| 101 | +} |
| 102 | + |
| 103 | +/** |
| 104 | + * fbnic_pcs_irq_enable - Configure the MAC to enable it to advertise link |
| 105 | + * @fbd: Pointer to device to initialize |
| 106 | + * |
| 107 | + * This function provides basic bringup for the MAC/PCS IRQ. For now the IRQ |
| 108 | + * will remain disabled until we start the MAC/PCS/PHY logic via phylink. |
| 109 | + * |
| 110 | + * Return: non-zero on failure. |
| 111 | + **/ |
| 112 | +int fbnic_pcs_irq_enable(struct fbnic_dev *fbd) |
| 113 | +{ |
| 114 | + u32 vector = fbd->pcs_msix_vector; |
| 115 | + int err; |
| 116 | + |
| 117 | + /* Request the IRQ for MAC link vector. |
| 118 | + * Map MAC cause to it, and unmask it |
| 119 | + */ |
| 120 | + err = request_irq(vector, &fbnic_pcs_msix_intr, 0, |
| 121 | + fbd->netdev->name, fbd); |
| 122 | + if (err) |
| 123 | + return err; |
| 124 | + |
| 125 | + fbnic_wr32(fbd, FBNIC_INTR_MSIX_CTRL(FBNIC_INTR_MSIX_CTRL_PCS_IDX), |
| 126 | + FBNIC_PCS_MSIX_ENTRY | FBNIC_INTR_MSIX_CTRL_ENABLE); |
| 127 | + |
| 128 | + return 0; |
| 129 | +} |
| 130 | + |
| 131 | +/** |
| 132 | + * fbnic_pcs_irq_disable - Teardown the MAC IRQ to prepare for stopping |
| 133 | + * @fbd: Pointer to device that is stopping |
| 134 | + * |
| 135 | + * This function undoes the work done in fbnic_pcs_irq_enable and prepares |
| 136 | + * the device to no longer receive traffic on the host interface. |
| 137 | + **/ |
| 138 | +void fbnic_pcs_irq_disable(struct fbnic_dev *fbd) |
| 139 | +{ |
| 140 | + /* Disable interrupt */ |
| 141 | + fbnic_wr32(fbd, FBNIC_INTR_MSIX_CTRL(FBNIC_INTR_MSIX_CTRL_PCS_IDX), |
| 142 | + FBNIC_PCS_MSIX_ENTRY); |
| 143 | + fbnic_wr32(fbd, FBNIC_INTR_MASK_SET(0), 1u << FBNIC_PCS_MSIX_ENTRY); |
| 144 | + |
| 145 | + /* Free the vector */ |
| 146 | + free_irq(fbd->pcs_msix_vector, fbd); |
| 147 | +} |
| 148 | + |
84 | 149 | int fbnic_request_irq(struct fbnic_dev *fbd, int nr, irq_handler_t handler, |
85 | 150 | unsigned long flags, const char *name, void *data) |
86 | 151 | { |
@@ -108,6 +173,7 @@ void fbnic_free_irqs(struct fbnic_dev *fbd) |
108 | 173 | { |
109 | 174 | struct pci_dev *pdev = to_pci_dev(fbd->dev); |
110 | 175 |
|
| 176 | + fbd->pcs_msix_vector = 0; |
111 | 177 | fbd->fw_msix_vector = 0; |
112 | 178 |
|
113 | 179 | fbd->num_irqs = 0; |
@@ -135,6 +201,7 @@ int fbnic_alloc_irqs(struct fbnic_dev *fbd) |
135 | 201 |
|
136 | 202 | fbd->num_irqs = num_irqs; |
137 | 203 |
|
| 204 | + fbd->pcs_msix_vector = pci_irq_vector(pdev, FBNIC_PCS_MSIX_ENTRY); |
138 | 205 | fbd->fw_msix_vector = pci_irq_vector(pdev, FBNIC_FW_MSIX_ENTRY); |
139 | 206 |
|
140 | 207 | return 0; |
|
0 commit comments