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