* [PATCH net-next V3 3/9] liquidio CN23XX: VF config setup
From: Raghu Vatsavayi @ 2016-11-29 0:54 UTC (permalink / raw)
To: davem
Cc: netdev, Raghu Vatsavayi, Raghu Vatsavayi, Derek Chickles,
Satanand Burla, Felix Manlunas
In-Reply-To: <1480380881-19255-1-git-send-email-rvatsavayi@caviumnetworks.com>
Adds support for setting up VF configuration.
Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
---
drivers/net/ethernet/cavium/liquidio/Makefile | 2 +
.../ethernet/cavium/liquidio/cn23xx_vf_device.c | 44 +++++++
.../ethernet/cavium/liquidio/cn23xx_vf_device.h | 2 +
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 136 +++++++++++++++++++++
.../net/ethernet/cavium/liquidio/octeon_device.c | 11 +-
5 files changed, 191 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
diff --git a/drivers/net/ethernet/cavium/liquidio/Makefile b/drivers/net/ethernet/cavium/liquidio/Makefile
index 69d23fc..c4d411d 100644
--- a/drivers/net/ethernet/cavium/liquidio/Makefile
+++ b/drivers/net/ethernet/cavium/liquidio/Makefile
@@ -11,6 +11,7 @@ liquidio-$(CONFIG_LIQUIDIO) += lio_ethtool.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 \
@@ -31,6 +32,7 @@ liquidio_vf-$(CONFIG_LIQUIDIO_VF) += lio_ethtool.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 \
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
new file mode 100644
index 0000000..d683bda
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
@@ -0,0 +1,44 @@
+/**********************************************************************
+ * 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.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+#include "cn23xx_vf_device.h"
+#include "octeon_main.h"
+
+int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
+{
+ struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+
+ if (octeon_map_pci_barx(oct, 0, 0))
+ return 1;
+
+ cn23xx->conf = oct_get_config_info(oct, LIO_23XX);
+ if (!cn23xx->conf) {
+ dev_err(&oct->pci_dev->dev, "%s No Config found for CN23XX\n",
+ __func__);
+ octeon_unmap_pci_barx(oct, 0);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
index 015b6d4..9e4fb50 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
@@ -31,4 +31,6 @@
struct octeon_cn23xx_vf {
struct octeon_config *conf;
};
+
+int cn23xx_setup_octeon_vf_device(struct octeon_device *oct);
#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index fd108cd..dd1dad1 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -22,6 +22,8 @@
#include "octeon_iq.h"
#include "response_manager.h"
#include "octeon_device.h"
+#include "octeon_main.h"
+#include "cn23xx_vf_device.h"
MODULE_AUTHOR("Cavium Networks, <support@cavium.com>");
MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Virtual Function Driver");
@@ -37,6 +39,7 @@ struct octeon_device_priv {
static int
liquidio_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void liquidio_vf_remove(struct pci_dev *pdev);
+static int octeon_device_init(struct octeon_device *oct);
static const struct pci_device_id liquidio_vf_pci_tbl[] = {
{
@@ -84,10 +87,78 @@ struct octeon_device_priv {
/* set linux specific device pointer */
oct_dev->pci_dev = pdev;
+ if (octeon_device_init(oct_dev)) {
+ liquidio_vf_remove(pdev);
+ return -ENOMEM;
+ }
+
+ dev_dbg(&oct_dev->pci_dev->dev, "Device is ready\n");
+
return 0;
}
/**
+ * \brief PCI FLR for each Octeon device.
+ * @param oct octeon device
+ */
+static void octeon_pci_flr(struct octeon_device *oct)
+{
+ u16 status;
+
+ pci_save_state(oct->pci_dev);
+
+ pci_cfg_access_lock(oct->pci_dev);
+
+ /* Quiesce the device completely */
+ pci_write_config_word(oct->pci_dev, PCI_COMMAND,
+ PCI_COMMAND_INTX_DISABLE);
+
+ /* Wait for Transaction Pending bit clean */
+ msleep(100);
+ pcie_capability_read_word(oct->pci_dev, PCI_EXP_DEVSTA, &status);
+ if (status & PCI_EXP_DEVSTA_TRPND) {
+ dev_info(&oct->pci_dev->dev, "Function reset incomplete after 100ms, sleeping for 5 seconds\n");
+ ssleep(5);
+ pcie_capability_read_word(oct->pci_dev, PCI_EXP_DEVSTA,
+ &status);
+ if (status & PCI_EXP_DEVSTA_TRPND)
+ dev_info(&oct->pci_dev->dev, "Function reset still incomplete after 5s, reset anyway\n");
+ }
+ pcie_capability_set_word(oct->pci_dev, PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_BCR_FLR);
+ mdelay(100);
+
+ pci_cfg_access_unlock(oct->pci_dev);
+
+ pci_restore_state(oct->pci_dev);
+}
+
+/**
+ *\brief Destroy resources associated with octeon device
+ * @param pdev PCI device structure
+ * @param ent unused
+ */
+static void octeon_destroy_resources(struct octeon_device *oct)
+{
+ switch (atomic_read(&oct->status)) {
+ case OCT_DEV_PCI_MAP_DONE:
+ octeon_unmap_pci_barx(oct, 0);
+ octeon_unmap_pci_barx(oct, 1);
+
+ /* fallthrough */
+ case OCT_DEV_PCI_ENABLE_DONE:
+ pci_clear_master(oct->pci_dev);
+ /* Disable the device, releasing the PCI INT */
+ pci_disable_device(oct->pci_dev);
+
+ /* fallthrough */
+ case OCT_DEV_BEGIN_STATE:
+ /* Nothing to be done here either */
+ break;
+ }
+}
+
+/**
* \brief Cleans up resources at unload time
* @param pdev PCI device structure
*/
@@ -97,12 +168,77 @@ static void liquidio_vf_remove(struct pci_dev *pdev)
dev_dbg(&oct_dev->pci_dev->dev, "Stopping device\n");
+ /* Reset the octeon device and cleanup all memory allocated for
+ * the octeon device by driver.
+ */
+ octeon_destroy_resources(oct_dev);
+
+ dev_info(&oct_dev->pci_dev->dev, "Device removed\n");
+
/* This octeon device has been removed. Update the global
* data structure to reflect this. Free the device structure.
*/
octeon_free_device_mem(oct_dev);
}
+/**
+ * \brief PCI initialization for each Octeon device.
+ * @param oct octeon device
+ */
+static int octeon_pci_os_setup(struct octeon_device *oct)
+{
+#ifdef CONFIG_PCI_IOV
+ /* setup PCI stuff first */
+ if (!oct->pci_dev->physfn)
+ octeon_pci_flr(oct);
+#endif
+
+ if (pci_enable_device(oct->pci_dev)) {
+ dev_err(&oct->pci_dev->dev, "pci_enable_device failed\n");
+ return 1;
+ }
+
+ if (dma_set_mask_and_coherent(&oct->pci_dev->dev, DMA_BIT_MASK(64))) {
+ dev_err(&oct->pci_dev->dev, "Unexpected DMA device capability\n");
+ pci_disable_device(oct->pci_dev);
+ return 1;
+ }
+
+ /* Enable PCI DMA Master. */
+ pci_set_master(oct->pci_dev);
+
+ return 0;
+}
+
+/**
+ * \brief Device initialization for each Octeon device that is probed
+ * @param octeon_dev octeon device
+ */
+static int octeon_device_init(struct octeon_device *oct)
+{
+ u32 rev_id;
+
+ atomic_set(&oct->status, OCT_DEV_BEGIN_STATE);
+
+ /* Enable access to the octeon device and make its DMA capability
+ * known to the OS.
+ */
+ if (octeon_pci_os_setup(oct))
+ return 1;
+ atomic_set(&oct->status, OCT_DEV_PCI_ENABLE_DONE);
+
+ oct->chip_id = OCTEON_CN23XX_VF_VID;
+ pci_read_config_dword(oct->pci_dev, 8, &rev_id);
+ oct->rev_id = rev_id & 0xff;
+
+ if (cn23xx_setup_octeon_vf_device(oct))
+ return 1;
+
+ atomic_set(&oct->status, OCT_DEV_PCI_MAP_DONE);
+
+ return 0;
+}
+
static int __init liquidio_vf_init(void)
{
octeon_init_device_list(0);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index 05bb0fd..7e6c8b8 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
@@ -572,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:
@@ -596,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;
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next V3 5/9] liquidio CN23XX: VF register access
From: Raghu Vatsavayi @ 2016-11-29 0:54 UTC (permalink / raw)
To: davem
Cc: netdev, Raghu Vatsavayi, Raghu Vatsavayi, Derek Chickles,
Satanand Burla, Felix Manlunas
In-Reply-To: <1480380881-19255-1-git-send-email-rvatsavayi@caviumnetworks.com>
This patch adds support for VF device register access.
Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
---
.../ethernet/cavium/liquidio/cn23xx_vf_device.c | 189 +++++++++++++++++++++
.../ethernet/cavium/liquidio/cn23xx_vf_device.h | 2 +
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 5 +
3 files changed, 196 insertions(+)
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
index 60fd138..ad4e442 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
@@ -76,6 +76,161 @@ static int cn23xx_vf_reset_io_queues(struct octeon_device *oct, u32 num_queues)
return ret_val;
}
+static int cn23xx_vf_setup_global_input_regs(struct octeon_device *oct)
+{
+ struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+ struct octeon_instr_queue *iq;
+ u64 q_no, intr_threshold;
+ u64 d64;
+
+ if (cn23xx_vf_reset_io_queues(oct, oct->sriov_info.rings_per_vf))
+ return -1;
+
+ for (q_no = 0; q_no < (oct->sriov_info.rings_per_vf); q_no++) {
+ void __iomem *inst_cnt_reg;
+
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_DOORBELL(q_no),
+ 0xFFFFFFFF);
+ iq = oct->instr_queue[q_no];
+
+ if (iq)
+ inst_cnt_reg = iq->inst_cnt_reg;
+ else
+ inst_cnt_reg = (u8 *)oct->mmio[0].hw_addr +
+ CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no);
+
+ d64 = octeon_read_csr64(oct,
+ CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no));
+
+ d64 &= 0xEFFFFFFFFFFFFFFFL;
+
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no),
+ d64);
+
+ /* Select ES, RO, NS, RDSIZE,DPTR Fomat#0 for
+ * the Input Queues
+ */
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ CN23XX_PKT_INPUT_CTL_MASK);
+
+ /* set the wmark level to trigger PI_INT */
+ intr_threshold = CFG_GET_IQ_INTR_PKT(cn23xx->conf) &
+ CN23XX_PKT_IN_DONE_WMARK_MASK;
+
+ writeq((readq(inst_cnt_reg) &
+ ~(CN23XX_PKT_IN_DONE_WMARK_MASK <<
+ CN23XX_PKT_IN_DONE_WMARK_BIT_POS)) |
+ (intr_threshold << CN23XX_PKT_IN_DONE_WMARK_BIT_POS),
+ inst_cnt_reg);
+ }
+ return 0;
+}
+
+static void cn23xx_vf_setup_global_output_regs(struct octeon_device *oct)
+{
+ u32 reg_val;
+ u32 q_no;
+
+ for (q_no = 0; q_no < (oct->sriov_info.rings_per_vf); q_no++) {
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_PKTS_CREDIT(q_no),
+ 0xFFFFFFFF);
+
+ reg_val =
+ octeon_read_csr(oct, CN23XX_VF_SLI_OQ_PKTS_SENT(q_no));
+
+ reg_val &= 0xEFFFFFFFFFFFFFFFL;
+
+ reg_val =
+ octeon_read_csr(oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no));
+
+ /* set IPTR & DPTR */
+ reg_val |=
+ (CN23XX_PKT_OUTPUT_CTL_IPTR | CN23XX_PKT_OUTPUT_CTL_DPTR);
+
+ /* reset BMODE */
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_BMODE);
+
+ /* No Relaxed Ordering, No Snoop, 64-bit Byte swap
+ * for Output Queue ScatterList reset ROR_P, NSR_P
+ */
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ROR_P);
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_NSR_P);
+
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ES_P);
+#else
+ reg_val |= (CN23XX_PKT_OUTPUT_CTL_ES_P);
+#endif
+ /* No Relaxed Ordering, No Snoop, 64-bit Byte swap
+ * for Output Queue Data reset ROR, NSR
+ */
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ROR);
+ reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_NSR);
+ /* set the ES bit */
+ reg_val |= (CN23XX_PKT_OUTPUT_CTL_ES);
+
+ /* write all the selected settings */
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no),
+ reg_val);
+ }
+}
+
+static int cn23xx_setup_vf_device_regs(struct octeon_device *oct)
+{
+ if (cn23xx_vf_setup_global_input_regs(oct))
+ return -1;
+
+ cn23xx_vf_setup_global_output_regs(oct);
+
+ return 0;
+}
+
+static void cn23xx_setup_vf_iq_regs(struct octeon_device *oct, u32 iq_no)
+{
+ struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
+ u64 pkt_in_done;
+
+ /* Write the start of the input queue's ring and its size */
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_BASE_ADDR64(iq_no),
+ iq->base_addr_dma);
+ octeon_write_csr(oct, CN23XX_VF_SLI_IQ_SIZE(iq_no), iq->max_count);
+
+ /* Remember the doorbell & instruction count register addr
+ * for this queue
+ */
+ iq->doorbell_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_IQ_DOORBELL(iq_no);
+ iq->inst_cnt_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_IQ_INSTR_COUNT64(iq_no);
+ dev_dbg(&oct->pci_dev->dev, "InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p\n",
+ iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
+
+ /* Store the current instruction counter (used in flush_iq
+ * calculation)
+ */
+ pkt_in_done = readq(iq->inst_cnt_reg);
+
+ iq->reset_instr_cnt = 0;
+}
+
+static void cn23xx_setup_vf_oq_regs(struct octeon_device *oct, u32 oq_no)
+{
+ struct octeon_droq *droq = oct->droq[oq_no];
+
+ octeon_write_csr64(oct, CN23XX_VF_SLI_OQ_BASE_ADDR64(oq_no),
+ droq->desc_ring_dma);
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_SIZE(oq_no), droq->max_count);
+
+ octeon_write_csr(oct, CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(oq_no),
+ (droq->buffer_size | (OCT_RH_SIZE << 16)));
+
+ /* Get the mapped address of the pkt_sent and pkts_credit regs */
+ droq->pkts_sent_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_OQ_PKTS_SENT(oq_no);
+ droq->pkts_credit_reg =
+ (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_OQ_PKTS_CREDIT(oq_no);
+}
+
static int cn23xx_enable_vf_io_queues(struct octeon_device *oct)
{
u32 q_no;
@@ -181,8 +336,42 @@ int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
}
}
+ oct->fn_list.setup_iq_regs = cn23xx_setup_vf_iq_regs;
+ oct->fn_list.setup_oq_regs = cn23xx_setup_vf_oq_regs;
+ oct->fn_list.setup_device_regs = cn23xx_setup_vf_device_regs;
+
oct->fn_list.enable_io_queues = cn23xx_enable_vf_io_queues;
oct->fn_list.disable_io_queues = cn23xx_disable_vf_io_queues;
return 0;
}
+
+void cn23xx_dump_vf_iq_regs(struct octeon_device *oct)
+{
+ u32 regval, q_no;
+
+ dev_dbg(&oct->pci_dev->dev, "SLI_IQ_DOORBELL_0 [0x%x]: 0x%016llx\n",
+ CN23XX_VF_SLI_IQ_DOORBELL(0),
+ CVM_CAST64(octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_DOORBELL(0))));
+
+ dev_dbg(&oct->pci_dev->dev, "SLI_IQ_BASEADDR_0 [0x%x]: 0x%016llx\n",
+ CN23XX_VF_SLI_IQ_BASE_ADDR64(0),
+ CVM_CAST64(octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_BASE_ADDR64(0))));
+
+ dev_dbg(&oct->pci_dev->dev, "SLI_IQ_FIFO_RSIZE_0 [0x%x]: 0x%016llx\n",
+ CN23XX_VF_SLI_IQ_SIZE(0),
+ CVM_CAST64(octeon_read_csr64(oct, CN23XX_VF_SLI_IQ_SIZE(0))));
+
+ for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) {
+ dev_dbg(&oct->pci_dev->dev, "SLI_PKT[%d]_INPUT_CTL [0x%x]: 0x%016llx\n",
+ q_no, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ CVM_CAST64(octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no))));
+ }
+
+ pci_read_config_dword(oct->pci_dev, CN23XX_CONFIG_PCIE_DEVCTL, ®val);
+ dev_dbg(&oct->pci_dev->dev, "Config DevCtl [0x%x]: 0x%08x\n",
+ CN23XX_CONFIG_PCIE_DEVCTL, regval);
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
index 6785796..d17c1ce 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
@@ -35,4 +35,6 @@ struct octeon_cn23xx_vf {
#define BUSY_READING_REG_VF_LOOP_COUNT 10000
int cn23xx_setup_octeon_vf_device(struct octeon_device *oct);
+
+void cn23xx_dump_vf_initialized_regs(struct octeon_device *oct);
#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 41fc9d2..61c8b78 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -241,6 +241,11 @@ static int octeon_device_init(struct octeon_device *oct)
return 1;
}
+ if (oct->fn_list.setup_device_regs(oct)) {
+ dev_err(&oct->pci_dev->dev, "device registers configuration failed\n");
+ return 1;
+ }
+
return 0;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next V3 4/9] liquidio CN23XX: VF queue setup
From: Raghu Vatsavayi @ 2016-11-29 0:54 UTC (permalink / raw)
To: davem
Cc: netdev, Raghu Vatsavayi, Raghu Vatsavayi, Derek Chickles,
Satanand Burla, Felix Manlunas
In-Reply-To: <1480380881-19255-1-git-send-email-rvatsavayi@caviumnetworks.com>
Adds support for configuring VF input/output queues.
Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
---
.../ethernet/cavium/liquidio/cn23xx_vf_device.c | 144 +++++++++++++++++++++
.../ethernet/cavium/liquidio/cn23xx_vf_device.h | 2 +
drivers/net/ethernet/cavium/liquidio/lio_main.c | 6 +-
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 5 +
.../net/ethernet/cavium/liquidio/octeon_device.c | 43 +++++-
.../net/ethernet/cavium/liquidio/octeon_device.h | 7 +-
.../net/ethernet/cavium/liquidio/request_manager.c | 4 +-
7 files changed, 207 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
index d683bda..60fd138 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
@@ -25,13 +25,134 @@
#include "cn23xx_vf_device.h"
#include "octeon_main.h"
+static int cn23xx_vf_reset_io_queues(struct octeon_device *oct, u32 num_queues)
+{
+ u32 loop = BUSY_READING_REG_VF_LOOP_COUNT;
+ int ret_val = 0;
+ u32 q_no;
+ u64 d64;
+
+ for (q_no = 0; q_no < num_queues; q_no++) {
+ /* set RST bit to 1. This bit applies to both IQ and OQ */
+ d64 = octeon_read_csr64(oct,
+ CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ d64 |= CN23XX_PKT_INPUT_CTL_RST;
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ d64);
+ }
+
+ /* wait until the RST bit is clear or the RST and QUIET bits are set */
+ for (q_no = 0; q_no < num_queues; q_no++) {
+ u64 reg_val = octeon_read_csr64(oct,
+ CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ while ((READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_RST) &&
+ !(READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_QUIET) &&
+ loop) {
+ WRITE_ONCE(reg_val, octeon_read_csr64(
+ oct, CN23XX_VF_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;
+ }
+ WRITE_ONCE(reg_val, READ_ONCE(reg_val) &
+ ~CN23XX_PKT_INPUT_CTL_RST);
+ octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+ READ_ONCE(reg_val));
+
+ WRITE_ONCE(reg_val, octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no)));
+ if (READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_RST) {
+ dev_err(&oct->pci_dev->dev,
+ "clearing the reset failed for qno: %u\n",
+ q_no);
+ ret_val = -1;
+ }
+ }
+
+ return ret_val;
+}
+
+static int cn23xx_enable_vf_io_queues(struct octeon_device *oct)
+{
+ u32 q_no;
+
+ for (q_no = 0; q_no < oct->num_iqs; q_no++) {
+ u64 reg_val;
+
+ /* set the corresponding IQ IS_64B bit */
+ if (oct->io_qmask.iq64B & BIT_ULL(q_no)) {
+ reg_val = octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ reg_val |= CN23XX_PKT_INPUT_CTL_IS_64B;
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
+ }
+
+ /* set the corresponding IQ ENB bit */
+ if (oct->io_qmask.iq & BIT_ULL(q_no)) {
+ reg_val = octeon_read_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+ reg_val |= CN23XX_PKT_INPUT_CTL_RING_ENB;
+ octeon_write_csr64(
+ oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
+ }
+ }
+ for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+ u32 reg_val;
+
+ /* set the corresponding OQ ENB bit */
+ if (oct->io_qmask.oq & BIT_ULL(q_no)) {
+ reg_val = octeon_read_csr(
+ oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no));
+ reg_val |= CN23XX_PKT_OUTPUT_CTL_RING_ENB;
+ octeon_write_csr(
+ oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no), reg_val);
+ }
+ }
+
+ return 0;
+}
+
+static void cn23xx_disable_vf_io_queues(struct octeon_device *oct)
+{
+ u32 num_queues = oct->num_iqs;
+
+ /* per HRM, rings can only be disabled via reset operation,
+ * NOT via SLI_PKT()_INPUT/OUTPUT_CONTROL[ENB]
+ */
+ if (num_queues < oct->num_oqs)
+ num_queues = oct->num_oqs;
+
+ cn23xx_vf_reset_io_queues(oct, num_queues);
+}
+
int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
{
struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+ u32 rings_per_vf, ring_flag;
+ u64 reg_val;
if (octeon_map_pci_barx(oct, 0, 0))
return 1;
+ /* INPUT_CONTROL[RPVF] gives the VF IOq count */
+ reg_val = octeon_read_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(0));
+
+ oct->pf_num = (reg_val >> CN23XX_PKT_INPUT_CTL_PF_NUM_POS) &
+ CN23XX_PKT_INPUT_CTL_PF_NUM_MASK;
+ oct->vf_num = (reg_val >> CN23XX_PKT_INPUT_CTL_VF_NUM_POS) &
+ CN23XX_PKT_INPUT_CTL_VF_NUM_MASK;
+
+ reg_val = reg_val >> CN23XX_PKT_INPUT_CTL_RPVF_POS;
+
+ rings_per_vf = reg_val & CN23XX_PKT_INPUT_CTL_RPVF_MASK;
+
+ ring_flag = 0;
+
cn23xx->conf = oct_get_config_info(oct, LIO_23XX);
if (!cn23xx->conf) {
dev_err(&oct->pci_dev->dev, "%s No Config found for CN23XX\n",
@@ -40,5 +161,28 @@ int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
return 1;
}
+ if (oct->sriov_info.rings_per_vf > rings_per_vf) {
+ dev_warn(&oct->pci_dev->dev,
+ "num_queues:%d greater than PF configured rings_per_vf:%d. Reducing to %d.\n",
+ oct->sriov_info.rings_per_vf, rings_per_vf,
+ rings_per_vf);
+ oct->sriov_info.rings_per_vf = rings_per_vf;
+ } else {
+ if (rings_per_vf > num_present_cpus()) {
+ dev_warn(&oct->pci_dev->dev,
+ "PF configured rings_per_vf:%d greater than num_cpu:%d. Using rings_per_vf:%d equal to num cpus\n",
+ rings_per_vf,
+ num_present_cpus(),
+ num_present_cpus());
+ oct->sriov_info.rings_per_vf =
+ num_present_cpus();
+ } else {
+ oct->sriov_info.rings_per_vf = rings_per_vf;
+ }
+ }
+
+ oct->fn_list.enable_io_queues = cn23xx_enable_vf_io_queues;
+ oct->fn_list.disable_io_queues = cn23xx_disable_vf_io_queues;
+
return 0;
}
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
index 9e4fb50..6785796 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
@@ -32,5 +32,7 @@ struct octeon_cn23xx_vf {
struct octeon_config *conf;
};
+#define BUSY_READING_REG_VF_LOOP_COUNT 10000
+
int cn23xx_setup_octeon_vf_device(struct octeon_device *oct);
#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 3d05b2f..39a9665 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -40,6 +40,7 @@
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_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;
module_param(ddr_timeout, int, 0644);
@@ -4484,7 +4485,10 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
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)) {
ret = octeon_dev->fn_list.setup_device_regs(octeon_dev);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index dd1dad1..41fc9d2 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -236,6 +236,11 @@ static int octeon_device_init(struct octeon_device *oct)
atomic_set(&oct->status, OCT_DEV_PCI_MAP_DONE);
+ if (octeon_set_io_queues_off(oct)) {
+ dev_err(&oct->pci_dev->dev, "setting io queues off failed\n");
+ return 1;
+ }
+
return 0;
}
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index 7e6c8b8..fe84e90 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
@@ -860,12 +860,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,
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.h b/drivers/net/ethernet/cavium/liquidio/octeon_device.h
index 5ce2048..1e6bfa1 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.h
@@ -401,8 +401,13 @@ struct octeon_device {
/** Octeon Chip type. */
u16 chip_id;
+
u16 rev_id;
+
u16 pf_num;
+
+ u16 vf_num;
+
/** This device's id - set by the driver. */
u32 octeon_id;
@@ -766,7 +771,7 @@ int octeon_download_firmware(struct octeon_device *oct, const u8 *data,
/** Turns off the input and output queues for the device
* @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
* @param oct which octeon to change
diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
index 8531a00..0e10e2a 100644
--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
@@ -235,7 +235,9 @@ int octeon_setup_iq(struct octeon_device *oct,
}
oct->num_iqs++;
- oct->fn_list.enable_io_queues(oct);
+ if (oct->fn_list.enable_io_queues(oct))
+ return 1;
+
return 0;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next V3 2/9] liquidio CN23XX: VF registration
From: Raghu Vatsavayi @ 2016-11-29 0:54 UTC (permalink / raw)
To: davem
Cc: netdev, Raghu Vatsavayi, Raghu Vatsavayi, Derek Chickles,
Satanand Burla, Felix Manlunas
In-Reply-To: <1480380881-19255-1-git-send-email-rvatsavayi@caviumnetworks.com>
Adds support for cn23xx VF probe and registration.
Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
---
drivers/net/ethernet/cavium/Kconfig | 12 +++
drivers/net/ethernet/cavium/liquidio/Makefile | 21 ++++
.../ethernet/cavium/liquidio/cn23xx_vf_device.h | 34 ++++++
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 120 +++++++++++++++++++++
.../net/ethernet/cavium/liquidio/octeon_device.c | 4 +
5 files changed, 191 insertions(+)
create mode 100644 drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
create mode 100644 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 92f411c..c0679c2 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -74,4 +74,16 @@ config OCTEON_MGMT_ETHERNET
port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
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
diff --git a/drivers/net/ethernet/cavium/liquidio/Makefile b/drivers/net/ethernet/cavium/liquidio/Makefile
index 14958de..69d23fc 100644
--- a/drivers/net/ethernet/cavium/liquidio/Makefile
+++ b/drivers/net/ethernet/cavium/liquidio/Makefile
@@ -17,3 +17,24 @@ liquidio-$(CONFIG_LIQUIDIO) += lio_ethtool.o \
octeon_nic.o
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 \
+ octeon_mailbox.o \
+ octeon_mem_ops.o \
+ octeon_droq.o \
+ octeon_nic.o
+
+liquidio_vf-objs := lio_vf_main.o $(liquidio_vf-y)
+endif
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
new file mode 100644
index 0000000..015b6d4
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
@@ -0,0 +1,34 @@
+/**********************************************************************
+ * 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;
+};
+#endif
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
new file mode 100644
index 0000000..fd108cd
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -0,0 +1,120 @@
+/**********************************************************************
+ * 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.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <net/vxlan.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+
+MODULE_AUTHOR("Cavium Networks, <support@cavium.com>");
+MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Virtual Function Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(LIQUIDIO_VERSION);
+
+struct octeon_device_priv {
+ /* Tasklet structures for this device. */
+ struct tasklet_struct droq_tasklet;
+ unsigned long napi_mask;
+};
+
+static int
+liquidio_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void liquidio_vf_remove(struct pci_dev *pdev);
+
+static const struct pci_device_id liquidio_vf_pci_tbl[] = {
+ {
+ PCI_VENDOR_ID_CAVIUM, OCTEON_CN23XX_VF_VID,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0, 0, 0, 0
+ }
+};
+MODULE_DEVICE_TABLE(pci, liquidio_vf_pci_tbl);
+
+static struct pci_driver liquidio_vf_pci_driver = {
+ .name = "LiquidIO_VF",
+ .id_table = liquidio_vf_pci_tbl,
+ .probe = liquidio_vf_probe,
+ .remove = liquidio_vf_remove,
+};
+
+/**
+ * \brief PCI probe handler
+ * @param pdev PCI device structure
+ * @param ent unused
+ */
+static int
+liquidio_vf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent __attribute__((unused)))
+{
+ struct octeon_device *oct_dev = NULL;
+
+ oct_dev = octeon_allocate_device(pdev->device,
+ sizeof(struct octeon_device_priv));
+
+ if (!oct_dev) {
+ dev_err(&pdev->dev, "Unable to allocate device\n");
+ return -ENOMEM;
+ }
+
+ dev_info(&pdev->dev, "Initializing device %x:%x.\n",
+ (u32)pdev->vendor, (u32)pdev->device);
+
+ /* Assign octeon_device for this device to the private data area. */
+ pci_set_drvdata(pdev, oct_dev);
+
+ /* set linux specific device pointer */
+ oct_dev->pci_dev = pdev;
+
+ return 0;
+}
+
+/**
+ * \brief Cleans up resources at unload time
+ * @param pdev PCI device structure
+ */
+static void liquidio_vf_remove(struct pci_dev *pdev)
+{
+ struct octeon_device *oct_dev = pci_get_drvdata(pdev);
+
+ dev_dbg(&oct_dev->pci_dev->dev, "Stopping device\n");
+
+ /* This octeon device has been removed. Update the global
+ * data structure to reflect this. Free the device structure.
+ */
+ octeon_free_device_mem(oct_dev);
+}
+
+static int __init liquidio_vf_init(void)
+{
+ octeon_init_device_list(0);
+ return pci_register_driver(&liquidio_vf_pci_driver);
+}
+
+static void __exit liquidio_vf_exit(void)
+{
+ pci_unregister_driver(&liquidio_vf_pci_driver);
+
+ pr_info("LiquidIO_VF network module is now unloaded\n");
+}
+
+module_init(liquidio_vf_init);
+module_exit(liquidio_vf_exit);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index 79c8875..05bb0fd 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.
@@ -672,6 +673,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__,
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next V3 1/9] liquidio CN23XX: VF register definitions
From: Raghu Vatsavayi @ 2016-11-29 0:54 UTC (permalink / raw)
To: davem
Cc: netdev, Raghu Vatsavayi, Raghu Vatsavayi, Derek Chickles,
Satanand Burla, Felix Manlunas
In-Reply-To: <1480380881-19255-1-git-send-email-rvatsavayi@caviumnetworks.com>
Adds support for CN23xx VF registers.
Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
---
.../net/ethernet/cavium/liquidio/cn23xx_vf_regs.h | 274 +++++++++++++++++++++
1 file changed, 274 insertions(+)
create mode 100644 drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h
new file mode 100644
index 0000000..d33dd8f
--- /dev/null
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h
@@ -0,0 +1,274 @@
+/**********************************************************************
+ * 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_vf_regs.h
+ * \brief Host Driver: Register Address and Register Mask values for
+ * Octeon CN23XX vf functions.
+ */
+
+#ifndef __CN23XX_VF_REGS_H__
+#define __CN23XX_VF_REGS_H__
+
+#define CN23XX_CONFIG_XPANSION_BAR 0x38
+
+#define CN23XX_CONFIG_PCIE_CAP 0x70
+#define CN23XX_CONFIG_PCIE_DEVCAP 0x74
+#define CN23XX_CONFIG_PCIE_DEVCTL 0x78
+#define CN23XX_CONFIG_PCIE_LINKCAP 0x7C
+#define CN23XX_CONFIG_PCIE_LINKCTL 0x80
+#define CN23XX_CONFIG_PCIE_SLOTCAP 0x84
+#define CN23XX_CONFIG_PCIE_SLOTCTL 0x88
+
+#define CN23XX_CONFIG_PCIE_FLTMSK 0x720
+
+/* The input jabber is used to determine the TSO max size.
+ * Due to H/W limitation, this need to be reduced to 60000
+ * in order to to H/W TSO and avoid the WQE malfarmation
+ * PKO_BUG_24989_WQE_LEN
+ */
+#define CN23XX_DEFAULT_INPUT_JABBER 0xEA60 /*60000*/
+
+/* ############## BAR0 Registers ################ */
+
+/* Each Input Queue register is at a 16-byte Offset in BAR0 */
+#define CN23XX_VF_IQ_OFFSET 0x20000
+
+/*###################### REQUEST QUEUE #########################*/
+
+/* 64 registers for Input Queue Instr Count - SLI_PKT_IN_DONE0_CNTS */
+#define CN23XX_VF_SLI_IQ_INSTR_COUNT_START64 0x10040
+
+/* 64 registers for Input Queues Start Addr - SLI_PKT0_INSTR_BADDR */
+#define CN23XX_VF_SLI_IQ_BASE_ADDR_START64 0x10010
+
+/* 64 registers for Input Doorbell - SLI_PKT0_INSTR_BAOFF_DBELL */
+#define CN23XX_VF_SLI_IQ_DOORBELL_START 0x10020
+
+/* 64 registers for Input Queue size - SLI_PKT0_INSTR_FIFO_RSIZE */
+#define CN23XX_VF_SLI_IQ_SIZE_START 0x10030
+
+/* 64 registers (64-bit) - ES, RO, NS, Arbitration for Input Queue Data &
+ * gather list fetches. SLI_PKT(0..63)_INPUT_CONTROL.
+ */
+#define CN23XX_VF_SLI_IQ_PKT_CONTROL_START64 0x10000
+
+/*------- Request Queue Macros ---------*/
+#define CN23XX_VF_SLI_IQ_PKT_CONTROL64(iq) \
+ (CN23XX_VF_SLI_IQ_PKT_CONTROL_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_BASE_ADDR64(iq) \
+ (CN23XX_VF_SLI_IQ_BASE_ADDR_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_SIZE(iq) \
+ (CN23XX_VF_SLI_IQ_SIZE_START + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_DOORBELL(iq) \
+ (CN23XX_VF_SLI_IQ_DOORBELL_START + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_INSTR_COUNT64(iq) \
+ (CN23XX_VF_SLI_IQ_INSTR_COUNT_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+/*------------------ Masks ----------------*/
+#define CN23XX_PKT_INPUT_CTL_VF_NUM BIT_ULL(32)
+#define CN23XX_PKT_INPUT_CTL_MAC_NUM BIT(29)
+/* Number of instructions to be read in one MAC read request.
+ * setting to Max value(4)
+ */
+#define CN23XX_PKT_INPUT_CTL_RDSIZE (3 << 25)
+#define CN23XX_PKT_INPUT_CTL_IS_64B BIT(24)
+#define CN23XX_PKT_INPUT_CTL_RST BIT(23)
+#define CN23XX_PKT_INPUT_CTL_QUIET BIT(28)
+#define CN23XX_PKT_INPUT_CTL_RING_ENB BIT(22)
+#define CN23XX_PKT_INPUT_CTL_DATA_NS BIT(8)
+#define CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP BIT(6)
+#define CN23XX_PKT_INPUT_CTL_DATA_RO BIT(5)
+#define CN23XX_PKT_INPUT_CTL_USE_CSR BIT(4)
+#define CN23XX_PKT_INPUT_CTL_GATHER_NS BIT(3)
+#define CN23XX_PKT_INPUT_CTL_GATHER_ES_64B_SWAP (2)
+#define CN23XX_PKT_INPUT_CTL_GATHER_RO (1)
+
+/** Rings per Virtual Function [RO] **/
+#define CN23XX_PKT_INPUT_CTL_RPVF_MASK (0x3F)
+#define CN23XX_PKT_INPUT_CTL_RPVF_POS (48)
+/* These bits[47:44][RO] give the Physical function number info within the MAC*/
+#define CN23XX_PKT_INPUT_CTL_PF_NUM_MASK (0x7)
+#define CN23XX_PKT_INPUT_CTL_PF_NUM_POS (45)
+/** These bits[43:32][RO] give the virtual function number info within the PF*/
+#define CN23XX_PKT_INPUT_CTL_VF_NUM_MASK (0x1FFF)
+#define CN23XX_PKT_INPUT_CTL_VF_NUM_POS (32)
+#define CN23XX_PKT_INPUT_CTL_MAC_NUM_MASK (0x3)
+#define CN23XX_PKT_INPUT_CTL_MAC_NUM_POS (29)
+#define CN23XX_PKT_IN_DONE_WMARK_MASK (0xFFFFULL)
+#define CN23XX_PKT_IN_DONE_WMARK_BIT_POS (32)
+#define CN23XX_PKT_IN_DONE_CNT_MASK (0x00000000FFFFFFFFULL)
+
+#ifdef __LITTLE_ENDIAN_BITFIELD
+#define CN23XX_PKT_INPUT_CTL_MASK \
+ (CN23XX_PKT_INPUT_CTL_RDSIZE \
+ | CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP \
+ | CN23XX_PKT_INPUT_CTL_USE_CSR)
+#else
+#define CN23XX_PKT_INPUT_CTL_MASK \
+ (CN23XX_PKT_INPUT_CTL_RDSIZE \
+ | CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP \
+ | CN23XX_PKT_INPUT_CTL_USE_CSR \
+ | CN23XX_PKT_INPUT_CTL_GATHER_ES_64B_SWAP)
+#endif
+
+/** Masks for SLI_PKT_IN_DONE(0..63)_CNTS Register */
+#define CN23XX_IN_DONE_CNTS_PI_INT BIT_ULL(62)
+#define CN23XX_IN_DONE_CNTS_CINT_ENB BIT_ULL(48)
+
+/*############################ OUTPUT QUEUE #########################*/
+
+/* 64 registers for Output queue control - SLI_PKT(0..63)_OUTPUT_CONTROL */
+#define CN23XX_VF_SLI_OQ_PKT_CONTROL_START 0x10050
+
+/* 64 registers for Output queue buffer and info size - SLI_PKT0_OUT_SIZE */
+#define CN23XX_VF_SLI_OQ0_BUFF_INFO_SIZE 0x10060
+
+/* 64 registers for Output Queue Start Addr - SLI_PKT0_SLIST_BADDR */
+#define CN23XX_VF_SLI_OQ_BASE_ADDR_START64 0x10070
+
+/* 64 registers for Output Queue Packet Credits - SLI_PKT0_SLIST_BAOFF_DBELL */
+#define CN23XX_VF_SLI_OQ_PKT_CREDITS_START 0x10080
+
+/* 64 registers for Output Queue size - SLI_PKT0_SLIST_FIFO_RSIZE */
+#define CN23XX_VF_SLI_OQ_SIZE_START 0x10090
+
+/* 64 registers for Output Queue Packet Count - SLI_PKT0_CNTS */
+#define CN23XX_VF_SLI_OQ_PKT_SENT_START 0x100B0
+
+/* 64 registers for Output Queue INT Levels - SLI_PKT0_INT_LEVELS */
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 0x100A0
+
+/* Each Output Queue register is at a 16-byte Offset in BAR0 */
+#define CN23XX_VF_OQ_OFFSET 0x20000
+
+/*------- Output Queue Macros ---------*/
+
+#define CN23XX_VF_SLI_OQ_PKT_CONTROL(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_CONTROL_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_BASE_ADDR64(oq) \
+ (CN23XX_VF_SLI_OQ_BASE_ADDR_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_SIZE(oq) \
+ (CN23XX_VF_SLI_OQ_SIZE_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(oq) \
+ (CN23XX_VF_SLI_OQ0_BUFF_INFO_SIZE + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKTS_SENT(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_SENT_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKTS_CREDIT(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_CREDITS_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+/* Macro's for accessing CNT and TIME separately from INT_LEVELS */
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_CNT(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_TIME(oq) \
+ (CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + \
+ ((oq) * CN23XX_VF_OQ_OFFSET) + 4)
+
+/*------------------ Masks ----------------*/
+#define CN23XX_PKT_OUTPUT_CTL_TENB BIT(13)
+#define CN23XX_PKT_OUTPUT_CTL_CENB BIT(12)
+#define CN23XX_PKT_OUTPUT_CTL_IPTR BIT(11)
+#define CN23XX_PKT_OUTPUT_CTL_ES BIT(9)
+#define CN23XX_PKT_OUTPUT_CTL_NSR BIT(8)
+#define CN23XX_PKT_OUTPUT_CTL_ROR BIT(7)
+#define CN23XX_PKT_OUTPUT_CTL_DPTR BIT(6)
+#define CN23XX_PKT_OUTPUT_CTL_BMODE BIT(5)
+#define CN23XX_PKT_OUTPUT_CTL_ES_P BIT(3)
+#define CN23XX_PKT_OUTPUT_CTL_NSR_P BIT(2)
+#define CN23XX_PKT_OUTPUT_CTL_ROR_P BIT(1)
+#define CN23XX_PKT_OUTPUT_CTL_RING_ENB BIT(0)
+
+/*######################### Mailbox Reg Macros ########################*/
+#define CN23XX_VF_SLI_PKT_MBOX_INT_START 0x10210
+#define CN23XX_SLI_PKT_PF_VF_MBOX_SIG_START 0x10200
+
+#define CN23XX_SLI_MBOX_OFFSET 0x20000
+#define CN23XX_SLI_MBOX_SIG_IDX_OFFSET 0x8
+
+#define CN23XX_VF_SLI_PKT_MBOX_INT(q) \
+ (CN23XX_VF_SLI_PKT_MBOX_INT_START + ((q) * CN23XX_SLI_MBOX_OFFSET))
+
+#define CN23XX_SLI_PKT_PF_VF_MBOX_SIG(q, idx) \
+ (CN23XX_SLI_PKT_PF_VF_MBOX_SIG_START + \
+ ((q) * CN23XX_SLI_MBOX_OFFSET + \
+ (idx) * CN23XX_SLI_MBOX_SIG_IDX_OFFSET))
+
+/*######################## INTERRUPTS #########################*/
+
+#define CN23XX_VF_SLI_INT_SUM_START 0x100D0
+
+#define CN23XX_VF_SLI_INT_SUM(q) \
+ (CN23XX_VF_SLI_INT_SUM_START + ((q) * CN23XX_VF_IQ_OFFSET))
+
+/*------------------ Interrupt Masks ----------------*/
+
+#define CN23XX_INTR_PO_INT BIT_ULL(63)
+#define CN23XX_INTR_PI_INT BIT_ULL(62)
+#define CN23XX_INTR_MBOX_INT BIT_ULL(61)
+#define CN23XX_INTR_RESEND BIT_ULL(60)
+
+#define CN23XX_INTR_CINT_ENB BIT_ULL(48)
+#define CN23XX_INTR_MBOX_ENB BIT(0)
+
+/*############################ MIO #########################*/
+#define CN23XX_MIO_PTP_CLOCK_CFG 0x0001070000000f00ULL
+#define CN23XX_MIO_PTP_CLOCK_LO 0x0001070000000f08ULL
+#define CN23XX_MIO_PTP_CLOCK_HI 0x0001070000000f10ULL
+#define CN23XX_MIO_PTP_CLOCK_COMP 0x0001070000000f18ULL
+#define CN23XX_MIO_PTP_TIMESTAMP 0x0001070000000f20ULL
+#define CN23XX_MIO_PTP_EVT_CNT 0x0001070000000f28ULL
+#define CN23XX_MIO_PTP_CKOUT_THRESH_LO 0x0001070000000f30ULL
+#define CN23XX_MIO_PTP_CKOUT_THRESH_HI 0x0001070000000f38ULL
+#define CN23XX_MIO_PTP_CKOUT_HI_INCR 0x0001070000000f40ULL
+#define CN23XX_MIO_PTP_CKOUT_LO_INCR 0x0001070000000f48ULL
+#define CN23XX_MIO_PTP_PPS_THRESH_LO 0x0001070000000f50ULL
+#define CN23XX_MIO_PTP_PPS_THRESH_HI 0x0001070000000f58ULL
+#define CN23XX_MIO_PTP_PPS_HI_INCR 0x0001070000000f60ULL
+#define CN23XX_MIO_PTP_PPS_LO_INCR 0x0001070000000f68ULL
+
+/*############################ RST #########################*/
+#define CN23XX_RST_BOOT 0x0001180006001600ULL
+
+/*######################## MSIX TABLE #########################*/
+
+#define CN23XX_MSIX_TABLE_ADDR_START 0x0
+#define CN23XX_MSIX_TABLE_DATA_START 0x8
+
+#define CN23XX_MSIX_TABLE_SIZE 0x10
+#define CN23XX_MSIX_TABLE_ENTRIES 0x41
+
+#define CN23XX_MSIX_ENTRY_VECTOR_CTL BIT_ULL(32)
+
+#define CN23XX_MSIX_TABLE_ADDR(idx) \
+ (CN23XX_MSIX_TABLE_ADDR_START + ((idx) * CN23XX_MSIX_TABLE_SIZE))
+
+#define CN23XX_MSIX_TABLE_DATA(idx) \
+ (CN23XX_MSIX_TABLE_DATA_START + ((idx) * CN23XX_MSIX_TABLE_SIZE))
+
+#endif
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next V3 0/9] liquidio VF operations
From: Raghu Vatsavayi @ 2016-11-29 0:54 UTC (permalink / raw)
To: davem; +Cc: netdev, Raghu Vatsavayi
Hi Dave,
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.
Thanks
Raghu Vatsavayi (9):
liquidio CN23XX: VF register definitions
liquidio CN23XX: VF registration
liquidio CN23XX: VF config setup
liquidio CN23XX: VF queue setup
liquidio CN23XX: VF register access
liquidio CN23XX: init VF softcommand queues
liquidio CN23XX: VF mailbox
liquidio CN23XX: VF interrupt
liquidio CN23XX: VF init and destroy
drivers/net/ethernet/cavium/Kconfig | 12 +
drivers/net/ethernet/cavium/liquidio/Makefile | 23 +
.../ethernet/cavium/liquidio/cn23xx_vf_device.c | 701 +++++++++++++++++++++
.../ethernet/cavium/liquidio/cn23xx_vf_device.h | 48 ++
.../net/ethernet/cavium/liquidio/cn23xx_vf_regs.h | 274 ++++++++
drivers/net/ethernet/cavium/liquidio/lio_core.c | 7 -
drivers/net/ethernet/cavium/liquidio/lio_main.c | 6 +-
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 614 ++++++++++++++++++
.../net/ethernet/cavium/liquidio/octeon_device.c | 66 +-
.../net/ethernet/cavium/liquidio/octeon_device.h | 9 +-
.../net/ethernet/cavium/liquidio/request_manager.c | 11 +-
11 files changed, 1756 insertions(+), 15 deletions(-)
create mode 100644 drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
create mode 100644 drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
create mode 100644 drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h
create mode 100644 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH net] openvswitch: Fix skb leak in IPv6 reassembly.
From: Florian Westphal @ 2016-11-29 0:45 UTC (permalink / raw)
To: Eric Dumazet
Cc: Daniele Di Proietto, netdev, Florian Westphal, Pravin B Shelar,
Joe Stringer
In-Reply-To: <1480378950.18162.107.camel@edumazet-glaptop3.roam.corp.google.com>
Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2016-11-28 at 15:43 -0800, Daniele Di Proietto wrote:
> > If nf_ct_frag6_gather() returns an error other than -EINPROGRESS, it
> > means that we still have a reference to the skb. We should free it
> > before returning from handle_fragments, as stated in the comment above.
> >
> > Fixes: daaa7d647f81 ("netfilter: ipv6: avoid nf_iterate recursion")
> > CC: Florian Westphal <fw@strlen.de>
> > CC: Pravin B Shelar <pshelar@ovn.org>
> > CC: Joe Stringer <joe@ovn.org>
> > Signed-off-by: Daniele Di Proietto <diproiettod@ovn.org>
> > ---
> > net/openvswitch/conntrack.c | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> > index 31045ef..fecefa2 100644
> > --- a/net/openvswitch/conntrack.c
> > +++ b/net/openvswitch/conntrack.c
> > @@ -370,8 +370,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
> > skb_orphan(skb);
> > memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
> > err = nf_ct_frag6_gather(net, skb, user);
> > - if (err)
> > + if (err) {
> > + if (err != -EINPROGRESS)
> > + kfree_skb(skb);
> > return err;
> > + }
> >
> > key->ip.proto = ipv6_hdr(skb)->nexthdr;
> > ovs_cb.mru = IP6CB(skb)->frag_max_size;
>
> Interesting, have you followed the "GPF in eth_header" thread today ?
>
> In a nutshell, we want a complete patch, not something that would solve
> part of the problem.
I think this patch is fine, intent seems to be to only take fully reassembled
skb, rather than a stray fragment (ovs does NOT seem to call handle_fragments
in case skb is already known to not contain a fragment header, afaics).
I'll send a patch for the GPF in eth_header thing soon.
^ permalink raw reply
* Re: [PATCH net-next 1/3] ethtool: (uapi) Add ETHTOOL_PHY_LOOPBACK to PHY tunables
From: Andrew Lunn @ 2016-11-29 0:46 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Allan W. Nielsen, netdev, raju.lakkaraju
In-Reply-To: <fabb91cd-9fc5-d935-727e-ff57e441e919@gmail.com>
> > If you really do what to do this, you should look at NETIF_F_LOOPBACK
> > and consider how this concept can be applied at the PHY, not the MAC.
> > But you need the full concept, so you see things like:
> >
> > 2: eth0: <LOOPBACK,BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
> > link/ether 80:ee:73:83:60:27 brd ff:ff:ff:ff:ff:ff
> >
> > Humm, i've no idea how you actually enable the MAC loopback
> > NETIF_F_LOOPBACK represents. I don't see anything with ip link set.
>
> I am afraid you lost me on this, NETIF_F_LOOPBACK is a netdev_features_t
> bit, so it tells ethtool that this is a potential feature to be turned
> on with ethtool -K <iface>.
Yep, i'm talking rubbish after jumping to a wrong conclusion.
> The semantics of this loopack feature are
> not defined AFAICT, but a reasonable behavior from the driver is to put
> itself in a mode where packets send by a socket-level application are
> looped through the Ethernet adapter itself. Whether this happens at the
> DMA level, the MII signals, or somewhere in the PHY, is driver specific
> unfortunately.
Yes, the interesting one might be forcedeth which writes to the PHY
BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
when the NETIF_F_LOOPBACK feature is set.
Maybe this could be generalised and made available for all MACs which
don't support MAC loopback?
What needs considering is the correct duplex and speed. We need to
ensure the MAC and PHY agree on this.
> Now, there is another way to toggle a loopback for a given Ethernet
> adapter which is to actually set IFF_LOOPBACK in dev->flags for this
> interface. Some drivers seem to be able to properly react to that as
> well, although I see no way this can be done looking at the iproute2 or
> ifconfig man pages..
I prefer this one, since i expect this will set LOOPBACK in
2: eth0: <LOOPBACK,BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
making it lot more obvious something funny is going on.
Andrew
^ permalink raw reply
* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2016-11-29 0:31 UTC (permalink / raw)
To: David Miller, Networking; +Cc: linux-next, linux-kernel, Daniel Borkmann
Hi all,
Today's linux-next merge of the net-next tree got a conflict in:
net/sched/cls_flower.c
between commit:
d936377414fa ("net, sched: respect rcu grace period on cls destruction")
from the net tree and commit:
13fa876ebd03 ("net/sched: cls_flower: merge filter delete/destroy common code")
from the net-next tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc net/sched/cls_flower.c
index b296f3991ab2,e8dd09af0d0c..000000000000
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@@ -273,24 -272,14 +276,32 @@@ static void fl_hw_update_stats(struct t
dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc);
}
+static void fl_destroy_sleepable(struct work_struct *work)
+{
+ struct cls_fl_head *head = container_of(work, struct cls_fl_head,
+ work);
+ if (head->mask_assigned)
+ rhashtable_destroy(&head->ht);
+ kfree(head);
+ module_put(THIS_MODULE);
+}
+
+static void fl_destroy_rcu(struct rcu_head *rcu)
+{
+ struct cls_fl_head *head = container_of(rcu, struct cls_fl_head, rcu);
+
+ INIT_WORK(&head->work, fl_destroy_sleepable);
+ schedule_work(&head->work);
+}
+
+ static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)
+ {
+ list_del_rcu(&f->list);
+ fl_hw_destroy_filter(tp, (unsigned long)f);
+ tcf_unbind_filter(tp, &f->res);
+ call_rcu(&f->rcu, fl_destroy_filter);
+ }
+
static bool fl_destroy(struct tcf_proto *tp, bool force)
{
struct cls_fl_head *head = rtnl_dereference(tp->root);
@@@ -299,14 -288,12 +310,11 @@@
if (!force && !list_empty(&head->filters))
return false;
- list_for_each_entry_safe(f, next, &head->filters, list) {
- fl_hw_destroy_filter(tp, (unsigned long)f);
- list_del_rcu(&f->list);
- call_rcu(&f->rcu, fl_destroy_filter);
- }
+ list_for_each_entry_safe(f, next, &head->filters, list)
+ __fl_delete(tp, f);
- RCU_INIT_POINTER(tp->root, NULL);
- if (head->mask_assigned)
- rhashtable_destroy(&head->ht);
- kfree_rcu(head, rcu);
+
+ __module_get(THIS_MODULE);
+ call_rcu(&head->rcu, fl_destroy_rcu);
return true;
}
^ permalink raw reply
* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2016-11-29 0:25 UTC (permalink / raw)
To: David Miller, Networking; +Cc: linux-next, linux-kernel, Tariq Toukan
Hi all,
Today's linux-next merge of the net-next tree got a conflict in:
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
between commit:
b4353708f5a1 ("Revert "net/mlx4_en: Avoid unregister_netdev at shutdown flow"")
from the net tree and commit:
67f8b1dcb9ee ("net/mlx4_en: Refactor the XDP forwarding rings scheme")
from the net-next tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index fb8bb027b69c,ea76b28b728b..000000000000
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@@ -2155,6 -2209,9 +2202,7 @@@ void mlx4_en_destroy_netdev(struct net_
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
- bool shutdown = mdev->dev->persist->interface_state &
- MLX4_INTERFACE_STATE_SHUTDOWN;
+ int t;
en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
@@@ -2188,10 -2248,13 +2236,12 @@@
mlx4_en_free_resources(priv);
mutex_unlock(&mdev->state_lock);
- kfree(priv->tx_ring);
- kfree(priv->tx_cq);
+ for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+ kfree(priv->tx_ring[t]);
+ kfree(priv->tx_cq[t]);
+ }
- if (!shutdown)
- free_netdev(dev);
+ free_netdev(dev);
}
static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
^ permalink raw reply
* Re: [PATCH net] openvswitch: Fix skb leak in IPv6 reassembly.
From: Eric Dumazet @ 2016-11-29 0:22 UTC (permalink / raw)
To: Daniele Di Proietto
Cc: netdev, Florian Westphal, Pravin B Shelar, Joe Stringer
In-Reply-To: <20161128234353.4262-1-diproiettod@ovn.org>
On Mon, 2016-11-28 at 15:43 -0800, Daniele Di Proietto wrote:
> If nf_ct_frag6_gather() returns an error other than -EINPROGRESS, it
> means that we still have a reference to the skb. We should free it
> before returning from handle_fragments, as stated in the comment above.
>
> Fixes: daaa7d647f81 ("netfilter: ipv6: avoid nf_iterate recursion")
> CC: Florian Westphal <fw@strlen.de>
> CC: Pravin B Shelar <pshelar@ovn.org>
> CC: Joe Stringer <joe@ovn.org>
> Signed-off-by: Daniele Di Proietto <diproiettod@ovn.org>
> ---
> net/openvswitch/conntrack.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> index 31045ef..fecefa2 100644
> --- a/net/openvswitch/conntrack.c
> +++ b/net/openvswitch/conntrack.c
> @@ -370,8 +370,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
> skb_orphan(skb);
> memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
> err = nf_ct_frag6_gather(net, skb, user);
> - if (err)
> + if (err) {
> + if (err != -EINPROGRESS)
> + kfree_skb(skb);
> return err;
> + }
>
> key->ip.proto = ipv6_hdr(skb)->nexthdr;
> ovs_cb.mru = IP6CB(skb)->frag_max_size;
Interesting, have you followed the "GPF in eth_header" thread today ?
In a nutshell, we want a complete patch, not something that would solve
part of the problem.
^ permalink raw reply
* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2016-11-29 0:22 UTC (permalink / raw)
To: David Miller, Networking
Cc: linux-next, linux-kernel, Borislav Petkov, Tom Lendacky
Hi all,
Today's linux-next merge of the net-next tree got a conflict in:
drivers/net/ethernet/amd/xgbe/xgbe-main.c
between commit:
91eefaabf102 ("amd-xgbe: Fix unused suspend handlers build warning")
from the net tree and commit:
bd8255d8ba35 ("amd-xgbe: Prepare for supporting PCI devices")
from the net-next tree.
I fixed it up (the latter removed the code modified by the former)
and can carry the fix as necessary. This is now fixed as far as linux-next
is concerned, but any non trivial conflicts should be mentioned to your
upstream maintainer when your tree is submitted for merging. You may
also want to consider cooperating with the maintainer of the conflicting
tree to minimise any particularly complex conflicts.
--
Cheers,
Stephen Rothwell
^ permalink raw reply
* Re: Aw: Re: [PATCH] mlx4: give precise rx/tx bytes/packets counters
From: Eric Dumazet @ 2016-11-29 0:19 UTC (permalink / raw)
To: Lino Sanfilippo; +Cc: David Laight, David Miller, netdev, Tariq Toukan
In-Reply-To: <b58286a4-d97f-18dd-e5bd-0f69d3746b81@gmx.de>
On Mon, 2016-11-28 at 23:02 +0100, Lino Sanfilippo wrote:
> Hi Eric,
>
> On 25.11.2016 20:19, Eric Dumazet wrote:
> > On Fri, 2016-11-25 at 17:30 +0100, Lino Sanfilippo wrote:
> >> Hi,
> >>
> >>
> >> >
> >> > The READ_ONCE() are documenting the fact that no lock is taken to fetch
> >> > the stats, while another cpus might being changing them.
> >> >
> >> > I had no answer yet from https://patchwork.ozlabs.org/patch/698449/
> >> >
> >> > So I thought it was not needed to explain this in the changelog, given
> >> > that it apparently is one of the few things that can block someone to
> >> > understand one of my changes :/
> >> >
> >> > Apparently nobody really understands READ_ONCE() purpose, it is really a
> >> > pity we have to explain this over and over.
> >> >
> >>
> >> Even at the risk of showing once more a lack of understanding for
> >> READ_ONCE():
> >> Does not a READ_ONCE() have to e paired with some kind of
> >> WRITE_ONCE()?
> >
> > You are right.
> >
> > Although in this case, the producers are using a lock, and do
> >
> > ring->packets++;
> >
> > We hopefully have compilers/cpus that do not put intermediate garbage in
> > ring->packets while doing the increment.
> >
> > One problem with :
> >
> > WRITE_ONCE(ring->packets, ring->packets + 1);
> >
> > is that gcc no longer uses an INC instruction.
>
> I see. So we would have to do something like
>
> tmp = ring->packets;
> tmp++;
> WRITE_ONCE(ring->packets, tmp);
Well, gcc will generate a code with more instructions than a mere
"inc offset(%register)"
Which is kind of unfortunate, given it is the fast path.
Better add a comment, like :
/* We should use WRITE_ONCE() to pair with the READ_ONCE() found in xxxx()
* But gcc would generate non optimal code.
*/
^ permalink raw reply
* Re: [PATCH v2] net: phy: Fix use after free in phy_detach()
From: Zach Brown @ 2016-11-29 0:05 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Florian Fainelli, David S. Miller, Josh Cartwright,
Nathan Sullivan, Woojung Huh, netdev, linux-renesas-soc,
linux-kernel
In-Reply-To: <1480342711-26407-1-git-send-email-geert+renesas@glider.be>
On Mon, Nov 28, 2016 at 03:18:31PM +0100, Geert Uytterhoeven wrote:
> If device_release_driver(&phydev->mdio.dev) is called, it releases all
> resources belonging to the PHY device. Hence the subsequent call to
> phy_led_triggers_unregister() will access already freed memory when
> unregistering the LEDs.
>
> Move the call to phy_led_triggers_unregister() before the possible call
> to device_release_driver() to fix this.
>
> Fixes: 2e0bc452f4721520 ("net: phy: leds: add support for led triggers on phy link state change")
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> This is v2 of "[RFC] net: phy: Fix double free in phy_detach()".
>
> v2:
> - Dropped RFC,
> - Reworded, as commit a7dac9f9c1695d74 ("phy: fix error case of
> phy_led_triggers_(un)register") fixed the double free, and thus the
> warning I was seeing during "poweroff" on sh73a0/kzm9g,
> - Verified use after free using CONFIG_DEBUG_DEVRES, log_devres = 1,
> and additional debug code printing the address of
> phy->phy_led_triggers. Adding poisoning of freed memory to
> devres_log() will cause a crash.
> ---
> drivers/net/phy/phy_device.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index ba86c191a13ea81c..a1d6e13b1b4113a4 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -981,6 +981,8 @@ void phy_detach(struct phy_device *phydev)
> phydev->attached_dev = NULL;
> phy_suspend(phydev);
>
> + phy_led_triggers_unregister(phydev);
> +
> /* If the device had no specific driver before (i.e. - it
> * was using the generic driver), we unbind the device
> * from the generic driver so that there's a chance a
> @@ -994,8 +996,6 @@ void phy_detach(struct phy_device *phydev)
> }
> }
>
> - phy_led_triggers_unregister(phydev);
> -
> /*
> * The phydev might go away on the put_device() below, so avoid
> * a use-after-free bug by reading the underlying bus first.
> --
> 1.9.1
>
I was able to recreate the issue and confirmed this patch fixes it.
Tested-by: Zach Brown <zach.brown@ni.com>
--Zach
^ permalink raw reply
* Re: [PATCH net-next 2/2] net: phy: bcm7xxx: Plug in support for reading PHY error counters
From: kbuild test robot @ 2016-11-28 23:43 UTC (permalink / raw)
To: Florian Fainelli
Cc: kbuild-all, netdev, davem, andrew, bcm-kernel-feedback-list,
allan.nielsen, raju.lakkaraju, Florian Fainelli
In-Reply-To: <20161128210614.12621-3-f.fainelli@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 817 bytes --]
Hi Florian,
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Florian-Fainelli/net-phy-broadcom-Add-support-code-for-reading-PHY-counters/20161129-054614
config: x86_64-randconfig-a0-11290519 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
>> ERROR: "bcm_phy_get_strings" [drivers/net/phy/bcm7xxx.ko] undefined!
>> ERROR: "bcm_phy_get_sset_count" [drivers/net/phy/bcm7xxx.ko] undefined!
>> ERROR: "bcm_phy_get_stats" [drivers/net/phy/bcm7xxx.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29154 bytes --]
^ permalink raw reply
* [PATCH net] openvswitch: Fix skb leak in IPv6 reassembly.
From: Daniele Di Proietto @ 2016-11-28 23:43 UTC (permalink / raw)
To: netdev; +Cc: Daniele Di Proietto, Florian Westphal, Pravin B Shelar,
Joe Stringer
If nf_ct_frag6_gather() returns an error other than -EINPROGRESS, it
means that we still have a reference to the skb. We should free it
before returning from handle_fragments, as stated in the comment above.
Fixes: daaa7d647f81 ("netfilter: ipv6: avoid nf_iterate recursion")
CC: Florian Westphal <fw@strlen.de>
CC: Pravin B Shelar <pshelar@ovn.org>
CC: Joe Stringer <joe@ovn.org>
Signed-off-by: Daniele Di Proietto <diproiettod@ovn.org>
---
net/openvswitch/conntrack.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 31045ef..fecefa2 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -370,8 +370,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
skb_orphan(skb);
memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
err = nf_ct_frag6_gather(net, skb, user);
- if (err)
+ if (err) {
+ if (err != -EINPROGRESS)
+ kfree_skb(skb);
return err;
+ }
key->ip.proto = ipv6_hdr(skb)->nexthdr;
ovs_cb.mru = IP6CB(skb)->frag_max_size;
--
2.10.2
^ permalink raw reply related
* Re: [net PATCH 0/2] Don't use lco_csum to compute IPv4 checksum
From: Stephen Rothwell @ 2016-11-28 23:43 UTC (permalink / raw)
To: Jeff Kirsher; +Cc: netdev, intel-wired-lan, Alexander Duyck, davem
In-Reply-To: <1480371962.2402.36.camel@intel.com>
Hi Jeff,
On Mon, 28 Nov 2016 14:26:02 -0800 Jeff Kirsher <jeffrey.t.kirsher@intel.com> wrote:
>
> On Mon, 2016-11-28 at 10:42 -0500, Alexander Duyck wrote:
> > When I implemented the GSO partial support in the Intel drivers I was
> > using
> > lco_csum to compute the checksum that we needed to plug into the IPv4
> > checksum field in order to cancel out the data that was not a part of the
> > IPv4 header. However this didn't take into account that the transport
> > offset might be pointing to the inner transport header.
> >
> > Instead of using lco_csum I have just coded around it so that we can use
> > the outer IP header plus the IP header length to determine where we need
> > to
> > start our checksum and then just call csum_partial ourselves.
> >
> > This should fix the SIT issue reported on igb interfaces as well as
> > simliar
> > issues that would pop up on other Intel NICs.
> >
> > ---
> >
> > Alexander Duyck (2):
> > igb/igbvf: Don't use lco_csum to compute IPv4 checksum
> > ixgbe/ixgbevf: Don't use lco_csum to compute IPv4 checksum
>
> Stephen, I have applied Alex's patches to my net-queue tree. Can you
> confirm they resolve the bug seen?
Its a bit tricky because the origin problem only happens on my
production server (ozlabs.org), but I will see if I can manage to just
remove and reload the driver ... though, the server is running a 4.7.8
kernel and I am wondering how well these patches will apply?
--
Cheers,
Stephen Rothwell
^ permalink raw reply
* Re: [net-next PATCH v2 3/5] virtio_net: Add XDP support
From: John Fastabend @ 2016-11-28 23:26 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: daniel, eric.dumazet, kubakici, shm, davem, alexei.starovoitov,
netdev, bblanco, john.r.fastabend, brouer, tgraf
In-Reply-To: <20161128060446-mutt-send-email-mst@kernel.org>
[...]
>> Perfect! hacking qemu for testing is no problem this helps a lot thanks
>> and saves me time trying to figure out how to get qemu to do this.
>
> Pls note I didn't try this at all, so might not work, but should
> give you the idea.
>
>>>
>>> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
>>> index b68c69d..4866144 100644
>>> --- a/hw/net/virtio-net.c
>>> +++ b/hw/net/virtio-net.c
>>> @@ -1164,6 +1164,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
>>> offset = n->host_hdr_len;
>>> total += n->guest_hdr_len;
>>> guest_offset = n->guest_hdr_len;
>>> + continue;
>>> } else {
>>> guest_offset = 0;
>>> }
>>>
>>>
>>>
>>> here's one that should cap the 1st s/g to 100 bytes:
>>>
>>>
>>> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
>>> index b68c69d..7943004 100644
>>> --- a/hw/net/virtio-net.c
>>> +++ b/hw/net/virtio-net.c
>>> @@ -1164,6 +1164,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
>>> offset = n->host_hdr_len;
>>> total += n->guest_hdr_len;
>>> guest_offset = n->guest_hdr_len;
>>> + sg.iov_len = MIN(sg.iov_len, 100);
>>> } else {
>>> guest_offset = 0;
>>> }
>>>
Here is the patch I went with, I'm using vhost=on:
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1777,7 +1777,8 @@ static int translate_desc(struct vhost_virtqueue
*vq, u64
_iov = iov + ret;
size = node->size - addr + node->start;
- _iov->iov_len = min((u64)len - s, size);
+ printk("%s: build 100 length headers!\n", __func__);
+ _iov->iov_len = min((u64)len - s, (u64)100);//size);
_iov->iov_base = (void __user *)(unsigned long)
(node->userspace_addr + addr - node->start);
s += size;
This seems to do the trick and with 100 I can use 'ping -s' to generate
as many bufs is needed up to MTU. The patch I have seems to be working
fine I'll let it run a bit and test it with some real traffic (not just
ping) then push out a v3 assuming I don't find any issues.
Thanks,
John
^ permalink raw reply
* [PATCH net] ipv6: Allow IPv4-mapped address as next-hop
From: Erik Nordmark @ 2016-11-28 23:27 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy
Cc: netdev, Bob Gilligan
In-Reply-To: <20161128181000.CED72D3427AA@us153.sjc.aristanetworks.com>
Made kernel accept IPv6 routes with IPv4-mapped address as next-hop.
It is possible to configure IP interfaces with IPv4-mapped addresses, and
one can add IPv6 routes for IPv4-mapped destinations/prefixes, yet prior
to this fix the kernel returned an EINVAL when attempting to add an IPv6
route with an IPv4-mapped address as a nexthop/gateway.
RFC 4798 (a proposed standard RFC) uses IPv4-mapped addresses as nexthops,
thus in order to support that type of address configuration the kernel
needs to allow IPv4-mapped addresses as nexthops.
Signed-off-by: Erik Nordmark <nordmark@arista.com>
Signed-off-by: Bob Gilligan <gilligan@arista.com>"
Index: net/net/ipv6/route.c
===================================================================
--- net.orig/net/ipv6/route.c
+++ net/net/ipv6/route.c
@@ -1995,8 +1995,11 @@ static struct rt6_info *ip6_route_info_c
It is very good, but in some (rare!) circumstances
(SIT, PtP, NBMA NOARP links) it is handy to allow
some exceptions. --ANK
+ We allow IPv4-mapped nexthops to support RFC4798-type
+ addressing
*/
- if (!(gwa_type & IPV6_ADDR_UNICAST))
+ if (!(gwa_type & (IPV6_ADDR_UNICAST |
+ IPV6_ADDR_MAPPED)))
goto out;
if (cfg->fc_table) {
^ permalink raw reply
* [PATCH net-next v2] ipv6 addrconf: Implemented enhanced DAD (RFC7527)
From: Erik Nordmark @ 2016-11-28 23:26 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy
Cc: netdev, Bob Gilligan, Hannes Frederic Sowa
In-Reply-To: <20161128060811.1E49FD341C60@us153.sjc.aristanetworks.com>
Implemented RFC7527 Enhanced DAD.
IPv6 duplicate address detection can fail if there is some temporary
loopback of Ethernet frames. RFC7527 solves this by including a random
nonce in the NS messages used for DAD, and if an NS is received with the
same nonce it is assumed to be a looped back DAD probe and is ignored.
RFC7527 is enabled by default. Can be disabled by setting both of
conf/{all,interface}/enhanced_dad to zero.
Signed-off-by: Erik Nordmark<nordmark@arista.com>
Signed-off-by: Bob Gilligan<gilligan@arista.com>"
---
v2: renamed sysctl and made it default to true, plus minor code review fixes
Index: net-next/Documentation/networking/ip-sysctl.txt
===================================================================
--- net-next.orig/Documentation/networking/ip-sysctl.txt
+++ net-next/Documentation/networking/ip-sysctl.txt
@@ -1729,6 +1729,15 @@ drop_unsolicited_na - BOOLEAN
By default this is turned off.
+enhanced_dad - BOOLEAN
+ Include a nonce option in the IPv6 neighbor solicitation messages used for
+ duplicate address detection per RFC7527. A received DAD NS will only signal
+ a duplicate address if the nonce is different. This avoids any false
+ detection of duplicates due to loopback of the NS messages that we send.
+ The nonce option will be sent on an interface unless both of
+ conf/{all,interface}/enhanced_dad are set to FALSE.
+ Default: TRUE
+
icmp/*:
ratelimit - INTEGER
Limit the maximal rates for sending ICMPv6 packets.
Index: net-next/include/linux/ipv6.h
===================================================================
--- net-next.orig/include/linux/ipv6.h
+++ net-next/include/linux/ipv6.h
@@ -68,6 +68,7 @@ struct ipv6_devconf {
#ifdef CONFIG_IPV6_SEG6_HMAC
__s32 seg6_require_hmac;
#endif
+ __u32 enhanced_dad;
struct ctl_table_header *sysctl_header;
};
Index: net-next/include/net/if_inet6.h
===================================================================
--- net-next.orig/include/net/if_inet6.h
+++ net-next/include/net/if_inet6.h
@@ -55,6 +55,7 @@ struct inet6_ifaddr {
__u8 stable_privacy_retry;
__u16 scope;
+ __u64 dad_nonce;
unsigned long cstamp; /* created timestamp */
unsigned long tstamp; /* updated timestamp */
Index: net-next/include/net/ndisc.h
===================================================================
--- net-next.orig/include/net/ndisc.h
+++ net-next/include/net/ndisc.h
@@ -31,6 +31,7 @@ enum {
ND_OPT_PREFIX_INFO = 3, /* RFC2461 */
ND_OPT_REDIRECT_HDR = 4, /* RFC2461 */
ND_OPT_MTU = 5, /* RFC2461 */
+ ND_OPT_NONCE = 14, /* RFC7527 */
__ND_OPT_ARRAY_MAX,
ND_OPT_ROUTE_INFO = 24, /* RFC4191 */
ND_OPT_RDNSS = 25, /* RFC5006 */
@@ -121,6 +122,7 @@ struct ndisc_options {
#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
+#define nd_opts_nonce nd_opt_array[ND_OPT_NONCE]
#define nd_802154_opts_src_lladdr nd_802154_opt_array[ND_OPT_SOURCE_LL_ADDR]
#define nd_802154_opts_tgt_lladdr nd_802154_opt_array[ND_OPT_TARGET_LL_ADDR]
@@ -398,7 +400,8 @@ void ndisc_cleanup(void);
int ndisc_rcv(struct sk_buff *skb);
void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
- const struct in6_addr *daddr, const struct in6_addr *saddr);
+ const struct in6_addr *daddr, const struct in6_addr *saddr,
+ u64 nonce);
void ndisc_send_rs(struct net_device *dev,
const struct in6_addr *saddr, const struct in6_addr *daddr);
Index: net-next/include/uapi/linux/ipv6.h
===================================================================
--- net-next.orig/include/uapi/linux/ipv6.h
+++ net-next/include/uapi/linux/ipv6.h
@@ -181,6 +181,7 @@ enum {
DEVCONF_RTR_SOLICIT_MAX_INTERVAL,
DEVCONF_SEG6_ENABLED,
DEVCONF_SEG6_REQUIRE_HMAC,
+ DEVCONF_ENHANCED_DAD,
DEVCONF_MAX
};
Index: net-next/net/ipv6/addrconf.c
===================================================================
--- net-next.orig/net/ipv6/addrconf.c
+++ net-next/net/ipv6/addrconf.c
@@ -242,6 +242,7 @@ static struct ipv6_devconf ipv6_devconf
#ifdef CONFIG_IPV6_SEG6_HMAC
.seg6_require_hmac = 0,
#endif
+ .enhanced_dad = 1,
};
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -292,6 +293,7 @@ static struct ipv6_devconf ipv6_devconf_
#ifdef CONFIG_IPV6_SEG6_HMAC
.seg6_require_hmac = 0,
#endif
+ .enhanced_dad = 1,
};
/* Check if a valid qdisc is available */
@@ -3734,12 +3736,21 @@ static void addrconf_dad_kick(struct ine
{
unsigned long rand_num;
struct inet6_dev *idev = ifp->idev;
+ u64 nonce;
if (ifp->flags & IFA_F_OPTIMISTIC)
rand_num = 0;
else
rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1);
+ nonce = 0;
+ if (idev->cnf.enhanced_dad ||
+ dev_net(idev->dev)->ipv6.devconf_all->enhanced_dad) {
+ do
+ get_random_bytes(&nonce, 6);
+ while (nonce == 0);
+ }
+ ifp->dad_nonce = nonce;
ifp->dad_probes = idev->cnf.dad_transmits;
addrconf_mod_dad_work(ifp, rand_num);
}
@@ -3915,7 +3926,8 @@ static void addrconf_dad_work(struct wor
/* send a neighbour solicitation for our addr */
addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
- ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any);
+ ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any,
+ ifp->dad_nonce);
out:
in6_ifa_put(ifp);
rtnl_unlock();
@@ -4956,6 +4968,7 @@ static inline void ipv6_store_devconf(st
#ifdef CONFIG_IPV6_SEG6_HMAC
array[DEVCONF_SEG6_REQUIRE_HMAC] = cnf->seg6_require_hmac;
#endif
+ array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
}
static inline size_t inet6_ifla6_size(void)
@@ -6064,6 +6077,13 @@ static const struct ctl_table addrconf_s
},
#endif
{
+ .procname = "enhanced_dad",
+ .data = &ipv6_devconf.enhanced_dad,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
/* sentinel */
}
};
Index: net-next/net/ipv6/ndisc.c
===================================================================
--- net-next.orig/net/ipv6/ndisc.c
+++ net-next/net/ipv6/ndisc.c
@@ -233,6 +233,7 @@ struct ndisc_options *ndisc_parse_option
case ND_OPT_SOURCE_LL_ADDR:
case ND_OPT_TARGET_LL_ADDR:
case ND_OPT_MTU:
+ case ND_OPT_NONCE:
case ND_OPT_REDIRECT_HDR:
if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
ND_PRINTK(2, warn,
@@ -568,7 +569,8 @@ static void ndisc_send_unsol_na(struct n
}
void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
- const struct in6_addr *daddr, const struct in6_addr *saddr)
+ const struct in6_addr *daddr, const struct in6_addr *saddr,
+ u64 nonce)
{
struct sk_buff *skb;
struct in6_addr addr_buf;
@@ -588,6 +590,8 @@ void ndisc_send_ns(struct net_device *de
if (inc_opt)
optlen += ndisc_opt_addr_space(dev,
NDISC_NEIGHBOUR_SOLICITATION);
+ if (nonce != 0)
+ optlen += 8;
skb = ndisc_alloc_skb(dev, sizeof(*msg) + optlen);
if (!skb)
@@ -605,6 +609,13 @@ void ndisc_send_ns(struct net_device *de
ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
dev->dev_addr,
NDISC_NEIGHBOUR_SOLICITATION);
+ if (nonce != 0) {
+ u8 *opt = skb_put(skb, 8);
+
+ opt[0] = ND_OPT_NONCE;
+ opt[1] = 8 >> 3;
+ memcpy(opt + 2, &nonce, 6);
+ }
ndisc_send_skb(skb, daddr, saddr);
}
@@ -693,12 +704,12 @@ static void ndisc_solicit(struct neighbo
"%s: trying to ucast probe in NUD_INVALID: %pI6\n",
__func__, target);
}
- ndisc_send_ns(dev, target, target, saddr);
+ ndisc_send_ns(dev, target, target, saddr, 0);
} else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
neigh_app_ns(neigh);
} else {
addrconf_addr_solict_mult(target, &mcaddr);
- ndisc_send_ns(dev, target, &mcaddr, saddr);
+ ndisc_send_ns(dev, target, &mcaddr, saddr, 0);
}
}
@@ -742,6 +753,7 @@ static void ndisc_recv_ns(struct sk_buff
int dad = ipv6_addr_any(saddr);
bool inc;
int is_router = -1;
+ u64 nonce = 0;
if (skb->len < sizeof(struct nd_msg)) {
ND_PRINTK(2, warn, "NS: packet too short\n");
@@ -786,6 +798,8 @@ static void ndisc_recv_ns(struct sk_buff
return;
}
}
+ if (ndopts.nd_opts_nonce)
+ memcpy(&nonce, (u8 *)(ndopts.nd_opts_nonce + 1), 6);
inc = ipv6_addr_is_multicast(daddr);
@@ -794,6 +808,17 @@ static void ndisc_recv_ns(struct sk_buff
have_ifp:
if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
if (dad) {
+ if (nonce != 0 && ifp->dad_nonce == nonce) {
+ u8 *np = (u8 *)&nonce;
+ /* Matching nonce if looped back */
+ ND_PRINTK(2, notice,
+ "%s: IPv6 DAD loopback for address %pI6c nonce %02x:%02x:%02x:%02x:%02x:%02x ignored\n",
+ ifp->idev->dev->name,
+ &ifp->addr,
+ np[0], np[1], np[2], np[3],
+ np[4], np[5]);
+ goto out;
+ }
/*
* We are colliding with another node
* who is doing DAD
^ permalink raw reply
* Re: net: GPF in eth_header
From: Eric Dumazet @ 2016-11-28 23:16 UTC (permalink / raw)
To: Florian Westphal
Cc: Dmitry Vyukov, syzkaller, Hannes Frederic Sowa, David Miller,
Tom Herbert, Alexander Duyck, Jiri Benc, Sabrina Dubroca, netdev,
LKML
In-Reply-To: <20161128221923.GC9858@breakpoint.cc>
On Mon, 2016-11-28 at 23:19 +0100, Florian Westphal wrote:
> It currently returns -EINVAL in cases where skb wasn't changed/altered
> (e.g. because it doesn't have a fragment header), so we should ACCEPT in
> that case.
>
Maybe nf_ct_frag6_queue() should return direct NF_ codes then ...
^ permalink raw reply
* [PATCH 4/6] net: ethernet: ti: cpts: add ptp pps support
From: Grygorii Strashko @ 2016-11-28 23:04 UTC (permalink / raw)
To: David S. Miller, netdev, Mugunthan V N, Richard Cochran
Cc: Sekhar Nori, linux-kernel, linux-omap, Rob Herring, devicetree,
Murali Karicheri, Wingman Kwok, Grygorii Strashko
In-Reply-To: <20161128230428.6872-1-grygorii.strashko@ti.com>
The TS_COMP output in the CPSW CPTS module is asserted for
ts_comp_length[15:0] RCLK periods when the time_stamp value compares
with the ts_comp_val[31:0] and the length value is non-zero. The
TS_COMP pulse edge occurs three RCLK periods after the values
compare. A timestamp compare event is pushed into the event FIFO when
TS_COMP is asserted.
This patch adds support of Pulse-Per-Second (PPS) by using the
timestamp compare output. The CPTS driver adds one second of counter
value to the ts_comp_val register after each assertion of the TS_COMP
output. The TS_COMP pulse polarity and width are configurable in DT.
Signed-off-by: WingMan Kwok <w-kwok2@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
.../devicetree/bindings/net/keystone-netcp.txt | 10 +
drivers/net/ethernet/ti/cpts.c | 237 ++++++++++++++++++++-
drivers/net/ethernet/ti/cpts.h | 14 +-
3 files changed, 251 insertions(+), 10 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/keystone-netcp.txt b/Documentation/devicetree/bindings/net/keystone-netcp.txt
index 1c805319..060af96 100644
--- a/Documentation/devicetree/bindings/net/keystone-netcp.txt
+++ b/Documentation/devicetree/bindings/net/keystone-netcp.txt
@@ -127,6 +127,16 @@ Optional properties:
The number of external time stamp channels.
The different CPTS versions might support up 8
external time stamp channels. if absent - unsupported.
+ - cpts-ts-comp-length:
+ Enable time stamp comparison event and TS_COMP signal output
+ generation when CPTS counter reaches a value written to
+ the TS_COMP_VAL register.
+ The generated pulse width is 3 refclk cycles if this property
+ has no value (empty) or, otherwise, it should specify desired
+ pulse width in number of refclk periods - max value 2^16.
+ TS_COMP functionality will be disabled if not present.
+ - cpts-ts-comp-polarity-low:
+ Set polarity of TS_COMP signal to low. Default is hight.
NetCP interface properties: Interface specification for NetCP sub-modules.
Required properties:
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index 2f7641a..8ff70cc 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -31,9 +31,13 @@
#include "cpts.h"
+#define CPTS_TS_COMP_PULSE_LENGTH_DEF 3
+
#define cpts_read32(c, r) readl_relaxed(&c->reg->r)
#define cpts_write32(c, v, r) writel_relaxed(v, &c->reg->r)
+static int cpts_report_ts_events(struct cpts *cpts, bool pps_reload);
+
static int cpts_event_port(struct cpts_event *event)
{
return (event->high >> PORT_NUMBER_SHIFT) & PORT_NUMBER_MASK;
@@ -108,6 +112,7 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
type = event_type(event);
switch (type) {
case CPTS_EV_HW:
+ case CPTS_EV_COMP:
event->tmo +=
msecs_to_jiffies(CPTS_EVENT_HWSTAMP_TIMEOUT);
case CPTS_EV_PUSH:
@@ -153,6 +158,60 @@ static cycle_t cpts_systim_read(const struct cyclecounter *cc)
return val;
}
+static cycle_t cpts_cc_ns2cyc(struct cpts *cpts, u64 nsecs)
+{
+ cycle_t cyc = (nsecs << cpts->cc.shift) + nsecs;
+
+ do_div(cyc, cpts->cc.mult);
+
+ return cyc;
+}
+
+static void cpts_ts_comp_disable(struct cpts *cpts)
+{
+ cpts_write32(cpts, 0, ts_comp_length);
+}
+
+static void cpts_ts_comp_enable(struct cpts *cpts)
+{
+ /* TS_COMP_LENGTH should be 0 while the TS_COMP_VAL value is
+ * being written
+ */
+ cpts_write32(cpts, 0, ts_comp_length);
+ cpts_write32(cpts, cpts->ts_comp_next, ts_comp_val);
+ cpts_write32(cpts, cpts->ts_comp_length, ts_comp_length);
+}
+
+static void cpts_ts_comp_add_ns(struct cpts *cpts, s64 add_ns)
+{
+ cycle_t cyc_next;
+
+ if (add_ns == NSEC_PER_SEC)
+ /* avoid calculation */
+ cyc_next = cpts->ts_comp_one_sec_cycs;
+ else
+ cyc_next = cpts_cc_ns2cyc(cpts, add_ns);
+
+ cyc_next += cpts->ts_comp_next;
+ cpts->ts_comp_next = cyc_next & cpts->cc.mask;
+ pr_debug("cpts comp ts_comp_next: %u\n", cpts->ts_comp_next);
+}
+
+static void cpts_ts_comp_settime(struct cpts *cpts, s64 now_ns)
+{
+ struct timespec64 ts;
+
+ if (cpts->ts_comp_enabled) {
+ ts = ns_to_timespec64(now_ns);
+
+ /* align pulse to next sec boundary and add one sec */
+ cpts_ts_comp_add_ns(cpts, NSEC_PER_SEC - ts.tv_nsec);
+
+ /* enable ts_comp pulse */
+ cpts_ts_comp_enable(cpts);
+ }
+}
+
/* PTP clock operations */
static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
@@ -162,6 +221,7 @@ static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
int neg_adj = 0;
unsigned long flags;
struct cpts *cpts = container_of(ptp, struct cpts, info);
+ u64 ns;
if (ppb < 0) {
neg_adj = 1;
@@ -172,14 +232,31 @@ static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
adj *= ppb;
diff = div_u64(adj, 1000000000ULL);
+ mutex_lock(&cpts->ptp_clk_mutex);
+
spin_lock_irqsave(&cpts->lock, flags);
+ if (cpts->ts_comp_enabled) {
+ cpts_ts_comp_disable(cpts);
+ /* if any, report existing pulse before adj */
+ cpts_fifo_read(cpts, CPTS_EV_COMP);
+ /* if any, report existing pulse before adj */
+ cpts_report_ts_events(cpts, false);
+ }
timecounter_read(&cpts->tc);
cpts->cc.mult = neg_adj ? mult - diff : mult + diff;
-
+ /* get updated time with adj */
+ ns = timecounter_read(&cpts->tc);
+ cpts->ts_comp_next = cpts->tc.cycle_last;
spin_unlock_irqrestore(&cpts->lock, flags);
+ if (cpts->ts_comp_enabled)
+ cpts->ts_comp_one_sec_cycs = cpts_cc_ns2cyc(cpts, NSEC_PER_SEC);
+ cpts_ts_comp_settime(cpts, ns);
+
+ mutex_unlock(&cpts->ptp_clk_mutex);
+
return 0;
}
@@ -187,11 +264,28 @@ static int cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
unsigned long flags;
struct cpts *cpts = container_of(ptp, struct cpts, info);
+ u64 ns;
+
+ mutex_lock(&cpts->ptp_clk_mutex);
spin_lock_irqsave(&cpts->lock, flags);
+ if (cpts->ts_comp_enabled) {
+ cpts_ts_comp_disable(cpts);
+ /* if any, report existing pulse before adj */
+ cpts_fifo_read(cpts, CPTS_EV_COMP);
+ /* if any, report existing pulse before adj */
+ cpts_report_ts_events(cpts, false);
+ }
+
timecounter_adjtime(&cpts->tc, delta);
+ ns = timecounter_read(&cpts->tc);
+ cpts->ts_comp_next = cpts->tc.cycle_last;
spin_unlock_irqrestore(&cpts->lock, flags);
+ cpts_ts_comp_settime(cpts, ns);
+
+ mutex_unlock(&cpts->ptp_clk_mutex);
+
return 0;
}
@@ -213,25 +307,90 @@ static int cpts_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
static int cpts_ptp_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts)
{
- u64 ns;
- unsigned long flags;
struct cpts *cpts = container_of(ptp, struct cpts, info);
+ unsigned long flags;
+ u64 ns;
ns = timespec64_to_ns(ts);
+ mutex_lock(&cpts->ptp_clk_mutex);
+
spin_lock_irqsave(&cpts->lock, flags);
+ if (cpts->ts_comp_enabled) {
+ cpts_ts_comp_disable(cpts);
+ /* if any, get existing pulse event before adj */
+ cpts_fifo_read(cpts, CPTS_EV_COMP);
+ /* if any, report existing pulse before adj */
+ cpts_report_ts_events(cpts, false);
+ }
+
timecounter_init(&cpts->tc, &cpts->cc, ns);
+ cpts->ts_comp_next = cpts->tc.cycle_last;
spin_unlock_irqrestore(&cpts->lock, flags);
+ cpts_ts_comp_settime(cpts, ns);
+
+ mutex_unlock(&cpts->ptp_clk_mutex);
+
return 0;
}
-static int cpts_report_ts_events(struct cpts *cpts)
+static int cpts_pps_enable(struct cpts *cpts, int on)
+{
+ struct timespec64 ts;
+ unsigned long flags;
+ u64 ns;
+
+ if (cpts->ts_comp_enabled == on)
+ return 0;
+
+ mutex_lock(&cpts->ptp_clk_mutex);
+ cpts->ts_comp_enabled = on;
+
+ if (!on) {
+ cpts_ts_comp_disable(cpts);
+ if (!cpts->hw_ts_enable)
+ cpts->ov_check_period = cpts->ov_check_period_slow;
+ mutex_unlock(&cpts->ptp_clk_mutex);
+ return 0;
+ }
+
+ /* get current counter value */
+ spin_lock_irqsave(&cpts->lock, flags);
+ ns = timecounter_read(&cpts->tc);
+ cpts->ts_comp_next = cpts->tc.cycle_last;
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ ts = ns_to_timespec64(ns);
+ cpts->ts_comp_one_sec_cycs = cpts_cc_ns2cyc(cpts, NSEC_PER_SEC);
+ /* align to next sec boundary and add one sec to avoid the situation
+ * when the current time is very close to the next second point and
+ * it might be possible that ts_comp_val will be configured to
+ * the time in the past.
+ */
+ cpts_ts_comp_add_ns(cpts, 2 * NSEC_PER_SEC - ts.tv_nsec);
+
+ /* enable ts_comp pulse */
+ cpts_ts_comp_enable(cpts);
+
+ /* poll for events faster - evry 200 ms */
+ cpts->ov_check_period = msecs_to_jiffies(CPTS_EVENT_HWSTAMP_TIMEOUT);
+
+ mod_delayed_work(system_wq, &cpts->overflow_work,
+ cpts->ov_check_period);
+
+ mutex_unlock(&cpts->ptp_clk_mutex);
+
+ return 0;
+}
+
+static int cpts_report_ts_events(struct cpts *cpts, bool pps_reload)
{
struct list_head *this, *next;
struct ptp_clock_event pevent;
struct cpts_event *event;
int reported = 0, ev;
+ u64 ns;
list_for_each_safe(this, next, &cpts->events) {
event = list_entry(this, struct cpts_event, list);
@@ -248,6 +407,33 @@ static int cpts_report_ts_events(struct cpts *cpts)
++reported;
continue;
}
+
+ if (event_type(event) == CPTS_EV_COMP) {
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ if (cpts->ts_comp_next != event->low) {
+ pr_err("cpts ts_comp mismatch: %08x %08x\n",
+ cpts->ts_comp_next, event->low);
+ continue;
+ } else
+ pr_debug("cpts comp ev tstamp: %u\n",
+ event->low);
+
+ /* report the event */
+ ns = timecounter_cyc2time(&cpts->tc, event->low);
+ pevent.type = PTP_CLOCK_PPSUSR;
+ pevent.pps_times.ts_real = ns_to_timespec64(ns);
+ ptp_clock_event(cpts->clock, &pevent);
+
+ if (pps_reload) {
+ /* reload: add ns to ts_comp */
+ cpts_ts_comp_add_ns(cpts, NSEC_PER_SEC);
+ /* enable ts_comp pulse with new val */
+ cpts_ts_comp_enable(cpts);
+ }
+ ++reported;
+ continue;
+ }
}
return reported;
}
@@ -264,6 +450,8 @@ static int cpts_extts_enable(struct cpts *cpts, u32 index, int on)
if (((cpts->hw_ts_enable & BIT(index)) >> index) == on)
return 0;
+ mutex_lock(&cpts->ptp_clk_mutex);
+
spin_lock_irqsave(&cpts->lock, flags);
v = cpts_read32(cpts, control);
@@ -282,12 +470,12 @@ static int cpts_extts_enable(struct cpts *cpts, u32 index, int on)
/* poll for events faster - evry 200 ms */
cpts->ov_check_period =
msecs_to_jiffies(CPTS_EVENT_HWSTAMP_TIMEOUT);
- else
+ else if (!cpts->ts_comp_enabled)
cpts->ov_check_period = cpts->ov_check_period_slow;
mod_delayed_work(system_wq, &cpts->overflow_work,
cpts->ov_check_period);
-
+ mutex_unlock(&cpts->ptp_clk_mutex);
return 0;
}
@@ -299,6 +487,8 @@ static int cpts_ptp_enable(struct ptp_clock_info *ptp,
switch (rq->type) {
case PTP_CLK_REQ_EXTTS:
return cpts_extts_enable(cpts, rq->extts.index, on);
+ case PTP_CLK_REQ_PPS:
+ return cpts_pps_enable(cpts, on);
default:
break;
}
@@ -326,12 +516,15 @@ static void cpts_overflow_check(struct work_struct *work)
struct timespec64 ts;
unsigned long flags;
+ mutex_lock(&cpts->ptp_clk_mutex);
spin_lock_irqsave(&cpts->lock, flags);
ts = ns_to_timespec64(timecounter_read(&cpts->tc));
spin_unlock_irqrestore(&cpts->lock, flags);
- if (cpts->hw_ts_enable)
- cpts_report_ts_events(cpts);
+ if (cpts->hw_ts_enable || cpts->ts_comp_enabled)
+ cpts_report_ts_events(cpts, true);
+ mutex_unlock(&cpts->ptp_clk_mutex);
+
pr_debug("cpts overflow check at %lld.%09lu\n", ts.tv_sec, ts.tv_nsec);
schedule_delayed_work(&cpts->overflow_work, cpts->ov_check_period);
}
@@ -445,6 +638,7 @@ EXPORT_SYMBOL_GPL(cpts_tx_timestamp);
int cpts_register(struct cpts *cpts)
{
int err, i;
+ u32 control;
INIT_LIST_HEAD(&cpts->events);
INIT_LIST_HEAD(&cpts->pool);
@@ -453,7 +647,14 @@ int cpts_register(struct cpts *cpts)
clk_enable(cpts->refclk);
- cpts_write32(cpts, CPTS_EN, control);
+ control = CPTS_EN;
+ if (cpts->caps & CPTS_CAP_TS_COMP_EN) {
+ if (cpts->caps & CPTS_CAP_TS_COMP_POL_LOW_SEL)
+ control &= ~TS_COMP_POL;
+ else
+ control |= TS_COMP_POL;
+ }
+ cpts_write32(cpts, control, control);
cpts_write32(cpts, TS_PEND_EN, int_enable);
cpts->cc.mult = cpts->cc_mult;
@@ -558,6 +759,20 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
cpts->rftclk_sel = prop & CPTS_RFTCLK_SEL_MASK;
}
+ if (of_property_read_bool(node, "cpts-ts-comp-length")) {
+ cpts->caps |= CPTS_CAP_TS_COMP_EN;
+ cpts->ts_comp_length = CPTS_TS_COMP_PULSE_LENGTH_DEF;
+ }
+
+ if (cpts->caps & CPTS_CAP_TS_COMP_EN) {
+ ret = of_property_read_u32(node, "cpts-ts-comp-length", &prop);
+ if (!ret)
+ cpts->ts_comp_length = prop;
+
+ if (of_property_read_bool(node, "cpts-ts-comp-polarity-low"))
+ cpts->caps |= CPTS_CAP_TS_COMP_POL_LOW_SEL;
+ }
+
if (!of_property_read_u32(node, "cpts-ext-ts-inputs", &prop))
cpts->ext_ts_inputs = prop;
@@ -584,6 +799,7 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
cpts->dev = dev;
cpts->reg = (struct cpsw_cpts __iomem *)regs;
spin_lock_init(&cpts->lock);
+ mutex_init(&cpts->ptp_clk_mutex);
INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check);
ret = cpts_of_parse(cpts, node);
@@ -608,6 +824,9 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
if (cpts->ext_ts_inputs)
cpts->info.n_ext_ts = cpts->ext_ts_inputs;
+ if (cpts->caps & CPTS_CAP_TS_COMP_EN)
+ cpts->info.pps = 1;
+
cpts_calc_mult_shift(cpts);
return cpts;
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
index ad80c95..a82520d 100644
--- a/drivers/net/ethernet/ti/cpts.h
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -39,7 +39,8 @@ struct cpsw_cpts {
u32 ts_push; /* Time stamp event push */
u32 ts_load_val; /* Time stamp load value */
u32 ts_load_en; /* Time stamp load enable */
- u32 res2[2];
+ u32 ts_comp_val; /* Time stamp comparison value, v1.5 & up */
+ u32 ts_comp_length; /* Time stamp comp assert len, v1.5 & up */
u32 intstat_raw; /* Time sync interrupt status raw */
u32 intstat_masked; /* Time sync interrupt status masked */
u32 int_enable; /* Time sync interrupt enable */
@@ -64,11 +65,14 @@ struct cpsw_cpts {
#define HW3_TS_PUSH_EN (1<<10) /* Hardware push 3 enable */
#define HW2_TS_PUSH_EN (1<<9) /* Hardware push 2 enable */
#define HW1_TS_PUSH_EN (1<<8) /* Hardware push 1 enable */
+#define TS_COMP_POL BIT(2) /* TS_COMP Polarity */
#define INT_TEST (1<<1) /* Interrupt Test */
#define CPTS_EN (1<<0) /* Time Sync Enable */
#define CPTS_RFTCLK_SEL_MASK 0x1f
+#define CPTS_TS_COMP_LENGTH_MASK 0xffff
+
/*
* Definitions for the single bit resisters:
* TS_PUSH TS_LOAD_EN INTSTAT_RAW INTSTAT_MASKED INT_ENABLE EVENT_POP
@@ -97,6 +101,7 @@ enum {
CPTS_EV_HW, /* Hardware Time Stamp Push Event */
CPTS_EV_RX, /* Ethernet Receive Event */
CPTS_EV_TX, /* Ethernet Transmit Event */
+ CPTS_EV_COMP, /* Time Stamp Compare Event */
};
#define CPTS_FIFO_DEPTH 16
@@ -113,6 +118,8 @@ struct cpts_event {
};
#define CPTS_CAP_RFTCLK_SEL BIT(0)
+#define CPTS_CAP_TS_COMP_EN BIT(1)
+#define CPTS_CAP_TS_COMP_POL_LOW_SEL BIT(2)
struct cpts {
struct device *dev;
@@ -137,6 +144,11 @@ struct cpts {
u32 ext_ts_inputs;
u32 hw_ts_enable;
u32 caps;
+ u32 ts_comp_next; /* next time_stamp value to compare with */
+ u32 ts_comp_length; /* TS_COMP Output pulse width */
+ u32 ts_comp_one_sec_cycs; /* number of counter cycles in one sec */
+ int ts_comp_enabled;
+ struct mutex ptp_clk_mutex; /* sync PTP interface with overflow_work */
};
void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
--
2.10.1
^ permalink raw reply related
* [PATCH 3/6] net: ethernet: ti: cpts: add support of cpts HW_TS_PUSH
From: Grygorii Strashko @ 2016-11-28 23:04 UTC (permalink / raw)
To: David S. Miller, netdev, Mugunthan V N, Richard Cochran
Cc: Sekhar Nori, linux-kernel, linux-omap, Rob Herring, devicetree,
Murali Karicheri, Wingman Kwok, Grygorii Strashko
In-Reply-To: <20161128230428.6872-1-grygorii.strashko@ti.com>
This patch adds support of the CPTS HW_TS_PUSH events which are generated
by external low frequency time stamp channels on TI's OMAP CPSW and
Keystone 2 platforms. It supports up to 8 external time stamp channels for
HW_TS_PUSH input pins (the number of supported channel is different for
different SoCs and CPTS versions, check corresponding Data maual before
enabling it). Therefore, new DT property "cpts-ext-ts-inputs" is introduced
for specifying number of available external timestamp channels.
The PTP external timestamp (extts) infrastructure can be used for
HW_TS_PUSH timestamp controlling and reporting.
This also change overflow polling period when HW_TS_PUSH feature is
enabled - overflow check work will be scheduled more often (every
200ms) for proper HW_TS_PUSH events reporting.
Signed-off-by: WingMan Kwok <w-kwok2@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 4 +
.../devicetree/bindings/net/keystone-netcp.txt | 4 +
drivers/net/ethernet/ti/cpts.c | 104 ++++++++++++++++++++-
drivers/net/ethernet/ti/cpts.h | 6 ++
4 files changed, 114 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index ebda7c9..86a2f61 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -38,6 +38,10 @@ Optional properties:
Mult and shift will be calculated basing on CPTS
rftclk frequency if both cpts_clock_shift and
cpts_clock_mult properties are not provided.
+- cpts-ext-ts-inputs : The number of external time stamp channels.
+ The different CPTS versions might support up 8
+ external time stamp channels.
+ if absent - unsupported.
Slave Properties:
Required properties:
diff --git a/Documentation/devicetree/bindings/net/keystone-netcp.txt b/Documentation/devicetree/bindings/net/keystone-netcp.txt
index ec4a241..1c805319 100644
--- a/Documentation/devicetree/bindings/net/keystone-netcp.txt
+++ b/Documentation/devicetree/bindings/net/keystone-netcp.txt
@@ -123,6 +123,10 @@ Optional properties:
Defaults: clock_mult, clock_shift = calculated from
CPTS refclk
+ - cpts-ext-ts-inputs:
+ The number of external time stamp channels.
+ The different CPTS versions might support up 8
+ external time stamp channels. if absent - unsupported.
NetCP interface properties: Interface specification for NetCP sub-modules.
Required properties:
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index 9c5b835..2f7641a 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -34,6 +34,11 @@
#define cpts_read32(c, r) readl_relaxed(&c->reg->r)
#define cpts_write32(c, v, r) writel_relaxed(v, &c->reg->r)
+static int cpts_event_port(struct cpts_event *event)
+{
+ return (event->high >> PORT_NUMBER_SHIFT) & PORT_NUMBER_MASK;
+}
+
static int event_expired(struct cpts_event *event)
{
return time_after(jiffies, event->tmo);
@@ -96,11 +101,15 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
}
event = list_first_entry(&cpts->pool, struct cpts_event, list);
- event->tmo = jiffies + 2;
+ event->tmo = jiffies +
+ msecs_to_jiffies(CPTS_EVENT_RX_TX_TIMEOUT);
event->high = hi;
event->low = lo;
type = event_type(event);
switch (type) {
+ case CPTS_EV_HW:
+ event->tmo +=
+ msecs_to_jiffies(CPTS_EVENT_HWSTAMP_TIMEOUT);
case CPTS_EV_PUSH:
case CPTS_EV_RX:
case CPTS_EV_TX:
@@ -109,7 +118,6 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
break;
case CPTS_EV_ROLL:
case CPTS_EV_HALF:
- case CPTS_EV_HW:
break;
default:
pr_err("cpts: unknown event type\n");
@@ -218,9 +226,83 @@ static int cpts_ptp_settime(struct ptp_clock_info *ptp,
return 0;
}
+static int cpts_report_ts_events(struct cpts *cpts)
+{
+ struct list_head *this, *next;
+ struct ptp_clock_event pevent;
+ struct cpts_event *event;
+ int reported = 0, ev;
+
+ list_for_each_safe(this, next, &cpts->events) {
+ event = list_entry(this, struct cpts_event, list);
+ ev = event_type(event);
+ if (ev == CPTS_EV_HW) {
+ list_del_init(&event->list);
+ list_add(&event->list, &cpts->pool);
+ /* report the event */
+ pevent.timestamp =
+ timecounter_cyc2time(&cpts->tc, event->low);
+ pevent.type = PTP_CLOCK_EXTTS;
+ pevent.index = cpts_event_port(event) - 1;
+ ptp_clock_event(cpts->clock, &pevent);
+ ++reported;
+ continue;
+ }
+ }
+ return reported;
+}
+
+/* HW TS */
+static int cpts_extts_enable(struct cpts *cpts, u32 index, int on)
+{
+ unsigned long flags;
+ u32 v;
+
+ if (index >= cpts->info.n_ext_ts)
+ return -ENXIO;
+
+ if (((cpts->hw_ts_enable & BIT(index)) >> index) == on)
+ return 0;
+
+ spin_lock_irqsave(&cpts->lock, flags);
+
+ v = cpts_read32(cpts, control);
+ if (on) {
+ v |= BIT(8 + index);
+ cpts->hw_ts_enable |= BIT(index);
+ } else {
+ v &= ~BIT(8 + index);
+ cpts->hw_ts_enable &= ~BIT(index);
+ }
+ cpts_write32(cpts, v, control);
+
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ if (cpts->hw_ts_enable)
+ /* poll for events faster - evry 200 ms */
+ cpts->ov_check_period =
+ msecs_to_jiffies(CPTS_EVENT_HWSTAMP_TIMEOUT);
+ else
+ cpts->ov_check_period = cpts->ov_check_period_slow;
+
+ mod_delayed_work(system_wq, &cpts->overflow_work,
+ cpts->ov_check_period);
+
+ return 0;
+}
+
static int cpts_ptp_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
+ struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+ switch (rq->type) {
+ case PTP_CLK_REQ_EXTTS:
+ return cpts_extts_enable(cpts, rq->extts.index, on);
+ default:
+ break;
+ }
+
return -EOPNOTSUPP;
}
@@ -240,10 +322,16 @@ static struct ptp_clock_info cpts_info = {
static void cpts_overflow_check(struct work_struct *work)
{
- struct timespec64 ts;
struct cpts *cpts = container_of(work, struct cpts, overflow_work.work);
+ struct timespec64 ts;
+ unsigned long flags;
- cpts_ptp_gettime(&cpts->info, &ts);
+ spin_lock_irqsave(&cpts->lock, flags);
+ ts = ns_to_timespec64(timecounter_read(&cpts->tc));
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
+ if (cpts->hw_ts_enable)
+ cpts_report_ts_events(cpts);
pr_debug("cpts overflow check at %lld.%09lu\n", ts.tv_sec, ts.tv_nsec);
schedule_delayed_work(&cpts->overflow_work, cpts->ov_check_period);
}
@@ -422,6 +510,8 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
/* Calc overflow check period (maxsec / 2) */
cpts->ov_check_period = (HZ * maxsec) / 2;
+ cpts->ov_check_period_slow = cpts->ov_check_period;
+
dev_info(cpts->dev, "cpts: overflow check period %lu (jiffies)\n",
cpts->ov_check_period);
@@ -468,6 +558,9 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
cpts->rftclk_sel = prop & CPTS_RFTCLK_SEL_MASK;
}
+ if (!of_property_read_u32(node, "cpts-ext-ts-inputs", &prop))
+ cpts->ext_ts_inputs = prop;
+
return 0;
of_error:
@@ -512,6 +605,9 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
cpts->cc.mask = CLOCKSOURCE_MASK(32);
cpts->info = cpts_info;
+ if (cpts->ext_ts_inputs)
+ cpts->info.n_ext_ts = cpts->ext_ts_inputs;
+
cpts_calc_mult_shift(cpts);
return cpts;
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
index c934b61..ad80c95 100644
--- a/drivers/net/ethernet/ti/cpts.h
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -102,6 +102,9 @@ enum {
#define CPTS_FIFO_DEPTH 16
#define CPTS_MAX_EVENTS 32
+#define CPTS_EVENT_RX_TX_TIMEOUT 20 /* ms */
+#define CPTS_EVENT_HWSTAMP_TIMEOUT 200 /* ms */
+
struct cpts_event {
struct list_head list;
unsigned long tmo;
@@ -129,7 +132,10 @@ struct cpts {
struct list_head pool;
struct cpts_event pool_data[CPTS_MAX_EVENTS];
unsigned long ov_check_period;
+ unsigned long ov_check_period_slow;
u32 rftclk_sel;
+ u32 ext_ts_inputs;
+ u32 hw_ts_enable;
u32 caps;
};
--
2.10.1
^ permalink raw reply related
* [PATCH 6/6] ARM: dts: keystone: enable time synchronization (cpts) submodule
From: Grygorii Strashko @ 2016-11-28 23:04 UTC (permalink / raw)
To: David S. Miller, netdev, Mugunthan V N, Richard Cochran
Cc: Sekhar Nori, linux-kernel, linux-omap, Rob Herring, devicetree,
Murali Karicheri, Wingman Kwok, Grygorii Strashko
In-Reply-To: <20161128230428.6872-1-grygorii.strashko@ti.com>
This patch adds DT configuration for Time Synchronization (CPTS) submodule
which is present on KeyStone 66AK2HK/E/Lx 1G Switch Subsystem.
The SYSCLK2 is selected as CPTS rftclk by default.
The ts_comp enabled for 66AK2E/L SoCs.
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
arch/arm/boot/dts/keystone-k2e-netcp.dtsi | 3 +++
arch/arm/boot/dts/keystone-k2hk-netcp.dtsi | 1 +
arch/arm/boot/dts/keystone-k2l-netcp.dtsi | 3 +++
3 files changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi b/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
index ba828cb..919e655 100644
--- a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
@@ -158,6 +158,9 @@ netcp: netcp@24000000 {
/* enable-ale; */
tx-queue = <896>;
tx-channel = "nettx";
+ cpts-rftclk-sel = <0>;
+ cpts-ext-ts-inputs = <6>;
+ cpts-ts-comp-length;
interfaces {
gbe0: interface-0 {
diff --git a/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi b/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
index a5ac845..772097b 100644
--- a/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
@@ -177,6 +177,7 @@ netcp: netcp@2000000 {
/* enable-ale; */
tx-queue = <648>;
tx-channel = "nettx";
+ cpts-rftclk-sel = <0>;
interfaces {
gbe0: interface-0 {
diff --git a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
index b6f2682..580e2b2 100644
--- a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
@@ -157,6 +157,9 @@ netcp: netcp@26000000 {
/* enable-ale; */
tx-queue = <896>;
tx-channel = "nettx";
+ cpts-rftclk-sel = <0>;
+ cpts-ext-ts-inputs = <6>;
+ cpts-ts-comp-length;
interfaces {
gbe0: interface-0 {
--
2.10.1
^ permalink raw reply related
* [PATCH 5/6] ARM: keystone: dts: fix netcp clocks and add names
From: Grygorii Strashko @ 2016-11-28 23:04 UTC (permalink / raw)
To: David S. Miller, netdev-u79uwXL29TY76Z2rM5mHXA, Mugunthan V N,
Richard Cochran
Cc: Sekhar Nori, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Murali Karicheri, Wingman Kwok,
Grygorii Strashko
In-Reply-To: <20161128230428.6872-1-grygorii.strashko-l0cyMroinI0@public.gmane.org>
From: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
Fix the pa clock to point to the clkpa which has clock rate of 1/3 of PA
PLL clock and add clock names.
Signed-off-by: Murali Karicheri <m-karicheri2-l0cyMroinI0@public.gmane.org>
Signed-off-by: Grygorii Strashko <grygorii.strashko-l0cyMroinI0@public.gmane.org>
---
arch/arm/boot/dts/keystone-k2e-netcp.dtsi | 3 ++-
arch/arm/boot/dts/keystone-k2hk-netcp.dtsi | 3 ++-
arch/arm/boot/dts/keystone-k2l-netcp.dtsi | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi b/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
index ac990f6..ba828cb 100644
--- a/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
@@ -138,7 +138,8 @@ netcp: netcp@24000000 {
/* NetCP address range */
ranges = <0 0x24000000 0x1000000>;
- clocks = <&papllclk>, <&clkcpgmac>, <&chipclk12>;
+ clocks = <&clkpa>, <&clkcpgmac>, <&chipclk12>;
+ clock-names = "pa_clk", "ethss_clk", "cpts";
dma-coherent;
ti,navigator-dmas = <&dma_gbe 0>,
diff --git a/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi b/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
index f86d6dd..a5ac845 100644
--- a/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
@@ -155,7 +155,8 @@ netcp: netcp@2000000 {
/* NetCP address range */
ranges = <0 0x2000000 0x100000>;
- clocks = <&papllclk>, <&clkcpgmac>, <&chipclk12>;
+ clocks = <&clkpa>, <&clkcpgmac>, <&chipclk12>;
+ clock-names = "pa_clk", "ethss_clk", "cpts";
dma-coherent;
ti,navigator-dmas = <&dma_gbe 22>,
diff --git a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
index 5acbd0d..b6f2682 100644
--- a/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
+++ b/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
@@ -137,7 +137,8 @@ netcp: netcp@26000000 {
/* NetCP address range */
ranges = <0 0x26000000 0x1000000>;
- clocks = <&clkosr>, <&papllclk>, <&clkcpgmac>, <&chipclk12>;
+ clocks = <&clkpa>, <&clkcpgmac>, <&chipclk12>, <&clkosr>;
+ clock-names = "pa_clk", "ethss_clk", "cpts", "osr_clk";
dma-coherent;
ti,navigator-dmas = <&dma_gbe 0>,
--
2.10.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox