mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-17 18:56:24 +00:00
eth: fbnic: Add scaffolding for Meta's NIC driver
Create a bare-bones PCI driver for Meta's NIC. Subsequent changes will flesh it out. Signed-off-by: Alexander Duyck <alexanderduyck@fb.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Link: https://patch.msgid.link/172079935646.1778861.9710282776096050607.stgit@ahduyck-xeon-server.home.arpa Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c5eaf1b3f8
commit
546dd90be9
@ -14579,6 +14579,13 @@ T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml
|
||||
F: drivers/staging/media/meson/vdec/
|
||||
|
||||
META ETHERNET DRIVERS
|
||||
M: Alexander Duyck <alexanderduyck@fb.com>
|
||||
M: Jakub Kicinski <kuba@kernel.org>
|
||||
R: kernel-team@meta.com
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/meta/
|
||||
|
||||
METHODE UDPU SUPPORT
|
||||
M: Robert Marko <robert.marko@sartura.hr>
|
||||
S: Maintained
|
||||
|
@ -122,6 +122,7 @@ source "drivers/net/ethernet/litex/Kconfig"
|
||||
source "drivers/net/ethernet/marvell/Kconfig"
|
||||
source "drivers/net/ethernet/mediatek/Kconfig"
|
||||
source "drivers/net/ethernet/mellanox/Kconfig"
|
||||
source "drivers/net/ethernet/meta/Kconfig"
|
||||
source "drivers/net/ethernet/micrel/Kconfig"
|
||||
source "drivers/net/ethernet/microchip/Kconfig"
|
||||
source "drivers/net/ethernet/mscc/Kconfig"
|
||||
|
@ -59,6 +59,7 @@ obj-$(CONFIG_NET_VENDOR_LITEX) += litex/
|
||||
obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
|
||||
obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/
|
||||
obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
|
||||
obj-$(CONFIG_NET_VENDOR_META) += meta/
|
||||
obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/
|
||||
obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/
|
||||
obj-$(CONFIG_NET_VENDOR_MICROSEMI) += mscc/
|
||||
|
30
drivers/net/ethernet/meta/Kconfig
Normal file
30
drivers/net/ethernet/meta/Kconfig
Normal file
@ -0,0 +1,30 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Meta Platforms network device configuration
|
||||
#
|
||||
|
||||
config NET_VENDOR_META
|
||||
bool "Meta Platforms devices"
|
||||
default y
|
||||
help
|
||||
If you have a network (Ethernet) card designed by Meta, say Y.
|
||||
That's Meta as in the parent company of Facebook.
|
||||
|
||||
Note that the answer to this question doesn't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all
|
||||
the questions about Meta cards. If you say Y, you will be asked for
|
||||
your specific card in the following questions.
|
||||
|
||||
if NET_VENDOR_META
|
||||
|
||||
config FBNIC
|
||||
tristate "Meta Platforms Host Network Interface"
|
||||
depends on X86_64 || COMPILE_TEST
|
||||
depends on PCI_MSI
|
||||
help
|
||||
This driver supports Meta Platforms Host Network Interface.
|
||||
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called fbnic. MSI-X interrupt support is required.
|
||||
|
||||
endif # NET_VENDOR_META
|
6
drivers/net/ethernet/meta/Makefile
Normal file
6
drivers/net/ethernet/meta/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for the Meta Platforms network device drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_FBNIC) += fbnic/
|
10
drivers/net/ethernet/meta/fbnic/Makefile
Normal file
10
drivers/net/ethernet/meta/fbnic/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#
|
||||
# Makefile for the Meta(R) Host Network Interface
|
||||
#
|
||||
|
||||
obj-$(CONFIG_FBNIC) += fbnic.o
|
||||
|
||||
fbnic-y := fbnic_pci.o
|
19
drivers/net/ethernet/meta/fbnic/fbnic.h
Normal file
19
drivers/net/ethernet/meta/fbnic/fbnic.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#ifndef _FBNIC_H_
|
||||
#define _FBNIC_H_
|
||||
|
||||
#include "fbnic_csr.h"
|
||||
|
||||
extern char fbnic_driver_name[];
|
||||
|
||||
enum fbnic_boards {
|
||||
fbnic_board_asic
|
||||
};
|
||||
|
||||
struct fbnic_info {
|
||||
unsigned int bar_mask;
|
||||
};
|
||||
|
||||
#endif /* _FBNIC_H_ */
|
9
drivers/net/ethernet/meta/fbnic/fbnic_csr.h
Normal file
9
drivers/net/ethernet/meta/fbnic/fbnic_csr.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#ifndef _FBNIC_CSR_H_
|
||||
#define _FBNIC_CSR_H_
|
||||
|
||||
#define PCI_DEVICE_ID_META_FBNIC_ASIC 0x0013
|
||||
|
||||
#endif /* _FBNIC_CSR_H_ */
|
5
drivers/net/ethernet/meta/fbnic/fbnic_drvinfo.h
Normal file
5
drivers/net/ethernet/meta/fbnic/fbnic_drvinfo.h
Normal file
@ -0,0 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#define DRV_NAME "fbnic"
|
||||
#define DRV_SUMMARY "Meta(R) Host Network Interface Driver"
|
201
drivers/net/ethernet/meta/fbnic/fbnic_pci.c
Normal file
201
drivers/net/ethernet/meta/fbnic/fbnic_pci.c
Normal file
@ -0,0 +1,201 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "fbnic.h"
|
||||
#include "fbnic_drvinfo.h"
|
||||
|
||||
char fbnic_driver_name[] = DRV_NAME;
|
||||
|
||||
MODULE_DESCRIPTION(DRV_SUMMARY);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static const struct fbnic_info fbnic_asic_info = {
|
||||
.bar_mask = BIT(0) | BIT(4)
|
||||
};
|
||||
|
||||
static const struct fbnic_info *fbnic_info_tbl[] = {
|
||||
[fbnic_board_asic] = &fbnic_asic_info,
|
||||
};
|
||||
|
||||
static const struct pci_device_id fbnic_pci_tbl[] = {
|
||||
{ PCI_DEVICE_DATA(META, FBNIC_ASIC, fbnic_board_asic) },
|
||||
/* Required last entry */
|
||||
{0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, fbnic_pci_tbl);
|
||||
|
||||
/**
|
||||
* fbnic_probe - Device Initialization Routine
|
||||
* @pdev: PCI device information struct
|
||||
* @ent: entry in fbnic_pci_tbl
|
||||
*
|
||||
* Initializes a PCI device identified by a pci_dev structure.
|
||||
* The OS initialization, configuring of the adapter private structure,
|
||||
* and a hardware reset occur.
|
||||
*
|
||||
* Return: 0 on success, negative on failure
|
||||
**/
|
||||
static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
const struct fbnic_info *info = fbnic_info_tbl[ent->driver_data];
|
||||
int err;
|
||||
|
||||
if (pdev->error_state != pci_channel_io_normal) {
|
||||
dev_err(&pdev->dev,
|
||||
"PCI device still in an error state. Unable to load...\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = pcim_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "PCI enable device failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(46));
|
||||
if (err)
|
||||
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "DMA configuration failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = pcim_iomap_regions(pdev, info->bar_mask, fbnic_driver_name);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"pci_request_selected_regions failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
pci_save_state(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fbnic_remove - Device Removal Routine
|
||||
* @pdev: PCI device information struct
|
||||
*
|
||||
* Called by the PCI subsystem to alert the driver that it should release
|
||||
* a PCI device. The could be caused by a Hot-Plug event, or because the
|
||||
* driver is going to be removed from memory.
|
||||
**/
|
||||
static void fbnic_remove(struct pci_dev *pdev)
|
||||
{
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static int fbnic_pm_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __fbnic_pm_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused fbnic_pm_resume(struct device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __fbnic_pm_resume(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops fbnic_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(fbnic_pm_suspend, fbnic_pm_resume)
|
||||
};
|
||||
|
||||
static void fbnic_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
fbnic_pm_suspend(&pdev->dev);
|
||||
}
|
||||
|
||||
static pci_ers_result_t fbnic_err_error_detected(struct pci_dev *pdev,
|
||||
pci_channel_state_t state)
|
||||
{
|
||||
/* Disconnect device if failure is not recoverable via reset */
|
||||
if (state == pci_channel_io_perm_failure)
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
|
||||
fbnic_pm_suspend(&pdev->dev);
|
||||
|
||||
/* Request a slot reset */
|
||||
return PCI_ERS_RESULT_NEED_RESET;
|
||||
}
|
||||
|
||||
static pci_ers_result_t fbnic_err_slot_reset(struct pci_dev *pdev)
|
||||
{
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
pci_save_state(pdev);
|
||||
|
||||
if (pci_enable_device_mem(pdev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot re-enable PCI device after reset.\n");
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
return PCI_ERS_RESULT_RECOVERED;
|
||||
}
|
||||
|
||||
static void fbnic_err_resume(struct pci_dev *pdev)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers fbnic_err_handler = {
|
||||
.error_detected = fbnic_err_error_detected,
|
||||
.slot_reset = fbnic_err_slot_reset,
|
||||
.resume = fbnic_err_resume,
|
||||
};
|
||||
|
||||
static struct pci_driver fbnic_driver = {
|
||||
.name = fbnic_driver_name,
|
||||
.id_table = fbnic_pci_tbl,
|
||||
.probe = fbnic_probe,
|
||||
.remove = fbnic_remove,
|
||||
.driver.pm = &fbnic_pm_ops,
|
||||
.shutdown = fbnic_shutdown,
|
||||
.err_handler = &fbnic_err_handler,
|
||||
};
|
||||
|
||||
/**
|
||||
* fbnic_init_module - Driver Registration Routine
|
||||
*
|
||||
* The first routine called when the driver is loaded. All it does is
|
||||
* register with the PCI subsystem.
|
||||
*
|
||||
* Return: 0 on success, negative on failure
|
||||
**/
|
||||
static int __init fbnic_init_module(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pci_register_driver(&fbnic_driver);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
pr_info(DRV_SUMMARY " (%s)", fbnic_driver.name);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
module_init(fbnic_init_module);
|
||||
|
||||
/**
|
||||
* fbnic_exit_module - Driver Exit Cleanup Routine
|
||||
*
|
||||
* Called just before the driver is removed from memory.
|
||||
**/
|
||||
static void __exit fbnic_exit_module(void)
|
||||
{
|
||||
pci_unregister_driver(&fbnic_driver);
|
||||
}
|
||||
module_exit(fbnic_exit_module);
|
Loading…
x
Reference in New Issue
Block a user