|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | +/* Copyright(c) 2023 Advanced Micro Devices, Inc */ |
| 3 | + |
| 4 | +#include <linux/pci.h> |
| 5 | + |
| 6 | +#include "core.h" |
| 7 | +#include <linux/pds/pds_auxbus.h> |
| 8 | + |
| 9 | +static void pdsc_auxbus_dev_release(struct device *dev) |
| 10 | +{ |
| 11 | + struct pds_auxiliary_dev *padev = |
| 12 | + container_of(dev, struct pds_auxiliary_dev, aux_dev.dev); |
| 13 | + |
| 14 | + kfree(padev); |
| 15 | +} |
| 16 | + |
| 17 | +static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf, |
| 18 | + struct pdsc *pf, |
| 19 | + char *name) |
| 20 | +{ |
| 21 | + struct auxiliary_device *aux_dev; |
| 22 | + struct pds_auxiliary_dev *padev; |
| 23 | + int err; |
| 24 | + |
| 25 | + padev = kzalloc(sizeof(*padev), GFP_KERNEL); |
| 26 | + if (!padev) |
| 27 | + return ERR_PTR(-ENOMEM); |
| 28 | + |
| 29 | + padev->vf_pdev = cf->pdev; |
| 30 | + |
| 31 | + aux_dev = &padev->aux_dev; |
| 32 | + aux_dev->name = name; |
| 33 | + aux_dev->id = cf->uid; |
| 34 | + aux_dev->dev.parent = cf->dev; |
| 35 | + aux_dev->dev.release = pdsc_auxbus_dev_release; |
| 36 | + |
| 37 | + err = auxiliary_device_init(aux_dev); |
| 38 | + if (err < 0) { |
| 39 | + dev_warn(cf->dev, "auxiliary_device_init of %s failed: %pe\n", |
| 40 | + name, ERR_PTR(err)); |
| 41 | + goto err_out; |
| 42 | + } |
| 43 | + |
| 44 | + err = auxiliary_device_add(aux_dev); |
| 45 | + if (err) { |
| 46 | + dev_warn(cf->dev, "auxiliary_device_add of %s failed: %pe\n", |
| 47 | + name, ERR_PTR(err)); |
| 48 | + goto err_out_uninit; |
| 49 | + } |
| 50 | + |
| 51 | + return padev; |
| 52 | + |
| 53 | +err_out_uninit: |
| 54 | + auxiliary_device_uninit(aux_dev); |
| 55 | +err_out: |
| 56 | + kfree(padev); |
| 57 | + return ERR_PTR(err); |
| 58 | +} |
| 59 | + |
| 60 | +int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf) |
| 61 | +{ |
| 62 | + struct pds_auxiliary_dev *padev; |
| 63 | + int err = 0; |
| 64 | + |
| 65 | + mutex_lock(&pf->config_lock); |
| 66 | + |
| 67 | + padev = pf->vfs[cf->vf_id].padev; |
| 68 | + if (padev) { |
| 69 | + auxiliary_device_delete(&padev->aux_dev); |
| 70 | + auxiliary_device_uninit(&padev->aux_dev); |
| 71 | + } |
| 72 | + pf->vfs[cf->vf_id].padev = NULL; |
| 73 | + |
| 74 | + mutex_unlock(&pf->config_lock); |
| 75 | + return err; |
| 76 | +} |
| 77 | + |
| 78 | +int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf) |
| 79 | +{ |
| 80 | + struct pds_auxiliary_dev *padev; |
| 81 | + enum pds_core_vif_types vt; |
| 82 | + u16 vt_support; |
| 83 | + int err = 0; |
| 84 | + |
| 85 | + mutex_lock(&pf->config_lock); |
| 86 | + |
| 87 | + /* We only support vDPA so far, so it is the only one to |
| 88 | + * be verified that it is available in the Core device and |
| 89 | + * enabled in the devlink param. In the future this might |
| 90 | + * become a loop for several VIF types. |
| 91 | + */ |
| 92 | + |
| 93 | + /* Verify that the type is supported and enabled. It is not |
| 94 | + * an error if there is no auxbus device support for this |
| 95 | + * VF, it just means something else needs to happen with it. |
| 96 | + */ |
| 97 | + vt = PDS_DEV_TYPE_VDPA; |
| 98 | + vt_support = !!le16_to_cpu(pf->dev_ident.vif_types[vt]); |
| 99 | + if (!(vt_support && |
| 100 | + pf->viftype_status[vt].supported && |
| 101 | + pf->viftype_status[vt].enabled)) |
| 102 | + goto out_unlock; |
| 103 | + |
| 104 | + padev = pdsc_auxbus_dev_register(cf, pf, |
| 105 | + pf->viftype_status[vt].name); |
| 106 | + if (IS_ERR(padev)) { |
| 107 | + err = PTR_ERR(padev); |
| 108 | + goto out_unlock; |
| 109 | + } |
| 110 | + pf->vfs[cf->vf_id].padev = padev; |
| 111 | + |
| 112 | +out_unlock: |
| 113 | + mutex_unlock(&pf->config_lock); |
| 114 | + return err; |
| 115 | +} |
0 commit comments