From d8a2efc7561df103cd6fdd850792c5befad1dcd9 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Mon, 19 Aug 2019 15:59:57 -0700 Subject: [PATCH] Add port management code to driver --- modules/mqnic/Makefile | 2 +- modules/mqnic/mqnic.h | 21 ++++++++ modules/mqnic/mqnic_hw.h | 1 + modules/mqnic/mqnic_netdev.c | 23 +++++++-- modules/mqnic/mqnic_port.c | 98 ++++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 modules/mqnic/mqnic_port.c diff --git a/modules/mqnic/Makefile b/modules/mqnic/Makefile index e76905635..a6cc7d764 100644 --- a/modules/mqnic/Makefile +++ b/modules/mqnic/Makefile @@ -1,7 +1,7 @@ # object files to build obj-m += mqnic.o -mqnic-objs += mqnic_main.o mqnic_dev.o mqnic_netdev.o mqnic_ethtool.o mqnic_i2c.o mqnic_ptp.o mqnic_tx.o mqnic_rx.o mqnic_cq.o mqnic_eq.o +mqnic-objs += mqnic_main.o mqnic_dev.o mqnic_netdev.o mqnic_port.o mqnic_ethtool.o mqnic_i2c.o mqnic_ptp.o mqnic_tx.o mqnic_rx.o mqnic_cq.o mqnic_eq.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index 092184998..60c42f2b5 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -209,6 +209,22 @@ struct mqnic_eq_ring { u8 __iomem *hw_tail_ptr; }; +struct mqnic_port { + struct device *dev; + struct net_device *ndev; + + int index; + + u32 port_id; + u32 port_features; + u32 sched_count; + u32 sched_offset; + u32 sched_stride; + u32 sched_type; + + u8 __iomem *hw_addr; +}; + struct mqnic_priv { struct device *dev; struct net_device *ndev; @@ -243,6 +259,7 @@ struct mqnic_priv { struct mqnic_cq_ring *tx_cpl_ring[MQNIC_MAX_TX_CPL_RINGS]; struct mqnic_ring *rx_ring[MQNIC_MAX_RX_RINGS]; struct mqnic_cq_ring *rx_cpl_ring[MQNIC_MAX_RX_CPL_RINGS]; + struct mqnic_port *ports[MQNIC_MAX_PORTS]; struct hwtstamp_config hwts_config; }; @@ -258,6 +275,10 @@ void mqnic_update_stats(struct net_device *ndev); int mqnic_init_netdev(struct mqnic_dev *mdev, int port, u8 __iomem *hw_addr); void mqnic_destroy_netdev(struct net_device *ndev); +// mqnic_port.c +int mqnic_create_port(struct mqnic_priv *priv, struct mqnic_port **port_ptr, int index, u8 __iomem *hw_addr); +void mqnic_destroy_port(struct mqnic_priv *priv, struct mqnic_port **port_ptr); + // mqnic_ptp.c void mqnic_register_phc(struct mqnic_dev *mdev); void mqnic_unregister_phc(struct mqnic_dev *mdev); diff --git a/modules/mqnic/mqnic_hw.h b/modules/mqnic/mqnic_hw.h index ca8a70a5d..31e350810 100644 --- a/modules/mqnic/mqnic_hw.h +++ b/modules/mqnic/mqnic_hw.h @@ -37,6 +37,7 @@ either expressed or implied, of The Regents of the University of California. #include #define MQNIC_MAX_IF 8 +#define MQNIC_MAX_PORTS 8 #define MQNIC_MAX_EVENT_RINGS 256 #define MQNIC_MAX_TX_RINGS 256 diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index 17860874d..731556bd1 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -406,6 +406,9 @@ int mqnic_init_netdev(struct mqnic_dev *mdev, int port, u8 __iomem *hw_addr) if (priv->rx_cpl_queue_count > MQNIC_MAX_RX_CPL_RINGS) priv->rx_cpl_queue_count = MQNIC_MAX_RX_CPL_RINGS; + if (priv->port_count > MQNIC_MAX_PORTS) + priv->port_count = MQNIC_MAX_PORTS; + // TODO use all queues priv->event_queue_count = 1; priv->tx_queue_count = 1; @@ -489,10 +492,14 @@ int mqnic_init_netdev(struct mqnic_dev *mdev, int port, u8 __iomem *hw_addr) } } - // scheduler queue enable - iowrite32(0xffffffff, hw_addr+priv->port_offset+0x0200); - // scheduler global enable - iowrite32(0xffffffff, hw_addr+priv->port_offset+0x0300); + for (k = 0; k < priv->port_count; k++) + { + ret = mqnic_create_port(priv, &priv->ports[k], k, hw_addr+priv->port_offset+k*priv->port_stride); + if (ret) + { + goto fail; + } + } // entry points ndev->netdev_ops = &mqnic_netdev_ops; @@ -591,6 +598,14 @@ void mqnic_destroy_netdev(struct net_device *ndev) } } + for (k = 0; k < MQNIC_MAX_PORTS; k++) + { + if (priv->ports[k]) + { + mqnic_destroy_port(priv, &priv->ports[k]); + } + } + pci_free_irq(mdev->pdev, priv->port, priv); free_netdev(ndev); } diff --git a/modules/mqnic/mqnic_port.c b/modules/mqnic/mqnic_port.c new file mode 100644 index 000000000..f96a42682 --- /dev/null +++ b/modules/mqnic/mqnic_port.c @@ -0,0 +1,98 @@ +/* + +Copyright 2019, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +#include "mqnic.h" + +int mqnic_create_port(struct mqnic_priv *priv, struct mqnic_port **port_ptr, int index, u8 __iomem *hw_addr) +{ + struct device *dev = priv->dev; + struct mqnic_port *port; + int k; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + { + dev_err(dev, "Failed to allocate port"); + return -ENOMEM; + } + + port->dev = dev; + port->ndev = priv->ndev; + + port->index = index; + + port->hw_addr = hw_addr; + + // read ID registers + port->port_id = ioread32(port->hw_addr+MQNIC_PORT_REG_PORT_ID); + dev_info(dev, "Port ID: 0x%08x", port->port_id); + + port->sched_count = ioread32(port->hw_addr+MQNIC_PORT_REG_SCHED_COUNT); + dev_info(dev, "Scheduler count: %d", port->sched_count); + port->sched_offset = ioread32(port->hw_addr+MQNIC_PORT_REG_SCHED_OFFSET); + dev_info(dev, "Scheduler offset: 0x%08x", port->sched_offset); + port->sched_stride = ioread32(port->hw_addr+MQNIC_PORT_REG_SCHED_STRIDE); + dev_info(dev, "Scheduler stride: 0x%08x", port->sched_stride); + port->sched_type = ioread32(port->hw_addr+MQNIC_PORT_REG_SCHED_TYPE); + dev_info(dev, "Scheduler type: 0x%08x", port->sched_type); + + // disable schedulers + iowrite32(0, port->hw_addr+MQNIC_PORT_REG_SCHED_ENABLE); + + // enable schedulers + iowrite32(0xffffffff, port->hw_addr+MQNIC_PORT_REG_SCHED_ENABLE); + + for (k = 0; k < 32; k++) + { + iowrite32(1, port->hw_addr+port->sched_offset+k*4); + } + + // scheduler queue enable + iowrite32(0xffffffff, port->hw_addr+port->sched_offset+0x0200); + // scheduler global enable + iowrite32(0xffffffff, port->hw_addr+port->sched_offset+0x0300); + + return 0; +} + +void mqnic_destroy_port(struct mqnic_priv *priv, struct mqnic_port **port_ptr) +{ + struct device *dev = priv->dev; + struct mqnic_port *port = *port_ptr; + *port_ptr = NULL; + + mqnic_deactivate_port(priv, port); + + kfree(port); +} +