Commit 36195d86 authored by David S. Miller's avatar David S. Miller

Merge branch 'liquidio-next'

Raghu Vatsavayi says:

====================
liquidio: updates and bug fixes

Please consider following patch series for liquidio bug fixes
and updates on top of net-next. Following patches should be
applied in the following order as some of them depend on
earlier patches in the series.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b38066da 4b129ae3
......@@ -367,7 +367,8 @@ void lio_cn6xxx_enable_io_queues(struct octeon_device *oct)
void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
{
u32 mask, i, loop = HZ;
int i;
u32 mask, loop = HZ;
u32 d32;
/* Reset the Enable bits for Input Queues. */
......@@ -376,7 +377,7 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, mask);
/* Wait until hardware indicates that the queues are out of reset. */
mask = oct->io_qmask.iq;
mask = (u32)oct->io_qmask.iq;
d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_IQ);
while (((d32 & mask) != mask) && loop--) {
d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_IQ);
......@@ -384,8 +385,8 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
}
/* Reset the doorbell register for each Input queue. */
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES; i++) {
if (!(oct->io_qmask.iq & (1UL << i)))
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
if (!(oct->io_qmask.iq & (1ULL << i)))
continue;
octeon_write_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i), 0xFFFFFFFF);
d32 = octeon_read_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i));
......@@ -398,7 +399,7 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
/* Wait until hardware indicates that the queues are out of reset. */
loop = HZ;
mask = oct->io_qmask.oq;
mask = (u32)oct->io_qmask.oq;
d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_OQ);
while (((d32 & mask) != mask) && loop--) {
d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_OQ);
......@@ -408,8 +409,8 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
/* Reset the doorbell register for each Output queue. */
/* for (i = 0; i < oct->num_oqs; i++) { */
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES; i++) {
if (!(oct->io_qmask.oq & (1UL << i)))
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
if (!(oct->io_qmask.oq & (1ULL << i)))
continue;
octeon_write_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i), 0xFFFFFFFF);
d32 = octeon_read_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i));
......@@ -429,16 +430,16 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
void lio_cn6xxx_reinit_regs(struct octeon_device *oct)
{
u32 i;
int i;
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES; i++) {
if (!(oct->io_qmask.iq & (1UL << i)))
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
if (!(oct->io_qmask.iq & (1ULL << i)))
continue;
oct->fn_list.setup_iq_regs(oct, i);
}
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES; i++) {
if (!(oct->io_qmask.oq & (1UL << i)))
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
if (!(oct->io_qmask.oq & (1ULL << i)))
continue;
oct->fn_list.setup_oq_regs(oct, i);
}
......@@ -450,8 +451,8 @@ void lio_cn6xxx_reinit_regs(struct octeon_device *oct)
oct->fn_list.enable_io_queues(oct);
/* for (i = 0; i < oct->num_oqs; i++) { */
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES; i++) {
if (!(oct->io_qmask.oq & (1UL << i)))
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
if (!(oct->io_qmask.oq & (1ULL << i)))
continue;
writel(oct->droq[i]->max_count, oct->droq[i]->pkts_credit_reg);
}
......@@ -495,8 +496,7 @@ u32 lio_cn6xxx_bar1_idx_read(struct octeon_device *oct, u32 idx)
}
u32
lio_cn6xxx_update_read_index(struct octeon_device *oct __attribute__((unused)),
struct octeon_instr_queue *iq)
lio_cn6xxx_update_read_index(struct octeon_instr_queue *iq)
{
u32 new_idx = readl(iq->inst_cnt_reg);
......@@ -557,7 +557,8 @@ lio_cn6xxx_process_pcie_error_intr(struct octeon_device *oct, u64 intr64)
int lio_cn6xxx_process_droq_intr_regs(struct octeon_device *oct)
{
struct octeon_droq *droq;
u32 oq_no, pkt_count, droq_time_mask, droq_mask, droq_int_enb;
int oq_no;
u32 pkt_count, droq_time_mask, droq_mask, droq_int_enb;
u32 droq_cnt_enb, droq_cnt_mask;
droq_cnt_enb = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB);
......@@ -573,8 +574,8 @@ int lio_cn6xxx_process_droq_intr_regs(struct octeon_device *oct)
oct->droq_intr = 0;
/* for (oq_no = 0; oq_no < oct->num_oqs; oq_no++) { */
for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES; oq_no++) {
if (!(droq_mask & (1 << oq_no)))
for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES(oct); oq_no++) {
if (!(droq_mask & (1ULL << oq_no)))
continue;
droq = oct->droq[oq_no];
......
......@@ -91,8 +91,7 @@ void lio_cn6xxx_bar1_idx_setup(struct octeon_device *oct, u64 core_addr,
void lio_cn6xxx_bar1_idx_write(struct octeon_device *oct, u32 idx, u32 mask);
u32 lio_cn6xxx_bar1_idx_read(struct octeon_device *oct, u32 idx);
u32
lio_cn6xxx_update_read_index(struct octeon_device *oct __attribute__((unused)),
struct octeon_instr_queue *iq);
lio_cn6xxx_update_read_index(struct octeon_instr_queue *iq);
void lio_cn6xxx_enable_interrupt(void *chip);
void lio_cn6xxx_disable_interrupt(void *chip);
void cn6xxx_get_pcie_qlmport(struct octeon_device *oct);
......
......@@ -30,11 +30,10 @@
#include "octeon_config.h"
#define LIQUIDIO_VERSION "1.1.9"
#define LIQUIDIO_MAJOR_VERSION 1
#define LIQUIDIO_MINOR_VERSION 1
#define LIQUIDIO_MICRO_VERSION 9
#define LIQUIDIO_BASE_VERSION "1.4"
#define LIQUIDIO_MICRO_VERSION ".1"
#define LIQUIDIO_PACKAGE ""
#define LIQUIDIO_VERSION "1.4.1"
#define CONTROL_IQ 0
/** Tag types used by Octeon cores in its work. */
enum octeon_tag_type {
......@@ -214,6 +213,10 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry,
#define OCTNET_CMD_VERBOSE_ENABLE 0x14
#define OCTNET_CMD_VERBOSE_DISABLE 0x15
#define OCTNET_CMD_ENABLE_VLAN_FILTER 0x16
#define OCTNET_CMD_ADD_VLAN_FILTER 0x17
#define OCTNET_CMD_DEL_VLAN_FILTER 0x18
/* RX(packets coming from wire) Checksum verification flags */
/* TCP/UDP csum */
#define CNNIC_L4SUM_VERIFIED 0x1
......@@ -482,15 +485,15 @@ struct octeon_instr_irh {
u64 opcode:4;
u64 rflag:1;
u64 subcode:7;
u64 len:3;
u64 rid:13;
u64 reserved:4;
u64 vlan:12;
u64 priority:3;
u64 reserved:5;
u64 ossp:32; /* opcode/subcode specific parameters */
#else
u64 ossp:32; /* opcode/subcode specific parameters */
u64 reserved:4;
u64 rid:13;
u64 len:3;
u64 reserved:5;
u64 priority:3;
u64 vlan:12;
u64 subcode:7;
u64 rflag:1;
u64 opcode:4;
......@@ -517,28 +520,27 @@ union octeon_rh {
struct {
u64 opcode:4;
u64 subcode:8;
u64 len:3; /** additional 64-bit words */
u64 rid:13; /** request id in response to pkt sent by host */
u64 reserved:4;
u64 ossp:32; /** opcode/subcode specific parameters */
u64 len:3; /** additional 64-bit words */
u64 reserved:17;
u64 ossp:32; /** opcode/subcode specific parameters */
} r;
struct {
u64 opcode:4;
u64 subcode:8;
u64 len:3; /** additional 64-bit words */
u64 rid:13; /** request id in response to pkt sent by host */
u64 extra:24;
u64 link:8;
u64 len:3; /** additional 64-bit words */
u64 extra:28;
u64 vlan:12;
u64 priority:3;
u64 csum_verified:3; /** checksum verified. */
u64 has_hwtstamp:1; /** Has hardware timestamp. 1 = yes. */
} r_dh;
struct {
u64 opcode:4;
u64 subcode:8;
u64 len:3; /** additional 64-bit words */
u64 rid:13; /** request id in response to pkt sent by host */
u64 len:3; /** additional 64-bit words */
u64 reserved:11;
u64 num_gmx_ports:8;
u64 max_nic_ports:8;
u64 max_nic_ports:10;
u64 app_cap_flags:4;
u64 app_mode:16;
} r_core_drv_init;
......@@ -554,8 +556,7 @@ union octeon_rh {
u64 u64;
struct {
u64 ossp:32; /** opcode/subcode specific parameters */
u64 reserved:4;
u64 rid:13; /** req id in response to pkt sent by host */
u64 reserved:17;
u64 len:3; /** additional 64-bit words */
u64 subcode:8;
u64 opcode:4;
......@@ -563,9 +564,9 @@ union octeon_rh {
struct {
u64 has_hwtstamp:1; /** 1 = has hwtstamp */
u64 csum_verified:3; /** checksum verified. */
u64 link:8;
u64 extra:24;
u64 rid:13; /** req id in response to pkt sent by host */
u64 priority:3;
u64 vlan:12;
u64 extra:28;
u64 len:3; /** additional 64-bit words */
u64 subcode:8;
u64 opcode:4;
......@@ -573,9 +574,9 @@ union octeon_rh {
struct {
u64 app_mode:16;
u64 app_cap_flags:4;
u64 max_nic_ports:8;
u64 max_nic_ports:10;
u64 num_gmx_ports:8;
u64 rid:13;
u64 reserved:11;
u64 len:3; /** additional 64-bit words */
u64 subcode:8;
u64 opcode:4;
......@@ -627,13 +628,13 @@ union oct_link_status {
u64 speed:16;
u64 link_up:1;
u64 autoneg:1;
u64 interface:4;
u64 if_mode:5;
u64 pause:1;
u64 reserved:17;
u64 reserved:16;
#else
u64 reserved:17;
u64 reserved:16;
u64 pause:1;
u64 interface:4;
u64 if_mode:5;
u64 autoneg:1;
u64 link_up:1;
u64 speed:16;
......@@ -710,6 +711,7 @@ struct liquidio_if_cfg_info {
u64 iqmask; /** mask for IQs enabled for the port */
u64 oqmask; /** mask for OQs enabled for the port */
struct oct_link_info linfo; /** initial link information */
char liquidio_firmware_version[32];
};
/** Stats for each NIC port in RX direction. */
......@@ -734,10 +736,16 @@ struct nic_rx_stats {
u64 fw_err_pko;
u64 fw_err_link;
u64 fw_err_drop;
/* LRO */
u64 fw_lro_pkts; /* Number of packets that are LROed */
u64 fw_lro_octs; /* Number of octets that are LROed */
u64 fw_total_lro; /* Number of LRO packets formed */
u64 fw_lro_aborts; /* Number of times lRO of packet aborted */
u64 fw_lro_aborts_port;
u64 fw_lro_aborts_seq;
u64 fw_lro_aborts_tsval;
u64 fw_lro_aborts_timer;
/* intrmod: packet forward rate */
u64 fwd_rate;
};
......@@ -761,9 +769,13 @@ struct nic_tx_stats {
/* firmware stats */
u64 fw_total_sent;
u64 fw_total_fwd;
u64 fw_total_fwd_bytes;
u64 fw_err_pko;
u64 fw_err_link;
u64 fw_err_drop;
u64 fw_err_tso;
u64 fw_tso; /* number of tso requests */
u64 fw_tso_fwd; /* number of packets segmented in tso */
};
struct oct_link_stats {
......@@ -794,23 +806,44 @@ struct oct_mdio_cmd {
#define OCT_LINK_STATS_SIZE (sizeof(struct oct_link_stats))
/* intrmod: max. packet rate threshold */
#define LIO_INTRMOD_MAXPKT_RATETHR 196608
/* intrmod: min. packet rate threshold */
#define LIO_INTRMOD_MINPKT_RATETHR 9216
/* intrmod: max. packets to trigger interrupt */
#define LIO_INTRMOD_RXMAXCNT_TRIGGER 384
/* intrmod: min. packets to trigger interrupt */
#define LIO_INTRMOD_RXMINCNT_TRIGGER 1
/* intrmod: max. time to trigger interrupt */
#define LIO_INTRMOD_RXMAXTMR_TRIGGER 128
/* 66xx:intrmod: min. time to trigger interrupt
* (value of 1 is optimum for TCP_RR)
*/
#define LIO_INTRMOD_RXMINTMR_TRIGGER 1
/* intrmod: max. packets to trigger interrupt */
#define LIO_INTRMOD_TXMAXCNT_TRIGGER 64
/* intrmod: min. packets to trigger interrupt */
#define LIO_INTRMOD_TXMINCNT_TRIGGER 0
/* intrmod: poll interval in seconds */
#define LIO_INTRMOD_CHECK_INTERVAL 1
#define LIO_INTRMOD_MAXPKT_RATETHR 196608 /* max pkt rate threshold */
#define LIO_INTRMOD_MINPKT_RATETHR 9216 /* min pkt rate threshold */
#define LIO_INTRMOD_MAXCNT_TRIGGER 384 /* max pkts to trigger interrupt */
#define LIO_INTRMOD_MINCNT_TRIGGER 1 /* min pkts to trigger interrupt */
#define LIO_INTRMOD_MAXTMR_TRIGGER 128 /* max time to trigger interrupt */
#define LIO_INTRMOD_MINTMR_TRIGGER 32 /* min time to trigger interrupt */
struct oct_intrmod_cfg {
u64 intrmod_enable;
u64 intrmod_check_intrvl;
u64 intrmod_maxpkt_ratethr;
u64 intrmod_minpkt_ratethr;
u64 intrmod_maxcnt_trigger;
u64 intrmod_maxtmr_trigger;
u64 intrmod_mincnt_trigger;
u64 intrmod_mintmr_trigger;
u64 rx_enable;
u64 tx_enable;
u64 check_intrvl;
u64 maxpkt_ratethr;
u64 minpkt_ratethr;
u64 rx_maxcnt_trigger;
u64 rx_mincnt_trigger;
u64 rx_maxtmr_trigger;
u64 rx_mintmr_trigger;
u64 tx_mincnt_trigger;
u64 tx_maxcnt_trigger;
u64 rx_frames;
u64 tx_frames;
u64 rx_usecs;
};
#define BASE_QUEUE_NOT_REQUESTED 65535
......
......@@ -37,7 +37,7 @@
/* Maximum octeon devices defined as MAX_OCTEON_NICIF to support
* multiple(<= MAX_OCTEON_NICIF) Miniports
*/
#define MAX_OCTEON_NICIF 32
#define MAX_OCTEON_NICIF 128
#define MAX_OCTEON_DEVICES MAX_OCTEON_NICIF
#define MAX_OCTEON_LINKS MAX_OCTEON_NICIF
#define MAX_OCTEON_MULTICAST_ADDR 32
......@@ -135,7 +135,7 @@
#define CFG_GET_IS_SLI_BP_ON(cfg) ((cfg)->misc.enable_sli_oq_bp)
/* Max IOQs per OCTEON Link */
#define MAX_IOQS_PER_NICIF 32
#define MAX_IOQS_PER_NICIF 64
enum lio_card_type {
LIO_210SV = 0, /* Two port, 66xx */
......@@ -416,9 +416,11 @@ struct octeon_config {
#define DISPATCH_LIST_SIZE BIT(OPCODE_MASK_BITS)
/* Maximum number of Octeon Instruction (command) queues */
#define MAX_OCTEON_INSTR_QUEUES CN6XXX_MAX_INPUT_QUEUES
#define MAX_OCTEON_INSTR_QUEUES(oct) CN6XXX_MAX_INPUT_QUEUES
/* Maximum number of Octeon Output queues */
#define MAX_OCTEON_OUTPUT_QUEUES(oct) CN6XXX_MAX_OUTPUT_QUEUES
/* Maximum number of Octeon Instruction (command) queues */
#define MAX_OCTEON_OUTPUT_QUEUES CN6XXX_MAX_OUTPUT_QUEUES
#define MAX_POSSIBLE_OCTEON_INSTR_QUEUES CN6XXX_MAX_INPUT_QUEUES
#define MAX_POSSIBLE_OCTEON_OUTPUT_QUEUES CN6XXX_MAX_OUTPUT_QUEUES
#endif /* __OCTEON_CONFIG_H__ */
......@@ -549,17 +549,19 @@ static char *get_oct_app_string(u32 app_mode)
return oct_dev_app_str[CVM_DRV_INVALID_APP - CVM_DRV_APP_START];
}
u8 fbuf[4 * 1024 * 1024];
int octeon_download_firmware(struct octeon_device *oct, const u8 *data,
size_t size)
{
int ret = 0;
u8 *p;
u8 *buffer;
u8 *p = fbuf;
u32 crc32_result;
u64 load_addr;
u32 image_len;
struct octeon_firmware_file_header *h;
u32 i;
u32 i, rem, base_len = strlen(LIQUIDIO_BASE_VERSION);
char *base;
if (size < sizeof(struct octeon_firmware_file_header)) {
dev_err(&oct->pci_dev->dev, "Firmware file too small (%d < %d).\n",
......@@ -575,19 +577,26 @@ int octeon_download_firmware(struct octeon_device *oct, const u8 *data,
return -EINVAL;
}
crc32_result =
crc32(~0, data,
sizeof(struct octeon_firmware_file_header) -
sizeof(u32)) ^ ~0U;
crc32_result = crc32((unsigned int)~0, data,
sizeof(struct octeon_firmware_file_header) -
sizeof(u32)) ^ ~0U;
if (crc32_result != be32_to_cpu(h->crc32)) {
dev_err(&oct->pci_dev->dev, "Firmware CRC mismatch (0x%08x != 0x%08x).\n",
crc32_result, be32_to_cpu(h->crc32));
return -EINVAL;
}
if (memcmp(LIQUIDIO_VERSION, h->version, strlen(LIQUIDIO_VERSION))) {
dev_err(&oct->pci_dev->dev, "Unmatched firmware version. Expected %s, got %s.\n",
LIQUIDIO_VERSION, h->version);
if (strncmp(LIQUIDIO_PACKAGE, h->version, strlen(LIQUIDIO_PACKAGE))) {
dev_err(&oct->pci_dev->dev, "Unmatched firmware package type. Expected %s, got %s.\n",
LIQUIDIO_PACKAGE, h->version);
return -EINVAL;
}
base = h->version + strlen(LIQUIDIO_PACKAGE);
ret = memcmp(LIQUIDIO_BASE_VERSION, base, base_len);
if (ret) {
dev_err(&oct->pci_dev->dev, "Unmatched firmware version. Expected %s.x, got %s.\n",
LIQUIDIO_BASE_VERSION, base);
return -EINVAL;
}
......@@ -601,56 +610,56 @@ int octeon_download_firmware(struct octeon_device *oct, const u8 *data,
snprintf(oct->fw_info.liquidio_firmware_version, 32, "LIQUIDIO: %s",
h->version);
buffer = kmemdup(data, size, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
p = buffer + sizeof(struct octeon_firmware_file_header);
data += sizeof(struct octeon_firmware_file_header);
dev_info(&oct->pci_dev->dev, "%s: Loading %d images\n", __func__,
be32_to_cpu(h->num_images));
/* load all images */
for (i = 0; i < be32_to_cpu(h->num_images); i++) {
load_addr = be64_to_cpu(h->desc[i].addr);
image_len = be32_to_cpu(h->desc[i].len);
/* validate the image */
crc32_result = crc32(~0, p, image_len) ^ ~0U;
if (crc32_result != be32_to_cpu(h->desc[i].crc32)) {
dev_err(&oct->pci_dev->dev,
"Firmware CRC mismatch in image %d (0x%08x != 0x%08x).\n",
i, crc32_result,
be32_to_cpu(h->desc[i].crc32));
ret = -EINVAL;
goto done_downloading;
}
dev_info(&oct->pci_dev->dev, "Loading firmware %d at %llx\n",
image_len, load_addr);
/* download the image */
octeon_pci_write_core_mem(oct, load_addr, p, image_len);
/* Write in 4MB chunks*/
rem = image_len;
p += image_len;
dev_dbg(&oct->pci_dev->dev,
"Downloaded image %d (%d bytes) to address 0x%016llx\n",
i, image_len, load_addr);
while (rem) {
if (rem < (4 * 1024 * 1024))
size = rem;
else
size = 4 * 1024 * 1024;
memcpy(p, data, size);
/* download the image */
octeon_pci_write_core_mem(oct, load_addr, p, (u32)size);
data += size;
rem -= (u32)size;
load_addr += size;
}
}
dev_info(&oct->pci_dev->dev, "Writing boot command: %s\n",
h->bootcmd);
/* Invoke the bootcmd */
ret = octeon_console_send_cmd(oct, h->bootcmd, 50);
done_downloading:
kfree(buffer);
return ret;
return 0;
}
void octeon_free_device_mem(struct octeon_device *oct)
{
u32 i;
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES; i++) {
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
/* could check mask as well */
vfree(oct->droq[i]);
}
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES; i++) {
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
/* could check mask as well */
vfree(oct->instr_queue[i]);
}
......@@ -734,7 +743,7 @@ struct octeon_device *octeon_allocate_device(u32 pci_id,
octeon_device[oct_idx] = oct;
oct->octeon_id = oct_idx;
snprintf((oct->device_name), sizeof(oct->device_name),
snprintf(oct->device_name, sizeof(oct->device_name),
"LiquidIO%d", (oct->octeon_id));
return oct;
......@@ -1157,8 +1166,8 @@ int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf)
int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
{
if (oct && (q_no < MAX_OCTEON_INSTR_QUEUES) &&
(oct->io_qmask.iq & (1UL << q_no)))
if (oct && (q_no < MAX_OCTEON_INSTR_QUEUES(oct)) &&
(oct->io_qmask.iq & (1ULL << q_no)))
return oct->instr_queue[q_no]->max_count;
return -1;
......@@ -1166,8 +1175,8 @@ int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
{
if (oct && (q_no < MAX_OCTEON_OUTPUT_QUEUES) &&
(oct->io_qmask.oq & (1UL << q_no)))
if (oct && (q_no < MAX_OCTEON_OUTPUT_QUEUES(oct)) &&
(oct->io_qmask.oq & (1ULL << q_no)))
return oct->droq[q_no]->max_count;
return -1;
}
......@@ -1258,10 +1267,10 @@ void lio_pci_writeq(struct octeon_device *oct,
int octeon_mem_access_ok(struct octeon_device *oct)
{
u64 access_okay = 0;
u64 lmc0_reset_ctl;
/* Check to make sure a DDR interface is enabled */
u64 lmc0_reset_ctl = lio_pci_readq(oct, CN6XXX_LMC0_RESET_CTL);
lmc0_reset_ctl = lio_pci_readq(oct, CN6XXX_LMC0_RESET_CTL);
access_okay = (lmc0_reset_ctl & CN6XXX_LMC0_RESET_CTL_DDR3RST_MASK);
return access_okay ? 0 : 1;
......@@ -1275,9 +1284,6 @@ int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout)
if (!timeout)
return ret;
while (*timeout == 0)
schedule_timeout_uninterruptible(HZ / 10);
for (ms = 0; (ret != 0) && ((*timeout == 0) || (ms <= *timeout));
ms += HZ / 10) {
ret = octeon_mem_access_ok(oct);
......
......@@ -152,9 +152,9 @@ struct octeon_mmio {
#define MAX_OCTEON_MAPS 32
struct octeon_io_enable {
u32 iq;
u32 oq;
u32 iq64B;
u64 iq;
u64 oq;
u64 iq64B;
};
struct octeon_reg_list {
......@@ -204,8 +204,7 @@ struct octeon_fn_list {
void (*bar1_idx_setup)(struct octeon_device *, u64, u32, int);
void (*bar1_idx_write)(struct octeon_device *, u32, u32);
u32 (*bar1_idx_read)(struct octeon_device *, u32);
u32 (*update_iq_read_idx)(struct octeon_device *,
struct octeon_instr_queue *);
u32 (*update_iq_read_idx)(struct octeon_instr_queue *);
void (*enable_oq_pkt_time_intr)(struct octeon_device *, u32);
void (*disable_oq_pkt_time_intr)(struct octeon_device *, u32);
......@@ -267,6 +266,7 @@ struct octdev_props {
/* Each interface in the Octeon device has a network
* device pointer (used for OS specific calls).
*/
int napi_enabled;
int gmxport;
struct net_device *netdev;
};
......@@ -325,7 +325,8 @@ struct octeon_device {
struct octeon_sc_buffer_pool sc_buf_pool;
/** The input instruction queues */
struct octeon_instr_queue *instr_queue[MAX_OCTEON_INSTR_QUEUES];
struct octeon_instr_queue *instr_queue
[MAX_POSSIBLE_OCTEON_INSTR_QUEUES];
/** The doubly-linked list of instruction response */
struct octeon_response_list response_list[MAX_RESPONSE_LISTS];
......@@ -333,7 +334,7 @@ struct octeon_device {
u32 num_oqs;
/** The DROQ output queues */
struct octeon_droq *droq[MAX_OCTEON_OUTPUT_QUEUES];
struct octeon_droq *droq[MAX_POSSIBLE_OCTEON_OUTPUT_QUEUES];
struct octeon_io_enable io_qmask;
......@@ -382,15 +383,29 @@ struct octeon_device {
struct cavium_wq dma_comp_wq;
struct cavium_wq check_db_wq[MAX_OCTEON_INSTR_QUEUES];
/** Lock for dma response list */
spinlock_t cmd_resp_wqlock;
u32 cmd_resp_state;
struct cavium_wq check_db_wq[MAX_POSSIBLE_OCTEON_INSTR_QUEUES];
struct cavium_wk nic_poll_work;
struct cavium_wk console_poll_work[MAX_OCTEON_MAPS];
void *priv;
int rx_pause;
int tx_pause;
struct oct_link_stats link_stats; /*stastics from firmware*/
/* private flags to control driver-specific features through ethtool */
u32 priv_flags;
};
#define OCT_DRV_ONLINE 1
#define OCT_DRV_OFFLINE 2
#define OCTEON_CN6XXX(oct) ((oct->chip_id == OCTEON_CN66XX) || \
(oct->chip_id == OCTEON_CN68XX))
#define CHIP_FIELD(oct, TYPE, field) \
......@@ -647,4 +662,17 @@ void *oct_get_config_info(struct octeon_device *oct, u16 card_type);
*/
struct octeon_config *octeon_get_conf(struct octeon_device *oct);
/* LiquidIO driver pivate flags */
enum {
OCT_PRIV_FLAG_TX_BYTES = 0, /* Tx interrupts by pending byte count */
};
static inline void lio_set_priv_flag(struct octeon_device *octdev, u32 flag,
u32 val)
{
if (val)
octdev->priv_flags |= (0x1 << flag);
else
octdev->priv_flags &= ~(0x1 << flag);
}
#endif
......@@ -337,7 +337,7 @@ int octeon_init_droq(struct octeon_device *oct,
/* For 56xx Pass1, this function won't be called, so no checks. */
oct->fn_list.setup_oq_regs(oct, q_no);
oct->io_qmask.oq |= (1 << q_no);
oct->io_qmask.oq |= (1ULL << q_no);
return 0;
......
......@@ -65,6 +65,10 @@ struct oct_iq_stats {
u64 tx_iq_busy;/**< Numof times this iq was found to be full. */
u64 tx_dropped;/**< Numof pkts dropped dueto xmitpath errors. */
u64 tx_tot_bytes;/**< Total count of bytes sento to network. */
u64 tx_gso; /* count of tso */
u64 tx_dmamap_fail;
u64 tx_restart;
/*u64 tx_timeout_count;*/
};
#define OCT_IQ_STATS_SIZE (sizeof(struct oct_iq_stats))
......@@ -80,6 +84,12 @@ struct octeon_instr_queue {
/** A spinlock to protect access to the input ring. */
spinlock_t lock;
/** A spinlock to protect while posting on the ring. */
spinlock_t post_lock;
/** A spinlock to protect access to the input ring.*/
spinlock_t iq_flush_running_lock;
/** Flag that indicates if the queue uses 64 byte commands. */
u32 iqcmd_64B:1;
......@@ -244,7 +254,7 @@ union octeon_instr_64B {
/** The size of each buffer in soft command buffer pool
*/
#define SOFT_COMMAND_BUFFER_SIZE 1024
#define SOFT_COMMAND_BUFFER_SIZE 1536
struct octeon_soft_command {
/** Soft command buffer info. */
......@@ -282,7 +292,7 @@ struct octeon_soft_command {
/** Maximum number of buffers to allocate into soft command buffer pool
*/
#define MAX_SOFT_COMMAND_BUFFERS 16
#define MAX_SOFT_COMMAND_BUFFERS 256
/** Head of a soft command buffer pool.
*/
......@@ -339,7 +349,7 @@ octeon_register_reqtype_free_fn(struct octeon_device *oct, int reqtype,
int
lio_process_iq_request_list(struct octeon_device *oct,
struct octeon_instr_queue *iq);
struct octeon_instr_queue *iq, u32 napi_budget);
int octeon_send_command(struct octeon_device *oct, u32 iq_no,
u32 force_db, void *cmd, void *buf,
......@@ -357,5 +367,7 @@ int octeon_send_soft_command(struct octeon_device *oct,
int octeon_setup_iq(struct octeon_device *oct, int ifidx,
int q_index, union oct_txpciq iq_no, u32 num_descs,
void *app_ctx);
int
octeon_flush_iq(struct octeon_device *oct, struct octeon_instr_queue *iq,
u32 pending_thresh, u32 napi_budget);
#endif /* __OCTEON_IQ_H__ */
......@@ -30,6 +30,17 @@
#include <linux/dma-mapping.h>
#include <linux/ptp_clock_kernel.h>
struct oct_nic_stats_resp {
u64 rh;
struct oct_link_stats stats;
u64 status;
};
struct oct_nic_stats_ctrl {
struct completion complete;
struct net_device *netdev;
};
/** LiquidIO per-interface network private data */
struct lio {
/** State of the interface. Rx/Tx happens only in the RUNNING state. */
......
......@@ -171,20 +171,36 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
int retval;
struct octeon_soft_command *sc = NULL;
spin_lock_bh(&oct->cmd_resp_wqlock);
/* Allow only rx ctrl command to stop traffic on the chip
* during offline operations
*/
if ((oct->cmd_resp_state == OCT_DRV_OFFLINE) &&
(nctrl->ncmd.s.cmd != OCTNET_CMD_RX_CTL)) {
spin_unlock_bh(&oct->cmd_resp_wqlock);
dev_err(&oct->pci_dev->dev,
"%s cmd:%d not processed since driver offline\n",
__func__, nctrl->ncmd.s.cmd);
return -1;
}
sc = octnic_alloc_ctrl_pkt_sc(oct, nctrl);
if (!sc) {
dev_err(&oct->pci_dev->dev, "%s soft command alloc failed\n",
__func__);
spin_unlock_bh(&oct->cmd_resp_wqlock);
return -1;
}
retval = octeon_send_soft_command(oct, sc);
if (retval == IQ_SEND_FAILED) {
octeon_free_soft_command(oct, sc);
dev_err(&oct->pci_dev->dev, "%s soft command send failed status: %x\n",
__func__, retval);
dev_err(&oct->pci_dev->dev, "%s soft command:%d send failed status: %x\n",
__func__, nctrl->ncmd.s.cmd, retval);
spin_unlock_bh(&oct->cmd_resp_wqlock);
return -1;
}
spin_unlock_bh(&oct->cmd_resp_wqlock);
return retval;
}
......@@ -51,7 +51,7 @@ struct iq_post_status {
};
static void check_db_timeout(struct work_struct *work);
static void __check_db_timeout(struct octeon_device *oct, unsigned long iq_no);
static void __check_db_timeout(struct octeon_device *oct, u64 iq_no);
static void (*reqtype_free_fn[MAX_OCTEON_DEVICES][REQTYPE_LAST + 1]) (void *);
......@@ -149,8 +149,11 @@ int octeon_init_instr_queue(struct octeon_device *oct,
/* Initialize the spinlock for this instruction queue */
spin_lock_init(&iq->lock);
spin_lock_init(&iq->post_lock);
oct->io_qmask.iq |= (1 << iq_no);
spin_lock_init(&iq->iq_flush_running_lock);
oct->io_qmask.iq |= (1ULL << iq_no);
/* Set the 32B/64B mode for each input queue */
oct->io_qmask.iq64B |= ((conf->instr_type == 64) << iq_no);
......@@ -253,8 +256,8 @@ int lio_wait_for_instr_fetch(struct octeon_device *oct)
instr_cnt = 0;
/*for (i = 0; i < oct->num_iqs; i++) {*/
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES; i++) {
if (!(oct->io_qmask.iq & (1UL << i)))
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
if (!(oct->io_qmask.iq & (1ULL << i)))
continue;
pending =
atomic_read(&oct->
......@@ -391,13 +394,13 @@ __add_to_request_list(struct octeon_instr_queue *iq,
int
lio_process_iq_request_list(struct octeon_device *oct,
struct octeon_instr_queue *iq)
struct octeon_instr_queue *iq, u32 napi_budget)
{
int reqtype;
void *buf;
u32 old = iq->flush_index;
u32 inst_count = 0;
unsigned pkts_compl = 0, bytes_compl = 0;
unsigned int pkts_compl = 0, bytes_compl = 0;
struct octeon_soft_command *sc;
struct octeon_instr_irh *irh;
......@@ -457,6 +460,9 @@ lio_process_iq_request_list(struct octeon_device *oct,
skip_this:
inst_count++;
INCR_INDEX_BY1(old, iq->max_count);
if ((napi_budget) && (inst_count >= napi_budget))
break;
}
if (bytes_compl)
octeon_report_tx_completion_to_bql(iq->app_ctx, pkts_compl,
......@@ -466,38 +472,63 @@ lio_process_iq_request_list(struct octeon_device *oct,
return inst_count;
}
static inline void
update_iq_indices(struct octeon_device *oct, struct octeon_instr_queue *iq)
/* Can only be called from process context */
int
octeon_flush_iq(struct octeon_device *oct, struct octeon_instr_queue *iq,
u32 pending_thresh, u32 napi_budget)
{
u32 inst_processed = 0;
u32 tot_inst_processed = 0;
int tx_done = 1;
/* Calculate how many commands Octeon has read and move the read index
* accordingly.
*/
iq->octeon_read_index = oct->fn_list.update_iq_read_idx(oct, iq);
if (!spin_trylock(&iq->iq_flush_running_lock))
return tx_done;
/* Move the NORESPONSE requests to the per-device completion list. */
if (iq->flush_index != iq->octeon_read_index)
inst_processed = lio_process_iq_request_list(oct, iq);
spin_lock_bh(&iq->lock);
if (inst_processed) {
atomic_sub(inst_processed, &iq->instr_pending);
iq->stats.instr_processed += inst_processed;
}
}
iq->octeon_read_index = oct->fn_list.update_iq_read_idx(iq);
static void
octeon_flush_iq(struct octeon_device *oct, struct octeon_instr_queue *iq,
u32 pending_thresh)
{
if (atomic_read(&iq->instr_pending) >= (s32)pending_thresh) {
spin_lock_bh(&iq->lock);
update_iq_indices(oct, iq);
spin_unlock_bh(&iq->lock);
do {
/* Process any outstanding IQ packets. */
if (iq->flush_index == iq->octeon_read_index)
break;
if (napi_budget)
inst_processed = lio_process_iq_request_list
(oct, iq,
napi_budget - tot_inst_processed);
else
inst_processed =
lio_process_iq_request_list(oct, iq, 0);
if (inst_processed) {
atomic_sub(inst_processed, &iq->instr_pending);
iq->stats.instr_processed += inst_processed;
}
tot_inst_processed += inst_processed;
inst_processed = 0;
} while (tot_inst_processed < napi_budget);
if (napi_budget && (tot_inst_processed >= napi_budget))
tx_done = 0;
}
iq->last_db_time = jiffies;
spin_unlock_bh(&iq->lock);
spin_unlock(&iq->iq_flush_running_lock);
return tx_done;
}
static void __check_db_timeout(struct octeon_device *oct, unsigned long iq_no)
/* Process instruction queue after timeout.
* This routine gets called from a workqueue or when removing the module.
*/
static void __check_db_timeout(struct octeon_device *oct, u64 iq_no)
{
struct octeon_instr_queue *iq;
u64 next_time;
......@@ -508,24 +539,17 @@ static void __check_db_timeout(struct octeon_device *oct, unsigned long iq_no)
if (!iq)
return;
/* return immediately, if no work pending */
if (!atomic_read(&iq->instr_pending))
return;
/* If jiffies - last_db_time < db_timeout do nothing */
next_time = iq->last_db_time + iq->db_timeout;
if (!time_after(jiffies, (unsigned long)next_time))
return;
iq->last_db_time = jiffies;
/* Get the lock and prevent tasklets. This routine gets called from
* the poll thread. Instructions can now be posted in tasklet context
*/
spin_lock_bh(&iq->lock);
if (iq->fill_cnt != 0)
ring_doorbell(oct, iq);
spin_unlock_bh(&iq->lock);
/* Flush the instruction queue */
if (iq->do_auto_flush)
octeon_flush_iq(oct, iq, 1);
octeon_flush_iq(oct, iq, 1, 0);
}
/* Called by the Poll thread at regular intervals to check the instruction
......@@ -550,7 +574,10 @@ octeon_send_command(struct octeon_device *oct, u32 iq_no,
struct iq_post_status st;
struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
spin_lock_bh(&iq->lock);
/* Get the lock and prevent other tasks and tx interrupt handler from
* running.
*/
spin_lock_bh(&iq->post_lock);
st = __post_command2(oct, iq, force_db, cmd);
......@@ -566,10 +593,13 @@ octeon_send_command(struct octeon_device *oct, u32 iq_no,
INCR_INSTRQUEUE_PKT_COUNT(oct, iq_no, instr_dropped, 1);
}
spin_unlock_bh(&iq->lock);
spin_unlock_bh(&iq->post_lock);
if (iq->do_auto_flush)
octeon_flush_iq(oct, iq, 2);
/* This is only done here to expedite packets being flushed
* for cases where there are no IQ completion interrupts.
*/
/*if (iq->do_auto_flush)*/
/* octeon_flush_iq(oct, iq, 2, 0);*/
return st.status;
}
......
......@@ -54,6 +54,7 @@ int octeon_setup_response_list(struct octeon_device *oct)
spin_lock_init(&oct->response_list[i].lock);
atomic_set(&oct->response_list[i].pending_req_count, 0);
}
spin_lock_init(&oct->cmd_resp_wqlock);
oct->dma_comp_wq.wq = alloc_workqueue("dma-comp", WQ_MEM_RECLAIM, 0);
if (!oct->dma_comp_wq.wq) {
......@@ -64,6 +65,7 @@ int octeon_setup_response_list(struct octeon_device *oct)
cwq = &oct->dma_comp_wq;
INIT_DELAYED_WORK(&cwq->wk.work, oct_poll_req_completion);
cwq->wk.ctxptr = oct;
oct->cmd_resp_state = OCT_DRV_ONLINE;
queue_delayed_work(cwq->wq, &cwq->wk.work, msecs_to_jiffies(100));
return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment