Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-23 Thread Jason Wang



On 2019/10/23 下午5:24, Zhu, Lingshan wrote:



set_config/get_config is missing. It looks to me they are not 
hard, just implementing the access to dev_cfg. It's key to make 
kernel virtio driver to work.


And in the new version of virito-mdev, features like _F_LOG_ALL 
should be advertised through get_mdev_features.
IMHO, currently the driver can work without set/get_config, 
vhost_mdev doesn't call them for now.



Yes, but it was required by virtio_mdev for host driver to work, and 
it looks to me it's not hard to add them. If possible please add 
them and "virtio" type then we can use the ops for both the case of 
VM and containers.

sure


Hello Jason,

Just want to double confirm the implementation of set/get_config, for 
now, dev_cfg only contains mac[6], status and max_virtqueue_pairs, is 
that enough to support virtio_mdev?


THanks!



Yes, and it depends on the features that you want to advertise. If you 
don't want to advertise MQ, there's no need to expose max_virtqueue_pairs.


Thanks



Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-23 Thread Zhu, Lingshan



On 10/22/2019 2:53 PM, Zhu Lingshan wrote:


On 10/21/2019 6:19 PM, Jason Wang wrote:


On 2019/10/21 下午5:53, Zhu, Lingshan wrote:


On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
  drivers/vhost/ifcvf/ifcvf_main.c | 541 
+++

  1 file changed, 541 insertions(+)
  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c 
b/drivers/vhost/ifcvf/ifcvf_main.c

new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING    "0.1"
+#define DRIVER_AUTHOR    "Intel Corporation"
+#define IFCVF_DRIVER_NAME    "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+    struct vring_info *vring = arg;
+
+    if (vring->cb.callback)
+    return vring->cb.callback(vring->cb.private);
+
+    return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+    return IFC_SUPPORTED_FEATURES;



I would expect this should be done by querying the hw. Or IFC VF 
can't get any update through its firmware?


Hi Jason,

Thanks for your comments, for now driver just support these features.



Ok, it should work but less flexible, we can change it in the future.

sure!









+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 
features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 
qid)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw 
since it's an internal state.

for now, it's working, we intend to support LM in next version drivers.



I'm not sure I understand here, I don't see any synchronization 
between the hardware and last_avail_idx, so last_avail_idx should not 
change.


Btw, what did "LM" mean :) ?


I can add bar IO operations here, LM = live migration, sorry for the 
abbreviation.









+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 
qid, u64 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].last_used_idx = num;



I fail to understand why last_used_idx is needed. It looks to me 
the used idx in the used ring is sufficient.

I will remove it.




+ vf->vring[qid].last_avail_idx = num;



Do we need a synchronization with hw immediately here?



+
+    return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, 
u16 idx,

+ u64 desc_area, u64 driver_area,
+ u64 device_area)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].desc = desc_area;
+    vf->vring[idx].avail = driver_area;
+    vf->vring[idx].used = device_area;
+
+    return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 
qid, u32 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+    u16 qid, bool ready)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 
qid)

+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+ struct virtio_mdev_callback *cb)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return 

Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-23 Thread Jason Wang



On 2019/10/23 下午2:19, Zhu, Lingshan wrote:


On 10/22/2019 9:05 PM, Jason Wang wrote:


On 2019/10/22 下午2:53, Zhu Lingshan wrote:


On 10/21/2019 6:19 PM, Jason Wang wrote:


On 2019/10/21 下午5:53, Zhu, Lingshan wrote:


On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---



[...]











+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, 
u64 features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, 
u16 qid)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw 
since it's an internal state.
for now, it's working, we intend to support LM in next version 
drivers.



I'm not sure I understand here, I don't see any synchronization 
between the hardware and last_avail_idx, so last_avail_idx should 
not change.


Btw, what did "LM" mean :) ?


I can add bar IO operations here, LM = live migration, sorry for the 
abbreviation.



Just make sure I understand here, I believe you mean reading 
last_avail_idx through IO bar here?


Thanks


Hi Jason,

Yes, I mean last_avail_idx. is that correct?

THanks



Yes.

Thanks











Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-23 Thread Zhu, Lingshan



On 10/22/2019 9:05 PM, Jason Wang wrote:


On 2019/10/22 下午2:53, Zhu Lingshan wrote:


On 10/21/2019 6:19 PM, Jason Wang wrote:


On 2019/10/21 下午5:53, Zhu, Lingshan wrote:


On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---



[...]











+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 
features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 
qid)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw 
since it's an internal state.
for now, it's working, we intend to support LM in next version 
drivers.



I'm not sure I understand here, I don't see any synchronization 
between the hardware and last_avail_idx, so last_avail_idx should 
not change.


Btw, what did "LM" mean :) ?


I can add bar IO operations here, LM = live migration, sorry for the 
abbreviation.



Just make sure I understand here, I believe you mean reading 
last_avail_idx through IO bar here?


Thanks


Hi Jason,

Yes, I mean last_avail_idx. is that correct?

THanks






Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-22 Thread Jason Wang



On 2019/10/22 下午2:53, Zhu Lingshan wrote:


On 10/21/2019 6:19 PM, Jason Wang wrote:


On 2019/10/21 下午5:53, Zhu, Lingshan wrote:


On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---



[...]











+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 
features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 
qid)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw 
since it's an internal state.

for now, it's working, we intend to support LM in next version drivers.



I'm not sure I understand here, I don't see any synchronization 
between the hardware and last_avail_idx, so last_avail_idx should not 
change.


Btw, what did "LM" mean :) ?


I can add bar IO operations here, LM = live migration, sorry for the 
abbreviation.



Just make sure I understand here, I believe you mean reading 
last_avail_idx through IO bar here?


Thanks




Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-22 Thread Zhu Lingshan



On 10/21/2019 6:19 PM, Jason Wang wrote:


On 2019/10/21 下午5:53, Zhu, Lingshan wrote:


On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
  drivers/vhost/ifcvf/ifcvf_main.c | 541 
+++

  1 file changed, 541 insertions(+)
  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c 
b/drivers/vhost/ifcvf/ifcvf_main.c

new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING    "0.1"
+#define DRIVER_AUTHOR    "Intel Corporation"
+#define IFCVF_DRIVER_NAME    "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+    struct vring_info *vring = arg;
+
+    if (vring->cb.callback)
+    return vring->cb.callback(vring->cb.private);
+
+    return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+    return IFC_SUPPORTED_FEATURES;



I would expect this should be done by querying the hw. Or IFC VF 
can't get any update through its firmware?


Hi Jason,

Thanks for your comments, for now driver just support these features.



Ok, it should work but less flexible, we can change it in the future.

sure!









+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 
features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw since 
it's an internal state.

for now, it's working, we intend to support LM in next version drivers.



I'm not sure I understand here, I don't see any synchronization 
between the hardware and last_avail_idx, so last_avail_idx should not 
change.


Btw, what did "LM" mean :) ?


I can add bar IO operations here, LM = live migration, sorry for the 
abbreviation.









+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 
qid, u64 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].last_used_idx = num;



I fail to understand why last_used_idx is needed. It looks to me the 
used idx in the used ring is sufficient.

I will remove it.




+ vf->vring[qid].last_avail_idx = num;



Do we need a synchronization with hw immediately here?



+
+    return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 
idx,

+ u64 desc_area, u64 driver_area,
+ u64 device_area)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].desc = desc_area;
+    vf->vring[idx].avail = driver_area;
+    vf->vring[idx].used = device_area;
+
+    return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 
qid, u32 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+    u16 qid, bool ready)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 
qid)

+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+ struct virtio_mdev_callback *cb)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->status;
+}
+
+static u32 

Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-21 Thread Jason Wang



On 2019/10/21 下午5:53, Zhu, Lingshan wrote:


On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
  drivers/vhost/ifcvf/ifcvf_main.c | 541 
+++

  1 file changed, 541 insertions(+)
  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c 
b/drivers/vhost/ifcvf/ifcvf_main.c

new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING    "0.1"
+#define DRIVER_AUTHOR    "Intel Corporation"
+#define IFCVF_DRIVER_NAME    "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+    struct vring_info *vring = arg;
+
+    if (vring->cb.callback)
+    return vring->cb.callback(vring->cb.private);
+
+    return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+    return IFC_SUPPORTED_FEATURES;



I would expect this should be done by querying the hw. Or IFC VF 
can't get any update through its firmware?


Hi Jason,

Thanks for your comments, for now driver just support these features.



Ok, it should work but less flexible, we can change it in the future.








+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 
features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw since 
it's an internal state.

for now, it's working, we intend to support LM in next version drivers.



I'm not sure I understand here, I don't see any synchronization between 
the hardware and last_avail_idx, so last_avail_idx should not change.


Btw, what did "LM" mean :) ?






+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 
qid, u64 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].last_used_idx = num;



I fail to understand why last_used_idx is needed. It looks to me the 
used idx in the used ring is sufficient.

I will remove it.




+    vf->vring[qid].last_avail_idx = num;



Do we need a synchronization with hw immediately here?



+
+    return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 
idx,

+ u64 desc_area, u64 driver_area,
+ u64 device_area)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].desc = desc_area;
+    vf->vring[idx].avail = driver_area;
+    vf->vring[idx].used = device_area;
+
+    return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 
qid, u32 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+    u16 qid, bool ready)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+ struct virtio_mdev_callback *cb)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = 

Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-21 Thread Zhu, Lingshan



On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
  drivers/vhost/ifcvf/ifcvf_main.c | 541 
+++

  1 file changed, 541 insertions(+)
  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c 
b/drivers/vhost/ifcvf/ifcvf_main.c

new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING    "0.1"
+#define DRIVER_AUTHOR    "Intel Corporation"
+#define IFCVF_DRIVER_NAME    "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+    struct vring_info *vring = arg;
+
+    if (vring->cb.callback)
+    return vring->cb.callback(vring->cb.private);
+
+    return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+    return IFC_SUPPORTED_FEATURES;



I would expect this should be done by querying the hw. Or IFC VF can't 
get any update through its firmware?


Hi Jason,

Thanks for your comments, for now driver just support these features.





+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 
features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw since 
it's an internal state.

for now, it's working, we intend to support LM in next version drivers.




+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 
qid, u64 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].last_used_idx = num;



I fail to understand why last_used_idx is needed. It looks to me the 
used idx in the used ring is sufficient.

I will remove it.




+    vf->vring[qid].last_avail_idx = num;



Do we need a synchronization with hw immediately here?



+
+    return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
+ u64 desc_area, u64 driver_area,
+ u64 device_area)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].desc = desc_area;
+    vf->vring[idx].avail = driver_area;
+    vf->vring[idx].used = device_area;
+
+    return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, 
u32 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+    u16 qid, bool ready)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+ struct virtio_mdev_callback *cb)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->generation;
+}
+
+static int ifcvf_mdev_get_version(struct mdev_device *mdev)
+{
+    return VIRTIO_MDEV_VERSION;
+}
+
+static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
+{
+    return IFCVF_DEVICE_ID;
+}
+
+static u32 ifcvf_mdev_get_vendor_id(struct 

Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-21 Thread Zhu, Lingshan



On 10/16/2019 5:53 PM, Simon Horman wrote:

Hi Zhu,

thanks for your patch.

On Wed, Oct 16, 2019 at 09:03:18AM +0800, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
  drivers/vhost/ifcvf/ifcvf_main.c | 541 +++
  1 file changed, 541 insertions(+)
  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c b/drivers/vhost/ifcvf/ifcvf_main.c
new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING "0.1"
+#define DRIVER_AUTHOR  "Intel Corporation"
+#define IFCVF_DRIVER_NAME  "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+   struct vring_info *vring = arg;
+
+   if (vring->cb.callback)
+   return vring->cb.callback(vring->cb.private);
+
+   return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+   return IFC_SUPPORTED_FEATURES;
+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 features)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);

Perhaps a helper that takes a struct mdev_device would be useful.
The pattern above seems to be repeated many times.


Hi Simon, thanks a lot for your comments.

sure, can do




+
+   vf->req_features = features;
+
+   return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].last_avail_idx;
+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 qid, u64 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].last_used_idx = num;
+   vf->vring[qid].last_avail_idx = num;
+
+   return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
+u64 desc_area, u64 driver_area,
+u64 device_area)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].desc = desc_area;
+   vf->vring[idx].avail = driver_area;
+   vf->vring[idx].used = device_area;
+
+   return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, u32 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+   u16 qid, bool ready)

u16 should be vertically whitespace aligned with struct mdev_device.


+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+struct virtio_mdev_callback *cb)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->generation;
+}
+
+static int ifcvf_mdev_get_version(struct mdev_device *mdev)
+{
+   return VIRTIO_MDEV_VERSION;
+}
+
+static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
+{
+   return IFCVF_DEVICE_ID;
+}
+
+static u32 ifcvf_mdev_get_vendor_id(struct mdev_device *mdev)
+{
+   return IFCVF_VENDOR_ID;
+}
+
+static u16 

Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-18 Thread Zhu, Lingshan

Hello Jason,

Thanks for your comments, I am on a conference travel, I will reply next 
Monday.


Thanks,
BR
Zhu Lingshan
On 10/16/2019 6:19 PM, Jason Wang wrote:


On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
  drivers/vhost/ifcvf/ifcvf_main.c | 541 
+++

  1 file changed, 541 insertions(+)
  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c 
b/drivers/vhost/ifcvf/ifcvf_main.c

new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING    "0.1"
+#define DRIVER_AUTHOR    "Intel Corporation"
+#define IFCVF_DRIVER_NAME    "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+    struct vring_info *vring = arg;
+
+    if (vring->cb.callback)
+    return vring->cb.callback(vring->cb.private);
+
+    return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+    return IFC_SUPPORTED_FEATURES;



I would expect this should be done by querying the hw. Or IFC VF can't 
get any update through its firmware?




+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 
features)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->req_features = features;
+
+    return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw since 
it's an internal state.




+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 
qid, u64 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].last_used_idx = num;



I fail to understand why last_used_idx is needed. It looks to me the 
used idx in the used ring is sufficient.




+    vf->vring[qid].last_avail_idx = num;



Do we need a synchronization with hw immediately here?



+
+    return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
+ u64 desc_area, u64 driver_area,
+ u64 device_area)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].desc = desc_area;
+    vf->vring[idx].avail = driver_area;
+    vf->vring[idx].used = device_area;
+
+    return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, 
u32 num)

+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+    u16 qid, bool ready)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+ struct virtio_mdev_callback *cb)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+    struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+    struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+    return vf->generation;
+}
+
+static int ifcvf_mdev_get_version(struct mdev_device *mdev)
+{
+    return VIRTIO_MDEV_VERSION;
+}
+
+static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
+{
+    return IFCVF_DEVICE_ID;
+}
+
+static u32 ifcvf_mdev_get_vendor_id(struct mdev_device *mdev)
+{
+    return IFCVF_VENDOR_ID;
+}
+
+static 

Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-16 Thread Jason Wang



On 2019/10/16 上午9:30, Zhu Lingshan wrote:

This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
  drivers/vhost/ifcvf/ifcvf_main.c | 541 +++
  1 file changed, 541 insertions(+)
  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c b/drivers/vhost/ifcvf/ifcvf_main.c
new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING "0.1"
+#define DRIVER_AUTHOR  "Intel Corporation"
+#define IFCVF_DRIVER_NAME  "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+   struct vring_info *vring = arg;
+
+   if (vring->cb.callback)
+   return vring->cb.callback(vring->cb.private);
+
+   return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+   return IFC_SUPPORTED_FEATURES;



I would expect this should be done by querying the hw. Or IFC VF can't 
get any update through its firmware?




+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 features)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->req_features = features;
+
+   return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].last_avail_idx;



Does this really work? I'd expect it should be fetched from hw since 
it's an internal state.




+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 qid, u64 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].last_used_idx = num;



I fail to understand why last_used_idx is needed. It looks to me the 
used idx in the used ring is sufficient.




+   vf->vring[qid].last_avail_idx = num;



Do we need a synchronization with hw immediately here?



+
+   return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
+u64 desc_area, u64 driver_area,
+u64 device_area)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].desc = desc_area;
+   vf->vring[idx].avail = driver_area;
+   vf->vring[idx].used = device_area;
+
+   return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, u32 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+   u16 qid, bool ready)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+struct virtio_mdev_callback *cb)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->generation;
+}
+
+static int ifcvf_mdev_get_version(struct mdev_device *mdev)
+{
+   return VIRTIO_MDEV_VERSION;
+}
+
+static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
+{
+   return IFCVF_DEVICE_ID;
+}
+
+static u32 ifcvf_mdev_get_vendor_id(struct mdev_device *mdev)
+{
+   return 

Re: [RFC 2/2] vhost: IFC VF vdpa layer

2019-10-16 Thread Simon Horman
Hi Zhu,

thanks for your patch.

On Wed, Oct 16, 2019 at 09:03:18AM +0800, Zhu Lingshan wrote:
> This commit introduced IFC VF operations for vdpa, which complys to
> vhost_mdev interfaces, handles IFC VF initialization,
> configuration and removal.
> 
> Signed-off-by: Zhu Lingshan 
> ---
>  drivers/vhost/ifcvf/ifcvf_main.c | 541 
> +++
>  1 file changed, 541 insertions(+)
>  create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c
> 
> diff --git a/drivers/vhost/ifcvf/ifcvf_main.c 
> b/drivers/vhost/ifcvf/ifcvf_main.c
> new file mode 100644
> index ..c48a29969a85
> --- /dev/null
> +++ b/drivers/vhost/ifcvf/ifcvf_main.c
> @@ -0,0 +1,541 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2019 Intel Corporation.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "ifcvf_base.h"
> +
> +#define VERSION_STRING   "0.1"
> +#define DRIVER_AUTHOR"Intel Corporation"
> +#define IFCVF_DRIVER_NAME"ifcvf"
> +
> +static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
> +{
> + struct vring_info *vring = arg;
> +
> + if (vring->cb.callback)
> + return vring->cb.callback(vring->cb.private);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
> +{
> + return IFC_SUPPORTED_FEATURES;
> +}
> +
> +static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 features)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);

Perhaps a helper that takes a struct mdev_device would be useful.
The pattern above seems to be repeated many times.

> +
> + vf->req_features = features;
> +
> + return 0;
> +}
> +
> +static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + return vf->vring[qid].last_avail_idx;
> +}
> +
> +static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 qid, u64 
> num)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + vf->vring[qid].last_used_idx = num;
> + vf->vring[qid].last_avail_idx = num;
> +
> + return 0;
> +}
> +
> +static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
> +  u64 desc_area, u64 driver_area,
> +  u64 device_area)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + vf->vring[idx].desc = desc_area;
> + vf->vring[idx].avail = driver_area;
> + vf->vring[idx].used = device_area;
> +
> + return 0;
> +}
> +
> +static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, u32 num)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + vf->vring[qid].size = num;
> +}
> +
> +static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
> + u16 qid, bool ready)

u16 should be vertically whitespace aligned with struct mdev_device.

> +{
> +
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + vf->vring[qid].ready = ready;
> +}
> +
> +static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
> +{
> +
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + return vf->vring[qid].ready;
> +}
> +
> +static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
> +  struct virtio_mdev_callback *cb)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + vf->vring[idx].cb = *cb;
> +}
> +
> +static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + ifcvf_notify_queue(vf, idx);
> +}
> +
> +static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + return vf->status;
> +}
> +
> +static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
> +{
> + struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
> + struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
> +
> + return vf->generation;
> +}
> +
> +static int ifcvf_mdev_get_version(struct mdev_device *mdev)
> +{
> + return VIRTIO_MDEV_VERSION;
> +}
> +
> +static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
> +{
> + return IFCVF_DEVICE_ID;
> +}
> +

[RFC 2/2] vhost: IFC VF vdpa layer

2019-10-15 Thread Zhu Lingshan
This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
 drivers/vhost/ifcvf/ifcvf_main.c | 541 +++
 1 file changed, 541 insertions(+)
 create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c b/drivers/vhost/ifcvf/ifcvf_main.c
new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING "0.1"
+#define DRIVER_AUTHOR  "Intel Corporation"
+#define IFCVF_DRIVER_NAME  "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+   struct vring_info *vring = arg;
+
+   if (vring->cb.callback)
+   return vring->cb.callback(vring->cb.private);
+
+   return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+   return IFC_SUPPORTED_FEATURES;
+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 features)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->req_features = features;
+
+   return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].last_avail_idx;
+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 qid, u64 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].last_used_idx = num;
+   vf->vring[qid].last_avail_idx = num;
+
+   return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
+u64 desc_area, u64 driver_area,
+u64 device_area)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].desc = desc_area;
+   vf->vring[idx].avail = driver_area;
+   vf->vring[idx].used = device_area;
+
+   return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, u32 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+   u16 qid, bool ready)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+struct virtio_mdev_callback *cb)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->generation;
+}
+
+static int ifcvf_mdev_get_version(struct mdev_device *mdev)
+{
+   return VIRTIO_MDEV_VERSION;
+}
+
+static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
+{
+   return IFCVF_DEVICE_ID;
+}
+
+static u32 ifcvf_mdev_get_vendor_id(struct mdev_device *mdev)
+{
+   return IFCVF_VENDOR_ID;
+}
+
+static u16 ifcvf_mdev_get_vq_align(struct mdev_device *mdev)
+{
+   return IFCVF_QUEUE_ALIGNMENT;
+}
+
+static int ifcvf_start_datapath(void *private)
+{
+   int i, ret;
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(private);
+
+   for (i = 0; i < (IFCVF_MAX_QUEUE_PAIRS * 2); i++) {
+   if (!vf->vring[i].ready)
+   break;
+
+   if (!vf->vring[i].size)
+  

[RFC 2/2] vhost: IFC VF vdpa layer

2019-10-15 Thread Zhu Lingshan
This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
 drivers/vhost/ifcvf/ifcvf_main.c | 541 +++
 1 file changed, 541 insertions(+)
 create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c b/drivers/vhost/ifcvf/ifcvf_main.c
new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING "0.1"
+#define DRIVER_AUTHOR  "Intel Corporation"
+#define IFCVF_DRIVER_NAME  "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+   struct vring_info *vring = arg;
+
+   if (vring->cb.callback)
+   return vring->cb.callback(vring->cb.private);
+
+   return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+   return IFC_SUPPORTED_FEATURES;
+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 features)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->req_features = features;
+
+   return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].last_avail_idx;
+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 qid, u64 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].last_used_idx = num;
+   vf->vring[qid].last_avail_idx = num;
+
+   return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
+u64 desc_area, u64 driver_area,
+u64 device_area)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].desc = desc_area;
+   vf->vring[idx].avail = driver_area;
+   vf->vring[idx].used = device_area;
+
+   return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, u32 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+   u16 qid, bool ready)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+struct virtio_mdev_callback *cb)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->generation;
+}
+
+static int ifcvf_mdev_get_version(struct mdev_device *mdev)
+{
+   return VIRTIO_MDEV_VERSION;
+}
+
+static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
+{
+   return IFCVF_DEVICE_ID;
+}
+
+static u32 ifcvf_mdev_get_vendor_id(struct mdev_device *mdev)
+{
+   return IFCVF_VENDOR_ID;
+}
+
+static u16 ifcvf_mdev_get_vq_align(struct mdev_device *mdev)
+{
+   return IFCVF_QUEUE_ALIGNMENT;
+}
+
+static int ifcvf_start_datapath(void *private)
+{
+   int i, ret;
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(private);
+
+   for (i = 0; i < (IFCVF_MAX_QUEUE_PAIRS * 2); i++) {
+   if (!vf->vring[i].ready)
+   break;
+
+   if (!vf->vring[i].size)
+  

[RFC 2/2] vhost: IFC VF vdpa layer

2019-10-15 Thread Zhu Lingshan
This commit introduced IFC VF operations for vdpa, which complys to
vhost_mdev interfaces, handles IFC VF initialization,
configuration and removal.

Signed-off-by: Zhu Lingshan 
---
 drivers/vhost/ifcvf/ifcvf_main.c | 541 +++
 1 file changed, 541 insertions(+)
 create mode 100644 drivers/vhost/ifcvf/ifcvf_main.c

diff --git a/drivers/vhost/ifcvf/ifcvf_main.c b/drivers/vhost/ifcvf/ifcvf_main.c
new file mode 100644
index ..c48a29969a85
--- /dev/null
+++ b/drivers/vhost/ifcvf/ifcvf_main.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 Intel Corporation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ifcvf_base.h"
+
+#define VERSION_STRING "0.1"
+#define DRIVER_AUTHOR  "Intel Corporation"
+#define IFCVF_DRIVER_NAME  "ifcvf"
+
+static irqreturn_t ifcvf_intr_handler(int irq, void *arg)
+{
+   struct vring_info *vring = arg;
+
+   if (vring->cb.callback)
+   return vring->cb.callback(vring->cb.private);
+
+   return IRQ_HANDLED;
+}
+
+static u64 ifcvf_mdev_get_features(struct mdev_device *mdev)
+{
+   return IFC_SUPPORTED_FEATURES;
+}
+
+static int ifcvf_mdev_set_features(struct mdev_device *mdev, u64 features)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->req_features = features;
+
+   return 0;
+}
+
+static u64 ifcvf_mdev_get_vq_state(struct mdev_device *mdev, u16 qid)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].last_avail_idx;
+}
+
+static int ifcvf_mdev_set_vq_state(struct mdev_device *mdev, u16 qid, u64 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].last_used_idx = num;
+   vf->vring[qid].last_avail_idx = num;
+
+   return 0;
+}
+
+static int ifcvf_mdev_set_vq_address(struct mdev_device *mdev, u16 idx,
+u64 desc_area, u64 driver_area,
+u64 device_area)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].desc = desc_area;
+   vf->vring[idx].avail = driver_area;
+   vf->vring[idx].used = device_area;
+
+   return 0;
+}
+
+static void ifcvf_mdev_set_vq_num(struct mdev_device *mdev, u16 qid, u32 num)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].size = num;
+}
+
+static void ifcvf_mdev_set_vq_ready(struct mdev_device *mdev,
+   u16 qid, bool ready)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[qid].ready = ready;
+}
+
+static bool ifcvf_mdev_get_vq_ready(struct mdev_device *mdev, u16 qid)
+{
+
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->vring[qid].ready;
+}
+
+static void ifcvf_mdev_set_vq_cb(struct mdev_device *mdev, u16 idx,
+struct virtio_mdev_callback *cb)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   vf->vring[idx].cb = *cb;
+}
+
+static void ifcvf_mdev_kick_vq(struct mdev_device *mdev, u16 idx)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   ifcvf_notify_queue(vf, idx);
+}
+
+static u8 ifcvf_mdev_get_status(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->status;
+}
+
+static u32 ifcvf_mdev_get_generation(struct mdev_device *mdev)
+{
+   struct ifcvf_adapter *adapter = mdev_get_drvdata(mdev);
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(adapter);
+
+   return vf->generation;
+}
+
+static int ifcvf_mdev_get_version(struct mdev_device *mdev)
+{
+   return VIRTIO_MDEV_VERSION;
+}
+
+static u32 ifcvf_mdev_get_device_id(struct mdev_device *mdev)
+{
+   return IFCVF_DEVICE_ID;
+}
+
+static u32 ifcvf_mdev_get_vendor_id(struct mdev_device *mdev)
+{
+   return IFCVF_VENDOR_ID;
+}
+
+static u16 ifcvf_mdev_get_vq_align(struct mdev_device *mdev)
+{
+   return IFCVF_QUEUE_ALIGNMENT;
+}
+
+static int ifcvf_start_datapath(void *private)
+{
+   int i, ret;
+   struct ifcvf_hw *vf = IFC_PRIVATE_TO_VF(private);
+
+   for (i = 0; i < (IFCVF_MAX_QUEUE_PAIRS * 2); i++) {
+   if (!vf->vring[i].ready)
+   break;
+
+   if (!vf->vring[i].size)
+