1 /* Broadcom NetXtreme-C/E network driver.
3 * Copyright (c) 2016-2018 Broadcom Limited
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation.
10 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/interrupt.h>
15 #include <linux/pci.h>
16 #include <linux/netdevice.h>
17 #include <linux/rtnetlink.h>
18 #include <linux/bitops.h>
19 #include <linux/irq.h>
20 #include <asm/byteorder.h>
21 #include <linux/bitmap.h>
27 static int bnxt_register_dev(struct bnxt_en_dev
*edev
, int ulp_id
,
28 struct bnxt_ulp_ops
*ulp_ops
, void *handle
)
30 struct net_device
*dev
= edev
->net
;
31 struct bnxt
*bp
= netdev_priv(dev
);
35 if (ulp_id
>= BNXT_MAX_ULP
)
38 ulp
= &edev
->ulp_tbl
[ulp_id
];
39 if (rcu_access_pointer(ulp
->ulp_ops
)) {
40 netdev_err(bp
->dev
, "ulp id %d already registered\n", ulp_id
);
43 if (ulp_id
== BNXT_ROCE_ULP
) {
44 unsigned int max_stat_ctxs
;
46 max_stat_ctxs
= bnxt_get_max_func_stat_ctxs(bp
);
47 if (max_stat_ctxs
<= BNXT_MIN_ROCE_STAT_CTXS
||
48 bp
->cp_nr_rings
== max_stat_ctxs
)
52 atomic_set(&ulp
->ref_count
, 0);
54 rcu_assign_pointer(ulp
->ulp_ops
, ulp_ops
);
56 if (ulp_id
== BNXT_ROCE_ULP
) {
57 if (test_bit(BNXT_STATE_OPEN
, &bp
->state
))
58 bnxt_hwrm_vnic_cfg(bp
, 0);
64 static int bnxt_unregister_dev(struct bnxt_en_dev
*edev
, int ulp_id
)
66 struct net_device
*dev
= edev
->net
;
67 struct bnxt
*bp
= netdev_priv(dev
);
72 if (ulp_id
>= BNXT_MAX_ULP
)
75 ulp
= &edev
->ulp_tbl
[ulp_id
];
76 if (!rcu_access_pointer(ulp
->ulp_ops
)) {
77 netdev_err(bp
->dev
, "ulp id %d not registered\n", ulp_id
);
80 if (ulp_id
== BNXT_ROCE_ULP
&& ulp
->msix_requested
)
81 edev
->en_ops
->bnxt_free_msix(edev
, ulp_id
);
83 if (ulp
->max_async_event_id
)
84 bnxt_hwrm_func_drv_rgtr(bp
, NULL
, 0, true);
86 RCU_INIT_POINTER(ulp
->ulp_ops
, NULL
);
88 ulp
->max_async_event_id
= 0;
89 ulp
->async_events_bmap
= NULL
;
90 while (atomic_read(&ulp
->ref_count
) != 0 && i
< 10) {
97 static void bnxt_fill_msix_vecs(struct bnxt
*bp
, struct bnxt_msix_entry
*ent
)
99 struct bnxt_en_dev
*edev
= bp
->edev
;
100 int num_msix
, idx
, i
;
102 num_msix
= edev
->ulp_tbl
[BNXT_ROCE_ULP
].msix_requested
;
103 idx
= edev
->ulp_tbl
[BNXT_ROCE_ULP
].msix_base
;
104 for (i
= 0; i
< num_msix
; i
++) {
105 ent
[i
].vector
= bp
->irq_tbl
[idx
+ i
].vector
;
106 ent
[i
].ring_idx
= idx
+ i
;
107 ent
[i
].db_offset
= (idx
+ i
) * 0x80;
111 static int bnxt_req_msix_vecs(struct bnxt_en_dev
*edev
, int ulp_id
,
112 struct bnxt_msix_entry
*ent
, int num_msix
)
114 struct net_device
*dev
= edev
->net
;
115 struct bnxt
*bp
= netdev_priv(dev
);
116 struct bnxt_hw_resc
*hw_resc
;
117 int max_idx
, max_cp_rings
;
123 if (ulp_id
!= BNXT_ROCE_ULP
)
126 if (!(bp
->flags
& BNXT_FLAG_USING_MSIX
))
129 if (edev
->ulp_tbl
[ulp_id
].msix_requested
)
132 max_cp_rings
= bnxt_get_max_func_cp_rings(bp
);
133 avail_msix
= bnxt_get_avail_msix(bp
, num_msix
);
136 if (avail_msix
> num_msix
)
137 avail_msix
= num_msix
;
139 if (BNXT_NEW_RM(bp
)) {
140 idx
= bp
->cp_nr_rings
;
142 max_idx
= min_t(int, bp
->total_irqs
, max_cp_rings
);
143 idx
= max_idx
- avail_msix
;
145 edev
->ulp_tbl
[ulp_id
].msix_base
= idx
;
146 edev
->ulp_tbl
[ulp_id
].msix_requested
= avail_msix
;
147 hw_resc
= &bp
->hw_resc
;
148 total_vecs
= idx
+ avail_msix
;
149 if (bp
->total_irqs
< total_vecs
||
150 (BNXT_NEW_RM(bp
) && hw_resc
->resv_irqs
< total_vecs
)) {
151 if (netif_running(dev
)) {
152 bnxt_close_nic(bp
, true, false);
153 rc
= bnxt_open_nic(bp
, true, false);
155 rc
= bnxt_reserve_rings(bp
, true);
159 edev
->ulp_tbl
[ulp_id
].msix_requested
= 0;
163 if (BNXT_NEW_RM(bp
)) {
166 resv_msix
= hw_resc
->resv_irqs
- bp
->cp_nr_rings
;
167 avail_msix
= min_t(int, resv_msix
, avail_msix
);
168 edev
->ulp_tbl
[ulp_id
].msix_requested
= avail_msix
;
170 bnxt_fill_msix_vecs(bp
, ent
);
171 edev
->flags
|= BNXT_EN_FLAG_MSIX_REQUESTED
;
175 static int bnxt_free_msix_vecs(struct bnxt_en_dev
*edev
, int ulp_id
)
177 struct net_device
*dev
= edev
->net
;
178 struct bnxt
*bp
= netdev_priv(dev
);
181 if (ulp_id
!= BNXT_ROCE_ULP
)
184 if (!(edev
->flags
& BNXT_EN_FLAG_MSIX_REQUESTED
))
187 edev
->ulp_tbl
[ulp_id
].msix_requested
= 0;
188 edev
->flags
&= ~BNXT_EN_FLAG_MSIX_REQUESTED
;
189 if (netif_running(dev
) && !(edev
->flags
& BNXT_EN_FLAG_ULP_STOPPED
)) {
190 bnxt_close_nic(bp
, true, false);
191 bnxt_open_nic(bp
, true, false);
196 int bnxt_get_ulp_msix_num(struct bnxt
*bp
)
198 if (bnxt_ulp_registered(bp
->edev
, BNXT_ROCE_ULP
)) {
199 struct bnxt_en_dev
*edev
= bp
->edev
;
201 return edev
->ulp_tbl
[BNXT_ROCE_ULP
].msix_requested
;
206 int bnxt_get_ulp_msix_base(struct bnxt
*bp
)
208 if (bnxt_ulp_registered(bp
->edev
, BNXT_ROCE_ULP
)) {
209 struct bnxt_en_dev
*edev
= bp
->edev
;
211 if (edev
->ulp_tbl
[BNXT_ROCE_ULP
].msix_requested
)
212 return edev
->ulp_tbl
[BNXT_ROCE_ULP
].msix_base
;
217 int bnxt_get_ulp_stat_ctxs(struct bnxt
*bp
)
219 if (bnxt_ulp_registered(bp
->edev
, BNXT_ROCE_ULP
))
220 return BNXT_MIN_ROCE_STAT_CTXS
;
225 static int bnxt_send_msg(struct bnxt_en_dev
*edev
, int ulp_id
,
226 struct bnxt_fw_msg
*fw_msg
)
228 struct net_device
*dev
= edev
->net
;
229 struct bnxt
*bp
= netdev_priv(dev
);
233 if (ulp_id
!= BNXT_ROCE_ULP
&& bp
->fw_reset_state
)
236 mutex_lock(&bp
->hwrm_cmd_lock
);
238 req
->resp_addr
= cpu_to_le64(bp
->hwrm_cmd_resp_dma_addr
);
239 rc
= _hwrm_send_message(bp
, fw_msg
->msg
, fw_msg
->msg_len
,
242 struct output
*resp
= bp
->hwrm_cmd_resp_addr
;
243 u32 len
= le16_to_cpu(resp
->resp_len
);
245 if (fw_msg
->resp_max_len
< len
)
246 len
= fw_msg
->resp_max_len
;
248 memcpy(fw_msg
->resp
, resp
, len
);
250 mutex_unlock(&bp
->hwrm_cmd_lock
);
254 static void bnxt_ulp_get(struct bnxt_ulp
*ulp
)
256 atomic_inc(&ulp
->ref_count
);
259 static void bnxt_ulp_put(struct bnxt_ulp
*ulp
)
261 atomic_dec(&ulp
->ref_count
);
264 void bnxt_ulp_stop(struct bnxt
*bp
)
266 struct bnxt_en_dev
*edev
= bp
->edev
;
267 struct bnxt_ulp_ops
*ops
;
273 edev
->flags
|= BNXT_EN_FLAG_ULP_STOPPED
;
274 for (i
= 0; i
< BNXT_MAX_ULP
; i
++) {
275 struct bnxt_ulp
*ulp
= &edev
->ulp_tbl
[i
];
277 ops
= rtnl_dereference(ulp
->ulp_ops
);
278 if (!ops
|| !ops
->ulp_stop
)
280 ops
->ulp_stop(ulp
->handle
);
284 void bnxt_ulp_start(struct bnxt
*bp
, int err
)
286 struct bnxt_en_dev
*edev
= bp
->edev
;
287 struct bnxt_ulp_ops
*ops
;
293 edev
->flags
&= ~BNXT_EN_FLAG_ULP_STOPPED
;
298 for (i
= 0; i
< BNXT_MAX_ULP
; i
++) {
299 struct bnxt_ulp
*ulp
= &edev
->ulp_tbl
[i
];
301 ops
= rtnl_dereference(ulp
->ulp_ops
);
302 if (!ops
|| !ops
->ulp_start
)
304 ops
->ulp_start(ulp
->handle
);
308 void bnxt_ulp_sriov_cfg(struct bnxt
*bp
, int num_vfs
)
310 struct bnxt_en_dev
*edev
= bp
->edev
;
311 struct bnxt_ulp_ops
*ops
;
317 for (i
= 0; i
< BNXT_MAX_ULP
; i
++) {
318 struct bnxt_ulp
*ulp
= &edev
->ulp_tbl
[i
];
321 ops
= rcu_dereference(ulp
->ulp_ops
);
322 if (!ops
|| !ops
->ulp_sriov_config
) {
328 ops
->ulp_sriov_config(ulp
->handle
, num_vfs
);
333 void bnxt_ulp_shutdown(struct bnxt
*bp
)
335 struct bnxt_en_dev
*edev
= bp
->edev
;
336 struct bnxt_ulp_ops
*ops
;
342 for (i
= 0; i
< BNXT_MAX_ULP
; i
++) {
343 struct bnxt_ulp
*ulp
= &edev
->ulp_tbl
[i
];
345 ops
= rtnl_dereference(ulp
->ulp_ops
);
346 if (!ops
|| !ops
->ulp_shutdown
)
348 ops
->ulp_shutdown(ulp
->handle
);
352 void bnxt_ulp_irq_stop(struct bnxt
*bp
)
354 struct bnxt_en_dev
*edev
= bp
->edev
;
355 struct bnxt_ulp_ops
*ops
;
357 if (!edev
|| !(edev
->flags
& BNXT_EN_FLAG_MSIX_REQUESTED
))
360 if (bnxt_ulp_registered(bp
->edev
, BNXT_ROCE_ULP
)) {
361 struct bnxt_ulp
*ulp
= &edev
->ulp_tbl
[BNXT_ROCE_ULP
];
363 if (!ulp
->msix_requested
)
366 ops
= rtnl_dereference(ulp
->ulp_ops
);
367 if (!ops
|| !ops
->ulp_irq_stop
)
369 ops
->ulp_irq_stop(ulp
->handle
);
373 void bnxt_ulp_irq_restart(struct bnxt
*bp
, int err
)
375 struct bnxt_en_dev
*edev
= bp
->edev
;
376 struct bnxt_ulp_ops
*ops
;
378 if (!edev
|| !(edev
->flags
& BNXT_EN_FLAG_MSIX_REQUESTED
))
381 if (bnxt_ulp_registered(bp
->edev
, BNXT_ROCE_ULP
)) {
382 struct bnxt_ulp
*ulp
= &edev
->ulp_tbl
[BNXT_ROCE_ULP
];
383 struct bnxt_msix_entry
*ent
= NULL
;
385 if (!ulp
->msix_requested
)
388 ops
= rtnl_dereference(ulp
->ulp_ops
);
389 if (!ops
|| !ops
->ulp_irq_restart
)
393 ent
= kcalloc(ulp
->msix_requested
, sizeof(*ent
),
397 bnxt_fill_msix_vecs(bp
, ent
);
399 ops
->ulp_irq_restart(ulp
->handle
, ent
);
404 void bnxt_ulp_async_events(struct bnxt
*bp
, struct hwrm_async_event_cmpl
*cmpl
)
406 u16 event_id
= le16_to_cpu(cmpl
->event_id
);
407 struct bnxt_en_dev
*edev
= bp
->edev
;
408 struct bnxt_ulp_ops
*ops
;
415 for (i
= 0; i
< BNXT_MAX_ULP
; i
++) {
416 struct bnxt_ulp
*ulp
= &edev
->ulp_tbl
[i
];
418 ops
= rcu_dereference(ulp
->ulp_ops
);
419 if (!ops
|| !ops
->ulp_async_notifier
)
421 if (!ulp
->async_events_bmap
||
422 event_id
> ulp
->max_async_event_id
)
425 /* Read max_async_event_id first before testing the bitmap. */
427 if (test_bit(event_id
, ulp
->async_events_bmap
))
428 ops
->ulp_async_notifier(ulp
->handle
, cmpl
);
433 static int bnxt_register_async_events(struct bnxt_en_dev
*edev
, int ulp_id
,
434 unsigned long *events_bmap
, u16 max_id
)
436 struct net_device
*dev
= edev
->net
;
437 struct bnxt
*bp
= netdev_priv(dev
);
438 struct bnxt_ulp
*ulp
;
440 if (ulp_id
>= BNXT_MAX_ULP
)
443 ulp
= &edev
->ulp_tbl
[ulp_id
];
444 ulp
->async_events_bmap
= events_bmap
;
445 /* Make sure bnxt_ulp_async_events() sees this order */
447 ulp
->max_async_event_id
= max_id
;
448 bnxt_hwrm_func_drv_rgtr(bp
, events_bmap
, max_id
+ 1, true);
452 static const struct bnxt_en_ops bnxt_en_ops_tbl
= {
453 .bnxt_register_device
= bnxt_register_dev
,
454 .bnxt_unregister_device
= bnxt_unregister_dev
,
455 .bnxt_request_msix
= bnxt_req_msix_vecs
,
456 .bnxt_free_msix
= bnxt_free_msix_vecs
,
457 .bnxt_send_fw_msg
= bnxt_send_msg
,
458 .bnxt_register_fw_async_events
= bnxt_register_async_events
,
461 struct bnxt_en_dev
*bnxt_ulp_probe(struct net_device
*dev
)
463 struct bnxt
*bp
= netdev_priv(dev
);
464 struct bnxt_en_dev
*edev
;
468 edev
= kzalloc(sizeof(*edev
), GFP_KERNEL
);
470 return ERR_PTR(-ENOMEM
);
471 edev
->en_ops
= &bnxt_en_ops_tbl
;
472 if (bp
->flags
& BNXT_FLAG_ROCEV1_CAP
)
473 edev
->flags
|= BNXT_EN_FLAG_ROCEV1_CAP
;
474 if (bp
->flags
& BNXT_FLAG_ROCEV2_CAP
)
475 edev
->flags
|= BNXT_EN_FLAG_ROCEV2_CAP
;
477 edev
->pdev
= bp
->pdev
;