aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/cavium/liquidio/octeon_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/cavium/liquidio/octeon_device.c')
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_device.c66
1 files changed, 61 insertions, 5 deletions
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index 79c8875ffd61..6d54032b10ab 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
@@ -28,6 +28,7 @@
#include "cn66xx_regs.h"
#include "cn66xx_device.h"
#include "cn23xx_pf_device.h"
+#include "cn23xx_vf_device.h"
/** Default configuration
* for CN66XX OCTEON Models.
@@ -571,15 +572,17 @@ static void *__retrieve_octeon_config_info(struct octeon_device *oct,
switch (oct_conf_info[oct_id].conf_type) {
case OCTEON_CONFIG_TYPE_DEFAULT:
if (oct->chip_id == OCTEON_CN66XX) {
- ret = (void *)&default_cn66xx_conf;
+ ret = &default_cn66xx_conf;
} else if ((oct->chip_id == OCTEON_CN68XX) &&
(card_type == LIO_210NV)) {
- ret = (void *)&default_cn68xx_210nv_conf;
+ ret = &default_cn68xx_210nv_conf;
} else if ((oct->chip_id == OCTEON_CN68XX) &&
(card_type == LIO_410NV)) {
- ret = (void *)&default_cn68xx_conf;
+ ret = &default_cn68xx_conf;
} 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;
default:
@@ -595,6 +598,7 @@ static int __verify_octeon_config_info(struct octeon_device *oct, void *conf)
case OCTEON_CN68XX:
return lio_validate_cn6xxx_config_info(oct, conf);
case OCTEON_CN23XX_PF_VID:
+ case OCTEON_CN23XX_VF_VID:
return 0;
default:
break;
@@ -672,6 +676,9 @@ static struct octeon_device *octeon_allocate_device_mem(u32 pci_id,
case OCTEON_CN23XX_PF_VID:
configsize = sizeof(struct octeon_cn23xx_pf);
break;
+ case OCTEON_CN23XX_VF_VID:
+ configsize = sizeof(struct octeon_cn23xx_vf);
+ break;
default:
pr_err("%s: Unknown PCI Device: 0x%x\n",
__func__,
@@ -747,6 +754,9 @@ octeon_allocate_ioq_vector(struct octeon_device *oct)
if (OCTEON_CN23XX_PF(oct))
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;
oct->ioq_vector = vmalloc(size);
@@ -790,6 +800,8 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn6xxx));
else if (OCTEON_CN23XX_PF(oct))
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;
@@ -835,6 +847,9 @@ int octeon_setup_output_queues(struct octeon_device *oct)
} else if (OCTEON_CN23XX_PF(oct)) {
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));
+ } 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->droq[0] = vmalloc_node(sizeof(*oct->droq[0]), numa_node);
@@ -853,12 +868,53 @@ int octeon_setup_output_queues(struct octeon_device *oct)
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)) {
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_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,