FILE
ig3rdma_if.c
File preview with syntax highlighting.
linux-6.19.14/drivers/infiniband/hw/irdma/ig3rdma_if.c
1// SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB 2/* Copyright (c) 2023 - 2024 Intel Corporation */ 3 4#include "main.h" 5#include <linux/net/intel/iidc_rdma_idpf.h> 6#include "ig3rdma_hw.h" 7 8static void ig3rdma_idc_core_event_handler(struct iidc_rdma_core_dev_info *cdev_info, 9 struct iidc_rdma_event *event) 10{ 11 struct irdma_pci_f *rf = auxiliary_get_drvdata(cdev_info->adev); 12 13 if (*event->type & BIT(IIDC_RDMA_EVENT_WARN_RESET)) { 14 rf->reset = true; 15 rf->sc_dev.vchnl_up = false; 16 } 17} 18 19int ig3rdma_vchnl_send_sync(struct irdma_sc_dev *dev, u8 *msg, u16 len, 20 u8 *recv_msg, u16 *recv_len) 21{ 22 struct iidc_rdma_core_dev_info *cdev_info = dev_to_rf(dev)->cdev; 23 int ret; 24 25 ret = idpf_idc_rdma_vc_send_sync(cdev_info, msg, len, recv_msg, 26 recv_len); 27 if (ret == -ETIMEDOUT) { 28 ibdev_err(&(dev_to_rf(dev)->iwdev->ibdev), 29 "Virtual channel Req <-> Resp completion timeout\n"); 30 dev->vchnl_up = false; 31 } 32 33 return ret; 34} 35 36static int ig3rdma_vchnl_init(struct irdma_pci_f *rf, 37 struct iidc_rdma_core_dev_info *cdev_info, 38 u8 *rdma_ver) 39{ 40 struct iidc_rdma_priv_dev_info *idc_priv = cdev_info->iidc_priv; 41 struct irdma_vchnl_init_info virt_info; 42 u8 gen = rf->rdma_ver; 43 int ret; 44 45 rf->vchnl_wq = alloc_ordered_workqueue("irdma-virtchnl-wq", 0); 46 if (!rf->vchnl_wq) 47 return -ENOMEM; 48 49 mutex_init(&rf->sc_dev.vchnl_mutex); 50 51 virt_info.is_pf = !idc_priv->ftype; 52 virt_info.hw_rev = gen; 53 virt_info.privileged = gen == IRDMA_GEN_2; 54 virt_info.vchnl_wq = rf->vchnl_wq; 55 ret = irdma_sc_vchnl_init(&rf->sc_dev, &virt_info); 56 if (ret) { 57 destroy_workqueue(rf->vchnl_wq); 58 mutex_destroy(&rf->sc_dev.vchnl_mutex); 59 return ret; 60 } 61 62 *rdma_ver = rf->sc_dev.hw_attrs.uk_attrs.hw_rev; 63 64 return 0; 65} 66 67/** 68 * ig3rdma_request_reset - Request a reset 69 * @rf: RDMA PCI function 70 */ 71static void ig3rdma_request_reset(struct irdma_pci_f *rf) 72{ 73 ibdev_warn(&rf->iwdev->ibdev, "Requesting a reset\n"); 74 idpf_idc_request_reset(rf->cdev, IIDC_FUNC_RESET); 75} 76 77static int ig3rdma_cfg_regions(struct irdma_hw *hw, 78 struct iidc_rdma_core_dev_info *cdev_info) 79{ 80 struct iidc_rdma_priv_dev_info *idc_priv = cdev_info->iidc_priv; 81 struct pci_dev *pdev = cdev_info->pdev; 82 int i; 83 84 switch (idc_priv->ftype) { 85 case IIDC_FUNCTION_TYPE_PF: 86 hw->rdma_reg.len = IG3_PF_RDMA_REGION_LEN; 87 hw->rdma_reg.offset = IG3_PF_RDMA_REGION_OFFSET; 88 break; 89 case IIDC_FUNCTION_TYPE_VF: 90 hw->rdma_reg.len = IG3_VF_RDMA_REGION_LEN; 91 hw->rdma_reg.offset = IG3_VF_RDMA_REGION_OFFSET; 92 break; 93 default: 94 return -ENODEV; 95 } 96 97 hw->rdma_reg.addr = ioremap(pci_resource_start(pdev, 0) + hw->rdma_reg.offset, 98 hw->rdma_reg.len); 99 100 if (!hw->rdma_reg.addr) 101 return -ENOMEM; 102 103 hw->num_io_regions = le16_to_cpu(idc_priv->num_memory_regions); 104 hw->io_regs = kcalloc(hw->num_io_regions, 105 sizeof(struct irdma_mmio_region), GFP_KERNEL); 106 107 if (!hw->io_regs) { 108 iounmap(hw->rdma_reg.addr); 109 return -ENOMEM; 110 } 111 112 for (i = 0; i < hw->num_io_regions; i++) { 113 hw->io_regs[i].addr = 114 idc_priv->mapped_mem_regions[i].region_addr; 115 hw->io_regs[i].len = 116 le64_to_cpu(idc_priv->mapped_mem_regions[i].size); 117 hw->io_regs[i].offset = 118 le64_to_cpu(idc_priv->mapped_mem_regions[i].start_offset); 119 } 120 121 return 0; 122} 123 124static void ig3rdma_decfg_rf(struct irdma_pci_f *rf) 125{ 126 struct irdma_hw *hw = &rf->hw; 127 128 mutex_destroy(&rf->ah_tbl_lock); 129 destroy_workqueue(rf->vchnl_wq); 130 mutex_destroy(&rf->sc_dev.vchnl_mutex); 131 kfree(hw->io_regs); 132 iounmap(hw->rdma_reg.addr); 133} 134 135static int ig3rdma_cfg_rf(struct irdma_pci_f *rf, 136 struct iidc_rdma_core_dev_info *cdev_info) 137{ 138 struct iidc_rdma_priv_dev_info *idc_priv = cdev_info->iidc_priv; 139 int err; 140 141 rf->sc_dev.hw = &rf->hw; 142 rf->cdev = cdev_info; 143 rf->pcidev = cdev_info->pdev; 144 rf->hw.device = &rf->pcidev->dev; 145 rf->msix_count = idc_priv->msix_count; 146 rf->msix_entries = idc_priv->msix_entries; 147 148 err = ig3rdma_vchnl_init(rf, cdev_info, &rf->rdma_ver); 149 if (err) 150 return err; 151 152 err = ig3rdma_cfg_regions(&rf->hw, cdev_info); 153 if (err) { 154 destroy_workqueue(rf->vchnl_wq); 155 mutex_destroy(&rf->sc_dev.vchnl_mutex); 156 return err; 157 } 158 159 rf->protocol_used = IRDMA_ROCE_PROTOCOL_ONLY; 160 rf->rsrc_profile = IRDMA_HMC_PROFILE_DEFAULT; 161 rf->rst_to = IRDMA_RST_TIMEOUT_HZ; 162 rf->gen_ops.request_reset = ig3rdma_request_reset; 163 rf->limits_sel = 7; 164 mutex_init(&rf->ah_tbl_lock); 165 166 return 0; 167} 168 169static int ig3rdma_core_probe(struct auxiliary_device *aux_dev, 170 const struct auxiliary_device_id *id) 171{ 172 struct iidc_rdma_core_auxiliary_dev *idc_adev = 173 container_of(aux_dev, struct iidc_rdma_core_auxiliary_dev, adev); 174 struct iidc_rdma_core_dev_info *cdev_info = idc_adev->cdev_info; 175 struct irdma_pci_f *rf; 176 int err; 177 178 rf = kzalloc(sizeof(*rf), GFP_KERNEL); 179 if (!rf) 180 return -ENOMEM; 181 182 err = ig3rdma_cfg_rf(rf, cdev_info); 183 if (err) 184 goto err_cfg_rf; 185 186 err = irdma_ctrl_init_hw(rf); 187 if (err) 188 goto err_ctrl_init; 189 190 auxiliary_set_drvdata(aux_dev, rf); 191 192 err = idpf_idc_vport_dev_ctrl(cdev_info, true); 193 if (err) 194 goto err_vport_ctrl; 195 196 return 0; 197 198err_vport_ctrl: 199 irdma_ctrl_deinit_hw(rf); 200err_ctrl_init: 201 ig3rdma_decfg_rf(rf); 202err_cfg_rf: 203 kfree(rf); 204 205 return err; 206} 207 208static void ig3rdma_core_remove(struct auxiliary_device *aux_dev) 209{ 210 struct iidc_rdma_core_auxiliary_dev *idc_adev = 211 container_of(aux_dev, struct iidc_rdma_core_auxiliary_dev, adev); 212 struct iidc_rdma_core_dev_info *cdev_info = idc_adev->cdev_info; 213 struct irdma_pci_f *rf = auxiliary_get_drvdata(aux_dev); 214 215 idpf_idc_vport_dev_ctrl(cdev_info, false); 216 irdma_ctrl_deinit_hw(rf); 217 ig3rdma_decfg_rf(rf); 218 kfree(rf); 219} 220 221static const struct auxiliary_device_id ig3rdma_core_auxiliary_id_table[] = { 222 {.name = "idpf.8086.rdma.core", }, 223 {}, 224}; 225 226MODULE_DEVICE_TABLE(auxiliary, ig3rdma_core_auxiliary_id_table); 227 228struct iidc_rdma_core_auxiliary_drv ig3rdma_core_auxiliary_drv = { 229 .adrv = { 230 .name = "core", 231 .id_table = ig3rdma_core_auxiliary_id_table, 232 .probe = ig3rdma_core_probe, 233 .remove = ig3rdma_core_remove, 234 }, 235 .event_handler = ig3rdma_idc_core_event_handler, 236};
~/
Read-only file preview.