Commit 67f27b8b authored by Shannon Nelson's avatar Shannon Nelson Committed by Michael S. Tsirkin
Browse files

pds_vdpa: subscribe to the pds_core events



Register for the pds_core's notification events, primarily to
find out when the FW has been reset so we can pass this on
back up the chain.

Signed-off-by: default avatarShannon Nelson <shannon.nelson@amd.com>
Acked-by: default avatarJason Wang <jasowang@redhat.com>
Message-Id: <20230519215632.12343-11-shannon.nelson@amd.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 151cc834
Loading
Loading
Loading
Loading
+58 −1
Original line number Diff line number Diff line
@@ -23,6 +23,52 @@ static struct pds_vdpa_device *vdpa_to_pdsv(struct vdpa_device *vdpa_dev)
	return container_of(vdpa_dev, struct pds_vdpa_device, vdpa_dev);
}

static int pds_vdpa_notify_handler(struct notifier_block *nb,
				   unsigned long ecode,
				   void *data)
{
	struct pds_vdpa_device *pdsv = container_of(nb, struct pds_vdpa_device, nb);
	struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev;

	dev_dbg(dev, "%s: event code %lu\n", __func__, ecode);

	if (ecode == PDS_EVENT_RESET || ecode == PDS_EVENT_LINK_CHANGE) {
		if (pdsv->config_cb.callback)
			pdsv->config_cb.callback(pdsv->config_cb.private);
	}

	return 0;
}

static int pds_vdpa_register_event_handler(struct pds_vdpa_device *pdsv)
{
	struct device *dev = &pdsv->vdpa_aux->padev->aux_dev.dev;
	struct notifier_block *nb = &pdsv->nb;
	int err;

	if (!nb->notifier_call) {
		nb->notifier_call = pds_vdpa_notify_handler;
		err = pdsc_register_notify(nb);
		if (err) {
			nb->notifier_call = NULL;
			dev_err(dev, "failed to register pds event handler: %ps\n",
				ERR_PTR(err));
			return -EINVAL;
		}
		dev_dbg(dev, "pds event handler registered\n");
	}

	return 0;
}

static void pds_vdpa_unregister_event_handler(struct pds_vdpa_device *pdsv)
{
	if (pdsv->nb.notifier_call) {
		pdsc_unregister_notify(&pdsv->nb);
		pdsv->nb.notifier_call = NULL;
	}
}

static int pds_vdpa_set_vq_address(struct vdpa_device *vdpa_dev, u16 qid,
				   u64 desc_addr, u64 driver_addr, u64 device_addr)
{
@@ -595,6 +641,12 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,

	pdsv->vdpa_dev.mdev = &vdpa_aux->vdpa_mdev;

	err = pds_vdpa_register_event_handler(pdsv);
	if (err) {
		dev_err(dev, "Failed to register for PDS events: %pe\n", ERR_PTR(err));
		goto err_unmap;
	}

	/* We use the _vdpa_register_device() call rather than the
	 * vdpa_register_device() to avoid a deadlock because our
	 * dev_add() is called with the vdpa_dev_lock already set
@@ -603,13 +655,15 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
	err = _vdpa_register_device(&pdsv->vdpa_dev, pdsv->num_vqs);
	if (err) {
		dev_err(dev, "Failed to register to vDPA bus: %pe\n", ERR_PTR(err));
		goto err_unmap;
		goto err_unevent;
	}

	pds_vdpa_debugfs_add_vdpadev(vdpa_aux);

	return 0;

err_unevent:
	pds_vdpa_unregister_event_handler(pdsv);
err_unmap:
	put_device(&pdsv->vdpa_dev.dev);
	vdpa_aux->pdsv = NULL;
@@ -619,8 +673,11 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
static void pds_vdpa_dev_del(struct vdpa_mgmt_dev *mdev,
			     struct vdpa_device *vdpa_dev)
{
	struct pds_vdpa_device *pdsv = vdpa_to_pdsv(vdpa_dev);
	struct pds_vdpa_aux *vdpa_aux;

	pds_vdpa_unregister_event_handler(pdsv);

	vdpa_aux = container_of(mdev, struct pds_vdpa_aux, vdpa_mdev);
	_vdpa_unregister_device(vdpa_dev);

+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ struct pds_vdpa_device {
	u8 vdpa_index;			/* rsvd for future subdevice use */
	u8 num_vqs;			/* num vqs in use */
	struct vdpa_callback config_cb;
	struct notifier_block nb;
};

#define PDS_VDPA_PACKED_INVERT_IDX	0x8000