18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2005 - 2016 Broadcom
48c2ecf20Sopenharmony_ci * All rights reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Contact Information:
78c2ecf20Sopenharmony_ci * linux-drivers@emulex.com
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Emulex
108c2ecf20Sopenharmony_ci * 3333 Susan Street
118c2ecf20Sopenharmony_ci * Costa Mesa, CA 92626
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/mutex.h>
158c2ecf20Sopenharmony_ci#include <linux/list.h>
168c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include "be.h"
208c2ecf20Sopenharmony_ci#include "be_cmds.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic struct ocrdma_driver *ocrdma_drv;
238c2ecf20Sopenharmony_cistatic LIST_HEAD(be_adapter_list);
248c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(be_adapter_list_lock);
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic void _be_roce_dev_add(struct be_adapter *adapter)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	struct be_dev_info dev_info;
298c2ecf20Sopenharmony_ci	int i, num_vec;
308c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	if (!ocrdma_drv)
338c2ecf20Sopenharmony_ci		return;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	if (ocrdma_drv->be_abi_version != BE_ROCE_ABI_VERSION) {
368c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev, "Cannot initialize RoCE due to ocrdma ABI mismatch\n");
378c2ecf20Sopenharmony_ci		return;
388c2ecf20Sopenharmony_ci	}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (pdev->device == OC_DEVICE_ID5) {
418c2ecf20Sopenharmony_ci		/* only msix is supported on these devices */
428c2ecf20Sopenharmony_ci		if (!msix_enabled(adapter))
438c2ecf20Sopenharmony_ci			return;
448c2ecf20Sopenharmony_ci		/* DPP region address and length */
458c2ecf20Sopenharmony_ci		dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
468c2ecf20Sopenharmony_ci		dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
478c2ecf20Sopenharmony_ci	} else {
488c2ecf20Sopenharmony_ci		dev_info.dpp_unmapped_addr = 0;
498c2ecf20Sopenharmony_ci		dev_info.dpp_unmapped_len = 0;
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci	dev_info.pdev = adapter->pdev;
528c2ecf20Sopenharmony_ci	dev_info.db = adapter->db;
538c2ecf20Sopenharmony_ci	dev_info.unmapped_db = adapter->roce_db.io_addr;
548c2ecf20Sopenharmony_ci	dev_info.db_page_size = adapter->roce_db.size;
558c2ecf20Sopenharmony_ci	dev_info.db_total_size = adapter->roce_db.total_size;
568c2ecf20Sopenharmony_ci	dev_info.netdev = adapter->netdev;
578c2ecf20Sopenharmony_ci	memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
588c2ecf20Sopenharmony_ci	dev_info.dev_family = adapter->sli_family;
598c2ecf20Sopenharmony_ci	if (msix_enabled(adapter)) {
608c2ecf20Sopenharmony_ci		/* provide all the vectors, so that EQ creation response
618c2ecf20Sopenharmony_ci		 * can decide which one to use.
628c2ecf20Sopenharmony_ci		 */
638c2ecf20Sopenharmony_ci		num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
648c2ecf20Sopenharmony_ci		dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
658c2ecf20Sopenharmony_ci		dev_info.msix.num_vectors = min(num_vec, MAX_MSIX_VECTORS);
668c2ecf20Sopenharmony_ci		/* provide start index of the vector,
678c2ecf20Sopenharmony_ci		 * so in case of linear usage,
688c2ecf20Sopenharmony_ci		 * it can use the base as starting point.
698c2ecf20Sopenharmony_ci		 */
708c2ecf20Sopenharmony_ci		dev_info.msix.start_vector = adapter->num_evt_qs;
718c2ecf20Sopenharmony_ci		for (i = 0; i < dev_info.msix.num_vectors; i++) {
728c2ecf20Sopenharmony_ci			dev_info.msix.vector_list[i] =
738c2ecf20Sopenharmony_ci			    adapter->msix_entries[i].vector;
748c2ecf20Sopenharmony_ci		}
758c2ecf20Sopenharmony_ci	} else {
768c2ecf20Sopenharmony_ci		dev_info.msix.num_vectors = 0;
778c2ecf20Sopenharmony_ci		dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci	adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_civoid be_roce_dev_add(struct be_adapter *adapter)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	if (be_roce_supported(adapter)) {
858c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&adapter->entry);
868c2ecf20Sopenharmony_ci		mutex_lock(&be_adapter_list_lock);
878c2ecf20Sopenharmony_ci		list_add_tail(&adapter->entry, &be_adapter_list);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci		/* invoke add() routine of roce driver only if
908c2ecf20Sopenharmony_ci		 * valid driver registered with add method and add() is not yet
918c2ecf20Sopenharmony_ci		 * invoked on a given adapter.
928c2ecf20Sopenharmony_ci		 */
938c2ecf20Sopenharmony_ci		_be_roce_dev_add(adapter);
948c2ecf20Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
958c2ecf20Sopenharmony_ci	}
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic void _be_roce_dev_remove(struct be_adapter *adapter)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
1018c2ecf20Sopenharmony_ci		ocrdma_drv->remove(adapter->ocrdma_dev);
1028c2ecf20Sopenharmony_ci	adapter->ocrdma_dev = NULL;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_civoid be_roce_dev_remove(struct be_adapter *adapter)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	if (be_roce_supported(adapter)) {
1088c2ecf20Sopenharmony_ci		mutex_lock(&be_adapter_list_lock);
1098c2ecf20Sopenharmony_ci		_be_roce_dev_remove(adapter);
1108c2ecf20Sopenharmony_ci		list_del(&adapter->entry);
1118c2ecf20Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_civoid be_roce_dev_shutdown(struct be_adapter *adapter)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	if (be_roce_supported(adapter)) {
1188c2ecf20Sopenharmony_ci		mutex_lock(&be_adapter_list_lock);
1198c2ecf20Sopenharmony_ci		if (ocrdma_drv && adapter->ocrdma_dev &&
1208c2ecf20Sopenharmony_ci		    ocrdma_drv->state_change_handler)
1218c2ecf20Sopenharmony_ci			ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
1228c2ecf20Sopenharmony_ci							 BE_DEV_SHUTDOWN);
1238c2ecf20Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ciint be_roce_register_driver(struct ocrdma_driver *drv)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	struct be_adapter *dev;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	mutex_lock(&be_adapter_list_lock);
1328c2ecf20Sopenharmony_ci	if (ocrdma_drv) {
1338c2ecf20Sopenharmony_ci		mutex_unlock(&be_adapter_list_lock);
1348c2ecf20Sopenharmony_ci		return -EINVAL;
1358c2ecf20Sopenharmony_ci	}
1368c2ecf20Sopenharmony_ci	ocrdma_drv = drv;
1378c2ecf20Sopenharmony_ci	list_for_each_entry(dev, &be_adapter_list, entry) {
1388c2ecf20Sopenharmony_ci		_be_roce_dev_add(dev);
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci	mutex_unlock(&be_adapter_list_lock);
1418c2ecf20Sopenharmony_ci	return 0;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(be_roce_register_driver);
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_civoid be_roce_unregister_driver(struct ocrdma_driver *drv)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	struct be_adapter *dev;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	mutex_lock(&be_adapter_list_lock);
1508c2ecf20Sopenharmony_ci	list_for_each_entry(dev, &be_adapter_list, entry) {
1518c2ecf20Sopenharmony_ci		if (dev->ocrdma_dev)
1528c2ecf20Sopenharmony_ci			_be_roce_dev_remove(dev);
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci	ocrdma_drv = NULL;
1558c2ecf20Sopenharmony_ci	mutex_unlock(&be_adapter_list_lock);
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(be_roce_unregister_driver);
158