/********************************************************************** * 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/vmalloc.h> #include <linux/etherdevice.h> #include"liquidio_common.h" #include"octeon_droq.h" #include"octeon_iq.h" #include"response_manager.h" #include"octeon_device.h" #include"cn23xx_pf_device.h" #include"octeon_main.h" #include"octeon_mailbox.h"
#define RESET_NOTDONE 0 #define RESET_DONE 1
/* Change the value of SLI Packet Input Jabber Register to allow * VXLAN TSO packets which can be 64424 bytes, exceeding the * MAX_GSO_SIZE we supplied to the kernel
*/ #define CN23XX_INPUT_JABBER 64600
/* This gives the clock cycles per millisecond */
oqticks_per_us *= 1000;
/* This gives the oq ticks (1024 core clock cycles) per millisecond */
oqticks_per_us /= 1024;
/* time_intr is in microseconds. The next 2 steps gives the oq ticks * corresponding to time_intr.
*/
oqticks_per_us *= time_intr_in_us;
oqticks_per_us /= 1000;
/* As per HRM reg description, s/w can't write 0 to ENB. */ /* We need to set the RST bit, to turn the queue off. */
/* Reset the enable bit for all the 64 IQs. */ for (q_no = srn; q_no < ern; q_no++) { /* set RST bit to 1. This bit applies to both IQ and OQ */
d64 = octeon_read_csr64(oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
d64 = d64 | CN23XX_PKT_INPUT_CTL_RST;
octeon_write_csr64(oct, CN23XX_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 = srn; q_no < ern; q_no++) {
u64 reg_val = octeon_read_csr64(oct,
CN23XX_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_SLI_IQ_PKT_CONTROL64(q_no)));
} 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_SLI_IQ_PKT_CONTROL64(q_no),
READ_ONCE(reg_val));
WRITE_ONCE(reg_val, octeon_read_csr64(
oct, CN23XX_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;
}
}
/* Set the MAC_NUM and PVF_NUM in IQ_PKT_CONTROL reg * for all queues. Only PF can set these bits. * bits 29:30 indicate the MAC num. * bits 32:47 indicate the PVF num.
*/ for (q_no = 0; q_no < ern; q_no++) {
reg_val = (u64)oct->pcie_port << CN23XX_PKT_INPUT_CTL_MAC_NUM_POS;
/* 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_SLI_OQ_PKT_CONTROL(q_no), reg_val);
/* Enabling these interrupt in oct->fn_list.enable_interrupt() * routine which called after IOQ init. * Set up interrupt packet and time thresholds * for all the OQs
*/
time_threshold = cn23xx_pf_get_oq_ticks(
oct, (u32)CFG_GET_OQ_INTR_TIME(cn23xx->conf));
/** Setting the water mark level for pko back pressure **/
writeq(0x40, (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_OQ_WMARK);
/* Disabling setting OQs in reset when ring has no doorbells * enabling this will cause of head of line blocking
*/ /* Do it only for pass1.1. and pass1.2 */ if ((oct->rev_id == OCTEON_CN23XX_REV_1_0) ||
(oct->rev_id == OCTEON_CN23XX_REV_1_1))
writeq(readq((u8 *)oct->mmio[0].hw_addr +
CN23XX_SLI_GBL_CONTROL) | 0x2,
(u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_GBL_CONTROL);
/* Program the MAC(0..3)_RINFO before setting up input/output regs */
cn23xx_setup_global_mac_regs(oct);
if (cn23xx_pf_setup_global_input_regs(oct)) return -1;
cn23xx_pf_setup_global_output_regs(oct);
/* Default error timeout value should be 0x200000 to avoid host hang * when reads invalid register
*/
octeon_write_csr64(oct, CN23XX_SLI_WINDOW_CTL,
CN23XX_SLI_WINDOW_CTL_DEFAULT);
/* Set SLI_PKT_IN_JABBER to handle large VXLAN packets */
octeon_write_csr64(oct, CN23XX_SLI_PKT_IN_JABBER, CN23XX_INPUT_JABBER); return 0;
}
/* Write the start of the input queue's ring and its size */
octeon_write_csr64(oct, CN23XX_SLI_IQ_BASE_ADDR64(iq_no),
iq->base_addr_dma);
octeon_write_csr(oct, CN23XX_SLI_IQ_SIZE(iq_no), iq->max_count);
/* Store the current instruction counter (used in flush_iq * calculation)
*/
pkt_in_done = readq(iq->inst_cnt_reg);
if (oct->msix_on) { /* Set CINT_ENB to enable IQ interrupt */
writeq((pkt_in_done | CN23XX_INTR_CINT_ENB),
iq->inst_cnt_reg);
} else { /* Clear the count by writing back what we read, but don't * enable interrupts
*/
writeq(pkt_in_done, iq->inst_cnt_reg);
}
/* Get the mapped address of the pkt_sent and pkts_credit regs */
droq->pkts_sent_reg =
(u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_OQ_PKTS_SENT(oq_no);
droq->pkts_credit_reg =
(u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_OQ_PKTS_CREDIT(oq_no);
if (!oct->msix_on) { /* Enable this output queue to generate Packet Timer Interrupt
*/
reg_val =
octeon_read_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no));
reg_val |= CN23XX_PKT_OUTPUT_CTL_TENB;
octeon_write_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no),
reg_val);
for (i = 0; i < oct->sriov_info.max_vfs; i++) {
q_no = i * oct->sriov_info.rings_per_vf;
cancel_delayed_work_sync(
&oct->mbox[q_no]->mbox_poll_wk.work);
vfree(oct->mbox[q_no]);
}
for (q_no = srn; q_no < ern; q_no++) { /* Set the corresponding IQ IS_64B bit */ if (oct->io_qmask.iq64B & BIT_ULL(q_no - srn)) {
reg_val = octeon_read_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
reg_val = reg_val | CN23XX_PKT_INPUT_CTL_IS_64B;
octeon_write_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
}
/* Set the corresponding IQ ENB bit */ if (oct->io_qmask.iq & BIT_ULL(q_no - srn)) { /* IOQs are in reset by default in PEM2 mode, * clearing reset bit
*/
reg_val = octeon_read_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
if (reg_val & CN23XX_PKT_INPUT_CTL_RST) { 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));
} 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, "clearing the reset failed for qno: %u\n",
q_no); return -1;
}
}
reg_val = octeon_read_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
reg_val = reg_val | CN23XX_PKT_INPUT_CTL_RING_ENB;
octeon_write_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
}
} for (q_no = srn; q_no < ern; q_no++) {
u32 reg_val; /* Set the corresponding OQ ENB bit */ if (oct->io_qmask.oq & BIT_ULL(q_no - srn)) {
reg_val = octeon_read_csr(
oct, CN23XX_SLI_OQ_PKT_CONTROL(q_no));
reg_val = reg_val | CN23XX_PKT_OUTPUT_CTL_RING_ENB;
octeon_write_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(q_no),
reg_val);
}
} return 0;
}
/* Start the Reset for a particular ring */
WRITE_ONCE(d64, octeon_read_csr64(
oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no)));
WRITE_ONCE(d64, READ_ONCE(d64) &
(~(CN23XX_PKT_INPUT_CTL_RING_ENB)));
WRITE_ONCE(d64, READ_ONCE(d64) | CN23XX_PKT_INPUT_CTL_RST);
octeon_write_csr64(oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
READ_ONCE(d64));
/* Wait until hardware indicates that the particular IQ * is out of reset.
*/
WRITE_ONCE(d64, octeon_read_csr64(
oct, CN23XX_SLI_PKT_IOQ_RING_RST)); while (!(READ_ONCE(d64) & BIT_ULL(q_no)) && loop--) {
WRITE_ONCE(d64, octeon_read_csr64(
oct, CN23XX_SLI_PKT_IOQ_RING_RST));
schedule_timeout_uninterruptible(1);
}
/* Reset the doorbell register for this Input Queue. */
octeon_write_csr(oct, CN23XX_SLI_IQ_DOORBELL(q_no), 0xFFFFFFFF); while (octeon_read_csr64(oct, CN23XX_SLI_IQ_DOORBELL(q_no)) &&
loop--) {
schedule_timeout_uninterruptible(1);
}
}
/* Wait until hardware indicates that the particular IQ * is out of reset. Given that SLI_PKT_RING_RST is * common for both IQs and OQs
*/
WRITE_ONCE(d64, octeon_read_csr64(
oct, CN23XX_SLI_PKT_IOQ_RING_RST)); while (!(READ_ONCE(d64) & BIT_ULL(q_no)) && loop--) {
WRITE_ONCE(d64, octeon_read_csr64(
oct, CN23XX_SLI_PKT_IOQ_RING_RST));
schedule_timeout_uninterruptible(1);
}
/* Reset the doorbell register for this Output Queue. */
octeon_write_csr(oct, CN23XX_SLI_OQ_PKTS_CREDIT(q_no),
0xFFFFFFFF); while (octeon_read_csr64(oct,
CN23XX_SLI_OQ_PKTS_CREDIT(q_no)) &&
loop--) {
schedule_timeout_uninterruptible(1);
}
/* Clear the SLI_PKT(0..63)_CNTS[CNT] reg value */
WRITE_ONCE(d32, octeon_read_csr(
oct, CN23XX_SLI_OQ_PKTS_SENT(q_no)));
octeon_write_csr(oct, CN23XX_SLI_OQ_PKTS_SENT(q_no),
READ_ONCE(d32));
}
}
dev_dbg(&oct->pci_dev->dev, "In %s octeon_dev @ %p\n", __func__, oct);
if (!droq) {
dev_err(&oct->pci_dev->dev, "23XX bringup FIXME: oct pfnum:%d ioq_vector->ioq_num :%d droq is NULL\n",
oct->pf_num, ioq_vector->ioq_num); return 0;
}
pkts_sent = readq(droq->pkts_sent_reg);
/* If our device has interrupted, then proceed. Also check * for all f's if interrupt was triggered on an error * and the PCI read fails.
*/ if (!pkts_sent || (pkts_sent == 0xFFFFFFFFFFFFFFFFULL)) return ret;
/* Write count reg in sli_pkt_cnts to clear these int. */ if ((pkts_sent & CN23XX_INTR_PO_INT) ||
(pkts_sent & CN23XX_INTR_PI_INT)) { if (pkts_sent & CN23XX_INTR_PO_INT)
ret |= MSIX_PO_INT;
}
if (pkts_sent & CN23XX_INTR_PI_INT) /* We will clear the count when we update the read_index. */
ret |= MSIX_PI_INT;
/* Never need to handle msix mbox intr for pf. They arrive on the last * msix
*/ return ret;
}
/* Modulo of the new index with the IQ size will give us * the new index. The iq->reset_instr_cnt is always zero for * cn23xx, so no extra adjustments are needed.
*/
new_idx = (iq->octeon_read_index +
(u32)(last_done & CN23XX_PKT_IN_DONE_CNT_MASK)) %
iq->max_count;
/* Read Function Dependency Link reg to get the function number */ if (pci_read_config_dword(oct->pci_dev, CN23XX_PCIE_SRIOV_FDL,
&fdl_bit) == 0) {
oct->pf_num = ((fdl_bit >> CN23XX_PCIE_SRIOV_FDL_BIT_POS) &
CN23XX_PCIE_SRIOV_FDL_MASK);
} else {
ret = -EINVAL;
/* Under some virtual environments, extended PCI regs are * inaccessible, in which case the above read will have failed. * In this case, read the PF number from the * SLI_PKT0_INPUT_CONTROL reg (written by f/w)
*/
pkt0_in_ctl =
octeon_read_csr64(oct, CN23XX_SLI_IQ_PKT_CONTROL64(0));
pfnum = (pkt0_in_ctl >> CN23XX_PKT_INPUT_CTL_PF_NUM_POS) &
CN23XX_PKT_INPUT_CTL_PF_NUM_MASK;
mac = (octeon_read_csr(oct, CN23XX_SLI_MAC_NUMBER)) & 0xff;
/* Validate PF num by reading RINFO; f/w writes RINFO.trs == 1 */
d64 = octeon_read_csr64(oct,
CN23XX_SLI_PKT_MAC_RINFO64(mac, pfnum));
trs = (int)(d64 >> CN23XX_PKT_MAC_CTL_RINFO_TRS_BIT_POS) & 0xff; if (trs == 1) {
dev_err(&oct->pci_dev->dev, "OCTEON: error reading PCI cfg space pfnum, re-read %u\n",
pfnum);
oct->pf_num = pfnum;
ret = 0;
} else {
dev_err(&oct->pci_dev->dev, "OCTEON: error reading PCI cfg space pfnum; could not ascertain PF number\n");
}
}
int cn23xx_fw_loaded(struct octeon_device *oct)
{
u64 val;
/* If there's more than one active PF on this NIC, then that * implies that the NIC firmware is loaded and running. This check * prevents a rare false negative that might occur if we only relied * on checking the SCR2_BIT_FW_LOADED flag. The false negative would * happen if the PF driver sees SCR2_BIT_FW_LOADED as cleared even * though the firmware was already loaded but still booting and has yet * to set SCR2_BIT_FW_LOADED.
*/ if (atomic_read(oct->adapter_refcount) > 1) return 1;
do {
schedule_timeout_uninterruptible(1);
} while ((atomic_read(&ctx.status) == 0) && (count++ < timeout));
ret = atomic_read(&ctx.status); if (ret == 0) {
octeon_mbox_cancel(oct, 0);
dev_err(&oct->pci_dev->dev, "Unable to get stats from VF-%d, timedout\n",
vfidx); return -1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.