summaryrefslogtreecommitdiff
path: root/gpxe/src/drivers/net/mtnic.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
committerH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
commitf2f897a1762fab84d2905f32b1c15dd7b42abb56 (patch)
treea38f51d3f1fcbf44afddb4736d549c12eaf491be /gpxe/src/drivers/net/mtnic.c
parent72d2959272b4616f17a97667e6dfa9d06bf109a3 (diff)
downloadsyslinux-f2f897a1762fab84d2905f32b1c15dd7b42abb56.tar.gz
gpxe: delete long since obsolete snapshot of gPXE
gPXE has been deprecated in favor of iPXE for many, many years now. It is much better than users get it directly from the iPXE project, since we should no longer need any special modifications for Syslinux use. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'gpxe/src/drivers/net/mtnic.c')
-rw-r--r--gpxe/src/drivers/net/mtnic.c1853
1 files changed, 0 insertions, 1853 deletions
diff --git a/gpxe/src/drivers/net/mtnic.c b/gpxe/src/drivers/net/mtnic.c
deleted file mode 100644
index d7ee8d2b..00000000
--- a/gpxe/src/drivers/net/mtnic.c
+++ /dev/null
@@ -1,1853 +0,0 @@
-/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * - 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.
- *
- * 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.
- *
- */
-
-FILE_LICENCE ( GPL2_ONLY );
-
-#include <strings.h>
-#include <errno.h>
-#include <gpxe/malloc.h>
-#include <gpxe/umalloc.h>
-#include <byteswap.h>
-#include <unistd.h>
-#include <gpxe/io.h>
-#include <gpxe/pci.h>
-#include <gpxe/ethernet.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/iobuf.h>
-#include "mtnic.h"
-
-
-/*
-
-
- mtnic.c - gPXE driver for Mellanox 10Gig ConnectX EN
-
-
-*/
-
-
-
-/********************************************************************
-*
-* MTNIC allocation functions
-*
-*********************************************************************/
-/**
-* mtnic_alloc_aligned
-*
-* @v unsigned int size size
-* @v void **va virtual address
-* @v u32 *pa physical address
-* @v u32 aligment aligment
-*
-* Function allocate aligned buffer and put it's virtual address in 'va'
-* and it's physical aligned address in 'pa'
-*/
-static int
-mtnic_alloc_aligned(unsigned int size, void **va, unsigned long *pa, unsigned int alignment)
-{
- *va = alloc_memblock(size, alignment);
- if (!*va) {
- return -EADDRINUSE;
- }
- *pa = (u32)virt_to_bus(*va);
- return 0;
-}
-
-
-
-/**
- *
- * mtnic alloc command interface
- *
- */
-static int
-mtnic_alloc_cmdif(struct mtnic *mtnic)
-{
- u32 bar = mtnic_pci_dev.dev.bar[0];
-
- mtnic->hcr = ioremap(bar + MTNIC_HCR_BASE, MTNIC_HCR_SIZE);
- if ( !mtnic->hcr ) {
- DBG("Couldn't map command register\n");
- return -EADDRINUSE;
- }
- mtnic_alloc_aligned(PAGE_SIZE, (void *)&mtnic->cmd.buf, &mtnic->cmd.mapping, PAGE_SIZE);
- if ( !mtnic->cmd.buf ) {
- DBG("Error in allocating buffer for command interface\n");
- return -EADDRINUSE;
- }
- return 0;
-}
-
-/**
- * Free RX io buffers
- */
-static void
-mtnic_free_io_buffers(struct mtnic_ring *ring)
-{
- int index;
-
- for (; ring->cons <= ring->prod; ++ring->cons) {
- index = ring->cons & ring->size_mask;
- if ( ring->iobuf[index] ) {
- free_iob(ring->iobuf[index]);
- }
- }
-}
-
-
-
-/**
- *
- * mtnic alloc and attach io buffers
- *
- */
-static int
-mtnic_alloc_iobuf(struct mtnic_port *priv, struct mtnic_ring *ring,
- unsigned int size)
-{
- struct mtnic_rx_desc *rx_desc_ptr = ring->buf;
- u32 index;
-
- while ((u32)(ring->prod - ring->cons) < UNITS_BUFFER_SIZE) {
- index = ring->prod & ring->size_mask;
- ring->iobuf[index] = alloc_iob(size);
- if (!ring->iobuf[index]) {
- if (ring->prod <= (ring->cons + 1)) {
- DBG ( "Dropping packet, buffer is full\n" );
- }
- break;
- }
-
- /* Attach io_buffer to descriptor */
- rx_desc_ptr = ring->buf +
- (sizeof(struct mtnic_rx_desc) * index);
- rx_desc_ptr->data.count = cpu_to_be32(size);
- rx_desc_ptr->data.mem_type = priv->mtnic->fw.mem_type_snoop_be;
- rx_desc_ptr->data.addr_l = cpu_to_be32(
- virt_to_bus(ring->iobuf[index]->data));
-
- ++ ring->prod;
- }
-
- /* Update RX producer index (PI) */
- ring->db->count = cpu_to_be32(ring->prod & 0xffff);
- return 0;
-}
-
-
-/**
- * mtnic alloc ring
- *
- * Alloc and configure TX or RX ring
- *
- */
-static int
-mtnic_alloc_ring(struct mtnic_port *priv, struct mtnic_ring *ring,
- u32 size, u16 stride, u16 cq, u8 is_rx)
-{
- unsigned int i;
- int err;
- struct mtnic_rx_desc *rx_desc;
- struct mtnic_tx_desc *tx_desc;
-
- ring->size = size; /* Number of descriptors */
- ring->size_mask = size - 1;
- ring->stride = stride; /* Size of each entry */
- ring->cq = cq; /* CQ number associated with this ring */
- ring->cons = 0;
- ring->prod = 0;
-
- /* Alloc descriptors buffer */
- ring->buf_size = ring->size * ((is_rx) ? sizeof(struct mtnic_rx_desc) :
- sizeof(struct mtnic_tx_desc));
- err = mtnic_alloc_aligned(ring->buf_size, (void *)&ring->buf,
- &ring->dma, PAGE_SIZE);
- if (err) {
- DBG("Failed allocating descriptor ring sizeof %x\n",
- ring->buf_size);
- return -EADDRINUSE;
- }
- memset(ring->buf, 0, ring->buf_size);
-
- DBG("Allocated %s ring (addr:%p) - buf:%p size:%x"
- "buf_size:%x dma:%lx\n",
- is_rx ? "Rx" : "Tx", ring, ring->buf, ring->size,
- ring->buf_size, ring->dma);
-
-
- if (is_rx) { /* RX ring */
- /* Alloc doorbell */
- err = mtnic_alloc_aligned(sizeof(struct mtnic_cq_db_record),
- (void *)&ring->db, &ring->db_dma, 32);
- if (err) {
- DBG("Failed allocating Rx ring doorbell record\n");
- free_memblock(ring->buf, ring->buf_size);
- return -EADDRINUSE;
- }
-
- /* ==- Configure Descriptor -== */
- /* Init ctrl seg of rx desc */
- for (i = 0; i < UNITS_BUFFER_SIZE; ++i) {
- rx_desc = ring->buf +
- (sizeof(struct mtnic_rx_desc) * i);
- /* Pre-link descriptor */
- rx_desc->next = cpu_to_be16(i + 1);
- }
- /*The last ctrl descriptor is '0' and points to the first one*/
-
- /* Alloc IO_BUFFERS */
- err = mtnic_alloc_iobuf ( priv, ring, DEF_IOBUF_SIZE );
- if (err) {
- DBG("ERROR Allocating io buffer\n");
- free_memblock(ring->buf, ring->buf_size);
- return -EADDRINUSE;
- }
-
- } else { /* TX ring */
- /* Set initial ownership of all Tx Desc' to SW (1) */
- for (i = 0; i < ring->size; i++) {
- tx_desc = ring->buf + ring->stride * i;
- tx_desc->ctrl.op_own = cpu_to_be32(MTNIC_BIT_DESC_OWN);
- }
- /* DB */
- ring->db_offset = cpu_to_be32(
- ((u32) priv->mtnic->fw.tx_offset[priv->port]) << 8);
-
- /* Map Tx+CQ doorbells */
- DBG("Mapping TxCQ doorbell at offset:0x%x\n",
- priv->mtnic->fw.txcq_db_offset);
- ring->txcq_db = ioremap(mtnic_pci_dev.dev.bar[2] +
- priv->mtnic->fw.txcq_db_offset, PAGE_SIZE);
- if (!ring->txcq_db) {
- DBG("Couldn't map txcq doorbell, aborting...\n");
- free_memblock(ring->buf, ring->buf_size);
- return -EADDRINUSE;
- }
- }
-
- return 0;
-}
-
-
-
-/**
- * mtnic alloc CQ
- *
- * Alloc and configure CQ.
- *
- */
-static int
-mtnic_alloc_cq(struct net_device *dev, int num, struct mtnic_cq *cq,
- u8 is_rx, u32 size, u32 offset_ind)
-{
- int err ;
- unsigned int i;
-
- cq->num = num;
- cq->dev = dev;
- cq->size = size;
- cq->last = 0;
- cq->is_rx = is_rx;
- cq->offset_ind = offset_ind;
-
- /* Alloc doorbell */
- err = mtnic_alloc_aligned(sizeof(struct mtnic_cq_db_record),
- (void *)&cq->db, &cq->db_dma, 32);
- if (err) {
- DBG("Failed allocating CQ doorbell record\n");
- return -EADDRINUSE;
- }
- memset(cq->db, 0, sizeof(struct mtnic_cq_db_record));
-
- /* Alloc CQEs buffer */
- cq->buf_size = size * sizeof(struct mtnic_cqe);
- err = mtnic_alloc_aligned(cq->buf_size,
- (void *)&cq->buf, &cq->dma, PAGE_SIZE);
- if (err) {
- DBG("Failed allocating CQ buffer\n");
- free_memblock(cq->db, sizeof(struct mtnic_cq_db_record));
- return -EADDRINUSE;
- }
- memset(cq->buf, 0, cq->buf_size);
- DBG("Allocated CQ (addr:%p) - size:%x buf:%p buf_size:%x "
- "dma:%lx db:%p db_dma:%lx\n"
- "cqn offset:%x \n", cq, cq->size, cq->buf,
- cq->buf_size, cq->dma, cq->db,
- cq->db_dma, offset_ind);
-
-
- /* Set ownership of all CQEs to HW */
- DBG("Setting HW ownership for CQ:%d\n", num);
- for (i = 0; i < cq->size; i++) {
- /* Initial HW ownership is 1 */
- cq->buf[i].op_tr_own = MTNIC_BIT_CQ_OWN;
- }
- return 0;
-}
-
-
-
-/**
- * mtnic_alloc_resources
- *
- * Alloc and configure CQs, Tx, Rx
- */
-unsigned int
-mtnic_alloc_resources(struct net_device *dev)
-{
- struct mtnic_port *priv = netdev_priv(dev);
- int err;
- int cq_ind = 0;
- int cq_offset = priv->mtnic->fw.cq_offset;
-
- /* Alloc 1st CQ */
- err = mtnic_alloc_cq(dev, cq_ind, &priv->cq[cq_ind], 1 /* RX */,
- UNITS_BUFFER_SIZE, cq_offset + cq_ind);
- if (err) {
- DBG("Failed allocating Rx CQ\n");
- return -EADDRINUSE;
- }
-
-
- /* Alloc RX */
- err = mtnic_alloc_ring(priv, &priv->rx_ring, UNITS_BUFFER_SIZE,
- sizeof(struct mtnic_rx_desc), cq_ind, /* RX */1);
- if (err) {
- DBG("Failed allocating Rx Ring\n");
- goto cq0_error;
- }
-
-
- ++cq_ind;
-
- /* alloc 2nd CQ */
- err = mtnic_alloc_cq(dev, cq_ind, &priv->cq[cq_ind], 0 /* TX */,
- UNITS_BUFFER_SIZE, cq_offset + cq_ind);
- if (err) {
- DBG("Failed allocating Tx CQ\n");
- goto rx_error;
- }
-
- /* Alloc TX */
- err = mtnic_alloc_ring(priv, &priv->tx_ring, UNITS_BUFFER_SIZE,
- sizeof(struct mtnic_tx_desc), cq_ind, /* TX */ 0);
- if (err) {
- DBG("Failed allocating Tx ring\n");
- goto cq1_error;
- }
-
- return 0;
-
-cq1_error:
- free_memblock(priv->cq[1].buf, priv->cq[1].buf_size);
- free_memblock(priv->cq[1].db, sizeof(struct mtnic_cq_db_record));
-
-rx_error:
- free_memblock(priv->rx_ring.buf, priv->rx_ring.buf_size);
- free_memblock(priv->rx_ring.db, sizeof(struct mtnic_cq_db_record));
- mtnic_free_io_buffers(&priv->rx_ring);
-cq0_error:
- free_memblock(priv->cq[0].buf, priv->cq[0].buf_size);
- free_memblock(priv->cq[0].db, sizeof(struct mtnic_cq_db_record));
-
- return -EADDRINUSE;
-}
-
-
-/**
- * mtnic alloc_eq
- *
- * Note: EQ is not used by the driver but must be allocated
- */
-static int
-mtnic_alloc_eq(struct mtnic *mtnic)
-{
- int err;
- unsigned int i;
- struct mtnic_eqe *eqe_desc = NULL;
-
- /* Allocating doorbell */
- mtnic->eq_db = ioremap(mtnic_pci_dev.dev.bar[2] +
- mtnic->fw.eq_db_offset, sizeof(u32));
- if (!mtnic->eq_db) {
- DBG("Couldn't map EQ doorbell, aborting...\n");
- return -EADDRINUSE;
- }
-
- /* Allocating buffer */
- mtnic->eq.size = NUM_EQES;
- mtnic->eq.buf_size = mtnic->eq.size * sizeof(struct mtnic_eqe);
- err = mtnic_alloc_aligned(mtnic->eq.buf_size, (void *)&mtnic->eq.buf,
- &mtnic->eq.dma, PAGE_SIZE);
- if (err) {
- DBG("Failed allocating EQ buffer\n");
- iounmap(mtnic->eq_db);
- return -EADDRINUSE;
- }
- memset(mtnic->eq.buf, 0, mtnic->eq.buf_size);
-
- for (i = 0; i < mtnic->eq.size; i++)
- eqe_desc = mtnic->eq.buf + (sizeof(struct mtnic_eqe) * i);
- eqe_desc->own |= MTNIC_BIT_EQE_OWN;
-
- mdelay(20);
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-/********************************************************************
-*
-* Mtnic commands functions
-* -=-=-=-=-=-=-=-=-=-=-=-=
-*
-*
-*
-*********************************************************************/
-static inline int
-cmdif_go_bit(struct mtnic *mtnic)
-{
- struct mtnic_if_cmd_reg *hcr = mtnic->hcr;
- u32 status;
- int i;
-
- for (i = 0; i < TBIT_RETRIES; i++) {
- status = be32_to_cpu(readl(&hcr->status_go_opcode));
- if ((status & MTNIC_BC_MASK(MTNIC_MASK_CMD_REG_T_BIT)) ==
- (mtnic->cmd.tbit << MTNIC_BC_OFF(MTNIC_MASK_CMD_REG_T_BIT))) {
- /* Read expected t-bit - now return go-bit value */
- return status & MTNIC_BC_MASK(MTNIC_MASK_CMD_REG_GO_BIT);
- }
- }
-
- DBG("Invalid tbit after %d retries!\n", TBIT_RETRIES);
- return -EBUSY; /* Return busy... */
-}
-
-/* Base Command interface */
-static int
-mtnic_cmd(struct mtnic *mtnic, void *in_imm,
- void *out_imm, u32 in_modifier, u16 op)
-{
-
- struct mtnic_if_cmd_reg *hcr = mtnic->hcr;
- int err = 0;
- u32 out_param_h = 0;
- u32 out_param_l = 0;
- u32 in_param_h = 0;
- u32 in_param_l = 0;
-
-
- static u16 token = 0x8000;
- u32 status;
- unsigned int timeout = 0;
-
- token++;
-
- if ( cmdif_go_bit ( mtnic ) ) {
- DBG("GO BIT BUSY:%p.\n", hcr + 6);
- err = -EBUSY;
- goto out;
- }
- if (in_imm) {
- in_param_h = *((u32*)in_imm);
- in_param_l = *((u32*)in_imm + 1);
- } else {
- in_param_l = cpu_to_be32(mtnic->cmd.mapping);
- }
- out_param_l = cpu_to_be32(mtnic->cmd.mapping);
-
- /* writing to MCR */
- writel(in_param_h, &hcr->in_param_h);
- writel(in_param_l, &hcr->in_param_l);
- writel((u32) cpu_to_be32(in_modifier), &hcr->input_modifier);
- writel(out_param_h, &hcr->out_param_h);
- writel(out_param_l, &hcr->out_param_l);
- writel((u32)cpu_to_be32(token << 16), &hcr->token);
- wmb();
-
- /* flip toggle bit before each write to the HCR */
- mtnic->cmd.tbit = !mtnic->cmd.tbit;
- writel( ( u32 )
- cpu_to_be32(MTNIC_BC_MASK(MTNIC_MASK_CMD_REG_GO_BIT) |
- ( mtnic->cmd.tbit << MTNIC_BC_OFF ( MTNIC_MASK_CMD_REG_T_BIT ) ) | op ),
- &hcr->status_go_opcode);
-
- while ( cmdif_go_bit ( mtnic ) && ( timeout <= GO_BIT_TIMEOUT ) ) {
- mdelay ( 1 );
- ++timeout;
- }
-
- if ( cmdif_go_bit ( mtnic ) ) {
- DBG("Command opcode:0x%x token:0x%x TIMEOUT.\n", op, token);
- err = -EBUSY;
- goto out;
- }
-
- if (out_imm) {
- *((u32 *)out_imm) = readl(&hcr->out_param_h);
- *((u32 *)out_imm + 1) = readl(&hcr->out_param_l);
- }
-
- status = be32_to_cpu((u32)readl(&hcr->status_go_opcode)) >> 24;
-
- if (status) {
- DBG("Command opcode:0x%x token:0x%x returned:0x%x\n",
- op, token, status);
- return status;
- }
-
-out:
- return err;
-}
-
-/* MAP PAGES wrapper */
-static int
-mtnic_map_cmd(struct mtnic *mtnic, u16 op, struct mtnic_pages pages)
-{
- unsigned int j;
- u32 addr;
- unsigned int len;
- u32 *page_arr = mtnic->cmd.buf;
- int nent = 0;
- int err = 0;
-
- memset(page_arr, 0, PAGE_SIZE);
-
- len = PAGE_SIZE * pages.num;
- pages.buf = (u32 *)umalloc(PAGE_SIZE * (pages.num + 1));
- addr = PAGE_SIZE + ((virt_to_bus(pages.buf) & 0xfffff000) + PAGE_SIZE);
- DBG("Mapping pages: size: %x address: %p\n", pages.num, pages.buf);
-
- if (addr & (PAGE_MASK)) {
- DBG("Got FW area not aligned to %d (%llx/%x)\n",
- PAGE_SIZE, (u64) addr, len);
- return -EADDRINUSE;
- }
-
- /* Function maps each PAGE seperately */
- for (j = 0; j < len; j+= PAGE_SIZE) {
- page_arr[nent * 4 + 3] = cpu_to_be32(addr + j);
- if (++nent == MTNIC_MAILBOX_SIZE / 16) {
- err = mtnic_cmd(mtnic, NULL, NULL, nent, op);
- if (err)
- return -EIO;
- nent = 0;
- }
- }
-
- if (nent) {
- err = mtnic_cmd(mtnic, NULL, NULL, nent, op);
- }
- return err;
-}
-
-
-
-/*
- * Query FW
- */
-static int
-mtnic_QUERY_FW ( struct mtnic *mtnic )
-{
- int err;
- struct mtnic_if_query_fw_out_mbox *cmd = mtnic->cmd.buf;
-
- err = mtnic_cmd(mtnic, NULL, NULL, 0, MTNIC_IF_CMD_QUERY_FW);
- if (err)
- return -EIO;
-
- /* Get FW and interface versions */
- mtnic->fw_ver = ((u64) be16_to_cpu(cmd->rev_maj) << 32) |
- ((u64) be16_to_cpu(cmd->rev_min) << 16) |
- (u64) be16_to_cpu(cmd->rev_smin);
- mtnic->fw.ifc_rev = be16_to_cpu(cmd->ifc_rev);
-
- /* Get offset for internal error reports (debug) */
- mtnic->fw.err_buf.offset = be64_to_cpu(cmd->err_buf_start);
- mtnic->fw.err_buf.size = be32_to_cpu(cmd->err_buf_size);
-
- DBG("Error buf offset is %llx\n", mtnic->fw.err_buf.offset);
-
- /* Get number of required FW (4k) pages */
- mtnic->fw.fw_pages.num = be16_to_cpu(cmd->fw_pages);
-
- return 0;
-}
-
-
-static int
-mtnic_OPEN_NIC(struct mtnic *mtnic)
-{
- struct mtnic_if_open_nic_in_mbox *open_nic = mtnic->cmd.buf;
- u32 extra_pages[2] = {0};
- int err;
-
- memset(open_nic, 0, sizeof *open_nic);
-
- /* port 1 */
- open_nic->log_rx_p1 = 0;
- open_nic->log_cq_p1 = 1;
-
- open_nic->log_tx_p1 = 0;
- open_nic->steer_p1 = MTNIC_IF_STEER_RSS;
- /* MAC + VLAN - leave reserved */
-
- /* port 2 */
- open_nic->log_rx_p2 = 0;
- open_nic->log_cq_p2 = 1;
-
- open_nic->log_tx_p2 = 0;
- open_nic->steer_p2 = MTNIC_IF_STEER_RSS;
- /* MAC + VLAN - leave reserved */
-
- err = mtnic_cmd(mtnic, NULL, extra_pages, 0, MTNIC_IF_CMD_OPEN_NIC);
-
- mtnic->fw.extra_pages.num = be32_to_cpu(*(extra_pages+1));
- DBG("Extra pages num is %x\n", mtnic->fw.extra_pages.num);
- return err;
-}
-
-static int
-mtnic_CONFIG_RX(struct mtnic *mtnic)
-{
- struct mtnic_if_config_rx_in_imm config_rx;
-
- memset(&config_rx, 0, sizeof config_rx);
- return mtnic_cmd(mtnic, &config_rx, NULL, 0, MTNIC_IF_CMD_CONFIG_RX);
-}
-
-static int
-mtnic_CONFIG_TX(struct mtnic *mtnic)
-{
- struct mtnic_if_config_send_in_imm config_tx;
-
- config_tx.enph_gpf = 0;
- return mtnic_cmd(mtnic, &config_tx, NULL, 0, MTNIC_IF_CMD_CONFIG_TX);
-}
-
-static int
-mtnic_HEART_BEAT(struct mtnic_port *priv, u32 *link_state)
-{
- struct mtnic_if_heart_beat_out_imm heart_beat;
-
- int err;
- u32 flags;
- err = mtnic_cmd(priv->mtnic, NULL, &heart_beat, 0, MTNIC_IF_CMD_HEART_BEAT);
- if (!err) {
- flags = be32_to_cpu(heart_beat.flags);
- if (flags & MTNIC_BC_MASK(MTNIC_MASK_HEAR_BEAT_INT_ERROR)) {
- DBG("Internal error detected\n");
- return -EIO;
- }
- *link_state = flags &
- ~((u32) MTNIC_BC_MASK(MTNIC_MASK_HEAR_BEAT_INT_ERROR));
- }
- return err;
-}
-
-
-/*
- * Port commands
- */
-
-static int
-mtnic_SET_PORT_DEFAULT_RING(struct mtnic_port *priv, u8 port, u16 ring)
-{
- struct mtnic_if_set_port_default_ring_in_imm def_ring;
-
- memset(&def_ring, 0, sizeof(def_ring));
- def_ring.ring = ring;
- return mtnic_cmd(priv->mtnic, &def_ring, NULL, port + 1,
- MTNIC_IF_CMD_SET_PORT_DEFAULT_RING);
-}
-
-static int
-mtnic_CONFIG_PORT_RSS_STEER(struct mtnic_port *priv, int port)
-{
- memset(priv->mtnic->cmd.buf, 0, PAGE_SIZE);
- return mtnic_cmd(priv->mtnic, NULL, NULL, port + 1,
- MTNIC_IF_CMD_CONFIG_PORT_RSS_STEER);
-}
-
-static int
-mtnic_SET_PORT_RSS_INDIRECTION(struct mtnic_port *priv, int port)
-
-{
- memset(priv->mtnic->cmd.buf, 0, PAGE_SIZE);
- return mtnic_cmd(priv->mtnic, NULL, NULL, port + 1,
- MTNIC_IF_CMD_SET_PORT_RSS_INDIRECTION);
-}
-
-
-/*
- * Config commands
- */
-static int
-mtnic_CONFIG_CQ(struct mtnic_port *priv, int port,
- u16 cq_ind, struct mtnic_cq *cq)
-{
- struct mtnic_if_config_cq_in_mbox *config_cq = priv->mtnic->cmd.buf;
-
- memset(config_cq, 0, sizeof *config_cq);
- config_cq->cq = cq_ind;
- config_cq->size = fls(UNITS_BUFFER_SIZE - 1);
- config_cq->offset = ((cq->dma) & (PAGE_MASK)) >> 6;
- config_cq->db_record_addr_l = cpu_to_be32(cq->db_dma);
- config_cq->page_address[1] = cpu_to_be32(cq->dma);
- DBG("config cq address: %x dma_address: %lx"
- "offset: %d size %d index: %d\n"
- , config_cq->page_address[1],cq->dma,
- config_cq->offset, config_cq->size, config_cq->cq );
-
- return mtnic_cmd(priv->mtnic, NULL, NULL, port + 1,
- MTNIC_IF_CMD_CONFIG_CQ);
-}
-
-
-static int
-mtnic_CONFIG_TX_RING(struct mtnic_port *priv, u8 port,
- u16 ring_ind, struct mtnic_ring *ring)
-{
- struct mtnic_if_config_send_ring_in_mbox *config_tx_ring = priv->mtnic->cmd.buf;
- memset(config_tx_ring, 0, sizeof *config_tx_ring);
- config_tx_ring->ring = cpu_to_be16(ring_ind);
- config_tx_ring->size = fls(UNITS_BUFFER_SIZE - 1);
- config_tx_ring->cq = cpu_to_be16(ring->cq);
- config_tx_ring->page_address[1] = cpu_to_be32(ring->dma);
-
- return mtnic_cmd(priv->mtnic, NULL, NULL, port + 1,
- MTNIC_IF_CMD_CONFIG_TX_RING);
-}
-
-static int
-mtnic_CONFIG_RX_RING(struct mtnic_port *priv, u8 port,
- u16 ring_ind, struct mtnic_ring *ring)
-{
- struct mtnic_if_config_rx_ring_in_mbox *config_rx_ring = priv->mtnic->cmd.buf;
- memset(config_rx_ring, 0, sizeof *config_rx_ring);
- config_rx_ring->ring = ring_ind;
- MTNIC_BC_PUT(config_rx_ring->stride_size, fls(UNITS_BUFFER_SIZE - 1),
- MTNIC_MASK_CONFIG_RX_RING_SIZE);
- MTNIC_BC_PUT(config_rx_ring->stride_size, 1,
- MTNIC_MASK_CONFIG_RX_RING_STRIDE);
- config_rx_ring->cq = cpu_to_be16(ring->cq);
- config_rx_ring->db_record_addr_l = cpu_to_be32(ring->db_dma);
-
- DBG("Config RX ring starting at address:%lx\n", ring->dma);
-
- config_rx_ring->page_address[1] = cpu_to_be32(ring->dma);
-
- return mtnic_cmd(priv->mtnic, NULL, NULL, port + 1,
- MTNIC_IF_CMD_CONFIG_RX_RING);
-}
-
-static int
-mtnic_CONFIG_EQ(struct mtnic *mtnic)
-{
- struct mtnic_if_config_eq_in_mbox *eq = mtnic->cmd.buf;
-
- if (mtnic->eq.dma & (PAGE_MASK)) {
- DBG("misalligned eq buffer:%lx\n",
- mtnic->eq.dma);
- return -EADDRINUSE;
- }
-
- memset(eq, 0, sizeof *eq);
- MTNIC_BC_PUT(eq->offset, mtnic->eq.dma >> 6, MTNIC_MASK_CONFIG_EQ_OFFSET);
- MTNIC_BC_PUT(eq->size, fls(mtnic->eq.size - 1) - 1, MTNIC_MASK_CONFIG_EQ_SIZE);
- MTNIC_BC_PUT(eq->int_vector, 0, MTNIC_MASK_CONFIG_EQ_INT_VEC);
- eq->page_address[1] = cpu_to_be32(mtnic->eq.dma);
-
- return mtnic_cmd(mtnic, NULL, NULL, 0, MTNIC_IF_CMD_CONFIG_EQ);
-}
-
-
-
-
-static int
-mtnic_SET_RX_RING_ADDR(struct mtnic_port *priv, u8 port, u64* mac)
-{
- struct mtnic_if_set_rx_ring_addr_in_imm ring_addr;
- u32 modifier = ((u32) port + 1) << 16;
-
- memset(&ring_addr, 0, sizeof(ring_addr));
-
- ring_addr.mac_31_0 = cpu_to_be32(*mac & 0xffffffff);
- ring_addr.mac_47_32 = cpu_to_be16((*mac >> 32) & 0xffff);
- ring_addr.flags_vlan_id |= cpu_to_be16(
- MTNIC_BC_MASK(MTNIC_MASK_SET_RX_RING_ADDR_BY_MAC));
-
- return mtnic_cmd(priv->mtnic, &ring_addr, NULL, modifier, MTNIC_IF_CMD_SET_RX_RING_ADDR);
-}
-
-static int
-mtnic_SET_PORT_STATE(struct mtnic_port *priv, u8 port, u8 state)
-{
- struct mtnic_if_set_port_state_in_imm port_state;
-
- port_state.state = state ? cpu_to_be32(
- MTNIC_BC_MASK(MTNIC_MASK_CONFIG_PORT_STATE)) : 0;
- port_state.reserved = 0;
- return mtnic_cmd(priv->mtnic, &port_state, NULL, port + 1,
- MTNIC_IF_CMD_SET_PORT_STATE);
-}
-
-static int
-mtnic_SET_PORT_MTU(struct mtnic_port *priv, u8 port, u16 mtu)
-{
- struct mtnic_if_set_port_mtu_in_imm set_mtu;
-
- memset(&set_mtu, 0, sizeof(set_mtu));
- set_mtu.mtu = cpu_to_be16(mtu);
- return mtnic_cmd(priv->mtnic, &set_mtu, NULL, port + 1,
- MTNIC_IF_CMD_SET_PORT_MTU);
-}
-
-/*
-static int
-mtnic_CONFIG_PORT_VLAN_FILTER(struct mtnic_port *priv, int port)
-{
- struct mtnic_if_config_port_vlan_filter_in_mbox *vlan_filter = priv->mtnic->cmd.buf;
-
- // When no vlans are configured we disable the filter
- // (i.e., pass all vlans) because we ignore them anyhow
- memset(vlan_filter, 0xff, sizeof(*vlan_filter));
- return mtnic_cmd(priv->mtnic, NULL, NULL, port + 1,
- MTNIC_IF_CMD_CONFIG_PORT_VLAN_FILTER);
-}
-*/
-
-
-static int
-mtnic_RELEASE_RESOURCE(struct mtnic_port *priv, u8 port, u8 type, u8 index)
-{
- struct mtnic_if_release_resource_in_imm rel;
- memset(&rel, 0, sizeof rel);
- rel.index = index;
- rel.type = type;
- return mtnic_cmd ( priv->mtnic,
- &rel, NULL, ( type == MTNIC_IF_RESOURCE_TYPE_EQ ) ?
- 0 : port + 1, MTNIC_IF_CMD_RELEASE_RESOURCE );
-}
-
-
-static int
-mtnic_QUERY_CAP(struct mtnic *mtnic, u8 index, u8 mod, u64 *result)
-{
- struct mtnic_if_query_cap_in_imm cap;
- u32 out_imm[2];
- int err;
-
- memset(&cap, 0, sizeof cap);
- cap.cap_index = index;
- cap.cap_modifier = mod;
- err = mtnic_cmd(mtnic, &cap, &out_imm, 0, MTNIC_IF_CMD_QUERY_CAP);
-
- *((u32*)result) = be32_to_cpu(*(out_imm+1));
- *((u32*)result + 1) = be32_to_cpu(*out_imm);
-
- DBG("Called Query cap with index:0x%x mod:%d result:0x%llx"
- " error:%d\n", index, mod, *result, err);
- return err;
-}
-
-
-#define DO_QUERY_CAP(cap, mod, var) \
- err = mtnic_QUERY_CAP(mtnic, cap, mod, &result);\
- if (err) \
- return err; \
- (var) = result
-
-static int
-mtnic_query_num_ports(struct mtnic *mtnic)
-{
- int err = 0;
- u64 result;
-
- DO_QUERY_CAP(MTNIC_IF_CAP_NUM_PORTS, 0, mtnic->fw.num_ports);
-
- return 0;
-}
-
-static int
-mtnic_query_mac(struct mtnic *mtnic)
-{
- int err = 0;
- int i;
- u64 result;
-
- for (i = 0; i < mtnic->fw.num_ports; i++) {
- DO_QUERY_CAP(MTNIC_IF_CAP_DEFAULT_MAC, i + 1, mtnic->fw.mac[i]);
- }
-
- return 0;
-}
-
-static int
-mtnic_query_offsets(struct mtnic *mtnic)
-{
- int err;
- int i;
- u64 result;
-
- DO_QUERY_CAP(MTNIC_IF_CAP_MEM_KEY,
- MTNIC_IF_MEM_TYPE_SNOOP,
- mtnic->fw.mem_type_snoop_be);
- mtnic->fw.mem_type_snoop_be = cpu_to_be32(mtnic->fw.mem_type_snoop_be);
- DO_QUERY_CAP(MTNIC_IF_CAP_TX_CQ_DB_OFFSET, 0, mtnic->fw.txcq_db_offset);
- DO_QUERY_CAP(MTNIC_IF_CAP_EQ_DB_OFFSET, 0, mtnic->fw.eq_db_offset);
-
- for (i = 0; i < mtnic->fw.num_ports; i++) {
- DO_QUERY_CAP(MTNIC_IF_CAP_CQ_OFFSET, i + 1, mtnic->fw.cq_offset);
- DO_QUERY_CAP(MTNIC_IF_CAP_TX_OFFSET, i + 1, mtnic->fw.tx_offset[i]);
- DO_QUERY_CAP(MTNIC_IF_CAP_RX_OFFSET, i + 1, mtnic->fw.rx_offset[i]);
- DBG("--> Port %d CQ offset:0x%x\n", i, mtnic->fw.cq_offset);
- DBG("--> Port %d Tx offset:0x%x\n", i, mtnic->fw.tx_offset[i]);
- DBG("--> Port %d Rx offset:0x%x\n", i, mtnic->fw.rx_offset[i]);
- }
-
- mdelay(20);
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-/********************************************************************
-*
-* MTNIC initalization functions
-*
-*
-*
-*
-*********************************************************************/
-
-/**
- * Reset device
- */
-void
-mtnic_reset ( void )
-{
- void *reset = ioremap ( mtnic_pci_dev.dev.bar[0] + MTNIC_RESET_OFFSET,
- 4 );
- writel ( cpu_to_be32 ( 1 ), reset );
- iounmap ( reset );
-}
-
-
-/**
- * Restore PCI config
- */
-static int
-restore_config(void)
-{
- int i;
- int rc;
-
- for (i = 0; i < 64; ++i) {
- if (i != 22 && i != 23) {
- rc = pci_write_config_dword(mtnic_pci_dev.dev.dev,
- i << 2,
- mtnic_pci_dev.dev.
- dev_config_space[i]);
- if (rc)
- return rc;
- }
- }
- return 0;
-}
-
-
-
-/**
- * Init PCI configuration
- */
-static int
-mtnic_init_pci(struct pci_device *dev)
-{
- int i;
- int err;
-
- /* save bars */
- DBG("bus=%d devfn=0x%x\n", dev->bus, dev->devfn);
- for (i = 0; i < 6; ++i) {
- mtnic_pci_dev.dev.bar[i] =
- pci_bar_start(dev, PCI_BASE_ADDRESS_0 + (i << 2));
- DBG("bar[%d]= 0x%08lx \n", i, mtnic_pci_dev.dev.bar[i]);
- }
-
- /* save config space */
- for (i = 0; i < 64; ++i) {
- err = pci_read_config_dword(dev, i << 2,
- &mtnic_pci_dev.dev.
- dev_config_space[i]);
- if (err) {
- DBG("Can not save configuration space");
- return err;
- }
- }
-
- mtnic_pci_dev.dev.dev = dev;
-
- return 0;
-}
-
-/**
- * Initial hardware
- */
-static inline
-int mtnic_init_card(struct mtnic *mtnic)
-{
- int err = 0;
-
-
- /* Alloc command interface */
- err = mtnic_alloc_cmdif ( mtnic );
- if (err) {
- DBG("Failed to init command interface, aborting\n");
- return -EADDRINUSE;
- }
-
-
- /**
- * Bring up HW
- */
- err = mtnic_QUERY_FW ( mtnic );
- if (err) {
- DBG("QUERY_FW command failed, aborting\n");
- goto cmd_error;
- }
- DBG("Command interface revision:%d\n", mtnic->fw.ifc_rev);
-
- /* Allocate memory for FW and start it */
- err = mtnic_map_cmd(mtnic, MTNIC_IF_CMD_MAP_FW, mtnic->fw.fw_pages);
- if (err) {
- DBG("Eror In MAP_FW\n");
- if (mtnic->fw.fw_pages.buf)
- ufree((intptr_t)mtnic->fw.fw_pages.buf);
- goto cmd_error;
- }
-
- /* Run firmware */
- err = mtnic_cmd(mtnic, NULL, NULL, 0, MTNIC_IF_CMD_RUN_FW);
- if (err) {
- DBG("Eror In RUN FW\n");
- goto map_fw_error;
- }
-
- DBG("FW version:%d.%d.%d\n",
- (u16) (mtnic->fw_ver >> 32),
- (u16) ((mtnic->fw_ver >> 16) & 0xffff),
- (u16) (mtnic->fw_ver & 0xffff));
-
-
- /* Query num ports */
- err = mtnic_query_num_ports(mtnic);
- if (err) {
- DBG("Insufficient resources, aborting\n");
- goto map_fw_error;
- }
-
- /* Open NIC */
- err = mtnic_OPEN_NIC(mtnic);
- if (err) {
- DBG("Failed opening NIC, aborting\n");
- goto map_fw_error;
- }
-
- /* Allocate and map pages worksace */
- err = mtnic_map_cmd(mtnic, MTNIC_IF_CMD_MAP_PAGES, mtnic->fw.extra_pages);
- if (err) {
- DBG("Couldn't allocate %x FW extra pages, aborting\n",
- mtnic->fw.extra_pages.num);
- if (mtnic->fw.extra_pages.buf)
- ufree((intptr_t)mtnic->fw.extra_pages.buf);
- goto map_fw_error;
- }
-
-
- /* Get device information */
- err = mtnic_query_mac(mtnic);
- if (err) {
- DBG("Insufficient resources in quesry mac, aborting\n");
- goto map_fw_error;
- }
-
- /* Get device offsets */
- err = mtnic_query_offsets(mtnic);
- if (err) {
- DBG("Failed retrieving resource offests, aborting\n");
- ufree((intptr_t)mtnic->fw.extra_pages.buf);
- goto map_extra_error;
- }
-
-
- /* Alloc EQ */
- err = mtnic_alloc_eq(mtnic);
- if (err) {
- DBG("Failed init shared resources. error: %d\n", err);
- goto map_extra_error;
- }
-
- /* Configure HW */
- err = mtnic_CONFIG_EQ(mtnic);
- if (err) {
- DBG("Failed configuring EQ\n");
- goto eq_error;
- }
- err = mtnic_CONFIG_RX(mtnic);
- if (err) {
- DBG("Failed Rx configuration\n");
- goto eq_error;
- }
- err = mtnic_CONFIG_TX(mtnic);
- if (err) {
- DBG("Failed Tx configuration\n");
- goto eq_error;
- }
-
-
- return 0;
-
-
-eq_error:
- iounmap(mtnic->eq_db);
- free_memblock(mtnic->eq.buf, mtnic->eq.buf_size);
-map_extra_error:
- ufree((intptr_t)mtnic->fw.extra_pages.buf);
-map_fw_error:
- ufree((intptr_t)mtnic->fw.fw_pages.buf);
-
-cmd_error:
- iounmap(mtnic->hcr);
- free_memblock(mtnic->cmd.buf, PAGE_SIZE);
-
- return -EADDRINUSE;
-}
-
-
-
-
-
-
-
-
-
-
-/*******************************************************************
-*
-* Process functions
-*
-* process compliations of TX and RX
-*
-*
-********************************************************************/
-void mtnic_process_tx_cq(struct mtnic_port *priv, struct net_device *dev,
- struct mtnic_cq *cq)
-{
- struct mtnic_cqe *cqe = cq->buf;
- struct mtnic_ring *ring = &priv->tx_ring;
- u16 index;
-
-
- index = cq->last & (cq->size-1);
- cqe = &cq->buf[index];
-
- /* Owner bit changes every round */
- while (XNOR(cqe->op_tr_own & MTNIC_BIT_CQ_OWN, cq->last & cq->size)) {
- netdev_tx_complete (dev, ring->iobuf[index]);
- ++cq->last;
- index = cq->last & (cq->size-1);
- cqe = &cq->buf[index];
- }
-
- /* Update consumer index */
- cq->db->update_ci = cpu_to_be32(cq->last & 0xffffff);
- wmb(); /* ensure HW sees CQ consumer before we post new buffers */
- ring->cons = cq->last;
-}
-
-
-int mtnic_process_rx_cq(struct mtnic_port *priv,
- struct net_device *dev,
- struct mtnic_cq *cq)
-{
- struct mtnic_cqe *cqe;
- struct mtnic_ring *ring = &priv->rx_ring;
- int index;
- int err;
- struct io_buffer *rx_iob;
- unsigned int length;
-
-
- /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
- * descriptor offset can be deduced from the CQE index instead of
- * reading 'cqe->index' */
- index = cq->last & (cq->size-1);
- cqe = &cq->buf[index];
-
- /* Process all completed CQEs */
- while (XNOR(cqe->op_tr_own & MTNIC_BIT_CQ_OWN, cq->last & cq->size)) {
- /* Drop packet on bad receive or bad checksum */
- if ((cqe->op_tr_own & 0x1f) == MTNIC_OPCODE_ERROR) {
- DBG("CQE completed with error - vendor \n");
- free_iob(ring->iobuf[index]);
- goto next;
- }
- if (cqe->enc_bf & MTNIC_BIT_BAD_FCS) {
- DBG("Accepted packet with bad FCS\n");
- free_iob(ring->iobuf[index]);
- goto next;
- }
-
- /*
- * Packet is OK - process it.
- */
- length = be32_to_cpu(cqe->byte_cnt);
- rx_iob = ring->iobuf[index];
- iob_put(rx_iob, length);
-
- /* Add this packet to the receive queue. */
- netdev_rx(dev, rx_iob);
- ring->iobuf[index] = NULL;
-
-next:
- ++cq->last;
- index = cq->last & (cq->size-1);
- cqe = &cq->buf[index];
-
-
-
- }
-
- /* Update consumer index */
- cq->db->update_ci = cpu_to_be32(cq->last & 0xffffff);
- wmb(); /* ensure HW sees CQ consumer before we post new buffers */
- ring->cons = cq->last;
-
- if (ring->prod - ring->cons < (MAX_GAP_PROD_CONS)) {
- err = mtnic_alloc_iobuf(priv, &priv->rx_ring, DEF_IOBUF_SIZE);
- if (err) {
- DBG("ERROR Allocating io buffer");
- return -EADDRINUSE;
- }
- }
-
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/********************************************************************
-*
-* net_device functions
-*
-*
-* open, poll, close, probe, disable, irq
-*
-*********************************************************************/
-static int
-mtnic_open(struct net_device *dev)
-{
- struct mtnic_port *priv = netdev_priv(dev);
-
- int err = 0;
- struct mtnic_ring *ring;
- struct mtnic_cq *cq;
- int cq_ind = 0;
- u32 dev_link_state;
- int link_check;
-
- DBG("starting port:%d, MAC Address: 0x%12llx\n",
- priv->port, priv->mtnic->fw.mac[priv->port]);
-
- /* Alloc and configure CQs, TX, RX */
- err = mtnic_alloc_resources ( dev );
- if (err) {
- DBG("Error allocating resources\n");
- return -EADDRINUSE;
- }
-
- /* Pass CQs configuration to HW */
- for (cq_ind = 0; cq_ind < NUM_CQS; ++cq_ind) {
- cq = &priv->cq[cq_ind];
- err = mtnic_CONFIG_CQ(priv, priv->port, cq_ind, cq);
- if (err) {
- DBG("Failed configuring CQ:%d error %d\n",
- cq_ind, err);
- if (cq_ind)
- goto cq_error;
- else
- goto allocation_error;
- }
- /* Update consumer index */
- cq->db->update_ci = cpu_to_be32(cq->last & 0xffffff);
- }
-
-
-
- /* Pass Tx configuration to HW */
- ring = &priv->tx_ring;
- err = mtnic_CONFIG_TX_RING(priv, priv->port, 0, ring);
- if (err) {
- DBG("Failed configuring Tx ring:0\n");
- goto cq_error;
- }
-
- /* Pass RX configuration to HW */
- ring = &priv->rx_ring;
- err = mtnic_CONFIG_RX_RING(priv, priv->port, 0, ring);
- if (err) {
- DBG("Failed configuring Rx ring:0\n");
- goto tx_error;
- }
-
- /* Configure Rx steering */
- err = mtnic_CONFIG_PORT_RSS_STEER(priv, priv->port);
- if (!err)
- err = mtnic_SET_PORT_RSS_INDIRECTION(priv, priv->port);
- if (err) {
- DBG("Failed configuring RSS steering\n");
- goto rx_error;
- }
-
-
- /* Set the port default ring to ring 0 */
- err = mtnic_SET_PORT_DEFAULT_RING(priv, priv->port, 0);
- if (err) {
- DBG("Failed setting default ring\n");
- goto rx_error;
- }
-
- /* Set Mac address */
- err = mtnic_SET_RX_RING_ADDR(priv, priv->port, &priv->mtnic->fw.mac[priv->port]);
- if (err) {
- DBG("Failed setting default MAC address\n");
- goto rx_error;
- }
-
- /* Set MTU */
- err = mtnic_SET_PORT_MTU(priv, priv->port, DEF_MTU);
- if (err) {
- DBG("Failed setting MTU\n");
- goto rx_error;
- }
-
- /* Configure VLAN filter */
- /* By adding this function, The second port won't accept packets
- err = mtnic_CONFIG_PORT_VLAN_FILTER(priv, priv->port);
- if (err) {
- DBG("Failed configuring VLAN filter\n");
- goto rx_error;
- }
- */
-
-
- /* Bring up physical link */
- err = mtnic_SET_PORT_STATE(priv, priv->port, 1);
- if (err) {
- DBG("Failed bringing up port\n");
- goto rx_error;
- }
-
- /* PORT IS UP */
- priv->state = CARD_UP;
-
-
- /* Checking Link is up */
- DBG ( "Checking if link is up\n" );
-
-
- for ( link_check = 0; link_check < CHECK_LINK_TIMES; link_check ++ ) {
- /* Let link state stabilize if cable was connected */
- mdelay ( DELAY_LINK_CHECK );
-
- err = mtnic_HEART_BEAT(priv, &dev_link_state);
- if (err) {
- DBG("Failed getting device link state\n");
- return -ENETDOWN;
- }
-
- if ( dev_link_state & priv->port ) {
- /* Link is up */
- break;
- }
- }
-
-
- if ( ! ( dev_link_state & 0x3 ) ) {
- DBG("Link down, check cables and restart\n");
- netdev_link_down ( dev );
- return -ENETDOWN;
- }
-
- DBG ( "Link is up!\n" );
-
- /* Mark as link up */
- netdev_link_up ( dev );
-
- return 0;
-
-rx_error:
- err = mtnic_RELEASE_RESOURCE(priv, priv->port,
- MTNIC_IF_RESOURCE_TYPE_RX_RING, 0);
-tx_error:
- err |= mtnic_RELEASE_RESOURCE(priv, priv->port,
- MTNIC_IF_RESOURCE_TYPE_TX_RING, 0);
-
-cq_error:
- while (cq_ind) {
- err |= mtnic_RELEASE_RESOURCE(priv, priv->port,
- MTNIC_IF_RESOURCE_TYPE_CQ, --cq_ind);
- }
- if (err)
- DBG("Eror Releasing resources\n");
-
-allocation_error:
-
- free_memblock(priv->tx_ring.buf, priv->tx_ring.buf_size);
- iounmap(priv->tx_ring.txcq_db);
- free_memblock(priv->cq[1].buf, priv->cq[1].buf_size);
- free_memblock(priv->cq[1].db, sizeof(struct mtnic_cq_db_record));
- free_memblock(priv->rx_ring.buf, priv->rx_ring.buf_size);
- free_memblock(priv->rx_ring.db, sizeof(struct mtnic_cq_db_record));
- free_memblock(priv->cq[0].buf, priv->cq[0].buf_size);
- free_memblock(priv->cq[0].db, sizeof(struct mtnic_cq_db_record));
-
- mtnic_free_io_buffers(&priv->rx_ring);
-
- return -ENETDOWN;
-}
-
-
-
-
-/** Check if we got completion for receive and transmit and
- * check the line with heart_bit command */
-static void
-mtnic_poll ( struct net_device *dev )
-{
- struct mtnic_port *priv = netdev_priv(dev);
- struct mtnic_cq *cq;
- u32 dev_link_state;
- int err;
- unsigned int i;
-
- /* In case of an old error then return */
- if (priv->state != CARD_UP)
- return;
-
- /* We do not check the device every call _poll call,
- since it will slow it down */
- if ((priv->poll_counter % ROUND_TO_CHECK) == 0) {
- /* Check device */
- err = mtnic_HEART_BEAT(priv, &dev_link_state);
- if (err) {
- DBG("Device has internal error\n");
- priv->state = CARD_LINK_DOWN;
- return;
- }
- if (!(dev_link_state & 0x3)) {
- DBG("Link down, check cables and restart\n");
- priv->state = CARD_LINK_DOWN;
- return;
- }
- }
- /* Polling CQ */
- for (i = 0; i < NUM_CQS; i++) {
- cq = &priv->cq[i]; //Passing on the 2 cqs.
-
- if (cq->is_rx) {
- err = mtnic_process_rx_cq(priv, cq->dev, cq);
- if (err) {
- priv->state = CARD_LINK_DOWN;
- DBG(" Error allocating RX buffers\n");
- return;
- }
- } else {
- mtnic_process_tx_cq(priv, cq->dev, cq);
- }
- }
- ++ priv->poll_counter;
-}
-
-
-
-static int
-mtnic_transmit( struct net_device *dev, struct io_buffer *iobuf )
-{
-
- struct mtnic_port *priv = netdev_priv(dev);
- struct mtnic_ring *ring;
- struct mtnic_tx_desc *tx_desc;
- struct mtnic_data_seg *data;
- u32 index;
-
- /* In case of an error then return */
- if (priv->state != CARD_UP)
- return -ENETDOWN;
-
- ring = &priv->tx_ring;
-
- index = ring->prod & ring->size_mask;
- if ((ring->prod - ring->cons) >= ring->size) {
- DBG("No space left for descriptors!!! cons: %x prod: %x\n",
- ring->cons, ring->prod);
- mdelay(5);
- return -EAGAIN;/* no space left */
- }
-
- /* get current descriptor */
- tx_desc = ring->buf + (index * sizeof(struct mtnic_tx_desc));
-
- /* Prepare Data Seg */
- data = &tx_desc->data;
- data->addr_l = cpu_to_be32((u32)virt_to_bus(iobuf->data));
- data->count = cpu_to_be32(iob_len(iobuf));
- data->mem_type = priv->mtnic->fw.mem_type_snoop_be;
-
- /* Prepare ctrl segement */
- tx_desc->ctrl.size_vlan = cpu_to_be32(2);
- tx_desc->ctrl.flags = cpu_to_be32(MTNIC_BIT_TX_COMP |
- MTNIC_BIT_NO_ICRC);
- tx_desc->ctrl.op_own = cpu_to_be32(MTNIC_OPCODE_SEND) |
- ((ring->prod & ring->size) ?
- cpu_to_be32(MTNIC_BIT_DESC_OWN) : 0);
-
- /* Attach io_buffer */
- ring->iobuf[index] = iobuf;
-
- /* Update producer index */
- ++ring->prod;
-
- /* Ring doorbell! */
- wmb();
- writel((u32) ring->db_offset, &ring->txcq_db->send_db);
-
- return 0;
-}
-
-
-static void
-mtnic_close(struct net_device *dev)
-{
- struct mtnic_port *priv = netdev_priv(dev);
- int err = 0;
- DBG("Close called for port:%d\n", priv->port);
-
- if ( ( priv->state == CARD_UP ) ||
- ( priv->state == CARD_LINK_DOWN ) ) {
-
- /* Disable port */
- err |= mtnic_SET_PORT_STATE(priv, priv->port, 0);
- /*
- * Stop HW associated with this port
- */
- mdelay(5);
-
- /* Stop RX */
- err |= mtnic_RELEASE_RESOURCE(priv, priv->port,
- MTNIC_IF_RESOURCE_TYPE_RX_RING, 0);
-
- /* Stop TX */
- err |= mtnic_RELEASE_RESOURCE(priv, priv->port,
- MTNIC_IF_RESOURCE_TYPE_TX_RING, 0);
-
- /* Stop CQs */
- err |= mtnic_RELEASE_RESOURCE(priv, priv->port,
- MTNIC_IF_RESOURCE_TYPE_CQ, 0);
- err |= mtnic_RELEASE_RESOURCE(priv, priv->port,
- MTNIC_IF_RESOURCE_TYPE_CQ, 1);
- if (err) {
- DBG("Close reported error %d\n", err);
- }
-
- mdelay ( 10 );
-
- /* free memory */
- free_memblock(priv->tx_ring.buf, priv->tx_ring.buf_size);
- iounmap(priv->tx_ring.txcq_db);
- free_memblock(priv->cq[1].buf, priv->cq[1].buf_size);
- free_memblock(priv->cq[1].db, sizeof(struct mtnic_cq_db_record));
- free_memblock(priv->rx_ring.buf, priv->rx_ring.buf_size);
- free_memblock(priv->rx_ring.db, sizeof(struct mtnic_cq_db_record));
- free_memblock(priv->cq[0].buf, priv->cq[0].buf_size);
- free_memblock(priv->cq[0].db, sizeof(struct mtnic_cq_db_record));
-
- /* Free RX buffers */
- mtnic_free_io_buffers(&priv->rx_ring);
-
-
-
- }
-
- priv->state = CARD_INITIALIZED;
-
-}
-
-
-static void
-mtnic_disable(struct pci_device *pci)
-{
-
- int err;
- int i;
- struct mtnic *mtnic = pci_get_drvdata(pci);
-
-
- struct net_device *dev;
- struct mtnic_port *priv;
-
- for ( i = ( mtnic->fw.num_ports - 1 ); i >= 0; i-- ) {
-
- dev = mtnic->netdev[i];
-
- priv = netdev_priv(dev);
-
- /* Just in case */
- if ( ( priv->state == CARD_UP ) ||
- ( priv->state == CARD_LINK_DOWN ) )
- mtnic_close ( dev );
- }
-
- /* Releasing EQ */
- priv = netdev_priv ( mtnic->netdev[0] );
- err = mtnic_RELEASE_RESOURCE(priv, 1,
- MTNIC_IF_RESOURCE_TYPE_EQ, 0);
-
- DBG("Calling MTNIC_CLOSE command\n");
- err |= mtnic_cmd(mtnic, NULL, NULL, 0,
- MTNIC_IF_CMD_CLOSE_NIC);
- if (err) {
- DBG("Error Releasing resources %d\n", err);
- }
-
- free_memblock(mtnic->cmd.buf, PAGE_SIZE);
- iounmap(mtnic->hcr);
- ufree((intptr_t)mtnic->fw.fw_pages.buf);
- ufree((intptr_t)mtnic->fw.extra_pages.buf);
- free_memblock(mtnic->eq.buf, mtnic->eq.buf_size);
- iounmap(mtnic->eq_db);
-
-
- for ( i = ( mtnic->fw.num_ports - 1 ); i >= 0; i-- ) {
- dev = mtnic->netdev[i];
- unregister_netdev ( dev );
- netdev_nullify ( dev );
- netdev_put ( dev );
- }
-
- free ( mtnic );
-
-
- mtnic_reset ();
- mdelay ( 1000 );
- /* Restore config, if we would like to retry booting */
- restore_config ();
-
-
-}
-
-
-
-static void
-mtnic_irq(struct net_device *netdev __unused, int enable __unused)
-{
- /* Not implemented */
-}
-
-
-
-/** mtnic net device operations */
-static struct net_device_operations mtnic_operations = {
- .open = mtnic_open,
- .close = mtnic_close,
- .transmit = mtnic_transmit,
- .poll = mtnic_poll,
- .irq = mtnic_irq,
-};
-
-
-
-
-
-
-
-static int
-mtnic_probe(struct pci_device *pci,
- const struct pci_device_id *id __unused)
-{
- struct mtnic_port *priv;
- struct mtnic *mtnic;
- int err;
- u64 mac;
- int port_index;
-
-
- adjust_pci_device(pci);
-
- err = mtnic_init_pci(pci);
- if (err) {
- DBG("Error in pci_init\n");
- return -EIO;
- }
-
- mtnic_reset();
- mdelay(1000);
-
- err = restore_config();
- if (err) {
- DBG("Error in restoring config\n");
- return err;
- }
-
- mtnic = zalloc ( sizeof ( *mtnic ) );
- if ( ! mtnic ) {
- DBG ( "Error Allocating mtnic buffer\n" );
- return -EADDRINUSE;
- }
-
- pci_set_drvdata(pci, mtnic);
-
- mtnic->pdev = pci;
-
-
- /* Initialize hardware */
- err = mtnic_init_card ( mtnic );
- if (err) {
- DBG("Error in init_card\n");
- goto err_init_card;
- }
-
- for ( port_index = 0; port_index < mtnic->fw.num_ports; port_index ++ ) {
- /* Initializing net device */
- mtnic->netdev[port_index] = alloc_etherdev( sizeof ( struct mtnic_port ) );
- if ( mtnic->netdev[port_index] == NULL ) {
- DBG("Net device allocation failed\n");
- goto err_alloc_mtnic;
- }
-
- /*
- * Initialize driver private data
- */
-
- mtnic->netdev[port_index]->dev = &pci->dev;
- priv = netdev_priv ( mtnic->netdev[port_index] );
- memset ( priv, 0, sizeof ( struct mtnic_port ) );
- priv->mtnic = mtnic;
- priv->netdev = mtnic->netdev[port_index];
-
- /* Attach pci device */
- netdev_init(mtnic->netdev[port_index], &mtnic_operations);
-
- /* Set port number */
- priv->port = port_index;
-
- /* Set state */
- priv->state = CARD_DOWN;
- }
-
-
- int mac_idx;
- for ( port_index = 0; port_index < mtnic->fw.num_ports; port_index ++ ) {
- priv = netdev_priv ( mtnic->netdev[port_index] );
- /* Program the MAC address */
- mac = priv->mtnic->fw.mac[port_index];
- for (mac_idx = 0; mac_idx < MAC_ADDRESS_SIZE; ++mac_idx) {
- mtnic->netdev[port_index]->hw_addr[MAC_ADDRESS_SIZE - mac_idx - 1] = mac & 0xFF;
- mac = mac >> 8;
- }
-
- if ( register_netdev ( mtnic->netdev[port_index] ) ) {
- DBG("Netdev registration failed\n");
- priv->state = CARD_INITIALIZED;
- goto err_alloc_mtnic;
- }
- }
-
-
- return 0;
-
-err_alloc_mtnic:
- free ( mtnic );
-err_init_card:
- return -EIO;
-}
-
-
-
-
-static struct pci_device_id mtnic_nics[] = {
- PCI_ROM ( 0x15b3, 0x6368, "mt25448", "Mellanox ConnectX EN driver", 0 ),
- PCI_ROM ( 0x15b3, 0x6372, "mt25458", "Mellanox ConnectX ENt driver", 0 ),
- PCI_ROM ( 0x15b3, 0x6750, "mt26448", "Mellanox ConnectX EN GEN2 driver", 0 ),
- PCI_ROM ( 0x15b3, 0x675a, "mt26458", "Mellanox ConnectX ENt GEN2 driver", 0 ),
-};
-
-struct pci_driver mtnic_driver __pci_driver = {
- .ids = mtnic_nics,
- .id_count = sizeof(mtnic_nics) / sizeof(mtnic_nics[0]),
- .probe = mtnic_probe,
- .remove = mtnic_disable,
-};
-