FILE
bnge_auxr.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/broadcom/bnge/bnge_auxr.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.