162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2005 - 2016 Broadcom
462306a36Sopenharmony_ci * All rights reserved.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Contact Information:
762306a36Sopenharmony_ci * linux-drivers@emulex.com
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Emulex
1062306a36Sopenharmony_ci * 3333 Susan Street
1162306a36Sopenharmony_ci * Costa Mesa, CA 92626
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/mutex.h>
1562306a36Sopenharmony_ci#include <linux/list.h>
1662306a36Sopenharmony_ci#include <linux/netdevice.h>
1762306a36Sopenharmony_ci#include <linux/module.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "be.h"
2062306a36Sopenharmony_ci#include "be_cmds.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic struct ocrdma_driver *ocrdma_drv;
2362306a36Sopenharmony_cistatic LIST_HEAD(be_adapter_list);
2462306a36Sopenharmony_cistatic DEFINE_MUTEX(be_adapter_list_lock);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic void _be_roce_dev_add(struct be_adapter *adapter)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	struct be_dev_info dev_info;
2962306a36Sopenharmony_ci	int i, num_vec;
3062306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (!ocrdma_drv)
3362306a36Sopenharmony_ci		return;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	if (ocrdma_drv->be_abi_version != BE_ROCE_ABI_VERSION) {
3662306a36Sopenharmony_ci		dev_warn(&pdev->dev, "Cannot initialize RoCE due to ocrdma ABI mismatch\n");
3762306a36Sopenharmony_ci		return;
3862306a36Sopenharmony_ci	}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	if (pdev->device == OC_DEVICE_ID5) {
4162306a36Sopenharmony_ci		/* only msix is supported on these devices */
4262306a36Sopenharmony_ci		if (!msix_enabled(adapter))
4362306a36Sopenharmony_ci			return;
4462306a36Sopenharmony_ci		/* DPP region address and length */
4562306a36Sopenharmony_ci		dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
4662306a36Sopenharmony_ci		dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
4762306a36Sopenharmony_ci	} else {
4862306a36Sopenharmony_ci		dev_info.dpp_unmapped_addr = 0;
4962306a36Sopenharmony_ci		dev_info.dpp_unmapped_len = 0;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci	dev_info.pdev = adapter->pdev;
5262306a36Sopenharmony_ci	dev_info.db = adapter->db;
5362306a36Sopenharmony_ci	dev_info.unmapped_db = adapter->roce_db.io_addr;
5462306a36Sopenharmony_ci	dev_info.db_page_size = adapter->roce_db.size;
5562306a36Sopenharmony_ci	dev_info.db_total_size = adapter->roce_db.total_size;
5662306a36Sopenharmony_ci	dev_info.netdev = adapter->netdev;
5762306a36Sopenharmony_ci	memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
5862306a36Sopenharmony_ci	dev_info.dev_family = adapter->sli_family;
5962306a36Sopenharmony_ci	if (msix_enabled(adapter)) {
6062306a36Sopenharmony_ci		/* provide all the vectors, so that EQ creation response
6162306a36Sopenharmony_ci		 * can decide which one to use.
6262306a36Sopenharmony_ci		 */
6362306a36Sopenharmony_ci		num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
6462306a36Sopenharmony_ci		dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
6562306a36Sopenharmony_ci		dev_info.msix.num_vectors = min(num_vec, MAX_MSIX_VECTORS);
6662306a36Sopenharmony_ci		/* provide start index of the vector,
6762306a36Sopenharmony_ci		 * so in case of linear usage,
6862306a36Sopenharmony_ci		 * it can use the base as starting point.
6962306a36Sopenharmony_ci		 */
7062306a36Sopenharmony_ci		dev_info.msix.start_vector = adapter->num_evt_qs;
7162306a36Sopenharmony_ci		for (i = 0; i < dev_info.msix.num_vectors; i++) {
7262306a36Sopenharmony_ci			dev_info.msix.vector_list[i] =
7362306a36Sopenharmony_ci			    adapter->msix_entries[i].vector;
7462306a36Sopenharmony_ci		}
7562306a36Sopenharmony_ci	} else {
7662306a36Sopenharmony_ci		dev_info.msix.num_vectors = 0;
7762306a36Sopenharmony_ci		dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
7862306a36Sopenharmony_ci	}
7962306a36Sopenharmony_ci	adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_civoid be_roce_dev_add(struct be_adapter *adapter)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	if (be_roce_supported(adapter)) {
8562306a36Sopenharmony_ci		INIT_LIST_HEAD(&adapter->entry);
8662306a36Sopenharmony_ci		mutex_lock(&be_adapter_list_lock);
8762306a36Sopenharmony_ci		list_add_tail(&adapter->entry, &be_adapter_list);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci		/* invoke add() routine of roce driver only if
9062306a36Sopenharmony_ci		 * valid driver registered with add method and add() is not yet
9162306a36Sopenharmony_ci		 * invoked on a given adapter.
9262306a36Sopenharmony_ci		 */
9362306a36Sopenharmony_ci		_be_roce_dev_add(adapter);
9462306a36Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
9562306a36Sopenharmony_ci	}
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic void _be_roce_dev_remove(struct be_adapter *adapter)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
10162306a36Sopenharmony_ci		ocrdma_drv->remove(adapter->ocrdma_dev);
10262306a36Sopenharmony_ci	adapter->ocrdma_dev = NULL;
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_civoid be_roce_dev_remove(struct be_adapter *adapter)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	if (be_roce_supported(adapter)) {
10862306a36Sopenharmony_ci		mutex_lock(&be_adapter_list_lock);
10962306a36Sopenharmony_ci		_be_roce_dev_remove(adapter);
11062306a36Sopenharmony_ci		list_del(&adapter->entry);
11162306a36Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
11262306a36Sopenharmony_ci	}
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_civoid be_roce_dev_shutdown(struct be_adapter *adapter)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	if (be_roce_supported(adapter)) {
11862306a36Sopenharmony_ci		mutex_lock(&be_adapter_list_lock);
11962306a36Sopenharmony_ci		if (ocrdma_drv && adapter->ocrdma_dev &&
12062306a36Sopenharmony_ci		    ocrdma_drv->state_change_handler)
12162306a36Sopenharmony_ci			ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
12262306a36Sopenharmony_ci							 BE_DEV_SHUTDOWN);
12362306a36Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciint be_roce_register_driver(struct ocrdma_driver *drv)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	struct be_adapter *dev;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	mutex_lock(&be_adapter_list_lock);
13262306a36Sopenharmony_ci	if (ocrdma_drv) {
13362306a36Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
13462306a36Sopenharmony_ci		return -EINVAL;
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci	ocrdma_drv = drv;
13762306a36Sopenharmony_ci	list_for_each_entry(dev, &be_adapter_list, entry) {
13862306a36Sopenharmony_ci		_be_roce_dev_add(dev);
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci	mutex_unlock(&be_adapter_list_lock);
14162306a36Sopenharmony_ci	return 0;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ciEXPORT_SYMBOL(be_roce_register_driver);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_civoid be_roce_unregister_driver(struct ocrdma_driver *drv)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct be_adapter *dev;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	mutex_lock(&be_adapter_list_lock);
15062306a36Sopenharmony_ci	list_for_each_entry(dev, &be_adapter_list, entry) {
15162306a36Sopenharmony_ci		if (dev->ocrdma_dev)
15262306a36Sopenharmony_ci			_be_roce_dev_remove(dev);
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci	ocrdma_drv = NULL;
15562306a36Sopenharmony_ci	mutex_unlock(&be_adapter_list_lock);
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ciEXPORT_SYMBOL(be_roce_unregister_driver);
158