linux/drivers/net/ethernet/emulex/benet/be_roce.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2005 - 2016 Broadcom
   4 * All rights reserved.
   5 *
   6 * Contact Information:
   7 * linux-drivers@emulex.com
   8 *
   9 * Emulex
  10 * 3333 Susan Street
  11 * Costa Mesa, CA 92626
  12 */
  13
  14#include <linux/mutex.h>
  15#include <linux/list.h>
  16#include <linux/netdevice.h>
  17#include <linux/module.h>
  18
  19#include "be.h"
  20#include "be_cmds.h"
  21
  22static struct ocrdma_driver *ocrdma_drv;
  23static LIST_HEAD(be_adapter_list);
  24static DEFINE_MUTEX(be_adapter_list_lock);
  25
  26static void _be_roce_dev_add(struct be_adapter *adapter)
  27{
  28        struct be_dev_info dev_info;
  29        int i, num_vec;
  30        struct pci_dev *pdev = adapter->pdev;
  31
  32        if (!ocrdma_drv)
  33                return;
  34
  35        if (ocrdma_drv->be_abi_version != BE_ROCE_ABI_VERSION) {
  36                dev_warn(&pdev->dev, "Cannot initialize RoCE due to ocrdma ABI mismatch\n");
  37                return;
  38        }
  39
  40        if (pdev->device == OC_DEVICE_ID5) {
  41                /* only msix is supported on these devices */
  42                if (!msix_enabled(adapter))
  43                        return;
  44                /* DPP region address and length */
  45                dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
  46                dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
  47        } else {
  48                dev_info.dpp_unmapped_addr = 0;
  49                dev_info.dpp_unmapped_len = 0;
  50        }
  51        dev_info.pdev = adapter->pdev;
  52        dev_info.db = adapter->db;
  53        dev_info.unmapped_db = adapter->roce_db.io_addr;
  54        dev_info.db_page_size = adapter->roce_db.size;
  55        dev_info.db_total_size = adapter->roce_db.total_size;
  56        dev_info.netdev = adapter->netdev;
  57        memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
  58        dev_info.dev_family = adapter->sli_family;
  59        if (msix_enabled(adapter)) {
  60                /* provide all the vectors, so that EQ creation response
  61                 * can decide which one to use.
  62                 */
  63                num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
  64                dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
  65                dev_info.msix.num_vectors = min(num_vec, MAX_MSIX_VECTORS);
  66                /* provide start index of the vector,
  67                 * so in case of linear usage,
  68                 * it can use the base as starting point.
  69                 */
  70                dev_info.msix.start_vector = adapter->num_evt_qs;
  71                for (i = 0; i < dev_info.msix.num_vectors; i++) {
  72                        dev_info.msix.vector_list[i] =
  73                            adapter->msix_entries[i].vector;
  74                }
  75        } else {
  76                dev_info.msix.num_vectors = 0;
  77                dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
  78        }
  79        adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
  80}
  81
  82void be_roce_dev_add(struct be_adapter *adapter)
  83{
  84        if (be_roce_supported(adapter)) {
  85                INIT_LIST_HEAD(&adapter->entry);
  86                mutex_lock(&be_adapter_list_lock);
  87                list_add_tail(&adapter->entry, &be_adapter_list);
  88
  89                /* invoke add() routine of roce driver only if
  90                 * valid driver registered with add method and add() is not yet
  91                 * invoked on a given adapter.
  92                 */
  93                _be_roce_dev_add(adapter);
  94                mutex_unlock(&be_adapter_list_lock);
  95        }
  96}
  97
  98static void _be_roce_dev_remove(struct be_adapter *adapter)
  99{
 100        if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
 101                ocrdma_drv->remove(adapter->ocrdma_dev);
 102        adapter->ocrdma_dev = NULL;
 103}
 104
 105void be_roce_dev_remove(struct be_adapter *adapter)
 106{
 107        if (be_roce_supported(adapter)) {
 108                mutex_lock(&be_adapter_list_lock);
 109                _be_roce_dev_remove(adapter);
 110                list_del(&adapter->entry);
 111                mutex_unlock(&be_adapter_list_lock);
 112        }
 113}
 114
 115void be_roce_dev_shutdown(struct be_adapter *adapter)
 116{
 117        if (be_roce_supported(adapter)) {
 118                mutex_lock(&be_adapter_list_lock);
 119                if (ocrdma_drv && adapter->ocrdma_dev &&
 120                    ocrdma_drv->state_change_handler)
 121                        ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
 122                                                         BE_DEV_SHUTDOWN);
 123                mutex_unlock(&be_adapter_list_lock);
 124        }
 125}
 126
 127int be_roce_register_driver(struct ocrdma_driver *drv)
 128{
 129        struct be_adapter *dev;
 130
 131        mutex_lock(&be_adapter_list_lock);
 132        if (ocrdma_drv) {
 133                mutex_unlock(&be_adapter_list_lock);
 134                return -EINVAL;
 135        }
 136        ocrdma_drv = drv;
 137        list_for_each_entry(dev, &be_adapter_list, entry) {
 138                _be_roce_dev_add(dev);
 139        }
 140        mutex_unlock(&be_adapter_list_lock);
 141        return 0;
 142}
 143EXPORT_SYMBOL(be_roce_register_driver);
 144
 145void be_roce_unregister_driver(struct ocrdma_driver *drv)
 146{
 147        struct be_adapter *dev;
 148
 149        mutex_lock(&be_adapter_list_lock);
 150        list_for_each_entry(dev, &be_adapter_list, entry) {
 151                if (dev->ocrdma_dev)
 152                        _be_roce_dev_remove(dev);
 153        }
 154        ocrdma_drv = NULL;
 155        mutex_unlock(&be_adapter_list_lock);
 156}
 157EXPORT_SYMBOL(be_roce_unregister_driver);
 158