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