File Index
Files and directories
Sign in
FILE

bnge_auxr.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/broadcom/bnge/bnge_auxr.c C
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (c) 2025 Broadcom.
  3
  4#include <linux/module.h>
  5
  6#include <linux/kernel.h>
  7#include <linux/errno.h>
  8#include <linux/interrupt.h>
  9#include <linux/pci.h>
 10#include <linux/netdevice.h>
 11#include <linux/rtnetlink.h>
 12#include <linux/bitops.h>
 13#include <linux/irq.h>
 14#include <asm/byteorder.h>
 15#include <linux/bitmap.h>
 16#include <linux/auxiliary_bus.h>
 17#include <linux/bnxt/hsi.h>
 18
 19#include "bnge.h"
 20#include "bnge_hwrm.h"
 21#include "bnge_auxr.h"
 22
 23static DEFINE_IDA(bnge_aux_dev_ids);
 24
 25static void bnge_fill_msix_vecs(struct bnge_dev *bd,
 26				struct bnge_msix_info *info)
 27{
 28	struct bnge_auxr_dev *auxr_dev = bd->auxr_dev;
 29	int num_msix, i;
 30
 31	if (!auxr_dev->auxr_info->msix_requested) {
 32		dev_warn(bd->dev, "Requested MSI-X vectors not allocated\n");
 33		return;
 34	}
 35	num_msix = auxr_dev->auxr_info->msix_requested;
 36	for (i = 0; i < num_msix; i++) {
 37		info[i].vector = bd->irq_tbl[i].vector;
 38		info[i].db_offset = bd->db_offset;
 39		info[i].ring_idx = i;
 40	}
 41}
 42
 43int bnge_register_dev(struct bnge_auxr_dev *auxr_dev,
 44		      void *handle)
 45{
 46	struct bnge_dev *bd = pci_get_drvdata(auxr_dev->pdev);
 47	struct bnge_auxr_info *auxr_info;
 48	int rc = 0;
 49
 50	netdev_lock(bd->netdev);
 51	mutex_lock(&auxr_dev->auxr_dev_lock);
 52	if (!bd->irq_tbl) {
 53		rc = -ENODEV;
 54		goto exit;
 55	}
 56
 57	if (!bnge_aux_has_enough_resources(bd)) {
 58		rc = -ENOMEM;
 59		goto exit;
 60	}
 61
 62	auxr_info = auxr_dev->auxr_info;
 63	auxr_info->handle = handle;
 64
 65	auxr_info->msix_requested = bd->aux_num_msix;
 66
 67	bnge_fill_msix_vecs(bd, bd->auxr_dev->msix_info);
 68	auxr_dev->flags |= BNGE_ARDEV_MSIX_ALLOC;
 69
 70exit:
 71	mutex_unlock(&auxr_dev->auxr_dev_lock);
 72	netdev_unlock(bd->netdev);
 73	return rc;
 74}
 75EXPORT_SYMBOL(bnge_register_dev);
 76
 77void bnge_unregister_dev(struct bnge_auxr_dev *auxr_dev)
 78{
 79	struct bnge_dev *bd = pci_get_drvdata(auxr_dev->pdev);
 80	struct bnge_auxr_info *auxr_info;
 81
 82	auxr_info = auxr_dev->auxr_info;
 83	netdev_lock(bd->netdev);
 84	mutex_lock(&auxr_dev->auxr_dev_lock);
 85	if (auxr_info->msix_requested)
 86		auxr_dev->flags &= ~BNGE_ARDEV_MSIX_ALLOC;
 87	auxr_info->msix_requested = 0;
 88
 89	mutex_unlock(&auxr_dev->auxr_dev_lock);
 90	netdev_unlock(bd->netdev);
 91}
 92EXPORT_SYMBOL(bnge_unregister_dev);
 93
 94int bnge_send_msg(struct bnge_auxr_dev *auxr_dev, struct bnge_fw_msg *fw_msg)
 95{
 96	struct bnge_dev *bd = pci_get_drvdata(auxr_dev->pdev);
 97	struct output *resp;
 98	struct input *req;
 99	u32 resp_len;
100	int rc;
101
102	rc = bnge_hwrm_req_init(bd, req, 0 /* don't care */);
103	if (rc)
104		return rc;
105
106	rc = bnge_hwrm_req_replace(bd, req, fw_msg->msg, fw_msg->msg_len);
107	if (rc)
108		goto drop_req;
109
110	bnge_hwrm_req_timeout(bd, req, fw_msg->timeout);
111	resp = bnge_hwrm_req_hold(bd, req);
112	rc = bnge_hwrm_req_send(bd, req);
113	resp_len = le16_to_cpu(resp->resp_len);
114	if (resp_len) {
115		if (fw_msg->resp_max_len < resp_len)
116			resp_len = fw_msg->resp_max_len;
117
118		memcpy(fw_msg->resp, resp, resp_len);
119	}
120drop_req:
121	bnge_hwrm_req_drop(bd, req);
122	return rc;
123}
124EXPORT_SYMBOL(bnge_send_msg);
125
126void bnge_rdma_aux_device_uninit(struct bnge_dev *bd)
127{
128	struct bnge_auxr_priv *aux_priv;
129	struct auxiliary_device *adev;
130
131	/* Skip if no auxiliary device init was done. */
132	if (!bd->aux_priv)
133		return;
134
135	aux_priv = bd->aux_priv;
136	adev = &aux_priv->aux_dev;
137	auxiliary_device_uninit(adev);
138}
139
140static void bnge_aux_dev_release(struct device *dev)
141{
142	struct bnge_auxr_priv *aux_priv =
143			container_of(dev, struct bnge_auxr_priv, aux_dev.dev);
144	struct bnge_dev *bd = pci_get_drvdata(aux_priv->auxr_dev->pdev);
145
146	ida_free(&bnge_aux_dev_ids, aux_priv->id);
147	kfree(aux_priv->auxr_dev->auxr_info);
148	bd->auxr_dev = NULL;
149	kfree(aux_priv->auxr_dev);
150	kfree(aux_priv);
151	bd->aux_priv = NULL;
152}
153
154void bnge_rdma_aux_device_del(struct bnge_dev *bd)
155{
156	if (!bd->auxr_dev)
157		return;
158
159	auxiliary_device_delete(&bd->aux_priv->aux_dev);
160}
161
162static void bnge_set_auxr_dev_info(struct bnge_auxr_dev *auxr_dev,
163				   struct bnge_dev *bd)
164{
165	auxr_dev->pdev = bd->pdev;
166	auxr_dev->l2_db_size = bd->db_size;
167	auxr_dev->l2_db_size_nc = bd->db_size;
168	auxr_dev->l2_db_offset = bd->db_offset;
169	mutex_init(&auxr_dev->auxr_dev_lock);
170
171	if (bd->flags & BNGE_EN_ROCE_V1)
172		auxr_dev->flags |= BNGE_ARDEV_ROCEV1_SUPP;
173	if (bd->flags & BNGE_EN_ROCE_V2)
174		auxr_dev->flags |= BNGE_ARDEV_ROCEV2_SUPP;
175
176	auxr_dev->chip_num = bd->chip_num;
177	auxr_dev->hw_ring_stats_size = bd->hw_ring_stats_size;
178	auxr_dev->pf_port_id = bd->pf.port_id;
179	auxr_dev->en_state = bd->state;
180	auxr_dev->bar0 = bd->bar0;
181}
182
183void bnge_rdma_aux_device_add(struct bnge_dev *bd)
184{
185	struct auxiliary_device *aux_dev;
186	int rc;
187
188	if (!bd->auxr_dev)
189		return;
190
191	aux_dev = &bd->aux_priv->aux_dev;
192	rc = auxiliary_device_add(aux_dev);
193	if (rc) {
194		dev_warn(bd->dev, "Failed to add auxiliary device for ROCE\n");
195		auxiliary_device_uninit(aux_dev);
196		bd->flags &= ~BNGE_EN_ROCE;
197		return;
198	}
199
200	bd->auxr_dev->net = bd->netdev;
201}
202
203void bnge_rdma_aux_device_init(struct bnge_dev *bd)
204{
205	struct auxiliary_device *aux_dev;
206	struct bnge_auxr_info *auxr_info;
207	struct bnge_auxr_priv *aux_priv;
208	struct bnge_auxr_dev *auxr_dev;
209	int rc;
210
211	if (!bnge_is_roce_en(bd))
212		return;
213
214	aux_priv = kzalloc(sizeof(*aux_priv), GFP_KERNEL);
215	if (!aux_priv)
216		goto exit;
217
218	aux_priv->id = ida_alloc(&bnge_aux_dev_ids, GFP_KERNEL);
219	if (aux_priv->id < 0) {
220		dev_warn(bd->dev, "ida alloc failed for aux device\n");
221		kfree(aux_priv);
222		goto exit;
223	}
224
225	aux_dev = &aux_priv->aux_dev;
226	aux_dev->id = aux_priv->id;
227	aux_dev->name = "rdma";
228	aux_dev->dev.parent = &bd->pdev->dev;
229	aux_dev->dev.release = bnge_aux_dev_release;
230
231	rc = auxiliary_device_init(aux_dev);
232	if (rc) {
233		ida_free(&bnge_aux_dev_ids, aux_priv->id);
234		kfree(aux_priv);
235		goto exit;
236	}
237	bd->aux_priv = aux_priv;
238
239	auxr_dev = kzalloc(sizeof(*auxr_dev), GFP_KERNEL);
240	if (!auxr_dev)
241		goto aux_dev_uninit;
242
243	aux_priv->auxr_dev = auxr_dev;
244
245	auxr_info = kzalloc(sizeof(*auxr_info), GFP_KERNEL);
246	if (!auxr_info)
247		goto aux_dev_uninit;
248
249	auxr_dev->auxr_info = auxr_info;
250	bd->auxr_dev = auxr_dev;
251	bnge_set_auxr_dev_info(auxr_dev, bd);
252
253	return;
254
255aux_dev_uninit:
256	auxiliary_device_uninit(aux_dev);
257exit:
258	bd->flags &= ~BNGE_EN_ROCE;
259}
~/ Read-only file preview.