1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 /* QLogic qedr NIC Driver
3 * Copyright (c) 2015-2017 QLogic Corporation
4 * Copyright (c) 2019-2020 Marvell International Ltd.
8 #include <linux/netdevice.h>
9 #include <linux/list.h>
10 #include <linux/mutex.h>
11 #include <linux/qed/qede_rdma.h>
14 static struct qedr_driver
*qedr_drv
;
15 static LIST_HEAD(qedr_dev_list
);
16 static DEFINE_MUTEX(qedr_dev_list_lock
);
18 bool qede_rdma_supported(struct qede_dev
*dev
)
20 return dev
->dev_info
.common
.rdma_supported
;
23 static void _qede_rdma_dev_add(struct qede_dev
*edev
)
28 /* Leftovers from previous error recovery */
29 edev
->rdma_info
.exp_recovery
= false;
30 edev
->rdma_info
.qedr_dev
= qedr_drv
->add(edev
->cdev
, edev
->pdev
,
34 static int qede_rdma_create_wq(struct qede_dev
*edev
)
36 INIT_LIST_HEAD(&edev
->rdma_info
.rdma_event_list
);
37 kref_init(&edev
->rdma_info
.refcnt
);
38 init_completion(&edev
->rdma_info
.event_comp
);
40 edev
->rdma_info
.rdma_wq
= create_singlethread_workqueue("rdma_wq");
41 if (!edev
->rdma_info
.rdma_wq
) {
42 DP_NOTICE(edev
, "qedr: Could not create workqueue\n");
49 static void qede_rdma_cleanup_event(struct qede_dev
*edev
)
51 struct list_head
*head
= &edev
->rdma_info
.rdma_event_list
;
52 struct qede_rdma_event_work
*event_node
;
54 flush_workqueue(edev
->rdma_info
.rdma_wq
);
55 while (!list_empty(head
)) {
56 event_node
= list_entry(head
->next
, struct qede_rdma_event_work
,
58 cancel_work_sync(&event_node
->work
);
59 list_del(&event_node
->list
);
64 static void qede_rdma_complete_event(struct kref
*ref
)
66 struct qede_rdma_dev
*rdma_dev
=
67 container_of(ref
, struct qede_rdma_dev
, refcnt
);
69 /* no more events will be added after this */
70 complete(&rdma_dev
->event_comp
);
73 static void qede_rdma_destroy_wq(struct qede_dev
*edev
)
75 /* Avoid race with add_event flow, make sure it finishes before
76 * we start accessing the list and cleaning up the work
78 kref_put(&edev
->rdma_info
.refcnt
, qede_rdma_complete_event
);
79 wait_for_completion(&edev
->rdma_info
.event_comp
);
81 qede_rdma_cleanup_event(edev
);
82 destroy_workqueue(edev
->rdma_info
.rdma_wq
);
83 edev
->rdma_info
.rdma_wq
= NULL
;
86 int qede_rdma_dev_add(struct qede_dev
*edev
, bool recovery
)
90 if (!qede_rdma_supported(edev
))
93 /* Cannot start qedr while recovering since it wasn't fully stopped */
97 rc
= qede_rdma_create_wq(edev
);
101 INIT_LIST_HEAD(&edev
->rdma_info
.entry
);
102 mutex_lock(&qedr_dev_list_lock
);
103 list_add_tail(&edev
->rdma_info
.entry
, &qedr_dev_list
);
104 _qede_rdma_dev_add(edev
);
105 mutex_unlock(&qedr_dev_list_lock
);
110 static void _qede_rdma_dev_remove(struct qede_dev
*edev
)
112 if (qedr_drv
&& qedr_drv
->remove
&& edev
->rdma_info
.qedr_dev
)
113 qedr_drv
->remove(edev
->rdma_info
.qedr_dev
);
116 void qede_rdma_dev_remove(struct qede_dev
*edev
, bool recovery
)
118 if (!qede_rdma_supported(edev
))
121 /* Cannot remove qedr while recovering since it wasn't fully stopped */
123 qede_rdma_destroy_wq(edev
);
124 mutex_lock(&qedr_dev_list_lock
);
125 if (!edev
->rdma_info
.exp_recovery
)
126 _qede_rdma_dev_remove(edev
);
127 edev
->rdma_info
.qedr_dev
= NULL
;
128 list_del(&edev
->rdma_info
.entry
);
129 mutex_unlock(&qedr_dev_list_lock
);
131 if (!edev
->rdma_info
.exp_recovery
) {
132 mutex_lock(&qedr_dev_list_lock
);
133 _qede_rdma_dev_remove(edev
);
134 mutex_unlock(&qedr_dev_list_lock
);
136 edev
->rdma_info
.exp_recovery
= true;
140 static void _qede_rdma_dev_open(struct qede_dev
*edev
)
142 if (qedr_drv
&& edev
->rdma_info
.qedr_dev
&& qedr_drv
->notify
)
143 qedr_drv
->notify(edev
->rdma_info
.qedr_dev
, QEDE_UP
);
146 static void qede_rdma_dev_open(struct qede_dev
*edev
)
148 if (!qede_rdma_supported(edev
))
151 mutex_lock(&qedr_dev_list_lock
);
152 _qede_rdma_dev_open(edev
);
153 mutex_unlock(&qedr_dev_list_lock
);
156 static void _qede_rdma_dev_close(struct qede_dev
*edev
)
158 if (qedr_drv
&& edev
->rdma_info
.qedr_dev
&& qedr_drv
->notify
)
159 qedr_drv
->notify(edev
->rdma_info
.qedr_dev
, QEDE_DOWN
);
162 static void qede_rdma_dev_close(struct qede_dev
*edev
)
164 if (!qede_rdma_supported(edev
))
167 mutex_lock(&qedr_dev_list_lock
);
168 _qede_rdma_dev_close(edev
);
169 mutex_unlock(&qedr_dev_list_lock
);
172 static void qede_rdma_dev_shutdown(struct qede_dev
*edev
)
174 if (!qede_rdma_supported(edev
))
177 mutex_lock(&qedr_dev_list_lock
);
178 if (qedr_drv
&& edev
->rdma_info
.qedr_dev
&& qedr_drv
->notify
)
179 qedr_drv
->notify(edev
->rdma_info
.qedr_dev
, QEDE_CLOSE
);
180 mutex_unlock(&qedr_dev_list_lock
);
183 int qede_rdma_register_driver(struct qedr_driver
*drv
)
185 struct qede_dev
*edev
;
188 mutex_lock(&qedr_dev_list_lock
);
190 mutex_unlock(&qedr_dev_list_lock
);
195 list_for_each_entry(edev
, &qedr_dev_list
, rdma_info
.entry
) {
196 struct net_device
*ndev
;
199 _qede_rdma_dev_add(edev
);
201 if (netif_running(ndev
) && netif_oper_up(ndev
))
202 _qede_rdma_dev_open(edev
);
204 mutex_unlock(&qedr_dev_list_lock
);
206 pr_notice("qedr: discovered and registered %d RDMA funcs\n",
211 EXPORT_SYMBOL(qede_rdma_register_driver
);
213 void qede_rdma_unregister_driver(struct qedr_driver
*drv
)
215 struct qede_dev
*edev
;
217 mutex_lock(&qedr_dev_list_lock
);
218 list_for_each_entry(edev
, &qedr_dev_list
, rdma_info
.entry
) {
219 /* If device has experienced recovery it was already removed */
220 if (edev
->rdma_info
.qedr_dev
&& !edev
->rdma_info
.exp_recovery
)
221 _qede_rdma_dev_remove(edev
);
224 mutex_unlock(&qedr_dev_list_lock
);
226 EXPORT_SYMBOL(qede_rdma_unregister_driver
);
228 static void qede_rdma_changeaddr(struct qede_dev
*edev
)
230 if (!qede_rdma_supported(edev
))
233 if (qedr_drv
&& edev
->rdma_info
.qedr_dev
&& qedr_drv
->notify
)
234 qedr_drv
->notify(edev
->rdma_info
.qedr_dev
, QEDE_CHANGE_ADDR
);
237 static void qede_rdma_change_mtu(struct qede_dev
*edev
)
239 if (qede_rdma_supported(edev
)) {
240 if (qedr_drv
&& edev
->rdma_info
.qedr_dev
&& qedr_drv
->notify
)
241 qedr_drv
->notify(edev
->rdma_info
.qedr_dev
,
246 static struct qede_rdma_event_work
*
247 qede_rdma_get_free_event_node(struct qede_dev
*edev
)
249 struct qede_rdma_event_work
*event_node
= NULL
;
250 struct list_head
*list_node
= NULL
;
253 list_for_each(list_node
, &edev
->rdma_info
.rdma_event_list
) {
254 event_node
= list_entry(list_node
, struct qede_rdma_event_work
,
256 if (!work_pending(&event_node
->work
)) {
263 event_node
= kzalloc(sizeof(*event_node
), GFP_ATOMIC
);
266 "qedr: Could not allocate memory for rdma work\n");
269 list_add_tail(&event_node
->list
,
270 &edev
->rdma_info
.rdma_event_list
);
276 static void qede_rdma_handle_event(struct work_struct
*work
)
278 struct qede_rdma_event_work
*event_node
;
279 enum qede_rdma_event event
;
280 struct qede_dev
*edev
;
282 event_node
= container_of(work
, struct qede_rdma_event_work
, work
);
283 event
= event_node
->event
;
284 edev
= event_node
->ptr
;
288 qede_rdma_dev_open(edev
);
291 qede_rdma_dev_close(edev
);
294 qede_rdma_dev_shutdown(edev
);
296 case QEDE_CHANGE_ADDR
:
297 qede_rdma_changeaddr(edev
);
299 case QEDE_CHANGE_MTU
:
300 qede_rdma_change_mtu(edev
);
303 DP_NOTICE(edev
, "Invalid rdma event %d", event
);
307 static void qede_rdma_add_event(struct qede_dev
*edev
,
308 enum qede_rdma_event event
)
310 struct qede_rdma_event_work
*event_node
;
312 /* If a recovery was experienced avoid adding the event */
313 if (edev
->rdma_info
.exp_recovery
)
316 if (!edev
->rdma_info
.qedr_dev
|| !edev
->rdma_info
.rdma_wq
)
319 /* We don't want the cleanup flow to start while we're allocating and
320 * scheduling the work
322 if (!kref_get_unless_zero(&edev
->rdma_info
.refcnt
))
323 return; /* already being destroyed */
325 event_node
= qede_rdma_get_free_event_node(edev
);
329 event_node
->event
= event
;
330 event_node
->ptr
= edev
;
332 INIT_WORK(&event_node
->work
, qede_rdma_handle_event
);
333 queue_work(edev
->rdma_info
.rdma_wq
, &event_node
->work
);
336 kref_put(&edev
->rdma_info
.refcnt
, qede_rdma_complete_event
);
339 void qede_rdma_dev_event_open(struct qede_dev
*edev
)
341 qede_rdma_add_event(edev
, QEDE_UP
);
344 void qede_rdma_dev_event_close(struct qede_dev
*edev
)
346 qede_rdma_add_event(edev
, QEDE_DOWN
);
349 void qede_rdma_event_changeaddr(struct qede_dev
*edev
)
351 qede_rdma_add_event(edev
, QEDE_CHANGE_ADDR
);
354 void qede_rdma_event_change_mtu(struct qede_dev
*edev
)
356 qede_rdma_add_event(edev
, QEDE_CHANGE_MTU
);