2019-06-01 10:08:37 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2017-01-23 22:09:15 -08:00
/*
* aQuantia Corporation Network Driver
2019-10-22 09:53:35 +00:00
* Copyright ( C ) 2014 - 2019 aQuantia Corporation . All rights reserved
2017-01-23 22:09:15 -08:00
*/
/* File aq_pci_func.c: Definition of PCI functions. */
2018-01-15 16:41:18 +03:00
# include <linux/interrupt.h>
# include <linux/module.h>
2018-01-19 17:03:21 +03:00
# include "aq_main.h"
2017-01-23 22:09:15 -08:00
# include "aq_nic.h"
# include "aq_vec.h"
# include "aq_hw.h"
2018-01-19 17:03:21 +03:00
# include "aq_pci_func.h"
2018-01-15 16:41:18 +03:00
# include "hw_atl/hw_atl_a0.h"
# include "hw_atl/hw_atl_b0.h"
2020-04-30 11:04:39 +03:00
# include "hw_atl2/hw_atl2.h"
2018-11-12 15:46:00 +00:00
# include "aq_filters.h"
2019-04-29 10:04:38 +00:00
# include "aq_drvinfo.h"
2020-03-25 15:52:39 +03:00
# include "aq_macsec.h"
2017-01-23 22:09:15 -08:00
2018-01-15 16:41:18 +03:00
static const struct pci_device_id aq_pci_tbl [ ] = {
2018-01-19 17:03:18 +03:00
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_0001 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_D100 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_D107 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_D108 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_D109 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC100 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC107 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC108 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC109 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC111 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC112 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC100S ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC107S ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC108S ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC109S ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC111S ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC112S ) , } ,
2020-04-30 11:04:39 +03:00
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC113DEV ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC113CS ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC114CS ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC113 ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC113C ) , } ,
{ PCI_VDEVICE ( AQUANTIA , AQ_DEVICE_ID_AQC115C ) , } ,
2018-01-15 16:41:18 +03:00
{ }
} ;
2018-01-23 02:10:38 +00:00
static const struct aq_board_revision_s hw_atl_boards [ ] = {
2018-01-19 17:03:19 +03:00
{ AQ_DEVICE_ID_0001 , AQ_HWREV_1 , & hw_atl_ops_a0 , & hw_atl_a0_caps_aqc107 , } ,
{ AQ_DEVICE_ID_D100 , AQ_HWREV_1 , & hw_atl_ops_a0 , & hw_atl_a0_caps_aqc100 , } ,
{ AQ_DEVICE_ID_D107 , AQ_HWREV_1 , & hw_atl_ops_a0 , & hw_atl_a0_caps_aqc107 , } ,
{ AQ_DEVICE_ID_D108 , AQ_HWREV_1 , & hw_atl_ops_a0 , & hw_atl_a0_caps_aqc108 , } ,
{ AQ_DEVICE_ID_D109 , AQ_HWREV_1 , & hw_atl_ops_a0 , & hw_atl_a0_caps_aqc109 , } ,
{ AQ_DEVICE_ID_0001 , AQ_HWREV_2 , & hw_atl_ops_b0 , & hw_atl_b0_caps_aqc107 , } ,
{ AQ_DEVICE_ID_D100 , AQ_HWREV_2 , & hw_atl_ops_b0 , & hw_atl_b0_caps_aqc100 , } ,
{ AQ_DEVICE_ID_D107 , AQ_HWREV_2 , & hw_atl_ops_b0 , & hw_atl_b0_caps_aqc107 , } ,
{ AQ_DEVICE_ID_D108 , AQ_HWREV_2 , & hw_atl_ops_b0 , & hw_atl_b0_caps_aqc108 , } ,
{ AQ_DEVICE_ID_D109 , AQ_HWREV_2 , & hw_atl_ops_b0 , & hw_atl_b0_caps_aqc109 , } ,
2020-04-25 08:58:11 +08:00
{ AQ_DEVICE_ID_AQC100 , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc100 , } ,
2018-01-19 17:03:19 +03:00
{ AQ_DEVICE_ID_AQC107 , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc107 , } ,
{ AQ_DEVICE_ID_AQC108 , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc108 , } ,
{ AQ_DEVICE_ID_AQC109 , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc109 , } ,
{ AQ_DEVICE_ID_AQC111 , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc111 , } ,
{ AQ_DEVICE_ID_AQC112 , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc112 , } ,
{ AQ_DEVICE_ID_AQC100S , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc100s , } ,
{ AQ_DEVICE_ID_AQC107S , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc107s , } ,
{ AQ_DEVICE_ID_AQC108S , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc108s , } ,
{ AQ_DEVICE_ID_AQC109S , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc109s , } ,
{ AQ_DEVICE_ID_AQC111S , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc111s , } ,
{ AQ_DEVICE_ID_AQC112S , AQ_HWREV_ANY , & hw_atl_ops_b1 , & hw_atl_b0_caps_aqc112s , } ,
2020-04-30 11:04:39 +03:00
{ AQ_DEVICE_ID_AQC113DEV , AQ_HWREV_ANY , & hw_atl2_ops , & hw_atl2_caps_aqc113 , } ,
{ AQ_DEVICE_ID_AQC113 , AQ_HWREV_ANY , & hw_atl2_ops , & hw_atl2_caps_aqc113 , } ,
{ AQ_DEVICE_ID_AQC113CS , AQ_HWREV_ANY , & hw_atl2_ops , & hw_atl2_caps_aqc113 , } ,
{ AQ_DEVICE_ID_AQC114CS , AQ_HWREV_ANY , & hw_atl2_ops , & hw_atl2_caps_aqc113 , } ,
{ AQ_DEVICE_ID_AQC113C , AQ_HWREV_ANY , & hw_atl2_ops , & hw_atl2_caps_aqc113 , } ,
{ AQ_DEVICE_ID_AQC115C , AQ_HWREV_ANY , & hw_atl2_ops , & hw_atl2_caps_aqc113 , } ,
2018-01-19 17:03:19 +03:00
} ;
2018-01-15 16:41:18 +03:00
MODULE_DEVICE_TABLE ( pci , aq_pci_tbl ) ;
2018-01-19 17:03:19 +03:00
static int aq_pci_probe_get_hw_by_id ( struct pci_dev * pdev ,
const struct aq_hw_ops * * ops ,
const struct aq_hw_caps_s * * caps )
2018-01-15 16:41:18 +03:00
{
2018-10-08 14:35:58 +01:00
int i ;
2018-01-19 17:03:19 +03:00
if ( pdev - > vendor ! = PCI_VENDOR_ID_AQUANTIA )
return - EINVAL ;
for ( i = 0 ; i < ARRAY_SIZE ( hw_atl_boards ) ; i + + ) {
if ( hw_atl_boards [ i ] . devid = = pdev - > device & &
( hw_atl_boards [ i ] . revision = = AQ_HWREV_ANY | |
hw_atl_boards [ i ] . revision = = pdev - > revision ) ) {
* ops = hw_atl_boards [ i ] . ops ;
* caps = hw_atl_boards [ i ] . caps ;
break ;
}
}
2018-01-15 16:41:18 +03:00
2018-01-19 17:03:19 +03:00
if ( i = = ARRAY_SIZE ( hw_atl_boards ) )
return - EINVAL ;
2018-01-15 16:41:18 +03:00
2018-01-19 17:03:19 +03:00
return 0 ;
2018-01-15 16:41:18 +03:00
}
2018-01-19 17:03:21 +03:00
int aq_pci_func_init ( struct pci_dev * pdev )
2017-01-23 22:09:15 -08:00
{
2018-10-08 14:35:58 +01:00
int err ;
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
err = pci_set_dma_mask ( pdev , DMA_BIT_MASK ( 64 ) ) ;
2020-04-30 11:04:39 +03:00
if ( ! err )
2018-01-19 17:03:21 +03:00
err = pci_set_consistent_dma_mask ( pdev , DMA_BIT_MASK ( 64 ) ) ;
2017-01-23 22:09:15 -08:00
if ( err ) {
2018-01-19 17:03:21 +03:00
err = pci_set_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ;
2017-01-23 22:09:15 -08:00
if ( ! err )
2018-01-19 17:03:21 +03:00
err = pci_set_consistent_dma_mask ( pdev ,
2017-01-23 22:09:15 -08:00
DMA_BIT_MASK ( 32 ) ) ;
}
if ( err ! = 0 ) {
err = - ENOSR ;
goto err_exit ;
}
2018-01-19 17:03:21 +03:00
err = pci_request_regions ( pdev , AQ_CFG_DRV_NAME " _mmio " ) ;
2017-01-23 22:09:15 -08:00
if ( err < 0 )
goto err_exit ;
2018-01-19 17:03:21 +03:00
pci_set_master ( pdev ) ;
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
return 0 ;
2017-01-23 22:09:15 -08:00
err_exit :
return err ;
}
2018-01-19 17:03:21 +03:00
int aq_pci_func_alloc_irq ( struct aq_nic_s * self , unsigned int i ,
2019-04-29 10:04:48 +00:00
char * name , irq_handler_t irq_handler ,
void * irq_arg , cpumask_t * affinity_mask )
2017-01-23 22:09:15 -08:00
{
2017-02-15 08:38:47 +01:00
struct pci_dev * pdev = self - > pdev ;
2018-10-08 14:35:58 +01:00
int err ;
2017-01-23 22:09:15 -08:00
2017-02-15 08:38:47 +01:00
if ( pdev - > msix_enabled | | pdev - > msi_enabled )
2019-04-29 10:04:48 +00:00
err = request_irq ( pci_irq_vector ( pdev , i ) , irq_handler , 0 ,
name , irq_arg ) ;
2017-02-15 08:38:47 +01:00
else
err = request_irq ( pci_irq_vector ( pdev , i ) , aq_vec_isr_legacy ,
2019-04-29 10:04:48 +00:00
IRQF_SHARED , name , irq_arg ) ;
2017-01-23 22:09:15 -08:00
if ( err > = 0 ) {
self - > msix_entry_mask | = ( 1 < < i ) ;
2019-04-29 10:04:48 +00:00
if ( pdev - > msix_enabled & & affinity_mask )
2017-02-15 08:38:47 +01:00
irq_set_affinity_hint ( pci_irq_vector ( pdev , i ) ,
2017-01-23 22:09:15 -08:00
affinity_mask ) ;
}
2019-04-29 10:04:48 +00:00
2017-01-23 22:09:15 -08:00
return err ;
}
2018-01-19 17:03:21 +03:00
void aq_pci_func_free_irqs ( struct aq_nic_s * self )
2017-01-23 22:09:15 -08:00
{
2017-02-15 08:38:47 +01:00
struct pci_dev * pdev = self - > pdev ;
2018-10-08 14:35:58 +01:00
unsigned int i ;
2019-04-29 10:04:48 +00:00
void * irq_data ;
2017-01-23 22:09:15 -08:00
for ( i = 32U ; i - - ; ) {
if ( ! ( ( 1U < < i ) & self - > msix_entry_mask ) )
continue ;
2019-04-29 10:04:48 +00:00
if ( self - > aq_nic_cfg . link_irq_vec & &
i = = self - > aq_nic_cfg . link_irq_vec )
irq_data = self ;
else if ( i < AQ_CFG_VECS_MAX )
irq_data = self - > aq_vec [ i ] ;
else
2019-02-27 12:10:07 +00:00
continue ;
2017-01-23 22:09:15 -08:00
2017-02-15 08:38:47 +01:00
if ( pdev - > msix_enabled )
irq_set_affinity_hint ( pci_irq_vector ( pdev , i ) , NULL ) ;
2019-04-29 10:04:48 +00:00
free_irq ( pci_irq_vector ( pdev , i ) , irq_data ) ;
2017-01-23 22:09:15 -08:00
self - > msix_entry_mask & = ~ ( 1U < < i ) ;
}
}
2018-01-19 17:03:21 +03:00
unsigned int aq_pci_func_get_irq_type ( struct aq_nic_s * self )
2017-01-23 22:09:15 -08:00
{
2017-02-15 08:38:47 +01:00
if ( self - > pdev - > msix_enabled )
return AQ_HW_IRQ_MSIX ;
if ( self - > pdev - > msi_enabled )
2019-04-29 10:04:55 +00:00
return AQ_HW_IRQ_MSI ;
2019-11-07 22:42:00 +00:00
2017-02-15 08:38:47 +01:00
return AQ_HW_IRQ_LEGACY ;
2017-01-23 22:09:15 -08:00
}
2018-01-19 17:03:21 +03:00
static void aq_pci_free_irq_vectors ( struct aq_nic_s * self )
2017-01-23 22:09:15 -08:00
{
2017-02-15 08:38:47 +01:00
pci_free_irq_vectors ( self - > pdev ) ;
2018-01-19 17:03:21 +03:00
}
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
static int aq_pci_probe ( struct pci_dev * pdev ,
const struct pci_device_id * pci_id )
{
struct net_device * ndev ;
resource_size_t mmio_pa ;
2019-11-07 22:42:00 +00:00
struct aq_nic_s * self ;
2018-01-19 17:03:21 +03:00
u32 numvecs ;
2019-11-07 22:42:00 +00:00
u32 bar ;
int err ;
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
err = pci_enable_device ( pdev ) ;
if ( err )
return err ;
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
err = aq_pci_func_init ( pdev ) ;
if ( err )
goto err_pci_func ;
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
ndev = aq_ndev_alloc ( ) ;
2018-01-23 02:10:46 +00:00
if ( ! ndev ) {
err = - ENOMEM ;
2018-01-19 17:03:21 +03:00
goto err_ndev ;
2018-01-23 02:10:46 +00:00
}
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
self = netdev_priv ( ndev ) ;
self - > pdev = pdev ;
SET_NETDEV_DEV ( ndev , & pdev - > dev ) ;
pci_set_drvdata ( pdev , self ) ;
2017-01-23 22:09:15 -08:00
2019-04-29 10:04:57 +00:00
mutex_init ( & self - > fwreq_mutex ) ;
2018-01-19 17:03:21 +03:00
err = aq_pci_probe_get_hw_by_id ( pdev , & self - > aq_hw_ops ,
& aq_nic_get_cfg ( self ) - > aq_hw_caps ) ;
if ( err )
goto err_ioremap ;
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
self - > aq_hw = kzalloc ( sizeof ( * self - > aq_hw ) , GFP_KERNEL ) ;
2018-02-22 12:11:55 +03:00
if ( ! self - > aq_hw ) {
err = - ENOMEM ;
goto err_ioremap ;
}
2018-01-19 17:03:21 +03:00
self - > aq_hw - > aq_nic_cfg = aq_nic_get_cfg ( self ) ;
2020-04-30 11:04:39 +03:00
if ( self - > aq_hw - > aq_nic_cfg - > aq_hw_caps - > priv_data_len ) {
int len = self - > aq_hw - > aq_nic_cfg - > aq_hw_caps - > priv_data_len ;
self - > aq_hw - > priv = kzalloc ( len , GFP_KERNEL ) ;
if ( ! self - > aq_hw - > priv ) {
err = - ENOMEM ;
goto err_free_aq_hw ;
}
}
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
for ( bar = 0 ; bar < 4 ; + + bar ) {
if ( IORESOURCE_MEM & pci_resource_flags ( pdev , bar ) ) {
resource_size_t reg_sz ;
2017-10-19 18:23:57 +03:00
2018-01-19 17:03:21 +03:00
mmio_pa = pci_resource_start ( pdev , bar ) ;
if ( mmio_pa = = 0U ) {
err = - EIO ;
2020-04-30 11:04:39 +03:00
goto err_free_aq_hw_priv ;
2018-01-19 17:03:21 +03:00
}
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
reg_sz = pci_resource_len ( pdev , bar ) ;
if ( ( reg_sz < = 24 /*ATL_REGS_SIZE*/ ) ) {
err = - EIO ;
2020-04-30 11:04:39 +03:00
goto err_free_aq_hw_priv ;
2018-01-19 17:03:21 +03:00
}
2017-01-23 22:09:15 -08:00
2020-01-06 09:43:50 +01:00
self - > aq_hw - > mmio = ioremap ( mmio_pa , reg_sz ) ;
2018-01-19 17:03:21 +03:00
if ( ! self - > aq_hw - > mmio ) {
err = - EIO ;
2020-04-30 11:04:39 +03:00
goto err_free_aq_hw_priv ;
2018-01-19 17:03:21 +03:00
}
break ;
}
}
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
if ( bar = = 4 ) {
err = - EIO ;
2020-04-30 11:04:39 +03:00
goto err_free_aq_hw_priv ;
2017-01-23 22:09:15 -08:00
}
2018-01-19 17:03:21 +03:00
numvecs = min ( ( u8 ) AQ_CFG_VECS_DEF ,
aq_nic_get_cfg ( self ) - > aq_hw_caps - > msix_irqs ) ;
numvecs = min ( numvecs , num_online_cpus ( ) ) ;
2019-10-22 09:53:35 +00:00
/* Request IRQ vector for PTP */
numvecs + = 1 ;
2019-04-29 10:04:48 +00:00
numvecs + = AQ_HW_SERVICE_IRQS ;
2018-01-19 17:03:21 +03:00
/*enable interrupts */
# if !AQ_CFG_FORCE_LEGACY_INT
2018-06-07 17:54:37 -04:00
err = pci_alloc_irq_vectors ( self - > pdev , 1 , numvecs ,
PCI_IRQ_MSIX | PCI_IRQ_MSI |
PCI_IRQ_LEGACY ) ;
2018-05-07 16:10:39 +03:00
2018-06-07 17:54:37 -04:00
if ( err < 0 )
2018-05-07 16:10:39 +03:00
goto err_hwinit ;
2018-06-07 17:54:37 -04:00
numvecs = err ;
2018-01-19 17:03:21 +03:00
# endif
2018-05-07 16:10:39 +03:00
self - > irqvecs = numvecs ;
2017-01-23 22:09:15 -08:00
2018-01-19 17:03:21 +03:00
/* net device init */
aq_nic_cfg_start ( self ) ;
2018-01-15 16:41:18 +03:00
2018-01-19 17:03:21 +03:00
aq_nic_ndev_init ( self ) ;
2018-01-15 16:41:18 +03:00
2018-01-19 17:03:21 +03:00
err = aq_nic_ndev_register ( self ) ;
2018-01-15 16:41:18 +03:00
if ( err < 0 )
2018-01-19 17:03:21 +03:00
goto err_register ;
2018-01-15 16:41:18 +03:00
2019-04-29 10:04:38 +00:00
aq_drvinfo_init ( ndev ) ;
2018-01-19 17:03:21 +03:00
return 0 ;
err_register :
aq_nic_free_vectors ( self ) ;
aq_pci_free_irq_vectors ( self ) ;
err_hwinit :
iounmap ( self - > aq_hw - > mmio ) ;
2020-04-30 11:04:39 +03:00
err_free_aq_hw_priv :
kfree ( self - > aq_hw - > priv ) ;
2018-02-22 12:11:55 +03:00
err_free_aq_hw :
kfree ( self - > aq_hw ) ;
2018-01-19 17:03:21 +03:00
err_ioremap :
free_netdev ( ndev ) ;
err_ndev :
2018-05-07 16:10:39 +03:00
pci_release_regions ( pdev ) ;
err_pci_func :
2018-01-19 17:03:21 +03:00
pci_disable_device ( pdev ) ;
2019-11-07 22:42:00 +00:00
2018-01-15 16:41:18 +03:00
return err ;
}
static void aq_pci_remove ( struct pci_dev * pdev )
{
2018-01-19 17:03:21 +03:00
struct aq_nic_s * self = pci_get_drvdata ( pdev ) ;
if ( self - > ndev ) {
2018-11-12 15:46:00 +00:00
aq_clear_rxnfc_all_rules ( self ) ;
2018-01-19 17:03:21 +03:00
if ( self - > ndev - > reg_state = = NETREG_REGISTERED )
unregister_netdev ( self - > ndev ) ;
2020-03-25 15:52:39 +03:00
# if IS_ENABLED(CONFIG_MACSEC)
aq_macsec_free ( self ) ;
# endif
2018-01-19 17:03:21 +03:00
aq_nic_free_vectors ( self ) ;
aq_pci_free_irq_vectors ( self ) ;
iounmap ( self - > aq_hw - > mmio ) ;
2020-04-30 11:04:39 +03:00
kfree ( self - > aq_hw - > priv ) ;
2018-01-19 17:03:21 +03:00
kfree ( self - > aq_hw ) ;
pci_release_regions ( pdev ) ;
free_netdev ( self - > ndev ) ;
}
2018-01-15 16:41:18 +03:00
2018-01-19 17:03:21 +03:00
pci_disable_device ( pdev ) ;
2018-01-15 16:41:18 +03:00
}
2018-03-20 14:40:36 +03:00
static void aq_pci_shutdown ( struct pci_dev * pdev )
{
struct aq_nic_s * self = pci_get_drvdata ( pdev ) ;
aq_nic_shutdown ( self ) ;
pci_disable_device ( pdev ) ;
if ( system_state = = SYSTEM_POWER_OFF ) {
pci_wake_from_d3 ( pdev , false ) ;
pci_set_power_state ( pdev , PCI_D3hot ) ;
}
}
2019-11-07 22:41:52 +00:00
static int aq_suspend_common ( struct device * dev , bool deep )
2018-01-15 16:41:18 +03:00
{
2019-11-07 22:41:52 +00:00
struct aq_nic_s * nic = pci_get_drvdata ( to_pci_dev ( dev ) ) ;
rtnl_lock ( ) ;
nic - > power_state = AQ_HW_POWER_STATE_D3 ;
netif_device_detach ( nic - > ndev ) ;
netif_tx_stop_all_queues ( nic - > ndev ) ;
2018-01-15 16:41:18 +03:00
2020-02-14 18:44:57 +03:00
if ( netif_running ( nic - > ndev ) )
aq_nic_stop ( nic ) ;
2019-11-07 22:41:52 +00:00
if ( deep ) {
aq_nic_deinit ( nic , ! nic - > aq_hw - > aq_nic_cfg - > wol ) ;
aq_nic_set_power ( nic ) ;
}
rtnl_unlock ( ) ;
return 0 ;
2018-01-15 16:41:18 +03:00
}
2019-11-07 22:41:52 +00:00
static int atl_resume_common ( struct device * dev , bool deep )
2018-01-15 16:41:18 +03:00
{
2019-11-07 22:41:52 +00:00
struct pci_dev * pdev = to_pci_dev ( dev ) ;
struct aq_nic_s * nic ;
2020-02-14 18:44:57 +03:00
int ret = 0 ;
2019-11-07 22:41:52 +00:00
nic = pci_get_drvdata ( pdev ) ;
rtnl_lock ( ) ;
pci_set_power_state ( pdev , PCI_D0 ) ;
pci_restore_state ( pdev ) ;
if ( deep ) {
ret = aq_nic_init ( nic ) ;
if ( ret )
goto err_exit ;
}
2020-02-14 18:44:57 +03:00
if ( netif_running ( nic - > ndev ) ) {
ret = aq_nic_start ( nic ) ;
if ( ret )
goto err_exit ;
}
2019-11-07 22:41:52 +00:00
netif_device_attach ( nic - > ndev ) ;
netif_tx_start_all_queues ( nic - > ndev ) ;
2018-01-15 16:41:18 +03:00
2019-11-07 22:41:52 +00:00
err_exit :
2020-05-22 11:19:37 +03:00
if ( ret < 0 )
aq_nic_deinit ( nic , true ) ;
2019-11-07 22:41:52 +00:00
rtnl_unlock ( ) ;
return ret ;
}
static int aq_pm_freeze ( struct device * dev )
{
return aq_suspend_common ( dev , false ) ;
2018-01-15 16:41:18 +03:00
}
2019-11-07 22:41:52 +00:00
static int aq_pm_suspend_poweroff ( struct device * dev )
{
return aq_suspend_common ( dev , true ) ;
}
static int aq_pm_thaw ( struct device * dev )
{
return atl_resume_common ( dev , false ) ;
}
static int aq_pm_resume_restore ( struct device * dev )
{
return atl_resume_common ( dev , true ) ;
}
2019-11-12 14:59:41 +08:00
static const struct dev_pm_ops aq_pm_ops = {
2019-11-07 22:41:52 +00:00
. suspend = aq_pm_suspend_poweroff ,
. poweroff = aq_pm_suspend_poweroff ,
. freeze = aq_pm_freeze ,
. resume = aq_pm_resume_restore ,
. restore = aq_pm_resume_restore ,
. thaw = aq_pm_thaw ,
} ;
2018-01-15 16:41:18 +03:00
static struct pci_driver aq_pci_ops = {
. name = AQ_CFG_DRV_NAME ,
. id_table = aq_pci_tbl ,
. probe = aq_pci_probe ,
. remove = aq_pci_remove ,
2018-03-20 14:40:36 +03:00
. shutdown = aq_pci_shutdown ,
2019-11-07 22:41:52 +00:00
# ifdef CONFIG_PM
. driver . pm = & aq_pm_ops ,
# endif
2018-01-15 16:41:18 +03:00
} ;
2019-04-29 10:04:45 +00:00
int aq_pci_func_register_driver ( void )
{
return pci_register_driver ( & aq_pci_ops ) ;
}
void aq_pci_func_unregister_driver ( void )
{
pci_unregister_driver ( & aq_pci_ops ) ;
}