aboutsummaryrefslogtreecommitdiff
path: root/sys/ofed/drivers/net/mlx4
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ofed/drivers/net/mlx4')
-rw-r--r--sys/ofed/drivers/net/mlx4/Makefile33
-rw-r--r--sys/ofed/drivers/net/mlx4/alloc.c455
-rw-r--r--sys/ofed/drivers/net/mlx4/catas.c175
-rw-r--r--sys/ofed/drivers/net/mlx4/cmd.c2606
-rw-r--r--sys/ofed/drivers/net/mlx4/cq.c400
-rw-r--r--sys/ofed/drivers/net/mlx4/en_cq.c214
-rw-r--r--sys/ofed/drivers/net/mlx4/en_main.c343
-rw-r--r--sys/ofed/drivers/net/mlx4/en_netdev.c2818
-rw-r--r--sys/ofed/drivers/net/mlx4/en_port.c598
-rw-r--r--sys/ofed/drivers/net/mlx4/en_port.h563
-rw-r--r--sys/ofed/drivers/net/mlx4/en_resources.c121
-rw-r--r--sys/ofed/drivers/net/mlx4/en_rx.c922
-rw-r--r--sys/ofed/drivers/net/mlx4/en_tx.c1119
-rw-r--r--sys/ofed/drivers/net/mlx4/eq.c1406
-rw-r--r--sys/ofed/drivers/net/mlx4/fw.c1956
-rw-r--r--sys/ofed/drivers/net/mlx4/fw.h230
-rw-r--r--sys/ofed/drivers/net/mlx4/icm.c473
-rw-r--r--sys/ofed/drivers/net/mlx4/icm.h129
-rw-r--r--sys/ofed/drivers/net/mlx4/intf.c188
-rw-r--r--sys/ofed/drivers/net/mlx4/main.c3883
-rw-r--r--sys/ofed/drivers/net/mlx4/mcg.c1543
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4.h1328
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4_en.h912
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4_stats.h185
-rw-r--r--sys/ofed/drivers/net/mlx4/mr.c996
-rw-r--r--sys/ofed/drivers/net/mlx4/pd.c302
-rw-r--r--sys/ofed/drivers/net/mlx4/port.c1224
-rw-r--r--sys/ofed/drivers/net/mlx4/profile.c249
-rw-r--r--sys/ofed/drivers/net/mlx4/qp.c615
-rw-r--r--sys/ofed/drivers/net/mlx4/reset.c185
-rw-r--r--sys/ofed/drivers/net/mlx4/resource_tracker.c4686
-rw-r--r--sys/ofed/drivers/net/mlx4/sense.c143
-rw-r--r--sys/ofed/drivers/net/mlx4/srq.c314
-rw-r--r--sys/ofed/drivers/net/mlx4/sys_tune.c323
34 files changed, 0 insertions, 31637 deletions
diff --git a/sys/ofed/drivers/net/mlx4/Makefile b/sys/ofed/drivers/net/mlx4/Makefile
deleted file mode 100644
index 05338e804fa2..000000000000
--- a/sys/ofed/drivers/net/mlx4/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-# $FreeBSD$
-#.PATH: ${.CURDIR}/../../ofed/drivers/net/mlx4:${.CURDIR}/../../ofed/include/linux
-.PATH: ${.CURDIR}/../../../../../include/linux
-
-.include <src.opts.mk>
-
-
-KMOD = mlx4
-SRCS = device_if.h bus_if.h pci_if.h vnode_if.h
-SRCS+= alloc.c catas.c cmd.c cq.c eq.c fw.c icm.c intf.c main.c mcg.c mr.c linux_compat.c linux_radix.c
-SRCS+= pd.c port.c profile.c qp.c reset.c sense.c srq.c resource_tracker.c sys_tune.c
-SRCS+= opt_inet.h opt_inet6.h
-
-
-#CFLAGS+= -I${.CURDIR}/../../ofed/drivers/net/mlx4
-#CFLAGS+= -I${.CURDIR}/../../ofed/include/
-CFLAGS+= -I${.CURDIR}/../../../../../include
-
-.if !defined(KERNBUILDDIR)
-.if ${MK_INET_SUPPORT} != "no"
-opt_inet.h:
- @echo "#define INET 1" > ${.TARGET}
-.endif
-
-.if ${MK_INET6_SUPPORT} != "no"
-opt_inet6.h:
- @echo "#define INET6 1" > ${.TARGET}
-.endif
-.endif
-
-.include <bsd.kmod.mk>
-
-CFLAGS+= -Wno-cast-qual -Wno-pointer-arith
diff --git a/sys/ofed/drivers/net/mlx4/alloc.c b/sys/ofed/drivers/net/mlx4/alloc.c
deleted file mode 100644
index da36b34d98b5..000000000000
--- a/sys/ofed/drivers/net/mlx4/alloc.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008, 2014 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.
- */
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
-
-#include "mlx4.h"
-
-u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
-{
- u32 obj;
-
- spin_lock(&bitmap->lock);
-
- obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last);
- if (obj >= bitmap->max) {
- bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
- & bitmap->mask;
- obj = find_first_zero_bit(bitmap->table, bitmap->max);
- }
-
- if (obj < bitmap->max) {
- set_bit(obj, bitmap->table);
- bitmap->last = (obj + 1);
- if (bitmap->last == bitmap->max)
- bitmap->last = 0;
- obj |= bitmap->top;
- } else
- obj = -1;
-
- if (obj != -1)
- --bitmap->avail;
-
- spin_unlock(&bitmap->lock);
-
- return obj;
-}
-
-void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr)
-{
- mlx4_bitmap_free_range(bitmap, obj, 1, use_rr);
-}
-
-static unsigned long find_aligned_range(unsigned long *bitmap,
- u32 start, u32 nbits,
- int len, int align, u32 skip_mask)
-{
- unsigned long end, i;
-
-again:
- start = ALIGN(start, align);
-
- while ((start < nbits) && (test_bit(start, bitmap) ||
- (start & skip_mask)))
- start += align;
-
- if (start >= nbits)
- return -1;
-
- end = start+len;
- if (end > nbits)
- return -1;
-
- for (i = start + 1; i < end; i++) {
- if (test_bit(i, bitmap) || ((u32)i & skip_mask)) {
- start = i + 1;
- goto again;
- }
- }
-
- return start;
-}
-
-u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt,
- int align, u32 skip_mask)
-{
- u32 obj;
-
- if (likely(cnt == 1 && align == 1 && !skip_mask))
- return mlx4_bitmap_alloc(bitmap);
-
- spin_lock(&bitmap->lock);
-
- obj = find_aligned_range(bitmap->table, bitmap->last,
- bitmap->max, cnt, align, skip_mask);
- if (obj >= bitmap->max) {
- bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
- & bitmap->mask;
- obj = find_aligned_range(bitmap->table, 0, bitmap->max,
- cnt, align, skip_mask);
- }
-
- if (obj < bitmap->max) {
- bitmap_set(bitmap->table, obj, cnt);
- if (obj == bitmap->last) {
- bitmap->last = (obj + cnt);
- if (bitmap->last >= bitmap->max)
- bitmap->last = 0;
- }
- obj |= bitmap->top;
- } else
- obj = -1;
-
- if (obj != -1)
- bitmap->avail -= cnt;
-
- spin_unlock(&bitmap->lock);
-
- return obj;
-}
-
-u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap)
-{
- return bitmap->avail;
-}
-
-void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
- int use_rr)
-{
- obj &= bitmap->max + bitmap->reserved_top - 1;
-
- spin_lock(&bitmap->lock);
- if (!use_rr) {
- bitmap->last = min(bitmap->last, obj);
- bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
- & bitmap->mask;
- }
- bitmap_clear(bitmap->table, obj, cnt);
- bitmap->avail += cnt;
- spin_unlock(&bitmap->lock);
-}
-
-int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
- u32 reserved_bot, u32 reserved_top)
-{
- /* sanity check */
- if (num <= (u64)reserved_top + reserved_bot)
- return -EINVAL;
-
- /* num must be a power of 2 */
- if (num != roundup_pow_of_two(num))
- return -EINVAL;
-
- if (reserved_bot + reserved_top >= num)
- return -EINVAL;
-
- bitmap->last = 0;
- bitmap->top = 0;
- bitmap->max = num - reserved_top;
- bitmap->mask = mask;
- bitmap->reserved_top = reserved_top;
- bitmap->avail = num - reserved_top - reserved_bot;
- spin_lock_init(&bitmap->lock);
- bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *
- sizeof (long), GFP_KERNEL);
- if (!bitmap->table)
- return -ENOMEM;
-
- bitmap_set(bitmap->table, 0, reserved_bot);
-
- return 0;
-}
-
-void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap)
-{
- kfree(bitmap->table);
-}
-
-/*
- * Handling for queue buffers -- we allocate a bunch of memory and
- * register it in a memory region at HCA virtual address 0. If the
- * requested size is > max_direct, we split the allocation into
- * multiple pages, so we don't require too much contiguous memory.
- */
-
-int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
- struct mlx4_buf *buf)
-{
- dma_addr_t t;
-
- if (size <= max_direct) {
- buf->nbufs = 1;
- buf->npages = 1;
- buf->page_shift = get_order(size) + PAGE_SHIFT;
- buf->direct.buf = dma_alloc_coherent(&dev->pdev->dev,
- size, &t, GFP_KERNEL);
- if (!buf->direct.buf)
- return -ENOMEM;
-
- buf->direct.map = t;
-
- while (t & ((1 << buf->page_shift) - 1)) {
- --buf->page_shift;
- buf->npages *= 2;
- }
-
- memset(buf->direct.buf, 0, size);
- } else {
- int i;
-
- buf->direct.buf = NULL;
- buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE;
- buf->npages = buf->nbufs;
- buf->page_shift = PAGE_SHIFT;
- buf->page_list = kcalloc(buf->nbufs, sizeof(*buf->page_list),
- GFP_KERNEL);
- if (!buf->page_list)
- return -ENOMEM;
-
- for (i = 0; i < buf->nbufs; ++i) {
- buf->page_list[i].buf =
- dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
- &t, GFP_KERNEL);
- if (!buf->page_list[i].buf)
- goto err_free;
-
- buf->page_list[i].map = t;
-
- memset(buf->page_list[i].buf, 0, PAGE_SIZE);
- }
-
- if (BITS_PER_LONG == 64) {
- struct page **pages;
- pages = kmalloc(sizeof *pages * buf->nbufs, GFP_KERNEL);
- if (!pages)
- goto err_free;
- for (i = 0; i < buf->nbufs; ++i)
- pages[i] = virt_to_page(buf->page_list[i].buf);
- buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, PAGE_KERNEL);
- kfree(pages);
- if (!buf->direct.buf)
- goto err_free;
- }
- }
-
- return 0;
-
-err_free:
- mlx4_buf_free(dev, size, buf);
-
- return -ENOMEM;
-}
-EXPORT_SYMBOL_GPL(mlx4_buf_alloc);
-
-void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf)
-{
- int i;
-
- if (buf->nbufs == 1)
- dma_free_coherent(&dev->pdev->dev, size, buf->direct.buf,
- buf->direct.map);
- else {
- if (BITS_PER_LONG == 64 && buf->direct.buf)
- vunmap(buf->direct.buf);
-
- for (i = 0; i < buf->nbufs; ++i)
- if (buf->page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- buf->page_list[i].buf,
- buf->page_list[i].map);
- kfree(buf->page_list);
- }
-}
-EXPORT_SYMBOL_GPL(mlx4_buf_free);
-
-static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device)
-{
- struct mlx4_db_pgdir *pgdir;
-
- pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL);
- if (!pgdir)
- return NULL;
-
- bitmap_fill(pgdir->order1, MLX4_DB_PER_PAGE / 2);
- pgdir->bits[0] = pgdir->order0;
- pgdir->bits[1] = pgdir->order1;
- pgdir->db_page = dma_alloc_coherent(dma_device, PAGE_SIZE,
- &pgdir->db_dma, GFP_KERNEL);
- if (!pgdir->db_page) {
- kfree(pgdir);
- return NULL;
- }
-
- return pgdir;
-}
-
-static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir,
- struct mlx4_db *db, int order)
-{
- int o;
- int i;
-
- for (o = order; o <= 1; ++o) {
- i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o);
- if (i < MLX4_DB_PER_PAGE >> o)
- goto found;
- }
-
- return -ENOMEM;
-
-found:
- clear_bit(i, pgdir->bits[o]);
-
- i <<= o;
-
- if (o > order)
- set_bit(i ^ 1, pgdir->bits[order]);
-
- db->u.pgdir = pgdir;
- db->index = i;
- db->db = pgdir->db_page + db->index;
- db->dma = pgdir->db_dma + db->index * 4;
- db->order = order;
-
- return 0;
-}
-
-int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_db_pgdir *pgdir;
- int ret = 0;
-
- mutex_lock(&priv->pgdir_mutex);
-
- list_for_each_entry(pgdir, &priv->pgdir_list, list)
- if (!mlx4_alloc_db_from_pgdir(pgdir, db, order))
- goto out;
-
- pgdir = mlx4_alloc_db_pgdir(&(dev->pdev->dev));
- if (!pgdir) {
- ret = -ENOMEM;
- goto out;
- }
-
- list_add(&pgdir->list, &priv->pgdir_list);
-
- /* This should never fail -- we just allocated an empty page: */
- WARN_ON(mlx4_alloc_db_from_pgdir(pgdir, db, order));
-
-out:
- mutex_unlock(&priv->pgdir_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(mlx4_db_alloc);
-
-void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int o;
- int i;
-
- mutex_lock(&priv->pgdir_mutex);
-
- o = db->order;
- i = db->index;
-
- if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) {
- clear_bit(i ^ 1, db->u.pgdir->order0);
- ++o;
- }
- i >>= o;
- set_bit(i, db->u.pgdir->bits[o]);
-
- if (bitmap_full(db->u.pgdir->order1, MLX4_DB_PER_PAGE / 2)) {
- dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
- db->u.pgdir->db_page, db->u.pgdir->db_dma);
- list_del(&db->u.pgdir->list);
- kfree(db->u.pgdir);
- }
-
- mutex_unlock(&priv->pgdir_mutex);
-}
-EXPORT_SYMBOL_GPL(mlx4_db_free);
-
-int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
- int size, int max_direct)
-{
- int err;
-
- err = mlx4_db_alloc(dev, &wqres->db, 1);
- if (err)
- return err;
-
- *wqres->db.db = 0;
-
- err = mlx4_buf_alloc(dev, size, max_direct, &wqres->buf);
- if (err)
- goto err_db;
-
- err = mlx4_mtt_init(dev, wqres->buf.npages, wqres->buf.page_shift,
- &wqres->mtt);
- if (err)
- goto err_buf;
-
- err = mlx4_buf_write_mtt(dev, &wqres->mtt, &wqres->buf);
- if (err)
- goto err_mtt;
-
- return 0;
-
-err_mtt:
- mlx4_mtt_cleanup(dev, &wqres->mtt);
-err_buf:
- mlx4_buf_free(dev, size, &wqres->buf);
-err_db:
- mlx4_db_free(dev, &wqres->db);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_alloc_hwq_res);
-
-void mlx4_free_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres,
- int size)
-{
- mlx4_mtt_cleanup(dev, &wqres->mtt);
- mlx4_buf_free(dev, size, &wqres->buf);
- mlx4_db_free(dev, &wqres->db);
-}
-EXPORT_SYMBOL_GPL(mlx4_free_hwq_res);
diff --git a/sys/ofed/drivers/net/mlx4/catas.c b/sys/ofed/drivers/net/mlx4/catas.c
deleted file mode 100644
index 497e0ddb8956..000000000000
--- a/sys/ofed/drivers/net/mlx4/catas.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008, 2014 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.
- */
-
-#define LINUXKPI_PARAM_PREFIX mlx4_
-
-#include <linux/workqueue.h>
-#include <linux/module.h>
-
-#include <asm/byteorder.h>
-
-#include "mlx4.h"
-
-#define MLX4_CATAS_POLL_INTERVAL (5 * HZ)
-
-static DEFINE_SPINLOCK(catas_lock);
-
-static LIST_HEAD(catas_list);
-static struct work_struct catas_work;
-
-static int internal_err_reset = 1;
-module_param(internal_err_reset, int, 0644);
-MODULE_PARM_DESC(internal_err_reset,
- "Reset device on internal errors if non-zero"
- " (default 1, in SRIOV mode default is 0)");
-
-static void dump_err_buf(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- int i;
-
- mlx4_err(dev, "Internal error detected:\n");
- for (i = 0; i < priv->fw.catas_size; ++i)
- mlx4_err(dev, " buf[%02x]: %08x\n",
- i, swab32(readl(priv->catas_err.map + i)));
-}
-
-static void poll_catas(unsigned long dev_ptr)
-{
- struct mlx4_dev *dev = (struct mlx4_dev *) dev_ptr;
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- if (readl(priv->catas_err.map)) {
- /* If the device is off-line, we cannot try to recover it */
- if (pci_channel_offline(dev->pdev))
- mod_timer(&priv->catas_err.timer,
- round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL));
- else {
- dump_err_buf(dev);
- mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0);
-
- if (internal_err_reset) {
- spin_lock(&catas_lock);
- list_add(&priv->catas_err.list, &catas_list);
- spin_unlock(&catas_lock);
-
- queue_work(mlx4_wq, &catas_work);
- }
- }
- } else
- mod_timer(&priv->catas_err.timer,
- round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL));
-}
-
-static void catas_reset(struct work_struct *work)
-{
- struct mlx4_priv *priv, *tmppriv;
- struct mlx4_dev *dev;
-
- LIST_HEAD(tlist);
- int ret;
-
- spin_lock_irq(&catas_lock);
- list_splice_init(&catas_list, &tlist);
- spin_unlock_irq(&catas_lock);
-
- list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) {
- struct pci_dev *pdev = priv->dev.pdev;
-
- /* If the device is off-line, we cannot reset it */
- if (pci_channel_offline(pdev))
- continue;
-
- ret = mlx4_restart_one(priv->dev.pdev);
- /* 'priv' now is not valid */
- if (ret)
- pr_err("mlx4 %s: Reset failed (%d)\n",
- pci_name(pdev), ret);
- else {
- dev = pci_get_drvdata(pdev);
- mlx4_dbg(dev, "Reset succeeded\n");
- }
- }
-}
-
-void mlx4_start_catas_poll(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- phys_addr_t addr;
-
- /*If we are in SRIOV the default of the module param must be 0*/
- if (mlx4_is_mfunc(dev))
- internal_err_reset = 0;
-
- INIT_LIST_HEAD(&priv->catas_err.list);
- init_timer(&priv->catas_err.timer);
- priv->catas_err.map = NULL;
-
- addr = pci_resource_start(dev->pdev, priv->fw.catas_bar) +
- priv->fw.catas_offset;
-
- priv->catas_err.map = ioremap(addr, priv->fw.catas_size * 4);
- if (!priv->catas_err.map) {
- mlx4_warn(dev, "Failed to map internal error buffer at 0x%llx\n",
- (unsigned long long) addr);
- return;
- }
-
- priv->catas_err.timer.data = (unsigned long) dev;
- priv->catas_err.timer.function = poll_catas;
- priv->catas_err.timer.expires =
- round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL);
- add_timer(&priv->catas_err.timer);
-}
-
-void mlx4_stop_catas_poll(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- del_timer_sync(&priv->catas_err.timer);
-
- if (priv->catas_err.map) {
- iounmap(priv->catas_err.map);
- priv->catas_err.map = NULL;
- }
-
- spin_lock_irq(&catas_lock);
- list_del_init(&priv->catas_err.list);
- spin_unlock_irq(&catas_lock);
-}
-
-void __init mlx4_catas_init(void)
-{
- INIT_WORK(&catas_work, catas_reset);
-}
diff --git a/sys/ofed/drivers/net/mlx4/cmd.c b/sys/ofed/drivers/net/mlx4/cmd.c
deleted file mode 100644
index 9d5177965162..000000000000
--- a/sys/ofed/drivers/net/mlx4/cmd.c
+++ /dev/null
@@ -1,2606 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-
-#include <linux/mlx4/cmd.h>
-#include <linux/mlx4/device.h>
-#include <linux/semaphore.h>
-#include <rdma/ib_smi.h>
-
-#include <asm/io.h>
-#include <linux/ktime.h>
-
-#include "mlx4.h"
-#include "fw.h"
-
-#define CMD_POLL_TOKEN 0xffff
-#define INBOX_MASK 0xffffffffffffff00ULL
-
-#define CMD_CHAN_VER 1
-#define CMD_CHAN_IF_REV 1
-
-enum {
- /* command completed successfully: */
- CMD_STAT_OK = 0x00,
- /* Internal error (such as a bus error) occurred while processing command: */
- CMD_STAT_INTERNAL_ERR = 0x01,
- /* Operation/command not supported or opcode modifier not supported: */
- CMD_STAT_BAD_OP = 0x02,
- /* Parameter not supported or parameter out of range: */
- CMD_STAT_BAD_PARAM = 0x03,
- /* System not enabled or bad system state: */
- CMD_STAT_BAD_SYS_STATE = 0x04,
- /* Attempt to access reserved or unallocaterd resource: */
- CMD_STAT_BAD_RESOURCE = 0x05,
- /* Requested resource is currently executing a command, or is otherwise busy: */
- CMD_STAT_RESOURCE_BUSY = 0x06,
- /* Required capability exceeds device limits: */
- CMD_STAT_EXCEED_LIM = 0x08,
- /* Resource is not in the appropriate state or ownership: */
- CMD_STAT_BAD_RES_STATE = 0x09,
- /* Index out of range: */
- CMD_STAT_BAD_INDEX = 0x0a,
- /* FW image corrupted: */
- CMD_STAT_BAD_NVMEM = 0x0b,
- /* Error in ICM mapping (e.g. not enough auxiliary ICM pages to execute command): */
- CMD_STAT_ICM_ERROR = 0x0c,
- /* Attempt to modify a QP/EE which is not in the presumed state: */
- CMD_STAT_BAD_QP_STATE = 0x10,
- /* Bad segment parameters (Address/Size): */
- CMD_STAT_BAD_SEG_PARAM = 0x20,
- /* Memory Region has Memory Windows bound to: */
- CMD_STAT_REG_BOUND = 0x21,
- /* HCA local attached memory not present: */
- CMD_STAT_LAM_NOT_PRE = 0x22,
- /* Bad management packet (silently discarded): */
- CMD_STAT_BAD_PKT = 0x30,
- /* More outstanding CQEs in CQ than new CQ size: */
- CMD_STAT_BAD_SIZE = 0x40,
- /* Multi Function device support required: */
- CMD_STAT_MULTI_FUNC_REQ = 0x50,
-};
-
-enum {
- HCR_IN_PARAM_OFFSET = 0x00,
- HCR_IN_MODIFIER_OFFSET = 0x08,
- HCR_OUT_PARAM_OFFSET = 0x0c,
- HCR_TOKEN_OFFSET = 0x14,
- HCR_STATUS_OFFSET = 0x18,
-
- HCR_OPMOD_SHIFT = 12,
- HCR_T_BIT = 21,
- HCR_E_BIT = 22,
- HCR_GO_BIT = 23
-};
-
-enum {
- GO_BIT_TIMEOUT_MSECS = 10000
-};
-
-enum mlx4_vlan_transition {
- MLX4_VLAN_TRANSITION_VST_VST = 0,
- MLX4_VLAN_TRANSITION_VST_VGT = 1,
- MLX4_VLAN_TRANSITION_VGT_VST = 2,
- MLX4_VLAN_TRANSITION_VGT_VGT = 3,
-};
-
-
-struct mlx4_cmd_context {
- struct completion done;
- int result;
- int next;
- u64 out_param;
- u16 token;
- u8 fw_status;
-};
-
-static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr_cmd *in_vhcr);
-
-static int mlx4_status_to_errno(u8 status)
-{
- static const int trans_table[] = {
- [CMD_STAT_INTERNAL_ERR] = -EIO,
- [CMD_STAT_BAD_OP] = -EPERM,
- [CMD_STAT_BAD_PARAM] = -EINVAL,
- [CMD_STAT_BAD_SYS_STATE] = -ENXIO,
- [CMD_STAT_BAD_RESOURCE] = -EBADF,
- [CMD_STAT_RESOURCE_BUSY] = -EBUSY,
- [CMD_STAT_EXCEED_LIM] = -ENOMEM,
- [CMD_STAT_BAD_RES_STATE] = -EBADF,
- [CMD_STAT_BAD_INDEX] = -EBADF,
- [CMD_STAT_BAD_NVMEM] = -EFAULT,
- [CMD_STAT_ICM_ERROR] = -ENFILE,
- [CMD_STAT_BAD_QP_STATE] = -EINVAL,
- [CMD_STAT_BAD_SEG_PARAM] = -EFAULT,
- [CMD_STAT_REG_BOUND] = -EBUSY,
- [CMD_STAT_LAM_NOT_PRE] = -EAGAIN,
- [CMD_STAT_BAD_PKT] = -EINVAL,
- [CMD_STAT_BAD_SIZE] = -ENOMEM,
- [CMD_STAT_MULTI_FUNC_REQ] = -EACCES,
- };
-
- if (status >= ARRAY_SIZE(trans_table) ||
- (status != CMD_STAT_OK && trans_table[status] == 0))
- return -EIO;
-
- return trans_table[status];
-}
-
-static const char *cmd_to_str(u16 cmd)
-{
- switch (cmd) {
- case MLX4_CMD_SYS_EN: return "SYS_EN";
- case MLX4_CMD_SYS_DIS: return "SYS_DIS";
- case MLX4_CMD_MAP_FA: return "MAP_FA";
- case MLX4_CMD_UNMAP_FA: return "UNMAP_FA";
- case MLX4_CMD_RUN_FW: return "RUN_FW";
- case MLX4_CMD_MOD_STAT_CFG: return "MOD_STAT_CFG";
- case MLX4_CMD_QUERY_DEV_CAP: return "QUERY_DEV_CAP";
- case MLX4_CMD_QUERY_FW: return "QUERY_FW";
- case MLX4_CMD_ENABLE_LAM: return "ENABLE_LAM";
- case MLX4_CMD_DISABLE_LAM: return "DISABLE_LAM";
- case MLX4_CMD_QUERY_DDR: return "QUERY_DDR";
- case MLX4_CMD_QUERY_ADAPTER: return "QUERY_ADAPTER";
- case MLX4_CMD_INIT_HCA: return "INIT_HCA";
- case MLX4_CMD_CLOSE_HCA: return "CLOSE_HCA";
- case MLX4_CMD_INIT_PORT: return "INIT_PORT";
- case MLX4_CMD_CLOSE_PORT: return "CLOSE_PORT";
- case MLX4_CMD_QUERY_HCA: return "QUERY_HCA";
- case MLX4_CMD_QUERY_PORT: return "QUERY_PORT";
- case MLX4_CMD_SENSE_PORT: return "SENSE_PORT";
- case MLX4_CMD_HW_HEALTH_CHECK: return "HW_HEALTH_CHECK";
- case MLX4_CMD_SET_PORT: return "SET_PORT";
- case MLX4_CMD_SET_NODE: return "SET_NODE";
- case MLX4_CMD_QUERY_FUNC: return "QUERY_FUNC";
- case MLX4_CMD_MAP_ICM: return "MAP_ICM";
- case MLX4_CMD_UNMAP_ICM: return "UNMAP_ICM";
- case MLX4_CMD_MAP_ICM_AUX: return "MAP_ICM_AUX";
- case MLX4_CMD_UNMAP_ICM_AUX: return "UNMAP_ICM_AUX";
- case MLX4_CMD_SET_ICM_SIZE: return "SET_ICM_SIZE";
- /*master notify fw on finish for slave's flr*/
- case MLX4_CMD_INFORM_FLR_DONE: return "INFORM_FLR_DONE";
- case MLX4_CMD_GET_OP_REQ: return "GET_OP_REQ";
-
- /* TPT commands */
- case MLX4_CMD_SW2HW_MPT: return "SW2HW_MPT";
- case MLX4_CMD_QUERY_MPT: return "QUERY_MPT";
- case MLX4_CMD_HW2SW_MPT: return "HW2SW_MPT";
- case MLX4_CMD_READ_MTT: return "READ_MTT";
- case MLX4_CMD_WRITE_MTT: return "WRITE_MTT";
- case MLX4_CMD_SYNC_TPT: return "SYNC_TPT";
-
- /* EQ commands */
- case MLX4_CMD_MAP_EQ: return "MAP_EQ";
- case MLX4_CMD_SW2HW_EQ: return "SW2HW_EQ";
- case MLX4_CMD_HW2SW_EQ: return "HW2SW_EQ";
- case MLX4_CMD_QUERY_EQ: return "QUERY_EQ";
-
- /* CQ commands */
- case MLX4_CMD_SW2HW_CQ: return "SW2HW_CQ";
- case MLX4_CMD_HW2SW_CQ: return "HW2SW_CQ";
- case MLX4_CMD_QUERY_CQ: return "QUERY_CQ:";
- case MLX4_CMD_MODIFY_CQ: return "MODIFY_CQ:";
-
- /* SRQ commands */
- case MLX4_CMD_SW2HW_SRQ: return "SW2HW_SRQ";
- case MLX4_CMD_HW2SW_SRQ: return "HW2SW_SRQ";
- case MLX4_CMD_QUERY_SRQ: return "QUERY_SRQ";
- case MLX4_CMD_ARM_SRQ: return "ARM_SRQ";
-
- /* QP/EE commands */
- case MLX4_CMD_RST2INIT_QP: return "RST2INIT_QP";
- case MLX4_CMD_INIT2RTR_QP: return "INIT2RTR_QP";
- case MLX4_CMD_RTR2RTS_QP: return "RTR2RTS_QP";
- case MLX4_CMD_RTS2RTS_QP: return "RTS2RTS_QP";
- case MLX4_CMD_SQERR2RTS_QP: return "SQERR2RTS_QP";
- case MLX4_CMD_2ERR_QP: return "2ERR_QP";
- case MLX4_CMD_RTS2SQD_QP: return "RTS2SQD_QP";
- case MLX4_CMD_SQD2SQD_QP: return "SQD2SQD_QP";
- case MLX4_CMD_SQD2RTS_QP: return "SQD2RTS_QP";
- case MLX4_CMD_2RST_QP: return "2RST_QP";
- case MLX4_CMD_QUERY_QP: return "QUERY_QP";
- case MLX4_CMD_INIT2INIT_QP: return "INIT2INIT_QP";
- case MLX4_CMD_SUSPEND_QP: return "SUSPEND_QP";
- case MLX4_CMD_UNSUSPEND_QP: return "UNSUSPEND_QP";
- /* special QP and management commands */
- case MLX4_CMD_CONF_SPECIAL_QP: return "CONF_SPECIAL_QP";
- case MLX4_CMD_MAD_IFC: return "MAD_IFC";
-
- /* multicast commands */
- case MLX4_CMD_READ_MCG: return "READ_MCG";
- case MLX4_CMD_WRITE_MCG: return "WRITE_MCG";
- case MLX4_CMD_MGID_HASH: return "MGID_HASH";
-
- /* miscellaneous commands */
- case MLX4_CMD_DIAG_RPRT: return "DIAG_RPRT";
- case MLX4_CMD_NOP: return "NOP";
- case MLX4_CMD_ACCESS_MEM: return "ACCESS_MEM";
- case MLX4_CMD_SET_VEP: return "SET_VEP";
-
- /* Ethernet specific commands */
- case MLX4_CMD_SET_VLAN_FLTR: return "SET_VLAN_FLTR";
- case MLX4_CMD_SET_MCAST_FLTR: return "SET_MCAST_FLTR";
- case MLX4_CMD_DUMP_ETH_STATS: return "DUMP_ETH_STATS";
-
- /* Communication channel commands */
- case MLX4_CMD_ARM_COMM_CHANNEL: return "ARM_COMM_CHANNEL";
- case MLX4_CMD_GEN_EQE: return "GEN_EQE";
-
- /* virtual commands */
- case MLX4_CMD_ALLOC_RES: return "ALLOC_RES";
- case MLX4_CMD_FREE_RES: return "FREE_RES";
- case MLX4_CMD_MCAST_ATTACH: return "MCAST_ATTACH";
- case MLX4_CMD_UCAST_ATTACH: return "UCAST_ATTACH";
- case MLX4_CMD_PROMISC: return "PROMISC";
- case MLX4_CMD_QUERY_FUNC_CAP: return "QUERY_FUNC_CAP";
- case MLX4_CMD_QP_ATTACH: return "QP_ATTACH";
-
- /* debug commands */
- case MLX4_CMD_QUERY_DEBUG_MSG: return "QUERY_DEBUG_MSG";
- case MLX4_CMD_SET_DEBUG_MSG: return "SET_DEBUG_MSG";
-
- /* statistics commands */
- case MLX4_CMD_QUERY_IF_STAT: return "QUERY_IF_STAT";
- case MLX4_CMD_SET_IF_STAT: return "SET_IF_STAT";
-
- /* register/delete flow steering network rules */
- case MLX4_QP_FLOW_STEERING_ATTACH: return "QP_FLOW_STEERING_ATTACH";
- case MLX4_QP_FLOW_STEERING_DETACH: return "QP_FLOW_STEERING_DETACH";
- case MLX4_FLOW_STEERING_IB_UC_QP_RANGE: return "FLOW_STEERING_IB_UC_QP_RANGE";
- default: return "OTHER";
- }
-}
-
-static u8 mlx4_errno_to_status(int errno)
-{
- switch (errno) {
- case -EPERM:
- return CMD_STAT_BAD_OP;
- case -EINVAL:
- return CMD_STAT_BAD_PARAM;
- case -ENXIO:
- return CMD_STAT_BAD_SYS_STATE;
- case -EBUSY:
- return CMD_STAT_RESOURCE_BUSY;
- case -ENOMEM:
- return CMD_STAT_EXCEED_LIM;
- case -ENFILE:
- return CMD_STAT_ICM_ERROR;
- default:
- return CMD_STAT_INTERNAL_ERR;
- }
-}
-
-static int comm_pending(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- u32 status = readl(&priv->mfunc.comm->slave_read);
-
- return (swab32(status) >> 31) != priv->cmd.comm_toggle;
-}
-
-static void mlx4_comm_cmd_post(struct mlx4_dev *dev, u8 cmd, u16 param)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- u32 val;
-
- priv->cmd.comm_toggle ^= 1;
- val = param | (cmd << 16) | (priv->cmd.comm_toggle << 31);
- __raw_writel((__force u32) cpu_to_be32(val),
- &priv->mfunc.comm->slave_write);
- mmiowb();
-}
-
-static int mlx4_comm_cmd_poll(struct mlx4_dev *dev, u8 cmd, u16 param,
- unsigned long timeout)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- unsigned long end;
- int err = 0;
- int ret_from_pending = 0;
-
- /* First, verify that the master reports correct status */
- if (comm_pending(dev)) {
- mlx4_warn(dev, "Communication channel is not idle."
- "my toggle is %d (cmd:0x%x)\n",
- priv->cmd.comm_toggle, cmd);
- return -EAGAIN;
- }
-
- /* Write command */
- down(&priv->cmd.poll_sem);
- mlx4_comm_cmd_post(dev, cmd, param);
-
- end = msecs_to_jiffies(timeout) + jiffies;
- while (comm_pending(dev) && time_before(jiffies, end))
- cond_resched();
- ret_from_pending = comm_pending(dev);
- if (ret_from_pending) {
- /* check if the slave is trying to boot in the middle of
- * FLR process. The only non-zero result in the RESET command
- * is MLX4_DELAY_RESET_SLAVE*/
- if ((MLX4_COMM_CMD_RESET == cmd)) {
- mlx4_warn(dev, "Got slave FLRed from Communication"
- " channel (ret:0x%x)\n", ret_from_pending);
- err = MLX4_DELAY_RESET_SLAVE;
- } else {
- mlx4_warn(dev, "Communication channel timed out\n");
- err = -ETIMEDOUT;
- }
- }
-
- up(&priv->cmd.poll_sem);
- return err;
-}
-
-static int mlx4_comm_cmd_wait(struct mlx4_dev *dev, u8 op,
- u16 param, unsigned long timeout)
-{
- struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
- struct mlx4_cmd_context *context;
- unsigned long end;
- int err = 0;
-
- down(&cmd->event_sem);
-
- end = msecs_to_jiffies(timeout) + jiffies;
- while (comm_pending(dev) && time_before(jiffies, end))
- cond_resched();
- if (comm_pending(dev)) {
- mlx4_warn(dev, "mlx4_comm_cmd_wait: Comm channel "
- "is not idle. My toggle is %d (op: 0x%x)\n",
- mlx4_priv(dev)->cmd.comm_toggle, op);
- up(&cmd->event_sem);
- return -EAGAIN;
- }
-
- spin_lock(&cmd->context_lock);
- BUG_ON(cmd->free_head < 0);
- context = &cmd->context[cmd->free_head];
- context->token += cmd->token_mask + 1;
- cmd->free_head = context->next;
- spin_unlock(&cmd->context_lock);
-
- init_completion(&context->done);
-
- mlx4_comm_cmd_post(dev, op, param);
-
- /* In slave, wait unconditionally for completion */
- wait_for_completion(&context->done);
-
- err = context->result;
- if (err && context->fw_status != CMD_STAT_MULTI_FUNC_REQ) {
- mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n",
- op, context->fw_status);
- goto out;
- }
-
-out:
- /* wait for comm channel ready
- * this is necessary for prevention the race
- * when switching between event to polling mode
- */
- end = msecs_to_jiffies(timeout) + jiffies;
- while (comm_pending(dev) && time_before(jiffies, end))
- cond_resched();
-
- spin_lock(&cmd->context_lock);
- context->next = cmd->free_head;
- cmd->free_head = context - cmd->context;
- spin_unlock(&cmd->context_lock);
-
- up(&cmd->event_sem);
- return err;
-}
-
-int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param,
- unsigned long timeout)
-{
- if (mlx4_priv(dev)->cmd.use_events)
- return mlx4_comm_cmd_wait(dev, cmd, param, timeout);
- return mlx4_comm_cmd_poll(dev, cmd, param, timeout);
-}
-
-static int cmd_pending(struct mlx4_dev *dev)
-{
- u32 status;
-
- if (pci_channel_offline(dev->pdev))
- return -EIO;
-
- status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
-
- return (status & swab32(1 << HCR_GO_BIT)) ||
- (mlx4_priv(dev)->cmd.toggle ==
- !!(status & swab32(1 << HCR_T_BIT)));
-}
-
-static int get_status(struct mlx4_dev *dev, u32 *status, int *go_bit,
- int *t_bit)
-{
- if (pci_channel_offline(dev->pdev))
- return -EIO;
-
- *status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
- *t_bit = !!(*status & swab32(1 << HCR_T_BIT));
- *go_bit = !!(*status & swab32(1 << HCR_GO_BIT));
-
- return 0;
-}
-
-static int mlx4_cmd_post(struct mlx4_dev *dev, struct timespec *ts1,
- u64 in_param, u64 out_param, u32 in_modifier,
- u8 op_modifier, u16 op, u16 token, int event)
-{
- struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
- u32 __iomem *hcr = cmd->hcr;
- int ret = -EAGAIN;
- unsigned long end;
- int err, go_bit = 0, t_bit = 0;
- u32 status = 0;
-
- mutex_lock(&cmd->hcr_mutex);
-
- if (pci_channel_offline(dev->pdev)) {
- /*
- * Device is going through error recovery
- * and cannot accept commands.
- */
- ret = -EIO;
- goto out;
- }
-
- end = jiffies;
- if (event)
- end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS);
-
- while (cmd_pending(dev)) {
- if (pci_channel_offline(dev->pdev)) {
- /*
- * Device is going through error recovery
- * and cannot accept commands.
- */
- ret = -EIO;
- goto out;
- }
-
- if (time_after_eq(jiffies, end)) {
- mlx4_err(dev, "%s:cmd_pending failed\n", __func__);
- goto out;
- }
- cond_resched();
- }
-
- /*
- * We use writel (instead of something like memcpy_toio)
- * because writes of less than 32 bits to the HCR don't work
- * (and some architectures such as ia64 implement memcpy_toio
- * in terms of writeb).
- */
- __raw_writel((__force u32) cpu_to_be32(in_param >> 32), hcr + 0);
- __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), hcr + 1);
- __raw_writel((__force u32) cpu_to_be32(in_modifier), hcr + 2);
- __raw_writel((__force u32) cpu_to_be32(out_param >> 32), hcr + 3);
- __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4);
- __raw_writel((__force u32) cpu_to_be32(token << 16), hcr + 5);
-
- if (ts1)
- ktime_get_ts(ts1);
-
- /* __raw_writel may not order writes. */
- wmb();
-
- __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
- (cmd->toggle << HCR_T_BIT) |
- (event ? (1 << HCR_E_BIT) : 0) |
- (op_modifier << HCR_OPMOD_SHIFT) |
- op), hcr + 6);
-
- /*
- * Make sure that our HCR writes don't get mixed in with
- * writes from another CPU starting a FW command.
- */
- mmiowb();
-
- cmd->toggle = cmd->toggle ^ 1;
-
- ret = 0;
-
-out:
- if (ret) {
- err = get_status(dev, &status, &go_bit, &t_bit);
- mlx4_warn(dev, "Could not post command %s (0x%x): ret=%d, "
- "in_param=0x%llx, in_mod=0x%x, op_mod=0x%x, "
- "get_status err=%d, status_reg=0x%x, go_bit=%d, "
- "t_bit=%d, toggle=0x%x\n", cmd_to_str(op), op, ret,
- (unsigned long long) in_param, in_modifier, op_modifier, err, status,
- go_bit, t_bit, cmd->toggle);
- }
- mutex_unlock(&cmd->hcr_mutex);
- return ret;
-}
-
-static int mlx4_slave_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
- int out_is_imm, u32 in_modifier, u8 op_modifier,
- u16 op, unsigned long timeout)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_vhcr_cmd *vhcr = priv->mfunc.vhcr;
- int ret;
-
- mutex_lock(&priv->cmd.slave_cmd_mutex);
-
- vhcr->in_param = cpu_to_be64(in_param);
- vhcr->out_param = out_param ? cpu_to_be64(*out_param) : 0;
- vhcr->in_modifier = cpu_to_be32(in_modifier);
- vhcr->opcode = cpu_to_be16((((u16) op_modifier) << 12) | (op & 0xfff));
- vhcr->token = cpu_to_be16(CMD_POLL_TOKEN);
- vhcr->status = 0;
- vhcr->flags = !!(priv->cmd.use_events) << 6;
-
- if (mlx4_is_master(dev)) {
- ret = mlx4_master_process_vhcr(dev, dev->caps.function, vhcr);
- if (!ret) {
- if (out_is_imm) {
- if (out_param)
- *out_param =
- be64_to_cpu(vhcr->out_param);
- else {
- mlx4_err(dev, "response expected while"
- "output mailbox is NULL for "
- "command 0x%x\n", op);
- vhcr->status = CMD_STAT_BAD_PARAM;
- }
- }
- ret = mlx4_status_to_errno(vhcr->status);
- }
- } else {
- ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0,
- MLX4_COMM_TIME + timeout);
- if (!ret) {
- if (out_is_imm) {
- if (out_param)
- *out_param =
- be64_to_cpu(vhcr->out_param);
- else {
- mlx4_err(dev, "response expected while"
- "output mailbox is NULL for "
- "command 0x%x\n", op);
- vhcr->status = CMD_STAT_BAD_PARAM;
- }
- }
- ret = mlx4_status_to_errno(vhcr->status);
- } else
- mlx4_err(dev, "failed execution of VHCR_POST command"
- "opcode %s (0x%x)\n", cmd_to_str(op), op);
- }
-
- mutex_unlock(&priv->cmd.slave_cmd_mutex);
- return ret;
-}
-
-static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
- int out_is_imm, u32 in_modifier, u8 op_modifier,
- u16 op, unsigned long timeout)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- void __iomem *hcr = priv->cmd.hcr;
- int err = 0;
- unsigned long end;
- u32 stat;
-
- down(&priv->cmd.poll_sem);
-
- if (pci_channel_offline(dev->pdev)) {
- /*
- * Device is going through error recovery
- * and cannot accept commands.
- */
- err = -EIO;
- goto out;
- }
-
- err = mlx4_cmd_post(dev, NULL, in_param, out_param ? *out_param : 0,
- in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0);
- if (err)
- goto out;
-
- end = msecs_to_jiffies(timeout) + jiffies;
- while (cmd_pending(dev) && time_before(jiffies, end)) {
- if (pci_channel_offline(dev->pdev)) {
- /*
- * Device is going through error recovery
- * and cannot accept commands.
- */
- err = -EIO;
- goto out;
- }
-
- cond_resched();
- }
-
- if (cmd_pending(dev)) {
- mlx4_warn(dev, "command %s (0x%x) timed out (go bit not cleared)\n",
- cmd_to_str(op), op);
- err = -ETIMEDOUT;
- goto out;
- }
-
- if (out_is_imm)
- *out_param =
- (u64) be32_to_cpu((__force __be32)
- __raw_readl(hcr + HCR_OUT_PARAM_OFFSET)) << 32 |
- (u64) be32_to_cpu((__force __be32)
- __raw_readl(hcr + HCR_OUT_PARAM_OFFSET + 4));
- stat = be32_to_cpu((__force __be32)
- __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24;
- err = mlx4_status_to_errno(stat);
- if (err)
- mlx4_err(dev, "command %s (0x%x) failed: fw status = 0x%x\n",
- cmd_to_str(op), op, stat);
-
-out:
- up(&priv->cmd.poll_sem);
- return err;
-}
-
-void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_context *context =
- &priv->cmd.context[token & priv->cmd.token_mask];
-
- /* previously timed out command completing at long last */
- if (token != context->token)
- return;
-
- context->fw_status = status;
- context->result = mlx4_status_to_errno(status);
- context->out_param = out_param;
-
- complete(&context->done);
-}
-
-static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
- int out_is_imm, u32 in_modifier, u8 op_modifier,
- u16 op, unsigned long timeout)
-{
- struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
- struct mlx4_cmd_context *context;
- int err = 0;
- int go_bit = 0, t_bit = 0, stat_err;
- u32 status = 0;
- struct timespec ts1, ts2;
- ktime_t t1, t2, delta;
- s64 ds;
-
- if (out_is_imm && !out_param)
- return -EINVAL;
-
- down(&cmd->event_sem);
-
- spin_lock(&cmd->context_lock);
- BUG_ON(cmd->free_head < 0);
- context = &cmd->context[cmd->free_head];
- context->token += cmd->token_mask + 1;
- cmd->free_head = context->next;
- spin_unlock(&cmd->context_lock);
-
- init_completion(&context->done);
-
- err = mlx4_cmd_post(dev, &ts1, in_param, out_param ? *out_param : 0,
- in_modifier, op_modifier, op, context->token, 1);
- if (err)
- goto out;
-
- if (!wait_for_completion_timeout(&context->done,
- msecs_to_jiffies(timeout))) {
- stat_err = get_status(dev, &status, &go_bit, &t_bit);
- mlx4_warn(dev, "command %s (0x%x) timed out: in_param=0x%llx, "
- "in_mod=0x%x, op_mod=0x%x, get_status err=%d, "
- "status_reg=0x%x, go_bit=%d, t_bit=%d, toggle=0x%x\n"
- , cmd_to_str(op), op, (unsigned long long) in_param, in_modifier,
- op_modifier, stat_err, status, go_bit, t_bit,
- mlx4_priv(dev)->cmd.toggle);
- err = -EBUSY;
- goto out;
- }
- if (mlx4_debug_level & MLX4_DEBUG_MASK_CMD_TIME) {
- ktime_get_ts(&ts2);
- t1 = timespec_to_ktime(ts1);
- t2 = timespec_to_ktime(ts2);
- delta = ktime_sub(t2, t1);
- ds = ktime_to_ns(delta);
- pr_info("mlx4: fw exec time for %s is %lld nsec\n", cmd_to_str(op), (long long) ds);
- }
-
- err = context->result;
- if (err) {
- mlx4_err(dev, "command %s (0x%x) failed: in_param=0x%llx, "
- "in_mod=0x%x, op_mod=0x%x, fw status = 0x%x\n",
- cmd_to_str(op), op, (unsigned long long) in_param, in_modifier,
- op_modifier, context->fw_status);
-
- switch(context->fw_status) {
- case CMD_STAT_BAD_PARAM:
- mlx4_err(dev, "Parameter is not supported, "
- "parameter is out of range\n");
- break;
- case CMD_STAT_EXCEED_LIM:
- mlx4_err(dev, "Required capability exceeded "
- "device limits\n");
- break;
- default:
- break;
- }
- goto out;
- }
-
- if (out_is_imm)
- *out_param = context->out_param;
-
-out:
- spin_lock(&cmd->context_lock);
- context->next = cmd->free_head;
- cmd->free_head = context - cmd->context;
- spin_unlock(&cmd->context_lock);
-
- up(&cmd->event_sem);
- return err;
-}
-
-int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
- int out_is_imm, u32 in_modifier, u8 op_modifier,
- u16 op, unsigned long timeout, int native)
-{
- if (pci_channel_offline(dev->pdev))
- return -EIO;
-
- if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) {
- if (mlx4_priv(dev)->cmd.use_events)
- return mlx4_cmd_wait(dev, in_param, out_param,
- out_is_imm, in_modifier,
- op_modifier, op, timeout);
- else
- return mlx4_cmd_poll(dev, in_param, out_param,
- out_is_imm, in_modifier,
- op_modifier, op, timeout);
- }
- return mlx4_slave_cmd(dev, in_param, out_param, out_is_imm,
- in_modifier, op_modifier, op, timeout);
-}
-EXPORT_SYMBOL_GPL(__mlx4_cmd);
-
-
-static int mlx4_ARM_COMM_CHANNEL(struct mlx4_dev *dev)
-{
- return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_ARM_COMM_CHANNEL,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-}
-
-static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr,
- int slave, u64 slave_addr,
- int size, int is_read)
-{
- u64 in_param;
- u64 out_param;
-
- if ((slave_addr & 0xfff) | (master_addr & 0xfff) |
- (slave & ~0x7f) | (size & 0xff)) {
- mlx4_err(dev, "Bad access mem params - slave_addr:0x%llx "
- "master_addr:0x%llx slave_id:%d size:%d\n",
- (unsigned long long) slave_addr, (unsigned long long) master_addr, slave, size);
- return -EINVAL;
- }
-
- if (is_read) {
- in_param = (u64) slave | slave_addr;
- out_param = (u64) dev->caps.function | master_addr;
- } else {
- in_param = (u64) dev->caps.function | master_addr;
- out_param = (u64) slave | slave_addr;
- }
-
- return mlx4_cmd_imm(dev, in_param, &out_param, size, 0,
- MLX4_CMD_ACCESS_MEM,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-}
-
-static int query_pkey_block(struct mlx4_dev *dev, u8 port, u16 index, u16 *pkey,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox)
-{
- struct ib_smp *in_mad = (struct ib_smp *)(inbox->buf);
- struct ib_smp *out_mad = (struct ib_smp *)(outbox->buf);
- int err;
- int i;
-
- if (index & 0x1f)
- return -EINVAL;
-
- in_mad->attr_mod = cpu_to_be32(index / 32);
-
- err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
- MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
- MLX4_CMD_NATIVE);
- if (err)
- return err;
-
- for (i = 0; i < 32; ++i)
- pkey[i] = be16_to_cpu(((__be16 *) out_mad->data)[i]);
-
- return err;
-}
-
-static int get_full_pkey_table(struct mlx4_dev *dev, u8 port, u16 *table,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox)
-{
- int i;
- int err;
-
- for (i = 0; i < dev->caps.pkey_table_len[port]; i += 32) {
- err = query_pkey_block(dev, port, i, table + i, inbox, outbox);
- if (err)
- return err;
- }
-
- return 0;
-}
-#define PORT_CAPABILITY_LOCATION_IN_SMP 20
-#define PORT_STATE_OFFSET 32
-
-static enum ib_port_state vf_port_state(struct mlx4_dev *dev, int port, int vf)
-{
- if (mlx4_get_slave_port_state(dev, vf, port) == SLAVE_PORT_UP)
- return IB_PORT_ACTIVE;
- else
- return IB_PORT_DOWN;
-}
-
-static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct ib_smp *smp = inbox->buf;
- u32 index;
- u8 port;
- u16 *table;
- int err;
- int vidx, pidx;
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct ib_smp *outsmp = outbox->buf;
- __be16 *outtab = (__be16 *)(outsmp->data);
- __be32 slave_cap_mask;
- __be64 slave_node_guid;
- port = vhcr->in_modifier;
-
- if (smp->base_version == 1 &&
- smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
- smp->class_version == 1) {
- if (smp->method == IB_MGMT_METHOD_GET) {
- if (smp->attr_id == IB_SMP_ATTR_PKEY_TABLE) {
- index = be32_to_cpu(smp->attr_mod);
- if (port < 1 || port > dev->caps.num_ports)
- return -EINVAL;
- table = kcalloc(dev->caps.pkey_table_len[port], sizeof *table, GFP_KERNEL);
- if (!table)
- return -ENOMEM;
- /* need to get the full pkey table because the paravirtualized
- * pkeys may be scattered among several pkey blocks.
- */
- err = get_full_pkey_table(dev, port, table, inbox, outbox);
- if (!err) {
- for (vidx = index * 32; vidx < (index + 1) * 32; ++vidx) {
- pidx = priv->virt2phys_pkey[slave][port - 1][vidx];
- outtab[vidx % 32] = cpu_to_be16(table[pidx]);
- }
- }
- kfree(table);
- return err;
- }
- if (smp->attr_id == IB_SMP_ATTR_PORT_INFO) {
- /*get the slave specific caps:*/
- /*do the command */
- err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
- vhcr->in_modifier, vhcr->op_modifier,
- vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
- /* modify the response for slaves */
- if (!err && slave != mlx4_master_func_num(dev)) {
- u8 *state = outsmp->data + PORT_STATE_OFFSET;
-
- *state = (*state & 0xf0) | vf_port_state(dev, port, slave);
- slave_cap_mask = priv->mfunc.master.slave_state[slave].ib_cap_mask[port];
- memcpy(outsmp->data + PORT_CAPABILITY_LOCATION_IN_SMP, &slave_cap_mask, 4);
- }
- return err;
- }
- if (smp->attr_id == IB_SMP_ATTR_GUID_INFO) {
- /* compute slave's gid block */
- smp->attr_mod = cpu_to_be32(slave / 8);
- /* execute cmd */
- err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
- vhcr->in_modifier, vhcr->op_modifier,
- vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
- if (!err) {
- /* if needed, move slave gid to index 0 */
- if (slave % 8)
- memcpy(outsmp->data,
- outsmp->data + (slave % 8) * 8, 8);
- /* delete all other gids */
- memset(outsmp->data + 8, 0, 56);
- }
- return err;
- }
- if (smp->attr_id == IB_SMP_ATTR_NODE_INFO) {
- err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
- vhcr->in_modifier, vhcr->op_modifier,
- vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
- if (!err) {
- slave_node_guid = mlx4_get_slave_node_guid(dev, slave);
- memcpy(outsmp->data + 12, &slave_node_guid, 8);
- }
- return err;
- }
- }
- }
- if (slave != mlx4_master_func_num(dev) &&
- ((smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) ||
- (smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
- smp->method == IB_MGMT_METHOD_SET))) {
- mlx4_err(dev, "slave %d is trying to execute a Subnet MGMT MAD, "
- "class 0x%x, method 0x%x for attr 0x%x. Rejecting\n",
- slave, smp->method, smp->mgmt_class,
- be16_to_cpu(smp->attr_id));
- return -EPERM;
- }
- /*default:*/
- return mlx4_cmd_box(dev, inbox->dma, outbox->dma,
- vhcr->in_modifier, vhcr->op_modifier,
- vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
-}
-
-static int MLX4_CMD_DIAG_RPRT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- return -EPERM;
-}
-
-static int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- return -EPERM;
-}
-
-int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- u64 in_param;
- u64 out_param;
- int err;
-
- in_param = cmd->has_inbox ? (u64) inbox->dma : vhcr->in_param;
- out_param = cmd->has_outbox ? (u64) outbox->dma : vhcr->out_param;
- if (cmd->encode_slave_id) {
- in_param &= 0xffffffffffffff00ll;
- in_param |= slave;
- }
-
- err = __mlx4_cmd(dev, in_param, &out_param, cmd->out_is_imm,
- vhcr->in_modifier, vhcr->op_modifier, vhcr->op,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-
- if (cmd->out_is_imm)
- vhcr->out_param = out_param;
-
- return err;
-}
-
-static struct mlx4_cmd_info cmd_info[] = {
- {
- .opcode = MLX4_CMD_QUERY_FW,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_FW_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_HCA,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = NULL
- },
- {
- .opcode = MLX4_CMD_QUERY_DEV_CAP,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_DEV_CAP_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_FUNC_CAP,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_FUNC_CAP_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_ADAPTER,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = NULL
- },
- {
- .opcode = MLX4_CMD_INIT_PORT,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_INIT_PORT_wrapper
- },
- {
- .opcode = MLX4_CMD_CLOSE_PORT,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_CLOSE_PORT_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_PORT,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_PORT_wrapper
- },
- {
- .opcode = MLX4_CMD_SET_PORT,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_SET_PORT_wrapper
- },
- {
- .opcode = MLX4_CMD_MAP_EQ,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_MAP_EQ_wrapper
- },
- {
- .opcode = MLX4_CMD_SW2HW_EQ,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = true,
- .verify = NULL,
- .wrapper = mlx4_SW2HW_EQ_wrapper
- },
- {
- .opcode = MLX4_CMD_HW_HEALTH_CHECK,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = NULL
- },
- {
- .opcode = MLX4_CMD_DIAG_RPRT,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .skip_err_print = true,
- .verify = NULL,
- .wrapper = MLX4_CMD_DIAG_RPRT_wrapper
- },
- {
- .opcode = MLX4_CMD_NOP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = NULL
- },
- {
- .opcode = MLX4_CMD_ALLOC_RES,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = true,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_ALLOC_RES_wrapper
- },
- {
- .opcode = MLX4_CMD_FREE_RES,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_FREE_RES_wrapper
- },
- {
- .opcode = MLX4_CMD_SW2HW_MPT,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = true,
- .verify = NULL,
- .wrapper = mlx4_SW2HW_MPT_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_MPT,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_MPT_wrapper
- },
- {
- .opcode = MLX4_CMD_HW2SW_MPT,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_HW2SW_MPT_wrapper
- },
- {
- .opcode = MLX4_CMD_READ_MTT,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = NULL
- },
- {
- .opcode = MLX4_CMD_WRITE_MTT,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_WRITE_MTT_wrapper
- },
- {
- .opcode = MLX4_CMD_SYNC_TPT,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = NULL
- },
- {
- .opcode = MLX4_CMD_HW2SW_EQ,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = true,
- .verify = NULL,
- .wrapper = mlx4_HW2SW_EQ_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_EQ,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = true,
- .verify = NULL,
- .wrapper = mlx4_QUERY_EQ_wrapper
- },
- {
- .opcode = MLX4_CMD_SW2HW_CQ,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = true,
- .verify = NULL,
- .wrapper = mlx4_SW2HW_CQ_wrapper
- },
- {
- .opcode = MLX4_CMD_HW2SW_CQ,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_HW2SW_CQ_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_CQ,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_CQ_wrapper
- },
- {
- .opcode = MLX4_CMD_MODIFY_CQ,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = true,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_MODIFY_CQ_wrapper
- },
- {
- .opcode = MLX4_CMD_SW2HW_SRQ,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = true,
- .verify = NULL,
- .wrapper = mlx4_SW2HW_SRQ_wrapper
- },
- {
- .opcode = MLX4_CMD_HW2SW_SRQ,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_HW2SW_SRQ_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_SRQ,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_SRQ_wrapper
- },
- {
- .opcode = MLX4_CMD_ARM_SRQ,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_ARM_SRQ_wrapper
- },
- {
- .opcode = MLX4_CMD_RST2INIT_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = true,
- .verify = NULL,
- .wrapper = mlx4_RST2INIT_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_INIT2INIT_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_INIT2INIT_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_INIT2RTR_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_INIT2RTR_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_RTR2RTS_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_RTR2RTS_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_RTS2RTS_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_RTS2RTS_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_SQERR2RTS_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_SQERR2RTS_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_2ERR_QP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_GEN_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_RTS2SQD_QP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_GEN_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_SQD2SQD_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_SQD2SQD_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_SQD2RTS_QP,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_SQD2RTS_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_2RST_QP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_2RST_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_QP,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_GEN_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_SUSPEND_QP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_GEN_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_UNSUSPEND_QP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_GEN_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_UPDATE_QP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .skip_err_print = true,
- .verify = NULL,
- .wrapper = MLX4_CMD_UPDATE_QP_wrapper
- },
- {
- .opcode = MLX4_CMD_CONF_SPECIAL_QP,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL, /* XXX verify: only demux can do this */
- .wrapper = NULL
- },
- {
- .opcode = MLX4_CMD_MAD_IFC,
- .has_inbox = true,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_MAD_IFC_wrapper
- },
- {
- .opcode = MLX4_CMD_QUERY_IF_STAT,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QUERY_IF_STAT_wrapper
- },
- /* Native multicast commands are not available for guests */
- {
- .opcode = MLX4_CMD_QP_ATTACH,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QP_ATTACH_wrapper
- },
- {
- .opcode = MLX4_CMD_PROMISC,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_PROMISC_wrapper
- },
- /* Ethernet specific commands */
- {
- .opcode = MLX4_CMD_SET_VLAN_FLTR,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_SET_VLAN_FLTR_wrapper
- },
- {
- .opcode = MLX4_CMD_SET_MCAST_FLTR,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_SET_MCAST_FLTR_wrapper
- },
- {
- .opcode = MLX4_CMD_DUMP_ETH_STATS,
- .has_inbox = false,
- .has_outbox = true,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_DUMP_ETH_STATS_wrapper
- },
- {
- .opcode = MLX4_CMD_INFORM_FLR_DONE,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = NULL
- },
- /* flow steering commands */
- {
- .opcode = MLX4_QP_FLOW_STEERING_ATTACH,
- .has_inbox = true,
- .has_outbox = false,
- .out_is_imm = true,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QP_FLOW_STEERING_ATTACH_wrapper
- },
- {
- .opcode = MLX4_QP_FLOW_STEERING_DETACH,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .verify = NULL,
- .wrapper = mlx4_QP_FLOW_STEERING_DETACH_wrapper
- },
- /* wol commands */
- {
- .opcode = MLX4_CMD_MOD_STAT_CFG,
- .has_inbox = false,
- .has_outbox = false,
- .out_is_imm = false,
- .encode_slave_id = false,
- .skip_err_print = true,
- .verify = NULL,
- .wrapper = mlx4_MOD_STAT_CFG_wrapper
- },
-};
-
-static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr_cmd *in_vhcr)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_info *cmd = NULL;
- struct mlx4_vhcr_cmd *vhcr_cmd = in_vhcr ? in_vhcr : priv->mfunc.vhcr;
- struct mlx4_vhcr *vhcr;
- struct mlx4_cmd_mailbox *inbox = NULL;
- struct mlx4_cmd_mailbox *outbox = NULL;
- u64 in_param;
- u64 out_param;
- int ret = 0;
- int i;
- int err = 0;
-
- /* Create sw representation of Virtual HCR */
- vhcr = kzalloc(sizeof(struct mlx4_vhcr), GFP_KERNEL);
- if (!vhcr)
- return -ENOMEM;
-
- /* DMA in the vHCR */
- if (!in_vhcr) {
- ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave,
- priv->mfunc.master.slave_state[slave].vhcr_dma,
- ALIGN(sizeof(struct mlx4_vhcr_cmd),
- MLX4_ACCESS_MEM_ALIGN), 1);
- if (ret) {
- mlx4_err(dev, "%s:Failed reading vhcr"
- "ret: 0x%x\n", __func__, ret);
- kfree(vhcr);
- return ret;
- }
- }
-
- /* Fill SW VHCR fields */
- vhcr->in_param = be64_to_cpu(vhcr_cmd->in_param);
- vhcr->out_param = be64_to_cpu(vhcr_cmd->out_param);
- vhcr->in_modifier = be32_to_cpu(vhcr_cmd->in_modifier);
- vhcr->token = be16_to_cpu(vhcr_cmd->token);
- vhcr->op = be16_to_cpu(vhcr_cmd->opcode) & 0xfff;
- vhcr->op_modifier = (u8) (be16_to_cpu(vhcr_cmd->opcode) >> 12);
- vhcr->e_bit = vhcr_cmd->flags & (1 << 6);
-
- /* Lookup command */
- for (i = 0; i < ARRAY_SIZE(cmd_info); ++i) {
- if (vhcr->op == cmd_info[i].opcode) {
- cmd = &cmd_info[i];
- break;
- }
- }
- if (!cmd) {
- mlx4_err(dev, "unparavirt command: %s (0x%x) accepted from slave:%d\n",
- cmd_to_str(vhcr->op), vhcr->op, slave);
- vhcr_cmd->status = CMD_STAT_BAD_PARAM;
- goto out_status;
- }
-
- /* Read inbox */
- if (cmd->has_inbox) {
- vhcr->in_param &= INBOX_MASK;
- inbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(inbox)) {
- vhcr_cmd->status = CMD_STAT_BAD_SIZE;
- inbox = NULL;
- goto out_status;
- }
-
- if (mlx4_ACCESS_MEM(dev, inbox->dma, slave,
- vhcr->in_param,
- MLX4_MAILBOX_SIZE, 1)) {
- mlx4_err(dev, "%s: Failed reading inbox for cmd %s (0x%x)\n",
- __func__, cmd_to_str(cmd->opcode), cmd->opcode);
- vhcr_cmd->status = CMD_STAT_INTERNAL_ERR;
- goto out_status;
- }
- }
-
- /* Apply permission and bound checks if applicable */
- if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) {
- mlx4_warn(dev, "Command %s (0x%x) from slave: %d failed protection "
- "checks for resource_id: %d\n", cmd_to_str(vhcr->op),
- vhcr->op, slave, vhcr->in_modifier);
- vhcr_cmd->status = CMD_STAT_BAD_OP;
- goto out_status;
- }
-
- /* Allocate outbox */
- if (cmd->has_outbox) {
- outbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(outbox)) {
- vhcr_cmd->status = CMD_STAT_BAD_SIZE;
- outbox = NULL;
- goto out_status;
- }
- }
-
- /* Execute the command! */
- if (cmd->wrapper) {
- err = cmd->wrapper(dev, slave, vhcr, inbox, outbox,
- cmd);
- if (cmd->out_is_imm)
- vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param);
- } else {
- in_param = cmd->has_inbox ? (u64) inbox->dma :
- vhcr->in_param;
- out_param = cmd->has_outbox ? (u64) outbox->dma :
- vhcr->out_param;
- err = __mlx4_cmd(dev, in_param, &out_param,
- cmd->out_is_imm, vhcr->in_modifier,
- vhcr->op_modifier, vhcr->op,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
-
- if (cmd->out_is_imm) {
- vhcr->out_param = out_param;
- vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param);
- }
- }
-
- if (err) {
- if (!cmd->skip_err_print)
- mlx4_warn(dev, "vhcr command %s (0x%x) slave:%d "
- "in_param 0x%llx in_mod=0x%x, op_mod=0x%x "
- "failed with error:%d, status %d\n",
- cmd_to_str(vhcr->op), vhcr->op, slave,
- (unsigned long long) vhcr->in_param, vhcr->in_modifier,
- vhcr->op_modifier, vhcr->errno, err);
- vhcr_cmd->status = mlx4_errno_to_status(err);
- goto out_status;
- }
-
-
- /* Write outbox if command completed successfully */
- if (cmd->has_outbox && !vhcr_cmd->status) {
- ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave,
- vhcr->out_param,
- MLX4_MAILBOX_SIZE, MLX4_CMD_WRAPPED);
- if (ret) {
- /* If we failed to write back the outbox after the
- *command was successfully executed, we must fail this
- * slave, as it is now in undefined state */
- mlx4_err(dev, "%s: Failed writing outbox\n", __func__);
- goto out;
- }
- }
-
-out_status:
- /* DMA back vhcr result */
- if (!in_vhcr) {
- ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave,
- priv->mfunc.master.slave_state[slave].vhcr_dma,
- ALIGN(sizeof(struct mlx4_vhcr),
- MLX4_ACCESS_MEM_ALIGN),
- MLX4_CMD_WRAPPED);
- if (ret)
- mlx4_err(dev, "%s:Failed writing vhcr result\n",
- __func__);
- else if (vhcr->e_bit &&
- mlx4_GEN_EQE(dev, slave, &priv->mfunc.master.cmd_eqe))
- mlx4_warn(dev, "Failed to generate command completion "
- "eqe for slave %d\n", slave);
- }
-
-out:
- kfree(vhcr);
- mlx4_free_cmd_mailbox(dev, inbox);
- mlx4_free_cmd_mailbox(dev, outbox);
- return ret;
-}
-
-static int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
- int slave, int port)
-{
- struct mlx4_vport_oper_state *vp_oper;
- struct mlx4_vport_state *vp_admin;
- struct mlx4_vf_immed_vlan_work *work;
- int err;
- int admin_vlan_ix = NO_INDX;
-
- vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
- vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
-
- if (vp_oper->state.default_vlan == vp_admin->default_vlan &&
- vp_oper->state.default_qos == vp_admin->default_qos)
- return 0;
-
- work = kzalloc(sizeof(*work), GFP_KERNEL);
- if (!work)
- return -ENOMEM;
-
- if (vp_oper->state.default_vlan != vp_admin->default_vlan) {
- if (MLX4_VGT != vp_admin->default_vlan) {
- err = __mlx4_register_vlan(&priv->dev, port,
- vp_admin->default_vlan,
- &admin_vlan_ix);
- if (err) {
- mlx4_warn((&priv->dev),
- "No vlan resources slave %d, port %d\n",
- slave, port);
- kfree(work);
- return err;
- }
- } else {
- admin_vlan_ix = NO_INDX;
- }
- work->flags |= MLX4_VF_IMMED_VLAN_FLAG_VLAN;
- mlx4_dbg((&(priv->dev)),
- "alloc vlan %d idx %d slave %d port %d\n",
- (int)(vp_admin->default_vlan),
- admin_vlan_ix, slave, port);
- }
-
- /* save original vlan ix and vlan id */
- work->orig_vlan_id = vp_oper->state.default_vlan;
- work->orig_vlan_ix = vp_oper->vlan_idx;
-
- /* handle new qos */
- if (vp_oper->state.default_qos != vp_admin->default_qos)
- work->flags |= MLX4_VF_IMMED_VLAN_FLAG_QOS;
-
- if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN)
- vp_oper->vlan_idx = admin_vlan_ix;
-
- vp_oper->state.default_vlan = vp_admin->default_vlan;
- vp_oper->state.default_qos = vp_admin->default_qos;
-
- /* iterate over QPs owned by this slave, using UPDATE_QP */
- work->port = port;
- work->slave = slave;
- work->qos = vp_oper->state.default_qos;
- work->vlan_id = vp_oper->state.default_vlan;
- work->vlan_ix = vp_oper->vlan_idx;
- work->priv = priv;
- INIT_WORK(&work->work, mlx4_vf_immed_vlan_work_handler);
- queue_work(priv->mfunc.master.comm_wq, &work->work);
-
- return 0;
-}
-
-
-static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
-{
- int port, err;
- struct mlx4_vport_state *vp_admin;
- struct mlx4_vport_oper_state *vp_oper;
-
- for (port = 1; port <= MLX4_MAX_PORTS; port++) {
- vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
- vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
- vp_oper->state = *vp_admin;
- if (MLX4_VGT != vp_admin->default_vlan) {
- err = __mlx4_register_vlan(&priv->dev, port,
- vp_admin->default_vlan, &(vp_oper->vlan_idx));
- if (err) {
- vp_oper->vlan_idx = NO_INDX;
- mlx4_warn((&priv->dev),
- "No vlan resorces slave %d, port %d\n",
- slave, port);
- return err;
- }
- mlx4_dbg((&(priv->dev)), "alloc vlan %d idx %d slave %d port %d\n",
- (int)(vp_oper->state.default_vlan),
- vp_oper->vlan_idx, slave, port);
- }
- if (vp_admin->spoofchk) {
- vp_oper->mac_idx = __mlx4_register_mac(&priv->dev,
- port,
- vp_admin->mac);
- if (0 > vp_oper->mac_idx) {
- err = vp_oper->mac_idx;
- vp_oper->mac_idx = NO_INDX;
- mlx4_warn((&priv->dev),
- "No mac resources slave %d, port %d\n",
- slave, port);
- return err;
- }
- mlx4_dbg((&(priv->dev)), "alloc mac %llx idx %d slave %d port %d\n",
- (unsigned long long) vp_oper->state.mac, vp_oper->mac_idx, slave, port);
- }
- }
- return 0;
-}
-
-static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave)
-{
- int port;
- struct mlx4_vport_oper_state *vp_oper;
-
- for (port = 1; port <= MLX4_MAX_PORTS; port++) {
- vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
- if (NO_INDX != vp_oper->vlan_idx) {
- __mlx4_unregister_vlan(&priv->dev,
- port, vp_oper->state.default_vlan);
- vp_oper->vlan_idx = NO_INDX;
- }
- if (NO_INDX != vp_oper->mac_idx) {
- __mlx4_unregister_mac(&priv->dev, port, vp_oper->state.mac);
- vp_oper->mac_idx = NO_INDX;
- }
- }
- return;
-}
-
-static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
- u16 param, u8 toggle)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
- u32 reply;
- u8 is_going_down = 0;
- int i;
- unsigned long flags;
-
- slave_state[slave].comm_toggle ^= 1;
- reply = (u32) slave_state[slave].comm_toggle << 31;
- if (toggle != slave_state[slave].comm_toggle) {
- mlx4_warn(dev, "Incorrect toggle %d from slave %d. *** MASTER"
- "STATE COMPROMISIED ***\n", toggle, slave);
- goto reset_slave;
- }
- if (cmd == MLX4_COMM_CMD_RESET) {
- mlx4_warn(dev, "Received reset from slave:%d\n", slave);
- slave_state[slave].active = false;
- slave_state[slave].old_vlan_api = false;
- mlx4_master_deactivate_admin_state(priv, slave);
- for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
- slave_state[slave].event_eq[i].eqn = -1;
- slave_state[slave].event_eq[i].token = 0;
- }
- /*check if we are in the middle of FLR process,
- if so return "retry" status to the slave*/
- if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd)
- goto inform_slave_state;
-
- mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, slave);
-
- /* write the version in the event field */
- reply |= mlx4_comm_get_version();
-
- goto reset_slave;
- }
- /*command from slave in the middle of FLR*/
- if (cmd != MLX4_COMM_CMD_RESET &&
- MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
- mlx4_warn(dev, "slave:%d is Trying to run cmd (0x%x) "
- "in the middle of FLR\n", slave, cmd);
- return;
- }
-
- switch (cmd) {
- case MLX4_COMM_CMD_VHCR0:
- if (slave_state[slave].last_cmd != MLX4_COMM_CMD_RESET)
- goto reset_slave;
- slave_state[slave].vhcr_dma = ((u64) param) << 48;
- priv->mfunc.master.slave_state[slave].cookie = 0;
- break;
- case MLX4_COMM_CMD_VHCR1:
- if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0)
- goto reset_slave;
- slave_state[slave].vhcr_dma |= ((u64) param) << 32;
- break;
- case MLX4_COMM_CMD_VHCR2:
- if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR1)
- goto reset_slave;
- slave_state[slave].vhcr_dma |= ((u64) param) << 16;
- break;
- case MLX4_COMM_CMD_VHCR_EN:
- if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
- goto reset_slave;
- slave_state[slave].vhcr_dma |= param;
- if (mlx4_master_activate_admin_state(priv, slave))
- goto reset_slave;
- slave_state[slave].active = true;
- mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave);
- break;
- case MLX4_COMM_CMD_VHCR_POST:
- if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) &&
- (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_POST))
- goto reset_slave;
-
- mutex_lock(&priv->cmd.slave_cmd_mutex);
- if (mlx4_master_process_vhcr(dev, slave, NULL)) {
- mlx4_err(dev, "Failed processing vhcr for slave: %d,"
- " resetting slave.\n", slave);
- mutex_unlock(&priv->cmd.slave_cmd_mutex);
- goto reset_slave;
- }
- mutex_unlock(&priv->cmd.slave_cmd_mutex);
- break;
- default:
- mlx4_warn(dev, "Bad comm cmd: %d from slave: %d\n", cmd, slave);
- goto reset_slave;
- }
- spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
- if (!slave_state[slave].is_slave_going_down)
- slave_state[slave].last_cmd = cmd;
- else
- is_going_down = 1;
- spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
- if (is_going_down) {
- mlx4_warn(dev, "Slave is going down aborting command (%d)"
- " executing from slave: %d\n",
- cmd, slave);
- return;
- }
- __raw_writel((__force u32) cpu_to_be32(reply),
- &priv->mfunc.comm[slave].slave_read);
- mmiowb();
-
- return;
-
-reset_slave:
- /* cleanup any slave resources */
- mlx4_delete_all_resources_for_slave(dev, slave);
- spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
- if (!slave_state[slave].is_slave_going_down)
- slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET;
- spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
- /*with slave in the middle of flr, no need to clean resources again.*/
-inform_slave_state:
- __raw_writel((__force u32) cpu_to_be32(reply),
- &priv->mfunc.comm[slave].slave_read);
- wmb();
-}
-
-/* master command processing */
-void mlx4_master_comm_channel(struct work_struct *work)
-{
- struct mlx4_mfunc_master_ctx *master =
- container_of(work,
- struct mlx4_mfunc_master_ctx,
- comm_work);
- struct mlx4_mfunc *mfunc =
- container_of(master, struct mlx4_mfunc, master);
- struct mlx4_priv *priv =
- container_of(mfunc, struct mlx4_priv, mfunc);
- struct mlx4_dev *dev = &priv->dev;
- __be32 *bit_vec;
- u32 comm_cmd;
- u32 vec;
- int i, j, slave;
- int toggle;
- int served = 0;
- int reported = 0;
- u32 slt;
-
- bit_vec = master->comm_arm_bit_vector;
- for (i = 0; i < COMM_CHANNEL_BIT_ARRAY_SIZE; i++) {
- vec = be32_to_cpu(bit_vec[i]);
- for (j = 0; j < 32; j++) {
- if (!(vec & (1 << j)))
- continue;
- ++reported;
- slave = (i * 32) + j;
- comm_cmd = swab32(readl(
- &mfunc->comm[slave].slave_write));
- slt = swab32(readl(&mfunc->comm[slave].slave_read))
- >> 31;
- toggle = comm_cmd >> 31;
- if (toggle != slt) {
- if (master->slave_state[slave].comm_toggle
- != slt) {
- mlx4_info(dev, "slave %d out of sync."
- " read toggle %d, state toggle %d. "
- "Resynching.\n", slave, slt,
- master->slave_state[slave].comm_toggle);
- master->slave_state[slave].comm_toggle =
- slt;
- }
- mlx4_master_do_cmd(dev, slave,
- comm_cmd >> 16 & 0xff,
- comm_cmd & 0xffff, toggle);
- ++served;
- } else
- mlx4_err(dev, "slave %d out of sync."
- " read toggle %d, write toggle %d.\n", slave, slt,
- toggle);
- }
- }
-
- if (reported && reported != served)
- mlx4_warn(dev, "Got command event with bitmask from %d slaves"
- " but %d were served\n",
- reported, served);
-}
-/* master command processing */
-void mlx4_master_arm_comm_channel(struct work_struct *work)
-{
- struct mlx4_mfunc_master_ctx *master =
- container_of(work,
- struct mlx4_mfunc_master_ctx,
- arm_comm_work);
- struct mlx4_mfunc *mfunc =
- container_of(master, struct mlx4_mfunc, master);
- struct mlx4_priv *priv =
- container_of(mfunc, struct mlx4_priv, mfunc);
- struct mlx4_dev *dev = &priv->dev;
-
- if (mlx4_ARM_COMM_CHANNEL(dev))
- mlx4_warn(dev, "Failed to arm comm channel events\n");
-}
-
-static int sync_toggles(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int wr_toggle;
- int rd_toggle;
- unsigned long end;
-
- wr_toggle = swab32(readl(&priv->mfunc.comm->slave_write)) >> 31;
- end = jiffies + msecs_to_jiffies(5000);
-
- while (time_before(jiffies, end)) {
- rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)) >> 31;
- if (rd_toggle == wr_toggle) {
- priv->cmd.comm_toggle = rd_toggle;
- return 0;
- }
-
- cond_resched();
- }
-
- /*
- * we could reach here if for example the previous VM using this
- * function misbehaved and left the channel with unsynced state. We
- * should fix this here and give this VM a chance to use a properly
- * synced channel
- */
- mlx4_warn(dev, "recovering from previously mis-behaved VM\n");
- __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_read);
- __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_write);
- priv->cmd.comm_toggle = 0;
-
- return 0;
-}
-
-int mlx4_multi_func_init(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *s_state;
- int i, j, err, port;
-
- if (mlx4_is_master(dev))
- priv->mfunc.comm =
- ioremap(pci_resource_start(dev->pdev, priv->fw.comm_bar) +
- priv->fw.comm_base, MLX4_COMM_PAGESIZE);
- else
- priv->mfunc.comm =
- ioremap(pci_resource_start(dev->pdev, 2) +
- MLX4_SLAVE_COMM_BASE, MLX4_COMM_PAGESIZE);
- if (!priv->mfunc.comm) {
- mlx4_err(dev, "Couldn't map communication vector.\n");
- goto err_vhcr;
- }
-
- if (mlx4_is_master(dev)) {
- priv->mfunc.master.slave_state =
- kzalloc(dev->num_slaves *
- sizeof(struct mlx4_slave_state), GFP_KERNEL);
- if (!priv->mfunc.master.slave_state)
- goto err_comm;
-
- priv->mfunc.master.vf_admin =
- kzalloc(dev->num_slaves *
- sizeof(struct mlx4_vf_admin_state), GFP_KERNEL);
- if (!priv->mfunc.master.vf_admin)
- goto err_comm_admin;
-
- priv->mfunc.master.vf_oper =
- kzalloc(dev->num_slaves *
- sizeof(struct mlx4_vf_oper_state), GFP_KERNEL);
- if (!priv->mfunc.master.vf_oper)
- goto err_comm_oper;
-
- for (i = 0; i < dev->num_slaves; ++i) {
- s_state = &priv->mfunc.master.slave_state[i];
- s_state->last_cmd = MLX4_COMM_CMD_RESET;
- mutex_init(&priv->mfunc.master.gen_eqe_mutex[i]);
- for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j)
- s_state->event_eq[j].eqn = -1;
- __raw_writel((__force u32) 0,
- &priv->mfunc.comm[i].slave_write);
- __raw_writel((__force u32) 0,
- &priv->mfunc.comm[i].slave_read);
- mmiowb();
- for (port = 1; port <= MLX4_MAX_PORTS; port++) {
- s_state->vlan_filter[port] =
- kzalloc(sizeof(struct mlx4_vlan_fltr),
- GFP_KERNEL);
- if (!s_state->vlan_filter[port]) {
- if (--port)
- kfree(s_state->vlan_filter[port]);
- goto err_slaves;
- }
- INIT_LIST_HEAD(&s_state->mcast_filters[port]);
- priv->mfunc.master.vf_admin[i].vport[port].default_vlan = MLX4_VGT;
- priv->mfunc.master.vf_oper[i].vport[port].state.default_vlan = MLX4_VGT;
- priv->mfunc.master.vf_oper[i].vport[port].vlan_idx = NO_INDX;
- priv->mfunc.master.vf_oper[i].vport[port].mac_idx = NO_INDX;
- }
- spin_lock_init(&s_state->lock);
- }
-
- memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
- priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
- INIT_WORK(&priv->mfunc.master.comm_work,
- mlx4_master_comm_channel);
- INIT_WORK(&priv->mfunc.master.arm_comm_work,
- mlx4_master_arm_comm_channel);
- INIT_WORK(&priv->mfunc.master.slave_event_work,
- mlx4_gen_slave_eqe);
- INIT_WORK(&priv->mfunc.master.slave_flr_event_work,
- mlx4_master_handle_slave_flr);
- spin_lock_init(&priv->mfunc.master.slave_state_lock);
- spin_lock_init(&priv->mfunc.master.slave_eq.event_lock);
- priv->mfunc.master.comm_wq =
- create_singlethread_workqueue("mlx4_comm");
- if (!priv->mfunc.master.comm_wq)
- goto err_slaves;
-
- if (mlx4_init_resource_tracker(dev))
- goto err_thread;
-
- err = mlx4_ARM_COMM_CHANNEL(dev);
- if (err) {
- mlx4_err(dev, " Failed to arm comm channel eq: %x\n",
- err);
- goto err_resource;
- }
-
- } else {
- err = sync_toggles(dev);
- if (err) {
- mlx4_err(dev, "Couldn't sync toggles\n");
- goto err_comm;
- }
- }
- return 0;
-
-err_resource:
- mlx4_free_resource_tracker(dev, RES_TR_FREE_ALL);
-err_thread:
- flush_workqueue(priv->mfunc.master.comm_wq);
- destroy_workqueue(priv->mfunc.master.comm_wq);
-err_slaves:
- while (--i) {
- for (port = 1; port <= MLX4_MAX_PORTS; port++)
- kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
- }
- kfree(priv->mfunc.master.vf_oper);
-err_comm_oper:
- kfree(priv->mfunc.master.vf_admin);
-err_comm_admin:
- kfree(priv->mfunc.master.slave_state);
-err_comm:
- iounmap(priv->mfunc.comm);
-err_vhcr:
- dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
- priv->mfunc.vhcr,
- priv->mfunc.vhcr_dma);
- priv->mfunc.vhcr = NULL;
- return -ENOMEM;
-}
-
-int mlx4_cmd_init(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- mutex_init(&priv->cmd.hcr_mutex);
- mutex_init(&priv->cmd.slave_cmd_mutex);
- sema_init(&priv->cmd.poll_sem, 1);
- priv->cmd.use_events = 0;
- priv->cmd.toggle = 1;
-
- priv->cmd.hcr = NULL;
- priv->mfunc.vhcr = NULL;
-
- if (!mlx4_is_slave(dev)) {
- priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) +
- MLX4_HCR_BASE, MLX4_HCR_SIZE);
- if (!priv->cmd.hcr) {
- mlx4_err(dev, "Couldn't map command register.\n");
- return -ENOMEM;
- }
- }
-
- if (mlx4_is_mfunc(dev)) {
- priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
- &priv->mfunc.vhcr_dma,
- GFP_KERNEL);
- if (!priv->mfunc.vhcr) {
- mlx4_err(dev, "Couldn't allocate VHCR.\n");
- goto err_hcr;
- }
- }
-
- priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev,
- MLX4_MAILBOX_SIZE,
- MLX4_MAILBOX_SIZE, 0);
- if (!priv->cmd.pool)
- goto err_vhcr;
-
- return 0;
-
-err_vhcr:
- if (mlx4_is_mfunc(dev))
- dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
- priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
- priv->mfunc.vhcr = NULL;
-
-err_hcr:
- if (!mlx4_is_slave(dev))
- iounmap(priv->cmd.hcr);
- return -ENOMEM;
-}
-
-void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i, port;
-
- if (mlx4_is_master(dev)) {
- flush_workqueue(priv->mfunc.master.comm_wq);
- destroy_workqueue(priv->mfunc.master.comm_wq);
- for (i = 0; i < dev->num_slaves; i++) {
- for (port = 1; port <= MLX4_MAX_PORTS; port++)
- kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
- }
- kfree(priv->mfunc.master.slave_state);
- kfree(priv->mfunc.master.vf_admin);
- kfree(priv->mfunc.master.vf_oper);
- }
-
- iounmap(priv->mfunc.comm);
-}
-
-void mlx4_cmd_cleanup(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- pci_pool_destroy(priv->cmd.pool);
-
- if (!mlx4_is_slave(dev))
- iounmap(priv->cmd.hcr);
- if (mlx4_is_mfunc(dev))
- dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
- priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
- priv->mfunc.vhcr = NULL;
-}
-
-/*
- * Switch to using events to issue FW commands (can only be called
- * after event queue for command events has been initialized).
- */
-int mlx4_cmd_use_events(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i;
- int err = 0;
-
- priv->cmd.context = kmalloc(priv->cmd.max_cmds *
- sizeof (struct mlx4_cmd_context),
- GFP_KERNEL);
- if (!priv->cmd.context)
- return -ENOMEM;
-
- for (i = 0; i < priv->cmd.max_cmds; ++i) {
- priv->cmd.context[i].token = i;
- priv->cmd.context[i].next = i + 1;
- }
-
- priv->cmd.context[priv->cmd.max_cmds - 1].next = -1;
- priv->cmd.free_head = 0;
-
- sema_init(&priv->cmd.event_sem, priv->cmd.max_cmds);
- spin_lock_init(&priv->cmd.context_lock);
-
- for (priv->cmd.token_mask = 1;
- priv->cmd.token_mask < priv->cmd.max_cmds;
- priv->cmd.token_mask <<= 1)
- ; /* nothing */
- --priv->cmd.token_mask;
-
- down(&priv->cmd.poll_sem);
- priv->cmd.use_events = 1;
-
- return err;
-}
-
-/*
- * Switch back to polling (used when shutting down the device)
- */
-void mlx4_cmd_use_polling(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i;
-
- priv->cmd.use_events = 0;
-
- for (i = 0; i < priv->cmd.max_cmds; ++i)
- down(&priv->cmd.event_sem);
-
- kfree(priv->cmd.context);
-
- up(&priv->cmd.poll_sem);
-}
-
-struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev)
-{
- struct mlx4_cmd_mailbox *mailbox;
-
- mailbox = kmalloc(sizeof *mailbox, GFP_KERNEL);
- if (!mailbox)
- return ERR_PTR(-ENOMEM);
-
- mailbox->buf = pci_pool_alloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL,
- &mailbox->dma);
- if (!mailbox->buf) {
- kfree(mailbox);
- return ERR_PTR(-ENOMEM);
- }
-
- memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
-
- return mailbox;
-}
-EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox);
-
-void mlx4_free_cmd_mailbox(struct mlx4_dev *dev,
- struct mlx4_cmd_mailbox *mailbox)
-{
- if (!mailbox)
- return;
-
- pci_pool_free(mlx4_priv(dev)->cmd.pool, mailbox->buf, mailbox->dma);
- kfree(mailbox);
-}
-EXPORT_SYMBOL_GPL(mlx4_free_cmd_mailbox);
-
-u32 mlx4_comm_get_version(void)
-{
- return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER;
-}
-
-static int mlx4_get_slave_indx(struct mlx4_dev *dev, int vf)
-{
- if ((vf < 0) || (vf >= dev->num_vfs)) {
- mlx4_err(dev, "Bad vf number:%d (number of activated vf: %d)\n", vf, dev->num_vfs);
- return -EINVAL;
- }
- return (vf+1);
-}
-
-int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u8 *mac)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_vport_state *s_info;
- int slave;
-
- if (!mlx4_is_master(dev))
- return -EPROTONOSUPPORT;
-
- slave = mlx4_get_slave_indx(dev, vf);
- if (slave < 0)
- return -EINVAL;
-
- s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
- s_info->mac = mlx4_mac_to_u64(mac);
- mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n",
- vf, port, (unsigned long long) s_info->mac);
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);
-
-int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_vport_oper_state *vf_oper;
- struct mlx4_vport_state *vf_admin;
- int slave;
-
- if ((!mlx4_is_master(dev)) ||
- !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL))
- return -EPROTONOSUPPORT;
-
- if ((vlan > 4095) || (qos > 7))
- return -EINVAL;
-
- slave = mlx4_get_slave_indx(dev, vf);
- if (slave < 0)
- return -EINVAL;
-
- vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
- vf_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
-
- if ((0 == vlan) && (0 == qos))
- vf_admin->default_vlan = MLX4_VGT;
- else
- vf_admin->default_vlan = vlan;
- vf_admin->default_qos = qos;
-
- if (priv->mfunc.master.slave_state[slave].active &&
- dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {
- mlx4_info(dev, "updating vf %d port %d config params immediately\n",
- vf, port);
- mlx4_master_immediate_activate_vlan_qos(priv, slave, port);
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);
-
- /* mlx4_get_slave_default_vlan -
- * retrun true if VST ( default vlan)
- * if VST will fill vlan & qos (if not NULL) */
-bool mlx4_get_slave_default_vlan(struct mlx4_dev *dev, int port, int slave, u16 *vlan, u8 *qos)
-{
- struct mlx4_vport_oper_state *vp_oper;
- struct mlx4_priv *priv;
-
- priv = mlx4_priv(dev);
- vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
-
- if (MLX4_VGT != vp_oper->state.default_vlan) {
- if (vlan)
- *vlan = vp_oper->state.default_vlan;
- if (qos)
- *qos = vp_oper->state.default_qos;
- return true;
- }
- return false;
-}
-EXPORT_SYMBOL_GPL(mlx4_get_slave_default_vlan);
-
-int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_vport_state *s_info;
- int slave;
-
- if ((!mlx4_is_master(dev)) ||
- !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FSM))
- return -EPROTONOSUPPORT;
-
- slave = mlx4_get_slave_indx(dev, vf);
- if (slave < 0)
- return -EINVAL;
-
- s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
- s_info->spoofchk = setting;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_set_vf_spoofchk);
-
-int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_vport_state *s_info;
- struct mlx4_vport_oper_state *vp_oper;
- int slave;
- u8 link_stat_event;
-
- slave = mlx4_get_slave_indx(dev, vf);
- if (slave < 0)
- return -EINVAL;
-
- switch (link_state) {
- case IFLA_VF_LINK_STATE_AUTO:
- /* get link curent state */
- if (!priv->sense.do_sense_port[port])
- link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE;
- else
- link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN;
- break;
-
- case IFLA_VF_LINK_STATE_ENABLE:
- link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE;
- break;
-
- case IFLA_VF_LINK_STATE_DISABLE:
- link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN;
- break;
-
- default:
- mlx4_warn(dev, "unknown value for link_state %02x on slave %d port %d\n",
- link_state, slave, port);
- return -EINVAL;
- }
- /* update the admin & oper state on the link state */
- s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
- vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
- s_info->link_state = link_state;
- vp_oper->state.link_state = link_state;
-
- /* send event */
- mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event);
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state);
-
-int mlx4_get_vf_link_state(struct mlx4_dev *dev, int port, int vf)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_vport_state *s_info;
- int slave;
-
- if (!mlx4_is_master(dev))
- return -EPROTONOSUPPORT;
-
- slave = mlx4_get_slave_indx(dev, vf);
- if (slave < 0)
- return -EINVAL;
-
- s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
-
- return s_info->link_state;
-}
-EXPORT_SYMBOL_GPL(mlx4_get_vf_link_state);
-
diff --git a/sys/ofed/drivers/net/mlx4/cq.c b/sys/ofed/drivers/net/mlx4/cq.c
deleted file mode 100644
index b133ae615ea4..000000000000
--- a/sys/ofed/drivers/net/mlx4/cq.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2004 Voltaire, Inc. 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.
- */
-
-#include <linux/hardirq.h>
-#include <linux/module.h>
-#include <linux/mlx4/cmd.h>
-#include <linux/mlx4/cq.h>
-
-#include "mlx4.h"
-#include "icm.h"
-
-#define MLX4_CQ_STATUS_OK ( 0 << 28)
-#define MLX4_CQ_STATUS_OVERFLOW ( 9 << 28)
-#define MLX4_CQ_STATUS_WRITE_FAIL (10 << 28)
-#define MLX4_CQ_FLAG_CC ( 1 << 18)
-#define MLX4_CQ_FLAG_OI ( 1 << 17)
-#define MLX4_CQ_STATE_ARMED ( 9 << 8)
-#define MLX4_CQ_STATE_ARMED_SOL ( 6 << 8)
-#define MLX4_EQ_STATE_FIRED (10 << 8)
-
-void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn)
-{
- struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
- struct mlx4_cq *cq;
-
- read_lock(&cq_table->cq_table_lock);
-
- cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
- cqn & (dev->caps.num_cqs - 1));
- if (cq)
- atomic_inc(&cq->refcount);
-
- read_unlock(&cq_table->cq_table_lock);
-
- if (!cq) {
- mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn);
- return;
- }
-
- ++cq->arm_sn;
-
- cq->comp(cq);
-
- if (atomic_dec_and_test(&cq->refcount))
- complete(&cq->free);
-}
-
-void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
-{
- struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
- struct mlx4_cq *cq;
-
- read_lock(&cq_table->cq_table_lock);
-
- cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
- if (cq)
- atomic_inc(&cq->refcount);
-
- read_unlock(&cq_table->cq_table_lock);
-
- if (!cq) {
- mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
- return;
- }
-
- cq->event(cq, event_type);
-
- if (atomic_dec_and_test(&cq->refcount))
- complete(&cq->free);
-}
-
-static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int cq_num)
-{
- return mlx4_cmd(dev, mailbox->dma, cq_num, 0,
- MLX4_CMD_SW2HW_CQ, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int cq_num, u32 opmod)
-{
- return mlx4_cmd(dev, mailbox->dma, cq_num, opmod, MLX4_CMD_MODIFY_CQ,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int cq_num)
-{
- return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
- cq_num, mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
-}
-
-int mlx4_cq_modify(struct mlx4_dev *dev, struct mlx4_cq *cq,
- u16 count, u16 period)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_cq_context *cq_context;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- cq_context = mailbox->buf;
- memset(cq_context, 0, sizeof *cq_context);
-
- cq_context->cq_max_count = cpu_to_be16(count);
- cq_context->cq_period = cpu_to_be16(period);
-
- err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 1);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_cq_modify);
-
-int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
- int entries, struct mlx4_mtt *mtt)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_cq_context *cq_context;
- u64 mtt_addr;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- cq_context = mailbox->buf;
- memset(cq_context, 0, sizeof *cq_context);
-
- cq_context->logsize_usrpage = cpu_to_be32(ilog2(entries) << 24);
- cq_context->log_page_size = mtt->page_shift - 12;
- mtt_addr = mlx4_mtt_addr(dev, mtt);
- cq_context->mtt_base_addr_h = mtt_addr >> 32;
- cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
-
- err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 0);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_cq_resize);
-
-int mlx4_cq_ignore_overrun(struct mlx4_dev *dev, struct mlx4_cq *cq)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_cq_context *cq_context;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- cq_context = mailbox->buf;
- memset(cq_context, 0, sizeof *cq_context);
-
- cq_context->flags |= cpu_to_be32(MLX4_CQ_FLAG_OI);
-
- err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 3);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_cq_ignore_overrun);
-
-int __mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cq_table *cq_table = &priv->cq_table;
- int err;
-
- *cqn = mlx4_bitmap_alloc(&cq_table->bitmap);
- if (*cqn == -1)
- return -ENOMEM;
-
- err = mlx4_table_get(dev, &cq_table->table, *cqn);
- if (err)
- goto err_out;
-
- err = mlx4_table_get(dev, &cq_table->cmpt_table, *cqn);
- if (err)
- goto err_put;
- return 0;
-
-err_put:
- mlx4_table_put(dev, &cq_table->table, *cqn);
-
-err_out:
- mlx4_bitmap_free(&cq_table->bitmap, *cqn, MLX4_NO_RR);
- return err;
-}
-
-static int mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn)
-{
- u64 out_param;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- err = mlx4_cmd_imm(dev, 0, &out_param, RES_CQ,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err)
- return err;
- else {
- *cqn = get_param_l(&out_param);
- return 0;
- }
- }
- return __mlx4_cq_alloc_icm(dev, cqn);
-}
-
-void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cq_table *cq_table = &priv->cq_table;
-
- mlx4_table_put(dev, &cq_table->cmpt_table, cqn);
- mlx4_table_put(dev, &cq_table->table, cqn);
- mlx4_bitmap_free(&cq_table->bitmap, cqn, MLX4_NO_RR);
-}
-
-static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
-{
- u64 in_param = 0;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, cqn);
- err = mlx4_cmd(dev, in_param, RES_CQ, RES_OP_RESERVE_AND_MAP,
- MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err)
- mlx4_warn(dev, "Failed freeing cq:%d\n", cqn);
- } else
- __mlx4_cq_free_icm(dev, cqn);
-}
-
-int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
- struct mlx4_mtt *mtt, struct mlx4_uar *uar, u64 db_rec,
- struct mlx4_cq *cq, unsigned vector, int collapsed,
- int timestamp_en)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cq_table *cq_table = &priv->cq_table;
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_cq_context *cq_context;
- u64 mtt_addr;
- int err;
-
- if (vector > dev->caps.num_comp_vectors + dev->caps.comp_pool)
- return -EINVAL;
-
- cq->vector = vector;
-
- err = mlx4_cq_alloc_icm(dev, &cq->cqn);
- if (err)
- return err;
-
- spin_lock_irq(&cq_table->lock);
- err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
- spin_unlock_irq(&cq_table->lock);
- if (err)
- goto err_icm;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- goto err_radix;
- }
-
- cq_context = mailbox->buf;
- memset(cq_context, 0, sizeof *cq_context);
-
- cq_context->flags = cpu_to_be32(!!collapsed << 18);
- if (timestamp_en)
- cq_context->flags |= cpu_to_be32(1 << 19);
-
- cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
- cq_context->comp_eqn = priv->eq_table.eq[vector].eqn;
- cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
-
- mtt_addr = mlx4_mtt_addr(dev, mtt);
- cq_context->mtt_base_addr_h = mtt_addr >> 32;
- cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
- cq_context->db_rec_addr = cpu_to_be64(db_rec);
-
- err = mlx4_SW2HW_CQ(dev, mailbox, cq->cqn);
- mlx4_free_cmd_mailbox(dev, mailbox);
- if (err)
- goto err_radix;
-
- cq->cons_index = 0;
- cq->arm_sn = 1;
- cq->uar = uar;
- atomic_set(&cq->refcount, 1);
- init_completion(&cq->free);
-
- cq->eqn = priv->eq_table.eq[cq->vector].eqn;
- cq->irq = priv->eq_table.eq[cq->vector].irq;
-
- return 0;
-
-err_radix:
- spin_lock_irq(&cq_table->lock);
- radix_tree_delete(&cq_table->tree, cq->cqn);
- spin_unlock_irq(&cq_table->lock);
-
-err_icm:
- mlx4_cq_free_icm(dev, cq->cqn);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_cq_alloc);
-
-void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cq_table *cq_table = &priv->cq_table;
- int err;
-
- err = mlx4_HW2SW_CQ(dev, NULL, cq->cqn);
- if (err)
- mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
-
- synchronize_irq(priv->eq_table.eq[cq->vector].irq);
-
- spin_lock_irq(&cq_table->lock);
- radix_tree_delete(&cq_table->tree, cq->cqn);
- spin_unlock_irq(&cq_table->lock);
-
- if (atomic_dec_and_test(&cq->refcount))
- complete(&cq->free);
- wait_for_completion(&cq->free);
-
- mlx4_cq_free_icm(dev, cq->cqn);
-}
-EXPORT_SYMBOL_GPL(mlx4_cq_free);
-
-int mlx4_init_cq_table(struct mlx4_dev *dev)
-{
- struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
- int err;
-
- spin_lock_init(&cq_table->lock);
- rwlock_init(&cq_table->cq_table_lock);
- INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC);
- if (mlx4_is_slave(dev))
- return 0;
-
- err = mlx4_bitmap_init(&cq_table->bitmap, dev->caps.num_cqs,
- dev->caps.num_cqs - 1, dev->caps.reserved_cqs, 0);
- if (err)
- return err;
-
- return 0;
-}
-
-void mlx4_cleanup_cq_table(struct mlx4_dev *dev)
-{
- if (mlx4_is_slave(dev))
- return;
- /* Nothing to do to clean up radix_tree */
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->cq_table.bitmap);
-}
diff --git a/sys/ofed/drivers/net/mlx4/en_cq.c b/sys/ofed/drivers/net/mlx4/en_cq.c
deleted file mode 100644
index 591404d0a83c..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_cq.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#include <linux/mlx4/cq.h>
-#include <linux/mlx4/qp.h>
-#include <linux/mlx4/cmd.h>
-
-#include "mlx4_en.h"
-
-
-static void mlx4_en_cq_event(struct mlx4_cq *cq, enum mlx4_event event)
-{
- return;
-}
-
-
-int mlx4_en_create_cq(struct mlx4_en_priv *priv,
- struct mlx4_en_cq **pcq,
- int entries, int ring, enum cq_type mode,
- int node)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_cq *cq;
- int err;
-
- cq = kzalloc_node(sizeof(struct mlx4_en_cq), GFP_KERNEL, node);
- if (!cq) {
- cq = kzalloc(sizeof(struct mlx4_en_cq), GFP_KERNEL);
- if (!cq) {
- en_err(priv, "Failed to allocate CW struture\n");
- return -ENOMEM;
- }
- }
-
- cq->size = entries;
- cq->buf_size = cq->size * mdev->dev->caps.cqe_size;
-
- cq->tq = taskqueue_create_fast("mlx4_en_que", M_NOWAIT,
- taskqueue_thread_enqueue, &cq->tq);
- if (mode == RX) {
- TASK_INIT(&cq->cq_task, 0, mlx4_en_rx_que, cq);
- taskqueue_start_threads(&cq->tq, 1, PI_NET, "%s rx cq",
- if_name(priv->dev));
-
- } else {
- TASK_INIT(&cq->cq_task, 0, mlx4_en_tx_que, cq);
- taskqueue_start_threads(&cq->tq, 1, PI_NET, "%s tx cq",
- if_name(priv->dev));
- }
-
- cq->ring = ring;
- cq->is_tx = mode;
- spin_lock_init(&cq->lock);
-
- err = mlx4_alloc_hwq_res(mdev->dev, &cq->wqres,
- cq->buf_size, 2 * PAGE_SIZE);
- if (err)
- goto err_cq;
-
- err = mlx4_en_map_buffer(&cq->wqres.buf);
- if (err)
- goto err_res;
-
- cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf;
- *pcq = cq;
-
- return 0;
-
-err_res:
- mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
-err_cq:
- kfree(cq);
- return err;
-}
-
-
-int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
- int cq_idx)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- int err = 0;
- char name[25];
- int timestamp_en = 0;
-
- cq->dev = mdev->pndev[priv->port];
- cq->mcq.set_ci_db = cq->wqres.db.db;
- cq->mcq.arm_db = cq->wqres.db.db + 1;
- *cq->mcq.set_ci_db = 0;
- *cq->mcq.arm_db = 0;
- memset(cq->buf, 0, cq->buf_size);
-
- if (cq->is_tx == RX) {
- if (mdev->dev->caps.comp_pool) {
- if (!cq->vector) {
- sprintf(name, "%s-%d", if_name(priv->dev),
- cq->ring);
- /* Set IRQ for specific name (per ring) */
- if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) {
- cq->vector = (cq->ring + 1 + priv->port)
- % mdev->dev->caps.num_comp_vectors;
- mlx4_warn(mdev, "Failed Assigning an EQ to "
- "%s ,Falling back to legacy EQ's\n",
- name);
- }
- }
- } else {
- cq->vector = (cq->ring + 1 + priv->port) %
- mdev->dev->caps.num_comp_vectors;
- }
- } else {
- struct mlx4_en_cq *rx_cq;
- /*
- * For TX we use the same irq per
- * ring we assigned for the RX
- */
- cq_idx = cq_idx % priv->rx_ring_num;
- rx_cq = priv->rx_cq[cq_idx];
- cq->vector = rx_cq->vector;
- }
-
- if (!cq->is_tx)
- cq->size = priv->rx_ring[cq->ring]->actual_size;
- err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt,
- &mdev->priv_uar, cq->wqres.db.dma, &cq->mcq,
- cq->vector, 0, timestamp_en);
- if (err)
- return err;
-
- cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
- cq->mcq.event = mlx4_en_cq_event;
-
- if (cq->is_tx) {
- init_timer(&cq->timer);
- cq->timer.function = mlx4_en_poll_tx_cq;
- cq->timer.data = (unsigned long) cq;
- }
-
-
- return 0;
-}
-
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_cq *cq = *pcq;
-
- taskqueue_drain(cq->tq, &cq->cq_task);
- taskqueue_free(cq->tq);
- mlx4_en_unmap_buffer(&cq->wqres.buf);
- mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
- if (priv->mdev->dev->caps.comp_pool && cq->vector)
- mlx4_release_eq(priv->mdev->dev, cq->vector);
- kfree(cq);
- *pcq = NULL;
-}
-
-void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
-
- taskqueue_drain(cq->tq, &cq->cq_task);
- if (cq->is_tx)
- del_timer_sync(&cq->timer);
-
- mlx4_cq_free(mdev->dev, &cq->mcq);
-}
-
-
-/* Set rx cq moderation parameters */
-int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
-{
- return mlx4_cq_modify(priv->mdev->dev, &cq->mcq,
- cq->moder_cnt, cq->moder_time);
-}
-
-int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
-{
- mlx4_cq_arm(&cq->mcq, MLX4_CQ_DB_REQ_NOT, priv->mdev->uar_map,
- &priv->mdev->uar_lock);
-
- return 0;
-}
-
-
diff --git a/sys/ofed/drivers/net/mlx4/en_main.c b/sys/ofed/drivers/net/mlx4/en_main.c
deleted file mode 100644
index 7cff16bbba27..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_main.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#define LINUXKPI_PARAM_PREFIX mlx4_
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/slab.h>
-
-#include <linux/mlx4/driver.h>
-#include <linux/mlx4/device.h>
-#include <linux/mlx4/cmd.h>
-
-#include "mlx4_en.h"
-
-/* Mellanox ConnectX HCA Ethernet driver */
-
-#define MLX4_EN_PARM_INT(X, def_val, desc) \
- static unsigned int X = def_val;\
- module_param(X , uint, 0444); \
- MODULE_PARM_DESC(X, desc);
-
-
-/*
- * Device scope module parameters
- */
-
-/* Enable RSS UDP traffic */
-MLX4_EN_PARM_INT(udp_rss, 1,
- "Enable RSS for incoming UDP traffic");
-
-/* Priority pausing */
-MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
- " Per priority bit mask");
-MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]."
- " Per priority bit mask");
-
-#define MAX_PFC_TX 0xff
-#define MAX_PFC_RX 0xff
-
-
-static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
-{
- struct mlx4_en_profile *params = &mdev->profile;
- int i;
-
- params->udp_rss = udp_rss;
- params->num_tx_rings_p_up = min_t(int, mp_ncpus,
- MLX4_EN_MAX_TX_RING_P_UP);
- if (params->udp_rss && !(mdev->dev->caps.flags
- & MLX4_DEV_CAP_FLAG_UDP_RSS)) {
- mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
- params->udp_rss = 0;
- }
- for (i = 1; i <= MLX4_MAX_PORTS; i++) {
- params->prof[i].rx_pause = 1;
- params->prof[i].rx_ppp = pfcrx;
- params->prof[i].tx_pause = 1;
- params->prof[i].tx_ppp = pfctx;
- params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
- params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
- params->prof[i].tx_ring_num = params->num_tx_rings_p_up *
- MLX4_EN_NUM_UP;
- params->prof[i].rss_rings = 0;
- }
-
- return 0;
-}
-
-static void *mlx4_en_get_netdev(struct mlx4_dev *dev, void *ctx, u8 port)
-{
- struct mlx4_en_dev *endev = ctx;
-
- return endev->pndev[port];
-}
-
-static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr,
- enum mlx4_dev_event event, unsigned long port)
-{
- struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr;
- struct mlx4_en_priv *priv;
-
- switch (event) {
- case MLX4_DEV_EVENT_PORT_UP:
- case MLX4_DEV_EVENT_PORT_DOWN:
- if (!mdev->pndev[port])
- return;
- priv = netdev_priv(mdev->pndev[port]);
- /* To prevent races, we poll the link state in a separate
- task rather than changing it here */
- priv->link_state = event;
- queue_work(mdev->workqueue, &priv->linkstate_task);
- break;
-
- case MLX4_DEV_EVENT_CATASTROPHIC_ERROR:
- mlx4_err(mdev, "Internal error detected, restarting device\n");
- break;
-
- case MLX4_DEV_EVENT_SLAVE_INIT:
- case MLX4_DEV_EVENT_SLAVE_SHUTDOWN:
- break;
- default:
- if (port < 1 || port > dev->caps.num_ports ||
- !mdev->pndev[port])
- return;
- mlx4_warn(mdev, "Unhandled event %d for port %d\n", event,
- (int) port);
- }
-}
-
-static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
-{
- struct mlx4_en_dev *mdev = endev_ptr;
- int i, ret;
-
- mutex_lock(&mdev->state_lock);
- mdev->device_up = false;
- mutex_unlock(&mdev->state_lock);
-
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
- if (mdev->pndev[i])
- mlx4_en_destroy_netdev(mdev->pndev[i]);
-
- flush_workqueue(mdev->workqueue);
- destroy_workqueue(mdev->workqueue);
- ret = mlx4_mr_free(dev, &mdev->mr);
- if (ret)
- mlx4_err(mdev, "Error deregistering MR. The system may have become unstable.");
- iounmap(mdev->uar_map);
- mlx4_uar_free(dev, &mdev->priv_uar);
- mlx4_pd_free(dev, mdev->priv_pdn);
- kfree(mdev);
-}
-
-static void *mlx4_en_add(struct mlx4_dev *dev)
-{
- struct mlx4_en_dev *mdev;
- int i;
- int err;
-
- mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
- if (!mdev) {
- dev_err(&dev->pdev->dev, "Device struct alloc failed, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_free_res;
- }
-
- if (mlx4_pd_alloc(dev, &mdev->priv_pdn))
- goto err_free_dev;
-
- if (mlx4_uar_alloc(dev, &mdev->priv_uar))
- goto err_pd;
-
- mdev->uar_map = ioremap((phys_addr_t) mdev->priv_uar.pfn << PAGE_SHIFT,
- PAGE_SIZE);
- if (!mdev->uar_map)
- goto err_uar;
- spin_lock_init(&mdev->uar_lock);
-
- mdev->dev = dev;
- mdev->dma_device = &(dev->pdev->dev);
- mdev->pdev = dev->pdev;
- mdev->device_up = false;
-
- mdev->LSO_support = !!(dev->caps.flags & (1 << 15));
- if (!mdev->LSO_support)
- mlx4_warn(mdev, "LSO not supported, please upgrade to later "
- "FW version to enable LSO\n");
-
- if (mlx4_mr_alloc(mdev->dev, mdev->priv_pdn, 0, ~0ull,
- MLX4_PERM_LOCAL_WRITE | MLX4_PERM_LOCAL_READ,
- 0, 0, &mdev->mr)) {
- mlx4_err(mdev, "Failed allocating memory region\n");
- goto err_map;
- }
- if (mlx4_mr_enable(mdev->dev, &mdev->mr)) {
- mlx4_err(mdev, "Failed enabling memory region\n");
- goto err_mr;
- }
-
- /* Build device profile according to supplied module parameters */
- err = mlx4_en_get_profile(mdev);
- if (err) {
- mlx4_err(mdev, "Bad module parameters, aborting.\n");
- goto err_mr;
- }
-
- /* Configure which ports to start according to module parameters */
- mdev->port_cnt = 0;
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
- mdev->port_cnt++;
-
-
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
- if (!dev->caps.comp_pool) {
- mdev->profile.prof[i].rx_ring_num =
- rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
- min_t(int,
- dev->caps.num_comp_vectors,
- DEF_RX_RINGS)));
- } else {
- mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
- min_t(int, dev->caps.comp_pool /
- dev->caps.num_ports, MAX_MSIX_P_PORT));
- }
- }
-
- /* Create our own workqueue for reset/multicast tasks
- * Note: we cannot use the shared workqueue because of deadlocks caused
- * by the rtnl lock */
- mdev->workqueue = create_singlethread_workqueue("mlx4_en");
- if (!mdev->workqueue) {
- err = -ENOMEM;
- goto err_mr;
- }
-
- /* At this stage all non-port specific tasks are complete:
- * mark the card state as up */
- mutex_init(&mdev->state_lock);
- mdev->device_up = true;
-
- /* Setup ports */
-
- /* Create a netdev for each port */
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
- mlx4_info(mdev, "Activating port:%d\n", i);
- if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i]))
- mdev->pndev[i] = NULL;
- }
-
- return mdev;
-
-err_mr:
- err = mlx4_mr_free(dev, &mdev->mr);
- if (err)
- mlx4_err(mdev, "Error deregistering MR. The system may have become unstable.");
-err_map:
- if (mdev->uar_map)
- iounmap(mdev->uar_map);
-err_uar:
- mlx4_uar_free(dev, &mdev->priv_uar);
-err_pd:
- mlx4_pd_free(dev, mdev->priv_pdn);
-err_free_dev:
- kfree(mdev);
-err_free_res:
- return NULL;
-}
-
-static struct mlx4_interface mlx4_en_interface = {
- .add = mlx4_en_add,
- .remove = mlx4_en_remove,
- .event = mlx4_en_event,
- .get_dev = mlx4_en_get_netdev,
- .protocol = MLX4_PROT_ETH,
-};
-
-static void mlx4_en_verify_params(void)
-{
- if (pfctx > MAX_PFC_TX) {
- pr_warn("mlx4_en: WARNING: illegal module parameter pfctx 0x%x - "
- "should be in range 0-0x%x, will be changed to default (0)\n",
- pfctx, MAX_PFC_TX);
- pfctx = 0;
- }
-
- if (pfcrx > MAX_PFC_RX) {
- pr_warn("mlx4_en: WARNING: illegal module parameter pfcrx 0x%x - "
- "should be in range 0-0x%x, will be changed to default (0)\n",
- pfcrx, MAX_PFC_RX);
- pfcrx = 0;
- }
-}
-
-
-static int __init mlx4_en_init(void)
-{
- mlx4_en_verify_params();
-
-#ifdef CONFIG_DEBUG_FS
- int err = 0;
- err = mlx4_en_register_debugfs();
- if (err)
- pr_err(KERN_ERR "Failed to register debugfs\n");
-#endif
- return mlx4_register_interface(&mlx4_en_interface);
-}
-
-static void __exit mlx4_en_cleanup(void)
-{
- mlx4_unregister_interface(&mlx4_en_interface);
-#ifdef CONFIG_DEBUG_FS
- mlx4_en_unregister_debugfs();
-#endif
-}
-
-module_init(mlx4_en_init);
-module_exit(mlx4_en_cleanup);
-
-static int
-mlxen_evhand(module_t mod, int event, void *arg)
-{
- return (0);
-}
-static moduledata_t mlxen_mod = {
- .name = "mlxen",
- .evhand = mlxen_evhand,
-};
-DECLARE_MODULE(mlxen, mlxen_mod, SI_SUB_OFED_PREINIT, SI_ORDER_ANY);
-MODULE_DEPEND(mlxen, mlx4, 1, 1, 1);
-MODULE_DEPEND(mlxen, linuxkpi, 1, 1, 1);
diff --git a/sys/ofed/drivers/net/mlx4/en_netdev.c b/sys/ofed/drivers/net/mlx4/en_netdev.c
deleted file mode 100644
index 26a0c6ce7336..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_netdev.c
+++ /dev/null
@@ -1,2818 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#ifdef CONFIG_NET_RX_BUSY_POLL
-#include <net/busy_poll.h>
-#endif
-
-#include <linux/list.h>
-#include <linux/if_ether.h>
-
-#include <linux/mlx4/driver.h>
-#include <linux/mlx4/device.h>
-#include <linux/mlx4/cmd.h>
-#include <linux/mlx4/cq.h>
-
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-
-#include "mlx4_en.h"
-#include "en_port.h"
-
-static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv);
-static void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv);
-static int mlx4_en_unit;
-
-#ifdef CONFIG_NET_RX_BUSY_POLL
-/* must be called with local_bh_disable()d */
-static int mlx4_en_low_latency_recv(struct napi_struct *napi)
-{
- struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi);
- struct net_device *dev = cq->dev;
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring];
- int done;
-
- if (!priv->port_up)
- return LL_FLUSH_FAILED;
-
- if (!mlx4_en_cq_lock_poll(cq))
- return LL_FLUSH_BUSY;
-
- done = mlx4_en_process_rx_cq(dev, cq, 4);
-#ifdef LL_EXTENDED_STATS
- if (done)
- rx_ring->cleaned += done;
- else
- rx_ring->misses++;
-#endif
-
- mlx4_en_cq_unlock_poll(cq);
-
- return done;
-}
-#endif /* CONFIG_NET_RX_BUSY_POLL */
-
-#ifdef CONFIG_RFS_ACCEL
-
-struct mlx4_en_filter {
- struct list_head next;
- struct work_struct work;
-
- u8 ip_proto;
- __be32 src_ip;
- __be32 dst_ip;
- __be16 src_port;
- __be16 dst_port;
-
- int rxq_index;
- struct mlx4_en_priv *priv;
- u32 flow_id; /* RFS infrastructure id */
- int id; /* mlx4_en driver id */
- u64 reg_id; /* Flow steering API id */
- u8 activated; /* Used to prevent expiry before filter
- * is attached
- */
- struct hlist_node filter_chain;
-};
-
-static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv);
-
-static enum mlx4_net_trans_rule_id mlx4_ip_proto_to_trans_rule_id(u8 ip_proto)
-{
- switch (ip_proto) {
- case IPPROTO_UDP:
- return MLX4_NET_TRANS_RULE_ID_UDP;
- case IPPROTO_TCP:
- return MLX4_NET_TRANS_RULE_ID_TCP;
- default:
- return -EPROTONOSUPPORT;
- }
-};
-
-static void mlx4_en_filter_work(struct work_struct *work)
-{
- struct mlx4_en_filter *filter = container_of(work,
- struct mlx4_en_filter,
- work);
- struct mlx4_en_priv *priv = filter->priv;
- struct mlx4_spec_list spec_tcp_udp = {
- .id = mlx4_ip_proto_to_trans_rule_id(filter->ip_proto),
- {
- .tcp_udp = {
- .dst_port = filter->dst_port,
- .dst_port_msk = (__force __be16)-1,
- .src_port = filter->src_port,
- .src_port_msk = (__force __be16)-1,
- },
- },
- };
- struct mlx4_spec_list spec_ip = {
- .id = MLX4_NET_TRANS_RULE_ID_IPV4,
- {
- .ipv4 = {
- .dst_ip = filter->dst_ip,
- .dst_ip_msk = (__force __be32)-1,
- .src_ip = filter->src_ip,
- .src_ip_msk = (__force __be32)-1,
- },
- },
- };
- struct mlx4_spec_list spec_eth = {
- .id = MLX4_NET_TRANS_RULE_ID_ETH,
- };
- struct mlx4_net_trans_rule rule = {
- .list = LIST_HEAD_INIT(rule.list),
- .queue_mode = MLX4_NET_TRANS_Q_LIFO,
- .exclusive = 1,
- .allow_loopback = 1,
- .promisc_mode = MLX4_FS_REGULAR,
- .port = priv->port,
- .priority = MLX4_DOMAIN_RFS,
- };
- int rc;
- __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
-
- if (spec_tcp_udp.id < 0) {
- en_warn(priv, "RFS: ignoring unsupported ip protocol (%d)\n",
- filter->ip_proto);
- goto ignore;
- }
- list_add_tail(&spec_eth.list, &rule.list);
- list_add_tail(&spec_ip.list, &rule.list);
- list_add_tail(&spec_tcp_udp.list, &rule.list);
-
- rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn;
- memcpy(spec_eth.eth.dst_mac, priv->dev->dev_addr, ETH_ALEN);
- memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
-
- filter->activated = 0;
-
- if (filter->reg_id) {
- rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
- if (rc && rc != -ENOENT)
- en_err(priv, "Error detaching flow. rc = %d\n", rc);
- }
-
- rc = mlx4_flow_attach(priv->mdev->dev, &rule, &filter->reg_id);
- if (rc)
- en_err(priv, "Error attaching flow. err = %d\n", rc);
-
-ignore:
- mlx4_en_filter_rfs_expire(priv);
-
- filter->activated = 1;
-}
-
-static inline struct hlist_head *
-filter_hash_bucket(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
- __be16 src_port, __be16 dst_port)
-{
- unsigned long l;
- int bucket_idx;
-
- l = (__force unsigned long)src_port |
- ((__force unsigned long)dst_port << 2);
- l ^= (__force unsigned long)(src_ip ^ dst_ip);
-
- bucket_idx = hash_long(l, MLX4_EN_FILTER_HASH_SHIFT);
-
- return &priv->filter_hash[bucket_idx];
-}
-
-static struct mlx4_en_filter *
-mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
- __be32 dst_ip, u8 ip_proto, __be16 src_port,
- __be16 dst_port, u32 flow_id)
-{
- struct mlx4_en_filter *filter = NULL;
-
- filter = kzalloc(sizeof(struct mlx4_en_filter), GFP_ATOMIC);
- if (!filter)
- return NULL;
-
- filter->priv = priv;
- filter->rxq_index = rxq_index;
- INIT_WORK(&filter->work, mlx4_en_filter_work);
-
- filter->src_ip = src_ip;
- filter->dst_ip = dst_ip;
- filter->ip_proto = ip_proto;
- filter->src_port = src_port;
- filter->dst_port = dst_port;
-
- filter->flow_id = flow_id;
-
- filter->id = priv->last_filter_id++ % RPS_NO_FILTER;
-
- list_add_tail(&filter->next, &priv->filters);
- hlist_add_head(&filter->filter_chain,
- filter_hash_bucket(priv, src_ip, dst_ip, src_port,
- dst_port));
-
- return filter;
-}
-
-static void mlx4_en_filter_free(struct mlx4_en_filter *filter)
-{
- struct mlx4_en_priv *priv = filter->priv;
- int rc;
-
- list_del(&filter->next);
-
- rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
- if (rc && rc != -ENOENT)
- en_err(priv, "Error detaching flow. rc = %d\n", rc);
-
- kfree(filter);
-}
-
-static inline struct mlx4_en_filter *
-mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
- u8 ip_proto, __be16 src_port, __be16 dst_port)
-{
- struct mlx4_en_filter *filter;
- struct mlx4_en_filter *ret = NULL;
-
- hlist_for_each_entry(filter,
- filter_hash_bucket(priv, src_ip, dst_ip,
- src_port, dst_port),
- filter_chain) {
- if (filter->src_ip == src_ip &&
- filter->dst_ip == dst_ip &&
- filter->ip_proto == ip_proto &&
- filter->src_port == src_port &&
- filter->dst_port == dst_port) {
- ret = filter;
- break;
- }
- }
-
- return ret;
-}
-
-static int
-mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
- u16 rxq_index, u32 flow_id)
-{
- struct mlx4_en_priv *priv = netdev_priv(net_dev);
- struct mlx4_en_filter *filter;
- const struct iphdr *ip;
- const __be16 *ports;
- u8 ip_proto;
- __be32 src_ip;
- __be32 dst_ip;
- __be16 src_port;
- __be16 dst_port;
- int nhoff = skb_network_offset(skb);
- int ret = 0;
-
- if (skb->protocol != htons(ETH_P_IP))
- return -EPROTONOSUPPORT;
-
- ip = (const struct iphdr *)(skb->data + nhoff);
- if (ip_is_fragment(ip))
- return -EPROTONOSUPPORT;
-
- if ((ip->protocol != IPPROTO_TCP) && (ip->protocol != IPPROTO_UDP))
- return -EPROTONOSUPPORT;
- ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
-
- ip_proto = ip->protocol;
- src_ip = ip->saddr;
- dst_ip = ip->daddr;
- src_port = ports[0];
- dst_port = ports[1];
-
- spin_lock_bh(&priv->filters_lock);
- filter = mlx4_en_filter_find(priv, src_ip, dst_ip, ip_proto,
- src_port, dst_port);
- if (filter) {
- if (filter->rxq_index == rxq_index)
- goto out;
-
- filter->rxq_index = rxq_index;
- } else {
- filter = mlx4_en_filter_alloc(priv, rxq_index,
- src_ip, dst_ip, ip_proto,
- src_port, dst_port, flow_id);
- if (!filter) {
- ret = -ENOMEM;
- goto err;
- }
- }
-
- queue_work(priv->mdev->workqueue, &filter->work);
-
-out:
- ret = filter->id;
-err:
- spin_unlock_bh(&priv->filters_lock);
-
- return ret;
-}
-
-void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *rx_ring)
-{
- struct mlx4_en_filter *filter, *tmp;
- LIST_HEAD(del_list);
-
- spin_lock_bh(&priv->filters_lock);
- list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
- list_move(&filter->next, &del_list);
- hlist_del(&filter->filter_chain);
- }
- spin_unlock_bh(&priv->filters_lock);
-
- list_for_each_entry_safe(filter, tmp, &del_list, next) {
- cancel_work_sync(&filter->work);
- mlx4_en_filter_free(filter);
- }
-}
-
-static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_filter *filter = NULL, *tmp, *last_filter = NULL;
- LIST_HEAD(del_list);
- int i = 0;
-
- spin_lock_bh(&priv->filters_lock);
- list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
- if (i > MLX4_EN_FILTER_EXPIRY_QUOTA)
- break;
-
- if (filter->activated &&
- !work_pending(&filter->work) &&
- rps_may_expire_flow(priv->dev,
- filter->rxq_index, filter->flow_id,
- filter->id)) {
- list_move(&filter->next, &del_list);
- hlist_del(&filter->filter_chain);
- } else
- last_filter = filter;
-
- i++;
- }
-
- if (last_filter && (&last_filter->next != priv->filters.next))
- list_move(&priv->filters, &last_filter->next);
-
- spin_unlock_bh(&priv->filters_lock);
-
- list_for_each_entry_safe(filter, tmp, &del_list, next)
- mlx4_en_filter_free(filter);
-}
-#endif
-
-static void mlx4_en_vlan_rx_add_vid(void *arg, struct net_device *dev, u16 vid)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int err;
- int idx;
-
- if (arg != priv)
- return;
-
- en_dbg(HW, priv, "adding VLAN:%d\n", vid);
-
- set_bit(vid, priv->active_vlans);
-
- /* Add VID to port VLAN filter */
- mutex_lock(&mdev->state_lock);
- if (mdev->device_up && priv->port_up) {
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
- if (err)
- en_err(priv, "Failed configuring VLAN filter\n");
- }
- if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx))
- en_dbg(HW, priv, "failed adding vlan %d\n", vid);
- mutex_unlock(&mdev->state_lock);
-
-}
-
-static void mlx4_en_vlan_rx_kill_vid(void *arg, struct net_device *dev, u16 vid)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int err;
-
- if (arg != priv)
- return;
-
- en_dbg(HW, priv, "Killing VID:%d\n", vid);
-
- clear_bit(vid, priv->active_vlans);
-
- /* Remove VID from port VLAN filter */
- mutex_lock(&mdev->state_lock);
- mlx4_unregister_vlan(mdev->dev, priv->port, vid);
-
- if (mdev->device_up && priv->port_up) {
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
- if (err)
- en_err(priv, "Failed configuring VLAN filter\n");
- }
- mutex_unlock(&mdev->state_lock);
-
-}
-
-static int mlx4_en_uc_steer_add(struct mlx4_en_priv *priv,
- unsigned char *mac, int *qpn, u64 *reg_id)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_dev *dev = mdev->dev;
- int err;
-
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_B0: {
- struct mlx4_qp qp;
- u8 gid[16] = {0};
-
- qp.qpn = *qpn;
- memcpy(&gid[10], mac, ETH_ALEN);
- gid[5] = priv->port;
-
- err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH);
- break;
- }
- case MLX4_STEERING_MODE_DEVICE_MANAGED: {
- struct mlx4_spec_list spec_eth = { {NULL} };
- __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
-
- struct mlx4_net_trans_rule rule = {
- .queue_mode = MLX4_NET_TRANS_Q_FIFO,
- .exclusive = 0,
- .allow_loopback = 1,
- .promisc_mode = MLX4_FS_REGULAR,
- .priority = MLX4_DOMAIN_NIC,
- };
-
- rule.port = priv->port;
- rule.qpn = *qpn;
- INIT_LIST_HEAD(&rule.list);
-
- spec_eth.id = MLX4_NET_TRANS_RULE_ID_ETH;
- memcpy(spec_eth.eth.dst_mac, mac, ETH_ALEN);
- memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
- list_add_tail(&spec_eth.list, &rule.list);
-
- err = mlx4_flow_attach(dev, &rule, reg_id);
- break;
- }
- default:
- return -EINVAL;
- }
- if (err)
- en_warn(priv, "Failed Attaching Unicast\n");
-
- return err;
-}
-
-static void mlx4_en_uc_steer_release(struct mlx4_en_priv *priv,
- unsigned char *mac, int qpn, u64 reg_id)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_dev *dev = mdev->dev;
-
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_B0: {
- struct mlx4_qp qp;
- u8 gid[16] = {0};
-
- qp.qpn = qpn;
- memcpy(&gid[10], mac, ETH_ALEN);
- gid[5] = priv->port;
-
- mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH);
- break;
- }
- case MLX4_STEERING_MODE_DEVICE_MANAGED: {
- mlx4_flow_detach(dev, reg_id);
- break;
- }
- default:
- en_err(priv, "Invalid steering mode.\n");
- }
-}
-
-static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_dev *dev = mdev->dev;
- struct mlx4_mac_entry *entry;
- int index = 0;
- int err = 0;
- u64 reg_id;
- int *qpn = &priv->base_qpn;
- u64 mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
-
- en_dbg(DRV, priv, "Registering MAC: %pM for adding\n",
- IF_LLADDR(priv->dev));
- index = mlx4_register_mac(dev, priv->port, mac);
- if (index < 0) {
- err = index;
- en_err(priv, "Failed adding MAC: %pM\n",
- IF_LLADDR(priv->dev));
- return err;
- }
-
- if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
- int base_qpn = mlx4_get_base_qpn(dev, priv->port);
- *qpn = base_qpn + index;
- return 0;
- }
-
- err = mlx4_qp_reserve_range(dev, 1, 1, qpn, 0);
- en_dbg(DRV, priv, "Reserved qp %d\n", *qpn);
- if (err) {
- en_err(priv, "Failed to reserve qp for mac registration\n");
- goto qp_err;
- }
-
- err = mlx4_en_uc_steer_add(priv, IF_LLADDR(priv->dev), qpn, &reg_id);
- if (err)
- goto steer_err;
-
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- err = -ENOMEM;
- goto alloc_err;
- }
- memcpy(entry->mac, IF_LLADDR(priv->dev), sizeof(entry->mac));
- entry->reg_id = reg_id;
-
- hlist_add_head(&entry->hlist,
- &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
-
- return 0;
-
-alloc_err:
- mlx4_en_uc_steer_release(priv, IF_LLADDR(priv->dev), *qpn, reg_id);
-
-steer_err:
- mlx4_qp_release_range(dev, *qpn, 1);
-
-qp_err:
- mlx4_unregister_mac(dev, priv->port, mac);
- return err;
-}
-
-static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_dev *dev = mdev->dev;
- int qpn = priv->base_qpn;
- u64 mac;
-
- if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
- mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
- en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
- IF_LLADDR(priv->dev));
- mlx4_unregister_mac(dev, priv->port, mac);
- } else {
- struct mlx4_mac_entry *entry;
- struct hlist_node *tmp;
- struct hlist_head *bucket;
- unsigned int i;
-
- for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
- bucket = &priv->mac_hash[i];
- hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
- mac = mlx4_mac_to_u64(entry->mac);
- en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
- entry->mac);
- mlx4_en_uc_steer_release(priv, entry->mac,
- qpn, entry->reg_id);
-
- mlx4_unregister_mac(dev, priv->port, mac);
- hlist_del(&entry->hlist);
- kfree(entry);
- }
- }
-
- en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
- priv->port, qpn);
- mlx4_qp_release_range(dev, qpn, 1);
- priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
- }
-}
-
-static void mlx4_en_clear_list(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_mc_list *tmp, *mc_to_del;
-
- list_for_each_entry_safe(mc_to_del, tmp, &priv->mc_list, list) {
- list_del(&mc_to_del->list);
- kfree(mc_to_del);
- }
-}
-
-static void mlx4_en_cache_mclist(struct net_device *dev)
-{
- struct ifmultiaddr *ifma;
- struct mlx4_en_mc_list *tmp;
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- if_maddr_rlock(dev);
- TAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen !=
- ETHER_ADDR_LEN)
- continue;
- /* Make sure the list didn't grow. */
- tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC);
- if (tmp == NULL) {
- en_err(priv, "Failed to allocate multicast list\n");
- break;
- }
- memcpy(tmp->addr,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETH_ALEN);
- list_add_tail(&tmp->list, &priv->mc_list);
- }
- if_maddr_runlock(dev);
-}
-
-static void update_mclist_flags(struct mlx4_en_priv *priv,
- struct list_head *dst,
- struct list_head *src)
-{
- struct mlx4_en_mc_list *dst_tmp, *src_tmp, *new_mc;
- bool found;
-
- /* Find all the entries that should be removed from dst,
- * These are the entries that are not found in src
- */
- list_for_each_entry(dst_tmp, dst, list) {
- found = false;
- list_for_each_entry(src_tmp, src, list) {
- if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
- found = true;
- break;
- }
- }
- if (!found)
- dst_tmp->action = MCLIST_REM;
- }
-
- /* Add entries that exist in src but not in dst
- * mark them as need to add
- */
- list_for_each_entry(src_tmp, src, list) {
- found = false;
- list_for_each_entry(dst_tmp, dst, list) {
- if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
- dst_tmp->action = MCLIST_NONE;
- found = true;
- break;
- }
- }
- if (!found) {
- new_mc = kmalloc(sizeof(struct mlx4_en_mc_list),
- GFP_KERNEL);
- if (!new_mc) {
- en_err(priv, "Failed to allocate current multicast list\n");
- return;
- }
- memcpy(new_mc, src_tmp,
- sizeof(struct mlx4_en_mc_list));
- new_mc->action = MCLIST_ADD;
- list_add_tail(&new_mc->list, dst);
- }
- }
-}
-
-static void mlx4_en_set_rx_mode(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- if (!priv->port_up)
- return;
-
- queue_work(priv->mdev->workqueue, &priv->rx_mode_task);
-}
-
-static void mlx4_en_set_promisc_mode(struct mlx4_en_priv *priv,
- struct mlx4_en_dev *mdev)
-{
- int err = 0;
- if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) {
- priv->flags |= MLX4_EN_FLAG_PROMISC;
-
- /* Enable promiscouos mode */
- switch (mdev->dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- err = mlx4_flow_steer_promisc_add(mdev->dev,
- priv->port,
- priv->base_qpn,
- MLX4_FS_ALL_DEFAULT);
- if (err)
- en_err(priv, "Failed enabling promiscuous mode\n");
- priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
- break;
-
- case MLX4_STEERING_MODE_B0:
- err = mlx4_unicast_promisc_add(mdev->dev,
- priv->base_qpn,
- priv->port);
- if (err)
- en_err(priv, "Failed enabling unicast promiscuous mode\n");
-
- /* Add the default qp number as multicast
- * promisc
- */
- if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
- err = mlx4_multicast_promisc_add(mdev->dev,
- priv->base_qpn,
- priv->port);
- if (err)
- en_err(priv, "Failed enabling multicast promiscuous mode\n");
- priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
- }
- break;
-
- case MLX4_STEERING_MODE_A0:
- err = mlx4_SET_PORT_qpn_calc(mdev->dev,
- priv->port,
- priv->base_qpn,
- 1);
- if (err)
- en_err(priv, "Failed enabling promiscuous mode\n");
- break;
- }
-
- /* Disable port multicast filter (unconditionally) */
- err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
- 0, MLX4_MCAST_DISABLE);
- if (err)
- en_err(priv, "Failed disabling multicast filter\n");
- }
-}
-
-static void mlx4_en_clear_promisc_mode(struct mlx4_en_priv *priv,
- struct mlx4_en_dev *mdev)
-{
- int err = 0;
-
- priv->flags &= ~MLX4_EN_FLAG_PROMISC;
-
- /* Disable promiscouos mode */
- switch (mdev->dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- err = mlx4_flow_steer_promisc_remove(mdev->dev,
- priv->port,
- MLX4_FS_ALL_DEFAULT);
- if (err)
- en_err(priv, "Failed disabling promiscuous mode\n");
- priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
- break;
-
- case MLX4_STEERING_MODE_B0:
- err = mlx4_unicast_promisc_remove(mdev->dev,
- priv->base_qpn,
- priv->port);
- if (err)
- en_err(priv, "Failed disabling unicast promiscuous mode\n");
- /* Disable Multicast promisc */
- if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
- err = mlx4_multicast_promisc_remove(mdev->dev,
- priv->base_qpn,
- priv->port);
- if (err)
- en_err(priv, "Failed disabling multicast promiscuous mode\n");
- priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
- }
- break;
-
- case MLX4_STEERING_MODE_A0:
- err = mlx4_SET_PORT_qpn_calc(mdev->dev,
- priv->port,
- priv->base_qpn, 0);
- if (err)
- en_err(priv, "Failed disabling promiscuous mode\n");
- break;
- }
-}
-
-static void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
- struct net_device *dev,
- struct mlx4_en_dev *mdev)
-{
- struct mlx4_en_mc_list *mclist, *tmp;
- u8 mc_list[16] = {0};
- int err = 0;
- u64 mcast_addr = 0;
-
-
- /* Enable/disable the multicast filter according to IFF_ALLMULTI */
- if (dev->if_flags & IFF_ALLMULTI) {
- err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
- 0, MLX4_MCAST_DISABLE);
- if (err)
- en_err(priv, "Failed disabling multicast filter\n");
-
- /* Add the default qp number as multicast promisc */
- if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
- switch (mdev->dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- err = mlx4_flow_steer_promisc_add(mdev->dev,
- priv->port,
- priv->base_qpn,
- MLX4_FS_MC_DEFAULT);
- break;
-
- case MLX4_STEERING_MODE_B0:
- err = mlx4_multicast_promisc_add(mdev->dev,
- priv->base_qpn,
- priv->port);
- break;
-
- case MLX4_STEERING_MODE_A0:
- break;
- }
- if (err)
- en_err(priv, "Failed entering multicast promisc mode\n");
- priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
- }
- } else {
- /* Disable Multicast promisc */
- if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
- switch (mdev->dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- err = mlx4_flow_steer_promisc_remove(mdev->dev,
- priv->port,
- MLX4_FS_MC_DEFAULT);
- break;
-
- case MLX4_STEERING_MODE_B0:
- err = mlx4_multicast_promisc_remove(mdev->dev,
- priv->base_qpn,
- priv->port);
- break;
-
- case MLX4_STEERING_MODE_A0:
- break;
- }
- if (err)
- en_err(priv, "Failed disabling multicast promiscuous mode\n");
- priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
- }
-
- err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
- 0, MLX4_MCAST_DISABLE);
- if (err)
- en_err(priv, "Failed disabling multicast filter\n");
-
- /* Flush mcast filter and init it with broadcast address */
- mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
- 1, MLX4_MCAST_CONFIG);
-
- /* Update multicast list - we cache all addresses so they won't
- * change while HW is updated holding the command semaphor */
- mlx4_en_cache_mclist(dev);
- list_for_each_entry(mclist, &priv->mc_list, list) {
- mcast_addr = mlx4_mac_to_u64(mclist->addr);
- mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
- mcast_addr, 0, MLX4_MCAST_CONFIG);
- }
- err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
- 0, MLX4_MCAST_ENABLE);
- if (err)
- en_err(priv, "Failed enabling multicast filter\n");
-
- update_mclist_flags(priv, &priv->curr_list, &priv->mc_list);
- list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
- if (mclist->action == MCLIST_REM) {
- /* detach this address and delete from list */
- memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
- mc_list[5] = priv->port;
- err = mlx4_multicast_detach(mdev->dev,
- &priv->rss_map.indir_qp,
- mc_list,
- MLX4_PROT_ETH,
- mclist->reg_id);
- if (err)
- en_err(priv, "Fail to detach multicast address\n");
-
- /* remove from list */
- list_del(&mclist->list);
- kfree(mclist);
- } else if (mclist->action == MCLIST_ADD) {
- /* attach the address */
- memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
- /* needed for B0 steering support */
- mc_list[5] = priv->port;
- err = mlx4_multicast_attach(mdev->dev,
- &priv->rss_map.indir_qp,
- mc_list,
- priv->port, 0,
- MLX4_PROT_ETH,
- &mclist->reg_id);
- if (err)
- en_err(priv, "Fail to attach multicast address\n");
-
- }
- }
- }
-}
-
-static void mlx4_en_do_set_rx_mode(struct work_struct *work)
-{
- struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
- rx_mode_task);
- struct mlx4_en_dev *mdev = priv->mdev;
- struct net_device *dev = priv->dev;
-
-
- mutex_lock(&mdev->state_lock);
- if (!mdev->device_up) {
- en_dbg(HW, priv, "Card is not up, ignoring rx mode change.\n");
- goto out;
- }
- if (!priv->port_up) {
- en_dbg(HW, priv, "Port is down, ignoring rx mode change.\n");
- goto out;
- }
- if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
- if (priv->port_state.link_state) {
- priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
- /* update netif baudrate */
- priv->dev->if_baudrate =
- IF_Mbps(priv->port_state.link_speed);
- /* Important note: the following call for if_link_state_change
- * is needed for interface up scenario (start port, link state
- * change) */
- if_link_state_change(priv->dev, LINK_STATE_UP);
- en_dbg(HW, priv, "Link Up\n");
- }
- }
-
- /* Promsicuous mode: disable all filters */
- if ((dev->if_flags & IFF_PROMISC) ||
- (priv->flags & MLX4_EN_FLAG_FORCE_PROMISC)) {
- mlx4_en_set_promisc_mode(priv, mdev);
- goto out;
- }
-
- /* Not in promiscuous mode */
- if (priv->flags & MLX4_EN_FLAG_PROMISC)
- mlx4_en_clear_promisc_mode(priv, mdev);
-
- mlx4_en_do_multicast(priv, dev, mdev);
-out:
- mutex_unlock(&mdev->state_lock);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void mlx4_en_netpoll(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_cq *cq;
- unsigned long flags;
- int i;
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- cq = priv->rx_cq[i];
- spin_lock_irqsave(&cq->lock, flags);
- napi_synchronize(&cq->napi);
- mlx4_en_process_rx_cq(dev, cq, 0);
- spin_unlock_irqrestore(&cq->lock, flags);
- }
-}
-#endif
-
-static void mlx4_en_watchdog_timeout(void *arg)
-{
- struct mlx4_en_priv *priv = arg;
- struct mlx4_en_dev *mdev = priv->mdev;
-
- en_dbg(DRV, priv, "Scheduling watchdog\n");
- queue_work(mdev->workqueue, &priv->watchdog_task);
- if (priv->port_up)
- callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
- mlx4_en_watchdog_timeout, priv);
-}
-
-
-
-static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_cq *cq;
- int i;
-
- /* If we haven't received a specific coalescing setting
- * (module param), we set the moderation parameters as follows:
- * - moder_cnt is set to the number of mtu sized packets to
- * satisfy our coelsing target.
- * - moder_time is set to a fixed value.
- */
- priv->rx_frames = MLX4_EN_RX_COAL_TARGET / priv->dev->if_mtu + 1;
- priv->rx_usecs = MLX4_EN_RX_COAL_TIME;
- priv->tx_frames = MLX4_EN_TX_COAL_PKTS;
- priv->tx_usecs = MLX4_EN_TX_COAL_TIME;
- en_dbg(INTR, priv, "Default coalesing params for mtu: %u - "
- "rx_frames:%d rx_usecs:%d\n",
- (unsigned)priv->dev->if_mtu, priv->rx_frames, priv->rx_usecs);
-
- /* Setup cq moderation params */
- for (i = 0; i < priv->rx_ring_num; i++) {
- cq = priv->rx_cq[i];
- cq->moder_cnt = priv->rx_frames;
- cq->moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- priv->last_moder_packets[i] = 0;
- priv->last_moder_bytes[i] = 0;
- }
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- cq = priv->tx_cq[i];
- cq->moder_cnt = priv->tx_frames;
- cq->moder_time = priv->tx_usecs;
- }
-
- /* Reset auto-moderation params */
- priv->pkt_rate_low = MLX4_EN_RX_RATE_LOW;
- priv->rx_usecs_low = MLX4_EN_RX_COAL_TIME_LOW;
- priv->pkt_rate_high = MLX4_EN_RX_RATE_HIGH;
- priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
- priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
- priv->adaptive_rx_coal = 1;
- priv->last_moder_jiffies = 0;
- priv->last_moder_tx_packets = 0;
-}
-
-static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
-{
- unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies);
- struct mlx4_en_cq *cq;
- unsigned long packets;
- unsigned long rate;
- unsigned long avg_pkt_size;
- unsigned long rx_packets;
- unsigned long rx_bytes;
- unsigned long rx_pkt_diff;
- int moder_time;
- int ring, err;
-
- if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
- return;
-
- for (ring = 0; ring < priv->rx_ring_num; ring++) {
- spin_lock(&priv->stats_lock);
- rx_packets = priv->rx_ring[ring]->packets;
- rx_bytes = priv->rx_ring[ring]->bytes;
- spin_unlock(&priv->stats_lock);
-
- rx_pkt_diff = ((unsigned long) (rx_packets -
- priv->last_moder_packets[ring]));
- packets = rx_pkt_diff;
- rate = packets * HZ / period;
- avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
- priv->last_moder_bytes[ring])) / packets : 0;
-
- /* Apply auto-moderation only when packet rate
- * exceeds a rate that it matters */
- if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
- avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
- if (rate < priv->pkt_rate_low)
- moder_time = priv->rx_usecs_low;
- else if (rate > priv->pkt_rate_high)
- moder_time = priv->rx_usecs_high;
- else
- moder_time = (rate - priv->pkt_rate_low) *
- (priv->rx_usecs_high - priv->rx_usecs_low) /
- (priv->pkt_rate_high - priv->pkt_rate_low) +
- priv->rx_usecs_low;
- } else {
- moder_time = priv->rx_usecs_low;
- }
-
- if (moder_time != priv->last_moder_time[ring]) {
- priv->last_moder_time[ring] = moder_time;
- cq = priv->rx_cq[ring];
- cq->moder_time = moder_time;
- err = mlx4_en_set_cq_moder(priv, cq);
- if (err)
- en_err(priv, "Failed modifying moderation for cq:%d\n",
- ring);
- }
- priv->last_moder_packets[ring] = rx_packets;
- priv->last_moder_bytes[ring] = rx_bytes;
- }
-
- priv->last_moder_jiffies = jiffies;
-}
-
-static void mlx4_en_do_get_stats(struct work_struct *work)
-{
- struct delayed_work *delay = to_delayed_work(work);
- struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
- stats_task);
- struct mlx4_en_dev *mdev = priv->mdev;
- int err;
-
- mutex_lock(&mdev->state_lock);
- if (mdev->device_up) {
- if (priv->port_up) {
- err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0);
- if (err)
- en_dbg(HW, priv, "Could not update stats\n");
-
- mlx4_en_auto_moderation(priv);
- }
-
- queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
- }
- mutex_unlock(&mdev->state_lock);
-}
-
-/* mlx4_en_service_task - Run service task for tasks that needed to be done
- * periodically
- */
-static void mlx4_en_service_task(struct work_struct *work)
-{
- struct delayed_work *delay = to_delayed_work(work);
- struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
- service_task);
- struct mlx4_en_dev *mdev = priv->mdev;
-
- mutex_lock(&mdev->state_lock);
- if (mdev->device_up) {
- queue_delayed_work(mdev->workqueue, &priv->service_task,
- SERVICE_TASK_DELAY);
- }
- mutex_unlock(&mdev->state_lock);
-}
-
-static void mlx4_en_linkstate(struct work_struct *work)
-{
- struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
- linkstate_task);
- struct mlx4_en_dev *mdev = priv->mdev;
- int linkstate = priv->link_state;
-
- mutex_lock(&mdev->state_lock);
- /* If observable port state changed set carrier state and
- * report to system log */
- if (priv->last_link_state != linkstate) {
- if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
- en_info(priv, "Link Down\n");
- if_link_state_change(priv->dev, LINK_STATE_DOWN);
- /* update netif baudrate */
- priv->dev->if_baudrate = 0;
-
- /* make sure the port is up before notifying the OS.
- * This is tricky since we get here on INIT_PORT and
- * in such case we can't tell the OS the port is up.
- * To solve this there is a call to if_link_state_change
- * in set_rx_mode.
- * */
- } else if (priv->port_up && (linkstate == MLX4_DEV_EVENT_PORT_UP)){
- if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
- en_info(priv, "Query port failed\n");
- priv->dev->if_baudrate =
- IF_Mbps(priv->port_state.link_speed);
- en_info(priv, "Link Up\n");
- if_link_state_change(priv->dev, LINK_STATE_UP);
- }
- }
- priv->last_link_state = linkstate;
- mutex_unlock(&mdev->state_lock);
-}
-
-
-int mlx4_en_start_port(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_cq *cq;
- struct mlx4_en_tx_ring *tx_ring;
- int rx_index = 0;
- int tx_index = 0;
- int err = 0;
- int i;
- int j;
- u8 mc_list[16] = {0};
-
-
- if (priv->port_up) {
- en_dbg(DRV, priv, "start port called while port already up\n");
- return 0;
- }
-
- INIT_LIST_HEAD(&priv->mc_list);
- INIT_LIST_HEAD(&priv->curr_list);
- INIT_LIST_HEAD(&priv->ethtool_list);
-
- /* Calculate Rx buf size */
- dev->if_mtu = min(dev->if_mtu, priv->max_mtu);
- mlx4_en_calc_rx_buf(dev);
- en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_mb_size);
-
- /* Configure rx cq's and rings */
- err = mlx4_en_activate_rx_rings(priv);
- if (err) {
- en_err(priv, "Failed to activate RX rings\n");
- return err;
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- cq = priv->rx_cq[i];
-
- mlx4_en_cq_init_lock(cq);
- err = mlx4_en_activate_cq(priv, cq, i);
- if (err) {
- en_err(priv, "Failed activating Rx CQ\n");
- goto cq_err;
- }
- for (j = 0; j < cq->size; j++)
- cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK;
- err = mlx4_en_set_cq_moder(priv, cq);
- if (err) {
- en_err(priv, "Failed setting cq moderation parameters");
- mlx4_en_deactivate_cq(priv, cq);
- goto cq_err;
- }
- mlx4_en_arm_cq(priv, cq);
- priv->rx_ring[i]->cqn = cq->mcq.cqn;
- ++rx_index;
- }
-
- /* Set qp number */
- en_dbg(DRV, priv, "Getting qp number for port %d\n", priv->port);
- err = mlx4_en_get_qp(priv);
- if (err) {
- en_err(priv, "Failed getting eth qp\n");
- goto cq_err;
- }
- mdev->mac_removed[priv->port] = 0;
-
- /* gets default allocated counter index from func cap */
- /* or sink counter index if no resources */
- priv->counter_index = mdev->dev->caps.def_counter_index[priv->port - 1];
-
- en_dbg(DRV, priv, "%s: default counter index %d for port %d\n",
- __func__, priv->counter_index, priv->port);
-
- err = mlx4_en_config_rss_steer(priv);
- if (err) {
- en_err(priv, "Failed configuring rss steering\n");
- goto mac_err;
- }
-
- err = mlx4_en_create_drop_qp(priv);
- if (err)
- goto rss_err;
-
- /* Configure tx cq's and rings */
- for (i = 0; i < priv->tx_ring_num; i++) {
- /* Configure cq */
- cq = priv->tx_cq[i];
- err = mlx4_en_activate_cq(priv, cq, i);
- if (err) {
- en_err(priv, "Failed activating Tx CQ\n");
- goto tx_err;
- }
- err = mlx4_en_set_cq_moder(priv, cq);
- if (err) {
- en_err(priv, "Failed setting cq moderation parameters");
- mlx4_en_deactivate_cq(priv, cq);
- goto tx_err;
- }
- en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
- cq->buf->wqe_index = cpu_to_be16(0xffff);
-
- /* Configure ring */
- tx_ring = priv->tx_ring[i];
-
- err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
- i / priv->num_tx_rings_p_up);
- if (err) {
- en_err(priv, "Failed activating Tx ring %d\n", i);
- mlx4_en_deactivate_cq(priv, cq);
- goto tx_err;
- }
-
- /* Arm CQ for TX completions */
- mlx4_en_arm_cq(priv, cq);
-
- /* Set initial ownership of all Tx TXBBs to SW (1) */
- for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
- *((u32 *) (tx_ring->buf + j)) = 0xffffffff;
- ++tx_index;
- }
-
- /* Configure port */
- err = mlx4_SET_PORT_general(mdev->dev, priv->port,
- priv->rx_mb_size,
- priv->prof->tx_pause,
- priv->prof->tx_ppp,
- priv->prof->rx_pause,
- priv->prof->rx_ppp);
- if (err) {
- en_err(priv, "Failed setting port general configurations for port %d, with error %d\n",
- priv->port, err);
- goto tx_err;
- }
- /* Set default qp number */
- err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0);
- if (err) {
- en_err(priv, "Failed setting default qp numbers\n");
- goto tx_err;
- }
-
- /* Init port */
- en_dbg(HW, priv, "Initializing port\n");
- err = mlx4_INIT_PORT(mdev->dev, priv->port);
- if (err) {
- en_err(priv, "Failed Initializing port\n");
- goto tx_err;
- }
-
- /* Attach rx QP to bradcast address */
- memset(&mc_list[10], 0xff, ETH_ALEN);
- mc_list[5] = priv->port; /* needed for B0 steering support */
- if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
- priv->port, 0, MLX4_PROT_ETH,
- &priv->broadcast_id))
- mlx4_warn(mdev, "Failed Attaching Broadcast\n");
-
- /* Must redo promiscuous mode setup. */
- priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC);
-
- /* Schedule multicast task to populate multicast list */
- queue_work(mdev->workqueue, &priv->rx_mode_task);
-
- mlx4_set_stats_bitmap(mdev->dev, priv->stats_bitmap);
-
- priv->port_up = true;
-
- /* Enable the queues. */
- dev->if_drv_flags &= ~IFF_DRV_OACTIVE;
- dev->if_drv_flags |= IFF_DRV_RUNNING;
-#ifdef CONFIG_DEBUG_FS
- mlx4_en_create_debug_files(priv);
-#endif
- callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
- mlx4_en_watchdog_timeout, priv);
-
-
- return 0;
-
-tx_err:
- while (tx_index--) {
- mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[tx_index]);
- mlx4_en_deactivate_cq(priv, priv->tx_cq[tx_index]);
- }
- mlx4_en_destroy_drop_qp(priv);
-rss_err:
- mlx4_en_release_rss_steer(priv);
-mac_err:
- mlx4_en_put_qp(priv);
-cq_err:
- while (rx_index--)
- mlx4_en_deactivate_cq(priv, priv->rx_cq[rx_index]);
- for (i = 0; i < priv->rx_ring_num; i++)
- mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
-
- return err; /* need to close devices */
-}
-
-
-void mlx4_en_stop_port(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_mc_list *mclist, *tmp;
- int i;
- u8 mc_list[16] = {0};
-
- if (!priv->port_up) {
- en_dbg(DRV, priv, "stop port called while port already down\n");
- return;
- }
-
-#ifdef CONFIG_DEBUG_FS
- mlx4_en_delete_debug_files(priv);
-#endif
-
- /* close port*/
- mlx4_CLOSE_PORT(mdev->dev, priv->port);
-
- /* Set port as not active */
- priv->port_up = false;
- if (priv->counter_index != 0xff) {
- mlx4_counter_free(mdev->dev, priv->port, priv->counter_index);
- priv->counter_index = 0xff;
- }
-
- /* Promsicuous mode */
- if (mdev->dev->caps.steering_mode ==
- MLX4_STEERING_MODE_DEVICE_MANAGED) {
- priv->flags &= ~(MLX4_EN_FLAG_PROMISC |
- MLX4_EN_FLAG_MC_PROMISC);
- mlx4_flow_steer_promisc_remove(mdev->dev,
- priv->port,
- MLX4_FS_ALL_DEFAULT);
- mlx4_flow_steer_promisc_remove(mdev->dev,
- priv->port,
- MLX4_FS_MC_DEFAULT);
- } else if (priv->flags & MLX4_EN_FLAG_PROMISC) {
- priv->flags &= ~MLX4_EN_FLAG_PROMISC;
-
- /* Disable promiscouos mode */
- mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
- priv->port);
-
- /* Disable Multicast promisc */
- if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
- mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
- priv->port);
- priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
- }
- }
-
- /* Detach All multicasts */
- memset(&mc_list[10], 0xff, ETH_ALEN);
- mc_list[5] = priv->port; /* needed for B0 steering support */
- mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
- MLX4_PROT_ETH, priv->broadcast_id);
- list_for_each_entry(mclist, &priv->curr_list, list) {
- memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
- mc_list[5] = priv->port;
- mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
- mc_list, MLX4_PROT_ETH, mclist->reg_id);
- }
- mlx4_en_clear_list(dev);
- list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
- list_del(&mclist->list);
- kfree(mclist);
- }
-
- /* Flush multicast filter */
- mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
- mlx4_en_destroy_drop_qp(priv);
-
- /* Free TX Rings */
- for (i = 0; i < priv->tx_ring_num; i++) {
- mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[i]);
- mlx4_en_deactivate_cq(priv, priv->tx_cq[i]);
- }
- msleep(10);
-
- for (i = 0; i < priv->tx_ring_num; i++)
- mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
-
- /* Free RSS qps */
- mlx4_en_release_rss_steer(priv);
-
- /* Unregister Mac address for the port */
- mlx4_en_put_qp(priv);
- mdev->mac_removed[priv->port] = 1;
-
- /* Free RX Rings */
- for (i = 0; i < priv->rx_ring_num; i++) {
- struct mlx4_en_cq *cq = priv->rx_cq[i];
- mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
- mlx4_en_deactivate_cq(priv, cq);
- }
-
- callout_stop(&priv->watchdog_timer);
-
- dev->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-}
-
-static void mlx4_en_restart(struct work_struct *work)
-{
- struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
- watchdog_task);
- struct mlx4_en_dev *mdev = priv->mdev;
- struct net_device *dev = priv->dev;
- struct mlx4_en_tx_ring *ring;
- int i;
-
-
- if (priv->blocked == 0 || priv->port_up == 0)
- return;
- for (i = 0; i < priv->tx_ring_num; i++) {
- ring = priv->tx_ring[i];
- if (ring->blocked &&
- ring->watchdog_time + MLX4_EN_WATCHDOG_TIMEOUT < ticks)
- goto reset;
- }
- return;
-
-reset:
- priv->port_stats.tx_timeout++;
- en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
-
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- mlx4_en_stop_port(dev);
- //for (i = 0; i < priv->tx_ring_num; i++)
- // netdev_tx_reset_queue(priv->tx_ring[i]->tx_queue);
- if (mlx4_en_start_port(dev))
- en_err(priv, "Failed restarting port %d\n", priv->port);
- }
- mutex_unlock(&mdev->state_lock);
-}
-
-static void mlx4_en_clear_stats(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int i;
-
- if (!mlx4_is_slave(mdev->dev))
- if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
- en_dbg(HW, priv, "Failed dumping statistics\n");
-
- memset(&priv->pstats, 0, sizeof(priv->pstats));
- memset(&priv->pkstats, 0, sizeof(priv->pkstats));
- memset(&priv->port_stats, 0, sizeof(priv->port_stats));
- memset(&priv->vport_stats, 0, sizeof(priv->vport_stats));
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->tx_ring[i]->bytes = 0;
- priv->tx_ring[i]->packets = 0;
- priv->tx_ring[i]->tx_csum = 0;
- priv->tx_ring[i]->oversized_packets = 0;
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_ring[i]->bytes = 0;
- priv->rx_ring[i]->packets = 0;
- priv->rx_ring[i]->csum_ok = 0;
- priv->rx_ring[i]->csum_none = 0;
- }
-}
-
-static void mlx4_en_open(void* arg)
-{
-
- struct mlx4_en_priv *priv;
- struct mlx4_en_dev *mdev;
- struct net_device *dev;
- int err = 0;
-
- priv = arg;
- mdev = priv->mdev;
- dev = priv->dev;
-
-
- mutex_lock(&mdev->state_lock);
-
- if (!mdev->device_up) {
- en_err(priv, "Cannot open - device down/disabled\n");
- goto out;
- }
-
- /* Reset HW statistics and SW counters */
- mlx4_en_clear_stats(dev);
-
- err = mlx4_en_start_port(dev);
- if (err)
- en_err(priv, "Failed starting port:%d\n", priv->port);
-
-out:
- mutex_unlock(&mdev->state_lock);
- return;
-}
-
-void mlx4_en_free_resources(struct mlx4_en_priv *priv)
-{
- int i;
-
-#ifdef CONFIG_RFS_ACCEL
- if (priv->dev->rx_cpu_rmap) {
- free_irq_cpu_rmap(priv->dev->rx_cpu_rmap);
- priv->dev->rx_cpu_rmap = NULL;
- }
-#endif
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- if (priv->tx_ring && priv->tx_ring[i])
- mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
- if (priv->tx_cq && priv->tx_cq[i])
- mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
- }
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- if (priv->rx_ring[i])
- mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
- priv->prof->rx_ring_size, priv->stride);
- if (priv->rx_cq[i])
- mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
- }
-
- if (priv->sysctl)
- sysctl_ctx_free(&priv->stat_ctx);
-}
-
-int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_port_profile *prof = priv->prof;
- int i;
- int node = 0;
-
- /* Create rx Rings */
- for (i = 0; i < priv->rx_ring_num; i++) {
- if (mlx4_en_create_cq(priv, &priv->rx_cq[i],
- prof->rx_ring_size, i, RX, node))
- goto err;
-
- if (mlx4_en_create_rx_ring(priv, &priv->rx_ring[i],
- prof->rx_ring_size, node))
- goto err;
- }
-
- /* Create tx Rings */
- for (i = 0; i < priv->tx_ring_num; i++) {
- if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
- prof->tx_ring_size, i, TX, node))
- goto err;
-
- if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
- prof->tx_ring_size, TXBB_SIZE, node, i))
- goto err;
- }
-
-#ifdef CONFIG_RFS_ACCEL
- priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->rx_ring_num);
- if (!priv->dev->rx_cpu_rmap)
- goto err;
-#endif
- /* Re-create stat sysctls in case the number of rings changed. */
- mlx4_en_sysctl_stat(priv);
- return 0;
-
-err:
- en_err(priv, "Failed to allocate NIC resources\n");
- for (i = 0; i < priv->rx_ring_num; i++) {
- if (priv->rx_ring[i])
- mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
- prof->rx_ring_size,
- priv->stride);
- if (priv->rx_cq[i])
- mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
- }
- for (i = 0; i < priv->tx_ring_num; i++) {
- if (priv->tx_ring[i])
- mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
- if (priv->tx_cq[i])
- mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
- }
- priv->port_up = false;
- return -ENOMEM;
-}
-
-struct en_port_attribute {
- struct attribute attr;
- ssize_t (*show)(struct en_port *, struct en_port_attribute *, char *buf);
- ssize_t (*store)(struct en_port *, struct en_port_attribute *, char *buf, size_t count);
-};
-
-#define PORT_ATTR_RO(_name) \
-struct en_port_attribute en_port_attr_##_name = __ATTR_RO(_name)
-
-#define EN_PORT_ATTR(_name, _mode, _show, _store) \
-struct en_port_attribute en_port_attr_##_name = __ATTR(_name, _mode, _show, _store)
-
-void mlx4_en_destroy_netdev(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
-
- en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
-
- if (priv->vlan_attach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_config, priv->vlan_attach);
- if (priv->vlan_detach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach);
-
- /* Unregister device - this will close the port if it was up */
- if (priv->registered) {
- mutex_lock(&mdev->state_lock);
- ether_ifdetach(dev);
- mutex_unlock(&mdev->state_lock);
- }
-
- if (priv->allocated)
- mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
-
- mutex_lock(&mdev->state_lock);
- mlx4_en_stop_port(dev);
- mutex_unlock(&mdev->state_lock);
-
-
- cancel_delayed_work(&priv->stats_task);
- cancel_delayed_work(&priv->service_task);
- /* flush any pending task for this netdev */
- flush_workqueue(mdev->workqueue);
- callout_drain(&priv->watchdog_timer);
-
- /* Detach the netdev so tasks would not attempt to access it */
- mutex_lock(&mdev->state_lock);
- mdev->pndev[priv->port] = NULL;
- mutex_unlock(&mdev->state_lock);
-
-
- mlx4_en_free_resources(priv);
-
- /* freeing the sysctl conf cannot be called from within mlx4_en_free_resources */
- if (priv->sysctl)
- sysctl_ctx_free(&priv->conf_ctx);
-
- kfree(priv->tx_ring);
- kfree(priv->tx_cq);
-
- kfree(priv);
- if_free(dev);
-
-}
-
-static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int err = 0;
-
- en_dbg(DRV, priv, "Change MTU called - current:%u new:%u\n",
- (unsigned)dev->if_mtu, (unsigned)new_mtu);
-
- if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
- en_err(priv, "Bad MTU size:%d.\n", new_mtu);
- return -EPERM;
- }
- mutex_lock(&mdev->state_lock);
- dev->if_mtu = new_mtu;
- if (dev->if_drv_flags & IFF_DRV_RUNNING) {
- if (!mdev->device_up) {
- /* NIC is probably restarting - let watchdog task reset
- * * the port */
- en_dbg(DRV, priv, "Change MTU called with card down!?\n");
- } else {
- mlx4_en_stop_port(dev);
- err = mlx4_en_start_port(dev);
- if (err) {
- en_err(priv, "Failed restarting port:%d\n",
- priv->port);
- queue_work(mdev->workqueue, &priv->watchdog_task);
- }
- }
- }
- mutex_unlock(&mdev->state_lock);
- return 0;
-}
-
-static int mlx4_en_calc_media(struct mlx4_en_priv *priv)
-{
- int trans_type;
- int active;
-
- active = IFM_ETHER;
- if (priv->last_link_state == MLX4_DEV_EVENT_PORT_DOWN)
- return (active);
- active |= IFM_FDX;
- trans_type = priv->port_state.transciver;
- /* XXX I don't know all of the transceiver values. */
- switch (priv->port_state.link_speed) {
- case 1000:
- active |= IFM_1000_T;
- break;
- case 10000:
- if (trans_type > 0 && trans_type <= 0xC)
- active |= IFM_10G_SR;
- else if (trans_type == 0x80 || trans_type == 0)
- active |= IFM_10G_CX4;
- break;
- case 40000:
- active |= IFM_40G_CR4;
- break;
- }
- if (priv->prof->tx_pause)
- active |= IFM_ETH_TXPAUSE;
- if (priv->prof->rx_pause)
- active |= IFM_ETH_RXPAUSE;
-
- return (active);
-}
-
-static void mlx4_en_media_status(struct ifnet *dev, struct ifmediareq *ifmr)
-{
- struct mlx4_en_priv *priv;
-
- priv = dev->if_softc;
- ifmr->ifm_status = IFM_AVALID;
- if (priv->last_link_state != MLX4_DEV_EVENT_PORT_DOWN)
- ifmr->ifm_status |= IFM_ACTIVE;
- ifmr->ifm_active = mlx4_en_calc_media(priv);
-
- return;
-}
-
-static int mlx4_en_media_change(struct ifnet *dev)
-{
- struct mlx4_en_priv *priv;
- struct ifmedia *ifm;
- int rxpause;
- int txpause;
- int error;
-
- priv = dev->if_softc;
- ifm = &priv->media;
- rxpause = txpause = 0;
- error = 0;
-
- if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
- return (EINVAL);
- switch (IFM_SUBTYPE(ifm->ifm_media)) {
- case IFM_AUTO:
- break;
- case IFM_10G_SR:
- case IFM_10G_CX4:
- case IFM_1000_T:
- case IFM_40G_CR4:
- if ((IFM_SUBTYPE(ifm->ifm_media)
- == IFM_SUBTYPE(mlx4_en_calc_media(priv)))
- && (ifm->ifm_media & IFM_FDX))
- break;
- /* Fallthrough */
- default:
- printf("%s: Only auto media type\n", if_name(dev));
- return (EINVAL);
- }
- /* Allow user to set/clear pause */
- if (IFM_OPTIONS(ifm->ifm_media) & IFM_ETH_RXPAUSE)
- rxpause = 1;
- if (IFM_OPTIONS(ifm->ifm_media) & IFM_ETH_TXPAUSE)
- txpause = 1;
- if (priv->prof->tx_pause != txpause || priv->prof->rx_pause != rxpause) {
- priv->prof->tx_pause = txpause;
- priv->prof->rx_pause = rxpause;
- error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
- priv->rx_mb_size + ETHER_CRC_LEN, priv->prof->tx_pause,
- priv->prof->tx_ppp, priv->prof->rx_pause,
- priv->prof->rx_ppp);
- }
- return (error);
-}
-
-static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data)
-{
- struct mlx4_en_priv *priv;
- struct mlx4_en_dev *mdev;
- struct ifreq *ifr;
- int error;
- int mask;
-
- error = 0;
- mask = 0;
- priv = dev->if_softc;
- mdev = priv->mdev;
- ifr = (struct ifreq *) data;
- switch (command) {
-
- case SIOCSIFMTU:
- error = -mlx4_en_change_mtu(dev, ifr->ifr_mtu);
- break;
- case SIOCSIFFLAGS:
- if (dev->if_flags & IFF_UP) {
- if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- mutex_lock(&mdev->state_lock);
- mlx4_en_start_port(dev);
- mutex_unlock(&mdev->state_lock);
- } else {
- mlx4_en_set_rx_mode(dev);
- }
- } else {
- mutex_lock(&mdev->state_lock);
- if (dev->if_drv_flags & IFF_DRV_RUNNING) {
- mlx4_en_stop_port(dev);
- if_link_state_change(dev, LINK_STATE_DOWN);
- }
- mutex_unlock(&mdev->state_lock);
- }
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- mlx4_en_set_rx_mode(dev);
- break;
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(dev, ifr, &priv->media, command);
- break;
- case SIOCSIFCAP:
- mutex_lock(&mdev->state_lock);
- mask = ifr->ifr_reqcap ^ dev->if_capenable;
- if (mask & IFCAP_TXCSUM) {
- dev->if_capenable ^= IFCAP_TXCSUM;
- dev->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
-
- if (IFCAP_TSO4 & dev->if_capenable &&
- !(IFCAP_TXCSUM & dev->if_capenable)) {
- dev->if_capenable &= ~IFCAP_TSO4;
- dev->if_hwassist &= ~CSUM_IP_TSO;
- if_printf(dev,
- "tso4 disabled due to -txcsum.\n");
- }
- }
- if (mask & IFCAP_TXCSUM_IPV6) {
- dev->if_capenable ^= IFCAP_TXCSUM_IPV6;
- dev->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
-
- if (IFCAP_TSO6 & dev->if_capenable &&
- !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
- dev->if_capenable &= ~IFCAP_TSO6;
- dev->if_hwassist &= ~CSUM_IP6_TSO;
- if_printf(dev,
- "tso6 disabled due to -txcsum6.\n");
- }
- }
- if (mask & IFCAP_RXCSUM)
- dev->if_capenable ^= IFCAP_RXCSUM;
- if (mask & IFCAP_RXCSUM_IPV6)
- dev->if_capenable ^= IFCAP_RXCSUM_IPV6;
-
- if (mask & IFCAP_TSO4) {
- if (!(IFCAP_TSO4 & dev->if_capenable) &&
- !(IFCAP_TXCSUM & dev->if_capenable)) {
- if_printf(dev, "enable txcsum first.\n");
- error = EAGAIN;
- goto out;
- }
- dev->if_capenable ^= IFCAP_TSO4;
- dev->if_hwassist ^= CSUM_IP_TSO;
- }
- if (mask & IFCAP_TSO6) {
- if (!(IFCAP_TSO6 & dev->if_capenable) &&
- !(IFCAP_TXCSUM_IPV6 & dev->if_capenable)) {
- if_printf(dev, "enable txcsum6 first.\n");
- error = EAGAIN;
- goto out;
- }
- dev->if_capenable ^= IFCAP_TSO6;
- dev->if_hwassist ^= CSUM_IP6_TSO;
- }
- if (mask & IFCAP_LRO)
- dev->if_capenable ^= IFCAP_LRO;
- if (mask & IFCAP_VLAN_HWTAGGING)
- dev->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (mask & IFCAP_VLAN_HWFILTER)
- dev->if_capenable ^= IFCAP_VLAN_HWFILTER;
- if (mask & IFCAP_WOL_MAGIC)
- dev->if_capenable ^= IFCAP_WOL_MAGIC;
- if (dev->if_drv_flags & IFF_DRV_RUNNING)
- mlx4_en_start_port(dev);
-out:
- mutex_unlock(&mdev->state_lock);
- VLAN_CAPABILITIES(dev);
- break;
-#if __FreeBSD_version >= 1100036
- case SIOCGI2C: {
- struct ifi2creq i2c;
-
- error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
- if (error)
- break;
- if (i2c.len > sizeof(i2c.data)) {
- error = EINVAL;
- break;
- }
- /*
- * Note that we ignore i2c.addr here. The driver hardcodes
- * the address to 0x50, while standard expects it to be 0xA0.
- */
- error = mlx4_get_module_info(mdev->dev, priv->port,
- i2c.offset, i2c.len, i2c.data);
- if (error < 0) {
- error = -error;
- break;
- }
- error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
- break;
- }
-#endif
- default:
- error = ether_ioctl(dev, command, data);
- break;
- }
-
- return (error);
-}
-
-
-int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
- struct mlx4_en_port_profile *prof)
-{
- struct net_device *dev;
- struct mlx4_en_priv *priv;
- uint8_t dev_addr[ETHER_ADDR_LEN];
- int err;
- int i;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- dev = priv->dev = if_alloc(IFT_ETHER);
- if (dev == NULL) {
- en_err(priv, "Net device allocation failed\n");
- kfree(priv);
- return -ENOMEM;
- }
- dev->if_softc = priv;
- if_initname(dev, "mlxen", atomic_fetchadd_int(&mlx4_en_unit, 1));
- dev->if_mtu = ETHERMTU;
- dev->if_init = mlx4_en_open;
- dev->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- dev->if_ioctl = mlx4_en_ioctl;
- dev->if_transmit = mlx4_en_transmit;
- dev->if_qflush = mlx4_en_qflush;
- dev->if_snd.ifq_maxlen = prof->tx_ring_size;
-
- /*
- * Initialize driver private data
- */
- priv->counter_index = 0xff;
- spin_lock_init(&priv->stats_lock);
- INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
- INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
- INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
- INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
- INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
- callout_init(&priv->watchdog_timer, 1);
-#ifdef CONFIG_RFS_ACCEL
- INIT_LIST_HEAD(&priv->filters);
- spin_lock_init(&priv->filters_lock);
-#endif
-
- priv->msg_enable = MLX4_EN_MSG_LEVEL;
- priv->dev = dev;
- priv->mdev = mdev;
- priv->ddev = &mdev->pdev->dev;
- priv->prof = prof;
- priv->port = port;
- priv->port_up = false;
- priv->flags = prof->flags;
-
- priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
- priv->tx_ring_num = prof->tx_ring_num;
- priv->tx_ring = kcalloc(MAX_TX_RINGS,
- sizeof(struct mlx4_en_tx_ring *), GFP_KERNEL);
- if (!priv->tx_ring) {
- err = -ENOMEM;
- goto out;
- }
- priv->tx_cq = kcalloc(sizeof(struct mlx4_en_cq *), MAX_TX_RINGS,
- GFP_KERNEL);
- if (!priv->tx_cq) {
- err = -ENOMEM;
- goto out;
- }
-
- priv->rx_ring_num = prof->rx_ring_num;
- priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
- priv->mac_index = -1;
- priv->last_ifq_jiffies = 0;
- priv->if_counters_rx_errors = 0;
- priv->if_counters_rx_no_buffer = 0;
-#ifdef CONFIG_MLX4_EN_DCB
- if (!mlx4_is_slave(priv->mdev->dev)) {
- priv->dcbx_cap = DCB_CAP_DCBX_HOST;
- priv->flags |= MLX4_EN_FLAG_DCB_ENABLED;
- if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETS_CFG) {
- dev->dcbnl_ops = &mlx4_en_dcbnl_ops;
- } else {
- en_info(priv, "QoS disabled - no HW support\n");
- dev->dcbnl_ops = &mlx4_en_dcbnl_pfc_ops;
- }
- }
-#endif
-
- for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i)
- INIT_HLIST_HEAD(&priv->mac_hash[i]);
-
- /* Query for default mac and max mtu */
- priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
- priv->mac = mdev->dev->caps.def_mac[priv->port];
- if (ILLEGAL_MAC(priv->mac)) {
-#if BITS_PER_LONG == 64
- en_err(priv, "Port: %d, invalid mac burned: 0x%lx, quiting\n",
- priv->port, priv->mac);
-#elif BITS_PER_LONG == 32
- en_err(priv, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
- priv->port, priv->mac);
-#endif
- err = -EINVAL;
- goto out;
- }
-
- priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
- DS_SIZE);
-
- mlx4_en_sysctl_conf(priv);
-
- err = mlx4_en_alloc_resources(priv);
- if (err)
- goto out;
-
- /* Allocate page for receive rings */
- err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
- MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
- if (err) {
- en_err(priv, "Failed to allocate page for rx qps\n");
- goto out;
- }
- priv->allocated = 1;
-
- /*
- * Set driver features
- */
- dev->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6;
- dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
- dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
- dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
- dev->if_capabilities |= IFCAP_LRO;
- dev->if_capabilities |= IFCAP_HWSTATS;
-
- if (mdev->LSO_support)
- dev->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTSO;
-
-#if __FreeBSD_version >= 1100000
- /* set TSO limits so that we don't have to drop TX packets */
- dev->if_hw_tsomax = MLX4_EN_TX_MAX_PAYLOAD_SIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN) /* hdr */;
- dev->if_hw_tsomaxsegcount = MLX4_EN_TX_MAX_MBUF_FRAGS - 1 /* hdr */;
- dev->if_hw_tsomaxsegsize = MLX4_EN_TX_MAX_MBUF_SIZE;
-#endif
-
- dev->if_capenable = dev->if_capabilities;
-
- dev->if_hwassist = 0;
- if (dev->if_capenable & (IFCAP_TSO4 | IFCAP_TSO6))
- dev->if_hwassist |= CSUM_TSO;
- if (dev->if_capenable & IFCAP_TXCSUM)
- dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP);
- if (dev->if_capenable & IFCAP_TXCSUM_IPV6)
- dev->if_hwassist |= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6);
-
-
- /* Register for VLAN events */
- priv->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
- mlx4_en_vlan_rx_add_vid, priv, EVENTHANDLER_PRI_FIRST);
- priv->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
- mlx4_en_vlan_rx_kill_vid, priv, EVENTHANDLER_PRI_FIRST);
-
- mdev->pndev[priv->port] = dev;
-
- priv->last_link_state = MLX4_DEV_EVENT_PORT_DOWN;
- mlx4_en_set_default_moderation(priv);
-
- /* Set default MAC */
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- dev_addr[ETHER_ADDR_LEN - 1 - i] = (u8) (priv->mac >> (8 * i));
-
-
- ether_ifattach(dev, dev_addr);
- if_link_state_change(dev, LINK_STATE_DOWN);
- ifmedia_init(&priv->media, IFM_IMASK | IFM_ETH_FMASK,
- mlx4_en_media_change, mlx4_en_media_status);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_1000_T, 0, NULL);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_SR, 0, NULL);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_CX4, 0, NULL);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_40G_CR4, 0, NULL);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
-
- en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
- en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
-
- priv->registered = 1;
-
- en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
- en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
-
-
- priv->rx_mb_size = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
- err = mlx4_SET_PORT_general(mdev->dev, priv->port,
- priv->rx_mb_size,
- prof->tx_pause, prof->tx_ppp,
- prof->rx_pause, prof->rx_ppp);
- if (err) {
- en_err(priv, "Failed setting port general configurations "
- "for port %d, with error %d\n", priv->port, err);
- goto out;
- }
-
- /* Init port */
- en_warn(priv, "Initializing port\n");
- err = mlx4_INIT_PORT(mdev->dev, priv->port);
- if (err) {
- en_err(priv, "Failed Initializing port\n");
- goto out;
- }
-
- queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
-
- if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
- queue_delayed_work(mdev->workqueue, &priv->service_task, SERVICE_TASK_DELAY);
-
- return 0;
-
-out:
- mlx4_en_destroy_netdev(dev);
- return err;
-}
-
-static int mlx4_en_set_ring_size(struct net_device *dev,
- int rx_size, int tx_size)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int port_up = 0;
- int err = 0;
-
- rx_size = roundup_pow_of_two(rx_size);
- rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
- rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
- tx_size = roundup_pow_of_two(tx_size);
- tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
- tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
-
- if (rx_size == (priv->port_up ?
- priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size) &&
- tx_size == priv->tx_ring[0]->size)
- return 0;
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- port_up = 1;
- mlx4_en_stop_port(dev);
- }
- mlx4_en_free_resources(priv);
- priv->prof->tx_ring_size = tx_size;
- priv->prof->rx_ring_size = rx_size;
- err = mlx4_en_alloc_resources(priv);
- if (err) {
- en_err(priv, "Failed reallocating port resources\n");
- goto out;
- }
- if (port_up) {
- err = mlx4_en_start_port(dev);
- if (err)
- en_err(priv, "Failed starting port\n");
- }
-out:
- mutex_unlock(&mdev->state_lock);
- return err;
-}
-static int mlx4_en_set_rx_ring_size(SYSCTL_HANDLER_ARGS)
-{
- struct mlx4_en_priv *priv;
- int size;
- int error;
-
- priv = arg1;
- size = priv->prof->rx_ring_size;
- error = sysctl_handle_int(oidp, &size, 0, req);
- if (error || !req->newptr)
- return (error);
- error = -mlx4_en_set_ring_size(priv->dev, size,
- priv->prof->tx_ring_size);
- return (error);
-}
-
-static int mlx4_en_set_tx_ring_size(SYSCTL_HANDLER_ARGS)
-{
- struct mlx4_en_priv *priv;
- int size;
- int error;
-
- priv = arg1;
- size = priv->prof->tx_ring_size;
- error = sysctl_handle_int(oidp, &size, 0, req);
- if (error || !req->newptr)
- return (error);
- error = -mlx4_en_set_ring_size(priv->dev, priv->prof->rx_ring_size,
- size);
-
- return (error);
-}
-
-static int mlx4_en_get_module_info(struct net_device *dev,
- struct ethtool_modinfo *modinfo)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int ret;
- u8 data[4];
-
- /* Read first 2 bytes to get Module & REV ID */
- ret = mlx4_get_module_info(mdev->dev, priv->port,
- 0/*offset*/, 2/*size*/, data);
-
- if (ret < 2) {
- en_err(priv, "Failed to read eeprom module first two bytes, error: 0x%x\n", -ret);
- return -EIO;
- }
-
- switch (data[0] /* identifier */) {
- case MLX4_MODULE_ID_QSFP:
- modinfo->type = ETH_MODULE_SFF_8436;
- modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
- break;
- case MLX4_MODULE_ID_QSFP_PLUS:
- if (data[1] >= 0x3) { /* revision id */
- modinfo->type = ETH_MODULE_SFF_8636;
- modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
- } else {
- modinfo->type = ETH_MODULE_SFF_8436;
- modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
- }
- break;
- case MLX4_MODULE_ID_QSFP28:
- modinfo->type = ETH_MODULE_SFF_8636;
- modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
- break;
- case MLX4_MODULE_ID_SFP:
- modinfo->type = ETH_MODULE_SFF_8472;
- modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
- break;
- default:
- en_err(priv, "mlx4_en_get_module_info : Not recognized cable type\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int mlx4_en_get_module_eeprom(struct net_device *dev,
- struct ethtool_eeprom *ee,
- u8 *data)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int offset = ee->offset;
- int i = 0, ret;
-
- if (ee->len == 0)
- return -EINVAL;
-
- memset(data, 0, ee->len);
-
- while (i < ee->len) {
- en_dbg(DRV, priv,
- "mlx4_get_module_info i(%d) offset(%d) len(%d)\n",
- i, offset, ee->len - i);
-
- ret = mlx4_get_module_info(mdev->dev, priv->port,
- offset, ee->len - i, data + i);
-
- if (!ret) /* Done reading */
- return 0;
-
- if (ret < 0) {
- en_err(priv,
- "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n",
- i, offset, ee->len - i, ret);
- return -1;
- }
-
- i += ret;
- offset += ret;
- }
- return 0;
-}
-
-static void mlx4_en_print_eeprom(u8 *data, __u32 len)
-{
- int i;
- int j = 0;
- int row = 0;
- const int NUM_OF_BYTES = 16;
-
- printf("\nOffset\t\tValues\n");
- printf("------\t\t------\n");
- while(row < len){
- printf("0x%04x\t\t",row);
- for(i=0; i < NUM_OF_BYTES; i++){
- printf("%02x ", data[j]);
- row++;
- j++;
- }
- printf("\n");
- }
-}
-
-/* Read cable EEPROM module information by first inspecting the first
- * two bytes to get the length and then read the rest of the information.
- * The information is printed to dmesg. */
-static int mlx4_en_read_eeprom(SYSCTL_HANDLER_ARGS)
-{
-
- u8* data;
- int error;
- int result = 0;
- struct mlx4_en_priv *priv;
- struct net_device *dev;
- struct ethtool_modinfo modinfo;
- struct ethtool_eeprom ee;
-
- error = sysctl_handle_int(oidp, &result, 0, req);
- if (error || !req->newptr)
- return (error);
-
- if (result == 1) {
- priv = arg1;
- dev = priv->dev;
- data = kmalloc(PAGE_SIZE, GFP_KERNEL);
-
- error = mlx4_en_get_module_info(dev, &modinfo);
- if (error) {
- en_err(priv,
- "mlx4_en_get_module_info returned with error - FAILED (0x%x)\n",
- -error);
- goto out;
- }
-
- ee.len = modinfo.eeprom_len;
- ee.offset = 0;
-
- error = mlx4_en_get_module_eeprom(dev, &ee, data);
- if (error) {
- en_err(priv,
- "mlx4_en_get_module_eeprom returned with error - FAILED (0x%x)\n",
- -error);
- /* Continue printing partial information in case of an error */
- }
-
- /* EEPROM information will be printed in dmesg */
- mlx4_en_print_eeprom(data, ee.len);
-out:
- kfree(data);
- }
- /* Return zero to prevent sysctl failure. */
- return (0);
-}
-
-static int mlx4_en_set_tx_ppp(SYSCTL_HANDLER_ARGS)
-{
- struct mlx4_en_priv *priv;
- int ppp;
- int error;
-
- priv = arg1;
- ppp = priv->prof->tx_ppp;
- error = sysctl_handle_int(oidp, &ppp, 0, req);
- if (error || !req->newptr)
- return (error);
- if (ppp > 0xff || ppp < 0)
- return (-EINVAL);
- priv->prof->tx_ppp = ppp;
- error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
- priv->rx_mb_size + ETHER_CRC_LEN,
- priv->prof->tx_pause,
- priv->prof->tx_ppp,
- priv->prof->rx_pause,
- priv->prof->rx_ppp);
-
- return (error);
-}
-
-static int mlx4_en_set_rx_ppp(SYSCTL_HANDLER_ARGS)
-{
- struct mlx4_en_priv *priv;
- struct mlx4_en_dev *mdev;
- int ppp;
- int error;
- int port_up;
-
- port_up = 0;
- priv = arg1;
- mdev = priv->mdev;
- ppp = priv->prof->rx_ppp;
- error = sysctl_handle_int(oidp, &ppp, 0, req);
- if (error || !req->newptr)
- return (error);
- if (ppp > 0xff || ppp < 0)
- return (-EINVAL);
- /* See if we have to change the number of tx queues. */
- if (!ppp != !priv->prof->rx_ppp) {
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- port_up = 1;
- mlx4_en_stop_port(priv->dev);
- }
- mlx4_en_free_resources(priv);
- priv->prof->rx_ppp = ppp;
- error = -mlx4_en_alloc_resources(priv);
- if (error)
- en_err(priv, "Failed reallocating port resources\n");
- if (error == 0 && port_up) {
- error = -mlx4_en_start_port(priv->dev);
- if (error)
- en_err(priv, "Failed starting port\n");
- }
- mutex_unlock(&mdev->state_lock);
- return (error);
-
- }
- priv->prof->rx_ppp = ppp;
- error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
- priv->rx_mb_size + ETHER_CRC_LEN,
- priv->prof->tx_pause,
- priv->prof->tx_ppp,
- priv->prof->rx_pause,
- priv->prof->rx_ppp);
-
- return (error);
-}
-
-static void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv)
-{
- struct net_device *dev;
- struct sysctl_ctx_list *ctx;
- struct sysctl_oid *node;
- struct sysctl_oid_list *node_list;
- struct sysctl_oid *coal;
- struct sysctl_oid_list *coal_list;
- const char *pnameunit;
-
- dev = priv->dev;
- ctx = &priv->conf_ctx;
- pnameunit = device_get_nameunit(priv->mdev->pdev->dev.bsddev);
-
- sysctl_ctx_init(ctx);
- priv->sysctl = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
- OID_AUTO, dev->if_xname, CTLFLAG_RD, 0, "mlx4 10gig ethernet");
- node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO,
- "conf", CTLFLAG_RD, NULL, "Configuration");
- node_list = SYSCTL_CHILDREN(node);
-
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "msg_enable",
- CTLFLAG_RW, &priv->msg_enable, 0,
- "Driver message enable bitfield");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_rings",
- CTLFLAG_RD, &priv->rx_ring_num, 0,
- "Number of receive rings");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_rings",
- CTLFLAG_RD, &priv->tx_ring_num, 0,
- "Number of transmit rings");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_size",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_rx_ring_size, "I", "Receive ring size");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_size",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_tx_ring_size, "I", "Transmit ring size");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_ppp",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_tx_ppp, "I", "TX Per-priority pause");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_ppp",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_rx_ppp, "I", "RX Per-priority pause");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "port_num",
- CTLFLAG_RD, &priv->port, 0,
- "Port Number");
- SYSCTL_ADD_STRING(ctx, node_list, OID_AUTO, "device_name",
- CTLFLAG_RD, __DECONST(void *, pnameunit), 0,
- "PCI device name");
-
- /* Add coalescer configuration. */
- coal = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO,
- "coalesce", CTLFLAG_RD, NULL, "Interrupt coalesce configuration");
- coal_list = SYSCTL_CHILDREN(coal);
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_low",
- CTLFLAG_RW, &priv->pkt_rate_low, 0,
- "Packets per-second for minimum delay");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_low",
- CTLFLAG_RW, &priv->rx_usecs_low, 0,
- "Minimum RX delay in micro-seconds");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_high",
- CTLFLAG_RW, &priv->pkt_rate_high, 0,
- "Packets per-second for maximum delay");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_high",
- CTLFLAG_RW, &priv->rx_usecs_high, 0,
- "Maximum RX delay in micro-seconds");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "sample_interval",
- CTLFLAG_RW, &priv->sample_interval, 0,
- "adaptive frequency in units of HZ ticks");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "adaptive_rx_coal",
- CTLFLAG_RW, &priv->adaptive_rx_coal, 0,
- "Enable adaptive rx coalescing");
- /* EEPROM support */
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "eeprom_info",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_read_eeprom, "I", "EEPROM information");
-}
-
-static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
-{
- struct sysctl_ctx_list *ctx;
- struct sysctl_oid *node;
- struct sysctl_oid_list *node_list;
- struct sysctl_oid *ring_node;
- struct sysctl_oid_list *ring_list;
- struct mlx4_en_tx_ring *tx_ring;
- struct mlx4_en_rx_ring *rx_ring;
- char namebuf[128];
- int i;
-
- ctx = &priv->stat_ctx;
- sysctl_ctx_init(ctx);
- node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO,
- "stat", CTLFLAG_RD, NULL, "Statistics");
- node_list = SYSCTL_CHILDREN(node);
-
-#ifdef MLX4_EN_PERF_STAT
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_poll", CTLFLAG_RD,
- &priv->pstats.tx_poll, "TX Poll calls");
- SYSCTL_ADD_QUAD(ctx, node_list, OID_AUTO, "tx_pktsz_avg", CTLFLAG_RD,
- &priv->pstats.tx_pktsz_avg, "TX average packet size");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "inflight_avg", CTLFLAG_RD,
- &priv->pstats.inflight_avg, "TX average packets in-flight");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_coal_avg", CTLFLAG_RD,
- &priv->pstats.tx_coal_avg, "TX average coalesced completions");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_coal_avg", CTLFLAG_RD,
- &priv->pstats.rx_coal_avg, "RX average coalesced completions");
-#endif
-
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tso_packets", CTLFLAG_RD,
- &priv->port_stats.tso_packets, "TSO packets sent");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "queue_stopped", CTLFLAG_RD,
- &priv->port_stats.queue_stopped, "Queue full");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "wake_queue", CTLFLAG_RD,
- &priv->port_stats.wake_queue, "Queue resumed after full");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_timeout", CTLFLAG_RD,
- &priv->port_stats.tx_timeout, "Transmit timeouts");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_oversized_packets", CTLFLAG_RD,
- &priv->port_stats.oversized_packets, "TX oversized packets, m_defrag failed");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_alloc_failed", CTLFLAG_RD,
- &priv->port_stats.rx_alloc_failed, "RX failed to allocate mbuf");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_good", CTLFLAG_RD,
- &priv->port_stats.rx_chksum_good, "RX checksum offload success");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_chksum_none", CTLFLAG_RD,
- &priv->port_stats.rx_chksum_none, "RX without checksum offload");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_chksum_offload",
- CTLFLAG_RD, &priv->port_stats.tx_chksum_offload,
- "TX checksum offloads");
-
- /* Could strdup the names and add in a loop. This is simpler. */
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_bytes", CTLFLAG_RD,
- &priv->pkstats.rx_bytes, "RX Bytes");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_packets", CTLFLAG_RD,
- &priv->pkstats.rx_packets, "RX packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_multicast_packets", CTLFLAG_RD,
- &priv->pkstats.rx_multicast_packets, "RX Multicast Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_broadcast_packets", CTLFLAG_RD,
- &priv->pkstats.rx_broadcast_packets, "RX Broadcast Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_errors", CTLFLAG_RD,
- &priv->pkstats.rx_errors, "RX Errors");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_dropped", CTLFLAG_RD,
- &priv->pkstats.rx_dropped, "RX Dropped");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_length_errors", CTLFLAG_RD,
- &priv->pkstats.rx_length_errors, "RX Length Errors");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_over_errors", CTLFLAG_RD,
- &priv->pkstats.rx_over_errors, "RX Over Errors");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_crc_errors", CTLFLAG_RD,
- &priv->pkstats.rx_crc_errors, "RX CRC Errors");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_jabbers", CTLFLAG_RD,
- &priv->pkstats.rx_jabbers, "RX Jabbers");
-
-
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_in_range_length_error", CTLFLAG_RD,
- &priv->pkstats.rx_in_range_length_error, "RX IN_Range Length Error");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_out_range_length_error",
- CTLFLAG_RD, &priv->pkstats.rx_out_range_length_error,
- "RX Out Range Length Error");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_lt_64_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_lt_64_bytes_packets, "RX Lt 64 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_127_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_127_bytes_packets, "RX 127 bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_255_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_255_bytes_packets, "RX 255 bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_511_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_511_bytes_packets, "RX 511 bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1023_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_1023_bytes_packets, "RX 1023 bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1518_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_1518_bytes_packets, "RX 1518 bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1522_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_1522_bytes_packets, "RX 1522 bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1548_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_1548_bytes_packets, "RX 1548 bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_gt_1548_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.rx_gt_1548_bytes_packets,
- "RX Greater Then 1548 bytes Packets");
-
-struct mlx4_en_pkt_stats {
- unsigned long tx_packets;
- unsigned long tx_bytes;
- unsigned long tx_multicast_packets;
- unsigned long tx_broadcast_packets;
- unsigned long tx_errors;
- unsigned long tx_dropped;
- unsigned long tx_lt_64_bytes_packets;
- unsigned long tx_127_bytes_packets;
- unsigned long tx_255_bytes_packets;
- unsigned long tx_511_bytes_packets;
- unsigned long tx_1023_bytes_packets;
- unsigned long tx_1518_bytes_packets;
- unsigned long tx_1522_bytes_packets;
- unsigned long tx_1548_bytes_packets;
- unsigned long tx_gt_1548_bytes_packets;
- unsigned long rx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
- unsigned long tx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
-#define NUM_PKT_STATS 72
-};
-
-
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_packets", CTLFLAG_RD,
- &priv->pkstats.tx_packets, "TX packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_bytes", CTLFLAG_RD,
- &priv->pkstats.tx_bytes, "TX Bytes");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_multicast_packets", CTLFLAG_RD,
- &priv->pkstats.tx_multicast_packets, "TX Multicast Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_broadcast_packets", CTLFLAG_RD,
- &priv->pkstats.tx_broadcast_packets, "TX Broadcast Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_errors", CTLFLAG_RD,
- &priv->pkstats.tx_errors, "TX Errors");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_dropped", CTLFLAG_RD,
- &priv->pkstats.tx_dropped, "TX Dropped");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_lt_64_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_lt_64_bytes_packets, "TX Less Then 64 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_127_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_127_bytes_packets, "TX 127 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_255_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_255_bytes_packets, "TX 255 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_511_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_511_bytes_packets, "TX 511 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1023_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_1023_bytes_packets, "TX 1023 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1518_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_1518_bytes_packets, "TX 1518 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1522_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_1522_bytes_packets, "TX 1522 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1548_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_1548_bytes_packets, "TX 1548 Bytes Packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_gt_1548_bytes_packets", CTLFLAG_RD,
- &priv->pkstats.tx_gt_1548_bytes_packets,
- "TX Greater Then 1548 Bytes Packets");
-
-
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- tx_ring = priv->tx_ring[i];
- snprintf(namebuf, sizeof(namebuf), "tx_ring%d", i);
- ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
- CTLFLAG_RD, NULL, "TX Ring");
- ring_list = SYSCTL_CHILDREN(ring_node);
- SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "packets",
- CTLFLAG_RD, &tx_ring->packets, "TX packets");
- SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
- CTLFLAG_RD, &tx_ring->bytes, "TX bytes");
- }
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- rx_ring = priv->rx_ring[i];
- snprintf(namebuf, sizeof(namebuf), "rx_ring%d", i);
- ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
- CTLFLAG_RD, NULL, "RX Ring");
- ring_list = SYSCTL_CHILDREN(ring_node);
- SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "packets",
- CTLFLAG_RD, &rx_ring->packets, "RX packets");
- SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
- CTLFLAG_RD, &rx_ring->bytes, "RX bytes");
- SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "error",
- CTLFLAG_RD, &rx_ring->errors, "RX soft errors");
- }
-}
diff --git a/sys/ofed/drivers/net/mlx4/en_port.c b/sys/ofed/drivers/net/mlx4/en_port.c
deleted file mode 100644
index 2a1c4ba406a9..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_port.c
+++ /dev/null
@@ -1,598 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#include <sys/types.h>
-#include <linux/if_vlan.h>
-
-#include <linux/mlx4/device.h>
-#include <linux/mlx4/cmd.h>
-
-#include "en_port.h"
-#include "mlx4_en.h"
-#define EN_IFQ_MIN_INTERVAL 3000
-
-
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_vlan_fltr_mbox *filter;
- int i;
- int j;
- int index = 0;
- u32 entry;
- int err = 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- filter = mailbox->buf;
- memset(filter, 0, sizeof(*filter));
- for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
- entry = 0;
- for (j = 0; j < 32; j++) {
- if (test_bit(index, priv->active_vlans))
- entry |= 1 << j;
- index++;
- }
- filter->entry[i] = cpu_to_be32(entry);
- }
- err = mlx4_cmd(dev, mailbox->dma, priv->port, 0, MLX4_CMD_SET_VLAN_FLTR,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
-{
- struct mlx4_en_query_port_context *qport_context;
- struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
- struct mlx4_en_port_state *state = &priv->port_state;
- struct mlx4_cmd_mailbox *mailbox;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- memset(mailbox->buf, 0, sizeof(*qport_context));
- err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
- MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_WRAPPED);
- if (err)
- goto out;
- qport_context = mailbox->buf;
-
- /* This command is always accessed from Ethtool context
- * already synchronized, no need in locking */
- state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
- switch (qport_context->link_speed & MLX4_EN_SPEED_MASK) {
- case MLX4_EN_1G_SPEED:
- state->link_speed = 1000;
- break;
- case MLX4_EN_10G_SPEED_XAUI:
- case MLX4_EN_10G_SPEED_XFI:
- state->link_speed = 10000;
- break;
- case MLX4_EN_20G_SPEED:
- state->link_speed = 20000;
- break;
- case MLX4_EN_40G_SPEED:
- state->link_speed = 40000;
- break;
- case MLX4_EN_56G_SPEED:
- state->link_speed = 56000;
- break;
- default:
- state->link_speed = -1;
- break;
- }
- state->transciver = qport_context->transceiver;
- state->autoneg = !!(qport_context->autoneg & MLX4_EN_AUTONEG_MASK);
-
-out:
- mlx4_free_cmd_mailbox(mdev->dev, mailbox);
- return err;
-}
-
-int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
-{
- struct mlx4_en_stat_out_mbox *mlx4_en_stats;
- struct mlx4_en_stat_out_flow_control_mbox *flowstats;
- struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
- struct mlx4_en_vport_stats *vport_stats = &priv->vport_stats;
- struct mlx4_cmd_mailbox *mailbox = NULL;
- struct mlx4_cmd_mailbox *mailbox_flow = NULL;
- u64 in_mod = reset << 8 | port;
- int err;
- int i;
- int do_if_stat = 1;
- unsigned long period = (unsigned long) (jiffies - priv->last_ifq_jiffies);
- struct mlx4_en_vport_stats tmp_vport_stats;
- struct net_device *dev;
-
- if (jiffies_to_msecs(period) < EN_IFQ_MIN_INTERVAL ||
- priv->counter_index == 0xff)
- do_if_stat = 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- goto mailbox_out;
- }
-
- mailbox_flow = mlx4_alloc_cmd_mailbox(mdev->dev);
- if (IS_ERR(mailbox_flow)) {
- mlx4_free_cmd_mailbox(mdev->dev, mailbox);
- err = PTR_ERR(mailbox_flow);
- goto mailbox_out;
- }
-
- /* 0xffs indicates invalid value */
- memset(mailbox_flow->buf, 0xff, sizeof(*flowstats) *
- MLX4_NUM_PRIORITIES);
-
- if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) {
- memset(mailbox_flow->buf, 0, sizeof(*flowstats));
- err = mlx4_cmd_box(mdev->dev, 0, mailbox_flow->dma,
- in_mod | 1<<12, 0, MLX4_CMD_DUMP_ETH_STATS,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-
- if (err)
- goto out;
- }
-
- err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0,
- MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_NATIVE);
- if (err)
- goto out;
-
- mlx4_en_stats = mailbox->buf;
-
- spin_lock(&priv->stats_lock);
-
- priv->port_stats.rx_chksum_good = 0;
- priv->port_stats.rx_chksum_none = 0;
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok;
- priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none;
- }
-
- priv->port_stats.tx_chksum_offload = 0;
- priv->port_stats.queue_stopped = 0;
- priv->port_stats.wake_queue = 0;
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->port_stats.tx_chksum_offload += priv->tx_ring[i]->tx_csum;
- priv->port_stats.queue_stopped += priv->tx_ring[i]->queue_stopped;
- priv->port_stats.wake_queue += priv->tx_ring[i]->wake_queue;
- priv->port_stats.oversized_packets += priv->tx_ring[i]->oversized_packets;
- }
- /* RX Statistics */
- priv->pkstats.rx_packets = be64_to_cpu(mlx4_en_stats->RTOT_prio_0) +
- be64_to_cpu(mlx4_en_stats->RTOT_prio_1) +
- be64_to_cpu(mlx4_en_stats->RTOT_prio_2) +
- be64_to_cpu(mlx4_en_stats->RTOT_prio_3) +
- be64_to_cpu(mlx4_en_stats->RTOT_prio_4) +
- be64_to_cpu(mlx4_en_stats->RTOT_prio_5) +
- be64_to_cpu(mlx4_en_stats->RTOT_prio_6) +
- be64_to_cpu(mlx4_en_stats->RTOT_prio_7) +
- be64_to_cpu(mlx4_en_stats->RTOT_novlan);
- priv->pkstats.rx_bytes = be64_to_cpu(mlx4_en_stats->ROCT_prio_0) +
- be64_to_cpu(mlx4_en_stats->ROCT_prio_1) +
- be64_to_cpu(mlx4_en_stats->ROCT_prio_2) +
- be64_to_cpu(mlx4_en_stats->ROCT_prio_3) +
- be64_to_cpu(mlx4_en_stats->ROCT_prio_4) +
- be64_to_cpu(mlx4_en_stats->ROCT_prio_5) +
- be64_to_cpu(mlx4_en_stats->ROCT_prio_6) +
- be64_to_cpu(mlx4_en_stats->ROCT_prio_7) +
- be64_to_cpu(mlx4_en_stats->ROCT_novlan);
- priv->pkstats.rx_multicast_packets = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_1) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_2) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_3) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_4) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_5) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_6) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_7) +
- be64_to_cpu(mlx4_en_stats->MCAST_novlan);
- priv->pkstats.rx_broadcast_packets = be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) +
- be64_to_cpu(mlx4_en_stats->RBCAST_novlan);
- priv->pkstats.rx_errors = be64_to_cpu(mlx4_en_stats->PCS) +
- be32_to_cpu(mlx4_en_stats->RJBBR) +
- be32_to_cpu(mlx4_en_stats->RCRC) +
- be32_to_cpu(mlx4_en_stats->RRUNT) +
- be64_to_cpu(mlx4_en_stats->RInRangeLengthErr) +
- be64_to_cpu(mlx4_en_stats->ROutRangeLengthErr) +
- be32_to_cpu(mlx4_en_stats->RSHORT) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_0) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_1) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_2) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_3) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_4) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_5) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_6) +
- be64_to_cpu(mlx4_en_stats->RGIANT_prio_7) +
- be64_to_cpu(mlx4_en_stats->RGIANT_novlan);
- priv->pkstats.rx_dropped = be32_to_cpu(mlx4_en_stats->RdropOvflw);
- priv->pkstats.rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
- priv->pkstats.rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
- priv->pkstats.rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
- priv->pkstats.rx_jabbers = be32_to_cpu(mlx4_en_stats->RJBBR);
- priv->pkstats.rx_in_range_length_error = be64_to_cpu(mlx4_en_stats->RInRangeLengthErr);
- priv->pkstats.rx_out_range_length_error = be64_to_cpu(mlx4_en_stats->ROutRangeLengthErr);
- priv->pkstats.rx_lt_64_bytes_packets = be64_to_cpu(mlx4_en_stats->R64_prio_0) +
- be64_to_cpu(mlx4_en_stats->R64_prio_1) +
- be64_to_cpu(mlx4_en_stats->R64_prio_2) +
- be64_to_cpu(mlx4_en_stats->R64_prio_3) +
- be64_to_cpu(mlx4_en_stats->R64_prio_4) +
- be64_to_cpu(mlx4_en_stats->R64_prio_5) +
- be64_to_cpu(mlx4_en_stats->R64_prio_6) +
- be64_to_cpu(mlx4_en_stats->R64_prio_7) +
- be64_to_cpu(mlx4_en_stats->R64_novlan);
- priv->pkstats.rx_127_bytes_packets = be64_to_cpu(mlx4_en_stats->R127_prio_0) +
- be64_to_cpu(mlx4_en_stats->R127_prio_1) +
- be64_to_cpu(mlx4_en_stats->R127_prio_2) +
- be64_to_cpu(mlx4_en_stats->R127_prio_3) +
- be64_to_cpu(mlx4_en_stats->R127_prio_4) +
- be64_to_cpu(mlx4_en_stats->R127_prio_5) +
- be64_to_cpu(mlx4_en_stats->R127_prio_6) +
- be64_to_cpu(mlx4_en_stats->R127_prio_7) +
- be64_to_cpu(mlx4_en_stats->R127_novlan);
- priv->pkstats.rx_255_bytes_packets = be64_to_cpu(mlx4_en_stats->R255_prio_0) +
- be64_to_cpu(mlx4_en_stats->R255_prio_1) +
- be64_to_cpu(mlx4_en_stats->R255_prio_2) +
- be64_to_cpu(mlx4_en_stats->R255_prio_3) +
- be64_to_cpu(mlx4_en_stats->R255_prio_4) +
- be64_to_cpu(mlx4_en_stats->R255_prio_5) +
- be64_to_cpu(mlx4_en_stats->R255_prio_6) +
- be64_to_cpu(mlx4_en_stats->R255_prio_7) +
- be64_to_cpu(mlx4_en_stats->R255_novlan);
- priv->pkstats.rx_511_bytes_packets = be64_to_cpu(mlx4_en_stats->R511_prio_0) +
- be64_to_cpu(mlx4_en_stats->R511_prio_1) +
- be64_to_cpu(mlx4_en_stats->R511_prio_2) +
- be64_to_cpu(mlx4_en_stats->R511_prio_3) +
- be64_to_cpu(mlx4_en_stats->R511_prio_4) +
- be64_to_cpu(mlx4_en_stats->R511_prio_5) +
- be64_to_cpu(mlx4_en_stats->R511_prio_6) +
- be64_to_cpu(mlx4_en_stats->R511_prio_7) +
- be64_to_cpu(mlx4_en_stats->R511_novlan);
- priv->pkstats.rx_1023_bytes_packets = be64_to_cpu(mlx4_en_stats->R1023_prio_0) +
- be64_to_cpu(mlx4_en_stats->R1023_prio_1) +
- be64_to_cpu(mlx4_en_stats->R1023_prio_2) +
- be64_to_cpu(mlx4_en_stats->R1023_prio_3) +
- be64_to_cpu(mlx4_en_stats->R1023_prio_4) +
- be64_to_cpu(mlx4_en_stats->R1023_prio_5) +
- be64_to_cpu(mlx4_en_stats->R1023_prio_6) +
- be64_to_cpu(mlx4_en_stats->R1023_prio_7) +
- be64_to_cpu(mlx4_en_stats->R1023_novlan);
- priv->pkstats.rx_1518_bytes_packets = be64_to_cpu(mlx4_en_stats->R1518_prio_0) +
- be64_to_cpu(mlx4_en_stats->R1518_prio_1) +
- be64_to_cpu(mlx4_en_stats->R1518_prio_2) +
- be64_to_cpu(mlx4_en_stats->R1518_prio_3) +
- be64_to_cpu(mlx4_en_stats->R1518_prio_4) +
- be64_to_cpu(mlx4_en_stats->R1518_prio_5) +
- be64_to_cpu(mlx4_en_stats->R1518_prio_6) +
- be64_to_cpu(mlx4_en_stats->R1518_prio_7) +
- be64_to_cpu(mlx4_en_stats->R1518_novlan);
- priv->pkstats.rx_1522_bytes_packets = be64_to_cpu(mlx4_en_stats->R1522_prio_0) +
- be64_to_cpu(mlx4_en_stats->R1522_prio_1) +
- be64_to_cpu(mlx4_en_stats->R1522_prio_2) +
- be64_to_cpu(mlx4_en_stats->R1522_prio_3) +
- be64_to_cpu(mlx4_en_stats->R1522_prio_4) +
- be64_to_cpu(mlx4_en_stats->R1522_prio_5) +
- be64_to_cpu(mlx4_en_stats->R1522_prio_6) +
- be64_to_cpu(mlx4_en_stats->R1522_prio_7) +
- be64_to_cpu(mlx4_en_stats->R1522_novlan);
- priv->pkstats.rx_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->R1548_prio_0) +
- be64_to_cpu(mlx4_en_stats->R1548_prio_1) +
- be64_to_cpu(mlx4_en_stats->R1548_prio_2) +
- be64_to_cpu(mlx4_en_stats->R1548_prio_3) +
- be64_to_cpu(mlx4_en_stats->R1548_prio_4) +
- be64_to_cpu(mlx4_en_stats->R1548_prio_5) +
- be64_to_cpu(mlx4_en_stats->R1548_prio_6) +
- be64_to_cpu(mlx4_en_stats->R1548_prio_7) +
- be64_to_cpu(mlx4_en_stats->R1548_novlan);
- priv->pkstats.rx_gt_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->R2MTU_prio_0) +
- be64_to_cpu(mlx4_en_stats->R2MTU_prio_1) +
- be64_to_cpu(mlx4_en_stats->R2MTU_prio_2) +
- be64_to_cpu(mlx4_en_stats->R2MTU_prio_3) +
- be64_to_cpu(mlx4_en_stats->R2MTU_prio_4) +
- be64_to_cpu(mlx4_en_stats->R2MTU_prio_5) +
- be64_to_cpu(mlx4_en_stats->R2MTU_prio_6) +
- be64_to_cpu(mlx4_en_stats->R2MTU_prio_7) +
- be64_to_cpu(mlx4_en_stats->R2MTU_novlan);
-
- /* Tx Stats */
- priv->pkstats.tx_packets = be64_to_cpu(mlx4_en_stats->TTOT_prio_0) +
- be64_to_cpu(mlx4_en_stats->TTOT_prio_1) +
- be64_to_cpu(mlx4_en_stats->TTOT_prio_2) +
- be64_to_cpu(mlx4_en_stats->TTOT_prio_3) +
- be64_to_cpu(mlx4_en_stats->TTOT_prio_4) +
- be64_to_cpu(mlx4_en_stats->TTOT_prio_5) +
- be64_to_cpu(mlx4_en_stats->TTOT_prio_6) +
- be64_to_cpu(mlx4_en_stats->TTOT_prio_7) +
- be64_to_cpu(mlx4_en_stats->TTOT_novlan);
- priv->pkstats.tx_bytes = be64_to_cpu(mlx4_en_stats->TOCT_prio_0) +
- be64_to_cpu(mlx4_en_stats->TOCT_prio_1) +
- be64_to_cpu(mlx4_en_stats->TOCT_prio_2) +
- be64_to_cpu(mlx4_en_stats->TOCT_prio_3) +
- be64_to_cpu(mlx4_en_stats->TOCT_prio_4) +
- be64_to_cpu(mlx4_en_stats->TOCT_prio_5) +
- be64_to_cpu(mlx4_en_stats->TOCT_prio_6) +
- be64_to_cpu(mlx4_en_stats->TOCT_prio_7) +
- be64_to_cpu(mlx4_en_stats->TOCT_novlan);
- priv->pkstats.tx_multicast_packets = be64_to_cpu(mlx4_en_stats->TMCAST_prio_0) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_1) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_2) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_3) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_4) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_5) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_6) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_7) +
- be64_to_cpu(mlx4_en_stats->TMCAST_novlan);
- priv->pkstats.tx_broadcast_packets = be64_to_cpu(mlx4_en_stats->TBCAST_prio_0) +
- be64_to_cpu(mlx4_en_stats->TBCAST_prio_1) +
- be64_to_cpu(mlx4_en_stats->TBCAST_prio_2) +
- be64_to_cpu(mlx4_en_stats->TBCAST_prio_3) +
- be64_to_cpu(mlx4_en_stats->TBCAST_prio_4) +
- be64_to_cpu(mlx4_en_stats->TBCAST_prio_5) +
- be64_to_cpu(mlx4_en_stats->TBCAST_prio_6) +
- be64_to_cpu(mlx4_en_stats->TBCAST_prio_7) +
- be64_to_cpu(mlx4_en_stats->TBCAST_novlan);
- priv->pkstats.tx_errors = be64_to_cpu(mlx4_en_stats->TGIANT_prio_0) +
- be64_to_cpu(mlx4_en_stats->TGIANT_prio_1) +
- be64_to_cpu(mlx4_en_stats->TGIANT_prio_2) +
- be64_to_cpu(mlx4_en_stats->TGIANT_prio_3) +
- be64_to_cpu(mlx4_en_stats->TGIANT_prio_4) +
- be64_to_cpu(mlx4_en_stats->TGIANT_prio_5) +
- be64_to_cpu(mlx4_en_stats->TGIANT_prio_6) +
- be64_to_cpu(mlx4_en_stats->TGIANT_prio_7) +
- be64_to_cpu(mlx4_en_stats->TGIANT_novlan);
- priv->pkstats.tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP) -
- priv->pkstats.tx_errors;
- priv->pkstats.tx_lt_64_bytes_packets = be64_to_cpu(mlx4_en_stats->T64_prio_0) +
- be64_to_cpu(mlx4_en_stats->T64_prio_1) +
- be64_to_cpu(mlx4_en_stats->T64_prio_2) +
- be64_to_cpu(mlx4_en_stats->T64_prio_3) +
- be64_to_cpu(mlx4_en_stats->T64_prio_4) +
- be64_to_cpu(mlx4_en_stats->T64_prio_5) +
- be64_to_cpu(mlx4_en_stats->T64_prio_6) +
- be64_to_cpu(mlx4_en_stats->T64_prio_7) +
- be64_to_cpu(mlx4_en_stats->T64_novlan);
- priv->pkstats.tx_127_bytes_packets = be64_to_cpu(mlx4_en_stats->T127_prio_0) +
- be64_to_cpu(mlx4_en_stats->T127_prio_1) +
- be64_to_cpu(mlx4_en_stats->T127_prio_2) +
- be64_to_cpu(mlx4_en_stats->T127_prio_3) +
- be64_to_cpu(mlx4_en_stats->T127_prio_4) +
- be64_to_cpu(mlx4_en_stats->T127_prio_5) +
- be64_to_cpu(mlx4_en_stats->T127_prio_6) +
- be64_to_cpu(mlx4_en_stats->T127_prio_7) +
- be64_to_cpu(mlx4_en_stats->T127_novlan);
- priv->pkstats.tx_255_bytes_packets = be64_to_cpu(mlx4_en_stats->T255_prio_0) +
- be64_to_cpu(mlx4_en_stats->T255_prio_1) +
- be64_to_cpu(mlx4_en_stats->T255_prio_2) +
- be64_to_cpu(mlx4_en_stats->T255_prio_3) +
- be64_to_cpu(mlx4_en_stats->T255_prio_4) +
- be64_to_cpu(mlx4_en_stats->T255_prio_5) +
- be64_to_cpu(mlx4_en_stats->T255_prio_6) +
- be64_to_cpu(mlx4_en_stats->T255_prio_7) +
- be64_to_cpu(mlx4_en_stats->T255_novlan);
- priv->pkstats.tx_511_bytes_packets = be64_to_cpu(mlx4_en_stats->T511_prio_0) +
- be64_to_cpu(mlx4_en_stats->T511_prio_1) +
- be64_to_cpu(mlx4_en_stats->T511_prio_2) +
- be64_to_cpu(mlx4_en_stats->T511_prio_3) +
- be64_to_cpu(mlx4_en_stats->T511_prio_4) +
- be64_to_cpu(mlx4_en_stats->T511_prio_5) +
- be64_to_cpu(mlx4_en_stats->T511_prio_6) +
- be64_to_cpu(mlx4_en_stats->T511_prio_7) +
- be64_to_cpu(mlx4_en_stats->T511_novlan);
- priv->pkstats.tx_1023_bytes_packets = be64_to_cpu(mlx4_en_stats->T1023_prio_0) +
- be64_to_cpu(mlx4_en_stats->T1023_prio_1) +
- be64_to_cpu(mlx4_en_stats->T1023_prio_2) +
- be64_to_cpu(mlx4_en_stats->T1023_prio_3) +
- be64_to_cpu(mlx4_en_stats->T1023_prio_4) +
- be64_to_cpu(mlx4_en_stats->T1023_prio_5) +
- be64_to_cpu(mlx4_en_stats->T1023_prio_6) +
- be64_to_cpu(mlx4_en_stats->T1023_prio_7) +
- be64_to_cpu(mlx4_en_stats->T1023_novlan);
- priv->pkstats.tx_1518_bytes_packets = be64_to_cpu(mlx4_en_stats->T1518_prio_0) +
- be64_to_cpu(mlx4_en_stats->T1518_prio_1) +
- be64_to_cpu(mlx4_en_stats->T1518_prio_2) +
- be64_to_cpu(mlx4_en_stats->T1518_prio_3) +
- be64_to_cpu(mlx4_en_stats->T1518_prio_4) +
- be64_to_cpu(mlx4_en_stats->T1518_prio_5) +
- be64_to_cpu(mlx4_en_stats->T1518_prio_6) +
- be64_to_cpu(mlx4_en_stats->T1518_prio_7) +
- be64_to_cpu(mlx4_en_stats->T1518_novlan);
- priv->pkstats.tx_1522_bytes_packets = be64_to_cpu(mlx4_en_stats->T1522_prio_0) +
- be64_to_cpu(mlx4_en_stats->T1522_prio_1) +
- be64_to_cpu(mlx4_en_stats->T1522_prio_2) +
- be64_to_cpu(mlx4_en_stats->T1522_prio_3) +
- be64_to_cpu(mlx4_en_stats->T1522_prio_4) +
- be64_to_cpu(mlx4_en_stats->T1522_prio_5) +
- be64_to_cpu(mlx4_en_stats->T1522_prio_6) +
- be64_to_cpu(mlx4_en_stats->T1522_prio_7) +
- be64_to_cpu(mlx4_en_stats->T1522_novlan);
- priv->pkstats.tx_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->T1548_prio_0) +
- be64_to_cpu(mlx4_en_stats->T1548_prio_1) +
- be64_to_cpu(mlx4_en_stats->T1548_prio_2) +
- be64_to_cpu(mlx4_en_stats->T1548_prio_3) +
- be64_to_cpu(mlx4_en_stats->T1548_prio_4) +
- be64_to_cpu(mlx4_en_stats->T1548_prio_5) +
- be64_to_cpu(mlx4_en_stats->T1548_prio_6) +
- be64_to_cpu(mlx4_en_stats->T1548_prio_7) +
- be64_to_cpu(mlx4_en_stats->T1548_novlan);
- priv->pkstats.tx_gt_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->T2MTU_prio_0) +
- be64_to_cpu(mlx4_en_stats->T2MTU_prio_1) +
- be64_to_cpu(mlx4_en_stats->T2MTU_prio_2) +
- be64_to_cpu(mlx4_en_stats->T2MTU_prio_3) +
- be64_to_cpu(mlx4_en_stats->T2MTU_prio_4) +
- be64_to_cpu(mlx4_en_stats->T2MTU_prio_5) +
- be64_to_cpu(mlx4_en_stats->T2MTU_prio_6) +
- be64_to_cpu(mlx4_en_stats->T2MTU_prio_7) +
- be64_to_cpu(mlx4_en_stats->T2MTU_novlan);
-
- priv->pkstats.rx_prio[0][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0);
- priv->pkstats.rx_prio[0][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_0);
- priv->pkstats.rx_prio[1][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1);
- priv->pkstats.rx_prio[1][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_1);
- priv->pkstats.rx_prio[2][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2);
- priv->pkstats.rx_prio[2][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_2);
- priv->pkstats.rx_prio[3][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3);
- priv->pkstats.rx_prio[3][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_3);
- priv->pkstats.rx_prio[4][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4);
- priv->pkstats.rx_prio[4][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_4);
- priv->pkstats.rx_prio[5][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5);
- priv->pkstats.rx_prio[5][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_5);
- priv->pkstats.rx_prio[6][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6);
- priv->pkstats.rx_prio[6][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_6);
- priv->pkstats.rx_prio[7][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7);
- priv->pkstats.rx_prio[7][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_7);
- priv->pkstats.rx_prio[8][0] = be64_to_cpu(mlx4_en_stats->RTOT_novlan);
- priv->pkstats.rx_prio[8][1] = be64_to_cpu(mlx4_en_stats->ROCT_novlan);
- priv->pkstats.tx_prio[0][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0);
- priv->pkstats.tx_prio[0][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_0);
- priv->pkstats.tx_prio[1][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1);
- priv->pkstats.tx_prio[1][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_1);
- priv->pkstats.tx_prio[2][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2);
- priv->pkstats.tx_prio[2][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_2);
- priv->pkstats.tx_prio[3][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3);
- priv->pkstats.tx_prio[3][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_3);
- priv->pkstats.tx_prio[4][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4);
- priv->pkstats.tx_prio[4][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_4);
- priv->pkstats.tx_prio[5][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5);
- priv->pkstats.tx_prio[5][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_5);
- priv->pkstats.tx_prio[6][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6);
- priv->pkstats.tx_prio[6][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_6);
- priv->pkstats.tx_prio[7][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7);
- priv->pkstats.tx_prio[7][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_7);
- priv->pkstats.tx_prio[8][0] = be64_to_cpu(mlx4_en_stats->TTOT_novlan);
- priv->pkstats.tx_prio[8][1] = be64_to_cpu(mlx4_en_stats->TOCT_novlan);
-
- flowstats = mailbox_flow->buf;
-
- for (i = 0; i < MLX4_NUM_PRIORITIES; i++) {
- priv->flowstats[i].rx_pause =
- be64_to_cpu(flowstats[i].rx_pause);
- priv->flowstats[i].rx_pause_duration =
- be64_to_cpu(flowstats[i].rx_pause_duration);
- priv->flowstats[i].rx_pause_transition =
- be64_to_cpu(flowstats[i].rx_pause_transition);
- priv->flowstats[i].tx_pause =
- be64_to_cpu(flowstats[i].tx_pause);
- priv->flowstats[i].tx_pause_duration =
- be64_to_cpu(flowstats[i].tx_pause_duration);
- priv->flowstats[i].tx_pause_transition =
- be64_to_cpu(flowstats[i].tx_pause_transition);
- }
-
- memset(&tmp_vport_stats, 0, sizeof(tmp_vport_stats));
- spin_unlock(&priv->stats_lock);
- err = mlx4_get_vport_ethtool_stats(mdev->dev, port,
- &tmp_vport_stats, reset);
- spin_lock(&priv->stats_lock);
- if (!err) {
- /* ethtool stats format */
- vport_stats->rx_unicast_packets = tmp_vport_stats.rx_unicast_packets;
- vport_stats->rx_unicast_bytes = tmp_vport_stats.rx_unicast_bytes;
- vport_stats->rx_multicast_packets = tmp_vport_stats.rx_multicast_packets;
- vport_stats->rx_multicast_bytes = tmp_vport_stats.rx_multicast_bytes;
- vport_stats->rx_broadcast_packets = tmp_vport_stats.rx_broadcast_packets;
- vport_stats->rx_broadcast_bytes = tmp_vport_stats.rx_broadcast_bytes;
- vport_stats->rx_dropped = tmp_vport_stats.rx_dropped;
- vport_stats->rx_errors = tmp_vport_stats.rx_errors;
- vport_stats->tx_unicast_packets = tmp_vport_stats.tx_unicast_packets;
- vport_stats->tx_unicast_bytes = tmp_vport_stats.tx_unicast_bytes;
- vport_stats->tx_multicast_packets = tmp_vport_stats.tx_multicast_packets;
- vport_stats->tx_multicast_bytes = tmp_vport_stats.tx_multicast_bytes;
- vport_stats->tx_broadcast_packets = tmp_vport_stats.tx_broadcast_packets;
- vport_stats->tx_broadcast_bytes = tmp_vport_stats.tx_broadcast_bytes;
- vport_stats->tx_errors = tmp_vport_stats.tx_errors;
- }
-
- if (!mlx4_is_mfunc(mdev->dev)) {
-/* netdevice stats format */
-#if __FreeBSD_version >= 1100000
- if (reset == 0) {
- dev = mdev->pndev[port];
- if_inc_counter(dev, IFCOUNTER_IPACKETS,
- priv->pkstats.rx_packets - priv->pkstats_last.rx_packets);
- if_inc_counter(dev, IFCOUNTER_OPACKETS,
- priv->pkstats.tx_packets - priv->pkstats_last.tx_packets);
- if_inc_counter(dev, IFCOUNTER_IBYTES,
- priv->pkstats.rx_bytes - priv->pkstats_last.rx_bytes);
- if_inc_counter(dev, IFCOUNTER_OBYTES,
- priv->pkstats.tx_bytes - priv->pkstats_last.tx_bytes);
- if_inc_counter(dev, IFCOUNTER_IERRORS,
- priv->pkstats.rx_errors - priv->pkstats_last.rx_errors);
- if_inc_counter(dev, IFCOUNTER_IQDROPS,
- priv->pkstats.rx_dropped - priv->pkstats_last.rx_dropped);
- if_inc_counter(dev, IFCOUNTER_IMCASTS,
- priv->pkstats.rx_multicast_packets - priv->pkstats_last.rx_multicast_packets);
- if_inc_counter(dev, IFCOUNTER_OMCASTS,
- priv->pkstats.tx_multicast_packets - priv->pkstats_last.tx_multicast_packets);
- }
- priv->pkstats_last = priv->pkstats;
-#else
- dev = mdev->pndev[port];
- dev->if_ipackets = priv->pkstats.rx_packets;
- dev->if_opackets = priv->pkstats.tx_packets;
- dev->if_ibytes = priv->pkstats.rx_bytes;
- dev->if_obytes = priv->pkstats.tx_bytes;
- dev->if_ierrors = priv->pkstats.rx_errors;
- dev->if_iqdrops = priv->pkstats.rx_dropped;
- dev->if_imcasts = priv->pkstats.rx_multicast_packets;
- dev->if_omcasts = priv->pkstats.tx_multicast_packets;
- dev->if_collisions = 0;
-#endif
- }
-
- spin_unlock(&priv->stats_lock);
-
-out:
- mlx4_free_cmd_mailbox(mdev->dev, mailbox_flow);
- mlx4_free_cmd_mailbox(mdev->dev, mailbox);
-
-mailbox_out:
- if (do_if_stat)
- priv->last_ifq_jiffies = jiffies;
-
- return err;
-}
diff --git a/sys/ofed/drivers/net/mlx4/en_port.h b/sys/ofed/drivers/net/mlx4/en_port.h
deleted file mode 100644
index 6301717e1814..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_port.h
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#ifndef _MLX4_EN_PORT_H_
-#define _MLX4_EN_PORT_H_
-
-
-#define SET_PORT_GEN_ALL_VALID 0x7
-#define SET_PORT_PROMISC_SHIFT 31
-#define SET_PORT_MC_PROMISC_SHIFT 30
-
-#define MLX4_EN_NUM_TC 8
-
-#define VLAN_FLTR_SIZE 128
-struct mlx4_set_vlan_fltr_mbox {
- __be32 entry[VLAN_FLTR_SIZE];
-};
-
-
-enum {
- MLX4_MCAST_CONFIG = 0,
- MLX4_MCAST_DISABLE = 1,
- MLX4_MCAST_ENABLE = 2,
-};
-
-enum {
- MLX4_EN_10G_SPEED_XAUI = 0x00,
- MLX4_EN_10G_SPEED_XFI = 0x01,
- MLX4_EN_1G_SPEED = 0x02,
- MLX4_EN_20G_SPEED = 0x08,
- MLX4_EN_40G_SPEED = 0x40,
- MLX4_EN_56G_SPEED = 0x20,
- MLX4_EN_OTHER_SPEED = 0x0f,
-};
-
-struct mlx4_en_query_port_context {
- u8 link_up;
-#define MLX4_EN_LINK_UP_MASK 0x80
- u8 autoneg;
-#define MLX4_EN_AUTONEG_MASK 0x80
- __be16 mtu;
- u8 reserved2;
- u8 link_speed;
-#define MLX4_EN_SPEED_MASK 0x6b
- u16 reserved3[5];
- __be64 mac;
- u8 transceiver;
-};
-
-
-struct mlx4_en_stat_out_mbox {
- /* Received frames with a length of 64 octets */
- __be64 R64_prio_0;
- __be64 R64_prio_1;
- __be64 R64_prio_2;
- __be64 R64_prio_3;
- __be64 R64_prio_4;
- __be64 R64_prio_5;
- __be64 R64_prio_6;
- __be64 R64_prio_7;
- __be64 R64_novlan;
- /* Received frames with a length of 127 octets */
- __be64 R127_prio_0;
- __be64 R127_prio_1;
- __be64 R127_prio_2;
- __be64 R127_prio_3;
- __be64 R127_prio_4;
- __be64 R127_prio_5;
- __be64 R127_prio_6;
- __be64 R127_prio_7;
- __be64 R127_novlan;
- /* Received frames with a length of 255 octets */
- __be64 R255_prio_0;
- __be64 R255_prio_1;
- __be64 R255_prio_2;
- __be64 R255_prio_3;
- __be64 R255_prio_4;
- __be64 R255_prio_5;
- __be64 R255_prio_6;
- __be64 R255_prio_7;
- __be64 R255_novlan;
- /* Received frames with a length of 511 octets */
- __be64 R511_prio_0;
- __be64 R511_prio_1;
- __be64 R511_prio_2;
- __be64 R511_prio_3;
- __be64 R511_prio_4;
- __be64 R511_prio_5;
- __be64 R511_prio_6;
- __be64 R511_prio_7;
- __be64 R511_novlan;
- /* Received frames with a length of 1023 octets */
- __be64 R1023_prio_0;
- __be64 R1023_prio_1;
- __be64 R1023_prio_2;
- __be64 R1023_prio_3;
- __be64 R1023_prio_4;
- __be64 R1023_prio_5;
- __be64 R1023_prio_6;
- __be64 R1023_prio_7;
- __be64 R1023_novlan;
- /* Received frames with a length of 1518 octets */
- __be64 R1518_prio_0;
- __be64 R1518_prio_1;
- __be64 R1518_prio_2;
- __be64 R1518_prio_3;
- __be64 R1518_prio_4;
- __be64 R1518_prio_5;
- __be64 R1518_prio_6;
- __be64 R1518_prio_7;
- __be64 R1518_novlan;
- /* Received frames with a length of 1522 octets */
- __be64 R1522_prio_0;
- __be64 R1522_prio_1;
- __be64 R1522_prio_2;
- __be64 R1522_prio_3;
- __be64 R1522_prio_4;
- __be64 R1522_prio_5;
- __be64 R1522_prio_6;
- __be64 R1522_prio_7;
- __be64 R1522_novlan;
- /* Received frames with a length of 1548 octets */
- __be64 R1548_prio_0;
- __be64 R1548_prio_1;
- __be64 R1548_prio_2;
- __be64 R1548_prio_3;
- __be64 R1548_prio_4;
- __be64 R1548_prio_5;
- __be64 R1548_prio_6;
- __be64 R1548_prio_7;
- __be64 R1548_novlan;
- /* Received frames with a length of 1548 < octets < MTU */
- __be64 R2MTU_prio_0;
- __be64 R2MTU_prio_1;
- __be64 R2MTU_prio_2;
- __be64 R2MTU_prio_3;
- __be64 R2MTU_prio_4;
- __be64 R2MTU_prio_5;
- __be64 R2MTU_prio_6;
- __be64 R2MTU_prio_7;
- __be64 R2MTU_novlan;
- /* Received frames with a length of MTU< octets and good CRC */
- __be64 RGIANT_prio_0;
- __be64 RGIANT_prio_1;
- __be64 RGIANT_prio_2;
- __be64 RGIANT_prio_3;
- __be64 RGIANT_prio_4;
- __be64 RGIANT_prio_5;
- __be64 RGIANT_prio_6;
- __be64 RGIANT_prio_7;
- __be64 RGIANT_novlan;
- /* Received broadcast frames with good CRC */
- __be64 RBCAST_prio_0;
- __be64 RBCAST_prio_1;
- __be64 RBCAST_prio_2;
- __be64 RBCAST_prio_3;
- __be64 RBCAST_prio_4;
- __be64 RBCAST_prio_5;
- __be64 RBCAST_prio_6;
- __be64 RBCAST_prio_7;
- __be64 RBCAST_novlan;
- /* Received multicast frames with good CRC */
- __be64 MCAST_prio_0;
- __be64 MCAST_prio_1;
- __be64 MCAST_prio_2;
- __be64 MCAST_prio_3;
- __be64 MCAST_prio_4;
- __be64 MCAST_prio_5;
- __be64 MCAST_prio_6;
- __be64 MCAST_prio_7;
- __be64 MCAST_novlan;
- /* Received unicast not short or GIANT frames with good CRC */
- __be64 RTOTG_prio_0;
- __be64 RTOTG_prio_1;
- __be64 RTOTG_prio_2;
- __be64 RTOTG_prio_3;
- __be64 RTOTG_prio_4;
- __be64 RTOTG_prio_5;
- __be64 RTOTG_prio_6;
- __be64 RTOTG_prio_7;
- __be64 RTOTG_novlan;
-
- /* Count of total octets of received frames, includes framing characters */
- __be64 RTTLOCT_prio_0;
- /* Count of total octets of received frames, not including framing
- characters */
- __be64 RTTLOCT_NOFRM_prio_0;
- /* Count of Total number of octets received
- (only for frames without errors) */
- __be64 ROCT_prio_0;
-
- __be64 RTTLOCT_prio_1;
- __be64 RTTLOCT_NOFRM_prio_1;
- __be64 ROCT_prio_1;
-
- __be64 RTTLOCT_prio_2;
- __be64 RTTLOCT_NOFRM_prio_2;
- __be64 ROCT_prio_2;
-
- __be64 RTTLOCT_prio_3;
- __be64 RTTLOCT_NOFRM_prio_3;
- __be64 ROCT_prio_3;
-
- __be64 RTTLOCT_prio_4;
- __be64 RTTLOCT_NOFRM_prio_4;
- __be64 ROCT_prio_4;
-
- __be64 RTTLOCT_prio_5;
- __be64 RTTLOCT_NOFRM_prio_5;
- __be64 ROCT_prio_5;
-
- __be64 RTTLOCT_prio_6;
- __be64 RTTLOCT_NOFRM_prio_6;
- __be64 ROCT_prio_6;
-
- __be64 RTTLOCT_prio_7;
- __be64 RTTLOCT_NOFRM_prio_7;
- __be64 ROCT_prio_7;
-
- __be64 RTTLOCT_novlan;
- __be64 RTTLOCT_NOFRM_novlan;
- __be64 ROCT_novlan;
-
- /* Count of Total received frames including bad frames */
- __be64 RTOT_prio_0;
- /* Count of Total number of received frames with 802.1Q encapsulation */
- __be64 R1Q_prio_0;
- __be64 reserved1;
-
- __be64 RTOT_prio_1;
- __be64 R1Q_prio_1;
- __be64 reserved2;
-
- __be64 RTOT_prio_2;
- __be64 R1Q_prio_2;
- __be64 reserved3;
-
- __be64 RTOT_prio_3;
- __be64 R1Q_prio_3;
- __be64 reserved4;
-
- __be64 RTOT_prio_4;
- __be64 R1Q_prio_4;
- __be64 reserved5;
-
- __be64 RTOT_prio_5;
- __be64 R1Q_prio_5;
- __be64 reserved6;
-
- __be64 RTOT_prio_6;
- __be64 R1Q_prio_6;
- __be64 reserved7;
-
- __be64 RTOT_prio_7;
- __be64 R1Q_prio_7;
- __be64 reserved8;
-
- __be64 RTOT_novlan;
- __be64 R1Q_novlan;
- __be64 reserved9;
-
- /* Total number of Successfully Received Control Frames */
- __be64 RCNTL;
- __be64 reserved10;
- __be64 reserved11;
- __be64 reserved12;
- /* Count of received frames with a length/type field value between 46
- (42 for VLANtagged frames) and 1500 (also 1500 for VLAN-tagged frames),
- inclusive */
- __be64 RInRangeLengthErr;
- /* Count of received frames with length/type field between 1501 and 1535
- decimal, inclusive */
- __be64 ROutRangeLengthErr;
- /* Count of received frames that are longer than max allowed size for
- 802.3 frames (1518/1522) */
- __be64 RFrmTooLong;
- /* Count frames received with PCS error */
- __be64 PCS;
-
- /* Transmit frames with a length of 64 octets */
- __be64 T64_prio_0;
- __be64 T64_prio_1;
- __be64 T64_prio_2;
- __be64 T64_prio_3;
- __be64 T64_prio_4;
- __be64 T64_prio_5;
- __be64 T64_prio_6;
- __be64 T64_prio_7;
- __be64 T64_novlan;
- __be64 T64_loopbk;
- /* Transmit frames with a length of 65 to 127 octets. */
- __be64 T127_prio_0;
- __be64 T127_prio_1;
- __be64 T127_prio_2;
- __be64 T127_prio_3;
- __be64 T127_prio_4;
- __be64 T127_prio_5;
- __be64 T127_prio_6;
- __be64 T127_prio_7;
- __be64 T127_novlan;
- __be64 T127_loopbk;
- /* Transmit frames with a length of 128 to 255 octets */
- __be64 T255_prio_0;
- __be64 T255_prio_1;
- __be64 T255_prio_2;
- __be64 T255_prio_3;
- __be64 T255_prio_4;
- __be64 T255_prio_5;
- __be64 T255_prio_6;
- __be64 T255_prio_7;
- __be64 T255_novlan;
- __be64 T255_loopbk;
- /* Transmit frames with a length of 256 to 511 octets */
- __be64 T511_prio_0;
- __be64 T511_prio_1;
- __be64 T511_prio_2;
- __be64 T511_prio_3;
- __be64 T511_prio_4;
- __be64 T511_prio_5;
- __be64 T511_prio_6;
- __be64 T511_prio_7;
- __be64 T511_novlan;
- __be64 T511_loopbk;
- /* Transmit frames with a length of 512 to 1023 octets */
- __be64 T1023_prio_0;
- __be64 T1023_prio_1;
- __be64 T1023_prio_2;
- __be64 T1023_prio_3;
- __be64 T1023_prio_4;
- __be64 T1023_prio_5;
- __be64 T1023_prio_6;
- __be64 T1023_prio_7;
- __be64 T1023_novlan;
- __be64 T1023_loopbk;
- /* Transmit frames with a length of 1024 to 1518 octets */
- __be64 T1518_prio_0;
- __be64 T1518_prio_1;
- __be64 T1518_prio_2;
- __be64 T1518_prio_3;
- __be64 T1518_prio_4;
- __be64 T1518_prio_5;
- __be64 T1518_prio_6;
- __be64 T1518_prio_7;
- __be64 T1518_novlan;
- __be64 T1518_loopbk;
- /* Counts transmit frames with a length of 1519 to 1522 bytes */
- __be64 T1522_prio_0;
- __be64 T1522_prio_1;
- __be64 T1522_prio_2;
- __be64 T1522_prio_3;
- __be64 T1522_prio_4;
- __be64 T1522_prio_5;
- __be64 T1522_prio_6;
- __be64 T1522_prio_7;
- __be64 T1522_novlan;
- __be64 T1522_loopbk;
- /* Transmit frames with a length of 1523 to 1548 octets */
- __be64 T1548_prio_0;
- __be64 T1548_prio_1;
- __be64 T1548_prio_2;
- __be64 T1548_prio_3;
- __be64 T1548_prio_4;
- __be64 T1548_prio_5;
- __be64 T1548_prio_6;
- __be64 T1548_prio_7;
- __be64 T1548_novlan;
- __be64 T1548_loopbk;
- /* Counts transmit frames with a length of 1549 to MTU bytes */
- __be64 T2MTU_prio_0;
- __be64 T2MTU_prio_1;
- __be64 T2MTU_prio_2;
- __be64 T2MTU_prio_3;
- __be64 T2MTU_prio_4;
- __be64 T2MTU_prio_5;
- __be64 T2MTU_prio_6;
- __be64 T2MTU_prio_7;
- __be64 T2MTU_novlan;
- __be64 T2MTU_loopbk;
- /* Transmit frames with a length greater than MTU octets and a good CRC. */
- __be64 TGIANT_prio_0;
- __be64 TGIANT_prio_1;
- __be64 TGIANT_prio_2;
- __be64 TGIANT_prio_3;
- __be64 TGIANT_prio_4;
- __be64 TGIANT_prio_5;
- __be64 TGIANT_prio_6;
- __be64 TGIANT_prio_7;
- __be64 TGIANT_novlan;
- __be64 TGIANT_loopbk;
- /* Transmit broadcast frames with a good CRC */
- __be64 TBCAST_prio_0;
- __be64 TBCAST_prio_1;
- __be64 TBCAST_prio_2;
- __be64 TBCAST_prio_3;
- __be64 TBCAST_prio_4;
- __be64 TBCAST_prio_5;
- __be64 TBCAST_prio_6;
- __be64 TBCAST_prio_7;
- __be64 TBCAST_novlan;
- __be64 TBCAST_loopbk;
- /* Transmit multicast frames with a good CRC */
- __be64 TMCAST_prio_0;
- __be64 TMCAST_prio_1;
- __be64 TMCAST_prio_2;
- __be64 TMCAST_prio_3;
- __be64 TMCAST_prio_4;
- __be64 TMCAST_prio_5;
- __be64 TMCAST_prio_6;
- __be64 TMCAST_prio_7;
- __be64 TMCAST_novlan;
- __be64 TMCAST_loopbk;
- /* Transmit good frames that are neither broadcast nor multicast */
- __be64 TTOTG_prio_0;
- __be64 TTOTG_prio_1;
- __be64 TTOTG_prio_2;
- __be64 TTOTG_prio_3;
- __be64 TTOTG_prio_4;
- __be64 TTOTG_prio_5;
- __be64 TTOTG_prio_6;
- __be64 TTOTG_prio_7;
- __be64 TTOTG_novlan;
- __be64 TTOTG_loopbk;
-
- /* total octets of transmitted frames, including framing characters */
- __be64 TTTLOCT_prio_0;
- /* total octets of transmitted frames, not including framing characters */
- __be64 TTTLOCT_NOFRM_prio_0;
- /* ifOutOctets */
- __be64 TOCT_prio_0;
-
- __be64 TTTLOCT_prio_1;
- __be64 TTTLOCT_NOFRM_prio_1;
- __be64 TOCT_prio_1;
-
- __be64 TTTLOCT_prio_2;
- __be64 TTTLOCT_NOFRM_prio_2;
- __be64 TOCT_prio_2;
-
- __be64 TTTLOCT_prio_3;
- __be64 TTTLOCT_NOFRM_prio_3;
- __be64 TOCT_prio_3;
-
- __be64 TTTLOCT_prio_4;
- __be64 TTTLOCT_NOFRM_prio_4;
- __be64 TOCT_prio_4;
-
- __be64 TTTLOCT_prio_5;
- __be64 TTTLOCT_NOFRM_prio_5;
- __be64 TOCT_prio_5;
-
- __be64 TTTLOCT_prio_6;
- __be64 TTTLOCT_NOFRM_prio_6;
- __be64 TOCT_prio_6;
-
- __be64 TTTLOCT_prio_7;
- __be64 TTTLOCT_NOFRM_prio_7;
- __be64 TOCT_prio_7;
-
- __be64 TTTLOCT_novlan;
- __be64 TTTLOCT_NOFRM_novlan;
- __be64 TOCT_novlan;
-
- __be64 TTTLOCT_loopbk;
- __be64 TTTLOCT_NOFRM_loopbk;
- __be64 TOCT_loopbk;
-
- /* Total frames transmitted with a good CRC that are not aborted */
- __be64 TTOT_prio_0;
- /* Total number of frames transmitted with 802.1Q encapsulation */
- __be64 T1Q_prio_0;
- __be64 reserved13;
-
- __be64 TTOT_prio_1;
- __be64 T1Q_prio_1;
- __be64 reserved14;
-
- __be64 TTOT_prio_2;
- __be64 T1Q_prio_2;
- __be64 reserved15;
-
- __be64 TTOT_prio_3;
- __be64 T1Q_prio_3;
- __be64 reserved16;
-
- __be64 TTOT_prio_4;
- __be64 T1Q_prio_4;
- __be64 reserved17;
-
- __be64 TTOT_prio_5;
- __be64 T1Q_prio_5;
- __be64 reserved18;
-
- __be64 TTOT_prio_6;
- __be64 T1Q_prio_6;
- __be64 reserved19;
-
- __be64 TTOT_prio_7;
- __be64 T1Q_prio_7;
- __be64 reserved20;
-
- __be64 TTOT_novlan;
- __be64 T1Q_novlan;
- __be64 reserved21;
-
- __be64 TTOT_loopbk;
- __be64 T1Q_loopbk;
- __be64 reserved22;
-
- /* Received frames with a length greater than MTU octets and a bad CRC */
- __be32 RJBBR;
- /* Received frames with a bad CRC that are not runts, jabbers,
- or alignment errors */
- __be32 RCRC;
- /* Received frames with SFD with a length of less than 64 octets and a
- bad CRC */
- __be32 RRUNT;
- /* Received frames with a length less than 64 octets and a good CRC */
- __be32 RSHORT;
- /* Total Number of Received Packets Dropped */
- __be32 RDROP;
- /* Drop due to overflow */
- __be32 RdropOvflw;
- /* Drop due to overflow */
- __be32 RdropLength;
- /* Total of good frames. Does not include frames received with
- frame-too-long, FCS, or length errors */
- __be32 RTOTFRMS;
- /* Total dropped Xmited packets */
- __be32 TDROP;
-};
-
-
-#endif
diff --git a/sys/ofed/drivers/net/mlx4/en_resources.c b/sys/ofed/drivers/net/mlx4/en_resources.c
deleted file mode 100644
index 669ecbd11843..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_resources.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mlx4/qp.h>
-
-#include "mlx4_en.h"
-
-
-void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
- int is_tx, int rss, int qpn, int cqn,
- int user_prio, struct mlx4_qp_context *context)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct net_device *dev = priv->dev;
-
- memset(context, 0, sizeof *context);
- context->flags = cpu_to_be32(7 << 16 | rss << MLX4_RSS_QPC_FLAG_OFFSET);
- context->pd = cpu_to_be32(mdev->priv_pdn);
- context->mtu_msgmax = 0xff;
- if (!is_tx && !rss)
- context->rq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4);
- if (is_tx)
- context->sq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4);
- else
- context->sq_size_stride = ilog2(TXBB_SIZE) - 4;
- context->usr_page = cpu_to_be32(mdev->priv_uar.index);
- context->local_qpn = cpu_to_be32(qpn);
- context->pri_path.ackto = 1 & 0x07;
- context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6;
- if (user_prio >= 0) {
- context->pri_path.sched_queue |= user_prio << 3;
- context->pri_path.feup = 1 << 6;
- }
- context->pri_path.counter_index = (u8)(priv->counter_index);
- if (!rss &&
- (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
- context->pri_path.counter_index != 0xFF) {
- /* disable multicast loopback to qp with same counter */
- context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
- context->pri_path.vlan_control |=
- MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
- }
-
- context->cqn_send = cpu_to_be32(cqn);
- context->cqn_recv = cpu_to_be32(cqn);
- context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
- if (!(dev->if_capabilities & IFCAP_VLAN_HWCSUM))
- context->param3 |= cpu_to_be32(1 << 30);
-}
-
-
-int mlx4_en_map_buffer(struct mlx4_buf *buf)
-{
- struct page **pages;
- int i;
-
- // if nbufs == 1 - there is no need to vmap
- // if buf->direct.buf is not NULL it means that vmap was already done by mlx4_alloc_buff
- if (buf->direct.buf != NULL || buf->nbufs == 1)
- return 0;
-
- pages = kmalloc(sizeof *pages * buf->nbufs, GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
-
- for (i = 0; i < buf->nbufs; ++i)
- pages[i] = virt_to_page(buf->page_list[i].buf);
-
- buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, PAGE_KERNEL);
- kfree(pages);
- if (!buf->direct.buf)
- return -ENOMEM;
-
- return 0;
-}
-
-void mlx4_en_unmap_buffer(struct mlx4_buf *buf)
-{
- if (BITS_PER_LONG == 64 || buf->nbufs == 1)
- return;
-
- vunmap(buf->direct.buf);
-}
-
-void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event)
-{
- return;
-}
-
diff --git a/sys/ofed/drivers/net/mlx4/en_rx.c b/sys/ofed/drivers/net/mlx4/en_rx.c
deleted file mode 100644
index 2711b22b8667..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_rx.c
+++ /dev/null
@@ -1,922 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-#include "opt_inet.h"
-#include <linux/mlx4/cq.h>
-#include <linux/slab.h>
-#include <linux/mlx4/qp.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/vmalloc.h>
-#include <linux/mlx4/driver.h>
-#ifdef CONFIG_NET_RX_BUSY_POLL
-#include <net/busy_poll.h>
-#endif
-
-#include "mlx4_en.h"
-
-
-static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring,
- int index)
-{
- struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
- (ring->buf + (ring->stride * index));
- int possible_frags;
- int i;
-
- /* Set size and memtype fields */
- rx_desc->data[0].byte_count = cpu_to_be32(priv->rx_mb_size - MLX4_NET_IP_ALIGN);
- rx_desc->data[0].lkey = cpu_to_be32(priv->mdev->mr.key);
-
- /*
- * If the number of used fragments does not fill up the ring
- * stride, remaining (unused) fragments must be padded with
- * null address/size and a special memory key:
- */
- possible_frags = (ring->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE;
- for (i = 1; i < possible_frags; i++) {
- rx_desc->data[i].byte_count = 0;
- rx_desc->data[i].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD);
- rx_desc->data[i].addr = 0;
- }
-}
-
-static int
-mlx4_en_alloc_buf(struct mlx4_en_rx_ring *ring,
- __be64 *pdma, struct mlx4_en_rx_mbuf *mb_list)
-{
- bus_dma_segment_t segs[1];
- bus_dmamap_t map;
- struct mbuf *mb;
- int nsegs;
- int err;
-
- /* try to allocate a new spare mbuf */
- if (unlikely(ring->spare.mbuf == NULL)) {
- mb = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, ring->rx_mb_size);
- if (unlikely(mb == NULL))
- return (-ENOMEM);
- /* setup correct length */
- mb->m_pkthdr.len = mb->m_len = ring->rx_mb_size;
-
- /* make sure IP header gets aligned */
- m_adj(mb, MLX4_NET_IP_ALIGN);
-
- /* load spare mbuf into BUSDMA */
- err = -bus_dmamap_load_mbuf_sg(ring->dma_tag, ring->spare.dma_map,
- mb, segs, &nsegs, BUS_DMA_NOWAIT);
- if (unlikely(err != 0)) {
- m_freem(mb);
- return (err);
- }
-
- /* store spare info */
- ring->spare.mbuf = mb;
- ring->spare.paddr_be = cpu_to_be64(segs[0].ds_addr);
-
- bus_dmamap_sync(ring->dma_tag, ring->spare.dma_map,
- BUS_DMASYNC_PREREAD);
- }
-
- /* synchronize and unload the current mbuf, if any */
- if (likely(mb_list->mbuf != NULL)) {
- bus_dmamap_sync(ring->dma_tag, mb_list->dma_map,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(ring->dma_tag, mb_list->dma_map);
- }
-
- mb = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, ring->rx_mb_size);
- if (unlikely(mb == NULL))
- goto use_spare;
-
- /* setup correct length */
- mb->m_pkthdr.len = mb->m_len = ring->rx_mb_size;
-
- /* make sure IP header gets aligned */
- m_adj(mb, MLX4_NET_IP_ALIGN);
-
- err = -bus_dmamap_load_mbuf_sg(ring->dma_tag, mb_list->dma_map,
- mb, segs, &nsegs, BUS_DMA_NOWAIT);
- if (unlikely(err != 0)) {
- m_freem(mb);
- goto use_spare;
- }
-
- *pdma = cpu_to_be64(segs[0].ds_addr);
- mb_list->mbuf = mb;
-
- bus_dmamap_sync(ring->dma_tag, mb_list->dma_map, BUS_DMASYNC_PREREAD);
- return (0);
-
-use_spare:
- /* swap DMA maps */
- map = mb_list->dma_map;
- mb_list->dma_map = ring->spare.dma_map;
- ring->spare.dma_map = map;
-
- /* swap MBUFs */
- mb_list->mbuf = ring->spare.mbuf;
- ring->spare.mbuf = NULL;
-
- /* store physical address */
- *pdma = ring->spare.paddr_be;
- return (0);
-}
-
-static void
-mlx4_en_free_buf(struct mlx4_en_rx_ring *ring, struct mlx4_en_rx_mbuf *mb_list)
-{
- bus_dmamap_t map = mb_list->dma_map;
- bus_dmamap_sync(ring->dma_tag, map, BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(ring->dma_tag, map);
- m_freem(mb_list->mbuf);
- mb_list->mbuf = NULL; /* safety clearing */
-}
-
-static int
-mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring, int index)
-{
- struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
- (ring->buf + (index * ring->stride));
- struct mlx4_en_rx_mbuf *mb_list = ring->mbuf + index;
-
- mb_list->mbuf = NULL;
-
- if (mlx4_en_alloc_buf(ring, &rx_desc->data[0].addr, mb_list)) {
- priv->port_stats.rx_alloc_failed++;
- return (-ENOMEM);
- }
- return (0);
-}
-
-static inline void
-mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
-{
- *ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
-}
-
-static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_rx_ring *ring;
- int ring_ind;
- int buf_ind;
- int new_size;
- int err;
-
- for (buf_ind = 0; buf_ind < priv->prof->rx_ring_size; buf_ind++) {
- for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = priv->rx_ring[ring_ind];
-
- err = mlx4_en_prepare_rx_desc(priv, ring,
- ring->actual_size);
- if (err) {
- if (ring->actual_size == 0) {
- en_err(priv, "Failed to allocate "
- "enough rx buffers\n");
- return -ENOMEM;
- } else {
- new_size =
- rounddown_pow_of_two(ring->actual_size);
- en_warn(priv, "Only %d buffers allocated "
- "reducing ring size to %d\n",
- ring->actual_size, new_size);
- goto reduce_rings;
- }
- }
- ring->actual_size++;
- ring->prod++;
- }
- }
- return 0;
-
-reduce_rings:
- for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = priv->rx_ring[ring_ind];
- while (ring->actual_size > new_size) {
- ring->actual_size--;
- ring->prod--;
- mlx4_en_free_buf(ring,
- ring->mbuf + ring->actual_size);
- }
- }
-
- return 0;
-}
-
-static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring)
-{
- int index;
-
- en_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n",
- ring->cons, ring->prod);
-
- /* Unmap and free Rx buffers */
- BUG_ON((u32) (ring->prod - ring->cons) > ring->actual_size);
- while (ring->cons != ring->prod) {
- index = ring->cons & ring->size_mask;
- en_dbg(DRV, priv, "Processing descriptor:%d\n", index);
- mlx4_en_free_buf(ring, ring->mbuf + index);
- ++ring->cons;
- }
-}
-
-void mlx4_en_calc_rx_buf(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- int eff_mtu = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN +
- MLX4_NET_IP_ALIGN;
-
- if (eff_mtu > MJUM16BYTES) {
- en_err(priv, "MTU(%d) is too big\n", dev->if_mtu);
- eff_mtu = MJUM16BYTES;
- } else if (eff_mtu > MJUM9BYTES) {
- eff_mtu = MJUM16BYTES;
- } else if (eff_mtu > MJUMPAGESIZE) {
- eff_mtu = MJUM9BYTES;
- } else if (eff_mtu > MCLBYTES) {
- eff_mtu = MJUMPAGESIZE;
- } else {
- eff_mtu = MCLBYTES;
- }
-
- priv->rx_mb_size = eff_mtu;
-
- en_dbg(DRV, priv, "Effective RX MTU: %d bytes\n", eff_mtu);
-}
-
-int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring **pring,
- u32 size, int node)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_rx_ring *ring;
- int err;
- int tmp;
- uint32_t x;
-
- ring = kzalloc(sizeof(struct mlx4_en_rx_ring), GFP_KERNEL);
- if (!ring) {
- en_err(priv, "Failed to allocate RX ring structure\n");
- return -ENOMEM;
- }
-
- /* Create DMA descriptor TAG */
- if ((err = -bus_dma_tag_create(
- bus_get_dma_tag(mdev->pdev->dev.bsddev),
- 1, /* any alignment */
- 0, /* no boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MJUM16BYTES, /* maxsize */
- 1, /* nsegments */
- MJUM16BYTES, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockfuncarg */
- &ring->dma_tag))) {
- en_err(priv, "Failed to create DMA tag\n");
- goto err_ring;
- }
-
- ring->prod = 0;
- ring->cons = 0;
- ring->size = size;
- ring->size_mask = size - 1;
- ring->stride = roundup_pow_of_two(
- sizeof(struct mlx4_en_rx_desc) + DS_SIZE);
- ring->log_stride = ffs(ring->stride) - 1;
- ring->buf_size = ring->size * ring->stride + TXBB_SIZE;
-
- tmp = size * sizeof(struct mlx4_en_rx_mbuf);
-
- ring->mbuf = kzalloc(tmp, GFP_KERNEL);
- if (ring->mbuf == NULL) {
- err = -ENOMEM;
- goto err_dma_tag;
- }
-
- err = -bus_dmamap_create(ring->dma_tag, 0, &ring->spare.dma_map);
- if (err != 0)
- goto err_info;
-
- for (x = 0; x != size; x++) {
- err = -bus_dmamap_create(ring->dma_tag, 0,
- &ring->mbuf[x].dma_map);
- if (err != 0) {
- while (x--)
- bus_dmamap_destroy(ring->dma_tag,
- ring->mbuf[x].dma_map);
- goto err_info;
- }
- }
- en_dbg(DRV, priv, "Allocated MBUF ring at addr:%p size:%d\n",
- ring->mbuf, tmp);
-
- err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres,
- ring->buf_size, 2 * PAGE_SIZE);
- if (err)
- goto err_dma_map;
-
- err = mlx4_en_map_buffer(&ring->wqres.buf);
- if (err) {
- en_err(priv, "Failed to map RX buffer\n");
- goto err_hwq;
- }
- ring->buf = ring->wqres.buf.direct.buf;
- *pring = ring;
- return 0;
-
-err_hwq:
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
-err_dma_map:
- for (x = 0; x != size; x++) {
- bus_dmamap_destroy(ring->dma_tag,
- ring->mbuf[x].dma_map);
- }
- bus_dmamap_destroy(ring->dma_tag, ring->spare.dma_map);
-err_info:
- vfree(ring->mbuf);
-err_dma_tag:
- bus_dma_tag_destroy(ring->dma_tag);
-err_ring:
- kfree(ring);
- return (err);
-}
-
-int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_rx_ring *ring;
- int i;
- int ring_ind;
- int err;
- int stride = roundup_pow_of_two(
- sizeof(struct mlx4_en_rx_desc) + DS_SIZE);
-
- for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = priv->rx_ring[ring_ind];
-
- ring->prod = 0;
- ring->cons = 0;
- ring->actual_size = 0;
- ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn;
- ring->rx_mb_size = priv->rx_mb_size;
-
- ring->stride = stride;
- if (ring->stride <= TXBB_SIZE)
- ring->buf += TXBB_SIZE;
-
- ring->log_stride = ffs(ring->stride) - 1;
- ring->buf_size = ring->size * ring->stride;
-
- memset(ring->buf, 0, ring->buf_size);
- mlx4_en_update_rx_prod_db(ring);
-
- /* Initialize all descriptors */
- for (i = 0; i < ring->size; i++)
- mlx4_en_init_rx_desc(priv, ring, i);
-
-#ifdef INET
- /* Configure lro mngr */
- if (priv->dev->if_capenable & IFCAP_LRO) {
- if (tcp_lro_init(&ring->lro))
- priv->dev->if_capenable &= ~IFCAP_LRO;
- else
- ring->lro.ifp = priv->dev;
- }
-#endif
- }
-
-
- err = mlx4_en_fill_rx_buffers(priv);
- if (err)
- goto err_buffers;
-
- for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = priv->rx_ring[ring_ind];
-
- ring->size_mask = ring->actual_size - 1;
- mlx4_en_update_rx_prod_db(ring);
- }
-
- return 0;
-
-err_buffers:
- for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++)
- mlx4_en_free_rx_buf(priv, priv->rx_ring[ring_ind]);
-
- ring_ind = priv->rx_ring_num - 1;
-
- while (ring_ind >= 0) {
- ring = priv->rx_ring[ring_ind];
- if (ring->stride <= TXBB_SIZE)
- ring->buf -= TXBB_SIZE;
- ring_ind--;
- }
-
- return err;
-}
-
-
-void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring **pring,
- u32 size, u16 stride)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_rx_ring *ring = *pring;
- uint32_t x;
-
- mlx4_en_unmap_buffer(&ring->wqres.buf);
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
- for (x = 0; x != size; x++)
- bus_dmamap_destroy(ring->dma_tag, ring->mbuf[x].dma_map);
- /* free spare mbuf, if any */
- if (ring->spare.mbuf != NULL) {
- bus_dmamap_sync(ring->dma_tag, ring->spare.dma_map,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(ring->dma_tag, ring->spare.dma_map);
- m_freem(ring->spare.mbuf);
- }
- bus_dmamap_destroy(ring->dma_tag, ring->spare.dma_map);
- vfree(ring->mbuf);
- bus_dma_tag_destroy(ring->dma_tag);
- kfree(ring);
- *pring = NULL;
-#ifdef CONFIG_RFS_ACCEL
- mlx4_en_cleanup_filters(priv, ring);
-#endif
-}
-
-void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring)
-{
-#ifdef INET
- tcp_lro_free(&ring->lro);
-#endif
- mlx4_en_free_rx_buf(priv, ring);
- if (ring->stride <= TXBB_SIZE)
- ring->buf -= TXBB_SIZE;
-}
-
-
-static void validate_loopback(struct mlx4_en_priv *priv, struct mbuf *mb)
-{
- int i;
- int offset = ETHER_HDR_LEN;
-
- for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) {
- if (*(mb->m_data + offset) != (unsigned char) (i & 0xff))
- goto out_loopback;
- }
- /* Loopback found */
- priv->loopback_ok = 1;
-
-out_loopback:
- m_freem(mb);
-}
-
-
-static inline int invalid_cqe(struct mlx4_en_priv *priv,
- struct mlx4_cqe *cqe)
-{
- /* Drop packet on bad receive or bad checksum */
- if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
- MLX4_CQE_OPCODE_ERROR)) {
- en_err(priv, "CQE completed in error - vendor syndrom:%d syndrom:%d\n",
- ((struct mlx4_err_cqe *)cqe)->vendor_err_syndrome,
- ((struct mlx4_err_cqe *)cqe)->syndrome);
- return 1;
- }
- if (unlikely(cqe->badfcs_enc & MLX4_CQE_BAD_FCS)) {
- en_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n");
- return 1;
- }
-
- return 0;
-}
-
-static struct mbuf *
-mlx4_en_rx_mb(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring,
- struct mlx4_en_rx_desc *rx_desc, struct mlx4_en_rx_mbuf *mb_list,
- int length)
-{
- struct mbuf *mb;
-
- /* get mbuf */
- mb = mb_list->mbuf;
-
- /* collect used fragment while atomically replacing it */
- if (mlx4_en_alloc_buf(ring, &rx_desc->data[0].addr, mb_list))
- return (NULL);
-
- /* range check hardware computed value */
- if (unlikely(length > mb->m_len))
- length = mb->m_len;
-
- /* update total packet length in packet header */
- mb->m_len = mb->m_pkthdr.len = length;
- return (mb);
-}
-
-/* For cpu arch with cache line of 64B the performance is better when cqe size==64B
- * To enlarge cqe size from 32B to 64B --> 32B of garbage (i.e. 0xccccccc)
- * was added in the beginning of each cqe (the real data is in the corresponding 32B).
- * The following calc ensures that when factor==1, it means we are aligned to 64B
- * and we get the real cqe data*/
-#define CQE_FACTOR_INDEX(index, factor) ((index << factor) + factor)
-int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_cqe *cqe;
- struct mlx4_en_rx_ring *ring = priv->rx_ring[cq->ring];
- struct mlx4_en_rx_mbuf *mb_list;
- struct mlx4_en_rx_desc *rx_desc;
- struct mbuf *mb;
- struct mlx4_cq *mcq = &cq->mcq;
- struct mlx4_cqe *buf = cq->buf;
- int index;
- unsigned int length;
- int polled = 0;
- u32 cons_index = mcq->cons_index;
- u32 size_mask = ring->size_mask;
- int size = cq->size;
- int factor = priv->cqe_factor;
-
- if (!priv->port_up)
- return 0;
-
- /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
- * descriptor offset can be deducted from the CQE index instead of
- * reading 'cqe->index' */
- index = cons_index & size_mask;
- cqe = &buf[CQE_FACTOR_INDEX(index, factor)];
-
- /* Process all completed CQEs */
- while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
- cons_index & size)) {
- mb_list = ring->mbuf + index;
- rx_desc = (struct mlx4_en_rx_desc *)
- (ring->buf + (index << ring->log_stride));
-
- /*
- * make sure we read the CQE after we read the ownership bit
- */
- rmb();
-
- if (invalid_cqe(priv, cqe)) {
- goto next;
- }
- /*
- * Packet is OK - process it.
- */
- length = be32_to_cpu(cqe->byte_cnt);
- length -= ring->fcs_del;
-
- mb = mlx4_en_rx_mb(priv, ring, rx_desc, mb_list, length);
- if (unlikely(!mb)) {
- ring->errors++;
- goto next;
- }
-
- ring->bytes += length;
- ring->packets++;
-
- if (unlikely(priv->validate_loopback)) {
- validate_loopback(priv, mb);
- goto next;
- }
-
- /* forward Toeplitz compatible hash value */
- mb->m_pkthdr.flowid = be32_to_cpu(cqe->immed_rss_invalid);
- M_HASHTYPE_SET(mb, M_HASHTYPE_OPAQUE_HASH);
- mb->m_pkthdr.rcvif = dev;
- if (be32_to_cpu(cqe->vlan_my_qpn) &
- MLX4_CQE_VLAN_PRESENT_MASK) {
- mb->m_pkthdr.ether_vtag = be16_to_cpu(cqe->sl_vid);
- mb->m_flags |= M_VLANTAG;
- }
- if (likely(dev->if_capenable &
- (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) &&
- (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
- (cqe->checksum == cpu_to_be16(0xffff))) {
- priv->port_stats.rx_chksum_good++;
- mb->m_pkthdr.csum_flags =
- CSUM_IP_CHECKED | CSUM_IP_VALID |
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- mb->m_pkthdr.csum_data = htons(0xffff);
- /* This packet is eligible for LRO if it is:
- * - DIX Ethernet (type interpretation)
- * - TCP/IP (v4)
- * - without IP options
- * - not an IP fragment
- */
-#ifdef INET
- if (mlx4_en_can_lro(cqe->status) &&
- (dev->if_capenable & IFCAP_LRO)) {
- if (ring->lro.lro_cnt != 0 &&
- tcp_lro_rx(&ring->lro, mb, 0) == 0)
- goto next;
- }
-
-#endif
- /* LRO not possible, complete processing here */
- INC_PERF_COUNTER(priv->pstats.lro_misses);
- } else {
- mb->m_pkthdr.csum_flags = 0;
- priv->port_stats.rx_chksum_none++;
- }
-
- /* Push it up the stack */
- dev->if_input(dev, mb);
-
-next:
- ++cons_index;
- index = cons_index & size_mask;
- cqe = &buf[CQE_FACTOR_INDEX(index, factor)];
- if (++polled == budget)
- goto out;
- }
- /* Flush all pending IP reassembly sessions */
-out:
-#ifdef INET
- tcp_lro_flush_all(&ring->lro);
-#endif
- AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
- mcq->cons_index = cons_index;
- mlx4_cq_set_ci(mcq);
- wmb(); /* ensure HW sees CQ consumer before we post new buffers */
- ring->cons = mcq->cons_index;
- ring->prod += polled; /* Polled descriptors were realocated in place */
- mlx4_en_update_rx_prod_db(ring);
- return polled;
-
-}
-
-/* Rx CQ polling - called by NAPI */
-static int mlx4_en_poll_rx_cq(struct mlx4_en_cq *cq, int budget)
-{
- struct net_device *dev = cq->dev;
- int done;
-
- done = mlx4_en_process_rx_cq(dev, cq, budget);
- cq->tot_rx += done;
-
- return done;
-
-}
-void mlx4_en_rx_irq(struct mlx4_cq *mcq)
-{
- struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq);
- struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- int done;
-
- // Shoot one within the irq context
- // Because there is no NAPI in freeBSD
- done = mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET);
- if (priv->port_up && (done == MLX4_EN_RX_BUDGET) ) {
- cq->curr_poll_rx_cpu_id = curcpu;
- taskqueue_enqueue(cq->tq, &cq->cq_task);
- }
- else {
- mlx4_en_arm_cq(priv, cq);
- }
-}
-
-void mlx4_en_rx_que(void *context, int pending)
-{
- struct mlx4_en_cq *cq;
- struct thread *td;
-
- cq = context;
- td = curthread;
-
- thread_lock(td);
- sched_bind(td, cq->curr_poll_rx_cpu_id);
- thread_unlock(td);
-
- while (mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET)
- == MLX4_EN_RX_BUDGET);
- mlx4_en_arm_cq(cq->dev->if_softc, cq);
-}
-
-
-/* RSS related functions */
-
-static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
- struct mlx4_en_rx_ring *ring,
- enum mlx4_qp_state *state,
- struct mlx4_qp *qp)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_qp_context *context;
- int err = 0;
-
- context = kmalloc(sizeof *context , GFP_KERNEL);
- if (!context) {
- en_err(priv, "Failed to allocate qp context\n");
- return -ENOMEM;
- }
-
- err = mlx4_qp_alloc(mdev->dev, qpn, qp);
- if (err) {
- en_err(priv, "Failed to allocate qp #%x\n", qpn);
- goto out;
- }
- qp->event = mlx4_en_sqp_event;
-
- memset(context, 0, sizeof *context);
- mlx4_en_fill_qp_context(priv, ring->actual_size, ring->stride, 0, 0,
- qpn, ring->cqn, -1, context);
- context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
-
- /* Cancel FCS removal if FW allows */
- if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP) {
- context->param3 |= cpu_to_be32(1 << 29);
- ring->fcs_del = ETH_FCS_LEN;
- } else
- ring->fcs_del = 0;
-
- err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state);
- if (err) {
- mlx4_qp_remove(mdev->dev, qp);
- mlx4_qp_free(mdev->dev, qp);
- }
- mlx4_en_update_rx_prod_db(ring);
-out:
- kfree(context);
- return err;
-}
-
-int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv)
-{
- int err;
- u32 qpn;
-
- err = mlx4_qp_reserve_range(priv->mdev->dev, 1, 1, &qpn, 0);
- if (err) {
- en_err(priv, "Failed reserving drop qpn\n");
- return err;
- }
- err = mlx4_qp_alloc(priv->mdev->dev, qpn, &priv->drop_qp);
- if (err) {
- en_err(priv, "Failed allocating drop qp\n");
- mlx4_qp_release_range(priv->mdev->dev, qpn, 1);
- return err;
- }
-
- return 0;
-}
-
-void mlx4_en_destroy_drop_qp(struct mlx4_en_priv *priv)
-{
- u32 qpn;
-
- qpn = priv->drop_qp.qpn;
- mlx4_qp_remove(priv->mdev->dev, &priv->drop_qp);
- mlx4_qp_free(priv->mdev->dev, &priv->drop_qp);
- mlx4_qp_release_range(priv->mdev->dev, qpn, 1);
-}
-
-/* Allocate rx qp's and configure them according to rss map */
-int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_rss_map *rss_map = &priv->rss_map;
- struct mlx4_qp_context context;
- struct mlx4_rss_context *rss_context;
- int rss_rings;
- void *ptr;
- u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 |
- MLX4_RSS_TCP_IPV6);
- int i;
- int err = 0;
- int good_qps = 0;
- static const u32 rsskey[10] = { 0xD181C62C, 0xF7F4DB5B, 0x1983A2FC,
- 0x943E1ADB, 0xD9389E6B, 0xD1039C2C, 0xA74499AD,
- 0x593D56D9, 0xF3253C06, 0x2ADC1FFC};
-
- en_dbg(DRV, priv, "Configuring rss steering\n");
- err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num,
- priv->rx_ring_num,
- &rss_map->base_qpn, 0);
- if (err) {
- en_err(priv, "Failed reserving %d qps\n", priv->rx_ring_num);
- return err;
- }
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_ring[i]->qpn = rss_map->base_qpn + i;
- err = mlx4_en_config_rss_qp(priv, priv->rx_ring[i]->qpn,
- priv->rx_ring[i],
- &rss_map->state[i],
- &rss_map->qps[i]);
- if (err)
- goto rss_err;
-
- ++good_qps;
- }
-
- /* Configure RSS indirection qp */
- err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
- if (err) {
- en_err(priv, "Failed to allocate RSS indirection QP\n");
- goto rss_err;
- }
- rss_map->indir_qp.event = mlx4_en_sqp_event;
- mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
- priv->rx_ring[0]->cqn, -1, &context);
-
- if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
- rss_rings = priv->rx_ring_num;
- else
- rss_rings = priv->prof->rss_rings;
-
- ptr = ((u8 *)&context) + offsetof(struct mlx4_qp_context, pri_path) +
- MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
- rss_context = ptr;
- rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
- (rss_map->base_qpn));
- rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
- if (priv->mdev->profile.udp_rss) {
- rss_mask |= MLX4_RSS_UDP_IPV4 | MLX4_RSS_UDP_IPV6;
- rss_context->base_qpn_udp = rss_context->default_qpn;
- }
- rss_context->flags = rss_mask;
- rss_context->hash_fn = MLX4_RSS_HASH_TOP;
- for (i = 0; i < 10; i++)
- rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
-
- err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
- &rss_map->indir_qp, &rss_map->indir_state);
- if (err)
- goto indir_err;
-
- return 0;
-
-indir_err:
- mlx4_qp_modify(mdev->dev, NULL, rss_map->indir_state,
- MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
- mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
- mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
-rss_err:
- for (i = 0; i < good_qps; i++) {
- mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
- MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]);
- mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
- mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
- }
- mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, priv->rx_ring_num);
- return err;
-}
-
-void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_rss_map *rss_map = &priv->rss_map;
- int i;
-
- mlx4_qp_modify(mdev->dev, NULL, rss_map->indir_state,
- MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
- mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
- mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
- MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]);
- mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
- mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
- }
- mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, priv->rx_ring_num);
-}
-
diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c
deleted file mode 100644
index 9090c51679dd..000000000000
--- a/sys/ofed/drivers/net/mlx4/en_tx.c
+++ /dev/null
@@ -1,1119 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#define LINUXKPI_PARAM_PREFIX mlx4_
-
-#include <linux/page.h>
-#include <linux/mlx4/cq.h>
-#include <linux/slab.h>
-#include <linux/mlx4/qp.h>
-#include <linux/if_vlan.h>
-#include <linux/vmalloc.h>
-#include <linux/moduleparam.h>
-
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_lro.h>
-#include <netinet/udp.h>
-
-#include "mlx4_en.h"
-
-enum {
- MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
- MAX_BF = 256,
- MIN_PKT_LEN = 17,
-};
-
-static int inline_thold __read_mostly = MAX_INLINE;
-
-module_param_named(inline_thold, inline_thold, uint, 0444);
-MODULE_PARM_DESC(inline_thold, "threshold for using inline data");
-
-int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring **pring, u32 size,
- u16 stride, int node, int queue_idx)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_tx_ring *ring;
- uint32_t x;
- int tmp;
- int err;
-
- ring = kzalloc_node(sizeof(struct mlx4_en_tx_ring), GFP_KERNEL, node);
- if (!ring) {
- ring = kzalloc(sizeof(struct mlx4_en_tx_ring), GFP_KERNEL);
- if (!ring) {
- en_err(priv, "Failed allocating TX ring\n");
- return -ENOMEM;
- }
- }
-
- /* Create DMA descriptor TAG */
- if ((err = -bus_dma_tag_create(
- bus_get_dma_tag(mdev->pdev->dev.bsddev),
- 1, /* any alignment */
- 0, /* no boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MLX4_EN_TX_MAX_PAYLOAD_SIZE, /* maxsize */
- MLX4_EN_TX_MAX_MBUF_FRAGS, /* nsegments */
- MLX4_EN_TX_MAX_MBUF_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockfuncarg */
- &ring->dma_tag)))
- goto done;
-
- ring->size = size;
- ring->size_mask = size - 1;
- ring->stride = stride;
- ring->inline_thold = MAX(MIN_PKT_LEN, MIN(inline_thold, MAX_INLINE));
- mtx_init(&ring->tx_lock.m, "mlx4 tx", NULL, MTX_DEF);
- mtx_init(&ring->comp_lock.m, "mlx4 comp", NULL, MTX_DEF);
-
- /* Allocate the buf ring */
- ring->br = buf_ring_alloc(MLX4_EN_DEF_TX_QUEUE_SIZE, M_DEVBUF,
- M_WAITOK, &ring->tx_lock.m);
- if (ring->br == NULL) {
- en_err(priv, "Failed allocating tx_info ring\n");
- err = -ENOMEM;
- goto err_free_dma_tag;
- }
-
- tmp = size * sizeof(struct mlx4_en_tx_info);
- ring->tx_info = kzalloc_node(tmp, GFP_KERNEL, node);
- if (!ring->tx_info) {
- ring->tx_info = kzalloc(tmp, GFP_KERNEL);
- if (!ring->tx_info) {
- err = -ENOMEM;
- goto err_ring;
- }
- }
-
- /* Create DMA descriptor MAPs */
- for (x = 0; x != size; x++) {
- err = -bus_dmamap_create(ring->dma_tag, 0,
- &ring->tx_info[x].dma_map);
- if (err != 0) {
- while (x--) {
- bus_dmamap_destroy(ring->dma_tag,
- ring->tx_info[x].dma_map);
- }
- goto err_info;
- }
- }
-
- en_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n",
- ring->tx_info, tmp);
-
- ring->buf_size = ALIGN(size * ring->stride, MLX4_EN_PAGE_SIZE);
-
- /* Allocate HW buffers on provided NUMA node */
- err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size,
- 2 * PAGE_SIZE);
- if (err) {
- en_err(priv, "Failed allocating hwq resources\n");
- goto err_dma_map;
- }
-
- err = mlx4_en_map_buffer(&ring->wqres.buf);
- if (err) {
- en_err(priv, "Failed to map TX buffer\n");
- goto err_hwq_res;
- }
-
- ring->buf = ring->wqres.buf.direct.buf;
-
- en_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d "
- "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size,
- ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map);
-
- err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn,
- MLX4_RESERVE_BF_QP);
- if (err) {
- en_err(priv, "failed reserving qp for TX ring\n");
- goto err_map;
- }
-
- err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp);
- if (err) {
- en_err(priv, "Failed allocating qp %d\n", ring->qpn);
- goto err_reserve;
- }
- ring->qp.event = mlx4_en_sqp_event;
-
- err = mlx4_bf_alloc(mdev->dev, &ring->bf, node);
- if (err) {
- en_dbg(DRV, priv, "working without blueflame (%d)", err);
- ring->bf.uar = &mdev->priv_uar;
- ring->bf.uar->map = mdev->uar_map;
- ring->bf_enabled = false;
- } else
- ring->bf_enabled = true;
- ring->queue_index = queue_idx;
- if (queue_idx < priv->num_tx_rings_p_up )
- CPU_SET(queue_idx, &ring->affinity_mask);
-
- *pring = ring;
- return 0;
-
-err_reserve:
- mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
-err_map:
- mlx4_en_unmap_buffer(&ring->wqres.buf);
-err_hwq_res:
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
-err_dma_map:
- for (x = 0; x != size; x++)
- bus_dmamap_destroy(ring->dma_tag, ring->tx_info[x].dma_map);
-err_info:
- vfree(ring->tx_info);
-err_ring:
- buf_ring_free(ring->br, M_DEVBUF);
-err_free_dma_tag:
- bus_dma_tag_destroy(ring->dma_tag);
-done:
- kfree(ring);
- return err;
-}
-
-void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring **pring)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_tx_ring *ring = *pring;
- uint32_t x;
- en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
-
- buf_ring_free(ring->br, M_DEVBUF);
- if (ring->bf_enabled)
- mlx4_bf_free(mdev->dev, &ring->bf);
- mlx4_qp_remove(mdev->dev, &ring->qp);
- mlx4_qp_free(mdev->dev, &ring->qp);
- mlx4_qp_release_range(priv->mdev->dev, ring->qpn, 1);
- mlx4_en_unmap_buffer(&ring->wqres.buf);
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
- for (x = 0; x != ring->size; x++)
- bus_dmamap_destroy(ring->dma_tag, ring->tx_info[x].dma_map);
- vfree(ring->tx_info);
- mtx_destroy(&ring->tx_lock.m);
- mtx_destroy(&ring->comp_lock.m);
- bus_dma_tag_destroy(ring->dma_tag);
- kfree(ring);
- *pring = NULL;
-}
-
-int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring,
- int cq, int user_prio)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
- int err;
-
- ring->cqn = cq;
- ring->prod = 0;
- ring->cons = 0xffffffff;
- ring->last_nr_txbb = 1;
- ring->poll_cnt = 0;
- ring->blocked = 0;
- memset(ring->buf, 0, ring->buf_size);
-
- ring->qp_state = MLX4_QP_STATE_RST;
- ring->doorbell_qpn = ring->qp.qpn << 8;
-
- mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
- ring->cqn, user_prio, &ring->context);
- if (ring->bf_enabled)
- ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
-
- err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
- &ring->qp, &ring->qp_state);
- return err;
-}
-
-void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring)
-{
- struct mlx4_en_dev *mdev = priv->mdev;
-
- mlx4_qp_modify(mdev->dev, NULL, ring->qp_state,
- MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
-}
-
-static volatile struct mlx4_wqe_data_seg *
-mlx4_en_store_inline_lso_data(volatile struct mlx4_wqe_data_seg *dseg,
- struct mbuf *mb, int len, __be32 owner_bit)
-{
- uint8_t *inl = __DEVOLATILE(uint8_t *, dseg);
-
- /* copy data into place */
- m_copydata(mb, 0, len, inl + 4);
- dseg += DIV_ROUND_UP(4 + len, DS_SIZE_ALIGNMENT);
- return (dseg);
-}
-
-static void
-mlx4_en_store_inline_lso_header(volatile struct mlx4_wqe_data_seg *dseg,
- int len, __be32 owner_bit)
-{
-}
-
-static void
-mlx4_en_stamp_wqe(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring, u32 index, u8 owner)
-{
- struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
- struct mlx4_en_tx_desc *tx_desc = (struct mlx4_en_tx_desc *)
- (ring->buf + (index * TXBB_SIZE));
- volatile __be32 *ptr = (__be32 *)tx_desc;
- const __be32 stamp = cpu_to_be32(STAMP_VAL |
- ((u32)owner << STAMP_SHIFT));
- u32 i;
-
- /* Stamp the freed descriptor */
- for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
- *ptr = stamp;
- ptr += STAMP_DWORDS;
- }
-}
-
-static u32
-mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring, u32 index)
-{
- struct mlx4_en_tx_info *tx_info;
- struct mbuf *mb;
-
- tx_info = &ring->tx_info[index];
- mb = tx_info->mb;
-
- if (mb == NULL)
- goto done;
-
- bus_dmamap_sync(ring->dma_tag, tx_info->dma_map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(ring->dma_tag, tx_info->dma_map);
-
- m_freem(mb);
-done:
- return (tx_info->nr_txbb);
-}
-
-int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- int cnt = 0;
-
- /* Skip last polled descriptor */
- ring->cons += ring->last_nr_txbb;
- en_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n",
- ring->cons, ring->prod);
-
- if ((u32) (ring->prod - ring->cons) > ring->size) {
- en_warn(priv, "Tx consumer passed producer!\n");
- return 0;
- }
-
- while (ring->cons != ring->prod) {
- ring->last_nr_txbb = mlx4_en_free_tx_desc(priv, ring,
- ring->cons & ring->size_mask);
- ring->cons += ring->last_nr_txbb;
- cnt++;
- }
-
- if (cnt)
- en_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt);
-
- return cnt;
-}
-
-static bool
-mlx4_en_tx_ring_is_full(struct mlx4_en_tx_ring *ring)
-{
- int wqs;
- wqs = ring->size - (ring->prod - ring->cons);
- return (wqs < (HEADROOM + (2 * MLX4_EN_TX_WQE_MAX_WQEBBS)));
-}
-
-static int mlx4_en_process_tx_cq(struct net_device *dev,
- struct mlx4_en_cq *cq)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_cq *mcq = &cq->mcq;
- struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
- struct mlx4_cqe *cqe;
- u16 index;
- u16 new_index, ring_index, stamp_index;
- u32 txbbs_skipped = 0;
- u32 txbbs_stamp = 0;
- u32 cons_index = mcq->cons_index;
- int size = cq->size;
- u32 size_mask = ring->size_mask;
- struct mlx4_cqe *buf = cq->buf;
- int factor = priv->cqe_factor;
-
- if (!priv->port_up)
- return 0;
-
- index = cons_index & size_mask;
- cqe = &buf[(index << factor) + factor];
- ring_index = ring->cons & size_mask;
- stamp_index = ring_index;
-
- /* Process all completed CQEs */
- while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
- cons_index & size)) {
- /*
- * make sure we read the CQE after we read the
- * ownership bit
- */
- rmb();
-
- if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
- MLX4_CQE_OPCODE_ERROR)) {
- en_err(priv, "CQE completed in error - vendor syndrom: 0x%x syndrom: 0x%x\n",
- ((struct mlx4_err_cqe *)cqe)->
- vendor_err_syndrome,
- ((struct mlx4_err_cqe *)cqe)->syndrome);
- }
-
- /* Skip over last polled CQE */
- new_index = be16_to_cpu(cqe->wqe_index) & size_mask;
-
- do {
- txbbs_skipped += ring->last_nr_txbb;
- ring_index = (ring_index + ring->last_nr_txbb) & size_mask;
- /* free next descriptor */
- ring->last_nr_txbb = mlx4_en_free_tx_desc(
- priv, ring, ring_index);
- mlx4_en_stamp_wqe(priv, ring, stamp_index,
- !!((ring->cons + txbbs_stamp) &
- ring->size));
- stamp_index = ring_index;
- txbbs_stamp = txbbs_skipped;
- } while (ring_index != new_index);
-
- ++cons_index;
- index = cons_index & size_mask;
- cqe = &buf[(index << factor) + factor];
- }
-
-
- /*
- * To prevent CQ overflow we first update CQ consumer and only then
- * the ring consumer.
- */
- mcq->cons_index = cons_index;
- mlx4_cq_set_ci(mcq);
- wmb();
- ring->cons += txbbs_skipped;
-
- /* Wakeup Tx queue if it was stopped and ring is not full */
- if (unlikely(ring->blocked) && !mlx4_en_tx_ring_is_full(ring)) {
- ring->blocked = 0;
- if (atomic_fetchadd_int(&priv->blocked, -1) == 1)
- atomic_clear_int(&dev->if_drv_flags ,IFF_DRV_OACTIVE);
- ring->wake_queue++;
- priv->port_stats.wake_queue++;
- }
- return (0);
-}
-
-void mlx4_en_tx_irq(struct mlx4_cq *mcq)
-{
- struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq);
- struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
-
- if (priv->port_up == 0 || !spin_trylock(&ring->comp_lock))
- return;
- mlx4_en_process_tx_cq(cq->dev, cq);
- mod_timer(&cq->timer, jiffies + 1);
- spin_unlock(&ring->comp_lock);
-}
-
-void mlx4_en_poll_tx_cq(unsigned long data)
-{
- struct mlx4_en_cq *cq = (struct mlx4_en_cq *) data;
- struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
- u32 inflight;
-
- INC_PERF_COUNTER(priv->pstats.tx_poll);
-
- if (priv->port_up == 0)
- return;
- if (!spin_trylock(&ring->comp_lock)) {
- mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
- return;
- }
- mlx4_en_process_tx_cq(cq->dev, cq);
- inflight = (u32) (ring->prod - ring->cons - ring->last_nr_txbb);
-
- /* If there are still packets in flight and the timer has not already
- * been scheduled by the Tx routine then schedule it here to guarantee
- * completion processing of these packets */
- if (inflight && priv->port_up)
- mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
-
- spin_unlock(&ring->comp_lock);
-}
-
-static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
-{
- struct mlx4_en_cq *cq = priv->tx_cq[tx_ind];
- struct mlx4_en_tx_ring *ring = priv->tx_ring[tx_ind];
-
- if (priv->port_up == 0)
- return;
-
- /* If we don't have a pending timer, set one up to catch our recent
- post in case the interface becomes idle */
- if (!timer_pending(&cq->timer))
- mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
-
- /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */
- if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0)
- if (spin_trylock(&ring->comp_lock)) {
- mlx4_en_process_tx_cq(priv->dev, cq);
- spin_unlock(&ring->comp_lock);
- }
-}
-
-static u16
-mlx4_en_get_inline_hdr_size(struct mlx4_en_tx_ring *ring, struct mbuf *mb)
-{
- u16 retval;
-
- /* only copy from first fragment, if possible */
- retval = MIN(ring->inline_thold, mb->m_len);
-
- /* check for too little data */
- if (unlikely(retval < MIN_PKT_LEN))
- retval = MIN(ring->inline_thold, mb->m_pkthdr.len);
- return (retval);
-}
-
-static int
-mlx4_en_get_header_size(struct mbuf *mb)
-{
- struct ether_vlan_header *eh;
- struct tcphdr *th;
- struct ip *ip;
- int ip_hlen, tcp_hlen;
- struct ip6_hdr *ip6;
- uint16_t eth_type;
- int eth_hdr_len;
-
- eh = mtod(mb, struct ether_vlan_header *);
- if (mb->m_len < ETHER_HDR_LEN)
- return (0);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- eth_type = ntohs(eh->evl_proto);
- eth_hdr_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- } else {
- eth_type = ntohs(eh->evl_encap_proto);
- eth_hdr_len = ETHER_HDR_LEN;
- }
- if (mb->m_len < eth_hdr_len)
- return (0);
- switch (eth_type) {
- case ETHERTYPE_IP:
- ip = (struct ip *)(mb->m_data + eth_hdr_len);
- if (mb->m_len < eth_hdr_len + sizeof(*ip))
- return (0);
- if (ip->ip_p != IPPROTO_TCP)
- return (0);
- ip_hlen = ip->ip_hl << 2;
- eth_hdr_len += ip_hlen;
- break;
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mb->m_data + eth_hdr_len);
- if (mb->m_len < eth_hdr_len + sizeof(*ip6))
- return (0);
- if (ip6->ip6_nxt != IPPROTO_TCP)
- return (0);
- eth_hdr_len += sizeof(*ip6);
- break;
- default:
- return (0);
- }
- if (mb->m_len < eth_hdr_len + sizeof(*th))
- return (0);
- th = (struct tcphdr *)(mb->m_data + eth_hdr_len);
- tcp_hlen = th->th_off << 2;
- eth_hdr_len += tcp_hlen;
- if (mb->m_len < eth_hdr_len)
- return (0);
- return (eth_hdr_len);
-}
-
-static volatile struct mlx4_wqe_data_seg *
-mlx4_en_store_inline_data(volatile struct mlx4_wqe_data_seg *dseg,
- struct mbuf *mb, int len, __be32 owner_bit)
-{
- uint8_t *inl = __DEVOLATILE(uint8_t *, dseg);
- const int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - 4;
-
- if (unlikely(len < MIN_PKT_LEN)) {
- m_copydata(mb, 0, len, inl + 4);
- memset(inl + 4 + len, 0, MIN_PKT_LEN - len);
- dseg += DIV_ROUND_UP(4 + MIN_PKT_LEN, DS_SIZE_ALIGNMENT);
- } else if (len <= spc) {
- m_copydata(mb, 0, len, inl + 4);
- dseg += DIV_ROUND_UP(4 + len, DS_SIZE_ALIGNMENT);
- } else {
- m_copydata(mb, 0, spc, inl + 4);
- m_copydata(mb, spc, len - spc, inl + 8 + spc);
- dseg += DIV_ROUND_UP(8 + len, DS_SIZE_ALIGNMENT);
- }
- return (dseg);
-}
-
-static void
-mlx4_en_store_inline_header(volatile struct mlx4_wqe_data_seg *dseg,
- int len, __be32 owner_bit)
-{
- uint8_t *inl = __DEVOLATILE(uint8_t *, dseg);
- const int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - 4;
-
- if (unlikely(len < MIN_PKT_LEN)) {
- *(volatile uint32_t *)inl =
- SET_BYTE_COUNT((1 << 31) | MIN_PKT_LEN);
- } else if (len <= spc) {
- *(volatile uint32_t *)inl =
- SET_BYTE_COUNT((1 << 31) | len);
- } else {
- *(volatile uint32_t *)(inl + 4 + spc) =
- SET_BYTE_COUNT((1 << 31) | (len - spc));
- wmb();
- *(volatile uint32_t *)inl =
- SET_BYTE_COUNT((1 << 31) | spc);
- }
-}
-
-static uint32_t hashrandom;
-static void hashrandom_init(void *arg)
-{
- /*
- * It is assumed that the random subsystem has been
- * initialized when this function is called:
- */
- hashrandom = m_ether_tcpip_hash_init();
-}
-SYSINIT(hashrandom_init, SI_SUB_RANDOM, SI_ORDER_ANY, &hashrandom_init, NULL);
-
-u16 mlx4_en_select_queue(struct net_device *dev, struct mbuf *mb)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- u32 rings_p_up = priv->num_tx_rings_p_up;
- u32 up = 0;
- u32 queue_index;
-
-#if (MLX4_EN_NUM_UP > 1)
- /* Obtain VLAN information if present */
- if (mb->m_flags & M_VLANTAG) {
- u32 vlan_tag = mb->m_pkthdr.ether_vtag;
- up = (vlan_tag >> 13) % MLX4_EN_NUM_UP;
- }
-#endif
- queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom);
-
- return ((queue_index % rings_p_up) + (up * rings_p_up));
-}
-
-static void mlx4_bf_copy(void __iomem *dst, volatile unsigned long *src, unsigned bytecnt)
-{
- __iowrite64_copy(dst, __DEVOLATILE(void *, src), bytecnt / 8);
-}
-
-static u64 mlx4_en_mac_to_u64(u8 *addr)
-{
- u64 mac = 0;
- int i;
-
- for (i = 0; i < ETHER_ADDR_LEN; i++) {
- mac <<= 8;
- mac |= addr[i];
- }
- return mac;
-}
-
-static int mlx4_en_xmit(struct mlx4_en_priv *priv, int tx_ind, struct mbuf **mbp)
-{
- enum {
- DS_FACT = TXBB_SIZE / DS_SIZE_ALIGNMENT,
- CTRL_FLAGS = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
- MLX4_WQE_CTRL_SOLICITED),
- };
- bus_dma_segment_t segs[MLX4_EN_TX_MAX_MBUF_FRAGS];
- volatile struct mlx4_wqe_data_seg *dseg;
- volatile struct mlx4_wqe_data_seg *dseg_inline;
- volatile struct mlx4_en_tx_desc *tx_desc;
- struct mlx4_en_tx_ring *ring = priv->tx_ring[tx_ind];
- struct ifnet *ifp = priv->dev;
- struct mlx4_en_tx_info *tx_info;
- struct mbuf *mb = *mbp;
- struct mbuf *m;
- __be32 owner_bit;
- int nr_segs;
- int pad;
- int err;
- u32 bf_size;
- u32 bf_prod;
- u32 opcode;
- u16 index;
- u16 ds_cnt;
- u16 ihs;
-
- if (unlikely(!priv->port_up)) {
- err = EINVAL;
- goto tx_drop;
- }
-
- /* check if TX ring is full */
- if (unlikely(mlx4_en_tx_ring_is_full(ring))) {
- /* every full native Tx ring stops queue */
- if (ring->blocked == 0)
- atomic_add_int(&priv->blocked, 1);
- /* Set HW-queue-is-full flag */
- atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
- priv->port_stats.queue_stopped++;
- ring->blocked = 1;
- priv->port_stats.queue_stopped++;
- ring->queue_stopped++;
-
- /* Use interrupts to find out when queue opened */
- mlx4_en_arm_cq(priv, priv->tx_cq[tx_ind]);
- return (ENOBUFS);
- }
-
- /* sanity check we are not wrapping around */
- KASSERT(((~ring->prod) & ring->size_mask) >=
- (MLX4_EN_TX_WQE_MAX_WQEBBS - 1), ("Wrapping around TX ring"));
-
- /* Track current inflight packets for performance analysis */
- AVG_PERF_COUNTER(priv->pstats.inflight_avg,
- (u32) (ring->prod - ring->cons - 1));
-
- /* Track current mbuf packet header length */
- AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, mb->m_pkthdr.len);
-
- /* Grab an index and try to transmit packet */
- owner_bit = (ring->prod & ring->size) ?
- cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0;
- index = ring->prod & ring->size_mask;
- tx_desc = (volatile struct mlx4_en_tx_desc *)
- (ring->buf + index * TXBB_SIZE);
- tx_info = &ring->tx_info[index];
- dseg = &tx_desc->data;
-
- /* send a copy of the frame to the BPF listener, if any */
- if (ifp != NULL && ifp->if_bpf != NULL)
- ETHER_BPF_MTAP(ifp, mb);
-
- /* get default flags */
- tx_desc->ctrl.srcrb_flags = CTRL_FLAGS;
-
- if (mb->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TSO))
- tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM);
-
- if (mb->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP |
- CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO))
- tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_TCP_UDP_CSUM);
-
- /* do statistics */
- if (likely(tx_desc->ctrl.srcrb_flags != CTRL_FLAGS)) {
- priv->port_stats.tx_chksum_offload++;
- ring->tx_csum++;
- }
-
- /* check for VLAN tag */
- if (mb->m_flags & M_VLANTAG) {
- tx_desc->ctrl.vlan_tag = cpu_to_be16(mb->m_pkthdr.ether_vtag);
- tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN;
- } else {
- tx_desc->ctrl.vlan_tag = 0;
- tx_desc->ctrl.ins_vlan = 0;
- }
-
- /* clear immediate field */
- tx_desc->ctrl.imm = 0;
-
- /* Handle LSO (TSO) packets */
- if (mb->m_pkthdr.csum_flags & CSUM_TSO) {
- u32 payload_len;
- u32 mss = mb->m_pkthdr.tso_segsz;
- u32 num_pkts;
-
- opcode = cpu_to_be32(MLX4_OPCODE_LSO | MLX4_WQE_CTRL_RR) |
- owner_bit;
- ihs = mlx4_en_get_header_size(mb);
- if (unlikely(ihs > MAX_INLINE)) {
- ring->oversized_packets++;
- err = EINVAL;
- goto tx_drop;
- }
- tx_desc->lso.mss_hdr_size = cpu_to_be32((mss << 16) | ihs);
- payload_len = mb->m_pkthdr.len - ihs;
- if (unlikely(payload_len == 0))
- num_pkts = 1;
- else
- num_pkts = DIV_ROUND_UP(payload_len, mss);
- ring->bytes += payload_len + (num_pkts * ihs);
- ring->packets += num_pkts;
- priv->port_stats.tso_packets++;
- /* store pointer to inline header */
- dseg_inline = dseg;
- /* copy data inline */
- dseg = mlx4_en_store_inline_lso_data(dseg,
- mb, ihs, owner_bit);
- } else {
- opcode = cpu_to_be32(MLX4_OPCODE_SEND) |
- owner_bit;
- ihs = mlx4_en_get_inline_hdr_size(ring, mb);
- ring->bytes += max_t (unsigned int,
- mb->m_pkthdr.len, ETHER_MIN_LEN - ETHER_CRC_LEN);
- ring->packets++;
- /* store pointer to inline header */
- dseg_inline = dseg;
- /* copy data inline */
- dseg = mlx4_en_store_inline_data(dseg,
- mb, ihs, owner_bit);
- }
- m_adj(mb, ihs);
-
- /* trim off empty mbufs */
- while (mb->m_len == 0) {
- mb = m_free(mb);
- /* check if all data has been inlined */
- if (mb == NULL) {
- nr_segs = 0;
- goto skip_dma;
- }
- }
-
- err = bus_dmamap_load_mbuf_sg(ring->dma_tag, tx_info->dma_map,
- mb, segs, &nr_segs, BUS_DMA_NOWAIT);
- if (unlikely(err == EFBIG)) {
- /* Too many mbuf fragments */
- m = m_defrag(mb, M_NOWAIT);
- if (m == NULL) {
- ring->oversized_packets++;
- goto tx_drop;
- }
- mb = m;
- /* Try again */
- err = bus_dmamap_load_mbuf_sg(ring->dma_tag, tx_info->dma_map,
- mb, segs, &nr_segs, BUS_DMA_NOWAIT);
- }
- /* catch errors */
- if (unlikely(err != 0)) {
- ring->oversized_packets++;
- goto tx_drop;
- }
- /* make sure all mbuf data is written to RAM */
- bus_dmamap_sync(ring->dma_tag, tx_info->dma_map,
- BUS_DMASYNC_PREWRITE);
-
-skip_dma:
- /* compute number of DS needed */
- ds_cnt = (dseg - ((volatile struct mlx4_wqe_data_seg *)tx_desc)) + nr_segs;
-
- /*
- * Check if the next request can wrap around and fill the end
- * of the current request with zero immediate data:
- */
- pad = DIV_ROUND_UP(ds_cnt, DS_FACT);
- pad = (~(ring->prod + pad)) & ring->size_mask;
-
- if (unlikely(pad < (MLX4_EN_TX_WQE_MAX_WQEBBS - 1))) {
- /*
- * Compute the least number of DS blocks we need to
- * pad in order to achieve a TX ring wraparound:
- */
- pad = (DS_FACT * (pad + 1));
- } else {
- /*
- * The hardware will automatically jump to the next
- * TXBB. No need for padding.
- */
- pad = 0;
- }
-
- /* compute total number of DS blocks */
- ds_cnt += pad;
- /*
- * When modifying this code, please ensure that the following
- * computation is always less than or equal to 0x3F:
- *
- * ((MLX4_EN_TX_WQE_MAX_WQEBBS - 1) * DS_FACT) +
- * (MLX4_EN_TX_WQE_MAX_WQEBBS * DS_FACT)
- *
- * Else the "ds_cnt" variable can become too big.
- */
- tx_desc->ctrl.fence_size = (ds_cnt & 0x3f);
-
- /* store pointer to mbuf */
- tx_info->mb = mb;
- tx_info->nr_txbb = DIV_ROUND_UP(ds_cnt, DS_FACT);
- bf_size = ds_cnt * DS_SIZE_ALIGNMENT;
- bf_prod = ring->prod;
-
- /* compute end of "dseg" array */
- dseg += nr_segs + pad;
-
- /* pad using zero immediate dseg */
- while (pad--) {
- dseg--;
- dseg->addr = 0;
- dseg->lkey = 0;
- wmb();
- dseg->byte_count = SET_BYTE_COUNT((1 << 31)|0);
- }
-
- /* fill segment list */
- while (nr_segs--) {
- if (unlikely(segs[nr_segs].ds_len == 0)) {
- dseg--;
- dseg->addr = 0;
- dseg->lkey = 0;
- wmb();
- dseg->byte_count = SET_BYTE_COUNT((1 << 31)|0);
- } else {
- dseg--;
- dseg->addr = cpu_to_be64((uint64_t)segs[nr_segs].ds_addr);
- dseg->lkey = cpu_to_be32(priv->mdev->mr.key);
- wmb();
- dseg->byte_count = SET_BYTE_COUNT((uint32_t)segs[nr_segs].ds_len);
- }
- }
-
- wmb();
-
- /* write owner bits in reverse order */
- if ((opcode & cpu_to_be32(0x1F)) == cpu_to_be32(MLX4_OPCODE_LSO))
- mlx4_en_store_inline_lso_header(dseg_inline, ihs, owner_bit);
- else
- mlx4_en_store_inline_header(dseg_inline, ihs, owner_bit);
-
- if (unlikely(priv->validate_loopback)) {
- /* Copy dst mac address to wqe */
- struct ether_header *ethh;
- u64 mac;
- u32 mac_l, mac_h;
-
- ethh = mtod(mb, struct ether_header *);
- mac = mlx4_en_mac_to_u64(ethh->ether_dhost);
- if (mac) {
- mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
- mac_l = (u32) (mac & 0xffffffff);
- tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
- tx_desc->ctrl.imm = cpu_to_be32(mac_l);
- }
- }
-
- /* update producer counter */
- ring->prod += tx_info->nr_txbb;
-
- if (ring->bf_enabled && bf_size <= MAX_BF &&
- (tx_desc->ctrl.ins_vlan != MLX4_WQE_CTRL_INS_VLAN)) {
-
- /* store doorbell number */
- *(volatile __be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);
-
- /* or in producer number for this WQE */
- opcode |= cpu_to_be32((bf_prod & 0xffff) << 8);
-
- /*
- * Ensure the new descriptor hits memory before
- * setting ownership of this descriptor to HW:
- */
- wmb();
- tx_desc->ctrl.owner_opcode = opcode;
- wmb();
- mlx4_bf_copy(((u8 *)ring->bf.reg) + ring->bf.offset,
- (volatile unsigned long *) &tx_desc->ctrl, bf_size);
- wmb();
- ring->bf.offset ^= ring->bf.buf_size;
- } else {
- /*
- * Ensure the new descriptor hits memory before
- * setting ownership of this descriptor to HW:
- */
- wmb();
- tx_desc->ctrl.owner_opcode = opcode;
- wmb();
- writel(cpu_to_be32(ring->doorbell_qpn),
- ((u8 *)ring->bf.uar->map) + MLX4_SEND_DOORBELL);
- }
-
- return (0);
-tx_drop:
- *mbp = NULL;
- m_freem(mb);
- return (err);
-}
-
-static int
-mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_tx_ring *ring;
- struct mbuf *next;
- int enqueued, err = 0;
-
- ring = priv->tx_ring[tx_ind];
- if ((dev->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING || priv->port_up == 0) {
- if (m != NULL)
- err = drbr_enqueue(dev, ring->br, m);
- return (err);
- }
-
- enqueued = 0;
- if (m != NULL)
- /*
- * If we can't insert mbuf into drbr, try to xmit anyway.
- * We keep the error we got so we could return that after xmit.
- */
- err = drbr_enqueue(dev, ring->br, m);
-
- /* Process the queue */
- while ((next = drbr_peek(dev, ring->br)) != NULL) {
- if (mlx4_en_xmit(priv, tx_ind, &next) != 0) {
- if (next == NULL) {
- drbr_advance(dev, ring->br);
- } else {
- drbr_putback(dev, ring->br, next);
- }
- break;
- }
- drbr_advance(dev, ring->br);
- enqueued++;
- if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0)
- break;
- }
-
- if (enqueued > 0)
- ring->watchdog_time = ticks;
-
- return (err);
-}
-
-void
-mlx4_en_tx_que(void *context, int pending)
-{
- struct mlx4_en_tx_ring *ring;
- struct mlx4_en_priv *priv;
- struct net_device *dev;
- struct mlx4_en_cq *cq;
- int tx_ind;
- cq = context;
- dev = cq->dev;
- priv = dev->if_softc;
- tx_ind = cq->ring;
- ring = priv->tx_ring[tx_ind];
-
- if (priv->port_up != 0 &&
- (dev->if_drv_flags & IFF_DRV_RUNNING) != 0) {
- mlx4_en_xmit_poll(priv, tx_ind);
- spin_lock(&ring->tx_lock);
- if (!drbr_empty(dev, ring->br))
- mlx4_en_transmit_locked(dev, tx_ind, NULL);
- spin_unlock(&ring->tx_lock);
- }
-}
-
-int
-mlx4_en_transmit(struct ifnet *dev, struct mbuf *m)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_tx_ring *ring;
- struct mlx4_en_cq *cq;
- int i, err = 0;
-
- if (priv->port_up == 0) {
- m_freem(m);
- return (ENETDOWN);
- }
-
- /* Compute which queue to use */
- if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
- i = (m->m_pkthdr.flowid % 128) % priv->tx_ring_num;
- }
- else {
- i = mlx4_en_select_queue(dev, m);
- }
-
- ring = priv->tx_ring[i];
- if (spin_trylock(&ring->tx_lock)) {
- err = mlx4_en_transmit_locked(dev, i, m);
- spin_unlock(&ring->tx_lock);
- /* Poll CQ here */
- mlx4_en_xmit_poll(priv, i);
- } else {
- err = drbr_enqueue(dev, ring->br, m);
- cq = priv->tx_cq[i];
- taskqueue_enqueue(cq->tq, &cq->cq_task);
- }
-
- return (err);
-}
-
-/*
- * Flush ring buffers.
- */
-void
-mlx4_en_qflush(struct ifnet *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_tx_ring *ring;
- struct mbuf *m;
-
- if (priv->port_up == 0)
- return;
-
- for (int i = 0; i < priv->tx_ring_num; i++) {
- ring = priv->tx_ring[i];
- spin_lock(&ring->tx_lock);
- while ((m = buf_ring_dequeue_sc(ring->br)) != NULL)
- m_freem(m);
- spin_unlock(&ring->tx_lock);
- }
- if_qflush(dev);
-}
diff --git a/sys/ofed/drivers/net/mlx4/eq.c b/sys/ofed/drivers/net/mlx4/eq.c
deleted file mode 100644
index 145b9bc55909..000000000000
--- a/sys/ofed/drivers/net/mlx4/eq.c
+++ /dev/null
@@ -1,1406 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/dma-mapping.h>
-
-#include <linux/mlx4/cmd.h>
-
-#include "mlx4.h"
-#include "fw.h"
-
-enum {
- MLX4_IRQNAME_SIZE = 32
-};
-
-enum {
- MLX4_NUM_ASYNC_EQE = 0x100,
- MLX4_NUM_SPARE_EQE = 0x80,
- MLX4_EQ_ENTRY_SIZE = 0x20
-};
-
-#define MLX4_EQ_STATUS_OK ( 0 << 28)
-#define MLX4_EQ_STATUS_WRITE_FAIL (10 << 28)
-#define MLX4_EQ_OWNER_SW ( 0 << 24)
-#define MLX4_EQ_OWNER_HW ( 1 << 24)
-#define MLX4_EQ_FLAG_EC ( 1 << 18)
-#define MLX4_EQ_FLAG_OI ( 1 << 17)
-#define MLX4_EQ_STATE_ARMED ( 9 << 8)
-#define MLX4_EQ_STATE_FIRED (10 << 8)
-#define MLX4_EQ_STATE_ALWAYS_ARMED (11 << 8)
-
-#define MLX4_ASYNC_EVENT_MASK ((1ull << MLX4_EVENT_TYPE_PATH_MIG) | \
- (1ull << MLX4_EVENT_TYPE_COMM_EST) | \
- (1ull << MLX4_EVENT_TYPE_SQ_DRAINED) | \
- (1ull << MLX4_EVENT_TYPE_CQ_ERROR) | \
- (1ull << MLX4_EVENT_TYPE_WQ_CATAS_ERROR) | \
- (1ull << MLX4_EVENT_TYPE_EEC_CATAS_ERROR) | \
- (1ull << MLX4_EVENT_TYPE_PATH_MIG_FAILED) | \
- (1ull << MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \
- (1ull << MLX4_EVENT_TYPE_WQ_ACCESS_ERROR) | \
- (1ull << MLX4_EVENT_TYPE_PORT_CHANGE) | \
- (1ull << MLX4_EVENT_TYPE_ECC_DETECT) | \
- (1ull << MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) | \
- (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \
- (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \
- (1ull << MLX4_EVENT_TYPE_CMD) | \
- (1ull << MLX4_EVENT_TYPE_OP_REQUIRED) | \
- (1ull << MLX4_EVENT_TYPE_COMM_CHANNEL) | \
- (1ull << MLX4_EVENT_TYPE_FLR_EVENT) | \
- (1ull << MLX4_EVENT_TYPE_FATAL_WARNING))
-
-static u64 get_async_ev_mask(struct mlx4_dev *dev)
-{
- u64 async_ev_mask = MLX4_ASYNC_EVENT_MASK;
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV)
- async_ev_mask |= (1ull << MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT);
- if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT)
- async_ev_mask |= (1ull << MLX4_EVENT_TYPE_RECOVERABLE_ERROR_EVENT);
-
- return async_ev_mask;
-}
-
-static void eq_set_ci(struct mlx4_eq *eq, int req_not)
-{
- __raw_writel((__force u32) cpu_to_be32((eq->cons_index & 0xffffff) |
- req_not << 31),
- eq->doorbell);
- /* We still want ordering, just not swabbing, so add a barrier */
- mb();
-}
-
-static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor)
-{
- /* (entry & (eq->nent - 1)) gives us a cyclic array */
- unsigned long offset = (entry & (eq->nent - 1)) * (MLX4_EQ_ENTRY_SIZE << eqe_factor);
- /* CX3 is capable of extending the EQE from 32 to 64 bytes.
- * When this feature is enabled, the first (in the lower addresses)
- * 32 bytes in the 64 byte EQE are reserved and the next 32 bytes
- * contain the legacy EQE information.
- */
- return eq->page_list[offset / PAGE_SIZE].buf + (offset + (eqe_factor ? MLX4_EQ_ENTRY_SIZE : 0)) % PAGE_SIZE;
-}
-
-static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq, u8 eqe_factor)
-{
- struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index, eqe_factor);
- return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe;
-}
-
-static struct mlx4_eqe *next_slave_event_eqe(struct mlx4_slave_event_eq *slave_eq)
-{
- struct mlx4_eqe *eqe =
- &slave_eq->event_eqe[slave_eq->cons & (SLAVE_EVENT_EQ_SIZE - 1)];
- return (!!(eqe->owner & 0x80) ^
- !!(slave_eq->cons & SLAVE_EVENT_EQ_SIZE)) ?
- eqe : NULL;
-}
-
-void mlx4_gen_slave_eqe(struct work_struct *work)
-{
- struct mlx4_mfunc_master_ctx *master =
- container_of(work, struct mlx4_mfunc_master_ctx,
- slave_event_work);
- struct mlx4_mfunc *mfunc =
- container_of(master, struct mlx4_mfunc, master);
- struct mlx4_priv *priv = container_of(mfunc, struct mlx4_priv, mfunc);
- struct mlx4_dev *dev = &priv->dev;
- struct mlx4_slave_event_eq *slave_eq = &mfunc->master.slave_eq;
- struct mlx4_eqe *eqe;
- u8 slave;
- int i;
-
- for (eqe = next_slave_event_eqe(slave_eq); eqe;
- eqe = next_slave_event_eqe(slave_eq)) {
- slave = eqe->slave_id;
-
- /* All active slaves need to receive the event */
- if (slave == ALL_SLAVES) {
- for (i = 0; i < dev->num_slaves; i++) {
- if (mlx4_GEN_EQE(dev, i, eqe))
- mlx4_warn(dev, "Failed to generate "
- "event for slave %d\n", i);
- }
- } else {
- if (mlx4_GEN_EQE(dev, slave, eqe))
- mlx4_warn(dev, "Failed to generate event "
- "for slave %d\n", slave);
- }
- ++slave_eq->cons;
- }
-}
-
-
-static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_event_eq *slave_eq = &priv->mfunc.master.slave_eq;
- struct mlx4_eqe *s_eqe;
- unsigned long flags;
-
- spin_lock_irqsave(&slave_eq->event_lock, flags);
- s_eqe = &slave_eq->event_eqe[slave_eq->prod & (SLAVE_EVENT_EQ_SIZE - 1)];
- if ((!!(s_eqe->owner & 0x80)) ^
- (!!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE))) {
- mlx4_warn(dev, "Master failed to generate an EQE for slave: %d. "
- "No free EQE on slave events queue\n", slave);
- spin_unlock_irqrestore(&slave_eq->event_lock, flags);
- return;
- }
-
- memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
- s_eqe->slave_id = slave;
- /* ensure all information is written before setting the ownersip bit */
- wmb();
- s_eqe->owner = !!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE) ? 0x0 : 0x80;
- ++slave_eq->prod;
-
- queue_work(priv->mfunc.master.comm_wq,
- &priv->mfunc.master.slave_event_work);
- spin_unlock_irqrestore(&slave_eq->event_lock, flags);
-}
-
-static void mlx4_slave_event(struct mlx4_dev *dev, int slave,
- struct mlx4_eqe *eqe)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- if (slave < 0 || slave >= dev->num_slaves ||
- slave == dev->caps.function)
- return;
-
- if (!priv->mfunc.master.slave_state[slave].active)
- return;
-
- slave_event(dev, slave, eqe);
-}
-
-int mlx4_gen_pkey_eqe(struct mlx4_dev *dev, int slave, u8 port)
-{
- struct mlx4_eqe eqe;
-
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *s_slave = &priv->mfunc.master.slave_state[slave];
-
- if (!s_slave->active)
- return 0;
-
- memset(&eqe, 0, sizeof eqe);
-
- eqe.type = MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT;
- eqe.subtype = MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE;
- eqe.event.port_mgmt_change.port = port;
-
- return mlx4_GEN_EQE(dev, slave, &eqe);
-}
-EXPORT_SYMBOL(mlx4_gen_pkey_eqe);
-
-int mlx4_gen_guid_change_eqe(struct mlx4_dev *dev, int slave, u8 port)
-{
- struct mlx4_eqe eqe;
-
- /*don't send if we don't have the that slave */
- if (dev->num_vfs < slave)
- return 0;
- memset(&eqe, 0, sizeof eqe);
-
- eqe.type = MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT;
- eqe.subtype = MLX4_DEV_PMC_SUBTYPE_GUID_INFO;
- eqe.event.port_mgmt_change.port = port;
-
- return mlx4_GEN_EQE(dev, slave, &eqe);
-}
-EXPORT_SYMBOL(mlx4_gen_guid_change_eqe);
-
-int mlx4_gen_port_state_change_eqe(struct mlx4_dev *dev, int slave, u8 port,
- u8 port_subtype_change)
-{
- struct mlx4_eqe eqe;
-
- /*don't send if we don't have the that slave */
- if (dev->num_vfs < slave)
- return 0;
- memset(&eqe, 0, sizeof eqe);
-
- eqe.type = MLX4_EVENT_TYPE_PORT_CHANGE;
- eqe.subtype = port_subtype_change;
- eqe.event.port_change.port = cpu_to_be32(port << 28);
-
- mlx4_dbg(dev, "%s: sending: %d to slave: %d on port: %d\n", __func__,
- port_subtype_change, slave, port);
- return mlx4_GEN_EQE(dev, slave, &eqe);
-}
-EXPORT_SYMBOL(mlx4_gen_port_state_change_eqe);
-
-enum slave_port_state mlx4_get_slave_port_state(struct mlx4_dev *dev, int slave, u8 port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *s_state = priv->mfunc.master.slave_state;
- if (slave >= dev->num_slaves || port > MLX4_MAX_PORTS) {
- pr_err("%s: Error: asking for slave:%d, port:%d\n",
- __func__, slave, port);
- return SLAVE_PORT_DOWN;
- }
- return s_state[slave].port_state[port];
-}
-EXPORT_SYMBOL(mlx4_get_slave_port_state);
-
-static int mlx4_set_slave_port_state(struct mlx4_dev *dev, int slave, u8 port,
- enum slave_port_state state)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *s_state = priv->mfunc.master.slave_state;
-
- if (slave >= dev->num_slaves || port > MLX4_MAX_PORTS || port == 0) {
- pr_err("%s: Error: asking for slave:%d, port:%d\n",
- __func__, slave, port);
- return -1;
- }
- s_state[slave].port_state[port] = state;
-
- return 0;
-}
-
-static void set_all_slave_state(struct mlx4_dev *dev, u8 port, int event)
-{
- int i;
- enum slave_port_gen_event gen_event;
-
- for (i = 0; i < dev->num_slaves; i++)
- set_and_calc_slave_port_state(dev, i, port, event, &gen_event);
-}
-/**************************************************************************
- The function get as input the new event to that port,
- and according to the prev state change the slave's port state.
- The events are:
- MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN,
- MLX4_PORT_STATE_DEV_EVENT_PORT_UP
- MLX4_PORT_STATE_IB_EVENT_GID_VALID
- MLX4_PORT_STATE_IB_EVENT_GID_INVALID
-***************************************************************************/
-int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
- u8 port, int event,
- enum slave_port_gen_event *gen_event)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *ctx = NULL;
- unsigned long flags;
- int ret = -1;
- enum slave_port_state cur_state =
- mlx4_get_slave_port_state(dev, slave, port);
-
- *gen_event = SLAVE_PORT_GEN_EVENT_NONE;
-
- if (slave >= dev->num_slaves || port > MLX4_MAX_PORTS || port == 0) {
- pr_err("%s: Error: asking for slave:%d, port:%d\n",
- __func__, slave, port);
- return ret;
- }
-
- ctx = &priv->mfunc.master.slave_state[slave];
- spin_lock_irqsave(&ctx->lock, flags);
-
- switch (cur_state) {
- case SLAVE_PORT_DOWN:
- if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event)
- mlx4_set_slave_port_state(dev, slave, port,
- SLAVE_PENDING_UP);
- break;
- case SLAVE_PENDING_UP:
- if (MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN == event)
- mlx4_set_slave_port_state(dev, slave, port,
- SLAVE_PORT_DOWN);
- else if (MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID == event) {
- mlx4_set_slave_port_state(dev, slave, port,
- SLAVE_PORT_UP);
- *gen_event = SLAVE_PORT_GEN_EVENT_UP;
- }
- break;
- case SLAVE_PORT_UP:
- if (MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN == event) {
- mlx4_set_slave_port_state(dev, slave, port,
- SLAVE_PORT_DOWN);
- *gen_event = SLAVE_PORT_GEN_EVENT_DOWN;
- } else if (MLX4_PORT_STATE_IB_EVENT_GID_INVALID ==
- event) {
- mlx4_set_slave_port_state(dev, slave, port,
- SLAVE_PENDING_UP);
- *gen_event = SLAVE_PORT_GEN_EVENT_DOWN;
- }
- break;
- default:
- pr_err("%s: BUG!!! UNKNOWN state: "
- "slave:%d, port:%d\n", __func__, slave, port);
- goto out;
- }
- ret = mlx4_get_slave_port_state(dev, slave, port);
-
-out:
- spin_unlock_irqrestore(&ctx->lock, flags);
- return ret;
-}
-
-EXPORT_SYMBOL(set_and_calc_slave_port_state);
-
-int mlx4_gen_slaves_port_mgt_ev(struct mlx4_dev *dev, u8 port, int attr, u16 sm_lid, u8 sm_sl)
-{
- struct mlx4_eqe eqe;
-
- memset(&eqe, 0, sizeof eqe);
-
- eqe.type = MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT;
- eqe.subtype = MLX4_DEV_PMC_SUBTYPE_PORT_INFO;
- eqe.event.port_mgmt_change.port = port;
- eqe.event.port_mgmt_change.params.port_info.changed_attr =
- cpu_to_be32((u32) attr);
- if (attr & MSTR_SM_CHANGE_MASK) {
- eqe.event.port_mgmt_change.params.port_info.mstr_sm_lid =
- cpu_to_be16(sm_lid);
- eqe.event.port_mgmt_change.params.port_info.mstr_sm_sl =
- sm_sl;
- }
-
- slave_event(dev, ALL_SLAVES, &eqe);
- return 0;
-}
-EXPORT_SYMBOL(mlx4_gen_slaves_port_mgt_ev);
-
-void mlx4_master_handle_slave_flr(struct work_struct *work)
-{
- struct mlx4_mfunc_master_ctx *master =
- container_of(work, struct mlx4_mfunc_master_ctx,
- slave_flr_event_work);
- struct mlx4_mfunc *mfunc =
- container_of(master, struct mlx4_mfunc, master);
- struct mlx4_priv *priv =
- container_of(mfunc, struct mlx4_priv, mfunc);
- struct mlx4_dev *dev = &priv->dev;
- struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
- int i;
- int err;
- unsigned long flags;
-
- mlx4_dbg(dev, "mlx4_handle_slave_flr\n");
-
- for (i = 0 ; i < dev->num_slaves; i++) {
-
- if (MLX4_COMM_CMD_FLR == slave_state[i].last_cmd) {
- mlx4_dbg(dev, "mlx4_handle_slave_flr: "
- "clean slave: %d\n", i);
-
- mlx4_delete_all_resources_for_slave(dev, i);
- /*return the slave to running mode*/
- spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
- slave_state[i].last_cmd = MLX4_COMM_CMD_RESET;
- slave_state[i].is_slave_going_down = 0;
- spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
- /*notify the FW:*/
- err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err)
- mlx4_warn(dev, "Failed to notify FW on "
- "FLR done (slave:%d)\n", i);
- }
- }
-}
-
-static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_eqe *eqe;
- int cqn;
- int eqes_found = 0;
- int set_ci = 0;
- int port;
- int slave = 0;
- int ret;
- u32 flr_slave;
- u8 update_slave_state;
- int i;
- enum slave_port_gen_event gen_event;
- unsigned long flags;
- struct mlx4_vport_state *s_info;
-
- while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) {
- /*
- * Make sure we read EQ entry contents after we've
- * checked the ownership bit.
- */
- rmb();
-
- switch (eqe->type) {
- case MLX4_EVENT_TYPE_COMP:
- cqn = be32_to_cpu(eqe->event.comp.cqn) & 0xffffff;
- mlx4_cq_completion(dev, cqn);
- break;
-
- case MLX4_EVENT_TYPE_PATH_MIG:
- case MLX4_EVENT_TYPE_COMM_EST:
- case MLX4_EVENT_TYPE_SQ_DRAINED:
- case MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE:
- case MLX4_EVENT_TYPE_WQ_CATAS_ERROR:
- case MLX4_EVENT_TYPE_PATH_MIG_FAILED:
- case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
- case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR:
- mlx4_dbg(dev, "event %d arrived\n", eqe->type);
- if (mlx4_is_master(dev)) {
- /* forward only to slave owning the QP */
- ret = mlx4_get_slave_from_resource_id(dev,
- RES_QP,
- be32_to_cpu(eqe->event.qp.qpn)
- & 0xffffff, &slave);
- if (ret && ret != -ENOENT) {
- mlx4_dbg(dev, "QP event %02x(%02x) on "
- "EQ %d at index %u: could "
- "not get slave id (%d)\n",
- eqe->type, eqe->subtype,
- eq->eqn, eq->cons_index, ret);
- break;
- }
-
- if (!ret && slave != dev->caps.function) {
- mlx4_slave_event(dev, slave, eqe);
- break;
- }
-
- }
- mlx4_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) &
- 0xffffff, eqe->type);
- break;
-
- case MLX4_EVENT_TYPE_SRQ_LIMIT:
- mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
- __func__);
- /* fall through */
- case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
- if (mlx4_is_master(dev)) {
- /* forward only to slave owning the SRQ */
- ret = mlx4_get_slave_from_resource_id(dev,
- RES_SRQ,
- be32_to_cpu(eqe->event.srq.srqn)
- & 0xffffff,
- &slave);
- if (ret && ret != -ENOENT) {
- mlx4_warn(dev, "SRQ event %02x(%02x) "
- "on EQ %d at index %u: could"
- " not get slave id (%d)\n",
- eqe->type, eqe->subtype,
- eq->eqn, eq->cons_index, ret);
- break;
- }
- mlx4_dbg(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
- __func__, slave,
- be32_to_cpu(eqe->event.srq.srqn),
- eqe->type, eqe->subtype);
-
- if (!ret && slave != dev->caps.function) {
- mlx4_dbg(dev, "%s: sending event %02x(%02x) to slave:%d\n",
- __func__, eqe->type,
- eqe->subtype, slave);
- mlx4_slave_event(dev, slave, eqe);
- break;
- }
- }
- mlx4_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) &
- 0xffffff, eqe->type);
- break;
-
- case MLX4_EVENT_TYPE_CMD:
- mlx4_cmd_event(dev,
- be16_to_cpu(eqe->event.cmd.token),
- eqe->event.cmd.status,
- be64_to_cpu(eqe->event.cmd.out_param));
- break;
-
- case MLX4_EVENT_TYPE_PORT_CHANGE:
- port = be32_to_cpu(eqe->event.port_change.port) >> 28;
- if (eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_DOWN) {
- mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_DOWN,
- port);
- mlx4_priv(dev)->sense.do_sense_port[port] = 1;
- if (!mlx4_is_master(dev))
- break;
- for (i = 0; i < dev->num_slaves; i++) {
- if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) {
- if (i == mlx4_master_func_num(dev))
- continue;
- mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN"
- " to slave: %d, port:%d\n",
- __func__, i, port);
- s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
- if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state)
- mlx4_slave_event(dev, i, eqe);
- } else { /* IB port */
- set_and_calc_slave_port_state(dev, i, port,
- MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN,
- &gen_event);
- /*we can be in pending state, then do not send port_down event*/
- if (SLAVE_PORT_GEN_EVENT_DOWN == gen_event) {
- if (i == mlx4_master_func_num(dev))
- continue;
- mlx4_slave_event(dev, i, eqe);
- }
- }
- }
- } else {
- mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_UP, port);
-
- mlx4_priv(dev)->sense.do_sense_port[port] = 0;
-
- if (!mlx4_is_master(dev))
- break;
- if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
- for (i = 0; i < dev->num_slaves; i++) {
- if (i == mlx4_master_func_num(dev))
- continue;
- s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
- if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state)
- mlx4_slave_event(dev, i, eqe);
- }
- else /* IB port */
- /* port-up event will be sent to a slave when the
- * slave's alias-guid is set. This is done in alias_GUID.c
- */
- set_all_slave_state(dev, port, MLX4_DEV_EVENT_PORT_UP);
- }
- break;
-
- case MLX4_EVENT_TYPE_CQ_ERROR:
- mlx4_warn(dev, "CQ %s on CQN %06x\n",
- eqe->event.cq_err.syndrome == 1 ?
- "overrun" : "access violation",
- be32_to_cpu(eqe->event.cq_err.cqn) & 0xffffff);
- if (mlx4_is_master(dev)) {
- ret = mlx4_get_slave_from_resource_id(dev,
- RES_CQ,
- be32_to_cpu(eqe->event.cq_err.cqn)
- & 0xffffff, &slave);
- if (ret && ret != -ENOENT) {
- mlx4_dbg(dev, "CQ event %02x(%02x) on "
- "EQ %d at index %u: could "
- "not get slave id (%d)\n",
- eqe->type, eqe->subtype,
- eq->eqn, eq->cons_index, ret);
- break;
- }
-
- if (!ret && slave != dev->caps.function) {
- mlx4_slave_event(dev, slave, eqe);
- break;
- }
- }
- mlx4_cq_event(dev,
- be32_to_cpu(eqe->event.cq_err.cqn)
- & 0xffffff,
- eqe->type);
- break;
-
- case MLX4_EVENT_TYPE_EQ_OVERFLOW:
- mlx4_warn(dev, "EQ overrun on EQN %d\n", eq->eqn);
- break;
-
- case MLX4_EVENT_TYPE_OP_REQUIRED:
- atomic_inc(&priv->opreq_count);
- /* FW commands can't be executed from interrupt context
- working in deferred task */
- queue_work(mlx4_wq, &priv->opreq_task);
- break;
-
- case MLX4_EVENT_TYPE_COMM_CHANNEL:
- if (!mlx4_is_master(dev)) {
- mlx4_warn(dev, "Received comm channel event "
- "for non master device\n");
- break;
- }
-
- memcpy(&priv->mfunc.master.comm_arm_bit_vector,
- eqe->event.comm_channel_arm.bit_vec,
- sizeof eqe->event.comm_channel_arm.bit_vec);
-
- if (!queue_work(priv->mfunc.master.comm_wq,
- &priv->mfunc.master.comm_work))
- mlx4_warn(dev, "Failed to queue comm channel work\n");
-
- if (!queue_work(priv->mfunc.master.comm_wq,
- &priv->mfunc.master.arm_comm_work))
- mlx4_warn(dev, "Failed to queue arm comm channel work\n");
- break;
-
- case MLX4_EVENT_TYPE_FLR_EVENT:
- flr_slave = be32_to_cpu(eqe->event.flr_event.slave_id);
- if (!mlx4_is_master(dev)) {
- mlx4_warn(dev, "Non-master function received"
- "FLR event\n");
- break;
- }
-
- mlx4_dbg(dev, "FLR event for slave: %d\n", flr_slave);
-
- if (flr_slave >= dev->num_slaves) {
- mlx4_warn(dev,
- "Got FLR for unknown function: %d\n",
- flr_slave);
- update_slave_state = 0;
- } else
- update_slave_state = 1;
-
- spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
- if (update_slave_state) {
- priv->mfunc.master.slave_state[flr_slave].active = false;
- priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR;
- priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1;
- }
- spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
- queue_work(priv->mfunc.master.comm_wq,
- &priv->mfunc.master.slave_flr_event_work);
- break;
-
- case MLX4_EVENT_TYPE_FATAL_WARNING:
- if (eqe->subtype == MLX4_FATAL_WARNING_SUBTYPE_WARMING) {
- if (mlx4_is_master(dev))
- for (i = 0; i < dev->num_slaves; i++) {
- mlx4_dbg(dev, "%s: Sending "
- "MLX4_FATAL_WARNING_SUBTYPE_WARMING"
- " to slave: %d\n", __func__, i);
- if (i == dev->caps.function)
- continue;
- mlx4_slave_event(dev, i, eqe);
- }
- mlx4_err(dev, "Temperature Threshold was reached! "
- "Threshold: %d celsius degrees; "
- "Current Temperature: %d\n",
- be16_to_cpu(eqe->event.warming.warning_threshold),
- be16_to_cpu(eqe->event.warming.current_temperature));
- } else
- mlx4_warn(dev, "Unhandled event FATAL WARNING (%02x), "
- "subtype %02x on EQ %d at index %u. owner=%x, "
- "nent=0x%x, slave=%x, ownership=%s\n",
- eqe->type, eqe->subtype, eq->eqn,
- eq->cons_index, eqe->owner, eq->nent,
- eqe->slave_id,
- !!(eqe->owner & 0x80) ^
- !!(eq->cons_index & eq->nent) ? "HW" : "SW");
-
- break;
-
- case MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT:
- mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_MGMT_CHANGE,
- (unsigned long) eqe);
- break;
-
- case MLX4_EVENT_TYPE_RECOVERABLE_ERROR_EVENT:
- switch (eqe->subtype) {
- case MLX4_RECOVERABLE_ERROR_EVENT_SUBTYPE_BAD_CABLE:
- mlx4_warn(dev, "Bad cable detected on port %u\n",
- eqe->event.bad_cable.port);
- break;
- case MLX4_RECOVERABLE_ERROR_EVENT_SUBTYPE_UNSUPPORTED_CABLE:
- mlx4_warn(dev, "Unsupported cable detected\n");
- break;
- default:
- mlx4_dbg(dev, "Unhandled recoverable error event "
- "detected: %02x(%02x) on EQ %d at index %u. "
- "owner=%x, nent=0x%x, ownership=%s\n",
- eqe->type, eqe->subtype, eq->eqn,
- eq->cons_index, eqe->owner, eq->nent,
- !!(eqe->owner & 0x80) ^
- !!(eq->cons_index & eq->nent) ? "HW" : "SW");
- break;
- }
- break;
-
- case MLX4_EVENT_TYPE_EEC_CATAS_ERROR:
- case MLX4_EVENT_TYPE_ECC_DETECT:
- default:
- mlx4_warn(dev, "Unhandled event %02x(%02x) on EQ %d at "
- "index %u. owner=%x, nent=0x%x, slave=%x, "
- "ownership=%s\n",
- eqe->type, eqe->subtype, eq->eqn,
- eq->cons_index, eqe->owner, eq->nent,
- eqe->slave_id,
- !!(eqe->owner & 0x80) ^
- !!(eq->cons_index & eq->nent) ? "HW" : "SW");
- break;
- }
-
- ++eq->cons_index;
- eqes_found = 1;
- ++set_ci;
-
- /*
- * The HCA will think the queue has overflowed if we
- * don't tell it we've been processing events. We
- * create our EQs with MLX4_NUM_SPARE_EQE extra
- * entries, so we must update our consumer index at
- * least that often.
- */
- if (unlikely(set_ci >= MLX4_NUM_SPARE_EQE)) {
- eq_set_ci(eq, 0);
- set_ci = 0;
- }
- }
-
- eq_set_ci(eq, 1);
-
- return eqes_found;
-}
-
-static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr)
-{
- struct mlx4_dev *dev = dev_ptr;
- struct mlx4_priv *priv = mlx4_priv(dev);
- int work = 0;
- int i;
-
- writel(priv->eq_table.clr_mask, priv->eq_table.clr_int);
-
- for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
- work |= mlx4_eq_int(dev, &priv->eq_table.eq[i]);
-
- return IRQ_RETVAL(work);
-}
-
-static irqreturn_t mlx4_msi_x_interrupt(int irq, void *eq_ptr)
-{
- struct mlx4_eq *eq = eq_ptr;
- struct mlx4_dev *dev = eq->dev;
-
- mlx4_eq_int(dev, eq);
-
- /* MSI-X vectors always belong to us */
- return IRQ_HANDLED;
-}
-
-int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_event_eq_info *event_eq =
- priv->mfunc.master.slave_state[slave].event_eq;
- u32 in_modifier = vhcr->in_modifier;
- u32 eqn = in_modifier & 0x3FF;
- u64 in_param = vhcr->in_param;
- int err = 0;
- int i;
-
- if (slave == dev->caps.function)
- err = mlx4_cmd(dev, in_param, (in_modifier & 0x80000000) | eqn,
- 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_NATIVE);
- if (!err)
- for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i)
- if (in_param & (1LL << i))
- event_eq[i].eqn = in_modifier >> 31 ? -1 : eqn;
-
- return err;
-}
-
-static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap,
- int eq_num)
-{
- return mlx4_cmd(dev, event_mask, (unmap << 31) | eq_num,
- 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int eq_num)
-{
- return mlx4_cmd(dev, mailbox->dma, eq_num, 0,
- MLX4_CMD_SW2HW_EQ, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int eq_num)
-{
- return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num,
- 0, MLX4_CMD_HW2SW_EQ, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_num_eq_uar(struct mlx4_dev *dev)
-{
- /*
- * Each UAR holds 4 EQ doorbells. To figure out how many UARs
- * we need to map, take the difference of highest index and
- * the lowest index we'll use and add 1.
- */
- return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs +
- dev->caps.comp_pool)/4 - dev->caps.reserved_eqs/4 + 1;
-}
-
-static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int index;
-
- index = eq->eqn / 4 - dev->caps.reserved_eqs / 4;
-
- if (!priv->eq_table.uar_map[index]) {
- priv->eq_table.uar_map[index] =
- ioremap(pci_resource_start(dev->pdev, 2) +
- ((eq->eqn / 4) << PAGE_SHIFT),
- PAGE_SIZE);
- if (!priv->eq_table.uar_map[index]) {
- mlx4_err(dev, "Couldn't map EQ doorbell for EQN 0x%06x\n",
- eq->eqn);
- return NULL;
- }
- }
-
- return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4);
-}
-
-static void mlx4_unmap_uar(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i;
-
- for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
- if (priv->eq_table.uar_map[i]) {
- iounmap(priv->eq_table.uar_map[i]);
- priv->eq_table.uar_map[i] = NULL;
- }
-}
-
-static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
- u8 intr, struct mlx4_eq *eq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_eq_context *eq_context;
- int npages;
- u64 *dma_list = NULL;
- dma_addr_t t;
- u64 mtt_addr;
- int err = -ENOMEM;
- int i;
-
- eq->dev = dev;
- eq->nent = roundup_pow_of_two(max(nent, 2));
- /* CX3 is capable of extending the CQE\EQE from 32 to 64 bytes */
- npages = PAGE_ALIGN(eq->nent * (MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor)) / PAGE_SIZE;
-
- eq->page_list = kmalloc(npages * sizeof *eq->page_list,
- GFP_KERNEL);
- if (!eq->page_list)
- goto err_out;
-
- for (i = 0; i < npages; ++i)
- eq->page_list[i].buf = NULL;
-
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
- if (!dma_list)
- goto err_out_free;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- goto err_out_free;
- eq_context = mailbox->buf;
-
- for (i = 0; i < npages; ++i) {
- eq->page_list[i].buf = dma_alloc_coherent(&dev->pdev->dev,
- PAGE_SIZE, &t, GFP_KERNEL);
- if (!eq->page_list[i].buf)
- goto err_out_free_pages;
-
- dma_list[i] = t;
- eq->page_list[i].map = t;
-
- memset(eq->page_list[i].buf, 0, PAGE_SIZE);
- }
-
- eq->eqn = mlx4_bitmap_alloc(&priv->eq_table.bitmap);
- if (eq->eqn == -1)
- goto err_out_free_pages;
-
- eq->doorbell = mlx4_get_eq_uar(dev, eq);
- if (!eq->doorbell) {
- err = -ENOMEM;
- goto err_out_free_eq;
- }
-
- err = mlx4_mtt_init(dev, npages, PAGE_SHIFT, &eq->mtt);
- if (err)
- goto err_out_free_eq;
-
- err = mlx4_write_mtt(dev, &eq->mtt, 0, npages, dma_list);
- if (err)
- goto err_out_free_mtt;
-
- memset(eq_context, 0, sizeof *eq_context);
- eq_context->flags = cpu_to_be32(MLX4_EQ_STATUS_OK |
- MLX4_EQ_STATE_ARMED);
- eq_context->log_eq_size = ilog2(eq->nent);
- eq_context->intr = intr;
- eq_context->log_page_size = PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT;
-
- mtt_addr = mlx4_mtt_addr(dev, &eq->mtt);
- eq_context->mtt_base_addr_h = mtt_addr >> 32;
- eq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
-
- err = mlx4_SW2HW_EQ(dev, mailbox, eq->eqn);
- if (err) {
- mlx4_warn(dev, "SW2HW_EQ failed (%d)\n", err);
- goto err_out_free_mtt;
- }
-
- kfree(dma_list);
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- eq->cons_index = 0;
-
- return err;
-
-err_out_free_mtt:
- mlx4_mtt_cleanup(dev, &eq->mtt);
-
-err_out_free_eq:
- mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR);
-
-err_out_free_pages:
- for (i = 0; i < npages; ++i)
- if (eq->page_list[i].buf)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- eq->page_list[i].buf,
- eq->page_list[i].map);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
-
-err_out_free:
- kfree(eq->page_list);
- kfree(dma_list);
-
-err_out:
- return err;
-}
-
-static void mlx4_free_eq(struct mlx4_dev *dev,
- struct mlx4_eq *eq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_mailbox *mailbox;
- int err;
- int i;
- /* CX3 is capable of extending the CQE\EQE from 32 to 64 bytes */
- int npages = PAGE_ALIGN((MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor) * eq->nent) / PAGE_SIZE;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return;
-
- err = mlx4_HW2SW_EQ(dev, mailbox, eq->eqn);
- if (err)
- mlx4_warn(dev, "HW2SW_EQ failed (%d)\n", err);
-
- if (0) {
- mlx4_dbg(dev, "Dumping EQ context %02x:\n", eq->eqn);
- for (i = 0; i < sizeof (struct mlx4_eq_context) / 4; ++i) {
- if (i % 4 == 0)
- pr_cont("[%02x] ", i * 4);
- pr_cont(" %08x", be32_to_cpup(mailbox->buf + i * 4));
- if ((i + 1) % 4 == 0)
- pr_cont("\n");
- }
- }
-
- mlx4_mtt_cleanup(dev, &eq->mtt);
- for (i = 0; i < npages; ++i)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- eq->page_list[i].buf,
- eq->page_list[i].map);
-
- kfree(eq->page_list);
- mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR);
- mlx4_free_cmd_mailbox(dev, mailbox);
-}
-
-static void mlx4_free_irqs(struct mlx4_dev *dev)
-{
- struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table;
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i, vec;
-
- if (eq_table->have_irq)
- free_irq(dev->pdev->irq, dev);
-
- for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
- if (eq_table->eq[i].have_irq) {
- free_irq(eq_table->eq[i].irq, eq_table->eq + i);
- eq_table->eq[i].have_irq = 0;
- }
-
- for (i = 0; i < dev->caps.comp_pool; i++) {
- /*
- * Freeing the assigned irq's
- * all bits should be 0, but we need to validate
- */
- if (priv->msix_ctl.pool_bm & 1ULL << i) {
- /* NO need protecting*/
- vec = dev->caps.num_comp_vectors + 1 + i;
- free_irq(priv->eq_table.eq[vec].irq,
- &priv->eq_table.eq[vec]);
- }
- }
-
-
- kfree(eq_table->irq_names);
-}
-
-static int mlx4_map_clr_int(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- priv->clr_base = ioremap(pci_resource_start(dev->pdev, priv->fw.clr_int_bar) +
- priv->fw.clr_int_base, MLX4_CLR_INT_SIZE);
- if (!priv->clr_base) {
- mlx4_err(dev, "Couldn't map interrupt clear register, aborting.\n");
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void mlx4_unmap_clr_int(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- iounmap(priv->clr_base);
-}
-
-int mlx4_alloc_eq_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- priv->eq_table.eq = kcalloc(dev->caps.num_eqs - dev->caps.reserved_eqs,
- sizeof *priv->eq_table.eq, GFP_KERNEL);
- if (!priv->eq_table.eq)
- return -ENOMEM;
-
- return 0;
-}
-
-void mlx4_free_eq_table(struct mlx4_dev *dev)
-{
- kfree(mlx4_priv(dev)->eq_table.eq);
-}
-
-int mlx4_init_eq_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err;
- int i;
-
- priv->eq_table.uar_map = kcalloc(mlx4_num_eq_uar(dev),
- sizeof *priv->eq_table.uar_map,
- GFP_KERNEL);
- if (!priv->eq_table.uar_map) {
- err = -ENOMEM;
- goto err_out_free;
- }
-
- err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs,
- dev->caps.num_eqs - 1, dev->caps.reserved_eqs, 0);
- if (err)
- goto err_out_free;
-
- for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
- priv->eq_table.uar_map[i] = NULL;
-
- if (!mlx4_is_slave(dev)) {
- err = mlx4_map_clr_int(dev);
- if (err)
- goto err_out_bitmap;
-
- priv->eq_table.clr_mask =
- swab32(1 << (priv->eq_table.inta_pin & 31));
- priv->eq_table.clr_int = priv->clr_base +
- (priv->eq_table.inta_pin < 32 ? 4 : 0);
- }
-
- priv->eq_table.irq_names =
- kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1 +
- dev->caps.comp_pool),
- GFP_KERNEL);
- if (!priv->eq_table.irq_names) {
- err = -ENOMEM;
- goto err_out_clr_int;
- }
-
- for (i = 0; i < dev->caps.num_comp_vectors; ++i) {
- err = mlx4_create_eq(dev, dev->caps.num_cqs -
- dev->caps.reserved_cqs +
- MLX4_NUM_SPARE_EQE,
- (dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
- &priv->eq_table.eq[i]);
- if (err) {
- --i;
- goto err_out_unmap;
- }
- }
-
- err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE,
- (dev->flags & MLX4_FLAG_MSI_X) ? dev->caps.num_comp_vectors : 0,
- &priv->eq_table.eq[dev->caps.num_comp_vectors]);
- if (err)
- goto err_out_comp;
-
- /*if additional completion vectors poolsize is 0 this loop will not run*/
- for (i = dev->caps.num_comp_vectors + 1;
- i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i) {
-
- err = mlx4_create_eq(dev, dev->caps.num_cqs -
- dev->caps.reserved_cqs +
- MLX4_NUM_SPARE_EQE,
- (dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
- &priv->eq_table.eq[i]);
- if (err) {
- --i;
- goto err_out_unmap;
- }
- }
-
-
- if (dev->flags & MLX4_FLAG_MSI_X) {
- const char *eq_name;
-
- for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) {
- if (i < dev->caps.num_comp_vectors) {
- snprintf(priv->eq_table.irq_names +
- i * MLX4_IRQNAME_SIZE,
- MLX4_IRQNAME_SIZE,
- "mlx4-comp-%d@pci:%s", i,
- pci_name(dev->pdev));
- } else {
- snprintf(priv->eq_table.irq_names +
- i * MLX4_IRQNAME_SIZE,
- MLX4_IRQNAME_SIZE,
- "mlx4-async@pci:%s",
- pci_name(dev->pdev));
- }
-
- eq_name = priv->eq_table.irq_names +
- i * MLX4_IRQNAME_SIZE;
- err = request_irq(priv->eq_table.eq[i].irq,
- mlx4_msi_x_interrupt, 0, eq_name,
- priv->eq_table.eq + i);
- if (err)
- goto err_out_async;
-
- priv->eq_table.eq[i].have_irq = 1;
- }
- } else {
- snprintf(priv->eq_table.irq_names,
- MLX4_IRQNAME_SIZE,
- DRV_NAME "@pci:%s",
- pci_name(dev->pdev));
- err = request_irq(dev->pdev->irq, mlx4_interrupt,
- IRQF_SHARED, priv->eq_table.irq_names, dev);
- if (err)
- goto err_out_async;
-
- priv->eq_table.have_irq = 1;
- }
-
- err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
- priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
- if (err)
- mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
- priv->eq_table.eq[dev->caps.num_comp_vectors].eqn, err);
-
- for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
- eq_set_ci(&priv->eq_table.eq[i], 1);
-
- return 0;
-
-err_out_async:
- mlx4_free_eq(dev, &priv->eq_table.eq[dev->caps.num_comp_vectors]);
-
-err_out_comp:
- i = dev->caps.num_comp_vectors - 1;
-
-err_out_unmap:
- while (i >= 0) {
- mlx4_free_eq(dev, &priv->eq_table.eq[i]);
- --i;
- }
- mlx4_free_irqs(dev);
-
-err_out_clr_int:
- if (!mlx4_is_slave(dev))
- mlx4_unmap_clr_int(dev);
-
-err_out_bitmap:
- mlx4_unmap_uar(dev);
- mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
-
-err_out_free:
- kfree(priv->eq_table.uar_map);
-
- return err;
-}
-
-void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i;
-
- mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 1,
- priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
-
- mlx4_free_irqs(dev);
-
- for (i = 0; i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i)
- mlx4_free_eq(dev, &priv->eq_table.eq[i]);
-
- if (!mlx4_is_slave(dev))
- mlx4_unmap_clr_int(dev);
-
- mlx4_unmap_uar(dev);
- mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
-
- kfree(priv->eq_table.uar_map);
-}
-
-/* A test that verifies that we can accept interrupts on all
- * the irq vectors of the device.
- * Interrupts are checked using the NOP command.
- */
-int mlx4_test_interrupts(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i;
- int err;
-
- err = mlx4_NOP(dev);
- /* When not in MSI_X, there is only one irq to check */
- if (!(dev->flags & MLX4_FLAG_MSI_X) || mlx4_is_slave(dev))
- return err;
-
- /* A loop over all completion vectors, for each vector we will check
- * whether it works by mapping command completions to that vector
- * and performing a NOP command
- */
- for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
- /* Temporary use polling for command completions */
- mlx4_cmd_use_polling(dev);
-
- /* Map the new eq to handle all asyncronous events */
- err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
- priv->eq_table.eq[i].eqn);
- if (err) {
- mlx4_warn(dev, "Failed mapping eq for interrupt test\n");
- mlx4_cmd_use_events(dev);
- break;
- }
-
- /* Go back to using events */
- mlx4_cmd_use_events(dev);
- err = mlx4_NOP(dev);
- }
-
- /* Return to default */
- mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
- priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
- return err;
-}
-EXPORT_SYMBOL(mlx4_test_interrupts);
-
-int mlx4_assign_eq(struct mlx4_dev *dev, char* name, int * vector)
-{
-
- struct mlx4_priv *priv = mlx4_priv(dev);
- int vec = 0, err = 0, i;
-
- mutex_lock(&priv->msix_ctl.pool_lock);
- for (i = 0; !vec && i < dev->caps.comp_pool; i++) {
- if (~priv->msix_ctl.pool_bm & 1ULL << i) {
- priv->msix_ctl.pool_bm |= 1ULL << i;
- vec = dev->caps.num_comp_vectors + 1 + i;
- snprintf(priv->eq_table.irq_names +
- vec * MLX4_IRQNAME_SIZE,
- MLX4_IRQNAME_SIZE, "%s", name);
- err = request_irq(priv->eq_table.eq[vec].irq,
- mlx4_msi_x_interrupt, 0,
- &priv->eq_table.irq_names[vec<<5],
- priv->eq_table.eq + vec);
- if (err) {
- /*zero out bit by fliping it*/
- priv->msix_ctl.pool_bm ^= 1 << i;
- vec = 0;
- continue;
- /*we dont want to break here*/
- }
- eq_set_ci(&priv->eq_table.eq[vec], 1);
- }
- }
- mutex_unlock(&priv->msix_ctl.pool_lock);
-
- if (vec) {
- *vector = vec;
- } else {
- *vector = 0;
- err = (i == dev->caps.comp_pool) ? -ENOSPC : err;
- }
- return err;
-}
-EXPORT_SYMBOL(mlx4_assign_eq);
-
-void mlx4_release_eq(struct mlx4_dev *dev, int vec)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- /*bm index*/
- int i = vec - dev->caps.num_comp_vectors - 1;
-
- if (likely(i >= 0)) {
- /*sanity check , making sure were not trying to free irq's
- Belonging to a legacy EQ*/
- mutex_lock(&priv->msix_ctl.pool_lock);
- if (priv->msix_ctl.pool_bm & 1ULL << i) {
- free_irq(priv->eq_table.eq[vec].irq,
- &priv->eq_table.eq[vec]);
- priv->msix_ctl.pool_bm &= ~(1ULL << i);
- }
- mutex_unlock(&priv->msix_ctl.pool_lock);
- }
-
-}
-EXPORT_SYMBOL(mlx4_release_eq);
-
diff --git a/sys/ofed/drivers/net/mlx4/fw.c b/sys/ofed/drivers/net/mlx4/fw.c
deleted file mode 100644
index e2909fa60f89..000000000000
--- a/sys/ofed/drivers/net/mlx4/fw.c
+++ /dev/null
@@ -1,1956 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#define LINUXKPI_PARAM_PREFIX mlx4_
-
-#include <linux/etherdevice.h>
-#include <linux/mlx4/cmd.h>
-#include <linux/module.h>
-#include <linux/cache.h>
-
-#include "fw.h"
-#include "icm.h"
-
-enum {
- MLX4_COMMAND_INTERFACE_MIN_REV = 2,
- MLX4_COMMAND_INTERFACE_MAX_REV = 3,
- MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS = 3,
-};
-
-extern void __buggy_use_of_MLX4_GET(void);
-extern void __buggy_use_of_MLX4_PUT(void);
-
-static u8 enable_qos;
-module_param(enable_qos, byte, 0444);
-MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (default: off)");
-
-#define MLX4_GET(dest, source, offset) \
- do { \
- void *__p = (char *) (source) + (offset); \
- switch (sizeof (dest)) { \
- case 1: (dest) = *(u8 *) __p; break; \
- case 2: (dest) = be16_to_cpup(__p); break; \
- case 4: (dest) = be32_to_cpup(__p); break; \
- case 8: (dest) = be64_to_cpup(__p); break; \
- default: __buggy_use_of_MLX4_GET(); \
- } \
- } while (0)
-
-#define MLX4_PUT(dest, source, offset) \
- do { \
- void *__d = ((char *) (dest) + (offset)); \
- switch (sizeof(source)) { \
- case 1: *(u8 *) __d = (source); break; \
- case 2: *(__be16 *) __d = cpu_to_be16(source); break; \
- case 4: *(__be32 *) __d = cpu_to_be32(source); break; \
- case 8: *(__be64 *) __d = cpu_to_be64(source); break; \
- default: __buggy_use_of_MLX4_PUT(); \
- } \
- } while (0)
-
-static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
-{
- static const char *fname[] = {
- [ 0] = "RC transport",
- [ 1] = "UC transport",
- [ 2] = "UD transport",
- [ 3] = "XRC transport",
- [ 4] = "reliable multicast",
- [ 5] = "FCoIB support",
- [ 6] = "SRQ support",
- [ 7] = "IPoIB checksum offload",
- [ 8] = "P_Key violation counter",
- [ 9] = "Q_Key violation counter",
- [10] = "VMM",
- [12] = "DPDP",
- [15] = "Big LSO headers",
- [16] = "MW support",
- [17] = "APM support",
- [18] = "Atomic ops support",
- [19] = "Raw multicast support",
- [20] = "Address vector port checking support",
- [21] = "UD multicast support",
- [24] = "Demand paging support",
- [25] = "Router support",
- [30] = "IBoE support",
- [32] = "Unicast loopback support",
- [34] = "FCS header control",
- [38] = "Wake On LAN support",
- [40] = "UDP RSS support",
- [41] = "Unicast VEP steering support",
- [42] = "Multicast VEP steering support",
- [44] = "Cross-channel (sync_qp) operations support",
- [48] = "Counters support",
- [59] = "Port management change event support",
- [60] = "eSwitch support",
- [61] = "64 byte EQE support",
- [62] = "64 byte CQE support",
- };
- int i;
-
- mlx4_dbg(dev, "DEV_CAP flags:\n");
- for (i = 0; i < ARRAY_SIZE(fname); ++i)
- if (fname[i] && (flags & (1LL << i)))
- mlx4_dbg(dev, " %s\n", fname[i]);
-}
-
-static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
-{
- static const char * const fname[] = {
- [0] = "RSS support",
- [1] = "RSS Toeplitz Hash Function support",
- [2] = "RSS XOR Hash Function support",
- [3] = "Device manage flow steering support",
- [4] = "FSM (MAC unti-spoofing) support",
- [5] = "VST (control vlan insertion/stripping) support",
- [6] = "Dynamic QP updates support",
- [7] = "Loopback source checks support",
- [8] = "Device managed flow steering IPoIB support",
- [9] = "ETS configuration support",
- [10] = "ETH backplane autoneg report",
- [11] = "Ethernet Flow control statistics support",
- [12] = "Recoverable error events support",
- [13] = "Time stamping support",
- [14] = "Report driver version to FW support"
- };
- int i;
-
- for (i = 0; i < ARRAY_SIZE(fname); ++i)
- if (fname[i] && (flags & (1LL << i)))
- mlx4_dbg(dev, " %s\n", fname[i]);
-}
-
-int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 *inbox;
- int err = 0;
-
-#define MOD_STAT_CFG_IN_SIZE 0x100
-
-#define MOD_STAT_CFG_PG_SZ_M_OFFSET 0x002
-#define MOD_STAT_CFG_PG_SZ_OFFSET 0x003
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
-
- memset(inbox, 0, MOD_STAT_CFG_IN_SIZE);
-
- MLX4_PUT(inbox, cfg->log_pg_sz, MOD_STAT_CFG_PG_SZ_OFFSET);
- MLX4_PUT(inbox, cfg->log_pg_sz_m, MOD_STAT_CFG_PG_SZ_M_OFFSET);
-
- err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_MOD_STAT_CFG,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- u8 field, port;
- u32 size;
- int err = 0;
-
-#define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0
-#define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1
-#define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4
-#define QUERY_FUNC_CAP_FMR_OFFSET 0x8
-#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP 0x10
-#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP 0x14
-#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP 0x18
-#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP 0x20
-#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP 0x24
-#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP 0x28
-#define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c
-#define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0x30
-
-#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x50
-#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x54
-#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x58
-#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x60
-#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64
-#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68
-
-#define QUERY_FUNC_CAP_FMR_FLAG 0x80
-#define QUERY_FUNC_CAP_FLAG_RDMA 0x40
-#define QUERY_FUNC_CAP_FLAG_ETH 0x80
-#define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10
-
-/* when opcode modifier = 1 */
-#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3
-#define QUERY_FUNC_CAP_FLAGS0_OFFSET 0x8
-#define QUERY_FUNC_CAP_FLAGS1_OFFSET 0xc
-#define QUERY_FUNC_CAP_COUNTER_INDEX_OFFSET 0xd
-
-#define QUERY_FUNC_CAP_QP0_TUNNEL 0x10
-#define QUERY_FUNC_CAP_QP0_PROXY 0x14
-#define QUERY_FUNC_CAP_QP1_TUNNEL 0x18
-#define QUERY_FUNC_CAP_QP1_PROXY 0x1c
-
-#define QUERY_FUNC_CAP_ETH_PROPS_FORCE_MAC 0x40
-#define QUERY_FUNC_CAP_ETH_PROPS_FORCE_VLAN 0x80
-#define QUERY_FUNC_CAP_PROPS_DEF_COUNTER 0x20
-
-#define QUERY_FUNC_CAP_RDMA_PROPS_FORCE_PHY_WQE_GID 0x80
-
- if (vhcr->op_modifier == 1) {
- port = vhcr->in_modifier; /* phys-port = logical-port */
- MLX4_PUT(outbox->buf, port, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
-
- field = 0;
- /* ensure that phy_wqe_gid bit is not set */
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS0_OFFSET);
-
- /* ensure force vlan and force mac bits are not set
- * and that default counter bit is set
- */
- field = QUERY_FUNC_CAP_PROPS_DEF_COUNTER; /* def counter */
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET);
-
- /* There is always default counter legal or sink counter */
- field = mlx4_get_default_counter_index(dev, slave, vhcr->in_modifier);
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_COUNTER_INDEX_OFFSET);
-
- /* size is now the QP number */
- size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + port - 1;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL);
-
- size += 2;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL);
-
- size = dev->phys_caps.base_proxy_sqpn + 8 * slave + port - 1;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_PROXY);
-
- size += 2;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_PROXY);
-
- } else if (vhcr->op_modifier == 0) {
- /* enable rdma and ethernet interfaces, and new quota locations */
- field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA |
- QUERY_FUNC_CAP_FLAG_QUOTAS);
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
-
- field = dev->caps.num_ports;
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
-
- size = dev->caps.function_caps; /* set PF behaviours */
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
-
- field = 0; /* protected FMR support not available as yet */
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FMR_OFFSET);
-
- size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave];
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
- size = dev->caps.num_qps;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
-
- size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave];
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
- size = dev->caps.num_srqs;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
-
- size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave];
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
- size = dev->caps.num_cqs;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
-
- size = dev->caps.num_eqs;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
-
- size = dev->caps.reserved_eqs;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
-
- size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave];
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
- size = dev->caps.num_mpts;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
-
- size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave];
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
- size = dev->caps.num_mtts;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
-
- size = dev->caps.num_mgms + dev->caps.num_amgms;
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
- MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
-
- } else
- err = -EINVAL;
-
- return err;
-}
-
-int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
- struct mlx4_func_cap *func_cap)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 *outbox;
- u8 field, op_modifier;
- u32 size;
- int err = 0, quotas = 0;
-
- op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- err = mlx4_cmd_box(dev, 0, mailbox->dma, gen_or_port, op_modifier,
- MLX4_CMD_QUERY_FUNC_CAP,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err)
- goto out;
-
- outbox = mailbox->buf;
-
- if (!op_modifier) {
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS_OFFSET);
- if (!(field & (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA))) {
- mlx4_err(dev, "The host supports neither eth nor rdma interfaces\n");
- err = -EPROTONOSUPPORT;
- goto out;
- }
- func_cap->flags = field;
- quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS);
-
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
- func_cap->num_ports = field;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
- func_cap->pf_context_behaviour = size;
-
- if (quotas) {
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
- func_cap->qp_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
- func_cap->srq_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
- func_cap->cq_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
- func_cap->mpt_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
- func_cap->mtt_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
- func_cap->mcg_quota = size & 0xFFFFFF;
-
- } else {
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
- func_cap->qp_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
- func_cap->srq_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
- func_cap->cq_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
- func_cap->mpt_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
- func_cap->mtt_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
- func_cap->mcg_quota = size & 0xFFFFFF;
- }
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
- func_cap->max_eq = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
- func_cap->reserved_eq = size & 0xFFFFFF;
-
- goto out;
- }
-
- /* logical port query */
- if (gen_or_port > dev->caps.num_ports) {
- err = -EINVAL;
- goto out;
- }
-
- if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_ETH) {
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET);
- if (field & QUERY_FUNC_CAP_ETH_PROPS_FORCE_VLAN) {
- mlx4_err(dev, "VLAN is enforced on this port\n");
- err = -EPROTONOSUPPORT;
- goto out;
- }
-
- if (field & QUERY_FUNC_CAP_ETH_PROPS_FORCE_MAC) {
- mlx4_err(dev, "Force mac is enabled on this port\n");
- err = -EPROTONOSUPPORT;
- goto out;
- }
- } else if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_IB) {
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET);
- if (field & QUERY_FUNC_CAP_RDMA_PROPS_FORCE_PHY_WQE_GID) {
- mlx4_err(dev, "phy_wqe_gid is "
- "enforced on this ib port\n");
- err = -EPROTONOSUPPORT;
- goto out;
- }
- }
-
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
- func_cap->physical_port = field;
- if (func_cap->physical_port != gen_or_port) {
- err = -ENOSYS;
- goto out;
- }
-
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET);
- if (field & QUERY_FUNC_CAP_PROPS_DEF_COUNTER) {
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_COUNTER_INDEX_OFFSET);
- func_cap->def_counter_index = field;
- } else {
- func_cap->def_counter_index = MLX4_SINK_COUNTER_INDEX;
- }
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL);
- func_cap->qp0_tunnel_qpn = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_PROXY);
- func_cap->qp0_proxy_qpn = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_TUNNEL);
- func_cap->qp1_tunnel_qpn = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP1_PROXY);
- func_cap->qp1_proxy_qpn = size & 0xFFFFFF;
-
- /* All other resources are allocated by the master, but we still report
- * 'num' and 'reserved' capabilities as follows:
- * - num remains the maximum resource index
- * - 'num - reserved' is the total available objects of a resource, but
- * resource indices may be less than 'reserved'
- * TODO: set per-resource quotas */
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- return err;
-}
-
-int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 *outbox;
- u8 field;
- u32 field32, flags, ext_flags;
- u16 size;
- u16 stat_rate;
- int err;
- int i;
-
-#define QUERY_DEV_CAP_OUT_SIZE 0x100
-#define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10
-#define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET 0x11
-#define QUERY_DEV_CAP_RSVD_QP_OFFSET 0x12
-#define QUERY_DEV_CAP_MAX_QP_OFFSET 0x13
-#define QUERY_DEV_CAP_RSVD_SRQ_OFFSET 0x14
-#define QUERY_DEV_CAP_MAX_SRQ_OFFSET 0x15
-#define QUERY_DEV_CAP_RSVD_EEC_OFFSET 0x16
-#define QUERY_DEV_CAP_MAX_EEC_OFFSET 0x17
-#define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET 0x19
-#define QUERY_DEV_CAP_RSVD_CQ_OFFSET 0x1a
-#define QUERY_DEV_CAP_MAX_CQ_OFFSET 0x1b
-#define QUERY_DEV_CAP_MAX_MPT_OFFSET 0x1d
-#define QUERY_DEV_CAP_RSVD_EQ_OFFSET 0x1e
-#define QUERY_DEV_CAP_MAX_EQ_OFFSET 0x1f
-#define QUERY_DEV_CAP_RSVD_MTT_OFFSET 0x20
-#define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET 0x21
-#define QUERY_DEV_CAP_RSVD_MRW_OFFSET 0x22
-#define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET 0x23
-#define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27
-#define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29
-#define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b
-#define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d
-#define QUERY_DEV_CAP_RSS_OFFSET 0x2e
-#define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f
-#define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33
-#define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35
-#define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36
-#define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37
-#define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET 0x38
-#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b
-#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c
-#define QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET 0x3e
-#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f
-#define QUERY_DEV_CAP_EXT_FLAGS_OFFSET 0x40
-#define QUERY_DEV_CAP_SYNC_QP_OFFSET 0x42
-#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44
-#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48
-#define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49
-#define QUERY_DEV_CAP_PAGE_SZ_OFFSET 0x4b
-#define QUERY_DEV_CAP_BF_OFFSET 0x4c
-#define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET 0x4d
-#define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET 0x4e
-#define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET 0x4f
-#define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET 0x51
-#define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52
-#define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55
-#define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56
-#define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61
-#define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62
-#define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63
-#define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64
-#define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65
-#define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66
-#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
-#define QUERY_DEV_CAP_MAX_BASIC_COUNTERS_OFFSET 0x68
-#define QUERY_DEV_CAP_MAX_EXTENDED_COUNTERS_OFFSET 0x6c
-#define QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET 0x70
-#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76
-#define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET 0x70
-#define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET 0x74
-#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77
-#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
-#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
-#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84
-#define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET 0x86
-#define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET 0x88
-#define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET 0x8a
-#define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET 0x8c
-#define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e
-#define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90
-#define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92
-#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94
-#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
-#define QUERY_DEV_CAP_ETS_CFG_OFFSET 0x9c
-#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
-
- dev_cap->flags2 = 0;
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
-
- err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (err)
- goto out;
-
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET);
- dev_cap->reserved_qps = 1 << (field & 0xf);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET);
- dev_cap->max_qps = 1 << (field & 0x1f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET);
- dev_cap->reserved_srqs = 1 << (field >> 4);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_OFFSET);
- dev_cap->max_srqs = 1 << (field & 0x1f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET);
- dev_cap->max_cq_sz = 1 << field;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_CQ_OFFSET);
- dev_cap->reserved_cqs = 1 << (field & 0xf);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_OFFSET);
- dev_cap->max_cqs = 1 << (field & 0x1f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET);
- dev_cap->max_mpts = 1 << (field & 0x3f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET);
- dev_cap->reserved_eqs = field & 0xf;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET);
- dev_cap->max_eqs = 1 << (field & 0xf);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET);
- dev_cap->reserved_mtts = 1 << (field >> 4);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET);
- dev_cap->max_mrw_sz = 1 << field;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MRW_OFFSET);
- dev_cap->reserved_mrws = 1 << (field & 0xf);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET);
- dev_cap->max_mtt_seg = 1 << (field & 0x3f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET);
- dev_cap->max_requester_per_qp = 1 << (field & 0x3f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET);
- dev_cap->max_responder_per_qp = 1 << (field & 0x3f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GSO_OFFSET);
- field &= 0x1f;
- if (!field)
- dev_cap->max_gso_sz = 0;
- else
- dev_cap->max_gso_sz = 1 << field;
-
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET);
- if (field & 0x20)
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR;
- if (field & 0x10)
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP;
- field &= 0xf;
- if (field) {
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS;
- dev_cap->max_rss_tbl_sz = 1 << field;
- } else
- dev_cap->max_rss_tbl_sz = 0;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET);
- dev_cap->max_rdma_global = 1 << (field & 0x3f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
- dev_cap->local_ca_ack_delay = field & 0x1f;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
- dev_cap->num_ports = field & 0xf;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
- dev_cap->max_msg_sz = 1 << (field & 0x1f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET);
- if (field & 0x10)
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
- if (field & 0x80)
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
- if (field & 0x80)
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB;
- dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
- dev_cap->fs_max_num_qp_per_entry = field;
- MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
- dev_cap->stat_rate_support = stat_rate;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
- if (field & 0x80)
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_TS;
- MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
- MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
- dev_cap->flags = flags | (u64)ext_flags << 32;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_SYNC_QP_OFFSET);
- dev_cap->sync_qp = field & 0x10;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
- dev_cap->reserved_uars = field >> 4;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET);
- dev_cap->uar_size = 1 << ((field & 0x3f) + 20);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_PAGE_SZ_OFFSET);
- dev_cap->min_page_sz = 1 << field;
-
- MLX4_GET(field, outbox, QUERY_DEV_CAP_BF_OFFSET);
- if (field & 0x80) {
- MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET);
- dev_cap->bf_reg_size = 1 << (field & 0x1f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET);
- if ((1 << (field & 0x3f)) > (PAGE_SIZE / dev_cap->bf_reg_size))
- field = 3;
- dev_cap->bf_regs_per_page = 1 << (field & 0x3f);
- mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n",
- dev_cap->bf_reg_size, dev_cap->bf_regs_per_page);
- } else {
- dev_cap->bf_reg_size = 0;
- mlx4_dbg(dev, "BlueFlame not available\n");
- }
-
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_SQ_OFFSET);
- dev_cap->max_sq_sg = field;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET);
- dev_cap->max_sq_desc_sz = size;
-
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_MCG_OFFSET);
- dev_cap->max_qp_per_mcg = 1 << field;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MCG_OFFSET);
- dev_cap->reserved_mgms = field & 0xf;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MCG_OFFSET);
- dev_cap->max_mcgs = 1 << field;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_PD_OFFSET);
- dev_cap->reserved_pds = field >> 4;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
- dev_cap->max_pds = 1 << (field & 0x3f);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET);
- dev_cap->reserved_xrcds = field >> 4;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_XRC_OFFSET);
- dev_cap->max_xrcds = 1 << (field & 0x1f);
-
- MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET);
- dev_cap->rdmarc_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET);
- dev_cap->qpc_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET);
- dev_cap->aux_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET);
- dev_cap->altc_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET);
- dev_cap->eqc_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET);
- dev_cap->cqc_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET);
- dev_cap->srq_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET);
- dev_cap->cmpt_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET);
- dev_cap->mtt_entry_sz = size;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET);
- dev_cap->dmpt_entry_sz = size;
-
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET);
- dev_cap->max_srq_sz = 1 << field;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_SZ_OFFSET);
- dev_cap->max_qp_sz = 1 << field;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_RSZ_SRQ_OFFSET);
- dev_cap->resize_srq = field & 1;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_RQ_OFFSET);
- dev_cap->max_rq_sg = field;
- MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET);
- dev_cap->max_rq_desc_sz = size;
-
- MLX4_GET(dev_cap->bmme_flags, outbox,
- QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
- MLX4_GET(dev_cap->reserved_lkey, outbox,
- QUERY_DEV_CAP_RSVD_LKEY_OFFSET);
- MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETS_CFG_OFFSET);
- if (field32 & (1 << 0))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP;
- if (field32 & (1 << 7))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT;
- if (field32 & (1 << 8))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DRIVER_VERSION_TO_FW;
- if (field32 & (1 << 13))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETS_CFG;
-
- MLX4_GET(dev_cap->max_icm_sz, outbox,
- QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
- if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
- MLX4_GET(dev_cap->max_basic_counters, outbox,
- QUERY_DEV_CAP_MAX_BASIC_COUNTERS_OFFSET);
- /* FW reports 256 however real value is 255 */
- dev_cap->max_basic_counters = min_t(u32, dev_cap->max_basic_counters, 255);
- if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS_EXT)
- MLX4_GET(dev_cap->max_extended_counters, outbox,
- QUERY_DEV_CAP_MAX_EXTENDED_COUNTERS_OFFSET);
-
- MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
- if (field32 & (1 << 16))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
- if (field32 & (1 << 19))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_LB_SRC_CHK;
- if (field32 & (1 << 20))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM;
- if (field32 & (1 << 26))
- dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
-
- if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
- for (i = 1; i <= dev_cap->num_ports; ++i) {
- MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
- dev_cap->max_vl[i] = field >> 4;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
- dev_cap->ib_mtu[i] = field >> 4;
- dev_cap->max_port_width[i] = field & 0xf;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
- dev_cap->max_gids[i] = 1 << (field & 0xf);
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
- dev_cap->max_pkeys[i] = 1 << (field & 0xf);
- }
- } else {
-#define QUERY_PORT_SUPPORTED_TYPE_OFFSET 0x00
-#define QUERY_PORT_MTU_OFFSET 0x01
-#define QUERY_PORT_ETH_MTU_OFFSET 0x02
-#define QUERY_PORT_WIDTH_OFFSET 0x06
-#define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07
-#define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a
-#define QUERY_PORT_MAX_VL_OFFSET 0x0b
-#define QUERY_PORT_MAC_OFFSET 0x10
-#define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18
-#define QUERY_PORT_WAVELENGTH_OFFSET 0x1c
-#define QUERY_PORT_TRANS_CODE_OFFSET 0x20
-
- for (i = 1; i <= dev_cap->num_ports; ++i) {
- err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
- if (err)
- goto out;
-
- MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET);
- dev_cap->supported_port_types[i] = field & 3;
- dev_cap->suggested_type[i] = (field >> 3) & 1;
- dev_cap->default_sense[i] = (field >> 4) & 1;
- MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
- dev_cap->ib_mtu[i] = field & 0xf;
- MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
- dev_cap->max_port_width[i] = field & 0xf;
- MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET);
- dev_cap->max_gids[i] = 1 << (field >> 4);
- dev_cap->max_pkeys[i] = 1 << (field & 0xf);
- MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET);
- dev_cap->max_vl[i] = field & 0xf;
- MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET);
- dev_cap->log_max_macs[i] = field & 0xf;
- dev_cap->log_max_vlans[i] = field >> 4;
- MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET);
- MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET);
- MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET);
- dev_cap->trans_type[i] = field32 >> 24;
- dev_cap->vendor_oui[i] = field32 & 0xffffff;
- MLX4_GET(dev_cap->wavelength[i], outbox, QUERY_PORT_WAVELENGTH_OFFSET);
- MLX4_GET(dev_cap->trans_code[i], outbox, QUERY_PORT_TRANS_CODE_OFFSET);
- }
- }
-
- mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n",
- dev_cap->bmme_flags, dev_cap->reserved_lkey);
-
- /*
- * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then
- * we can't use any EQs whose doorbell falls on that page,
- * even if the EQ itself isn't reserved.
- */
- dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4,
- dev_cap->reserved_eqs);
-
- mlx4_dbg(dev, "Max ICM size %lld MB\n",
- (unsigned long long) dev_cap->max_icm_sz >> 20);
- mlx4_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n",
- dev_cap->max_qps, dev_cap->reserved_qps, dev_cap->qpc_entry_sz);
- mlx4_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n",
- dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz);
- mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n",
- dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz);
- mlx4_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n",
- dev_cap->max_eqs, dev_cap->reserved_eqs, dev_cap->eqc_entry_sz);
- mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n",
- dev_cap->reserved_mrws, dev_cap->reserved_mtts);
- mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n",
- dev_cap->max_pds, dev_cap->reserved_pds, dev_cap->reserved_uars);
- mlx4_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
- dev_cap->max_pds, dev_cap->reserved_mgms);
- mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
- dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz);
- mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n",
- dev_cap->local_ca_ack_delay, 128 << dev_cap->ib_mtu[1],
- dev_cap->max_port_width[1]);
- mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n",
- dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
- mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
- dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
- mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
- mlx4_dbg(dev, "Max basic counters: %d\n", dev_cap->max_basic_counters);
- mlx4_dbg(dev, "Max extended counters: %d\n", dev_cap->max_extended_counters);
- mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz);
-
- dump_dev_cap_flags(dev, dev_cap->flags);
- dump_dev_cap_flags2(dev, dev_cap->flags2);
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- u64 flags;
- int err = 0;
- u8 field;
-
- err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (err)
- return err;
-
- /* add port mng change event capability unconditionally to slaves */
- MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
- flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV;
- MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
-
- /* For guests, report Blueflame disabled */
- MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
- field &= 0x7f;
- MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET);
-
- /* turn off device-managed steering capability if not enabled */
- if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
- MLX4_GET(field, outbox->buf,
- QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
- field &= 0x7f;
- MLX4_PUT(outbox->buf, field,
- QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
- }
- return 0;
-}
-
-int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- u64 def_mac;
- u8 port_type;
- u16 short_field;
- int err;
- int admin_link_state;
-
-#define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0
-#define MLX4_PORT_LINK_UP_MASK 0x80
-#define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c
-#define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e
-
- err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0,
- MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_NATIVE);
-
- if (!err && dev->caps.function != slave) {
- /* set slave default_mac address to be zero MAC */
- def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
- MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
-
- /* get port type - currently only eth is enabled */
- MLX4_GET(port_type, outbox->buf,
- QUERY_PORT_SUPPORTED_TYPE_OFFSET);
-
- /* No link sensing allowed */
- port_type &= MLX4_VF_PORT_NO_LINK_SENSE_MASK;
- /* set port type to currently operating port type */
- port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3);
-
- admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state;
- if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state)
- port_type |= MLX4_PORT_LINK_UP_MASK;
- else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state)
- port_type &= ~MLX4_PORT_LINK_UP_MASK;
-
- MLX4_PUT(outbox->buf, port_type,
- QUERY_PORT_SUPPORTED_TYPE_OFFSET);
-
- if (dev->caps.port_type[vhcr->in_modifier] == MLX4_PORT_TYPE_ETH)
- short_field = mlx4_get_slave_num_gids(dev, slave);
- else
- short_field = 1; /* slave max gids */
- MLX4_PUT(outbox->buf, short_field,
- QUERY_PORT_CUR_MAX_GID_OFFSET);
-
- short_field = dev->caps.pkey_table_len[vhcr->in_modifier];
- MLX4_PUT(outbox->buf, short_field,
- QUERY_PORT_CUR_MAX_PKEY_OFFSET);
- }
-
- return err;
-}
-
-int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port,
- int *gid_tbl_len, int *pkey_tbl_len)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 *outbox;
- u16 field;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0,
- MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_WRAPPED);
- if (err)
- goto out;
-
- outbox = mailbox->buf;
-
- MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_GID_OFFSET);
- *gid_tbl_len = field;
-
- MLX4_GET(field, outbox, QUERY_PORT_CUR_MAX_PKEY_OFFSET);
- *pkey_tbl_len = field;
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL(mlx4_get_slave_pkey_gid_tbl_len);
-
-int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_icm_iter iter;
- __be64 *pages;
- int lg;
- int nent = 0;
- int i;
- int err = 0;
- int ts = 0, tc = 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
- pages = mailbox->buf;
-
- for (mlx4_icm_first(icm, &iter);
- !mlx4_icm_last(&iter);
- mlx4_icm_next(&iter)) {
- /*
- * We have to pass pages that are aligned to their
- * size, so find the least significant 1 in the
- * address or size and use that as our log2 size.
- */
- lg = ffs(mlx4_icm_addr(&iter) | mlx4_icm_size(&iter)) - 1;
- if (lg < MLX4_ICM_PAGE_SHIFT) {
- mlx4_warn(dev, "Got FW area not aligned to %d (%llx/%lx).\n",
- MLX4_ICM_PAGE_SIZE,
- (unsigned long long) mlx4_icm_addr(&iter),
- mlx4_icm_size(&iter));
- err = -EINVAL;
- goto out;
- }
-
- for (i = 0; i < mlx4_icm_size(&iter) >> lg; ++i) {
- if (virt != -1) {
- pages[nent * 2] = cpu_to_be64(virt);
- virt += 1 << lg;
- }
-
- pages[nent * 2 + 1] =
- cpu_to_be64((mlx4_icm_addr(&iter) + (i << lg)) |
- (lg - MLX4_ICM_PAGE_SHIFT));
- ts += 1 << (lg - 10);
- ++tc;
-
- if (++nent == MLX4_MAILBOX_SIZE / 16) {
- err = mlx4_cmd(dev, mailbox->dma, nent, 0, op,
- MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_NATIVE);
- if (err)
- goto out;
- nent = 0;
- }
- }
- }
-
- if (nent)
- err = mlx4_cmd(dev, mailbox->dma, nent, 0, op,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
- if (err)
- goto out;
-
- switch (op) {
- case MLX4_CMD_MAP_FA:
- mlx4_dbg(dev, "Mapped %d chunks/%d KB for FW.\n", tc, ts);
- break;
- case MLX4_CMD_MAP_ICM_AUX:
- mlx4_dbg(dev, "Mapped %d chunks/%d KB for ICM aux.\n", tc, ts);
- break;
- case MLX4_CMD_MAP_ICM:
- mlx4_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM.\n",
- tc, ts, (unsigned long long) virt - (ts << 10));
- break;
- }
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm)
-{
- return mlx4_map_cmd(dev, MLX4_CMD_MAP_FA, icm, -1);
-}
-
-int mlx4_UNMAP_FA(struct mlx4_dev *dev)
-{
- return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-}
-
-
-int mlx4_RUN_FW(struct mlx4_dev *dev)
-{
- return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-}
-
-int mlx4_QUERY_FW(struct mlx4_dev *dev)
-{
- struct mlx4_fw *fw = &mlx4_priv(dev)->fw;
- struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
- struct mlx4_cmd_mailbox *mailbox;
- u32 *outbox;
- int err = 0;
- u64 fw_ver;
- u16 cmd_if_rev;
- u8 lg;
-
-#define QUERY_FW_OUT_SIZE 0x100
-#define QUERY_FW_VER_OFFSET 0x00
-#define QUERY_FW_PPF_ID 0x09
-#define QUERY_FW_CMD_IF_REV_OFFSET 0x0a
-#define QUERY_FW_MAX_CMD_OFFSET 0x0f
-#define QUERY_FW_ERR_START_OFFSET 0x30
-#define QUERY_FW_ERR_SIZE_OFFSET 0x38
-#define QUERY_FW_ERR_BAR_OFFSET 0x3c
-
-#define QUERY_FW_SIZE_OFFSET 0x00
-#define QUERY_FW_CLR_INT_BASE_OFFSET 0x20
-#define QUERY_FW_CLR_INT_BAR_OFFSET 0x28
-
-#define QUERY_FW_COMM_BASE_OFFSET 0x40
-#define QUERY_FW_COMM_BAR_OFFSET 0x48
-
-#define QUERY_FW_CLOCK_OFFSET 0x50
-#define QUERY_FW_CLOCK_BAR 0x58
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
-
- err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (err)
- goto out;
-
- MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET);
- /*
- * FW subminor version is at more significant bits than minor
- * version, so swap here.
- */
- dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) |
- ((fw_ver & 0xffff0000ull) >> 16) |
- ((fw_ver & 0x0000ffffull) << 16);
-
- MLX4_GET(lg, outbox, QUERY_FW_PPF_ID);
- dev->caps.function = lg;
-
- if (mlx4_is_slave(dev))
- goto out;
-
-
- MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
- if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
- cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
- mlx4_err(dev, "Installed FW has unsupported "
- "command interface revision %d.\n",
- cmd_if_rev);
- mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n",
- (int) (dev->caps.fw_ver >> 32),
- (int) (dev->caps.fw_ver >> 16) & 0xffff,
- (int) dev->caps.fw_ver & 0xffff);
- mlx4_err(dev, "This driver version supports only revisions %d to %d.\n",
- MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV);
- err = -ENODEV;
- goto out;
- }
-
- if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS)
- dev->flags |= MLX4_FLAG_OLD_PORT_CMDS;
-
- MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
- cmd->max_cmds = 1 << lg;
-
- mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n",
- (int) (dev->caps.fw_ver >> 32),
- (int) (dev->caps.fw_ver >> 16) & 0xffff,
- (int) dev->caps.fw_ver & 0xffff,
- cmd_if_rev, cmd->max_cmds);
-
- MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET);
- MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
- MLX4_GET(fw->catas_bar, outbox, QUERY_FW_ERR_BAR_OFFSET);
- fw->catas_bar = (fw->catas_bar >> 6) * 2;
-
- mlx4_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x, BAR %d\n",
- (unsigned long long) fw->catas_offset, fw->catas_size, fw->catas_bar);
-
- MLX4_GET(fw->fw_pages, outbox, QUERY_FW_SIZE_OFFSET);
- MLX4_GET(fw->clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET);
- MLX4_GET(fw->clr_int_bar, outbox, QUERY_FW_CLR_INT_BAR_OFFSET);
- fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2;
-
- MLX4_GET(fw->comm_base, outbox, QUERY_FW_COMM_BASE_OFFSET);
- MLX4_GET(fw->comm_bar, outbox, QUERY_FW_COMM_BAR_OFFSET);
- fw->comm_bar = (fw->comm_bar >> 6) * 2;
- mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n",
- fw->comm_bar, (unsigned long long)fw->comm_base);
- mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
-
- MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET);
- MLX4_GET(fw->clock_bar, outbox, QUERY_FW_CLOCK_BAR);
- fw->clock_bar = (fw->clock_bar >> 6) * 2;
- mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n",
- fw->comm_bar, (unsigned long long)fw->comm_base);
-
- /*
- * Round up number of system pages needed in case
- * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
- */
- fw->fw_pages =
- ALIGN(fw->fw_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >>
- (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT);
-
- mlx4_dbg(dev, "Clear int @ %llx, BAR %d\n",
- (unsigned long long) fw->clr_int_base, fw->clr_int_bar);
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- u8 *outbuf;
- int err;
-
- outbuf = outbox->buf;
- err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_FW,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (err)
- return err;
-
- /* for slaves, set pci PPF ID to invalid and zero out everything
- * else except FW version */
- outbuf[0] = outbuf[1] = 0;
- memset(&outbuf[8], 0, QUERY_FW_OUT_SIZE - 8);
- outbuf[QUERY_FW_PPF_ID] = MLX4_INVALID_SLAVE_ID;
-
- return 0;
-}
-
-static void get_board_id(void *vsd, char *board_id, char *vsdstr)
-{
- int i;
-
-#define VSD_OFFSET_SIG1 0x00
-#define VSD_OFFSET_SIG2 0xde
-#define VSD_OFFSET_MLX_BOARD_ID 0xd0
-#define VSD_OFFSET_TS_BOARD_ID 0x20
-#define VSD_LEN 0xd0
-
-#define VSD_SIGNATURE_TOPSPIN 0x5ad
-
- memset(vsdstr, 0, MLX4_VSD_LEN);
-
- for (i = 0; i < VSD_LEN / 4; i++)
- ((u32 *)vsdstr)[i] =
- swab32(*(u32 *)(vsd + i * 4));
-
- memset(board_id, 0, MLX4_BOARD_ID_LEN);
-
- if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
- be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
- strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN);
- } else {
- /*
- * The board ID is a string but the firmware byte
- * swaps each 4-byte word before passing it back to
- * us. Therefore we need to swab it before printing.
- */
- for (i = 0; i < 4; ++i)
- ((u32 *) board_id)[i] =
- swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
- }
-}
-
-int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 *outbox;
- int err;
-
-#define QUERY_ADAPTER_OUT_SIZE 0x100
-#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
-#define QUERY_ADAPTER_VSD_OFFSET 0x20
-#define QUERY_ADAPTER_VSD_VENDOR_ID_OFFSET 0x1e
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
-
- err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (err)
- goto out;
-
- MLX4_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
-
- adapter->vsd_vendor_id = be16_to_cpup((u16 *)outbox +
- QUERY_ADAPTER_VSD_VENDOR_ID_OFFSET / 2);
-
- get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
- adapter->board_id, adapter->vsd);
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
-{
- struct mlx4_cmd_mailbox *mailbox;
- __be32 *inbox;
- u32 mw_enable;
- int err;
-
-#define INIT_HCA_IN_SIZE 0x200
-#define INIT_HCA_DRV_NAME_FOR_FW_MAX_SIZE 64
-#define INIT_HCA_VERSION_OFFSET 0x000
-#define INIT_HCA_VERSION 2
-#define INIT_HCA_CACHELINE_SZ_OFFSET 0x0e
-#define INIT_HCA_FLAGS_OFFSET 0x014
-#define INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET 0x018
-#define INIT_HCA_QPC_OFFSET 0x020
-#define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10)
-#define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17)
-#define INIT_HCA_SRQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x28)
-#define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f)
-#define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30)
-#define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37)
-#define INIT_HCA_EQE_CQE_OFFSETS (INIT_HCA_QPC_OFFSET + 0x38)
-#define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40)
-#define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50)
-#define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60)
-#define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67)
-#define INIT_HCA_RDMARC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70)
-#define INIT_HCA_LOG_RD_OFFSET (INIT_HCA_QPC_OFFSET + 0x77)
-#define INIT_HCA_MCAST_OFFSET 0x0c0
-#define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00)
-#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
-#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16)
-#define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18)
-#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
-#define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6
-#define INIT_HCA_DRIVER_VERSION_OFFSET 0x140
-#define INIT_HCA_FS_PARAM_OFFSET 0x1d0
-#define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00)
-#define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12)
-#define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b)
-#define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21)
-#define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22)
-#define INIT_HCA_FS_IB_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x25)
-#define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26)
-#define INIT_HCA_TPT_OFFSET 0x0f0
-#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
-#define INIT_HCA_TPT_MW_OFFSET (INIT_HCA_TPT_OFFSET + 0x08)
-#define INIT_HCA_TPT_MW_ENABLE (1 << 31)
-#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b)
-#define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10)
-#define INIT_HCA_CMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x18)
-#define INIT_HCA_UAR_OFFSET 0x120
-#define INIT_HCA_LOG_UAR_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0a)
-#define INIT_HCA_UAR_PAGE_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0b)
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
-
- memset(inbox, 0, INIT_HCA_IN_SIZE);
-
- *((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION;
-
- *((u8 *) mailbox->buf + INIT_HCA_CACHELINE_SZ_OFFSET) =
- ((ilog2(cache_line_size()) - 4) << 5) | (1 << 4);
-
-#if defined(__LITTLE_ENDIAN)
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1);
-#elif defined(__BIG_ENDIAN)
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1);
-#else
-#error Host endianness not defined
-#endif
- /* Check port for UD address vector: */
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1);
-
- /* Enable IPoIB checksumming if we can: */
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
-
- /* Enable QoS support if module parameter set */
- if (enable_qos)
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
-
- /* Enable fast drop performance optimization */
- if (dev->caps.fast_drop)
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 7);
-
- /* enable counters */
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS)
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4);
-
- /* CX3 is capable of extending CQEs\EQEs from 32 to 64 bytes */
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) {
- *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29);
- dev->caps.eqe_size = 64;
- dev->caps.eqe_factor = 1;
- } else {
- dev->caps.eqe_size = 32;
- dev->caps.eqe_factor = 0;
- }
-
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) {
- *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30);
- dev->caps.cqe_size = 64;
- dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE;
- } else {
- dev->caps.cqe_size = 32;
- }
-
- if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT)
- *(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1 << 31);
-
- if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DRIVER_VERSION_TO_FW) {
- strncpy((u8 *)mailbox->buf + INIT_HCA_DRIVER_VERSION_OFFSET,
- DRV_NAME_FOR_FW,
- INIT_HCA_DRV_NAME_FOR_FW_MAX_SIZE - 1);
- mlx4_dbg(dev, "Reporting Driver Version to FW: %s\n",
- (u8 *)mailbox->buf + INIT_HCA_DRIVER_VERSION_OFFSET);
- }
-
- /* QPC/EEC/CQC/EQC/RDMARC attributes */
-
- MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
- MLX4_PUT(inbox, param->log_num_qps, INIT_HCA_LOG_QP_OFFSET);
- MLX4_PUT(inbox, param->srqc_base, INIT_HCA_SRQC_BASE_OFFSET);
- MLX4_PUT(inbox, param->log_num_srqs, INIT_HCA_LOG_SRQ_OFFSET);
- MLX4_PUT(inbox, param->cqc_base, INIT_HCA_CQC_BASE_OFFSET);
- MLX4_PUT(inbox, param->log_num_cqs, INIT_HCA_LOG_CQ_OFFSET);
- MLX4_PUT(inbox, param->altc_base, INIT_HCA_ALTC_BASE_OFFSET);
- MLX4_PUT(inbox, param->auxc_base, INIT_HCA_AUXC_BASE_OFFSET);
- MLX4_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET);
- MLX4_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET);
- MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET);
- MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET);
-
- /* steering attributes */
- if (dev->caps.steering_mode ==
- MLX4_STEERING_MODE_DEVICE_MANAGED) {
- *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |=
- cpu_to_be32(1 <<
- INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN);
-
- MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET);
- MLX4_PUT(inbox, param->log_mc_entry_sz,
- INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
- MLX4_PUT(inbox, param->log_mc_table_sz,
- INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
- /* Enable Ethernet flow steering
- * with udp unicast and tcp unicast
- */
- MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN),
- INIT_HCA_FS_ETH_BITS_OFFSET);
- MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
- INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET);
- /* Enable IPoIB flow steering
- * with udp unicast and tcp unicast
- */
- MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN),
- INIT_HCA_FS_IB_BITS_OFFSET);
- MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
- INIT_HCA_FS_IB_NUM_ADDRS_OFFSET);
- } else {
- MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
- MLX4_PUT(inbox, param->log_mc_entry_sz,
- INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
- MLX4_PUT(inbox, param->log_mc_hash_sz,
- INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
- MLX4_PUT(inbox, param->log_mc_table_sz,
- INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
- if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
- MLX4_PUT(inbox, (u8) (1 << 3),
- INIT_HCA_UC_STEERING_OFFSET);
- }
-
- /* TPT attributes */
-
- MLX4_PUT(inbox, param->dmpt_base, INIT_HCA_DMPT_BASE_OFFSET);
- mw_enable = param->mw_enable ? INIT_HCA_TPT_MW_ENABLE : 0;
- MLX4_PUT(inbox, mw_enable, INIT_HCA_TPT_MW_OFFSET);
- MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET);
- MLX4_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET);
- MLX4_PUT(inbox, param->cmpt_base, INIT_HCA_CMPT_BASE_OFFSET);
-
- /* UAR attributes */
-
- MLX4_PUT(inbox, param->uar_page_sz, INIT_HCA_UAR_PAGE_SZ_OFFSET);
- MLX4_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET);
-
- err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000,
- MLX4_CMD_NATIVE);
-
- if (err)
- mlx4_err(dev, "INIT_HCA returns %d\n", err);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_QUERY_HCA(struct mlx4_dev *dev,
- struct mlx4_init_hca_param *param)
-{
- struct mlx4_cmd_mailbox *mailbox;
- __be32 *outbox;
- u32 dword_field;
- u32 mw_enable;
- int err;
- u8 byte_field;
-
-#define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04
-#define QUERY_HCA_CORE_CLOCK_OFFSET 0x0c
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
-
- err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
- MLX4_CMD_QUERY_HCA,
- MLX4_CMD_TIME_CLASS_B,
- !mlx4_is_slave(dev));
- if (err)
- goto out;
-
- MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET);
- MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET);
-
- /* QPC/EEC/CQC/EQC/RDMARC attributes */
-
- MLX4_GET(param->qpc_base, outbox, INIT_HCA_QPC_BASE_OFFSET);
- MLX4_GET(param->log_num_qps, outbox, INIT_HCA_LOG_QP_OFFSET);
- MLX4_GET(param->srqc_base, outbox, INIT_HCA_SRQC_BASE_OFFSET);
- MLX4_GET(param->log_num_srqs, outbox, INIT_HCA_LOG_SRQ_OFFSET);
- MLX4_GET(param->cqc_base, outbox, INIT_HCA_CQC_BASE_OFFSET);
- MLX4_GET(param->log_num_cqs, outbox, INIT_HCA_LOG_CQ_OFFSET);
- MLX4_GET(param->altc_base, outbox, INIT_HCA_ALTC_BASE_OFFSET);
- MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET);
- MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET);
- MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET);
- MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
- MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
-
- MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
- if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
- param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
- } else {
- MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET);
- if (byte_field & 0x8)
- param->steering_mode = MLX4_STEERING_MODE_B0;
- else
- param->steering_mode = MLX4_STEERING_MODE_A0;
- }
- /* steering attributes */
- if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
- MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
- MLX4_GET(param->log_mc_entry_sz, outbox,
- INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
- MLX4_GET(param->log_mc_table_sz, outbox,
- INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
- } else {
- MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
- MLX4_GET(param->log_mc_entry_sz, outbox,
- INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
- MLX4_GET(param->log_mc_hash_sz, outbox,
- INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
- MLX4_GET(param->log_mc_table_sz, outbox,
- INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
- }
-
- /* CX3 is capable of extending CQEs\EQEs from 32 to 64 bytes */
- MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS);
- if (byte_field & 0x20) /* 64-bytes eqe enabled */
- param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED;
- if (byte_field & 0x40) /* 64-bytes cqe enabled */
- param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED;
-
- /* TPT attributes */
-
- MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET);
- MLX4_GET(mw_enable, outbox, INIT_HCA_TPT_MW_OFFSET);
- param->mw_enable = (mw_enable & INIT_HCA_TPT_MW_ENABLE) ==
- INIT_HCA_TPT_MW_ENABLE;
- MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
- MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET);
- MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET);
-
- /* UAR attributes */
-
- MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
- MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- return err;
-}
-
-/* for IB-type ports only in SRIOV mode. Checks that both proxy QP0
- * and real QP0 are active, so that the paravirtualized QP0 is ready
- * to operate */
-static int check_qp0_state(struct mlx4_dev *dev, int function, int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- /* irrelevant if not infiniband */
- if (priv->mfunc.master.qp0_state[port].proxy_qp0_active &&
- priv->mfunc.master.qp0_state[port].qp0_active)
- return 1;
- return 0;
-}
-
-int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int port = vhcr->in_modifier;
- int err;
-
- if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port))
- return 0;
-
- if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
- /* Enable port only if it was previously disabled */
- if (!priv->mfunc.master.init_port_ref[port]) {
- err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (err)
- return err;
- }
- priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
- } else {
- if (slave == mlx4_master_func_num(dev)) {
- if (check_qp0_state(dev, slave, port) &&
- !priv->mfunc.master.qp0_state[port].port_active) {
- err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (err)
- return err;
- priv->mfunc.master.qp0_state[port].port_active = 1;
- priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
- }
- } else
- priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
- }
- ++priv->mfunc.master.init_port_ref[port];
- return 0;
-}
-
-int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 *inbox;
- int err;
- u32 flags;
- u16 field;
-
- if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
-#define INIT_PORT_IN_SIZE 256
-#define INIT_PORT_FLAGS_OFFSET 0x00
-#define INIT_PORT_FLAG_SIG (1 << 18)
-#define INIT_PORT_FLAG_NG (1 << 17)
-#define INIT_PORT_FLAG_G0 (1 << 16)
-#define INIT_PORT_VL_SHIFT 4
-#define INIT_PORT_PORT_WIDTH_SHIFT 8
-#define INIT_PORT_MTU_OFFSET 0x04
-#define INIT_PORT_MAX_GID_OFFSET 0x06
-#define INIT_PORT_MAX_PKEY_OFFSET 0x0a
-#define INIT_PORT_GUID0_OFFSET 0x10
-#define INIT_PORT_NODE_GUID_OFFSET 0x18
-#define INIT_PORT_SI_GUID_OFFSET 0x20
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
-
- memset(inbox, 0, INIT_PORT_IN_SIZE);
-
- flags = 0;
- flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT;
- flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
- MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET);
-
- field = 128 << dev->caps.ib_mtu_cap[port];
- MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET);
- field = dev->caps.gid_table_len[port];
- MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET);
- field = dev->caps.pkey_table_len[port];
- MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET);
-
- err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- } else
- err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_INIT_PORT);
-
-int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int port = vhcr->in_modifier;
- int err;
-
- if (!(priv->mfunc.master.slave_state[slave].init_port_mask &
- (1 << port)))
- return 0;
-
- if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB) {
- if (priv->mfunc.master.init_port_ref[port] == 1) {
- err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
- 1000, MLX4_CMD_NATIVE);
- if (err)
- return err;
- }
- priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
- } else {
- /* infiniband port */
- if (slave == mlx4_master_func_num(dev)) {
- if (!priv->mfunc.master.qp0_state[port].qp0_active &&
- priv->mfunc.master.qp0_state[port].port_active) {
- err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT,
- 1000, MLX4_CMD_NATIVE);
- if (err)
- return err;
- priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
- priv->mfunc.master.qp0_state[port].port_active = 0;
- }
- } else
- priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port);
- }
- --priv->mfunc.master.init_port_ref[port];
- return 0;
-}
-
-int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port)
-{
- return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000,
- MLX4_CMD_WRAPPED);
-}
-EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT);
-
-int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic)
-{
- return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA, 1000,
- MLX4_CMD_NATIVE);
-}
-
-int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages)
-{
- int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0,
- MLX4_CMD_SET_ICM_SIZE,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (ret)
- return ret;
-
- /*
- * Round up number of system pages needed in case
- * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
- */
- *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >>
- (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT);
-
- return 0;
-}
-
-int mlx4_NOP(struct mlx4_dev *dev)
-{
- /* Input modifier of 0x1f means "finish as soon as possible." */
- return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-}
-
-int mlx4_query_diag_counters(struct mlx4_dev *dev, int array_length,
- u8 op_modifier, u32 in_offset[],
- u32 counter_out[])
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 *outbox;
- int ret;
- int i;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- outbox = mailbox->buf;
-
- ret = mlx4_cmd_box(dev, 0, mailbox->dma, 0, op_modifier,
- MLX4_CMD_DIAG_RPRT, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (ret)
- goto out;
-
- for (i = 0; i < array_length; i++) {
- if (in_offset[i] > MLX4_MAILBOX_SIZE) {
- ret = -EINVAL;
- goto out;
- }
-
- MLX4_GET(counter_out[i], outbox, in_offset[i]);
- }
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return ret;
-}
-EXPORT_SYMBOL_GPL(mlx4_query_diag_counters);
-
-int mlx4_MOD_STAT_CFG_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- return -EPERM;
-}
-
-#define MLX4_WOL_SETUP_MODE (5 << 28)
-int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
-{
- u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
-
- return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
- MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
-}
-EXPORT_SYMBOL_GPL(mlx4_wol_read);
-
-int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
-{
- u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
-
- return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-}
-EXPORT_SYMBOL_GPL(mlx4_wol_write);
-
-enum {
- ADD_TO_MCG = 0x26,
-};
-
-
-void mlx4_opreq_action(struct work_struct *work)
-{
- struct mlx4_priv *priv = container_of(work, struct mlx4_priv, opreq_task);
- struct mlx4_dev *dev = &priv->dev;
- int num_tasks = atomic_read(&priv->opreq_count);
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm;
- u32 *outbox;
- u32 modifier;
- u16 token;
- u16 type_m;
- u16 type;
- int err;
- u32 num_qps;
- struct mlx4_qp qp;
- int i;
- u8 rem_mcg;
- u8 prot;
-
-#define GET_OP_REQ_MODIFIER_OFFSET 0x08
-#define GET_OP_REQ_TOKEN_OFFSET 0x14
-#define GET_OP_REQ_TYPE_OFFSET 0x1a
-#define GET_OP_REQ_DATA_OFFSET 0x20
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- mlx4_err(dev, "Failed to allocate mailbox for GET_OP_REQ\n");
- return;
- }
- outbox = mailbox->buf;
-
- while (num_tasks) {
- err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
- MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err) {
- mlx4_err(dev, "Failed to retrieve required operation: %d\n", err);
- return;
- }
- MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET);
- MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET);
- MLX4_GET(type, outbox, GET_OP_REQ_TYPE_OFFSET);
- type_m = type >> 12;
- type &= 0xfff;
-
- switch (type) {
- case ADD_TO_MCG:
- if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
- mlx4_warn(dev, "ADD MCG operation is not supported in "
- "DEVICE_MANAGED steerign mode\n");
- err = EPERM;
- break;
- }
- mgm = (struct mlx4_mgm *) ((u8 *) (outbox) + GET_OP_REQ_DATA_OFFSET);
- num_qps = be32_to_cpu(mgm->members_count) & MGM_QPN_MASK;
- rem_mcg = ((u8 *) (&mgm->members_count))[0] & 1;
- prot = ((u8 *) (&mgm->members_count))[0] >> 6;
-
- for (i = 0; i < num_qps; i++) {
- qp.qpn = be32_to_cpu(mgm->qp[i]);
- if (rem_mcg)
- err = mlx4_multicast_detach(dev, &qp, mgm->gid, prot, 0);
- else
- err = mlx4_multicast_attach(dev, &qp, mgm->gid, mgm->gid[5] ,0, prot, NULL);
- if (err)
- break;
- }
- break;
- default:
- mlx4_warn(dev, "Bad type for required operation\n");
- err = EINVAL;
- break;
- }
- err = mlx4_cmd(dev, 0, ((u32) err | cpu_to_be32(token) << 16), 1,
- MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err) {
- mlx4_err(dev, "Failed to acknowledge required request: %d\n", err);
- goto out;
- }
- memset(outbox, 0, 0xffc);
- num_tasks = atomic_dec_return(&priv->opreq_count);
- }
-
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
-}
diff --git a/sys/ofed/drivers/net/mlx4/fw.h b/sys/ofed/drivers/net/mlx4/fw.h
deleted file mode 100644
index 0efd047ec3ad..000000000000
--- a/sys/ofed/drivers/net/mlx4/fw.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2006, 2007 Cisco Systems. 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.
- */
-
-#ifndef MLX4_FW_H
-#define MLX4_FW_H
-
-#include "mlx4.h"
-#include "icm.h"
-
-struct mlx4_mod_stat_cfg {
- u8 log_pg_sz;
- u8 log_pg_sz_m;
-};
-
-struct mlx4_dev_cap {
- int max_srq_sz;
- int max_qp_sz;
- int reserved_qps;
- int max_qps;
- int reserved_srqs;
- int max_srqs;
- int max_cq_sz;
- int reserved_cqs;
- int max_cqs;
- int max_mpts;
- int reserved_eqs;
- int max_eqs;
- int reserved_mtts;
- int max_mrw_sz;
- int reserved_mrws;
- int max_mtt_seg;
- int max_requester_per_qp;
- int max_responder_per_qp;
- int max_rdma_global;
- int local_ca_ack_delay;
- int num_ports;
- u32 max_msg_sz;
- int ib_mtu[MLX4_MAX_PORTS + 1];
- int max_port_width[MLX4_MAX_PORTS + 1];
- int max_vl[MLX4_MAX_PORTS + 1];
- int max_gids[MLX4_MAX_PORTS + 1];
- int max_pkeys[MLX4_MAX_PORTS + 1];
- u64 def_mac[MLX4_MAX_PORTS + 1];
- u16 eth_mtu[MLX4_MAX_PORTS + 1];
- int trans_type[MLX4_MAX_PORTS + 1];
- int vendor_oui[MLX4_MAX_PORTS + 1];
- u16 wavelength[MLX4_MAX_PORTS + 1];
- u64 trans_code[MLX4_MAX_PORTS + 1];
- u16 stat_rate_support;
- int fs_log_max_ucast_qp_range_size;
- int fs_max_num_qp_per_entry;
- u64 flags;
- u64 flags2;
- int reserved_uars;
- int uar_size;
- int min_page_sz;
- int bf_reg_size;
- int bf_regs_per_page;
- int max_sq_sg;
- int max_sq_desc_sz;
- int max_rq_sg;
- int max_rq_desc_sz;
- int max_qp_per_mcg;
- int reserved_mgms;
- int max_mcgs;
- int reserved_pds;
- int max_pds;
- int reserved_xrcds;
- int max_xrcds;
- int qpc_entry_sz;
- int rdmarc_entry_sz;
- int altc_entry_sz;
- int aux_entry_sz;
- int srq_entry_sz;
- int cqc_entry_sz;
- int eqc_entry_sz;
- int dmpt_entry_sz;
- int cmpt_entry_sz;
- int mtt_entry_sz;
- int resize_srq;
- u32 bmme_flags;
- u32 reserved_lkey;
- u64 max_icm_sz;
- int max_gso_sz;
- int max_rss_tbl_sz;
- u8 supported_port_types[MLX4_MAX_PORTS + 1];
- u8 suggested_type[MLX4_MAX_PORTS + 1];
- u8 default_sense[MLX4_MAX_PORTS + 1];
- u8 log_max_macs[MLX4_MAX_PORTS + 1];
- u8 log_max_vlans[MLX4_MAX_PORTS + 1];
- u32 max_basic_counters;
- u32 sync_qp;
- u8 timestamp_support;
- u32 max_extended_counters;
-};
-
-struct mlx4_func_cap {
- u8 num_ports;
- u8 flags;
- u32 pf_context_behaviour;
- int qp_quota;
- int cq_quota;
- int srq_quota;
- int mpt_quota;
- int mtt_quota;
- int max_eq;
- int reserved_eq;
- int mcg_quota;
- u32 qp0_tunnel_qpn;
- u32 qp0_proxy_qpn;
- u32 qp1_tunnel_qpn;
- u32 qp1_proxy_qpn;
- u8 physical_port;
- u8 port_flags;
- u8 def_counter_index;
-};
-
-struct mlx4_adapter {
- u16 vsd_vendor_id;
- char board_id[MLX4_BOARD_ID_LEN];
- char vsd[MLX4_VSD_LEN];
- u8 inta_pin;
-};
-
-struct mlx4_init_hca_param {
- u64 qpc_base;
- u64 rdmarc_base;
- u64 auxc_base;
- u64 altc_base;
- u64 srqc_base;
- u64 cqc_base;
- u64 eqc_base;
- u64 mc_base;
- u64 dmpt_base;
- u64 cmpt_base;
- u64 mtt_base;
- u64 global_caps;
- u16 log_mc_entry_sz;
- u16 log_mc_hash_sz;
- u16 hca_core_clock;
- u8 log_num_qps;
- u8 log_num_srqs;
- u8 log_num_cqs;
- u8 log_num_eqs;
- u8 log_rd_per_qp;
- u8 log_mc_table_sz;
- u8 log_mpt_sz;
- u8 log_uar_sz;
- u8 uar_page_sz; /* log pg sz in 4k chunks */
- u8 mw_enable; /* Enable memory windows */
- u8 fs_hash_enable_bits;
- u8 steering_mode; /* for QUERY_HCA */
- u64 dev_cap_enabled;
-};
-
-struct mlx4_init_ib_param {
- int port_width;
- int vl_cap;
- int mtu_cap;
- u16 gid_cap;
- u16 pkey_cap;
- int set_guid0;
- u64 guid0;
- int set_node_guid;
- u64 node_guid;
- int set_si_guid;
- u64 si_guid;
-};
-
-struct mlx4_set_ib_param {
- int set_si_guid;
- int reset_qkey_viol;
- u64 si_guid;
- u32 cap_mask;
-};
-
-int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap);
-int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
- struct mlx4_func_cap *func_cap);
-int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm);
-int mlx4_UNMAP_FA(struct mlx4_dev *dev);
-int mlx4_RUN_FW(struct mlx4_dev *dev);
-int mlx4_QUERY_FW(struct mlx4_dev *dev);
-int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter);
-int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param);
-int mlx4_QUERY_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param);
-int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic);
-int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt);
-int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages);
-int mlx4_NOP(struct mlx4_dev *dev);
-int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg);
-void mlx4_opreq_action(struct work_struct *work);
-
-#endif /* MLX4_FW_H */
diff --git a/sys/ofed/drivers/net/mlx4/icm.c b/sys/ofed/drivers/net/mlx4/icm.c
deleted file mode 100644
index 25ae7b7fb8cc..000000000000
--- a/sys/ofed/drivers/net/mlx4/icm.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/math64.h>
-
-#include <linux/mlx4/cmd.h>
-
-#include "mlx4.h"
-#include "icm.h"
-#include "fw.h"
-
-/*
- * We allocate in as big chunks as we can, up to a maximum of 256 KB
- * per chunk.
- */
-enum {
- MLX4_ICM_ALLOC_SIZE = 1 << 18,
- MLX4_TABLE_CHUNK_SIZE = 1 << 18
-};
-
-static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk)
-{
- int i;
-
- if (chunk->nsg > 0)
- pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
-
- for (i = 0; i < chunk->npages; ++i)
- __free_pages(sg_page(&chunk->mem[i]),
- get_order(chunk->mem[i].length));
-}
-
-static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk)
-{
- int i;
-
- for (i = 0; i < chunk->npages; ++i)
- dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length,
- lowmem_page_address(sg_page(&chunk->mem[i])),
- sg_dma_address(&chunk->mem[i]));
-}
-
-void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent)
-{
- struct mlx4_icm_chunk *chunk, *tmp;
-
- if (!icm)
- return;
-
- list_for_each_entry_safe(chunk, tmp, &icm->chunk_list, list) {
- if (coherent)
- mlx4_free_icm_coherent(dev, chunk);
- else
- mlx4_free_icm_pages(dev, chunk);
-
- kfree(chunk);
- }
-
- kfree(icm);
-}
-
-static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order,
- gfp_t gfp_mask, int node)
-{
- struct page *page;
-
- page = alloc_pages_node(node, gfp_mask, order);
- if (!page) {
- page = alloc_pages(gfp_mask, order);
- if (!page)
- return -ENOMEM;
- }
-
- sg_set_page(mem, page, PAGE_SIZE << order, 0);
- return 0;
-}
-
-static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
- int order, gfp_t gfp_mask)
-{
- void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order,
- &sg_dma_address(mem), gfp_mask);
- if (!buf)
- return -ENOMEM;
-
- sg_set_buf(mem, buf, PAGE_SIZE << order);
- BUG_ON(mem->offset);
- sg_dma_len(mem) = PAGE_SIZE << order;
- return 0;
-}
-
-struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
- gfp_t gfp_mask, int coherent)
-{
- struct mlx4_icm *icm;
- struct mlx4_icm_chunk *chunk = NULL;
- int cur_order;
- int ret;
-
- /* We use sg_set_buf for coherent allocs, which assumes low memory */
- BUG_ON(coherent && (gfp_mask & __GFP_HIGHMEM));
-
- icm = kmalloc_node(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN),
- dev->numa_node);
- if (!icm) {
- icm = kmalloc(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
- if (!icm)
- return NULL;
- }
-
- icm->refcount = 0;
- INIT_LIST_HEAD(&icm->chunk_list);
-
- cur_order = get_order(MLX4_ICM_ALLOC_SIZE);
-
- while (npages > 0) {
- if (!chunk) {
- chunk = kmalloc_node(sizeof *chunk,
- gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN),
- dev->numa_node);
- if (!chunk) {
- chunk = kmalloc(sizeof *chunk,
- gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
- if (!chunk)
- goto fail;
- }
-
- sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN);
- chunk->npages = 0;
- chunk->nsg = 0;
- list_add_tail(&chunk->list, &icm->chunk_list);
- }
-
- while (1 << cur_order > npages)
- --cur_order;
-
- if (coherent)
- ret = mlx4_alloc_icm_coherent(&dev->pdev->dev,
- &chunk->mem[chunk->npages],
- cur_order, gfp_mask);
- else
- ret = mlx4_alloc_icm_pages(&chunk->mem[chunk->npages],
- cur_order, gfp_mask,
- dev->numa_node);
-
- if (ret) {
- if (--cur_order < 0)
- goto fail;
- else
- continue;
- }
-
- ++chunk->npages;
-
- if (coherent)
- ++chunk->nsg;
- else if (chunk->npages == MLX4_ICM_CHUNK_LEN) {
- chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
- chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
-
- if (chunk->nsg <= 0)
- goto fail;
- }
-
- if (chunk->npages == MLX4_ICM_CHUNK_LEN)
- chunk = NULL;
-
- npages -= 1 << cur_order;
- }
-
- if (!coherent && chunk) {
- chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
- chunk->npages,
- PCI_DMA_BIDIRECTIONAL);
-
- if (chunk->nsg <= 0)
- goto fail;
- }
-
- return icm;
-
-fail:
- mlx4_free_icm(dev, icm, coherent);
- return NULL;
-}
-
-static int mlx4_MAP_ICM(struct mlx4_dev *dev, struct mlx4_icm *icm, u64 virt)
-{
- return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM, icm, virt);
-}
-
-static int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count)
-{
- return mlx4_cmd(dev, virt, page_count, 0, MLX4_CMD_UNMAP_ICM,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-}
-
-int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm)
-{
- return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM_AUX, icm, -1);
-}
-
-int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev)
-{
- return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_ICM_AUX,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-}
-
-int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
-{
- u32 i = (obj & (table->num_obj - 1)) /
- (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
- int ret = 0;
-
- mutex_lock(&table->mutex);
-
- if (table->icm[i]) {
- ++table->icm[i]->refcount;
- goto out;
- }
-
- table->icm[i] = mlx4_alloc_icm(dev, MLX4_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
- (table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
- __GFP_NOWARN, table->coherent);
- if (!table->icm[i]) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (mlx4_MAP_ICM(dev, table->icm[i], table->virt +
- (u64) i * MLX4_TABLE_CHUNK_SIZE)) {
- mlx4_free_icm(dev, table->icm[i], table->coherent);
- table->icm[i] = NULL;
- ret = -ENOMEM;
- goto out;
- }
-
- ++table->icm[i]->refcount;
-
-out:
- mutex_unlock(&table->mutex);
- return ret;
-}
-
-void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
-{
- u32 i;
- u64 offset;
-
- i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
-
- mutex_lock(&table->mutex);
-
- if (--table->icm[i]->refcount == 0) {
- offset = (u64) i * MLX4_TABLE_CHUNK_SIZE;
-
- if (!mlx4_UNMAP_ICM(dev, table->virt + offset,
- MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE)) {
- mlx4_free_icm(dev, table->icm[i], table->coherent);
- table->icm[i] = NULL;
- } else {
- pr_warn("mlx4_core: mlx4_UNMAP_ICM failed.\n");
- }
- }
-
- mutex_unlock(&table->mutex);
-}
-
-void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
- dma_addr_t *dma_handle)
-{
- int offset, dma_offset, i;
- u64 idx;
- struct mlx4_icm_chunk *chunk;
- struct mlx4_icm *icm;
- struct page *page = NULL;
-
- if (!table->lowmem)
- return NULL;
-
- mutex_lock(&table->mutex);
-
- idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size;
- icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE];
- dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE;
-
- if (!icm)
- goto out;
-
- list_for_each_entry(chunk, &icm->chunk_list, list) {
- for (i = 0; i < chunk->npages; ++i) {
- if (dma_handle && dma_offset >= 0) {
- if (sg_dma_len(&chunk->mem[i]) > dma_offset)
- *dma_handle = sg_dma_address(&chunk->mem[i]) +
- dma_offset;
- dma_offset -= sg_dma_len(&chunk->mem[i]);
- }
- /*
- * DMA mapping can merge pages but not split them,
- * so if we found the page, dma_handle has already
- * been assigned to.
- */
- if (chunk->mem[i].length > offset) {
- page = sg_page(&chunk->mem[i]);
- goto out;
- }
- offset -= chunk->mem[i].length;
- }
- }
-
-out:
- mutex_unlock(&table->mutex);
- return page ? lowmem_page_address(page) + offset : NULL;
-}
-
-int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u32 start, u32 end)
-{
- int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size;
- int err;
- u32 i;
-
- for (i = start; i <= end; i += inc) {
- err = mlx4_table_get(dev, table, i);
- if (err)
- goto fail;
- }
-
- return 0;
-
-fail:
- while (i > start) {
- i -= inc;
- mlx4_table_put(dev, table, i);
- }
-
- return err;
-}
-
-void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u32 start, u32 end)
-{
- u32 i;
-
- for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size)
- mlx4_table_put(dev, table, i);
-}
-
-int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u64 virt, int obj_size, u64 nobj, int reserved,
- int use_lowmem, int use_coherent)
-{
- int obj_per_chunk;
- int num_icm;
- unsigned chunk_size;
- int i;
- u64 size;
-
- obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size;
- num_icm = div_u64((nobj + obj_per_chunk - 1), obj_per_chunk);
-
- table->icm = kcalloc(num_icm, sizeof *table->icm, GFP_KERNEL);
- if (!table->icm)
- return -ENOMEM;
- table->virt = virt;
- table->num_icm = num_icm;
- table->num_obj = nobj;
- table->obj_size = obj_size;
- table->lowmem = use_lowmem;
- table->coherent = use_coherent;
- mutex_init(&table->mutex);
-
- size = (u64) nobj * obj_size;
- for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {
- chunk_size = MLX4_TABLE_CHUNK_SIZE;
- if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > size)
- chunk_size = PAGE_ALIGN(size -
- i * MLX4_TABLE_CHUNK_SIZE);
-
- table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT,
- (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
- __GFP_NOWARN, use_coherent);
- if (!table->icm[i])
- goto err;
- if (mlx4_MAP_ICM(dev, table->icm[i], virt + i * MLX4_TABLE_CHUNK_SIZE)) {
- mlx4_free_icm(dev, table->icm[i], use_coherent);
- table->icm[i] = NULL;
- goto err;
- }
-
- /*
- * Add a reference to this ICM chunk so that it never
- * gets freed (since it contains reserved firmware objects).
- */
- ++table->icm[i]->refcount;
- }
-
- return 0;
-
-err:
- for (i = 0; i < num_icm; ++i)
- if (table->icm[i]) {
- if (!mlx4_UNMAP_ICM(dev,
- virt + i * MLX4_TABLE_CHUNK_SIZE,
- MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE)) {
- mlx4_free_icm(dev, table->icm[i], use_coherent);
- } else {
- pr_warn("mlx4_core: mlx4_UNMAP_ICM failed.\n");
- return -ENOMEM;
- }
- }
- kfree(table->icm);
-
- return -ENOMEM;
-}
-
-void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table)
-{
- int i, err = 0;
-
- for (i = 0; i < table->num_icm; ++i)
- if (table->icm[i]) {
- err = mlx4_UNMAP_ICM(dev,
- table->virt + i * MLX4_TABLE_CHUNK_SIZE,
- MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
- if (!err) {
- mlx4_free_icm(dev, table->icm[i],
- table->coherent);
- } else {
- pr_warn("mlx4_core: mlx4_UNMAP_ICM failed.\n");
- break;
- }
- }
-
- if (!err)
- kfree(table->icm);
-}
diff --git a/sys/ofed/drivers/net/mlx4/icm.h b/sys/ofed/drivers/net/mlx4/icm.h
deleted file mode 100644
index f7a2537bfbc0..000000000000
--- a/sys/ofed/drivers/net/mlx4/icm.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#ifndef MLX4_ICM_H
-#define MLX4_ICM_H
-
-#include <linux/list.h>
-#include <linux/pci.h>
-#include <linux/mutex.h>
-#include <linux/scatterlist.h>
-
-#define MLX4_ICM_CHUNK_LEN \
- ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \
- (sizeof (struct scatterlist)))
-
-enum {
- MLX4_ICM_PAGE_SHIFT = 12,
- MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT,
-};
-
-struct mlx4_icm_chunk {
- struct list_head list;
- int npages;
- int nsg;
- struct scatterlist mem[MLX4_ICM_CHUNK_LEN];
-};
-
-struct mlx4_icm {
- struct list_head chunk_list;
- int refcount;
-};
-
-struct mlx4_icm_iter {
- struct mlx4_icm *icm;
- struct mlx4_icm_chunk *chunk;
- int page_idx;
-};
-
-struct mlx4_dev;
-
-struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
- gfp_t gfp_mask, int coherent);
-void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent);
-
-int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
-void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
-int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u32 start, u32 end);
-void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u32 start, u32 end);
-int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u64 virt, int obj_size, u64 nobj, int reserved,
- int use_lowmem, int use_coherent);
-void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);
-void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle);
-
-static inline void mlx4_icm_first(struct mlx4_icm *icm,
- struct mlx4_icm_iter *iter)
-{
- iter->icm = icm;
- iter->chunk = list_empty(&icm->chunk_list) ?
- NULL : list_entry(icm->chunk_list.next,
- struct mlx4_icm_chunk, list);
- iter->page_idx = 0;
-}
-
-static inline int mlx4_icm_last(struct mlx4_icm_iter *iter)
-{
- return !iter->chunk;
-}
-
-static inline void mlx4_icm_next(struct mlx4_icm_iter *iter)
-{
- if (++iter->page_idx >= iter->chunk->nsg) {
- if (iter->chunk->list.next == &iter->icm->chunk_list) {
- iter->chunk = NULL;
- return;
- }
-
- iter->chunk = list_entry(iter->chunk->list.next,
- struct mlx4_icm_chunk, list);
- iter->page_idx = 0;
- }
-}
-
-static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter)
-{
- return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
-}
-
-static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter)
-{
- return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
-}
-
-int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
-int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);
-
-#endif /* MLX4_ICM_H */
diff --git a/sys/ofed/drivers/net/mlx4/intf.c b/sys/ofed/drivers/net/mlx4/intf.c
deleted file mode 100644
index 141629801d2f..000000000000
--- a/sys/ofed/drivers/net/mlx4/intf.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008, 2014 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.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include "mlx4.h"
-
-struct mlx4_device_context {
- struct list_head list;
- struct mlx4_interface *intf;
- void *context;
-};
-
-static LIST_HEAD(intf_list);
-static LIST_HEAD(dev_list);
-static DEFINE_MUTEX(intf_mutex);
-
-static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
-{
- struct mlx4_device_context *dev_ctx;
-
- dev_ctx = kmalloc(sizeof *dev_ctx, GFP_KERNEL);
- if (!dev_ctx)
- return;
-
- dev_ctx->intf = intf;
- dev_ctx->context = intf->add(&priv->dev);
-
- if (dev_ctx->context) {
- spin_lock_irq(&priv->ctx_lock);
- list_add_tail(&dev_ctx->list, &priv->ctx_list);
- spin_unlock_irq(&priv->ctx_lock);
- } else
- kfree(dev_ctx);
-}
-
-static void mlx4_remove_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
-{
- struct mlx4_device_context *dev_ctx;
-
- list_for_each_entry(dev_ctx, &priv->ctx_list, list)
- if (dev_ctx->intf == intf) {
- spin_lock_irq(&priv->ctx_lock);
- list_del(&dev_ctx->list);
- spin_unlock_irq(&priv->ctx_lock);
-
- intf->remove(&priv->dev, dev_ctx->context);
- kfree(dev_ctx);
- return;
- }
-}
-
-int mlx4_register_interface(struct mlx4_interface *intf)
-{
- struct mlx4_priv *priv;
-
- if (!intf->add || !intf->remove)
- return -EINVAL;
-
- mutex_lock(&intf_mutex);
-
- list_add_tail(&intf->list, &intf_list);
- list_for_each_entry(priv, &dev_list, dev_list)
- mlx4_add_device(intf, priv);
-
- mutex_unlock(&intf_mutex);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_register_interface);
-
-void mlx4_unregister_interface(struct mlx4_interface *intf)
-{
- struct mlx4_priv *priv;
-
- mutex_lock(&intf_mutex);
-
- list_for_each_entry(priv, &dev_list, dev_list)
- mlx4_remove_device(intf, priv);
-
- list_del(&intf->list);
-
- mutex_unlock(&intf_mutex);
-}
-EXPORT_SYMBOL_GPL(mlx4_unregister_interface);
-
-void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type,
- unsigned long param)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_device_context *dev_ctx;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->ctx_lock, flags);
-
- list_for_each_entry(dev_ctx, &priv->ctx_list, list)
- if (dev_ctx->intf->event)
- dev_ctx->intf->event(dev, dev_ctx->context, type, param);
-
- spin_unlock_irqrestore(&priv->ctx_lock, flags);
-}
-
-int mlx4_register_device(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_interface *intf;
-
- mutex_lock(&intf_mutex);
-
- list_add_tail(&priv->dev_list, &dev_list);
- list_for_each_entry(intf, &intf_list, list)
- mlx4_add_device(intf, priv);
-
- mutex_unlock(&intf_mutex);
- if (!mlx4_is_slave(dev))
- mlx4_start_catas_poll(dev);
-
- return 0;
-}
-
-void mlx4_unregister_device(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_interface *intf;
-
- if (!mlx4_is_slave(dev))
- mlx4_stop_catas_poll(dev);
- mutex_lock(&intf_mutex);
-
- list_for_each_entry(intf, &intf_list, list)
- mlx4_remove_device(intf, priv);
-
- list_del_init(&priv->dev_list);
-
- mutex_unlock(&intf_mutex);
-}
-
-void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_device_context *dev_ctx;
- unsigned long flags;
- void *result = NULL;
-
- spin_lock_irqsave(&priv->ctx_lock, flags);
-
- list_for_each_entry(dev_ctx, &priv->ctx_list, list)
- if (dev_ctx->intf->protocol == proto && dev_ctx->intf->get_dev) {
- result = dev_ctx->intf->get_dev(dev, dev_ctx->context, port);
- break;
- }
-
- spin_unlock_irqrestore(&priv->ctx_lock, flags);
-
- return result;
-}
-EXPORT_SYMBOL_GPL(mlx4_get_protocol_dev);
diff --git a/sys/ofed/drivers/net/mlx4/main.c b/sys/ofed/drivers/net/mlx4/main.c
deleted file mode 100644
index 78e8f1bb585e..000000000000
--- a/sys/ofed/drivers/net/mlx4/main.c
+++ /dev/null
@@ -1,3883 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#define LINUXKPI_PARAM_PREFIX mlx4_
-
-#include <linux/kmod.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/io-mapping.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-
-#include <linux/mlx4/device.h>
-#include <linux/mlx4/doorbell.h>
-
-#include "mlx4.h"
-#include "fw.h"
-#include "icm.h"
-#include "mlx4_stats.h"
-
-/* Mellanox ConnectX HCA low-level driver */
-
-struct workqueue_struct *mlx4_wq;
-
-#ifdef CONFIG_MLX4_DEBUG
-
-int mlx4_debug_level = 0;
-module_param_named(debug_level, mlx4_debug_level, int, 0644);
-MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
-
-#endif /* CONFIG_MLX4_DEBUG */
-
-#ifdef CONFIG_PCI_MSI
-
-static int msi_x = 1;
-module_param(msi_x, int, 0444);
-MODULE_PARM_DESC(msi_x, "0 - don't use MSI-X, 1 - use MSI-X, >1 - limit number of MSI-X irqs to msi_x (non-SRIOV only)");
-
-#else /* CONFIG_PCI_MSI */
-
-#define msi_x (0)
-
-#endif /* CONFIG_PCI_MSI */
-
-static int enable_sys_tune = 0;
-module_param(enable_sys_tune, int, 0444);
-MODULE_PARM_DESC(enable_sys_tune, "Tune the cpu's for better performance (default 0)");
-
-int mlx4_blck_lb = 1;
-module_param_named(block_loopback, mlx4_blck_lb, int, 0644);
-MODULE_PARM_DESC(block_loopback, "Block multicast loopback packets if > 0 "
- "(default: 1)");
-enum {
- DEFAULT_DOMAIN = 0,
- BDF_STR_SIZE = 8, /* bb:dd.f- */
- DBDF_STR_SIZE = 13 /* mmmm:bb:dd.f- */
-};
-
-enum {
- NUM_VFS,
- PROBE_VF,
- PORT_TYPE_ARRAY
-};
-
-enum {
- VALID_DATA,
- INVALID_DATA,
- INVALID_STR
-};
-
-struct param_data {
- int id;
- struct mlx4_dbdf2val_lst dbdf2val;
-};
-
-static struct param_data num_vfs = {
- .id = NUM_VFS,
- .dbdf2val = {
- .name = "num_vfs param",
- .num_vals = 1,
- .def_val = {0},
- .range = {0, MLX4_MAX_NUM_VF}
- }
-};
-module_param_string(num_vfs, num_vfs.dbdf2val.str,
- sizeof(num_vfs.dbdf2val.str), 0444);
-MODULE_PARM_DESC(num_vfs,
- "Either single value (e.g. '5') to define uniform num_vfs value for all devices functions\n"
- "\t\tor a string to map device function numbers to their num_vfs values (e.g. '0000:04:00.0-5,002b:1c:0b.a-15').\n"
- "\t\tHexadecimal digits for the device function (e.g. 002b:1c:0b.a) and decimal for num_vfs value (e.g. 15).");
-
-static struct param_data probe_vf = {
- .id = PROBE_VF,
- .dbdf2val = {
- .name = "probe_vf param",
- .num_vals = 1,
- .def_val = {0},
- .range = {0, MLX4_MAX_NUM_VF}
- }
-};
-module_param_string(probe_vf, probe_vf.dbdf2val.str,
- sizeof(probe_vf.dbdf2val.str), 0444);
-MODULE_PARM_DESC(probe_vf,
- "Either single value (e.g. '3') to define uniform number of VFs to probe by the pf driver for all devices functions\n"
- "\t\tor a string to map device function numbers to their probe_vf values (e.g. '0000:04:00.0-3,002b:1c:0b.a-13').\n"
- "\t\tHexadecimal digits for the device function (e.g. 002b:1c:0b.a) and decimal for probe_vf value (e.g. 13).");
-
-int mlx4_log_num_mgm_entry_size = MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE;
-
-module_param_named(log_num_mgm_entry_size,
- mlx4_log_num_mgm_entry_size, int, 0444);
-MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
- " of qp per mcg, for example:"
- " 10 gives 248.range: 7 <="
- " log_num_mgm_entry_size <= 12."
- " To activate device managed"
- " flow steering when available, set to -1");
-
-static int high_rate_steer;
-module_param(high_rate_steer, int, 0444);
-MODULE_PARM_DESC(high_rate_steer, "Enable steering mode for higher packet rate"
- " (default off)");
-
-static int fast_drop;
-module_param_named(fast_drop, fast_drop, int, 0444);
-MODULE_PARM_DESC(fast_drop,
- "Enable fast packet drop when no receive WQEs are posted");
-
-int mlx4_enable_64b_cqe_eqe = 1;
-module_param_named(enable_64b_cqe_eqe, mlx4_enable_64b_cqe_eqe, int, 0644);
-MODULE_PARM_DESC(enable_64b_cqe_eqe,
- "Enable 64 byte CQEs/EQEs when the FW supports this if non-zero (default: 1)");
-
-#define HCA_GLOBAL_CAP_MASK 0
-
-#define PF_CONTEXT_BEHAVIOUR_MASK MLX4_FUNC_CAP_64B_EQE_CQE
-
-static char mlx4_version[] __devinitdata =
- DRV_NAME ": Mellanox ConnectX VPI driver v"
- DRV_VERSION " (" DRV_RELDATE ")\n";
-
-static int log_num_mac = 7;
-module_param_named(log_num_mac, log_num_mac, int, 0444);
-MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
-
-static int log_num_vlan;
-module_param_named(log_num_vlan, log_num_vlan, int, 0444);
-MODULE_PARM_DESC(log_num_vlan,
- "(Obsolete) Log2 max number of VLANs per ETH port (0-7)");
-/* Log2 max number of VLANs per ETH port (0-7) */
-#define MLX4_LOG_NUM_VLANS 7
-
-int log_mtts_per_seg = ilog2(1);
-module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
-MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment "
- "(0-7) (default: 0)");
-
-static struct param_data port_type_array = {
- .id = PORT_TYPE_ARRAY,
- .dbdf2val = {
- .name = "port_type_array param",
- .num_vals = 2,
- .def_val = {MLX4_PORT_TYPE_ETH, MLX4_PORT_TYPE_ETH},
- .range = {MLX4_PORT_TYPE_IB, MLX4_PORT_TYPE_NA}
- }
-};
-module_param_string(port_type_array, port_type_array.dbdf2val.str,
- sizeof(port_type_array.dbdf2val.str), 0444);
-MODULE_PARM_DESC(port_type_array,
- "Either pair of values (e.g. '1,2') to define uniform port1/port2 types configuration for all devices functions\n"
- "\t\tor a string to map device function numbers to their pair of port types values (e.g. '0000:04:00.0-1;2,002b:1c:0b.a-1;1').\n"
- "\t\tValid port types: 1-ib, 2-eth, 3-auto, 4-N/A\n"
- "\t\tIn case that only one port is available use the N/A port type for port2 (e.g '1,4').");
-
-
-struct mlx4_port_config {
- struct list_head list;
- enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1];
- struct pci_dev *pdev;
-};
-
-#define MLX4_LOG_NUM_MTT 20
-/* We limit to 30 as of a bit map issue which uses int and not uint.
- see mlx4_buddy_init -> bitmap_zero which gets int.
-*/
-#define MLX4_MAX_LOG_NUM_MTT 30
-static struct mlx4_profile mod_param_profile = {
- .num_qp = 19,
- .num_srq = 16,
- .rdmarc_per_qp = 4,
- .num_cq = 16,
- .num_mcg = 13,
- .num_mpt = 19,
- .num_mtt_segs = 0, /* max(20, 2*MTTs for host memory)) */
-};
-
-module_param_named(log_num_qp, mod_param_profile.num_qp, int, 0444);
-MODULE_PARM_DESC(log_num_qp, "log maximum number of QPs per HCA (default: 19)");
-
-module_param_named(log_num_srq, mod_param_profile.num_srq, int, 0444);
-MODULE_PARM_DESC(log_num_srq, "log maximum number of SRQs per HCA "
- "(default: 16)");
-
-module_param_named(log_rdmarc_per_qp, mod_param_profile.rdmarc_per_qp, int,
- 0444);
-MODULE_PARM_DESC(log_rdmarc_per_qp, "log number of RDMARC buffers per QP "
- "(default: 4)");
-
-module_param_named(log_num_cq, mod_param_profile.num_cq, int, 0444);
-MODULE_PARM_DESC(log_num_cq, "log maximum number of CQs per HCA (default: 16)");
-
-module_param_named(log_num_mcg, mod_param_profile.num_mcg, int, 0444);
-MODULE_PARM_DESC(log_num_mcg, "log maximum number of multicast groups per HCA "
- "(default: 13)");
-
-module_param_named(log_num_mpt, mod_param_profile.num_mpt, int, 0444);
-MODULE_PARM_DESC(log_num_mpt,
- "log maximum number of memory protection table entries per "
- "HCA (default: 19)");
-
-module_param_named(log_num_mtt, mod_param_profile.num_mtt_segs, int, 0444);
-MODULE_PARM_DESC(log_num_mtt,
- "log maximum number of memory translation table segments per "
- "HCA (default: max(20, 2*MTTs for register all of the host memory limited to 30))");
-
-enum {
- MLX4_IF_STATE_BASIC,
- MLX4_IF_STATE_EXTENDED
-};
-
-static inline u64 dbdf_to_u64(int domain, int bus, int dev, int fn)
-{
- return (domain << 20) | (bus << 12) | (dev << 4) | fn;
-}
-
-static inline void pr_bdf_err(const char *dbdf, const char *pname)
-{
- pr_warn("mlx4_core: '%s' is not valid bdf in '%s'\n", dbdf, pname);
-}
-
-static inline void pr_val_err(const char *dbdf, const char *pname,
- const char *val)
-{
- pr_warn("mlx4_core: value '%s' of bdf '%s' in '%s' is not valid\n"
- , val, dbdf, pname);
-}
-
-static inline void pr_out_of_range_bdf(const char *dbdf, int val,
- struct mlx4_dbdf2val_lst *dbdf2val)
-{
- pr_warn("mlx4_core: value %d in bdf '%s' of '%s' is out of its valid range (%d,%d)\n"
- , val, dbdf, dbdf2val->name , dbdf2val->range.min,
- dbdf2val->range.max);
-}
-
-static inline void pr_out_of_range(struct mlx4_dbdf2val_lst *dbdf2val)
-{
- pr_warn("mlx4_core: value of '%s' is out of its valid range (%d,%d)\n"
- , dbdf2val->name , dbdf2val->range.min, dbdf2val->range.max);
-}
-
-static inline int is_in_range(int val, struct mlx4_range *r)
-{
- return (val >= r->min && val <= r->max);
-}
-
-static int update_defaults(struct param_data *pdata)
-{
- long int val[MLX4_MAX_BDF_VALS];
- int ret;
- char *t, *p = pdata->dbdf2val.str;
- char sval[32];
- int val_len;
-
- if (!strlen(p) || strchr(p, ':') || strchr(p, '.') || strchr(p, ';'))
- return INVALID_STR;
-
- switch (pdata->id) {
- case PORT_TYPE_ARRAY:
- t = strchr(p, ',');
- if (!t || t == p || (t - p) > sizeof(sval))
- return INVALID_STR;
-
- val_len = t - p;
- strncpy(sval, p, val_len);
- sval[val_len] = 0;
-
- ret = kstrtol(sval, 0, &val[0]);
- if (ret == -EINVAL)
- return INVALID_STR;
- if (ret || !is_in_range(val[0], &pdata->dbdf2val.range)) {
- pr_out_of_range(&pdata->dbdf2val);
- return INVALID_DATA;
- }
-
- ret = kstrtol(t + 1, 0, &val[1]);
- if (ret == -EINVAL)
- return INVALID_STR;
- if (ret || !is_in_range(val[1], &pdata->dbdf2val.range)) {
- pr_out_of_range(&pdata->dbdf2val);
- return INVALID_DATA;
- }
-
- pdata->dbdf2val.tbl[0].val[0] = val[0];
- pdata->dbdf2val.tbl[0].val[1] = val[1];
- break;
-
- case NUM_VFS:
- case PROBE_VF:
- ret = kstrtol(p, 0, &val[0]);
- if (ret == -EINVAL)
- return INVALID_STR;
- if (ret || !is_in_range(val[0], &pdata->dbdf2val.range)) {
- pr_out_of_range(&pdata->dbdf2val);
- return INVALID_DATA;
- }
- pdata->dbdf2val.tbl[0].val[0] = val[0];
- break;
- }
- pdata->dbdf2val.tbl[1].dbdf = MLX4_ENDOF_TBL;
-
- return VALID_DATA;
-}
-
-int mlx4_fill_dbdf2val_tbl(struct mlx4_dbdf2val_lst *dbdf2val_lst)
-{
- int domain, bus, dev, fn;
- u64 dbdf;
- char *p, *t, *v;
- char tmp[32];
- char sbdf[32];
- char sep = ',';
- int j, k, str_size, i = 1;
- int prfx_size;
-
- p = dbdf2val_lst->str;
-
- for (j = 0; j < dbdf2val_lst->num_vals; j++)
- dbdf2val_lst->tbl[0].val[j] = dbdf2val_lst->def_val[j];
- dbdf2val_lst->tbl[1].dbdf = MLX4_ENDOF_TBL;
-
- str_size = strlen(dbdf2val_lst->str);
-
- if (str_size == 0)
- return 0;
-
- while (strlen(p)) {
- prfx_size = BDF_STR_SIZE;
- sbdf[prfx_size] = 0;
- strncpy(sbdf, p, prfx_size);
- domain = DEFAULT_DOMAIN;
- if (sscanf(sbdf, "%02x:%02x.%x-", &bus, &dev, &fn) != 3) {
- prfx_size = DBDF_STR_SIZE;
- sbdf[prfx_size] = 0;
- strncpy(sbdf, p, prfx_size);
- if (sscanf(sbdf, "%04x:%02x:%02x.%x-", &domain, &bus,
- &dev, &fn) != 4) {
- pr_bdf_err(sbdf, dbdf2val_lst->name);
- goto err;
- }
- sprintf(tmp, "%04x:%02x:%02x.%x-", domain, bus, dev,
- fn);
- } else {
- sprintf(tmp, "%02x:%02x.%x-", bus, dev, fn);
- }
-
- if (strnicmp(sbdf, tmp, sizeof(tmp))) {
- pr_bdf_err(sbdf, dbdf2val_lst->name);
- goto err;
- }
-
- dbdf = dbdf_to_u64(domain, bus, dev, fn);
-
- for (j = 1; j < i; j++)
- if (dbdf2val_lst->tbl[j].dbdf == dbdf) {
- pr_warn("mlx4_core: in '%s', %s appears multiple times\n"
- , dbdf2val_lst->name, sbdf);
- goto err;
- }
-
- if (i >= MLX4_DEVS_TBL_SIZE) {
- pr_warn("mlx4_core: Too many devices in '%s'\n"
- , dbdf2val_lst->name);
- goto err;
- }
-
- p += prfx_size;
- t = strchr(p, sep);
- t = t ? t : p + strlen(p);
- if (p >= t) {
- pr_val_err(sbdf, dbdf2val_lst->name, "");
- goto err;
- }
-
- for (k = 0; k < dbdf2val_lst->num_vals; k++) {
- char sval[32];
- long int val;
- int ret, val_len;
- char vsep = ';';
-
- v = (k == dbdf2val_lst->num_vals - 1) ? t : strchr(p, vsep);
- if (!v || v > t || v == p || (v - p) > sizeof(sval)) {
- pr_val_err(sbdf, dbdf2val_lst->name, p);
- goto err;
- }
- val_len = v - p;
- strncpy(sval, p, val_len);
- sval[val_len] = 0;
-
- ret = kstrtol(sval, 0, &val);
- if (ret) {
- if (strchr(p, vsep))
- pr_warn("mlx4_core: too many vals in bdf '%s' of '%s'\n"
- , sbdf, dbdf2val_lst->name);
- else
- pr_val_err(sbdf, dbdf2val_lst->name,
- sval);
- goto err;
- }
- if (!is_in_range(val, &dbdf2val_lst->range)) {
- pr_out_of_range_bdf(sbdf, val, dbdf2val_lst);
- goto err;
- }
-
- dbdf2val_lst->tbl[i].val[k] = val;
- p = v;
- if (p[0] == vsep)
- p++;
- }
-
- dbdf2val_lst->tbl[i].dbdf = dbdf;
- if (strlen(p)) {
- if (p[0] != sep) {
- pr_warn("mlx4_core: expect separator '%c' before '%s' in '%s'\n"
- , sep, p, dbdf2val_lst->name);
- goto err;
- }
- p++;
- }
- i++;
- if (i < MLX4_DEVS_TBL_SIZE)
- dbdf2val_lst->tbl[i].dbdf = MLX4_ENDOF_TBL;
- }
-
- return 0;
-
-err:
- dbdf2val_lst->tbl[1].dbdf = MLX4_ENDOF_TBL;
- pr_warn("mlx4_core: The value of '%s' is incorrect. The value is discarded!\n"
- , dbdf2val_lst->name);
-
- return -EINVAL;
-}
-EXPORT_SYMBOL(mlx4_fill_dbdf2val_tbl);
-
-int mlx4_get_val(struct mlx4_dbdf2val *tbl, struct pci_dev *pdev, int idx,
- int *val)
-{
- u64 dbdf;
- int i = 1;
-
- *val = tbl[0].val[idx];
- if (!pdev)
- return -EINVAL;
-
- dbdf = dbdf_to_u64(pci_get_domain(pdev->dev.bsddev), pci_get_bus(pdev->dev.bsddev),
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-
- while ((i < MLX4_DEVS_TBL_SIZE) && (tbl[i].dbdf != MLX4_ENDOF_TBL)) {
- if (tbl[i].dbdf == dbdf) {
- *val = tbl[i].val[idx];
- return 0;
- }
- i++;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(mlx4_get_val);
-
-static void process_mod_param_profile(struct mlx4_profile *profile)
-{
- vm_size_t hwphyssz;
- hwphyssz = 0;
- TUNABLE_ULONG_FETCH("hw.realmem", (u_long *) &hwphyssz);
-
- profile->num_qp = 1 << mod_param_profile.num_qp;
- profile->num_srq = 1 << mod_param_profile.num_srq;
- profile->rdmarc_per_qp = 1 << mod_param_profile.rdmarc_per_qp;
- profile->num_cq = 1 << mod_param_profile.num_cq;
- profile->num_mcg = 1 << mod_param_profile.num_mcg;
- profile->num_mpt = 1 << mod_param_profile.num_mpt;
- /*
- * We want to scale the number of MTTs with the size of the
- * system memory, since it makes sense to register a lot of
- * memory on a system with a lot of memory. As a heuristic,
- * make sure we have enough MTTs to register twice the system
- * memory (with PAGE_SIZE entries).
- *
- * This number has to be a power of two and fit into 32 bits
- * due to device limitations. We cap this at 2^30 as of bit map
- * limitation to work with int instead of uint (mlx4_buddy_init -> bitmap_zero)
- * That limits us to 4TB of memory registration per HCA with
- * 4KB pages, which is probably OK for the next few months.
- */
- if (mod_param_profile.num_mtt_segs)
- profile->num_mtt_segs = 1 << mod_param_profile.num_mtt_segs;
- else {
- profile->num_mtt_segs =
- roundup_pow_of_two(max_t(unsigned,
- 1 << (MLX4_LOG_NUM_MTT - log_mtts_per_seg),
- min(1UL <<
- (MLX4_MAX_LOG_NUM_MTT -
- log_mtts_per_seg),
- (hwphyssz << 1)
- >> log_mtts_per_seg)));
- /* set the actual value, so it will be reflected to the user
- using the sysfs */
- mod_param_profile.num_mtt_segs = ilog2(profile->num_mtt_segs);
- }
-}
-
-int mlx4_check_port_params(struct mlx4_dev *dev,
- enum mlx4_port_type *port_type)
-{
- int i;
-
- for (i = 0; i < dev->caps.num_ports - 1; i++) {
- if (port_type[i] != port_type[i + 1]) {
- if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) {
- mlx4_err(dev, "Only same port types supported "
- "on this HCA, aborting.\n");
- return -EINVAL;
- }
- }
- }
-
- for (i = 0; i < dev->caps.num_ports; i++) {
- if (!(port_type[i] & dev->caps.supported_type[i+1])) {
- mlx4_err(dev, "Requested port type for port %d is not "
- "supported on this HCA\n", i + 1);
- return -EINVAL;
- }
- }
- return 0;
-}
-
-static void mlx4_set_port_mask(struct mlx4_dev *dev)
-{
- int i;
-
- for (i = 1; i <= dev->caps.num_ports; ++i)
- dev->caps.port_mask[i] = dev->caps.port_type[i];
-}
-
-static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
-{
- int err;
- int i;
-
- err = mlx4_QUERY_DEV_CAP(dev, dev_cap);
- if (err) {
- mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n");
- return err;
- }
-
- if (dev_cap->min_page_sz > PAGE_SIZE) {
- mlx4_err(dev, "HCA minimum page size of %d bigger than "
- "kernel PAGE_SIZE of %d, aborting.\n",
- dev_cap->min_page_sz, (int)PAGE_SIZE);
- return -ENODEV;
- }
- if (dev_cap->num_ports > MLX4_MAX_PORTS) {
- mlx4_err(dev, "HCA has %d ports, but we only support %d, "
- "aborting.\n",
- dev_cap->num_ports, MLX4_MAX_PORTS);
- return -ENODEV;
- }
-
- if (dev_cap->uar_size > pci_resource_len(dev->pdev, 2)) {
- mlx4_err(dev, "HCA reported UAR size of 0x%x bigger than "
- "PCI resource 2 size of 0x%llx, aborting.\n",
- dev_cap->uar_size,
- (unsigned long long) pci_resource_len(dev->pdev, 2));
- return -ENODEV;
- }
-
- dev->caps.num_ports = dev_cap->num_ports;
- dev->phys_caps.num_phys_eqs = MLX4_MAX_EQ_NUM;
- for (i = 1; i <= dev->caps.num_ports; ++i) {
- dev->caps.vl_cap[i] = dev_cap->max_vl[i];
- dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i];
- dev->phys_caps.gid_phys_table_len[i] = dev_cap->max_gids[i];
- dev->phys_caps.pkey_phys_table_len[i] = dev_cap->max_pkeys[i];
- /* set gid and pkey table operating lengths by default
- * to non-sriov values */
- dev->caps.gid_table_len[i] = dev_cap->max_gids[i];
- dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i];
- dev->caps.port_width_cap[i] = dev_cap->max_port_width[i];
- dev->caps.eth_mtu_cap[i] = dev_cap->eth_mtu[i];
- dev->caps.def_mac[i] = dev_cap->def_mac[i];
- dev->caps.supported_type[i] = dev_cap->supported_port_types[i];
- dev->caps.suggested_type[i] = dev_cap->suggested_type[i];
- dev->caps.default_sense[i] = dev_cap->default_sense[i];
- dev->caps.trans_type[i] = dev_cap->trans_type[i];
- dev->caps.vendor_oui[i] = dev_cap->vendor_oui[i];
- dev->caps.wavelength[i] = dev_cap->wavelength[i];
- dev->caps.trans_code[i] = dev_cap->trans_code[i];
- }
-
- dev->caps.uar_page_size = PAGE_SIZE;
- dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE;
- dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay;
- dev->caps.bf_reg_size = dev_cap->bf_reg_size;
- dev->caps.bf_regs_per_page = dev_cap->bf_regs_per_page;
- dev->caps.max_sq_sg = dev_cap->max_sq_sg;
- dev->caps.max_rq_sg = dev_cap->max_rq_sg;
- dev->caps.max_wqes = dev_cap->max_qp_sz;
- dev->caps.max_qp_init_rdma = dev_cap->max_requester_per_qp;
- dev->caps.max_srq_wqes = dev_cap->max_srq_sz;
- dev->caps.max_srq_sge = dev_cap->max_rq_sg - 1;
- dev->caps.reserved_srqs = dev_cap->reserved_srqs;
- dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz;
- dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz;
- /*
- * Subtract 1 from the limit because we need to allocate a
- * spare CQE to enable resizing the CQ
- */
- dev->caps.max_cqes = dev_cap->max_cq_sz - 1;
- dev->caps.reserved_cqs = dev_cap->reserved_cqs;
- dev->caps.reserved_eqs = dev_cap->reserved_eqs;
- dev->caps.reserved_mtts = dev_cap->reserved_mtts;
- dev->caps.reserved_mrws = dev_cap->reserved_mrws;
-
- /* The first 128 UARs are used for EQ doorbells */
- dev->caps.reserved_uars = max_t(int, 128, dev_cap->reserved_uars);
- dev->caps.reserved_pds = dev_cap->reserved_pds;
- dev->caps.reserved_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
- dev_cap->reserved_xrcds : 0;
- dev->caps.max_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
- dev_cap->max_xrcds : 0;
- dev->caps.mtt_entry_sz = dev_cap->mtt_entry_sz;
-
- dev->caps.max_msg_sz = dev_cap->max_msg_sz;
- dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
- dev->caps.flags = dev_cap->flags;
- dev->caps.flags2 = dev_cap->flags2;
- dev->caps.bmme_flags = dev_cap->bmme_flags;
- dev->caps.reserved_lkey = dev_cap->reserved_lkey;
- dev->caps.stat_rate_support = dev_cap->stat_rate_support;
- dev->caps.cq_timestamp = dev_cap->timestamp_support;
- dev->caps.max_gso_sz = dev_cap->max_gso_sz;
- dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz;
-
- /* Sense port always allowed on supported devices for ConnectX-1 and -2 */
- if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT)
- dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
- /* Don't do sense port on multifunction devices (for now at least) */
- if (mlx4_is_mfunc(dev))
- dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
-
- dev->caps.log_num_macs = log_num_mac;
- dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
-
- dev->caps.fast_drop = fast_drop ?
- !!(dev->caps.flags & MLX4_DEV_CAP_FLAG_FAST_DROP) :
- 0;
-
- for (i = 1; i <= dev->caps.num_ports; ++i) {
- dev->caps.port_type[i] = MLX4_PORT_TYPE_NONE;
- if (dev->caps.supported_type[i]) {
- /* if only ETH is supported - assign ETH */
- if (dev->caps.supported_type[i] == MLX4_PORT_TYPE_ETH)
- dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH;
- /* if only IB is supported, assign IB */
- else if (dev->caps.supported_type[i] ==
- MLX4_PORT_TYPE_IB)
- dev->caps.port_type[i] = MLX4_PORT_TYPE_IB;
- else {
- /*
- * if IB and ETH are supported, we set the port
- * type according to user selection of port type;
- * if there is no user selection, take the FW hint
- */
- int pta;
- mlx4_get_val(port_type_array.dbdf2val.tbl,
- pci_physfn(dev->pdev), i - 1,
- &pta);
- if (pta == MLX4_PORT_TYPE_NONE) {
- dev->caps.port_type[i] = dev->caps.suggested_type[i] ?
- MLX4_PORT_TYPE_ETH : MLX4_PORT_TYPE_IB;
- } else if (pta == MLX4_PORT_TYPE_NA) {
- mlx4_err(dev, "Port %d is valid port. "
- "It is not allowed to configure its type to N/A(%d)\n",
- i, MLX4_PORT_TYPE_NA);
- return -EINVAL;
- } else {
- dev->caps.port_type[i] = pta;
- }
- }
- }
- /*
- * Link sensing is allowed on the port if 3 conditions are true:
- * 1. Both protocols are supported on the port.
- * 2. Different types are supported on the port
- * 3. FW declared that it supports link sensing
- */
- mlx4_priv(dev)->sense.sense_allowed[i] =
- ((dev->caps.supported_type[i] == MLX4_PORT_TYPE_AUTO) &&
- (dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP) &&
- (dev->caps.flags & MLX4_DEV_CAP_FLAG_SENSE_SUPPORT));
-
- /* Disablling auto sense for default Eth ports support */
- mlx4_priv(dev)->sense.sense_allowed[i] = 0;
-
- /*
- * If "default_sense" bit is set, we move the port to "AUTO" mode
- * and perform sense_port FW command to try and set the correct
- * port type from beginning
- */
- if (mlx4_priv(dev)->sense.sense_allowed[i] && dev->caps.default_sense[i]) {
- enum mlx4_port_type sensed_port = MLX4_PORT_TYPE_NONE;
- dev->caps.possible_type[i] = MLX4_PORT_TYPE_AUTO;
- mlx4_SENSE_PORT(dev, i, &sensed_port);
- if (sensed_port != MLX4_PORT_TYPE_NONE)
- dev->caps.port_type[i] = sensed_port;
- } else {
- dev->caps.possible_type[i] = dev->caps.port_type[i];
- }
-
- if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) {
- dev->caps.log_num_macs = dev_cap->log_max_macs[i];
- mlx4_warn(dev, "Requested number of MACs is too much "
- "for port %d, reducing to %d.\n",
- i, 1 << dev->caps.log_num_macs);
- }
- if (dev->caps.log_num_vlans > dev_cap->log_max_vlans[i]) {
- dev->caps.log_num_vlans = dev_cap->log_max_vlans[i];
- mlx4_warn(dev, "Requested number of VLANs is too much "
- "for port %d, reducing to %d.\n",
- i, 1 << dev->caps.log_num_vlans);
- }
- }
-
- dev->caps.max_basic_counters = dev_cap->max_basic_counters;
- dev->caps.max_extended_counters = dev_cap->max_extended_counters;
- /* support extended counters if available */
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS_EXT)
- dev->caps.max_counters = dev->caps.max_extended_counters;
- else
- dev->caps.max_counters = dev->caps.max_basic_counters;
-
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] =
- (1 << dev->caps.log_num_macs) *
- (1 << dev->caps.log_num_vlans) *
- dev->caps.num_ports;
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH] = MLX4_NUM_FEXCH;
-
- dev->caps.reserved_qps = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] +
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] +
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] +
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH];
-
- dev->caps.sync_qp = dev_cap->sync_qp;
- if (dev->pdev->device == 0x1003)
- dev->caps.cq_flags |= MLX4_DEV_CAP_CQ_FLAG_IO;
-
- dev->caps.sqp_demux = (mlx4_is_master(dev)) ? MLX4_MAX_NUM_SLAVES : 0;
-
- if (!mlx4_enable_64b_cqe_eqe && !mlx4_is_slave(dev)) {
- if (dev_cap->flags &
- (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) {
- mlx4_warn(dev, "64B EQEs/CQEs supported by the device but not enabled\n");
- dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE;
- dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE;
- }
- }
-
- if ((dev->caps.flags &
- (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) &&
- mlx4_is_master(dev))
- dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE;
-
- if (!mlx4_is_slave(dev)) {
- for (i = 0; i < dev->caps.num_ports; ++i)
- dev->caps.def_counter_index[i] = i << 1;
- }
-
- return 0;
-}
-/*The function checks if there are live vf, return the num of them*/
-static int mlx4_how_many_lives_vf(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *s_state;
- int i;
- int ret = 0;
-
- for (i = 1/*the ppf is 0*/; i < dev->num_slaves; ++i) {
- s_state = &priv->mfunc.master.slave_state[i];
- if (s_state->active && s_state->last_cmd !=
- MLX4_COMM_CMD_RESET) {
- mlx4_warn(dev, "%s: slave: %d is still active\n",
- __func__, i);
- ret++;
- }
- }
- return ret;
-}
-
-int mlx4_get_parav_qkey(struct mlx4_dev *dev, u32 qpn, u32 *qkey)
-{
- u32 qk = MLX4_RESERVED_QKEY_BASE;
-
- if (qpn >= dev->phys_caps.base_tunnel_sqpn + 8 * MLX4_MFUNC_MAX ||
- qpn < dev->phys_caps.base_proxy_sqpn)
- return -EINVAL;
-
- if (qpn >= dev->phys_caps.base_tunnel_sqpn)
- /* tunnel qp */
- qk += qpn - dev->phys_caps.base_tunnel_sqpn;
- else
- qk += qpn - dev->phys_caps.base_proxy_sqpn;
- *qkey = qk;
- return 0;
-}
-EXPORT_SYMBOL(mlx4_get_parav_qkey);
-
-void mlx4_sync_pkey_table(struct mlx4_dev *dev, int slave, int port, int i, int val)
-{
- struct mlx4_priv *priv = container_of(dev, struct mlx4_priv, dev);
-
- if (!mlx4_is_master(dev))
- return;
-
- priv->virt2phys_pkey[slave][port - 1][i] = val;
-}
-EXPORT_SYMBOL(mlx4_sync_pkey_table);
-
-void mlx4_put_slave_node_guid(struct mlx4_dev *dev, int slave, __be64 guid)
-{
- struct mlx4_priv *priv = container_of(dev, struct mlx4_priv, dev);
-
- if (!mlx4_is_master(dev))
- return;
-
- priv->slave_node_guids[slave] = guid;
-}
-EXPORT_SYMBOL(mlx4_put_slave_node_guid);
-
-__be64 mlx4_get_slave_node_guid(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = container_of(dev, struct mlx4_priv, dev);
-
- if (!mlx4_is_master(dev))
- return 0;
-
- return priv->slave_node_guids[slave];
-}
-EXPORT_SYMBOL(mlx4_get_slave_node_guid);
-
-int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *s_slave;
-
- if (!mlx4_is_master(dev))
- return 0;
-
- s_slave = &priv->mfunc.master.slave_state[slave];
- return !!s_slave->active;
-}
-EXPORT_SYMBOL(mlx4_is_slave_active);
-
-static void slave_adjust_steering_mode(struct mlx4_dev *dev,
- struct mlx4_dev_cap *dev_cap,
- struct mlx4_init_hca_param *hca_param)
-{
- dev->caps.steering_mode = hca_param->steering_mode;
- if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED)
- dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry;
- else
- dev->caps.num_qp_per_mgm =
- 4 * ((1 << hca_param->log_mc_entry_sz)/16 - 2);
-
- mlx4_dbg(dev, "Steering mode is: %s\n",
- mlx4_steering_mode_str(dev->caps.steering_mode));
-}
-
-static int mlx4_slave_cap(struct mlx4_dev *dev)
-{
- int err;
- u32 page_size;
- struct mlx4_dev_cap dev_cap;
- struct mlx4_func_cap func_cap;
- struct mlx4_init_hca_param hca_param;
- int i;
-
- memset(&hca_param, 0, sizeof(hca_param));
- err = mlx4_QUERY_HCA(dev, &hca_param);
- if (err) {
- mlx4_err(dev, "QUERY_HCA command failed, aborting.\n");
- return err;
- }
-
- /*fail if the hca has an unknown capability */
- if ((hca_param.global_caps | HCA_GLOBAL_CAP_MASK) !=
- HCA_GLOBAL_CAP_MASK) {
- mlx4_err(dev, "Unknown hca global capabilities\n");
- return -ENOSYS;
- }
-
- mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz;
-
- dev->caps.hca_core_clock = hca_param.hca_core_clock;
-
- memset(&dev_cap, 0, sizeof(dev_cap));
- dev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp;
- err = mlx4_dev_cap(dev, &dev_cap);
- if (err) {
- mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n");
- return err;
- }
-
- err = mlx4_QUERY_FW(dev);
- if (err)
- mlx4_err(dev, "QUERY_FW command failed: could not get FW version.\n");
-
- if (!hca_param.mw_enable) {
- dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
- dev->caps.bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
- }
-
- page_size = ~dev->caps.page_size_cap + 1;
- mlx4_warn(dev, "HCA minimum page size:%d\n", page_size);
- if (page_size > PAGE_SIZE) {
- mlx4_err(dev, "HCA minimum page size of %d bigger than "
- "kernel PAGE_SIZE of %d, aborting.\n",
- page_size, (int)PAGE_SIZE);
- return -ENODEV;
- }
-
- /* slave gets uar page size from QUERY_HCA fw command */
- dev->caps.uar_page_size = 1 << (hca_param.uar_page_sz + 12);
-
- /* TODO: relax this assumption */
- if (dev->caps.uar_page_size != PAGE_SIZE) {
- mlx4_err(dev, "UAR size:%d != kernel PAGE_SIZE of %d\n",
- dev->caps.uar_page_size, (int)PAGE_SIZE);
- return -ENODEV;
- }
-
- memset(&func_cap, 0, sizeof(func_cap));
- err = mlx4_QUERY_FUNC_CAP(dev, 0, &func_cap);
- if (err) {
- mlx4_err(dev, "QUERY_FUNC_CAP general command failed, aborting (%d).\n",
- err);
- return err;
- }
-
- if ((func_cap.pf_context_behaviour | PF_CONTEXT_BEHAVIOUR_MASK) !=
- PF_CONTEXT_BEHAVIOUR_MASK) {
- mlx4_err(dev, "Unknown pf context behaviour\n");
- return -ENOSYS;
- }
-
- dev->caps.num_ports = func_cap.num_ports;
- dev->quotas.qp = func_cap.qp_quota;
- dev->quotas.srq = func_cap.srq_quota;
- dev->quotas.cq = func_cap.cq_quota;
- dev->quotas.mpt = func_cap.mpt_quota;
- dev->quotas.mtt = func_cap.mtt_quota;
- dev->caps.num_qps = 1 << hca_param.log_num_qps;
- dev->caps.num_srqs = 1 << hca_param.log_num_srqs;
- dev->caps.num_cqs = 1 << hca_param.log_num_cqs;
- dev->caps.num_mpts = 1 << hca_param.log_mpt_sz;
- dev->caps.num_eqs = func_cap.max_eq;
- dev->caps.reserved_eqs = func_cap.reserved_eq;
- dev->caps.num_pds = MLX4_NUM_PDS;
- dev->caps.num_mgms = 0;
- dev->caps.num_amgms = 0;
-
- if (dev->caps.num_ports > MLX4_MAX_PORTS) {
- mlx4_err(dev, "HCA has %d ports, but we only support %d, "
- "aborting.\n", dev->caps.num_ports, MLX4_MAX_PORTS);
- return -ENODEV;
- }
-
- dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
- dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
- dev->caps.qp1_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
- dev->caps.qp1_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
-
- if (!dev->caps.qp0_tunnel || !dev->caps.qp0_proxy ||
- !dev->caps.qp1_tunnel || !dev->caps.qp1_proxy) {
- err = -ENOMEM;
- goto err_mem;
- }
-
- for (i = 1; i <= dev->caps.num_ports; ++i) {
- err = mlx4_QUERY_FUNC_CAP(dev, (u32) i, &func_cap);
- if (err) {
- mlx4_err(dev, "QUERY_FUNC_CAP port command failed for"
- " port %d, aborting (%d).\n", i, err);
- goto err_mem;
- }
- dev->caps.qp0_tunnel[i - 1] = func_cap.qp0_tunnel_qpn;
- dev->caps.qp0_proxy[i - 1] = func_cap.qp0_proxy_qpn;
- dev->caps.qp1_tunnel[i - 1] = func_cap.qp1_tunnel_qpn;
- dev->caps.qp1_proxy[i - 1] = func_cap.qp1_proxy_qpn;
- dev->caps.def_counter_index[i - 1] = func_cap.def_counter_index;
-
- dev->caps.port_mask[i] = dev->caps.port_type[i];
- err = mlx4_get_slave_pkey_gid_tbl_len(dev, i,
- &dev->caps.gid_table_len[i],
- &dev->caps.pkey_table_len[i]);
- if (err)
- goto err_mem;
- }
-
- if (dev->caps.uar_page_size * (dev->caps.num_uars -
- dev->caps.reserved_uars) >
- pci_resource_len(dev->pdev, 2)) {
- mlx4_err(dev, "HCA reported UAR region size of 0x%x bigger than "
- "PCI resource 2 size of 0x%llx, aborting.\n",
- dev->caps.uar_page_size * dev->caps.num_uars,
- (unsigned long long) pci_resource_len(dev->pdev, 2));
- err = -ENOMEM;
- goto err_mem;
- }
-
- if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_EQE_ENABLED) {
- dev->caps.eqe_size = 64;
- dev->caps.eqe_factor = 1;
- } else {
- dev->caps.eqe_size = 32;
- dev->caps.eqe_factor = 0;
- }
-
- if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) {
- dev->caps.cqe_size = 64;
- dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE;
- } else {
- dev->caps.cqe_size = 32;
- }
-
- dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
- mlx4_warn(dev, "Timestamping is not supported in slave mode.\n");
-
- slave_adjust_steering_mode(dev, &dev_cap, &hca_param);
-
- return 0;
-
-err_mem:
- kfree(dev->caps.qp0_tunnel);
- kfree(dev->caps.qp0_proxy);
- kfree(dev->caps.qp1_tunnel);
- kfree(dev->caps.qp1_proxy);
- dev->caps.qp0_tunnel = dev->caps.qp0_proxy =
- dev->caps.qp1_tunnel = dev->caps.qp1_proxy = NULL;
-
- return err;
-}
-
-static void mlx4_request_modules(struct mlx4_dev *dev)
-{
- int port;
- int has_ib_port = false;
- int has_eth_port = false;
-#define EN_DRV_NAME "mlx4_en"
-#define IB_DRV_NAME "mlx4_ib"
-
- for (port = 1; port <= dev->caps.num_ports; port++) {
- if (dev->caps.port_type[port] == MLX4_PORT_TYPE_IB)
- has_ib_port = true;
- else if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
- has_eth_port = true;
- }
-
- if (has_ib_port)
- request_module_nowait(IB_DRV_NAME);
- if (has_eth_port)
- request_module_nowait(EN_DRV_NAME);
-}
-
-/*
- * Change the port configuration of the device.
- * Every user of this function must hold the port mutex.
- */
-int mlx4_change_port_types(struct mlx4_dev *dev,
- enum mlx4_port_type *port_types)
-{
- int err = 0;
- int change = 0;
- int port;
-
- for (port = 0; port < dev->caps.num_ports; port++) {
- /* Change the port type only if the new type is different
- * from the current, and not set to Auto */
- if (port_types[port] != dev->caps.port_type[port + 1])
- change = 1;
- }
- if (change) {
- mlx4_unregister_device(dev);
- for (port = 1; port <= dev->caps.num_ports; port++) {
- mlx4_CLOSE_PORT(dev, port);
- dev->caps.port_type[port] = port_types[port - 1];
- err = mlx4_SET_PORT(dev, port, -1);
- if (err) {
- mlx4_err(dev, "Failed to set port %d, "
- "aborting\n", port);
- goto out;
- }
- }
- mlx4_set_port_mask(dev);
- err = mlx4_register_device(dev);
- if (err) {
- mlx4_err(dev, "Failed to register device\n");
- goto out;
- }
- mlx4_request_modules(dev);
- }
-
-out:
- return err;
-}
-
-static ssize_t show_port_type(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
- port_attr);
- struct mlx4_dev *mdev = info->dev;
- char type[8];
-
- sprintf(type, "%s",
- (mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_IB) ?
- "ib" : "eth");
- if (mdev->caps.possible_type[info->port] == MLX4_PORT_TYPE_AUTO)
- sprintf(buf, "auto (%s)\n", type);
- else
- sprintf(buf, "%s\n", type);
-
- return strlen(buf);
-}
-
-static ssize_t set_port_type(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
- port_attr);
- struct mlx4_dev *mdev = info->dev;
- struct mlx4_priv *priv = mlx4_priv(mdev);
- enum mlx4_port_type types[MLX4_MAX_PORTS];
- enum mlx4_port_type new_types[MLX4_MAX_PORTS];
- int i;
- int err = 0;
-
- if (!strcmp(buf, "ib\n"))
- info->tmp_type = MLX4_PORT_TYPE_IB;
- else if (!strcmp(buf, "eth\n"))
- info->tmp_type = MLX4_PORT_TYPE_ETH;
- else if (!strcmp(buf, "auto\n"))
- info->tmp_type = MLX4_PORT_TYPE_AUTO;
- else {
- mlx4_err(mdev, "%s is not supported port type\n", buf);
- return -EINVAL;
- }
-
- if ((info->tmp_type & mdev->caps.supported_type[info->port]) !=
- info->tmp_type) {
- mlx4_err(mdev, "Requested port type for port %d is not supported on this HCA\n",
- info->port);
- return -EINVAL;
- }
-
- mlx4_stop_sense(mdev);
- mutex_lock(&priv->port_mutex);
- /* Possible type is always the one that was delivered */
- mdev->caps.possible_type[info->port] = info->tmp_type;
-
- for (i = 0; i < mdev->caps.num_ports; i++) {
- types[i] = priv->port[i+1].tmp_type ? priv->port[i+1].tmp_type :
- mdev->caps.possible_type[i+1];
- if (types[i] == MLX4_PORT_TYPE_AUTO)
- types[i] = mdev->caps.port_type[i+1];
- }
-
- if (!(mdev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP) &&
- !(mdev->caps.flags & MLX4_DEV_CAP_FLAG_SENSE_SUPPORT)) {
- for (i = 1; i <= mdev->caps.num_ports; i++) {
- if (mdev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) {
- mdev->caps.possible_type[i] = mdev->caps.port_type[i];
- err = -EINVAL;
- }
- }
- }
- if (err) {
- mlx4_err(mdev, "Auto sensing is not supported on this HCA. "
- "Set only 'eth' or 'ib' for both ports "
- "(should be the same)\n");
- goto out;
- }
-
- mlx4_do_sense_ports(mdev, new_types, types);
-
- err = mlx4_check_port_params(mdev, new_types);
- if (err)
- goto out;
-
- /* We are about to apply the changes after the configuration
- * was verified, no need to remember the temporary types
- * any more */
- for (i = 0; i < mdev->caps.num_ports; i++)
- priv->port[i + 1].tmp_type = 0;
-
- err = mlx4_change_port_types(mdev, new_types);
-
-out:
- mlx4_start_sense(mdev);
- mutex_unlock(&priv->port_mutex);
- return err ? err : count;
-}
-
-enum ibta_mtu {
- IB_MTU_256 = 1,
- IB_MTU_512 = 2,
- IB_MTU_1024 = 3,
- IB_MTU_2048 = 4,
- IB_MTU_4096 = 5
-};
-
-static inline int int_to_ibta_mtu(int mtu)
-{
- switch (mtu) {
- case 256: return IB_MTU_256;
- case 512: return IB_MTU_512;
- case 1024: return IB_MTU_1024;
- case 2048: return IB_MTU_2048;
- case 4096: return IB_MTU_4096;
- default: return -1;
- }
-}
-
-static inline int ibta_mtu_to_int(enum ibta_mtu mtu)
-{
- switch (mtu) {
- case IB_MTU_256: return 256;
- case IB_MTU_512: return 512;
- case IB_MTU_1024: return 1024;
- case IB_MTU_2048: return 2048;
- case IB_MTU_4096: return 4096;
- default: return -1;
- }
-}
-
-static ssize_t
-show_board(struct device *device, struct device_attribute *attr,
- char *buf)
-{
- struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info,
- board_attr);
- struct mlx4_dev *mdev = info->dev;
-
- return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN,
- mdev->board_id);
-}
-
-static ssize_t
-show_hca(struct device *device, struct device_attribute *attr,
- char *buf)
-{
- struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info,
- hca_attr);
- struct mlx4_dev *mdev = info->dev;
-
- return sprintf(buf, "MT%d\n", mdev->pdev->device);
-}
-
-static ssize_t
-show_firmware_version(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct mlx4_hca_info *info = container_of(attr, struct mlx4_hca_info,
- firmware_attr);
- struct mlx4_dev *mdev = info->dev;
-
- return sprintf(buf, "%d.%d.%d\n", (int)(mdev->caps.fw_ver >> 32),
- (int)(mdev->caps.fw_ver >> 16) & 0xffff,
- (int)mdev->caps.fw_ver & 0xffff);
-}
-
-static ssize_t show_port_ib_mtu(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
- port_mtu_attr);
- struct mlx4_dev *mdev = info->dev;
-
- /* When port type is eth, port mtu value isn't used. */
- if (mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_ETH)
- return -EINVAL;
-
- sprintf(buf, "%d\n",
- ibta_mtu_to_int(mdev->caps.port_ib_mtu[info->port]));
- return strlen(buf);
-}
-
-static ssize_t set_port_ib_mtu(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
- port_mtu_attr);
- struct mlx4_dev *mdev = info->dev;
- struct mlx4_priv *priv = mlx4_priv(mdev);
- int err, port, mtu, ibta_mtu = -1;
-
- if (mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_ETH) {
- mlx4_warn(mdev, "port level mtu is only used for IB ports\n");
- return -EINVAL;
- }
-
- mtu = (int) simple_strtol(buf, NULL, 0);
- ibta_mtu = int_to_ibta_mtu(mtu);
-
- if (ibta_mtu < 0) {
- mlx4_err(mdev, "%s is invalid IBTA mtu\n", buf);
- return -EINVAL;
- }
-
- mdev->caps.port_ib_mtu[info->port] = ibta_mtu;
-
- mlx4_stop_sense(mdev);
- mutex_lock(&priv->port_mutex);
- mlx4_unregister_device(mdev);
- for (port = 1; port <= mdev->caps.num_ports; port++) {
- mlx4_CLOSE_PORT(mdev, port);
- err = mlx4_SET_PORT(mdev, port, -1);
- if (err) {
- mlx4_err(mdev, "Failed to set port %d, "
- "aborting\n", port);
- goto err_set_port;
- }
- }
- err = mlx4_register_device(mdev);
-err_set_port:
- mutex_unlock(&priv->port_mutex);
- mlx4_start_sense(mdev);
- return err ? err : count;
-}
-
-static int mlx4_load_fw(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err, unmap_flag = 0;
-
- priv->fw.fw_icm = mlx4_alloc_icm(dev, priv->fw.fw_pages,
- GFP_HIGHUSER | __GFP_NOWARN, 0);
- if (!priv->fw.fw_icm) {
- mlx4_err(dev, "Couldn't allocate FW area, aborting.\n");
- return -ENOMEM;
- }
-
- err = mlx4_MAP_FA(dev, priv->fw.fw_icm);
- if (err) {
- mlx4_err(dev, "MAP_FA command failed, aborting.\n");
- goto err_free;
- }
-
- err = mlx4_RUN_FW(dev);
- if (err) {
- mlx4_err(dev, "RUN_FW command failed, aborting.\n");
- goto err_unmap_fa;
- }
-
- return 0;
-
-err_unmap_fa:
- unmap_flag = mlx4_UNMAP_FA(dev);
- if (unmap_flag)
- pr_warn("mlx4_core: mlx4_UNMAP_FA failed.\n");
-
-err_free:
- if (!unmap_flag)
- mlx4_free_icm(dev, priv->fw.fw_icm, 0);
- return err;
-}
-
-static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
- int cmpt_entry_sz)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err;
- int num_eqs;
-
- err = mlx4_init_icm_table(dev, &priv->qp_table.cmpt_table,
- cmpt_base +
- ((u64) (MLX4_CMPT_TYPE_QP *
- cmpt_entry_sz) << MLX4_CMPT_SHIFT),
- cmpt_entry_sz, dev->caps.num_qps,
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
- 0, 0);
- if (err)
- goto err;
-
- err = mlx4_init_icm_table(dev, &priv->srq_table.cmpt_table,
- cmpt_base +
- ((u64) (MLX4_CMPT_TYPE_SRQ *
- cmpt_entry_sz) << MLX4_CMPT_SHIFT),
- cmpt_entry_sz, dev->caps.num_srqs,
- dev->caps.reserved_srqs, 0, 0);
- if (err)
- goto err_qp;
-
- err = mlx4_init_icm_table(dev, &priv->cq_table.cmpt_table,
- cmpt_base +
- ((u64) (MLX4_CMPT_TYPE_CQ *
- cmpt_entry_sz) << MLX4_CMPT_SHIFT),
- cmpt_entry_sz, dev->caps.num_cqs,
- dev->caps.reserved_cqs, 0, 0);
- if (err)
- goto err_srq;
-
- num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs :
- dev->caps.num_eqs;
- err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table,
- cmpt_base +
- ((u64) (MLX4_CMPT_TYPE_EQ *
- cmpt_entry_sz) << MLX4_CMPT_SHIFT),
- cmpt_entry_sz, num_eqs, num_eqs, 0, 0);
- if (err)
- goto err_cq;
-
- return 0;
-
-err_cq:
- mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table);
-
-err_srq:
- mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table);
-
-err_qp:
- mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table);
-
-err:
- return err;
-}
-
-static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
- struct mlx4_init_hca_param *init_hca, u64 icm_size)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- u64 aux_pages;
- int num_eqs;
- int err, unmap_flag = 0;
-
- err = mlx4_SET_ICM_SIZE(dev, icm_size, &aux_pages);
- if (err) {
- mlx4_err(dev, "SET_ICM_SIZE command failed, aborting.\n");
- return err;
- }
-
- mlx4_dbg(dev, "%lld KB of HCA context requires %lld KB aux memory.\n",
- (unsigned long long) icm_size >> 10,
- (unsigned long long) aux_pages << 2);
-
- priv->fw.aux_icm = mlx4_alloc_icm(dev, aux_pages,
- GFP_HIGHUSER | __GFP_NOWARN, 0);
- if (!priv->fw.aux_icm) {
- mlx4_err(dev, "Couldn't allocate aux memory, aborting.\n");
- return -ENOMEM;
- }
-
- err = mlx4_MAP_ICM_AUX(dev, priv->fw.aux_icm);
- if (err) {
- mlx4_err(dev, "MAP_ICM_AUX command failed, aborting.\n");
- goto err_free_aux;
- }
-
- err = mlx4_init_cmpt_table(dev, init_hca->cmpt_base, dev_cap->cmpt_entry_sz);
- if (err) {
- mlx4_err(dev, "Failed to map cMPT context memory, aborting.\n");
- goto err_unmap_aux;
- }
-
-
- num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs :
- dev->caps.num_eqs;
- err = mlx4_init_icm_table(dev, &priv->eq_table.table,
- init_hca->eqc_base, dev_cap->eqc_entry_sz,
- num_eqs, num_eqs, 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map EQ context memory, aborting.\n");
- goto err_unmap_cmpt;
- }
-
- /*
- * Reserved MTT entries must be aligned up to a cacheline
- * boundary, since the FW will write to them, while the driver
- * writes to all other MTT entries. (The variable
- * dev->caps.mtt_entry_sz below is really the MTT segment
- * size, not the raw entry size)
- */
- dev->caps.reserved_mtts =
- ALIGN(dev->caps.reserved_mtts * dev->caps.mtt_entry_sz,
- dma_get_cache_alignment()) / dev->caps.mtt_entry_sz;
-
- err = mlx4_init_icm_table(dev, &priv->mr_table.mtt_table,
- init_hca->mtt_base,
- dev->caps.mtt_entry_sz,
- dev->caps.num_mtts,
- dev->caps.reserved_mtts, 1, 0);
- if (err) {
- mlx4_err(dev, "Failed to map MTT context memory, aborting.\n");
- goto err_unmap_eq;
- }
-
- err = mlx4_init_icm_table(dev, &priv->mr_table.dmpt_table,
- init_hca->dmpt_base,
- dev_cap->dmpt_entry_sz,
- dev->caps.num_mpts,
- dev->caps.reserved_mrws, 1, 1);
- if (err) {
- mlx4_err(dev, "Failed to map dMPT context memory, aborting.\n");
- goto err_unmap_mtt;
- }
-
- err = mlx4_init_icm_table(dev, &priv->qp_table.qp_table,
- init_hca->qpc_base,
- dev_cap->qpc_entry_sz,
- dev->caps.num_qps,
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
- 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map QP context memory, aborting.\n");
- goto err_unmap_dmpt;
- }
-
- err = mlx4_init_icm_table(dev, &priv->qp_table.auxc_table,
- init_hca->auxc_base,
- dev_cap->aux_entry_sz,
- dev->caps.num_qps,
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
- 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map AUXC context memory, aborting.\n");
- goto err_unmap_qp;
- }
-
- err = mlx4_init_icm_table(dev, &priv->qp_table.altc_table,
- init_hca->altc_base,
- dev_cap->altc_entry_sz,
- dev->caps.num_qps,
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
- 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map ALTC context memory, aborting.\n");
- goto err_unmap_auxc;
- }
-
- err = mlx4_init_icm_table(dev, &priv->qp_table.rdmarc_table,
- init_hca->rdmarc_base,
- dev_cap->rdmarc_entry_sz << priv->qp_table.rdmarc_shift,
- dev->caps.num_qps,
- dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW],
- 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map RDMARC context memory, aborting\n");
- goto err_unmap_altc;
- }
-
- err = mlx4_init_icm_table(dev, &priv->cq_table.table,
- init_hca->cqc_base,
- dev_cap->cqc_entry_sz,
- dev->caps.num_cqs,
- dev->caps.reserved_cqs, 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map CQ context memory, aborting.\n");
- goto err_unmap_rdmarc;
- }
-
- err = mlx4_init_icm_table(dev, &priv->srq_table.table,
- init_hca->srqc_base,
- dev_cap->srq_entry_sz,
- dev->caps.num_srqs,
- dev->caps.reserved_srqs, 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map SRQ context memory, aborting.\n");
- goto err_unmap_cq;
- }
-
- /*
- * For flow steering device managed mode it is required to use
- * mlx4_init_icm_table. For B0 steering mode it's not strictly
- * required, but for simplicity just map the whole multicast
- * group table now. The table isn't very big and it's a lot
- * easier than trying to track ref counts.
- */
- err = mlx4_init_icm_table(dev, &priv->mcg_table.table,
- init_hca->mc_base,
- mlx4_get_mgm_entry_size(dev),
- dev->caps.num_mgms + dev->caps.num_amgms,
- dev->caps.num_mgms + dev->caps.num_amgms,
- 0, 0);
- if (err) {
- mlx4_err(dev, "Failed to map MCG context memory, aborting.\n");
- goto err_unmap_srq;
- }
-
- return 0;
-
-err_unmap_srq:
- mlx4_cleanup_icm_table(dev, &priv->srq_table.table);
-
-err_unmap_cq:
- mlx4_cleanup_icm_table(dev, &priv->cq_table.table);
-
-err_unmap_rdmarc:
- mlx4_cleanup_icm_table(dev, &priv->qp_table.rdmarc_table);
-
-err_unmap_altc:
- mlx4_cleanup_icm_table(dev, &priv->qp_table.altc_table);
-
-err_unmap_auxc:
- mlx4_cleanup_icm_table(dev, &priv->qp_table.auxc_table);
-
-err_unmap_qp:
- mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table);
-
-err_unmap_dmpt:
- mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table);
-
-err_unmap_mtt:
- mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table);
-
-err_unmap_eq:
- mlx4_cleanup_icm_table(dev, &priv->eq_table.table);
-
-err_unmap_cmpt:
- mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table);
- mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table);
- mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table);
- mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table);
-
-err_unmap_aux:
- unmap_flag = mlx4_UNMAP_ICM_AUX(dev);
- if (unmap_flag)
- pr_warn("mlx4_core: mlx4_UNMAP_ICM_AUX failed.\n");
-
-err_free_aux:
- if (!unmap_flag)
- mlx4_free_icm(dev, priv->fw.aux_icm, 0);
-
- return err;
-}
-
-static void mlx4_free_icms(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- mlx4_cleanup_icm_table(dev, &priv->mcg_table.table);
- mlx4_cleanup_icm_table(dev, &priv->srq_table.table);
- mlx4_cleanup_icm_table(dev, &priv->cq_table.table);
- mlx4_cleanup_icm_table(dev, &priv->qp_table.rdmarc_table);
- mlx4_cleanup_icm_table(dev, &priv->qp_table.altc_table);
- mlx4_cleanup_icm_table(dev, &priv->qp_table.auxc_table);
- mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table);
- mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table);
- mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table);
- mlx4_cleanup_icm_table(dev, &priv->eq_table.table);
- mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table);
- mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table);
- mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table);
- mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table);
-
- if (!mlx4_UNMAP_ICM_AUX(dev))
- mlx4_free_icm(dev, priv->fw.aux_icm, 0);
- else
- pr_warn("mlx4_core: mlx4_UNMAP_ICM_AUX failed.\n");
-}
-
-static void mlx4_slave_exit(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- mutex_lock(&priv->cmd.slave_cmd_mutex);
- if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, MLX4_COMM_TIME))
- mlx4_warn(dev, "Failed to close slave function.\n");
- mutex_unlock(&priv->cmd.slave_cmd_mutex);
-}
-
-static int map_bf_area(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- resource_size_t bf_start;
- resource_size_t bf_len;
- int err = 0;
-
- if (!dev->caps.bf_reg_size)
- return -ENXIO;
-
- bf_start = pci_resource_start(dev->pdev, 2) +
- (dev->caps.num_uars << PAGE_SHIFT);
- bf_len = pci_resource_len(dev->pdev, 2) -
- (dev->caps.num_uars << PAGE_SHIFT);
- priv->bf_mapping = io_mapping_create_wc(bf_start, bf_len);
- if (!priv->bf_mapping)
- err = -ENOMEM;
-
- return err;
-}
-
-static void unmap_bf_area(struct mlx4_dev *dev)
-{
- if (mlx4_priv(dev)->bf_mapping)
- io_mapping_free(mlx4_priv(dev)->bf_mapping);
-}
-
-int mlx4_read_clock(struct mlx4_dev *dev)
-{
- u32 clockhi, clocklo, clockhi1;
- cycle_t cycles;
- int i;
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- if (!priv->clock_mapping)
- return -ENOTSUPP;
-
- for (i = 0; i < 10; i++) {
- clockhi = swab32(readl(priv->clock_mapping));
- clocklo = swab32(readl(priv->clock_mapping + 4));
- clockhi1 = swab32(readl(priv->clock_mapping));
- if (clockhi == clockhi1)
- break;
- }
-
- cycles = (u64) clockhi << 32 | (u64) clocklo;
-
- return cycles;
-}
-EXPORT_SYMBOL_GPL(mlx4_read_clock);
-
-
-static int map_internal_clock(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- priv->clock_mapping = ioremap(pci_resource_start(dev->pdev,
- priv->fw.clock_bar) +
- priv->fw.clock_offset, MLX4_CLOCK_SIZE);
-
- if (!priv->clock_mapping)
- return -ENOMEM;
-
- return 0;
-}
-
-
-int mlx4_get_internal_clock_params(struct mlx4_dev *dev,
- struct mlx4_clock_params *params)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- if (mlx4_is_slave(dev))
- return -ENOTSUPP;
- if (!params)
- return -EINVAL;
-
- params->bar = priv->fw.clock_bar;
- params->offset = priv->fw.clock_offset;
- params->size = MLX4_CLOCK_SIZE;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_get_internal_clock_params);
-
-static void unmap_internal_clock(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- if (priv->clock_mapping)
- iounmap(priv->clock_mapping);
-}
-
-static void mlx4_close_hca(struct mlx4_dev *dev)
-{
- unmap_internal_clock(dev);
- unmap_bf_area(dev);
- if (mlx4_is_slave(dev)) {
- mlx4_slave_exit(dev);
- } else {
- mlx4_CLOSE_HCA(dev, 0);
- mlx4_free_icms(dev);
-
- if (!mlx4_UNMAP_FA(dev))
- mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0);
- else
- pr_warn("mlx4_core: mlx4_UNMAP_FA failed.\n");
- }
-}
-
-static int mlx4_init_slave(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- u64 dma = (u64) priv->mfunc.vhcr_dma;
- int num_of_reset_retries = NUM_OF_RESET_RETRIES;
- int ret_from_reset = 0;
- u32 slave_read;
- u32 cmd_channel_ver;
-
- mutex_lock(&priv->cmd.slave_cmd_mutex);
- priv->cmd.max_cmds = 1;
- mlx4_warn(dev, "Sending reset\n");
- ret_from_reset = mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0,
- MLX4_COMM_TIME);
- /* if we are in the middle of flr the slave will try
- * NUM_OF_RESET_RETRIES times before leaving.*/
- if (ret_from_reset) {
- if (MLX4_DELAY_RESET_SLAVE == ret_from_reset) {
- msleep(SLEEP_TIME_IN_RESET);
- while (ret_from_reset && num_of_reset_retries) {
- mlx4_warn(dev, "slave is currently in the"
- "middle of FLR. retrying..."
- "(try num:%d)\n",
- (NUM_OF_RESET_RETRIES -
- num_of_reset_retries + 1));
- ret_from_reset =
- mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET,
- 0, MLX4_COMM_TIME);
- num_of_reset_retries = num_of_reset_retries - 1;
- }
- } else
- goto err;
- }
-
- /* check the driver version - the slave I/F revision
- * must match the master's */
- slave_read = swab32(readl(&priv->mfunc.comm->slave_read));
- cmd_channel_ver = mlx4_comm_get_version();
-
- if (MLX4_COMM_GET_IF_REV(cmd_channel_ver) !=
- MLX4_COMM_GET_IF_REV(slave_read)) {
- mlx4_err(dev, "slave driver version is not supported"
- " by the master\n");
- goto err;
- }
-
- mlx4_warn(dev, "Sending vhcr0\n");
- if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR0, dma >> 48,
- MLX4_COMM_TIME))
- goto err;
- if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR1, dma >> 32,
- MLX4_COMM_TIME))
- goto err;
- if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR2, dma >> 16,
- MLX4_COMM_TIME))
- goto err;
- if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_EN, dma, MLX4_COMM_TIME))
- goto err;
-
- mutex_unlock(&priv->cmd.slave_cmd_mutex);
- return 0;
-
-err:
- mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, 0);
- mutex_unlock(&priv->cmd.slave_cmd_mutex);
- return -EIO;
-}
-
-static void mlx4_parav_master_pf_caps(struct mlx4_dev *dev)
-{
- int i;
-
- for (i = 1; i <= dev->caps.num_ports; i++) {
- if (dev->caps.port_type[i] == MLX4_PORT_TYPE_ETH)
- dev->caps.gid_table_len[i] =
- mlx4_get_slave_num_gids(dev, 0);
- else
- dev->caps.gid_table_len[i] = 1;
- dev->caps.pkey_table_len[i] =
- dev->phys_caps.pkey_phys_table_len[i] - 1;
- }
-}
-
-static int choose_log_fs_mgm_entry_size(int qp_per_entry)
-{
- int i = MLX4_MIN_MGM_LOG_ENTRY_SIZE;
-
- for (i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE;
- i++) {
- if (qp_per_entry <= 4 * ((1 << i) / 16 - 2))
- break;
- }
-
- return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1;
-}
-
-static void choose_steering_mode(struct mlx4_dev *dev,
- struct mlx4_dev_cap *dev_cap)
-{
- int nvfs;
-
- mlx4_get_val(num_vfs.dbdf2val.tbl, pci_physfn(dev->pdev), 0, &nvfs);
- if (high_rate_steer && !mlx4_is_mfunc(dev)) {
- dev->caps.flags &= ~(MLX4_DEV_CAP_FLAG_VEP_MC_STEER |
- MLX4_DEV_CAP_FLAG_VEP_UC_STEER);
- dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_FS_EN;
- }
-
- if (mlx4_log_num_mgm_entry_size == -1 &&
- dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN &&
- (!mlx4_is_mfunc(dev) ||
- (dev_cap->fs_max_num_qp_per_entry >= (nvfs + 1))) &&
- choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry) >=
- MLX4_MIN_MGM_LOG_ENTRY_SIZE) {
- dev->oper_log_mgm_entry_size =
- choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry);
- dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
- dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry;
- } else {
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER &&
- dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
- dev->caps.steering_mode = MLX4_STEERING_MODE_B0;
- else {
- dev->caps.steering_mode = MLX4_STEERING_MODE_A0;
-
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER ||
- dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
- mlx4_warn(dev, "Must have both UC_STEER and MC_STEER flags "
- "set to use B0 steering. Falling back to A0 steering mode.\n");
- }
- dev->oper_log_mgm_entry_size =
- mlx4_log_num_mgm_entry_size > 0 ?
- mlx4_log_num_mgm_entry_size :
- MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE;
- dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
- }
- mlx4_dbg(dev, "Steering mode is: %s, oper_log_mgm_entry_size = %d, "
- "log_num_mgm_entry_size = %d\n",
- mlx4_steering_mode_str(dev->caps.steering_mode),
- dev->oper_log_mgm_entry_size, mlx4_log_num_mgm_entry_size);
-}
-
-static int mlx4_init_hca(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_dev_cap *dev_cap = NULL;
- struct mlx4_adapter adapter;
- struct mlx4_mod_stat_cfg mlx4_cfg;
- struct mlx4_profile profile;
- struct mlx4_init_hca_param init_hca;
- u64 icm_size;
- int err;
-
- if (!mlx4_is_slave(dev)) {
- err = mlx4_QUERY_FW(dev);
- if (err) {
- if (err == -EACCES)
- mlx4_info(dev, "non-primary physical function, skipping.\n");
- else
- mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
- return err;
- }
-
- err = mlx4_load_fw(dev);
- if (err) {
- mlx4_err(dev, "Failed to start FW, aborting.\n");
- return err;
- }
-
- mlx4_cfg.log_pg_sz_m = 1;
- mlx4_cfg.log_pg_sz = 0;
- err = mlx4_MOD_STAT_CFG(dev, &mlx4_cfg);
- if (err)
- mlx4_warn(dev, "Failed to override log_pg_sz parameter\n");
-
- dev_cap = kzalloc(sizeof *dev_cap, GFP_KERNEL);
- if (!dev_cap) {
- mlx4_err(dev, "Failed to allocate memory for dev_cap\n");
- err = -ENOMEM;
- goto err_stop_fw;
- }
-
- err = mlx4_dev_cap(dev, dev_cap);
- if (err) {
- mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n");
- goto err_stop_fw;
- }
-
- choose_steering_mode(dev, dev_cap);
-
- if (mlx4_is_master(dev))
- mlx4_parav_master_pf_caps(dev);
-
- process_mod_param_profile(&profile);
- if (dev->caps.steering_mode ==
- MLX4_STEERING_MODE_DEVICE_MANAGED)
- profile.num_mcg = MLX4_FS_NUM_MCG;
-
- icm_size = mlx4_make_profile(dev, &profile, dev_cap,
- &init_hca);
- if ((long long) icm_size < 0) {
- err = icm_size;
- goto err_stop_fw;
- }
-
- dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1;
-
- init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
- init_hca.uar_page_sz = PAGE_SHIFT - 12;
-
- err = mlx4_init_icm(dev, dev_cap, &init_hca, icm_size);
- if (err)
- goto err_stop_fw;
-
- init_hca.mw_enable = 1;
-
- err = mlx4_INIT_HCA(dev, &init_hca);
- if (err) {
- mlx4_err(dev, "INIT_HCA command failed, aborting.\n");
- goto err_free_icm;
- }
-
- /*
- * Read HCA frequency by QUERY_HCA command
- */
- if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
- memset(&init_hca, 0, sizeof(init_hca));
- err = mlx4_QUERY_HCA(dev, &init_hca);
- if (err) {
- mlx4_err(dev, "QUERY_HCA command failed, disable timestamp.\n");
- dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
- } else {
- dev->caps.hca_core_clock =
- init_hca.hca_core_clock;
- }
-
- /* In case we got HCA frequency 0 - disable timestamping
- * to avoid dividing by zero
- */
- if (!dev->caps.hca_core_clock) {
- dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
- mlx4_err(dev, "HCA frequency is 0. Timestamping is not supported.");
- } else if (map_internal_clock(dev)) {
- /* Map internal clock,
- * in case of failure disable timestamping
- */
- dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
- mlx4_err(dev, "Failed to map internal clock. Timestamping is not supported.\n");
- }
- }
- } else {
- err = mlx4_init_slave(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize slave\n");
- return err;
- }
-
- err = mlx4_slave_cap(dev);
- if (err) {
- mlx4_err(dev, "Failed to obtain slave caps\n");
- goto err_close;
- }
- }
-
- if (map_bf_area(dev))
- mlx4_dbg(dev, "Failed to map blue flame area\n");
-
- /* Only the master set the ports, all the rest got it from it.*/
- if (!mlx4_is_slave(dev))
- mlx4_set_port_mask(dev);
-
- err = mlx4_QUERY_ADAPTER(dev, &adapter);
- if (err) {
- mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n");
- goto unmap_bf;
- }
-
- priv->eq_table.inta_pin = adapter.inta_pin;
- memcpy(dev->board_id, adapter.board_id, sizeof dev->board_id);
- memcpy(dev->vsd, adapter.vsd, sizeof(dev->vsd));
- dev->vsd_vendor_id = adapter.vsd_vendor_id;
-
- if (!mlx4_is_slave(dev))
- kfree(dev_cap);
-
- return 0;
-
-unmap_bf:
- if (!mlx4_is_slave(dev))
- unmap_internal_clock(dev);
- unmap_bf_area(dev);
-
- if (mlx4_is_slave(dev)) {
- kfree(dev->caps.qp0_tunnel);
- kfree(dev->caps.qp0_proxy);
- kfree(dev->caps.qp1_tunnel);
- kfree(dev->caps.qp1_proxy);
- }
-
-err_close:
- if (mlx4_is_slave(dev))
- mlx4_slave_exit(dev);
- else
- mlx4_CLOSE_HCA(dev, 0);
-
-err_free_icm:
- if (!mlx4_is_slave(dev))
- mlx4_free_icms(dev);
-
-err_stop_fw:
- if (!mlx4_is_slave(dev)) {
- if (!mlx4_UNMAP_FA(dev))
- mlx4_free_icm(dev, priv->fw.fw_icm, 0);
- else
- pr_warn("mlx4_core: mlx4_UNMAP_FA failed.\n");
- kfree(dev_cap);
- }
- return err;
-}
-
-static int mlx4_init_counters_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int nent_pow2, port_indx, vf_index, num_counters;
- int res, index = 0;
- struct counter_index *new_counter_index;
-
-
- if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
- return -ENOENT;
-
- if (!mlx4_is_slave(dev) &&
- dev->caps.max_counters == dev->caps.max_extended_counters) {
- res = mlx4_cmd(dev, MLX4_IF_STATE_EXTENDED, 0, 0,
- MLX4_CMD_SET_IF_STAT,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
- if (res) {
- mlx4_err(dev, "Failed to set extended counters (err=%d)\n", res);
- return res;
- }
- }
-
- mutex_init(&priv->counters_table.mutex);
-
- if (mlx4_is_slave(dev)) {
- for (port_indx = 0; port_indx < dev->caps.num_ports; port_indx++) {
- INIT_LIST_HEAD(&priv->counters_table.global_port_list[port_indx]);
- if (dev->caps.def_counter_index[port_indx] != 0xFF) {
- new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
- if (!new_counter_index)
- return -ENOMEM;
- new_counter_index->index = dev->caps.def_counter_index[port_indx];
- list_add_tail(&new_counter_index->list, &priv->counters_table.global_port_list[port_indx]);
- }
- }
- mlx4_dbg(dev, "%s: slave allocated %d counters for %d ports\n",
- __func__, dev->caps.num_ports, dev->caps.num_ports);
- return 0;
- }
-
- nent_pow2 = roundup_pow_of_two(dev->caps.max_counters);
-
- for (port_indx = 0; port_indx < dev->caps.num_ports; port_indx++) {
- INIT_LIST_HEAD(&priv->counters_table.global_port_list[port_indx]);
- /* allocating 2 counters per port for PFs */
- /* For the PF, the ETH default counters are 0,2; */
- /* and the RoCE default counters are 1,3 */
- for (num_counters = 0; num_counters < 2; num_counters++, index++) {
- new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
- if (!new_counter_index)
- return -ENOMEM;
- new_counter_index->index = index;
- list_add_tail(&new_counter_index->list,
- &priv->counters_table.global_port_list[port_indx]);
- }
- }
-
- if (mlx4_is_master(dev)) {
- for (vf_index = 0; vf_index < dev->num_vfs; vf_index++) {
- for (port_indx = 0; port_indx < dev->caps.num_ports; port_indx++) {
- INIT_LIST_HEAD(&priv->counters_table.vf_list[vf_index][port_indx]);
- new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
- if (!new_counter_index)
- return -ENOMEM;
- if (index < nent_pow2 - 2) {
- new_counter_index->index = index;
- index++;
- } else {
- new_counter_index->index = MLX4_SINK_COUNTER_INDEX;
- }
-
- list_add_tail(&new_counter_index->list,
- &priv->counters_table.vf_list[vf_index][port_indx]);
- }
- }
-
- res = mlx4_bitmap_init(&priv->counters_table.bitmap,
- nent_pow2, nent_pow2 - 1,
- index, 1);
- mlx4_dbg(dev, "%s: master allocated %d counters for %d VFs\n",
- __func__, index, dev->num_vfs);
- } else {
- res = mlx4_bitmap_init(&priv->counters_table.bitmap,
- nent_pow2, nent_pow2 - 1,
- index, 1);
- mlx4_dbg(dev, "%s: native allocated %d counters for %d ports\n",
- __func__, index, dev->caps.num_ports);
- }
-
- return 0;
-
-}
-
-static void mlx4_cleanup_counters_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i, j;
- struct counter_index *port, *tmp_port;
- struct counter_index *vf, *tmp_vf;
-
- mutex_lock(&priv->counters_table.mutex);
-
- if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS) {
- for (i = 0; i < dev->caps.num_ports; i++) {
- list_for_each_entry_safe(port, tmp_port,
- &priv->counters_table.global_port_list[i],
- list) {
- list_del(&port->list);
- kfree(port);
- }
- }
- if (!mlx4_is_slave(dev)) {
- for (i = 0; i < dev->num_vfs; i++) {
- for (j = 0; j < dev->caps.num_ports; j++) {
- list_for_each_entry_safe(vf, tmp_vf,
- &priv->counters_table.vf_list[i][j],
- list) {
- /* clear the counter statistic */
- if (__mlx4_clear_if_stat(dev, vf->index))
- mlx4_dbg(dev, "%s: reset counter %d failed\n",
- __func__, vf->index);
- list_del(&vf->list);
- kfree(vf);
- }
- }
- }
- mlx4_bitmap_cleanup(&priv->counters_table.bitmap);
- }
- }
- mutex_unlock(&priv->counters_table.mutex);
-}
-
-int __mlx4_slave_counters_free(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i, first;
- struct counter_index *vf, *tmp_vf;
-
- /* clean VF's counters for the next useg */
- if (slave > 0 && slave <= dev->num_vfs) {
- mlx4_dbg(dev, "%s: free counters of slave(%d)\n"
- , __func__, slave);
-
- mutex_lock(&priv->counters_table.mutex);
- for (i = 0; i < dev->caps.num_ports; i++) {
- first = 0;
- list_for_each_entry_safe(vf, tmp_vf,
- &priv->counters_table.vf_list[slave - 1][i],
- list) {
- /* clear the counter statistic */
- if (__mlx4_clear_if_stat(dev, vf->index))
- mlx4_dbg(dev, "%s: reset counter %d failed\n",
- __func__, vf->index);
- if (first++ && vf->index != MLX4_SINK_COUNTER_INDEX) {
- mlx4_dbg(dev, "%s: delete counter index %d for slave %d and port %d\n"
- , __func__, vf->index, slave, i + 1);
- mlx4_bitmap_free(&priv->counters_table.bitmap, vf->index, MLX4_USE_RR);
- list_del(&vf->list);
- kfree(vf);
- } else {
- mlx4_dbg(dev, "%s: can't delete default counter index %d for slave %d and port %d\n"
- , __func__, vf->index, slave, i + 1);
- }
- }
- }
- mutex_unlock(&priv->counters_table.mutex);
- }
-
- return 0;
-}
-
-int __mlx4_counter_alloc(struct mlx4_dev *dev, int slave, int port, u32 *idx)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct counter_index *new_counter_index;
-
- if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
- return -ENOENT;
-
- if ((slave > MLX4_MAX_NUM_VF) || (slave < 0) ||
- (port < 0) || (port > MLX4_MAX_PORTS)) {
- mlx4_dbg(dev, "%s: invalid slave(%d) or port(%d) index\n",
- __func__, slave, port);
- return -EINVAL;
- }
-
- /* handle old guest request does not support request by port index */
- if (port == 0) {
- *idx = MLX4_SINK_COUNTER_INDEX;
- mlx4_dbg(dev, "%s: allocated default counter index %d for slave %d port %d\n"
- , __func__, *idx, slave, port);
- return 0;
- }
-
- mutex_lock(&priv->counters_table.mutex);
-
- *idx = mlx4_bitmap_alloc(&priv->counters_table.bitmap);
- /* if no resources return the default counter of the slave and port */
- if (*idx == -1) {
- if (slave == 0) { /* its the ethernet counter ?????? */
- new_counter_index = list_entry(priv->counters_table.global_port_list[port - 1].next,
- struct counter_index,
- list);
- } else {
- new_counter_index = list_entry(priv->counters_table.vf_list[slave - 1][port - 1].next,
- struct counter_index,
- list);
- }
-
- *idx = new_counter_index->index;
- mlx4_dbg(dev, "%s: allocated defualt counter index %d for slave %d port %d\n"
- , __func__, *idx, slave, port);
- goto out;
- }
-
- if (slave == 0) { /* native or master */
- new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
- if (!new_counter_index)
- goto no_mem;
- new_counter_index->index = *idx;
- list_add_tail(&new_counter_index->list, &priv->counters_table.global_port_list[port - 1]);
- } else {
- new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
- if (!new_counter_index)
- goto no_mem;
- new_counter_index->index = *idx;
- list_add_tail(&new_counter_index->list, &priv->counters_table.vf_list[slave - 1][port - 1]);
- }
-
- mlx4_dbg(dev, "%s: allocated counter index %d for slave %d port %d\n"
- , __func__, *idx, slave, port);
-out:
- mutex_unlock(&priv->counters_table.mutex);
- return 0;
-
-no_mem:
- mlx4_bitmap_free(&priv->counters_table.bitmap, *idx, MLX4_USE_RR);
- mutex_unlock(&priv->counters_table.mutex);
- *idx = MLX4_SINK_COUNTER_INDEX;
- mlx4_dbg(dev, "%s: failed err (%d)\n"
- , __func__, -ENOMEM);
- return -ENOMEM;
-}
-
-int mlx4_counter_alloc(struct mlx4_dev *dev, u8 port, u32 *idx)
-{
- u64 out_param;
- int err;
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct counter_index *new_counter_index, *c_index;
-
- if (mlx4_is_mfunc(dev)) {
- err = mlx4_cmd_imm(dev, 0, &out_param,
- ((u32) port) << 8 | (u32) RES_COUNTER,
- RES_OP_RESERVE, MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (!err) {
- *idx = get_param_l(&out_param);
- if (*idx == MLX4_SINK_COUNTER_INDEX)
- return -ENOSPC;
-
- mutex_lock(&priv->counters_table.mutex);
- c_index = list_entry(priv->counters_table.global_port_list[port - 1].next,
- struct counter_index,
- list);
- mutex_unlock(&priv->counters_table.mutex);
- if (c_index->index == *idx)
- return -EEXIST;
-
- if (mlx4_is_slave(dev)) {
- new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
- if (!new_counter_index) {
- mlx4_counter_free(dev, port, *idx);
- return -ENOMEM;
- }
- new_counter_index->index = *idx;
- mutex_lock(&priv->counters_table.mutex);
- list_add_tail(&new_counter_index->list, &priv->counters_table.global_port_list[port - 1]);
- mutex_unlock(&priv->counters_table.mutex);
- mlx4_dbg(dev, "%s: allocated counter index %d for port %d\n"
- , __func__, *idx, port);
- }
- }
- return err;
- }
- return __mlx4_counter_alloc(dev, 0, port, idx);
-}
-EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
-
-void __mlx4_counter_free(struct mlx4_dev *dev, int slave, int port, u32 idx)
-{
- /* check if native or slave and deletes accordingly */
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct counter_index *pf, *tmp_pf;
- struct counter_index *vf, *tmp_vf;
- int first;
-
-
- if (idx == MLX4_SINK_COUNTER_INDEX) {
- mlx4_dbg(dev, "%s: try to delete default counter index %d for port %d\n"
- , __func__, idx, port);
- return;
- }
-
- if ((slave > MLX4_MAX_NUM_VF) || (slave < 0) ||
- (port < 0) || (port > MLX4_MAX_PORTS)) {
- mlx4_warn(dev, "%s: deletion failed due to invalid slave(%d) or port(%d) index\n"
- , __func__, slave, idx);
- return;
- }
-
- mutex_lock(&priv->counters_table.mutex);
- if (slave == 0) {
- first = 0;
- list_for_each_entry_safe(pf, tmp_pf,
- &priv->counters_table.global_port_list[port - 1],
- list) {
- /* the first 2 counters are reserved */
- if (pf->index == idx) {
- /* clear the counter statistic */
- if (__mlx4_clear_if_stat(dev, pf->index))
- mlx4_dbg(dev, "%s: reset counter %d failed\n",
- __func__, pf->index);
- if (1 < first && idx != MLX4_SINK_COUNTER_INDEX) {
- list_del(&pf->list);
- kfree(pf);
- mlx4_dbg(dev, "%s: delete counter index %d for native device (%d) port %d\n"
- , __func__, idx, slave, port);
- mlx4_bitmap_free(&priv->counters_table.bitmap, idx, MLX4_USE_RR);
- goto out;
- } else {
- mlx4_dbg(dev, "%s: can't delete default counter index %d for native device (%d) port %d\n"
- , __func__, idx, slave, port);
- goto out;
- }
- }
- first++;
- }
- mlx4_dbg(dev, "%s: can't delete counter index %d for native device (%d) port %d\n"
- , __func__, idx, slave, port);
- } else {
- first = 0;
- list_for_each_entry_safe(vf, tmp_vf,
- &priv->counters_table.vf_list[slave - 1][port - 1],
- list) {
- /* the first element is reserved */
- if (vf->index == idx) {
- /* clear the counter statistic */
- if (__mlx4_clear_if_stat(dev, vf->index))
- mlx4_dbg(dev, "%s: reset counter %d failed\n",
- __func__, vf->index);
- if (first) {
- list_del(&vf->list);
- kfree(vf);
- mlx4_dbg(dev, "%s: delete counter index %d for slave %d port %d\n",
- __func__, idx, slave, port);
- mlx4_bitmap_free(&priv->counters_table.bitmap, idx, MLX4_USE_RR);
- goto out;
- } else {
- mlx4_dbg(dev, "%s: can't delete default slave (%d) counter index %d for port %d\n"
- , __func__, slave, idx, port);
- goto out;
- }
- }
- first++;
- }
- mlx4_dbg(dev, "%s: can't delete slave (%d) counter index %d for port %d\n"
- , __func__, slave, idx, port);
- }
-
-out:
- mutex_unlock(&priv->counters_table.mutex);
-}
-
-void mlx4_counter_free(struct mlx4_dev *dev, u8 port, u32 idx)
-{
- u64 in_param = 0;
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct counter_index *counter, *tmp_counter;
- int first = 0;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, idx);
- mlx4_cmd(dev, in_param,
- ((u32) port) << 8 | (u32) RES_COUNTER,
- RES_OP_RESERVE,
- MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
-
- if (mlx4_is_slave(dev) && idx != MLX4_SINK_COUNTER_INDEX) {
- mutex_lock(&priv->counters_table.mutex);
- list_for_each_entry_safe(counter, tmp_counter,
- &priv->counters_table.global_port_list[port - 1],
- list) {
- if (counter->index == idx && first++) {
- list_del(&counter->list);
- kfree(counter);
- mlx4_dbg(dev, "%s: delete counter index %d for port %d\n"
- , __func__, idx, port);
- mutex_unlock(&priv->counters_table.mutex);
- return;
- }
- }
- mutex_unlock(&priv->counters_table.mutex);
- }
-
- return;
- }
- __mlx4_counter_free(dev, 0, port, idx);
-}
-EXPORT_SYMBOL_GPL(mlx4_counter_free);
-
-int __mlx4_clear_if_stat(struct mlx4_dev *dev,
- u8 counter_index)
-{
- struct mlx4_cmd_mailbox *if_stat_mailbox = NULL;
- int err = 0;
- u32 if_stat_in_mod = (counter_index & 0xff) | (1 << 31);
-
- if (counter_index == MLX4_SINK_COUNTER_INDEX)
- return -EINVAL;
-
- if (mlx4_is_slave(dev))
- return 0;
-
- if_stat_mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(if_stat_mailbox)) {
- err = PTR_ERR(if_stat_mailbox);
- return err;
- }
-
- err = mlx4_cmd_box(dev, 0, if_stat_mailbox->dma, if_stat_in_mod, 0,
- MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C,
- MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, if_stat_mailbox);
- return err;
-}
-
-u8 mlx4_get_default_counter_index(struct mlx4_dev *dev, int slave, int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct counter_index *new_counter_index;
-
- if (dev->caps.port_type[port] == MLX4_PORT_TYPE_IB) {
- mlx4_dbg(dev, "%s: return counter index %d for slave %d port (MLX4_PORT_TYPE_IB) %d\n",
- __func__, MLX4_SINK_COUNTER_INDEX, slave, port);
- return (u8)MLX4_SINK_COUNTER_INDEX;
- }
-
- mutex_lock(&priv->counters_table.mutex);
- if (slave == 0) {
- new_counter_index = list_entry(priv->counters_table.global_port_list[port - 1].next,
- struct counter_index,
- list);
- } else {
- new_counter_index = list_entry(priv->counters_table.vf_list[slave - 1][port - 1].next,
- struct counter_index,
- list);
- }
- mutex_unlock(&priv->counters_table.mutex);
-
- mlx4_dbg(dev, "%s: return counter index %d for slave %d port %d\n",
- __func__, new_counter_index->index, slave, port);
-
-
- return (u8)new_counter_index->index;
-}
-
-int mlx4_get_vport_ethtool_stats(struct mlx4_dev *dev, int port,
- struct mlx4_en_vport_stats *vport_stats,
- int reset)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_mailbox *if_stat_mailbox = NULL;
- union mlx4_counter *counter;
- int err = 0;
- u32 if_stat_in_mod;
- struct counter_index *vport, *tmp_vport;
-
- if (!vport_stats)
- return -EINVAL;
-
- if_stat_mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(if_stat_mailbox)) {
- err = PTR_ERR(if_stat_mailbox);
- return err;
- }
-
- mutex_lock(&priv->counters_table.mutex);
- list_for_each_entry_safe(vport, tmp_vport,
- &priv->counters_table.global_port_list[port - 1],
- list) {
- if (vport->index == MLX4_SINK_COUNTER_INDEX)
- continue;
-
- memset(if_stat_mailbox->buf, 0, sizeof(union mlx4_counter));
- if_stat_in_mod = (vport->index & 0xff) | ((reset & 1) << 31);
- err = mlx4_cmd_box(dev, 0, if_stat_mailbox->dma,
- if_stat_in_mod, 0,
- MLX4_CMD_QUERY_IF_STAT,
- MLX4_CMD_TIME_CLASS_C,
- MLX4_CMD_NATIVE);
- if (err) {
- mlx4_dbg(dev, "%s: failed to read statistics for counter index %d\n",
- __func__, vport->index);
- goto if_stat_out;
- }
- counter = (union mlx4_counter *)if_stat_mailbox->buf;
- if ((counter->control.cnt_mode & 0xf) == 1) {
- vport_stats->rx_broadcast_packets += be64_to_cpu(counter->ext.counters[0].IfRxBroadcastFrames);
- vport_stats->rx_unicast_packets += be64_to_cpu(counter->ext.counters[0].IfRxUnicastFrames);
- vport_stats->rx_multicast_packets += be64_to_cpu(counter->ext.counters[0].IfRxMulticastFrames);
- vport_stats->tx_broadcast_packets += be64_to_cpu(counter->ext.counters[0].IfTxBroadcastFrames);
- vport_stats->tx_unicast_packets += be64_to_cpu(counter->ext.counters[0].IfTxUnicastFrames);
- vport_stats->tx_multicast_packets += be64_to_cpu(counter->ext.counters[0].IfTxMulticastFrames);
- vport_stats->rx_broadcast_bytes += be64_to_cpu(counter->ext.counters[0].IfRxBroadcastOctets);
- vport_stats->rx_unicast_bytes += be64_to_cpu(counter->ext.counters[0].IfRxUnicastOctets);
- vport_stats->rx_multicast_bytes += be64_to_cpu(counter->ext.counters[0].IfRxMulticastOctets);
- vport_stats->tx_broadcast_bytes += be64_to_cpu(counter->ext.counters[0].IfTxBroadcastOctets);
- vport_stats->tx_unicast_bytes += be64_to_cpu(counter->ext.counters[0].IfTxUnicastOctets);
- vport_stats->tx_multicast_bytes += be64_to_cpu(counter->ext.counters[0].IfTxMulticastOctets);
- vport_stats->rx_errors += be64_to_cpu(counter->ext.counters[0].IfRxErrorFrames);
- vport_stats->rx_dropped += be64_to_cpu(counter->ext.counters[0].IfRxNoBufferFrames);
- vport_stats->tx_errors += be64_to_cpu(counter->ext.counters[0].IfTxDroppedFrames);
- }
- }
-
-if_stat_out:
- mutex_unlock(&priv->counters_table.mutex);
- mlx4_free_cmd_mailbox(dev, if_stat_mailbox);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_get_vport_ethtool_stats);
-
-static int mlx4_setup_hca(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err;
- int port;
- __be32 ib_port_default_caps;
-
- err = mlx4_init_uar_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "user access region table (err=%d), aborting.\n",
- err);
- return err;
- }
-
- err = mlx4_uar_alloc(dev, &priv->driver_uar);
- if (err) {
- mlx4_err(dev, "Failed to allocate driver access region "
- "(err=%d), aborting.\n", err);
- goto err_uar_table_free;
- }
-
- priv->kar = ioremap((phys_addr_t) priv->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
- if (!priv->kar) {
- mlx4_err(dev, "Couldn't map kernel access region, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_uar_free;
- }
-
- err = mlx4_init_pd_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "protection domain table (err=%d), aborting.\n", err);
- goto err_kar_unmap;
- }
-
- err = mlx4_init_xrcd_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "reliable connection domain table (err=%d), "
- "aborting.\n", err);
- goto err_pd_table_free;
- }
-
- err = mlx4_init_mr_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "memory region table (err=%d), aborting.\n", err);
- goto err_xrcd_table_free;
- }
-
- if (!mlx4_is_slave(dev)) {
- err = mlx4_init_mcg_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "multicast group table (err=%d), aborting.\n",
- err);
- goto err_mr_table_free;
- }
- }
-
- err = mlx4_init_eq_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "event queue table (err=%d), aborting.\n", err);
- goto err_mcg_table_free;
- }
-
- err = mlx4_cmd_use_events(dev);
- if (err) {
- mlx4_err(dev, "Failed to switch to event-driven "
- "firmware commands (err=%d), aborting.\n", err);
- goto err_eq_table_free;
- }
-
- err = mlx4_NOP(dev);
- if (err) {
- if (dev->flags & MLX4_FLAG_MSI_X) {
- mlx4_warn(dev, "NOP command failed to generate MSI-X "
- "interrupt IRQ %d).\n",
- priv->eq_table.eq[dev->caps.num_comp_vectors].irq);
- mlx4_warn(dev, "Trying again without MSI-X.\n");
- } else {
- mlx4_err(dev, "NOP command failed to generate interrupt "
- "(IRQ %d), aborting.\n",
- priv->eq_table.eq[dev->caps.num_comp_vectors].irq);
- mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n");
- }
-
- goto err_cmd_poll;
- }
-
- mlx4_dbg(dev, "NOP command IRQ test passed\n");
-
- err = mlx4_init_cq_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "completion queue table (err=%d), aborting.\n", err);
- goto err_cmd_poll;
- }
-
- err = mlx4_init_srq_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "shared receive queue table (err=%d), aborting.\n",
- err);
- goto err_cq_table_free;
- }
-
- err = mlx4_init_qp_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "queue pair table (err=%d), aborting.\n", err);
- goto err_srq_table_free;
- }
-
- err = mlx4_init_counters_table(dev);
- if (err && err != -ENOENT) {
- mlx4_err(dev, "Failed to initialize counters table (err=%d), "
- "aborting.\n", err);
- goto err_qp_table_free;
- }
-
- if (!mlx4_is_slave(dev)) {
- for (port = 1; port <= dev->caps.num_ports; port++) {
- ib_port_default_caps = 0;
- err = mlx4_get_port_ib_caps(dev, port,
- &ib_port_default_caps);
- if (err)
- mlx4_warn(dev, "failed to get port %d default "
- "ib capabilities (%d). Continuing "
- "with caps = 0\n", port, err);
- dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
-
- /* initialize per-slave default ib port capabilities */
- if (mlx4_is_master(dev)) {
- int i;
- for (i = 0; i < dev->num_slaves; i++) {
- if (i == mlx4_master_func_num(dev))
- continue;
- priv->mfunc.master.slave_state[i].ib_cap_mask[port] =
- ib_port_default_caps;
- }
- }
-
- dev->caps.port_ib_mtu[port] = IB_MTU_4096;
-
- err = mlx4_SET_PORT(dev, port, mlx4_is_master(dev) ?
- dev->caps.pkey_table_len[port] : -1);
- if (err) {
- mlx4_err(dev, "Failed to set port %d (err=%d), "
- "aborting\n", port, err);
- goto err_counters_table_free;
- }
- }
- }
-
- return 0;
-
-err_counters_table_free:
- mlx4_cleanup_counters_table(dev);
-
-err_qp_table_free:
- mlx4_cleanup_qp_table(dev);
-
-err_srq_table_free:
- mlx4_cleanup_srq_table(dev);
-
-err_cq_table_free:
- mlx4_cleanup_cq_table(dev);
-
-err_cmd_poll:
- mlx4_cmd_use_polling(dev);
-
-err_eq_table_free:
- mlx4_cleanup_eq_table(dev);
-
-err_mcg_table_free:
- if (!mlx4_is_slave(dev))
- mlx4_cleanup_mcg_table(dev);
-
-err_mr_table_free:
- mlx4_cleanup_mr_table(dev);
-
-err_xrcd_table_free:
- mlx4_cleanup_xrcd_table(dev);
-
-err_pd_table_free:
- mlx4_cleanup_pd_table(dev);
-
-err_kar_unmap:
- iounmap(priv->kar);
-
-err_uar_free:
- mlx4_uar_free(dev, &priv->driver_uar);
-
-err_uar_table_free:
- mlx4_cleanup_uar_table(dev);
- return err;
-}
-
-static void mlx4_enable_msi_x(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct msix_entry *entries;
- int nreq = min_t(int, dev->caps.num_ports *
- min_t(int, num_possible_cpus() + 1, MAX_MSIX_P_PORT)
- + MSIX_LEGACY_SZ, MAX_MSIX);
- int err;
- int i;
-
- if (msi_x) {
- nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
- nreq);
-
- if (msi_x > 1 && !mlx4_is_mfunc(dev))
- nreq = min_t(int, nreq, msi_x);
-
- entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
- if (!entries)
- goto no_msi;
-
- for (i = 0; i < nreq; ++i)
- entries[i].entry = i;
-
- retry:
- err = pci_enable_msix(dev->pdev, entries, nreq);
- if (err) {
- /* Try again if at least 2 vectors are available */
- if (err > 1) {
- mlx4_info(dev, "Requested %d vectors, "
- "but only %d MSI-X vectors available, "
- "trying again\n", nreq, err);
- nreq = err;
- goto retry;
- }
- kfree(entries);
- /* if error, or can't alloc even 1 IRQ */
- if (err < 0) {
- mlx4_err(dev, "No IRQs left, device can't "
- "be started.\n");
- goto no_irq;
- }
- goto no_msi;
- }
-
- if (nreq <
- MSIX_LEGACY_SZ + dev->caps.num_ports * MIN_MSIX_P_PORT) {
- /*Working in legacy mode , all EQ's shared*/
- dev->caps.comp_pool = 0;
- dev->caps.num_comp_vectors = nreq - 1;
- } else {
- dev->caps.comp_pool = nreq - MSIX_LEGACY_SZ;
- dev->caps.num_comp_vectors = MSIX_LEGACY_SZ - 1;
- }
- for (i = 0; i < nreq; ++i)
- priv->eq_table.eq[i].irq = entries[i].vector;
-
- dev->flags |= MLX4_FLAG_MSI_X;
-
- kfree(entries);
- return;
- }
-
-no_msi:
- dev->caps.num_comp_vectors = 1;
- dev->caps.comp_pool = 0;
-
- for (i = 0; i < 2; ++i)
- priv->eq_table.eq[i].irq = dev->pdev->irq;
- return;
-no_irq:
- dev->caps.num_comp_vectors = 0;
- dev->caps.comp_pool = 0;
- return;
-}
-
-static void
-mlx4_init_hca_info(struct mlx4_dev *dev)
-{
- struct mlx4_hca_info *info = &mlx4_priv(dev)->hca_info;
-
- info->dev = dev;
-
- info->firmware_attr = (struct device_attribute)__ATTR(fw_ver, S_IRUGO,
- show_firmware_version, NULL);
- if (device_create_file(&dev->pdev->dev, &info->firmware_attr))
- mlx4_err(dev, "Failed to add file firmware version");
-
- info->hca_attr = (struct device_attribute)__ATTR(hca, S_IRUGO, show_hca,
- NULL);
- if (device_create_file(&dev->pdev->dev, &info->hca_attr))
- mlx4_err(dev, "Failed to add file hca type");
-
- info->board_attr = (struct device_attribute)__ATTR(board_id, S_IRUGO,
- show_board, NULL);
- if (device_create_file(&dev->pdev->dev, &info->board_attr))
- mlx4_err(dev, "Failed to add file board id type");
-}
-
-static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
-{
- struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
- int err = 0;
-
- info->dev = dev;
- info->port = port;
- if (!mlx4_is_slave(dev)) {
- mlx4_init_mac_table(dev, &info->mac_table);
- mlx4_init_vlan_table(dev, &info->vlan_table);
- info->base_qpn = mlx4_get_base_qpn(dev, port);
- }
-
- sprintf(info->dev_name, "mlx4_port%d", port);
- info->port_attr.attr.name = info->dev_name;
- if (mlx4_is_mfunc(dev))
- info->port_attr.attr.mode = S_IRUGO;
- else {
- info->port_attr.attr.mode = S_IRUGO | S_IWUSR;
- info->port_attr.store = set_port_type;
- }
- info->port_attr.show = show_port_type;
- sysfs_attr_init(&info->port_attr.attr);
-
- err = device_create_file(&dev->pdev->dev, &info->port_attr);
- if (err) {
- mlx4_err(dev, "Failed to create file for port %d\n", port);
- info->port = -1;
- }
-
- sprintf(info->dev_mtu_name, "mlx4_port%d_mtu", port);
- info->port_mtu_attr.attr.name = info->dev_mtu_name;
- if (mlx4_is_mfunc(dev))
- info->port_mtu_attr.attr.mode = S_IRUGO;
- else {
- info->port_mtu_attr.attr.mode = S_IRUGO | S_IWUSR;
- info->port_mtu_attr.store = set_port_ib_mtu;
- }
- info->port_mtu_attr.show = show_port_ib_mtu;
- sysfs_attr_init(&info->port_mtu_attr.attr);
-
- err = device_create_file(&dev->pdev->dev, &info->port_mtu_attr);
- if (err) {
- mlx4_err(dev, "Failed to create mtu file for port %d\n", port);
- device_remove_file(&info->dev->pdev->dev, &info->port_attr);
- info->port = -1;
- }
-
- return err;
-}
-
-static void
-mlx4_cleanup_hca_info(struct mlx4_hca_info *info)
-{
- device_remove_file(&info->dev->pdev->dev, &info->firmware_attr);
- device_remove_file(&info->dev->pdev->dev, &info->board_attr);
- device_remove_file(&info->dev->pdev->dev, &info->hca_attr);
-}
-
-static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
-{
- if (info->port < 0)
- return;
-
- device_remove_file(&info->dev->pdev->dev, &info->port_attr);
- device_remove_file(&info->dev->pdev->dev, &info->port_mtu_attr);
-}
-
-static int mlx4_init_steering(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int num_entries = dev->caps.num_ports;
- int i, j;
-
- priv->steer = kzalloc(sizeof(struct mlx4_steer) * num_entries, GFP_KERNEL);
- if (!priv->steer)
- return -ENOMEM;
-
- for (i = 0; i < num_entries; i++)
- for (j = 0; j < MLX4_NUM_STEERS; j++) {
- INIT_LIST_HEAD(&priv->steer[i].promisc_qps[j]);
- INIT_LIST_HEAD(&priv->steer[i].steer_entries[j]);
- }
- return 0;
-}
-
-static void mlx4_clear_steering(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_steer_index *entry, *tmp_entry;
- struct mlx4_promisc_qp *pqp, *tmp_pqp;
- int num_entries = dev->caps.num_ports;
- int i, j;
-
- for (i = 0; i < num_entries; i++) {
- for (j = 0; j < MLX4_NUM_STEERS; j++) {
- list_for_each_entry_safe(pqp, tmp_pqp,
- &priv->steer[i].promisc_qps[j],
- list) {
- list_del(&pqp->list);
- kfree(pqp);
- }
- list_for_each_entry_safe(entry, tmp_entry,
- &priv->steer[i].steer_entries[j],
- list) {
- list_del(&entry->list);
- list_for_each_entry_safe(pqp, tmp_pqp,
- &entry->duplicates,
- list) {
- list_del(&pqp->list);
- kfree(pqp);
- }
- kfree(entry);
- }
- }
- }
- kfree(priv->steer);
-}
-
-static int extended_func_num(struct pci_dev *pdev)
-{
- return PCI_SLOT(pdev->devfn) * 8 + PCI_FUNC(pdev->devfn);
-}
-
-#define MLX4_OWNER_BASE 0x8069c
-#define MLX4_OWNER_SIZE 4
-
-static int mlx4_get_ownership(struct mlx4_dev *dev)
-{
- void __iomem *owner;
- u32 ret;
-
- if (pci_channel_offline(dev->pdev))
- return -EIO;
-
- owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE,
- MLX4_OWNER_SIZE);
- if (!owner) {
- mlx4_err(dev, "Failed to obtain ownership bit\n");
- return -ENOMEM;
- }
-
- ret = readl(owner);
- iounmap(owner);
- return (int) !!ret;
-}
-
-static void mlx4_free_ownership(struct mlx4_dev *dev)
-{
- void __iomem *owner;
-
- if (pci_channel_offline(dev->pdev))
- return;
-
- owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE,
- MLX4_OWNER_SIZE);
- if (!owner) {
- mlx4_err(dev, "Failed to obtain ownership bit\n");
- return;
- }
- writel(0, owner);
- msleep(1000);
- iounmap(owner);
-}
-
-static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
-{
- struct mlx4_priv *priv;
- struct mlx4_dev *dev;
- int err;
- int port;
- int nvfs, prb_vf;
-
- pr_info(DRV_NAME ": Initializing %s\n", pci_name(pdev));
-
- err = pci_enable_device(pdev);
- if (err) {
- dev_err(&pdev->dev, "Cannot enable PCI device, "
- "aborting.\n");
- return err;
- }
-
- mlx4_get_val(num_vfs.dbdf2val.tbl, pci_physfn(pdev), 0, &nvfs);
- mlx4_get_val(probe_vf.dbdf2val.tbl, pci_physfn(pdev), 0, &prb_vf);
- if (nvfs > MLX4_MAX_NUM_VF) {
- dev_err(&pdev->dev, "There are more VF's (%d) than allowed(%d)\n",
- nvfs, MLX4_MAX_NUM_VF);
- return -EINVAL;
- }
-
- if (nvfs < 0) {
- dev_err(&pdev->dev, "num_vfs module parameter cannot be negative\n");
- return -EINVAL;
- }
- /*
- * Check for BARs.
- */
- if (!(pci_dev_data & MLX4_PCI_DEV_IS_VF) &&
- !(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- dev_err(&pdev->dev, "Missing DCS, aborting."
- "(driver_data: 0x%x, pci_resource_flags(pdev, 0):0x%x)\n",
- pci_dev_data, pci_resource_flags(pdev, 0));
- err = -ENODEV;
- goto err_disable_pdev;
- }
- if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
- dev_err(&pdev->dev, "Missing UAR, aborting.\n");
- err = -ENODEV;
- goto err_disable_pdev;
- }
-
- err = pci_request_regions(pdev, DRV_NAME);
- if (err) {
- dev_err(&pdev->dev, "Couldn't get PCI resources, aborting\n");
- goto err_disable_pdev;
- }
-
- pci_set_master(pdev);
-
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
- if (err) {
- dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n");
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (err) {
- dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n");
- goto err_release_regions;
- }
- }
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (err) {
- dev_warn(&pdev->dev, "Warning: couldn't set 64-bit "
- "consistent PCI DMA mask.\n");
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (err) {
- dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, "
- "aborting.\n");
- goto err_release_regions;
- }
- }
-
- /* Allow large DMA segments, up to the firmware limit of 1 GB */
- dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
-
- priv = kzalloc(sizeof *priv, GFP_KERNEL);
- if (!priv) {
- dev_err(&pdev->dev, "Device struct alloc failed, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_release_regions;
- }
-
- dev = &priv->dev;
- dev->pdev = pdev;
- INIT_LIST_HEAD(&priv->dev_list);
- INIT_LIST_HEAD(&priv->ctx_list);
- spin_lock_init(&priv->ctx_lock);
-
- mutex_init(&priv->port_mutex);
-
- INIT_LIST_HEAD(&priv->pgdir_list);
- mutex_init(&priv->pgdir_mutex);
-
- INIT_LIST_HEAD(&priv->bf_list);
- mutex_init(&priv->bf_mutex);
-
- dev->rev_id = pdev->revision;
- dev->numa_node = dev_to_node(&pdev->dev);
- /* Detect if this device is a virtual function */
- if (pci_dev_data & MLX4_PCI_DEV_IS_VF) {
- /* When acting as pf, we normally skip vfs unless explicitly
- * requested to probe them. */
- if (nvfs && extended_func_num(pdev) > prb_vf) {
- mlx4_warn(dev, "Skipping virtual function:%d\n",
- extended_func_num(pdev));
- err = -ENODEV;
- goto err_free_dev;
- }
- mlx4_warn(dev, "Detected virtual function - running in slave mode\n");
- dev->flags |= MLX4_FLAG_SLAVE;
- } else {
- /* We reset the device and enable SRIOV only for physical
- * devices. Try to claim ownership on the device;
- * if already taken, skip -- do not allow multiple PFs */
- err = mlx4_get_ownership(dev);
- if (err) {
- if (err < 0)
- goto err_free_dev;
- else {
- mlx4_warn(dev, "Multiple PFs not yet supported."
- " Skipping PF.\n");
- err = -EINVAL;
- goto err_free_dev;
- }
- }
-
- if (nvfs) {
- mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", nvfs);
- err = pci_enable_sriov(pdev, nvfs);
- if (err) {
- mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n",
- err);
- err = 0;
- } else {
- mlx4_warn(dev, "Running in master mode\n");
- dev->flags |= MLX4_FLAG_SRIOV |
- MLX4_FLAG_MASTER;
- dev->num_vfs = nvfs;
- }
- }
-
- atomic_set(&priv->opreq_count, 0);
- INIT_WORK(&priv->opreq_task, mlx4_opreq_action);
-
- /*
- * Now reset the HCA before we touch the PCI capabilities or
- * attempt a firmware command, since a boot ROM may have left
- * the HCA in an undefined state.
- */
- err = mlx4_reset(dev);
- if (err) {
- mlx4_err(dev, "Failed to reset HCA, aborting.\n");
- goto err_sriov;
- }
- }
-
-slave_start:
- err = mlx4_cmd_init(dev);
- if (err) {
- mlx4_err(dev, "Failed to init command interface, aborting.\n");
- goto err_sriov;
- }
-
- /* In slave functions, the communication channel must be initialized
- * before posting commands. Also, init num_slaves before calling
- * mlx4_init_hca */
- if (mlx4_is_mfunc(dev)) {
- if (mlx4_is_master(dev))
- dev->num_slaves = MLX4_MAX_NUM_SLAVES;
- else {
- dev->num_slaves = 0;
- err = mlx4_multi_func_init(dev);
- if (err) {
- mlx4_err(dev, "Failed to init slave mfunc"
- " interface, aborting.\n");
- goto err_cmd;
- }
- }
- }
-
- err = mlx4_init_hca(dev);
- if (err) {
- if (err == -EACCES) {
- /* Not primary Physical function
- * Running in slave mode */
- mlx4_cmd_cleanup(dev);
- dev->flags |= MLX4_FLAG_SLAVE;
- dev->flags &= ~MLX4_FLAG_MASTER;
- goto slave_start;
- } else
- goto err_mfunc;
- }
-
- /* In master functions, the communication channel must be initialized
- * after obtaining its address from fw */
- if (mlx4_is_master(dev)) {
- err = mlx4_multi_func_init(dev);
- if (err) {
- mlx4_err(dev, "Failed to init master mfunc"
- "interface, aborting.\n");
- goto err_close;
- }
- }
-
- err = mlx4_alloc_eq_table(dev);
- if (err)
- goto err_master_mfunc;
-
- priv->msix_ctl.pool_bm = 0;
- mutex_init(&priv->msix_ctl.pool_lock);
-
- mlx4_enable_msi_x(dev);
-
- /* no MSIX and no shared IRQ */
- if (!dev->caps.num_comp_vectors && !dev->caps.comp_pool) {
- err = -ENOSPC;
- goto err_free_eq;
- }
-
- if ((mlx4_is_mfunc(dev)) &&
- !(dev->flags & MLX4_FLAG_MSI_X)) {
- err = -ENOSYS;
- mlx4_err(dev, "INTx is not supported in multi-function mode."
- " aborting.\n");
- goto err_free_eq;
- }
-
- if (!mlx4_is_slave(dev)) {
- err = mlx4_init_steering(dev);
- if (err)
- goto err_free_eq;
- }
-
- err = mlx4_setup_hca(dev);
- if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X) &&
- !mlx4_is_mfunc(dev)) {
- dev->flags &= ~MLX4_FLAG_MSI_X;
- dev->caps.num_comp_vectors = 1;
- dev->caps.comp_pool = 0;
- pci_disable_msix(pdev);
- err = mlx4_setup_hca(dev);
- }
-
- if (err)
- goto err_steer;
-
- mlx4_init_quotas(dev);
- mlx4_init_hca_info(dev);
-
- for (port = 1; port <= dev->caps.num_ports; port++) {
- err = mlx4_init_port_info(dev, port);
- if (err)
- goto err_port;
- }
-
- err = mlx4_register_device(dev);
- if (err)
- goto err_port;
-
- mlx4_request_modules(dev);
-
- mlx4_sense_init(dev);
- mlx4_start_sense(dev);
-
- priv->pci_dev_data = pci_dev_data;
- pci_set_drvdata(pdev, dev);
-
- return 0;
-
-err_port:
- for (--port; port >= 1; --port)
- mlx4_cleanup_port_info(&priv->port[port]);
-
- mlx4_cleanup_counters_table(dev);
- mlx4_cleanup_qp_table(dev);
- mlx4_cleanup_srq_table(dev);
- mlx4_cleanup_cq_table(dev);
- mlx4_cmd_use_polling(dev);
- mlx4_cleanup_eq_table(dev);
- mlx4_cleanup_mcg_table(dev);
- mlx4_cleanup_mr_table(dev);
- mlx4_cleanup_xrcd_table(dev);
- mlx4_cleanup_pd_table(dev);
- mlx4_cleanup_uar_table(dev);
-
-err_steer:
- if (!mlx4_is_slave(dev))
- mlx4_clear_steering(dev);
-
-err_free_eq:
- mlx4_free_eq_table(dev);
-
-err_master_mfunc:
- if (mlx4_is_master(dev)) {
- mlx4_free_resource_tracker(dev, RES_TR_FREE_STRUCTS_ONLY);
- mlx4_multi_func_cleanup(dev);
- }
-
- if (mlx4_is_slave(dev)) {
- kfree(dev->caps.qp0_tunnel);
- kfree(dev->caps.qp0_proxy);
- kfree(dev->caps.qp1_tunnel);
- kfree(dev->caps.qp1_proxy);
- }
-
-err_close:
- if (dev->flags & MLX4_FLAG_MSI_X)
- pci_disable_msix(pdev);
-
- mlx4_close_hca(dev);
-
-err_mfunc:
- if (mlx4_is_slave(dev))
- mlx4_multi_func_cleanup(dev);
-
-err_cmd:
- mlx4_cmd_cleanup(dev);
-
-err_sriov:
- if (dev->flags & MLX4_FLAG_SRIOV)
- pci_disable_sriov(pdev);
-
- if (!mlx4_is_slave(dev))
- mlx4_free_ownership(dev);
-
-err_free_dev:
- kfree(priv);
-
-err_release_regions:
- pci_release_regions(pdev);
-
-err_disable_pdev:
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
- return err;
-}
-
-static int __devinit mlx4_init_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- device_set_desc(pdev->dev.bsddev, mlx4_version);
- return __mlx4_init_one(pdev, id->driver_data);
-}
-
-static void mlx4_remove_one(struct pci_dev *pdev)
-{
- struct mlx4_dev *dev = pci_get_drvdata(pdev);
- struct mlx4_priv *priv = mlx4_priv(dev);
- int p;
-
- if (dev) {
- /* in SRIOV it is not allowed to unload the pf's
- * driver while there are alive vf's */
- if (mlx4_is_master(dev)) {
- if (mlx4_how_many_lives_vf(dev))
- mlx4_err(dev, "Removing PF when there are assigned VF's !!!\n");
- }
- mlx4_stop_sense(dev);
- mlx4_unregister_device(dev);
-
- mlx4_cleanup_hca_info(&priv->hca_info);
- for (p = 1; p <= dev->caps.num_ports; p++) {
- mlx4_cleanup_port_info(&priv->port[p]);
- mlx4_CLOSE_PORT(dev, p);
- }
-
- if (mlx4_is_master(dev))
- mlx4_free_resource_tracker(dev,
- RES_TR_FREE_SLAVES_ONLY);
-
- mlx4_cleanup_counters_table(dev);
- mlx4_cleanup_qp_table(dev);
- mlx4_cleanup_srq_table(dev);
- mlx4_cleanup_cq_table(dev);
- mlx4_cmd_use_polling(dev);
- mlx4_cleanup_eq_table(dev);
- mlx4_cleanup_mcg_table(dev);
- mlx4_cleanup_mr_table(dev);
- mlx4_cleanup_xrcd_table(dev);
- mlx4_cleanup_pd_table(dev);
-
- if (mlx4_is_master(dev))
- mlx4_free_resource_tracker(dev,
- RES_TR_FREE_STRUCTS_ONLY);
-
- iounmap(priv->kar);
- mlx4_uar_free(dev, &priv->driver_uar);
- mlx4_cleanup_uar_table(dev);
- if (!mlx4_is_slave(dev))
- mlx4_clear_steering(dev);
- mlx4_free_eq_table(dev);
- if (mlx4_is_master(dev))
- mlx4_multi_func_cleanup(dev);
- mlx4_close_hca(dev);
- if (mlx4_is_slave(dev))
- mlx4_multi_func_cleanup(dev);
- mlx4_cmd_cleanup(dev);
-
- if (dev->flags & MLX4_FLAG_MSI_X)
- pci_disable_msix(pdev);
- if (dev->flags & MLX4_FLAG_SRIOV) {
- mlx4_warn(dev, "Disabling SR-IOV\n");
- pci_disable_sriov(pdev);
- }
-
- if (!mlx4_is_slave(dev))
- mlx4_free_ownership(dev);
-
- kfree(dev->caps.qp0_tunnel);
- kfree(dev->caps.qp0_proxy);
- kfree(dev->caps.qp1_tunnel);
- kfree(dev->caps.qp1_proxy);
-
- kfree(priv);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
- }
-}
-
-static int restore_current_port_types(struct mlx4_dev *dev,
- enum mlx4_port_type *types,
- enum mlx4_port_type *poss_types)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err, i;
-
- mlx4_stop_sense(dev);
- mutex_lock(&priv->port_mutex);
- for (i = 0; i < dev->caps.num_ports; i++)
- dev->caps.possible_type[i + 1] = poss_types[i];
- err = mlx4_change_port_types(dev, types);
- mlx4_start_sense(dev);
- mutex_unlock(&priv->port_mutex);
- return err;
-}
-
-int mlx4_restart_one(struct pci_dev *pdev)
-{
- struct mlx4_dev *dev = pci_get_drvdata(pdev);
- struct mlx4_priv *priv = mlx4_priv(dev);
- enum mlx4_port_type curr_type[MLX4_MAX_PORTS];
- enum mlx4_port_type poss_type[MLX4_MAX_PORTS];
- int pci_dev_data, err, i;
-
- pci_dev_data = priv->pci_dev_data;
- for (i = 0; i < dev->caps.num_ports; i++) {
- curr_type[i] = dev->caps.port_type[i + 1];
- poss_type[i] = dev->caps.possible_type[i + 1];
- }
-
- mlx4_remove_one(pdev);
- err = __mlx4_init_one(pdev, pci_dev_data);
- if (err)
- return err;
-
- dev = pci_get_drvdata(pdev);
- err = restore_current_port_types(dev, curr_type, poss_type);
- if (err)
- mlx4_err(dev, "mlx4_restart_one: could not restore original port types (%d)\n",
- err);
- return 0;
-}
-
-static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = {
- /* MT25408 "Hermon" SDR */
- { PCI_VDEVICE(MELLANOX, 0x6340), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25408 "Hermon" DDR */
- { PCI_VDEVICE(MELLANOX, 0x634a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25408 "Hermon" QDR */
- { PCI_VDEVICE(MELLANOX, 0x6354), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25408 "Hermon" DDR PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x6732), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25408 "Hermon" QDR PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x673c), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25408 "Hermon" EN 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x6368), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x6750), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25458 ConnectX EN 10GBASE-T 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x6372), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x675a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT26468 ConnectX EN 10GigE PCIe gen2*/
- { PCI_VDEVICE(MELLANOX, 0x6764), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
- { PCI_VDEVICE(MELLANOX, 0x6746), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT26478 ConnectX2 40GigE PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x676e), MLX4_PCI_DEV_FORCE_SENSE_PORT },
- /* MT25400 Family [ConnectX-2 Virtual Function] */
- { PCI_VDEVICE(MELLANOX, 0x1002), MLX4_PCI_DEV_IS_VF },
- /* MT27500 Family [ConnectX-3] */
- { PCI_VDEVICE(MELLANOX, 0x1003), 0 },
- /* MT27500 Family [ConnectX-3 Virtual Function] */
- { PCI_VDEVICE(MELLANOX, 0x1004), MLX4_PCI_DEV_IS_VF },
- { PCI_VDEVICE(MELLANOX, 0x1005), 0 }, /* MT27510 Family */
- { PCI_VDEVICE(MELLANOX, 0x1006), 0 }, /* MT27511 Family */
- { PCI_VDEVICE(MELLANOX, 0x1007), 0 }, /* MT27520 Family */
- { PCI_VDEVICE(MELLANOX, 0x1008), 0 }, /* MT27521 Family */
- { PCI_VDEVICE(MELLANOX, 0x1009), 0 }, /* MT27530 Family */
- { PCI_VDEVICE(MELLANOX, 0x100a), 0 }, /* MT27531 Family */
- { PCI_VDEVICE(MELLANOX, 0x100b), 0 }, /* MT27540 Family */
- { PCI_VDEVICE(MELLANOX, 0x100c), 0 }, /* MT27541 Family */
- { PCI_VDEVICE(MELLANOX, 0x100d), 0 }, /* MT27550 Family */
- { PCI_VDEVICE(MELLANOX, 0x100e), 0 }, /* MT27551 Family */
- { PCI_VDEVICE(MELLANOX, 0x100f), 0 }, /* MT27560 Family */
- { PCI_VDEVICE(MELLANOX, 0x1010), 0 }, /* MT27561 Family */
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mlx4_pci_table);
-
-static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
- pci_channel_state_t state)
-{
- mlx4_remove_one(pdev);
-
- return state == pci_channel_io_perm_failure ?
- PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
-}
-
-static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
-{
- int ret = __mlx4_init_one(pdev, 0);
-
- return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
-}
-
-static const struct pci_error_handlers mlx4_err_handler = {
- .error_detected = mlx4_pci_err_detected,
- .slot_reset = mlx4_pci_slot_reset,
-};
-
-static int suspend(struct pci_dev *pdev, pm_message_t state)
-{
- mlx4_remove_one(pdev);
-
- return 0;
-}
-
-static int resume(struct pci_dev *pdev)
-{
- return __mlx4_init_one(pdev, 0);
-}
-
-static struct pci_driver mlx4_driver = {
- .name = DRV_NAME,
- .id_table = mlx4_pci_table,
- .probe = mlx4_init_one,
- .remove = __devexit_p(mlx4_remove_one),
- .suspend = suspend,
- .resume = resume,
- .err_handler = &mlx4_err_handler,
-};
-
-static int __init mlx4_verify_params(void)
-{
- int status;
-
- status = update_defaults(&port_type_array);
- if (status == INVALID_STR) {
- if (mlx4_fill_dbdf2val_tbl(&port_type_array.dbdf2val))
- return -1;
- } else if (status == INVALID_DATA) {
- return -1;
- }
-
- status = update_defaults(&num_vfs);
- if (status == INVALID_STR) {
- if (mlx4_fill_dbdf2val_tbl(&num_vfs.dbdf2val))
- return -1;
- } else if (status == INVALID_DATA) {
- return -1;
- }
-
- status = update_defaults(&probe_vf);
- if (status == INVALID_STR) {
- if (mlx4_fill_dbdf2val_tbl(&probe_vf.dbdf2val))
- return -1;
- } else if (status == INVALID_DATA) {
- return -1;
- }
-
- if (msi_x < 0) {
- pr_warn("mlx4_core: bad msi_x: %d\n", msi_x);
- return -1;
- }
-
- if ((log_num_mac < 0) || (log_num_mac > 7)) {
- pr_warning("mlx4_core: bad num_mac: %d\n", log_num_mac);
- return -1;
- }
-
- if (log_num_vlan != 0)
- pr_warning("mlx4_core: log_num_vlan - obsolete module param, using %d\n",
- MLX4_LOG_NUM_VLANS);
-
- if (mlx4_set_4k_mtu != -1)
- pr_warning("mlx4_core: set_4k_mtu - obsolete module param\n");
-
- if ((log_mtts_per_seg < 0) || (log_mtts_per_seg > 7)) {
- pr_warning("mlx4_core: bad log_mtts_per_seg: %d\n", log_mtts_per_seg);
- return -1;
- }
-
- if (mlx4_log_num_mgm_entry_size != -1 &&
- (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE ||
- mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) {
- pr_warning("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not "
- "in legal range (-1 or %d..%d)\n",
- mlx4_log_num_mgm_entry_size,
- MLX4_MIN_MGM_LOG_ENTRY_SIZE,
- MLX4_MAX_MGM_LOG_ENTRY_SIZE);
- return -1;
- }
-
- if (mod_param_profile.num_qp < 18 || mod_param_profile.num_qp > 23) {
- pr_warning("mlx4_core: bad log_num_qp: %d\n",
- mod_param_profile.num_qp);
- return -1;
- }
-
- if (mod_param_profile.num_srq < 10) {
- pr_warning("mlx4_core: too low log_num_srq: %d\n",
- mod_param_profile.num_srq);
- return -1;
- }
-
- if (mod_param_profile.num_cq < 10) {
- pr_warning("mlx4_core: too low log_num_cq: %d\n",
- mod_param_profile.num_cq);
- return -1;
- }
-
- if (mod_param_profile.num_mpt < 10) {
- pr_warning("mlx4_core: too low log_num_mpt: %d\n",
- mod_param_profile.num_mpt);
- return -1;
- }
-
- if (mod_param_profile.num_mtt_segs &&
- mod_param_profile.num_mtt_segs < 15) {
- pr_warning("mlx4_core: too low log_num_mtt: %d\n",
- mod_param_profile.num_mtt_segs);
- return -1;
- }
-
- if (mod_param_profile.num_mtt_segs > MLX4_MAX_LOG_NUM_MTT) {
- pr_warning("mlx4_core: too high log_num_mtt: %d\n",
- mod_param_profile.num_mtt_segs);
- return -1;
- }
- return 0;
-}
-
-static int __init mlx4_init(void)
-{
- int ret;
-
- if (mlx4_verify_params())
- return -EINVAL;
-
- mlx4_catas_init();
-
- mlx4_wq = create_singlethread_workqueue("mlx4");
- if (!mlx4_wq)
- return -ENOMEM;
-
- if (enable_sys_tune)
- sys_tune_init();
-
- ret = pci_register_driver(&mlx4_driver);
- if (ret < 0)
- goto err;
-
- return 0;
-
-err:
- if (enable_sys_tune)
- sys_tune_fini();
-
- destroy_workqueue(mlx4_wq);
-
- return ret;
-}
-
-static void __exit mlx4_cleanup(void)
-{
- if (enable_sys_tune)
- sys_tune_fini();
-
- pci_unregister_driver(&mlx4_driver);
- destroy_workqueue(mlx4_wq);
-}
-
-module_init_order(mlx4_init, SI_ORDER_MIDDLE);
-module_exit(mlx4_cleanup);
-
-static int
-mlx4_evhand(module_t mod, int event, void *arg)
-{
- return (0);
-}
-
-static moduledata_t mlx4_mod = {
- .name = "mlx4",
- .evhand = mlx4_evhand,
-};
-MODULE_VERSION(mlx4, 1);
-DECLARE_MODULE(mlx4, mlx4_mod, SI_SUB_OFED_PREINIT, SI_ORDER_ANY);
-MODULE_DEPEND(mlx4, linuxkpi, 1, 1, 1);
-
diff --git a/sys/ofed/drivers/net/mlx4/mcg.c b/sys/ofed/drivers/net/mlx4/mcg.c
deleted file mode 100644
index 71c1c838564c..000000000000
--- a/sys/ofed/drivers/net/mlx4/mcg.c
+++ /dev/null
@@ -1,1543 +0,0 @@
-/*
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008, 2014 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.
- */
-
-#include <linux/string.h>
-#include <linux/etherdevice.h>
-
-#include <linux/mlx4/cmd.h>
-#include <linux/module.h>
-#include <linux/printk.h>
-
-#include "mlx4.h"
-
-int mlx4_get_mgm_entry_size(struct mlx4_dev *dev)
-{
- return 1 << dev->oper_log_mgm_entry_size;
-}
-
-int mlx4_get_qp_per_mgm(struct mlx4_dev *dev)
-{
- return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2);
-}
-
-static int mlx4_QP_FLOW_STEERING_ATTACH(struct mlx4_dev *dev,
- struct mlx4_cmd_mailbox *mailbox,
- u32 size,
- u64 *reg_id)
-{
- u64 imm;
- int err = 0;
-
- err = mlx4_cmd_imm(dev, mailbox->dma, &imm, size, 0,
- MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err)
- return err;
- *reg_id = imm;
-
- return err;
-}
-
-static int mlx4_QP_FLOW_STEERING_DETACH(struct mlx4_dev *dev, u64 regid)
-{
- int err = 0;
-
- err = mlx4_cmd(dev, regid, 0, 0,
- MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
-
- return err;
-}
-
-static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
- struct mlx4_cmd_mailbox *mailbox)
-{
- return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-}
-
-static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
- struct mlx4_cmd_mailbox *mailbox)
-{
- return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-}
-
-static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 port, u8 steer,
- struct mlx4_cmd_mailbox *mailbox)
-{
- u32 in_mod;
-
- in_mod = (u32) port << 16 | steer << 1;
- return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1,
- MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
-}
-
-static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- u16 *hash, u8 op_mod)
-{
- u64 imm;
- int err;
-
- err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod,
- MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
-
- if (!err)
- *hash = imm;
-
- return err;
-}
-
-static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer,
- u32 qpn)
-{
- struct mlx4_steer *s_steer;
- struct mlx4_promisc_qp *pqp;
-
- if (port < 1 || port > dev->caps.num_ports)
- return NULL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
-
- list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
- if (pqp->qpn == qpn)
- return pqp;
- }
- /* not found */
- return NULL;
-}
-
-/*
- * Add new entry to steering data structure.
- * All promisc QPs should be added as well
- */
-static int new_steering_entry(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer,
- unsigned int index, u32 qpn)
-{
- struct mlx4_steer *s_steer;
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm;
- u32 members_count;
- struct mlx4_steer_index *new_entry;
- struct mlx4_promisc_qp *pqp;
- struct mlx4_promisc_qp *dqp = NULL;
- u32 prot;
- int err;
-
- if (port < 1 || port > dev->caps.num_ports)
- return -EINVAL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
- new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
- if (!new_entry)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&new_entry->duplicates);
- new_entry->index = index;
- list_add_tail(&new_entry->list, &s_steer->steer_entries[steer]);
-
- /* If the given qpn is also a promisc qp,
- * it should be inserted to duplicates list
- */
- pqp = get_promisc_qp(dev, port, steer, qpn);
- if (pqp) {
- dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
- if (!dqp) {
- err = -ENOMEM;
- goto out_alloc;
- }
- dqp->qpn = qpn;
- list_add_tail(&dqp->list, &new_entry->duplicates);
- }
-
- /* if no promisc qps for this vep, we are done */
- if (list_empty(&s_steer->promisc_qps[steer]))
- return 0;
-
- /* now need to add all the promisc qps to the new
- * steering entry, as they should also receive the packets
- * destined to this address */
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = -ENOMEM;
- goto out_alloc;
- }
- mgm = mailbox->buf;
-
- err = mlx4_READ_ENTRY(dev, index, mailbox);
- if (err)
- goto out_mailbox;
-
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- prot = be32_to_cpu(mgm->members_count) >> 30;
- list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
- /* don't add already existing qpn */
- if (pqp->qpn == qpn)
- continue;
- if (members_count == dev->caps.num_qp_per_mgm) {
- /* out of space */
- err = -ENOMEM;
- goto out_mailbox;
- }
-
- /* add the qpn */
- mgm->qp[members_count++] = cpu_to_be32(pqp->qpn & MGM_QPN_MASK);
- }
- /* update the qps count and update the entry with all the promisc qps*/
- mgm->members_count = cpu_to_be32(members_count | (prot << 30));
- err = mlx4_WRITE_ENTRY(dev, index, mailbox);
-
-out_mailbox:
- mlx4_free_cmd_mailbox(dev, mailbox);
- if (!err)
- return 0;
-out_alloc:
- if (dqp) {
- list_del(&dqp->list);
- kfree(dqp);
- }
- list_del(&new_entry->list);
- kfree(new_entry);
- return err;
-}
-
-/* update the data structures with existing steering entry */
-static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer,
- unsigned int index, u32 qpn)
-{
- struct mlx4_steer *s_steer;
- struct mlx4_steer_index *tmp_entry, *entry = NULL;
- struct mlx4_promisc_qp *pqp;
- struct mlx4_promisc_qp *dqp;
-
- if (port < 1 || port > dev->caps.num_ports)
- return -EINVAL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
-
- pqp = get_promisc_qp(dev, port, steer, qpn);
- if (!pqp)
- return 0; /* nothing to do */
-
- list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
- if (tmp_entry->index == index) {
- entry = tmp_entry;
- break;
- }
- }
- if (unlikely(!entry)) {
- mlx4_warn(dev, "Steering entry at index %x is not registered\n", index);
- return -EINVAL;
- }
-
- /* the given qpn is listed as a promisc qpn
- * we need to add it as a duplicate to this entry
- * for future references */
- list_for_each_entry(dqp, &entry->duplicates, list) {
- if (qpn == dqp->qpn)
- return 0; /* qp is already duplicated */
- }
-
- /* add the qp as a duplicate on this index */
- dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
- if (!dqp)
- return -ENOMEM;
- dqp->qpn = qpn;
- list_add_tail(&dqp->list, &entry->duplicates);
-
- return 0;
-}
-
-/* Check whether a qpn is a duplicate on steering entry
- * If so, it should not be removed from mgm */
-static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer,
- unsigned int index, u32 qpn)
-{
- struct mlx4_steer *s_steer;
- struct mlx4_steer_index *tmp_entry, *entry = NULL;
- struct mlx4_promisc_qp *dqp, *tmp_dqp;
-
- if (port < 1 || port > dev->caps.num_ports)
- return NULL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
-
- /* if qp is not promisc, it cannot be duplicated */
- if (!get_promisc_qp(dev, port, steer, qpn))
- return false;
-
- /* The qp is promisc qp so it is a duplicate on this index
- * Find the index entry, and remove the duplicate */
- list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
- if (tmp_entry->index == index) {
- entry = tmp_entry;
- break;
- }
- }
- if (unlikely(!entry)) {
- mlx4_warn(dev, "Steering entry for index %x is not registered\n", index);
- return false;
- }
- list_for_each_entry_safe(dqp, tmp_dqp, &entry->duplicates, list) {
- if (dqp->qpn == qpn) {
- list_del(&dqp->list);
- kfree(dqp);
- }
- }
- return true;
-}
-
-/*
- * returns true if all the QPs != tqpn contained in this entry
- * are Promisc QPs. return false otherwise.
- */
-static bool promisc_steering_entry(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer,
- unsigned int index, u32 tqpn, u32 *members_count)
-{
- struct mlx4_steer *s_steer;
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm;
- u32 m_count;
- bool ret = false;
- int i;
-
- if (port < 1 || port > dev->caps.num_ports)
- return false;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return false;
- mgm = mailbox->buf;
-
- if (mlx4_READ_ENTRY(dev, index, mailbox))
- goto out;
- m_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- if (members_count)
- *members_count = m_count;
-
- for (i = 0; i < m_count; i++) {
- u32 qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
- if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {
- /* the qp is not promisc, the entry can't be removed */
- goto out;
- }
- }
- ret = true;
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return ret;
-}
-
-/* IF a steering entry contains only promisc QPs, it can be removed. */
-static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer,
- unsigned int index, u32 tqpn)
-{
- struct mlx4_steer *s_steer;
- struct mlx4_steer_index *entry = NULL, *tmp_entry;
- u32 members_count;
- bool ret = false;
-
- if (port < 1 || port > dev->caps.num_ports)
- return NULL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
-
- if (!promisc_steering_entry(dev, port, steer, index, tqpn, &members_count))
- goto out;
-
- /* All the qps currently registered for this entry are promiscuous,
- * Checking for duplicates */
- ret = true;
- list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
- if (entry->index == index) {
- if (list_empty(&entry->duplicates) || members_count == 1) {
- struct mlx4_promisc_qp *pqp, *tmp_pqp;
- /*
- * If there is only 1 entry in duplicates than
- * this is the QP we want to delete, going over
- * the list and deleting the entry.
- */
- list_del(&entry->list);
- list_for_each_entry_safe(pqp, tmp_pqp,
- &entry->duplicates,
- list) {
- list_del(&pqp->list);
- kfree(pqp);
- }
- kfree(entry);
- } else {
- /* This entry contains duplicates so it shouldn't be removed */
- ret = false;
- goto out;
- }
- }
- }
-
-out:
- return ret;
-}
-
-static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer, u32 qpn)
-{
- struct mlx4_steer *s_steer;
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm;
- struct mlx4_steer_index *entry;
- struct mlx4_promisc_qp *pqp;
- struct mlx4_promisc_qp *dqp;
- u32 members_count;
- u32 prot;
- int i;
- bool found;
- int err;
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- if (port < 1 || port > dev->caps.num_ports)
- return -EINVAL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
-
- mutex_lock(&priv->mcg_table.mutex);
-
- if (get_promisc_qp(dev, port, steer, qpn)) {
- err = 0; /* Noting to do, already exists */
- goto out_mutex;
- }
-
- pqp = kmalloc(sizeof *pqp, GFP_KERNEL);
- if (!pqp) {
- err = -ENOMEM;
- goto out_mutex;
- }
- pqp->qpn = qpn;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = -ENOMEM;
- goto out_alloc;
- }
- mgm = mailbox->buf;
-
- if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
- /* the promisc qp needs to be added for each one of the steering
- * entries, if it already exists, needs to be added as a duplicate
- * for this entry */
- list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
- err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
-
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- prot = be32_to_cpu(mgm->members_count) >> 30;
- found = false;
- for (i = 0; i < members_count; i++) {
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
- /* Entry already exists, add to duplicates */
- dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
- if (!dqp) {
- err = -ENOMEM;
- goto out_mailbox;
- }
- dqp->qpn = qpn;
- list_add_tail(&dqp->list, &entry->duplicates);
- found = true;
- }
- }
- if (!found) {
- /* Need to add the qpn to mgm */
- if (members_count == dev->caps.num_qp_per_mgm) {
- /* entry is full */
- err = -ENOMEM;
- goto out_mailbox;
- }
- mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
- mgm->members_count = cpu_to_be32(members_count | (prot << 30));
- err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
- }
- }
- }
-
- /* add the new qpn to list of promisc qps */
- list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
- /* now need to add all the promisc qps to default entry */
- memset(mgm, 0, sizeof *mgm);
- members_count = 0;
- list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) {
- if (members_count == dev->caps.num_qp_per_mgm) {
- /* entry is full */
- err = -ENOMEM;
- goto out_list;
- }
- mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
- }
- mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
-
- err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
- if (err)
- goto out_list;
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- mutex_unlock(&priv->mcg_table.mutex);
- return 0;
-
-out_list:
- list_del(&pqp->list);
-out_mailbox:
- mlx4_free_cmd_mailbox(dev, mailbox);
-out_alloc:
- kfree(pqp);
-out_mutex:
- mutex_unlock(&priv->mcg_table.mutex);
- return err;
-}
-
-static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer, u32 qpn)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_steer *s_steer;
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm;
- struct mlx4_steer_index *entry, *tmp_entry;
- struct mlx4_promisc_qp *pqp;
- struct mlx4_promisc_qp *dqp;
- u32 members_count;
- bool found;
- bool back_to_list = false;
- int i, loc = -1;
- int err;
-
- if (port < 1 || port > dev->caps.num_ports)
- return -EINVAL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
- mutex_lock(&priv->mcg_table.mutex);
-
- pqp = get_promisc_qp(dev, port, steer, qpn);
- if (unlikely(!pqp)) {
- mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
- /* nothing to do */
- err = 0;
- goto out_mutex;
- }
-
- /*remove from list of promisc qps */
- list_del(&pqp->list);
-
- /* set the default entry not to include the removed one */
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = -ENOMEM;
- back_to_list = true;
- goto out_list;
- }
- mgm = mailbox->buf;
- memset(mgm, 0, sizeof *mgm);
- members_count = 0;
- list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
- mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
- mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
-
- err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
- if (err)
- goto out_mailbox;
-
- if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
- /* remove the qp from all the steering entries*/
- list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
- found = false;
- list_for_each_entry(dqp, &entry->duplicates, list) {
- if (dqp->qpn == qpn) {
- found = true;
- break;
- }
- }
- if (found) {
- /* a duplicate, no need to change the mgm,
- * only update the duplicates list */
- list_del(&dqp->list);
- kfree(dqp);
- } else {
- err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- if (!members_count) {
- mlx4_warn(dev, "QP %06x wasn't found in entry %x mcount=0."
- " deleting entry...\n", qpn, entry->index);
- list_del(&entry->list);
- kfree(entry);
- continue;
- }
-
- for (i = 0; i < members_count; ++i)
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
- loc = i;
- break;
- }
-
- if (loc < 0) {
- mlx4_err(dev, "QP %06x wasn't found in entry %d\n",
- qpn, entry->index);
- err = -EINVAL;
- goto out_mailbox;
- }
-
- /* copy the last QP in this MGM over removed QP */
- mgm->qp[loc] = mgm->qp[members_count - 1];
- mgm->qp[members_count - 1] = 0;
- mgm->members_count = cpu_to_be32(--members_count |
- (MLX4_PROT_ETH << 30));
-
- err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
- }
- }
- }
-
-out_mailbox:
- mlx4_free_cmd_mailbox(dev, mailbox);
-out_list:
- if (back_to_list)
- list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
- else
- kfree(pqp);
-out_mutex:
- mutex_unlock(&priv->mcg_table.mutex);
- return err;
-}
-
-/*
- * Caller must hold MCG table semaphore. gid and mgm parameters must
- * be properly aligned for command interface.
- *
- * Returns 0 unless a firmware command error occurs.
- *
- * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1
- * and *mgm holds MGM entry.
- *
- * if GID is found in AMGM, *index = index in AMGM, *prev = index of
- * previous entry in hash chain and *mgm holds AMGM entry.
- *
- * If no AMGM exists for given gid, *index = -1, *prev = index of last
- * entry in hash chain and *mgm holds end of hash chain.
- */
-static int find_entry(struct mlx4_dev *dev, u8 port,
- u8 *gid, enum mlx4_protocol prot,
- struct mlx4_cmd_mailbox *mgm_mailbox,
- int *prev, int *index)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm = mgm_mailbox->buf;
- u8 *mgid;
- int err;
- u16 hash;
- u8 op_mod = (prot == MLX4_PROT_ETH) ?
- !!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return -ENOMEM;
- mgid = mailbox->buf;
-
- memcpy(mgid, gid, 16);
-
- err = mlx4_GID_HASH(dev, mailbox, &hash, op_mod);
- mlx4_free_cmd_mailbox(dev, mailbox);
- if (err)
- return err;
-
- if (0) {
- mlx4_dbg(dev, "Hash for "GID_PRINT_FMT" is %04x\n",
- GID_PRINT_ARGS(gid), hash);
- }
-
- *index = hash;
- *prev = -1;
-
- do {
- err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox);
- if (err)
- return err;
-
- if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
- if (*index != hash) {
- mlx4_err(dev, "Found zero MGID in AMGM.\n");
- err = -EINVAL;
- }
- return err;
- }
-
- if (!memcmp(mgm->gid, gid, 16) &&
- be32_to_cpu(mgm->members_count) >> 30 == prot)
- return err;
-
- *prev = *index;
- *index = be32_to_cpu(mgm->next_gid_index) >> 6;
- } while (*index);
-
- *index = -1;
- return err;
-}
-
-static const u8 __promisc_mode[] = {
- [MLX4_FS_REGULAR] = 0x0,
- [MLX4_FS_ALL_DEFAULT] = 0x1,
- [MLX4_FS_MC_DEFAULT] = 0x3,
- [MLX4_FS_UC_SNIFFER] = 0x4,
- [MLX4_FS_MC_SNIFFER] = 0x5,
-};
-
-int map_sw_to_hw_steering_mode(struct mlx4_dev *dev,
- enum mlx4_net_trans_promisc_mode flow_type)
-{
- if (flow_type >= MLX4_FS_MODE_NUM || flow_type < 0) {
- mlx4_err(dev, "Invalid flow type. type = %d\n", flow_type);
- return -EINVAL;
- }
- return __promisc_mode[flow_type];
-}
-EXPORT_SYMBOL_GPL(map_sw_to_hw_steering_mode);
-
-static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,
- struct mlx4_net_trans_rule_hw_ctrl *hw)
-{
- u8 flags = 0;
-
- flags = ctrl->queue_mode == MLX4_NET_TRANS_Q_LIFO ? 1 : 0;
- flags |= ctrl->exclusive ? (1 << 2) : 0;
- flags |= ctrl->allow_loopback ? (1 << 3) : 0;
-
- hw->flags = flags;
- hw->type = __promisc_mode[ctrl->promisc_mode];
- hw->prio = cpu_to_be16(ctrl->priority);
- hw->port = ctrl->port;
- hw->qpn = cpu_to_be32(ctrl->qpn);
-}
-
-const u16 __sw_id_hw[] = {
- [MLX4_NET_TRANS_RULE_ID_ETH] = 0xE001,
- [MLX4_NET_TRANS_RULE_ID_IB] = 0xE005,
- [MLX4_NET_TRANS_RULE_ID_IPV6] = 0xE003,
- [MLX4_NET_TRANS_RULE_ID_IPV4] = 0xE002,
- [MLX4_NET_TRANS_RULE_ID_TCP] = 0xE004,
- [MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006
-};
-
-int map_sw_to_hw_steering_id(struct mlx4_dev *dev,
- enum mlx4_net_trans_rule_id id)
-{
- if (id >= MLX4_NET_TRANS_RULE_NUM || id < 0) {
- mlx4_err(dev, "Invalid network rule id. id = %d\n", id);
- return -EINVAL;
- }
- return __sw_id_hw[id];
-}
-EXPORT_SYMBOL_GPL(map_sw_to_hw_steering_id);
-
-static const int __rule_hw_sz[] = {
- [MLX4_NET_TRANS_RULE_ID_ETH] =
- sizeof(struct mlx4_net_trans_rule_hw_eth),
- [MLX4_NET_TRANS_RULE_ID_IB] =
- sizeof(struct mlx4_net_trans_rule_hw_ib),
- [MLX4_NET_TRANS_RULE_ID_IPV6] = 0,
- [MLX4_NET_TRANS_RULE_ID_IPV4] =
- sizeof(struct mlx4_net_trans_rule_hw_ipv4),
- [MLX4_NET_TRANS_RULE_ID_TCP] =
- sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
- [MLX4_NET_TRANS_RULE_ID_UDP] =
- sizeof(struct mlx4_net_trans_rule_hw_tcp_udp)
-};
-
-int hw_rule_sz(struct mlx4_dev *dev,
- enum mlx4_net_trans_rule_id id)
-{
- if (id >= MLX4_NET_TRANS_RULE_NUM || id < 0) {
- mlx4_err(dev, "Invalid network rule id. id = %d\n", id);
- return -EINVAL;
- }
-
- return __rule_hw_sz[id];
-}
-EXPORT_SYMBOL_GPL(hw_rule_sz);
-
-static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,
- struct _rule_hw *rule_hw)
-{
- if (hw_rule_sz(dev, spec->id) < 0)
- return -EINVAL;
- memset(rule_hw, 0, hw_rule_sz(dev, spec->id));
- rule_hw->id = cpu_to_be16(__sw_id_hw[spec->id]);
- rule_hw->size = hw_rule_sz(dev, spec->id) >> 2;
-
- switch (spec->id) {
- case MLX4_NET_TRANS_RULE_ID_ETH:
- memcpy(rule_hw->eth.dst_mac, spec->eth.dst_mac, ETH_ALEN);
- memcpy(rule_hw->eth.dst_mac_msk, spec->eth.dst_mac_msk,
- ETH_ALEN);
- memcpy(rule_hw->eth.src_mac, spec->eth.src_mac, ETH_ALEN);
- memcpy(rule_hw->eth.src_mac_msk, spec->eth.src_mac_msk,
- ETH_ALEN);
- if (spec->eth.ether_type_enable) {
- rule_hw->eth.ether_type_enable = 1;
- rule_hw->eth.ether_type = spec->eth.ether_type;
- }
- rule_hw->eth.vlan_tag = spec->eth.vlan_id;
- rule_hw->eth.vlan_tag_msk = spec->eth.vlan_id_msk;
- break;
-
- case MLX4_NET_TRANS_RULE_ID_IB:
- rule_hw->ib.l3_qpn = spec->ib.l3_qpn;
- rule_hw->ib.qpn_mask = spec->ib.qpn_msk;
- memcpy(&rule_hw->ib.dst_gid, &spec->ib.dst_gid, 16);
- memcpy(&rule_hw->ib.dst_gid_msk, &spec->ib.dst_gid_msk, 16);
- break;
-
- case MLX4_NET_TRANS_RULE_ID_IPV6:
- return -EOPNOTSUPP;
-
- case MLX4_NET_TRANS_RULE_ID_IPV4:
- rule_hw->ipv4.src_ip = spec->ipv4.src_ip;
- rule_hw->ipv4.src_ip_msk = spec->ipv4.src_ip_msk;
- rule_hw->ipv4.dst_ip = spec->ipv4.dst_ip;
- rule_hw->ipv4.dst_ip_msk = spec->ipv4.dst_ip_msk;
- break;
-
- case MLX4_NET_TRANS_RULE_ID_TCP:
- case MLX4_NET_TRANS_RULE_ID_UDP:
- rule_hw->tcp_udp.dst_port = spec->tcp_udp.dst_port;
- rule_hw->tcp_udp.dst_port_msk = spec->tcp_udp.dst_port_msk;
- rule_hw->tcp_udp.src_port = spec->tcp_udp.src_port;
- rule_hw->tcp_udp.src_port_msk = spec->tcp_udp.src_port_msk;
- break;
-
- default:
- return -EINVAL;
- }
-
- return __rule_hw_sz[spec->id];
-}
-
-static void mlx4_err_rule(struct mlx4_dev *dev, char *str,
- struct mlx4_net_trans_rule *rule)
-{
-#define BUF_SIZE 256
- struct mlx4_spec_list *cur;
- char buf[BUF_SIZE];
- int len = 0;
-
- mlx4_err(dev, "%s", str);
- len += snprintf(buf + len, BUF_SIZE - len,
- "port = %d prio = 0x%x qp = 0x%x ",
- rule->port, rule->priority, rule->qpn);
-
- list_for_each_entry(cur, &rule->list, list) {
- switch (cur->id) {
- case MLX4_NET_TRANS_RULE_ID_ETH:
- len += snprintf(buf + len, BUF_SIZE - len,
- "dmac = %pM ", &cur->eth.dst_mac);
- if (cur->eth.ether_type)
- len += snprintf(buf + len, BUF_SIZE - len,
- "ethertype = 0x%x ",
- be16_to_cpu(cur->eth.ether_type));
- if (cur->eth.vlan_id)
- len += snprintf(buf + len, BUF_SIZE - len,
- "vlan-id = %d ",
- be16_to_cpu(cur->eth.vlan_id));
- break;
-
- case MLX4_NET_TRANS_RULE_ID_IPV4:
- if (cur->ipv4.src_ip)
- len += snprintf(buf + len, BUF_SIZE - len,
- "src-ip = %pI4 ",
- &cur->ipv4.src_ip);
- if (cur->ipv4.dst_ip)
- len += snprintf(buf + len, BUF_SIZE - len,
- "dst-ip = %pI4 ",
- &cur->ipv4.dst_ip);
- break;
-
- case MLX4_NET_TRANS_RULE_ID_TCP:
- case MLX4_NET_TRANS_RULE_ID_UDP:
- if (cur->tcp_udp.src_port)
- len += snprintf(buf + len, BUF_SIZE - len,
- "src-port = %d ",
- be16_to_cpu(cur->tcp_udp.src_port));
- if (cur->tcp_udp.dst_port)
- len += snprintf(buf + len, BUF_SIZE - len,
- "dst-port = %d ",
- be16_to_cpu(cur->tcp_udp.dst_port));
- break;
-
- case MLX4_NET_TRANS_RULE_ID_IB:
- len += snprintf(buf + len, BUF_SIZE - len,
- "dst-gid = "GID_PRINT_FMT"\n",
- GID_PRINT_ARGS(cur->ib.dst_gid));
- len += snprintf(buf + len, BUF_SIZE - len,
- "dst-gid-mask = "GID_PRINT_FMT"\n",
- GID_PRINT_ARGS(cur->ib.dst_gid_msk));
- break;
-
- case MLX4_NET_TRANS_RULE_ID_IPV6:
- break;
-
- default:
- break;
- }
- }
- len += snprintf(buf + len, BUF_SIZE - len, "\n");
- mlx4_err(dev, "%s", buf);
-
- if (len >= BUF_SIZE)
- mlx4_err(dev, "Network rule error message was truncated, print buffer is too small.\n");
-}
-
-int mlx4_flow_attach(struct mlx4_dev *dev,
- struct mlx4_net_trans_rule *rule, u64 *reg_id)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_spec_list *cur;
- u32 size = 0;
- int ret;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- memset(mailbox->buf, 0, sizeof(struct mlx4_net_trans_rule_hw_ctrl));
- trans_rule_ctrl_to_hw(rule, mailbox->buf);
-
- size += sizeof(struct mlx4_net_trans_rule_hw_ctrl);
-
- list_for_each_entry(cur, &rule->list, list) {
- ret = parse_trans_rule(dev, cur, mailbox->buf + size);
- if (ret < 0) {
- mlx4_free_cmd_mailbox(dev, mailbox);
- return -EINVAL;
- }
- size += ret;
- }
-
- ret = mlx4_QP_FLOW_STEERING_ATTACH(dev, mailbox, size >> 2, reg_id);
- if (ret == -ENOMEM)
- mlx4_err_rule(dev,
- "mcg table is full. Fail to register network rule.\n",
- rule);
- else if (ret)
- mlx4_err_rule(dev, "Fail to register network rule.\n", rule);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(mlx4_flow_attach);
-
-int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id)
-{
- int err;
-
- err = mlx4_QP_FLOW_STEERING_DETACH(dev, reg_id);
- if (err)
- mlx4_err(dev, "Fail to detach network rule. registration id = 0x%llx\n",
- (unsigned long long)reg_id);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_flow_detach);
-
-int mlx4_FLOW_STEERING_IB_UC_QP_RANGE(struct mlx4_dev *dev, u32 min_range_qpn, u32 max_range_qpn)
-{
- int err;
- u64 in_param;
-
- in_param = ((u64) min_range_qpn) << 32;
- in_param |= ((u64) max_range_qpn) & 0xFFFFFFFF;
-
- err = mlx4_cmd(dev, in_param, 0, 0,
- MLX4_FLOW_STEERING_IB_UC_QP_RANGE,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_FLOW_STEERING_IB_UC_QP_RANGE);
-
-int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- int block_mcast_loopback, enum mlx4_protocol prot,
- enum mlx4_steer_type steer)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm;
- u32 members_count;
- int index, prev;
- int link = 0;
- int i;
- int err;
- u8 port = gid[5];
- u8 new_entry = 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- mgm = mailbox->buf;
-
- mutex_lock(&priv->mcg_table.mutex);
- err = find_entry(dev, port, gid, prot,
- mailbox, &prev, &index);
- if (err)
- goto out;
-
- if (index != -1) {
- if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
- new_entry = 1;
- memcpy(mgm->gid, gid, 16);
- }
- } else {
- link = 1;
-
- index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap);
- if (index == -1) {
- mlx4_err(dev, "No AMGM entries left\n");
- err = -ENOMEM;
- goto out;
- }
- index += dev->caps.num_mgms;
-
- new_entry = 1;
- memset(mgm, 0, sizeof *mgm);
- memcpy(mgm->gid, gid, 16);
- }
-
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- if (members_count == dev->caps.num_qp_per_mgm) {
- mlx4_err(dev, "MGM at index %x is full.\n", index);
- err = -ENOMEM;
- goto out;
- }
-
- for (i = 0; i < members_count; ++i)
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
- mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn);
- err = 0;
- goto out;
- }
-
- mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) |
- (!!mlx4_blck_lb << MGM_BLCK_LB_BIT));
-
- mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30);
-
- err = mlx4_WRITE_ENTRY(dev, index, mailbox);
- if (err)
- goto out;
-
- /* if !link, still add the new entry. */
- if (!link)
- goto skip_link;
-
- err = mlx4_READ_ENTRY(dev, prev, mailbox);
- if (err)
- goto out;
-
- mgm->next_gid_index = cpu_to_be32(index << 6);
-
- err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
- if (err)
- goto out;
-
-skip_link:
- if (prot == MLX4_PROT_ETH) {
- /* manage the steering entry for promisc mode */
- if (new_entry)
- new_steering_entry(dev, port, steer, index, qp->qpn);
- else
- existing_steering_entry(dev, port, steer,
- index, qp->qpn);
- }
-
-out:
- if (err && link && index != -1) {
- if (index < dev->caps.num_mgms)
- mlx4_warn(dev, "Got AMGM index %d < %d",
- index, dev->caps.num_mgms);
- else
- mlx4_bitmap_free(&priv->mcg_table.bitmap,
- index - dev->caps.num_mgms, MLX4_USE_RR);
- }
- mutex_unlock(&priv->mcg_table.mutex);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- enum mlx4_protocol prot, enum mlx4_steer_type steer)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mgm *mgm;
- u32 members_count;
- int prev, index;
- int i, loc = -1;
- int err;
- u8 port = gid[5];
- bool removed_entry = false;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- mgm = mailbox->buf;
-
- mutex_lock(&priv->mcg_table.mutex);
-
- err = find_entry(dev, port, gid, prot,
- mailbox, &prev, &index);
- if (err)
- goto out;
-
- if (index == -1) {
- mlx4_err(dev, "MGID "GID_PRINT_FMT" not found\n",
- GID_PRINT_ARGS(gid));
- err = -EINVAL;
- goto out;
- }
-
- /*
- if this QP is also a promisc QP, it shouldn't be removed only if
- at least one none promisc QP is also attached to this MCG
- */
- if (prot == MLX4_PROT_ETH &&
- check_duplicate_entry(dev, port, steer, index, qp->qpn) &&
- !promisc_steering_entry(dev, port, steer, index, qp->qpn, NULL))
- goto out;
-
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- for (i = 0; i < members_count; ++i)
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
- loc = i;
- break;
- }
-
- if (loc == -1) {
- mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn);
- err = -EINVAL;
- goto out;
- }
-
- /* copy the last QP in this MGM over removed QP */
- mgm->qp[loc] = mgm->qp[members_count - 1];
- mgm->qp[members_count - 1] = 0;
- mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
-
- if (prot == MLX4_PROT_ETH)
- removed_entry = can_remove_steering_entry(dev, port, steer,
- index, qp->qpn);
- if (members_count && (prot != MLX4_PROT_ETH || !removed_entry)) {
- err = mlx4_WRITE_ENTRY(dev, index, mailbox);
- goto out;
- }
-
- /* We are going to delete the entry, members count should be 0 */
- mgm->members_count = cpu_to_be32((u32) prot << 30);
-
- if (prev == -1) {
- /* Remove entry from MGM */
- int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
- if (amgm_index) {
- err = mlx4_READ_ENTRY(dev, amgm_index, mailbox);
- if (err)
- goto out;
- } else
- memset(mgm->gid, 0, 16);
-
- err = mlx4_WRITE_ENTRY(dev, index, mailbox);
- if (err)
- goto out;
-
- if (amgm_index) {
- if (amgm_index < dev->caps.num_mgms)
- mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d",
- index, amgm_index, dev->caps.num_mgms);
- else
- mlx4_bitmap_free(&priv->mcg_table.bitmap,
- amgm_index - dev->caps.num_mgms, MLX4_USE_RR);
- }
- } else {
- /* Remove entry from AMGM */
- int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
- err = mlx4_READ_ENTRY(dev, prev, mailbox);
- if (err)
- goto out;
-
- mgm->next_gid_index = cpu_to_be32(cur_next_index << 6);
-
- err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
- if (err)
- goto out;
-
- if (index < dev->caps.num_mgms)
- mlx4_warn(dev, "entry %d had next AMGM index %d < %d",
- prev, index, dev->caps.num_mgms);
- else
- mlx4_bitmap_free(&priv->mcg_table.bitmap,
- index - dev->caps.num_mgms, MLX4_USE_RR);
- }
-
-out:
- mutex_unlock(&priv->mcg_table.mutex);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
- u8 gid[16], u8 attach, u8 block_loopback,
- enum mlx4_protocol prot)
-{
- struct mlx4_cmd_mailbox *mailbox;
- int err = 0;
- int qpn;
-
- if (!mlx4_is_mfunc(dev))
- return -EBADF;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- memcpy(mailbox->buf, gid, 16);
- qpn = qp->qpn;
- qpn |= (prot << 28);
- if (attach && block_loopback)
- qpn |= (1 << 31);
-
- err = mlx4_cmd(dev, mailbox->dma, qpn, attach,
- MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_trans_to_dmfs_attach(struct mlx4_dev *dev, struct mlx4_qp *qp,
- u8 gid[16], u8 port,
- int block_mcast_loopback,
- enum mlx4_protocol prot, u64 *reg_id)
-{
- struct mlx4_spec_list spec = { {NULL} };
- __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
-
- struct mlx4_net_trans_rule rule = {
- .queue_mode = MLX4_NET_TRANS_Q_FIFO,
- .exclusive = 0,
- .promisc_mode = MLX4_FS_REGULAR,
- .priority = MLX4_DOMAIN_NIC,
- };
-
- rule.allow_loopback = !block_mcast_loopback;
- rule.port = port;
- rule.qpn = qp->qpn;
- INIT_LIST_HEAD(&rule.list);
-
- switch (prot) {
- case MLX4_PROT_ETH:
- spec.id = MLX4_NET_TRANS_RULE_ID_ETH;
- memcpy(spec.eth.dst_mac, &gid[10], ETH_ALEN);
- memcpy(spec.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
- break;
-
- case MLX4_PROT_IB_IPV6:
- spec.id = MLX4_NET_TRANS_RULE_ID_IB;
- memcpy(spec.ib.dst_gid, gid, 16);
- memset(&spec.ib.dst_gid_msk, 0xff, 16);
- break;
- default:
- return -EINVAL;
- }
- list_add_tail(&spec.list, &rule.list);
-
- return mlx4_flow_attach(dev, &rule, reg_id);
-}
-
-int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- u8 port, int block_mcast_loopback,
- enum mlx4_protocol prot, u64 *reg_id)
-{
- enum mlx4_steer_type steer;
- steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
-
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_A0:
- if (prot == MLX4_PROT_ETH)
- return 0;
-
- case MLX4_STEERING_MODE_B0:
- if (prot == MLX4_PROT_ETH)
- gid[7] |= (steer << 1);
-
- if (mlx4_is_mfunc(dev))
- return mlx4_QP_ATTACH(dev, qp, gid, 1,
- block_mcast_loopback, prot);
- return mlx4_qp_attach_common(dev, qp, gid,
- block_mcast_loopback, prot,
- MLX4_MC_STEER);
-
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- return mlx4_trans_to_dmfs_attach(dev, qp, gid, port,
- block_mcast_loopback,
- prot, reg_id);
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
-
-int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- enum mlx4_protocol prot, u64 reg_id)
-{
- enum mlx4_steer_type steer;
- steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
-
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_A0:
- if (prot == MLX4_PROT_ETH)
- return 0;
-
- case MLX4_STEERING_MODE_B0:
- if (prot == MLX4_PROT_ETH)
- gid[7] |= (steer << 1);
-
- if (mlx4_is_mfunc(dev))
- return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
-
- return mlx4_qp_detach_common(dev, qp, gid, prot,
- MLX4_MC_STEER);
-
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- return mlx4_flow_detach(dev, reg_id);
-
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
-
-int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port,
- u32 qpn, enum mlx4_net_trans_promisc_mode mode)
-{
- struct mlx4_net_trans_rule rule;
- u64 *regid_p;
-
- switch (mode) {
- case MLX4_FS_ALL_DEFAULT:
- regid_p = &dev->regid_promisc_array[port];
- break;
- case MLX4_FS_MC_DEFAULT:
- regid_p = &dev->regid_allmulti_array[port];
- break;
- default:
- return -1;
- }
-
- if (*regid_p != 0)
- return -1;
-
- rule.promisc_mode = mode;
- rule.port = port;
- rule.qpn = qpn;
- INIT_LIST_HEAD(&rule.list);
- mlx4_err(dev, "going promisc on %x\n", port);
-
- return mlx4_flow_attach(dev, &rule, regid_p);
-}
-EXPORT_SYMBOL_GPL(mlx4_flow_steer_promisc_add);
-
-int mlx4_flow_steer_promisc_remove(struct mlx4_dev *dev, u8 port,
- enum mlx4_net_trans_promisc_mode mode)
-{
- int ret;
- u64 *regid_p;
-
- switch (mode) {
- case MLX4_FS_ALL_DEFAULT:
- regid_p = &dev->regid_promisc_array[port];
- break;
- case MLX4_FS_MC_DEFAULT:
- regid_p = &dev->regid_allmulti_array[port];
- break;
- default:
- return -1;
- }
-
- if (*regid_p == 0)
- return -1;
-
- ret = mlx4_flow_detach(dev, *regid_p);
- if (ret == 0)
- *regid_p = 0;
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(mlx4_flow_steer_promisc_remove);
-
-int mlx4_unicast_attach(struct mlx4_dev *dev,
- struct mlx4_qp *qp, u8 gid[16],
- int block_mcast_loopback, enum mlx4_protocol prot)
-{
- if (prot == MLX4_PROT_ETH)
- gid[7] |= (MLX4_UC_STEER << 1);
-
- if (mlx4_is_mfunc(dev))
- return mlx4_QP_ATTACH(dev, qp, gid, 1,
- block_mcast_loopback, prot);
-
- return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback,
- prot, MLX4_UC_STEER);
-}
-EXPORT_SYMBOL_GPL(mlx4_unicast_attach);
-
-int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,
- u8 gid[16], enum mlx4_protocol prot)
-{
- if (prot == MLX4_PROT_ETH)
- gid[7] |= (MLX4_UC_STEER << 1);
-
- if (mlx4_is_mfunc(dev))
- return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
-
- return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_UC_STEER);
-}
-EXPORT_SYMBOL_GPL(mlx4_unicast_detach);
-
-int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- u32 qpn = (u32) vhcr->in_param & 0xffffffff;
- u8 port = vhcr->in_param >> 62;
- enum mlx4_steer_type steer = vhcr->in_modifier;
-
- /* Promiscuous unicast is not allowed in mfunc for VFs */
- if ((slave != dev->caps.function) && (steer == MLX4_UC_STEER))
- return 0;
-
- if (vhcr->op_modifier)
- return add_promisc_qp(dev, port, steer, qpn);
- else
- return remove_promisc_qp(dev, port, steer, qpn);
-}
-
-static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn,
- enum mlx4_steer_type steer, u8 add, u8 port)
-{
- return mlx4_cmd(dev, (u64) qpn | (u64) port << 62, (u32) steer, add,
- MLX4_CMD_PROMISC, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
-}
-
-int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
-{
- if (mlx4_is_mfunc(dev))
- return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port);
-
- return add_promisc_qp(dev, port, MLX4_MC_STEER, qpn);
-}
-EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
-
-int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
-{
- if (mlx4_is_mfunc(dev))
- return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port);
-
- return remove_promisc_qp(dev, port, MLX4_MC_STEER, qpn);
-}
-EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
-
-int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
-{
- if (mlx4_is_mfunc(dev))
- return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port);
-
- return add_promisc_qp(dev, port, MLX4_UC_STEER, qpn);
-}
-EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
-
-int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
-{
- if (mlx4_is_mfunc(dev))
- return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port);
-
- return remove_promisc_qp(dev, port, MLX4_UC_STEER, qpn);
-}
-EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
-
-int mlx4_init_mcg_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err;
-
- /* No need for mcg_table when fw managed the mcg table*/
- if (dev->caps.steering_mode ==
- MLX4_STEERING_MODE_DEVICE_MANAGED)
- return 0;
- err = mlx4_bitmap_init(&priv->mcg_table.bitmap, dev->caps.num_amgms,
- dev->caps.num_amgms - 1, 0, 0);
- if (err)
- return err;
-
- mutex_init(&priv->mcg_table.mutex);
-
- return 0;
-}
-
-void mlx4_cleanup_mcg_table(struct mlx4_dev *dev)
-{
- if (dev->caps.steering_mode !=
- MLX4_STEERING_MODE_DEVICE_MANAGED)
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap);
-}
diff --git a/sys/ofed/drivers/net/mlx4/mlx4.h b/sys/ofed/drivers/net/mlx4/mlx4.h
deleted file mode 100644
index e23e461fd022..000000000000
--- a/sys/ofed/drivers/net/mlx4/mlx4.h
+++ /dev/null
@@ -1,1328 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2004 Voltaire, Inc. 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.
- */
-
-#ifndef MLX4_H
-#define MLX4_H
-
-#include <linux/mutex.h>
-#include <linux/radix-tree.h>
-#include <linux/rbtree.h>
-#include <linux/timer.h>
-#include <linux/semaphore.h>
-#include <linux/workqueue.h>
-#include <linux/device.h>
-#include <linux/mlx4/device.h>
-#include <linux/mlx4/driver.h>
-#include <linux/mlx4/doorbell.h>
-#include <linux/mlx4/cmd.h>
-
-#define DRV_NAME "mlx4_core"
-#define PFX DRV_NAME ": "
-#define DRV_VERSION "2.1.6"
-#define DRV_RELDATE __DATE__
-
-#define DRV_STACK_NAME "Linux-MLNX_OFED"
-#define DRV_STACK_VERSION "2.1"
-#define DRV_NAME_FOR_FW DRV_STACK_NAME","DRV_STACK_VERSION
-
-#define MLX4_FS_UDP_UC_EN (1 << 1)
-#define MLX4_FS_TCP_UC_EN (1 << 2)
-#define MLX4_FS_NUM_OF_L2_ADDR 8
-#define MLX4_FS_MGM_LOG_ENTRY_SIZE 7
-#define MLX4_FS_NUM_MCG (1 << 17)
-
-struct mlx4_set_port_prio2tc_context {
- u8 prio2tc[4];
-};
-
-struct mlx4_port_scheduler_tc_cfg_be {
- __be16 pg;
- __be16 bw_precentage;
- __be16 max_bw_units; /* 3-100Mbps, 4-1Gbps, other values - reserved */
- __be16 max_bw_value;
-};
-
-struct mlx4_set_port_scheduler_context {
- struct mlx4_port_scheduler_tc_cfg_be tc[MLX4_NUM_TC];
-};
-
-enum {
- MLX4_HCR_BASE = 0x80680,
- MLX4_HCR_SIZE = 0x0001c,
- MLX4_CLR_INT_SIZE = 0x00008,
- MLX4_SLAVE_COMM_BASE = 0x0,
- MLX4_COMM_PAGESIZE = 0x1000,
- MLX4_CLOCK_SIZE = 0x00008
-};
-
-enum {
- MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE = 10,
- MLX4_MIN_MGM_LOG_ENTRY_SIZE = 7,
- MLX4_MAX_MGM_LOG_ENTRY_SIZE = 12,
- MLX4_MAX_QP_PER_MGM = 4 * ((1 << MLX4_MAX_MGM_LOG_ENTRY_SIZE)/16 - 2),
-};
-
-enum {
- MLX4_NUM_PDS = 1 << 15
-};
-
-enum {
- MLX4_CMPT_TYPE_QP = 0,
- MLX4_CMPT_TYPE_SRQ = 1,
- MLX4_CMPT_TYPE_CQ = 2,
- MLX4_CMPT_TYPE_EQ = 3,
- MLX4_CMPT_NUM_TYPE
-};
-
-enum {
- MLX4_CMPT_SHIFT = 24,
- MLX4_NUM_CMPTS = MLX4_CMPT_NUM_TYPE << MLX4_CMPT_SHIFT
-};
-
-enum mlx4_mpt_state {
- MLX4_MPT_DISABLED = 0,
- MLX4_MPT_EN_HW,
- MLX4_MPT_EN_SW
-};
-
-#define MLX4_COMM_TIME 10000
-enum {
- MLX4_COMM_CMD_RESET,
- MLX4_COMM_CMD_VHCR0,
- MLX4_COMM_CMD_VHCR1,
- MLX4_COMM_CMD_VHCR2,
- MLX4_COMM_CMD_VHCR_EN,
- MLX4_COMM_CMD_VHCR_POST,
- MLX4_COMM_CMD_FLR = 254
-};
-
-/*The flag indicates that the slave should delay the RESET cmd*/
-#define MLX4_DELAY_RESET_SLAVE 0xbbbbbbb
-/*indicates how many retries will be done if we are in the middle of FLR*/
-#define NUM_OF_RESET_RETRIES 10
-#define SLEEP_TIME_IN_RESET (2 * 1000)
-enum mlx4_resource {
- RES_QP,
- RES_CQ,
- RES_SRQ,
- RES_XRCD,
- RES_MPT,
- RES_MTT,
- RES_MAC,
- RES_VLAN,
- RES_NPORT_ID,
- RES_COUNTER,
- RES_FS_RULE,
- RES_EQ,
- MLX4_NUM_OF_RESOURCE_TYPE
-};
-
-enum mlx4_alloc_mode {
- RES_OP_RESERVE,
- RES_OP_RESERVE_AND_MAP,
- RES_OP_MAP_ICM,
-};
-
-enum mlx4_res_tracker_free_type {
- RES_TR_FREE_ALL,
- RES_TR_FREE_SLAVES_ONLY,
- RES_TR_FREE_STRUCTS_ONLY,
-};
-
-/*
- *Virtual HCR structures.
- * mlx4_vhcr is the sw representation, in machine endianness
- *
- * mlx4_vhcr_cmd is the formalized structure, the one that is passed
- * to FW to go through communication channel.
- * It is big endian, and has the same structure as the physical HCR
- * used by command interface
- */
-struct mlx4_vhcr {
- u64 in_param;
- u64 out_param;
- u32 in_modifier;
- u32 errno;
- u16 op;
- u16 token;
- u8 op_modifier;
- u8 e_bit;
-};
-
-struct mlx4_vhcr_cmd {
- __be64 in_param;
- __be32 in_modifier;
- u32 reserved1;
- __be64 out_param;
- __be16 token;
- u16 reserved;
- u8 status;
- u8 flags;
- __be16 opcode;
-} __packed;
-
-struct mlx4_cmd_info {
- u16 opcode;
- bool has_inbox;
- bool has_outbox;
- bool out_is_imm;
- bool encode_slave_id;
- bool skip_err_print;
- int (*verify)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox);
- int (*wrapper)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-};
-
-enum {
- MLX4_DEBUG_MASK_CMD_TIME = 0x100,
-};
-
-#ifdef CONFIG_MLX4_DEBUG
-extern int mlx4_debug_level;
-#else /* CONFIG_MLX4_DEBUG */
-#define mlx4_debug_level (0)
-#endif /* CONFIG_MLX4_DEBUG */
-
-#define mlx4_dbg(mdev, format, arg...) \
-do { \
- if (mlx4_debug_level) \
- dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ##arg); \
-} while (0)
-
-#define mlx4_err(mdev, format, arg...) \
- dev_err(&mdev->pdev->dev, format, ##arg)
-#define mlx4_info(mdev, format, arg...) \
- dev_info(&mdev->pdev->dev, format, ##arg)
-#define mlx4_warn(mdev, format, arg...) \
- dev_warn(&mdev->pdev->dev, format, ##arg)
-
-extern int mlx4_log_num_mgm_entry_size;
-extern int log_mtts_per_seg;
-extern int mlx4_blck_lb;
-extern int mlx4_set_4k_mtu;
-
-#define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF)
-#define ALL_SLAVES 0xff
-
-struct mlx4_bitmap {
- u32 last;
- u32 top;
- u32 max;
- u32 reserved_top;
- u32 mask;
- u32 avail;
- spinlock_t lock;
- unsigned long *table;
-};
-
-struct mlx4_buddy {
- unsigned long **bits;
- unsigned int *num_free;
- u32 max_order;
- spinlock_t lock;
-};
-
-struct mlx4_icm;
-
-struct mlx4_icm_table {
- u64 virt;
- int num_icm;
- u32 num_obj;
- int obj_size;
- int lowmem;
- int coherent;
- struct mutex mutex;
- struct mlx4_icm **icm;
-};
-
-#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
-#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
-#define MLX4_MPT_FLAG_MIO (1 << 17)
-#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15)
-#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
-#define MLX4_MPT_FLAG_REGION (1 << 8)
-
-#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27)
-#define MLX4_MPT_PD_FLAG_RAE (1 << 28)
-#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
-
-#define MLX4_MPT_QP_FLAG_BOUND_QP (1 << 7)
-
-#define MLX4_MPT_STATUS_SW 0xF0
-#define MLX4_MPT_STATUS_HW 0x00
-
-/*
- * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
- */
-struct mlx4_mpt_entry {
- __be32 flags;
- __be32 qpn;
- __be32 key;
- __be32 pd_flags;
- __be64 start;
- __be64 length;
- __be32 lkey;
- __be32 win_cnt;
- u8 reserved1[3];
- u8 mtt_rep;
- __be64 mtt_addr;
- __be32 mtt_sz;
- __be32 entity_size;
- __be32 first_byte_offset;
-} __packed;
-
-/*
- * Must be packed because start is 64 bits but only aligned to 32 bits.
- */
-struct mlx4_eq_context {
- __be32 flags;
- u16 reserved1[3];
- __be16 page_offset;
- u8 log_eq_size;
- u8 reserved2[4];
- u8 eq_period;
- u8 reserved3;
- u8 eq_max_count;
- u8 reserved4[3];
- u8 intr;
- u8 log_page_size;
- u8 reserved5[2];
- u8 mtt_base_addr_h;
- __be32 mtt_base_addr_l;
- u32 reserved6[2];
- __be32 consumer_index;
- __be32 producer_index;
- u32 reserved7[4];
-};
-
-struct mlx4_cq_context {
- __be32 flags;
- u16 reserved1[3];
- __be16 page_offset;
- __be32 logsize_usrpage;
- __be16 cq_period;
- __be16 cq_max_count;
- u8 reserved2[3];
- u8 comp_eqn;
- u8 log_page_size;
- u8 reserved3[2];
- u8 mtt_base_addr_h;
- __be32 mtt_base_addr_l;
- __be32 last_notified_index;
- __be32 solicit_producer_index;
- __be32 consumer_index;
- __be32 producer_index;
- u32 reserved4[2];
- __be64 db_rec_addr;
-};
-
-struct mlx4_srq_context {
- __be32 state_logsize_srqn;
- u8 logstride;
- u8 reserved1;
- __be16 xrcd;
- __be32 pg_offset_cqn;
- u32 reserved2;
- u8 log_page_size;
- u8 reserved3[2];
- u8 mtt_base_addr_h;
- __be32 mtt_base_addr_l;
- __be32 pd;
- __be16 limit_watermark;
- __be16 wqe_cnt;
- u16 reserved4;
- __be16 wqe_counter;
- u32 reserved5;
- __be64 db_rec_addr;
-};
-
-struct mlx4_eq {
- struct mlx4_dev *dev;
- void __iomem *doorbell;
- int eqn;
- u32 cons_index;
- u16 irq;
- u16 have_irq;
- int nent;
- struct mlx4_buf_list *page_list;
- struct mlx4_mtt mtt;
-};
-
-struct mlx4_slave_eqe {
- u8 type;
- u8 port;
- u32 param;
-};
-
-struct mlx4_slave_event_eq_info {
- int eqn;
- u16 token;
-};
-
-struct mlx4_profile {
- int num_qp;
- int rdmarc_per_qp;
- int num_srq;
- int num_cq;
- int num_mcg;
- int num_mpt;
- unsigned num_mtt_segs;
-};
-
-struct mlx4_fw {
- u64 clr_int_base;
- u64 catas_offset;
- u64 comm_base;
- u64 clock_offset;
- struct mlx4_icm *fw_icm;
- struct mlx4_icm *aux_icm;
- u32 catas_size;
- u16 fw_pages;
- u8 clr_int_bar;
- u8 catas_bar;
- u8 comm_bar;
- u8 clock_bar;
-};
-
-struct mlx4_comm {
- u32 slave_write;
- u32 slave_read;
-};
-
-enum {
- MLX4_MCAST_CONFIG = 0,
- MLX4_MCAST_DISABLE = 1,
- MLX4_MCAST_ENABLE = 2,
-};
-
-#define VLAN_FLTR_SIZE 128
-
-struct mlx4_vlan_fltr {
- __be32 entry[VLAN_FLTR_SIZE];
-};
-
-struct mlx4_mcast_entry {
- struct list_head list;
- u64 addr;
-};
-
-struct mlx4_promisc_qp {
- struct list_head list;
- u32 qpn;
-};
-
-struct mlx4_steer_index {
- struct list_head list;
- unsigned int index;
- struct list_head duplicates;
-};
-
-#define MLX4_EVENT_TYPES_NUM 64
-
-struct mlx4_slave_state {
- u8 comm_toggle;
- u8 last_cmd;
- u8 init_port_mask;
- bool active;
- bool old_vlan_api;
- u8 function;
- dma_addr_t vhcr_dma;
- u16 mtu[MLX4_MAX_PORTS + 1];
- __be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
- struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
- struct list_head mcast_filters[MLX4_MAX_PORTS + 1];
- struct mlx4_vlan_fltr *vlan_filter[MLX4_MAX_PORTS + 1];
- /* event type to eq number lookup */
- struct mlx4_slave_event_eq_info event_eq[MLX4_EVENT_TYPES_NUM];
- u16 eq_pi;
- u16 eq_ci;
- spinlock_t lock;
- /*initialized via the kzalloc*/
- u8 is_slave_going_down;
- u32 cookie;
- enum slave_port_state port_state[MLX4_MAX_PORTS + 1];
-};
-
-#define MLX4_VGT 4095
-#define NO_INDX (-1)
-
-
-struct mlx4_vport_state {
- u64 mac;
- u16 default_vlan;
- u8 default_qos;
- u32 tx_rate;
- bool spoofchk;
- u32 link_state;
-};
-
-struct mlx4_vf_admin_state {
- struct mlx4_vport_state vport[MLX4_MAX_PORTS + 1];
-};
-
-struct mlx4_vport_oper_state {
- struct mlx4_vport_state state;
- int mac_idx;
- int vlan_idx;
-};
-struct mlx4_vf_oper_state {
- struct mlx4_vport_oper_state vport[MLX4_MAX_PORTS + 1];
-};
-
-struct slave_list {
- struct mutex mutex;
- struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE];
-};
-
-struct resource_allocator {
- spinlock_t alloc_lock;
- union {
- int res_reserved;
- int res_port_rsvd[MLX4_MAX_PORTS];
- };
- union {
- int res_free;
- int res_port_free[MLX4_MAX_PORTS];
- };
- int *quota;
- int *allocated;
- int *guaranteed;
-};
-
-struct mlx4_resource_tracker {
- spinlock_t lock;
- /* tree for each resources */
- struct rb_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE];
- /* num_of_slave's lists, one per slave */
- struct slave_list *slave_list;
- struct resource_allocator res_alloc[MLX4_NUM_OF_RESOURCE_TYPE];
-};
-
-#define SLAVE_EVENT_EQ_SIZE 128
-struct mlx4_slave_event_eq {
- u32 eqn;
- u32 cons;
- u32 prod;
- spinlock_t event_lock;
- struct mlx4_eqe event_eqe[SLAVE_EVENT_EQ_SIZE];
-};
-
-struct mlx4_master_qp0_state {
- int proxy_qp0_active;
- int qp0_active;
- int port_active;
-};
-
-struct mlx4_mfunc_master_ctx {
- struct mlx4_slave_state *slave_state;
- struct mlx4_vf_admin_state *vf_admin;
- struct mlx4_vf_oper_state *vf_oper;
- struct mlx4_master_qp0_state qp0_state[MLX4_MAX_PORTS + 1];
- int init_port_ref[MLX4_MAX_PORTS + 1];
- u16 max_mtu[MLX4_MAX_PORTS + 1];
- int disable_mcast_ref[MLX4_MAX_PORTS + 1];
- struct mlx4_resource_tracker res_tracker;
- struct workqueue_struct *comm_wq;
- struct work_struct comm_work;
- struct work_struct arm_comm_work;
- struct work_struct slave_event_work;
- struct work_struct slave_flr_event_work;
- spinlock_t slave_state_lock;
- __be32 comm_arm_bit_vector[4];
- struct mlx4_eqe cmd_eqe;
- struct mlx4_slave_event_eq slave_eq;
- struct mutex gen_eqe_mutex[MLX4_MFUNC_MAX];
-};
-
-struct mlx4_mfunc {
- struct mlx4_comm __iomem *comm;
- struct mlx4_vhcr_cmd *vhcr;
- dma_addr_t vhcr_dma;
-
- struct mlx4_mfunc_master_ctx master;
-};
-
-#define MGM_QPN_MASK 0x00FFFFFF
-#define MGM_BLCK_LB_BIT 30
-
-struct mlx4_mgm {
- __be32 next_gid_index;
- __be32 members_count;
- u32 reserved[2];
- u8 gid[16];
- __be32 qp[MLX4_MAX_QP_PER_MGM];
-};
-
-struct mlx4_cmd {
- struct pci_pool *pool;
- void __iomem *hcr;
- struct mutex hcr_mutex;
- struct mutex slave_cmd_mutex;
- struct semaphore poll_sem;
- struct semaphore event_sem;
- int max_cmds;
- spinlock_t context_lock;
- int free_head;
- struct mlx4_cmd_context *context;
- u16 token_mask;
- u8 use_events;
- u8 toggle;
- u8 comm_toggle;
-};
-
-enum {
- MLX4_VF_IMMED_VLAN_FLAG_VLAN = 1 << 0,
- MLX4_VF_IMMED_VLAN_FLAG_QOS = 1 << 1,
-};
-struct mlx4_vf_immed_vlan_work {
- struct work_struct work;
- struct mlx4_priv *priv;
- int flags;
- int slave;
- int vlan_ix;
- int orig_vlan_ix;
- u8 port;
- u8 qos;
- u16 vlan_id;
- u16 orig_vlan_id;
-};
-
-
-struct mlx4_uar_table {
- struct mlx4_bitmap bitmap;
-};
-
-struct mlx4_mr_table {
- struct mlx4_bitmap mpt_bitmap;
- struct mlx4_buddy mtt_buddy;
- u64 mtt_base;
- u64 mpt_base;
- struct mlx4_icm_table mtt_table;
- struct mlx4_icm_table dmpt_table;
-};
-
-struct mlx4_cq_table {
- struct mlx4_bitmap bitmap;
- spinlock_t lock;
- rwlock_t cq_table_lock;
- struct radix_tree_root tree;
- struct mlx4_icm_table table;
- struct mlx4_icm_table cmpt_table;
-};
-
-struct mlx4_eq_table {
- struct mlx4_bitmap bitmap;
- char *irq_names;
- void __iomem *clr_int;
- void __iomem **uar_map;
- u32 clr_mask;
- struct mlx4_eq *eq;
- struct mlx4_icm_table table;
- struct mlx4_icm_table cmpt_table;
- int have_irq;
- u8 inta_pin;
-};
-
-struct mlx4_srq_table {
- struct mlx4_bitmap bitmap;
- spinlock_t lock;
- struct radix_tree_root tree;
- struct mlx4_icm_table table;
- struct mlx4_icm_table cmpt_table;
-};
-
-struct mlx4_qp_table {
- struct mlx4_bitmap bitmap;
- u32 rdmarc_base;
- int rdmarc_shift;
- spinlock_t lock;
- struct mlx4_icm_table qp_table;
- struct mlx4_icm_table auxc_table;
- struct mlx4_icm_table altc_table;
- struct mlx4_icm_table rdmarc_table;
- struct mlx4_icm_table cmpt_table;
-};
-
-struct mlx4_mcg_table {
- struct mutex mutex;
- struct mlx4_bitmap bitmap;
- struct mlx4_icm_table table;
-};
-
-struct mlx4_catas_err {
- u32 __iomem *map;
- struct timer_list timer;
- struct list_head list;
-};
-
-#define MLX4_MAX_MAC_NUM 128
-#define MLX4_MAC_TABLE_SIZE (MLX4_MAX_MAC_NUM << 3)
-
-struct mlx4_mac_table {
- __be64 entries[MLX4_MAX_MAC_NUM];
- int refs[MLX4_MAX_MAC_NUM];
- struct mutex mutex;
- int total;
- int max;
-};
-
-#define MLX4_MAX_VLAN_NUM 128
-#define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2)
-
-struct mlx4_vlan_table {
- __be32 entries[MLX4_MAX_VLAN_NUM];
- int refs[MLX4_MAX_VLAN_NUM];
- struct mutex mutex;
- int total;
- int max;
-};
-
-#define SET_PORT_GEN_ALL_VALID 0x7
-#define SET_PORT_PROMISC_SHIFT 31
-#define SET_PORT_MC_PROMISC_SHIFT 30
-
-enum {
- MCAST_DIRECT_ONLY = 0,
- MCAST_DIRECT = 1,
- MCAST_DEFAULT = 2
-};
-
-
-struct mlx4_set_port_general_context {
- u8 reserved[3];
- u8 flags;
- u16 reserved2;
- __be16 mtu;
- u8 pptx;
- u8 pfctx;
- u16 reserved3;
- u8 pprx;
- u8 pfcrx;
- u16 reserved4;
-};
-
-struct mlx4_set_port_rqp_calc_context {
- __be32 base_qpn;
- u8 rererved;
- u8 n_mac;
- u8 n_vlan;
- u8 n_prio;
- u8 reserved2[3];
- u8 mac_miss;
- u8 intra_no_vlan;
- u8 no_vlan;
- u8 intra_vlan_miss;
- u8 vlan_miss;
- u8 reserved3[3];
- u8 no_vlan_prio;
- __be32 promisc;
- __be32 mcast;
-};
-
-struct mlx4_hca_info {
- struct mlx4_dev *dev;
- struct device_attribute firmware_attr;
- struct device_attribute hca_attr;
- struct device_attribute board_attr;
-};
-
-struct mlx4_port_info {
- struct mlx4_dev *dev;
- int port;
- char dev_name[16];
- struct device_attribute port_attr;
- enum mlx4_port_type tmp_type;
- char dev_mtu_name[16];
- struct device_attribute port_mtu_attr;
- struct mlx4_mac_table mac_table;
- struct mlx4_vlan_table vlan_table;
- int base_qpn;
-};
-
-struct mlx4_sense {
- struct mlx4_dev *dev;
- u8 do_sense_port[MLX4_MAX_PORTS + 1];
- u8 sense_allowed[MLX4_MAX_PORTS + 1];
- struct delayed_work sense_poll;
-};
-
-struct mlx4_msix_ctl {
- u64 pool_bm;
- struct mutex pool_lock;
-};
-
-struct mlx4_steer {
- struct list_head promisc_qps[MLX4_NUM_STEERS];
- struct list_head steer_entries[MLX4_NUM_STEERS];
-};
-
-enum {
- MLX4_PCI_DEV_IS_VF = 1 << 0,
- MLX4_PCI_DEV_FORCE_SENSE_PORT = 1 << 1,
-};
-
-struct mlx4_roce_gid_entry {
- u8 raw[16];
-};
-
-struct counter_index {
- struct list_head list;
- u32 index;
-};
-
-struct mlx4_counters {
- struct mlx4_bitmap bitmap;
- struct list_head global_port_list[MLX4_MAX_PORTS];
- struct list_head vf_list[MLX4_MAX_NUM_VF][MLX4_MAX_PORTS];
- struct mutex mutex;
-};
-
-enum {
- MLX4_NO_RR = 0,
- MLX4_USE_RR = 1,
-};
-
-struct mlx4_priv {
- struct mlx4_dev dev;
-
- struct list_head dev_list;
- struct list_head ctx_list;
- spinlock_t ctx_lock;
-
- int pci_dev_data;
-
- struct list_head pgdir_list;
- struct mutex pgdir_mutex;
-
- struct mlx4_fw fw;
- struct mlx4_cmd cmd;
- struct mlx4_mfunc mfunc;
-
- struct mlx4_bitmap pd_bitmap;
- struct mlx4_bitmap xrcd_bitmap;
- struct mlx4_uar_table uar_table;
- struct mlx4_mr_table mr_table;
- struct mlx4_cq_table cq_table;
- struct mlx4_eq_table eq_table;
- struct mlx4_srq_table srq_table;
- struct mlx4_qp_table qp_table;
- struct mlx4_mcg_table mcg_table;
- struct mlx4_counters counters_table;
-
- struct mlx4_catas_err catas_err;
-
- void __iomem *clr_base;
-
- struct mlx4_uar driver_uar;
- void __iomem *kar;
- struct mlx4_port_info port[MLX4_MAX_PORTS + 1];
- struct mlx4_hca_info hca_info;
- struct mlx4_sense sense;
- struct mutex port_mutex;
- struct mlx4_msix_ctl msix_ctl;
- struct mlx4_steer *steer;
- struct list_head bf_list;
- struct mutex bf_mutex;
- struct io_mapping *bf_mapping;
- void __iomem *clock_mapping;
- int reserved_mtts;
- int fs_hash_mode;
- u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
- __be64 slave_node_guids[MLX4_MFUNC_MAX];
- struct mlx4_roce_gid_entry roce_gids[MLX4_MAX_PORTS][128];
- atomic_t opreq_count;
- struct work_struct opreq_task;
-};
-
-static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
-{
- return container_of(dev, struct mlx4_priv, dev);
-}
-
-#define MLX4_SENSE_RANGE (HZ * 3)
-
-extern struct workqueue_struct *mlx4_wq;
-
-u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap);
-void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr);
-u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt,
- int align, u32 skip_mask);
-void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
- int use_rr);
-u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap);
-int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
- u32 reserved_bot, u32 resetrved_top);
-void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap);
-
-int mlx4_reset(struct mlx4_dev *dev);
-
-int mlx4_alloc_eq_table(struct mlx4_dev *dev);
-void mlx4_free_eq_table(struct mlx4_dev *dev);
-
-int mlx4_init_pd_table(struct mlx4_dev *dev);
-int mlx4_init_xrcd_table(struct mlx4_dev *dev);
-int mlx4_init_uar_table(struct mlx4_dev *dev);
-int mlx4_init_mr_table(struct mlx4_dev *dev);
-int mlx4_init_eq_table(struct mlx4_dev *dev);
-int mlx4_init_cq_table(struct mlx4_dev *dev);
-int mlx4_init_qp_table(struct mlx4_dev *dev);
-int mlx4_init_srq_table(struct mlx4_dev *dev);
-int mlx4_init_mcg_table(struct mlx4_dev *dev);
-
-void mlx4_cleanup_pd_table(struct mlx4_dev *dev);
-void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev);
-void mlx4_cleanup_uar_table(struct mlx4_dev *dev);
-void mlx4_cleanup_mr_table(struct mlx4_dev *dev);
-void mlx4_cleanup_eq_table(struct mlx4_dev *dev);
-void mlx4_cleanup_cq_table(struct mlx4_dev *dev);
-void mlx4_cleanup_qp_table(struct mlx4_dev *dev);
-void mlx4_cleanup_srq_table(struct mlx4_dev *dev);
-void mlx4_cleanup_mcg_table(struct mlx4_dev *dev);
-int __mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn);
-void __mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn);
-int __mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn);
-void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn);
-int __mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn);
-void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn);
-int __mlx4_mpt_reserve(struct mlx4_dev *dev);
-void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index);
-int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index);
-void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index);
-u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order);
-void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 first_seg, int order);
-
-int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SYNC_TPT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
- int *base, u8 flags);
-void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt);
-int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac);
-void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac);
-int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- int start_index, int npages, u64 *page_list);
-int __mlx4_counter_alloc(struct mlx4_dev *dev, int slave, int port, u32 *idx);
-void __mlx4_counter_free(struct mlx4_dev *dev, int slave, int port, u32 idx);
-
-int __mlx4_slave_counters_free(struct mlx4_dev *dev, int slave);
-int __mlx4_clear_if_stat(struct mlx4_dev *dev,
- u8 counter_index);
-u8 mlx4_get_default_counter_index(struct mlx4_dev *dev, int slave, int port);
-
-int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
-void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);
-
-void mlx4_start_catas_poll(struct mlx4_dev *dev);
-void mlx4_stop_catas_poll(struct mlx4_dev *dev);
-void mlx4_catas_init(void);
-int mlx4_restart_one(struct pci_dev *pdev);
-int mlx4_register_device(struct mlx4_dev *dev);
-void mlx4_unregister_device(struct mlx4_dev *dev);
-void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type,
- unsigned long param);
-
-struct mlx4_dev_cap;
-struct mlx4_init_hca_param;
-
-u64 mlx4_make_profile(struct mlx4_dev *dev,
- struct mlx4_profile *request,
- struct mlx4_dev_cap *dev_cap,
- struct mlx4_init_hca_param *init_hca);
-void mlx4_master_comm_channel(struct work_struct *work);
-void mlx4_master_arm_comm_channel(struct work_struct *work);
-void mlx4_gen_slave_eqe(struct work_struct *work);
-void mlx4_master_handle_slave_flr(struct work_struct *work);
-
-int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_COMM_INT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_INIT2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_RTS2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SQERR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_2ERR_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_RTS2SQD_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SQD2SQD_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SQD2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-
-int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe);
-
-int mlx4_cmd_init(struct mlx4_dev *dev);
-void mlx4_cmd_cleanup(struct mlx4_dev *dev);
-int mlx4_multi_func_init(struct mlx4_dev *dev);
-void mlx4_multi_func_cleanup(struct mlx4_dev *dev);
-void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param);
-int mlx4_cmd_use_events(struct mlx4_dev *dev);
-void mlx4_cmd_use_polling(struct mlx4_dev *dev);
-
-int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param,
- unsigned long timeout);
-
-void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn);
-void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type);
-
-void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type);
-
-void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
-
-void mlx4_handle_catas_err(struct mlx4_dev *dev);
-
-int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
- enum mlx4_port_type *type);
-void mlx4_do_sense_ports(struct mlx4_dev *dev,
- enum mlx4_port_type *stype,
- enum mlx4_port_type *defaults);
-void mlx4_start_sense(struct mlx4_dev *dev);
-void mlx4_stop_sense(struct mlx4_dev *dev);
-void mlx4_sense_init(struct mlx4_dev *dev);
-int mlx4_check_port_params(struct mlx4_dev *dev,
- enum mlx4_port_type *port_type);
-int mlx4_change_port_types(struct mlx4_dev *dev,
- enum mlx4_port_type *port_types);
-
-void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
-void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
-void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
-int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
-
-int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz);
-/* resource tracker functions*/
-int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
- enum mlx4_resource resource_type,
- u64 resource_id, int *slave);
-void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id);
-int mlx4_init_resource_tracker(struct mlx4_dev *dev);
-
-void mlx4_free_resource_tracker(struct mlx4_dev *dev,
- enum mlx4_res_tracker_free_type type);
-
-int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps);
-
-int mlx4_get_slave_pkey_gid_tbl_len(struct mlx4_dev *dev, u8 port,
- int *gid_tbl_len, int *pkey_tbl_len);
-
-int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-
-int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- enum mlx4_protocol prot, enum mlx4_steer_type steer);
-int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- int block_mcast_loopback, enum mlx4_protocol prot,
- enum mlx4_steer_type steer);
-int mlx4_trans_to_dmfs_attach(struct mlx4_dev *dev, struct mlx4_qp *qp,
- u8 gid[16], u8 port,
- int block_mcast_loopback,
- enum mlx4_protocol prot, u64 *reg_id);
-int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
-int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_common_set_vlan_fltr(struct mlx4_dev *dev, int function,
- int port, void *buf);
-int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_PKEY_TABLE_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-int mlx4_MOD_STAT_CFG_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd);
-
-int mlx4_get_mgm_entry_size(struct mlx4_dev *dev);
-int mlx4_get_qp_per_mgm(struct mlx4_dev *dev);
-
-static inline void set_param_l(u64 *arg, u32 val)
-{
- *arg = (*arg & 0xffffffff00000000ULL) | (u64) val;
-}
-
-static inline void set_param_h(u64 *arg, u32 val)
-{
- *arg = (*arg & 0xffffffff) | ((u64) val << 32);
-}
-
-static inline u32 get_param_l(u64 *arg)
-{
- return (u32) (*arg & 0xffffffff);
-}
-
-static inline u32 get_param_h(u64 *arg)
-{
- return (u32)(*arg >> 32);
-}
-
-static inline spinlock_t *mlx4_tlock(struct mlx4_dev *dev)
-{
- return &mlx4_priv(dev)->mfunc.master.res_tracker.lock;
-}
-
-#define NOT_MASKED_PD_BITS 17
-
-void sys_tune_init(void);
-void sys_tune_fini(void);
-
-void mlx4_init_quotas(struct mlx4_dev *dev);
-
-int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave);
-int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave);
-void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work);
-
-#endif /* MLX4_H */
diff --git a/sys/ofed/drivers/net/mlx4/mlx4_en.h b/sys/ofed/drivers/net/mlx4/mlx4_en.h
deleted file mode 100644
index 17afa9e44022..000000000000
--- a/sys/ofed/drivers/net/mlx4/mlx4_en.h
+++ /dev/null
@@ -1,912 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#ifndef _MLX4_EN_H_
-#define _MLX4_EN_H_
-
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/kobject.h>
-#include <linux/netdevice.h>
-#include <linux/if_vlan.h>
-#include <linux/if_ether.h>
-#ifdef CONFIG_MLX4_EN_DCB
-#include <linux/dcbnl.h>
-#endif
-
-#include <linux/mlx4/device.h>
-#include <linux/mlx4/qp.h>
-#include <linux/mlx4/cq.h>
-#include <linux/mlx4/srq.h>
-#include <linux/mlx4/doorbell.h>
-#include <linux/mlx4/cmd.h>
-
-#include <netinet/tcp_lro.h>
-
-#include "en_port.h"
-#include "mlx4_stats.h"
-
-#define DRV_NAME "mlx4_en"
-
-#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
-
-/*
- * Device constants
- */
-
-
-#define MLX4_EN_PAGE_SHIFT 12
-#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
-#define MLX4_NET_IP_ALIGN 2 /* bytes */
-#define DEF_RX_RINGS 16
-#define MAX_RX_RINGS 128
-#define MIN_RX_RINGS 4
-#define TXBB_SIZE 64
-#define HEADROOM (2048 / TXBB_SIZE + 1)
-#define STAMP_STRIDE 64
-#define STAMP_DWORDS (STAMP_STRIDE / 4)
-#define STAMP_SHIFT 31
-#define STAMP_VAL 0x7fffffff
-#define STATS_DELAY (HZ / 4)
-#define SERVICE_TASK_DELAY (HZ / 4)
-#define MAX_NUM_OF_FS_RULES 256
-
-#define MLX4_EN_FILTER_HASH_SHIFT 4
-#define MLX4_EN_FILTER_EXPIRY_QUOTA 60
-
-#ifdef CONFIG_NET_RX_BUSY_POLL
-#define LL_EXTENDED_STATS
-#endif
-
-/* vlan valid range */
-#define VLAN_MIN_VALUE 1
-#define VLAN_MAX_VALUE 4094
-
-/*
- * OS related constants and tunables
- */
-
-#define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ)
-
-#define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(PAGE_SIZE)
-#define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE)
-
-enum mlx4_en_alloc_type {
- MLX4_EN_ALLOC_NEW = 0,
- MLX4_EN_ALLOC_REPLACEMENT = 1,
-};
-
-/* Maximum ring sizes */
-#define MLX4_EN_DEF_TX_QUEUE_SIZE 4096
-
-/* Minimum packet number till arming the CQ */
-#define MLX4_EN_MIN_RX_ARM 2048
-#define MLX4_EN_MIN_TX_ARM 2048
-
-/* Maximum ring sizes */
-#define MLX4_EN_MAX_TX_SIZE 8192
-#define MLX4_EN_MAX_RX_SIZE 8192
-
-/* Minimum ring sizes */
-#define MLX4_EN_MIN_RX_SIZE (4096 / TXBB_SIZE)
-#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
-
-#define MLX4_EN_SMALL_PKT_SIZE 64
-
-#define MLX4_EN_MAX_TX_RING_P_UP 32
-#define MLX4_EN_NUM_UP 1
-
-#define MAX_TX_RINGS (MLX4_EN_MAX_TX_RING_P_UP * \
- MLX4_EN_NUM_UP)
-
-#define MLX4_EN_DEF_TX_RING_SIZE 1024
-#define MLX4_EN_DEF_RX_RING_SIZE 1024
-
-/* Target number of bytes to coalesce with interrupt moderation */
-#define MLX4_EN_RX_COAL_TARGET 0x20000
-#define MLX4_EN_RX_COAL_TIME 0x10
-
-#define MLX4_EN_TX_COAL_PKTS 64
-#define MLX4_EN_TX_COAL_TIME 64
-
-#define MLX4_EN_RX_RATE_LOW 400000
-#define MLX4_EN_RX_COAL_TIME_LOW 0
-#define MLX4_EN_RX_RATE_HIGH 450000
-#define MLX4_EN_RX_COAL_TIME_HIGH 128
-#define MLX4_EN_RX_SIZE_THRESH 1024
-#define MLX4_EN_RX_RATE_THRESH (1000000 / MLX4_EN_RX_COAL_TIME_HIGH)
-#define MLX4_EN_SAMPLE_INTERVAL 0
-#define MLX4_EN_AVG_PKT_SMALL 256
-
-#define MLX4_EN_AUTO_CONF 0xffff
-
-#define MLX4_EN_DEF_RX_PAUSE 1
-#define MLX4_EN_DEF_TX_PAUSE 1
-
-/* Interval between successive polls in the Tx routine when polling is used
- instead of interrupts (in per-core Tx rings) - should be power of 2 */
-#define MLX4_EN_TX_POLL_MODER 16
-#define MLX4_EN_TX_POLL_TIMEOUT (HZ / 4)
-
-#define MLX4_EN_64_ALIGN (64 - NET_SKB_PAD)
-#define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN)
-#define HEADER_COPY_SIZE (128)
-#define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETHER_HDR_LEN)
-
-#define MLX4_EN_MIN_MTU 46
-#define ETH_BCAST 0xffffffffffffULL
-
-#define MLX4_EN_LOOPBACK_RETRIES 5
-#define MLX4_EN_LOOPBACK_TIMEOUT 100
-
-#ifdef MLX4_EN_PERF_STAT
-/* Number of samples to 'average' */
-#define AVG_SIZE 128
-#define AVG_FACTOR 1024
-
-#define INC_PERF_COUNTER(cnt) (++(cnt))
-#define ADD_PERF_COUNTER(cnt, add) ((cnt) += (add))
-#define AVG_PERF_COUNTER(cnt, sample) \
- ((cnt) = ((cnt) * (AVG_SIZE - 1) + (sample) * AVG_FACTOR) / AVG_SIZE)
-#define GET_PERF_COUNTER(cnt) (cnt)
-#define GET_AVG_PERF_COUNTER(cnt) ((cnt) / AVG_FACTOR)
-
-#else
-
-#define INC_PERF_COUNTER(cnt) do {} while (0)
-#define ADD_PERF_COUNTER(cnt, add) do {} while (0)
-#define AVG_PERF_COUNTER(cnt, sample) do {} while (0)
-#define GET_PERF_COUNTER(cnt) (0)
-#define GET_AVG_PERF_COUNTER(cnt) (0)
-#endif /* MLX4_EN_PERF_STAT */
-
-/*
- * Configurables
- */
-
-enum cq_type {
- RX = 0,
- TX = 1,
-};
-
-
-/*
- * Useful macros
- */
-#define ROUNDUP_LOG2(x) ilog2(roundup_pow_of_two(x))
-#define XNOR(x, y) (!(x) == !(y))
-#define ILLEGAL_MAC(addr) (addr == 0xffffffffffffULL || addr == 0x0)
-
-struct mlx4_en_tx_info {
- bus_dmamap_t dma_map;
- struct mbuf *mb;
- u32 nr_txbb;
- u32 nr_bytes;
-};
-
-
-#define MLX4_EN_BIT_DESC_OWN 0x80000000
-#define CTRL_SIZE sizeof(struct mlx4_wqe_ctrl_seg)
-#define MLX4_EN_MEMTYPE_PAD 0x100
-#define DS_SIZE sizeof(struct mlx4_wqe_data_seg)
-
-
-struct mlx4_en_tx_desc {
- struct mlx4_wqe_ctrl_seg ctrl;
- union {
- struct mlx4_wqe_data_seg data; /* at least one data segment */
- struct mlx4_wqe_lso_seg lso;
- struct mlx4_wqe_inline_seg inl;
- };
-};
-
-#define MLX4_EN_USE_SRQ 0x01000000
-
-#define MLX4_EN_RX_BUDGET 64
-
-#define MLX4_EN_TX_MAX_DESC_SIZE 512 /* bytes */
-#define MLX4_EN_TX_MAX_MBUF_SIZE 65536 /* bytes */
-#define MLX4_EN_TX_MAX_PAYLOAD_SIZE 65536 /* bytes */
-#define MLX4_EN_TX_MAX_MBUF_FRAGS \
- ((MLX4_EN_TX_MAX_DESC_SIZE - 128) / DS_SIZE_ALIGNMENT) /* units */
-#define MLX4_EN_TX_WQE_MAX_WQEBBS \
- (MLX4_EN_TX_MAX_DESC_SIZE / TXBB_SIZE) /* units */
-
-#define MLX4_EN_CX3_LOW_ID 0x1000
-#define MLX4_EN_CX3_HIGH_ID 0x1005
-
-struct mlx4_en_tx_ring {
- spinlock_t tx_lock;
- bus_dma_tag_t dma_tag;
- struct mlx4_hwq_resources wqres;
- u32 size ; /* number of TXBBs */
- u32 size_mask;
- u16 stride;
- u16 cqn; /* index of port CQ associated with this ring */
- u32 prod;
- u32 cons;
- u32 buf_size;
- u32 doorbell_qpn;
- u8 *buf;
- u16 poll_cnt;
- int blocked;
- struct mlx4_en_tx_info *tx_info;
- u8 queue_index;
- cpuset_t affinity_mask;
- struct buf_ring *br;
- u32 last_nr_txbb;
- struct mlx4_qp qp;
- struct mlx4_qp_context context;
- int qpn;
- enum mlx4_qp_state qp_state;
- struct mlx4_srq dummy;
- unsigned long bytes;
- unsigned long packets;
- unsigned long tx_csum;
- unsigned long queue_stopped;
- unsigned long oversized_packets;
- unsigned long wake_queue;
- struct mlx4_bf bf;
- bool bf_enabled;
- int hwtstamp_tx_type;
- spinlock_t comp_lock;
- int inline_thold;
- u64 watchdog_time;
-};
-
-struct mlx4_en_rx_desc {
- /* actual number of entries depends on rx ring stride */
- struct mlx4_wqe_data_seg data[0];
-};
-
-struct mlx4_en_rx_mbuf {
- bus_dmamap_t dma_map;
- struct mbuf *mbuf;
-};
-
-struct mlx4_en_rx_spare {
- bus_dmamap_t dma_map;
- struct mbuf *mbuf;
- u64 paddr_be;
-};
-
-struct mlx4_en_rx_ring {
- struct mlx4_hwq_resources wqres;
- bus_dma_tag_t dma_tag;
- struct mlx4_en_rx_spare spare;
- u32 size ; /* number of Rx descs*/
- u32 actual_size;
- u32 size_mask;
- u16 stride;
- u16 log_stride;
- u16 cqn; /* index of port CQ associated with this ring */
- u32 prod;
- u32 cons;
- u32 buf_size;
- u8 fcs_del;
- u32 rx_mb_size;
- int qpn;
- u8 *buf;
- struct mlx4_en_rx_mbuf *mbuf;
- unsigned long errors;
- unsigned long bytes;
- unsigned long packets;
-#ifdef LL_EXTENDED_STATS
- unsigned long yields;
- unsigned long misses;
- unsigned long cleaned;
-#endif
- unsigned long csum_ok;
- unsigned long csum_none;
- int hwtstamp_rx_filter;
- int numa_node;
- struct lro_ctrl lro;
-};
-
-static inline int mlx4_en_can_lro(__be16 status)
-{
- const __be16 status_all = cpu_to_be16(
- MLX4_CQE_STATUS_IPV4 |
- MLX4_CQE_STATUS_IPV4F |
- MLX4_CQE_STATUS_IPV6 |
- MLX4_CQE_STATUS_IPV4OPT |
- MLX4_CQE_STATUS_TCP |
- MLX4_CQE_STATUS_UDP |
- MLX4_CQE_STATUS_IPOK);
- const __be16 status_ipv4_ipok_tcp = cpu_to_be16(
- MLX4_CQE_STATUS_IPV4 |
- MLX4_CQE_STATUS_IPOK |
- MLX4_CQE_STATUS_TCP);
- const __be16 status_ipv6_ipok_tcp = cpu_to_be16(
- MLX4_CQE_STATUS_IPV6 |
- MLX4_CQE_STATUS_IPOK |
- MLX4_CQE_STATUS_TCP);
-
- status &= status_all;
- return (status == status_ipv4_ipok_tcp ||
- status == status_ipv6_ipok_tcp);
-}
-
-struct mlx4_en_cq {
- struct mlx4_cq mcq;
- struct mlx4_hwq_resources wqres;
- int ring;
- spinlock_t lock;
- struct net_device *dev;
- /* Per-core Tx cq processing support */
- struct timer_list timer;
- int size;
- int buf_size;
- unsigned vector;
- enum cq_type is_tx;
- u16 moder_time;
- u16 moder_cnt;
- struct mlx4_cqe *buf;
- struct task cq_task;
- struct taskqueue *tq;
-#define MLX4_EN_OPCODE_ERROR 0x1e
- u32 tot_rx;
- u32 tot_tx;
- u32 curr_poll_rx_cpu_id;
-
-#ifdef CONFIG_NET_RX_BUSY_POLL
- unsigned int state;
-#define MLX4_EN_CQ_STATEIDLE 0
-#define MLX4_EN_CQ_STATENAPI 1 /* NAPI owns this CQ */
-#define MLX4_EN_CQ_STATEPOLL 2 /* poll owns this CQ */
-#define MLX4_CQ_LOCKED (MLX4_EN_CQ_STATENAPI | MLX4_EN_CQ_STATEPOLL)
-#define MLX4_EN_CQ_STATENAPI_YIELD 4 /* NAPI yielded this CQ */
-#define MLX4_EN_CQ_STATEPOLL_YIELD 8 /* poll yielded this CQ */
-#define CQ_YIELD (MLX4_EN_CQ_STATENAPI_YIELD | MLX4_EN_CQ_STATEPOLL_YIELD)
-#define CQ_USER_PEND (MLX4_EN_CQ_STATEPOLL | MLX4_EN_CQ_STATEPOLL_YIELD)
- spinlock_t poll_lock; /* protects from LLS/napi conflicts */
-#endif /* CONFIG_NET_RX_BUSY_POLL */
-};
-
-struct mlx4_en_port_profile {
- u32 flags;
- u32 tx_ring_num;
- u32 rx_ring_num;
- u32 tx_ring_size;
- u32 rx_ring_size;
- u8 rx_pause;
- u8 rx_ppp;
- u8 tx_pause;
- u8 tx_ppp;
- int rss_rings;
-};
-
-struct mlx4_en_profile {
- int rss_xor;
- int udp_rss;
- u8 rss_mask;
- u32 active_ports;
- u32 small_pkt_int;
- u8 no_reset;
- u8 num_tx_rings_p_up;
- struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1];
-};
-
-struct mlx4_en_dev {
- struct mlx4_dev *dev;
- struct pci_dev *pdev;
- struct mutex state_lock;
- struct net_device *pndev[MLX4_MAX_PORTS + 1];
- u32 port_cnt;
- bool device_up;
- struct mlx4_en_profile profile;
- u32 LSO_support;
- struct workqueue_struct *workqueue;
- struct device *dma_device;
- void __iomem *uar_map;
- struct mlx4_uar priv_uar;
- struct mlx4_mr mr;
- u32 priv_pdn;
- spinlock_t uar_lock;
- u8 mac_removed[MLX4_MAX_PORTS + 1];
- unsigned long last_overflow_check;
- unsigned long overflow_period;
-};
-
-
-struct mlx4_en_rss_map {
- int base_qpn;
- struct mlx4_qp qps[MAX_RX_RINGS];
- enum mlx4_qp_state state[MAX_RX_RINGS];
- struct mlx4_qp indir_qp;
- enum mlx4_qp_state indir_state;
-};
-
-struct mlx4_en_port_state {
- int link_state;
- int link_speed;
- int transciver;
- int autoneg;
-};
-
-enum mlx4_en_mclist_act {
- MCLIST_NONE,
- MCLIST_REM,
- MCLIST_ADD,
-};
-
-struct mlx4_en_mc_list {
- struct list_head list;
- enum mlx4_en_mclist_act action;
- u8 addr[ETH_ALEN];
- u64 reg_id;
-};
-
-#ifdef CONFIG_MLX4_EN_DCB
-/* Minimal TC BW - setting to 0 will block traffic */
-#define MLX4_EN_BW_MIN 1
-#define MLX4_EN_BW_MAX 100 /* Utilize 100% of the line */
-
-#define MLX4_EN_TC_ETS 7
-
-#endif
-
-
-enum {
- MLX4_EN_FLAG_PROMISC = (1 << 0),
- MLX4_EN_FLAG_MC_PROMISC = (1 << 1),
- /* whether we need to enable hardware loopback by putting dmac
- * in Tx WQE
- */
- MLX4_EN_FLAG_ENABLE_HW_LOOPBACK = (1 << 2),
- /* whether we need to drop packets that hardware loopback-ed */
- MLX4_EN_FLAG_RX_FILTER_NEEDED = (1 << 3),
- MLX4_EN_FLAG_FORCE_PROMISC = (1 << 4),
-#ifdef CONFIG_MLX4_EN_DCB
- MLX4_EN_FLAG_DCB_ENABLED = (1 << 5)
-#endif
-};
-
-#define MLX4_EN_MAC_HASH_SIZE (1 << BITS_PER_BYTE)
-#define MLX4_EN_MAC_HASH_IDX 5
-
-struct en_port {
- struct kobject kobj;
- struct mlx4_dev *dev;
- u8 port_num;
- u8 vport_num;
-};
-
-struct mlx4_en_priv {
- struct mlx4_en_dev *mdev;
- struct mlx4_en_port_profile *prof;
- struct net_device *dev;
- unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- struct mlx4_en_port_state port_state;
- spinlock_t stats_lock;
- /* To allow rules removal while port is going down */
- struct list_head ethtool_list;
-
- unsigned long last_moder_packets[MAX_RX_RINGS];
- unsigned long last_moder_tx_packets;
- unsigned long last_moder_bytes[MAX_RX_RINGS];
- unsigned long last_moder_jiffies;
- int last_moder_time[MAX_RX_RINGS];
- u16 rx_usecs;
- u16 rx_frames;
- u16 tx_usecs;
- u16 tx_frames;
- u32 pkt_rate_low;
- u32 rx_usecs_low;
- u32 pkt_rate_high;
- u32 rx_usecs_high;
- u32 sample_interval;
- u32 adaptive_rx_coal;
- u32 msg_enable;
- u32 loopback_ok;
- u32 validate_loopback;
-
- struct mlx4_hwq_resources res;
- int link_state;
- int last_link_state;
- bool port_up;
- int port;
- int registered;
- int allocated;
- int stride;
- unsigned char current_mac[ETH_ALEN + 2];
- u64 mac;
- int mac_index;
- unsigned max_mtu;
- int base_qpn;
- int cqe_factor;
-
- struct mlx4_en_rss_map rss_map;
- u32 flags;
- u8 num_tx_rings_p_up;
- u32 tx_ring_num;
- u32 rx_ring_num;
- u32 rx_mb_size;
-
- struct mlx4_en_tx_ring **tx_ring;
- struct mlx4_en_rx_ring *rx_ring[MAX_RX_RINGS];
- struct mlx4_en_cq **tx_cq;
- struct mlx4_en_cq *rx_cq[MAX_RX_RINGS];
- struct mlx4_qp drop_qp;
- struct work_struct rx_mode_task;
- struct work_struct watchdog_task;
- struct work_struct linkstate_task;
- struct delayed_work stats_task;
- struct delayed_work service_task;
- struct mlx4_en_perf_stats pstats;
- struct mlx4_en_pkt_stats pkstats;
- struct mlx4_en_pkt_stats pkstats_last;
- struct mlx4_en_flow_stats flowstats[MLX4_NUM_PRIORITIES];
- struct mlx4_en_port_stats port_stats;
- struct mlx4_en_vport_stats vport_stats;
- struct mlx4_en_vf_stats vf_stats;
- DECLARE_BITMAP(stats_bitmap, NUM_ALL_STATS);
- struct list_head mc_list;
- struct list_head curr_list;
- u64 broadcast_id;
- struct mlx4_en_stat_out_mbox hw_stats;
- int vids[128];
- bool wol;
- struct device *ddev;
- struct dentry *dev_root;
- u32 counter_index;
- eventhandler_tag vlan_attach;
- eventhandler_tag vlan_detach;
- struct callout watchdog_timer;
- struct ifmedia media;
- volatile int blocked;
- struct sysctl_oid *sysctl;
- struct sysctl_ctx_list conf_ctx;
- struct sysctl_ctx_list stat_ctx;
-#define MLX4_EN_MAC_HASH_IDX 5
- struct hlist_head mac_hash[MLX4_EN_MAC_HASH_SIZE];
-
-#ifdef CONFIG_MLX4_EN_DCB
- struct ieee_ets ets;
- u16 maxrate[IEEE_8021QAZ_MAX_TCS];
- u8 dcbx_cap;
-#endif
-#ifdef CONFIG_RFS_ACCEL
- spinlock_t filters_lock;
- int last_filter_id;
- struct list_head filters;
- struct hlist_head filter_hash[1 << MLX4_EN_FILTER_HASH_SHIFT];
-#endif
- struct en_port *vf_ports[MLX4_MAX_NUM_VF];
- unsigned long last_ifq_jiffies;
- u64 if_counters_rx_errors;
- u64 if_counters_rx_no_buffer;
-};
-
-enum mlx4_en_wol {
- MLX4_EN_WOL_MAGIC = (1ULL << 61),
- MLX4_EN_WOL_ENABLED = (1ULL << 62),
-};
-
-struct mlx4_mac_entry {
- struct hlist_node hlist;
- unsigned char mac[ETH_ALEN + 2];
- u64 reg_id;
-};
-
-#ifdef CONFIG_NET_RX_BUSY_POLL
-static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq)
-{
- spin_lock_init(&cq->poll_lock);
- cq->state = MLX4_EN_CQ_STATEIDLE;
-}
-
-/* called from the device poll rutine to get ownership of a cq */
-static inline bool mlx4_en_cq_lock_napi(struct mlx4_en_cq *cq)
-{
- int rc = true;
- spin_lock(&cq->poll_lock);
- if (cq->state & MLX4_CQ_LOCKED) {
- WARN_ON(cq->state & MLX4_EN_CQ_STATENAPI);
- cq->state |= MLX4_EN_CQ_STATENAPI_YIELD;
- rc = false;
- } else
- /* we don't care if someone yielded */
- cq->state = MLX4_EN_CQ_STATENAPI;
- spin_unlock(&cq->poll_lock);
- return rc;
-}
-
-/* returns true is someone tried to get the cq while napi had it */
-static inline bool mlx4_en_cq_unlock_napi(struct mlx4_en_cq *cq)
-{
- int rc = false;
- spin_lock(&cq->poll_lock);
- WARN_ON(cq->state & (MLX4_EN_CQ_STATEPOLL |
- MLX4_EN_CQ_STATENAPI_YIELD));
-
- if (cq->state & MLX4_EN_CQ_STATEPOLL_YIELD)
- rc = true;
- cq->state = MLX4_EN_CQ_STATEIDLE;
- spin_unlock(&cq->poll_lock);
- return rc;
-}
-
-/* called from mlx4_en_low_latency_poll() */
-static inline bool mlx4_en_cq_lock_poll(struct mlx4_en_cq *cq)
-{
- int rc = true;
- spin_lock_bh(&cq->poll_lock);
- if ((cq->state & MLX4_CQ_LOCKED)) {
- struct net_device *dev = cq->dev;
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring];
-
- cq->state |= MLX4_EN_CQ_STATEPOLL_YIELD;
- rc = false;
-#ifdef LL_EXTENDED_STATS
- rx_ring->yields++;
-#endif
- } else
- /* preserve yield marks */
- cq->state |= MLX4_EN_CQ_STATEPOLL;
- spin_unlock_bh(&cq->poll_lock);
- return rc;
-}
-
-/* returns true if someone tried to get the cq while it was locked */
-static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq)
-{
- int rc = false;
- spin_lock_bh(&cq->poll_lock);
- WARN_ON(cq->state & (MLX4_EN_CQ_STATENAPI));
-
- if (cq->state & MLX4_EN_CQ_STATEPOLL_YIELD)
- rc = true;
- cq->state = MLX4_EN_CQ_STATEIDLE;
- spin_unlock_bh(&cq->poll_lock);
- return rc;
-}
-
-/* true if a socket is polling, even if it did not get the lock */
-static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq)
-{
- WARN_ON(!(cq->state & MLX4_CQ_LOCKED));
- return cq->state & CQ_USER_PEND;
-}
-#else
-static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq)
-{
-}
-
-static inline bool mlx4_en_cq_lock_napi(struct mlx4_en_cq *cq)
-{
- return true;
-}
-
-static inline bool mlx4_en_cq_unlock_napi(struct mlx4_en_cq *cq)
-{
- return false;
-}
-
-static inline bool mlx4_en_cq_lock_poll(struct mlx4_en_cq *cq)
-{
- return false;
-}
-
-static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq)
-{
- return false;
-}
-
-static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq)
-{
- return false;
-}
-#endif /* CONFIG_NET_RX_BUSY_POLL */
-
-#define MLX4_EN_WOL_DO_MODIFY (1ULL << 63)
-
-void mlx4_en_destroy_netdev(struct net_device *dev);
-int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
- struct mlx4_en_port_profile *prof);
-
-int mlx4_en_start_port(struct net_device *dev);
-void mlx4_en_stop_port(struct net_device *dev);
-
-void mlx4_en_free_resources(struct mlx4_en_priv *priv);
-int mlx4_en_alloc_resources(struct mlx4_en_priv *priv);
-
-int mlx4_en_pre_config(struct mlx4_en_priv *priv);
-int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq,
- int entries, int ring, enum cq_type mode, int node);
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq);
-int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
- int cq_idx);
-void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
-int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
-int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
-
-void mlx4_en_tx_irq(struct mlx4_cq *mcq);
-u16 mlx4_en_select_queue(struct net_device *dev, struct mbuf *mb);
-
-int mlx4_en_transmit(struct ifnet *dev, struct mbuf *m);
-int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring **pring,
- u32 size, u16 stride, int node, int queue_idx);
-void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring **pring);
-int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring,
- int cq, int user_prio);
-void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring);
-void mlx4_en_qflush(struct ifnet *dev);
-
-int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring **pring,
- u32 size, int node);
-void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring **pring,
- u32 size, u16 stride);
-void mlx4_en_tx_que(void *context, int pending);
-void mlx4_en_rx_que(void *context, int pending);
-int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv);
-void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring);
-int mlx4_en_process_rx_cq(struct net_device *dev,
- struct mlx4_en_cq *cq,
- int budget);
-void mlx4_en_poll_tx_cq(unsigned long data);
-void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
- int is_tx, int rss, int qpn, int cqn, int user_prio,
- struct mlx4_qp_context *context);
-void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
-int mlx4_en_map_buffer(struct mlx4_buf *buf);
-void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
-void mlx4_en_calc_rx_buf(struct net_device *dev);
-
-int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
-void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
-int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv);
-void mlx4_en_destroy_drop_qp(struct mlx4_en_priv *priv);
-int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
-void mlx4_en_rx_irq(struct mlx4_cq *mcq);
-
-int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv);
-
-int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
-int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
-int mlx4_en_get_vport_stats(struct mlx4_en_dev *mdev, u8 port);
-void mlx4_en_create_debug_files(struct mlx4_en_priv *priv);
-void mlx4_en_delete_debug_files(struct mlx4_en_priv *priv);
-int mlx4_en_register_debugfs(void);
-void mlx4_en_unregister_debugfs(void);
-
-#ifdef CONFIG_MLX4_EN_DCB
-extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops;
-extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops;
-#endif
-
-int mlx4_en_setup_tc(struct net_device *dev, u8 up);
-
-#ifdef CONFIG_RFS_ACCEL
-void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *rx_ring);
-#endif
-
-#define MLX4_EN_NUM_SELF_TEST 5
-void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
-void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
-
-/*
- * Functions for time stamping
- */
-#define SKBTX_HW_TSTAMP (1 << 0)
-#define SKBTX_IN_PROGRESS (1 << 2)
-
-u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe);
-
-/* Functions for caching and restoring statistics */
-int mlx4_en_get_sset_count(struct net_device *dev, int sset);
-void mlx4_en_restore_ethtool_stats(struct mlx4_en_priv *priv,
- u64 *data);
-
-/*
- * Globals
- */
-extern const struct ethtool_ops mlx4_en_ethtool_ops;
-
-/*
- * Defines for link speed - needed by selftest
- */
-#define MLX4_EN_LINK_SPEED_1G 1000
-#define MLX4_EN_LINK_SPEED_10G 10000
-#define MLX4_EN_LINK_SPEED_40G 40000
-
-enum {
- NETIF_MSG_DRV = 0x0001,
- NETIF_MSG_PROBE = 0x0002,
- NETIF_MSG_LINK = 0x0004,
- NETIF_MSG_TIMER = 0x0008,
- NETIF_MSG_IFDOWN = 0x0010,
- NETIF_MSG_IFUP = 0x0020,
- NETIF_MSG_RX_ERR = 0x0040,
- NETIF_MSG_TX_ERR = 0x0080,
- NETIF_MSG_TX_QUEUED = 0x0100,
- NETIF_MSG_INTR = 0x0200,
- NETIF_MSG_TX_DONE = 0x0400,
- NETIF_MSG_RX_STATUS = 0x0800,
- NETIF_MSG_PKTDATA = 0x1000,
- NETIF_MSG_HW = 0x2000,
- NETIF_MSG_WOL = 0x4000,
-};
-
-
-/*
- * printk / logging functions
- */
-
-#define en_print(level, priv, format, arg...) \
- { \
- if ((priv)->registered) \
- printk(level "%s: %s: " format, DRV_NAME, \
- (priv->dev)->if_xname, ## arg); \
- else \
- printk(level "%s: %s: Port %d: " format, \
- DRV_NAME, dev_name(&priv->mdev->pdev->dev), \
- (priv)->port, ## arg); \
- }
-
-
-#define en_dbg(mlevel, priv, format, arg...) \
-do { \
- if (NETIF_MSG_##mlevel & priv->msg_enable) \
- en_print(KERN_DEBUG, priv, format, ##arg); \
-} while (0)
-#define en_warn(priv, format, arg...) \
- en_print(KERN_WARNING, priv, format, ##arg)
-#define en_err(priv, format, arg...) \
- en_print(KERN_ERR, priv, format, ##arg)
-#define en_info(priv, format, arg...) \
- en_print(KERN_INFO, priv, format, ## arg)
-
-#define mlx4_err(mdev, format, arg...) \
- pr_err("%s %s: " format, DRV_NAME, \
- dev_name(&mdev->pdev->dev), ##arg)
-#define mlx4_info(mdev, format, arg...) \
- pr_info("%s %s: " format, DRV_NAME, \
- dev_name(&mdev->pdev->dev), ##arg)
-#define mlx4_warn(mdev, format, arg...) \
- pr_warning("%s %s: " format, DRV_NAME, \
- dev_name(&mdev->pdev->dev), ##arg)
-
-#endif
diff --git a/sys/ofed/drivers/net/mlx4/mlx4_stats.h b/sys/ofed/drivers/net/mlx4/mlx4_stats.h
deleted file mode 100644
index ef0b1c0a679b..000000000000
--- a/sys/ofed/drivers/net/mlx4/mlx4_stats.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2014 Mellanox Technologies Ltd. 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.
- */
-
-#ifndef _MLX4_STATS_
-#define _MLX4_STATS_
-
-
-#ifdef MLX4_EN_PERF_STAT
-#define NUM_PERF_STATS NUM_PERF_COUNTERS
-#else
-#define NUM_PERF_STATS 0
-#endif
-
-#define NUM_PRIORITIES 9
-#define NUM_PRIORITY_STATS 2
-
-struct mlx4_en_pkt_stats {
- unsigned long rx_packets;
- unsigned long rx_bytes;
- unsigned long rx_multicast_packets;
- unsigned long rx_broadcast_packets;
- unsigned long rx_errors;
- unsigned long rx_dropped;
- unsigned long rx_length_errors;
- unsigned long rx_over_errors;
- unsigned long rx_crc_errors;
- unsigned long rx_jabbers;
- unsigned long rx_in_range_length_error;
- unsigned long rx_out_range_length_error;
- unsigned long rx_lt_64_bytes_packets;
- unsigned long rx_127_bytes_packets;
- unsigned long rx_255_bytes_packets;
- unsigned long rx_511_bytes_packets;
- unsigned long rx_1023_bytes_packets;
- unsigned long rx_1518_bytes_packets;
- unsigned long rx_1522_bytes_packets;
- unsigned long rx_1548_bytes_packets;
- unsigned long rx_gt_1548_bytes_packets;
- unsigned long tx_packets;
- unsigned long tx_bytes;
- unsigned long tx_multicast_packets;
- unsigned long tx_broadcast_packets;
- unsigned long tx_errors;
- unsigned long tx_dropped;
- unsigned long tx_lt_64_bytes_packets;
- unsigned long tx_127_bytes_packets;
- unsigned long tx_255_bytes_packets;
- unsigned long tx_511_bytes_packets;
- unsigned long tx_1023_bytes_packets;
- unsigned long tx_1518_bytes_packets;
- unsigned long tx_1522_bytes_packets;
- unsigned long tx_1548_bytes_packets;
- unsigned long tx_gt_1548_bytes_packets;
- unsigned long rx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
- unsigned long tx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
-#define NUM_PKT_STATS 72
-};
-
-struct mlx4_en_vf_stats {
- unsigned long rx_packets;
- unsigned long rx_bytes;
- unsigned long rx_multicast_packets;
- unsigned long rx_broadcast_packets;
- unsigned long rx_errors;
- unsigned long rx_dropped;
- unsigned long tx_packets;
- unsigned long tx_bytes;
- unsigned long tx_multicast_packets;
- unsigned long tx_broadcast_packets;
- unsigned long tx_errors;
-#define NUM_VF_STATS 11
-};
-
-struct mlx4_en_vport_stats {
- unsigned long rx_unicast_packets;
- unsigned long rx_unicast_bytes;
- unsigned long rx_multicast_packets;
- unsigned long rx_multicast_bytes;
- unsigned long rx_broadcast_packets;
- unsigned long rx_broadcast_bytes;
- unsigned long rx_dropped;
- unsigned long rx_errors;
- unsigned long tx_unicast_packets;
- unsigned long tx_unicast_bytes;
- unsigned long tx_multicast_packets;
- unsigned long tx_multicast_bytes;
- unsigned long tx_broadcast_packets;
- unsigned long tx_broadcast_bytes;
- unsigned long tx_errors;
-#define NUM_VPORT_STATS 15
-};
-
-struct mlx4_en_port_stats {
- unsigned long tso_packets;
- unsigned long queue_stopped;
- unsigned long wake_queue;
- unsigned long tx_timeout;
- unsigned long oversized_packets;
- unsigned long rx_alloc_failed;
- unsigned long rx_chksum_good;
- unsigned long rx_chksum_none;
- unsigned long tx_chksum_offload;
-#define NUM_PORT_STATS 8
-};
-
-struct mlx4_en_perf_stats {
- u32 tx_poll;
- u64 tx_pktsz_avg;
- u32 inflight_avg;
- u16 tx_coal_avg;
- u16 rx_coal_avg;
- u32 napi_quota;
-#define NUM_PERF_COUNTERS 6
-};
-
-struct mlx4_en_flow_stats {
- u64 rx_pause;
- u64 rx_pause_duration;
- u64 rx_pause_transition;
- u64 tx_pause;
- u64 tx_pause_duration;
- u64 tx_pause_transition;
-};
-#define MLX4_NUM_PRIORITIES 8
-#define NUM_FLOW_PRIORITY_STATS 6
-#define NUM_FLOW_STATS (NUM_FLOW_PRIORITY_STATS*MLX4_NUM_PRIORITIES)
-
-
-struct mlx4_en_stat_out_flow_control_mbox {
- /* Total number of PAUSE frames received from the far-end port */
- __be64 rx_pause;
- /* Total number of microseconds that far-end port requested to pause
- * transmission of packets
- */
- __be64 rx_pause_duration;
- /* Number of received transmission from XOFF state to XON state */
- __be64 rx_pause_transition;
- /* Total number of PAUSE frames sent from the far-end port */
- __be64 tx_pause;
- /* Total time in microseconds that transmission of packets has been
- * paused
- */
- __be64 tx_pause_duration;
- /* Number of transmitter transitions from XOFF state to XON state */
- __be64 tx_pause_transition;
- /* Reserverd */
- __be64 reserved[2];
-};
-
-int mlx4_get_vport_ethtool_stats(struct mlx4_dev *dev, int port,
- struct mlx4_en_vport_stats *vport_stats,
- int reset);
-
-#define NUM_ALL_STATS (NUM_PKT_STATS + NUM_FLOW_STATS + NUM_VPORT_STATS + \
- NUM_VF_STATS + NUM_PORT_STATS + NUM_PERF_STATS)
-#endif
diff --git a/sys/ofed/drivers/net/mlx4/mr.c b/sys/ofed/drivers/net/mlx4/mr.c
deleted file mode 100644
index 876d16dba1a3..000000000000
--- a/sys/ofed/drivers/net/mlx4/mr.c
+++ /dev/null
@@ -1,996 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-
-#include <linux/mlx4/cmd.h>
-
-#include <linux/math64.h>
-
-#include "mlx4.h"
-#include "icm.h"
-
-static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
-{
- int o;
- int m;
- u32 seg;
-
- spin_lock(&buddy->lock);
-
- for (o = order; o <= buddy->max_order; ++o)
- if (buddy->num_free[o]) {
- m = 1 << (buddy->max_order - o);
- seg = find_first_bit(buddy->bits[o], m);
- if (seg < m)
- goto found;
- }
-
- spin_unlock(&buddy->lock);
- return -1;
-
- found:
- clear_bit(seg, buddy->bits[o]);
- --buddy->num_free[o];
-
- while (o > order) {
- --o;
- seg <<= 1;
- set_bit(seg ^ 1, buddy->bits[o]);
- ++buddy->num_free[o];
- }
-
- spin_unlock(&buddy->lock);
-
- seg <<= order;
-
- return seg;
-}
-
-static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order)
-{
- seg >>= order;
-
- spin_lock(&buddy->lock);
-
- while (test_bit(seg ^ 1, buddy->bits[order])) {
- clear_bit(seg ^ 1, buddy->bits[order]);
- --buddy->num_free[order];
- seg >>= 1;
- ++order;
- }
-
- set_bit(seg, buddy->bits[order]);
- ++buddy->num_free[order];
-
- spin_unlock(&buddy->lock);
-}
-
-static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
-{
- int i, s;
-
- buddy->max_order = max_order;
- spin_lock_init(&buddy->lock);
-
- buddy->bits = kcalloc(buddy->max_order + 1, sizeof (long *),
- GFP_KERNEL);
- buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
- GFP_KERNEL);
- if (!buddy->bits || !buddy->num_free)
- goto err_out;
-
- for (i = 0; i <= buddy->max_order; ++i) {
- s = BITS_TO_LONGS(1 << (buddy->max_order - i));
- buddy->bits[i] = kcalloc(s, sizeof (long), GFP_KERNEL | __GFP_NOWARN);
- if (!buddy->bits[i])
- goto err_out_free;
- }
-
- set_bit(0, buddy->bits[buddy->max_order]);
- buddy->num_free[buddy->max_order] = 1;
-
- return 0;
-
-err_out_free:
- for (i = 0; i <= buddy->max_order; ++i)
- kfree(buddy->bits[i]);
-
-err_out:
- kfree(buddy->bits);
- kfree(buddy->num_free);
-
- return -ENOMEM;
-}
-
-static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
-{
- int i;
-
- for (i = 0; i <= buddy->max_order; ++i)
- kfree(buddy->bits[i]);
-
- kfree(buddy->bits);
- kfree(buddy->num_free);
-}
-
-u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
-{
- struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
- u32 seg;
- int seg_order;
- u32 offset;
-
- seg_order = max_t(int, order - log_mtts_per_seg, 0);
-
- seg = mlx4_buddy_alloc(&mr_table->mtt_buddy, seg_order);
- if (seg == -1)
- return -1;
-
- offset = seg * (1 << log_mtts_per_seg);
-
- if (mlx4_table_get_range(dev, &mr_table->mtt_table, offset,
- offset + (1 << order) - 1)) {
- mlx4_buddy_free(&mr_table->mtt_buddy, seg, seg_order);
- return -1;
- }
-
- return offset;
-}
-
-static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
-{
- u64 in_param = 0;
- u64 out_param;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, order);
- err = mlx4_cmd_imm(dev, in_param, &out_param, RES_MTT,
- RES_OP_RESERVE_AND_MAP,
- MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
- if (err)
- return -1;
- return get_param_l(&out_param);
- }
- return __mlx4_alloc_mtt_range(dev, order);
-}
-
-int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift,
- struct mlx4_mtt *mtt)
-{
- int i;
-
- if (!npages) {
- mtt->order = -1;
- mtt->page_shift = MLX4_ICM_PAGE_SHIFT;
- return 0;
- } else
- mtt->page_shift = page_shift;
-
- for (mtt->order = 0, i = 1; i < npages; i <<= 1)
- ++mtt->order;
-
- mtt->offset = mlx4_alloc_mtt_range(dev, mtt->order);
- if (mtt->offset == -1) {
- mlx4_err(dev, "Failed to allocate mtts for %d pages(order %d)\n",
- npages, mtt->order);
- return -ENOMEM;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_mtt_init);
-
-void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
-{
- u32 first_seg;
- int seg_order;
- struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
-
- seg_order = max_t(int, order - log_mtts_per_seg, 0);
- first_seg = offset / (1 << log_mtts_per_seg);
-
- mlx4_buddy_free(&mr_table->mtt_buddy, first_seg, seg_order);
- mlx4_table_put_range(dev, &mr_table->mtt_table, offset,
- offset + (1 << order) - 1);
-}
-
-static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
-{
- u64 in_param = 0;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, offset);
- set_param_h(&in_param, order);
- err = mlx4_cmd(dev, in_param, RES_MTT, RES_OP_RESERVE_AND_MAP,
- MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
- if (err)
- mlx4_warn(dev, "Failed to free mtt range at:"
- "%d order:%d\n", offset, order);
- return;
- }
- __mlx4_free_mtt_range(dev, offset, order);
-}
-
-void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt)
-{
- if (mtt->order < 0)
- return;
-
- mlx4_free_mtt_range(dev, mtt->offset, mtt->order);
-}
-EXPORT_SYMBOL_GPL(mlx4_mtt_cleanup);
-
-u64 mlx4_mtt_addr(struct mlx4_dev *dev, struct mlx4_mtt *mtt)
-{
- return (u64) mtt->offset * dev->caps.mtt_entry_sz;
-}
-EXPORT_SYMBOL_GPL(mlx4_mtt_addr);
-
-static u32 hw_index_to_key(u32 ind)
-{
- return (ind >> 24) | (ind << 8);
-}
-
-static u32 key_to_hw_index(u32 key)
-{
- return (key << 24) | (key >> 8);
-}
-
-static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int mpt_index)
-{
- return mlx4_cmd(dev, mailbox->dma, mpt_index,
- 0, MLX4_CMD_SW2HW_MPT, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int mpt_index)
-{
- return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index,
- !mailbox, MLX4_CMD_HW2SW_MPT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd,
- u64 iova, u64 size, u32 access, int npages,
- int page_shift, struct mlx4_mr *mr)
-{
- mr->iova = iova;
- mr->size = size;
- mr->pd = pd;
- mr->access = access;
- mr->enabled = MLX4_MPT_DISABLED;
- mr->key = hw_index_to_key(mridx);
-
- return mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
-}
-
-static int mlx4_WRITE_MTT(struct mlx4_dev *dev,
- struct mlx4_cmd_mailbox *mailbox,
- int num_entries)
-{
- return mlx4_cmd(dev, mailbox->dma, num_entries, 0, MLX4_CMD_WRITE_MTT,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
-}
-
-int __mlx4_mpt_reserve(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap);
-}
-
-static int mlx4_mpt_reserve(struct mlx4_dev *dev)
-{
- u64 out_param;
-
- if (mlx4_is_mfunc(dev)) {
- if (mlx4_cmd_imm(dev, 0, &out_param, RES_MPT, RES_OP_RESERVE,
- MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED))
- return -1;
- return get_param_l(&out_param);
- }
- return __mlx4_mpt_reserve(dev);
-}
-
-void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index, MLX4_NO_RR);
-}
-
-static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
-{
- u64 in_param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, index);
- if (mlx4_cmd(dev, in_param, RES_MPT, RES_OP_RESERVE,
- MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED))
- mlx4_warn(dev, "Failed to release mr index:%d\n",
- index);
- return;
- }
- __mlx4_mpt_release(dev, index);
-}
-
-int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
-{
- struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
-
- return mlx4_table_get(dev, &mr_table->dmpt_table, index);
-}
-
-static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
-{
- u64 param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&param, index);
- return mlx4_cmd_imm(dev, param, &param, RES_MPT, RES_OP_MAP_ICM,
- MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
- }
- return __mlx4_mpt_alloc_icm(dev, index);
-}
-
-void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
-{
- struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
-
- mlx4_table_put(dev, &mr_table->dmpt_table, index);
-}
-
-static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
-{
- u64 in_param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, index);
- if (mlx4_cmd(dev, in_param, RES_MPT, RES_OP_MAP_ICM,
- MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED))
- mlx4_warn(dev, "Failed to free icm of mr index:%d\n",
- index);
- return;
- }
- return __mlx4_mpt_free_icm(dev, index);
-}
-
-int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
- int npages, int page_shift, struct mlx4_mr *mr)
-{
- u32 index;
- int err;
-
- index = mlx4_mpt_reserve(dev);
- if (index == -1)
- return -ENOMEM;
-
- err = mlx4_mr_alloc_reserved(dev, index, pd, iova, size,
- access, npages, page_shift, mr);
- if (err)
- mlx4_mpt_release(dev, index);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_mr_alloc);
-
-static int mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr)
-{
- int err;
-
- if (mr->enabled == MLX4_MPT_EN_HW) {
- err = mlx4_HW2SW_MPT(dev, NULL,
- key_to_hw_index(mr->key) &
- (dev->caps.num_mpts - 1));
- if (err) {
- mlx4_warn(dev, "HW2SW_MPT failed (%d).", err);
- mlx4_warn(dev, "Most likely the MR has MWs bound to it.\n");
- return err;
- }
-
- mr->enabled = MLX4_MPT_EN_SW;
- }
- mlx4_mtt_cleanup(dev, &mr->mtt);
-
- return 0;
-}
-
-int mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
-{
- int ret;
-
- ret = mlx4_mr_free_reserved(dev, mr);
- if (ret)
- return ret;
- if (mr->enabled)
- mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
- mlx4_mpt_release(dev, key_to_hw_index(mr->key));
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_mr_free);
-
-int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mpt_entry *mpt_entry;
- int err;
-
- err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mr->key));
- if (err)
- return err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- goto err_table;
- }
- mpt_entry = mailbox->buf;
-
- memset(mpt_entry, 0, sizeof *mpt_entry);
-
- mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_MIO |
- MLX4_MPT_FLAG_REGION |
- mr->access);
-
- mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key));
- mpt_entry->pd_flags = cpu_to_be32(mr->pd | MLX4_MPT_PD_FLAG_EN_INV);
- mpt_entry->start = cpu_to_be64(mr->iova);
- mpt_entry->length = cpu_to_be64(mr->size);
- mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
-
- if (mr->mtt.order < 0) {
- mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
- mpt_entry->mtt_addr = 0;
- } else {
- mpt_entry->mtt_addr = cpu_to_be64(mlx4_mtt_addr(dev,
- &mr->mtt));
- }
-
- if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) {
- /* fast register MR in free state */
- mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
- mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG |
- MLX4_MPT_PD_FLAG_RAE);
- mpt_entry->mtt_sz = cpu_to_be32(1 << mr->mtt.order);
- } else {
- mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
- }
-
- err = mlx4_SW2HW_MPT(dev, mailbox,
- key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1));
- if (err) {
- mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
- goto err_cmd;
- }
- mr->enabled = MLX4_MPT_EN_HW;
-
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- return 0;
-
-err_cmd:
- mlx4_free_cmd_mailbox(dev, mailbox);
-
-err_table:
- mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_mr_enable);
-
-static int mlx4_write_mtt_chunk(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- int start_index, int npages, u64 *page_list)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- __be64 *mtts;
- dma_addr_t dma_handle;
- int i;
-
- mtts = mlx4_table_find(&priv->mr_table.mtt_table, mtt->offset +
- start_index, &dma_handle);
-
- if (!mtts)
- return -ENOMEM;
-
- dma_sync_single_for_cpu(&dev->pdev->dev, dma_handle,
- npages * sizeof (u64), DMA_TO_DEVICE);
-
- for (i = 0; i < npages; ++i)
- mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT);
-
- dma_sync_single_for_device(&dev->pdev->dev, dma_handle,
- npages * sizeof (u64), DMA_TO_DEVICE);
-
- return 0;
-}
-
-int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- int start_index, int npages, u64 *page_list)
-{
- int err = 0;
- int chunk;
- int mtts_per_page;
- int max_mtts_first_page;
-
- /* compute how may mtts fit in the first page */
- mtts_per_page = PAGE_SIZE / sizeof(u64);
- max_mtts_first_page = mtts_per_page - (mtt->offset + start_index)
- % mtts_per_page;
-
- chunk = min_t(int, max_mtts_first_page, npages);
-
- while (npages > 0) {
- err = mlx4_write_mtt_chunk(dev, mtt, start_index, chunk, page_list);
- if (err)
- return err;
- npages -= chunk;
- start_index += chunk;
- page_list += chunk;
-
- chunk = min_t(int, mtts_per_page, npages);
- }
- return err;
-}
-
-int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- int start_index, int npages, u64 *page_list)
-{
- struct mlx4_cmd_mailbox *mailbox = NULL;
- __be64 *inbox = NULL;
- int chunk;
- int err = 0;
- int i;
-
- if (mtt->order < 0)
- return -EINVAL;
-
- if (mlx4_is_mfunc(dev)) {
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
-
- while (npages > 0) {
- chunk = min_t(int, MLX4_MAILBOX_SIZE / sizeof(u64) - 2,
- npages);
- inbox[0] = cpu_to_be64(mtt->offset + start_index);
- inbox[1] = 0;
- for (i = 0; i < chunk; ++i)
- inbox[i + 2] = cpu_to_be64(page_list[i] |
- MLX4_MTT_FLAG_PRESENT);
- err = mlx4_WRITE_MTT(dev, mailbox, chunk);
- if (err) {
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
- }
-
- npages -= chunk;
- start_index += chunk;
- page_list += chunk;
- }
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
- }
-
- return __mlx4_write_mtt(dev, mtt, start_index, npages, page_list);
-}
-EXPORT_SYMBOL_GPL(mlx4_write_mtt);
-
-int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- struct mlx4_buf *buf)
-{
- u64 *page_list;
- int err;
- int i;
-
- page_list = kmalloc(buf->npages * sizeof *page_list, GFP_KERNEL);
- if (!page_list)
- return -ENOMEM;
-
- for (i = 0; i < buf->npages; ++i)
- if (buf->nbufs == 1)
- page_list[i] = buf->direct.map + (i << buf->page_shift);
- else
- page_list[i] = buf->page_list[i].map;
-
- err = mlx4_write_mtt(dev, mtt, 0, buf->npages, page_list);
-
- kfree(page_list);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt);
-
-int mlx4_mw_alloc(struct mlx4_dev *dev, u32 pd, enum mlx4_mw_type type,
- struct mlx4_mw *mw)
-{
- u32 index;
-
- index = mlx4_mpt_reserve(dev);
- if (index == -1)
- return -ENOMEM;
-
- mw->key = hw_index_to_key(index);
- mw->pd = pd;
- mw->type = type;
- mw->enabled = MLX4_MPT_DISABLED;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_mw_alloc);
-
-int mlx4_mw_enable(struct mlx4_dev *dev, struct mlx4_mw *mw)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_mpt_entry *mpt_entry;
- int err;
-
- err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mw->key));
- if (err)
- return err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- goto err_table;
- }
- mpt_entry = mailbox->buf;
-
- memset(mpt_entry, 0, sizeof(*mpt_entry));
-
- /* Note that the MLX4_MPT_FLAG_REGION bit in mpt_entry->flags is turned
- * off, thus creating a memory window and not a memory region.
- */
- mpt_entry->key = cpu_to_be32(key_to_hw_index(mw->key));
- mpt_entry->pd_flags = cpu_to_be32(mw->pd);
- if (mw->type == MLX4_MW_TYPE_2) {
- mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
- mpt_entry->qpn = cpu_to_be32(MLX4_MPT_QP_FLAG_BOUND_QP);
- mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_EN_INV);
- }
-
- err = mlx4_SW2HW_MPT(dev, mailbox,
- key_to_hw_index(mw->key) &
- (dev->caps.num_mpts - 1));
- if (err) {
- mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
- goto err_cmd;
- }
- mw->enabled = MLX4_MPT_EN_HW;
-
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- return 0;
-
-err_cmd:
- mlx4_free_cmd_mailbox(dev, mailbox);
-
-err_table:
- mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_mw_enable);
-
-void mlx4_mw_free(struct mlx4_dev *dev, struct mlx4_mw *mw)
-{
- int err;
-
- if (mw->enabled == MLX4_MPT_EN_HW) {
- err = mlx4_HW2SW_MPT(dev, NULL,
- key_to_hw_index(mw->key) &
- (dev->caps.num_mpts - 1));
- if (err)
- mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err);
-
- mw->enabled = MLX4_MPT_EN_SW;
- }
- if (mw->enabled)
- mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
- mlx4_mpt_release(dev, key_to_hw_index(mw->key));
-}
-EXPORT_SYMBOL_GPL(mlx4_mw_free);
-
-int mlx4_init_mr_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_mr_table *mr_table = &priv->mr_table;
- int err;
-
- /* Nothing to do for slaves - all MR handling is forwarded
- * to the master */
- if (mlx4_is_slave(dev))
- return 0;
-
- if (!is_power_of_2(dev->caps.num_mpts))
- return -EINVAL;
-
- err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts,
- ~0, dev->caps.reserved_mrws, 0);
- if (err)
- return err;
-
- err = mlx4_buddy_init(&mr_table->mtt_buddy,
- ilog2(div_u64(dev->caps.num_mtts,
- (1 << log_mtts_per_seg))));
- if (err)
- goto err_buddy;
-
- if (dev->caps.reserved_mtts) {
- priv->reserved_mtts =
- mlx4_alloc_mtt_range(dev,
- fls(dev->caps.reserved_mtts - 1));
- if (priv->reserved_mtts < 0) {
- mlx4_warn(dev, "MTT table of order %u is too small.\n",
- mr_table->mtt_buddy.max_order);
- err = -ENOMEM;
- goto err_reserve_mtts;
- }
- }
-
- return 0;
-
-err_reserve_mtts:
- mlx4_buddy_cleanup(&mr_table->mtt_buddy);
-
-err_buddy:
- mlx4_bitmap_cleanup(&mr_table->mpt_bitmap);
-
- return err;
-}
-
-void mlx4_cleanup_mr_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_mr_table *mr_table = &priv->mr_table;
-
- if (mlx4_is_slave(dev))
- return;
- if (priv->reserved_mtts >= 0)
- mlx4_free_mtt_range(dev, priv->reserved_mtts,
- fls(dev->caps.reserved_mtts - 1));
- mlx4_buddy_cleanup(&mr_table->mtt_buddy);
- mlx4_bitmap_cleanup(&mr_table->mpt_bitmap);
-}
-
-static inline int mlx4_check_fmr(struct mlx4_fmr *fmr, u64 *page_list,
- int npages, u64 iova)
-{
- int i, page_mask;
-
- if (npages > fmr->max_pages)
- return -EINVAL;
-
- page_mask = (1 << fmr->page_shift) - 1;
-
- /* We are getting page lists, so va must be page aligned. */
- if (iova & page_mask)
- return -EINVAL;
-
- /* Trust the user not to pass misaligned data in page_list */
- if (0)
- for (i = 0; i < npages; ++i) {
- if (page_list[i] & ~page_mask)
- return -EINVAL;
- }
-
- if (fmr->maps >= fmr->max_maps)
- return -EINVAL;
-
- return 0;
-}
-
-int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list,
- int npages, u64 iova, u32 *lkey, u32 *rkey)
-{
- u32 key;
- int i, err;
-
- err = mlx4_check_fmr(fmr, page_list, npages, iova);
- if (err)
- return err;
-
- ++fmr->maps;
-
- key = key_to_hw_index(fmr->mr.key);
- key += dev->caps.num_mpts;
- *lkey = *rkey = fmr->mr.key = hw_index_to_key(key);
-
- *(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW;
-
- /* Make sure MPT status is visible before writing MTT entries */
- wmb();
-
- dma_sync_single_for_cpu(&dev->pdev->dev, fmr->dma_handle,
- npages * sizeof(u64), DMA_TO_DEVICE);
-
- for (i = 0; i < npages; ++i)
- fmr->mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT);
-
- dma_sync_single_for_device(&dev->pdev->dev, fmr->dma_handle,
- npages * sizeof(u64), DMA_TO_DEVICE);
-
- fmr->mpt->key = cpu_to_be32(key);
- fmr->mpt->lkey = cpu_to_be32(key);
- fmr->mpt->length = cpu_to_be64(npages * (1ull << fmr->page_shift));
- fmr->mpt->start = cpu_to_be64(iova);
-
- /* Make MTT entries are visible before setting MPT status */
- wmb();
-
- *(u8 *) fmr->mpt = MLX4_MPT_STATUS_HW;
-
- /* Make sure MPT status is visible before consumer can use FMR */
- wmb();
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_map_phys_fmr);
-
-int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
- int max_maps, u8 page_shift, struct mlx4_fmr *fmr)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err = -ENOMEM, ret;
-
- if (max_maps > dev->caps.max_fmr_maps)
- return -EINVAL;
-
- if (page_shift < (ffs(dev->caps.page_size_cap) - 1) || page_shift >= 32)
- return -EINVAL;
-
- /* All MTTs must fit in the same page */
- if (max_pages * sizeof *fmr->mtts > PAGE_SIZE)
- return -EINVAL;
-
- fmr->page_shift = page_shift;
- fmr->max_pages = max_pages;
- fmr->max_maps = max_maps;
- fmr->maps = 0;
-
- err = mlx4_mr_alloc(dev, pd, 0, 0, access, max_pages,
- page_shift, &fmr->mr);
- if (err)
- return err;
-
- fmr->mtts = mlx4_table_find(&priv->mr_table.mtt_table,
- fmr->mr.mtt.offset,
- &fmr->dma_handle);
-
- if (!fmr->mtts) {
- err = -ENOMEM;
- goto err_free;
- }
-
- return 0;
-
-err_free:
- ret = mlx4_mr_free(dev, &fmr->mr);
- if (ret)
- mlx4_err(dev, "Error deregistering MR. The system may have become unstable.");
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_fmr_alloc);
-
-int mlx4_fmr_enable(struct mlx4_dev *dev, struct mlx4_fmr *fmr)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int err;
-
- err = mlx4_mr_enable(dev, &fmr->mr);
- if (err)
- return err;
-
- fmr->mpt = mlx4_table_find(&priv->mr_table.dmpt_table,
- key_to_hw_index(fmr->mr.key), NULL);
- if (!fmr->mpt)
- return -ENOMEM;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_fmr_enable);
-
-void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
- u32 *lkey, u32 *rkey)
-{
- u32 key;
-
- if (!fmr->maps)
- return;
-
- key = key_to_hw_index(fmr->mr.key) & (dev->caps.num_mpts - 1);
-
- *(u8 *)fmr->mpt = MLX4_MPT_STATUS_SW;
-
- /* Make sure MPT status is visible before changing MPT fields */
- wmb();
-
- fmr->mr.key = hw_index_to_key(key);
-
- fmr->mpt->key = cpu_to_be32(key);
- fmr->mpt->lkey = cpu_to_be32(key);
- fmr->mpt->length = 0;
- fmr->mpt->start = 0;
-
- /* Make sure MPT data is visible before changing MPT status */
- wmb();
-
- *(u8 *)fmr->mpt = MLX4_MPT_STATUS_HW;
-
- /* Make sure MPT satus is visible */
- wmb();
-
- fmr->maps = 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_fmr_unmap);
-
-int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr)
-{
- int ret;
-
- if (fmr->maps)
- return -EBUSY;
-
- ret = mlx4_mr_free(dev, &fmr->mr);
- if (ret)
- return ret;
- fmr->mr.enabled = MLX4_MPT_DISABLED;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_fmr_free);
-
-int mlx4_SYNC_TPT(struct mlx4_dev *dev)
-{
- return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_SYNC_TPT, 1000,
- MLX4_CMD_NATIVE);
-}
-EXPORT_SYMBOL_GPL(mlx4_SYNC_TPT);
diff --git a/sys/ofed/drivers/net/mlx4/pd.c b/sys/ofed/drivers/net/mlx4/pd.c
deleted file mode 100644
index 89a8854699ac..000000000000
--- a/sys/ofed/drivers/net/mlx4/pd.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005, 2014 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.
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/io-mapping.h>
-
-#include <linux/page.h>
-
-#include "mlx4.h"
-#include "icm.h"
-
-enum {
- MLX4_NUM_RESERVED_UARS = 8
-};
-
-int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap);
- if (*pdn == -1)
- return -ENOMEM;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
-
-void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
-{
- mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn, MLX4_USE_RR);
-}
-EXPORT_SYMBOL_GPL(mlx4_pd_free);
-
-int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- *xrcdn = mlx4_bitmap_alloc(&priv->xrcd_bitmap);
- if (*xrcdn == -1)
- return -ENOMEM;
-
- return 0;
-}
-
-int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
-{
- u64 out_param;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- err = mlx4_cmd_imm(dev, 0, &out_param,
- RES_XRCD, RES_OP_RESERVE,
- MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err)
- return err;
-
- *xrcdn = get_param_l(&out_param);
- return 0;
- }
- return __mlx4_xrcd_alloc(dev, xrcdn);
-}
-EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
-
-void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
-{
- mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn, MLX4_USE_RR);
-}
-
-void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
-{
- u64 in_param = 0;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, xrcdn);
- err = mlx4_cmd(dev, in_param, RES_XRCD,
- RES_OP_RESERVE, MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err)
- mlx4_warn(dev, "Failed to release xrcdn %d\n", xrcdn);
- } else
- __mlx4_xrcd_free(dev, xrcdn);
-}
-EXPORT_SYMBOL_GPL(mlx4_xrcd_free);
-
-int mlx4_init_pd_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- return mlx4_bitmap_init(&priv->pd_bitmap, dev->caps.num_pds,
- (1 << NOT_MASKED_PD_BITS) - 1,
- dev->caps.reserved_pds, 0);
-}
-
-void mlx4_cleanup_pd_table(struct mlx4_dev *dev)
-{
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap);
-}
-
-int mlx4_init_xrcd_table(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- return mlx4_bitmap_init(&priv->xrcd_bitmap, (1 << 16),
- (1 << 16) - 1, dev->caps.reserved_xrcds + 1, 0);
-}
-
-void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev)
-{
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->xrcd_bitmap);
-}
-
-int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar)
-{
- int offset;
-
- uar->index = mlx4_bitmap_alloc(&mlx4_priv(dev)->uar_table.bitmap);
- if (uar->index == -1)
- return -ENOMEM;
-
- if (mlx4_is_slave(dev))
- offset = uar->index % ((int) pci_resource_len(dev->pdev, 2) /
- dev->caps.uar_page_size);
- else
- offset = uar->index;
- uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + offset;
- uar->map = NULL;
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_uar_alloc);
-
-void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar)
-{
- mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index, MLX4_USE_RR);
-}
-EXPORT_SYMBOL_GPL(mlx4_uar_free);
-
-#ifndef CONFIG_PPC
-int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf, int node)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_uar *uar;
- int err = 0;
- int idx;
-
- if (!priv->bf_mapping)
- return -ENOMEM;
-
- mutex_lock(&priv->bf_mutex);
- if (!list_empty(&priv->bf_list))
- uar = list_entry(priv->bf_list.next, struct mlx4_uar, bf_list);
- else {
- if (mlx4_bitmap_avail(&priv->uar_table.bitmap) < MLX4_NUM_RESERVED_UARS) {
- err = -ENOMEM;
- goto out;
- }
- uar = kmalloc_node(sizeof *uar, GFP_KERNEL, node);
- if (!uar) {
- uar = kmalloc(sizeof *uar, GFP_KERNEL);
- if (!uar) {
- err = -ENOMEM;
- goto out;
- }
- }
- err = mlx4_uar_alloc(dev, uar);
- if (err)
- goto free_kmalloc;
-
- uar->map = ioremap(uar->pfn << PAGE_SHIFT, PAGE_SIZE);
- if (!uar->map) {
- err = -ENOMEM;
- goto free_uar;
- }
-
- uar->bf_map = io_mapping_map_wc(priv->bf_mapping, uar->index << PAGE_SHIFT);
- if (!uar->bf_map) {
- err = -ENOMEM;
- goto unamp_uar;
- }
- uar->free_bf_bmap = 0;
- list_add(&uar->bf_list, &priv->bf_list);
- }
-
- bf->uar = uar;
- idx = ffz(uar->free_bf_bmap);
- uar->free_bf_bmap |= 1 << idx;
- bf->uar = uar;
- bf->offset = 0;
- bf->buf_size = dev->caps.bf_reg_size / 2;
- bf->reg = uar->bf_map + idx * dev->caps.bf_reg_size;
- if (uar->free_bf_bmap == (1 << dev->caps.bf_regs_per_page) - 1)
- list_del_init(&uar->bf_list);
-
- goto out;
-
-unamp_uar:
- bf->uar = NULL;
- iounmap(uar->map);
-
-free_uar:
- mlx4_uar_free(dev, uar);
-
-free_kmalloc:
- kfree(uar);
-
-out:
- mutex_unlock(&priv->bf_mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_bf_alloc);
-
-void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int idx;
-
- if (!bf->uar || !bf->uar->bf_map)
- return;
-
- mutex_lock(&priv->bf_mutex);
- idx = (bf->reg - bf->uar->bf_map) / dev->caps.bf_reg_size;
- bf->uar->free_bf_bmap &= ~(1 << idx);
- if (!bf->uar->free_bf_bmap) {
- if (!list_empty(&bf->uar->bf_list))
- list_del(&bf->uar->bf_list);
-
- io_mapping_unmap(bf->uar->bf_map);
- iounmap(bf->uar->map);
- mlx4_uar_free(dev, bf->uar);
- kfree(bf->uar);
- } else if (list_empty(&bf->uar->bf_list))
- list_add(&bf->uar->bf_list, &priv->bf_list);
-
- mutex_unlock(&priv->bf_mutex);
-}
-EXPORT_SYMBOL_GPL(mlx4_bf_free);
-
-#else
-int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf, int node)
-{
- memset(bf, 0, sizeof *bf);
- return -ENOSYS;
-}
-EXPORT_SYMBOL_GPL(mlx4_bf_alloc);
-
-void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf)
-{
- return;
-}
-EXPORT_SYMBOL_GPL(mlx4_bf_free);
-#endif
-
-int mlx4_init_uar_table(struct mlx4_dev *dev)
-{
- if (dev->caps.num_uars <= 128) {
- mlx4_err(dev, "Only %d UAR pages (need more than 128)\n",
- dev->caps.num_uars);
- mlx4_err(dev, "Increase firmware log2_uar_bar_megabytes?\n");
- return -ENODEV;
- }
-
- return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap,
- dev->caps.num_uars, dev->caps.num_uars - 1,
- dev->caps.reserved_uars, 0);
-}
-
-void mlx4_cleanup_uar_table(struct mlx4_dev *dev)
-{
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->uar_table.bitmap);
-}
diff --git a/sys/ofed/drivers/net/mlx4/port.c b/sys/ofed/drivers/net/mlx4/port.c
deleted file mode 100644
index aeb38746cbd5..000000000000
--- a/sys/ofed/drivers/net/mlx4/port.c
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- */
-
-#define LINUXKPI_PARAM_PREFIX mlx4_
-
-#include <linux/errno.h>
-#include <linux/if_ether.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <linux/mlx4/cmd.h>
-#include <linux/moduleparam.h>
-#include "mlx4.h"
-#include "mlx4_stats.h"
-
-
-int mlx4_set_4k_mtu = -1;
-module_param_named(set_4k_mtu, mlx4_set_4k_mtu, int, 0444);
-MODULE_PARM_DESC(set_4k_mtu,
- "(Obsolete) attempt to set 4K MTU to all ConnectX ports");
-
-
-#define MLX4_MAC_VALID (1ull << 63)
-
-#define MLX4_VLAN_VALID (1u << 31)
-#define MLX4_VLAN_MASK 0xfff
-
-void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
-{
- int i;
-
- mutex_init(&table->mutex);
- for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
- table->entries[i] = 0;
- table->refs[i] = 0;
- }
- table->max = 1 << dev->caps.log_num_macs;
- table->total = 0;
-}
-
-void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
-{
- int i;
-
- mutex_init(&table->mutex);
- for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
- table->entries[i] = 0;
- table->refs[i] = 0;
- }
- table->max = (1 << dev->caps.log_num_vlans) - MLX4_VLAN_REGULAR;
- table->total = 0;
-}
-
-static int validate_index(struct mlx4_dev *dev,
- struct mlx4_mac_table *table, int index)
-{
- int err = 0;
-
- if (index < 0 || index >= table->max || !table->refs[index]) {
- mlx4_warn(dev, "No valid Mac entry for the given index\n");
- err = -EINVAL;
- }
- return err;
-}
-
-static int find_index(struct mlx4_dev *dev,
- struct mlx4_mac_table *table, u64 mac)
-{
- int i;
-
- for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
- if ((mac & MLX4_MAC_MASK) ==
- (MLX4_MAC_MASK & be64_to_cpu(table->entries[i])))
- return i;
- }
- /* Mac not found */
- return -EINVAL;
-}
-
-static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port,
- __be64 *entries)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 in_mod;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE);
-
- in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port;
-
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
-{
- struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
- struct mlx4_mac_table *table = &info->mac_table;
- int i, err = 0;
- int free = -1;
-
- mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n",
- (unsigned long long) mac, port);
-
- mutex_lock(&table->mutex);
- for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
- if (free < 0 && !table->refs[i]) {
- free = i;
- continue;
- }
-
- if ((mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) &&
- table->refs[i]) {
- /* MAC already registered, Must not have duplicates */
- err = i;
- ++table->refs[i];
- goto out;
- }
- }
-
- mlx4_dbg(dev, "Free MAC index is %d\n", free);
-
- if (table->total == table->max) {
- /* No free mac entries */
- err = -ENOSPC;
- goto out;
- }
-
- /* Register new MAC */
- table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID);
-
- err = mlx4_set_port_mac_table(dev, port, table->entries);
- if (unlikely(err)) {
- mlx4_err(dev, "Failed adding MAC: 0x%llx\n",
- (unsigned long long) mac);
- table->entries[free] = 0;
- goto out;
- }
- table->refs[free] = 1;
-
- err = free;
- ++table->total;
-out:
- mutex_unlock(&table->mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(__mlx4_register_mac);
-
-int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
-{
- u64 out_param = 0;
- int err = -EINVAL;
-
- if (mlx4_is_mfunc(dev)) {
- if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
- err = mlx4_cmd_imm(dev, mac, &out_param,
- ((u32) port) << 8 | (u32) RES_MAC,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- }
- if (err && err == -EINVAL && mlx4_is_slave(dev)) {
- /* retry using old REG_MAC format */
- set_param_l(&out_param, port);
- err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (!err)
- dev->flags |= MLX4_FLAG_OLD_REG_MAC;
- }
- if (err)
- return err;
-
- return get_param_l(&out_param);
- }
- return __mlx4_register_mac(dev, port, mac);
-}
-EXPORT_SYMBOL_GPL(mlx4_register_mac);
-
-int mlx4_get_base_qpn(struct mlx4_dev *dev, u8 port)
-{
- return dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] +
- (port - 1) * (1 << dev->caps.log_num_macs);
-}
-EXPORT_SYMBOL_GPL(mlx4_get_base_qpn);
-
-void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
-{
- struct mlx4_port_info *info;
- struct mlx4_mac_table *table;
- int index;
-
- if (port < 1 || port > dev->caps.num_ports) {
- mlx4_warn(dev, "invalid port number (%d), aborting...\n", port);
- return;
- }
- info = &mlx4_priv(dev)->port[port];
- table = &info->mac_table;
- mutex_lock(&table->mutex);
-
- index = find_index(dev, table, mac);
-
- if (validate_index(dev, table, index))
- goto out;
-
- if (--table->refs[index]) {
- mlx4_dbg(dev, "Have more references for index %d,"
- "no need to modify mac table\n", index);
- goto out;
- }
-
- table->entries[index] = 0;
- mlx4_set_port_mac_table(dev, port, table->entries);
- --table->total;
-out:
- mutex_unlock(&table->mutex);
-}
-EXPORT_SYMBOL_GPL(__mlx4_unregister_mac);
-
-void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
-{
- u64 out_param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
- (void) mlx4_cmd_imm(dev, mac, &out_param,
- ((u32) port) << 8 | (u32) RES_MAC,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- } else {
- /* use old unregister mac format */
- set_param_l(&out_param, port);
- (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- }
- return;
- }
- __mlx4_unregister_mac(dev, port, mac);
- return;
-}
-EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
-
-int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac)
-{
- struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
- struct mlx4_mac_table *table = &info->mac_table;
- int index = qpn - info->base_qpn;
- int err = 0;
-
- /* CX1 doesn't support multi-functions */
- mutex_lock(&table->mutex);
-
- err = validate_index(dev, table, index);
- if (err)
- goto out;
-
- table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID);
-
- err = mlx4_set_port_mac_table(dev, port, table->entries);
- if (unlikely(err)) {
- mlx4_err(dev, "Failed adding MAC: 0x%llx\n",
- (unsigned long long) new_mac);
- table->entries[index] = 0;
- }
-out:
- mutex_unlock(&table->mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(__mlx4_replace_mac);
-
-static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
- __be32 *entries)
-{
- struct mlx4_cmd_mailbox *mailbox;
- u32 in_mod;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE);
- in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- return err;
-}
-
-int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
-{
- struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
- int i;
-
- for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) {
- if (table->refs[i] &&
- (vid == (MLX4_VLAN_MASK &
- be32_to_cpu(table->entries[i])))) {
- /* VLAN already registered, increase reference count */
- *idx = i;
- return 0;
- }
- }
-
- return -ENOENT;
-}
-EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
-
-int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
- int *index)
-{
- struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
- int i, err = 0;
- int free = -1;
-
- mutex_lock(&table->mutex);
-
- if (table->total == table->max) {
- /* No free vlan entries */
- err = -ENOSPC;
- goto out;
- }
-
- for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
- if (free < 0 && (table->refs[i] == 0)) {
- free = i;
- continue;
- }
-
- if (table->refs[i] &&
- (vlan == (MLX4_VLAN_MASK &
- be32_to_cpu(table->entries[i])))) {
- /* Vlan already registered, increase references count */
- *index = i;
- ++table->refs[i];
- goto out;
- }
- }
-
- if (free < 0) {
- err = -ENOMEM;
- goto out;
- }
-
- /* Register new VLAN */
- table->refs[free] = 1;
- table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
-
- err = mlx4_set_port_vlan_table(dev, port, table->entries);
- if (unlikely(err)) {
- mlx4_warn(dev, "Failed adding vlan: %u\n", vlan);
- table->refs[free] = 0;
- table->entries[free] = 0;
- goto out;
- }
-
- *index = free;
- ++table->total;
-out:
- mutex_unlock(&table->mutex);
- return err;
-}
-
-int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
-{
- u64 out_param = 0;
- int err;
-
- if (vlan > 4095)
- return -EINVAL;
-
- if (mlx4_is_mfunc(dev)) {
- err = mlx4_cmd_imm(dev, vlan, &out_param,
- ((u32) port) << 8 | (u32) RES_VLAN,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (!err)
- *index = get_param_l(&out_param);
-
- return err;
- }
- return __mlx4_register_vlan(dev, port, vlan, index);
-}
-EXPORT_SYMBOL_GPL(mlx4_register_vlan);
-
-void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
-{
- struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
- int index;
-
- mutex_lock(&table->mutex);
- if (mlx4_find_cached_vlan(dev, port, vlan, &index)) {
- mlx4_warn(dev, "vlan 0x%x is not in the vlan table\n", vlan);
- goto out;
- }
-
- if (index < MLX4_VLAN_REGULAR) {
- mlx4_warn(dev, "Trying to free special vlan index %d\n", index);
- goto out;
- }
-
- if (--table->refs[index]) {
- mlx4_dbg(dev, "Have %d more references for index %d, "
- "no need to modify vlan table\n", table->refs[index],
- index);
- goto out;
- }
- table->entries[index] = 0;
- mlx4_set_port_vlan_table(dev, port, table->entries);
- --table->total;
-out:
- mutex_unlock(&table->mutex);
-}
-
-void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
-{
- u64 out_param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- (void) mlx4_cmd_imm(dev, vlan, &out_param,
- ((u32) port) << 8 | (u32) RES_VLAN,
- RES_OP_RESERVE_AND_MAP,
- MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
- return;
- }
- __mlx4_unregister_vlan(dev, port, vlan);
-}
-EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);
-
-int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
-{
- struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
- u8 *inbuf, *outbuf;
- int err;
-
- inmailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(inmailbox))
- return PTR_ERR(inmailbox);
-
- outmailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(outmailbox)) {
- mlx4_free_cmd_mailbox(dev, inmailbox);
- return PTR_ERR(outmailbox);
- }
-
- inbuf = inmailbox->buf;
- outbuf = outmailbox->buf;
- memset(inbuf, 0, 256);
- memset(outbuf, 0, 256);
- inbuf[0] = 1;
- inbuf[1] = 1;
- inbuf[2] = 1;
- inbuf[3] = 1;
- *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015);
- *(__be32 *) (&inbuf[20]) = cpu_to_be32(port);
-
- err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3,
- MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
- MLX4_CMD_NATIVE);
- if (!err)
- *caps = *(__be32 *) (outbuf + 84);
- mlx4_free_cmd_mailbox(dev, inmailbox);
- mlx4_free_cmd_mailbox(dev, outmailbox);
- return err;
-}
-static struct mlx4_roce_gid_entry zgid_entry;
-
-int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave)
-{
- if (slave == 0)
- return MLX4_ROCE_PF_GIDS;
- if (slave <= ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) % dev->num_vfs))
- return ((MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / dev->num_vfs) + 1;
- return (MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS) / dev->num_vfs;
-}
-
-int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave)
-{
- int gids;
- int vfs;
-
- gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS;
- vfs = dev->num_vfs;
-
- if (slave == 0)
- return 0;
- if (slave <= gids % vfs)
- return MLX4_ROCE_PF_GIDS + ((gids / vfs) + 1) * (slave - 1);
-
- return MLX4_ROCE_PF_GIDS + (gids % vfs) + ((gids / vfs) * (slave - 1));
-}
-
-static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
- u8 op_mod, struct mlx4_cmd_mailbox *inbox)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_port_info *port_info;
- struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master;
- struct mlx4_slave_state *slave_st = &master->slave_state[slave];
- struct mlx4_set_port_rqp_calc_context *qpn_context;
- struct mlx4_set_port_general_context *gen_context;
- struct mlx4_roce_gid_entry *gid_entry_tbl, *gid_entry_mbox, *gid_entry_mb1;
- int reset_qkey_viols;
- int port;
- int is_eth;
- int num_gids;
- int base;
- u32 in_modifier;
- u32 promisc;
- u16 mtu, prev_mtu;
- int err;
- int i, j;
- int offset;
- __be32 agg_cap_mask;
- __be32 slave_cap_mask;
- __be32 new_cap_mask;
-
- port = in_mod & 0xff;
- in_modifier = (in_mod >> 8) & 0xff;
- is_eth = op_mod;
- port_info = &priv->port[port];
-
- if (op_mod > 1)
- return -EINVAL;
-
- /* Slaves cannot perform SET_PORT operations except changing MTU */
- if (is_eth) {
- if (slave != dev->caps.function &&
- in_modifier != MLX4_SET_PORT_GENERAL &&
- in_modifier != MLX4_SET_PORT_GID_TABLE) {
- mlx4_warn(dev, "denying SET_PORT for slave:%d,"
- "port %d, config_select 0x%x\n",
- slave, port, in_modifier);
- return -EINVAL;
- }
- switch (in_modifier) {
- case MLX4_SET_PORT_RQP_CALC:
- qpn_context = inbox->buf;
- qpn_context->base_qpn =
- cpu_to_be32(port_info->base_qpn);
- qpn_context->n_mac = 0x7;
- promisc = be32_to_cpu(qpn_context->promisc) >>
- SET_PORT_PROMISC_SHIFT;
- qpn_context->promisc = cpu_to_be32(
- promisc << SET_PORT_PROMISC_SHIFT |
- port_info->base_qpn);
- promisc = be32_to_cpu(qpn_context->mcast) >>
- SET_PORT_MC_PROMISC_SHIFT;
- qpn_context->mcast = cpu_to_be32(
- promisc << SET_PORT_MC_PROMISC_SHIFT |
- port_info->base_qpn);
- break;
- case MLX4_SET_PORT_GENERAL:
- gen_context = inbox->buf;
- /* Mtu is configured as the max MTU among all the
- * the functions on the port. */
- mtu = be16_to_cpu(gen_context->mtu);
- mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port] +
- ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
- prev_mtu = slave_st->mtu[port];
- slave_st->mtu[port] = mtu;
- if (mtu > master->max_mtu[port])
- master->max_mtu[port] = mtu;
- if (mtu < prev_mtu && prev_mtu ==
- master->max_mtu[port]) {
- slave_st->mtu[port] = mtu;
- master->max_mtu[port] = mtu;
- for (i = 0; i < dev->num_slaves; i++) {
- master->max_mtu[port] =
- max(master->max_mtu[port],
- master->slave_state[i].mtu[port]);
- }
- }
-
- gen_context->mtu = cpu_to_be16(master->max_mtu[port]);
- break;
- case MLX4_SET_PORT_GID_TABLE:
- /* change to MULTIPLE entries: number of guest's gids
- * need a FOR-loop here over number of gids the guest has.
- * 1. Check no duplicates in gids passed by slave
- */
- num_gids = mlx4_get_slave_num_gids(dev, slave);
- base = mlx4_get_base_gid_ix(dev, slave);
- gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf);
- for (i = 0; i < num_gids; gid_entry_mbox++, i++) {
- if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw,
- sizeof(zgid_entry)))
- continue;
- gid_entry_mb1 = gid_entry_mbox + 1;
- for (j = i + 1; j < num_gids; gid_entry_mb1++, j++) {
- if (!memcmp(gid_entry_mb1->raw,
- zgid_entry.raw, sizeof(zgid_entry)))
- continue;
- if (!memcmp(gid_entry_mb1->raw, gid_entry_mbox->raw,
- sizeof(gid_entry_mbox->raw))) {
- /* found duplicate */
- return -EINVAL;
- }
- }
- }
-
- /* 2. Check that do not have duplicates in OTHER
- * entries in the port GID table
- */
- for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
- if (i >= base && i < base + num_gids)
- continue; /* don't compare to slave's current gids */
- gid_entry_tbl = &priv->roce_gids[port - 1][i];
- if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry)))
- continue;
- gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf);
- for (j = 0; j < num_gids; gid_entry_mbox++, j++) {
- if (!memcmp(gid_entry_mbox->raw, zgid_entry.raw,
- sizeof(zgid_entry)))
- continue;
- if (!memcmp(gid_entry_mbox->raw, gid_entry_tbl->raw,
- sizeof(gid_entry_tbl->raw))) {
- /* found duplicate */
- mlx4_warn(dev, "requested gid entry for slave:%d "
- "is a duplicate of gid at index %d\n",
- slave, i);
- return -EINVAL;
- }
- }
- }
-
- /* insert slave GIDs with memcpy, starting at slave's base index */
- gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf);
- for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++)
- memcpy(priv->roce_gids[port - 1][offset].raw, gid_entry_mbox->raw, 16);
-
- /* Now, copy roce port gids table to current mailbox for passing to FW */
- gid_entry_mbox = (struct mlx4_roce_gid_entry *) (inbox->buf);
- for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++)
- memcpy(gid_entry_mbox->raw, priv->roce_gids[port - 1][i].raw, 16);
-
- break;
- }
- return mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
- MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_NATIVE);
- }
-
- /* For IB, we only consider:
- * - The capability mask, which is set to the aggregate of all
- * slave function capabilities
- * - The QKey violatin counter - reset according to each request.
- */
-
- if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
- reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40;
- new_cap_mask = ((__be32 *) inbox->buf)[2];
- } else {
- reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1;
- new_cap_mask = ((__be32 *) inbox->buf)[1];
- }
-
- /* slave may not set the IS_SM capability for the port */
- if (slave != mlx4_master_func_num(dev) &&
- (be32_to_cpu(new_cap_mask) & MLX4_PORT_CAP_IS_SM))
- return -EINVAL;
-
- /* No DEV_MGMT in multifunc mode */
- if (mlx4_is_mfunc(dev) &&
- (be32_to_cpu(new_cap_mask) & MLX4_PORT_CAP_DEV_MGMT_SUP))
- return -EINVAL;
-
- agg_cap_mask = 0;
- slave_cap_mask =
- priv->mfunc.master.slave_state[slave].ib_cap_mask[port];
- priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask;
- for (i = 0; i < dev->num_slaves; i++)
- agg_cap_mask |=
- priv->mfunc.master.slave_state[i].ib_cap_mask[port];
-
- /* only clear mailbox for guests. Master may be setting
- * MTU or PKEY table size
- */
- if (slave != dev->caps.function)
- memset(inbox->buf, 0, 256);
- if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
- *(u8 *) inbox->buf |= !!reset_qkey_viols << 6;
- ((__be32 *) inbox->buf)[2] = agg_cap_mask;
- } else {
- ((u8 *) inbox->buf)[3] |= !!reset_qkey_viols;
- ((__be32 *) inbox->buf)[1] = agg_cap_mask;
- }
-
- err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
- if (err)
- priv->mfunc.master.slave_state[slave].ib_cap_mask[port] =
- slave_cap_mask;
- return err;
-}
-
-int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- return mlx4_common_set_port(dev, slave, vhcr->in_modifier,
- vhcr->op_modifier, inbox);
-}
-
-/* bit locations for set port command with zero op modifier */
-enum {
- MLX4_SET_PORT_VL_CAP = 4, /* bits 7:4 */
- MLX4_SET_PORT_MTU_CAP = 12, /* bits 15:12 */
- MLX4_CHANGE_PORT_PKEY_TBL_SZ = 20,
- MLX4_CHANGE_PORT_VL_CAP = 21,
- MLX4_CHANGE_PORT_MTU_CAP = 22,
-};
-
-int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz)
-{
- struct mlx4_cmd_mailbox *mailbox;
- int err = -EINVAL, vl_cap, pkey_tbl_flag = 0;
- u32 in_mod;
-
- if (dev->caps.port_type[port] == MLX4_PORT_TYPE_NONE)
- return 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- memset(mailbox->buf, 0, 256);
-
- if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) {
- in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1,
- MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_WRAPPED);
- } else {
- ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port];
-
- if (pkey_tbl_sz >= 0 && mlx4_is_master(dev)) {
- pkey_tbl_flag = 1;
- ((__be16 *) mailbox->buf)[20] = cpu_to_be16(pkey_tbl_sz);
- }
-
- /* IB VL CAP enum isn't used by the firmware, just numerical values */
- for (vl_cap = dev->caps.vl_cap[port];
- vl_cap >= 1; vl_cap >>= 1) {
- ((__be32 *) mailbox->buf)[0] = cpu_to_be32(
- (1 << MLX4_CHANGE_PORT_MTU_CAP) |
- (1 << MLX4_CHANGE_PORT_VL_CAP) |
- (pkey_tbl_flag << MLX4_CHANGE_PORT_PKEY_TBL_SZ) |
- (dev->caps.port_ib_mtu[port] << MLX4_SET_PORT_MTU_CAP) |
- (vl_cap << MLX4_SET_PORT_VL_CAP));
- err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
- if (err != -ENOMEM)
- break;
- }
- }
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
- u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_port_general_context *context;
- int err;
- u32 in_mod;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- context->flags = SET_PORT_GEN_ALL_VALID;
- context->mtu = cpu_to_be16(mtu);
- context->pptx = (pptx * (!pfctx)) << 7;
- context->pfctx = pfctx;
- context->pprx = (pprx * (!pfcrx)) << 7;
- context->pfcrx = pfcrx;
-
- in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL(mlx4_SET_PORT_general);
-
-int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
- u8 promisc)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_port_rqp_calc_context *context;
- int err;
- u32 in_mod;
- u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ?
- MCAST_DIRECT : MCAST_DEFAULT;
-
- if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
- return 0;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- context->base_qpn = cpu_to_be32(base_qpn);
- context->n_mac = dev->caps.log_num_macs;
- context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
- base_qpn);
- context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
- base_qpn);
- context->intra_no_vlan = 0;
- context->no_vlan = MLX4_NO_VLAN_IDX;
- context->intra_vlan_miss = 0;
- context->vlan_miss = MLX4_VLAN_MISS_IDX;
-
- in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc);
-
-int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_port_prio2tc_context *context;
- int err;
- u32 in_mod;
- int i;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- for (i = 0; i < MLX4_NUM_UP; i += 2)
- context->prio2tc[i >> 1] = prio2tc[i] << 4 | prio2tc[i + 1];
-
- in_mod = MLX4_SET_PORT_PRIO2TC << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL(mlx4_SET_PORT_PRIO2TC);
-
-int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
- u8 *pg, u16 *ratelimit)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_port_scheduler_context *context;
- int err;
- u32 in_mod;
- int i;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- for (i = 0; i < MLX4_NUM_TC; i++) {
- struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i];
- u16 r;
- if (ratelimit && ratelimit[i]) {
- if (ratelimit[i] <= MLX4_MAX_100M_UNITS_VAL) {
- r = ratelimit[i];
- tc->max_bw_units =
- htons(MLX4_RATELIMIT_100M_UNITS);
- } else {
- r = ratelimit[i]/10;
- tc->max_bw_units =
- htons(MLX4_RATELIMIT_1G_UNITS);
- }
- tc->max_bw_value = htons(r);
- } else {
- tc->max_bw_value = htons(MLX4_RATELIMIT_DEFAULT);
- tc->max_bw_units = htons(MLX4_RATELIMIT_1G_UNITS);
- }
-
- tc->pg = htons(pg[i]);
- tc->bw_precentage = htons(tc_tx_bw[i]);
- }
-
- in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER);
-
-int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err = 0;
-
- return err;
-}
-
-int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
- u64 mac, u64 clear, u8 mode)
-{
- return mlx4_cmd(dev, (mac | (clear << 63)), port, mode,
- MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_WRAPPED);
-}
-EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR);
-
-int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err = 0;
-
- return err;
-}
-
-int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- return 0;
-}
-
-void mlx4_set_stats_bitmap(struct mlx4_dev *dev, unsigned long *stats_bitmap)
-{
- int last_i = 0;
-
- bitmap_zero(stats_bitmap, NUM_ALL_STATS);
-
- if (mlx4_is_slave(dev)) {
- last_i = dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN ?
- NUM_PKT_STATS + NUM_FLOW_STATS : NUM_PKT_STATS;
- } else {
- bitmap_set(stats_bitmap, last_i, NUM_PKT_STATS);
- last_i = NUM_PKT_STATS;
-
- if (dev->caps.flags2 &
- MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) {
- bitmap_set(stats_bitmap, last_i, NUM_FLOW_STATS);
- last_i += NUM_FLOW_STATS;
- }
- }
-
- if (mlx4_is_slave(dev))
- bitmap_set(stats_bitmap, last_i, NUM_VF_STATS);
- last_i += NUM_VF_STATS;
-
- if (mlx4_is_master(dev))
- bitmap_set(stats_bitmap, last_i, NUM_VPORT_STATS);
- last_i += NUM_VPORT_STATS;
-
- bitmap_set(stats_bitmap, last_i, NUM_PORT_STATS);
-}
-EXPORT_SYMBOL(mlx4_set_stats_bitmap);
-
-int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, int *slave_id)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i, found_ix = -1;
- int vf_gids = MLX4_ROCE_MAX_GIDS - MLX4_ROCE_PF_GIDS;
-
- if (!mlx4_is_mfunc(dev))
- return -EINVAL;
-
- for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
- if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) {
- found_ix = i;
- break;
- }
- }
-
- if (found_ix >= 0) {
- if (found_ix < MLX4_ROCE_PF_GIDS)
- *slave_id = 0;
- else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % dev->num_vfs) *
- (vf_gids / dev->num_vfs + 1))
- *slave_id = ((found_ix - MLX4_ROCE_PF_GIDS) /
- (vf_gids / dev->num_vfs + 1)) + 1;
- else
- *slave_id =
- ((found_ix - MLX4_ROCE_PF_GIDS -
- ((vf_gids % dev->num_vfs) * ((vf_gids / dev->num_vfs + 1)))) /
- (vf_gids / dev->num_vfs)) + vf_gids % dev->num_vfs + 1;
- }
-
- return (found_ix >= 0) ? 0 : -EINVAL;
-}
-EXPORT_SYMBOL(mlx4_get_slave_from_roce_gid);
-
-int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id, u8 *gid)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- if (!mlx4_is_master(dev))
- return -EINVAL;
-
- memcpy(gid, priv->roce_gids[port - 1][slave_id].raw, 16);
- return 0;
-}
-EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave);
-
-/* Cable Module Info */
-#define MODULE_INFO_MAX_READ 48
-
-#define I2C_ADDR_LOW 0x50
-#define I2C_ADDR_HIGH 0x51
-#define I2C_PAGE_SIZE 256
-
-/* Module Info Data */
-struct mlx4_cable_info {
- u8 i2c_addr;
- u8 page_num;
- __be16 dev_mem_address;
- __be16 reserved1;
- __be16 size;
- __be32 reserved2[2];
- u8 data[MODULE_INFO_MAX_READ];
-};
-
-enum cable_info_err {
- CABLE_INF_INV_PORT = 0x1,
- CABLE_INF_OP_NOSUP = 0x2,
- CABLE_INF_NOT_CONN = 0x3,
- CABLE_INF_NO_EEPRM = 0x4,
- CABLE_INF_PAGE_ERR = 0x5,
- CABLE_INF_INV_ADDR = 0x6,
- CABLE_INF_I2C_ADDR = 0x7,
- CABLE_INF_QSFP_VIO = 0x8,
- CABLE_INF_I2C_BUSY = 0x9,
-};
-
-#define MAD_STATUS_2_CABLE_ERR(mad_status) ((mad_status >> 8) & 0xFF)
-
-#ifdef DEBUG
-static inline const char *cable_info_mad_err_str(u16 mad_status)
-{
- u8 err = MAD_STATUS_2_CABLE_ERR(mad_status);
-
- switch (err) {
- case CABLE_INF_INV_PORT:
- return "invalid port selected";
- case CABLE_INF_OP_NOSUP:
- return "operation not supported for this port (the port is of type CX4 or internal)";
- case CABLE_INF_NOT_CONN:
- return "cable is not connected";
- case CABLE_INF_NO_EEPRM:
- return "the connected cable has no EPROM (passive copper cable)";
- case CABLE_INF_PAGE_ERR:
- return "page number is greater than 15";
- case CABLE_INF_INV_ADDR:
- return "invalid device_address or size (that is, size equals 0 or address+size is greater than 256)";
- case CABLE_INF_I2C_ADDR:
- return "invalid I2C slave address";
- case CABLE_INF_QSFP_VIO:
- return "at least one cable violates the QSFP specification and ignores the modsel signal";
- case CABLE_INF_I2C_BUSY:
- return "I2C bus is constantly busy";
- }
- return "Unknown Error";
-}
-#endif /* DEBUG */
-
-/**
- * mlx4_get_module_info - Read cable module eeprom data
- * @dev: mlx4_dev.
- * @port: port number.
- * @offset: byte offset in eeprom to start reading data from.
- * @size: num of bytes to read.
- * @data: output buffer to put the requested data into.
- *
- * Reads cable module eeprom data, puts the outcome data into
- * data pointer paramer.
- * Returns num of read bytes on success or a negative error
- * code.
- */
-int mlx4_get_module_info(struct mlx4_dev *dev, u8 port, u16 offset,
- u16 size, u8 *data)
-{
- struct mlx4_cmd_mailbox *inbox, *outbox;
- struct mlx4_mad_ifc *inmad, *outmad;
- struct mlx4_cable_info *cable_info;
- u16 i2c_addr;
- int ret;
-
- if (size > MODULE_INFO_MAX_READ)
- size = MODULE_INFO_MAX_READ;
-
- inbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(inbox)) {
- mlx4_err(dev,
- "mlx4_alloc_cmd_mailbox returned with error(%lx)", PTR_ERR(inbox));
- return PTR_ERR(inbox);
- }
-
- outbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(outbox)) {
- mlx4_free_cmd_mailbox(dev, inbox);
- mlx4_err(dev,
- "mlx4_alloc_cmd_mailbox returned with error(%lx)", PTR_ERR(outbox));
- return PTR_ERR(outbox);
- }
-
- inmad = (struct mlx4_mad_ifc *)(inbox->buf);
- outmad = (struct mlx4_mad_ifc *)(outbox->buf);
-
- inmad->method = 0x1; /* Get */
- inmad->class_version = 0x1;
- inmad->mgmt_class = 0x1;
- inmad->base_version = 0x1;
- inmad->attr_id = cpu_to_be16(0xFF60); /* Module Info */
-
- if (offset < I2C_PAGE_SIZE && offset + size > I2C_PAGE_SIZE)
- /* Cross pages reads are not allowed
- * read until offset 256 in low page
- */
- size -= offset + size - I2C_PAGE_SIZE;
-
- i2c_addr = I2C_ADDR_LOW;
- if (offset >= I2C_PAGE_SIZE) {
- /* Reset offset to high page */
- i2c_addr = I2C_ADDR_HIGH;
- offset -= I2C_PAGE_SIZE;
- }
-
- cable_info = (struct mlx4_cable_info *)inmad->data;
- cable_info->dev_mem_address = cpu_to_be16(offset);
- cable_info->page_num = 0;
- cable_info->i2c_addr = i2c_addr;
- cable_info->size = cpu_to_be16(size);
-
- ret = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
- MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
- if (ret)
- goto out;
-
- if (be16_to_cpu(outmad->status)) {
- /* Mad returned with bad status */
- ret = be16_to_cpu(outmad->status);
-#ifdef DEBUG
- mlx4_warn(dev, "MLX4_CMD_MAD_IFC Get Module info attr(%x) "
- "port(%d) i2c_addr(%x) offset(%d) size(%d): Response "
- "Mad Status(%x) - %s\n", 0xFF60, port, i2c_addr, offset,
- size, ret, cable_info_mad_err_str(ret));
-#endif
- if (i2c_addr == I2C_ADDR_HIGH &&
- MAD_STATUS_2_CABLE_ERR(ret) == CABLE_INF_I2C_ADDR)
- /* Some SFP cables do not support i2c slave
- * address 0x51 (high page), abort silently.
- */
- ret = 0;
- else
- ret = -ret;
- goto out;
- }
- cable_info = (struct mlx4_cable_info *)outmad->data;
- memcpy(data, cable_info->data, size);
- ret = size;
-out:
- mlx4_free_cmd_mailbox(dev, inbox);
- mlx4_free_cmd_mailbox(dev, outbox);
- return ret;
-}
-EXPORT_SYMBOL(mlx4_get_module_info);
diff --git a/sys/ofed/drivers/net/mlx4/profile.c b/sys/ofed/drivers/net/mlx4/profile.c
deleted file mode 100644
index aa5f957feccd..000000000000
--- a/sys/ofed/drivers/net/mlx4/profile.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#include <linux/slab.h>
-
-#include "mlx4.h"
-#include "fw.h"
-
-enum {
- MLX4_RES_QP,
- MLX4_RES_RDMARC,
- MLX4_RES_ALTC,
- MLX4_RES_AUXC,
- MLX4_RES_SRQ,
- MLX4_RES_CQ,
- MLX4_RES_EQ,
- MLX4_RES_DMPT,
- MLX4_RES_CMPT,
- MLX4_RES_MTT,
- MLX4_RES_MCG,
- MLX4_RES_NUM
-};
-
-static const char *res_name[] = {
- [MLX4_RES_QP] = "QP",
- [MLX4_RES_RDMARC] = "RDMARC",
- [MLX4_RES_ALTC] = "ALTC",
- [MLX4_RES_AUXC] = "AUXC",
- [MLX4_RES_SRQ] = "SRQ",
- [MLX4_RES_CQ] = "CQ",
- [MLX4_RES_EQ] = "EQ",
- [MLX4_RES_DMPT] = "DMPT",
- [MLX4_RES_CMPT] = "CMPT",
- [MLX4_RES_MTT] = "MTT",
- [MLX4_RES_MCG] = "MCG",
-};
-
-u64 mlx4_make_profile(struct mlx4_dev *dev,
- struct mlx4_profile *request,
- struct mlx4_dev_cap *dev_cap,
- struct mlx4_init_hca_param *init_hca)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource {
- u64 size;
- u64 start;
- int type;
- u64 num;
- int log_num;
- };
-
- u64 total_size = 0;
- struct mlx4_resource *profile;
- struct mlx4_resource tmp;
- int i, j;
-
- profile = kcalloc(MLX4_RES_NUM, sizeof(*profile), GFP_KERNEL);
- if (!profile)
- return -ENOMEM;
-
- profile[MLX4_RES_QP].size = dev_cap->qpc_entry_sz;
- profile[MLX4_RES_RDMARC].size = dev_cap->rdmarc_entry_sz;
- profile[MLX4_RES_ALTC].size = dev_cap->altc_entry_sz;
- profile[MLX4_RES_AUXC].size = dev_cap->aux_entry_sz;
- profile[MLX4_RES_SRQ].size = dev_cap->srq_entry_sz;
- profile[MLX4_RES_CQ].size = dev_cap->cqc_entry_sz;
- profile[MLX4_RES_EQ].size = dev_cap->eqc_entry_sz;
- profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz;
- profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz;
- profile[MLX4_RES_MTT].size = dev_cap->mtt_entry_sz;
- profile[MLX4_RES_MCG].size = mlx4_get_mgm_entry_size(dev);
-
- profile[MLX4_RES_QP].num = request->num_qp;
- profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp;
- profile[MLX4_RES_ALTC].num = request->num_qp;
- profile[MLX4_RES_AUXC].num = request->num_qp;
- profile[MLX4_RES_SRQ].num = request->num_srq;
- profile[MLX4_RES_CQ].num = request->num_cq;
- profile[MLX4_RES_EQ].num = mlx4_is_mfunc(dev) ?
- dev->phys_caps.num_phys_eqs :
- min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
- profile[MLX4_RES_DMPT].num = request->num_mpt;
- profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
- profile[MLX4_RES_MTT].num = ((u64)request->num_mtt_segs) *
- (1 << log_mtts_per_seg);
- profile[MLX4_RES_MCG].num = request->num_mcg;
-
- for (i = 0; i < MLX4_RES_NUM; ++i) {
- profile[i].type = i;
- profile[i].num = roundup_pow_of_two(profile[i].num);
- profile[i].log_num = ilog2(profile[i].num);
- profile[i].size *= profile[i].num;
- profile[i].size = max(profile[i].size, (u64) PAGE_SIZE);
- }
-
- /*
- * Sort the resources in decreasing order of size. Since they
- * all have sizes that are powers of 2, we'll be able to keep
- * resources aligned to their size and pack them without gaps
- * using the sorted order.
- */
- for (i = MLX4_RES_NUM; i > 0; --i)
- for (j = 1; j < i; ++j) {
- if (profile[j].size > profile[j - 1].size) {
- tmp = profile[j];
- profile[j] = profile[j - 1];
- profile[j - 1] = tmp;
- }
- }
-
- for (i = 0; i < MLX4_RES_NUM; ++i) {
- if (profile[i].size) {
- profile[i].start = total_size;
- total_size += profile[i].size;
- }
-
- if (total_size > dev_cap->max_icm_sz) {
- mlx4_err(dev, "Profile requires 0x%llx bytes; "
- "won't fit in 0x%llx bytes of context memory.\n",
- (unsigned long long) total_size,
- (unsigned long long) dev_cap->max_icm_sz);
- kfree(profile);
- return -ENOMEM;
- }
-
- if (profile[i].size)
- mlx4_dbg(dev, " profile[%2d] (%6s): 2^%02d entries @ 0x%10llx, "
- "size 0x%10llx\n",
- i, res_name[profile[i].type], profile[i].log_num,
- (unsigned long long) profile[i].start,
- (unsigned long long) profile[i].size);
- }
-
- mlx4_dbg(dev, "HCA context memory: reserving %d KB\n",
- (int) (total_size >> 10));
-
- for (i = 0; i < MLX4_RES_NUM; ++i) {
- switch (profile[i].type) {
- case MLX4_RES_QP:
- dev->caps.num_qps = profile[i].num;
- init_hca->qpc_base = profile[i].start;
- init_hca->log_num_qps = profile[i].log_num;
- break;
- case MLX4_RES_RDMARC:
- for (priv->qp_table.rdmarc_shift = 0;
- request->num_qp << priv->qp_table.rdmarc_shift < profile[i].num;
- ++priv->qp_table.rdmarc_shift)
- ; /* nothing */
- dev->caps.max_qp_dest_rdma = 1 << priv->qp_table.rdmarc_shift;
- priv->qp_table.rdmarc_base = (u32) profile[i].start;
- init_hca->rdmarc_base = profile[i].start;
- init_hca->log_rd_per_qp = priv->qp_table.rdmarc_shift;
- break;
- case MLX4_RES_ALTC:
- init_hca->altc_base = profile[i].start;
- break;
- case MLX4_RES_AUXC:
- init_hca->auxc_base = profile[i].start;
- break;
- case MLX4_RES_SRQ:
- dev->caps.num_srqs = profile[i].num;
- init_hca->srqc_base = profile[i].start;
- init_hca->log_num_srqs = profile[i].log_num;
- break;
- case MLX4_RES_CQ:
- dev->caps.num_cqs = profile[i].num;
- init_hca->cqc_base = profile[i].start;
- init_hca->log_num_cqs = profile[i].log_num;
- break;
- case MLX4_RES_EQ:
- dev->caps.num_eqs = roundup_pow_of_two(min_t(unsigned, dev_cap->max_eqs,
- MAX_MSIX));
- init_hca->eqc_base = profile[i].start;
- init_hca->log_num_eqs = ilog2(dev->caps.num_eqs);
- break;
- case MLX4_RES_DMPT:
- dev->caps.num_mpts = profile[i].num;
- priv->mr_table.mpt_base = profile[i].start;
- init_hca->dmpt_base = profile[i].start;
- init_hca->log_mpt_sz = profile[i].log_num;
- break;
- case MLX4_RES_CMPT:
- init_hca->cmpt_base = profile[i].start;
- break;
- case MLX4_RES_MTT:
- dev->caps.num_mtts = profile[i].num;
- priv->mr_table.mtt_base = profile[i].start;
- init_hca->mtt_base = profile[i].start;
- break;
- case MLX4_RES_MCG:
- init_hca->mc_base = profile[i].start;
- init_hca->log_mc_entry_sz =
- ilog2(mlx4_get_mgm_entry_size(dev));
- init_hca->log_mc_table_sz = profile[i].log_num;
- if (dev->caps.steering_mode ==
- MLX4_STEERING_MODE_DEVICE_MANAGED) {
- dev->caps.num_mgms = profile[i].num;
- } else {
- init_hca->log_mc_hash_sz =
- profile[i].log_num - 1;
- dev->caps.num_mgms = profile[i].num >> 1;
- dev->caps.num_amgms = profile[i].num >> 1;
- }
- break;
- default:
- break;
- }
- }
-
- /*
- * PDs don't take any HCA memory, but we assign them as part
- * of the HCA profile anyway.
- */
- dev->caps.num_pds = MLX4_NUM_PDS;
-
- kfree(profile);
- return total_size;
-}
diff --git a/sys/ofed/drivers/net/mlx4/qp.c b/sys/ofed/drivers/net/mlx4/qp.c
deleted file mode 100644
index fe8d3c2de07f..000000000000
--- a/sys/ofed/drivers/net/mlx4/qp.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2004 Voltaire, Inc. 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.
- */
-
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <linux/module.h>
-
-#include <linux/mlx4/cmd.h>
-#include <linux/mlx4/qp.h>
-
-#include "mlx4.h"
-#include "icm.h"
-
-/*
- * QP to support BF should have bits 6,7 cleared
- */
-#define MLX4_BF_QP_SKIP_MASK 0xc0
-#define MLX4_MAX_BF_QP_RANGE 0x40
-
-void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)
-{
- struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
- struct mlx4_qp *qp;
-
- spin_lock(&qp_table->lock);
-
- qp = __mlx4_qp_lookup(dev, qpn);
- if (qp)
- atomic_inc(&qp->refcount);
-
- spin_unlock(&qp_table->lock);
-
- if (!qp) {
- mlx4_dbg(dev, "Async event for none existent QP %08x\n", qpn);
- return;
- }
-
- qp->event(qp, event_type);
-
- if (atomic_dec_and_test(&qp->refcount))
- complete(&qp->free);
-}
-
-/* used for INIT/CLOSE port logic */
-static int is_master_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp, int *real_qp0, int *proxy_qp0)
-{
- /* this procedure is called after we already know we are on the master */
- /* qp0 is either the proxy qp0, or the real qp0 */
- u32 pf_proxy_offset = dev->phys_caps.base_proxy_sqpn + 8 * mlx4_master_func_num(dev);
- *proxy_qp0 = qp->qpn >= pf_proxy_offset && qp->qpn <= pf_proxy_offset + 1;
-
- *real_qp0 = qp->qpn >= dev->phys_caps.base_sqpn &&
- qp->qpn <= dev->phys_caps.base_sqpn + 1;
-
- return *real_qp0 || *proxy_qp0;
-}
-
-static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state,
- struct mlx4_qp_context *context,
- enum mlx4_qp_optpar optpar,
- int sqd_event, struct mlx4_qp *qp, int native)
-{
- static const u16 op[MLX4_QP_NUM_STATE][MLX4_QP_NUM_STATE] = {
- [MLX4_QP_STATE_RST] = {
- [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP,
- [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP,
- [MLX4_QP_STATE_INIT] = MLX4_CMD_RST2INIT_QP,
- },
- [MLX4_QP_STATE_INIT] = {
- [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP,
- [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP,
- [MLX4_QP_STATE_INIT] = MLX4_CMD_INIT2INIT_QP,
- [MLX4_QP_STATE_RTR] = MLX4_CMD_INIT2RTR_QP,
- },
- [MLX4_QP_STATE_RTR] = {
- [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP,
- [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP,
- [MLX4_QP_STATE_RTS] = MLX4_CMD_RTR2RTS_QP,
- },
- [MLX4_QP_STATE_RTS] = {
- [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP,
- [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP,
- [MLX4_QP_STATE_RTS] = MLX4_CMD_RTS2RTS_QP,
- [MLX4_QP_STATE_SQD] = MLX4_CMD_RTS2SQD_QP,
- },
- [MLX4_QP_STATE_SQD] = {
- [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP,
- [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP,
- [MLX4_QP_STATE_RTS] = MLX4_CMD_SQD2RTS_QP,
- [MLX4_QP_STATE_SQD] = MLX4_CMD_SQD2SQD_QP,
- },
- [MLX4_QP_STATE_SQER] = {
- [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP,
- [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP,
- [MLX4_QP_STATE_RTS] = MLX4_CMD_SQERR2RTS_QP,
- },
- [MLX4_QP_STATE_ERR] = {
- [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP,
- [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP,
- }
- };
-
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_cmd_mailbox *mailbox;
- int ret = 0;
- int real_qp0 = 0;
- int proxy_qp0 = 0;
- u8 port;
-
- if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE ||
- !op[cur_state][new_state])
- return -EINVAL;
-
- if (op[cur_state][new_state] == MLX4_CMD_2RST_QP) {
- ret = mlx4_cmd(dev, 0, qp->qpn, 2,
- MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A, native);
- if (mlx4_is_master(dev) && cur_state != MLX4_QP_STATE_ERR &&
- cur_state != MLX4_QP_STATE_RST &&
- is_master_qp0(dev, qp, &real_qp0, &proxy_qp0)) {
- port = (qp->qpn & 1) + 1;
- if (proxy_qp0)
- priv->mfunc.master.qp0_state[port].proxy_qp0_active = 0;
- else
- priv->mfunc.master.qp0_state[port].qp0_active = 0;
- }
- return ret;
- }
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- if (cur_state == MLX4_QP_STATE_RST && new_state == MLX4_QP_STATE_INIT) {
- u64 mtt_addr = mlx4_mtt_addr(dev, mtt);
- context->mtt_base_addr_h = mtt_addr >> 32;
- context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
- context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
- }
-
- *(__be32 *) mailbox->buf = cpu_to_be32(optpar);
- memcpy(mailbox->buf + 8, context, sizeof *context);
-
- ((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn =
- cpu_to_be32(qp->qpn);
-
- ret = mlx4_cmd(dev, mailbox->dma,
- qp->qpn | (!!sqd_event << 31),
- new_state == MLX4_QP_STATE_RST ? 2 : 0,
- op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native);
-
- if (mlx4_is_master(dev) && is_master_qp0(dev, qp, &real_qp0, &proxy_qp0)) {
- port = (qp->qpn & 1) + 1;
- if (cur_state != MLX4_QP_STATE_ERR &&
- cur_state != MLX4_QP_STATE_RST &&
- new_state == MLX4_QP_STATE_ERR) {
- if (proxy_qp0)
- priv->mfunc.master.qp0_state[port].proxy_qp0_active = 0;
- else
- priv->mfunc.master.qp0_state[port].qp0_active = 0;
- } else if (new_state == MLX4_QP_STATE_RTR) {
- if (proxy_qp0)
- priv->mfunc.master.qp0_state[port].proxy_qp0_active = 1;
- else
- priv->mfunc.master.qp0_state[port].qp0_active = 1;
- }
- }
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return ret;
-}
-
-int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state,
- struct mlx4_qp_context *context,
- enum mlx4_qp_optpar optpar,
- int sqd_event, struct mlx4_qp *qp)
-{
- return __mlx4_qp_modify(dev, mtt, cur_state, new_state, context,
- optpar, sqd_event, qp, 0);
-}
-EXPORT_SYMBOL_GPL(mlx4_qp_modify);
-
-int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
- int *base, u8 flags)
-{
- int bf_qp = !!(flags & (u8) MLX4_RESERVE_BF_QP);
-
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_qp_table *qp_table = &priv->qp_table;
-
- /* Only IPoIB uses a large cnt. In this case, just allocate
- * as usual, ignoring bf skipping, since IPoIB does not run over RoCE
- */
- if (cnt > MLX4_MAX_BF_QP_RANGE && bf_qp)
- bf_qp = 0;
-
- *base = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align,
- bf_qp ? MLX4_BF_QP_SKIP_MASK : 0);
- if (*base == -1)
- return -ENOMEM;
-
- return 0;
-}
-
-int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
- int *base, u8 flags)
-{
- u64 in_param = 0;
- u64 out_param;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, (((u32) flags) << 24) | (u32) cnt);
- set_param_h(&in_param, align);
- err = mlx4_cmd_imm(dev, in_param, &out_param,
- RES_QP, RES_OP_RESERVE,
- MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err)
- return err;
-
- *base = get_param_l(&out_param);
- return 0;
- }
- return __mlx4_qp_reserve_range(dev, cnt, align, base, flags);
-}
-EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range);
-
-void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_qp_table *qp_table = &priv->qp_table;
-
- if (mlx4_is_qp_reserved(dev, (u32) base_qpn))
- return;
- mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, MLX4_USE_RR);
-}
-
-void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
-{
- u64 in_param = 0;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, base_qpn);
- set_param_h(&in_param, cnt);
- err = mlx4_cmd(dev, in_param, RES_QP, RES_OP_RESERVE,
- MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (err) {
- mlx4_warn(dev, "Failed to release qp range"
- " base:%d cnt:%d\n", base_qpn, cnt);
- }
- } else
- __mlx4_qp_release_range(dev, base_qpn, cnt);
-}
-EXPORT_SYMBOL_GPL(mlx4_qp_release_range);
-
-int __mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_qp_table *qp_table = &priv->qp_table;
- int err;
-
- err = mlx4_table_get(dev, &qp_table->qp_table, qpn);
- if (err)
- goto err_out;
-
- err = mlx4_table_get(dev, &qp_table->auxc_table, qpn);
- if (err)
- goto err_put_qp;
-
- err = mlx4_table_get(dev, &qp_table->altc_table, qpn);
- if (err)
- goto err_put_auxc;
-
- err = mlx4_table_get(dev, &qp_table->rdmarc_table, qpn);
- if (err)
- goto err_put_altc;
-
- err = mlx4_table_get(dev, &qp_table->cmpt_table, qpn);
- if (err)
- goto err_put_rdmarc;
-
- return 0;
-
-err_put_rdmarc:
- mlx4_table_put(dev, &qp_table->rdmarc_table, qpn);
-
-err_put_altc:
- mlx4_table_put(dev, &qp_table->altc_table, qpn);
-
-err_put_auxc:
- mlx4_table_put(dev, &qp_table->auxc_table, qpn);
-
-err_put_qp:
- mlx4_table_put(dev, &qp_table->qp_table, qpn);
-
-err_out:
- return err;
-}
-
-static int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn)
-{
- u64 param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&param, qpn);
- return mlx4_cmd_imm(dev, param, &param, RES_QP, RES_OP_MAP_ICM,
- MLX4_CMD_ALLOC_RES, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
- }
- return __mlx4_qp_alloc_icm(dev, qpn);
-}
-
-void __mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_qp_table *qp_table = &priv->qp_table;
-
- mlx4_table_put(dev, &qp_table->cmpt_table, qpn);
- mlx4_table_put(dev, &qp_table->rdmarc_table, qpn);
- mlx4_table_put(dev, &qp_table->altc_table, qpn);
- mlx4_table_put(dev, &qp_table->auxc_table, qpn);
- mlx4_table_put(dev, &qp_table->qp_table, qpn);
-}
-
-static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
-{
- u64 in_param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, qpn);
- if (mlx4_cmd(dev, in_param, RES_QP, RES_OP_MAP_ICM,
- MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED))
- mlx4_warn(dev, "Failed to free icm of qp:%d\n", qpn);
- } else
- __mlx4_qp_free_icm(dev, qpn);
-}
-
-int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_qp_table *qp_table = &priv->qp_table;
- int err;
-
- if (!qpn)
- return -EINVAL;
-
- qp->qpn = qpn;
-
- err = mlx4_qp_alloc_icm(dev, qpn);
- if (err)
- return err;
-
- spin_lock_irq(&qp_table->lock);
- err = radix_tree_insert(&dev->qp_table_tree, qp->qpn &
- (dev->caps.num_qps - 1), qp);
- spin_unlock_irq(&qp_table->lock);
- if (err)
- goto err_icm;
-
- atomic_set(&qp->refcount, 1);
- init_completion(&qp->free);
-
- return 0;
-
-err_icm:
- mlx4_qp_free_icm(dev, qpn);
- return err;
-}
-
-EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
-
-void mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp)
-{
- struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
- unsigned long flags;
-
- spin_lock_irqsave(&qp_table->lock, flags);
- radix_tree_delete(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1));
- spin_unlock_irqrestore(&qp_table->lock, flags);
-}
-EXPORT_SYMBOL_GPL(mlx4_qp_remove);
-
-void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
-{
- if (atomic_dec_and_test(&qp->refcount))
- complete(&qp->free);
- wait_for_completion(&qp->free);
-
- mlx4_qp_free_icm(dev, qp->qpn);
-}
-EXPORT_SYMBOL_GPL(mlx4_qp_free);
-
-static int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn)
-{
- return mlx4_cmd(dev, 0, base_qpn, 0, MLX4_CMD_CONF_SPECIAL_QP,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-}
-
-int mlx4_init_qp_table(struct mlx4_dev *dev)
-{
- struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
- int err;
- int reserved_from_top = 0;
- int reserved_from_bot;
- int k;
-
- spin_lock_init(&qp_table->lock);
- INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC);
- if (mlx4_is_slave(dev))
- return 0;
-
- /*
- * We reserve 2 extra QPs per port for the special QPs. The
- * block of special QPs must be aligned to a multiple of 8, so
- * round up.
- *
- * We also reserve the MSB of the 24-bit QP number to indicate
- * that a QP is an XRC QP.
- */
- dev->phys_caps.base_sqpn =
- ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8);
-
- {
- int sort[MLX4_NUM_QP_REGION];
- int i, j, tmp;
- int last_base = dev->caps.num_qps;
-
- for (i = 1; i < MLX4_NUM_QP_REGION; ++i)
- sort[i] = i;
-
- for (i = MLX4_NUM_QP_REGION; i > 0; --i) {
- for (j = 2; j < i; ++j) {
- if (dev->caps.reserved_qps_cnt[sort[j]] >
- dev->caps.reserved_qps_cnt[sort[j - 1]]) {
- tmp = sort[j];
- sort[j] = sort[j - 1];
- sort[j - 1] = tmp;
- }
- }
- }
-
- for (i = 1; i < MLX4_NUM_QP_REGION; ++i) {
- last_base -= dev->caps.reserved_qps_cnt[sort[i]];
- dev->caps.reserved_qps_base[sort[i]] = last_base;
- reserved_from_top +=
- dev->caps.reserved_qps_cnt[sort[i]];
- }
-
- }
-
- /* Reserve 8 real SQPs in both native and SRIOV modes.
- * In addition, in SRIOV mode, reserve 8 proxy SQPs per function
- * (for all PFs and VFs), and 8 corresponding tunnel QPs.
- * Each proxy SQP works opposite its own tunnel QP.
- *
- * The QPs are arranged as follows:
- * a. 8 real SQPs
- * b. All the proxy SQPs (8 per function)
- * c. All the tunnel QPs (8 per function)
- */
- reserved_from_bot = mlx4_num_reserved_sqps(dev);
- if (reserved_from_bot + reserved_from_top > dev->caps.num_qps) {
- mlx4_err(dev, "Number of reserved QPs is higher than number "
- "of QPs, increase the value of log_num_qp\n");
- return -EINVAL;
- }
-
- err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
- (1 << 23) - 1, reserved_from_bot,
- reserved_from_top);
- if (err)
- return err;
-
- if (mlx4_is_mfunc(dev)) {
- /* for PPF use */
- dev->phys_caps.base_proxy_sqpn = dev->phys_caps.base_sqpn + 8;
- dev->phys_caps.base_tunnel_sqpn = dev->phys_caps.base_sqpn + 8 + 8 * MLX4_MFUNC_MAX;
-
- /* In mfunc, calculate proxy and tunnel qp offsets for the PF here,
- * since the PF does not call mlx4_slave_caps */
- dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
- dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
- dev->caps.qp1_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
- dev->caps.qp1_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
-
- if (!dev->caps.qp0_tunnel || !dev->caps.qp0_proxy ||
- !dev->caps.qp1_tunnel || !dev->caps.qp1_proxy) {
- err = -ENOMEM;
- goto err_mem;
- }
-
- for (k = 0; k < dev->caps.num_ports; k++) {
- dev->caps.qp0_proxy[k] = dev->phys_caps.base_proxy_sqpn +
- 8 * mlx4_master_func_num(dev) + k;
- dev->caps.qp0_tunnel[k] = dev->caps.qp0_proxy[k] + 8 * MLX4_MFUNC_MAX;
- dev->caps.qp1_proxy[k] = dev->phys_caps.base_proxy_sqpn +
- 8 * mlx4_master_func_num(dev) + MLX4_MAX_PORTS + k;
- dev->caps.qp1_tunnel[k] = dev->caps.qp1_proxy[k] + 8 * MLX4_MFUNC_MAX;
- }
- }
-
-
- err = mlx4_CONF_SPECIAL_QP(dev, dev->phys_caps.base_sqpn);
- if (err)
- goto err_mem;
- return 0;
-
-err_mem:
- kfree(dev->caps.qp0_tunnel);
- kfree(dev->caps.qp0_proxy);
- kfree(dev->caps.qp1_tunnel);
- kfree(dev->caps.qp1_proxy);
- dev->caps.qp0_tunnel = dev->caps.qp0_proxy =
- dev->caps.qp1_tunnel = dev->caps.qp1_proxy = NULL;
- return err;
-}
-
-void mlx4_cleanup_qp_table(struct mlx4_dev *dev)
-{
- if (mlx4_is_slave(dev))
- return;
-
- mlx4_CONF_SPECIAL_QP(dev, 0);
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap);
-}
-
-int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
- struct mlx4_qp_context *context)
-{
- struct mlx4_cmd_mailbox *mailbox;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0,
- MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
- if (!err)
- memcpy(context, mailbox->buf + 8, sizeof *context);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_qp_query);
-
-int mlx4_qp_to_ready(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
- struct mlx4_qp_context *context,
- struct mlx4_qp *qp, enum mlx4_qp_state *qp_state)
-{
- int err;
- int i;
- enum mlx4_qp_state states[] = {
- MLX4_QP_STATE_RST,
- MLX4_QP_STATE_INIT,
- MLX4_QP_STATE_RTR,
- MLX4_QP_STATE_RTS
- };
-
- for (i = 0; i < ARRAY_SIZE(states) - 1; i++) {
- context->flags &= cpu_to_be32(~(0xf << 28));
- context->flags |= cpu_to_be32(states[i + 1] << 28);
- err = mlx4_qp_modify(dev, mtt, states[i], states[i + 1],
- context, 0, 0, qp);
- if (err) {
- mlx4_err(dev, "Failed to bring QP to state: "
- "%d with error: %d\n",
- states[i + 1], err);
- return err;
- }
-
- *qp_state = states[i + 1];
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mlx4_qp_to_ready);
diff --git a/sys/ofed/drivers/net/mlx4/reset.c b/sys/ofed/drivers/net/mlx4/reset.c
deleted file mode 100644
index 44ec1e12b898..000000000000
--- a/sys/ofed/drivers/net/mlx4/reset.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008, 2014 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.
- */
-
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-
-#include "mlx4.h"
-
-int mlx4_reset(struct mlx4_dev *dev)
-{
- void __iomem *reset;
- u32 *hca_header = NULL;
- int pcie_cap;
- u16 devctl;
- u16 linkctl;
- u16 vendor;
- unsigned long end;
- u32 sem;
- int i;
- int err = 0;
-
-#define MLX4_RESET_BASE 0xf0000
-#define MLX4_RESET_SIZE 0x400
-#define MLX4_SEM_OFFSET 0x3fc
-#define MLX4_RESET_OFFSET 0x10
-#define MLX4_RESET_VALUE swab32(1)
-
-#define MLX4_SEM_TIMEOUT_JIFFIES (10 * HZ)
-#define MLX4_RESET_TIMEOUT_JIFFIES (2 * HZ)
-
- /*
- * Reset the chip. This is somewhat ugly because we have to
- * save off the PCI header before reset and then restore it
- * after the chip reboots. We skip config space offsets 22
- * and 23 since those have a special meaning.
- */
-
- /* Do we need to save off the full 4K PCI Express header?? */
- hca_header = kmalloc(256, GFP_KERNEL);
- if (!hca_header) {
- err = -ENOMEM;
- mlx4_err(dev, "Couldn't allocate memory to save HCA "
- "PCI header, aborting.\n");
- goto out;
- }
-
- pcie_cap = pci_pcie_cap(dev->pdev);
-
- for (i = 0; i < 64; ++i) {
- if (i == 22 || i == 23)
- continue;
- if (pci_read_config_dword(dev->pdev, i * 4, hca_header + i)) {
- err = -ENODEV;
- mlx4_err(dev, "Couldn't save HCA "
- "PCI header, aborting.\n");
- goto out;
- }
- }
-
- reset = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_RESET_BASE,
- MLX4_RESET_SIZE);
- if (!reset) {
- err = -ENOMEM;
- mlx4_err(dev, "Couldn't map HCA reset register, aborting.\n");
- goto out;
- }
-
- /* grab HW semaphore to lock out flash updates */
- end = jiffies + MLX4_SEM_TIMEOUT_JIFFIES;
- do {
- sem = readl(reset + MLX4_SEM_OFFSET);
- if (!sem)
- break;
-
- msleep(1);
- } while (time_before(jiffies, end));
-
- if (sem) {
- mlx4_err(dev, "Failed to obtain HW semaphore, aborting\n");
- err = -EAGAIN;
- iounmap(reset);
- goto out;
- }
-
- /* actually hit reset */
- writel(MLX4_RESET_VALUE, reset + MLX4_RESET_OFFSET);
- iounmap(reset);
-
- /* wait half a second before accessing device */
- msleep(500);
-
- end = jiffies + MLX4_RESET_TIMEOUT_JIFFIES;
- do {
- if (!pci_read_config_word(dev->pdev, PCI_VENDOR_ID, &vendor) &&
- vendor != 0xffff)
- break;
-
- msleep(1);
- } while (time_before(jiffies, end));
-
- if (vendor == 0xffff) {
- err = -ENODEV;
- mlx4_err(dev, "PCI device did not come back after reset, "
- "aborting.\n");
- goto out;
- }
-
- /* Now restore the PCI headers */
- if (pcie_cap) {
- devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4];
- if (pcie_capability_write_word(dev->pdev, PCI_EXP_DEVCTL,
- devctl)) {
- err = -ENODEV;
- mlx4_err(dev, "Couldn't restore HCA PCI Express "
- "Device Control register, aborting.\n");
- goto out;
- }
- linkctl = hca_header[(pcie_cap + PCI_EXP_LNKCTL) / 4];
- if (pcie_capability_write_word(dev->pdev, PCI_EXP_LNKCTL,
- linkctl)) {
- err = -ENODEV;
- mlx4_err(dev, "Couldn't restore HCA PCI Express "
- "Link control register, aborting.\n");
- goto out;
- }
- }
-
- for (i = 0; i < 16; ++i) {
- if (i * 4 == PCI_COMMAND)
- continue;
-
- if (pci_write_config_dword(dev->pdev, i * 4, hca_header[i])) {
- err = -ENODEV;
- mlx4_err(dev, "Couldn't restore HCA reg %x, "
- "aborting.\n", i);
- goto out;
- }
- }
-
- if (pci_write_config_dword(dev->pdev, PCI_COMMAND,
- hca_header[PCI_COMMAND / 4])) {
- err = -ENODEV;
- mlx4_err(dev, "Couldn't restore HCA COMMAND, "
- "aborting.\n");
- goto out;
- }
-
-out:
- kfree(hca_header);
-
- return err;
-}
diff --git a/sys/ofed/drivers/net/mlx4/resource_tracker.c b/sys/ofed/drivers/net/mlx4/resource_tracker.c
deleted file mode 100644
index 1bdab675ad1e..000000000000
--- a/sys/ofed/drivers/net/mlx4/resource_tracker.c
+++ /dev/null
@@ -1,4686 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies.
- * All rights reserved.
- * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. 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.
- */
-
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/mlx4/cmd.h>
-#include <linux/mlx4/qp.h>
-#include <linux/if_ether.h>
-#include <linux/etherdevice.h>
-
-#include "mlx4.h"
-#include "fw.h"
-
-#define MLX4_MAC_VALID (1ull << 63)
-
-struct mac_res {
- struct list_head list;
- u64 mac;
- int ref_count;
- u8 smac_index;
- u8 port;
-};
-
-struct vlan_res {
- struct list_head list;
- u16 vlan;
- int ref_count;
- int vlan_index;
- u8 port;
-};
-
-struct res_common {
- struct list_head list;
- struct rb_node node;
- u64 res_id;
- int owner;
- int state;
- int from_state;
- int to_state;
- int removing;
-};
-
-enum {
- RES_ANY_BUSY = 1
-};
-
-struct res_gid {
- struct list_head list;
- u8 gid[16];
- enum mlx4_protocol prot;
- enum mlx4_steer_type steer;
- u64 reg_id;
-};
-
-enum res_qp_states {
- RES_QP_BUSY = RES_ANY_BUSY,
-
- /* QP number was allocated */
- RES_QP_RESERVED,
-
- /* ICM memory for QP context was mapped */
- RES_QP_MAPPED,
-
- /* QP is in hw ownership */
- RES_QP_HW
-};
-
-struct res_qp {
- struct res_common com;
- struct res_mtt *mtt;
- struct res_cq *rcq;
- struct res_cq *scq;
- struct res_srq *srq;
- struct list_head mcg_list;
- spinlock_t mcg_spl;
- int local_qpn;
- atomic_t ref_count;
- u32 qpc_flags;
- /* saved qp params before VST enforcement in order to restore on VGT */
- u8 sched_queue;
- __be32 param3;
- u8 vlan_control;
- u8 fvl_rx;
- u8 pri_path_fl;
- u8 vlan_index;
- u8 feup;
-};
-
-enum res_mtt_states {
- RES_MTT_BUSY = RES_ANY_BUSY,
- RES_MTT_ALLOCATED,
-};
-
-static inline const char *mtt_states_str(enum res_mtt_states state)
-{
- switch (state) {
- case RES_MTT_BUSY: return "RES_MTT_BUSY";
- case RES_MTT_ALLOCATED: return "RES_MTT_ALLOCATED";
- default: return "Unknown";
- }
-}
-
-struct res_mtt {
- struct res_common com;
- int order;
- atomic_t ref_count;
-};
-
-enum res_mpt_states {
- RES_MPT_BUSY = RES_ANY_BUSY,
- RES_MPT_RESERVED,
- RES_MPT_MAPPED,
- RES_MPT_HW,
-};
-
-struct res_mpt {
- struct res_common com;
- struct res_mtt *mtt;
- int key;
-};
-
-enum res_eq_states {
- RES_EQ_BUSY = RES_ANY_BUSY,
- RES_EQ_RESERVED,
- RES_EQ_HW,
-};
-
-struct res_eq {
- struct res_common com;
- struct res_mtt *mtt;
-};
-
-enum res_cq_states {
- RES_CQ_BUSY = RES_ANY_BUSY,
- RES_CQ_ALLOCATED,
- RES_CQ_HW,
-};
-
-struct res_cq {
- struct res_common com;
- struct res_mtt *mtt;
- atomic_t ref_count;
-};
-
-enum res_srq_states {
- RES_SRQ_BUSY = RES_ANY_BUSY,
- RES_SRQ_ALLOCATED,
- RES_SRQ_HW,
-};
-
-struct res_srq {
- struct res_common com;
- struct res_mtt *mtt;
- struct res_cq *cq;
- atomic_t ref_count;
-};
-
-enum res_counter_states {
- RES_COUNTER_BUSY = RES_ANY_BUSY,
- RES_COUNTER_ALLOCATED,
-};
-
-struct res_counter {
- struct res_common com;
- int port;
-};
-
-enum res_xrcdn_states {
- RES_XRCD_BUSY = RES_ANY_BUSY,
- RES_XRCD_ALLOCATED,
-};
-
-struct res_xrcdn {
- struct res_common com;
- int port;
-};
-
-enum res_fs_rule_states {
- RES_FS_RULE_BUSY = RES_ANY_BUSY,
- RES_FS_RULE_ALLOCATED,
-};
-
-struct res_fs_rule {
- struct res_common com;
- int qpn;
-};
-
-static int mlx4_is_eth(struct mlx4_dev *dev, int port)
-{
- return dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB ? 0 : 1;
-}
-
-static void *res_tracker_lookup(struct rb_root *root, u64 res_id)
-{
- struct rb_node *node = root->rb_node;
-
- while (node) {
- struct res_common *res = container_of(node, struct res_common,
- node);
-
- if (res_id < res->res_id)
- node = node->rb_left;
- else if (res_id > res->res_id)
- node = node->rb_right;
- else
- return res;
- }
- return NULL;
-}
-
-static int res_tracker_insert(struct rb_root *root, struct res_common *res)
-{
- struct rb_node **new = &(root->rb_node), *parent = NULL;
-
- /* Figure out where to put new node */
- while (*new) {
- struct res_common *this = container_of(*new, struct res_common,
- node);
-
- parent = *new;
- if (res->res_id < this->res_id)
- new = &((*new)->rb_left);
- else if (res->res_id > this->res_id)
- new = &((*new)->rb_right);
- else
- return -EEXIST;
- }
-
- /* Add new node and rebalance tree. */
- rb_link_node(&res->node, parent, new);
- rb_insert_color(&res->node, root);
-
- return 0;
-}
-
-enum qp_transition {
- QP_TRANS_INIT2RTR,
- QP_TRANS_RTR2RTS,
- QP_TRANS_RTS2RTS,
- QP_TRANS_SQERR2RTS,
- QP_TRANS_SQD2SQD,
- QP_TRANS_SQD2RTS
-};
-
-/* For Debug uses */
-static const char *ResourceType(enum mlx4_resource rt)
-{
- switch (rt) {
- case RES_QP: return "RES_QP";
- case RES_CQ: return "RES_CQ";
- case RES_SRQ: return "RES_SRQ";
- case RES_MPT: return "RES_MPT";
- case RES_MTT: return "RES_MTT";
- case RES_MAC: return "RES_MAC";
- case RES_VLAN: return "RES_VLAN";
- case RES_EQ: return "RES_EQ";
- case RES_COUNTER: return "RES_COUNTER";
- case RES_FS_RULE: return "RES_FS_RULE";
- case RES_XRCD: return "RES_XRCD";
- default: return "Unknown resource type !!!";
- };
-}
-
-static void rem_slave_vlans(struct mlx4_dev *dev, int slave);
-static inline int mlx4_grant_resource(struct mlx4_dev *dev, int slave,
- enum mlx4_resource res_type, int count,
- int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct resource_allocator *res_alloc =
- &priv->mfunc.master.res_tracker.res_alloc[res_type];
- int err = -EINVAL;
- int allocated, free, reserved, guaranteed, from_free;
-
- spin_lock(&res_alloc->alloc_lock);
- allocated = (port > 0) ?
- res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] :
- res_alloc->allocated[slave];
- free = (port > 0) ? res_alloc->res_port_free[port - 1] :
- res_alloc->res_free;
- reserved = (port > 0) ? res_alloc->res_port_rsvd[port - 1] :
- res_alloc->res_reserved;
- guaranteed = res_alloc->guaranteed[slave];
-
- if (allocated + count > res_alloc->quota[slave])
- goto out;
-
- if (allocated + count <= guaranteed) {
- err = 0;
- } else {
- /* portion may need to be obtained from free area */
- if (guaranteed - allocated > 0)
- from_free = count - (guaranteed - allocated);
- else
- from_free = count;
-
- if (free - from_free > reserved)
- err = 0;
- }
-
- if (!err) {
- /* grant the request */
- if (port > 0) {
- res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] += count;
- res_alloc->res_port_free[port - 1] -= count;
- } else {
- res_alloc->allocated[slave] += count;
- res_alloc->res_free -= count;
- }
- }
-
-out:
- spin_unlock(&res_alloc->alloc_lock);
- return err;
-
-}
-
-static inline void mlx4_release_resource(struct mlx4_dev *dev, int slave,
- enum mlx4_resource res_type, int count,
- int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct resource_allocator *res_alloc =
- &priv->mfunc.master.res_tracker.res_alloc[res_type];
-
- spin_lock(&res_alloc->alloc_lock);
- if (port > 0) {
- res_alloc->allocated[(port - 1) * (dev->num_vfs + 1) + slave] -= count;
- res_alloc->res_port_free[port - 1] += count;
- } else {
- res_alloc->allocated[slave] -= count;
- res_alloc->res_free += count;
- }
-
- spin_unlock(&res_alloc->alloc_lock);
- return;
-}
-
-static inline void initialize_res_quotas(struct mlx4_dev *dev,
- struct resource_allocator *res_alloc,
- enum mlx4_resource res_type,
- int vf, int num_instances)
-{
- res_alloc->guaranteed[vf] = num_instances / (2 * (dev->num_vfs + 1));
- res_alloc->quota[vf] = (num_instances / 2) + res_alloc->guaranteed[vf];
- if (vf == mlx4_master_func_num(dev)) {
- res_alloc->res_free = num_instances;
- if (res_type == RES_MTT) {
- /* reserved mtts will be taken out of the PF allocation */
- res_alloc->res_free += dev->caps.reserved_mtts;
- res_alloc->guaranteed[vf] += dev->caps.reserved_mtts;
- res_alloc->quota[vf] += dev->caps.reserved_mtts;
- }
- }
-}
-
-void mlx4_init_quotas(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int pf;
-
- /* quotas for VFs are initialized in mlx4_slave_cap */
- if (mlx4_is_slave(dev))
- return;
-
- if (!mlx4_is_mfunc(dev)) {
- dev->quotas.qp = dev->caps.num_qps - dev->caps.reserved_qps -
- mlx4_num_reserved_sqps(dev);
- dev->quotas.cq = dev->caps.num_cqs - dev->caps.reserved_cqs;
- dev->quotas.srq = dev->caps.num_srqs - dev->caps.reserved_srqs;
- dev->quotas.mtt = dev->caps.num_mtts - dev->caps.reserved_mtts;
- dev->quotas.mpt = dev->caps.num_mpts - dev->caps.reserved_mrws;
- return;
- }
-
- pf = mlx4_master_func_num(dev);
- dev->quotas.qp =
- priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[pf];
- dev->quotas.cq =
- priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[pf];
- dev->quotas.srq =
- priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[pf];
- dev->quotas.mtt =
- priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[pf];
- dev->quotas.mpt =
- priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf];
-}
-int mlx4_init_resource_tracker(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i, j;
- int t;
-
- priv->mfunc.master.res_tracker.slave_list =
- kzalloc(dev->num_slaves * sizeof(struct slave_list),
- GFP_KERNEL);
- if (!priv->mfunc.master.res_tracker.slave_list)
- return -ENOMEM;
-
- for (i = 0 ; i < dev->num_slaves; i++) {
- for (t = 0; t < MLX4_NUM_OF_RESOURCE_TYPE; ++t)
- INIT_LIST_HEAD(&priv->mfunc.master.res_tracker.
- slave_list[i].res_list[t]);
- mutex_init(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
- }
-
- mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n",
- dev->num_slaves);
- for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++)
- priv->mfunc.master.res_tracker.res_tree[i] = RB_ROOT;
-
- for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
- struct resource_allocator *res_alloc =
- &priv->mfunc.master.res_tracker.res_alloc[i];
- res_alloc->quota = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
- res_alloc->guaranteed = kmalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
- if (i == RES_MAC || i == RES_VLAN)
- res_alloc->allocated = kzalloc(MLX4_MAX_PORTS *
- (dev->num_vfs + 1) * sizeof(int),
- GFP_KERNEL);
- else
- res_alloc->allocated = kzalloc((dev->num_vfs + 1) * sizeof(int), GFP_KERNEL);
-
- if (!res_alloc->quota || !res_alloc->guaranteed ||
- !res_alloc->allocated)
- goto no_mem_err;
-
- spin_lock_init(&res_alloc->alloc_lock);
- for (t = 0; t < dev->num_vfs + 1; t++) {
- switch (i) {
- case RES_QP:
- initialize_res_quotas(dev, res_alloc, RES_QP,
- t, dev->caps.num_qps -
- dev->caps.reserved_qps -
- mlx4_num_reserved_sqps(dev));
- break;
- case RES_CQ:
- initialize_res_quotas(dev, res_alloc, RES_CQ,
- t, dev->caps.num_cqs -
- dev->caps.reserved_cqs);
- break;
- case RES_SRQ:
- initialize_res_quotas(dev, res_alloc, RES_SRQ,
- t, dev->caps.num_srqs -
- dev->caps.reserved_srqs);
- break;
- case RES_MPT:
- initialize_res_quotas(dev, res_alloc, RES_MPT,
- t, dev->caps.num_mpts -
- dev->caps.reserved_mrws);
- break;
- case RES_MTT:
- initialize_res_quotas(dev, res_alloc, RES_MTT,
- t, dev->caps.num_mtts -
- dev->caps.reserved_mtts);
- break;
- case RES_MAC:
- if (t == mlx4_master_func_num(dev)) {
- res_alloc->quota[t] =
- MLX4_MAX_MAC_NUM - 2 * dev->num_vfs;
- res_alloc->guaranteed[t] = res_alloc->quota[t];
- for (j = 0; j < MLX4_MAX_PORTS; j++)
- res_alloc->res_port_free[j] = MLX4_MAX_MAC_NUM;
- } else {
- res_alloc->quota[t] = 2;
- res_alloc->guaranteed[t] = 2;
- }
- break;
- case RES_VLAN:
- if (t == mlx4_master_func_num(dev)) {
- res_alloc->quota[t] = MLX4_MAX_VLAN_NUM;
- res_alloc->guaranteed[t] = MLX4_MAX_VLAN_NUM / 2;
- for (j = 0; j < MLX4_MAX_PORTS; j++)
- res_alloc->res_port_free[j] =
- res_alloc->quota[t];
- } else {
- res_alloc->quota[t] = MLX4_MAX_VLAN_NUM / 2;
- res_alloc->guaranteed[t] = 0;
- }
- break;
- case RES_COUNTER:
- res_alloc->quota[t] = dev->caps.max_counters;
- res_alloc->guaranteed[t] = 0;
- if (t == mlx4_master_func_num(dev))
- res_alloc->res_free = res_alloc->quota[t];
- break;
- default:
- break;
- }
- if (i == RES_MAC || i == RES_VLAN) {
- for (j = 0; j < MLX4_MAX_PORTS; j++)
- res_alloc->res_port_rsvd[j] +=
- res_alloc->guaranteed[t];
- } else {
- res_alloc->res_reserved += res_alloc->guaranteed[t];
- }
- }
- }
- spin_lock_init(&priv->mfunc.master.res_tracker.lock);
- return 0;
-
-no_mem_err:
- for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
- kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);
- priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;
- kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);
- priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;
- kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);
- priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;
- }
- return -ENOMEM;
-}
-
-void mlx4_free_resource_tracker(struct mlx4_dev *dev,
- enum mlx4_res_tracker_free_type type)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- int i;
-
- if (priv->mfunc.master.res_tracker.slave_list) {
- if (type != RES_TR_FREE_STRUCTS_ONLY) {
- for (i = 0; i < dev->num_slaves; i++) {
- if (type == RES_TR_FREE_ALL ||
- dev->caps.function != i)
- mlx4_delete_all_resources_for_slave(dev, i);
- }
- /* free master's vlans */
- i = dev->caps.function;
- mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
- rem_slave_vlans(dev, i);
- mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
- }
-
- if (type != RES_TR_FREE_SLAVES_ONLY) {
- for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
- kfree(priv->mfunc.master.res_tracker.res_alloc[i].allocated);
- priv->mfunc.master.res_tracker.res_alloc[i].allocated = NULL;
- kfree(priv->mfunc.master.res_tracker.res_alloc[i].guaranteed);
- priv->mfunc.master.res_tracker.res_alloc[i].guaranteed = NULL;
- kfree(priv->mfunc.master.res_tracker.res_alloc[i].quota);
- priv->mfunc.master.res_tracker.res_alloc[i].quota = NULL;
- }
- kfree(priv->mfunc.master.res_tracker.slave_list);
- priv->mfunc.master.res_tracker.slave_list = NULL;
- }
- }
-}
-
-static void update_pkey_index(struct mlx4_dev *dev, int slave,
- struct mlx4_cmd_mailbox *inbox)
-{
- u8 sched = *(u8 *)(inbox->buf + 64);
- u8 orig_index = *(u8 *)(inbox->buf + 35);
- u8 new_index;
- struct mlx4_priv *priv = mlx4_priv(dev);
- int port;
-
- port = (sched >> 6 & 1) + 1;
-
- new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];
- *(u8 *)(inbox->buf + 35) = new_index;
-}
-
-static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
- u8 slave)
-{
- struct mlx4_qp_context *qp_ctx = inbox->buf + 8;
- enum mlx4_qp_optpar optpar = be32_to_cpu(*(__be32 *) inbox->buf);
- u32 ts = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;
- int port;
-
- if (MLX4_QP_ST_UD == ts) {
- port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
- if (mlx4_is_eth(dev, port))
- qp_ctx->pri_path.mgid_index = mlx4_get_base_gid_ix(dev, slave) | 0x80;
- else
- qp_ctx->pri_path.mgid_index = 0x80 | slave;
-
- } else if (MLX4_QP_ST_RC == ts || MLX4_QP_ST_UC == ts) {
- if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {
- port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
- if (mlx4_is_eth(dev, port)) {
- qp_ctx->pri_path.mgid_index += mlx4_get_base_gid_ix(dev, slave);
- qp_ctx->pri_path.mgid_index &= 0x7f;
- } else {
- qp_ctx->pri_path.mgid_index = slave & 0x7F;
- }
- }
- if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {
- port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;
- if (mlx4_is_eth(dev, port)) {
- qp_ctx->alt_path.mgid_index += mlx4_get_base_gid_ix(dev, slave);
- qp_ctx->alt_path.mgid_index &= 0x7f;
- } else {
- qp_ctx->alt_path.mgid_index = slave & 0x7F;
- }
- }
- }
-}
-
-static int check_counter_index_validity(struct mlx4_dev *dev, int slave, int port, int idx)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct counter_index *counter, *tmp_counter;
-
- if (slave == 0) {
- list_for_each_entry_safe(counter, tmp_counter,
- &priv->counters_table.global_port_list[port - 1],
- list) {
- if (counter->index == idx)
- return 0;
- }
- return -EINVAL;
- } else {
- list_for_each_entry_safe(counter, tmp_counter,
- &priv->counters_table.vf_list[slave - 1][port - 1],
- list) {
- if (counter->index == idx)
- return 0;
- }
- return -EINVAL;
- }
-}
-
-static int update_vport_qp_param(struct mlx4_dev *dev,
- struct mlx4_cmd_mailbox *inbox,
- u8 slave, u32 qpn)
-{
- struct mlx4_qp_context *qpc = inbox->buf + 8;
- struct mlx4_vport_oper_state *vp_oper;
- struct mlx4_priv *priv;
- u32 qp_type;
- int port;
-
- port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
- priv = mlx4_priv(dev);
- vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
- qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
-
- if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH &&
- qpc->pri_path.counter_index != MLX4_SINK_COUNTER_INDEX) {
- if (check_counter_index_validity(dev, slave, port,
- qpc->pri_path.counter_index))
- return -EINVAL;
- }
-
- mlx4_dbg(dev, "%s: QP counter_index %d for slave %d port %d\n",
- __func__, qpc->pri_path.counter_index, slave, port);
-
- if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
- dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH &&
- !mlx4_is_qp_reserved(dev, qpn) &&
- qp_type == MLX4_QP_ST_MLX &&
- qpc->pri_path.counter_index != 0xFF) {
- /* disable multicast loopback to qp with same counter */
- qpc->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
- qpc->pri_path.vlan_control |=
- MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
- }
-
- if (MLX4_VGT != vp_oper->state.default_vlan) {
- /* the reserved QPs (special, proxy, tunnel)
- * do not operate over vlans
- */
- if (mlx4_is_qp_reserved(dev, qpn))
- return 0;
-
- /* force strip vlan by clear vsd */
- qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
- /* preserve IF_COUNTER flag */
- qpc->pri_path.vlan_control &=
- MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
- if (MLX4_QP_ST_RC != qp_type) {
- if (0 != vp_oper->state.default_vlan) {
- qpc->pri_path.vlan_control |=
- MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
- MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
- MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
- } else { /* priority tagged */
- qpc->pri_path.vlan_control |=
- MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
- MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
- }
- }
- qpc->pri_path.fvl_rx |= MLX4_FVL_RX_FORCE_ETH_VLAN;
- qpc->pri_path.vlan_index = vp_oper->vlan_idx;
- qpc->pri_path.fl |= MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN;
- qpc->pri_path.feup |= MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;
- qpc->pri_path.sched_queue &= 0xC7;
- qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;
- }
- if (vp_oper->state.spoofchk) {
- qpc->pri_path.feup |= MLX4_FSM_FORCE_ETH_SRC_MAC;
- qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx;
- }
- return 0;
-}
-
-static int mpt_mask(struct mlx4_dev *dev)
-{
- return dev->caps.num_mpts - 1;
-}
-
-static void *find_res(struct mlx4_dev *dev, u64 res_id,
- enum mlx4_resource type)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- return res_tracker_lookup(&priv->mfunc.master.res_tracker.res_tree[type],
- res_id);
-}
-
-static int get_res(struct mlx4_dev *dev, int slave, u64 res_id,
- enum mlx4_resource type,
- void *res)
-{
- struct res_common *r;
- int err = 0;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = find_res(dev, res_id, type);
- if (!r) {
- err = -ENONET;
- goto exit;
- }
-
- if (r->state == RES_ANY_BUSY) {
- err = -EBUSY;
- goto exit;
- }
-
- if (r->owner != slave) {
- err = -EPERM;
- goto exit;
- }
-
- r->from_state = r->state;
- r->state = RES_ANY_BUSY;
-
- if (res)
- *((struct res_common **)res) = r;
-
-exit:
- spin_unlock_irq(mlx4_tlock(dev));
- return err;
-}
-
-int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
- enum mlx4_resource type,
- u64 res_id, int *slave)
-{
-
- struct res_common *r;
- int err = -ENOENT;
- int id = res_id;
-
- if (type == RES_QP)
- id &= 0x7fffff;
- spin_lock(mlx4_tlock(dev));
-
- r = find_res(dev, id, type);
- if (r) {
- *slave = r->owner;
- err = 0;
- }
- spin_unlock(mlx4_tlock(dev));
-
- return err;
-}
-
-static void put_res(struct mlx4_dev *dev, int slave, u64 res_id,
- enum mlx4_resource type)
-{
- struct res_common *r;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = find_res(dev, res_id, type);
- if (r)
- r->state = r->from_state;
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static struct res_common *alloc_qp_tr(int id)
-{
- struct res_qp *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_QP_RESERVED;
- ret->local_qpn = id;
- INIT_LIST_HEAD(&ret->mcg_list);
- spin_lock_init(&ret->mcg_spl);
- atomic_set(&ret->ref_count, 0);
-
- return &ret->com;
-}
-
-static struct res_common *alloc_mtt_tr(int id, int order)
-{
- struct res_mtt *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->order = order;
- ret->com.state = RES_MTT_ALLOCATED;
- atomic_set(&ret->ref_count, 0);
-
- return &ret->com;
-}
-
-static struct res_common *alloc_mpt_tr(int id, int key)
-{
- struct res_mpt *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_MPT_RESERVED;
- ret->key = key;
-
- return &ret->com;
-}
-
-static struct res_common *alloc_eq_tr(int id)
-{
- struct res_eq *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_EQ_RESERVED;
-
- return &ret->com;
-}
-
-static struct res_common *alloc_cq_tr(int id)
-{
- struct res_cq *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_CQ_ALLOCATED;
- atomic_set(&ret->ref_count, 0);
-
- return &ret->com;
-}
-
-static struct res_common *alloc_srq_tr(int id)
-{
- struct res_srq *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_SRQ_ALLOCATED;
- atomic_set(&ret->ref_count, 0);
-
- return &ret->com;
-}
-
-static struct res_common *alloc_counter_tr(int id)
-{
- struct res_counter *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_COUNTER_ALLOCATED;
-
- return &ret->com;
-}
-
-static struct res_common *alloc_xrcdn_tr(int id)
-{
- struct res_xrcdn *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_XRCD_ALLOCATED;
-
- return &ret->com;
-}
-
-static struct res_common *alloc_fs_rule_tr(u64 id, int qpn)
-{
- struct res_fs_rule *ret;
-
- ret = kzalloc(sizeof *ret, GFP_KERNEL);
- if (!ret)
- return NULL;
-
- ret->com.res_id = id;
- ret->com.state = RES_FS_RULE_ALLOCATED;
- ret->qpn = qpn;
- return &ret->com;
-}
-
-static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
- int extra)
-{
- struct res_common *ret;
-
- switch (type) {
- case RES_QP:
- ret = alloc_qp_tr(id);
- break;
- case RES_MPT:
- ret = alloc_mpt_tr(id, extra);
- break;
- case RES_MTT:
- ret = alloc_mtt_tr(id, extra);
- break;
- case RES_EQ:
- ret = alloc_eq_tr(id);
- break;
- case RES_CQ:
- ret = alloc_cq_tr(id);
- break;
- case RES_SRQ:
- ret = alloc_srq_tr(id);
- break;
- case RES_MAC:
- printk(KERN_ERR "implementation missing\n");
- return NULL;
- case RES_COUNTER:
- ret = alloc_counter_tr(id);
- break;
- case RES_XRCD:
- ret = alloc_xrcdn_tr(id);
- break;
- case RES_FS_RULE:
- ret = alloc_fs_rule_tr(id, extra);
- break;
- default:
- return NULL;
- }
- if (ret)
- ret->owner = slave;
-
- return ret;
-}
-
-static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
- enum mlx4_resource type, int extra)
-{
- int i;
- int err;
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct res_common **res_arr;
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct rb_root *root = &tracker->res_tree[type];
-
- res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL);
- if (!res_arr)
- return -ENOMEM;
-
- for (i = 0; i < count; ++i) {
- res_arr[i] = alloc_tr(base + i, type, slave, extra);
- if (!res_arr[i]) {
- for (--i; i >= 0; --i)
- kfree(res_arr[i]);
-
- kfree(res_arr);
- return -ENOMEM;
- }
- }
-
- spin_lock_irq(mlx4_tlock(dev));
- for (i = 0; i < count; ++i) {
- if (find_res(dev, base + i, type)) {
- err = -EEXIST;
- goto undo;
- }
- err = res_tracker_insert(root, res_arr[i]);
- if (err)
- goto undo;
- list_add_tail(&res_arr[i]->list,
- &tracker->slave_list[slave].res_list[type]);
- }
- spin_unlock_irq(mlx4_tlock(dev));
- kfree(res_arr);
-
- return 0;
-
-undo:
- for (--i; i >= 0; --i) {
- rb_erase(&res_arr[i]->node, root);
- list_del_init(&res_arr[i]->list);
- }
-
- spin_unlock_irq(mlx4_tlock(dev));
-
- for (i = 0; i < count; ++i)
- kfree(res_arr[i]);
-
- kfree(res_arr);
-
- return err;
-}
-
-static int remove_qp_ok(struct res_qp *res)
-{
- if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) ||
- !list_empty(&res->mcg_list)) {
- pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n",
- res->com.state, atomic_read(&res->ref_count));
- return -EBUSY;
- } else if (res->com.state != RES_QP_RESERVED) {
- return -EPERM;
- }
-
- return 0;
-}
-
-static int remove_mtt_ok(struct res_mtt *res, int order)
-{
- if (res->com.state == RES_MTT_BUSY ||
- atomic_read(&res->ref_count)) {
- printk(KERN_DEBUG "%s-%d: state %s, ref_count %d\n",
- __func__, __LINE__,
- mtt_states_str(res->com.state),
- atomic_read(&res->ref_count));
- return -EBUSY;
- } else if (res->com.state != RES_MTT_ALLOCATED)
- return -EPERM;
- else if (res->order != order)
- return -EINVAL;
-
- return 0;
-}
-
-static int remove_mpt_ok(struct res_mpt *res)
-{
- if (res->com.state == RES_MPT_BUSY)
- return -EBUSY;
- else if (res->com.state != RES_MPT_RESERVED)
- return -EPERM;
-
- return 0;
-}
-
-static int remove_eq_ok(struct res_eq *res)
-{
- if (res->com.state == RES_MPT_BUSY)
- return -EBUSY;
- else if (res->com.state != RES_MPT_RESERVED)
- return -EPERM;
-
- return 0;
-}
-
-static int remove_counter_ok(struct res_counter *res)
-{
- if (res->com.state == RES_COUNTER_BUSY)
- return -EBUSY;
- else if (res->com.state != RES_COUNTER_ALLOCATED)
- return -EPERM;
-
- return 0;
-}
-
-static int remove_xrcdn_ok(struct res_xrcdn *res)
-{
- if (res->com.state == RES_XRCD_BUSY)
- return -EBUSY;
- else if (res->com.state != RES_XRCD_ALLOCATED)
- return -EPERM;
-
- return 0;
-}
-
-static int remove_fs_rule_ok(struct res_fs_rule *res)
-{
- if (res->com.state == RES_FS_RULE_BUSY)
- return -EBUSY;
- else if (res->com.state != RES_FS_RULE_ALLOCATED)
- return -EPERM;
-
- return 0;
-}
-
-static int remove_cq_ok(struct res_cq *res)
-{
- if (res->com.state == RES_CQ_BUSY)
- return -EBUSY;
- else if (res->com.state != RES_CQ_ALLOCATED)
- return -EPERM;
-
- return 0;
-}
-
-static int remove_srq_ok(struct res_srq *res)
-{
- if (res->com.state == RES_SRQ_BUSY)
- return -EBUSY;
- else if (res->com.state != RES_SRQ_ALLOCATED)
- return -EPERM;
-
- return 0;
-}
-
-static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra)
-{
- switch (type) {
- case RES_QP:
- return remove_qp_ok((struct res_qp *)res);
- case RES_CQ:
- return remove_cq_ok((struct res_cq *)res);
- case RES_SRQ:
- return remove_srq_ok((struct res_srq *)res);
- case RES_MPT:
- return remove_mpt_ok((struct res_mpt *)res);
- case RES_MTT:
- return remove_mtt_ok((struct res_mtt *)res, extra);
- case RES_MAC:
- return -ENOSYS;
- case RES_EQ:
- return remove_eq_ok((struct res_eq *)res);
- case RES_COUNTER:
- return remove_counter_ok((struct res_counter *)res);
- case RES_XRCD:
- return remove_xrcdn_ok((struct res_xrcdn *)res);
- case RES_FS_RULE:
- return remove_fs_rule_ok((struct res_fs_rule *)res);
- default:
- return -EINVAL;
- }
-}
-
-static int rem_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
- enum mlx4_resource type, int extra)
-{
- u64 i;
- int err;
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_common *r;
-
- spin_lock_irq(mlx4_tlock(dev));
- for (i = base; i < base + count; ++i) {
- r = res_tracker_lookup(&tracker->res_tree[type], i);
- if (!r) {
- err = -ENOENT;
- goto out;
- }
- if (r->owner != slave) {
- err = -EPERM;
- goto out;
- }
- err = remove_ok(r, type, extra);
- if (err)
- goto out;
- }
-
- for (i = base; i < base + count; ++i) {
- r = res_tracker_lookup(&tracker->res_tree[type], i);
- rb_erase(&r->node, &tracker->res_tree[type]);
- list_del(&r->list);
- kfree(r);
- }
- err = 0;
-
-out:
- spin_unlock_irq(mlx4_tlock(dev));
-
- return err;
-}
-
-static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,
- enum res_qp_states state, struct res_qp **qp,
- int alloc)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_qp *r;
- int err = 0;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = res_tracker_lookup(&tracker->res_tree[RES_QP], qpn);
- if (!r)
- err = -ENOENT;
- else if (r->com.owner != slave)
- err = -EPERM;
- else {
- switch (state) {
- case RES_QP_BUSY:
- mlx4_dbg(dev, "%s: failed RES_QP, 0x%llx\n",
- __func__, (unsigned long long)r->com.res_id);
- err = -EBUSY;
- break;
-
- case RES_QP_RESERVED:
- if (r->com.state == RES_QP_MAPPED && !alloc)
- break;
-
- mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", (unsigned long long)r->com.res_id);
- err = -EINVAL;
- break;
-
- case RES_QP_MAPPED:
- if ((r->com.state == RES_QP_RESERVED && alloc) ||
- r->com.state == RES_QP_HW)
- break;
- else {
- mlx4_dbg(dev, "failed RES_QP, 0x%llx\n",
- (unsigned long long)r->com.res_id);
- err = -EINVAL;
- }
-
- break;
-
- case RES_QP_HW:
- if (r->com.state != RES_QP_MAPPED)
- err = -EINVAL;
- break;
- default:
- err = -EINVAL;
- }
-
- if (!err) {
- r->com.from_state = r->com.state;
- r->com.to_state = state;
- r->com.state = RES_QP_BUSY;
- if (qp)
- *qp = r;
- }
- }
-
- spin_unlock_irq(mlx4_tlock(dev));
-
- return err;
-}
-
-static int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
- enum res_mpt_states state, struct res_mpt **mpt)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_mpt *r;
- int err = 0;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = res_tracker_lookup(&tracker->res_tree[RES_MPT], index);
- if (!r)
- err = -ENOENT;
- else if (r->com.owner != slave)
- err = -EPERM;
- else {
- switch (state) {
- case RES_MPT_BUSY:
- err = -EINVAL;
- break;
-
- case RES_MPT_RESERVED:
- if (r->com.state != RES_MPT_MAPPED)
- err = -EINVAL;
- break;
-
- case RES_MPT_MAPPED:
- if (r->com.state != RES_MPT_RESERVED &&
- r->com.state != RES_MPT_HW)
- err = -EINVAL;
- break;
-
- case RES_MPT_HW:
- if (r->com.state != RES_MPT_MAPPED)
- err = -EINVAL;
- break;
- default:
- err = -EINVAL;
- }
-
- if (!err) {
- r->com.from_state = r->com.state;
- r->com.to_state = state;
- r->com.state = RES_MPT_BUSY;
- if (mpt)
- *mpt = r;
- }
- }
-
- spin_unlock_irq(mlx4_tlock(dev));
-
- return err;
-}
-
-static int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
- enum res_eq_states state, struct res_eq **eq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_eq *r;
- int err = 0;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = res_tracker_lookup(&tracker->res_tree[RES_EQ], index);
- if (!r)
- err = -ENOENT;
- else if (r->com.owner != slave)
- err = -EPERM;
- else {
- switch (state) {
- case RES_EQ_BUSY:
- err = -EINVAL;
- break;
-
- case RES_EQ_RESERVED:
- if (r->com.state != RES_EQ_HW)
- err = -EINVAL;
- break;
-
- case RES_EQ_HW:
- if (r->com.state != RES_EQ_RESERVED)
- err = -EINVAL;
- break;
-
- default:
- err = -EINVAL;
- }
-
- if (!err) {
- r->com.from_state = r->com.state;
- r->com.to_state = state;
- r->com.state = RES_EQ_BUSY;
- if (eq)
- *eq = r;
- }
- }
-
- spin_unlock_irq(mlx4_tlock(dev));
-
- return err;
-}
-
-static int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn,
- enum res_cq_states state, struct res_cq **cq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_cq *r;
- int err;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = res_tracker_lookup(&tracker->res_tree[RES_CQ], cqn);
- if (!r)
- err = -ENOENT;
- else if (r->com.owner != slave)
- err = -EPERM;
- else {
- switch (state) {
- case RES_CQ_BUSY:
- err = -EBUSY;
- break;
-
- case RES_CQ_ALLOCATED:
- if (r->com.state != RES_CQ_HW)
- err = -EINVAL;
- else if (atomic_read(&r->ref_count))
- err = -EBUSY;
- else
- err = 0;
- break;
-
- case RES_CQ_HW:
- if (r->com.state != RES_CQ_ALLOCATED)
- err = -EINVAL;
- else
- err = 0;
- break;
-
- default:
- err = -EINVAL;
- }
-
- if (!err) {
- r->com.from_state = r->com.state;
- r->com.to_state = state;
- r->com.state = RES_CQ_BUSY;
- if (cq)
- *cq = r;
- }
- }
-
- spin_unlock_irq(mlx4_tlock(dev));
-
- return err;
-}
-
-static int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
- enum res_srq_states state, struct res_srq **srq)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_srq *r;
- int err = 0;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = res_tracker_lookup(&tracker->res_tree[RES_SRQ], index);
- if (!r)
- err = -ENOENT;
- else if (r->com.owner != slave)
- err = -EPERM;
- else {
- switch (state) {
- case RES_SRQ_BUSY:
- err = -EINVAL;
- break;
-
- case RES_SRQ_ALLOCATED:
- if (r->com.state != RES_SRQ_HW)
- err = -EINVAL;
- else if (atomic_read(&r->ref_count))
- err = -EBUSY;
- break;
-
- case RES_SRQ_HW:
- if (r->com.state != RES_SRQ_ALLOCATED)
- err = -EINVAL;
- break;
-
- default:
- err = -EINVAL;
- }
-
- if (!err) {
- r->com.from_state = r->com.state;
- r->com.to_state = state;
- r->com.state = RES_SRQ_BUSY;
- if (srq)
- *srq = r;
- }
- }
-
- spin_unlock_irq(mlx4_tlock(dev));
-
- return err;
-}
-
-static void res_abort_move(struct mlx4_dev *dev, int slave,
- enum mlx4_resource type, int id)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_common *r;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = res_tracker_lookup(&tracker->res_tree[type], id);
- if (r && (r->owner == slave))
- r->state = r->from_state;
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void res_end_move(struct mlx4_dev *dev, int slave,
- enum mlx4_resource type, int id)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_common *r;
-
- spin_lock_irq(mlx4_tlock(dev));
- r = res_tracker_lookup(&tracker->res_tree[type], id);
- if (r && (r->owner == slave))
- r->state = r->to_state;
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static int valid_reserved(struct mlx4_dev *dev, int slave, int qpn)
-{
- return mlx4_is_qp_reserved(dev, qpn) &&
- (mlx4_is_master(dev) || mlx4_is_guest_proxy(dev, slave, qpn));
-}
-
-static int fw_reserved(struct mlx4_dev *dev, int qpn)
-{
- return qpn < dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW];
-}
-
-static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int err;
- int count;
- int align;
- int base;
- int qpn;
- u8 flags;
-
- switch (op) {
- case RES_OP_RESERVE:
- count = get_param_l(&in_param) & 0xffffff;
- flags = get_param_l(&in_param) >> 24;
- align = get_param_h(&in_param);
- err = mlx4_grant_resource(dev, slave, RES_QP, count, 0);
- if (err)
- return err;
-
- err = __mlx4_qp_reserve_range(dev, count, align, &base, flags);
- if (err) {
- mlx4_release_resource(dev, slave, RES_QP, count, 0);
- return err;
- }
-
- err = add_res_range(dev, slave, base, count, RES_QP, 0);
- if (err) {
- mlx4_release_resource(dev, slave, RES_QP, count, 0);
- __mlx4_qp_release_range(dev, base, count);
- return err;
- }
- set_param_l(out_param, base);
- break;
- case RES_OP_MAP_ICM:
- qpn = get_param_l(&in_param) & 0x7fffff;
- if (valid_reserved(dev, slave, qpn)) {
- err = add_res_range(dev, slave, qpn, 1, RES_QP, 0);
- if (err)
- return err;
- }
-
- err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED,
- NULL, 1);
- if (err)
- return err;
-
- if (!fw_reserved(dev, qpn)) {
- err = __mlx4_qp_alloc_icm(dev, qpn);
- if (err) {
- res_abort_move(dev, slave, RES_QP, qpn);
- return err;
- }
- }
-
- res_end_move(dev, slave, RES_QP, qpn);
- break;
-
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-static int mtt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int err = -EINVAL;
- int base;
- int order;
-
- if (op != RES_OP_RESERVE_AND_MAP)
- return err;
-
- order = get_param_l(&in_param);
-
- err = mlx4_grant_resource(dev, slave, RES_MTT, 1 << order, 0);
- if (err)
- return err;
-
- base = __mlx4_alloc_mtt_range(dev, order);
- if (base == -1) {
- mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
- return -ENOMEM;
- }
-
- err = add_res_range(dev, slave, base, 1, RES_MTT, order);
- if (err) {
- mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
- __mlx4_free_mtt_range(dev, base, order);
- } else
- set_param_l(out_param, base);
-
- return err;
-}
-
-static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int err = -EINVAL;
- int index;
- int id;
- struct res_mpt *mpt;
-
- switch (op) {
- case RES_OP_RESERVE:
- err = mlx4_grant_resource(dev, slave, RES_MPT, 1, 0);
- if (err)
- break;
-
- index = __mlx4_mpt_reserve(dev);
- if (index == -1) {
- mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
- break;
- }
- id = index & mpt_mask(dev);
-
- err = add_res_range(dev, slave, id, 1, RES_MPT, index);
- if (err) {
- mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
- __mlx4_mpt_release(dev, index);
- break;
- }
- set_param_l(out_param, index);
- break;
- case RES_OP_MAP_ICM:
- index = get_param_l(&in_param);
- id = index & mpt_mask(dev);
- err = mr_res_start_move_to(dev, slave, id,
- RES_MPT_MAPPED, &mpt);
- if (err)
- return err;
-
- err = __mlx4_mpt_alloc_icm(dev, mpt->key);
- if (err) {
- res_abort_move(dev, slave, RES_MPT, id);
- return err;
- }
-
- res_end_move(dev, slave, RES_MPT, id);
- break;
- }
- return err;
-}
-
-static int cq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int cqn;
- int err;
-
- switch (op) {
- case RES_OP_RESERVE_AND_MAP:
- err = mlx4_grant_resource(dev, slave, RES_CQ, 1, 0);
- if (err)
- break;
-
- err = __mlx4_cq_alloc_icm(dev, &cqn);
- if (err) {
- mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
- break;
- }
-
- err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0);
- if (err) {
- mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
- __mlx4_cq_free_icm(dev, cqn);
- break;
- }
-
- set_param_l(out_param, cqn);
- break;
-
- default:
- err = -EINVAL;
- }
-
- return err;
-}
-
-static int srq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int srqn;
- int err;
-
- switch (op) {
- case RES_OP_RESERVE_AND_MAP:
- err = mlx4_grant_resource(dev, slave, RES_SRQ, 1, 0);
- if (err)
- break;
-
- err = __mlx4_srq_alloc_icm(dev, &srqn);
- if (err) {
- mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
- break;
- }
-
- err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0);
- if (err) {
- mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
- __mlx4_srq_free_icm(dev, srqn);
- break;
- }
-
- set_param_l(out_param, srqn);
- break;
-
- default:
- err = -EINVAL;
- }
-
- return err;
-}
-
-static int mac_find_smac_ix_in_slave(struct mlx4_dev *dev, int slave, int port,
- u8 smac_index, u64 *mac)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *mac_list =
- &tracker->slave_list[slave].res_list[RES_MAC];
- struct mac_res *res, *tmp;
-
- list_for_each_entry_safe(res, tmp, mac_list, list) {
- if (res->smac_index == smac_index && res->port == (u8) port) {
- *mac = res->mac;
- return 0;
- }
- }
- return -ENOENT;
-}
-
-static int mac_add_to_slave(struct mlx4_dev *dev, int slave, u64 mac, int port, u8 smac_index)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *mac_list =
- &tracker->slave_list[slave].res_list[RES_MAC];
- struct mac_res *res, *tmp;
-
- list_for_each_entry_safe(res, tmp, mac_list, list) {
- if (res->mac == mac && res->port == (u8) port) {
- /* mac found. update ref count */
- ++res->ref_count;
- return 0;
- }
- }
-
- if (mlx4_grant_resource(dev, slave, RES_MAC, 1, port))
- return -EINVAL;
- res = kzalloc(sizeof *res, GFP_KERNEL);
- if (!res) {
- mlx4_release_resource(dev, slave, RES_MAC, 1, port);
- return -ENOMEM;
- }
- res->mac = mac;
- res->port = (u8) port;
- res->smac_index = smac_index;
- res->ref_count = 1;
- list_add_tail(&res->list,
- &tracker->slave_list[slave].res_list[RES_MAC]);
- return 0;
-}
-
-
-static void mac_del_from_slave(struct mlx4_dev *dev, int slave, u64 mac,
- int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *mac_list =
- &tracker->slave_list[slave].res_list[RES_MAC];
- struct mac_res *res, *tmp;
-
- list_for_each_entry_safe(res, tmp, mac_list, list) {
- if (res->mac == mac && res->port == (u8) port) {
- if (!--res->ref_count) {
- list_del(&res->list);
- mlx4_release_resource(dev, slave, RES_MAC, 1, port);
- kfree(res);
- }
- break;
- }
- }
-}
-
-static void rem_slave_macs(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *mac_list =
- &tracker->slave_list[slave].res_list[RES_MAC];
- struct mac_res *res, *tmp;
- int i;
-
- list_for_each_entry_safe(res, tmp, mac_list, list) {
- list_del(&res->list);
- /* dereference the mac the num times the slave referenced it */
- for (i = 0; i < res->ref_count; i++)
- __mlx4_unregister_mac(dev, res->port, res->mac);
- mlx4_release_resource(dev, slave, RES_MAC, 1, res->port);
- kfree(res);
- }
-}
-
-static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param, int in_port)
-{
- int err = -EINVAL;
- int port;
- u64 mac;
- u8 smac_index = 0;
-
- if (op != RES_OP_RESERVE_AND_MAP)
- return err;
-
- port = !in_port ? get_param_l(out_param) : in_port;
- mac = in_param;
-
- err = __mlx4_register_mac(dev, port, mac);
- if (err >= 0) {
- smac_index = err;
- set_param_l(out_param, err);
- err = 0;
- }
-
- if (!err) {
- err = mac_add_to_slave(dev, slave, mac, port, smac_index);
- if (err)
- __mlx4_unregister_mac(dev, port, mac);
- }
- return err;
-}
-
-static int vlan_add_to_slave(struct mlx4_dev *dev, int slave, u16 vlan,
- int port, int vlan_index)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *vlan_list =
- &tracker->slave_list[slave].res_list[RES_VLAN];
- struct vlan_res *res, *tmp;
-
- list_for_each_entry_safe(res, tmp, vlan_list, list) {
- if (res->vlan == vlan && res->port == (u8) port) {
- /* vlan found. update ref count */
- ++res->ref_count;
- return 0;
- }
- }
-
- if (mlx4_grant_resource(dev, slave, RES_VLAN, 1, port))
- return -EINVAL;
- res = kzalloc(sizeof(*res), GFP_KERNEL);
- if (!res) {
- mlx4_release_resource(dev, slave, RES_VLAN, 1, port);
- return -ENOMEM;
- }
- res->vlan = vlan;
- res->port = (u8) port;
- res->vlan_index = vlan_index;
- res->ref_count = 1;
- list_add_tail(&res->list,
- &tracker->slave_list[slave].res_list[RES_VLAN]);
- return 0;
-}
-
-
-static void vlan_del_from_slave(struct mlx4_dev *dev, int slave, u16 vlan,
- int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *vlan_list =
- &tracker->slave_list[slave].res_list[RES_VLAN];
- struct vlan_res *res, *tmp;
-
- list_for_each_entry_safe(res, tmp, vlan_list, list) {
- if (res->vlan == vlan && res->port == (u8) port) {
- if (!--res->ref_count) {
- list_del(&res->list);
- mlx4_release_resource(dev, slave, RES_VLAN,
- 1, port);
- kfree(res);
- }
- break;
- }
- }
-}
-
-static void rem_slave_vlans(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *vlan_list =
- &tracker->slave_list[slave].res_list[RES_VLAN];
- struct vlan_res *res, *tmp;
- int i;
-
- list_for_each_entry_safe(res, tmp, vlan_list, list) {
- list_del(&res->list);
- /* dereference the vlan the num times the slave referenced it */
- for (i = 0; i < res->ref_count; i++)
- __mlx4_unregister_vlan(dev, res->port, res->vlan);
- mlx4_release_resource(dev, slave, RES_VLAN, 1, res->port);
- kfree(res);
- }
-}
-
-static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param, int in_port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
- int err = -EINVAL;
- u16 vlan;
- int vlan_index;
- int port;
-
- port = !in_port ? get_param_l(out_param) : in_port;
-
- if (!port)
- return err;
-
- if (op != RES_OP_RESERVE_AND_MAP)
- return err;
-
- /* upstream kernels had NOP for reg/unreg vlan. Continue this. */
- if (!in_port && port > 0 && port <= dev->caps.num_ports) {
- slave_state[slave].old_vlan_api = true;
- return 0;
- }
-
- vlan = (u16) in_param;
-
- err = __mlx4_register_vlan(dev, port, vlan, &vlan_index);
- if (!err) {
- set_param_l(out_param, (u32) vlan_index);
- err = vlan_add_to_slave(dev, slave, vlan, port, vlan_index);
- if (err)
- __mlx4_unregister_vlan(dev, port, vlan);
- }
- return err;
-}
-
-static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param, int port)
-{
- u32 index;
- int err;
-
- if (op != RES_OP_RESERVE)
- return -EINVAL;
-
- err = __mlx4_counter_alloc(dev, slave, port, &index);
- if (!err)
- set_param_l(out_param, index);
-
- return err;
-}
-
-static int xrcdn_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- u32 xrcdn;
- int err;
-
- if (op != RES_OP_RESERVE)
- return -EINVAL;
-
- err = __mlx4_xrcd_alloc(dev, &xrcdn);
- if (err)
- return err;
-
- err = add_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
- if (err)
- __mlx4_xrcd_free(dev, xrcdn);
- else
- set_param_l(out_param, xrcdn);
-
- return err;
-}
-
-int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int alop = vhcr->op_modifier;
-
- switch (vhcr->in_modifier & 0xFF) {
- case RES_QP:
- err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_MTT:
- err = mtt_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_MPT:
- err = mpt_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_CQ:
- err = cq_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_SRQ:
- err = srq_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_MAC:
- err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param,
- (vhcr->in_modifier >> 8) & 0xFF);
- break;
-
- case RES_VLAN:
- err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param,
- (vhcr->in_modifier >> 8) & 0xFF);
- break;
-
- case RES_COUNTER:
- err = counter_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param,
- (vhcr->in_modifier >> 8) & 0xFF);
- break;
-
- case RES_XRCD:
- err = xrcdn_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-}
-
-static int qp_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param)
-{
- int err;
- int count;
- int base;
- int qpn;
-
- switch (op) {
- case RES_OP_RESERVE:
- base = get_param_l(&in_param) & 0x7fffff;
- count = get_param_h(&in_param);
- err = rem_res_range(dev, slave, base, count, RES_QP, 0);
- if (err)
- break;
- mlx4_release_resource(dev, slave, RES_QP, count, 0);
- __mlx4_qp_release_range(dev, base, count);
- break;
- case RES_OP_MAP_ICM:
- qpn = get_param_l(&in_param) & 0x7fffff;
- err = qp_res_start_move_to(dev, slave, qpn, RES_QP_RESERVED,
- NULL, 0);
- if (err)
- return err;
-
- if (!fw_reserved(dev, qpn))
- __mlx4_qp_free_icm(dev, qpn);
-
- res_end_move(dev, slave, RES_QP, qpn);
-
- if (valid_reserved(dev, slave, qpn))
- err = rem_res_range(dev, slave, qpn, 1, RES_QP, 0);
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-static int mtt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int err = -EINVAL;
- int base;
- int order;
-
- if (op != RES_OP_RESERVE_AND_MAP)
- return err;
-
- base = get_param_l(&in_param);
- order = get_param_h(&in_param);
- err = rem_res_range(dev, slave, base, 1, RES_MTT, order);
- if (!err) {
- mlx4_release_resource(dev, slave, RES_MTT, 1 << order, 0);
- __mlx4_free_mtt_range(dev, base, order);
- }
- return err;
-}
-
-static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param)
-{
- int err = -EINVAL;
- int index;
- int id;
- struct res_mpt *mpt;
-
- switch (op) {
- case RES_OP_RESERVE:
- index = get_param_l(&in_param);
- id = index & mpt_mask(dev);
- err = get_res(dev, slave, id, RES_MPT, &mpt);
- if (err)
- break;
- index = mpt->key;
- put_res(dev, slave, id, RES_MPT);
-
- err = rem_res_range(dev, slave, id, 1, RES_MPT, 0);
- if (err)
- break;
- mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
- __mlx4_mpt_release(dev, index);
- break;
- case RES_OP_MAP_ICM:
- index = get_param_l(&in_param);
- id = index & mpt_mask(dev);
- err = mr_res_start_move_to(dev, slave, id,
- RES_MPT_RESERVED, &mpt);
- if (err)
- return err;
-
- __mlx4_mpt_free_icm(dev, mpt->key);
- res_end_move(dev, slave, RES_MPT, id);
- return err;
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-static int cq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int cqn;
- int err;
-
- switch (op) {
- case RES_OP_RESERVE_AND_MAP:
- cqn = get_param_l(&in_param);
- err = rem_res_range(dev, slave, cqn, 1, RES_CQ, 0);
- if (err)
- break;
-
- mlx4_release_resource(dev, slave, RES_CQ, 1, 0);
- __mlx4_cq_free_icm(dev, cqn);
- break;
-
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-}
-
-static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int srqn;
- int err;
-
- switch (op) {
- case RES_OP_RESERVE_AND_MAP:
- srqn = get_param_l(&in_param);
- err = rem_res_range(dev, slave, srqn, 1, RES_SRQ, 0);
- if (err)
- break;
-
- mlx4_release_resource(dev, slave, RES_SRQ, 1, 0);
- __mlx4_srq_free_icm(dev, srqn);
- break;
-
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-}
-
-static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param, int in_port)
-{
- int port;
- int err = 0;
-
- switch (op) {
- case RES_OP_RESERVE_AND_MAP:
- port = !in_port ? get_param_l(out_param) : in_port;
- mac_del_from_slave(dev, slave, in_param, port);
- __mlx4_unregister_mac(dev, port, in_param);
- break;
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-
-}
-
-static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param, int port)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
- int err = 0;
-
- switch (op) {
- case RES_OP_RESERVE_AND_MAP:
- if (slave_state[slave].old_vlan_api == true)
- return 0;
- if (!port)
- return -EINVAL;
- vlan_del_from_slave(dev, slave, in_param, port);
- __mlx4_unregister_vlan(dev, port, in_param);
- break;
- default:
- err = -EINVAL;
- break;
- }
-
- return err;
-}
-
-static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param, int port)
-{
- int index;
-
- if (op != RES_OP_RESERVE)
- return -EINVAL;
-
- index = get_param_l(&in_param);
-
- __mlx4_counter_free(dev, slave, port, index);
-
- return 0;
-}
-
-static int xrcdn_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
-{
- int xrcdn;
- int err;
-
- if (op != RES_OP_RESERVE)
- return -EINVAL;
-
- xrcdn = get_param_l(&in_param);
- err = rem_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
- if (err)
- return err;
-
- __mlx4_xrcd_free(dev, xrcdn);
-
- return err;
-}
-
-int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err = -EINVAL;
- int alop = vhcr->op_modifier;
-
- switch (vhcr->in_modifier & 0xFF) {
- case RES_QP:
- err = qp_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param);
- break;
-
- case RES_MTT:
- err = mtt_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_MPT:
- err = mpt_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param);
- break;
-
- case RES_CQ:
- err = cq_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_SRQ:
- err = srq_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
- break;
-
- case RES_MAC:
- err = mac_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param,
- (vhcr->in_modifier >> 8) & 0xFF);
- break;
-
- case RES_VLAN:
- err = vlan_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param,
- (vhcr->in_modifier >> 8) & 0xFF);
- break;
-
- case RES_COUNTER:
- err = counter_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param,
- (vhcr->in_modifier >> 8) & 0xFF);
- break;
-
- case RES_XRCD:
- err = xrcdn_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
-
- default:
- break;
- }
- return err;
-}
-
-/* ugly but other choices are uglier */
-static int mr_phys_mpt(struct mlx4_mpt_entry *mpt)
-{
- return (be32_to_cpu(mpt->flags) >> 9) & 1;
-}
-
-static int mr_get_mtt_addr(struct mlx4_mpt_entry *mpt)
-{
- return (int)be64_to_cpu(mpt->mtt_addr) & 0xfffffff8;
-}
-
-static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
-{
- return be32_to_cpu(mpt->mtt_sz);
-}
-
-static u32 mr_get_pd(struct mlx4_mpt_entry *mpt)
-{
- return be32_to_cpu(mpt->pd_flags) & 0x00ffffff;
-}
-
-static int mr_is_fmr(struct mlx4_mpt_entry *mpt)
-{
- return be32_to_cpu(mpt->pd_flags) & MLX4_MPT_PD_FLAG_FAST_REG;
-}
-
-static int mr_is_bind_enabled(struct mlx4_mpt_entry *mpt)
-{
- return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_BIND_ENABLE;
-}
-
-static int mr_is_region(struct mlx4_mpt_entry *mpt)
-{
- return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_REGION;
-}
-
-static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
-{
- return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
-}
-
-static int srq_get_mtt_addr(struct mlx4_srq_context *srqc)
-{
- return be32_to_cpu(srqc->mtt_base_addr_l) & 0xfffffff8;
-}
-
-static int qp_get_mtt_size(struct mlx4_qp_context *qpc)
-{
- int page_shift = (qpc->log_page_size & 0x3f) + 12;
- int log_sq_size = (qpc->sq_size_stride >> 3) & 0xf;
- int log_sq_sride = qpc->sq_size_stride & 7;
- int log_rq_size = (qpc->rq_size_stride >> 3) & 0xf;
- int log_rq_stride = qpc->rq_size_stride & 7;
- int srq = (be32_to_cpu(qpc->srqn) >> 24) & 1;
- int rss = (be32_to_cpu(qpc->flags) >> 13) & 1;
- u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
- int xrc = (ts == MLX4_QP_ST_XRC) ? 1 : 0;
- int sq_size;
- int rq_size;
- int total_pages;
- int total_mem;
- int page_offset = (be32_to_cpu(qpc->params2) >> 6) & 0x3f;
-
- sq_size = 1 << (log_sq_size + log_sq_sride + 4);
- rq_size = (srq|rss|xrc) ? 0 : (1 << (log_rq_size + log_rq_stride + 4));
- total_mem = sq_size + rq_size;
- total_pages =
- roundup_pow_of_two((total_mem + (page_offset << 6)) >>
- page_shift);
-
- return total_pages;
-}
-
-static int check_mtt_range(struct mlx4_dev *dev, int slave, int start,
- int size, struct res_mtt *mtt)
-{
- int res_start = mtt->com.res_id;
- int res_size = (1 << mtt->order);
-
- if (start < res_start || start + size > res_start + res_size)
- return -EPERM;
- return 0;
-}
-
-int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int index = vhcr->in_modifier;
- struct res_mtt *mtt;
- struct res_mpt *mpt;
- int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz;
- int phys;
- int id;
- u32 pd;
- int pd_slave;
-
- id = index & mpt_mask(dev);
- err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt);
- if (err)
- return err;
-
- /* Currently disable memory windows since this feature isn't tested yet
- * under virtualization.
- */
- if (!mr_is_region(inbox->buf)) {
- err = -ENOSYS;
- goto ex_abort;
- }
-
- /* Make sure that the PD bits related to the slave id are zeros. */
- pd = mr_get_pd(inbox->buf);
- pd_slave = (pd >> 17) & 0x7f;
- if (pd_slave != 0 && pd_slave != slave) {
- err = -EPERM;
- goto ex_abort;
- }
-
- if (mr_is_fmr(inbox->buf)) {
- /* FMR and Bind Enable are forbidden in slave devices. */
- if (mr_is_bind_enabled(inbox->buf)) {
- err = -EPERM;
- goto ex_abort;
- }
- /* FMR and Memory Windows are also forbidden. */
- if (!mr_is_region(inbox->buf)) {
- err = -EPERM;
- goto ex_abort;
- }
- }
-
- phys = mr_phys_mpt(inbox->buf);
- if (!phys) {
- err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
- if (err)
- goto ex_abort;
-
- err = check_mtt_range(dev, slave, mtt_base,
- mr_get_mtt_size(inbox->buf), mtt);
- if (err)
- goto ex_put;
-
- mpt->mtt = mtt;
- }
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_put;
-
- if (!phys) {
- atomic_inc(&mtt->ref_count);
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
- }
-
- res_end_move(dev, slave, RES_MPT, id);
- return 0;
-
-ex_put:
- if (!phys)
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
-ex_abort:
- res_abort_move(dev, slave, RES_MPT, id);
-
- return err;
-}
-
-int mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int index = vhcr->in_modifier;
- struct res_mpt *mpt;
- int id;
-
- id = index & mpt_mask(dev);
- err = mr_res_start_move_to(dev, slave, id, RES_MPT_MAPPED, &mpt);
- if (err)
- return err;
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_abort;
-
- if (mpt->mtt)
- atomic_dec(&mpt->mtt->ref_count);
-
- res_end_move(dev, slave, RES_MPT, id);
- return 0;
-
-ex_abort:
- res_abort_move(dev, slave, RES_MPT, id);
-
- return err;
-}
-
-int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int index = vhcr->in_modifier;
- struct res_mpt *mpt;
- int id;
-
- id = index & mpt_mask(dev);
- err = get_res(dev, slave, id, RES_MPT, &mpt);
- if (err)
- return err;
-
- if (mpt->com.from_state != RES_MPT_HW) {
- err = -EBUSY;
- goto out;
- }
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-
-out:
- put_res(dev, slave, id, RES_MPT);
- return err;
-}
-
-static int qp_get_rcqn(struct mlx4_qp_context *qpc)
-{
- return be32_to_cpu(qpc->cqn_recv) & 0xffffff;
-}
-
-static int qp_get_scqn(struct mlx4_qp_context *qpc)
-{
- return be32_to_cpu(qpc->cqn_send) & 0xffffff;
-}
-
-static u32 qp_get_srqn(struct mlx4_qp_context *qpc)
-{
- return be32_to_cpu(qpc->srqn) & 0x1ffffff;
-}
-
-static void adjust_proxy_tun_qkey(struct mlx4_dev *dev, struct mlx4_vhcr *vhcr,
- struct mlx4_qp_context *context)
-{
- u32 qpn = vhcr->in_modifier & 0xffffff;
- u32 qkey = 0;
-
- if (mlx4_get_parav_qkey(dev, qpn, &qkey))
- return;
-
- /* adjust qkey in qp context */
- context->qkey = cpu_to_be32(qkey);
-}
-
-int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int qpn = vhcr->in_modifier & 0x7fffff;
- struct res_mtt *mtt;
- struct res_qp *qp;
- struct mlx4_qp_context *qpc = inbox->buf + 8;
- int mtt_base = qp_get_mtt_addr(qpc) / dev->caps.mtt_entry_sz;
- int mtt_size = qp_get_mtt_size(qpc);
- struct res_cq *rcq;
- struct res_cq *scq;
- int rcqn = qp_get_rcqn(qpc);
- int scqn = qp_get_scqn(qpc);
- u32 srqn = qp_get_srqn(qpc) & 0xffffff;
- int use_srq = (qp_get_srqn(qpc) >> 24) & 1;
- struct res_srq *srq;
- int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff;
-
- err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0);
- if (err)
- return err;
- qp->local_qpn = local_qpn;
- qp->sched_queue = 0;
- qp->param3 = 0;
- qp->vlan_control = 0;
- qp->fvl_rx = 0;
- qp->pri_path_fl = 0;
- qp->vlan_index = 0;
- qp->feup = 0;
- qp->qpc_flags = be32_to_cpu(qpc->flags);
-
- err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
- if (err)
- goto ex_abort;
-
- err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);
- if (err)
- goto ex_put_mtt;
-
- err = get_res(dev, slave, rcqn, RES_CQ, &rcq);
- if (err)
- goto ex_put_mtt;
-
- if (scqn != rcqn) {
- err = get_res(dev, slave, scqn, RES_CQ, &scq);
- if (err)
- goto ex_put_rcq;
- } else
- scq = rcq;
-
- if (use_srq) {
- err = get_res(dev, slave, srqn, RES_SRQ, &srq);
- if (err)
- goto ex_put_scq;
- }
-
- adjust_proxy_tun_qkey(dev, vhcr, qpc);
- update_pkey_index(dev, slave, inbox);
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_put_srq;
- atomic_inc(&mtt->ref_count);
- qp->mtt = mtt;
- atomic_inc(&rcq->ref_count);
- qp->rcq = rcq;
- atomic_inc(&scq->ref_count);
- qp->scq = scq;
-
- if (scqn != rcqn)
- put_res(dev, slave, scqn, RES_CQ);
-
- if (use_srq) {
- atomic_inc(&srq->ref_count);
- put_res(dev, slave, srqn, RES_SRQ);
- qp->srq = srq;
- }
- put_res(dev, slave, rcqn, RES_CQ);
- put_res(dev, slave, mtt_base, RES_MTT);
- res_end_move(dev, slave, RES_QP, qpn);
-
- return 0;
-
-ex_put_srq:
- if (use_srq)
- put_res(dev, slave, srqn, RES_SRQ);
-ex_put_scq:
- if (scqn != rcqn)
- put_res(dev, slave, scqn, RES_CQ);
-ex_put_rcq:
- put_res(dev, slave, rcqn, RES_CQ);
-ex_put_mtt:
- put_res(dev, slave, mtt_base, RES_MTT);
-ex_abort:
- res_abort_move(dev, slave, RES_QP, qpn);
-
- return err;
-}
-
-static int eq_get_mtt_addr(struct mlx4_eq_context *eqc)
-{
- return be32_to_cpu(eqc->mtt_base_addr_l) & 0xfffffff8;
-}
-
-static int eq_get_mtt_size(struct mlx4_eq_context *eqc)
-{
- int log_eq_size = eqc->log_eq_size & 0x1f;
- int page_shift = (eqc->log_page_size & 0x3f) + 12;
-
- if (log_eq_size + 5 < page_shift)
- return 1;
-
- return 1 << (log_eq_size + 5 - page_shift);
-}
-
-static int cq_get_mtt_addr(struct mlx4_cq_context *cqc)
-{
- return be32_to_cpu(cqc->mtt_base_addr_l) & 0xfffffff8;
-}
-
-static int cq_get_mtt_size(struct mlx4_cq_context *cqc)
-{
- int log_cq_size = (be32_to_cpu(cqc->logsize_usrpage) >> 24) & 0x1f;
- int page_shift = (cqc->log_page_size & 0x3f) + 12;
-
- if (log_cq_size + 5 < page_shift)
- return 1;
-
- return 1 << (log_cq_size + 5 - page_shift);
-}
-
-int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int eqn = vhcr->in_modifier;
- int res_id = (slave << 8) | eqn;
- struct mlx4_eq_context *eqc = inbox->buf;
- int mtt_base = eq_get_mtt_addr(eqc) / dev->caps.mtt_entry_sz;
- int mtt_size = eq_get_mtt_size(eqc);
- struct res_eq *eq;
- struct res_mtt *mtt;
-
- err = add_res_range(dev, slave, res_id, 1, RES_EQ, 0);
- if (err)
- return err;
- err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_HW, &eq);
- if (err)
- goto out_add;
-
- err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
- if (err)
- goto out_move;
-
- err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt);
- if (err)
- goto out_put;
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto out_put;
-
- atomic_inc(&mtt->ref_count);
- eq->mtt = mtt;
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
- res_end_move(dev, slave, RES_EQ, res_id);
- return 0;
-
-out_put:
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
-out_move:
- res_abort_move(dev, slave, RES_EQ, res_id);
-out_add:
- rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);
- return err;
-}
-
-static int get_containing_mtt(struct mlx4_dev *dev, int slave, int start,
- int len, struct res_mtt **res)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct res_mtt *mtt;
- int err = -EINVAL;
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry(mtt, &tracker->slave_list[slave].res_list[RES_MTT],
- com.list) {
- if (!check_mtt_range(dev, slave, start, len, mtt)) {
- *res = mtt;
- mtt->com.from_state = mtt->com.state;
- mtt->com.state = RES_MTT_BUSY;
- err = 0;
- break;
- }
- }
- spin_unlock_irq(mlx4_tlock(dev));
-
- return err;
-}
-
-static int verify_qp_parameters(struct mlx4_dev *dev,
- struct mlx4_cmd_mailbox *inbox,
- enum qp_transition transition, u8 slave)
-{
- u32 qp_type;
- struct mlx4_qp_context *qp_ctx;
- enum mlx4_qp_optpar optpar;
- int port;
- int num_gids;
-
- qp_ctx = inbox->buf + 8;
- qp_type = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;
- optpar = be32_to_cpu(*(__be32 *) inbox->buf);
-
- switch (qp_type) {
- case MLX4_QP_ST_RC:
- case MLX4_QP_ST_UC:
- switch (transition) {
- case QP_TRANS_INIT2RTR:
- case QP_TRANS_RTR2RTS:
- case QP_TRANS_RTS2RTS:
- case QP_TRANS_SQD2SQD:
- case QP_TRANS_SQD2RTS:
- if (slave != mlx4_master_func_num(dev))
- if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH) {
- port = (qp_ctx->pri_path.sched_queue >> 6 & 1) + 1;
- if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)
- num_gids = mlx4_get_slave_num_gids(dev, slave);
- else
- num_gids = 1;
- if (qp_ctx->pri_path.mgid_index >= num_gids)
- return -EINVAL;
- }
- if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) {
- port = (qp_ctx->alt_path.sched_queue >> 6 & 1) + 1;
- if (dev->caps.port_mask[port] != MLX4_PORT_TYPE_IB)
- num_gids = mlx4_get_slave_num_gids(dev, slave);
- else
- num_gids = 1;
- if (qp_ctx->alt_path.mgid_index >= num_gids)
- return -EINVAL;
- }
- break;
- default:
- break;
- }
-
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_mtt mtt;
- __be64 *page_list = inbox->buf;
- u64 *pg_list = (u64 *)page_list;
- int i;
- struct res_mtt *rmtt = NULL;
- int start = be64_to_cpu(page_list[0]);
- int npages = vhcr->in_modifier;
- int err;
-
- err = get_containing_mtt(dev, slave, start, npages, &rmtt);
- if (err)
- return err;
-
- /* Call the SW implementation of write_mtt:
- * - Prepare a dummy mtt struct
- * - Translate inbox contents to simple addresses in host endianness */
- mtt.offset = 0; /* TBD this is broken but I don't handle it since
- we don't really use it */
- mtt.order = 0;
- mtt.page_shift = 0;
- for (i = 0; i < npages; ++i)
- pg_list[i + 2] = (be64_to_cpu(page_list[i + 2]) & ~1ULL);
-
- err = __mlx4_write_mtt(dev, &mtt, be64_to_cpu(page_list[0]), npages,
- ((u64 *)page_list + 2));
-
- if (rmtt)
- put_res(dev, slave, rmtt->com.res_id, RES_MTT);
-
- return err;
-}
-
-int mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int eqn = vhcr->in_modifier;
- int res_id = eqn | (slave << 8);
- struct res_eq *eq;
- int err;
-
- err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_RESERVED, &eq);
- if (err)
- return err;
-
- err = get_res(dev, slave, eq->mtt->com.res_id, RES_MTT, NULL);
- if (err)
- goto ex_abort;
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_put;
-
- atomic_dec(&eq->mtt->ref_count);
- put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);
- res_end_move(dev, slave, RES_EQ, res_id);
- rem_res_range(dev, slave, res_id, 1, RES_EQ, 0);
-
- return 0;
-
-ex_put:
- put_res(dev, slave, eq->mtt->com.res_id, RES_MTT);
-ex_abort:
- res_abort_move(dev, slave, RES_EQ, res_id);
-
- return err;
-}
-
-int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_event_eq_info *event_eq;
- struct mlx4_cmd_mailbox *mailbox;
- u32 in_modifier = 0;
- int err;
- int res_id;
- struct res_eq *req;
-
- if (!priv->mfunc.master.slave_state)
- return -EINVAL;
-
- /* check for slave valid, slave not PF, and slave active */
- if (slave < 0 || slave >= dev->num_slaves ||
- slave == dev->caps.function ||
- !priv->mfunc.master.slave_state[slave].active)
- return 0;
-
- event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];
-
- /* Create the event only if the slave is registered */
- if (event_eq->eqn < 0)
- return 0;
-
- mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);
- res_id = (slave << 8) | event_eq->eqn;
- err = get_res(dev, slave, res_id, RES_EQ, &req);
- if (err)
- goto unlock;
-
- if (req->com.from_state != RES_EQ_HW) {
- err = -EINVAL;
- goto put;
- }
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- goto put;
- }
-
- if (eqe->type == MLX4_EVENT_TYPE_CMD) {
- ++event_eq->token;
- eqe->event.cmd.token = cpu_to_be16(event_eq->token);
- }
-
- memcpy(mailbox->buf, (u8 *) eqe, 28);
-
- in_modifier = (slave & 0xff) | ((event_eq->eqn & 0xff) << 16);
-
- err = mlx4_cmd(dev, mailbox->dma, in_modifier, 0,
- MLX4_CMD_GEN_EQE, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_NATIVE);
-
- put_res(dev, slave, res_id, RES_EQ);
- mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-
-put:
- put_res(dev, slave, res_id, RES_EQ);
-
-unlock:
- mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]);
- return err;
-}
-
-int mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int eqn = vhcr->in_modifier;
- int res_id = eqn | (slave << 8);
- struct res_eq *eq;
- int err;
-
- err = get_res(dev, slave, res_id, RES_EQ, &eq);
- if (err)
- return err;
-
- if (eq->com.from_state != RES_EQ_HW) {
- err = -EINVAL;
- goto ex_put;
- }
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-
-ex_put:
- put_res(dev, slave, res_id, RES_EQ);
- return err;
-}
-
-int mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int cqn = vhcr->in_modifier;
- struct mlx4_cq_context *cqc = inbox->buf;
- int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;
- struct res_cq *cq;
- struct res_mtt *mtt;
-
- err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_HW, &cq);
- if (err)
- return err;
- err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
- if (err)
- goto out_move;
- err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);
- if (err)
- goto out_put;
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto out_put;
- atomic_inc(&mtt->ref_count);
- cq->mtt = mtt;
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
- res_end_move(dev, slave, RES_CQ, cqn);
- return 0;
-
-out_put:
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
-out_move:
- res_abort_move(dev, slave, RES_CQ, cqn);
- return err;
-}
-
-int mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int cqn = vhcr->in_modifier;
- struct res_cq *cq;
-
- err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_ALLOCATED, &cq);
- if (err)
- return err;
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto out_move;
- atomic_dec(&cq->mtt->ref_count);
- res_end_move(dev, slave, RES_CQ, cqn);
- return 0;
-
-out_move:
- res_abort_move(dev, slave, RES_CQ, cqn);
- return err;
-}
-
-int mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int cqn = vhcr->in_modifier;
- struct res_cq *cq;
- int err;
-
- err = get_res(dev, slave, cqn, RES_CQ, &cq);
- if (err)
- return err;
-
- if (cq->com.from_state != RES_CQ_HW)
- goto ex_put;
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-ex_put:
- put_res(dev, slave, cqn, RES_CQ);
-
- return err;
-}
-
-static int handle_resize(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd,
- struct res_cq *cq)
-{
- int err;
- struct res_mtt *orig_mtt;
- struct res_mtt *mtt;
- struct mlx4_cq_context *cqc = inbox->buf;
- int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz;
-
- err = get_res(dev, slave, cq->mtt->com.res_id, RES_MTT, &orig_mtt);
- if (err)
- return err;
-
- if (orig_mtt != cq->mtt) {
- err = -EINVAL;
- goto ex_put;
- }
-
- err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
- if (err)
- goto ex_put;
-
- err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt);
- if (err)
- goto ex_put1;
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_put1;
- atomic_dec(&orig_mtt->ref_count);
- put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);
- atomic_inc(&mtt->ref_count);
- cq->mtt = mtt;
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
- return 0;
-
-ex_put1:
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
-ex_put:
- put_res(dev, slave, orig_mtt->com.res_id, RES_MTT);
-
- return err;
-
-}
-
-int mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int cqn = vhcr->in_modifier;
- struct res_cq *cq;
- int err;
-
- err = get_res(dev, slave, cqn, RES_CQ, &cq);
- if (err)
- return err;
-
- if (cq->com.from_state != RES_CQ_HW)
- goto ex_put;
-
- if (vhcr->op_modifier == 0) {
- err = handle_resize(dev, slave, vhcr, inbox, outbox, cmd, cq);
- goto ex_put;
- }
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-ex_put:
- put_res(dev, slave, cqn, RES_CQ);
-
- return err;
-}
-
-static int srq_get_mtt_size(struct mlx4_srq_context *srqc)
-{
- int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf;
- int log_rq_stride = srqc->logstride & 7;
- int page_shift = (srqc->log_page_size & 0x3f) + 12;
-
- if (log_srq_size + log_rq_stride + 4 < page_shift)
- return 1;
-
- return 1 << (log_srq_size + log_rq_stride + 4 - page_shift);
-}
-
-int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int srqn = vhcr->in_modifier;
- struct res_mtt *mtt;
- struct res_srq *srq;
- struct mlx4_srq_context *srqc = inbox->buf;
- int mtt_base = srq_get_mtt_addr(srqc) / dev->caps.mtt_entry_sz;
-
- if (srqn != (be32_to_cpu(srqc->state_logsize_srqn) & 0xffffff))
- return -EINVAL;
-
- err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_HW, &srq);
- if (err)
- return err;
- err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
- if (err)
- goto ex_abort;
- err = check_mtt_range(dev, slave, mtt_base, srq_get_mtt_size(srqc),
- mtt);
- if (err)
- goto ex_put_mtt;
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_put_mtt;
-
- atomic_inc(&mtt->ref_count);
- srq->mtt = mtt;
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
- res_end_move(dev, slave, RES_SRQ, srqn);
- return 0;
-
-ex_put_mtt:
- put_res(dev, slave, mtt->com.res_id, RES_MTT);
-ex_abort:
- res_abort_move(dev, slave, RES_SRQ, srqn);
-
- return err;
-}
-
-int mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int srqn = vhcr->in_modifier;
- struct res_srq *srq;
-
- err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_ALLOCATED, &srq);
- if (err)
- return err;
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_abort;
- atomic_dec(&srq->mtt->ref_count);
- if (srq->cq)
- atomic_dec(&srq->cq->ref_count);
- res_end_move(dev, slave, RES_SRQ, srqn);
-
- return 0;
-
-ex_abort:
- res_abort_move(dev, slave, RES_SRQ, srqn);
-
- return err;
-}
-
-int mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int srqn = vhcr->in_modifier;
- struct res_srq *srq;
-
- err = get_res(dev, slave, srqn, RES_SRQ, &srq);
- if (err)
- return err;
- if (srq->com.from_state != RES_SRQ_HW) {
- err = -EBUSY;
- goto out;
- }
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-out:
- put_res(dev, slave, srqn, RES_SRQ);
- return err;
-}
-
-int mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int srqn = vhcr->in_modifier;
- struct res_srq *srq;
-
- err = get_res(dev, slave, srqn, RES_SRQ, &srq);
- if (err)
- return err;
-
- if (srq->com.from_state != RES_SRQ_HW) {
- err = -EBUSY;
- goto out;
- }
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-out:
- put_res(dev, slave, srqn, RES_SRQ);
- return err;
-}
-
-int mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int qpn = vhcr->in_modifier & 0x7fffff;
- struct res_qp *qp;
-
- err = get_res(dev, slave, qpn, RES_QP, &qp);
- if (err)
- return err;
- if (qp->com.from_state != RES_QP_HW) {
- err = -EBUSY;
- goto out;
- }
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-out:
- put_res(dev, slave, qpn, RES_QP);
- return err;
-}
-
-int mlx4_INIT2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_qp_context *context = inbox->buf + 8;
- adjust_proxy_tun_qkey(dev, vhcr, context);
- update_pkey_index(dev, slave, inbox);
- return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-}
-
-static int roce_verify_mac(struct mlx4_dev *dev, int slave,
- struct mlx4_qp_context *qpc,
- struct mlx4_cmd_mailbox *inbox)
-{
- u64 mac;
- int port;
- u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
- u8 sched = *(u8 *)(inbox->buf + 64);
- u8 smac_ix;
-
- port = (sched >> 6 & 1) + 1;
- if (mlx4_is_eth(dev, port) && (ts != MLX4_QP_ST_MLX)) {
- smac_ix = qpc->pri_path.grh_mylmc & 0x7f;
- if (mac_find_smac_ix_in_slave(dev, slave, port, smac_ix, &mac))
- return -ENOENT;
- }
- return 0;
-}
-
-int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- struct mlx4_qp_context *qpc = inbox->buf + 8;
- int qpn = vhcr->in_modifier & 0x7fffff;
- struct res_qp *qp;
- u8 orig_sched_queue;
- __be32 orig_param3 = qpc->param3;
- u8 orig_vlan_control = qpc->pri_path.vlan_control;
- u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
- u8 orig_pri_path_fl = qpc->pri_path.fl;
- u8 orig_vlan_index = qpc->pri_path.vlan_index;
- u8 orig_feup = qpc->pri_path.feup;
-
- err = verify_qp_parameters(dev, inbox, QP_TRANS_INIT2RTR, slave);
- if (err)
- return err;
-
- if (roce_verify_mac(dev, slave, qpc, inbox))
- return -EINVAL;
-
- update_pkey_index(dev, slave, inbox);
- update_gid(dev, inbox, (u8)slave);
- adjust_proxy_tun_qkey(dev, vhcr, qpc);
- orig_sched_queue = qpc->pri_path.sched_queue;
-
- err = get_res(dev, slave, qpn, RES_QP, &qp);
- if (err)
- return err;
- if (qp->com.from_state != RES_QP_HW) {
- err = -EBUSY;
- goto out;
- }
-
- /* do not modify vport QP params for RSS QPs */
- if (!(qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET))) {
- err = update_vport_qp_param(dev, inbox, slave, qpn);
- if (err)
- goto out;
- }
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-out:
- /* if no error, save sched queue value passed in by VF. This is
- * essentially the QOS value provided by the VF. This will be useful
- * if we allow dynamic changes from VST back to VGT
- */
- if (!err) {
- qp->sched_queue = orig_sched_queue;
- qp->param3 = orig_param3;
- qp->vlan_control = orig_vlan_control;
- qp->fvl_rx = orig_fvl_rx;
- qp->pri_path_fl = orig_pri_path_fl;
- qp->vlan_index = orig_vlan_index;
- qp->feup = orig_feup;
- }
- put_res(dev, slave, qpn, RES_QP);
- return err;
-}
-
-int mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- struct mlx4_qp_context *context = inbox->buf + 8;
-
- err = verify_qp_parameters(dev, inbox, QP_TRANS_RTR2RTS, slave);
- if (err)
- return err;
-
- update_pkey_index(dev, slave, inbox);
- update_gid(dev, inbox, (u8)slave);
- adjust_proxy_tun_qkey(dev, vhcr, context);
- return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-}
-
-int mlx4_RTS2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- struct mlx4_qp_context *context = inbox->buf + 8;
-
- err = verify_qp_parameters(dev, inbox, QP_TRANS_RTS2RTS, slave);
- if (err)
- return err;
-
- update_pkey_index(dev, slave, inbox);
- update_gid(dev, inbox, (u8)slave);
- adjust_proxy_tun_qkey(dev, vhcr, context);
- return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-}
-
-
-int mlx4_SQERR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_qp_context *context = inbox->buf + 8;
- adjust_proxy_tun_qkey(dev, vhcr, context);
- return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-}
-
-int mlx4_SQD2SQD_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- struct mlx4_qp_context *context = inbox->buf + 8;
-
- err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2SQD, slave);
- if (err)
- return err;
-
- adjust_proxy_tun_qkey(dev, vhcr, context);
- update_gid(dev, inbox, (u8)slave);
- update_pkey_index(dev, slave, inbox);
- return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-}
-
-int mlx4_SQD2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- struct mlx4_qp_context *context = inbox->buf + 8;
-
- err = verify_qp_parameters(dev, inbox, QP_TRANS_SQD2RTS, slave);
- if (err)
- return err;
-
- adjust_proxy_tun_qkey(dev, vhcr, context);
- update_gid(dev, inbox, (u8)slave);
- update_pkey_index(dev, slave, inbox);
- return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-}
-
-int mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- int qpn = vhcr->in_modifier & 0x7fffff;
- struct res_qp *qp;
-
- err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, &qp, 0);
- if (err)
- return err;
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- if (err)
- goto ex_abort;
-
- atomic_dec(&qp->mtt->ref_count);
- atomic_dec(&qp->rcq->ref_count);
- atomic_dec(&qp->scq->ref_count);
- if (qp->srq)
- atomic_dec(&qp->srq->ref_count);
- res_end_move(dev, slave, RES_QP, qpn);
- return 0;
-
-ex_abort:
- res_abort_move(dev, slave, RES_QP, qpn);
-
- return err;
-}
-
-static struct res_gid *find_gid(struct mlx4_dev *dev, int slave,
- struct res_qp *rqp, u8 *gid)
-{
- struct res_gid *res;
-
- list_for_each_entry(res, &rqp->mcg_list, list) {
- if (!memcmp(res->gid, gid, 16))
- return res;
- }
- return NULL;
-}
-
-static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
- u8 *gid, enum mlx4_protocol prot,
- enum mlx4_steer_type steer, u64 reg_id)
-{
- struct res_gid *res;
- int err;
-
- res = kzalloc(sizeof *res, GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
- spin_lock_irq(&rqp->mcg_spl);
- if (find_gid(dev, slave, rqp, gid)) {
- kfree(res);
- err = -EEXIST;
- } else {
- memcpy(res->gid, gid, 16);
- res->prot = prot;
- res->steer = steer;
- res->reg_id = reg_id;
- list_add_tail(&res->list, &rqp->mcg_list);
- err = 0;
- }
- spin_unlock_irq(&rqp->mcg_spl);
-
- return err;
-}
-
-static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
- u8 *gid, enum mlx4_protocol prot,
- enum mlx4_steer_type steer, u64 *reg_id)
-{
- struct res_gid *res;
- int err;
-
- spin_lock_irq(&rqp->mcg_spl);
- res = find_gid(dev, slave, rqp, gid);
- if (!res || res->prot != prot || res->steer != steer)
- err = -EINVAL;
- else {
- *reg_id = res->reg_id;
- list_del(&res->list);
- kfree(res);
- err = 0;
- }
- spin_unlock_irq(&rqp->mcg_spl);
-
- return err;
-}
-
-static int qp_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- int block_loopback, enum mlx4_protocol prot,
- enum mlx4_steer_type type, u64 *reg_id)
-{
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- return mlx4_trans_to_dmfs_attach(dev, qp, gid, gid[5],
- block_loopback, prot,
- reg_id);
- case MLX4_STEERING_MODE_B0:
- return mlx4_qp_attach_common(dev, qp, gid,
- block_loopback, prot, type);
- default:
- return -EINVAL;
- }
-}
-
-static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- enum mlx4_protocol prot, enum mlx4_steer_type type,
- u64 reg_id)
-{
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- return mlx4_flow_detach(dev, reg_id);
- case MLX4_STEERING_MODE_B0:
- return mlx4_qp_detach_common(dev, qp, gid, prot, type);
- default:
- return -EINVAL;
- }
-}
-
-int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- struct mlx4_qp qp; /* dummy for calling attach/detach */
- u8 *gid = inbox->buf;
- enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7;
- int err;
- int qpn;
- struct res_qp *rqp;
- u64 reg_id = 0;
- int attach = vhcr->op_modifier;
- int block_loopback = vhcr->in_modifier >> 31;
- u8 steer_type_mask = 2;
- enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
-
- qpn = vhcr->in_modifier & 0xffffff;
- err = get_res(dev, slave, qpn, RES_QP, &rqp);
- if (err)
- return err;
-
- qp.qpn = qpn;
- if (attach) {
- err = qp_attach(dev, &qp, gid, block_loopback, prot,
- type, &reg_id);
- if (err) {
- pr_err("Fail to attach rule to qp 0x%x\n", qpn);
- goto ex_put;
- }
- err = add_mcg_res(dev, slave, rqp, gid, prot, type, reg_id);
- if (err)
- goto ex_detach;
- } else {
- err = rem_mcg_res(dev, slave, rqp, gid, prot, type, &reg_id);
- if (err)
- goto ex_put;
-
- err = qp_detach(dev, &qp, gid, prot, type, reg_id);
- if (err)
- pr_err("Fail to detach rule from qp 0x%x reg_id = 0x%llx\n",
- qpn, (unsigned long long)reg_id);
- }
- put_res(dev, slave, qpn, RES_QP);
- return err;
-
-ex_detach:
- qp_detach(dev, &qp, gid, prot, type, reg_id);
-ex_put:
- put_res(dev, slave, qpn, RES_QP);
- return err;
-}
-
-/*
- * MAC validation for Flow Steering rules.
- * VF can attach rules only with a mac address which is assigned to it.
- */
-static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
- struct list_head *rlist)
-{
- struct mac_res *res, *tmp;
- __be64 be_mac;
-
- /* make sure it isn't multicast or broadcast mac*/
- if (!is_multicast_ether_addr(eth_header->eth.dst_mac) &&
- !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
- list_for_each_entry_safe(res, tmp, rlist, list) {
- be_mac = cpu_to_be64(res->mac << 16);
- if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN))
- return 0;
- }
- pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",
- eth_header->eth.dst_mac, slave);
- return -EINVAL;
- }
- return 0;
-}
-
-/*
- * In case of missing eth header, append eth header with a MAC address
- * assigned to the VF.
- */
-static int add_eth_header(struct mlx4_dev *dev, int slave,
- struct mlx4_cmd_mailbox *inbox,
- struct list_head *rlist, int header_id)
-{
- struct mac_res *res, *tmp;
- u8 port;
- struct mlx4_net_trans_rule_hw_ctrl *ctrl;
- struct mlx4_net_trans_rule_hw_eth *eth_header;
- struct mlx4_net_trans_rule_hw_ipv4 *ip_header;
- struct mlx4_net_trans_rule_hw_tcp_udp *l4_header;
- __be64 be_mac = 0;
- __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
-
- ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
- port = ctrl->port;
- eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1);
-
- /* Clear a space in the inbox for eth header */
- switch (header_id) {
- case MLX4_NET_TRANS_RULE_ID_IPV4:
- ip_header =
- (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1);
- memmove(ip_header, eth_header,
- sizeof(*ip_header) + sizeof(*l4_header));
- break;
- case MLX4_NET_TRANS_RULE_ID_TCP:
- case MLX4_NET_TRANS_RULE_ID_UDP:
- l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *)
- (eth_header + 1);
- memmove(l4_header, eth_header, sizeof(*l4_header));
- break;
- default:
- return -EINVAL;
- }
- list_for_each_entry_safe(res, tmp, rlist, list) {
- if (port == res->port) {
- be_mac = cpu_to_be64(res->mac << 16);
- break;
- }
- }
- if (!be_mac) {
- pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n",
- port);
- return -EINVAL;
- }
-
- memset(eth_header, 0, sizeof(*eth_header));
- eth_header->size = sizeof(*eth_header) >> 2;
- eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]);
- memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN);
- memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN);
-
- return 0;
-
-}
-
-int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
-
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
- int err;
- int qpn;
- struct res_qp *rqp;
- struct mlx4_net_trans_rule_hw_ctrl *ctrl;
- struct _rule_hw *rule_header;
- int header_id;
-
- if (dev->caps.steering_mode !=
- MLX4_STEERING_MODE_DEVICE_MANAGED)
- return -EOPNOTSUPP;
-
- ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
- qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
- err = get_res(dev, slave, qpn, RES_QP, &rqp);
- if (err) {
- pr_err("Steering rule with qpn 0x%x rejected.\n", qpn);
- return err;
- }
- rule_header = (struct _rule_hw *)(ctrl + 1);
- header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
-
- switch (header_id) {
- case MLX4_NET_TRANS_RULE_ID_ETH:
- if (validate_eth_header_mac(slave, rule_header, rlist)) {
- err = -EINVAL;
- goto err_put;
- }
- break;
- case MLX4_NET_TRANS_RULE_ID_IB:
- break;
- case MLX4_NET_TRANS_RULE_ID_IPV4:
- case MLX4_NET_TRANS_RULE_ID_TCP:
- case MLX4_NET_TRANS_RULE_ID_UDP:
- pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
- if (add_eth_header(dev, slave, inbox, rlist, header_id)) {
- err = -EINVAL;
- goto err_put;
- }
- vhcr->in_modifier +=
- sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
- break;
- default:
- pr_err("Corrupted mailbox.\n");
- err = -EINVAL;
- goto err_put;
- }
-
- err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
- vhcr->in_modifier, 0,
- MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err)
- goto err_put;
-
- err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn);
- if (err) {
- mlx4_err(dev, "Fail to add flow steering resources.\n ");
- /* detach rule*/
- mlx4_cmd(dev, vhcr->out_param, 0, 0,
- MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- goto err_put;
- }
- atomic_inc(&rqp->ref_count);
-err_put:
- put_res(dev, slave, qpn, RES_QP);
- return err;
-}
-
-int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
- struct res_qp *rqp;
- struct res_fs_rule *rrule;
-
- if (dev->caps.steering_mode !=
- MLX4_STEERING_MODE_DEVICE_MANAGED)
- return -EOPNOTSUPP;
-
- err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule);
- if (err)
- return err;
- /* Release the rule form busy state before removal */
- put_res(dev, slave, vhcr->in_param, RES_FS_RULE);
- err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp);
- if (err)
- return err;
-
- err = mlx4_cmd(dev, vhcr->in_param, 0, 0,
- MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (!err) {
- err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE,
- 0);
- atomic_dec(&rqp->ref_count);
-
- if (err) {
- mlx4_err(dev, "Fail to remove flow steering resources.\n ");
- goto out;
- }
- }
-
-out:
- put_res(dev, slave, rrule->qpn, RES_QP);
- return err;
-}
-
-enum {
- BUSY_MAX_RETRIES = 10
-};
-
-int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave,
- struct mlx4_vhcr *vhcr,
- struct mlx4_cmd_mailbox *inbox,
- struct mlx4_cmd_mailbox *outbox,
- struct mlx4_cmd_info *cmd)
-{
- int err;
-
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
-
- return err;
-}
-
-static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
-{
- struct res_gid *rgid;
- struct res_gid *tmp;
- struct mlx4_qp qp; /* dummy for calling attach/detach */
-
- list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_DEVICE_MANAGED:
- mlx4_flow_detach(dev, rgid->reg_id);
- break;
- case MLX4_STEERING_MODE_B0:
- qp.qpn = rqp->local_qpn;
- (void) mlx4_qp_detach_common(dev, &qp, rgid->gid,
- rgid->prot, rgid->steer);
- break;
- }
- list_del(&rgid->list);
- kfree(rgid);
- }
-}
-
-static int _move_all_busy(struct mlx4_dev *dev, int slave,
- enum mlx4_resource type, int print)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker =
- &priv->mfunc.master.res_tracker;
- struct list_head *rlist = &tracker->slave_list[slave].res_list[type];
- struct res_common *r;
- struct res_common *tmp;
- int busy;
-
- busy = 0;
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(r, tmp, rlist, list) {
- if (r->owner == slave) {
- if (!r->removing) {
- if (r->state == RES_ANY_BUSY) {
- if (print)
- mlx4_dbg(dev,
- "%s id 0x%llx is busy\n",
- ResourceType(type),
- (unsigned long long)r->res_id);
- ++busy;
- } else {
- r->from_state = r->state;
- r->state = RES_ANY_BUSY;
- r->removing = 1;
- }
- }
- }
- }
- spin_unlock_irq(mlx4_tlock(dev));
-
- return busy;
-}
-
-static int move_all_busy(struct mlx4_dev *dev, int slave,
- enum mlx4_resource type)
-{
- unsigned long begin;
- int busy;
-
- begin = jiffies;
- do {
- busy = _move_all_busy(dev, slave, type, 0);
- if (time_after(jiffies, begin + 5 * HZ))
- break;
- if (busy)
- cond_resched();
- } while (busy);
-
- if (busy)
- busy = _move_all_busy(dev, slave, type, 1);
-
- return busy;
-}
-static void rem_slave_qps(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *qp_list =
- &tracker->slave_list[slave].res_list[RES_QP];
- struct res_qp *qp;
- struct res_qp *tmp;
- int state;
- u64 in_param;
- int qpn;
- int err;
-
- err = move_all_busy(dev, slave, RES_QP);
- if (err)
- mlx4_warn(dev, "rem_slave_qps: Could not move all qps to busy"
- "for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (qp->com.owner == slave) {
- qpn = qp->com.res_id;
- detach_qp(dev, slave, qp);
- state = qp->com.from_state;
- while (state != 0) {
- switch (state) {
- case RES_QP_RESERVED:
- spin_lock_irq(mlx4_tlock(dev));
- rb_erase(&qp->com.node,
- &tracker->res_tree[RES_QP]);
- list_del(&qp->com.list);
- spin_unlock_irq(mlx4_tlock(dev));
- if (!valid_reserved(dev, slave, qpn)) {
- __mlx4_qp_release_range(dev, qpn, 1);
- mlx4_release_resource(dev, slave,
- RES_QP, 1, 0);
- }
- kfree(qp);
- state = 0;
- break;
- case RES_QP_MAPPED:
- if (!valid_reserved(dev, slave, qpn))
- __mlx4_qp_free_icm(dev, qpn);
- state = RES_QP_RESERVED;
- break;
- case RES_QP_HW:
- in_param = slave;
- err = mlx4_cmd(dev, in_param,
- qp->local_qpn, 2,
- MLX4_CMD_2RST_QP,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err)
- mlx4_dbg(dev, "rem_slave_qps: failed"
- " to move slave %d qpn %d to"
- " reset\n", slave,
- qp->local_qpn);
- atomic_dec(&qp->rcq->ref_count);
- atomic_dec(&qp->scq->ref_count);
- atomic_dec(&qp->mtt->ref_count);
- if (qp->srq)
- atomic_dec(&qp->srq->ref_count);
- state = RES_QP_MAPPED;
- break;
- default:
- state = 0;
- }
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void rem_slave_srqs(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *srq_list =
- &tracker->slave_list[slave].res_list[RES_SRQ];
- struct res_srq *srq;
- struct res_srq *tmp;
- int state;
- u64 in_param;
- LIST_HEAD(tlist);
- int srqn;
- int err;
-
- err = move_all_busy(dev, slave, RES_SRQ);
- if (err)
- mlx4_warn(dev, "rem_slave_srqs: Could not move all srqs to "
- "busy for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(srq, tmp, srq_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (srq->com.owner == slave) {
- srqn = srq->com.res_id;
- state = srq->com.from_state;
- while (state != 0) {
- switch (state) {
- case RES_SRQ_ALLOCATED:
- __mlx4_srq_free_icm(dev, srqn);
- spin_lock_irq(mlx4_tlock(dev));
- rb_erase(&srq->com.node,
- &tracker->res_tree[RES_SRQ]);
- list_del(&srq->com.list);
- spin_unlock_irq(mlx4_tlock(dev));
- mlx4_release_resource(dev, slave,
- RES_SRQ, 1, 0);
- kfree(srq);
- state = 0;
- break;
-
- case RES_SRQ_HW:
- in_param = slave;
- err = mlx4_cmd(dev, in_param, srqn, 1,
- MLX4_CMD_HW2SW_SRQ,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err)
- mlx4_dbg(dev, "rem_slave_srqs: failed"
- " to move slave %d srq %d to"
- " SW ownership\n",
- slave, srqn);
-
- atomic_dec(&srq->mtt->ref_count);
- if (srq->cq)
- atomic_dec(&srq->cq->ref_count);
- state = RES_SRQ_ALLOCATED;
- break;
-
- default:
- state = 0;
- }
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void rem_slave_cqs(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *cq_list =
- &tracker->slave_list[slave].res_list[RES_CQ];
- struct res_cq *cq;
- struct res_cq *tmp;
- int state;
- u64 in_param;
- LIST_HEAD(tlist);
- int cqn;
- int err;
-
- err = move_all_busy(dev, slave, RES_CQ);
- if (err)
- mlx4_warn(dev, "rem_slave_cqs: Could not move all cqs to "
- "busy for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(cq, tmp, cq_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (cq->com.owner == slave && !atomic_read(&cq->ref_count)) {
- cqn = cq->com.res_id;
- state = cq->com.from_state;
- while (state != 0) {
- switch (state) {
- case RES_CQ_ALLOCATED:
- __mlx4_cq_free_icm(dev, cqn);
- spin_lock_irq(mlx4_tlock(dev));
- rb_erase(&cq->com.node,
- &tracker->res_tree[RES_CQ]);
- list_del(&cq->com.list);
- spin_unlock_irq(mlx4_tlock(dev));
- mlx4_release_resource(dev, slave,
- RES_CQ, 1, 0);
- kfree(cq);
- state = 0;
- break;
-
- case RES_CQ_HW:
- in_param = slave;
- err = mlx4_cmd(dev, in_param, cqn, 1,
- MLX4_CMD_HW2SW_CQ,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err)
- mlx4_dbg(dev, "rem_slave_cqs: failed"
- " to move slave %d cq %d to"
- " SW ownership\n",
- slave, cqn);
- atomic_dec(&cq->mtt->ref_count);
- state = RES_CQ_ALLOCATED;
- break;
-
- default:
- state = 0;
- }
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void rem_slave_mrs(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *mpt_list =
- &tracker->slave_list[slave].res_list[RES_MPT];
- struct res_mpt *mpt;
- struct res_mpt *tmp;
- int state;
- u64 in_param;
- LIST_HEAD(tlist);
- int mptn;
- int err;
-
- err = move_all_busy(dev, slave, RES_MPT);
- if (err)
- mlx4_warn(dev, "rem_slave_mrs: Could not move all mpts to "
- "busy for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(mpt, tmp, mpt_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (mpt->com.owner == slave) {
- mptn = mpt->com.res_id;
- state = mpt->com.from_state;
- while (state != 0) {
- switch (state) {
- case RES_MPT_RESERVED:
- __mlx4_mpt_release(dev, mpt->key);
- spin_lock_irq(mlx4_tlock(dev));
- rb_erase(&mpt->com.node,
- &tracker->res_tree[RES_MPT]);
- list_del(&mpt->com.list);
- spin_unlock_irq(mlx4_tlock(dev));
- mlx4_release_resource(dev, slave,
- RES_MPT, 1, 0);
- kfree(mpt);
- state = 0;
- break;
-
- case RES_MPT_MAPPED:
- __mlx4_mpt_free_icm(dev, mpt->key);
- state = RES_MPT_RESERVED;
- break;
-
- case RES_MPT_HW:
- in_param = slave;
- err = mlx4_cmd(dev, in_param, mptn, 0,
- MLX4_CMD_HW2SW_MPT,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err)
- mlx4_dbg(dev, "rem_slave_mrs: failed"
- " to move slave %d mpt %d to"
- " SW ownership\n",
- slave, mptn);
- if (mpt->mtt)
- atomic_dec(&mpt->mtt->ref_count);
- state = RES_MPT_MAPPED;
- break;
- default:
- state = 0;
- }
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void rem_slave_mtts(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker =
- &priv->mfunc.master.res_tracker;
- struct list_head *mtt_list =
- &tracker->slave_list[slave].res_list[RES_MTT];
- struct res_mtt *mtt;
- struct res_mtt *tmp;
- int state;
- LIST_HEAD(tlist);
- int base;
- int err;
-
- err = move_all_busy(dev, slave, RES_MTT);
- if (err)
- mlx4_warn(dev, "rem_slave_mtts: Could not move all mtts to "
- "busy for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(mtt, tmp, mtt_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (mtt->com.owner == slave) {
- base = mtt->com.res_id;
- state = mtt->com.from_state;
- while (state != 0) {
- switch (state) {
- case RES_MTT_ALLOCATED:
- __mlx4_free_mtt_range(dev, base,
- mtt->order);
- spin_lock_irq(mlx4_tlock(dev));
- rb_erase(&mtt->com.node,
- &tracker->res_tree[RES_MTT]);
- list_del(&mtt->com.list);
- spin_unlock_irq(mlx4_tlock(dev));
- mlx4_release_resource(dev, slave, RES_MTT,
- 1 << mtt->order, 0);
- kfree(mtt);
- state = 0;
- break;
-
- default:
- state = 0;
- }
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void rem_slave_fs_rule(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker =
- &priv->mfunc.master.res_tracker;
- struct list_head *fs_rule_list =
- &tracker->slave_list[slave].res_list[RES_FS_RULE];
- struct res_fs_rule *fs_rule;
- struct res_fs_rule *tmp;
- int state;
- u64 base;
- int err;
-
- err = move_all_busy(dev, slave, RES_FS_RULE);
- if (err)
- mlx4_warn(dev, "rem_slave_fs_rule: Could not move all mtts to busy for slave %d\n",
- slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(fs_rule, tmp, fs_rule_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (fs_rule->com.owner == slave) {
- base = fs_rule->com.res_id;
- state = fs_rule->com.from_state;
- while (state != 0) {
- switch (state) {
- case RES_FS_RULE_ALLOCATED:
- /* detach rule */
- err = mlx4_cmd(dev, base, 0, 0,
- MLX4_QP_FLOW_STEERING_DETACH,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
-
- spin_lock_irq(mlx4_tlock(dev));
- rb_erase(&fs_rule->com.node,
- &tracker->res_tree[RES_FS_RULE]);
- list_del(&fs_rule->com.list);
- spin_unlock_irq(mlx4_tlock(dev));
- kfree(fs_rule);
- state = 0;
- break;
-
- default:
- state = 0;
- }
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void rem_slave_eqs(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *eq_list =
- &tracker->slave_list[slave].res_list[RES_EQ];
- struct res_eq *eq;
- struct res_eq *tmp;
- int err;
- int state;
- LIST_HEAD(tlist);
- int eqn;
- struct mlx4_cmd_mailbox *mailbox;
-
- err = move_all_busy(dev, slave, RES_EQ);
- if (err)
- mlx4_warn(dev, "rem_slave_eqs: Could not move all eqs to "
- "busy for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(eq, tmp, eq_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (eq->com.owner == slave) {
- eqn = eq->com.res_id;
- state = eq->com.from_state;
- while (state != 0) {
- switch (state) {
- case RES_EQ_RESERVED:
- spin_lock_irq(mlx4_tlock(dev));
- rb_erase(&eq->com.node,
- &tracker->res_tree[RES_EQ]);
- list_del(&eq->com.list);
- spin_unlock_irq(mlx4_tlock(dev));
- kfree(eq);
- state = 0;
- break;
-
- case RES_EQ_HW:
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- cond_resched();
- continue;
- }
- err = mlx4_cmd_box(dev, slave, 0,
- eqn & 0xff, 0,
- MLX4_CMD_HW2SW_EQ,
- MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_NATIVE);
- if (err)
- mlx4_dbg(dev, "rem_slave_eqs: failed"
- " to move slave %d eqs %d to"
- " SW ownership\n", slave, eqn);
- mlx4_free_cmd_mailbox(dev, mailbox);
- atomic_dec(&eq->mtt->ref_count);
- state = RES_EQ_RESERVED;
- break;
-
- default:
- state = 0;
- }
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-static void rem_slave_counters(struct mlx4_dev *dev, int slave)
-{
- __mlx4_slave_counters_free(dev, slave);
-}
-
-static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *xrcdn_list =
- &tracker->slave_list[slave].res_list[RES_XRCD];
- struct res_xrcdn *xrcd;
- struct res_xrcdn *tmp;
- int err;
- int xrcdn;
-
- err = move_all_busy(dev, slave, RES_XRCD);
- if (err)
- mlx4_warn(dev, "rem_slave_xrcdns: Could not move all xrcdns to "
- "busy for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) {
- if (xrcd->com.owner == slave) {
- xrcdn = xrcd->com.res_id;
- rb_erase(&xrcd->com.node, &tracker->res_tree[RES_XRCD]);
- list_del(&xrcd->com.list);
- kfree(xrcd);
- __mlx4_xrcd_free(dev, xrcdn);
- }
- }
- spin_unlock_irq(mlx4_tlock(dev));
-}
-
-void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
-
- mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
- rem_slave_macs(dev, slave);
- rem_slave_vlans(dev, slave);
- rem_slave_fs_rule(dev, slave);
- rem_slave_qps(dev, slave);
- rem_slave_srqs(dev, slave);
- rem_slave_cqs(dev, slave);
- rem_slave_mrs(dev, slave);
- rem_slave_eqs(dev, slave);
- rem_slave_mtts(dev, slave);
- rem_slave_counters(dev, slave);
- rem_slave_xrcdns(dev, slave);
- mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
-}
-
-void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
-{
- struct mlx4_vf_immed_vlan_work *work =
- container_of(_work, struct mlx4_vf_immed_vlan_work, work);
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_update_qp_context *upd_context;
- struct mlx4_dev *dev = &work->priv->dev;
- struct mlx4_resource_tracker *tracker =
- &work->priv->mfunc.master.res_tracker;
- struct list_head *qp_list =
- &tracker->slave_list[work->slave].res_list[RES_QP];
- struct res_qp *qp;
- struct res_qp *tmp;
- u64 qp_path_mask_vlan_ctrl =
- ((1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_UNTAGGED) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_1P) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_TAGGED) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_UNTAGGED) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_1P) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_TAGGED));
-
- u64 qp_path_mask = ((1ULL << MLX4_UPD_QP_PATH_MASK_VLAN_INDEX) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_FVL) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_CV) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_HIDE_CQE_VLAN) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_FEUP) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_FVL_RX) |
- (1ULL << MLX4_UPD_QP_PATH_MASK_SCHED_QUEUE));
-
- int err;
- int port, errors = 0;
- u8 vlan_control;
-
- if (mlx4_is_slave(dev)) {
- mlx4_warn(dev, "Trying to update-qp in slave %d\n",
- work->slave);
- goto out;
- }
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- goto out;
-
- if (!work->vlan_id)
- vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
- MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
- else
- vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
- MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
- MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
-
- upd_context = mailbox->buf;
- upd_context->qp_mask = cpu_to_be64(MLX4_UPD_QP_MASK_VSD);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
- spin_unlock_irq(mlx4_tlock(dev));
- if (qp->com.owner == work->slave) {
- if (qp->com.from_state != RES_QP_HW ||
- !qp->sched_queue || /* no INIT2RTR trans yet */
- mlx4_is_qp_reserved(dev, qp->local_qpn) ||
- qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)) {
- spin_lock_irq(mlx4_tlock(dev));
- continue;
- }
- port = (qp->sched_queue >> 6 & 1) + 1;
- if (port != work->port) {
- spin_lock_irq(mlx4_tlock(dev));
- continue;
- }
- if (MLX4_QP_ST_RC == ((qp->qpc_flags >> 16) & 0xff))
- upd_context->primary_addr_path_mask = cpu_to_be64(qp_path_mask);
- else
- upd_context->primary_addr_path_mask =
- cpu_to_be64(qp_path_mask | qp_path_mask_vlan_ctrl);
- if (work->vlan_id == MLX4_VGT) {
- upd_context->qp_context.param3 = qp->param3;
- upd_context->qp_context.pri_path.vlan_control = qp->vlan_control;
- upd_context->qp_context.pri_path.fvl_rx = qp->fvl_rx;
- upd_context->qp_context.pri_path.vlan_index = qp->vlan_index;
- upd_context->qp_context.pri_path.fl = qp->pri_path_fl;
- upd_context->qp_context.pri_path.feup = qp->feup;
- upd_context->qp_context.pri_path.sched_queue =
- qp->sched_queue;
- } else {
- upd_context->qp_context.param3 = qp->param3 & ~cpu_to_be32(MLX4_STRIP_VLAN);
- upd_context->qp_context.pri_path.vlan_control = vlan_control;
- upd_context->qp_context.pri_path.vlan_index = work->vlan_ix;
- upd_context->qp_context.pri_path.fvl_rx =
- qp->fvl_rx | MLX4_FVL_RX_FORCE_ETH_VLAN;
- upd_context->qp_context.pri_path.fl =
- qp->pri_path_fl | MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN;
- upd_context->qp_context.pri_path.feup =
- qp->feup | MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;
- upd_context->qp_context.pri_path.sched_queue =
- qp->sched_queue & 0xC7;
- upd_context->qp_context.pri_path.sched_queue |=
- ((work->qos & 0x7) << 3);
- }
-
- err = mlx4_cmd(dev, mailbox->dma,
- qp->local_qpn & 0xffffff,
- 0, MLX4_CMD_UPDATE_QP,
- MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
- if (err) {
- mlx4_info(dev, "UPDATE_QP failed for slave %d, "
- "port %d, qpn %d (%d)\n",
- work->slave, port, qp->local_qpn,
- err);
- errors++;
- }
- }
- spin_lock_irq(mlx4_tlock(dev));
- }
- spin_unlock_irq(mlx4_tlock(dev));
- mlx4_free_cmd_mailbox(dev, mailbox);
-
- if (errors)
- mlx4_err(dev, "%d UPDATE_QP failures for slave %d, port %d\n",
- errors, work->slave, work->port);
-
- /* unregister previous vlan_id if needed and we had no errors
- * while updating the QPs
- */
- if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN && !errors &&
- NO_INDX != work->orig_vlan_ix)
- __mlx4_unregister_vlan(&work->priv->dev, work->port,
- work->orig_vlan_id);
-out:
- kfree(work);
- return;
-}
-
diff --git a/sys/ofed/drivers/net/mlx4/sense.c b/sys/ofed/drivers/net/mlx4/sense.c
deleted file mode 100644
index 3615e6513e9f..000000000000
--- a/sys/ofed/drivers/net/mlx4/sense.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2007, 2014 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.
- *
- */
-
-#include <linux/errno.h>
-#include <linux/if_ether.h>
-
-#include <linux/mlx4/cmd.h>
-
-#include "mlx4.h"
-
-int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
- enum mlx4_port_type *type)
-{
- u64 out_param;
- int err = 0;
-
- err = mlx4_cmd_imm(dev, 0, &out_param, port, 0,
- MLX4_CMD_SENSE_PORT, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_WRAPPED);
- if (err) {
- mlx4_err(dev, "Sense command failed for port: %d\n", port);
- return err;
- }
-
- if (out_param > 2) {
- mlx4_err(dev, "Sense returned illegal value: 0x%llx\n", (unsigned long long)out_param);
- return -EINVAL;
- }
-
- *type = out_param;
- return 0;
-}
-
-void mlx4_do_sense_ports(struct mlx4_dev *dev,
- enum mlx4_port_type *stype,
- enum mlx4_port_type *defaults)
-{
- struct mlx4_sense *sense = &mlx4_priv(dev)->sense;
- int err;
- int i;
-
- for (i = 1; i <= dev->caps.num_ports; i++) {
- stype[i - 1] = 0;
- if (sense->do_sense_port[i] && sense->sense_allowed[i] &&
- dev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) {
- err = mlx4_SENSE_PORT(dev, i, &stype[i - 1]);
- if (err)
- stype[i - 1] = defaults[i - 1];
- } else
- stype[i - 1] = defaults[i - 1];
- }
-
- /*
- * If sensed nothing, remain in current configuration.
- */
- for (i = 0; i < dev->caps.num_ports; i++)
- stype[i] = stype[i] ? stype[i] : defaults[i];
-
-}
-
-static void mlx4_sense_port(struct work_struct *work)
-{
- struct delayed_work *delay = to_delayed_work(work);
- struct mlx4_sense *sense = container_of(delay, struct mlx4_sense,
- sense_poll);
- struct mlx4_dev *dev = sense->dev;
- struct mlx4_priv *priv = mlx4_priv(dev);
- enum mlx4_port_type stype[MLX4_MAX_PORTS];
-
- mutex_lock(&priv->port_mutex);
- mlx4_do_sense_ports(dev, stype, &dev->caps.port_type[1]);
-
- if (mlx4_check_port_params(dev, stype))
- goto sense_again;
-
- if (mlx4_change_port_types(dev, stype))
- mlx4_err(dev, "Failed to change port_types\n");
-
-sense_again:
- mutex_unlock(&priv->port_mutex);
- queue_delayed_work(mlx4_wq , &sense->sense_poll,
- round_jiffies_relative(MLX4_SENSE_RANGE));
-}
-
-void mlx4_start_sense(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_sense *sense = &priv->sense;
-
- if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP))
- return;
-
- queue_delayed_work(mlx4_wq , &sense->sense_poll,
- round_jiffies_relative(MLX4_SENSE_RANGE));
-}
-
-void mlx4_stop_sense(struct mlx4_dev *dev)
-{
- cancel_delayed_work_sync(&mlx4_priv(dev)->sense.sense_poll);
-}
-
-void mlx4_sense_init(struct mlx4_dev *dev)
-{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_sense *sense = &priv->sense;
- int port;
-
- sense->dev = dev;
- for (port = 1; port <= dev->caps.num_ports; port++)
- sense->do_sense_port[port] = 1;
-
- INIT_DEFERRABLE_WORK(&sense->sense_poll, mlx4_sense_port);
-}
diff --git a/sys/ofed/drivers/net/mlx4/srq.c b/sys/ofed/drivers/net/mlx4/srq.c
deleted file mode 100644
index fcb6255c7e62..000000000000
--- a/sys/ofed/drivers/net/mlx4/srq.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008, 2014 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.
- */
-
-#include <linux/mlx4/cmd.h>
-#include <linux/mlx4/srq.h>
-#include <linux/module.h>
-#include <linux/gfp.h>
-
-#include "mlx4.h"
-#include "icm.h"
-
-void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
-{
- struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
- struct mlx4_srq *srq;
-
- spin_lock(&srq_table->lock);
-
- srq = radix_tree_lookup(&srq_table->tree, srqn & (dev->caps.num_srqs - 1));
- if (srq)
- atomic_inc(&srq->refcount);
-
- spin_unlock(&srq_table->lock);
-
- if (!srq) {
- mlx4_warn(dev, "Async event for bogus SRQ %08x\n", srqn);
- return;
- }
-
- srq->event(srq, event_type);
-
- if (atomic_dec_and_test(&srq->refcount))
- complete(&srq->free);
-}
-
-static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int srq_num)
-{
- return mlx4_cmd(dev, mailbox->dma, srq_num, 0,
- MLX4_CMD_SW2HW_SRQ, MLX4_CMD_TIME_CLASS_A,
- MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_HW2SW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int srq_num)
-{
- return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, srq_num,
- mailbox ? 0 : 1, MLX4_CMD_HW2SW_SRQ,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark)
-{
- return mlx4_cmd(dev, limit_watermark, srq_num, 0, MLX4_CMD_ARM_SRQ,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
-}
-
-static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
- int srq_num)
-{
- return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
-}
-
-int __mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn)
-{
- struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
- int err;
-
-
- *srqn = mlx4_bitmap_alloc(&srq_table->bitmap);
- if (*srqn == -1)
- return -ENOMEM;
-
- err = mlx4_table_get(dev, &srq_table->table, *srqn);
- if (err)
- goto err_out;
-
- err = mlx4_table_get(dev, &srq_table->cmpt_table, *srqn);
- if (err)
- goto err_put;
- return 0;
-
-err_put:
- mlx4_table_put(dev, &srq_table->table, *srqn);
-
-err_out:
- mlx4_bitmap_free(&srq_table->bitmap, *srqn, MLX4_NO_RR);
- return err;
-}
-
-static int mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn)
-{
- u64 out_param;
- int err;
-
- if (mlx4_is_mfunc(dev)) {
- err = mlx4_cmd_imm(dev, 0, &out_param, RES_SRQ,
- RES_OP_RESERVE_AND_MAP,
- MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (!err)
- *srqn = get_param_l(&out_param);
-
- return err;
- }
- return __mlx4_srq_alloc_icm(dev, srqn);
-}
-
-void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
-{
- struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
-
- mlx4_table_put(dev, &srq_table->cmpt_table, srqn);
- mlx4_table_put(dev, &srq_table->table, srqn);
- mlx4_bitmap_free(&srq_table->bitmap, srqn, MLX4_NO_RR);
-}
-
-static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
-{
- u64 in_param = 0;
-
- if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, srqn);
- if (mlx4_cmd(dev, in_param, RES_SRQ, RES_OP_RESERVE_AND_MAP,
- MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED))
- mlx4_warn(dev, "Failed freeing cq:%d\n", srqn);
- return;
- }
- __mlx4_srq_free_icm(dev, srqn);
-}
-
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
- struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq)
-{
- struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_srq_context *srq_context;
- u64 mtt_addr;
- int err;
-
- err = mlx4_srq_alloc_icm(dev, &srq->srqn);
- if (err)
- return err;
-
- spin_lock_irq(&srq_table->lock);
- err = radix_tree_insert(&srq_table->tree, srq->srqn, srq);
- spin_unlock_irq(&srq_table->lock);
- if (err)
- goto err_icm;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- goto err_radix;
- }
-
- srq_context = mailbox->buf;
- memset(srq_context, 0, sizeof *srq_context);
-
- srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) |
- srq->srqn);
- srq_context->logstride = srq->wqe_shift - 4;
- srq_context->xrcd = cpu_to_be16(xrcd);
- srq_context->pg_offset_cqn = cpu_to_be32(cqn & 0xffffff);
- srq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
-
- mtt_addr = mlx4_mtt_addr(dev, mtt);
- srq_context->mtt_base_addr_h = mtt_addr >> 32;
- srq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
- srq_context->pd = cpu_to_be32(pdn);
- srq_context->db_rec_addr = cpu_to_be64(db_rec);
-
- err = mlx4_SW2HW_SRQ(dev, mailbox, srq->srqn);
- mlx4_free_cmd_mailbox(dev, mailbox);
- if (err)
- goto err_radix;
-
- atomic_set(&srq->refcount, 1);
- init_completion(&srq->free);
-
- return 0;
-
-err_radix:
- spin_lock_irq(&srq_table->lock);
- radix_tree_delete(&srq_table->tree, srq->srqn);
- spin_unlock_irq(&srq_table->lock);
-
-err_icm:
- mlx4_srq_free_icm(dev, srq->srqn);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_srq_alloc);
-
-void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq)
-{
- struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
- int err;
-
- err = mlx4_HW2SW_SRQ(dev, NULL, srq->srqn);
- if (err)
- mlx4_warn(dev, "HW2SW_SRQ failed (%d) for SRQN %06x\n", err, srq->srqn);
-
- spin_lock_irq(&srq_table->lock);
- radix_tree_delete(&srq_table->tree, srq->srqn);
- spin_unlock_irq(&srq_table->lock);
-
- if (atomic_dec_and_test(&srq->refcount))
- complete(&srq->free);
- wait_for_completion(&srq->free);
-
- mlx4_srq_free_icm(dev, srq->srqn);
-}
-EXPORT_SYMBOL_GPL(mlx4_srq_free);
-
-int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark)
-{
- return mlx4_ARM_SRQ(dev, srq->srqn, limit_watermark);
-}
-EXPORT_SYMBOL_GPL(mlx4_srq_arm);
-
-int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_srq_context *srq_context;
- int err;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
-
- srq_context = mailbox->buf;
-
- err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn);
- if (err)
- goto err_out;
- *limit_watermark = be16_to_cpu(srq_context->limit_watermark);
-
-err_out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-EXPORT_SYMBOL_GPL(mlx4_srq_query);
-
-int mlx4_init_srq_table(struct mlx4_dev *dev)
-{
- struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
- int err;
-
- spin_lock_init(&srq_table->lock);
- INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC);
- if (mlx4_is_slave(dev))
- return 0;
-
- err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs,
- dev->caps.num_srqs - 1, dev->caps.reserved_srqs, 0);
- if (err)
- return err;
-
- return 0;
-}
-
-void mlx4_cleanup_srq_table(struct mlx4_dev *dev)
-{
- if (mlx4_is_slave(dev))
- return;
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap);
-}
-
-struct mlx4_srq *mlx4_srq_lookup(struct mlx4_dev *dev, u32 srqn)
-{
- struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
- struct mlx4_srq *srq;
- unsigned long flags;
-
- spin_lock_irqsave(&srq_table->lock, flags);
- srq = radix_tree_lookup(&srq_table->tree,
- srqn & (dev->caps.num_srqs - 1));
- spin_unlock_irqrestore(&srq_table->lock, flags);
-
- return srq;
-}
-EXPORT_SYMBOL_GPL(mlx4_srq_lookup);
diff --git a/sys/ofed/drivers/net/mlx4/sys_tune.c b/sys/ofed/drivers/net/mlx4/sys_tune.c
deleted file mode 100644
index 87eb30e6ccfe..000000000000
--- a/sys/ofed/drivers/net/mlx4/sys_tune.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2010, 2014 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.
- *
- */
-
-#include <linux/sched.h>
-#include <linux/mutex.h>
-#include <asm/atomic.h>
-
-#include "mlx4.h"
-
-#if defined(CONFIG_X86) && defined(CONFIG_APM_MODULE)
-
-/* Each CPU is put into a group. In most cases, the group number is
- * equal to the CPU number of one of the CPUs in the group. The
- * exception is group NR_CPUS which is the default group. This is
- * protected by sys_tune_startup_mutex. */
-DEFINE_PER_CPU(int, idle_cpu_group) = NR_CPUS;
-
-/* For each group, a count of the number of CPUs in the group which
- * are known to be busy. A busy CPU might be running the busy loop
- * below or general kernel code. The count is decremented on entry to
- * the old pm_idle handler and incremented on exit. The aim is to
- * avoid the count going to zero or negative. This situation can
- * occur temporarily during module unload or CPU hot-plug but
- * normality will be restored when the affected CPUs next exit the
- * idle loop. */
-static atomic_t busy_cpu_count[NR_CPUS+1];
-
-/* A workqueue item to be executed to cause the CPU to exit from the
- * idle loop. */
-DEFINE_PER_CPU(struct work_struct, sys_tune_cpu_work);
-
-#define sys_tune_set_state(CPU,STATE) \
- do { } while(0)
-
-
-/* A mutex to protect most of the module datastructures. */
-static DEFINE_MUTEX(sys_tune_startup_mutex);
-
-/* The old pm_idle handler. */
-static void (*old_pm_idle)(void) = NULL;
-
-static void sys_tune_pm_idle(void)
-{
- atomic_t *busy_cpus_ptr;
- int busy_cpus;
- int cpu = smp_processor_id();
-
- busy_cpus_ptr = &(busy_cpu_count[per_cpu(idle_cpu_group, cpu)]);
-
- sys_tune_set_state(cpu, 2);
-
- local_irq_enable();
- while (!need_resched()) {
- busy_cpus = atomic_read(busy_cpus_ptr);
-
- /* If other CPUs in this group are busy then let this
- * CPU go idle. We mustn't let the number of busy
- * CPUs drop below 1. */
- if ( busy_cpus > 1 &&
- old_pm_idle != NULL &&
- ( atomic_cmpxchg(busy_cpus_ptr, busy_cpus,
- busy_cpus-1) == busy_cpus ) ) {
- local_irq_disable();
- sys_tune_set_state(cpu, 3);
- /* This check might not be necessary, but it
- * seems safest to include it because there
- * might be a kernel version which requires
- * it. */
- if (need_resched())
- local_irq_enable();
- else
- old_pm_idle();
- /* This CPU is busy again. */
- sys_tune_set_state(cpu, 1);
- atomic_add(1, busy_cpus_ptr);
- return;
- }
-
- cpu_relax();
- }
- sys_tune_set_state(cpu, 0);
-}
-
-
-void sys_tune_work_func(struct work_struct *work)
-{
- /* Do nothing. Since this function is running in process
- * context, the idle thread isn't running on this CPU. */
-}
-
-
-#ifdef CONFIG_SMP
-static void sys_tune_smp_call(void *info)
-{
- schedule_work(&get_cpu_var(sys_tune_cpu_work));
- put_cpu_var(sys_tune_cpu_work);
-}
-#endif
-
-
-#ifdef CONFIG_SMP
-static void sys_tune_refresh(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
- on_each_cpu(&sys_tune_smp_call, NULL, 0, 1);
-#else
- on_each_cpu(&sys_tune_smp_call, NULL, 1);
-#endif
-}
-#else
-static void sys_tune_refresh(void)
-{
- /* The current thread is executing on the one and only CPU so
- * the idle thread isn't running. */
-}
-#endif
-
-
-
-static int sys_tune_cpu_group(int cpu)
-{
-#ifdef CONFIG_SMP
- const cpumask_t *mask;
- int other_cpu;
- int group;
-
-#if defined(topology_thread_cpumask) && defined(ST_HAVE_EXPORTED_CPU_SIBLING_MAP)
- /* Keep one hyperthread busy per core. */
- mask = topology_thread_cpumask(cpu);
-#else
- return cpu;
-#endif
- for_each_cpu_mask(cpu, *(mask)) {
- group = per_cpu(idle_cpu_group, other_cpu);
- if (group != NR_CPUS)
- return group;
- }
-#endif
-
- return cpu;
-}
-
-
-static void sys_tune_add_cpu(int cpu)
-{
- int group;
-
- /* Do nothing if this CPU has already been added. */
- if (per_cpu(idle_cpu_group, cpu) != NR_CPUS)
- return;
-
- group = sys_tune_cpu_group(cpu);
- per_cpu(idle_cpu_group, cpu) = group;
- atomic_inc(&(busy_cpu_count[group]));
-
-}
-
-static void sys_tune_del_cpu(int cpu)
-{
-
- int group;
-
- if (per_cpu(idle_cpu_group, cpu) == NR_CPUS)
- return;
-
- group = per_cpu(idle_cpu_group, cpu);
- /* If the CPU was busy, this can cause the count to drop to
- * zero. To rectify this, we need to cause one of the other
- * CPUs in the group to exit the idle loop. If the CPU was
- * not busy then this causes the contribution for this CPU to
- * go to -1 which can cause the overall count to drop to zero
- * or go negative. To rectify this situation we need to cause
- * this CPU to exit the idle loop. */
- atomic_dec(&(busy_cpu_count[group]));
- per_cpu(idle_cpu_group, cpu) = NR_CPUS;
-
-}
-
-
-static int sys_tune_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
-{
- int cpu = (long)hcpu;
-
- switch(action) {
-#ifdef CPU_ONLINE_FROZEN
- case CPU_ONLINE_FROZEN:
-#endif
- case CPU_ONLINE:
- mutex_lock(&sys_tune_startup_mutex);
- sys_tune_add_cpu(cpu);
- mutex_unlock(&sys_tune_startup_mutex);
- /* The CPU might have already entered the idle loop in
- * the wrong group. Make sure it exits the idle loop
- * so that it picks up the correct group. */
- sys_tune_refresh();
- break;
-
-#ifdef CPU_DEAD_FROZEN
- case CPU_DEAD_FROZEN:
-#endif
- case CPU_DEAD:
- mutex_lock(&sys_tune_startup_mutex);
- sys_tune_del_cpu(cpu);
- mutex_unlock(&sys_tune_startup_mutex);
- /* The deleted CPU may have been the only busy CPU in
- * the group. Make sure one of the other CPUs in the
- * group exits the idle loop. */
- sys_tune_refresh();
- break;
- }
- return NOTIFY_OK;
-}
-
-
-static struct notifier_block sys_tune_cpu_nb = {
- .notifier_call = sys_tune_cpu_notify,
-};
-
-
-static void sys_tune_ensure_init(void)
-{
- BUG_ON (old_pm_idle != NULL);
-
- /* Atomically update pm_idle to &sys_tune_pm_idle. The old value
- * is stored in old_pm_idle before installing the new
- * handler. */
- do {
- old_pm_idle = pm_idle;
- } while (cmpxchg(&pm_idle, old_pm_idle, &sys_tune_pm_idle) !=
- old_pm_idle);
-}
-#endif
-
-void sys_tune_fini(void)
-{
-#if defined(CONFIG_X86) && defined(CONFIG_APM_MODULE)
- void (*old)(void);
- int cpu;
-
- unregister_cpu_notifier(&sys_tune_cpu_nb);
-
- mutex_lock(&sys_tune_startup_mutex);
-
-
- old = cmpxchg(&pm_idle, &sys_tune_pm_idle, old_pm_idle);
-
- for_each_online_cpu(cpu)
- sys_tune_del_cpu(cpu);
-
- mutex_unlock(&sys_tune_startup_mutex);
-
- /* Our handler may still be executing on other CPUs.
- * Schedule this thread on all CPUs to make sure all
- * idle threads get interrupted. */
- sys_tune_refresh();
-
- /* Make sure the work item has finished executing on all CPUs.
- * This in turn ensures that all idle threads have been
- * interrupted. */
- flush_scheduled_work();
-#endif /* CONFIG_X86 */
-}
-
-void sys_tune_init(void)
-{
-#if defined(CONFIG_X86) && defined(CONFIG_APM_MODULE)
- int cpu;
-
- for_each_possible_cpu(cpu) {
- INIT_WORK(&per_cpu(sys_tune_cpu_work, cpu),
- sys_tune_work_func);
- }
-
- /* Start by registering the handler to ensure we don't miss
- * any updates. */
- register_cpu_notifier(&sys_tune_cpu_nb);
-
- mutex_lock(&sys_tune_startup_mutex);
-
- for_each_online_cpu(cpu)
- sys_tune_add_cpu(cpu);
-
- sys_tune_ensure_init();
-
-
- mutex_unlock(&sys_tune_startup_mutex);
-
- /* Ensure our idle handler starts to run. */
- sys_tune_refresh();
-#endif
-}
-