@@ -592,6 +592,22 @@ static const struct net_device_ops netxen_netdev_ops = {
592592#endif
593593};
594594
595+ static inline bool netxen_function_zero (struct pci_dev * pdev )
596+ {
597+ return (PCI_FUNC (pdev -> devfn ) == 0 ) ? true : false;
598+ }
599+
600+ static inline void netxen_set_interrupt_mode (struct netxen_adapter * adapter ,
601+ u32 mode )
602+ {
603+ NXWR32 (adapter , NETXEN_INTR_MODE_REG , mode );
604+ }
605+
606+ static inline u32 netxen_get_interrupt_mode (struct netxen_adapter * adapter )
607+ {
608+ return NXRD32 (adapter , NETXEN_INTR_MODE_REG );
609+ }
610+
595611static void
596612netxen_initialize_interrupt_registers (struct netxen_adapter * adapter )
597613{
@@ -654,10 +670,11 @@ static int netxen_setup_msi_interrupts(struct netxen_adapter *adapter,
654670 return 0 ;
655671 }
656672
673+ dev_err (& pdev -> dev , "Failed to acquire MSI-X/MSI interrupt vector\n" );
657674 return - EIO ;
658675}
659676
660- static void netxen_setup_intr (struct netxen_adapter * adapter )
677+ static int netxen_setup_intr (struct netxen_adapter * adapter )
661678{
662679 struct pci_dev * pdev = adapter -> pdev ;
663680 int num_msix ;
@@ -674,11 +691,24 @@ static void netxen_setup_intr(struct netxen_adapter *adapter)
674691 netxen_initialize_interrupt_registers (adapter );
675692 netxen_set_msix_bit (pdev , 0 );
676693
677- if (!netxen_setup_msi_interrupts (adapter , num_msix ))
678- return ;
694+ if (netxen_function_zero (pdev )) {
695+ if (!netxen_setup_msi_interrupts (adapter , num_msix ))
696+ netxen_set_interrupt_mode (adapter , NETXEN_MSI_MODE );
697+ else
698+ netxen_set_interrupt_mode (adapter , NETXEN_INTX_MODE );
699+ } else {
700+ if (netxen_get_interrupt_mode (adapter ) == NETXEN_MSI_MODE &&
701+ netxen_setup_msi_interrupts (adapter , num_msix )) {
702+ dev_err (& pdev -> dev , "Co-existence of MSI-X/MSI and INTx interrupts is not supported\n" );
703+ return - EIO ;
704+ }
705+ }
679706
680- adapter -> msix_entries [0 ].vector = pdev -> irq ;
681- dev_info (& pdev -> dev , "using legacy interrupts\n" );
707+ if (!NETXEN_IS_MSI_FAMILY (adapter )) {
708+ adapter -> msix_entries [0 ].vector = pdev -> irq ;
709+ dev_info (& pdev -> dev , "using legacy interrupts\n" );
710+ }
711+ return 0 ;
682712}
683713
684714static void
@@ -1525,7 +1555,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15251555
15261556 netxen_nic_clear_stats (adapter );
15271557
1528- netxen_setup_intr (adapter );
1558+ err = netxen_setup_intr (adapter );
1559+
1560+ if (err ) {
1561+ dev_err (& adapter -> pdev -> dev ,
1562+ "Failed to setup interrupts, error = %d\n" , err );
1563+ goto err_out_disable_msi ;
1564+ }
15291565
15301566 err = netxen_setup_netdev (adapter , netdev );
15311567 if (err )
@@ -1613,7 +1649,7 @@ static void netxen_nic_remove(struct pci_dev *pdev)
16131649 clear_bit (__NX_RESETTING , & adapter -> state );
16141650
16151651 netxen_teardown_intr (adapter );
1616-
1652+ netxen_set_interrupt_mode ( adapter , 0 );
16171653 netxen_remove_diag_entries (adapter );
16181654
16191655 netxen_cleanup_pci_map (adapter );
0 commit comments