1313
1414#include "../libwx/wx_type.h"
1515#include "../libwx/wx_hw.h"
16+ #include "../libwx/wx_lib.h"
1617#include "ngbe_type.h"
1718#include "ngbe_mdio.h"
1819#include "ngbe_hw.h"
@@ -148,6 +149,161 @@ static int ngbe_sw_init(struct wx *wx)
148149 return 0 ;
149150}
150151
152+ /**
153+ * ngbe_irq_enable - Enable default interrupt generation settings
154+ * @wx: board private structure
155+ * @queues: enable all queues interrupts
156+ **/
157+ static void ngbe_irq_enable (struct wx * wx , bool queues )
158+ {
159+ u32 mask ;
160+
161+ /* enable misc interrupt */
162+ mask = NGBE_PX_MISC_IEN_MASK ;
163+
164+ wr32 (wx , WX_GPIO_DDR , WX_GPIO_DDR_0 );
165+ wr32 (wx , WX_GPIO_INTEN , WX_GPIO_INTEN_0 | WX_GPIO_INTEN_1 );
166+ wr32 (wx , WX_GPIO_INTTYPE_LEVEL , 0x0 );
167+ wr32 (wx , WX_GPIO_POLARITY , wx -> gpio_ctrl ? 0 : 0x3 );
168+
169+ wr32 (wx , WX_PX_MISC_IEN , mask );
170+
171+ /* mask interrupt */
172+ if (queues )
173+ wx_intr_enable (wx , NGBE_INTR_ALL );
174+ else
175+ wx_intr_enable (wx , NGBE_INTR_MISC (wx ));
176+ }
177+
178+ /**
179+ * ngbe_intr - msi/legacy mode Interrupt Handler
180+ * @irq: interrupt number
181+ * @data: pointer to a network interface device structure
182+ **/
183+ static irqreturn_t ngbe_intr (int __always_unused irq , void * data )
184+ {
185+ struct wx_q_vector * q_vector ;
186+ struct wx * wx = data ;
187+ struct pci_dev * pdev ;
188+ u32 eicr ;
189+
190+ q_vector = wx -> q_vector [0 ];
191+ pdev = wx -> pdev ;
192+
193+ eicr = wx_misc_isb (wx , WX_ISB_VEC0 );
194+ if (!eicr ) {
195+ /* shared interrupt alert!
196+ * the interrupt that we masked before the EICR read.
197+ */
198+ if (netif_running (wx -> netdev ))
199+ ngbe_irq_enable (wx , true);
200+ return IRQ_NONE ; /* Not our interrupt */
201+ }
202+ wx -> isb_mem [WX_ISB_VEC0 ] = 0 ;
203+ if (!(pdev -> msi_enabled ))
204+ wr32 (wx , WX_PX_INTA , 1 );
205+
206+ wx -> isb_mem [WX_ISB_MISC ] = 0 ;
207+ /* would disable interrupts here but it is auto disabled */
208+ napi_schedule_irqoff (& q_vector -> napi );
209+
210+ if (netif_running (wx -> netdev ))
211+ ngbe_irq_enable (wx , false);
212+
213+ return IRQ_HANDLED ;
214+ }
215+
216+ static irqreturn_t ngbe_msix_other (int __always_unused irq , void * data )
217+ {
218+ struct wx * wx = data ;
219+
220+ /* re-enable the original interrupt state, no lsc, no queues */
221+ if (netif_running (wx -> netdev ))
222+ ngbe_irq_enable (wx , false);
223+
224+ return IRQ_HANDLED ;
225+ }
226+
227+ /**
228+ * ngbe_request_msix_irqs - Initialize MSI-X interrupts
229+ * @wx: board private structure
230+ *
231+ * ngbe_request_msix_irqs allocates MSI-X vectors and requests
232+ * interrupts from the kernel.
233+ **/
234+ static int ngbe_request_msix_irqs (struct wx * wx )
235+ {
236+ struct net_device * netdev = wx -> netdev ;
237+ int vector , err ;
238+
239+ for (vector = 0 ; vector < wx -> num_q_vectors ; vector ++ ) {
240+ struct wx_q_vector * q_vector = wx -> q_vector [vector ];
241+ struct msix_entry * entry = & wx -> msix_entries [vector ];
242+
243+ if (q_vector -> tx .ring && q_vector -> rx .ring )
244+ snprintf (q_vector -> name , sizeof (q_vector -> name ) - 1 ,
245+ "%s-TxRx-%d" , netdev -> name , entry -> entry );
246+ else
247+ /* skip this unused q_vector */
248+ continue ;
249+
250+ err = request_irq (entry -> vector , wx_msix_clean_rings , 0 ,
251+ q_vector -> name , q_vector );
252+ if (err ) {
253+ wx_err (wx , "request_irq failed for MSIX interrupt %s Error: %d\n" ,
254+ q_vector -> name , err );
255+ goto free_queue_irqs ;
256+ }
257+ }
258+
259+ err = request_irq (wx -> msix_entries [vector ].vector ,
260+ ngbe_msix_other , 0 , netdev -> name , wx );
261+
262+ if (err ) {
263+ wx_err (wx , "request_irq for msix_other failed: %d\n" , err );
264+ goto free_queue_irqs ;
265+ }
266+
267+ return 0 ;
268+
269+ free_queue_irqs :
270+ while (vector ) {
271+ vector -- ;
272+ free_irq (wx -> msix_entries [vector ].vector ,
273+ wx -> q_vector [vector ]);
274+ }
275+ wx_reset_interrupt_capability (wx );
276+ return err ;
277+ }
278+
279+ /**
280+ * ngbe_request_irq - initialize interrupts
281+ * @wx: board private structure
282+ *
283+ * Attempts to configure interrupts using the best available
284+ * capabilities of the hardware and kernel.
285+ **/
286+ static int ngbe_request_irq (struct wx * wx )
287+ {
288+ struct net_device * netdev = wx -> netdev ;
289+ struct pci_dev * pdev = wx -> pdev ;
290+ int err ;
291+
292+ if (pdev -> msix_enabled )
293+ err = ngbe_request_msix_irqs (wx );
294+ else if (pdev -> msi_enabled )
295+ err = request_irq (pdev -> irq , ngbe_intr , 0 ,
296+ netdev -> name , wx );
297+ else
298+ err = request_irq (pdev -> irq , ngbe_intr , IRQF_SHARED ,
299+ netdev -> name , wx );
300+
301+ if (err )
302+ wx_err (wx , "request_irq failed, Error %d\n" , err );
303+
304+ return err ;
305+ }
306+
151307static void ngbe_disable_device (struct wx * wx )
152308{
153309 struct net_device * netdev = wx -> netdev ;
@@ -157,6 +313,7 @@ static void ngbe_disable_device(struct wx *wx)
157313 netif_tx_disable (netdev );
158314 if (wx -> gpio_ctrl )
159315 ngbe_sfp_modules_txrx_powerctl (wx , false);
316+ wx_irq_disable (wx );
160317}
161318
162319static void ngbe_down (struct wx * wx )
@@ -167,8 +324,15 @@ static void ngbe_down(struct wx *wx)
167324
168325static void ngbe_up (struct wx * wx )
169326{
327+ wx_configure_vectors (wx );
328+
329+ /* clear any pending interrupts, may auto mask */
330+ rd32 (wx , WX_PX_IC );
331+ rd32 (wx , WX_PX_MISC_IC );
332+ ngbe_irq_enable (wx , true);
170333 if (wx -> gpio_ctrl )
171334 ngbe_sfp_modules_txrx_powerctl (wx , true);
335+
172336 phy_start (wx -> phydev );
173337}
174338
@@ -187,12 +351,26 @@ static int ngbe_open(struct net_device *netdev)
187351 int err ;
188352
189353 wx_control_hw (wx , true);
354+
355+ err = wx_setup_isb_resources (wx );
356+ if (err )
357+ return err ;
358+
359+ wx_configure (wx );
360+
361+ err = ngbe_request_irq (wx );
362+ if (err )
363+ goto err_req_irq ;
364+
190365 err = ngbe_phy_connect (wx );
191366 if (err )
192367 return err ;
193368 ngbe_up (wx );
194369
195370 return 0 ;
371+ err_req_irq :
372+ wx_free_isb_resources (wx );
373+ return err ;
196374}
197375
198376/**
@@ -211,6 +389,8 @@ static int ngbe_close(struct net_device *netdev)
211389 struct wx * wx = netdev_priv (netdev );
212390
213391 ngbe_down (wx );
392+ wx_free_irq (wx );
393+ wx_free_isb_resources (wx );
214394 phy_disconnect (wx -> phydev );
215395 wx_control_hw (wx , false);
216396
@@ -411,10 +591,14 @@ static int ngbe_probe(struct pci_dev *pdev,
411591 eth_hw_addr_set (netdev , wx -> mac .perm_addr );
412592 wx_mac_set_default_filter (wx , wx -> mac .perm_addr );
413593
594+ err = wx_init_interrupt_scheme (wx );
595+ if (err )
596+ goto err_free_mac_table ;
597+
414598 /* phy Interface Configuration */
415599 err = ngbe_mdio_init (wx );
416600 if (err )
417- goto err_free_mac_table ;
601+ goto err_clear_interrupt_scheme ;
418602
419603 err = register_netdev (netdev );
420604 if (err )
@@ -431,6 +615,8 @@ static int ngbe_probe(struct pci_dev *pdev,
431615
432616err_register :
433617 wx_control_hw (wx , false);
618+ err_clear_interrupt_scheme :
619+ wx_clear_interrupt_scheme (wx );
434620err_free_mac_table :
435621 kfree (wx -> mac_table );
436622err_pci_release_regions :
@@ -462,6 +648,7 @@ static void ngbe_remove(struct pci_dev *pdev)
462648 pci_select_bars (pdev , IORESOURCE_MEM ));
463649
464650 kfree (wx -> mac_table );
651+ wx_clear_interrupt_scheme (wx );
465652 pci_disable_pcie_error_reporting (pdev );
466653
467654 pci_disable_device (pdev );
0 commit comments