@@ -336,6 +336,14 @@ struct iwl_tso_hdr_page {
336
336
* @fw_mon_phys: physical address of the buffer for the firmware monitor
337
337
* @fw_mon_page: points to the first page of the buffer for the firmware monitor
338
338
* @fw_mon_size: size of the buffer for the firmware monitor
339
+ * @msix_entries: array of MSI-X entries
340
+ * @msix_enabled: true if managed to enable MSI-X
341
+ * @allocated_vector: the number of interrupt vector allocated by the OS
342
+ * @default_irq_num: default irq for non rx interrupt
343
+ * @fh_init_mask: initial unmasked fh causes
344
+ * @hw_init_mask: initial unmasked hw causes
345
+ * @fh_mask: current unmasked fh causes
346
+ * @hw_mask: current unmasked hw causes
339
347
*/
340
348
struct iwl_trans_pcie {
341
349
struct iwl_rxq * rxq ;
@@ -402,6 +410,15 @@ struct iwl_trans_pcie {
402
410
dma_addr_t fw_mon_phys ;
403
411
struct page * fw_mon_page ;
404
412
u32 fw_mon_size ;
413
+
414
+ struct msix_entry msix_entries [IWL_MAX_RX_HW_QUEUES ];
415
+ bool msix_enabled ;
416
+ u32 allocated_vector ;
417
+ u32 default_irq_num ;
418
+ u32 fh_init_mask ;
419
+ u32 hw_init_mask ;
420
+ u32 fh_mask ;
421
+ u32 hw_mask ;
405
422
};
406
423
407
424
static inline struct iwl_trans_pcie *
@@ -430,7 +447,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
430
447
* RX
431
448
******************************************************/
432
449
int iwl_pcie_rx_init (struct iwl_trans * trans );
450
+ irqreturn_t iwl_pcie_msix_isr (int irq , void * data );
433
451
irqreturn_t iwl_pcie_irq_handler (int irq , void * dev_id );
452
+ irqreturn_t iwl_pcie_irq_msix_handler (int irq , void * dev_id );
453
+ irqreturn_t iwl_pcie_irq_rx_msix_handler (int irq , void * dev_id );
434
454
int iwl_pcie_rx_stop (struct iwl_trans * trans );
435
455
void iwl_pcie_rx_free (struct iwl_trans * trans );
436
456
@@ -485,15 +505,24 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans);
485
505
******************************************************/
486
506
static inline void iwl_disable_interrupts (struct iwl_trans * trans )
487
507
{
488
- clear_bit (STATUS_INT_ENABLED , & trans -> status );
489
-
490
- /* disable interrupts from uCode/NIC to host */
491
- iwl_write32 (trans , CSR_INT_MASK , 0x00000000 );
508
+ struct iwl_trans_pcie * trans_pcie = IWL_TRANS_GET_PCIE_TRANS (trans );
492
509
493
- /* acknowledge/clear/reset any interrupts still pending
494
- * from uCode or flow handler (Rx/Tx DMA) */
495
- iwl_write32 (trans , CSR_INT , 0xffffffff );
496
- iwl_write32 (trans , CSR_FH_INT_STATUS , 0xffffffff );
510
+ clear_bit (STATUS_INT_ENABLED , & trans -> status );
511
+ if (!trans_pcie -> msix_enabled ) {
512
+ /* disable interrupts from uCode/NIC to host */
513
+ iwl_write32 (trans , CSR_INT_MASK , 0x00000000 );
514
+
515
+ /* acknowledge/clear/reset any interrupts still pending
516
+ * from uCode or flow handler (Rx/Tx DMA) */
517
+ iwl_write32 (trans , CSR_INT , 0xffffffff );
518
+ iwl_write32 (trans , CSR_FH_INT_STATUS , 0xffffffff );
519
+ } else {
520
+ /* disable all the interrupt we might use */
521
+ iwl_write32 (trans , CSR_MSIX_FH_INT_MASK_AD ,
522
+ trans_pcie -> fh_init_mask );
523
+ iwl_write32 (trans , CSR_MSIX_HW_INT_MASK_AD ,
524
+ trans_pcie -> hw_init_mask );
525
+ }
497
526
IWL_DEBUG_ISR (trans , "Disabled interrupts\n" );
498
527
}
499
528
@@ -503,26 +532,69 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
503
532
504
533
IWL_DEBUG_ISR (trans , "Enabling interrupts\n" );
505
534
set_bit (STATUS_INT_ENABLED , & trans -> status );
506
- trans_pcie -> inta_mask = CSR_INI_SET_MASK ;
507
- iwl_write32 (trans , CSR_INT_MASK , trans_pcie -> inta_mask );
535
+ if (!trans_pcie -> msix_enabled ) {
536
+ trans_pcie -> inta_mask = CSR_INI_SET_MASK ;
537
+ iwl_write32 (trans , CSR_INT_MASK , trans_pcie -> inta_mask );
538
+ } else {
539
+ /*
540
+ * fh/hw_mask keeps all the unmasked causes.
541
+ * Unlike msi, in msix cause is enabled when it is unset.
542
+ */
543
+ trans_pcie -> hw_mask = trans_pcie -> hw_init_mask ;
544
+ trans_pcie -> fh_mask = trans_pcie -> fh_init_mask ;
545
+ iwl_write32 (trans , CSR_MSIX_FH_INT_MASK_AD ,
546
+ ~trans_pcie -> fh_mask );
547
+ iwl_write32 (trans , CSR_MSIX_HW_INT_MASK_AD ,
548
+ ~trans_pcie -> hw_mask );
549
+ }
550
+ }
551
+
552
+ static inline void iwl_enable_hw_int_msk_msix (struct iwl_trans * trans , u32 msk )
553
+ {
554
+ struct iwl_trans_pcie * trans_pcie = IWL_TRANS_GET_PCIE_TRANS (trans );
555
+
556
+ iwl_write32 (trans , CSR_MSIX_HW_INT_MASK_AD , ~msk );
557
+ trans_pcie -> hw_mask = msk ;
558
+ }
559
+
560
+ static inline void iwl_enable_fh_int_msk_msix (struct iwl_trans * trans , u32 msk )
561
+ {
562
+ struct iwl_trans_pcie * trans_pcie = IWL_TRANS_GET_PCIE_TRANS (trans );
563
+
564
+ iwl_write32 (trans , CSR_MSIX_FH_INT_MASK_AD , ~msk );
565
+ trans_pcie -> fh_mask = msk ;
508
566
}
509
567
510
568
static inline void iwl_enable_fw_load_int (struct iwl_trans * trans )
511
569
{
512
570
struct iwl_trans_pcie * trans_pcie = IWL_TRANS_GET_PCIE_TRANS (trans );
513
571
514
572
IWL_DEBUG_ISR (trans , "Enabling FW load interrupt\n" );
515
- trans_pcie -> inta_mask = CSR_INT_BIT_FH_TX ;
516
- iwl_write32 (trans , CSR_INT_MASK , trans_pcie -> inta_mask );
573
+ if (!trans_pcie -> msix_enabled ) {
574
+ trans_pcie -> inta_mask = CSR_INT_BIT_FH_TX ;
575
+ iwl_write32 (trans , CSR_INT_MASK , trans_pcie -> inta_mask );
576
+ } else {
577
+ iwl_write32 (trans , CSR_MSIX_HW_INT_MASK_AD ,
578
+ trans_pcie -> hw_init_mask );
579
+ iwl_enable_fh_int_msk_msix (trans ,
580
+ MSIX_FH_INT_CAUSES_D2S_CH0_NUM );
581
+ }
517
582
}
518
583
519
584
static inline void iwl_enable_rfkill_int (struct iwl_trans * trans )
520
585
{
521
586
struct iwl_trans_pcie * trans_pcie = IWL_TRANS_GET_PCIE_TRANS (trans );
522
587
523
588
IWL_DEBUG_ISR (trans , "Enabling rfkill interrupt\n" );
524
- trans_pcie -> inta_mask = CSR_INT_BIT_RF_KILL ;
525
- iwl_write32 (trans , CSR_INT_MASK , trans_pcie -> inta_mask );
589
+ if (!trans_pcie -> msix_enabled ) {
590
+ trans_pcie -> inta_mask = CSR_INT_BIT_RF_KILL ;
591
+ iwl_write32 (trans , CSR_INT_MASK , trans_pcie -> inta_mask );
592
+ } else {
593
+ iwl_write32 (trans , CSR_MSIX_FH_INT_MASK_AD ,
594
+ trans_pcie -> fh_init_mask );
595
+ iwl_enable_hw_int_msk_msix (trans ,
596
+ MSIX_HW_INT_CAUSES_REG_RF_KILL );
597
+ }
526
598
}
527
599
528
600
static inline void iwl_wake_queue (struct iwl_trans * trans ,
0 commit comments