forked from openbmc/linux
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
net: ethernet: aquantia: Support for NIC-specific code
Add support for code specific to the Atlantic NIC. Signed-off-by: Alexander Loktionov <[email protected]> Signed-off-by: Dmitrii Tarakanov <[email protected]> Signed-off-by: Pavel Belous <[email protected]> Signed-off-by: Dmitry Bezrukov <[email protected]> Signed-off-by: David M. VomLehn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
- Loading branch information
Showing
5 changed files
with
1,381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
/* | ||
* aQuantia Corporation Network Driver | ||
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms and conditions of the GNU General Public License, | ||
* version 2, as published by the Free Software Foundation. | ||
*/ | ||
|
||
/* File aq_main.c: Main file for aQuantia Linux driver. */ | ||
|
||
#include "aq_main.h" | ||
#include "aq_nic.h" | ||
#include "aq_pci_func.h" | ||
#include "aq_ethtool.h" | ||
#include "hw_atl/hw_atl_a0.h" | ||
#include "hw_atl/hw_atl_b0.h" | ||
|
||
#include <linux/netdevice.h> | ||
#include <linux/module.h> | ||
|
||
static const struct pci_device_id aq_pci_tbl[] = { | ||
{ PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_0001), }, | ||
{ PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D100), }, | ||
{ PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D107), }, | ||
{ PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D108), }, | ||
{ PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D109), }, | ||
{} | ||
}; | ||
|
||
MODULE_DEVICE_TABLE(pci, aq_pci_tbl); | ||
|
||
MODULE_LICENSE("GPL v2"); | ||
MODULE_VERSION(AQ_CFG_DRV_VERSION); | ||
MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR); | ||
MODULE_DESCRIPTION(AQ_CFG_DRV_DESC); | ||
|
||
static struct aq_hw_ops *aq_pci_probe_get_hw_ops_by_id(struct pci_dev *pdev) | ||
{ | ||
struct aq_hw_ops *ops = NULL; | ||
|
||
ops = hw_atl_a0_get_ops_by_id(pdev); | ||
if (!ops) | ||
ops = hw_atl_b0_get_ops_by_id(pdev); | ||
|
||
return ops; | ||
} | ||
|
||
static int aq_ndev_open(struct net_device *ndev) | ||
{ | ||
struct aq_nic_s *aq_nic = NULL; | ||
int err = 0; | ||
|
||
aq_nic = aq_nic_alloc_hot(ndev); | ||
if (!aq_nic) { | ||
err = -ENOMEM; | ||
goto err_exit; | ||
} | ||
err = aq_nic_init(aq_nic); | ||
if (err < 0) | ||
goto err_exit; | ||
err = aq_nic_start(aq_nic); | ||
if (err < 0) | ||
goto err_exit; | ||
|
||
err_exit: | ||
if (err < 0) | ||
aq_nic_deinit(aq_nic); | ||
return err; | ||
} | ||
|
||
static int aq_ndev_close(struct net_device *ndev) | ||
{ | ||
int err = 0; | ||
struct aq_nic_s *aq_nic = netdev_priv(ndev); | ||
|
||
err = aq_nic_stop(aq_nic); | ||
if (err < 0) | ||
goto err_exit; | ||
aq_nic_deinit(aq_nic); | ||
aq_nic_free_hot_resources(aq_nic); | ||
|
||
err_exit: | ||
return err; | ||
} | ||
|
||
static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) | ||
{ | ||
struct aq_nic_s *aq_nic = netdev_priv(ndev); | ||
int err = 0; | ||
|
||
err = aq_nic_xmit(aq_nic, skb); | ||
if (err < 0) | ||
goto err_exit; | ||
|
||
err_exit: | ||
return err; | ||
} | ||
|
||
static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu) | ||
{ | ||
struct aq_nic_s *aq_nic = netdev_priv(ndev); | ||
int err = 0; | ||
|
||
if (new_mtu == ndev->mtu) { | ||
err = 0; | ||
goto err_exit; | ||
} | ||
if (new_mtu < 68) { | ||
err = -EINVAL; | ||
goto err_exit; | ||
} | ||
err = aq_nic_set_mtu(aq_nic, new_mtu + ETH_HLEN); | ||
if (err < 0) | ||
goto err_exit; | ||
ndev->mtu = new_mtu; | ||
|
||
if (netif_running(ndev)) { | ||
aq_ndev_close(ndev); | ||
aq_ndev_open(ndev); | ||
} | ||
|
||
err_exit: | ||
return err; | ||
} | ||
|
||
static int aq_ndev_set_features(struct net_device *ndev, | ||
netdev_features_t features) | ||
{ | ||
struct aq_nic_s *aq_nic = netdev_priv(ndev); | ||
struct aq_nic_cfg_s *aq_cfg = aq_nic_get_cfg(aq_nic); | ||
bool is_lro = false; | ||
|
||
if (aq_cfg->hw_features & NETIF_F_LRO) { | ||
is_lro = features & NETIF_F_LRO; | ||
|
||
if (aq_cfg->is_lro != is_lro) { | ||
aq_cfg->is_lro = is_lro; | ||
|
||
if (netif_running(ndev)) { | ||
aq_ndev_close(ndev); | ||
aq_ndev_open(ndev); | ||
} | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr) | ||
{ | ||
struct aq_nic_s *aq_nic = netdev_priv(ndev); | ||
int err = 0; | ||
|
||
err = eth_mac_addr(ndev, addr); | ||
if (err < 0) | ||
goto err_exit; | ||
err = aq_nic_set_mac(aq_nic, ndev); | ||
if (err < 0) | ||
goto err_exit; | ||
|
||
err_exit: | ||
return err; | ||
} | ||
|
||
static void aq_ndev_set_multicast_settings(struct net_device *ndev) | ||
{ | ||
struct aq_nic_s *aq_nic = netdev_priv(ndev); | ||
int err = 0; | ||
|
||
err = aq_nic_set_packet_filter(aq_nic, ndev->flags); | ||
if (err < 0) | ||
goto err_exit; | ||
|
||
if (netdev_mc_count(ndev)) { | ||
err = aq_nic_set_multicast_list(aq_nic, ndev); | ||
if (err < 0) | ||
goto err_exit; | ||
} | ||
|
||
err_exit:; | ||
} | ||
|
||
static const struct net_device_ops aq_ndev_ops = { | ||
.ndo_open = aq_ndev_open, | ||
.ndo_stop = aq_ndev_close, | ||
.ndo_start_xmit = aq_ndev_start_xmit, | ||
.ndo_set_rx_mode = aq_ndev_set_multicast_settings, | ||
.ndo_change_mtu = aq_ndev_change_mtu, | ||
.ndo_set_mac_address = aq_ndev_set_mac_address, | ||
.ndo_set_features = aq_ndev_set_features | ||
}; | ||
|
||
static int aq_pci_probe(struct pci_dev *pdev, | ||
const struct pci_device_id *pci_id) | ||
{ | ||
struct aq_hw_ops *aq_hw_ops = NULL; | ||
struct aq_pci_func_s *aq_pci_func = NULL; | ||
int err = 0; | ||
|
||
err = pci_enable_device(pdev); | ||
if (err < 0) | ||
goto err_exit; | ||
aq_hw_ops = aq_pci_probe_get_hw_ops_by_id(pdev); | ||
aq_pci_func = aq_pci_func_alloc(aq_hw_ops, pdev, | ||
&aq_ndev_ops, &aq_ethtool_ops); | ||
if (!aq_pci_func) { | ||
err = -ENOMEM; | ||
goto err_exit; | ||
} | ||
err = aq_pci_func_init(aq_pci_func); | ||
if (err < 0) | ||
goto err_exit; | ||
|
||
err_exit: | ||
if (err < 0) { | ||
if (aq_pci_func) | ||
aq_pci_func_free(aq_pci_func); | ||
} | ||
return err; | ||
} | ||
|
||
static void aq_pci_remove(struct pci_dev *pdev) | ||
{ | ||
struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev); | ||
|
||
aq_pci_func_deinit(aq_pci_func); | ||
aq_pci_func_free(aq_pci_func); | ||
} | ||
|
||
static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg) | ||
{ | ||
struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev); | ||
|
||
return aq_pci_func_change_pm_state(aq_pci_func, &pm_msg); | ||
} | ||
|
||
static int aq_pci_resume(struct pci_dev *pdev) | ||
{ | ||
struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev); | ||
pm_message_t pm_msg = PMSG_RESTORE; | ||
|
||
return aq_pci_func_change_pm_state(aq_pci_func, &pm_msg); | ||
} | ||
|
||
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, | ||
.suspend = aq_pci_suspend, | ||
.resume = aq_pci_resume, | ||
}; | ||
|
||
static int __init aq_module_init(void) | ||
{ | ||
int err = 0; | ||
|
||
err = pci_register_driver(&aq_pci_ops); | ||
if (err < 0) | ||
goto err_exit; | ||
|
||
err_exit: | ||
return err; | ||
} | ||
|
||
static void __exit aq_module_exit(void) | ||
{ | ||
pci_unregister_driver(&aq_pci_ops); | ||
} | ||
|
||
module_init(aq_module_init); | ||
module_exit(aq_module_exit); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* aQuantia Corporation Network Driver | ||
* Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms and conditions of the GNU General Public License, | ||
* version 2, as published by the Free Software Foundation. | ||
*/ | ||
|
||
/* File aq_main.h: Main file for aQuantia Linux driver. */ | ||
|
||
#ifndef AQ_MAIN_H | ||
#define AQ_MAIN_H | ||
|
||
#include "aq_common.h" | ||
|
||
#endif /* AQ_MAIN_H */ |
Oops, something went wrong.