mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
net: txgbe: Store PCI info
Get PCI config space info, set LAN id and check flash status. Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
957ed5e712
commit
a34b3e6ed8
|
|
@ -16,6 +16,11 @@ config NET_VENDOR_WANGXUN
|
||||||
|
|
||||||
if NET_VENDOR_WANGXUN
|
if NET_VENDOR_WANGXUN
|
||||||
|
|
||||||
|
config LIBWX
|
||||||
|
tristate
|
||||||
|
help
|
||||||
|
Common library for Wangxun(R) Ethernet drivers.
|
||||||
|
|
||||||
config NGBE
|
config NGBE
|
||||||
tristate "Wangxun(R) GbE PCI Express adapters support"
|
tristate "Wangxun(R) GbE PCI Express adapters support"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
|
@ -32,6 +37,7 @@ config NGBE
|
||||||
config TXGBE
|
config TXGBE
|
||||||
tristate "Wangxun(R) 10GbE PCI Express adapters support"
|
tristate "Wangxun(R) 10GbE PCI Express adapters support"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
select LIBWX
|
||||||
help
|
help
|
||||||
This driver supports Wangxun(R) 10GbE PCI Express family of
|
This driver supports Wangxun(R) 10GbE PCI Express family of
|
||||||
adapters.
|
adapters.
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,6 @@
|
||||||
# Makefile for the Wangxun network device drivers.
|
# Makefile for the Wangxun network device drivers.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_LIBWX) += libwx/
|
||||||
obj-$(CONFIG_TXGBE) += txgbe/
|
obj-$(CONFIG_TXGBE) += txgbe/
|
||||||
obj-$(CONFIG_NGBE) += ngbe/
|
obj-$(CONFIG_NGBE) += ngbe/
|
||||||
|
|
|
||||||
7
drivers/net/ethernet/wangxun/libwx/Makefile
Normal file
7
drivers/net/ethernet/wangxun/libwx/Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd.
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_LIBWX) += libwx.o
|
||||||
|
|
||||||
|
libwx-objs := wx_hw.o
|
||||||
88
drivers/net/ethernet/wangxun/libwx/wx_hw.c
Normal file
88
drivers/net/ethernet/wangxun/libwx/wx_hw.c
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */
|
||||||
|
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
|
#include "wx_type.h"
|
||||||
|
#include "wx_hw.h"
|
||||||
|
|
||||||
|
/* cmd_addr is used for some special command:
|
||||||
|
* 1. to be sector address, when implemented erase sector command
|
||||||
|
* 2. to be flash address when implemented read, write flash address
|
||||||
|
*/
|
||||||
|
static int wx_fmgr_cmd_op(struct wx_hw *wxhw, u32 cmd, u32 cmd_addr)
|
||||||
|
{
|
||||||
|
u32 cmd_val = 0, val = 0;
|
||||||
|
|
||||||
|
cmd_val = WX_SPI_CMD_CMD(cmd) |
|
||||||
|
WX_SPI_CMD_CLK(WX_SPI_CLK_DIV) |
|
||||||
|
cmd_addr;
|
||||||
|
wr32(wxhw, WX_SPI_CMD, cmd_val);
|
||||||
|
|
||||||
|
return read_poll_timeout(rd32, val, (val & 0x1), 10, 100000,
|
||||||
|
false, wxhw, WX_SPI_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wx_flash_read_dword(struct wx_hw *wxhw, u32 addr, u32 *data)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = wx_fmgr_cmd_op(wxhw, WX_SPI_CMD_READ_DWORD, addr);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*data = rd32(wxhw, WX_SPI_DATA);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wx_check_flash_load(struct wx_hw *hw, u32 check_bit)
|
||||||
|
{
|
||||||
|
u32 reg = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
/* if there's flash existing */
|
||||||
|
if (!(rd32(hw, WX_SPI_STATUS) &
|
||||||
|
WX_SPI_STATUS_FLASH_BYPASS)) {
|
||||||
|
/* wait hw load flash done */
|
||||||
|
err = read_poll_timeout(rd32, reg, !(reg & check_bit), 20000, 2000000,
|
||||||
|
false, hw, WX_SPI_ILDR_STATUS);
|
||||||
|
if (err < 0)
|
||||||
|
wx_err(hw, "Check flash load timeout.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(wx_check_flash_load);
|
||||||
|
|
||||||
|
int wx_sw_init(struct wx_hw *wxhw)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = wxhw->pdev;
|
||||||
|
u32 ssid = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
wxhw->vendor_id = pdev->vendor;
|
||||||
|
wxhw->device_id = pdev->device;
|
||||||
|
wxhw->revision_id = pdev->revision;
|
||||||
|
wxhw->oem_svid = pdev->subsystem_vendor;
|
||||||
|
wxhw->oem_ssid = pdev->subsystem_device;
|
||||||
|
wxhw->bus.device = PCI_SLOT(pdev->devfn);
|
||||||
|
wxhw->bus.func = PCI_FUNC(pdev->devfn);
|
||||||
|
|
||||||
|
if (wxhw->oem_svid == PCI_VENDOR_ID_WANGXUN) {
|
||||||
|
wxhw->subsystem_vendor_id = pdev->subsystem_vendor;
|
||||||
|
wxhw->subsystem_device_id = pdev->subsystem_device;
|
||||||
|
} else {
|
||||||
|
err = wx_flash_read_dword(wxhw, 0xfffdc, &ssid);
|
||||||
|
if (!err)
|
||||||
|
wxhw->subsystem_device_id = swab16((u16)ssid);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(wx_sw_init);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
10
drivers/net/ethernet/wangxun/libwx/wx_hw.h
Normal file
10
drivers/net/ethernet/wangxun/libwx/wx_hw.h
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */
|
||||||
|
|
||||||
|
#ifndef _WX_HW_H_
|
||||||
|
#define _WX_HW_H_
|
||||||
|
|
||||||
|
int wx_check_flash_load(struct wx_hw *hw, u32 check_bit);
|
||||||
|
int wx_sw_init(struct wx_hw *wxhw);
|
||||||
|
|
||||||
|
#endif /* _WX_HW_H_ */
|
||||||
54
drivers/net/ethernet/wangxun/libwx/wx_type.h
Normal file
54
drivers/net/ethernet/wangxun/libwx/wx_type.h
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */
|
||||||
|
|
||||||
|
#ifndef _WX_TYPE_H_
|
||||||
|
#define _WX_TYPE_H_
|
||||||
|
|
||||||
|
/* Vendor ID */
|
||||||
|
#ifndef PCI_VENDOR_ID_WANGXUN
|
||||||
|
#define PCI_VENDOR_ID_WANGXUN 0x8088
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FMGR Registers */
|
||||||
|
#define WX_SPI_CMD 0x10104
|
||||||
|
#define WX_SPI_CMD_READ_DWORD 0x1
|
||||||
|
#define WX_SPI_CLK_DIV 0x3
|
||||||
|
#define WX_SPI_CMD_CMD(_v) (((_v) & 0x7) << 28)
|
||||||
|
#define WX_SPI_CMD_CLK(_v) (((_v) & 0x7) << 25)
|
||||||
|
#define WX_SPI_CMD_ADDR(_v) (((_v) & 0xFFFFFF))
|
||||||
|
#define WX_SPI_DATA 0x10108
|
||||||
|
#define WX_SPI_DATA_BYPASS BIT(31)
|
||||||
|
#define WX_SPI_DATA_STATUS(_v) (((_v) & 0xFF) << 16)
|
||||||
|
#define WX_SPI_DATA_OP_DONE BIT(0)
|
||||||
|
#define WX_SPI_STATUS 0x1010C
|
||||||
|
#define WX_SPI_STATUS_OPDONE BIT(0)
|
||||||
|
#define WX_SPI_STATUS_FLASH_BYPASS BIT(31)
|
||||||
|
#define WX_SPI_ILDR_STATUS 0x10120
|
||||||
|
|
||||||
|
/* Bus parameters */
|
||||||
|
struct wx_bus_info {
|
||||||
|
u8 func;
|
||||||
|
u16 device;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wx_hw {
|
||||||
|
u8 __iomem *hw_addr;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
struct wx_bus_info bus;
|
||||||
|
u16 device_id;
|
||||||
|
u16 vendor_id;
|
||||||
|
u16 subsystem_device_id;
|
||||||
|
u16 subsystem_vendor_id;
|
||||||
|
u8 revision_id;
|
||||||
|
u16 oem_ssid;
|
||||||
|
u16 oem_svid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* register operations */
|
||||||
|
#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
|
||||||
|
#define rd32(a, reg) readl((a)->hw_addr + (reg))
|
||||||
|
|
||||||
|
#define wx_err(wxhw, fmt, arg...) \
|
||||||
|
dev_err(&(wxhw)->pdev->dev, fmt, ##arg)
|
||||||
|
|
||||||
|
#endif /* _WX_TYPE_H_ */
|
||||||
|
|
@ -17,6 +17,10 @@ struct txgbe_adapter {
|
||||||
/* OS defined structs */
|
/* OS defined structs */
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
/* structs defined in txgbe_type.h */
|
||||||
|
struct txgbe_hw hw;
|
||||||
|
u16 msg_enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern char txgbe_driver_name[];
|
extern char txgbe_driver_name[];
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
|
|
||||||
|
#include "../libwx/wx_type.h"
|
||||||
|
#include "../libwx/wx_hw.h"
|
||||||
#include "txgbe.h"
|
#include "txgbe.h"
|
||||||
|
|
||||||
char txgbe_driver_name[] = "txgbe";
|
char txgbe_driver_name[] = "txgbe";
|
||||||
|
|
@ -30,6 +32,69 @@ static const struct pci_device_id txgbe_pci_tbl[] = {
|
||||||
|
|
||||||
#define DEFAULT_DEBUG_LEVEL_SHIFT 3
|
#define DEFAULT_DEBUG_LEVEL_SHIFT 3
|
||||||
|
|
||||||
|
static void txgbe_check_minimum_link(struct txgbe_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
|
pdev = adapter->pdev;
|
||||||
|
pcie_print_link_status(pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* txgbe_enumerate_functions - Get the number of ports this device has
|
||||||
|
* @adapter: adapter structure
|
||||||
|
*
|
||||||
|
* This function enumerates the phsyical functions co-located on a single slot,
|
||||||
|
* in order to determine how many ports a device has. This is most useful in
|
||||||
|
* determining the required GT/s of PCIe bandwidth necessary for optimal
|
||||||
|
* performance.
|
||||||
|
**/
|
||||||
|
static int txgbe_enumerate_functions(struct txgbe_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct pci_dev *entry, *pdev = adapter->pdev;
|
||||||
|
int physfns = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(entry, &pdev->bus->devices, bus_list) {
|
||||||
|
/* When the devices on the bus don't all match our device ID,
|
||||||
|
* we can't reliably determine the correct number of
|
||||||
|
* functions. This can occur if a function has been direct
|
||||||
|
* attached to a virtual machine using VT-d.
|
||||||
|
*/
|
||||||
|
if (entry->vendor != pdev->vendor ||
|
||||||
|
entry->device != pdev->device)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
physfns++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return physfns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* txgbe_sw_init - Initialize general software structures (struct txgbe_adapter)
|
||||||
|
* @adapter: board private structure to initialize
|
||||||
|
**/
|
||||||
|
static int txgbe_sw_init(struct txgbe_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = adapter->pdev;
|
||||||
|
struct txgbe_hw *hw = &adapter->hw;
|
||||||
|
struct wx_hw *wxhw = &hw->wxhw;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
wxhw->hw_addr = adapter->io_addr;
|
||||||
|
wxhw->pdev = pdev;
|
||||||
|
|
||||||
|
/* PCI config space info */
|
||||||
|
err = wx_sw_init(wxhw);
|
||||||
|
if (err < 0) {
|
||||||
|
netif_err(adapter, probe, adapter->netdev,
|
||||||
|
"read of internal subsystem device id failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
||||||
{
|
{
|
||||||
struct txgbe_adapter *adapter = pci_get_drvdata(pdev);
|
struct txgbe_adapter *adapter = pci_get_drvdata(pdev);
|
||||||
|
|
@ -67,8 +132,10 @@ static int txgbe_probe(struct pci_dev *pdev,
|
||||||
const struct pci_device_id __always_unused *ent)
|
const struct pci_device_id __always_unused *ent)
|
||||||
{
|
{
|
||||||
struct txgbe_adapter *adapter = NULL;
|
struct txgbe_adapter *adapter = NULL;
|
||||||
|
struct txgbe_hw *hw = NULL;
|
||||||
|
struct wx_hw *wxhw = NULL;
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
int err;
|
int err, expected_gts;
|
||||||
|
|
||||||
err = pci_enable_device_mem(pdev);
|
err = pci_enable_device_mem(pdev);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
@ -107,6 +174,9 @@ static int txgbe_probe(struct pci_dev *pdev,
|
||||||
adapter = netdev_priv(netdev);
|
adapter = netdev_priv(netdev);
|
||||||
adapter->netdev = netdev;
|
adapter->netdev = netdev;
|
||||||
adapter->pdev = pdev;
|
adapter->pdev = pdev;
|
||||||
|
hw = &adapter->hw;
|
||||||
|
wxhw = &hw->wxhw;
|
||||||
|
adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
|
||||||
|
|
||||||
adapter->io_addr = devm_ioremap(&pdev->dev,
|
adapter->io_addr = devm_ioremap(&pdev->dev,
|
||||||
pci_resource_start(pdev, 0),
|
pci_resource_start(pdev, 0),
|
||||||
|
|
@ -116,10 +186,39 @@ static int txgbe_probe(struct pci_dev *pdev,
|
||||||
goto err_pci_release_regions;
|
goto err_pci_release_regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
|
||||||
|
|
||||||
|
/* setup the private structure */
|
||||||
|
err = txgbe_sw_init(adapter);
|
||||||
|
if (err)
|
||||||
|
goto err_pci_release_regions;
|
||||||
|
|
||||||
|
/* check if flash load is done after hw power up */
|
||||||
|
err = wx_check_flash_load(wxhw, TXGBE_SPI_ILDR_STATUS_PERST);
|
||||||
|
if (err)
|
||||||
|
goto err_pci_release_regions;
|
||||||
|
err = wx_check_flash_load(wxhw, TXGBE_SPI_ILDR_STATUS_PWRRST);
|
||||||
|
if (err)
|
||||||
|
goto err_pci_release_regions;
|
||||||
|
|
||||||
netdev->features |= NETIF_F_HIGHDMA;
|
netdev->features |= NETIF_F_HIGHDMA;
|
||||||
|
|
||||||
pci_set_drvdata(pdev, adapter);
|
pci_set_drvdata(pdev, adapter);
|
||||||
|
|
||||||
|
/* calculate the expected PCIe bandwidth required for optimal
|
||||||
|
* performance. Note that some older parts will never have enough
|
||||||
|
* bandwidth due to being older generation PCIe parts. We clamp these
|
||||||
|
* parts to ensure that no warning is displayed, as this could confuse
|
||||||
|
* users otherwise.
|
||||||
|
*/
|
||||||
|
expected_gts = txgbe_enumerate_functions(adapter) * 10;
|
||||||
|
|
||||||
|
/* don't check link if we failed to enumerate functions */
|
||||||
|
if (expected_gts > 0)
|
||||||
|
txgbe_check_minimum_link(adapter);
|
||||||
|
else
|
||||||
|
dev_warn(&pdev->dev, "Failed to enumerate PF devices.\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_pci_release_regions:
|
err_pci_release_regions:
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,6 @@
|
||||||
#ifndef _TXGBE_TYPE_H_
|
#ifndef _TXGBE_TYPE_H_
|
||||||
#define _TXGBE_TYPE_H_
|
#define _TXGBE_TYPE_H_
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/netdevice.h>
|
|
||||||
|
|
||||||
/************ txgbe_register.h ************/
|
|
||||||
/* Vendor ID */
|
|
||||||
#ifndef PCI_VENDOR_ID_WANGXUN
|
|
||||||
#define PCI_VENDOR_ID_WANGXUN 0x8088
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Device IDs */
|
/* Device IDs */
|
||||||
#define TXGBE_DEV_ID_SP1000 0x1001
|
#define TXGBE_DEV_ID_SP1000 0x1001
|
||||||
#define TXGBE_DEV_ID_WX1820 0x2001
|
#define TXGBE_DEV_ID_WX1820 0x2001
|
||||||
|
|
@ -54,4 +45,14 @@
|
||||||
/* Revision ID */
|
/* Revision ID */
|
||||||
#define TXGBE_SP_MPW 1
|
#define TXGBE_SP_MPW 1
|
||||||
|
|
||||||
|
/**************** SP Registers ****************************/
|
||||||
|
/* FMGR Registers */
|
||||||
|
#define TXGBE_SPI_ILDR_STATUS 0x10120
|
||||||
|
#define TXGBE_SPI_ILDR_STATUS_PERST BIT(0) /* PCIE_PERST is done */
|
||||||
|
#define TXGBE_SPI_ILDR_STATUS_PWRRST BIT(1) /* Power on reset is done */
|
||||||
|
|
||||||
|
struct txgbe_hw {
|
||||||
|
struct wx_hw wxhw;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _TXGBE_TYPE_H_ */
|
#endif /* _TXGBE_TYPE_H_ */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user