Commit 492e9d8c authored by David S. Miller's avatar David S. Miller

Merge branch 'liquidio-VF'

Raghu Vatsavayi says:

====================
liquidio VF operations

This patchseries adds support for VF device specific operations
like mailbox, queues and register access. This V3 patchset also
has changes based on comments form earlier versions:

1) Removed extra 'void *' casting.
2) Fixed all cross compilations issues reported on S390 and Powerpc
   architectures.

Please apply the patches in following order as these patches depend
on each other.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1379fd3c b3c35973
...@@ -74,4 +74,16 @@ config OCTEON_MGMT_ETHERNET ...@@ -74,4 +74,16 @@ config OCTEON_MGMT_ETHERNET
port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX, port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
CN54XX, CN52XX, and CN6XXX chips. CN54XX, CN52XX, and CN6XXX chips.
config LIQUIDIO_VF
tristate "Cavium LiquidIO VF support"
depends on 64BIT && PCI_MSI
select PTP_1588_CLOCK
---help---
This driver supports Cavium LiquidIO Intelligent Server Adapter
based on CN23XX chips.
To compile this driver as a module, choose M here: The module
will be called liquidio_vf. MSI-X interrupt support is required
for this driver to work correctly
endif # NET_VENDOR_CAVIUM endif # NET_VENDOR_CAVIUM
...@@ -11,9 +11,32 @@ liquidio-$(CONFIG_LIQUIDIO) += lio_ethtool.o \ ...@@ -11,9 +11,32 @@ liquidio-$(CONFIG_LIQUIDIO) += lio_ethtool.o \
cn66xx_device.o \ cn66xx_device.o \
cn68xx_device.o \ cn68xx_device.o \
cn23xx_pf_device.o \ cn23xx_pf_device.o \
cn23xx_vf_device.o \
octeon_mailbox.o \ octeon_mailbox.o \
octeon_mem_ops.o \ octeon_mem_ops.o \
octeon_droq.o \ octeon_droq.o \
octeon_nic.o octeon_nic.o
liquidio-objs := lio_main.o octeon_console.o $(liquidio-y) liquidio-objs := lio_main.o octeon_console.o $(liquidio-y)
obj-$(CONFIG_LIQUIDIO_VF) += liquidio_vf.o
ifeq ($(CONFIG_LIQUIDIO)$(CONFIG_LIQUIDIO_VF), yy)
liquidio_vf-objs := lio_vf_main.o
else
liquidio_vf-$(CONFIG_LIQUIDIO_VF) += lio_ethtool.o \
lio_core.o \
request_manager.o \
response_manager.o \
octeon_device.o \
cn66xx_device.o \
cn68xx_device.o \
cn23xx_pf_device.o \
cn23xx_vf_device.o \
octeon_mailbox.o \
octeon_mem_ops.o \
octeon_droq.o \
octeon_nic.o
liquidio_vf-objs := lio_vf_main.o $(liquidio_vf-y)
endif
This diff is collapsed.
/**********************************************************************
* Author: Cavium, Inc.
*
* Contact: support@cavium.com
* Please include "LiquidIO" in the subject.
*
* Copyright (c) 2003-2016 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.
***********************************************************************/
/*! \file cn23xx_device.h
* \brief Host Driver: Routines that perform CN23XX specific operations.
*/
#ifndef __CN23XX_VF_DEVICE_H__
#define __CN23XX_VF_DEVICE_H__
#include "cn23xx_vf_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_vf {
struct octeon_config *conf;
};
#define BUSY_READING_REG_VF_LOOP_COUNT 10000
#define CN23XX_MAILBOX_MSGPARAM_SIZE 6
#define MAX_VF_IP_OP_PENDING_PKT_COUNT 100
void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct);
int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct);
int cn23xx_setup_octeon_vf_device(struct octeon_device *oct);
void cn23xx_dump_vf_initialized_regs(struct octeon_device *oct);
#endif
This diff is collapsed.
...@@ -85,13 +85,6 @@ void octeon_update_tx_completion_counters(void *buf, int reqtype, ...@@ -85,13 +85,6 @@ void octeon_update_tx_completion_counters(void *buf, int reqtype,
} }
(*pkts_compl)++; (*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; *bytes_compl += skb->len;
} }
......
...@@ -40,6 +40,7 @@ MODULE_VERSION(LIQUIDIO_VERSION); ...@@ -40,6 +40,7 @@ MODULE_VERSION(LIQUIDIO_VERSION);
MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210SV_NAME LIO_FW_NAME_SUFFIX); MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210SV_NAME LIO_FW_NAME_SUFFIX);
MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210NV_NAME LIO_FW_NAME_SUFFIX); MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210NV_NAME LIO_FW_NAME_SUFFIX);
MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_410NV_NAME LIO_FW_NAME_SUFFIX); MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_410NV_NAME LIO_FW_NAME_SUFFIX);
MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_23XX_NAME LIO_FW_NAME_SUFFIX);
static int ddr_timeout = 10000; static int ddr_timeout = 10000;
module_param(ddr_timeout, int, 0644); module_param(ddr_timeout, int, 0644);
...@@ -4484,7 +4485,10 @@ static int octeon_device_init(struct octeon_device *octeon_dev) ...@@ -4484,7 +4485,10 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
atomic_set(&octeon_dev->status, OCT_DEV_DISPATCH_INIT_DONE); atomic_set(&octeon_dev->status, OCT_DEV_DISPATCH_INIT_DONE);
octeon_set_io_queues_off(octeon_dev); if (octeon_set_io_queues_off(octeon_dev)) {
dev_err(&octeon_dev->pci_dev->dev, "setting io queues off failed\n");
return 1;
}
if (OCTEON_CN23XX_PF(octeon_dev)) { if (OCTEON_CN23XX_PF(octeon_dev)) {
ret = octeon_dev->fn_list.setup_device_regs(octeon_dev); ret = octeon_dev->fn_list.setup_device_regs(octeon_dev);
......
This diff is collapsed.
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "cn66xx_regs.h" #include "cn66xx_regs.h"
#include "cn66xx_device.h" #include "cn66xx_device.h"
#include "cn23xx_pf_device.h" #include "cn23xx_pf_device.h"
#include "cn23xx_vf_device.h"
/** Default configuration /** Default configuration
* for CN66XX OCTEON Models. * for CN66XX OCTEON Models.
...@@ -571,15 +572,17 @@ static void *__retrieve_octeon_config_info(struct octeon_device *oct, ...@@ -571,15 +572,17 @@ static void *__retrieve_octeon_config_info(struct octeon_device *oct,
switch (oct_conf_info[oct_id].conf_type) { switch (oct_conf_info[oct_id].conf_type) {
case OCTEON_CONFIG_TYPE_DEFAULT: case OCTEON_CONFIG_TYPE_DEFAULT:
if (oct->chip_id == OCTEON_CN66XX) { if (oct->chip_id == OCTEON_CN66XX) {
ret = (void *)&default_cn66xx_conf; ret = &default_cn66xx_conf;
} else if ((oct->chip_id == OCTEON_CN68XX) && } else if ((oct->chip_id == OCTEON_CN68XX) &&
(card_type == LIO_210NV)) { (card_type == LIO_210NV)) {
ret = (void *)&default_cn68xx_210nv_conf; ret = &default_cn68xx_210nv_conf;
} else if ((oct->chip_id == OCTEON_CN68XX) && } else if ((oct->chip_id == OCTEON_CN68XX) &&
(card_type == LIO_410NV)) { (card_type == LIO_410NV)) {
ret = (void *)&default_cn68xx_conf; ret = &default_cn68xx_conf;
} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) { } else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
ret = (void *)&default_cn23xx_conf; ret = &default_cn23xx_conf;
} else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
ret = &default_cn23xx_conf;
} }
break; break;
default: default:
...@@ -595,6 +598,7 @@ static int __verify_octeon_config_info(struct octeon_device *oct, void *conf) ...@@ -595,6 +598,7 @@ static int __verify_octeon_config_info(struct octeon_device *oct, void *conf)
case OCTEON_CN68XX: case OCTEON_CN68XX:
return lio_validate_cn6xxx_config_info(oct, conf); return lio_validate_cn6xxx_config_info(oct, conf);
case OCTEON_CN23XX_PF_VID: case OCTEON_CN23XX_PF_VID:
case OCTEON_CN23XX_VF_VID:
return 0; return 0;
default: default:
break; break;
...@@ -672,6 +676,9 @@ static struct octeon_device *octeon_allocate_device_mem(u32 pci_id, ...@@ -672,6 +676,9 @@ static struct octeon_device *octeon_allocate_device_mem(u32 pci_id,
case OCTEON_CN23XX_PF_VID: case OCTEON_CN23XX_PF_VID:
configsize = sizeof(struct octeon_cn23xx_pf); configsize = sizeof(struct octeon_cn23xx_pf);
break; break;
case OCTEON_CN23XX_VF_VID:
configsize = sizeof(struct octeon_cn23xx_vf);
break;
default: default:
pr_err("%s: Unknown PCI Device: 0x%x\n", pr_err("%s: Unknown PCI Device: 0x%x\n",
__func__, __func__,
...@@ -747,6 +754,9 @@ octeon_allocate_ioq_vector(struct octeon_device *oct) ...@@ -747,6 +754,9 @@ octeon_allocate_ioq_vector(struct octeon_device *oct)
if (OCTEON_CN23XX_PF(oct)) if (OCTEON_CN23XX_PF(oct))
num_ioqs = oct->sriov_info.num_pf_rings; num_ioqs = oct->sriov_info.num_pf_rings;
else if (OCTEON_CN23XX_VF(oct))
num_ioqs = oct->sriov_info.rings_per_vf;
size = sizeof(struct octeon_ioq_vector) * num_ioqs; size = sizeof(struct octeon_ioq_vector) * num_ioqs;
oct->ioq_vector = vmalloc(size); oct->ioq_vector = vmalloc(size);
...@@ -790,6 +800,8 @@ int octeon_setup_instr_queues(struct octeon_device *oct) ...@@ -790,6 +800,8 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn6xxx)); CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn6xxx));
else if (OCTEON_CN23XX_PF(oct)) else if (OCTEON_CN23XX_PF(oct))
num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_pf)); num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_pf));
else if (OCTEON_CN23XX_VF(oct))
num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_vf));
oct->num_iqs = 0; oct->num_iqs = 0;
...@@ -835,6 +847,9 @@ int octeon_setup_output_queues(struct octeon_device *oct) ...@@ -835,6 +847,9 @@ int octeon_setup_output_queues(struct octeon_device *oct)
} else if (OCTEON_CN23XX_PF(oct)) { } else if (OCTEON_CN23XX_PF(oct)) {
num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_pf)); num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_pf));
desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_pf)); desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_pf));
} else if (OCTEON_CN23XX_VF(oct)) {
num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_vf));
desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_vf));
} }
oct->num_oqs = 0; oct->num_oqs = 0;
oct->droq[0] = vmalloc_node(sizeof(*oct->droq[0]), numa_node); oct->droq[0] = vmalloc_node(sizeof(*oct->droq[0]), numa_node);
...@@ -853,12 +868,53 @@ int octeon_setup_output_queues(struct octeon_device *oct) ...@@ -853,12 +868,53 @@ int octeon_setup_output_queues(struct octeon_device *oct)
return 0; return 0;
} }
void octeon_set_io_queues_off(struct octeon_device *oct) int octeon_set_io_queues_off(struct octeon_device *oct)
{ {
int loop = BUSY_READING_REG_VF_LOOP_COUNT;
if (OCTEON_CN6XXX(oct)) { if (OCTEON_CN6XXX(oct)) {
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0); octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0); octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
} else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
u32 q_no;
/* IOQs will already be in reset.
* If RST bit is set, wait for quiet bit to be set.
* Once quiet bit is set, clear the RST bit.
*/
for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) {
u64 reg_val = octeon_read_csr64(
oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
while ((reg_val & CN23XX_PKT_INPUT_CTL_RST) &&
!(reg_val & CN23XX_PKT_INPUT_CTL_QUIET) &&
loop) {
reg_val = octeon_read_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
loop--;
}
if (!loop) {
dev_err(&oct->pci_dev->dev,
"clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
q_no);
return -1;
} }
reg_val = reg_val & ~CN23XX_PKT_INPUT_CTL_RST;
octeon_write_csr64(oct,
CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
reg_val);
reg_val = octeon_read_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
if (reg_val & CN23XX_PKT_INPUT_CTL_RST) {
dev_err(&oct->pci_dev->dev,
"unable to reset qno %u\n", q_no);
return -1;
}
}
}
return 0;
} }
void octeon_set_droq_pkt_op(struct octeon_device *oct, void octeon_set_droq_pkt_op(struct octeon_device *oct,
......
...@@ -53,6 +53,7 @@ enum { ...@@ -53,6 +53,7 @@ enum {
NUM_OCTEON_CONFS, NUM_OCTEON_CONFS,
}; };
#define OCTEON_INPUT_INTR (1)
#define OCTEON_OUTPUT_INTR (2) #define OCTEON_OUTPUT_INTR (2)
#define OCTEON_MBOX_INTR (4) #define OCTEON_MBOX_INTR (4)
#define OCTEON_ALL_INTR 0xff #define OCTEON_ALL_INTR 0xff
...@@ -294,6 +295,7 @@ struct octdev_props { ...@@ -294,6 +295,7 @@ struct octdev_props {
#define LIO_FLAG_MSIX_ENABLED 0x1 #define LIO_FLAG_MSIX_ENABLED 0x1
#define MSIX_PO_INT 0x1 #define MSIX_PO_INT 0x1
#define MSIX_PI_INT 0x2 #define MSIX_PI_INT 0x2
#define MSIX_MBOX_INT 0x4
struct octeon_pf_vf_hs_word { struct octeon_pf_vf_hs_word {
#ifdef __LITTLE_ENDIAN_BITFIELD #ifdef __LITTLE_ENDIAN_BITFIELD
...@@ -401,8 +403,13 @@ struct octeon_device { ...@@ -401,8 +403,13 @@ struct octeon_device {
/** Octeon Chip type. */ /** Octeon Chip type. */
u16 chip_id; u16 chip_id;
u16 rev_id; u16 rev_id;
u16 pf_num; u16 pf_num;
u16 vf_num;
/** This device's id - set by the driver. */ /** This device's id - set by the driver. */
u32 octeon_id; u32 octeon_id;
...@@ -766,7 +773,7 @@ int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no); ...@@ -766,7 +773,7 @@ int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no);
/** Turns off the input and output queues for the device /** Turns off the input and output queues for the device
* @param oct which octeon to disable * @param oct which octeon to disable
*/ */
void octeon_set_io_queues_off(struct octeon_device *oct); int octeon_set_io_queues_off(struct octeon_device *oct);
/** Turns on or off the given output queue for the device /** Turns on or off the given output queue for the device
* @param oct which octeon to change * @param oct which octeon to change
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "octeon_network.h" #include "octeon_network.h"
#include "cn66xx_device.h" #include "cn66xx_device.h"
#include "cn23xx_pf_device.h" #include "cn23xx_pf_device.h"
#include "cn23xx_vf_device.h"
struct iq_post_status { struct iq_post_status {
int status; int status;
...@@ -68,6 +69,9 @@ int octeon_init_instr_queue(struct octeon_device *oct, ...@@ -68,6 +69,9 @@ int octeon_init_instr_queue(struct octeon_device *oct,
conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn6xxx))); conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn6xxx)));
else if (OCTEON_CN23XX_PF(oct)) else if (OCTEON_CN23XX_PF(oct))
conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn23xx_pf))); conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn23xx_pf)));
else if (OCTEON_CN23XX_VF(oct))
conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn23xx_vf)));
if (!conf) { if (!conf) {
dev_err(&oct->pci_dev->dev, "Unsupported Chip %x\n", dev_err(&oct->pci_dev->dev, "Unsupported Chip %x\n",
oct->chip_id); oct->chip_id);
...@@ -183,6 +187,9 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no) ...@@ -183,6 +187,9 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no)
else if (OCTEON_CN23XX_PF(oct)) else if (OCTEON_CN23XX_PF(oct))
desc_size = desc_size =
CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn23xx_pf)); CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn23xx_pf));
else if (OCTEON_CN23XX_VF(oct))
desc_size =
CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn23xx_vf));
vfree(iq->request_list); vfree(iq->request_list);
...@@ -235,7 +242,9 @@ int octeon_setup_iq(struct octeon_device *oct, ...@@ -235,7 +242,9 @@ int octeon_setup_iq(struct octeon_device *oct,
} }
oct->num_iqs++; oct->num_iqs++;
oct->fn_list.enable_io_queues(oct); if (oct->fn_list.enable_io_queues(oct))
return 1;
return 0; return 0;
} }
......
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