xref: /openbmc/linux/drivers/net/ethernet/emulex/benet/be_roce.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*6e9ef509SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2045508a8SParav Pandit /*
37dfbe7d7SSomnath Kotur  * Copyright (C) 2005 - 2016 Broadcom
4045508a8SParav Pandit  * All rights reserved.
5045508a8SParav Pandit  *
6045508a8SParav Pandit  * Contact Information:
7045508a8SParav Pandit  * linux-drivers@emulex.com
8045508a8SParav Pandit  *
9045508a8SParav Pandit  * Emulex
10045508a8SParav Pandit  * 3333 Susan Street
11045508a8SParav Pandit  * Costa Mesa, CA 92626
12045508a8SParav Pandit  */
13045508a8SParav Pandit 
14045508a8SParav Pandit #include <linux/mutex.h>
15045508a8SParav Pandit #include <linux/list.h>
16045508a8SParav Pandit #include <linux/netdevice.h>
17045508a8SParav Pandit #include <linux/module.h>
18045508a8SParav Pandit 
19045508a8SParav Pandit #include "be.h"
20045508a8SParav Pandit #include "be_cmds.h"
21045508a8SParav Pandit 
22045508a8SParav Pandit static struct ocrdma_driver *ocrdma_drv;
23045508a8SParav Pandit static LIST_HEAD(be_adapter_list);
24045508a8SParav Pandit static DEFINE_MUTEX(be_adapter_list_lock);
25045508a8SParav Pandit 
_be_roce_dev_add(struct be_adapter * adapter)26045508a8SParav Pandit static void _be_roce_dev_add(struct be_adapter *adapter)
27045508a8SParav Pandit {
28045508a8SParav Pandit 	struct be_dev_info dev_info;
29045508a8SParav Pandit 	int i, num_vec;
30045508a8SParav Pandit 	struct pci_dev *pdev = adapter->pdev;
31045508a8SParav Pandit 
32045508a8SParav Pandit 	if (!ocrdma_drv)
33045508a8SParav Pandit 		return;
342407116eSDevesh Sharma 
352407116eSDevesh Sharma 	if (ocrdma_drv->be_abi_version != BE_ROCE_ABI_VERSION) {
362407116eSDevesh Sharma 		dev_warn(&pdev->dev, "Cannot initialize RoCE due to ocrdma ABI mismatch\n");
372407116eSDevesh Sharma 		return;
382407116eSDevesh Sharma 	}
392407116eSDevesh Sharma 
40045508a8SParav Pandit 	if (pdev->device == OC_DEVICE_ID5) {
41045508a8SParav Pandit 		/* only msix is supported on these devices */
42045508a8SParav Pandit 		if (!msix_enabled(adapter))
43045508a8SParav Pandit 			return;
44045508a8SParav Pandit 		/* DPP region address and length */
45045508a8SParav Pandit 		dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
46045508a8SParav Pandit 		dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
47045508a8SParav Pandit 	} else {
48045508a8SParav Pandit 		dev_info.dpp_unmapped_addr = 0;
49045508a8SParav Pandit 		dev_info.dpp_unmapped_len = 0;
50045508a8SParav Pandit 	}
51045508a8SParav Pandit 	dev_info.pdev = adapter->pdev;
52045508a8SParav Pandit 	dev_info.db = adapter->db;
53045508a8SParav Pandit 	dev_info.unmapped_db = adapter->roce_db.io_addr;
54045508a8SParav Pandit 	dev_info.db_page_size = adapter->roce_db.size;
55045508a8SParav Pandit 	dev_info.db_total_size = adapter->roce_db.total_size;
56045508a8SParav Pandit 	dev_info.netdev = adapter->netdev;
57045508a8SParav Pandit 	memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
58045508a8SParav Pandit 	dev_info.dev_family = adapter->sli_family;
59045508a8SParav Pandit 	if (msix_enabled(adapter)) {
60045508a8SParav Pandit 		/* provide all the vectors, so that EQ creation response
61045508a8SParav Pandit 		 * can decide which one to use.
62045508a8SParav Pandit 		 */
63045508a8SParav Pandit 		num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
64045508a8SParav Pandit 		dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
6592bf14abSSathya Perla 		dev_info.msix.num_vectors = min(num_vec, MAX_MSIX_VECTORS);
66045508a8SParav Pandit 		/* provide start index of the vector,
67045508a8SParav Pandit 		 * so in case of linear usage,
68045508a8SParav Pandit 		 * it can use the base as starting point.
69045508a8SParav Pandit 		 */
70045508a8SParav Pandit 		dev_info.msix.start_vector = adapter->num_evt_qs;
71045508a8SParav Pandit 		for (i = 0; i < dev_info.msix.num_vectors; i++) {
72045508a8SParav Pandit 			dev_info.msix.vector_list[i] =
73045508a8SParav Pandit 			    adapter->msix_entries[i].vector;
74045508a8SParav Pandit 		}
75045508a8SParav Pandit 	} else {
76045508a8SParav Pandit 		dev_info.msix.num_vectors = 0;
77045508a8SParav Pandit 		dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
78045508a8SParav Pandit 	}
79045508a8SParav Pandit 	adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
80045508a8SParav Pandit }
81045508a8SParav Pandit 
be_roce_dev_add(struct be_adapter * adapter)82045508a8SParav Pandit void be_roce_dev_add(struct be_adapter *adapter)
83045508a8SParav Pandit {
84045508a8SParav Pandit 	if (be_roce_supported(adapter)) {
85045508a8SParav Pandit 		INIT_LIST_HEAD(&adapter->entry);
86045508a8SParav Pandit 		mutex_lock(&be_adapter_list_lock);
87045508a8SParav Pandit 		list_add_tail(&adapter->entry, &be_adapter_list);
88045508a8SParav Pandit 
89045508a8SParav Pandit 		/* invoke add() routine of roce driver only if
90045508a8SParav Pandit 		 * valid driver registered with add method and add() is not yet
91045508a8SParav Pandit 		 * invoked on a given adapter.
92045508a8SParav Pandit 		 */
93045508a8SParav Pandit 		_be_roce_dev_add(adapter);
94045508a8SParav Pandit 		mutex_unlock(&be_adapter_list_lock);
95045508a8SParav Pandit 	}
96045508a8SParav Pandit }
97045508a8SParav Pandit 
_be_roce_dev_remove(struct be_adapter * adapter)984188e7dfSJingoo Han static void _be_roce_dev_remove(struct be_adapter *adapter)
99045508a8SParav Pandit {
100045508a8SParav Pandit 	if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
101045508a8SParav Pandit 		ocrdma_drv->remove(adapter->ocrdma_dev);
102045508a8SParav Pandit 	adapter->ocrdma_dev = NULL;
103045508a8SParav Pandit }
104045508a8SParav Pandit 
be_roce_dev_remove(struct be_adapter * adapter)105045508a8SParav Pandit void be_roce_dev_remove(struct be_adapter *adapter)
106045508a8SParav Pandit {
107045508a8SParav Pandit 	if (be_roce_supported(adapter)) {
108045508a8SParav Pandit 		mutex_lock(&be_adapter_list_lock);
109045508a8SParav Pandit 		_be_roce_dev_remove(adapter);
110045508a8SParav Pandit 		list_del(&adapter->entry);
111045508a8SParav Pandit 		mutex_unlock(&be_adapter_list_lock);
112045508a8SParav Pandit 	}
113045508a8SParav Pandit }
114045508a8SParav Pandit 
be_roce_dev_shutdown(struct be_adapter * adapter)115d114f99aSDevesh Sharma void be_roce_dev_shutdown(struct be_adapter *adapter)
116d114f99aSDevesh Sharma {
117d114f99aSDevesh Sharma 	if (be_roce_supported(adapter)) {
118d114f99aSDevesh Sharma 		mutex_lock(&be_adapter_list_lock);
119d114f99aSDevesh Sharma 		if (ocrdma_drv && adapter->ocrdma_dev &&
120d114f99aSDevesh Sharma 		    ocrdma_drv->state_change_handler)
121d114f99aSDevesh Sharma 			ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
122d114f99aSDevesh Sharma 							 BE_DEV_SHUTDOWN);
123d114f99aSDevesh Sharma 		mutex_unlock(&be_adapter_list_lock);
124d114f99aSDevesh Sharma 	}
125d114f99aSDevesh Sharma }
126d114f99aSDevesh Sharma 
be_roce_register_driver(struct ocrdma_driver * drv)127045508a8SParav Pandit int be_roce_register_driver(struct ocrdma_driver *drv)
128045508a8SParav Pandit {
129045508a8SParav Pandit 	struct be_adapter *dev;
130045508a8SParav Pandit 
131045508a8SParav Pandit 	mutex_lock(&be_adapter_list_lock);
132045508a8SParav Pandit 	if (ocrdma_drv) {
133045508a8SParav Pandit 		mutex_unlock(&be_adapter_list_lock);
134045508a8SParav Pandit 		return -EINVAL;
135045508a8SParav Pandit 	}
136045508a8SParav Pandit 	ocrdma_drv = drv;
137045508a8SParav Pandit 	list_for_each_entry(dev, &be_adapter_list, entry) {
138045508a8SParav Pandit 		_be_roce_dev_add(dev);
139045508a8SParav Pandit 	}
140045508a8SParav Pandit 	mutex_unlock(&be_adapter_list_lock);
141045508a8SParav Pandit 	return 0;
142045508a8SParav Pandit }
143045508a8SParav Pandit EXPORT_SYMBOL(be_roce_register_driver);
144045508a8SParav Pandit 
be_roce_unregister_driver(struct ocrdma_driver * drv)145045508a8SParav Pandit void be_roce_unregister_driver(struct ocrdma_driver *drv)
146045508a8SParav Pandit {
147045508a8SParav Pandit 	struct be_adapter *dev;
148045508a8SParav Pandit 
149045508a8SParav Pandit 	mutex_lock(&be_adapter_list_lock);
150045508a8SParav Pandit 	list_for_each_entry(dev, &be_adapter_list, entry) {
151045508a8SParav Pandit 		if (dev->ocrdma_dev)
152045508a8SParav Pandit 			_be_roce_dev_remove(dev);
153045508a8SParav Pandit 	}
154045508a8SParav Pandit 	ocrdma_drv = NULL;
155045508a8SParav Pandit 	mutex_unlock(&be_adapter_list_lock);
156045508a8SParav Pandit }
157045508a8SParav Pandit EXPORT_SYMBOL(be_roce_unregister_driver);
158