Commit dbeb714a authored by David S. Miller's avatar David S. Miller

Merge branch 'liquidio-CN23XX-part-1'

Raghu Vatsavayi says:

====================
liquidio CN23XX support

Following patchset adds support for new device "CN23XX" in
liquidio family of adapters. As adviced by you I have split
the previous V3 patch of 18 patches into two halves. This
first patchset has first 10 patches, which are tested against
net-next. I will post the second half after this one.

This V4 patch also addressed all the comments from previous
submission:
1) Avoid busy loop while reading registers.
2) Other minor comments about debug messages and constants.

Please apply patches in following order as some of the
patches depend on earlier patches.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 650097cd c0eab5b3
...@@ -58,7 +58,7 @@ config LIQUIDIO ...@@ -58,7 +58,7 @@ config LIQUIDIO
select LIBCRC32C select LIBCRC32C
---help--- ---help---
This driver supports Cavium LiquidIO Intelligent Server Adapters This driver supports Cavium LiquidIO Intelligent Server Adapters
based on CN66XX and CN68XX chips. based on CN66XX, CN68XX and CN23XX chips.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called liquidio. This is recommended. will be called liquidio. This is recommended.
......
...@@ -3,14 +3,16 @@ ...@@ -3,14 +3,16 @@
# #
obj-$(CONFIG_LIQUIDIO) += liquidio.o obj-$(CONFIG_LIQUIDIO) += liquidio.o
liquidio-objs := lio_main.o \ liquidio-$(CONFIG_LIQUIDIO) += lio_ethtool.o \
lio_ethtool.o \ lio_core.o \
request_manager.o \ request_manager.o \
response_manager.o \ response_manager.o \
octeon_device.o \ octeon_device.o \
cn66xx_device.o \ cn66xx_device.o \
cn68xx_device.o \ cn68xx_device.o \
octeon_mem_ops.o \ cn23xx_pf_device.o \
octeon_droq.o \ octeon_mem_ops.o \
octeon_console.o \ octeon_droq.o \
octeon_nic.o octeon_nic.o
liquidio-objs := lio_main.o octeon_console.o $(liquidio-y)
This diff is collapsed.
/**********************************************************************
* Author: Cavium, Inc.
*
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
* Copyright (c) 2003-2015 Cavium, Inc.
*
* This file 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.
*
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
*
* This file may also be available under a different license from Cavium.
* Contact Cavium, Inc. for more information
**********************************************************************/
/*! \file cn23xx_device.h
* \brief Host Driver: Routines that perform CN23XX specific operations.
*/
#ifndef __CN23XX_PF_DEVICE_H__
#define __CN23XX_PF_DEVICE_H__
#include "cn23xx_pf_regs.h"
/* Register address and configuration for a CN23XX devices.
* If device specific changes need to be made then add a struct to include
* device specific fields as shown in the commented section
*/
struct octeon_cn23xx_pf {
/** PCI interrupt summary register */
u8 __iomem *intr_sum_reg64;
/** PCI interrupt enable register */
u8 __iomem *intr_enb_reg64;
/** The PCI interrupt mask used by interrupt handler */
u64 intr_mask64;
struct octeon_config *conf;
};
int setup_cn23xx_octeon_pf_device(struct octeon_device *oct);
int validate_cn23xx_pf_config_info(struct octeon_device *oct,
struct octeon_config *conf23xx);
void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct);
int cn23xx_fw_loaded(struct octeon_device *oct);
#endif
This diff is collapsed.
...@@ -338,7 +338,7 @@ void lio_cn6xxx_setup_oq_regs(struct octeon_device *oct, u32 oq_no) ...@@ -338,7 +338,7 @@ void lio_cn6xxx_setup_oq_regs(struct octeon_device *oct, u32 oq_no)
octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB, intr); octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB, intr);
} }
void lio_cn6xxx_enable_io_queues(struct octeon_device *oct) int lio_cn6xxx_enable_io_queues(struct octeon_device *oct)
{ {
u32 mask; u32 mask;
...@@ -353,6 +353,8 @@ void lio_cn6xxx_enable_io_queues(struct octeon_device *oct) ...@@ -353,6 +353,8 @@ void lio_cn6xxx_enable_io_queues(struct octeon_device *oct)
mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB); mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
mask |= oct->io_qmask.oq; mask |= oct->io_qmask.oq;
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, mask); octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, mask);
return 0;
} }
void lio_cn6xxx_disable_io_queues(struct octeon_device *oct) void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
...@@ -418,36 +420,6 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct) ...@@ -418,36 +420,6 @@ void lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT, d32); octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT, d32);
} }
void lio_cn6xxx_reinit_regs(struct octeon_device *oct)
{
int 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(oct); i++) {
if (!(oct->io_qmask.oq & (1ULL << i)))
continue;
oct->fn_list.setup_oq_regs(oct, i);
}
oct->fn_list.setup_device_regs(oct);
oct->fn_list.enable_interrupt(oct->chip);
oct->fn_list.enable_io_queues(oct);
/* for (i = 0; i < oct->num_oqs; 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);
}
}
void void
lio_cn6xxx_bar1_idx_setup(struct octeon_device *oct, lio_cn6xxx_bar1_idx_setup(struct octeon_device *oct,
u64 core_addr, u64 core_addr,
...@@ -507,18 +479,20 @@ lio_cn6xxx_update_read_index(struct octeon_instr_queue *iq) ...@@ -507,18 +479,20 @@ lio_cn6xxx_update_read_index(struct octeon_instr_queue *iq)
return new_idx; return new_idx;
} }
void lio_cn6xxx_enable_interrupt(void *chip) void lio_cn6xxx_enable_interrupt(struct octeon_device *oct,
u8 unused __attribute__((unused)))
{ {
struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)chip; struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
u64 mask = cn6xxx->intr_mask64 | CN6XXX_INTR_DMA0_FORCE; u64 mask = cn6xxx->intr_mask64 | CN6XXX_INTR_DMA0_FORCE;
/* Enable Interrupt */ /* Enable Interrupt */
writeq(mask, cn6xxx->intr_enb_reg64); writeq(mask, cn6xxx->intr_enb_reg64);
} }
void lio_cn6xxx_disable_interrupt(void *chip) void lio_cn6xxx_disable_interrupt(struct octeon_device *oct,
u8 unused __attribute__((unused)))
{ {
struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)chip; struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
/* Disable Interrupts */ /* Disable Interrupts */
writeq(0, cn6xxx->intr_enb_reg64); writeq(0, cn6xxx->intr_enb_reg64);
...@@ -714,7 +688,6 @@ int lio_setup_cn66xx_octeon_device(struct octeon_device *oct) ...@@ -714,7 +688,6 @@ int lio_setup_cn66xx_octeon_device(struct octeon_device *oct)
oct->fn_list.soft_reset = lio_cn6xxx_soft_reset; oct->fn_list.soft_reset = lio_cn6xxx_soft_reset;
oct->fn_list.setup_device_regs = lio_cn6xxx_setup_device_regs; oct->fn_list.setup_device_regs = lio_cn6xxx_setup_device_regs;
oct->fn_list.reinit_regs = lio_cn6xxx_reinit_regs;
oct->fn_list.update_iq_read_idx = lio_cn6xxx_update_read_index; oct->fn_list.update_iq_read_idx = lio_cn6xxx_update_read_index;
oct->fn_list.bar1_idx_setup = lio_cn6xxx_bar1_idx_setup; oct->fn_list.bar1_idx_setup = lio_cn6xxx_bar1_idx_setup;
......
...@@ -80,18 +80,17 @@ void lio_cn6xxx_setup_global_input_regs(struct octeon_device *oct); ...@@ -80,18 +80,17 @@ void lio_cn6xxx_setup_global_input_regs(struct octeon_device *oct);
void lio_cn6xxx_setup_global_output_regs(struct octeon_device *oct); void lio_cn6xxx_setup_global_output_regs(struct octeon_device *oct);
void lio_cn6xxx_setup_iq_regs(struct octeon_device *oct, u32 iq_no); void lio_cn6xxx_setup_iq_regs(struct octeon_device *oct, u32 iq_no);
void lio_cn6xxx_setup_oq_regs(struct octeon_device *oct, u32 oq_no); void lio_cn6xxx_setup_oq_regs(struct octeon_device *oct, u32 oq_no);
void lio_cn6xxx_enable_io_queues(struct octeon_device *oct); int lio_cn6xxx_enable_io_queues(struct octeon_device *oct);
void lio_cn6xxx_disable_io_queues(struct octeon_device *oct); void lio_cn6xxx_disable_io_queues(struct octeon_device *oct);
irqreturn_t lio_cn6xxx_process_interrupt_regs(void *dev); irqreturn_t lio_cn6xxx_process_interrupt_regs(void *dev);
void lio_cn6xxx_reinit_regs(struct octeon_device *oct);
void lio_cn6xxx_bar1_idx_setup(struct octeon_device *oct, u64 core_addr, void lio_cn6xxx_bar1_idx_setup(struct octeon_device *oct, u64 core_addr,
u32 idx, int valid); u32 idx, int valid);
void lio_cn6xxx_bar1_idx_write(struct octeon_device *oct, u32 idx, u32 mask); 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_bar1_idx_read(struct octeon_device *oct, u32 idx);
u32 u32
lio_cn6xxx_update_read_index(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_enable_interrupt(struct octeon_device *oct, u8 unused);
void lio_cn6xxx_disable_interrupt(void *chip); void lio_cn6xxx_disable_interrupt(struct octeon_device *oct, u8 unused);
void cn6xxx_get_pcie_qlmport(struct octeon_device *oct); void cn6xxx_get_pcie_qlmport(struct octeon_device *oct);
void lio_cn6xxx_setup_reg_address(struct octeon_device *oct, void *chip, void lio_cn6xxx_setup_reg_address(struct octeon_device *oct, void *chip,
struct octeon_reg_list *reg_list); struct octeon_reg_list *reg_list);
......
...@@ -148,7 +148,6 @@ int lio_setup_cn68xx_octeon_device(struct octeon_device *oct) ...@@ -148,7 +148,6 @@ int lio_setup_cn68xx_octeon_device(struct octeon_device *oct)
oct->fn_list.process_interrupt_regs = lio_cn6xxx_process_interrupt_regs; oct->fn_list.process_interrupt_regs = lio_cn6xxx_process_interrupt_regs;
oct->fn_list.soft_reset = lio_cn68xx_soft_reset; oct->fn_list.soft_reset = lio_cn68xx_soft_reset;
oct->fn_list.setup_device_regs = lio_cn68xx_setup_device_regs; oct->fn_list.setup_device_regs = lio_cn68xx_setup_device_regs;
oct->fn_list.reinit_regs = lio_cn6xxx_reinit_regs;
oct->fn_list.update_iq_read_idx = lio_cn6xxx_update_read_index; oct->fn_list.update_iq_read_idx = lio_cn6xxx_update_read_index;
oct->fn_list.bar1_idx_setup = lio_cn6xxx_bar1_idx_setup; oct->fn_list.bar1_idx_setup = lio_cn6xxx_bar1_idx_setup;
......
/**********************************************************************
* Author: Cavium, Inc.
*
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
* Copyright (c) 2003-2015 Cavium, Inc.
*
* This file 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.
*
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
*
* This file may also be available under a different license from Cavium.
* Contact Cavium, Inc. for more information
**********************************************************************/
#include <linux/pci.h>
#include <linux/if_vlan.h>
#include "liquidio_common.h"
#include "octeon_droq.h"
#include "octeon_iq.h"
#include "response_manager.h"
#include "octeon_device.h"
#include "octeon_nic.h"
#include "octeon_main.h"
#include "octeon_network.h"
int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octnic_ctrl_pkt nctrl;
int ret = 0;
memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
nctrl.ncmd.u64 = 0;
nctrl.ncmd.s.cmd = cmd;
nctrl.ncmd.s.param1 = param1;
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
nctrl.wait_time = 100;
nctrl.netpndev = (u64)netdev;
nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
if (ret < 0) {
dev_err(&oct->pci_dev->dev, "Feature change failed in core (ret: 0x%x)\n",
ret);
}
return ret;
}
void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl,
unsigned int bytes_compl)
{
struct netdev_queue *netdev_queue = txq;
netdev_tx_completed_queue(netdev_queue, pkts_compl, bytes_compl);
}
void octeon_update_tx_completion_counters(void *buf, int reqtype,
unsigned int *pkts_compl,
unsigned int *bytes_compl)
{
struct octnet_buf_free_info *finfo;
struct sk_buff *skb = NULL;
struct octeon_soft_command *sc;
switch (reqtype) {
case REQTYPE_NORESP_NET:
case REQTYPE_NORESP_NET_SG:
finfo = buf;
skb = finfo->skb;
break;
case REQTYPE_RESP_NET_SG:
case REQTYPE_RESP_NET:
sc = buf;
skb = sc->callback_arg;
break;
default:
return;
}
(*pkts_compl)++;
/*TODO, Use some other pound define to suggest
* the fact that iqs are not tied to netdevs
* and can take traffic from different netdevs
* hence bql reporting is done per packet
* than in bulk. Usage of NO_NAPI in txq completion is
* a little confusing
*/
*bytes_compl += skb->len;
}
void octeon_report_sent_bytes_to_bql(void *buf, int reqtype)
{
struct octnet_buf_free_info *finfo;
struct sk_buff *skb;
struct octeon_soft_command *sc;
struct netdev_queue *txq;
switch (reqtype) {
case REQTYPE_NORESP_NET:
case REQTYPE_NORESP_NET_SG:
finfo = buf;
skb = finfo->skb;
break;
case REQTYPE_RESP_NET_SG:
case REQTYPE_RESP_NET:
sc = buf;
skb = sc->callback_arg;
break;
default:
return;
}
txq = netdev_get_tx_queue(skb->dev, skb_get_queue_mapping(skb));
netdev_tx_sent_queue(txq, skb->len);
}
void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
{
struct octnic_ctrl_pkt *nctrl = (struct octnic_ctrl_pkt *)nctrl_ptr;
struct net_device *netdev = (struct net_device *)nctrl->netpndev;
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
u8 *mac;
switch (nctrl->ncmd.s.cmd) {
case OCTNET_CMD_CHANGE_DEVFLAGS:
case OCTNET_CMD_SET_MULTI_LIST:
break;
case OCTNET_CMD_CHANGE_MACADDR:
mac = ((u8 *)&nctrl->udd[0]) + 2;
netif_info(lio, probe, lio->netdev,
"MACAddr changed to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
mac[0], mac[1],
mac[2], mac[3],
mac[4], mac[5]);
break;
case OCTNET_CMD_CHANGE_MTU:
/* If command is successful, change the MTU. */
netif_info(lio, probe, lio->netdev, "MTU Changed from %d to %d\n",
netdev->mtu, nctrl->ncmd.s.param1);
dev_info(&oct->pci_dev->dev, "%s MTU Changed from %d to %d\n",
netdev->name, netdev->mtu,
nctrl->ncmd.s.param1);
rtnl_lock();
netdev->mtu = nctrl->ncmd.s.param1;
call_netdevice_notifiers(NETDEV_CHANGEMTU, netdev);
rtnl_unlock();
break;
case OCTNET_CMD_GPIO_ACCESS:
netif_info(lio, probe, lio->netdev, "LED Flashing visual identification\n");
break;
case OCTNET_CMD_LRO_ENABLE:
dev_info(&oct->pci_dev->dev, "%s LRO Enabled\n", netdev->name);
break;
case OCTNET_CMD_LRO_DISABLE:
dev_info(&oct->pci_dev->dev, "%s LRO Disabled\n",
netdev->name);
break;
case OCTNET_CMD_VERBOSE_ENABLE:
dev_info(&oct->pci_dev->dev, "%s Firmware debug enabled\n",
netdev->name);
break;
case OCTNET_CMD_VERBOSE_DISABLE:
dev_info(&oct->pci_dev->dev, "%s Firmware debug disabled\n",
netdev->name);
break;
case OCTNET_CMD_ENABLE_VLAN_FILTER:
dev_info(&oct->pci_dev->dev, "%s VLAN filter enabled\n",
netdev->name);
break;
case OCTNET_CMD_ADD_VLAN_FILTER:
dev_info(&oct->pci_dev->dev, "%s VLAN filter %d added\n",
netdev->name, nctrl->ncmd.s.param1);
break;
case OCTNET_CMD_DEL_VLAN_FILTER:
dev_info(&oct->pci_dev->dev, "%s VLAN filter %d removed\n",
netdev->name, nctrl->ncmd.s.param1);
break;
case OCTNET_CMD_SET_SETTINGS:
dev_info(&oct->pci_dev->dev, "%s settings changed\n",
netdev->name);
break;
/* Case to handle "OCTNET_CMD_TNL_RX_CSUM_CTL"
* Command passed by NIC driver
*/
case OCTNET_CMD_TNL_RX_CSUM_CTL:
if (nctrl->ncmd.s.param1 == OCTNET_CMD_RXCSUM_ENABLE) {
netif_info(lio, probe, lio->netdev,
"RX Checksum Offload Enabled\n");
} else if (nctrl->ncmd.s.param1 ==
OCTNET_CMD_RXCSUM_DISABLE) {
netif_info(lio, probe, lio->netdev,
"RX Checksum Offload Disabled\n");
}
break;
/* Case to handle "OCTNET_CMD_TNL_TX_CSUM_CTL"
* Command passed by NIC driver
*/
case OCTNET_CMD_TNL_TX_CSUM_CTL:
if (nctrl->ncmd.s.param1 == OCTNET_CMD_TXCSUM_ENABLE) {
netif_info(lio, probe, lio->netdev,
"TX Checksum Offload Enabled\n");
} else if (nctrl->ncmd.s.param1 ==
OCTNET_CMD_TXCSUM_DISABLE) {
netif_info(lio, probe, lio->netdev,
"TX Checksum Offload Disabled\n");
}
break;
/* Case to handle "OCTNET_CMD_VXLAN_PORT_CONFIG"
* Command passed by NIC driver
*/
case OCTNET_CMD_VXLAN_PORT_CONFIG:
if (nctrl->ncmd.s.more == OCTNET_CMD_VXLAN_PORT_ADD) {
netif_info(lio, probe, lio->netdev,
"VxLAN Destination UDP PORT:%d ADDED\n",
nctrl->ncmd.s.param1);
} else if (nctrl->ncmd.s.more ==
OCTNET_CMD_VXLAN_PORT_DEL) {
netif_info(lio, probe, lio->netdev,
"VxLAN Destination UDP PORT:%d DELETED\n",
nctrl->ncmd.s.param1);
}
break;
case OCTNET_CMD_SET_FLOW_CTL:
netif_info(lio, probe, lio->netdev, "Set RX/TX flow control parameters\n");
break;
default:
dev_err(&oct->pci_dev->dev, "%s Unknown cmd %d\n", __func__,
nctrl->ncmd.s.cmd);
}
}
...@@ -290,18 +290,16 @@ lio_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, ...@@ -290,18 +290,16 @@ lio_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
struct lio *lio = GET_LIO(netdev); struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct_dev = lio->oct_dev; struct octeon_device *oct_dev = lio->oct_dev;
struct octeon_board_info *board_info; struct octeon_board_info *board_info;
int len;
if (eeprom->offset != 0) if (eeprom->offset)
return -EINVAL; return -EINVAL;
eeprom->magic = oct_dev->pci_dev->vendor; eeprom->magic = oct_dev->pci_dev->vendor;
board_info = (struct octeon_board_info *)(&oct_dev->boardinfo); board_info = (struct octeon_board_info *)(&oct_dev->boardinfo);
len = sprintf((char *)bytes,
sprintf((char *)bytes, "boardname:%s serialnum:%s maj:%lld min:%lld\n",
"boardname:%s serialnum:%s maj:%lld min:%lld\n", board_info->name, board_info->serial_number,
board_info->name, board_info->serial_number, board_info->major, board_info->minor);
board_info->major, board_info->minor);
return 0; return 0;
} }
...@@ -406,7 +404,7 @@ octnet_mdio45_access(struct lio *lio, int op, int loc, int *value) ...@@ -406,7 +404,7 @@ octnet_mdio45_access(struct lio *lio, int op, int loc, int *value)
dev_err(&oct_dev->pci_dev->dev, dev_err(&oct_dev->pci_dev->dev,
"octnet_mdio45_access instruction failed status: %x\n", "octnet_mdio45_access instruction failed status: %x\n",
retval); retval);
retval = -EBUSY; retval = -EBUSY;
} else { } else {
/* Sleep on a wait queue till the cond flag indicates that the /* Sleep on a wait queue till the cond flag indicates that the
* response arrived * response arrived
...@@ -1320,8 +1318,8 @@ oct_cfg_rx_intrcnt(struct lio *lio, struct ethtool_coalesce *intr_coal) ...@@ -1320,8 +1318,8 @@ oct_cfg_rx_intrcnt(struct lio *lio, struct ethtool_coalesce *intr_coal)
return 0; return 0;
} }
static int oct_cfg_rx_intrtime(struct lio *lio, struct ethtool_coalesce static int oct_cfg_rx_intrtime(struct lio *lio,
*intr_coal) struct ethtool_coalesce *intr_coal)
{ {
struct octeon_device *oct = lio->oct_dev; struct octeon_device *oct = lio->oct_dev;
u32 time_threshold, rx_coalesce_usecs; u32 time_threshold, rx_coalesce_usecs;
......
...@@ -30,10 +30,24 @@ ...@@ -30,10 +30,24 @@
#include "octeon_config.h" #include "octeon_config.h"
#define LIQUIDIO_BASE_VERSION "1.4"
#define LIQUIDIO_MICRO_VERSION ".1"
#define LIQUIDIO_PACKAGE "" #define LIQUIDIO_PACKAGE ""
#define LIQUIDIO_VERSION "1.4.1" #define LIQUIDIO_BASE_MAJOR_VERSION 1
#define LIQUIDIO_BASE_MINOR_VERSION 4
#define LIQUIDIO_BASE_MICRO_VERSION 1
#define LIQUIDIO_BASE_VERSION __stringify(LIQUIDIO_BASE_MAJOR_VERSION) "." \
__stringify(LIQUIDIO_BASE_MINOR_VERSION)
#define LIQUIDIO_MICRO_VERSION "." __stringify(LIQUIDIO_BASE_MICRO_VERSION)
#define LIQUIDIO_VERSION LIQUIDIO_PACKAGE \
__stringify(LIQUIDIO_BASE_MAJOR_VERSION) "." \
__stringify(LIQUIDIO_BASE_MINOR_VERSION) \
"." __stringify(LIQUIDIO_BASE_MICRO_VERSION)
struct lio_version {
u16 major;
u16 minor;
u16 micro;
u16 reserved;
};
#define CONTROL_IQ 0 #define CONTROL_IQ 0
/** Tag types used by Octeon cores in its work. */ /** Tag types used by Octeon cores in its work. */
...@@ -832,7 +846,7 @@ struct oct_mdio_cmd { ...@@ -832,7 +846,7 @@ struct oct_mdio_cmd {
/* intrmod: max. packets to trigger interrupt */ /* intrmod: max. packets to trigger interrupt */
#define LIO_INTRMOD_RXMAXCNT_TRIGGER 384 #define LIO_INTRMOD_RXMAXCNT_TRIGGER 384
/* intrmod: min. packets to trigger interrupt */ /* intrmod: min. packets to trigger interrupt */
#define LIO_INTRMOD_RXMINCNT_TRIGGER 1 #define LIO_INTRMOD_RXMINCNT_TRIGGER 0
/* intrmod: max. time to trigger interrupt */ /* intrmod: max. time to trigger interrupt */
#define LIO_INTRMOD_RXMAXTMR_TRIGGER 128 #define LIO_INTRMOD_RXMAXTMR_TRIGGER 128
/* 66xx:intrmod: min. time to trigger interrupt /* 66xx:intrmod: min. time to trigger interrupt
......
...@@ -64,6 +64,34 @@ ...@@ -64,6 +64,34 @@
#define DEFAULT_NUM_NIC_PORTS_68XX 4 #define DEFAULT_NUM_NIC_PORTS_68XX 4
#define DEFAULT_NUM_NIC_PORTS_68XX_210NV 2 #define DEFAULT_NUM_NIC_PORTS_68XX_210NV 2
/* CN23xx IQ configuration macros */
#define CN23XX_MAX_RINGS_PER_PF_PASS_1_0 12
#define CN23XX_MAX_RINGS_PER_PF_PASS_1_1 32
#define CN23XX_MAX_RINGS_PER_PF 64
#define CN23XX_MAX_INPUT_QUEUES CN23XX_MAX_RINGS_PER_PF
#define CN23XX_MAX_IQ_DESCRIPTORS 2048
#define CN23XX_DB_MIN 1
#define CN23XX_DB_MAX 8
#define CN23XX_DB_TIMEOUT 1
#define CN23XX_MAX_OUTPUT_QUEUES CN23XX_MAX_RINGS_PER_PF
#define CN23XX_MAX_OQ_DESCRIPTORS 2048
#define CN23XX_OQ_BUF_SIZE 1536
#define CN23XX_OQ_PKTSPER_INTR 128
/*#define CAVIUM_ONLY_CN23XX_RX_PERF*/
#define CN23XX_OQ_REFIL_THRESHOLD 128
#define CN23XX_OQ_INTR_PKT 64
#define CN23XX_OQ_INTR_TIME 100
#define DEFAULT_NUM_NIC_PORTS_23XX 1
#define CN23XX_CFG_IO_QUEUES CN23XX_MAX_RINGS_PER_PF
/* PEMs count */
#define CN23XX_MAX_MACS 4
#define CN23XX_DEF_IQ_INTR_THRESHOLD 32
#define CN23XX_DEF_IQ_INTR_BYTE_THRESHOLD (64 * 1024)
/* common OCTEON configuration macros */ /* common OCTEON configuration macros */
#define CN6XXX_CFG_IO_QUEUES 32 #define CN6XXX_CFG_IO_QUEUES 32
#define OCTEON_32BYTE_INSTR 32 #define OCTEON_32BYTE_INSTR 32
...@@ -92,6 +120,9 @@ ...@@ -92,6 +120,9 @@
#define CFG_GET_IQ_DB_MIN(cfg) ((cfg)->iq.db_min) #define CFG_GET_IQ_DB_MIN(cfg) ((cfg)->iq.db_min)
#define CFG_GET_IQ_DB_TIMEOUT(cfg) ((cfg)->iq.db_timeout) #define CFG_GET_IQ_DB_TIMEOUT(cfg) ((cfg)->iq.db_timeout)
#define CFG_GET_IQ_INTR_PKT(cfg) ((cfg)->iq.iq_intr_pkt)
#define CFG_SET_IQ_INTR_PKT(cfg, val) (cfg)->iq.iq_intr_pkt = val
#define CFG_GET_OQ_MAX_Q(cfg) ((cfg)->oq.max_oqs) #define CFG_GET_OQ_MAX_Q(cfg) ((cfg)->oq.max_oqs)
#define CFG_GET_OQ_INFO_PTR(cfg) ((cfg)->oq.info_ptr) #define CFG_GET_OQ_INFO_PTR(cfg) ((cfg)->oq.info_ptr)
#define CFG_GET_OQ_PKTS_PER_INTR(cfg) ((cfg)->oq.pkts_per_intr) #define CFG_GET_OQ_PKTS_PER_INTR(cfg) ((cfg)->oq.pkts_per_intr)
...@@ -140,19 +171,24 @@ ...@@ -140,19 +171,24 @@
enum lio_card_type { enum lio_card_type {
LIO_210SV = 0, /* Two port, 66xx */ LIO_210SV = 0, /* Two port, 66xx */
LIO_210NV, /* Two port, 68xx */ LIO_210NV, /* Two port, 68xx */
LIO_410NV /* Four port, 68xx */ LIO_410NV, /* Four port, 68xx */
LIO_23XX /* 23xx */
}; };
#define LIO_210SV_NAME "210sv" #define LIO_210SV_NAME "210sv"
#define LIO_210NV_NAME "210nv" #define LIO_210NV_NAME "210nv"
#define LIO_410NV_NAME "410nv" #define LIO_410NV_NAME "410nv"
#define LIO_23XX_NAME "23xx"
/** Structure to define the configuration attributes for each Input queue. /** Structure to define the configuration attributes for each Input queue.
* Applicable to all Octeon processors * Applicable to all Octeon processors
**/ **/
struct octeon_iq_config { struct octeon_iq_config {
#ifdef __BIG_ENDIAN_BITFIELD #ifdef __BIG_ENDIAN_BITFIELD
u64 reserved:32; u64 reserved:16;
/** Tx interrupt packets. Applicable to 23xx only */
u64 iq_intr_pkt:16;
/** Minimum ticks to wait before checking for pending instructions. */ /** Minimum ticks to wait before checking for pending instructions. */
u64 db_timeout:16; u64 db_timeout:16;
...@@ -192,7 +228,10 @@ struct octeon_iq_config { ...@@ -192,7 +228,10 @@ struct octeon_iq_config {
/** Minimum ticks to wait before checking for pending instructions. */ /** Minimum ticks to wait before checking for pending instructions. */
u64 db_timeout:16; u64 db_timeout:16;
u64 reserved:32; /** Tx interrupt packets. Applicable to 23xx only */
u64 iq_intr_pkt:16;
u64 reserved:16;
#endif #endif
}; };
...@@ -416,11 +455,15 @@ struct octeon_config { ...@@ -416,11 +455,15 @@ struct octeon_config {
#define DISPATCH_LIST_SIZE BIT(OPCODE_MASK_BITS) #define DISPATCH_LIST_SIZE BIT(OPCODE_MASK_BITS)
/* Maximum number of Octeon Instruction (command) queues */ /* Maximum number of Octeon Instruction (command) queues */
#define MAX_OCTEON_INSTR_QUEUES(oct) CN6XXX_MAX_INPUT_QUEUES #define MAX_OCTEON_INSTR_QUEUES(oct) \
/* Maximum number of Octeon Output queues */ (OCTEON_CN23XX_PF(oct) ? CN23XX_MAX_INPUT_QUEUES : \
#define MAX_OCTEON_OUTPUT_QUEUES(oct) CN6XXX_MAX_OUTPUT_QUEUES CN6XXX_MAX_INPUT_QUEUES)
#define MAX_POSSIBLE_OCTEON_INSTR_QUEUES CN6XXX_MAX_INPUT_QUEUES /* Maximum number of Octeon Instruction (command) queues */
#define MAX_POSSIBLE_OCTEON_OUTPUT_QUEUES CN6XXX_MAX_OUTPUT_QUEUES #define MAX_OCTEON_OUTPUT_QUEUES(oct) \
(OCTEON_CN23XX_PF(oct) ? CN23XX_MAX_OUTPUT_QUEUES : \
CN6XXX_MAX_OUTPUT_QUEUES)
#define MAX_POSSIBLE_OCTEON_INSTR_QUEUES CN23XX_MAX_INPUT_QUEUES
#define MAX_POSSIBLE_OCTEON_OUTPUT_QUEUES CN23XX_MAX_OUTPUT_QUEUES
#endif /* __OCTEON_CONFIG_H__ */ #endif /* __OCTEON_CONFIG_H__ */
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
*/ */
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/crc32.h>
#include "liquidio_common.h" #include "liquidio_common.h"
#include "octeon_droq.h" #include "octeon_droq.h"
#include "octeon_iq.h" #include "octeon_iq.h"
#include "response_manager.h" #include "response_manager.h"
#include "octeon_device.h" #include "octeon_device.h"
#include "octeon_main.h" #include "liquidio_image.h"
#include "octeon_mem_ops.h" #include "octeon_mem_ops.h"
static void octeon_remote_lock(void); static void octeon_remote_lock(void);
...@@ -40,6 +41,10 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct, ...@@ -40,6 +41,10 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,
u32 flags); u32 flags);
static int octeon_console_read(struct octeon_device *oct, u32 console_num, static int octeon_console_read(struct octeon_device *oct, u32 console_num,
char *buffer, u32 buf_size); char *buffer, u32 buf_size);
static u32 console_bitmask;
module_param(console_bitmask, int, 0644);
MODULE_PARM_DESC(console_bitmask,
"Bitmask indicating which consoles have debug output redirected to syslog.");
#define MIN(a, b) min((a), (b)) #define MIN(a, b) min((a), (b))
#define CAST_ULL(v) ((u64)(v)) #define CAST_ULL(v) ((u64)(v))
...@@ -177,6 +182,15 @@ struct octeon_pci_console_desc { ...@@ -177,6 +182,15 @@ struct octeon_pci_console_desc {
__cvmx_bootmem_desc_get(oct, addr, \ __cvmx_bootmem_desc_get(oct, addr, \
offsetof(struct cvmx_bootmem_named_block_desc, field), \ offsetof(struct cvmx_bootmem_named_block_desc, field), \
SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field)) SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field))
/**
* \brief determines if a given console has debug enabled.
* @param console console to check
* @returns 1 = enabled. 0 otherwise
*/
static int octeon_console_debug_enabled(u32 console)
{
return (console_bitmask >> (console)) & 0x1;
}
/** /**
* This function is the implementation of the get macros defined * This function is the implementation of the get macros defined
...@@ -709,3 +723,104 @@ static int octeon_console_read(struct octeon_device *oct, u32 console_num, ...@@ -709,3 +723,104 @@ static int octeon_console_read(struct octeon_device *oct, u32 console_num,
return bytes_to_read; return bytes_to_read;
} }
#define FBUF_SIZE (4 * 1024 * 1024)
u8 fbuf[FBUF_SIZE];
int octeon_download_firmware(struct octeon_device *oct, const u8 *data,
size_t size)
{
int ret = 0;
u8 *p = fbuf;
u32 crc32_result;
u64 load_addr;
u32 image_len;
struct octeon_firmware_file_header *h;
u32 i, rem;
if (size < sizeof(struct octeon_firmware_file_header)) {
dev_err(&oct->pci_dev->dev, "Firmware file too small (%d < %d).\n",
(u32)size,
(u32)sizeof(struct octeon_firmware_file_header));
return -EINVAL;
}
h = (struct octeon_firmware_file_header *)data;
if (be32_to_cpu(h->magic) != LIO_NIC_MAGIC) {
dev_err(&oct->pci_dev->dev, "Unrecognized firmware file.\n");
return -EINVAL;
}
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 (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;
}
if (memcmp(LIQUIDIO_BASE_VERSION, h->version + strlen(LIQUIDIO_PACKAGE),
strlen(LIQUIDIO_BASE_VERSION))) {
dev_err(&oct->pci_dev->dev, "Unmatched firmware version. Expected %s.x, got %s.\n",
LIQUIDIO_BASE_VERSION,
h->version + strlen(LIQUIDIO_PACKAGE));
return -EINVAL;
}
if (be32_to_cpu(h->num_images) > LIO_MAX_IMAGES) {
dev_err(&oct->pci_dev->dev, "Too many images in firmware file (%d).\n",
be32_to_cpu(h->num_images));
return -EINVAL;
}
dev_info(&oct->pci_dev->dev, "Firmware version: %s\n", h->version);
snprintf(oct->fw_info.liquidio_firmware_version, 32, "LIQUIDIO: %s",
h->version);
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);
dev_info(&oct->pci_dev->dev, "Loading firmware %d at %llx\n",
image_len, load_addr);
/* Write in 4MB chunks*/
rem = image_len;
while (rem) {
if (rem < FBUF_SIZE)
size = rem;
else
size = FBUF_SIZE;
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);
return 0;
}
...@@ -30,13 +30,19 @@ ...@@ -30,13 +30,19 @@
/** PCI VendorId Device Id */ /** PCI VendorId Device Id */
#define OCTEON_CN68XX_PCIID 0x91177d #define OCTEON_CN68XX_PCIID 0x91177d
#define OCTEON_CN66XX_PCIID 0x92177d #define OCTEON_CN66XX_PCIID 0x92177d
#define OCTEON_CN23XX_PCIID_PF 0x9702177d
/** Driver identifies chips by these Ids, created by clubbing together /** Driver identifies chips by these Ids, created by clubbing together
* DeviceId+RevisionId; Where Revision Id is not used to distinguish * DeviceId+RevisionId; Where Revision Id is not used to distinguish
* between chips, a value of 0 is used for revision id. * between chips, a value of 0 is used for revision id.
*/ */
#define OCTEON_CN68XX 0x0091 #define OCTEON_CN68XX 0x0091
#define OCTEON_CN66XX 0x0092 #define OCTEON_CN66XX 0x0092
#define OCTEON_CN23XX_PF_VID 0x9702
/**RevisionId for the chips */
#define OCTEON_CN23XX_REV_1_0 0x00
#define OCTEON_CN23XX_REV_1_1 0x01
#define OCTEON_CN23XX_REV_2_0 0x80
/** Endian-swap modes supported by Octeon. */ /** Endian-swap modes supported by Octeon. */
enum octeon_pci_swap_mode { enum octeon_pci_swap_mode {
...@@ -46,6 +52,9 @@ enum octeon_pci_swap_mode { ...@@ -46,6 +52,9 @@ enum octeon_pci_swap_mode {
OCTEON_PCI_32BIT_LW_SWAP = 3 OCTEON_PCI_32BIT_LW_SWAP = 3
}; };
#define OCTEON_OUTPUT_INTR (2)
#define OCTEON_ALL_INTR 0xff
/*--------------- PCI BAR1 index registers -------------*/ /*--------------- PCI BAR1 index registers -------------*/
/* BAR1 Mask */ /* BAR1 Mask */
...@@ -198,9 +207,9 @@ struct octeon_fn_list { ...@@ -198,9 +207,9 @@ struct octeon_fn_list {
void (*setup_oq_regs)(struct octeon_device *, u32); void (*setup_oq_regs)(struct octeon_device *, u32);
irqreturn_t (*process_interrupt_regs)(void *); irqreturn_t (*process_interrupt_regs)(void *);
u64 (*msix_interrupt_handler)(void *);
int (*soft_reset)(struct octeon_device *); int (*soft_reset)(struct octeon_device *);
int (*setup_device_regs)(struct octeon_device *); int (*setup_device_regs)(struct octeon_device *);
void (*reinit_regs)(struct octeon_device *);
void (*bar1_idx_setup)(struct octeon_device *, u64, u32, int); void (*bar1_idx_setup)(struct octeon_device *, u64, u32, int);
void (*bar1_idx_write)(struct octeon_device *, u32, u32); void (*bar1_idx_write)(struct octeon_device *, u32, u32);
u32 (*bar1_idx_read)(struct octeon_device *, u32); u32 (*bar1_idx_read)(struct octeon_device *, u32);
...@@ -209,10 +218,10 @@ struct octeon_fn_list { ...@@ -209,10 +218,10 @@ struct octeon_fn_list {
void (*enable_oq_pkt_time_intr)(struct octeon_device *, u32); void (*enable_oq_pkt_time_intr)(struct octeon_device *, u32);
void (*disable_oq_pkt_time_intr)(struct octeon_device *, u32); void (*disable_oq_pkt_time_intr)(struct octeon_device *, u32);
void (*enable_interrupt)(void *); void (*enable_interrupt)(struct octeon_device *, u8);
void (*disable_interrupt)(void *); void (*disable_interrupt)(struct octeon_device *, u8);
void (*enable_io_queues)(struct octeon_device *); int (*enable_io_queues)(struct octeon_device *);
void (*disable_io_queues)(struct octeon_device *); void (*disable_io_queues)(struct octeon_device *);
}; };
...@@ -271,6 +280,66 @@ struct octdev_props { ...@@ -271,6 +280,66 @@ struct octdev_props {
struct net_device *netdev; struct net_device *netdev;
}; };
#define LIO_FLAG_MSIX_ENABLED 0x1
#define MSIX_PO_INT 0x1
#define MSIX_PI_INT 0x2
struct octeon_pf_vf_hs_word {
#ifdef __LITTLE_ENDIAN_BITFIELD
/** PKIND value assigned for the DPI interface */
u64 pkind : 8;
/** OCTEON core clock multiplier */
u64 core_tics_per_us : 16;
/** OCTEON coprocessor clock multiplier */
u64 coproc_tics_per_us : 16;
/** app that currently running on OCTEON */
u64 app_mode : 8;
/** RESERVED */
u64 reserved : 16;
#else
/** RESERVED */
u64 reserved : 16;
/** app that currently running on OCTEON */
u64 app_mode : 8;
/** OCTEON coprocessor clock multiplier */
u64 coproc_tics_per_us : 16;
/** OCTEON core clock multiplier */
u64 core_tics_per_us : 16;
/** PKIND value assigned for the DPI interface */
u64 pkind : 8;
#endif
};
struct octeon_sriov_info {
/* Actual rings left for PF device */
u32 num_pf_rings;
/* SRN of PF usable IO queues */
u32 pf_srn;
/* total pf rings */
u32 trs;
};
struct octeon_ioq_vector {
struct octeon_device *oct_dev;
int iq_index;
int droq_index;
int vector;
struct cpumask affinity_mask;
u32 ioq_num;
};
/** The Octeon device. /** The Octeon device.
* Each Octeon device has this structure to represent all its * Each Octeon device has this structure to represent all its
* components. * components.
...@@ -296,7 +365,7 @@ struct octeon_device { ...@@ -296,7 +365,7 @@ struct octeon_device {
/** Octeon Chip type. */ /** Octeon Chip type. */
u16 chip_id; u16 chip_id;
u16 rev_id; u16 rev_id;
u16 pf_num;
/** This device's id - set by the driver. */ /** This device's id - set by the driver. */
u32 octeon_id; u32 octeon_id;
...@@ -305,7 +374,6 @@ struct octeon_device { ...@@ -305,7 +374,6 @@ struct octeon_device {
u16 flags; u16 flags;
#define LIO_FLAG_MSI_ENABLED (u32)(1 << 1) #define LIO_FLAG_MSI_ENABLED (u32)(1 << 1)
#define LIO_FLAG_MSIX_ENABLED (u32)(1 << 2)
/** The state of this device */ /** The state of this device */
atomic_t status; atomic_t status;
...@@ -395,6 +463,19 @@ struct octeon_device { ...@@ -395,6 +463,19 @@ struct octeon_device {
void *priv; void *priv;
int num_msix_irqs;
void *msix_entries;
struct octeon_sriov_info sriov_info;
struct octeon_pf_vf_hs_word pfvf_hsword;
int msix_on;
/** IOq information of it's corresponding MSI-X interrupt. */
struct octeon_ioq_vector *ioq_vector;
int rx_pause; int rx_pause;
int tx_pause; int tx_pause;
...@@ -408,6 +489,7 @@ struct octeon_device { ...@@ -408,6 +489,7 @@ struct octeon_device {
#define OCT_DRV_OFFLINE 2 #define OCT_DRV_OFFLINE 2
#define OCTEON_CN6XXX(oct) ((oct->chip_id == OCTEON_CN66XX) || \ #define OCTEON_CN6XXX(oct) ((oct->chip_id == OCTEON_CN66XX) || \
(oct->chip_id == OCTEON_CN68XX)) (oct->chip_id == OCTEON_CN68XX))
#define OCTEON_CN23XX_PF(oct) (oct->chip_id == OCTEON_CN23XX_PF_VID)
#define CHIP_FIELD(oct, TYPE, field) \ #define CHIP_FIELD(oct, TYPE, field) \
(((struct octeon_ ## TYPE *)(oct->chip))->field) (((struct octeon_ ## TYPE *)(oct->chip))->field)
...@@ -661,6 +743,10 @@ void *oct_get_config_info(struct octeon_device *oct, u16 card_type); ...@@ -661,6 +743,10 @@ void *oct_get_config_info(struct octeon_device *oct, u16 card_type);
*/ */
struct octeon_config *octeon_get_conf(struct octeon_device *oct); struct octeon_config *octeon_get_conf(struct octeon_device *oct);
void octeon_free_ioq_vector(struct octeon_device *oct);
int octeon_allocate_ioq_vector(struct octeon_device *oct);
void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq);
/* LiquidIO driver pivate flags */ /* LiquidIO driver pivate flags */
enum { enum {
OCT_PRIV_FLAG_TX_BYTES = 0, /* Tx interrupts by pending byte count */ OCT_PRIV_FLAG_TX_BYTES = 0, /* Tx interrupts by pending byte count */
......
...@@ -92,22 +92,25 @@ static inline void *octeon_get_dispatch_arg(struct octeon_device *octeon_dev, ...@@ -92,22 +92,25 @@ static inline void *octeon_get_dispatch_arg(struct octeon_device *octeon_dev,
return fn_arg; return fn_arg;
} }
/** Check for packets on Droq. This function should be called with /** Check for packets on Droq. This function should be called with lock held.
* lock held.
* @param droq - Droq on which count is checked. * @param droq - Droq on which count is checked.
* @return Returns packet count. * @return Returns packet count.
*/ */
u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq) u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq)
{ {
u32 pkt_count = 0; u32 pkt_count = 0;
u32 last_count;
pkt_count = readl(droq->pkts_sent_reg); pkt_count = readl(droq->pkts_sent_reg);
if (pkt_count) {
atomic_add(pkt_count, &droq->pkts_pending);
writel(pkt_count, droq->pkts_sent_reg);
}
return pkt_count; last_count = pkt_count - droq->pkt_count;
droq->pkt_count = pkt_count;
/* we shall write to cnts at napi irq enable or end of droq tasklet */
if (last_count)
atomic_add(last_count, &droq->pkts_pending);
return last_count;
} }
static void octeon_droq_compute_max_packet_bufs(struct octeon_droq *droq) static void octeon_droq_compute_max_packet_bufs(struct octeon_droq *droq)
...@@ -735,16 +738,20 @@ octeon_droq_process_packets(struct octeon_device *oct, ...@@ -735,16 +738,20 @@ octeon_droq_process_packets(struct octeon_device *oct,
u32 pkt_count = 0, pkts_processed = 0; u32 pkt_count = 0, pkts_processed = 0;
struct list_head *tmp, *tmp2; struct list_head *tmp, *tmp2;
/* Grab the droq lock */
spin_lock(&droq->lock);
octeon_droq_check_hw_for_pkts(droq);
pkt_count = atomic_read(&droq->pkts_pending); pkt_count = atomic_read(&droq->pkts_pending);
if (!pkt_count)
if (!pkt_count) {
spin_unlock(&droq->lock);
return 0; return 0;
}
if (pkt_count > budget) if (pkt_count > budget)
pkt_count = budget; pkt_count = budget;
/* Grab the droq lock */
spin_lock(&droq->lock);
pkts_processed = octeon_droq_fast_process_packets(oct, droq, pkt_count); pkts_processed = octeon_droq_fast_process_packets(oct, droq, pkt_count);
atomic_sub(pkts_processed, &droq->pkts_pending); atomic_sub(pkts_processed, &droq->pkts_pending);
...@@ -789,6 +796,8 @@ octeon_droq_process_poll_pkts(struct octeon_device *oct, ...@@ -789,6 +796,8 @@ octeon_droq_process_poll_pkts(struct octeon_device *oct,
spin_lock(&droq->lock); spin_lock(&droq->lock);
while (total_pkts_processed < budget) { while (total_pkts_processed < budget) {
octeon_droq_check_hw_for_pkts(droq);
pkts_available = pkts_available =
CVM_MIN((budget - total_pkts_processed), CVM_MIN((budget - total_pkts_processed),
(u32)(atomic_read(&droq->pkts_pending))); (u32)(atomic_read(&droq->pkts_pending)));
...@@ -803,8 +812,6 @@ octeon_droq_process_poll_pkts(struct octeon_device *oct, ...@@ -803,8 +812,6 @@ octeon_droq_process_poll_pkts(struct octeon_device *oct,
atomic_sub(pkts_processed, &droq->pkts_pending); atomic_sub(pkts_processed, &droq->pkts_pending);
total_pkts_processed += pkts_processed; total_pkts_processed += pkts_processed;
octeon_droq_check_hw_for_pkts(droq);
} }
spin_unlock(&droq->lock); spin_unlock(&droq->lock);
......
...@@ -261,6 +261,8 @@ struct octeon_droq { ...@@ -261,6 +261,8 @@ struct octeon_droq {
u32 q_no; u32 q_no;
u32 pkt_count;
struct octeon_droq_ops ops; struct octeon_droq_ops ops;
struct octeon_device *oct_dev; struct octeon_device *oct_dev;
......
...@@ -88,6 +88,8 @@ struct octeon_instr_queue { ...@@ -88,6 +88,8 @@ struct octeon_instr_queue {
/** A spinlock to protect while posting on the ring. */ /** A spinlock to protect while posting on the ring. */
spinlock_t post_lock; spinlock_t post_lock;
u32 pkt_in_done;
/** A spinlock to protect access to the input ring.*/ /** A spinlock to protect access to the input ring.*/
spinlock_t iq_flush_running_lock; spinlock_t iq_flush_running_lock;
......
...@@ -38,12 +38,26 @@ ...@@ -38,12 +38,26 @@
#define DRV_NAME "LiquidIO" #define DRV_NAME "LiquidIO"
/** /** This structure is used by NIC driver to store information required
* \brief determines if a given console has debug enabled. * to free the sk_buff when the packet has been fetched by Octeon.
* @param console console to check * Bytes offset below assume worst-case of a 64-bit system.
* @returns 1 = enabled. 0 otherwise
*/ */
int octeon_console_debug_enabled(u32 console); struct octnet_buf_free_info {
/** Bytes 1-8. Pointer to network device private structure. */
struct lio *lio;
/** Bytes 9-16. Pointer to sk_buff. */
struct sk_buff *skb;
/** Bytes 17-24. Pointer to gather list. */
struct octnic_gather *g;
/** Bytes 25-32. Physical address of skb->data or gather list. */
u64 dptr;
/** Bytes 33-47. Piggybacked soft command, if any */
struct octeon_soft_command *sc;
};
/* BQL-related functions */ /* BQL-related functions */
void octeon_report_sent_bytes_to_bql(void *buf, int reqtype); void octeon_report_sent_bytes_to_bql(void *buf, int reqtype);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
* This file may also be available under a different license from Cavium. * This file may also be available under a different license from Cavium.
* Contact Cavium, Inc. for more information * Contact Cavium, Inc. for more information
**********************************************************************/ **********************************************************************/
#include <linux/pci.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include "liquidio_common.h" #include "liquidio_common.h"
#include "octeon_droq.h" #include "octeon_droq.h"
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#ifndef __OCTEON_NETWORK_H__ #ifndef __OCTEON_NETWORK_H__
#define __OCTEON_NETWORK_H__ #define __OCTEON_NETWORK_H__
#include <linux/version.h>
#include <linux/dma-mapping.h>
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
#define LIO_MAX_MTU_SIZE (OCTNET_MAX_FRM_SIZE - OCTNET_FRM_HEADER_SIZE) #define LIO_MAX_MTU_SIZE (OCTNET_MAX_FRM_SIZE - OCTNET_FRM_HEADER_SIZE)
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
* This file may also be available under a different license from Cavium. * This file may also be available under a different license from Cavium.
* Contact Cavium, Inc. for more information * Contact Cavium, Inc. for more information
**********************************************************************/ **********************************************************************/
#include <linux/interrupt.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include "liquidio_common.h" #include "liquidio_common.h"
...@@ -73,12 +72,9 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct, ...@@ -73,12 +72,9 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
} }
int octnet_send_nic_data_pkt(struct octeon_device *oct, int octnet_send_nic_data_pkt(struct octeon_device *oct,
struct octnic_data_pkt *ndata, struct octnic_data_pkt *ndata)
u32 xmit_more)
{ {
int ring_doorbell; int ring_doorbell = 1;
ring_doorbell = !xmit_more;
return octeon_send_command(oct, ndata->q_no, ring_doorbell, &ndata->cmd, return octeon_send_command(oct, ndata->q_no, ring_doorbell, &ndata->cmd,
ndata->buf, ndata->datasize, ndata->buf, ndata->datasize,
......
...@@ -278,7 +278,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct, ...@@ -278,7 +278,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
* queue should be stopped, and IQ_SEND_OK if it sent okay. * queue should be stopped, and IQ_SEND_OK if it sent okay.
*/ */
int octnet_send_nic_data_pkt(struct octeon_device *oct, int octnet_send_nic_data_pkt(struct octeon_device *oct,
struct octnic_data_pkt *ndata, u32 xmit_more); struct octnic_data_pkt *ndata);
/** Send a NIC control packet to the device /** Send a NIC control packet to the device
* @param oct - octeon device pointer * @param oct - octeon device pointer
......
...@@ -499,6 +499,7 @@ static void __check_db_timeout(struct octeon_device *oct, u64 iq_no) ...@@ -499,6 +499,7 @@ static void __check_db_timeout(struct octeon_device *oct, u64 iq_no)
if (!oct) if (!oct)
return; return;
iq = oct->instr_queue[iq_no]; iq = oct->instr_queue[iq_no];
if (!iq) if (!iq)
return; return;
...@@ -514,6 +515,8 @@ static void __check_db_timeout(struct octeon_device *oct, u64 iq_no) ...@@ -514,6 +515,8 @@ static void __check_db_timeout(struct octeon_device *oct, u64 iq_no)
/* Flush the instruction queue */ /* Flush the instruction queue */
octeon_flush_iq(oct, iq, 1, 0); octeon_flush_iq(oct, iq, 1, 0);
lio_enable_irq(NULL, iq);
} }
/* Called by the Poll thread at regular intervals to check the instruction /* Called by the Poll thread at regular intervals to check the instruction
......
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