marvell:Add compilation support to driver

- Renamed the directory to oak
- Updated the make files to compile the source
- Removed unused script

ESDP-16549
Bug 3882239
Bug 3824037

Change-Id: I1dee5def85b6e25f88dff999f1051bfe62d5613b
Signed-off-by: Sheetal Tigadoli <stigadoli@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2856988
Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Sheetal Tigadoli
2023-02-12 13:41:32 +00:00
committed by mobile promotions
parent afd05b80bd
commit 748fa9c699
36 changed files with 7 additions and 13 deletions

View File

@@ -0,0 +1,35 @@
##
##
## If you received this File from Marvell, you may opt to use, redistribute and/or
## modify this File in accordance with the terms and conditions of the General
## Public License Version 2, June 1991 (the "GPL License"), a copy of which is
## available along with the File in the license.txt file or by writing to the Free
## Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
## on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
## THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
## WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
## DISCLAIMED. The GPL License provides additional details about this warranty
## disclaimer.
##
##
#
# Makefile for the Marvell(R) YukonXG PCI Express ethernet driver
#
obj-m := oak_pci.o
EXTRA_CFLAGS += -DKERNEL -Werror
oak_pci-objs := oak.o oak_net.o oak_irq.o oak_ethtool.o oak_unimac.o oak_debug.o oak_chksum.o oak_dpm.o
all:
make W=1 -C /lib/modules/`uname -r`/build M=`pwd` modules
clean:
rm -f core *.o *.a *.s *.ko .mrvl* .oak* .*.o.cmd Module.symvers Module.markers oak_pci.mod* modules.order
clobber: clean
rm -f *.log
rm -rf .tmp_versions

View File

@@ -0,0 +1 @@
EMPTY

View File

@@ -0,0 +1,166 @@
Linux driver for OAK revision A0/B0 (For Linux kernel 5)
--------------------------------------------------------
The purpose of this linux driver is to provide basic functionality for network data
exchange between the common Linux protocol implementation and up to 10Gbit Ethernet
networks.
Additional functionality is provided by the driver to the user space, that allows
control of the particular chip components e.g.: Unimac, ESU and Gicu.
This functional enhancement is not subject of a common Linux driver but is primarily
used to control and test the operation modes of the test/board in a way that is not
directly supported by the standard network protocoll. See also the 'cmdtool' source.
Compilation:
------------
1) On your target Linux system execute: sudo su
2) Then change to any directory and extract the complete source from the source file:
tar -xvf ./drv-src.tar
3) The driver supports currently the two known Marvell PCIe device vendor IDs:
vendor: 0x11AB device: 0x0000 (undefined)
vendor: 0x11AB device: 0xABCD
Execute: lspci -v -d 11ab: -vv
If the device id is not listed above you do not need to change the ID in the system
but you just can add the alternate device ID to the driver source.
With a source code editor:
Just copy line 36 in file oak.c (PCI_DEVICE(0x11AB, 0x0000), insert the new line
after the current one and change the device ID 0x0000 to the one listed in your
PCIe configuration space.
4) COMPILATION:
Now the driver source has to be compiled against the kernel in use, at least kernel
release 5.4.2.
# make -C /lib/modules/`uname -r`/build M=`pwd` modules
The command line above locates your current kernel version (uname -r) and builds a new
kernel object (oak_pci.ko) in the current directory. Alternatively you can change the
KDIR line in the file ./m accordingly and execute: ./m
If there is any compilation error please report to Marvell.
Please note that the driver does not support MSI.
For the purpose of parallel processing of interrupts only MSIX is supported by the driver
and must be supported (enabled) by the linux kernel. This should be the default.
5) LOADING ...:
Once you have successfully generated the kernel object you may load it manually to
the kernel environment from your working directory. This is done with the 'insmod' system
tool.
When loading the kernel object you should define a debug level. This generates log messages
in the system log file that can be used to trace the driver activity.
To do this start the background syslog monitoring in a separate command shell:
# tail -f /var/log/syslog &
Alternatively you can also use the dmesg (-c / clear) command.
Then load the driver with debug level 3 (bit 0 and 1):
# insmod oak_pci.ko debug=0x00 chan=10 txs=32 rxs=32 rto=100 mhdr=0
Debug levels comply to the system defined values e.g.:
NETIF_MSG_DRV = 0x0001,
NETIF_MSG_PROBE = 0x0002,
NETIF_MSG_LINK = 0x0004,
NETIF_MSG_TIMER = 0x0008,
NETIF_MSG_IFDOWN = 0x0010,
NETIF_MSG_IFUP = 0x0020,
NETIF_MSG_RX_ERR = 0x0040,
NETIF_MSG_TX_ERR = 0x0080,
NETIF_MSG_TX_QUEUED = 0x0100,
NETIF_MSG_INTR = 0x0200,
NETIF_MSG_TX_DONE = 0x0400,
NETIF_MSG_RX_STATUS = 0x0800,
NETIF_MSG_PKTDATA = 0x1000,
NETIF_MSG_HW = 0x2000,
NETIF_MSG_WOL = 0x4000,
6) PARAMETERS:
Additional load parameter as used in 5) above:
chan=10 This load parameter is used to limit the internal number of transmit/receive
descriptor pairs of the PCIe Unimac at port 11.
The default is 10 and may be changed to a value between 1...10 e.g.
for better debugging. Note that not all channels will be in use by the
Linux protocol stack.
txs=32 This parameter defines the maximal number of descriptor entries on the
transmit side, that is the number of TX packets that can be queued to
each of the configured descriptors.
rxs=32 The same as txs but applies to the receive descriptors.
rto=100 Receive timeout: the timeout before a receive interrupt is executed on any
receive descriptor ring in case there is low traffic and packet delay time
in the ring shall be reduced (to be verfied with icmp response time/ping).
The value is given in micro seconds.
mhdr=1 Instructs the ESU to create the Marvell-header status per rx packet.
This may be required for some Unimac receive mappings that require packet
flow information e.g. source port id ....
There is no need to change it to zero.
7) Once the kernel object has been loaded successfully the ifconfig -a command should
display a new network interface.
Up to this level of operation the driver did not yet fully access the Unimac and other
parts. It just checked the existing PCIe device and 'attached' to the kernel's networking
interface and is still waiting to be started.
8) CONFIGURATION:
When you assign an IP address to the interface e.g. #ifconfig ethX 1.1.1.1 the driver gets
the start command for complete initialization of the hardware. This may be the most critical
situation for any problems. After this the driver should be able to send and receive packets
and process interrupt handling. It's now fully operational.
In this state you may use the cmdtool (test tool) as shown in 11) below.
9) STOP:
ifconfig ethX stops activities on the hardware again. The driver is now disconnected from
the network and not fully operational.
10) UNLOAD: Finally you may unload the driver with: # rmmod oak_pci
11) CMDTOOL (comamnd line tool, may be packaged sperately)
In the driver source directory extract the file cli-src.tar .
This creates a subdirectory cmdtool in the current directory.
Change to the directory: # cd cmdtool
and just execute: # make
This generates a binary: cli
Just execute for help: # ./cli
Syntax error, use: ./cli [ help ] <command> ...
commands : help mac esu gicu pcie gen exec rxmap irq showc dump set ATU VTU TCAM ESTAT ...
This shows a list of commands that can be executed on top of the driver's interface, that has to be specified
with the argument -if ethX
Each command can be shown in detail with # ./cli help <cmd>
The following most command groups can be used:
mac - write or read (dump) registers of the Unimac at port 11.
esu - write or read (dump) registers of the ESU.
gicu- write or read (dump) registers of the Gicu.
irq - displays the interrupt mapping scheme of MSIX interrupts in use for each particular tx/tx channel.
showc - display tx or rx descriptor information for a specific range of descritors but the maximal number
that have been configured with rxs/txs parameter. This displays the byte count of each frame in a
tx/rx descriptor , timestamp information, buffer DMA addresses, Vlan tags, checksum info and the
HW read/write pointers of the Unimac. This command may be used to trace round robin activities on
a particular descriptor ring of the Unimac.
ATU VTU TCAM ESTAT
Commands for ATU VTU operations or TCAM operations or ESU port statistics.
rxmap - setup a Unimac rx-mapping on a specific queue[0-9] on a rx descripror/ring.
dump - hexdump of binary file.

View File

@@ -0,0 +1,34 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_LDG_T
#define H_LDG_T
typedef struct ldg_tstruct {
struct napi_struct napi;
struct oak_tstruct *device;
u64 msi_tx;
u64 msi_rx;
u64 msi_te;
u64 msi_re;
u64 msi_ge;
u64 irq_mask;
u32 irq_first;
u32 irq_count;
u32 msi_grp;
char msiname[32];
} ldg_t;
#endif /* #ifndef H_LDG_T */

View File

@@ -0,0 +1,17 @@
Copyright 2020 Marvell
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA, or at http://www.gnu.org/licenses/gpl.txt

View File

@@ -0,0 +1,693 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "oak.h"
/* private function prototypes */
static int oak_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id);
static void oak_remove(struct pci_dev *pdev);
static void oak_read_set_mac_address(struct pci_dev *pdev);
/* Oak driver name, version, and copyright */
const char oak_driver_name[] = OAK_DRIVER_NAME;
const char oak_driver_version[] = OAK_DRIVER_VERSION;
static const char oak_driver_string[] = OAK_DRIVER_STRING;
static const char oak_driver_copyright[] = OAK_DRIVER_COPYRIGHT;
/* Oak PCI device ID structure */
static struct pci_device_id oak_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x1000)},
{PCI_DEVICE(0x11AB, 0x0000)}, /* FPGA board */
{PCI_DEVICE(0x11AB, 0xABCD)}, /* FPGA board */
{PCI_DEVICE(0x11AB, 0x0f13)},
{PCI_DEVICE(0x11AB, 0x0a72)}, /* Oak */
};
#ifdef CONFIG_PM_SLEEP
/* Device Power Management (DPM) support */
static const struct dev_pm_ops oak_dpm_ops = {
.suspend = oak_dpm_suspend,
.resume = oak_dpm_resume,
};
#endif
/* PCIe - interface structure */
static struct pci_driver oak_driver = {
.name = oak_driver_name,
.id_table = oak_pci_tbl,
.probe = oak_probe,
.remove = oak_remove,
#ifdef CONFIG_PM_SLEEP
.driver.pm = &oak_dpm_ops,
#endif
};
/* Oak ethtool operation structure */
static const struct ethtool_ops oak_ethtool_ops = {
.get_drvinfo = oak_ethtool_get_drvinfo,
.get_ethtool_stats = oak_ethtool_get_stats,
.get_strings = oak_ethtool_get_strings,
.get_sset_count = oak_ethtool_get_sscnt,
.get_link = ethtool_op_get_link,
.get_msglevel = oak_dbg_get_level,
.set_msglevel = oak_dbg_set_level,
.get_link_ksettings = oak_ethtool_get_link_ksettings,
};
/* Oak netdevice operation structure */
static const struct net_device_ops oak_netdev_ops = {
.ndo_open = oak_net_open,
.ndo_stop = oak_net_close,
.ndo_start_xmit = oak_net_xmit_frame,
.ndo_do_ioctl = oak_net_ioctl,
.ndo_set_mac_address = oak_net_set_mac_addr,
.ndo_select_queue = oak_net_select_queue,
.ndo_change_mtu = oak_net_esu_set_mtu,
.ndo_validate_addr = eth_validate_addr,
};
/* global variable declaration */
u32 debug;
u32 txs = 2048;
u32 rxs = 2048;
int chan = MAX_NUM_OF_CHANNELS;
int rto = 100;
int mhdr;
u32 port_speed = 10;
int napi_wt = NAPI_POLL_WEIGHT;
/* software level defination */
#define SOFTWARE_INIT 10
#define HARDWARE_INIT 20
#define SOFTWARE_STARTED 40
/* Name : oak_init_module
* Returns : int
* Parameters:
* Description : This function is the entry point for the driver registration.
*/
int oak_init_module(void)
{
s32 retval = 0;
pr_info("%s - (%s) version %s\n",
oak_driver_string, oak_driver_name, oak_driver_version);
pr_info("%s\n", oak_driver_copyright);
/* Register Oak PCI driver with the linux kernel
* PCI device drivers call pci_register_driver() during their
* initialization with a pointer to a structure describing the
* driver (struct pci_driver)
*/
retval = pci_register_driver(&oak_driver);
return retval;
}
/* Name : exit_module
* Returns : void
* Parameters:
* Description : This function is the exit point for the driver.
*/
void oak_exit_module(void)
{
/* Unregister Oak PCI driver from linux kernel */
pci_unregister_driver(&oak_driver);
}
/* Name : start_software
* Returns : int
* Parameters: struct pci_dev * pdev
* Description: This function registers the oak device to napi
*/
static int oak_start_software(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
int retval = 0;
netdev->ethtool_ops = &oak_ethtool_ops;
oak_net_add_napi(netdev);
/* register netdev will take a completed network device structure and
* add it to the kernel interfaces
*/
retval = register_netdev(netdev);
return retval;
}
/* Name : release_software
* Returns : void
* Parameters: struct pci_dev * pdev
* Description : This function release the Ethernet interface.
*/
static void oak_release_software(struct pci_dev *pdev)
{
int retval;
struct net_device *netdev = pci_get_drvdata(pdev);
oak_t *oak;
oak = netdev_priv(netdev);
#ifdef CONFIG_PM
/* Set the PCI device power state to D3hot */
retval = pci_set_power_state(pdev, PCI_D3hot);
if (retval == 0)
pr_info("oak: Device power state D%d\n", pdev->current_state);
else
pr_err("oak: Failed to set the device power state err: %d\n",
retval);
/* Remove sysfs entry */
oak_dpm_remove_sysfs(oak);
#endif
oakdbg(debug, PROBE, "pdev=%p ndev=%p", pdev, pci_get_drvdata(pdev));
free_netdev(netdev);
}
/* Name : oak_init_software
* Returns : int
* Parameters : struct pci_dev *pdev
* Description : This function initializes the PCIe interface and network device
*/
static int oak_init_software(struct pci_dev *pdev)
{
struct net_device *netdev = NULL;
oak_t *oak;
int retval = 0;
/* Allocates and sets up an Ethernet device
* Fill in the fields of the device structure with Ethernet-generic
* values. Basically does everything except registering the device
*/
netdev = alloc_etherdev_mq(sizeof(oak_t), chan);
if (netdev) {
/* Set the sysfs physical device reference for the network
* logical device if set prior to registration will cause a
* symlink during initialization.
*/
SET_NETDEV_DEV(netdev, &pdev->dev);
/* Set private driver data pointer for a pci_dev */
pci_set_drvdata(pdev, netdev);
oak = netdev_priv(netdev);
oak->device = &pdev->dev;
oak->netdev = netdev;
oak->pdev = pdev;
#ifdef CONFIG_PM
/* Create sysfs entry for D0, D1, D2 and D3 states testing */
oak_dpm_create_sysfs(oak);
#endif
/* Register network device operations */
netdev->netdev_ops = &oak_netdev_ops;
/* Set hardware's checksum Offload capabilities */
netdev->features = oak_chksum_get_config();
/* Set the min and max MTU size */
oak_set_mtu_config(netdev);
spin_lock_init(&oak->lock);
} else {
/* If software initialization fails then we need to release the
* device and free allocated structure with retnval as ENOMEM
*/
oak_release_software(pdev);
retval = -ENOMEM;
}
oakdbg(debug, PROBE, "pdev=%p ndev=%p err=%d",
pdev, pci_get_drvdata(pdev), retval);
return retval;
}
/* Name : oak_probe
* Returns : int
* Parameters : struct pci_dev *pdev, const struct pci_device_id *dev_id
* Description : This function probe the device and call initialization
* functions
*/
static int oak_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
{
int retval = 0;
int err = 0;
oak_t *adapter = NULL;
#ifdef CONFIG_PM
/* Set PCI device power state to D0 */
err = pci_set_power_state(pdev, PCI_D0);
if (err == 0)
pr_info("oak: Device power state D%d\n", pdev->current_state);
else
pr_err("oak: Failed to set the device power state err: %d\n",
err);
#endif
/* Initialize the oak software */
err = oak_init_software(pdev);
if (err == 0) {
struct net_device *netdev = pci_get_drvdata(pdev);
adapter = netdev_priv(netdev);
/* Set level as software initialization */
adapter->level = SOFTWARE_INIT;
/* Initialize the Oak hardware */
err = oak_init_hardware(pdev);
if (err == 0) {
/* Read MAC from firmware registers and set to the
* device address register.
*/
oak_read_set_mac_address(pdev);
err = oak_start_software(pdev);
if (err == 0)
/* Set level as driver software started */
adapter->level = SOFTWARE_STARTED;
else
retval = err;
} else {
retval = err;
}
} else {
retval = err;
}
if (err == 0) {
retval = err;
if (adapter->sw_base)
pr_info("%s[%d] - ESU register access is supported",
oak_driver_name, pdev->devfn);
} else {
oak_remove(pdev);
}
oakdbg(debug, PROBE, "pdev=%p ndev=%p err=%d", pdev,
pci_get_drvdata(pdev), err);
return retval;
}
/* Name : oak_get_msix_resources
* Returns : int
* Parameters : struct pci_dev * pdev
* Description : This function allocates the MSIX resources.
*/
static int oak_get_msix_resources(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
oak_t *adapter = netdev_priv(dev);
u32 num_irqs;
u32 num_cpus = num_online_cpus();
u32 i;
int cnt;
int retval = 0;
num_irqs = sizeof(adapter->gicu.msi_vec) / sizeof(struct msix_entry);
/* Return the number of device's MSI-X table entries */
cnt = pci_msix_vec_count(pdev);
if (cnt <= 0) {
retval = -EFAULT;
} else {
if (cnt <= num_irqs)
num_irqs = cnt;
if (num_irqs > num_cpus)
num_irqs = num_cpus;
for (i = 0; i < num_irqs; i++) {
adapter->gicu.msi_vec[i].vector = 0;
adapter->gicu.msi_vec[i].entry = i;
}
#ifdef OAK_MSIX_LEGACY
/* Configure device's MSI-X capability structure - Setup the
* MSI-X capability structure of device function with a
* maximum possible number of interrupts in the range between
* minvec and maxvec upon its software driver call to request
* for MSI-X mode enabled on its hardware device function.
* It returns a negative errno if an error occurs.
* If it succeeds, it returns the actual number of interrupts
* allocated and indicates the successful configuration of
* MSI-X capability structure with new allocated MSI-X
* interrupts.
*/
retval = pci_enable_msix_range(pdev, adapter->gicu.msi_vec,
num_irqs, num_irqs);
#else
/* Which allocates up to max_vecs interrupt vectors for a PCI
* device.
*/
retval = pci_alloc_irq_vectors(pdev, num_irqs, num_irqs,
PCI_IRQ_ALL_TYPES);
if (retval) {
pr_info("int vec count %d\n", retval);
num_irqs = retval;
}
#endif
if (retval >= 0)
retval = 0;
adapter->gicu.num_ldg = num_irqs;
oakdbg(debug, PROBE, "pdev=%p ndev=%p num_irqs=%d/%d retval=%d",
pdev, dev, num_irqs, cnt, retval);
}
return retval;
}
/* Name : release_hardware
* Returns : void
* Parameters: struct pci_dev * pdev
* Description : This function de initializes the hardware and
* release the resources.
*/
void oak_release_hardware(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
oak_t *adapter = netdev_priv(dev);
int err = 0;
if (adapter->gicu.num_ldg > 0)
pci_disable_msix(pdev);
/* Release reserved PCI I/O and memory resources */
pci_release_regions(pdev);
pci_disable_device(pdev);
oakdbg(debug, PROBE, "pdev=%p ndev=%p err=%d",
pdev, pci_get_drvdata(pdev), err);
}
/* Name : oak_init_map_config
* Returns : int
* Parameters : struct pci_dev *pdev
* Description : This function create a virtual mapping cookie for a PCI BAR
*/
static int oak_init_map_config(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
oak_t *adapter = netdev_priv(dev);
u32 mem_flags;
int retval = 0;
/* This function returns the flags associated with the PCI resource.
* Resource flags are used to define some features of the individual
* resource. For PCI resources associated with PCI I/O regions, the
* information is extracted from the base address registers, but can
* come from elsewhere for resources not associated with PCI devices.
*/
mem_flags = pci_resource_flags(pdev, 2);
if ((mem_flags & IORESOURCE_MEM) == 0)
retval = -EINVAL;
else
adapter->sw_base = pci_iomap(pdev, 2, 0);
oakdbg(debug, PROBE,
"Device found: dom=%d bus=%d dev=%d fun=%d reg-addr=%p",
pci_domain_nr(pdev->bus), pdev->bus->number,
PCI_SLOT(pdev->devfn), pdev->devfn, adapter->um_base);
return retval;
}
/* Name : oak_init_read_write_config
* Returns : int
* Parameters : struct pci_dev *pdev
* Description : This function read and write into config space.
*/
static int oak_init_read_write_config(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
oak_t *adapter = netdev_priv(dev);
u32 v0, v1;
u16 devctl;
int retval = 0;
/* Create virtual mapping the PCI BAR configuration space before doing
* read or write into configuration space
*/
retval = oak_init_map_config(pdev);
if (retval != 0)
pr_err("PCI config space mapping failed %d\n", retval);
/* After the driver has detected the device, it usually needs to read
* from or write to the three address spaces: memory, port, and
* configuration. In particular, accessing the configuration space is
* vital to the driver, because it is the only way it can find out
* where the device is mapped in memory and in the I/O space.
*/
pci_read_config_dword(pdev, 0x10, &v0);
pci_read_config_dword(pdev, 0x14, &v1);
v0 &= 0xfffffff0U;
v0 |= 1U;
pci_write_config_dword(pdev, 0x944, v1);
pci_write_config_dword(pdev, 0x940, v0);
pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &devctl);
/* Calculate and store TX max burst size */
adapter->rrs =
(u16)(1U << (((devctl & PCI_EXP_DEVCTL_READRQ) >> 12) + 6));
if (retval == 0)
retval = oak_get_msix_resources(pdev);
return retval;
}
/* Name : oak_init_pci_config
* Returns : int
* Parameters : struct pci_dev *pdev
* Description : This function initialize oak pci config space
*/
static int oak_init_pci_config(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
oak_t *adapter = netdev_priv(dev);
int err = 0;
err = pci_request_regions(pdev, OAK_DRIVER_NAME);
if (err == 0) {
/* Enables bus-mastering for device */
pci_set_master(pdev);
/* Save the PCI configuration space */
pci_save_state(pdev);
/* create a virtual mapping cookie for a PCI BAR. Using
* this function you will get a __iomem address to your
* device BAR. You can access it using ioread*() and
* iowrite*(). These functions hide the details if this
* is a MMIO or PIO address space and will just do what
* you expect from them in the correct way.
* void __iomem * pci_iomap(struct pci_dev * dev,
* int bar, unsigned long, maxlen);
* maxlen specifies the maximum length to map. If you
* want to get access to the complete BAR without
* checking for its length first, pass 0 here.
*/
adapter->um_base = pci_iomap(pdev, 0, 0);
if (!adapter->um_base)
err = -ENOMEM;
else
err = oak_init_read_write_config(pdev);
}
return err;
}
/* Name : oak_init_hardware
* Returns : int
* Parameters : struct pci_dev * pdev
* Description : This function initializes oak hardware
*/
int oak_init_hardware(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
oak_t *adapter = netdev_priv(dev);
int retval = 0;
u32 mem_flags;
/* Initialize device before it's used by a driver */
retval = pci_enable_device(pdev);
if (retval == 0) {
/* This function returns the flags associated with this
* resource. Resource flags are used to define some features
* of the individual resource. For PCI resources associated with
* PCI I/O regions, the information is extracted from the base
* address registers, but can come from elsewhere for resources
* not associated with PCI devices
*/
mem_flags = pci_resource_flags(pdev, 0);
if ((mem_flags & IORESOURCE_MEM) == 0) {
retval = -EINVAL;
} else {
pci_read_config_dword(pdev, PCI_CLASS_REVISION,
&adapter->pci_class_revision);
adapter->pci_class_revision &= 0x0000000FU;
if (adapter->pci_class_revision > OAK_REVISION_B0) {
retval = -EINVAL;
} else {
retval =
dma_set_mask_and_coherent(&pdev->dev,
DMA_BIT_MASK(64));
}
if (retval == 0)
retval = oak_init_pci_config(pdev);
}
} else {
pr_err("PCI enable device failed %d\n", retval);
}
oakdbg(debug, PROBE, "pdev=%p ndev=%p err=%d", pdev,
pci_get_drvdata(pdev), retval);
return retval;
}
/* Name : oak_set_mtu_config
* Returns : void
* Parameters: struct net_device *netdev
* Description: This function sets the min and max MTU size in the linux netdev.
*/
void oak_set_mtu_config(struct net_device *netdev)
{
netdev->min_mtu = ETH_MIN_MTU;
netdev->max_mtu = OAK_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
}
/* Name : oak_read_set_mac_address
* Returns : void
* Parameters : struct net_device *netdev
* Description : During startup, firmware writes its own MAC address into the
* EPU_DATA2 and EPU_DATA3 registers. When loaded, this function obtains MAC
* address from EPU_DATA registers and increments the NIC specific part of the
* MAC address by 1.
* The MAC address consists of two parts:
* Octet 1-3: Organizationally Unique Identifier (OUI)
* Octet 4-6: Network Interface Controller (NIC) specific part.
* The increment shall be done for the NIC specific part only.
*/
static void oak_read_set_mac_address(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
oak_t *np = netdev_priv(netdev);
/* Octet 1-3 from EPU_DATA2 */
u32 mac_oui;
/* Octet 4-6 from EPU_DATA3 */
u32 mac_nic;
u32 mac_update;
u32 oui_be;
unsigned char device_mac[sizeof(uint64_t)];
char nic_mac[ETH_ALEN];
bool rc;
/* Read MAC address from EPU_DATA2 and EPU_DATA3 registers */
mac_oui = oak_unimac_io_read_32(np, OAK_EPU_DATA2);
mac_nic = oak_unimac_io_read_32(np, OAK_EPU_DATA3);
pr_debug("Device MAC address OUI (EPU_DATA2) : 0x%x\n",
cpu_to_be32(mac_oui));
pr_debug("Device MAC address NIC (EPU_DATA3) : 0x%x\n",
cpu_to_be32(mac_nic));
/* Copy Oak device MAC address and print */
memcpy((void *)&device_mac, (void *)&mac_oui, sizeof(mac_oui));
memcpy((void *)&device_mac + 4, (void *)&mac_nic, sizeof(mac_nic));
rc = is_valid_ether_addr(device_mac);
if (rc != 0) {
/* Copy the OUI into network device structure */
oui_be = (__force u32)cpu_to_be32(mac_oui);
nic_mac[0] = (char)((oui_be & 0xff000000U) >> 24);
nic_mac[1] = (char)((oui_be & 0x00ff0000U) >> 16);
nic_mac[2] = (char)((oui_be & 0x0000ff00U) >> 8);
/* To construct MAC address we need to takeout one bye from
* EPU_DATA2 and two bytes from EPU_DATA3 register
* As an example: MAC address is 11:22:33:44:55:66 set by
* firmware then Data read from register will give below
* little endian output
* EPU_DATA2 - 0x44332211
* EPU_DATA3 - 0x6655
* Hence it is required to convert to endian using cpu_to_be32
* EPU_DATA2 - 0x11223344
* EPU_DATA3 - 0x55660000
* To construct NIC part as 0x445566
*/
mac_update = (__force u32)cpu_to_be32(mac_nic) >> 16;
mac_update = ((__force u32)cpu_to_be32(mac_oui) & 0xFFU) << 16 |
mac_update;
/* Update the NIC part by one */
mac_update = mac_update + 1;
/* Copy updated NIC to netdev layer */
nic_mac[3] = (char)((mac_update & 0xff0000U) >> 16);
nic_mac[4] = (char)((mac_update & 0x00ff00U) >> 8);
nic_mac[5] = (char)(mac_update & 0x0000ffU);
/* Validate locally constructed NIC MAC address and
* Copy to mac_address member of oak_t if its valid.
*/
rc = is_valid_ether_addr(nic_mac);
if (rc != 0) {
pr_info("Device MAC address : %pM\n", device_mac);
ether_addr_copy(np->mac_address, nic_mac);
ether_addr_copy(netdev->dev_addr, nic_mac);
pr_info("MAC address of NIC : %pM\n", nic_mac);
}
}
}
/* Name : stop_software
* Returns : void
* Parameters: struct pci_dev * pdev
* Description: This function unregisters the oak driver from netdev
*/
static void oak_stop_software(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
oak_net_del_napi(netdev);
/* This function shuts down a device interface and removes it from
* the kernel tables.
*/
unregister_netdev(netdev);
}
/* Name : oak_remove
* Returns : void
* Parameters : struct pci_dev * pdev
* Description : This function remove the device from kernel
*/
static void oak_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
oak_t *adapter = NULL;
if (netdev)
adapter = netdev_priv(netdev);
if (adapter) {
if (adapter->level >= SOFTWARE_STARTED)
oak_stop_software(pdev);
if (adapter->level >= HARDWARE_INIT)
oak_release_hardware(pdev);
if (adapter->level >= SOFTWARE_INIT)
oak_release_software(pdev);
}
oakdbg(debug, PROBE, "pdev=%p ndev=%p", pdev, pci_get_drvdata(pdev));
#ifndef OAK_MSIX_LEGACY
/* Free previously allocated IRQs for a device */
pci_free_irq_vectors(pdev);
#endif
}

View File

@@ -0,0 +1,53 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK
#define H_OAK
/* Include for relation to classifier oak_unimac */
#include "oak_unimac.h"
/* Include for relation to classifier oak_net */
#include "oak_net.h"
/* Include for relation to classifier oak_ethtool */
#include "oak_ethtool.h"
#include "oak_debug.h"
/* Include for relation to classifier oak_module */
#include "oak_module.h"
#include "oak_chksum.h"
#include "oak_dpm.h"
#define OAK_DRIVER_NAME "oak"
#define OAK_DRIVER_STRING "Marvell PCIe Switch Driver"
#define OAK_DRIVER_VERSION "3.01.0001"
#define OAK_DRIVER_COPYRIGHT "Copyright (c) Marvell - 2018"
#define OAK_MAX_JUMBO_FRAME_SIZE (10 * 1024)
/* EPU data register offset definition */
#define OAK_EPU_DATA2 0xF208
#define OAK_EPU_DATA3 0xF20C
u32 debug;
u32 txs;
u32 rxs;
int chan;
int rto;
int mhdr;
u32 port_speed;
#endif /* #ifndef H_OAK */

View File

@@ -0,0 +1,16 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "oak_channel_stat.h"

View File

@@ -0,0 +1,75 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_CHANNEL_STAT
#define H_OAK_CHANNEL_STAT
typedef struct oak_chan_infostruct {
u32 flags;
u32 r_count;
u32 r_size;
u32 r_pend;
u32 r_widx;
u32 r_ridx;
u32 r_len;
} oak_chan_info;
typedef struct oak_driver_rx_statstruct {
u64 channel;
u64 rx_alloc_pages;
u64 rx_unmap_pages;
u64 rx_alloc_error;
u64 rx_frame_error;
u64 rx_errors;
u64 rx_interrupts;
u64 rx_goodframe;
u64 rx_byte_count;
u64 rx_vlan;
u64 rx_badframe;
u64 rx_no_sof;
u64 rx_no_eof;
u64 rx_badcrc;
u64 rx_badcsum;
u64 rx_l4p_ok;
u64 rx_ip4_ok;
u64 rx_nores;
u64 rx_64;
u64 rx_128;
u64 rx_256;
u64 rx_512;
u64 rx_1024;
u64 rx_2048;
u64 rx_fragments;
} oak_driver_rx_stat;
typedef struct oak_driver_tx_statstruct {
u64 channel;
u64 tx_frame_count;
u64 tx_frame_compl;
u64 tx_byte_count;
u64 tx_fragm_count;
u64 tx_drop;
u64 tx_errors;
u64 tx_interrupts;
u64 tx_stall_count;
u64 tx_64;
u64 tx_128;
u64 tx_256;
u64 tx_512;
u64 tx_1024;
u64 tx_2048;
} oak_driver_tx_stat;
#endif /* #ifndef H_OAK_CHANNEL_STAT */

View File

@@ -0,0 +1,113 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "oak_net.h"
#include "oak_debug.h"
#include "oak_chksum.h"
/* Name : oak_chksum_get_config
* Returns : netdev_features_t
* Parameters : void
* Description : This function provides Oak Hardware's Checksum Offload
* capabilities
*/
netdev_features_t oak_chksum_get_config(void)
{
netdev_features_t features = OAK_CHKSUM_TYPE;
/* Oak HW Supports L3 & L3 Checksum Offload and Freagmented frame,
* so scatter gather need to be enabled.
*/
features |= NETIF_F_SG;
return features;
}
/* Name : oak_chksum_get_tx_config
* Returns : u32
* Parameters : struct sk_buff *skb, u32 *cs_l3, u32 *cs_l4
* Description : This function returns the Checksum Offload configuration
* for the transmit frame.
*/
u32 oak_chksum_get_tx_config(struct sk_buff *skb, u32 *cs_l3,
u32 *cs_l4)
{
u32 retval = 0;
int prot;
*cs_l3 = 0;
*cs_l4 = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
prot = oak_net_skb_tx_protocol_type(skb);
if (prot == L3_L4_CHKSUM) {
*cs_l3 = 1;
*cs_l4 = 1;
} else if (prot == L3_CHKSUM) {
*cs_l3 = 1;
*cs_l4 = 0;
} else {
/* Setting cs_l3 & cs_l4 to zero is done in error case after
* this function returns.
*/
retval = 1;
}
} else {
retval = 1;
}
return retval;
}
/* Name : oak_chksum_get_rx_config
* Returns : u32
* Parameters : struct oak_rx_chan_t *rxc, struct oak_rxs_t *rsr
* Description : This function returns the current receive frames
* checksum state.
*/
int oak_chksum_get_rx_config(oak_rx_chan_t *rxc, oak_rxs_t *rsr)
{
int retval = CHECKSUM_NONE;
if (rsr->vlan == 1)
++rxc->stat.rx_vlan;
if (rsr->l3_ipv4 == 1 || rsr->l3_ipv6 == 1) {
if (rsr->l4_prot == OAK_TCP_IP_FRAME ||
rsr->l4_prot == OAK_TCP_UDP_FRAME) {
if (rsr->l4_chk_ok == 1) {
rxc->stat.rx_l4p_ok++;
retval = CHECKSUM_UNNECESSARY;
}
} else if (rsr->l3_ipv4 == 1 && rsr->ipv4_hdr_ok == 1) {
/*
* Linux documentation for CHECKSUM_PARTIAL
* in include/linux/skbuff.h this state may occur on a packet
* received directly from another Linux OS,
* e.g., a virtualized Linux kernel on the same host,
* or it may be set in the input path in GRO or remote checksum
* offload.
* As per the discussion with the Linux kernel netdev forum
* setting ip_summed to PARTIAL on receive is only valid
* for software/virtual devices, never real HW.
* For a frame where the checksum is not verified by the HW,
* the flag will be set as CHECKSUM_NONE such that
* linux netdev layer verifies the same.
*/
rxc->stat.rx_ip4_ok++;
}
}
return retval;
}

View File

@@ -0,0 +1,53 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_CHKSUM
#define H_OAK_CHKSUM
/* Checksum configurations supported by the Oak HW */
#define OAK_CHKSUM_TYPE (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
#define L3_L4_CHKSUM 2
#define L3_CHKSUM 1
#define NO_CHKSUM 0
#define OAK_TCP_IP_FRAME 1
#define OAK_TCP_UDP_FRAME 2
/* Name : oak_chksum_get_config
* Returns : netdev_features_t
* Parameters : void
* Description : This function provides Oak Hardware's Checksum Offload
* capabilities.
*/
netdev_features_t oak_chksum_get_config(void);
/* Name : oak_chksum_get_tx_config
* Returns : u32
* Parameters : struct sk_buff *skb, u32 *cs_l3, u32 *cs_l4
* Description : This function returns the Checksum Offload configuration for
* the transmit frame.
*/
u32 oak_chksum_get_tx_config(struct sk_buff *skb, u32 *cs_l3,
u32 *cs_l4);
/* Name : oak_chksum_get_rx_config
* Returns : u32
* Parameters : oak_rx_chan_t*, oak_rxs_t*
* Description : This function returns the current receive frames
* checksum state.
*/
int oak_chksum_get_rx_config(oak_rx_chan_t *rxc, oak_rxs_t *rsr);
#endif /* #ifndef H_OAK_CHKSUM */

View File

@@ -0,0 +1,37 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "oak_debug.h"
/* Name : oak_dbg_set_level
* Returns : void
* Parameters : struct net_device *dev, u32 level
* Description : This function set the debug level of the Ethernet interface.
*/
void oak_dbg_set_level(struct net_device *dev, u32 level)
{
debug = level;
}
/* Name : oak_dbg_get_level
* Returns : u32
* Parameters : struct net_device *dev
* Description : This function get the debug level of the Ethernet interface.
*/
u32 oak_dbg_get_level(struct net_device *dev)
{
return debug;
}

View File

@@ -0,0 +1,22 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "linux/etherdevice.h"
#include "linux/pci.h"
#include "oak_irq.h"
void oak_dbg_set_level(struct net_device *dev, u32 level);
u32 oak_dbg_get_level(struct net_device *dev);

View File

@@ -0,0 +1,222 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifdef CONFIG_PM
#include "oak_dpm.h"
#include "oak_net.h"
/* Name : oak_dpm_set_power_state
* Returns : void
* Parameters : struct device *dev, pci_power_t state
* Description : This function set the device power state
*/
void oak_dpm_set_power_state(struct device *dev, pci_power_t state)
{
int retval;
pci_power_t D0 = 0;
struct net_device *ndev = dev_get_drvdata(dev);
oak_t *np = netdev_priv(ndev);
/* If user input state is D0 and current_state not D0
* i.e. current state is D3hot (D1, D2, D3) then
* we call resume operation
*/
if (state == PCI_D0 && np->pdev->current_state != D0) {
retval = oak_dpm_resume(dev);
if (retval)
pr_info("oak_dpm_resume: failed.\n");
}
/* If user input state is D1 or D2 or D3 and current_state D0
* then we do the suspend operation
*/
else if (((state == PCI_D1) ||
(state == PCI_D2) ||
(state == PCI_D3hot)) && (np->pdev->current_state == D0)) {
retval = oak_dpm_suspend(dev);
if (retval != 0)
pr_info("oak_dpm_suspend: failed\n");
}
}
/* Name : oak_dpm_state_store
* Returns : ssize_t
* Parameters : struct device *dev, struct device_attribute *attr,
* const char *buf, size_t count
* Description : This function store the sysfs entry
*/
static ssize_t oak_dpm_state_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
pci_power_t pwr;
bool d0, d1, d2, d3;
/* Validate user input */
d0 = sysfs_streq(buf, "D0");
d1 = sysfs_streq(buf, "D1");
d2 = sysfs_streq(buf, "D2");
d3 = sysfs_streq(buf, "D3");
/* D0 as input, set device as D0
* D1, D2, and D3 as input, set the device as D3
* For any other input, error message is triggered.
*/
if (d0) {
pwr = PCI_D0;
oak_dpm_set_power_state(dev, pwr);
} else if (d1 || d2 || d3) {
pwr = PCI_D3hot;
oak_dpm_set_power_state(dev, pwr);
} else {
pr_err("oak: Wrong input, Device power states are D0, D1, D2 or D3\n");
}
/* With the current sysfs implementation the kobject reference count is
* only modified directly by the function sysfs_schedule_callback().
*/
return count;
}
/* The sysfs kernel object device attribute file oak_dpm_state
* is wrtite only. Hence only oak_dpm_state_store function is
* called by kernel when a user does input to oak_dpm_state file
*/
static DEVICE_ATTR_WO(oak_dpm_state);
/* Name : oak_dpm_create_sysfs
* Returns : void
* Parameters : oak_t *np
* Description : This function creates sysfs entry for setting device power
* states D0, D1, D2 and D3.
*/
void oak_dpm_create_sysfs(oak_t *np)
{
int status;
status = sysfs_create_file(&np->pdev->dev.kobj,
&dev_attr_oak_dpm_state.attr);
if (status)
pr_err("oak: Failed to create sysfs entry\n");
}
/* Name : oak_dpm_remove_sysfs
* Returns : void
* Parameters : oak_t *np
* Description : This function removes sysfs entry of device power states
*/
void oak_dpm_remove_sysfs(oak_t *np)
{
sysfs_remove_file(&np->pdev->dev.kobj, &dev_attr_oak_dpm_state.attr);
}
#ifdef CONFIG_PM_SLEEP
/* Name : oak_dpm_suspend
* Returns : int
* Parameters : struct device *dev
* Description : This function is called when system goes into suspend state
* and put the device into sleep state
*/
int __maybe_unused oak_dpm_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
oak_t *np = netdev_priv(ndev);
int retval = 0;
/* If interface is up then, do driver specific operations
* gracefully close the interface
*/
retval = netif_running(ndev);
if (retval)
oak_net_close(ndev);
/* Inform to PCI core, wake me up from D3hot when event triggers */
pci_enable_wake(np->pdev, PCI_D3hot, true);
/* Release the oak hardware */
oak_release_hardware(np->pdev);
/* To synchronize changes hold rtnl lock */
rtnl_lock();
/* Save the PCI state and prepare to go for sleep */
pci_save_state(np->pdev);
pci_prepare_to_sleep(np->pdev);
/* Set the device power state as D3hot */
retval = pci_set_power_state(np->pdev, PCI_D3hot);
if (retval == 0)
pr_info("%s: dpm state=D%d\n", __func__,
np->pdev->current_state);
else
pr_err("%s: Failed to set the device power state err: %d\n",
__func__, retval);
/* Release the rtnl lock */
rtnl_unlock();
return retval;
}
/* Name : oak_dpm_resume
* Returns : int
* Parameters : struct device *dev
* Description : This function called when system goes into resume state and put
* the device into active state
*/
int __maybe_unused oak_dpm_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
oak_t *np = netdev_priv(ndev);
int retval = 0;
/* To synchronize changes hold rtnl lock */
rtnl_lock();
/* Set the device power state as D0 */
retval = pci_set_power_state(np->pdev, PCI_D0);
if (retval == 0)
pr_info("%s: dpm state=D%d\n", __func__,
np->pdev->current_state);
/* Restore the PCI state */
pci_restore_state(np->pdev);
/* The driver specific operations
* Initialize the oak hardware
* If interface is up, then call oak net open
*/
retval = oak_init_hardware(np->pdev);
if (retval) {
pr_err("%s: oak init hardware Not Successful %d\n", __func__,
retval);
} else {
retval = netif_running(ndev);
if (retval) {
retval = oak_net_open(ndev);
if (retval)
pr_err("%s: oak net open failed\n", __func__);
}
}
/* Release the rtnl lock */
rtnl_unlock();
return retval;
}
#endif
#endif

View File

@@ -0,0 +1,79 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifdef CONFIG_PM
#ifndef H_OAK_DPM
#define H_OAK_DPM
#include <linux/pm_runtime.h>
#include "oak_unimac.h"
/* Name : init_hardware
* Returns : int
* Parameters : struct pci_dev *pdev
* Description : Initialize oak hardware.
*/
int oak_init_hardware(struct pci_dev *pdev);
/* Name : release_hardware
* Returns : void
* Parameters : struct pci_dev * pdev
* Description : Release oak hardware.
*/
void oak_release_hardware(struct pci_dev *pdev);
/* Name : oak_dpm_create_sysfs
* Returns : void
* Parameters : oak_t *np
* Description : This function creates sysfs entry for setting device power
* states D0, D1, D2 and D3.
*/
void oak_dpm_create_sysfs(oak_t *np);
/* Name : oak_dpm_remove_sysfs
* Returns : void
* Parameters : oak_t *np
* Description : This function removes sysfs entry of device power states
*/
void oak_dpm_remove_sysfs(oak_t *np);
#ifdef CONFIG_PM_SLEEP
/* Name : oak_dpm_suspend
* Returns : int
* Parameters : struct device *dev
* Description : This function is called when system goes into suspend state
* It puts the device into sleep state
*/
int __maybe_unused oak_dpm_suspend(struct device *dev);
/* Name : oak_dpm_resume
* Returns : int
* Parameters : struct device *dev
* Description : This function called when system goes into resume state and put
* the device into active state
*/
int __maybe_unused oak_dpm_resume(struct device *dev);
/* Name : oak_dpm_set_power_state
* Returns : void
* Parameters : struct device *dev, pci_power_t state
* Description : This function set the device power state
*/
void oak_dpm_set_power_state(struct device *dev, pci_power_t state);
#endif /* End of PM_SLEEP */
#endif /* End of H_OAK_DPM */
#endif /* End of PM */

View File

@@ -0,0 +1,335 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "oak_ethtool.h"
#include "oak_net.h"
static const char umac_strings[][ETH_GSTRING_LEN] = {
{"rx_good_frames"},
{"rx_bad_frames"},
{"rx_stall_fifo"},
{"rx_stall_desc"},
{"rx_discard_desc"},
{"tx_pause"},
{"tx_stall_fifo"},
};
static const u8 rx_strings[][ETH_GSTRING_LEN] = {
{"Rx Channel"},
{"rx_alloc_pages"},
{"rx_unmap_pages"},
{"rx_alloc_error"},
{"rx_frame_error"},
{"rx_errors"},
{"rx_interrupts"},
{"rx_good_frames"},
{"rx_byte_count"},
{"rx_vlan"},
{"rx_bad_frames"},
{"rx_no_sof"},
{"rx_no_eof"},
{"rx_bad_crc"},
{"rx_bad_csum"},
{"rx_l4p_ok"},
{"rx_ip4_ok"},
{"rx_bad_nores"},
{"rx_64"},
{"rx_128"},
{"rx_256"},
{"rx_512"},
{"rx_1024"},
{"rx_2048"},
{"rx_fragments"},
};
static const u8 tx_strings[][ETH_GSTRING_LEN] = {
{"Tx Channel"},
{"tx_frame_count"},
{"tx_frame_compl"},
{"tx_byte_count"},
{"tx_fragm_count"},
{"tx_drop"},
{"tx_errors"},
{"tx_interrupts"},
{"tx_stall_count"},
{"tx_64"},
{"tx_128"},
{"tx_256"},
{"tx_512"},
{"tx_1024"},
{"tx_2048"},
};
/* private function prototypes */
static void oak_ethtool_get_txc_stats(oak_t *np, u64 **data);
static void oak_ethtool_get_rxc_stats(oak_t *np, u64 **data);
static void oak_ethtool_get_stall_stats(oak_t *np);
static void oak_ethtool_get_misc_stats(oak_t *np);
/* Name : oak_ethtool_get_rxc_stats
* Returns : void
* Parameters : oak_t *np, u64 **data
* Description : This function copy Rx channel stats
*/
static void oak_ethtool_get_rxc_stats(oak_t *np, u64 **data)
{
u32 i;
**data = 0;
for (i = 0; i < np->num_rx_chan; i++) {
oak_rx_chan_t *rxc = &np->rx_channel[i];
/* Copy rx channel statistics */
memcpy(*data, &rxc->stat, sizeof(oak_driver_rx_stat));
**data = i + 1;
*data += (sizeof(oak_driver_rx_stat) / sizeof(u64));
}
}
/* Name : oak_ethtool_get_txc_stats
* Returns : void
* Parameters : oak_t *np, u64 **data
* Description : This function copy Tx channel stats
*/
static void oak_ethtool_get_txc_stats(oak_t *np, u64 **data)
{
u32 i;
**data = 0;
for (i = 0; i < np->num_tx_chan; i++) {
oak_tx_chan_t *txc = &np->tx_channel[i];
/* Copy tx channel statistics */
memcpy(*data, &txc->stat, sizeof(oak_driver_tx_stat));
**data = i + 1;
*data += (sizeof(oak_driver_tx_stat) / sizeof(u64));
}
}
/* Name : oak_ethtool_get_stall_stats
* Returns : void
* Parameters : oak_t *np
* Description : This function get the tx or rx stall counter statistics of the
* Ethernet interface.
*/
static void oak_ethtool_get_stall_stats(oak_t *np)
{
np->unimac_stat.tx_stall_fifo =
oak_unimac_io_read_32(np, OAK_UNI_STAT_TX_STALL_FIFO);
np->unimac_stat.rx_stall_desc =
oak_unimac_io_read_32(np, OAK_UNI_STAT_RX_STALL_DESC);
np->unimac_stat.rx_stall_fifo =
oak_unimac_io_read_32(np, OAK_UNI_STAT_RX_STALL_FIFO);
}
/* Name : oak_ethtool_get_misc_stats
* Returns : void
* Parameters : oak_t *np
* Description : This function get the tx/rx good, bad, pause, disc descriptor
* statistics of the Ethernet interface.
*/
static void oak_ethtool_get_misc_stats(oak_t *np)
{
np->unimac_stat.tx_pause =
oak_unimac_io_read_32(np, OAK_UNI_STAT_TX_PAUSE);
np->unimac_stat.rx_good_frames =
oak_unimac_io_read_32(np, OAK_UNI_STAT_RX_GOOD_FRAMES);
np->unimac_stat.rx_bad_frames =
oak_unimac_io_read_32(np, OAK_UNI_STAT_RX_BAD_FRAMES);
np->unimac_stat.rx_discard_desc =
oak_unimac_io_read_32(np, OAK_UNI_STAT_RX_DISC_DESC);
}
/* Name : oak_ethtool_get_stats
* Returns : void
* Parameters : struct net_device *dev, struct ethtool_stats *stats,
* u64 *data
* Description : This function reads the statistics of the Ethernet interface.
*/
void oak_ethtool_get_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
oak_t *np = netdev_priv(dev);
/* Get tx/rx channels stall and misc counters statistics */
oak_ethtool_get_stall_stats(np);
oak_ethtool_get_misc_stats(np);
memcpy(data, &np->unimac_stat, sizeof(np->unimac_stat));
data += sizeof(np->unimac_stat) / sizeof(u64);
/* Get rx/tx channel statistics */
oak_ethtool_get_rxc_stats(np, &data);
oak_ethtool_get_txc_stats(np, &data);
}
/* Name : oak_ethtool_get_sscnt
* Returns : int
* Parameters : struct net_device *dev, int stringset
* Description : This function read the String Set Count value of the
* Ethernet interface.
*/
int oak_ethtool_get_sscnt(struct net_device *dev, int stringset)
{
int retval;
oak_t *np = netdev_priv(dev);
/* Get the string set count statistics */
if (stringset == ETH_SS_STATS) {
retval = sizeof(np->unimac_stat) / sizeof(u64);
retval += (np->num_rx_chan *
sizeof(oak_driver_rx_stat) / sizeof(u64));
retval += (np->num_tx_chan *
sizeof(oak_driver_tx_stat) / sizeof(u64));
} else {
retval = -EINVAL;
}
return retval;
}
/* Name : oak_ethtool_get_strings
* Returns : void
* Parameters : struct net_device *dev, u32 stringset, u8 *data
* Description : This function get the Tx and Rx channel strings value of the
* Ethernet interface.
*/
void oak_ethtool_get_strings(struct net_device *dev, u32 stringset,
u8 *data)
{
*data = 0;
if (stringset == ETH_SS_STATS) {
u32 off = 0;
u32 i;
oak_t *np = netdev_priv(dev);
memcpy(&data[off], umac_strings, sizeof(umac_strings));
off += sizeof(umac_strings);
/* Copy statistics data into rx channel structure */
for (i = 0; i < np->num_rx_chan; i++) {
memcpy(&data[off], rx_strings, sizeof(rx_strings));
off += sizeof(rx_strings);
}
/* Copy statistics data into tx channel structure */
for (i = 0; i < np->num_tx_chan; i++) {
memcpy(&data[off], tx_strings, sizeof(tx_strings));
off += sizeof(tx_strings);
}
}
}
/* Name : oak_ethtool_get_cur_speed
* Returns : int
* Parameters : oak_t *np, int pspeed
* Description : This function caps the current PCIe speed for the Oak/Spruce
* switch.
*/
u32 oak_ethtool_cap_cur_speed(oak_t *np, u32 pspeed)
{
enum pcie_link_width wdth;
wdth = oak_net_pcie_get_width_cap(np->pdev);
if (wdth == PCIE_LNK_X1) { /* Oak */
if (pspeed > OAK_MAX_SPEED)
pspeed = OAK_MAX_SPEED;
} else if (wdth == PCIE_LNK_X2) {
if (pspeed > SPRUCE_MAX_SPEED)
pspeed = SPRUCE_MAX_SPEED;
}
return pspeed;
}
/* Name : ethtool_get_link_ksettings
* Returns : int
* Parameters : struct net_device *dev, struct ethtool_link_ksettings *ecmd
* Description : This function get the current port link settings of the
* Ethernet interface.
*/
int oak_ethtool_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *ecmd)
{
oak_t *oak;
u32 supported, advertising;
oak = netdev_priv(dev);
supported = 0;
advertising = 0;
memset(ecmd, 0, sizeof(*ecmd));
if (oak->speed == OAK_SPEED_1000) {
ecmd->base.speed = SPEED_1000;
supported |= SUPPORTED_1000baseT_Full |
SUPPORTED_1000baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_10baseT_Half;
supported |= SUPPORTED_Autoneg;
advertising |= ADVERTISED_1000baseT_Full |
ADVERTISED_1000baseT_Half |
ADVERTISED_100baseT_Full |
ADVERTISED_100baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_10baseT_Half;
} else if (oak->speed == OAK_SPEED_2500) {
ecmd->base.speed = SPEED_2500;
supported = SUPPORTED_10000baseT_Full;
advertising = ADVERTISED_2500baseX_Full;
} else if (oak->speed == OAK_SPEED_5000) {
ecmd->base.speed = SPEED_5000;
supported = SUPPORTED_10000baseT_Full;
advertising = ADVERTISED_10000baseT_Full;
} else {
ecmd->base.speed = SPEED_10000;
supported = SUPPORTED_10000baseT_Full;
supported |= SUPPORTED_TP;
advertising = ADVERTISED_10000baseT_Full;
}
ecmd->base.port = PORT_TP;
ecmd->base.duplex = DUPLEX_FULL;
ecmd->base.autoneg = AUTONEG_ENABLE;
/* This function was added in kernel 4.7 in commit 6d62b4d5fac62 ("net:
* ethtool: export conversion function between u32 and link mode")
*/
ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
supported);
ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
advertising);
return 0;
}
/* Name : oak_ethtool_get_drvinfo
* Returns : void
* Parameters : struct net_device *dev, struct ethtool_drvinfo *drvinfo
* Description : This function copy driver name, version and PCI bus
* information into ethtool driver information structure.
*/
void oak_ethtool_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
oak_t *adapter = netdev_priv(netdev);
/* Copy a C-string into a sized buffer
* Copy driver name, version and bus information
*/
strscpy(drvinfo->driver, oak_driver_name, sizeof(drvinfo->driver));
strscpy(drvinfo->version, oak_driver_version,
sizeof(drvinfo->version));
strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
}

View File

@@ -0,0 +1,78 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_ETHTOOL
#define H_OAK_ETHTOOL
#include <linux/ethtool.h>
/* Include for relation to classifier oak_unimac */
#include "oak_unimac.h"
/* Oak & Spruce max PCIe speed in Gbps */
#define OAK_MAX_SPEED 5
#define SPRUCE_MAX_SPEED 10
#define OAK_SPEED_1000 1
#define OAK_SPEED_2500 2
#define OAK_SPEED_5000 5
/* External variables declaration */
extern u32 debug;
extern const char oak_driver_name[];
extern const char oak_driver_version[];
/* Name : get_stats
* Returns : void
* Parameters: struct net_device * dev, struct ethtool_stats * stats,
* uint64_t * data
*/
void oak_ethtool_get_stats(struct net_device *dev,
struct ethtool_stats *stats, uint64_t *data);
/* Name : get_sscnt
* Returns : int
* Parameters: oak_t * np
*/
int oak_ethtool_get_sscnt(struct net_device *dev, int stringset);
/* Name : get_strings
* Returns : void
* Parameters: struct net_device *dev, u32 stringset, u8 *data
*/
void oak_ethtool_get_strings(struct net_device *dev, u32 stringset,
u8 *data);
/* Name : cap_cur_speed
* Returns : int
* Parameters: oak_t * np, int pspeed
*/
u32 oak_ethtool_cap_cur_speed(oak_t *np, u32 pspeed);
/* Name : get_link_ksettings
* Returns : int
* Parameters: net_device * dev, ethtool_link_ksettings * ecmd
*/
int oak_ethtool_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *ecmd);
/* Name : oak_ethtool_get_drvinfo
* Returns : void
* Parameters : struct net_device *dev, struct ethtool_drvinfo *drvinfo
* Description : This function copy driver name, version and PCI bus
* information into ethtool driver information structure.
*/
void oak_ethtool_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo);
#endif /* #ifndef H_OAK_ETHTOOL */

View File

@@ -0,0 +1,71 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_GICU
#define H_OAK_GICU
/* Include for relation to classifier ldg_t */
#include "ldg_t.h"
typedef struct oak_gicustruct {
#define OAK_GICU_IRQ_BASE 0x00070000U
#define OAK_GICU_IRQ_REG(o) (OAK_GICU_IRQ_BASE + (o))
#define TX_DMA_BIT 0
#define TX_ERR_BIT 1
#define RX_DMA_BIT 2
#define RX_ERR_BIT 3
#define UNIMAC_DMA_BIT 31
#define OAK_GICU_INTR_DBG_CTRL OAK_GICU_IRQ_REG(0x000)
#define OAK_GICU_INTR_FLAG_0 OAK_GICU_IRQ_REG(0x010)
#define OAK_GICU_INTR_FLAG_1 OAK_GICU_IRQ_REG(0x014)
#define OAK_GICU_HOST_SET_MASK_0 OAK_GICU_IRQ_REG(0x020)
#define OAK_GICU_HOST_SET_MASK_1 OAK_GICU_IRQ_REG(0x024)
#define OAK_GICU_HOST_CLR_MASK_0 OAK_GICU_IRQ_REG(0x030)
#define OAK_GICU_HOST_CLR_MASK_1 OAK_GICU_IRQ_REG(0x034)
#define OAK_GICU_HOST_MASK_0 0xFFFFFFFFU
#define OAK_GICU_HOST_MASK_1 0x000000FFU
#define OAK_GICU_HOST_MASK_E 0x003FFC00U
#define OAK_GICU_HOST_UNIMAC_P11_IRQ BIT(8)
#define OAK_GICU_HOST_UNIMAC_P11_RESET BIT(9)
#define OAK_GICU_DBG_INTR_EVNT_0 OAK_GICU_IRQ_REG(0x040)
#define OAK_GICU_DBG_INTR_EVNT_1 OAK_GICU_IRQ_REG(0x044)
#define OAK_GICU_DBG_REG_0_L OAK_GICU_IRQ_REG(0x050)
#define OAK_GICU_DBG_REG_0_H OAK_GICU_IRQ_REG(0x054)
#define OAK_GICU_DBG_REG_1_L OAK_GICU_IRQ_REG(0x060)
#define OAK_GICU_DBG_REG_1_H OAK_GICU_IRQ_REG(0x064)
#define OAK_GICU_DBG_REG_2 OAK_GICU_IRQ_REG(0x070)
#define OAK_GICU_DBG_REG_3 OAK_GICU_IRQ_REG(0x078)
#define OAK_GICU_INTR_GRP_SET_MASK OAK_GICU_IRQ_REG(0x080)
#define OAK_GICU_INTR_GRP_CLR_MASK OAK_GICU_IRQ_REG(0x084)
#define OAK_GICU_INTR_GRP_MASK_ENABLE BIT(31)
#define OAK_GICU_INTR_GRP_MASK_0 OAK_GICU_IRQ_REG(0x090)
#define OAK_GICU_INTR_GRP_MASK_1 OAK_GICU_IRQ_REG(0x094)
#define OAK_GICU_EPU_INTR_MASK_0 OAK_GICU_IRQ_REG(0x0C0)
#define OAK_GICU_EPU_INTR_MASK_1 OAK_GICU_IRQ_REG(0x0C4)
#define OAK_GICU_PIN_INTR_MASK_0 OAK_GICU_IRQ_REG(0x0d0)
#define OAK_GICU_PIN_INTR_MASK_1 OAK_GICU_IRQ_REG(0x0d4)
#define OAK_MAX_INTR_GRP 64
#define OAK_MAX_CHAN_NUM 10
#define OAK_GICU_INTR_GRP(g) OAK_GICU_IRQ_REG(0x100 + 4 * (g))
#define OAK_INTR_MASK_TX_DMA BIT(0)
#define OAK_INTR_MASK_TX_ERR BIT(1)
#define OAK_INTR_MASK_RX_DMA BIT(2)
#define OAK_INTR_MASK_RX_ERR BIT(3)
#define OAK_NUM_IVEC (OAK_MAX_CHAN_NUM * 4 + 1)
struct msix_entry msi_vec[OAK_NUM_IVEC];
u32 num_ldg;
ldg_t ldg[OAK_NUM_IVEC];
} oak_gicu;
#endif /* #ifndef H_OAK_GICU */

View File

@@ -0,0 +1,39 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_IOC_FLOW
#define H_OAK_IOC_FLOW
typedef struct oak_ioc_flowstruct {
#define OAK_IOCTL_RXFLOW (SIOCDEVPRIVATE + 8)
#define OAK_IOCTL_RXFLOW_CLEAR 0
#define OAK_IOCTL_RXFLOW_MGMT BIT(0)
#define OAK_IOCTL_RXFLOW_QPRI BIT(3)
#define OAK_IOCTL_RXFLOW_SPID BIT(7)
#define OAK_IOCTL_RXFLOW_FLOW BIT(12)
#define OAK_IOCTL_RXFLOW_DA BIT(18)
#define OAK_IOCTL_RXFLOW_ET BIT(19)
#define OAK_IOCTL_RXFLOW_FID BIT(20)
#define OAK_IOCTL_RXFLOW_DA_MASK BIT(21)
__u32 cmd;
__u32 idx;
u32 val_lo;
u32 val_hi;
char data[16];
int ena;
int error;
} oak_ioc_flow;
#endif /* #ifndef H_OAK_IOC_FLOW */

View File

@@ -0,0 +1,39 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_IOC_LGEN
#define H_OAK_IOC_LGEN
typedef struct oak_ioc_lgenstruct {
#define OAK_IOCTL_LGEN (SIOCDEVPRIVATE + 3)
#define OAK_IOCTL_LGEN_INIT BIT(0)
#define OAK_IOCTL_LGEN_TX_DATA BIT(1)
#define OAK_IOCTL_LGEN_TX_START BIT(2)
#define OAK_IOCTL_LGEN_TX_STOP BIT(3)
#define OAK_IOCTL_LGEN_RX_START BIT(4)
#define OAK_IOCTL_LGEN_RX_STOP BIT(5)
#define OAK_IOCTL_LGEN_RX_DATA BIT(6)
#define OAK_IOCTL_LGEN_RELEASE BIT(7)
#define OAK_IOCTL_LGEN_TX_RESET BIT(8)
#define OAK_IOCTL_LGEN_RX_RESET BIT(9)
__u32 cmd;
__u32 offs;
__u32 len;
__u32 channel;
__u32 count;
char data[32];
int error;
} oak_ioc_lgen;
#endif /* #ifndef H_OAK_IOC_LGEN */

View File

@@ -0,0 +1,36 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_IOC_REG
#define H_OAK_IOC_REG
typedef struct oak_ioc_regstruct {
#define OAK_IOCTL_REG_ESU_REQ (SIOCDEVPRIVATE + 1)
#define OAK_IOCTL_REG_MAC_REQ (SIOCDEVPRIVATE + 2)
#define OAK_IOCTL_REG_AHSI_REQ (SIOCDEVPRIVATE + 3)
#define OAK_IOCTL_REG_RD 1
#define OAK_IOCTL_REG_WR 2
#define OAK_IOCTL_REG_WS 3
#define OAK_IOCTL_REG_WC 4
#define OAK_IOCTL_REG_OR 5
#define OAK_IOCTL_REG_AND 6
__u32 cmd;
__u32 offs;
__u32 dev_no;
__u32 data;
__u32 device;
int error;
} oak_ioc_reg;
#endif /* #ifndef H_OAK_IOC_REG */

View File

@@ -0,0 +1,28 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_IOC_SET
#define H_OAK_IOC_SET
typedef struct oak_ioc_setstruct {
#define OAK_IOCTL_SET_MAC_RATE_A (SIOCDEVPRIVATE + 5)
#define OAK_IOCTL_SET_MAC_RATE_B (SIOCDEVPRIVATE + 6)
#define OAK_IOCTL_SET_TXR_RATE (SIOCDEVPRIVATE + 7)
__u32 cmd;
__u32 idx;
__u32 data;
int error;
} oak_ioc_set;
#endif /* #ifndef H_OAK_IOC_SET */

View File

@@ -0,0 +1,33 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_IOC_STAT
#define H_OAK_IOC_STAT
typedef struct oak_ioc_statstruct {
#define OAK_IOCTL_STAT (SIOCDEVPRIVATE + 4)
#define OAK_IOCTL_STAT_GET_TXS BIT(0)
#define OAK_IOCTL_STAT_GET_RXS BIT(1)
#define OAK_IOCTL_STAT_GET_TXC BIT(2)
#define OAK_IOCTL_STAT_GET_RXC BIT(3)
#define OAK_IOCTL_STAT_GET_RXB BIT(4)
#define OAK_IOCTL_STAT_GET_LDG BIT(5)
__u32 cmd;
__u32 idx;
__u32 offs;
char data[128];
int error;
} oak_ioc_stat;
#endif /* #ifndef H_OAK_IOC_STAT */

View File

@@ -0,0 +1,498 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "oak_irq.h"
struct oak_tstruct;
/* Name : oak_irq_dis_gicu
* Returns : void
* Parameters : struct oak_tstruct *np, u32 mask_0, u32 mask_1
* Description : This function set GICU mask.
*/
static void oak_irq_dis_gicu(struct oak_tstruct *np, u32 mask_0, u32 mask_1)
{
oak_unimac_io_write_32(np, OAK_GICU_HOST_SET_MASK_0, mask_0);
oak_unimac_io_write_32(np, OAK_GICU_HOST_SET_MASK_1, mask_1);
}
/* Name : oak_irq_ena_gicu
* Returns : void
* Parameters : struct oak_tstruct *np, u32 mask_0, u32 mask_1
* Description : This function clear GICU mask.
*/
static void oak_irq_ena_gicu(struct oak_tstruct *np, u32 mask_0, u32 mask_1)
{
oak_unimac_io_write_32(np, OAK_GICU_HOST_CLR_MASK_0, mask_0);
oak_unimac_io_write_32(np, OAK_GICU_HOST_CLR_MASK_1, mask_1);
}
/* Name : oak_irq_reset_gicu_ldg
* Returns : void
* Parameters : struct oak_tstruct *np
* Description : This function resets Generic Interrupt Controller (gicu)
* Logical devices and device groups (ldg)
*/
static void oak_irq_reset_gicu_ldg(struct oak_tstruct *np)
{
u32 i = 0;
/* Reset GICU logical device group structure members */
while (i < np->gicu.num_ldg) {
np->gicu.ldg[i].device = np;
np->gicu.ldg[i].msi_grp = i;
np->gicu.ldg[i].msi_tx = 0;
np->gicu.ldg[i].msi_rx = 0;
np->gicu.ldg[i].msi_te = 0;
np->gicu.ldg[i].msi_re = 0;
np->gicu.ldg[i].msi_ge = 0;
np->gicu.ldg[i].msiname[0] = '\0';
++i;
}
}
/* Name : oak_irq_set_tx_rx_dma_bit
* Returns : int
* Parameters : struct oak_tstruct *np, int grp
* Description : This function sets the tx and rx bit of a dma channel
*/
static u32 oak_irq_set_tx_rx_dma_bit(struct oak_tstruct *np, u32 grp)
{
u32 i = 0;
u64 val;
val = (1UL << TX_DMA_BIT);
/* Set tx DMA bit for all the tx channels */
while (i < np->num_tx_chan) {
if (np->gicu.num_ldg > 0)
grp = (grp % np->gicu.num_ldg);
np->gicu.ldg[grp].msi_tx |= val;
val <<= 4ULL;
++grp;
++i;
}
i = 0;
val = (1UL << RX_DMA_BIT);
/* Set rx DMA bit for all the rx channels */
while (i < np->num_rx_chan) {
if (np->gicu.num_ldg > 0)
grp = (grp % np->gicu.num_ldg);
np->gicu.ldg[grp].msi_rx |= val;
val <<= 4UL;
++grp;
++i;
}
return grp;
}
/* Name : oak_irq_set_tx_rx_err_bit
* Returns : void
* Parameters : struct oak_tstruct *np, int grp
* Description : This function sets the tx and rx err bit of a dma channel
*/
static void oak_irq_set_tx_rx_err_bit(struct oak_tstruct *np, u32 grp)
{
u32 i = 0;
u64 val;
val = (1UL << TX_ERR_BIT);
/* Set tx error bit for all the tx channels */
while (i < np->num_tx_chan) {
if (np->gicu.num_ldg > 0)
grp = (grp % np->gicu.num_ldg);
np->gicu.ldg[grp].msi_te |= val;
val <<= 4ULL;
++grp;
++i;
}
i = 0;
val = (1UL << RX_ERR_BIT);
/* Set rx error bit for all the rx channels */
while (i < np->num_rx_chan) {
if (np->gicu.num_ldg > 0)
grp = (grp % np->gicu.num_ldg);
np->gicu.ldg[grp].msi_re |= val;
val <<= 4ULL;
++grp;
++i;
}
}
/* Name : oak_irq_callback
* Returns : irqreturn_t
* Parameters : int irq, void *cookie
* Description : This function set GICU IRQ mask and schedule NAPI
*/
static irqreturn_t oak_irq_callback(int irq, void *cookie)
{
ldg_t *ldg = (ldg_t *)cookie;
irqreturn_t rc_4 = IRQ_HANDLED;
oak_unimac_io_write_32(ldg->device, OAK_GICU_INTR_GRP_SET_MASK,
ldg->msi_grp |
(u32)OAK_GICU_INTR_GRP_MASK_ENABLE);
#ifdef DEBUG
{
u32 mask_0;
u32 mask_1;
mask_0 = oak_unimac_io_read_32(ldg->device,
OAK_GICU_INTR_FLAG_0);
mask_1 = oak_unimac_io_read_32(ldg->device,
OAK_GICU_INTR_FLAG_1);
oakdbg(debug, INTR, "IRQ GRP %d [flag0=0x%0x flag1=0x%0x]",
ldg->msi_grp, mask_0, mask_1);
}
#endif
/* Schedule NAPI poll */
napi_schedule(&ldg->napi);
oakdbg(debug, INTR, "============ IRQ GRP END ============");
return rc_4;
}
/* Name : oak_request_irq
* Returns : int
* Parameters : struct oak_tstruct *np, ldg_t *ldg,
* const char *str, u32 idx, int cpu
* Description : This function registers the PCIe irq
*/
static int oak_request_irq(struct oak_tstruct *np, ldg_t *ldg,
const char *str, u32 idx, u32 cpu)
{
int retval = 0;
snprintf(np->gicu.ldg[idx].msiname,
sizeof(np->gicu.ldg[idx].msiname) - 1,
"%s-%s-%d", np->pdev->driver->name, str, idx);
#ifdef OAK_MSIX_LEGACY
/* In older version of the kernel pci_irq_vector() is not supported
*/
retval = request_irq(np->gicu.msi_vec[idx].vector, oak_irq_callback, 0,
np->gicu.ldg[idx].msiname, &np->gicu.ldg[idx]);
if (retval == 0)
retval = irq_set_affinity_hint(np->gicu.msi_vec[idx].vector,
get_cpu_mask(cpu));
#else
/* To get the Linux IRQ numbers passed to request_irq(), Call the
* function pci_irq_vector() because most of the hard work is done for
* the driver in the PCI layer. The driver simply has to request that
* the PCI layer set up the MSI capability for Oak device.
*/
retval = request_irq(pci_irq_vector(np->pdev, idx), oak_irq_callback, 0,
np->gicu.ldg[idx].msiname, &np->gicu.ldg[idx]);
if (retval == 0)
/* Deprecated. Use irq_update_affinity_hint() or
* irq_set_affinity_and_hint() instead irq_set_affinity_hint
* as menioned in include/linux/interrupt.h
*/
retval = irq_set_affinity_hint(pci_irq_vector(np->pdev, idx),
get_cpu_mask(cpu));
#endif
oakdbg(debug, INTR,
"np=%p ivec[%2d]=%2d tx=0x%8llx rx=0x%8llx te=0x%8llx re=0x%8llx ge=%8llx type=%s err=%d",
np, np->gicu.ldg[idx].msi_grp, np->gicu.msi_vec[idx].vector,
ldg->msi_tx, ldg->msi_rx, ldg->msi_te, ldg->msi_re,
ldg->msi_ge, str, retval);
return retval;
}
/* Name : oak_request_single_ivec
* Returns : int
* Parameters : struct oak_tstruct *np, ldg_t *ldg, u64 val, u32 idx,
* int cpu
* Description : This function check and set the ldg msix value, then call the
* request irq oak driver function.
*/
static int oak_irq_request_single_ivec(struct oak_tstruct *np, ldg_t *ldg,
u64 val, u32 idx, u32 cpu)
{
const char *str = "xx";
int retval;
/* Set ldg MSI structure members tx, rx, te, re, ge */
if (val == ldg->msi_tx)
str = "tx";
if (val == ldg->msi_rx)
str = "rx";
if (val == ldg->msi_te)
str = "te";
if (val == ldg->msi_re)
str = "re";
if (val == ldg->msi_ge)
str = "ge";
retval = oak_request_irq(np, ldg, str, idx, cpu);
return retval;
}
/* Name : oak_irq_allocate_ivec
* Returns : int
* Parameters : struct oak_tstruct *np
* Description : This function allocate ivec
*/
static int oak_irq_allocate_ivec(struct oak_tstruct *np)
{
u32 i = 0;
u32 cpu;
int err = 0;
cpu = cpumask_first(cpu_online_mask);
/* In a loop we need to check for all the available online CPU and then
* request and map IRQ line from linux kernel. The function call
* oak_irq_request_single_ivec finally endup calling request_irq and
* irq_set_affinity_hint linux kernel functions.
*/
while ((i < np->gicu.num_ldg) && (err == 0)) {
u64 val;
ldg_t *p = &np->gicu.ldg[i];
val = (p->msi_tx | p->msi_rx | p->msi_te | p->msi_re
| p->msi_ge);
if (val != 0) {
err = oak_irq_request_single_ivec(np, p, val, i, cpu);
cpu = cpumask_next(cpu, cpu_online_mask);
if (cpu >= nr_cpu_ids)
cpu = cpumask_first(cpu_online_mask);
if (err != 0) {
/* Reset ldg MSI structure members */
p->msi_tx = 0;
p->msi_rx = 0;
p->msi_te = 0;
p->msi_re = 0;
p->msi_ge = 0;
}
}
++i;
}
return err;
}
/* Name : oak_irq_request_ivec
* Returns : int
* Parameters : struct oak_tstruct *np
* Description : This function request irq vector
*/
int oak_irq_request_ivec(struct oak_tstruct *np)
{
u32 grp = 0;
u32 num_chan_req;
int err = 0;
oak_irq_dis_gicu(np, OAK_GICU_HOST_MASK_0,
OAK_GICU_HOST_MASK_1 | OAK_GICU_HOST_MASK_E);
if (np->num_rx_chan < np->num_tx_chan)
num_chan_req = np->num_tx_chan;
else
num_chan_req = np->num_rx_chan;
if (num_chan_req <= MAX_NUM_OF_CHANNELS) {
oak_irq_reset_gicu_ldg(np);
grp = oak_irq_set_tx_rx_dma_bit(np, grp);
oak_irq_set_tx_rx_err_bit(np, grp);
} else {
err = -ENOMEM;
}
if (err == 0)
err = oak_irq_allocate_ivec(np);
if (err != 0)
oak_irq_release_ivec(np);
oakdbg(debug, INTR, "np=%p num_ldg=%d num_chan_req=%d err=%d", np,
np->gicu.num_ldg, num_chan_req, err);
return err;
}
/* Name : oak_irq_release_ivec
* Returns : void
* Parameters : struct oak_tstruct *np
* Description : This function reset the MSI interrupt vector structure.
*/
void oak_irq_release_ivec(struct oak_tstruct *np)
{
u32 i = 0;
while (i < np->gicu.num_ldg) {
ldg_t *p = &np->gicu.ldg[i];
if (((p->msi_tx | p->msi_rx | p->msi_te | p->msi_re |
p->msi_ge) != 0)) {
#ifdef OAK_MSIX_LEGACY
/* legacy kernel will not support pci_irq_vector() */
synchronize_irq(np->gicu.msi_vec[i].vector);
irq_set_affinity_hint(np->gicu.msi_vec[i].vector, NULL);
free_irq(np->gicu.msi_vec[i].vector, &np->gicu.ldg[i]);
#else
/* Wait for pending IRQ handlers (on other CPUs) -
* This function waits for any pending IRQ handlers for
* this interrupt to complete before returning
*/
synchronize_irq(pci_irq_vector(np->pdev, i));
irq_set_affinity_hint(pci_irq_vector(np->pdev, i),
NULL);
/* Free an interrupt allocated with request_irq */
free_irq(pci_irq_vector(np->pdev, i), &np->gicu.ldg[i]);
#endif
p->msi_tx = 0;
p->msi_rx = 0;
p->msi_te = 0;
p->msi_re = 0;
p->msi_ge = 0;
}
++i;
}
}
/* Name : oak_irq_enable_gicu_64
* Returns : void
* Parameters : struct oak_tstruct *np, u64 mask
* Description : This function set the 64bit GICU mask.
*/
void oak_irq_enable_gicu_64(struct oak_tstruct *np, u64 mask)
{
u32 val_0 = (u32)(mask & OAK_GICU_HOST_MASK_0);
u32 val_1 = (u32)((mask >> 32) & OAK_GICU_HOST_MASK_1);
oakdbg(debug, INTR, "Enable IRQ mask %016llx", mask);
oak_irq_ena_gicu(np, val_0, val_1);
}
/* Name : oak_irq_ena_general
* Returns : void
* Parameters : struct oak_tstruct *np, u32 enable
* Description : This function set the mask which serve general errors
*/
void oak_irq_ena_general(struct oak_tstruct *np, u32 enable)
{
if (enable != 0)
enable = (u32)(OAK_UNI_INTR_SEVERE_ERRORS);
oak_unimac_io_write_32(np, OAK_UNI_IMSK, enable);
}
/* Name : oak_unimac_enable_tx_rx_channel_irq
* Returns : void
* Parameters : struct oak_tstruct *np
* Description : This function enables tx and rx channel ring irqs
*/
static void oak_unimac_enable_tx_rx_channel_irq(struct oak_tstruct *np)
{
u32 i;
oak_irq_ena_gicu(np, 0, OAK_GICU_HOST_UNIMAC_P11_IRQ);
i = 0;
/* Enable IRQ for all the tx channels */
while (i < np->num_tx_chan) {
oak_unimac_ena_tx_ring_irq(np, i, 1);
++i;
}
i = 0;
/* Enable IRQ for all the rx channels */
while (i < np->num_rx_chan) {
oak_unimac_ena_rx_ring_irq(np, i, 1);
++i;
}
}
/* Name : oak_irq_enable_groups
* Returns : int
* Parameters : struct oak_tstruct *np
* Description : This function enables the group irqs
*/
int oak_irq_enable_groups(struct oak_tstruct *np)
{
u32 grp = 0;
u32 irq;
u64 irq_val;
int retval = 0;
/* Map irq bit and enable the group irqs for all the logical device
* groups in a loop. Then enable the IRQ on both tx/rx channel.
*/
while (grp < np->gicu.num_ldg) {
ldg_t *p = &np->gicu.ldg[grp];
p->irq_mask = (p->msi_tx | p->msi_rx | p->msi_te | p->msi_re |
p->msi_ge);
p->irq_first = 0;
p->irq_count = 0;
irq_val = 1;
irq = 0;
/* The below while loop does following
* -Map IRQ bit for each group
* -Enable the IRQ line
*/
while (irq < OAK_MAX_INTR_GRP) {
if (p->irq_mask & irq_val) {
if (p->irq_count == 0)
p->irq_first = irq;
++p->irq_count;
oak_unimac_io_write_32(np,
OAK_GICU_INTR_GRP(irq),
grp);
oakdbg(debug, INTR,
"Map IRQ bit %02d => group #%02d (1st=%2d of %2d)",
irq, grp, p->irq_first, p->irq_count);
}
irq_val <<= 1ULL;
++irq;
}
oak_irq_enable_gicu_64(np, p->irq_mask);
++grp;
}
oak_unimac_enable_tx_rx_channel_irq(np);
return retval;
}
/* Name : oak_irq_disable_groups
* Returns : void
* Parameters : struct oak_tstruct *np
* Description : This function disbles the group irq.
*/
void oak_irq_disable_groups(struct oak_tstruct *np)
{
u32 i;
oak_irq_dis_gicu(np, OAK_GICU_HOST_MASK_0, OAK_GICU_HOST_MASK_1);
i = 0;
/* Disable IRQ for all rx channels */
while (i < np->num_rx_chan) {
oak_unimac_ena_rx_ring_irq(np, i, 0);
++i;
}
i = 0;
/* Disable IRQ for all tx channels */
while (i < np->num_tx_chan) {
oak_unimac_ena_tx_ring_irq(np, i, 0);
++i;
}
}

View File

@@ -0,0 +1,66 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_IRQ
#define H_OAK_IRQ
/* Include for relation to classifier oak_unimac */
#include "oak_unimac.h"
extern u32 debug;
struct oak_tstruct;
/* Name : oak_irq_request_ivec
* Returns : int
* Parameters : struct oak_tstruct * np
* Description : This function request irq vector
*/
int oak_irq_request_ivec(struct oak_tstruct *np);
/* Name : oak_irq_release_ivec
* Returns : void
* Parameters : struct oak_tstruct *np
* Description : This function reset the MSI interrupt vector structure.
*/
void oak_irq_release_ivec(struct oak_tstruct *np);
/* Name : oak_irq_enable_gicu_64
* Returns : void
* Parameters : struct oak_tstruct *np, u64 mask
* Description : This function set the 64bit GICU mask.
*/
void oak_irq_enable_gicu_64(struct oak_tstruct *np, u64 mask);
/* Name : oak_irq_ena_general
* Returns : void
* Parameters : struct oak_tstruct *np, u32 enable
* Description : This function set the mask which serve general errors
*/
void oak_irq_ena_general(struct oak_tstruct *np, u32 enable);
/* Name : enable_groups
* Returns : int
* Parameters: struct oak_tstruct *np
* Description : This function enable the group irq
*/
int oak_irq_enable_groups(struct oak_tstruct *np);
/* Name : oak_irq_disable_groups
* Returns : void
* Parameters : struct oak_tstruct *np
* Description : This function disbles the group irq.
*/
void oak_irq_disable_groups(struct oak_tstruct *np);
#endif /* #ifndef H_OAK_IRQ */

View File

@@ -0,0 +1,49 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
int oak_init_module(void);
void oak_exit_module(void);
module_init(oak_init_module);
module_exit(oak_exit_module);
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "OAK debug level");
/* RX and TX ring sizes are given as a power of 2 e.g:
* x=[0-7] :: ring-size=2^(4+x), where x is the specified load parameter.
*/
module_param(rxs, int, 0);
MODULE_PARM_DESC(rxs, "Receive ring size");
module_param(txs, int, 0);
MODULE_PARM_DESC(txs, "Transmit ring size");
module_param(chan, int, 0);
MODULE_PARM_DESC(chan, "Number of (tx/rx) channels");
module_param(rto, int, 0);
MODULE_PARM_DESC(rto, "Receive descriptor timeout in usec");
module_param(mhdr, int, 0);
MODULE_PARM_DESC(mhdr, "Marvell header generation");
module_param(port_speed, int, 0);
MODULE_PARM_DESC(mhdr, "Unimac 11 Port speed");
module_param(napi_wt, int, 0);
MODULE_PARM_DESC(napi_wt, "NAPI Poll weight/budget");
MODULE_LICENSE("GPL");

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,194 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_NET
#define H_OAK_NET
/* Include for relation to classifier oak_unimac */
#include "oak_unimac.h"
#ifdef CMDTOOL
/* Include for relation to classifier oak_ctl */
#include "oak_ctl.h"
#endif
/* Include for relation to classifier linux/ip.h */
#include "linux/ip.h"
/* Include for relation to classifier linux/ipv6.h */
#include "linux/ipv6.h"
/* Include for relation to classifier linux/if_vlan.h */
#include "linux/if_vlan.h"
#define OAK_ONEBYTE 1
extern u32 rxs;
extern u32 txs;
extern int chan;
extern int rto;
extern int mhdr;
extern u32 port_speed;
extern int napi_wt;
/* Name : esu_set_mtu
* Returns : int
* Parameters: struct net_device * net_dev = net_dev, int new_mtu = new_mtu
* Description: This function set the MTU size of the Ethernet interface.
*/
int oak_net_esu_set_mtu(struct net_device *net_dev, int new_mtu);
/* Name : oak_set_mtu_config
* Returns : void
* Parameters: struct net_device *netdev
* Description: This function sets the min and max MTU size in the linux netdev.
*/
void oak_set_mtu_config(struct net_device *netdev);
/* Name : esu_ena_speed
* Returns : void
* Parameters: int gbit = gbit, oak_t * np = np
*/
void oak_net_esu_ena_speed(u32 gbit, oak_t *np);
/* Name : oak_net_open
* Returns : int
* Parameters : struct net_device * net_dev
* Description : This function initialize the interface
*/
int oak_net_open(struct net_device *net_dev);
/* Name : oak_net_close
* Returns : int
* Parameters : struct net_device *net_dev
* Description : This function close the interface
*/
int oak_net_close(struct net_device *net_dev);
/* Name : oak_net_ioctl
* Returns : int
* Parameters : struct net_device *net_dev, struct ifreq *ifr, int cmd
* Description : This function handles IOCTL request
*/
int oak_net_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd);
/* Name : add_napi
* Returns : void
* Parameters: struct net_device * netdev
*/
void oak_net_add_napi(struct net_device *netdev);
/* Name : del_napi
* Returns : void
* Parameters: struct net_device * netdev
*/
void oak_net_del_napi(struct net_device *netdev);
/* Name : set_mac_addr
* Returns : int
* Parameters: struct net_device * dev = dev, void * p_addr = addr
*/
int oak_net_set_mac_addr(struct net_device *dev, void *p_addr);
/* Name : alloc_page
* Returns : struct page *
* Parameters : oak_t *np, dma_addr_t * dma, nt direction
* Description : This function allocate page
*/
struct page *oak_net_alloc_page(oak_t *np, dma_addr_t *dma,
enum dma_data_direction dir);
/* Name : oak_net_select_queue
* Returns : u16
* Parameters : struct net_device *dev, struct sk_buff *skb,
* struct net_device *sb_dev
* Description : This function pre-seed the SKB by recording the RX queue
*/
u16 oak_net_select_queue(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev);
/* Name : xmit_frame
* Returns : int
* Parameters: struct sk_buff * skb, struct net_device * net_dev
*/
netdev_tx_t oak_net_xmit_frame(struct sk_buff *skb, struct net_device *net_dev);
/* Name : start_all
* Returns : int
* Parameters: oak_t * np = np
*/
int oak_net_start_all(oak_t *np);
/* Name : stop_all
* Returns : void
* Parameters: oak_t * np = np
*/
void oak_net_stop_all(oak_t *np);
/* Name : tbr_free
* Returns : void
* Parameters: oak_tx_chan_t * txp = txp
*/
void oak_net_tbr_free(oak_tx_chan_t *txp);
/* Name : oak_net_rbr_free
* Returns : void
* Parameters : oak_rx_chan_t *rxp = rxp
* Description : This function free the receive buffer ring
*/
void oak_net_rbr_free(oak_rx_chan_t *rxp);
/* Name : add_txd_length
* Returns : void
* Parameters: oak_tx_chan_t * txc, u16 len
*/
void oak_net_add_txd_length(oak_tx_chan_t *txc, u16 len);
/* Name : oak_net_set_txd_first
* Returns : void
* Parameters : oak_tx_chan_t *txc, u16 len, u32 g3, u32 g4,
* dma_addr_t map, u32 sz, int flags
* Description : This function set the transmit descriptor
*/
void oak_net_set_txd_first(oak_tx_chan_t *txc, u16 len, u32 g3,
u32 g4, dma_addr_t map, u32 sz, u32 flags);
/* Name : set_txd_page
* Returns : void
* Parameters: oak_tx_chan_t * txc, u16 len, dma_addr_t map, u32
* sz, int flags
*/
void oak_net_set_txd_page(oak_tx_chan_t *txc, u16 len, dma_addr_t map,
u32 sz, u32 flags);
/* Name : set_txd_last
* Returns : void
* Parameters: oak_tx_chan_t * txc, struct sk_buff * skb, struct page * page
*/
void oak_net_set_txd_last(oak_tx_chan_t *txc, struct sk_buff *skb,
struct page *page);
/* Name : oak_net_pcie_get_width_cap
* Returns : enum pcie_link_width
* Parameters: struct pci_dev *
*/
enum pcie_link_width oak_net_pcie_get_width_cap(struct pci_dev *dev);
/* Name : oak_net_skb_tx_protocol_type
* Returns : int
* Parameters : struct sk_buff *skb
* Description : This function returns the transmit frames protocol type for
* deciding the checksum offload configuration.
*/
int oak_net_skb_tx_protocol_type(struct sk_buff *skb);
#endif /* #ifndef H_OAK_NET */

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,713 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_UNIMAC
#define H_OAK_UNIMAC
/* Include for relation to classifier linux/etherdevice */
#include "linux/etherdevice.h"
/* Include for relation to classifier linux/pci */
#include "linux/pci.h"
/* Include for relation to classifier oak_gicu */
#include "oak_gicu.h"
/* Include for relation to classifier oak_channel_stat */
#include "oak_channel_stat.h"
/* Include for relation to classifier oak_unimac_stat */
#include "oak_unimac_stat.h"
/* Include for relation to classifier oak_unimac_desc */
#include "oak_unimac_desc.h"
/* Include for relation to classifier oak_ioc_reg */
#include "oak_ioc_reg.h"
/* Include for relation to classifier oak_ioc_lgen */
#include "oak_ioc_lgen.h"
/* Include for relation to classifier oak_ioc_stat */
#include "oak_ioc_stat.h"
/* Include for relation to classifier oak_ioc_set */
#include "oak_ioc_set.h"
/* Include for relation to classifier oak_ioc_flow */
#include "oak_ioc_flow.h"
/* Include for relation to classifier oak_irq */
#include "oak_irq.h"
#define OAK_REVISION_B0 1
#define OAK_PCIE_REGOFF_UNIMAC 0x00050000U
#define OAK_UNI_DMA_RING_BASE (OAK_PCIE_REGOFF_UNIMAC + 0x00000000)
#define OAK_UNI_DMA_TXCH_BASE (OAK_PCIE_REGOFF_UNIMAC + 0x00010000)
#define OAK_UNI_DMA_RXCH_BASE (OAK_PCIE_REGOFF_UNIMAC + 0x00011000)
#define OAK_UNI_DMA_GLOB_BASE (OAK_PCIE_REGOFF_UNIMAC + 0x00012000)
#define OAK_UNI_GLOBAL(o) (OAK_UNI_DMA_GLOB_BASE + (o))
#define OAK_UNI_DMA_TXCH_OFFS(o) (OAK_UNI_DMA_TXCH_BASE + (o))
#define OAK_UNI_DMA_RXCH_OFFS(o) (OAK_UNI_DMA_RXCH_BASE + (o))
#define OAK_UNI_DMA_RING_TX(r, o) (OAK_UNI_DMA_RING_BASE + \
0x0000 + 0x1000 * (r) + (o))
#define OAK_UNI_DMA_RING_RX(r, o) (OAK_UNI_DMA_RING_BASE + \
0x0800 + 0x1000 * (r) + (o))
#define OAK_UNI_CFG_0 OAK_UNI_GLOBAL(0x00)
#define OAK_UNI_CFG_1 OAK_UNI_GLOBAL(0x04)
#define OAK_UNI_CTRL OAK_UNI_GLOBAL(0x10)
#define OAK_UNI_STAT OAK_UNI_GLOBAL(0x14)
#define OAK_UNI_INTR OAK_UNI_GLOBAL(0x18)
#define OAK_UNI_IMSK OAK_UNI_GLOBAL(0x1C)
#define OAK_UNI_RXEN OAK_UNI_GLOBAL(0x40)
#define OAK_UNI_TXEN OAK_UNI_GLOBAL(0x44)
#define OAK_UNI_STAT_TX_WD_HISTORY BIT(7)
#define OAK_UNI_STAT_TX_WD_EVENT BIT(6)
#define OAK_UNI_STAT_RX_WD_HISTORY BIT(5)
#define OAK_UNI_STAT_RX_WD_EVENT BIT(4)
#define OAK_UNI_STAT_RX_FIFO_EMPTY BIT(3)
#define OAK_UNI_STAT_RX_FIFO_FULL BIT(2)
#define OAK_UNI_STAT_TX_FIFO_EMPTY BIT(1)
#define OAK_UNI_STAT_TX_FIFO_FULL BIT(0)
#define OAK_UNI_INTR_RX_STAT_MEM_UCE BIT(27)
#define OAK_UNI_INTR_RX_DESC_MEM_UCE BIT(26)
#define OAK_UNI_INTR_TX_DESC_MEM_UCE BIT(25)
#define OAK_UNI_INTR_AXI_WR_MEM_UCE BIT(24)
#define OAK_UNI_INTR_TX_DATA_MEM_UCE BIT(23)
#define OAK_UNI_INTR_TX_FIFO_MEM_UCS BIT(22)
#define OAK_UNI_INTR_RX_FIFO_MEM_UCS BIT(21)
#define OAK_UNI_INTR_HCS_MEM_UCE BIT(20)
#define OAK_UNI_INTR_RX_STAT_MEM_CE BIT(19)
#define OAK_UNI_INTR_RX_DESC_MEM_CE BIT(18)
#define OAK_UNI_INTR_TX_DESC_MEM_CE BIT(17)
#define OAK_UNI_INTR_AXI_WR_MEM_CE BIT(16)
#define OAK_UNI_INTR_TX_DATA_MEM_CE BIT(15)
#define OAK_UNI_INTR_TX_FIFO_MEM_CE BIT(14)
#define OAK_UNI_INTR_RX_FIFO_MEM_CE BIT(13)
#define OAK_UNI_INTR_HCS_MEM_CHECK BIT(12)
#define OAK_UNI_INTR_TX_MTU_ERR BIT(11)
#define OAK_UNI_INTR_RX_BERR_WR BIT(10)
#define OAK_UNI_INTR_RX_BERR_RD BIT(9)
#define OAK_UNI_INTR_TX_BERR_WR BIT(8)
#define OAK_UNI_INTR_TX_BERR_RD BIT(7)
#define OAK_UNI_INTR_BERR_HIC_A BIT(6)
#define OAK_UNI_INTR_BERR_HIC_B BIT(5)
#define OAK_UNI_INTR_COUNT_WRAP BIT(4)
#define OAK_UNI_INTR_RX_WATCHDOG BIT(3)
#define OAK_UNI_INTR_TX_WATCHDOG BIT(2)
#define OAK_UNI_INTR_RX_STALL_FIFO BIT(1)
#define OAK_UNI_INTR_TX_STALL_FIFO BIT(0)
#define OAK_UNI_INTR_SEVERE_ERRORS (\
OAK_UNI_INTR_RX_STAT_MEM_UCE | \
OAK_UNI_INTR_RX_DESC_MEM_UCE | \
OAK_UNI_INTR_TX_DESC_MEM_UCE | \
OAK_UNI_INTR_AXI_WR_MEM_UCE | \
OAK_UNI_INTR_TX_DATA_MEM_UCE | \
OAK_UNI_INTR_TX_FIFO_MEM_UCS | \
OAK_UNI_INTR_RX_FIFO_MEM_UCS | \
OAK_UNI_INTR_HCS_MEM_UCE | \
OAK_UNI_INTR_RX_STAT_MEM_CE | \
OAK_UNI_INTR_RX_DESC_MEM_CE | \
OAK_UNI_INTR_TX_DESC_MEM_CE | \
OAK_UNI_INTR_AXI_WR_MEM_CE | \
OAK_UNI_INTR_TX_DATA_MEM_CE | \
OAK_UNI_INTR_TX_FIFO_MEM_CE | \
OAK_UNI_INTR_RX_FIFO_MEM_CE | \
OAK_UNI_INTR_HCS_MEM_CHECK | \
OAK_UNI_INTR_TX_MTU_ERR | \
OAK_UNI_INTR_RX_BERR_WR | \
OAK_UNI_INTR_RX_BERR_RD | \
OAK_UNI_INTR_TX_BERR_WR | \
OAK_UNI_INTR_TX_BERR_RD \
)
#define OAK_UNI_INTR_NORMAL_ERRORS (OAK_UNI_INTR_BERR_HIC_A | \
OAK_UNI_INTR_BERR_HIC_B | \
OAK_UNI_INTR_COUNT_WRAP | \
OAK_UNI_INTR_RX_WATCHDOG | \
OAK_UNI_INTR_TX_WATCHDOG | \
OAK_UNI_INTR_RX_STALL_FIFO | \
OAK_UNI_INTR_TX_STALL_FIFO)
#define OAK_UNI_TXRATE_B OAK_UNI_GLOBAL(0x80)
#define OAK_UNI_TXRATE_A OAK_UNI_GLOBAL(0x84)
#define OAK_UNI_STAT_RX_GOOD_FRAMES OAK_UNI_GLOBAL(0x100)
#define OAK_UNI_STAT_RX_BAD_FRAMES OAK_UNI_GLOBAL(0x104)
#define OAK_UNI_STAT_TX_PAUSE OAK_UNI_GLOBAL(0x108)
#define OAK_UNI_STAT_TX_STALL_FIFO OAK_UNI_GLOBAL(0x10C)
#define OAK_UNI_STAT_RX_STALL_DESC OAK_UNI_GLOBAL(0x110)
#define OAK_UNI_STAT_RX_STALL_FIFO OAK_UNI_GLOBAL(0x114)
#define OAK_UNI_STAT_RX_DISC_DESC OAK_UNI_GLOBAL(0x118)
#define OAK_UNI_PTP_HW_TIME OAK_UNI_GLOBAL(0x17C)
#define OAK_UNI_ECC_ERR_CFG OAK_UNI_GLOBAL(0x1E4)
#define OAK_UNI_ECC_ERR_STAT_0 OAK_UNI_GLOBAL(0x1E8)
#define OAK_UNI_ECC_ERR_STAT_1 OAK_UNI_GLOBAL(0x1EC)
#define OAK_UNI_ECC_ERR_CNT_0 OAK_UNI_GLOBAL(0x1F0)
#define OAK_UNI_ECC_ERR_CNT_1 OAK_UNI_GLOBAL(0x1F4)
#define OAK_UNI_DMA_TX_CH_CFG OAK_UNI_DMA_TXCH_OFFS(0x00)
#define OAK_UNI_DMA_TX_CH_ARBIT_B0_LO OAK_UNI_DMA_TXCH_OFFS(0x04)
#define OAK_UNI_DMA_TX_CH_ARBIT_B0_HI OAK_UNI_DMA_TXCH_OFFS(0x08)
#define OAK_DMA_TX_CH_SCHED_B0_LO OAK_UNI_DMA_TXCH_OFFS(0x0C)
#define OAK_UNI_DMA_TX_CH_SCHED_B0_HI OAK_UNI_DMA_TXCH_OFFS(0x10)
#define OAK_DMA_TX_CH_SCHED_LO OAK_UNI_DMA_TXCH_OFFS(0x04)
#define OAK_UNI_DMA_TX_CH_SCHED_HI OAK_UNI_DMA_TXCH_OFFS(0x08)
#define OAK_UNI_DMA_RX_CH_CFG OAK_UNI_DMA_RXCH_OFFS(0x00)
#define OAK_UNI_DMA_RX_CH_ARBIT_B0_LO OAK_UNI_DMA_RXCH_OFFS(0x04)
#define OAK_UNI_DMA_RX_CH_ARBIT_B0_HI OAK_UNI_DMA_RXCH_OFFS(0x08)
#define OAK_DMA_RX_CH_SCHED_LO OAK_UNI_DMA_RXCH_OFFS(0x04)
#define OAK_UNI_DMA_RX_CH_SCHED_HI OAK_UNI_DMA_RXCH_OFFS(0x08)
#define OAK_UNI_TX_RING_CFG(r) OAK_UNI_DMA_RING_TX(r, 0x00)
#define OAK_UNI_TX_RING_PREF_THR(r) OAK_UNI_DMA_RING_TX(r, 0x04)
#define OAK_UNI_TX_RING_MBOX_THR(r) OAK_UNI_DMA_RING_TX(r, 0x08)
#define OAK_UNI_TX_RING_DMA_PTR(r) OAK_UNI_DMA_RING_TX(r, 0x0C)
#define OAK_UNI_TX_RING_CPU_PTR(r) OAK_UNI_DMA_RING_TX(r, 0x10)
#define OAK_UNI_TX_RING_EN(r) OAK_UNI_DMA_RING_TX(r, 0x14)
#define OAK_UNI_TX_RING_INT_CAUSE(r) OAK_UNI_DMA_RING_TX(r, 0x18)
#define OAK_UNI_TX_RING_INT_MASK(r) OAK_UNI_DMA_RING_TX(r, 0x1C)
#define OAK_UNI_TX_RING_DBASE_LO(r) OAK_UNI_DMA_RING_TX(r, 0x20)
#define OAK_UNI_TX_RING_DBASE_HI(r) OAK_UNI_DMA_RING_TX(r, 0x24)
#define OAK_UNI_TX_RING_MBASE_LO(r) OAK_UNI_DMA_RING_TX(r, 0x28)
#define OAK_UNI_TX_RING_MBASE_HI(r) OAK_UNI_DMA_RING_TX(r, 0x2C)
#define OAK_UNI_TX_RING_TIMEOUT(r) OAK_UNI_DMA_RING_TX(r, 0x30)
#define OAK_UNI_TX_RING_RATECTRL(r) OAK_UNI_DMA_RING_TX(r, 0x34)
#define OAK_UNI_TX_RING_MAXDTIME(r) OAK_UNI_DMA_RING_TX(r, 0x38)
#define OAK_UNI_RING_ENABLE_REQ BIT(0)
#define OAK_UNI_RING_ENABLE_DONE BIT(1)
#define OAK_UNI_RX_RING_CFG(r) OAK_UNI_DMA_RING_RX(r, 0x00)
#define OAK_UNI_RX_RING_PREF_THR(r) OAK_UNI_DMA_RING_RX(r, 0x04)
#define OAK_UNI_RX_RING_MBOX_THR(r) OAK_UNI_DMA_RING_RX(r, 0x08)
#define OAK_UNI_RX_RING_DMA_PTR(r) OAK_UNI_DMA_RING_RX(r, 0x0C)
#define OAK_UNI_RX_RING_CPU_PTR(r) OAK_UNI_DMA_RING_RX(r, 0x10)
#define OAK_UNI_RX_RING_WATERMARK(r) OAK_UNI_DMA_RING_RX(r, 0x14)
#define OAK_UNI_RX_RING_EN(r) OAK_UNI_DMA_RING_RX(r, 0x18)
#define OAK_UNI_RX_RING_INT_CAUSE(r) OAK_UNI_DMA_RING_RX(r, 0x1C)
#define OAK_UNI_RX_RING_INT_MASK(r) OAK_UNI_DMA_RING_RX(r, 0x20)
#define OAK_UNI_RX_RING_DBASE_LO(r) OAK_UNI_DMA_RING_RX(r, 0x24)
#define OAK_UNI_RX_RING_DBASE_HI(r) OAK_UNI_DMA_RING_RX(r, 0x28)
#define OAK_RING_TOUT_USEC(us) (OAK_CLOCK_FREQ_MHZ * 1 * (us))
#define OAK_UNI_RX_RING_SBASE_LO(r) OAK_UNI_DMA_RING_RX(r, 0x2C)
#define OAK_UNI_RX_RING_SBASE_HI(r) OAK_UNI_DMA_RING_RX(r, 0x30)
#define OAK_UNI_RX_RING_MBASE_LO(r) OAK_UNI_DMA_RING_RX(r, 0x34)
#define OAK_UNI_RX_RING_MBASE_HI(r) OAK_UNI_DMA_RING_RX(r, 0x38)
#define OAK_UNI_RX_RING_TIMEOUT(r) OAK_UNI_DMA_RING_RX(r, 0x3C)
#define OAK_UNI_RX_RING_DADDR_HI(r) OAK_UNI_DMA_RING_RX(r, 0x40)
#define OAK_UNI_RX_RING_DADDR_LO(r) OAK_UNI_DMA_RING_RX(r, 0x44)
#define OAK_UNI_RX_RING_ETYPE(r) OAK_UNI_DMA_RING_RX(r, 0x48)
#define OAK_UNI_RX_RING_MAP(r) OAK_UNI_DMA_RING_RX(r, 0x4C)
#define OAK_CLOCK_FREQ_MHZ (250U)
#define OAK_RING_TOUT_MSEC(ms) (OAK_CLOCK_FREQ_MHZ * 1000 * (ms))
#define OAK_MIN_TX_RATE_CLASS_A 0
#define OAK_MIN_TX_RATE_CLASS_B 1
#define OAK_MIN_TX_RATE_IN_KBPS 64
#define OAK_MAX_TX_RATE_IN_KBPS 4194240U
#define OAK_DEF_TX_HI_CREDIT_BYTES 1536U
#define OAK_MAX_TX_HI_CREDIT_BYTES 0x3fffU
#define OAK_UNI_RX_RING_DADDR_MASK_HI(r) OAK_UNI_DMA_RING_RX(r, 0x50)
#define OAK_UNI_RX_RING_DADDR_MASK_LO(r) OAK_UNI_DMA_RING_RX(r, 0x54)
/* Define DMA check numbers */
#define OAK_DMA_15 15U
#define OAK_DMA_7 7U
#define OAK_BUFFER_SIZE_16 16
#define OAK_BUFFER_SIZE_2048 2048
typedef struct oak_mbox_tstruct {
u32 dma_ptr_rel;
u32 intr_cause;
} oak_mbox_t;
typedef struct oak_rxa_tstruct {
struct page *page_virt;
dma_addr_t page_phys;
u32 page_offs;
} oak_rxa_t;
typedef struct oak_rx_chan_tstruct {
#define OAK_RX_BUFFER_SIZE 2048
#define OAK_RX_BUFFER_PER_PAGE (PAGE_SIZE / OAK_RX_BUFFER_SIZE)
#define OAK_RX_SKB_ALLOC_SIZE (128 + NET_IP_ALIGN)
#define OAK_RX_LGEN_RX_MODE BIT(0)
#define OAK_RX_REFILL_REQ BIT(1)
struct oak_tstruct *oak;
u32 enabled;
u32 flags;
u32 rbr_count;
u32 rbr_size;
u32 rsr_size;
u32 mbox_size;
atomic_t rbr_pend;
u32 rbr_widx;
u32 rbr_ridx;
u32 rbr_len;
u32 rbr_bsize; /* Rx buffer size */
u32 rbr_bpage; /* Number of descriptors per page */
dma_addr_t rbr_dma;
dma_addr_t rsr_dma;
dma_addr_t mbox_dma;
oak_rxa_t *rba;
oak_rxd_t *rbr;
oak_rxs_t *rsr;
oak_mbox_t *mbox;
oak_driver_rx_stat stat;
struct sk_buff *skb;
} oak_rx_chan_t;
typedef struct oak_txi_tstruct {
#define TX_BUFF_INFO_NONE 0x00000000U
#define TX_BUFF_INFO_ADR_MAPS 0x00000001U
#define TX_BUFF_INFO_ADR_MAPP 0x00000002U
#define TX_BUFF_INFO_EOP 0x00000004U
struct sk_buff *skb;
struct page *page;
dma_addr_t mapping;
u32 mapsize;
u32 flags;
} oak_txi_t;
typedef struct oak_tx_chan_tstruct {
#define OAK_RX_LGEN_TX_MODE BIT(0)
struct oak_tstruct *oak;
u32 enabled;
u32 flags;
u32 tbr_count;
u32 tbr_compl;
u32 tbr_size;
atomic_t tbr_pend;
u32 tbr_ridx;
u32 tbr_widx;
u32 tbr_len;
dma_addr_t tbr_dma;
oak_txd_t *tbr;
oak_txi_t *tbi;
u32 mbox_size;
dma_addr_t mbox_dma;
oak_mbox_t *mbox;
oak_driver_tx_stat stat;
/* lock */
spinlock_t lock;
} oak_tx_chan_t;
typedef struct oak_tstruct {
#define MAX_RBR_RING_ENTRIES 3U
#define MAX_TBR_RING_ENTRIES 3U
#define XBR_RING_SIZE(s) (1U << ((s) + 4U))
#define MAX_RBR_RING_SIZE XBR_RING_SIZE(MAX_RBR_RING_ENTRIES)
#define MAX_TBR_RING_SIZE XBR_RING_SIZE(MAX_TBR_RING_ENTRIES)
#define RX_DESC_PREFETCH_TH 5
#define RX_MBOX_WRITE_TH 5
#define TX_DESC_PREFETCH_TH 5
#define TX_MBOX_WRITE_TH 5
#define OAK_MBOX_RX_RES_LOW BIT(2)
#define OAK_MBOX_RX_COMP BIT(0)
#define OAK_MBOX_TX_ERR_ABORT BIT(4)
#define OAK_MBOX_TX_ERR_HCRED BIT(3)
#define OAK_MBOX_TX_LATE_TS BIT(2)
#define OAK_MBOX_TX_COMP BIT(0)
#define OAK_IVEC_UVEC1 BIT(8)
#define NEXT_IDX(i, sz) (((i) + 1) % (sz))
#define MAX_NUM_OF_CHANNELS 10
#define nw32(np, reg, val) writel((val), (np)->um_base + (reg))
#define MIN_NUM_OF_CHANNELS 1
#define nr32(np, reg) readl((np)->um_base + (reg))
#define sr32(np, reg) readl((np)->um_base + (reg))
#define sw32(np, reg, val) writel((val), (np)->um_base + (reg))
#define oakdbg(debug_var, TYPE, f, a...) \
do { \
if (((debug_var) & NETIF_MSG_##TYPE) != 0) { \
pr_info("%s:" f, __func__, ##a); \
} \
} while (0)
int level;
u32 pci_class_revision;
/* lock */
spinlock_t lock;
struct net_device *netdev;
struct device *device;
struct pci_dev *pdev;
void __iomem *um_base;
void __iomem *sw_base;
u32 page_order;
u32 page_size;
oak_gicu gicu;
u32 num_rx_chan;
oak_rx_chan_t rx_channel[MAX_NUM_OF_CHANNELS];
u32 num_tx_chan;
oak_tx_chan_t tx_channel[MAX_NUM_OF_CHANNELS];
oak_unimac_stat unimac_stat;
u16 rrs;
u32 speed;
char mac_address[ETH_ALEN];
} oak_t;
int oak_net_rbr_refill(oak_t *np, u32 ring);
/* Name : oak_unimac_disable_and_get_tx_irq_reason
* Returns : u32
* Parameters : oak_t *np, u32 ring, u32 *dma_ptr
* Description : This function check the reason for Tx IRQ
*/
u32 oak_unimac_disable_and_get_tx_irq_reason(oak_t *np, u32 ring,
u32 *dma_ptr);
/* Name : oak_unimac_alloc_channels
* Returns : int
* Parameters : oak_t *np, int rxs, int txs, int chan, int rto
* Description : This function allocate tx and rx channels
*/
int oak_unimac_alloc_channels(oak_t *np, u32 rxs, u32 txs, int chan, int rto);
/* Name : oak_unimac_free_channels
* Returns : void
* Parameters : oak_t *np
* Description : This function free the tx and rx channels
*/
void oak_unimac_free_channels(oak_t *np);
/* Name : oak_unimac_reset
* Returns : int
* Parameters : oak_t *np
* Description : This function reset unimac statistics
*/
int oak_unimac_reset(oak_t *np);
/* Name : oak_unimac_reset_statistics
* Returns : void
* Parameters : oak_t *np
* Description : This function reset the statistics counter
*/
void oak_unimac_reset_statistics(oak_t *np);
/* Name : oak_unimac_crt_bit_mask
* Returns : u32
* Parameters : u32 off, u32 len, u32 val, u32 bit_mask
* Description : This function calculate the crt bit mask
*/
u32 oak_unimac_crt_bit_mask(u32 off, u32 len, u32 val,
u32 bit_mask);
/* Name : oak_unimac_io_read_32
* Returns : u32
* Parameters : oak_t * np, u32 addr
* Description : This function read from register.
*/
u32 oak_unimac_io_read_32(oak_t *np, u32 addr);
/* Name : oak_unimac_io_write_32
* Returns : void
* Parameters : oak_t *np, u32 addr, u32 val
* Description : This function write value to register.
*/
void oak_unimac_io_write_32(oak_t *np, u32 addr, u32 val);
/* Name : oak_unimac_set_bit_num
* Returns : void
* Parameters : oak_t *np, u32 reg, u32 bit_num, int enable
* Description : This function set a bit number
*/
void oak_unimac_set_bit_num(oak_t *np, u32 reg, u32 bit_num,
u32 enable);
/* Name : oak_unimac_set_rx_none
* Returns : void
* Parameters : oak_t *np, u32 ring
* Description : This function clear the rx ring
*/
void oak_unimac_set_rx_none(oak_t *np, u32 ring);
/* Name : oak_unimac_set_rx_8021Q_et
* Returns : void
* Parameters : oak_t *np, u32 ring, u16 etype, u16 pcp_vid,
* int enable
* Description : This function write ethtype and calls set bit number for
* Rx ring
*/
void oak_unimac_set_rx_8021Q_et(oak_t *np, u32 ring, u16 etype,
u16 pcp_vid, u32 enable);
/* Name : oak_unimac_set_rx_8021Q_fid
* Returns : void
* Parameters : oak_t *np, u32 ring, u32 fid, int enable
* Description : This function set Rx ring Filtering database identifier (FID)
*/
void oak_unimac_set_rx_8021Q_fid(oak_t *np, u32 ring, u32 fid,
u32 enable);
/* Name : oak_unimac_set_rx_8021Q_flow
* Returns : void
* Parameters : oak_t *np, u32 ring, u32 flow_id, int enable
* Description : This function set Rx ring flow identifier
*/
void oak_unimac_set_rx_8021Q_flow(oak_t *np, u32 ring, u32 flow_id,
u32 enable);
/* Name : oak_unimac_set_rx_8021Q_qpri
* Returns : void
* Parameters : oak_t *np, u32 ring, u32 qpri, int enable
* Description : This function set Rx ring queue priority.
*/
void oak_unimac_set_rx_8021Q_qpri(oak_t *np, u32 ring, u32 qpri,
u32 enable);
/* Name : oak_unimac_set_rx_8021Q_spid
* Returns : void
* Parameters : oak_t *np, u32 ring, u32 spid, int enable
* Description : This function set Rx ring speed identifier (SPID).
*/
void oak_unimac_set_rx_8021Q_spid(oak_t *np, u32 ring, u32 spid,
u32 enable);
/* Name : oak_unimac_set_rx_da
* Returns : void
* Parameters : oak_t *np, u32 ring, unsigned char *addr, int enable
* Description : This function set rx ring MAC address
*/
void oak_unimac_set_rx_da(oak_t *np, u32 ring, unsigned char *addr,
u32 enable);
/* Name : oak_unimac_set_rx_da_mask
* Returns : void
* Parameters : oak_t *np, u32 ring, unsigned char *addr, int enable
* Description : This function set rx ring MAC address
*/
void oak_unimac_set_rx_da_mask(oak_t *np, u32 ring, unsigned char *addr,
int enable);
/* Name : oak_unimac_set_rx_mgmt
* Returns : void
* Parameters : oak_t *np, u32 ring, u32 val, int enable
* Description : This function call set bit number function with
* value and enable options
*/
void oak_unimac_set_rx_mgmt(oak_t *np, u32 ring, u32 val, u32 enable);
/* Name : oak_unimac_process_status
* Returns : void
* Parameters : ldg_t *ldg
* Description : This function get the process status
*/
void oak_unimac_process_status(ldg_t *ldg);
/* Name : oak_unimac_rx_error
* Returns : void
* Parameters : ldg_t *ldg, u32 ring
* Description : This function check interrupt cause reason and then if the
* reason is valid refill the receive ring else increment the rx errors
* counters.
*/
void oak_unimac_rx_error(ldg_t *ldg, u32 ring);
/* Name : oak_unimac_tx_error
* Returns : void
* Parameters : ldg_t *ldg, u32 ring
* Description : This function Tx error reason and then count errors
*/
void oak_unimac_tx_error(ldg_t *ldg, u32 ring);
/* Name : oak_unimac_ena_rx_ring_irq
* Returns : void
* Parameters : oak_t *np, u32 ring, u32 enable
* Description : This function enables the Rx ring irq.
*/
void oak_unimac_ena_rx_ring_irq(oak_t *np, u32 ring, u32 enable);
/* Name : oak_unimac_ena_tx_ring_irq
* Returns : void
* Parameters : oak_t *np, u32 ring, u32 enable
* Description : This function enables the Tx ring irq.
*/
void oak_unimac_ena_tx_ring_irq(oak_t *np, u32 ring, u32 enable);
/* Name : oak_unimac_set_tx_ring_rate
* Returns : int
* Parameters : oak_t *np, u32 ring, u32 sr_class,
* u32 hi_credit, u32 r_kbps
* Description : This function set tx ring rate limit.
*/
int oak_unimac_set_tx_ring_rate(oak_t *np, u32 ring, u32 sr_class,
u32 hi_credit, u32 r_kbps);
/* Name : oak_unimac_clr_tx_ring_rate
* Returns : void
* Parameters : oak_t *np, u32 ring
* Description : This function clear the tx ring rate limit
*/
void oak_unimac_clr_tx_ring_rate(oak_t *np, u32 ring);
/* Name : oak_unimac_set_tx_mac_rate
* Returns : int
* Parameters : oak_t *np, u32 sr_class, u32 hi_credit,
* u32 r_kbps
* Description : This function set transmision mac rate limit.
*/
int oak_unimac_set_tx_mac_rate(oak_t *np, u32 sr_class, u32 hi_credit,
u32 r_kbps);
/* Name : oak_unimac_start_all_txq
* Returns : int
* Parameters : oak_t *np, u32 enable
* Description : This function start all transmit queues
*/
int oak_unimac_start_all_txq(oak_t *np, u32 enable);
/* Name : oak_unimac_start_all_rxq
* Returns : int
* Parameters : oak_t *np, u32 enable
* Description : This function start all receive queues
*/
int oak_unimac_start_all_rxq(oak_t *np, u32 enable);
/* Name : oak_unimac_start_tx_ring
* Returns : u32
* Parameters : oak_t *np, int32_t ring, u32 enable
* Description : This function start rx ring
*/
u32 oak_unimac_start_tx_ring(oak_t *np, int32_t ring, u32 enable);
/* Name : oak_unimac_start_rx_ring
* Returns : u32
* Parameters : oak_t *np, u32 ring, u32 enable
* Description : This function start Rx ring
*/
u32 oak_unimac_start_rx_ring(oak_t *np, u32 ring, u32 enable);
/* Name : oak_ilog2_kernel_utility
* Returns : u32
* Parameters : u64 val
* Description : This function calls ilog2 kernel macro, ilog2 has complexity
* 67, the function ilog2 is called by net and unimac component.
*/
static inline u64 oak_ilog2_kernel_utility(u64 val)
{
return ilog2(val);
}
#endif /* #ifndef H_OAK_UNIMAC */

View File

@@ -0,0 +1,16 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#include "oak_unimac_desc.h"

View File

@@ -0,0 +1,62 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_UNIMAC_DESC
#define H_OAK_UNIMAC_DESC
typedef struct oak_rxd_tstruct {
u32 buf_ptr_lo;
u32 buf_ptr_hi;
} oak_rxd_t;
typedef struct oak_rxs_tstruct {
u32 bc : 16;
u32 es : 1;
u32 ec : 2;
u32 res1 : 1;
u32 first_last : 2;
u32 ipv4_hdr_ok : 1;
u32 l4_chk_ok : 1;
u32 l4_prot : 2;
u32 res2 : 1;
u32 l3_ipv4 : 1;
u32 l3_ipv6 : 1;
u32 vlan : 1;
u32 l2_prot : 2;
u32 timestamp : 32;
u32 rc_chksum : 16;
u32 udp_cs_0 : 1;
u32 res3 : 15;
u32 mhdr : 16;
u32 mhok : 1;
u32 res4 : 15;
} oak_rxs_t;
typedef struct oak_txd_tstruct {
u32 bc : 16;
u32 res1 : 4;
u32 last : 1;
u32 first : 1;
u32 gl3_chksum : 1;
u32 gl4_chksum : 1;
u32 res2 : 4;
u32 time_valid : 1;
u32 res3 : 3;
u32 timestamp : 32;
u32 buf_ptr_lo : 32;
u32 buf_ptr_hi : 32;
} oak_txd_t;
#endif /* #ifndef H_OAK_UNIMAC_DESC */

View File

@@ -0,0 +1,29 @@
/*
*
* If you received this File from Marvell, you may opt to use, redistribute and/or
* modify this File in accordance with the terms and conditions of the General
* Public License Version 2, June 1991 (the "GPL License"), a copy of which is
* available along with the File in the license.txt file or by writing to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
* on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this warranty
* disclaimer.
*
*/
#ifndef H_OAK_UNIMAC_STAT
#define H_OAK_UNIMAC_STAT
typedef struct oak_unimac_statstruct {
u64 rx_good_frames;
u64 rx_bad_frames;
u64 rx_stall_fifo;
u64 rx_stall_desc;
u64 rx_discard_desc;
u64 tx_pause;
u64 tx_stall_fifo;
} oak_unimac_stat;
#endif /* #ifndef H_OAK_UNIMAC_STAT */