Merge "atlantic forwarding driver v1.1.22"

This commit is contained in:
qctecmdr 2022-01-22 22:25:45 -08:00 • committed by Gerrit - the friendly Code Review server
commit 3035689d90
21 changed files with 973 additions and 57 deletions

View file

@ -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);

View file

@ -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);

View 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

View file

@ -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.

View file

@ -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;
}

View file

@ -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

View file

@ -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,
};

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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, &reg2, 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, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FCS_ERRS_CNTR_HI, &reg2, hwsem_put);
stats->tx_errors = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_TX_FIFO_ERRS_CNTR_HI, &reg2, hwsem_put);
stats->tx_errors += ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_PAUSE_HI, &reg2, 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, &reg2, 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, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_ERRS_CNTR_HI, &reg2, hwsem_put);
stats->rx_errors = ((uint64_t)reg2 << 32) | reg;
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_DROP_CNTR_LO, &reg, hwsem_put);
__READ_MSM_OR_GOTO(ret, hw, ATL_MSM2_CTR_RX_DROP_CNTR_HI, &reg2, 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);
}

View file

@ -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;

View file

@ -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"

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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));

View file

@ -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 {

View file

@ -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
==============