mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 04:42:04 -04:00
Merge "atlantic forwarding driver v1.1.22"
This commit is contained in:
commit
3035689d90
21 changed files with 973 additions and 57 deletions
|
|
@ -973,6 +973,15 @@ int atl2_fw_init(struct atl_hw *hw)
|
|||
|
||||
atl2_get_fw_version(hw);
|
||||
|
||||
/* Warn if FW is lower than 1.3.1 */
|
||||
if (((mcp->fw_rev >> 24) < 1) ||
|
||||
(((mcp->fw_rev >> 16) & 0xFFU) < 3) ||
|
||||
((mcp->fw_rev & 0xFFFFU) < 1))
|
||||
atl_dev_warn("FW_version: %u.%u.%u, is not stable version",
|
||||
(mcp->fw_rev >> 24),
|
||||
((mcp->fw_rev >> 16) & 0xFFU),
|
||||
(mcp->fw_rev & 0xFFFFU));
|
||||
|
||||
mcp->ops = &atl2_fw_ops;
|
||||
atl_dev_dbg("Detect ATL2FW %x\n", mcp->fw_rev);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#define ATL_VERSION "1.1.18"
|
||||
#define ATL_VERSION "1.1.22"
|
||||
|
||||
struct atl_nic;
|
||||
|
||||
|
|
@ -32,8 +32,6 @@ struct atl_nic;
|
|||
|
||||
#define ATL_MAX_QUEUES 8
|
||||
|
||||
#include "atl_fwd.h"
|
||||
|
||||
struct atl_ptp;
|
||||
|
||||
enum {
|
||||
|
|
@ -414,6 +412,7 @@ void atl_update_global_stats(struct atl_nic *nic);
|
|||
void atl_set_loopback(struct atl_nic *nic, int idx, bool on);
|
||||
void atl_set_intr_mod(struct atl_nic *nic);
|
||||
void atl_update_ntuple_flt(struct atl_nic *nic, int idx);
|
||||
int atl_vlan_promisc_status(struct net_device *ndev);
|
||||
void atl_set_vlan_promisc(struct atl_hw *hw, int promisc);
|
||||
int atl_hwsem_get(struct atl_hw *hw, int idx);
|
||||
void atl_hwsem_put(struct atl_hw *hw, int idx);
|
||||
|
|
@ -424,18 +423,6 @@ int atl_msm_write(struct atl_hw *hw, uint32_t addr, uint32_t val);
|
|||
int atl_update_eth_stats(struct atl_nic *nic);
|
||||
void atl_adjust_eth_stats(struct atl_ether_stats *stats,
|
||||
struct atl_ether_stats *base, bool add);
|
||||
void atl_fwd_release_rings(struct atl_nic *nic);
|
||||
#if IS_ENABLED(CONFIG_ATLFWD_FWD)
|
||||
enum atl_fwd_notify;
|
||||
int atl_fwd_suspend_rings(struct atl_nic *nic);
|
||||
int atl_fwd_resume_rings(struct atl_nic *nic);
|
||||
void atl_fwd_notify(struct atl_nic *nic, enum atl_fwd_notify notif, void *data);
|
||||
#else
|
||||
static inline int atl_fwd_suspend_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline int atl_fwd_resume_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline void atl_fwd_notify(struct atl_nic *nic,
|
||||
enum atl_fwd_notify notif, void *data) {}
|
||||
#endif
|
||||
int atl_get_lpi_timer(struct atl_nic *nic, uint32_t *lpi_delay);
|
||||
void atl_refresh_rxfs(struct atl_nic *nic);
|
||||
void atl_schedule_work(struct atl_nic *nic);
|
||||
|
|
|
|||
123
drivers/net/ethernet/aquantia/atlantic-fwd/atl_dump.h
Normal file
123
drivers/net/ethernet/aquantia/atlantic-fwd/atl_dump.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Atlantic Network Driver
|
||||
*
|
||||
* Copyright (C) 2021 Marvell International Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _ATL_DUMP_H_
|
||||
#define _ATL_DUMP_H_
|
||||
|
||||
enum atl_crash_dump_types {
|
||||
atl_crash_dump_type_regs = 0,
|
||||
atl_crash_dump_type_fwiface = 1,
|
||||
atl_crash_dump_type_act_res = 2,
|
||||
atl_crash_dump_type_ring = 3,
|
||||
};
|
||||
|
||||
/** Some of the registers we can not read safely from the device.
|
||||
* Those will not be read, with value 0xFFFFFFFF stored instead.
|
||||
*/
|
||||
struct atl_crash_dump_regs {
|
||||
u32 type;
|
||||
u32 length;
|
||||
union {
|
||||
u32 regs_data[0x9000/4];
|
||||
struct{
|
||||
u32 mif[0x1000/4];
|
||||
u32 pci[0x1000/4];
|
||||
u32 itr[0x1000/4];
|
||||
u32 com[0x1000/4];
|
||||
u32 mac_phy[0x1000/4];
|
||||
union {
|
||||
u32 rx[0x2000/4];
|
||||
struct{
|
||||
u32 res1[0x700/4];
|
||||
u32 pb_ctrl;
|
||||
u32 res2;
|
||||
u32 pb_status;
|
||||
u32 res3;
|
||||
/* 0x5710 */
|
||||
struct{
|
||||
u32 pb_reg1;
|
||||
u32 pb_reg2;
|
||||
u32 pb_reg3;
|
||||
} pb[8];
|
||||
u32 res4[0x100]; /* TODO */
|
||||
/* 0x5B00 */
|
||||
struct{
|
||||
u32 base_lo;
|
||||
u32 base_hi;
|
||||
u32 ctrl;
|
||||
u32 head;
|
||||
u32 tail;
|
||||
u32 status;
|
||||
u32 size;
|
||||
u32 threshold;
|
||||
} dma_desc[32];
|
||||
} layout;
|
||||
};
|
||||
u32 tx[0x2000/4];
|
||||
} layout;
|
||||
};
|
||||
};
|
||||
|
||||
struct atl_crash_dump_fwiface {
|
||||
u32 type;
|
||||
u32 length;
|
||||
/* struct fw_interface_in */
|
||||
u32 fw_interface_in[0x1000/4];
|
||||
/* struct fw_interface_out */
|
||||
u32 fw_interface_out[0x1000/4];
|
||||
};
|
||||
|
||||
/* Record table size of 128 with each entry holding (tag, mask, action) */
|
||||
#define ATL_ACT_RES_TABLE_SIZE 384
|
||||
struct atl_crash_dump_act_res {
|
||||
u32 type;
|
||||
u32 length;
|
||||
u32 act_res_data[ATL_ACT_RES_TABLE_SIZE];
|
||||
};
|
||||
|
||||
/* max_size = 'ring_size * (tx + rx) * 16 byte raw descriptor data' */
|
||||
#define ATL_MAX_RING_DESC_SIZE ATL_MAX_RING_SIZE * 32
|
||||
struct atl_crash_dump_ring {
|
||||
u32 type;
|
||||
u32 length;
|
||||
u32 index;
|
||||
u32 rx_head;
|
||||
u32 rx_tail;
|
||||
u32 tx_head;
|
||||
u32 tx_tail;
|
||||
u32 rx_ring_size;
|
||||
u32 tx_ring_size;
|
||||
u8 ring_data[ATL_MAX_RING_DESC_SIZE];
|
||||
};
|
||||
|
||||
/* This is an extensible structure to collect various debug data from
|
||||
* AQC device
|
||||
*/
|
||||
struct atl_crash_dump {
|
||||
u32 length; /* total crash structure length, in bytes */
|
||||
u32 sections_count; /* number of sections of type atl_crash_dump* following */
|
||||
u8 drv_version[16];
|
||||
u8 fw_version[16];
|
||||
union {
|
||||
struct {
|
||||
struct atl_crash_dump_regs regs;
|
||||
struct atl_crash_dump_fwiface fwiface;
|
||||
struct atl_crash_dump_act_res act_res;
|
||||
struct atl_crash_dump_ring ring[ATL_MAX_QUEUES];
|
||||
} antigua;
|
||||
struct {
|
||||
struct atl_crash_dump_regs regs;
|
||||
struct atl_crash_dump_ring ring[ATL_MAX_QUEUES];
|
||||
} atlantic;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
The tool atl_dump_parser is used to parse the register/device dump collected
|
||||
using "ethtool -d" command. Parser accepts dump in the binary format, hence the
|
||||
dump must be collected using 'raw' option i.e., 'ethtool -d <device> raw on'
|
||||
|
||||
Use gcc to build the binary from sources,
|
||||
gcc -o atl_dump_parser atl_dump_parser.c
|
||||
|
||||
Example:
|
||||
--------
|
||||
1. Collect ethtool dump from SUT machine
|
||||
#ethtool -d enp1s0 raw on > ethd_dump
|
||||
|
||||
2. Parse the dump
|
||||
#ls
|
||||
atl_dump_parser ethd_dump
|
||||
#./atl_dump_parser ethd_dump
|
||||
Parsing is completed successfully
|
||||
#ls ethd_dump_parsed
|
||||
action_resolver.txt atl_dump_parser ethd_dump fw_interface.txt registers.txt rings.txt
|
||||
#
|
||||
Parsed data will be copied to the text files under <input_file>_parsed folder.
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "atl_dump_parser.h"
|
||||
#include "../atl_dump.h"
|
||||
|
||||
#define DEV_FILE "device.txt"
|
||||
#define REG_FILE "registers.txt"
|
||||
#define FW_IFACE_FILE "fw_interface.txt"
|
||||
#define ACT_RES_FILE "action_resolver.txt"
|
||||
#define RING_FILE "rings.txt"
|
||||
|
||||
struct section_header {
|
||||
u32 type;
|
||||
u32 length;
|
||||
};
|
||||
|
||||
char out_folder[64];
|
||||
|
||||
int dump_device_info(struct atl_crash_dump *crash_dump)
|
||||
{
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, DEV_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "Driver version: %s\n", crash_dump->drv_version);
|
||||
fprintf(file, "FW version: %s\n", crash_dump->fw_version);
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_registers(struct atl_crash_dump_regs *reg)
|
||||
{
|
||||
int block = 0x1000/4, i, offset;
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, REG_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Skip MIF block */
|
||||
|
||||
offset = block * 4;
|
||||
fprintf(file, "PCI Registers\n");
|
||||
fprintf(file, "=============\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.pci[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nInterrupt Registers\n");
|
||||
fprintf(file, "=====================\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.itr[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nCOM Registers\n");
|
||||
fprintf(file, "===============\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.com[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nMac Phy Registers\n");
|
||||
fprintf(file, "=====================\n");
|
||||
for (i = 0; i < block; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.mac_phy[i]);
|
||||
|
||||
offset += block * 4;
|
||||
fprintf(file, "\n\nRx Registers\n");
|
||||
fprintf(file, "===============\n");
|
||||
/* Rx block size is 0x2000 */
|
||||
for (i = 0; i < block * 2; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.rx[i]);
|
||||
|
||||
offset += block * 2 * 4;
|
||||
fprintf(file, "\n\nTx Registers\n");
|
||||
fprintf(file, "===============\n");
|
||||
/* Tx block size is 0x2000 */
|
||||
for (i = 0; i < block * 2; i++)
|
||||
fprintf(file, "0x%08x: 0x%08x\n", offset + i * 4, reg->layout.tx[i]);
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_fwiface(struct atl_crash_dump_fwiface *fwiface)
|
||||
{
|
||||
int block = 0x1000/4, i;
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, FW_IFACE_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "FW input interface\n");
|
||||
fprintf(file, "==================\n");
|
||||
for (i = 0; i < block; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i,
|
||||
fwiface->fw_interface_in[i], fwiface->fw_interface_in[i + 1],
|
||||
fwiface->fw_interface_in[i + 2], fwiface->fw_interface_in[i + 3]);
|
||||
|
||||
fprintf(file, "\n\nFW output interface\n");
|
||||
fprintf(file, "=======================\n");
|
||||
for (i = 0; i < block; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i,
|
||||
fwiface->fw_interface_out[i], fwiface->fw_interface_out[i + 1],
|
||||
fwiface->fw_interface_out[i + 2], fwiface->fw_interface_out[i + 3]);
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_act_res(struct atl_crash_dump_act_res *act_res)
|
||||
{
|
||||
char file_name[64];
|
||||
int i, idx;
|
||||
FILE *file;
|
||||
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, ACT_RES_FILE);
|
||||
file = fopen(file_name, "w");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "RECORD RESOLVER TAG TAG Mask Action\n");
|
||||
fprintf(file, "==================================================\n");
|
||||
for (i = 0, idx = 0; i < ATL_ACT_RES_TABLE_SIZE / 3; i++) {
|
||||
fprintf(file, "%d\t0x%08x\t0x%08x\t0x%08x\n", i, act_res->act_res_data[idx++],
|
||||
act_res->act_res_data[idx++], act_res->act_res_data[idx++]);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_ring(struct atl_crash_dump_ring *ring)
|
||||
{
|
||||
char file_name[64];
|
||||
FILE *file;
|
||||
u32 *data;
|
||||
int i;
|
||||
|
||||
/* Assumption - file 'rings.txt' shouldn't exists */
|
||||
snprintf(file_name, 64, "%s/%s", out_folder, RING_FILE);
|
||||
file = fopen(file_name, "a+");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file %s\n", file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(file, "Ring Index %d\n", ring->index);
|
||||
fprintf(file, "==============\n");
|
||||
fprintf(file, "Rx head = 0x%08x tail = 0x%08x\n", ring->rx_head, ring->rx_tail);
|
||||
fprintf(file, "Tx head = 0x%08x tail = 0x%08x\n", ring->tx_head, ring->tx_tail);
|
||||
fprintf(file, "HW Ring rx_size = %d tx_size = %d\n", ring->rx_ring_size, ring->tx_ring_size);
|
||||
fprintf(file, "Rx Ring descriptor:\n");
|
||||
fprintf(file, "-------------------\n");
|
||||
data = (u32 *)ring->ring_data;
|
||||
for (i = 0; i < ring->rx_ring_size; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i, data[i], data[i + 1],
|
||||
data[i + 2], data[i + 3]);
|
||||
fprintf(file, "Tx Ring descriptor:\n");
|
||||
fprintf(file, "-------------------\n");
|
||||
data = (u32 *)ring->ring_data + ring->rx_ring_size;
|
||||
for (i = 0; i < ring->tx_ring_size; i += 4)
|
||||
fprintf(file, "0x%08x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", i, data[i], data[i + 1],
|
||||
data[i + 2], data[i + 3]);
|
||||
fprintf(file, "\n");
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct atl_crash_dump *crash_dump;
|
||||
struct section_header *header;
|
||||
int i, offset, ret = 0;
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm_val;
|
||||
FILE *input_file;
|
||||
struct stat st;
|
||||
char *buffer;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("No intput file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stat(argv[1], &st) == -1) {
|
||||
printf("File stat error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = malloc(st.st_size);
|
||||
if (!buffer) {
|
||||
printf("Mem alloc error\n");
|
||||
return -1;
|
||||
}
|
||||
/* open the source file for reading */
|
||||
input_file = fopen(argv[1],"rb");
|
||||
if (input_file == NULL) {
|
||||
ret = -1;
|
||||
printf("Error opening file %s\n", argv[1]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
fread(buffer, sizeof(char), st.st_size, input_file);
|
||||
fclose(input_file);
|
||||
|
||||
tm_val = localtime(&t);
|
||||
tm_val = NULL;
|
||||
if (tm_val)
|
||||
snprintf(out_folder, 64, "%s_%02d-%02d-%02d_%02d-%02d-%02d", argv[1],
|
||||
tm_val->tm_mon + 1, (int) tm_val->tm_mday, 1900 + tm_val->tm_year,
|
||||
tm_val->tm_hour, tm_val->tm_min, tm_val->tm_sec);
|
||||
else
|
||||
snprintf(out_folder, 64, "%s_parsed", argv[1]);
|
||||
if (stat(out_folder, &st) == -1) {
|
||||
if (mkdir(out_folder, 0644) == -1) {
|
||||
ret = -1;
|
||||
printf("Failed to creat folder` %s\n", out_folder);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
crash_dump = (struct atl_crash_dump *)buffer;
|
||||
ret = dump_device_info(crash_dump);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
offset = offsetof(struct atl_crash_dump, antigua);
|
||||
for (i = 0; i < crash_dump->sections_count; i++) {
|
||||
header = (struct section_header *)(buffer + offset);
|
||||
switch (header->type) {
|
||||
case atl_crash_dump_type_regs:
|
||||
ret = dump_registers((struct atl_crash_dump_regs *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
case atl_crash_dump_type_fwiface:
|
||||
ret = dump_fwiface((struct atl_crash_dump_fwiface *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
case atl_crash_dump_type_act_res:
|
||||
ret = dump_act_res((struct atl_crash_dump_act_res *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
case atl_crash_dump_type_ring:
|
||||
ret = dump_ring((struct atl_crash_dump_ring *)(buffer + offset));
|
||||
if (ret)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
printf("Parsing Error - invalid section\n");
|
||||
goto err;
|
||||
}
|
||||
offset += header->length;
|
||||
}
|
||||
|
||||
err:
|
||||
free(buffer);
|
||||
if (ret)
|
||||
printf("Failed to parse the dump\n");
|
||||
else
|
||||
printf("Parsing is completed successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __ATL_DUMP_PARSER
|
||||
#define __ATL_DUMP_PARSER
|
||||
|
||||
#define ATL_MAX_RING_SIZE (8192 - 8)
|
||||
#define ATL_MAX_QUEUES 8
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#endif
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include "atl_fwdnl.h"
|
||||
#include "atl_macsec.h"
|
||||
#include "atl_ptp.h"
|
||||
#include "atl_fwd.h"
|
||||
|
||||
static uint32_t atl_ethtool_get_link(struct net_device *ndev)
|
||||
{
|
||||
|
|
@ -633,8 +634,8 @@ static const struct atl_stat_desc eth_stat_descs[] = {
|
|||
ATL_ETH_STAT(tx_pause, tx_pause),
|
||||
ATL_ETH_STAT(tx_ether_pkts, tx_ether_pkts),
|
||||
ATL_ETH_STAT(tx_ether_octets, tx_ether_octets),
|
||||
ATL_ETH_STAT(tx_errors, tx_errors),
|
||||
ATL_ETH_STAT(rx_pause, rx_pause),
|
||||
ATL_ETH_STAT(rx_ether_drops, rx_ether_drops),
|
||||
ATL_ETH_STAT(rx_ether_octets, rx_ether_octets),
|
||||
ATL_ETH_STAT(rx_ether_pkts, rx_ether_pkts),
|
||||
ATL_ETH_STAT(rx_ether_broacasts, rx_ether_broacasts),
|
||||
|
|
@ -642,6 +643,13 @@ static const struct atl_stat_desc eth_stat_descs[] = {
|
|||
ATL_ETH_STAT(rx_ether_crc_align_errs, rx_ether_crc_align_errs),
|
||||
ATL_ETH_STAT(rx_filter_host, rx_filter_host),
|
||||
ATL_ETH_STAT(rx_filter_lost, rx_filter_lost),
|
||||
ATL_ETH_STAT(rx_errors, rx_errors),
|
||||
ATL_ETH_STAT(rx_drops, rx_drops),
|
||||
ATL_ETH_STAT(rx_dma_packets, rx_dma_packets),
|
||||
ATL_ETH_STAT(rx_dma_octets, rx_dma_octets),
|
||||
ATL_ETH_STAT(rx_dma_drops, rx_dma_drops),
|
||||
ATL_ETH_STAT(tx_dma_packets, tx_dma_packets),
|
||||
ATL_ETH_STAT(tx_dma_octets, tx_dma_octets),
|
||||
};
|
||||
|
||||
#define ATL_PRIV_FLAG(_name, _bit) \
|
||||
|
|
@ -2711,9 +2719,7 @@ static void atl_refresh_rxf_desc(struct atl_nic *nic,
|
|||
atl_for_each_rxf_idx(desc, idx)
|
||||
desc->update_rxf(nic, idx);
|
||||
|
||||
atl_set_vlan_promisc(&nic->hw, (nic->ndev->flags & IFF_PROMISC) ||
|
||||
nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw, atl_vlan_promisc_status(nic->ndev));
|
||||
}
|
||||
|
||||
void atl_refresh_rxfs(struct atl_nic *nic)
|
||||
|
|
@ -2723,9 +2729,7 @@ void atl_refresh_rxfs(struct atl_nic *nic)
|
|||
atl_for_each_rxf_desc(desc)
|
||||
atl_refresh_rxf_desc(nic, desc);
|
||||
|
||||
atl_set_vlan_promisc(&nic->hw, (nic->ndev->flags & IFF_PROMISC) ||
|
||||
nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw, atl_vlan_promisc_status(nic->ndev));
|
||||
}
|
||||
|
||||
static bool atl_vlan_pull_from_promisc(struct atl_nic *nic, uint32_t idx)
|
||||
|
|
@ -2765,9 +2769,8 @@ static bool atl_vlan_pull_from_promisc(struct atl_nic *nic, uint32_t idx)
|
|||
} while (idx & ATL_VIDX_FREE);
|
||||
|
||||
kfree(map);
|
||||
atl_set_vlan_promisc(&nic->hw, (nic->ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw, atl_vlan_promisc_status(nic->ndev));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2955,9 +2958,7 @@ int atl_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
|||
vlan->promisc_count++;
|
||||
if (pm_runtime_active(&nic->hw.pdev->dev))
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
(ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_vlan_promisc_status(nic->ndev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2984,9 +2985,8 @@ update_vlan:
|
|||
atl_rxf_update_vlan(nic, idx);
|
||||
if (pm_runtime_active(&nic->hw.pdev->dev))
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
(nic->ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_vlan_promisc_status(nic->ndev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3027,9 +3027,9 @@ int atl_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
|||
|
||||
update_vlan_promisc:
|
||||
if (pm_runtime_active(&nic->hw.pdev->dev))
|
||||
atl_set_vlan_promisc(&nic->hw, (ndev->flags & IFF_PROMISC) ||
|
||||
vlan->promisc_count ||
|
||||
!vlan->vlans_active);
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
atl_vlan_promisc_status(nic->ndev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3086,6 +3086,18 @@ static void atl_ethtool_complete(struct net_device *ndev)
|
|||
pm_runtime_put(&nic->hw.pdev->dev);
|
||||
}
|
||||
|
||||
static int atl_ethool_get_regs_len(struct net_device *ndev)
|
||||
{
|
||||
return atl_get_crash_dump(ndev, NULL);
|
||||
}
|
||||
|
||||
static void atl_ethool_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *buf)
|
||||
{
|
||||
regs->version = 0;
|
||||
memset(buf, 0, regs->len);
|
||||
atl_get_crash_dump(ndev, buf);
|
||||
}
|
||||
|
||||
const struct ethtool_ops atl_ethtool_ops = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
|
||||
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
|
||||
|
|
@ -3128,4 +3140,6 @@ const struct ethtool_ops atl_ethtool_ops = {
|
|||
.set_wol = atl_set_wol,
|
||||
.begin = atl_ethtool_begin,
|
||||
.complete = atl_ethtool_complete,
|
||||
.get_regs_len = atl_ethool_get_regs_len,
|
||||
.get_regs = atl_ethool_get_regs,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1172,6 +1172,39 @@ int atl_update_thermal_flag(struct atl_hw *hw, int bit, bool val)
|
|||
static unsigned int atl_wdog_period = 1100;
|
||||
module_param_named(wdog_period, atl_wdog_period, uint, 0644);
|
||||
|
||||
static int atl_fw_rev_check_and_warn(int fw_rev)
|
||||
{
|
||||
int major = (fw_rev >> 24) & 0xFFU;
|
||||
bool ret = true;
|
||||
|
||||
switch (major) {
|
||||
case 2:
|
||||
if ((((fw_rev >> 16) & 0xFFU) < 12) &&
|
||||
((fw_rev & 0xFFFFU) < 12))
|
||||
ret = false;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if ((((fw_rev >> 16) & 0xFFU) < 1) &&
|
||||
((fw_rev & 0xFFFFU) < 102))
|
||||
ret = false;
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if ((((fw_rev >> 16) & 0xFFU) < 2) &&
|
||||
((fw_rev & 0xFFFFU) < 37))
|
||||
ret = false;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int atl_fw_init(struct atl_hw *hw)
|
||||
{
|
||||
uint32_t tries, reg, major;
|
||||
|
|
@ -1186,6 +1219,13 @@ int atl_fw_init(struct atl_hw *hw)
|
|||
atl_dev_dbg("FW startup took %d ms\n", tries);
|
||||
|
||||
major = (reg >> 24) & 0xff;
|
||||
|
||||
/* Warn if FW is lower than 2.12.12, 3.1.102 and 4.2.37 */
|
||||
if (!atl_fw_rev_check_and_warn(reg))
|
||||
atl_dev_warn("FW_version: %u.%u.%u, is not stable version",
|
||||
(reg >> 24), ((reg >> 16) & 0xFFU),
|
||||
(reg & 0xFFFFU));
|
||||
|
||||
if (!major || major > 3) {
|
||||
atl_dev_err("Unsupported FW major version: %u\n", major);
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,46 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include "atl_common.h"
|
||||
#include "atl_desc.h"
|
||||
#include "atl_fwd.h"
|
||||
#include "atl_ring.h"
|
||||
|
||||
static u32 atl_skip_reglist[] = {
|
||||
/* PCIE */
|
||||
0x1030, 0x1200, 0x1514, 0x1F00, 0x1F04, 0x1F20, 0x1F24,
|
||||
|
||||
/* INTR Registers */
|
||||
0x21A0, 0x21A4, 0x21A8,
|
||||
|
||||
/* COM Registers */
|
||||
0x30A0, 0x30A8, 0x3900, 0x3920,
|
||||
|
||||
/* MAC PHY Registers */
|
||||
0x4058, 0x4060, 0x4064, 0x40B0, 0x40B4, 0x40B8, 0x40BC,
|
||||
0x4120, 0x4140, 0x4144, 0x4190, 0x419C, 0x41A0, 0x41A4,
|
||||
0x41A8, 0x4270, 0x4288, 0x428C, 0x4290, 0x4294, 0x42E8,
|
||||
0x42EC, 0x434C, 0x4378, 0x4380, 0x4384, 0x4440, 0x4444,
|
||||
0x4970, 0x4B40, 0x4B44, 0x4B48, 0x4B4C,
|
||||
|
||||
/* RX Registers */
|
||||
0x5108, 0x54CC, 0x55B0, 0x55B4, 0x55C0, 0x55E0, 0x55E4,
|
||||
0x5640, 0x5718, 0x5728, 0x5738, 0x5748, 0x5758, 0x5768,
|
||||
0x5778, 0x5788, 0x5808, 0x580C, 0x5A10, 0x5B14, 0x5B34,
|
||||
0x5B54, 0x5B74, 0x5B94, 0x5BB4, 0x5BD4, 0x5BF4, 0x5C14,
|
||||
0x5C34, 0x5C54, 0x5C74, 0x5C94, 0x5CB4, 0x5CD4, 0x5CF4,
|
||||
0x5D14, 0x5D34, 0x5D54, 0x5D74, 0x5D94, 0x5DB4, 0x5DD4,
|
||||
0x5DF4, 0x5E14, 0x5E34, 0x5E54, 0x5E74, 0x5E94, 0x5EB4,
|
||||
0x5ED4, 0x5EF4, 0x6900, 0x6F00, 0x6F20,
|
||||
|
||||
/* TX Registers */
|
||||
0x7808, 0x7848, 0x784C, 0x78B0, 0x78B4, 0x7918, 0x7928,
|
||||
0x7938, 0x7948, 0x7958, 0x7968, 0x7978, 0x7988, 0x7A34,
|
||||
0x7B10, 0x7B14, 0x7B18, 0x7C14, 0x7C54, 0x7C94, 0x7CD4,
|
||||
0x7D14, 0x7D54, 0x7D94, 0x7DD4, 0x7E14, 0x7E54, 0x7E94,
|
||||
0x7ED4, 0x7F14, 0x7F54, 0x7F94, 0x7FD4, 0x8014, 0x8054,
|
||||
0x8094, 0x80D4, 0x8114, 0x8154, 0x8194, 0x81D4, 0x8214,
|
||||
0x8254, 0x8294, 0x82D4, 0x8314, 0x8354, 0x8394, 0x83D4,
|
||||
0x8900, 0x8904, 0x8F00, 0x8F20,
|
||||
};
|
||||
|
||||
static const char *atl_fwd_dir_str(struct atl_fwd_ring *ring)
|
||||
{
|
||||
|
|
@ -903,3 +943,178 @@ int atl_fwd_resume_rings(struct atl_nic *nic)
|
|||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int atl_get_ext_stats(struct net_device *ndev, struct atl_ext_stats *stats)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
if (!stats)
|
||||
return -EINVAL;
|
||||
|
||||
atl_update_eth_stats(nic);
|
||||
atl_update_global_stats(nic);
|
||||
|
||||
memcpy(&stats->rx, &nic->stats.rx, sizeof(stats->rx));
|
||||
memcpy(&stats->tx, &nic->stats.tx, sizeof(stats->tx));
|
||||
memcpy(&stats->rx_fwd, &nic->stats.rx_fwd, sizeof(stats->rx_fwd));
|
||||
memcpy(&stats->eth, &nic->stats.eth, sizeof(stats->eth));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(atl_get_ext_stats);
|
||||
|
||||
static bool atl_skip_register(u32 reg)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
count = sizeof(atl_skip_reglist) / sizeof(u32);
|
||||
for (i = 0; i < count; i++)
|
||||
if (atl_skip_reglist[i] == reg)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_regs(struct atl_hw *hw, struct atl_crash_dump_regs *section)
|
||||
{
|
||||
int addr, index;
|
||||
|
||||
section->type = atl_crash_dump_type_regs;
|
||||
section->length = sizeof(struct atl_crash_dump_regs);
|
||||
|
||||
/* prefill with 'skip' value */
|
||||
for (addr = 0; addr < sizeof(section->regs_data); addr++)
|
||||
section->regs_data[addr] = 0xFFFFFFFF;
|
||||
|
||||
for (addr = 0x1000, index = 0x1000 / 4; addr < 0x9000; addr += 4, index++) {
|
||||
if (atl_skip_register(addr))
|
||||
continue;
|
||||
section->regs_data[index] = atl_read(hw, addr);
|
||||
}
|
||||
|
||||
return section->length;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_fwiface(struct atl_hw *hw, struct atl_crash_dump_fwiface *section)
|
||||
{
|
||||
int i;
|
||||
|
||||
section->type = atl_crash_dump_type_fwiface;
|
||||
section->length = sizeof(struct atl_crash_dump_fwiface);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(section->fw_interface_in); i++)
|
||||
section->fw_interface_in[i] = atl_read(hw, ATL2_MIF_SHARED_BUFFER_IN(i));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(section->fw_interface_out); i++)
|
||||
section->fw_interface_out[i] = atl_read(hw, ATL2_MIF_SHARED_BUFFER_OUT(i));
|
||||
|
||||
return section->length;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_act_res(struct atl_hw *hw, struct atl_crash_dump_act_res *section)
|
||||
{
|
||||
int i, idx, err;
|
||||
|
||||
section->type = atl_crash_dump_type_act_res;
|
||||
section->length = sizeof(struct atl_crash_dump_act_res);
|
||||
|
||||
err = atl_hwsem_get(hw, ATL2_MCP_SEM_ACT_RSLVR);
|
||||
if (err) {
|
||||
printk("Failed to aquire act_res semaphore\n");
|
||||
goto ret;
|
||||
}
|
||||
|
||||
for (i = 0, idx = 0; i < ATL_ACT_RES_TABLE_SIZE / 3; i++) {
|
||||
section->act_res_data[idx++] = atl_read(hw, ATL2_RPF_ACT_RSLVR_REQ_TAG(i));
|
||||
section->act_res_data[idx++] = atl_read(hw, ATL2_RPF_ACT_RSLVR_TAG_MASK(i));
|
||||
section->act_res_data[idx++] = atl_read(hw, ATL2_RPF_ACT_RSLVR_ACTN(i));
|
||||
}
|
||||
|
||||
atl_hwsem_put(hw, ATL2_MCP_SEM_ACT_RSLVR);
|
||||
|
||||
ret:
|
||||
return section->length;
|
||||
}
|
||||
|
||||
static int atl_get_crash_dump_ring(struct atl_nic *nic, int idx,
|
||||
struct atl_crash_dump_ring *section)
|
||||
{
|
||||
int size = sizeof(struct atl_crash_dump_ring), offset;
|
||||
struct atl_queue_vec *qvec = &nic->qvecs[idx];
|
||||
struct atl_hw_ring *hwring;
|
||||
|
||||
if (!test_bit(ATL_ST_UP, &nic->hw.state)) {
|
||||
memset(section, 0, size);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
section->type = atl_crash_dump_type_ring;
|
||||
section->index = qvec->idx;
|
||||
section->length = size;
|
||||
section->rx_head = qvec->rx.head;
|
||||
section->rx_tail = qvec->rx.tail;
|
||||
section->tx_head = qvec->tx.head;
|
||||
section->tx_tail = qvec->tx.tail;
|
||||
hwring = &qvec->rx.hw;
|
||||
section->rx_ring_size = hwring->size;
|
||||
memcpy(section->ring_data, hwring->descs, hwring->size * sizeof(*hwring->descs));
|
||||
offset = hwring->size * sizeof(*hwring->descs);
|
||||
hwring = &qvec->tx.hw;
|
||||
section->tx_ring_size = hwring->size;
|
||||
memcpy(section->ring_data + offset, hwring->descs, hwring->size * sizeof(*hwring->descs));
|
||||
|
||||
ret:
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
int atl_get_crash_dump(struct net_device *ndev, struct atl_crash_dump *crash_dump)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
u32 fw_rev = nic->hw.mcp.fw_rev;
|
||||
int recorded_sz = 0, i, nvecs;
|
||||
u8 *section;
|
||||
|
||||
if (!crash_dump)
|
||||
return sizeof(struct atl_crash_dump);
|
||||
|
||||
crash_dump->length = sizeof(*crash_dump);
|
||||
crash_dump->sections_count = 0;
|
||||
|
||||
strlcpy(crash_dump->drv_version, ATL_VERSION, sizeof(crash_dump->drv_version));
|
||||
snprintf(crash_dump->fw_version, sizeof(crash_dump->fw_version),
|
||||
"%d.%d.%d", fw_rev >> 24, fw_rev >> 16 & 0xff, fw_rev & 0xffff);
|
||||
|
||||
if (nic->hw.chip_id == ATL_ANTIGUA)
|
||||
section = (void *)&crash_dump->antigua.regs;
|
||||
else
|
||||
section = (void *)&crash_dump->atlantic.regs;
|
||||
|
||||
recorded_sz = atl_get_crash_dump_regs(&nic->hw, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
|
||||
if (nic->hw.chip_id == ATL_ANTIGUA) {
|
||||
recorded_sz = atl_get_crash_dump_fwiface(&nic->hw, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
|
||||
recorded_sz = atl_get_crash_dump_act_res(&nic->hw, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
}
|
||||
|
||||
nvecs = min_t(int, nic->nvecs, ATL_MAX_QUEUES);
|
||||
for (i = 0; i < nvecs; i++) {
|
||||
recorded_sz = atl_get_crash_dump_ring(nic, i, (void *)section);
|
||||
crash_dump->sections_count++;
|
||||
crash_dump->length += recorded_sz;
|
||||
section += recorded_sz;
|
||||
}
|
||||
|
||||
return crash_dump->length;
|
||||
}
|
||||
EXPORT_SYMBOL(atl_get_crash_dump);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
#define _ATL_FWD_H_
|
||||
|
||||
#include "atl_common.h"
|
||||
#include "atl_dump.h"
|
||||
|
||||
/* Each incompatible API change bumps the API version */
|
||||
#define ATL_FWD_API_VERSION 3
|
||||
#define ATL_FWD_API_VERSION 4
|
||||
|
||||
struct atl_fwd_event;
|
||||
|
||||
|
|
@ -405,4 +406,40 @@ enum atl_fwd_ring_state {
|
|||
ATL_FWR_ST_EVT_ENABLED = BIT(1),
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ATLFWD_FWD)
|
||||
enum atl_fwd_notify;
|
||||
void atl_fwd_release_rings(struct atl_nic *nic);
|
||||
int atl_fwd_suspend_rings(struct atl_nic *nic);
|
||||
int atl_fwd_resume_rings(struct atl_nic *nic);
|
||||
void atl_fwd_notify(struct atl_nic *nic, enum atl_fwd_notify notif, void *data);
|
||||
#else
|
||||
static inline void atl_fwd_release_rings(struct atl_nic *nic) {}
|
||||
static inline int atl_fwd_suspend_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline int atl_fwd_resume_rings(struct atl_nic *nic) { return 0; }
|
||||
static inline void atl_fwd_notify(struct atl_nic *nic,
|
||||
enum atl_fwd_notify notif, void *data) {}
|
||||
#endif
|
||||
|
||||
struct atl_ext_stats {
|
||||
struct atl_rx_ring_stats rx;
|
||||
struct atl_tx_ring_stats tx;
|
||||
struct atl_rx_fwd_ring_stats rx_fwd;
|
||||
|
||||
struct atl_ether_stats eth;
|
||||
};
|
||||
|
||||
/**
|
||||
* Direct statistics fetch call for the device
|
||||
*/
|
||||
int atl_get_ext_stats(struct net_device *ndev, struct atl_ext_stats *stats);
|
||||
|
||||
/**
|
||||
* Get the register and other crash related information from the device
|
||||
* If @crash_dump is NULL, function will return the requested length of the buffer to
|
||||
* store dump, in bytes
|
||||
* if @crash_dump is not null, function will fill the buffer with crashdump
|
||||
* sections filled, up to crash_dump->length
|
||||
*/
|
||||
int atl_get_crash_dump(struct net_device *ndev, struct atl_crash_dump *crash_dump);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "atl_fwdnl.h"
|
||||
|
||||
#include "atl_common.h"
|
||||
#include "atl_fwd.h"
|
||||
#include "atl_fwdnl_params.h"
|
||||
#include "atl_ring.h"
|
||||
#include "atl_trace.h"
|
||||
|
|
@ -1742,7 +1743,9 @@ static const struct nla_policy atlfwd_nl_policy[NUM_ATL_FWD_ATTR] = {
|
|||
[ATL_FWD_ATTR_QUEUE_INDEX] = { .type = NLA_S32 },
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) && \
|
||||
RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8, 0)
|
||||
#define ATLFWD_NL_OP_POLICY(op_policy) .policy = op_policy
|
||||
#else
|
||||
#define ATLFWD_NL_OP_POLICY(op_policy)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
|
||||
#include "atl_common.h"
|
||||
#include "atl_fwd.h"
|
||||
|
||||
unsigned int atlfwd_nl_tx_clean_threshold_msec = 200;
|
||||
unsigned int atlfwd_nl_tx_clean_threshold_frac = 8;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,16 @@ static void atl_set_promisc(struct atl_hw *hw, bool enabled, bool allmulti)
|
|||
}
|
||||
}
|
||||
|
||||
int atl_vlan_promisc_status(struct net_device *ndev)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
return ndev->flags & IFF_PROMISC ||
|
||||
nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active ||
|
||||
!(ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER);
|
||||
}
|
||||
|
||||
void atl_set_vlan_promisc(struct atl_hw *hw, int promisc)
|
||||
{
|
||||
atl_write_bit(hw, ATL_RX_VLAN_FLT_CTRL1, 1, !!promisc);
|
||||
|
|
@ -746,7 +756,7 @@ void atl_start_hw_global(struct atl_nic *nic)
|
|||
(tpb_size * 32 * 66 / 100) << 16 |
|
||||
(tpb_size * 32 * 50 / 100));
|
||||
/* 4-TC | Enable TPB */
|
||||
atl_set_bits(hw, ATL_TX_PBUF_CTRL1, BIT(8) | BIT(0));
|
||||
atl_set_bits(hw, ATL_TX_PBUF_CTRL1, BIT(8) | BIT(2) | BIT(0));
|
||||
/* TX Buffer clk gate off */
|
||||
if (hw->chip_id == ATL_ANTIGUA)
|
||||
atl_clear_bits(hw, ATL_TX_PBUF_CTRL1, BIT(5));
|
||||
|
|
@ -910,9 +920,7 @@ void atl_set_rx_mode(struct net_device *ndev)
|
|||
/* Enable promisc VLAN mode if IFF_PROMISC explicitly
|
||||
* requested or too many VIDs registered
|
||||
*/
|
||||
atl_set_vlan_promisc(hw,
|
||||
ndev->flags & IFF_PROMISC || nic->rxf_vlan.promisc_count ||
|
||||
!nic->rxf_vlan.vlans_active);
|
||||
atl_set_vlan_promisc(hw, atl_vlan_promisc_status(ndev));
|
||||
|
||||
atl_set_promisc(hw, promisc_needed,
|
||||
is_multicast_enabled && all_multi_needed);
|
||||
|
|
@ -1319,6 +1327,14 @@ static int __atl_fetch_msm2_stats(struct atl_hw *hw,
|
|||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_OCTETS_HI, ®2, hwsem_put);
|
||||
stats->tx_ether_octets = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_HI, ®2, hwsem_put);
|
||||
stats->tx_errors = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_HI, ®2, hwsem_put);
|
||||
stats->tx_errors += ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_HI, ®2, hwsem_put);
|
||||
stats->rx_pause = ((uint64_t)reg2 << 32) | reg;
|
||||
|
|
@ -1346,6 +1362,13 @@ static int __atl_fetch_msm2_stats(struct atl_hw *hw,
|
|||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ALIGN_ERRS_HI, ®2, hwsem_put);
|
||||
stats->rx_ether_crc_align_errs += ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ERRS_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ERRS_CNTR_HI, ®2, hwsem_put);
|
||||
stats->rx_errors = ((uint64_t)reg2 << 32) | reg;
|
||||
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_DROP_CNTR_LO, ®, hwsem_put);
|
||||
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_DROP_CNTR_HI, ®2, hwsem_put);
|
||||
stats->rx_drops = ((uint64_t)reg2 << 32) | reg;
|
||||
hwsem_put:
|
||||
atl_hwsem_put(hw, ATL_MCP_SEM_MSM);
|
||||
return ret;
|
||||
|
|
@ -1373,7 +1396,19 @@ int atl_update_eth_stats(struct atl_nic *nic)
|
|||
if (ret)
|
||||
goto unlock_fw;
|
||||
|
||||
stats.rx_ether_drops = atl_read(hw, ATL_RX_DMA_STATS_CNT7);
|
||||
stats.rx_dma_drops = atl_read(hw, ATL_RX_DMA_STATS_CNT7);
|
||||
|
||||
stats.rx_dma_packets = atl_read(hw, ATL_RX_DMA_STATS_CNT1);
|
||||
stats.rx_dma_packets += (uint64_t)atl_read(hw, ATL_RX_DMA_STATS_CNT2) << 32;
|
||||
|
||||
stats.rx_dma_octets = atl_read(hw, ATL_RX_DMA_STATS_CNT3);
|
||||
stats.rx_dma_octets += (uint64_t)atl_read(hw, ATL_RX_DMA_STATS_CNT4) << 32;
|
||||
|
||||
stats.tx_dma_packets = atl_read(hw, ATL_TX_DMA_STATS_CNT1);
|
||||
stats.tx_dma_packets += (uint64_t)atl_read(hw, ATL_RX_DMA_STATS_CNT2) << 32;
|
||||
|
||||
stats.tx_dma_octets = atl_read(hw, ATL_TX_DMA_STATS_CNT3);
|
||||
stats.tx_dma_octets += (uint64_t)atl_read(hw, ATL_TX_DMA_STATS_CNT4) << 32;
|
||||
|
||||
/* capture debug counters*/
|
||||
atl_write_bit(hw, ATL_RX_RPF_DBG_CNT_CTRL, 0x1f, 1);
|
||||
|
|
@ -1685,4 +1720,3 @@ static void atl2_hw_new_rx_filter_promisc(struct atl_hw *hw, bool promisc,
|
|||
off_action);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -241,6 +241,8 @@ void hw_atl_extract_hwts(struct atl_hw *hw, struct atl_rx_desc_hwts_wb *hwts_wb,
|
|||
sec += tmp;
|
||||
tmp = (u64)((hwts_wb->sec_hw >> 22) & 0x3ff) << 38;
|
||||
sec += tmp;
|
||||
if (sec == 0xffffffffffff && hwts_wb->ns == 0xffffffff)
|
||||
return;
|
||||
ns = sec * NSEC_PER_SEC + hwts_wb->ns;
|
||||
if (timestamp)
|
||||
*timestamp = ns + hw->ptp_clk_offset;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "atl_macsec.h"
|
||||
#if IS_ENABLED(CONFIG_MACSEC) && defined(NETIF_F_HW_MACSEC)
|
||||
#include "atl_common.h"
|
||||
#include "atl_fwd.h"
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "macsec/macsec_api.h"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include "atl_macsec.h"
|
||||
#include "atl_ptp.h"
|
||||
#include "atl_fwd.h"
|
||||
|
||||
const char atl_driver_name[] = "atlantic-fwd";
|
||||
|
||||
|
|
@ -384,7 +385,7 @@ int atl_do_reset(struct atl_nic *nic)
|
|||
|
||||
hw->mcp.ops->dump_cfg(hw);
|
||||
|
||||
atl_stop(nic, true);
|
||||
atl_stop(nic, false);
|
||||
|
||||
atl_fwd_suspend_rings(nic);
|
||||
|
||||
|
|
@ -765,9 +766,7 @@ static void atl_remove(struct pci_dev *pdev)
|
|||
atl_ptp_unregister(nic);
|
||||
unregister_netdev(nic->ndev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ATLFWD_FWD)
|
||||
atl_fwd_release_rings(nic);
|
||||
#endif
|
||||
|
||||
atl_clear_datapath(nic);
|
||||
|
||||
|
|
@ -948,6 +947,47 @@ static int atl_pm_runtime_idle(struct device *dev)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 0))
|
||||
static void atl_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct atl_nic *nic = pci_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_get_sync(&nic->hw.pdev->dev);
|
||||
rtnl_lock();
|
||||
|
||||
if (netif_running(nic->ndev))
|
||||
atl_stop(nic, false);
|
||||
|
||||
rtnl_unlock();
|
||||
pm_runtime_put_sync(&nic->hw.pdev->dev);
|
||||
}
|
||||
|
||||
static void atl_reset_done(struct pci_dev *pdev)
|
||||
{
|
||||
struct atl_nic *nic = pci_get_drvdata(pdev);
|
||||
|
||||
if (!nic) {
|
||||
dev_err(&pdev->dev, "%s failed, device is unrecoverable\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(&nic->hw.pdev->dev);
|
||||
rtnl_lock();
|
||||
|
||||
if (netif_running(nic->ndev))
|
||||
atl_start(nic);
|
||||
|
||||
rtnl_unlock();
|
||||
pm_runtime_put_sync(&nic->hw.pdev->dev);
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers atl_err_handlers = {
|
||||
.reset_prepare = atl_reset_prepare,
|
||||
.reset_done = atl_reset_done,
|
||||
};
|
||||
#endif
|
||||
|
||||
const struct dev_pm_ops atl_pm_ops = {
|
||||
.suspend = atl_suspend_poweroff,
|
||||
.poweroff = atl_suspend_poweroff,
|
||||
|
|
@ -968,6 +1008,11 @@ static struct pci_driver atl_pci_ops = {
|
|||
#ifdef CONFIG_PM
|
||||
.driver.pm = &atl_pm_ops,
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 13, 0))
|
||||
.err_handler = &atl_err_handlers,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct atl_thermal atl_def_thermal;
|
||||
|
|
|
|||
|
|
@ -893,8 +893,13 @@ void atl_ptp_tx_hwtstamp(struct atl_nic *nic, u64 timestamp)
|
|||
return;
|
||||
}
|
||||
|
||||
timestamp += atomic_read(&ptp->offset_egress);
|
||||
atl_ptp_convert_to_hwtstamp(&hwtstamp, timestamp);
|
||||
if (!timestamp) {
|
||||
atl_nic_err("ptp timestamp all-F from FW\n");
|
||||
memset(&hwtstamp, 0, sizeof(hwtstamp));
|
||||
} else {
|
||||
timestamp += atomic_read(&ptp->offset_egress);
|
||||
atl_ptp_convert_to_hwtstamp(&hwtstamp, timestamp);
|
||||
}
|
||||
do {
|
||||
skb_tstamp_tx(skb, &hwtstamp);
|
||||
dev_kfree_skb_any(skb);
|
||||
|
|
|
|||
|
|
@ -176,8 +176,17 @@ enum mcp_scratchpad {
|
|||
#define ATL_RX_RING_BUF_SIZE(ring) ATL_RING_OFFT(ring, 0x18)
|
||||
#define ATL_RX_RING_THRESH(ring) ATL_RING_OFFT(ring, 0x1c)
|
||||
|
||||
#define ATL_RX_DMA_STATS_CNT1 0x6800
|
||||
#define ATL_RX_DMA_STATS_CNT2 0x6804
|
||||
#define ATL_RX_DMA_STATS_CNT3 0x6808
|
||||
#define ATL_RX_DMA_STATS_CNT4 0x680C
|
||||
#define ATL_RX_DMA_STATS_CNT7 0x6818
|
||||
|
||||
#define ATL_TX_DMA_STATS_CNT1 0x8800
|
||||
#define ATL_TX_DMA_STATS_CNT2 0x8804
|
||||
#define ATL_TX_DMA_STATS_CNT3 0x8808
|
||||
#define ATL_TX_DMA_STATS_CNT4 0x880C
|
||||
|
||||
/* TX @ 0x7000 */
|
||||
#define ATL_TX_CTRL1 0x7000
|
||||
#define ATL_TX_PO_CTRL1 0x7800
|
||||
|
|
@ -224,6 +233,10 @@ enum mcp_scratchpad {
|
|||
#define ATL_MSM_CTR_RX_ERRS 0x120
|
||||
|
||||
|
||||
#define ATL_MSM2_CTR_RX_DROP_CNTR_LO 0x158
|
||||
#define ATL_MSM2_CTR_RX_DROP_CNTR_HI 0x15C
|
||||
#define ATL_MSM2_CTR_RX_ERRS_CNTR_LO 0x138
|
||||
#define ATL_MSM2_CTR_RX_ERRS_CNTR_HI 0x13C
|
||||
#define ATL_MSM2_CTR_RX_OCTETS_LO 0x100
|
||||
#define ATL_MSM2_CTR_RX_OCTETS_HI 0x104
|
||||
#define ATL_MSM2_CTR_RX_ALIGN_ERRS_LO 0x110
|
||||
|
|
@ -245,5 +258,9 @@ enum mcp_scratchpad {
|
|||
#define ATL_MSM2_CTR_TX_PKTS_LO 0x220
|
||||
#define ATL_MSM2_CTR_TX_PKTS_HI 0x224
|
||||
|
||||
#define ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_LO 0x228
|
||||
#define ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_HI 0x22C
|
||||
#define ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_LO 0x238
|
||||
#define ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_HI 0x23C
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -244,6 +244,14 @@ static uint32_t atl_insert_context(struct atl_txbuf *txbuf,
|
|||
return tx_cmd;
|
||||
}
|
||||
|
||||
static bool atl_ptp_udp(struct sk_buff *skb)
|
||||
{
|
||||
return (ip_hdr(skb)->version == 4) &&
|
||||
(ip_hdr(skb)->protocol == IPPROTO_UDP) &&
|
||||
((udp_hdr(skb)->dest == htons(319)) ||
|
||||
(udp_hdr(skb)->dest == htons(320)));
|
||||
}
|
||||
|
||||
netdev_tx_t atl_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
{
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
|
@ -257,12 +265,9 @@ netdev_tx_t atl_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
* and hardware PTP design of the chip. Otherwise ptp stream
|
||||
* will fail to sync
|
||||
*/
|
||||
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
|
||||
unlikely((ip_hdr(skb)->version == 4) &&
|
||||
(ip_hdr(skb)->protocol == IPPROTO_UDP) &&
|
||||
((udp_hdr(skb)->dest == htons(319)) ||
|
||||
(udp_hdr(skb)->dest == htons(320)))) ||
|
||||
unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588)))
|
||||
if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
|
||||
atl_ptp_udp(skb) ||
|
||||
(eth_hdr(skb)->h_proto == htons(ETH_P_1588))))
|
||||
return atl_ptp_start_xmit(nic, skb);
|
||||
}
|
||||
|
||||
|
|
@ -448,7 +453,7 @@ static bool atl_checksum_workaround(struct sk_buff *skb,
|
|||
|
||||
if (((desc->pkt_type & atl_rx_pkt_type_vlan_msk) ==
|
||||
atl_rx_pkt_type_vlan) &&
|
||||
!(desc->rx_estat & atl_rx_estat_vlan_stripped))
|
||||
!(desc->rx_estat & atl_rx_estat_vlan_stripped))
|
||||
ip_header_offset += sizeof(struct vlan_hdr);
|
||||
|
||||
if ((desc->pkt_type & atl_rx_pkt_type_vlan_msk) ==
|
||||
|
|
@ -773,6 +778,9 @@ static int atl_fill_hwts_rx(struct atl_desc_ring *ring, uint32_t count, bool ato
|
|||
count--;
|
||||
}
|
||||
|
||||
wmb();
|
||||
atl_write(ring_hw(ring), ATL_RX_RING_TAIL(ring), ring->tail);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1208,7 +1216,7 @@ int atl_clean_hwts_rx(struct atl_desc_ring *ring, int budget)
|
|||
uint32_t space = ring_space(ring);
|
||||
struct atl_rx_desc_hwts_wb *wb;
|
||||
struct atl_rxbuf *rxbuf;
|
||||
u64 ns;
|
||||
u64 ns = 0;
|
||||
DECLARE_SCRATCH_DESC(scratch);
|
||||
|
||||
if (space >= refill_batch)
|
||||
|
|
@ -2104,9 +2112,15 @@ void atl_stop_rings(struct atl_nic *nic)
|
|||
int atl_set_features(struct net_device *ndev, netdev_features_t features)
|
||||
{
|
||||
netdev_features_t changed = ndev->features ^ features;
|
||||
struct atl_nic *nic = netdev_priv(ndev);
|
||||
|
||||
ndev->features = features;
|
||||
|
||||
if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
|
||||
atl_set_vlan_promisc(&nic->hw,
|
||||
atl_vlan_promisc_status(ndev));
|
||||
}
|
||||
|
||||
if (changed & NETIF_F_LRO)
|
||||
atl_set_lro(netdev_priv(ndev));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ struct atl_rx_fwd_ring_stats {
|
|||
struct atl_tx_ring_stats {
|
||||
uint64_t packets;
|
||||
uint64_t bytes;
|
||||
uint64_t tx_busy;
|
||||
uint64_t tx_busy; /* number of times ring was full and tx failed */
|
||||
uint64_t tx_restart;
|
||||
uint64_t dma_map_failed;
|
||||
};
|
||||
|
|
@ -55,8 +55,8 @@ struct atl_ether_stats {
|
|||
uint64_t tx_pause;
|
||||
uint64_t tx_ether_pkts;
|
||||
uint64_t tx_ether_octets;
|
||||
uint64_t tx_errors; /* from MSM block */
|
||||
uint64_t rx_pause;
|
||||
uint64_t rx_ether_drops;
|
||||
uint64_t rx_ether_octets;
|
||||
uint64_t rx_ether_pkts;
|
||||
uint64_t rx_ether_broacasts;
|
||||
|
|
@ -64,6 +64,13 @@ struct atl_ether_stats {
|
|||
uint64_t rx_ether_crc_align_errs;
|
||||
uint64_t rx_filter_host;
|
||||
uint64_t rx_filter_lost;
|
||||
uint64_t rx_errors; /* from MSM block */
|
||||
uint64_t rx_drops; /* from MSM block */
|
||||
uint64_t rx_dma_packets;
|
||||
uint64_t rx_dma_octets;
|
||||
uint64_t rx_dma_drops; /* DMA level RX drops */
|
||||
uint64_t tx_dma_packets;
|
||||
uint64_t tx_dma_octets;
|
||||
};
|
||||
|
||||
struct atl_global_stats {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,38 @@
|
|||
Version 1.1.22
|
||||
Date 11/10/2021
|
||||
==============
|
||||
- Fixed header file and warning complains
|
||||
|
||||
Version 1.1.21
|
||||
Date 29/09/2021
|
||||
==============
|
||||
- Atl-fwd: Fix name string for mac_phy stats in ethtool-dump
|
||||
- Atl-fwd: Minor additions to ethtool dump implementation
|
||||
- Atl-fwd: Add ethtool-dump parser
|
||||
- ATLDRV-1776: Fix for link flip during IPA ring reconfig
|
||||
- Atl-fwd: Update crash-dump structure to fixed size structure
|
||||
|
||||
Version 1.1.20
|
||||
Date 23/08/2021
|
||||
==============
|
||||
- Atl-fwd: Correct driver README file and export couple of APIs
|
||||
- Atl-fwd: Populate Action resolve table and Ring data in the ethtool-dump
|
||||
- ATLDRV-1766: Fix to update HWTS ring tail value to HW
|
||||
- Fix error in populating the extended stats
|
||||
- AQC113 register dump support
|
||||
- stats+crashdump implementation draft
|
||||
- Statistics and crash dump API proposal
|
||||
- factor out fwd stuff to drop headers dependencies
|
||||
|
||||
Version 1.1.19
|
||||
Date 12/07/2021
|
||||
==============
|
||||
[ATLDRV-1744] - Add FW version check in Atl-fwd driver
|
||||
- Move check for PTP UDP packets to separate function, Enable TX pad insert and Handle all FFs in ptp tx TS
|
||||
[ATLDRV-1582] - Link not Up after FLR reset
|
||||
[ATLDRV-1653] - Packet with vlan id 1 doesn't get received when rx vlan filter is disabled
|
||||
[ATLDRV-1659] - Failed to compile with CONFIG_ATLFWD_FWD=y flag on RHEL 8.3 kernel
|
||||
|
||||
Version 1.1.18
|
||||
Date 21/02/2021
|
||||
==============
|
||||
|
|
|
|||
Loading…
Reference in a new issue