vDPA/ifcvf: enable Intel C5000X-PL virtio-block for vDPA
[linux-2.6-microblaze.git] / drivers / vdpa / ifcvf / ifcvf_main.c
index d555a6a..9a4a6df 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sysfs.h>
 #include "ifcvf_base.h"
 
-#define VERSION_STRING  "0.1"
 #define DRIVER_AUTHOR   "Intel Corporation"
 #define IFCVF_DRIVER_NAME       "ifcvf"
 
@@ -169,10 +168,23 @@ static struct ifcvf_hw *vdpa_to_vf(struct vdpa_device *vdpa_dev)
 
 static u64 ifcvf_vdpa_get_features(struct vdpa_device *vdpa_dev)
 {
+       struct ifcvf_adapter *adapter = vdpa_to_adapter(vdpa_dev);
        struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
+       struct pci_dev *pdev = adapter->pdev;
+
        u64 features;
 
-       features = ifcvf_get_features(vf) & IFCVF_SUPPORTED_FEATURES;
+       switch (vf->dev_type) {
+       case VIRTIO_ID_NET:
+               features = ifcvf_get_features(vf) & IFCVF_NET_SUPPORTED_FEATURES;
+               break;
+       case VIRTIO_ID_BLOCK:
+               features = ifcvf_get_features(vf);
+               break;
+       default:
+               features = 0;
+               IFCVF_ERR(pdev, "VIRTIO ID %u not supported\n", vf->dev_type);
+       }
 
        return features;
 }
@@ -180,6 +192,11 @@ static u64 ifcvf_vdpa_get_features(struct vdpa_device *vdpa_dev)
 static int ifcvf_vdpa_set_features(struct vdpa_device *vdpa_dev, u64 features)
 {
        struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
+       int ret;
+
+       ret = ifcvf_verify_min_features(vf, features);
+       if (ret)
+               return ret;
 
        vf->req_features = features;
 
@@ -319,12 +336,17 @@ static u32 ifcvf_vdpa_get_generation(struct vdpa_device *vdpa_dev)
 
 static u32 ifcvf_vdpa_get_device_id(struct vdpa_device *vdpa_dev)
 {
-       return VIRTIO_ID_NET;
+       struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
+
+       return vf->dev_type;
 }
 
 static u32 ifcvf_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev)
 {
-       return IFCVF_SUBSYS_VENDOR_ID;
+       struct ifcvf_adapter *adapter = vdpa_to_adapter(vdpa_dev);
+       struct pci_dev *pdev = adapter->pdev;
+
+       return pdev->subsystem_vendor;
 }
 
 static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
@@ -332,6 +354,11 @@ static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
        return IFCVF_QUEUE_ALIGNMENT;
 }
 
+static size_t ifcvf_vdpa_get_config_size(struct vdpa_device *vdpa_dev)
+{
+       return sizeof(struct virtio_net_config);
+}
+
 static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev,
                                  unsigned int offset,
                                  void *buf, unsigned int len)
@@ -392,6 +419,7 @@ static const struct vdpa_config_ops ifc_vdpa_ops = {
        .get_device_id  = ifcvf_vdpa_get_device_id,
        .get_vendor_id  = ifcvf_vdpa_get_vendor_id,
        .get_vq_align   = ifcvf_vdpa_get_vq_align,
+       .get_config_size        = ifcvf_vdpa_get_config_size,
        .get_config     = ifcvf_vdpa_get_config,
        .set_config     = ifcvf_vdpa_set_config,
        .set_config_cb  = ifcvf_vdpa_set_config_cb,
@@ -441,6 +469,19 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        pci_set_drvdata(pdev, adapter);
 
        vf = &adapter->vf;
+
+       /* This drirver drives both modern virtio devices and transitional
+        * devices in modern mode.
+        * vDPA requires feature bit VIRTIO_F_ACCESS_PLATFORM,
+        * so legacy devices and transitional devices in legacy
+        * mode will not work for vDPA, this driver will not
+        * drive devices with legacy interface.
+        */
+       if (pdev->device < 0x1040)
+               vf->dev_type =  pdev->subsystem_device;
+       else
+               vf->dev_type =  pdev->device - 0x1040;
+
        vf->base = pcim_iomap_table(pdev);
 
        adapter->pdev = pdev;
@@ -455,6 +496,8 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        for (i = 0; i < IFCVF_MAX_QUEUE_PAIRS * 2; i++)
                vf->vring[i].irq = -EINVAL;
 
+       vf->hw_features = ifcvf_get_hw_features(vf);
+
        ret = vdpa_register_device(&adapter->vdpa, IFCVF_MAX_QUEUE_PAIRS * 2);
        if (ret) {
                IFCVF_ERR(pdev, "Failed to register ifcvf to vdpa bus");
@@ -476,10 +519,19 @@ static void ifcvf_remove(struct pci_dev *pdev)
 }
 
 static struct pci_device_id ifcvf_pci_ids[] = {
-       { PCI_DEVICE_SUB(IFCVF_VENDOR_ID,
-               IFCVF_DEVICE_ID,
-               IFCVF_SUBSYS_VENDOR_ID,
-               IFCVF_SUBSYS_DEVICE_ID) },
+       { PCI_DEVICE_SUB(N3000_VENDOR_ID,
+                        N3000_DEVICE_ID,
+                        N3000_SUBSYS_VENDOR_ID,
+                        N3000_SUBSYS_DEVICE_ID) },
+       { PCI_DEVICE_SUB(C5000X_PL_VENDOR_ID,
+                        C5000X_PL_DEVICE_ID,
+                        C5000X_PL_SUBSYS_VENDOR_ID,
+                        C5000X_PL_SUBSYS_DEVICE_ID) },
+       { PCI_DEVICE_SUB(C5000X_PL_BLK_VENDOR_ID,
+                        C5000X_PL_BLK_DEVICE_ID,
+                        C5000X_PL_BLK_SUBSYS_VENDOR_ID,
+                        C5000X_PL_BLK_SUBSYS_DEVICE_ID) },
+
        { 0 },
 };
 MODULE_DEVICE_TABLE(pci, ifcvf_pci_ids);
@@ -494,4 +546,3 @@ static struct pci_driver ifcvf_driver = {
 module_pci_driver(ifcvf_driver);
 
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION(VERSION_STRING);