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 | |
22 | static struct ocrdma_driver *ocrdma_drv; |
23 | static LIST_HEAD(be_adapter_list); |
24 | static DEFINE_MUTEX(be_adapter_list_lock); |
25 | |
26 | static 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 | |
82 | void be_roce_dev_add(struct be_adapter *adapter) |
83 | { |
84 | if (be_roce_supported(adapter)) { |
85 | INIT_LIST_HEAD(list: &adapter->entry); |
86 | mutex_lock(&be_adapter_list_lock); |
87 | list_add_tail(new: &adapter->entry, head: &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(lock: &be_adapter_list_lock); |
95 | } |
96 | } |
97 | |
98 | static 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 | |
105 | void 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(entry: &adapter->entry); |
111 | mutex_unlock(lock: &be_adapter_list_lock); |
112 | } |
113 | } |
114 | |
115 | void 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(lock: &be_adapter_list_lock); |
124 | } |
125 | } |
126 | |
127 | int 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(lock: &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(adapter: dev); |
139 | } |
140 | mutex_unlock(lock: &be_adapter_list_lock); |
141 | return 0; |
142 | } |
143 | EXPORT_SYMBOL(be_roce_register_driver); |
144 | |
145 | void 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(adapter: dev); |
153 | } |
154 | ocrdma_drv = NULL; |
155 | mutex_unlock(lock: &be_adapter_list_lock); |
156 | } |
157 | EXPORT_SYMBOL(be_roce_unregister_driver); |
158 | |