From: Oliver Smith-Denny <osmithde@cisco.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Sesidhar Baddela <sebaddel@cisco.com>,
Gian Carlo Boffa <gcboffa@cisco.com>,
linux-scsi@vger.kernel.org, target-devel@vger.kernel.org,
linux-kernel@vger.kernel.org,
Oliver Smith-Denny <osmithde@cisco.com>
Subject: [PATCH 02/10] staging: fnic2 add resource allocation
Date: Thu, 5 Apr 2018 14:17:52 -0700 [thread overview]
Message-ID: <20180405211752.GC12584@osmithde-lnx.cisco.com> (raw)
In-Reply-To: <20180405211519.GA12584@osmithde-lnx.cisco.com>
These files contain logic for interrupts, resource allocation,
and initialization of hardware queues.
Signed-off-by: Oliver Smith-Denny <osmithde@cisco.com>
Signed-off-by: Sesidhar Baddela <sebaddel@cisco.com>
Signed-off-by: Anil Chintalapati <achintal@cisco.com>
Signed-off-by: Arulprabhu Ponnusamy <arulponn@cisco.com>
Signed-off-by: Gian Carlo Boffa <gcboffa@cisco.com>
Co-Developed-by: Arulprabhu Ponnusamy <arulponn@cisco.com>
Co-Developed-by: Gian Carlo Boffa <gcboffa@cisco.com>
Co-Developed-by: Oliver Smith-Denny <osmithde@cisco.com>
---
drivers/staging/fnic2/src/fnic2_isr.c | 324 +++++++++++++++++++++++++
drivers/staging/fnic2/src/fnic2_res.c | 430 ++++++++++++++++++++++++++++++++++
drivers/staging/fnic2/src/fnic2_res.h | 120 ++++++++++
3 files changed, 874 insertions(+)
create mode 100644 drivers/staging/fnic2/src/fnic2_isr.c
create mode 100644 drivers/staging/fnic2/src/fnic2_res.c
create mode 100644 drivers/staging/fnic2/src/fnic2_res.h
diff --git a/drivers/staging/fnic2/src/fnic2_isr.c b/drivers/staging/fnic2/src/fnic2_isr.c
new file mode 100644
index 0000000..07cf1a4
--- /dev/null
+++ b/drivers/staging/fnic2/src/fnic2_isr.c
@@ -0,0 +1,324 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright 2018 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include "vnic_dev.h"
+#include "vnic_intr.h"
+#include "vnic_stats.h"
+#include "fnic2.h"
+
+static irqreturn_t fnic2_isr_legacy(int irq, void *data)
+{
+ struct fnic2 *fnic2 = data;
+ uint32_t pba;
+ unsigned long work_done = 0;
+
+ pba = vnic_intr_legacy_pba(fnic2->legacy_pba);
+ if (!pba)
+ return IRQ_NONE;
+
+ if (pba & (1 << FNIC2_INTX_NOTIFY)) {
+ vnic_intr_return_all_credits(&fnic2->intr[FNIC2_INTX_NOTIFY]);
+ fnic2_handle_link_event(fnic2);
+ }
+
+ if (pba & (1 << FNIC2_INTX_ERR)) {
+ vnic_intr_return_all_credits(&fnic2->intr[FNIC2_INTX_ERR]);
+ fnic2_log_q_error(fnic2);
+ }
+
+ if (pba & (1 << FNIC2_INTX_WQ_RQ_COPYWQ)) {
+ work_done += fnic2_wq_copy_cmpl_handler(fnic2, -1);
+ work_done += fnic2_wq_cmpl_handler(fnic2, -1);
+ work_done += fnic2_rq_cmpl_handler(fnic2, -1);
+
+ vnic_intr_return_credits(&fnic2->intr[FNIC2_INTX_WQ_RQ_COPYWQ],
+ work_done,
+ 1 /* unmask intr */,
+ 1 /* reset intr timer */);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fnic2_isr_msi(int irq, void *data)
+{
+ struct fnic2 *fnic2 = data;
+ unsigned long work_done = 0;
+
+ work_done += fnic2_wq_copy_cmpl_handler(fnic2, -1);
+ work_done += fnic2_wq_cmpl_handler(fnic2, -1);
+ work_done += fnic2_rq_cmpl_handler(fnic2, -1);
+
+ vnic_intr_return_credits(&fnic2->intr[0],
+ work_done,
+ 1 /* unmask intr */,
+ 1 /* reset intr timer */);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fnic2_isr_msix_rq(int irq, void *data)
+{
+ struct fnic2 *fnic2 = data;
+ unsigned long rq_work_done = 0;
+
+ rq_work_done = fnic2_rq_cmpl_handler(fnic2, -1);
+ vnic_intr_return_credits(&fnic2->intr[FNIC2_MSIX_RQ],
+ rq_work_done,
+ 1 /* unmask intr */,
+ 1 /* reset intr timer */);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fnic2_isr_msix_wq(int irq, void *data)
+{
+ struct fnic2 *fnic2 = data;
+ unsigned long wq_work_done = 0;
+
+ wq_work_done = fnic2_wq_cmpl_handler(fnic2, -1);
+ vnic_intr_return_credits(&fnic2->intr[FNIC2_MSIX_WQ],
+ wq_work_done,
+ 1 /* unmask intr */,
+ 1 /* reset intr timer */);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fnic2_isr_msix_wq_copy(int irq, void *data)
+{
+ struct fnic2 *fnic2 = data;
+ unsigned long wq_copy_work_done = 0;
+
+ wq_copy_work_done = fnic2_wq_copy_cmpl_handler(fnic2, -1);
+ vnic_intr_return_credits(&fnic2->intr[FNIC2_MSIX_WQ_COPY],
+ wq_copy_work_done,
+ 1 /* unmask intr */,
+ 1 /* reset intr timer */);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fnic2_isr_msix_err_notify(int irq, void *data)
+{
+ struct fnic2 *fnic2 = data;
+
+ vnic_intr_return_all_credits(&fnic2->intr[FNIC2_MSIX_ERR_NOTIFY]);
+ fnic2_log_q_error(fnic2);
+ fnic2_handle_link_event(fnic2);
+
+ return IRQ_HANDLED;
+}
+
+void fnic2_free_intr(struct fnic2 *fnic2)
+{
+ int i;
+
+ switch (vnic_dev_get_intr_mode(fnic2->vdev)) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ case VNIC_DEV_INTR_MODE_MSI:
+ free_irq(fnic2->pdev->irq, fnic2);
+ break;
+
+ case VNIC_DEV_INTR_MODE_MSIX:
+ for (i = 0; i < ARRAY_SIZE(fnic2->msix); i++)
+ if (fnic2->msix[i].requested)
+ free_irq(fnic2->msix_entry[i].vector,
+ fnic2->msix[i].devid);
+ break;
+
+ default:
+ break;
+ }
+}
+
+int fnic2_request_intr(struct fnic2 *fnic2)
+{
+ int err = 0;
+ int i;
+
+ switch (vnic_dev_get_intr_mode(fnic2->vdev)) {
+
+ case VNIC_DEV_INTR_MODE_INTX:
+ err = request_irq(fnic2->pdev->irq, &fnic2_isr_legacy,
+ IRQF_SHARED, DRV_NAME, fnic2);
+ break;
+
+ case VNIC_DEV_INTR_MODE_MSI:
+ err = request_irq(fnic2->pdev->irq, &fnic2_isr_msi,
+ 0, fnic2->name, fnic2);
+ break;
+
+ case VNIC_DEV_INTR_MODE_MSIX:
+
+ sprintf(fnic2->msix[FNIC2_MSIX_RQ].devname,
+ "%.11s-fcs-rq", fnic2->name);
+ fnic2->msix[FNIC2_MSIX_RQ].isr = fnic2_isr_msix_rq;
+ fnic2->msix[FNIC2_MSIX_RQ].devid = fnic2;
+
+ sprintf(fnic2->msix[FNIC2_MSIX_WQ].devname,
+ "%.11s-fcs-wq", fnic2->name);
+ fnic2->msix[FNIC2_MSIX_WQ].isr = fnic2_isr_msix_wq;
+ fnic2->msix[FNIC2_MSIX_WQ].devid = fnic2;
+
+ sprintf(fnic2->msix[FNIC2_MSIX_WQ_COPY].devname,
+ "%.11s-scsi-wq", fnic2->name);
+ fnic2->msix[FNIC2_MSIX_WQ_COPY].isr = fnic2_isr_msix_wq_copy;
+ fnic2->msix[FNIC2_MSIX_WQ_COPY].devid = fnic2;
+
+ sprintf(fnic2->msix[FNIC2_MSIX_ERR_NOTIFY].devname,
+ "%.11s-err-notify", fnic2->name);
+ fnic2->msix[FNIC2_MSIX_ERR_NOTIFY].isr =
+ fnic2_isr_msix_err_notify;
+ fnic2->msix[FNIC2_MSIX_ERR_NOTIFY].devid = fnic2;
+
+ for (i = 0; i < ARRAY_SIZE(fnic2->msix); i++) {
+ err = request_irq(fnic2->msix_entry[i].vector,
+ fnic2->msix[i].isr, 0,
+ fnic2->msix[i].devname,
+ fnic2->msix[i].devid);
+ if (err) {
+ pr_err("MSIX: request_irq failed %d\n",
+ err);
+ fnic2_free_intr(fnic2);
+ break;
+ }
+ fnic2->msix[i].requested = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
+int fnic2_set_intr_mode(struct fnic2 *fnic2)
+{
+ unsigned int n = ARRAY_SIZE(fnic2->rq);
+ unsigned int m = ARRAY_SIZE(fnic2->wq);
+ unsigned int o = ARRAY_SIZE(fnic2->wq_copy);
+ unsigned int i;
+
+ /*
+ * Set interrupt mode (INTx, MSI, MSI-X) depending
+ * system capabilities.
+ *
+ * Try MSI-X first
+ *
+ * We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
+ * (last INTR is used for WQ/RQ errors and notification area)
+ */
+
+ WARN_ON(ARRAY_SIZE(fnic2->msix_entry) < n + m + o + 1);
+ for (i = 0; i < n + m + o + 1; i++)
+ fnic2->msix_entry[i].entry = i;
+
+ if (fnic2->rq_count >= n &&
+ fnic2->raw_wq_count >= m &&
+ fnic2->wq_copy_count >= o &&
+ fnic2->cq_count >= n + m + o) {
+ if (!pci_enable_msix_exact(fnic2->pdev, fnic2->msix_entry,
+ n + m + o + 1)) {
+ fnic2->rq_count = n;
+ fnic2->raw_wq_count = m;
+ fnic2->wq_copy_count = o;
+ fnic2->wq_count = m + o;
+ fnic2->cq_count = n + m + o;
+ fnic2->intr_count = n + m + o + 1;
+ fnic2->err_intr_offset = FNIC2_MSIX_ERR_NOTIFY;
+
+ pr_debug("Using MSI-X Interrupts\n");
+ vnic_dev_set_intr_mode(fnic2->vdev,
+ VNIC_DEV_INTR_MODE_MSIX);
+ return 0;
+ }
+ }
+
+ /*
+ * Next try MSI
+ * We need 1 RQ, 1 WQ, 1 WQ_COPY, 3 CQs, and 1 INTR
+ */
+ if (fnic2->rq_count >= 1 &&
+ fnic2->raw_wq_count >= 1 &&
+ fnic2->wq_copy_count >= 1 &&
+ fnic2->cq_count >= 3 &&
+ fnic2->intr_count >= 1 &&
+ !pci_enable_msi(fnic2->pdev)) {
+
+ fnic2->rq_count = 1;
+ fnic2->raw_wq_count = 1;
+ fnic2->wq_copy_count = 1;
+ fnic2->wq_count = 2;
+ fnic2->cq_count = 3;
+ fnic2->intr_count = 1;
+ fnic2->err_intr_offset = 0;
+
+ pr_debug("Using MSI Interrupts\n");
+ vnic_dev_set_intr_mode(fnic2->vdev, VNIC_DEV_INTR_MODE_MSI);
+
+ return 0;
+ }
+
+ /*
+ * Next try INTx
+ * We need 1 RQ, 1 WQ, 1 WQ_COPY, 3 CQs, and 3 INTRs
+ * 1 INTR is used for all 3 queues, 1 INTR for queue errors
+ * 1 INTR for notification area
+ */
+
+ if (fnic2->rq_count >= 1 &&
+ fnic2->raw_wq_count >= 1 &&
+ fnic2->wq_copy_count >= 1 &&
+ fnic2->cq_count >= 3 &&
+ fnic2->intr_count >= 3) {
+
+ fnic2->rq_count = 1;
+ fnic2->raw_wq_count = 1;
+ fnic2->wq_copy_count = 1;
+ fnic2->cq_count = 3;
+ fnic2->intr_count = 3;
+
+ pr_debug("Using Legacy Interrupts\n");
+ vnic_dev_set_intr_mode(fnic2->vdev, VNIC_DEV_INTR_MODE_INTX);
+
+ return 0;
+ }
+
+ vnic_dev_set_intr_mode(fnic2->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);
+
+ return -EINVAL;
+}
+
+void fnic2_clear_intr_mode(struct fnic2 *fnic2)
+{
+ switch (vnic_dev_get_intr_mode(fnic2->vdev)) {
+ case VNIC_DEV_INTR_MODE_MSIX:
+ pci_disable_msix(fnic2->pdev);
+ break;
+ case VNIC_DEV_INTR_MODE_MSI:
+ pci_disable_msi(fnic2->pdev);
+ break;
+ default:
+ break;
+ }
+
+ vnic_dev_set_intr_mode(fnic2->vdev, VNIC_DEV_INTR_MODE_INTX);
+}
diff --git a/drivers/staging/fnic2/src/fnic2_res.c b/drivers/staging/fnic2/src/fnic2_res.c
new file mode 100644
index 0000000..65b9a26
--- /dev/null
+++ b/drivers/staging/fnic2/src/fnic2_res.c
@@ -0,0 +1,430 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright 2018 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include "wq_enet_desc.h"
+#include "rq_enet_desc.h"
+#include "cq_enet_desc.h"
+#include "vnic_resource.h"
+#include "vnic_dev.h"
+#include "vnic_wq.h"
+#include "vnic_rq.h"
+#include "vnic_cq.h"
+#include "vnic_intr.h"
+#include "vnic_stats.h"
+#include "vnic_nic.h"
+#include "fnic2.h"
+
+int fnic2_get_vnic_config(struct fnic2 *fnic2)
+{
+ struct vnic_fc_config *c = &fnic2->config;
+ int err;
+
+#define GET_CONFIG(m) \
+ do { \
+ err = vnic_dev_spec(fnic2->vdev, \
+ offsetof(struct vnic_fc_config, m), \
+ sizeof(c->m), &c->m); \
+ if (err) { \
+ pr_err("Error getting %s, %d\n", #m, \
+ err); \
+ return err; \
+ } \
+ } while (0);
+
+ GET_CONFIG(node_wwn);
+ GET_CONFIG(port_wwn);
+ GET_CONFIG(wq_enet_desc_count);
+ GET_CONFIG(wq_copy_desc_count);
+ GET_CONFIG(rq_desc_count);
+ GET_CONFIG(maxdatafieldsize);
+ GET_CONFIG(ed_tov);
+ GET_CONFIG(ra_tov);
+ GET_CONFIG(intr_timer);
+ GET_CONFIG(intr_timer_type);
+ GET_CONFIG(flags);
+ GET_CONFIG(flogi_retries);
+ GET_CONFIG(flogi_timeout);
+ GET_CONFIG(plogi_retries);
+ GET_CONFIG(plogi_timeout);
+ GET_CONFIG(io_throttle_count);
+ GET_CONFIG(link_down_timeout);
+ GET_CONFIG(port_down_timeout);
+ GET_CONFIG(port_down_io_retries);
+ GET_CONFIG(luns_per_tgt);
+
+ c->wq_enet_desc_count =
+ min_t(uint32_t, VNIC_FNIC2_WQ_DESCS_MAX,
+ max_t(uint32_t, VNIC_FNIC2_WQ_DESCS_MIN,
+ c->wq_enet_desc_count));
+ c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16);
+
+ c->wq_copy_desc_count =
+ min_t(uint32_t, VNIC_FNIC2_WQ_COPY_DESCS_MAX,
+ max_t(uint32_t, VNIC_FNIC2_WQ_COPY_DESCS_MIN,
+ c->wq_copy_desc_count));
+ c->wq_copy_desc_count = ALIGN(c->wq_copy_desc_count, 16);
+
+ c->rq_desc_count =
+ min_t(uint32_t, VNIC_FNIC2_RQ_DESCS_MAX,
+ max_t(uint32_t, VNIC_FNIC2_RQ_DESCS_MIN,
+ c->rq_desc_count));
+ c->rq_desc_count = ALIGN(c->rq_desc_count, 16);
+
+ c->maxdatafieldsize =
+ min_t(uint16_t, VNIC_FNIC2_MAXDATAFIELDSIZE_MAX,
+ max_t(uint16_t, VNIC_FNIC2_MAXDATAFIELDSIZE_MIN,
+ c->maxdatafieldsize));
+ c->ed_tov =
+ min_t(uint32_t, VNIC_FNIC2_EDTOV_MAX,
+ max_t(uint32_t, VNIC_FNIC2_EDTOV_MIN,
+ c->ed_tov));
+
+ c->ra_tov =
+ min_t(uint32_t, VNIC_FNIC2_RATOV_MAX,
+ max_t(uint32_t, VNIC_FNIC2_RATOV_MIN,
+ c->ra_tov));
+
+ c->flogi_retries =
+ min_t(uint32_t, VNIC_FNIC2_FLOGI_RETRIES_MAX, c->flogi_retries);
+
+ c->flogi_timeout =
+ min_t(uint32_t, VNIC_FNIC2_FLOGI_TIMEOUT_MAX,
+ max_t(uint32_t, VNIC_FNIC2_FLOGI_TIMEOUT_MIN,
+ c->flogi_timeout));
+
+ c->plogi_retries =
+ min_t(uint32_t, VNIC_FNIC2_PLOGI_RETRIES_MAX, c->plogi_retries);
+
+ c->plogi_timeout =
+ min_t(uint32_t, VNIC_FNIC2_PLOGI_TIMEOUT_MAX,
+ max_t(uint32_t, VNIC_FNIC2_PLOGI_TIMEOUT_MIN,
+ c->plogi_timeout));
+
+ c->io_throttle_count =
+ min_t(uint32_t, VNIC_FNIC2_IO_THROTTLE_COUNT_MAX,
+ max_t(uint32_t, VNIC_FNIC2_IO_THROTTLE_COUNT_MIN,
+ c->io_throttle_count));
+
+ c->link_down_timeout =
+ min_t(uint32_t, VNIC_FNIC2_LINK_DOWN_TIMEOUT_MAX,
+ c->link_down_timeout);
+
+ c->port_down_timeout =
+ min_t(uint32_t, VNIC_FNIC2_PORT_DOWN_TIMEOUT_MAX,
+ c->port_down_timeout);
+
+ c->port_down_io_retries =
+ min_t(uint32_t, VNIC_FNIC2_PORT_DOWN_IO_RETRIES_MAX,
+ c->port_down_io_retries);
+
+ c->luns_per_tgt =
+ min_t(uint32_t, VNIC_FNIC2_LUNS_PER_TARGET_MAX,
+ max_t(uint32_t, VNIC_FNIC2_LUNS_PER_TARGET_MIN,
+ c->luns_per_tgt));
+
+ c->intr_timer = min_t(uint16_t, VNIC_INTR_TIMER_MAX, c->intr_timer);
+ c->intr_timer_type = c->intr_timer_type;
+
+ pr_info("vNIC wq/wq_copy/rq %d/%d/%d\n",
+ c->wq_enet_desc_count, c->wq_copy_desc_count,
+ c->rq_desc_count);
+ pr_info("vNIC node wwn %llx port wwn %llx\n",
+ c->node_wwn, c->port_wwn);
+ pr_info("vNIC ed_tov %d ra_tov %d\n",
+ c->ed_tov, c->ra_tov);
+ pr_info("vNIC mtu %d intr timer %d\n",
+ c->maxdatafieldsize, c->intr_timer);
+ pr_info("vNIC flags 0x%x luns per tgt %d\n",
+ c->flags, c->luns_per_tgt);
+ pr_info("vNIC flogi_retries %d flogi timeout %d\n",
+ c->flogi_retries, c->flogi_timeout);
+ pr_info("vNIC plogi retries %d plogi timeout %d\n",
+ c->plogi_retries, c->plogi_timeout);
+ pr_info("vNIC io throttle count %d link dn timeout %d\n",
+ c->io_throttle_count, c->link_down_timeout);
+ pr_info("vNIC port dn io retries %d port dn timeout %d\n",
+ c->port_down_io_retries, c->port_down_timeout);
+ return 0;
+}
+
+int fnic2_set_nic_config(struct fnic2 *fnic2, uint8_t rss_default_cpu,
+ uint8_t rss_hash_type,
+ uint8_t rss_hash_bits, uint8_t rss_base_cpu, uint8_t rss_enable,
+ uint8_t tso_ipid_split_en, uint8_t ig_vlan_strip_en)
+{
+ uint64_t a0, a1;
+ uint32_t nic_cfg;
+ int wait = 1000;
+
+ vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,
+ rss_hash_type, rss_hash_bits, rss_base_cpu,
+ rss_enable, tso_ipid_split_en, ig_vlan_strip_en);
+
+ a0 = nic_cfg;
+ a1 = 0;
+
+ return vnic_dev_cmd(fnic2->vdev, CMD_NIC_CFG, &a0, &a1, wait);
+}
+
+void fnic2_get_res_counts(struct fnic2 *fnic2)
+{
+ fnic2->wq_count = vnic_dev_get_res_count(fnic2->vdev, RES_TYPE_WQ);
+ fnic2->raw_wq_count = fnic2->wq_count - 1;
+ fnic2->wq_copy_count = fnic2->wq_count - fnic2->raw_wq_count;
+ fnic2->rq_count = vnic_dev_get_res_count(fnic2->vdev, RES_TYPE_RQ);
+ fnic2->cq_count = vnic_dev_get_res_count(fnic2->vdev, RES_TYPE_CQ);
+ fnic2->intr_count = vnic_dev_get_res_count(fnic2->vdev,
+ RES_TYPE_INTR_CTRL);
+}
+
+void fnic2_free_vnic_resources(struct fnic2 *fnic2)
+{
+ unsigned int i;
+
+ for (i = 0; i < fnic2->raw_wq_count; i++)
+ vnic_wq_free(&fnic2->wq[i]);
+
+ for (i = 0; i < fnic2->wq_copy_count; i++)
+ vnic_wq_copy_free(&fnic2->wq_copy[i]);
+
+ for (i = 0; i < fnic2->rq_count; i++)
+ vnic_rq_free(&fnic2->rq[i]);
+
+ for (i = 0; i < fnic2->cq_count; i++)
+ vnic_cq_free(&fnic2->cq[i]);
+
+ for (i = 0; i < fnic2->intr_count; i++)
+ vnic_intr_free(&fnic2->intr[i]);
+}
+
+int fnic2_alloc_vnic_resources(struct fnic2 *fnic2)
+{
+ enum vnic_dev_intr_mode intr_mode;
+ unsigned int mask_on_assertion;
+ unsigned int interrupt_offset;
+ unsigned int error_interrupt_enable;
+ unsigned int error_interrupt_offset;
+ unsigned int i, cq_index;
+ unsigned int wq_copy_cq_desc_count;
+ int err;
+
+ intr_mode = vnic_dev_get_intr_mode(fnic2->vdev);
+
+ pr_info("vNIC interrupt mode: %s\n",
+ intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" :
+ intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" :
+ intr_mode == VNIC_DEV_INTR_MODE_MSIX ?
+ "MSI-X" : "unknown");
+
+ pr_info("vNIC resources avail: wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n",
+ fnic2->wq_count, fnic2->wq_copy_count, fnic2->raw_wq_count,
+ fnic2->rq_count, fnic2->cq_count, fnic2->intr_count);
+
+ pr_info("Copy WQ desc count: %d\n",
+ fnic2->config.wq_copy_desc_count);
+
+ /* Allocate Raw WQ used for FCS frames */
+ for (i = 0; i < fnic2->raw_wq_count; i++) {
+ err = vnic_wq_alloc(fnic2->vdev, &fnic2->wq[i], i,
+ fnic2->config.wq_enet_desc_count,
+ sizeof(struct wq_enet_desc));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ /* Allocate Copy WQs used for SCSI IOs */
+ for (i = 0; i < fnic2->wq_copy_count; i++) {
+ err = vnic_wq_copy_alloc(fnic2->vdev, &fnic2->wq_copy[i],
+ (fnic2->raw_wq_count + i),
+ fnic2->config.wq_copy_desc_count,
+ sizeof(struct fcpio_host_req));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ /* RQ for receiving FCS and FCP frames */
+ for (i = 0; i < fnic2->rq_count; i++) {
+ err = vnic_rq_alloc(fnic2->vdev, &fnic2->rq[i], i,
+ fnic2->config.rq_desc_count,
+ sizeof(struct rq_enet_desc));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ /* CQ for each RQ */
+ for (i = 0; i < fnic2->rq_count; i++) {
+ cq_index = i;
+ err = vnic_cq_alloc(fnic2->vdev,
+ &fnic2->cq[cq_index], cq_index,
+ fnic2->config.rq_desc_count,
+ sizeof(struct cq_enet_rq_desc));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ /* CQ for each WQ */
+ for (i = 0; i < fnic2->raw_wq_count; i++) {
+ cq_index = fnic2->rq_count + i;
+ err = vnic_cq_alloc(fnic2->vdev, &fnic2->cq[cq_index], cq_index,
+ fnic2->config.wq_enet_desc_count,
+ sizeof(struct cq_enet_wq_desc));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ /* CQ for each COPY WQ */
+ wq_copy_cq_desc_count = (fnic2->config.wq_copy_desc_count * 3);
+ for (i = 0; i < fnic2->wq_copy_count; i++) {
+ cq_index = fnic2->raw_wq_count + fnic2->rq_count + i;
+ err = vnic_cq_alloc(fnic2->vdev, &fnic2->cq[cq_index],
+ cq_index,
+ wq_copy_cq_desc_count,
+ sizeof(struct fcpio_fw_req));
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ for (i = 0; i < fnic2->intr_count; i++) {
+ err = vnic_intr_alloc(fnic2->vdev, &fnic2->intr[i], i);
+ if (err)
+ goto err_out_cleanup;
+ }
+
+ fnic2->legacy_pba = vnic_dev_get_res(fnic2->vdev,
+ RES_TYPE_INTR_PBA_LEGACY, 0);
+
+ if (!fnic2->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) {
+ pr_info("Failed to hook legacy pba resource\n");
+ err = -ENODEV;
+ goto err_out_cleanup;
+ }
+
+ /*
+ * Init RQ/WQ resources.
+ *
+ * RQ[0 to n-1] point to CQ[0 to n-1]
+ * WQ[0 to m-1] point to CQ[n to n+m-1]
+ * WQ_COPY[0 to k-1] points to CQ[n+m to n+m+k-1]
+ *
+ * Note for copy wq we always initialize with cq_index = 0
+ *
+ * Error interrupt is not enabled for MSI.
+ */
+
+ switch (intr_mode) {
+ case VNIC_DEV_INTR_MODE_INTX:
+ case VNIC_DEV_INTR_MODE_MSIX:
+ error_interrupt_enable = 1;
+ error_interrupt_offset = fnic2->err_intr_offset;
+ break;
+ default:
+ error_interrupt_enable = 0;
+ error_interrupt_offset = 0;
+ break;
+ }
+
+ for (i = 0; i < fnic2->rq_count; i++) {
+ cq_index = i;
+ vnic_rq_init(&fnic2->rq[i],
+ cq_index,
+ error_interrupt_enable,
+ error_interrupt_offset);
+ }
+
+ for (i = 0; i < fnic2->raw_wq_count; i++) {
+ cq_index = i + fnic2->rq_count;
+ vnic_wq_init(&fnic2->wq[i],
+ cq_index,
+ error_interrupt_enable,
+ error_interrupt_offset);
+ }
+
+ for (i = 0; i < fnic2->wq_copy_count; i++) {
+ vnic_wq_copy_init(&fnic2->wq_copy[i],
+ 0 /* cq_index 0 - always */,
+ error_interrupt_enable,
+ error_interrupt_offset);
+ }
+
+ for (i = 0; i < fnic2->cq_count; i++) {
+
+ switch (intr_mode) {
+ case VNIC_DEV_INTR_MODE_MSIX:
+ interrupt_offset = i;
+ break;
+ default:
+ interrupt_offset = 0;
+ break;
+ }
+
+ vnic_cq_init(&fnic2->cq[i],
+ 0 /* flow_control_enable */,
+ 1 /* color_enable */,
+ 0 /* cq_head */,
+ 0 /* cq_tail */,
+ 1 /* cq_tail_color */,
+ 1 /* interrupt_enable */,
+ 1 /* cq_entry_enable */,
+ 0 /* cq_message_enable */,
+ interrupt_offset,
+ 0 /* cq_message_addr */);
+ }
+
+ /*
+ * Init INTR resources
+ *
+ * mask_on_assertion is not used for INTx due to the level-
+ * triggered nature of INTx
+ */
+
+ switch (intr_mode) {
+ case VNIC_DEV_INTR_MODE_MSI:
+ case VNIC_DEV_INTR_MODE_MSIX:
+ mask_on_assertion = 1;
+ break;
+ default:
+ mask_on_assertion = 0;
+ break;
+ }
+
+ for (i = 0; i < fnic2->intr_count; i++) {
+ vnic_intr_init(&fnic2->intr[i],
+ fnic2->config.intr_timer,
+ fnic2->config.intr_timer_type,
+ mask_on_assertion);
+ }
+
+ /* init the stats memory by making the first call here */
+ err = vnic_dev_stats_dump(fnic2->vdev, &fnic2->stats);
+ if (err) {
+ pr_info("vnic_dev_stats_dump failed - 0x%x\n", err);
+ goto err_out_cleanup;
+ }
+
+ /* Clear LIF stats */
+ vnic_dev_stats_clear(fnic2->vdev);
+
+ return 0;
+
+err_out_cleanup:
+ fnic2_free_vnic_resources(fnic2);
+
+ return err;
+}
diff --git a/drivers/staging/fnic2/src/fnic2_res.h b/drivers/staging/fnic2/src/fnic2_res.h
new file mode 100644
index 0000000..dab106c
--- /dev/null
+++ b/drivers/staging/fnic2/src/fnic2_res.h
@@ -0,0 +1,120 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright 2017 Cisco Systems, Inc. All rights reserved.
+ */
+#ifndef _FNIC2_RES_H_
+#define _FNIC2_RES_H_
+
+#include "wq_enet_desc.h"
+#include "rq_enet_desc.h"
+#include "vnic_wq.h"
+#include "vnic_rq.h"
+#include "fcpio.h"
+#include "vnic_wq_copy.h"
+#include "vnic_cq_copy.h"
+#include "fnic2_fdls.h"
+
+static inline void fnic2_queue_wq_desc(struct vnic_wq *wq,
+ void *os_buf, dma_addr_t dma_addr,
+ unsigned int len, unsigned int fc_eof,
+ int vlan_tag_insert,
+ unsigned int vlan_tag,
+ int cq_entry, int sop, int eop)
+{
+ struct wq_enet_desc *desc = vnic_wq_next_desc(wq);
+
+ wq_enet_desc_enc(desc,
+ (uint64_t)dma_addr | VNIC_PADDR_TARGET,
+ (uint16_t)len,
+ 0, /* mss_or_csum_offset */
+ (uint16_t)fc_eof,
+ 0, /* offload_mode */
+ (uint8_t)eop, (uint8_t)cq_entry,
+ 1, /* fcoe_encap */
+ (uint8_t)vlan_tag_insert,
+ (uint16_t)vlan_tag,
+ 0 /* loopback */);
+
+ vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop);
+}
+
+static inline void fnic2_queue_wq_copy_desc_flogi_reg(struct vnic_wq_copy *wq,
+ uint32_t fcpio_tag, uint8_t format,
+ uint32_t s_id, uint8_t *gw_mac)
+{
+ struct fcpio_host_req *desc = vnic_wq_copy_next_desc(wq);
+
+ desc->hdr.type = FCPIO_FLOGI_REG; /* enum fcpio_type */
+ desc->hdr.status = 0; /* header status entry */
+ desc->hdr._resvd = 0; /* reserved */
+ desc->hdr.fcpio_tag = fcpio_tag; /* id for this request */
+
+ desc->u.flogi_reg.format = format;
+ desc->u.flogi_reg._resvd = 0;
+ hton24(desc->u.flogi_reg.s_id, s_id);
+ memcpy(desc->u.flogi_reg.gateway_mac, gw_mac, ETH_ALEN);
+
+ vnic_wq_copy_post(wq);
+}
+
+static inline void fnic2_queue_wq_copy_desc_fip_reg(struct vnic_wq_copy *wq,
+ uint32_t fcpio_tag, uint32_t s_id,
+ uint8_t *fcf_mac, uint8_t *ha_mac,
+ uint32_t r_a_tov, uint32_t e_d_tov)
+{
+ struct fcpio_host_req *desc = vnic_wq_copy_next_desc(wq);
+
+ desc->hdr.type = FCPIO_FLOGI_FIP_REG; /* enum fcpio_type */
+ desc->hdr.status = 0; /* header status entry */
+ desc->hdr._resvd = 0; /* reserved */
+ desc->hdr.fcpio_tag = fcpio_tag; /* id for this request */
+
+ desc->u.flogi_fip_reg._resvd0 = 0;
+ hton24(desc->u.flogi_fip_reg.s_id, s_id);
+ memcpy(desc->u.flogi_fip_reg.fcf_mac, fcf_mac, ETH_ALEN);
+ desc->u.flogi_fip_reg._resvd1 = 0;
+ desc->u.flogi_fip_reg.r_a_tov = r_a_tov;
+ desc->u.flogi_fip_reg.e_d_tov = e_d_tov;
+ memcpy(desc->u.flogi_fip_reg.ha_mac, ha_mac, ETH_ALEN);
+ desc->u.flogi_fip_reg._resvd2 = 0;
+
+ vnic_wq_copy_post(wq);
+}
+
+static inline void fnic2_queue_wq_copy_desc_fw_reset(struct vnic_wq_copy *wq,
+ uint32_t fcpio_tag)
+{
+ struct fcpio_host_req *desc = vnic_wq_copy_next_desc(wq);
+
+ desc->hdr.type = FCPIO_RESET; /* enum fcpio_type */
+ desc->hdr.status = 0; /* header status entry */
+ desc->hdr._resvd = 0; /* reserved */
+ desc->hdr.fcpio_tag = fcpio_tag; /* id for this request */
+
+ vnic_wq_copy_post(wq);
+}
+
+static inline void fnic2_queue_rq_desc(struct vnic_rq *rq,
+ void *os_buf, dma_addr_t dma_addr,
+ uint16_t len)
+{
+ struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
+
+ rq_enet_desc_enc(desc,
+ (uint64_t)dma_addr | VNIC_PADDR_TARGET,
+ RQ_ENET_TYPE_ONLY_SOP,
+ (uint16_t)len);
+
+ vnic_rq_post(rq, os_buf, 0, dma_addr, len);
+}
+
+int fnic2_get_vnic_config(struct fnic2 *);
+int fnic2_alloc_vnic_resources(struct fnic2 *);
+void fnic2_free_vnic_resources(struct fnic2 *);
+void fnic2_get_res_counts(struct fnic2 *);
+int fnic2_set_nic_config(struct fnic2 *fnic2, uint8_t rss_default_cpu,
+ uint8_t rss_hash_type, uint8_t rss_hash_bits, uint8_t rss_base_cpu,
+ uint8_t rss_enable, uint8_t tso_ipid_split_en,
+ uint8_t ig_vlan_strip_en);
+
+#endif /* _FNIC2_RES_H_ */
--
1.8.3.1
next prev parent reply other threads:[~2018-04-05 21:17 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-05 21:15 [PATCH 00/10] staging: fnic2 Driver Introduction Oliver Smith-Denny
2018-04-05 21:16 ` [PATCH 01/10] staging: fnic2 add initialization Oliver Smith-Denny
2018-04-06 5:07 ` Greg Kroah-Hartman
2018-04-06 22:00 ` Oliver Smith-Denny
2018-04-07 6:09 ` Greg Kroah-Hartman
2018-04-09 19:49 ` Oliver Smith-Denny
2018-04-09 20:57 ` Martin K. Petersen
2018-04-12 17:32 ` Oliver Smith-Denny
2018-04-05 21:17 ` Oliver Smith-Denny [this message]
2018-04-06 5:08 ` [PATCH 02/10] staging: fnic2 add resource allocation Greg Kroah-Hartman
2018-04-05 21:18 ` [PATCH 03/10] staging: fnic2 add fip handling Oliver Smith-Denny
2018-04-06 5:08 ` Greg Kroah-Hartman
2018-04-05 21:19 ` [PATCH 04/10] staging: fnic2 add fdls system Oliver Smith-Denny
2018-04-05 21:20 ` [PATCH 05/10] staging: fnic2 add LIO interface Oliver Smith-Denny
2018-04-05 21:21 ` [PATCH 06/10] staging: fnic2 add main frame processing Oliver Smith-Denny
2018-04-05 21:21 ` [PATCH 07/10] staging: fnic2 add queue descriptors Oliver Smith-Denny
2018-04-05 21:22 ` [PATCH 08/10] staging: fnic2 add vnic queue interface Oliver Smith-Denny
2018-04-05 21:23 ` [PATCH 09/10] staging: fnic2 add vnic handling Oliver Smith-Denny
2018-04-05 21:24 ` [PATCH 10/10] staging: fnic2 add build and config Oliver Smith-Denny
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180405211752.GC12584@osmithde-lnx.cisco.com \
--to=osmithde@cisco.com \
--cc=gcboffa@cisco.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=sebaddel@cisco.com \
--cc=target-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®