File Index
Files and directories
Sign in
FILE

ig3rdma_if.c

File preview with syntax highlighting.

linux-6.19.14/drivers/infiniband/hw/irdma/ig3rdma_if.c 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.