ifcvf/vDPA: fix misuse virtio-net device config size for blk dev
This commit fixes a misuse of virtio-net device config size issue
for virtio-block devices.
A new member config_size in struct ifcvf_hw is introduced and would
be initialized through vdpa_dev_add() to record correct device
config size.
To be more generic, rename ifcvf_hw.net_config to ifcvf_hw.dev_config,
the helpers ifcvf_read/write_net_config() to ifcvf_read/write_dev_config()
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Reported-and-suggested-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Fixes: 6ad31d162a
("vDPA/ifcvf: enable Intel C5000X-PL virtio-block for vDPA")
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20211201081255.60187-1-lingshan.zhu@intel.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
b4d80c8dda
commit
0f420c383a
|
@ -143,8 +143,8 @@ int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *pdev)
|
||||||
IFCVF_DBG(pdev, "hw->isr = %p\n", hw->isr);
|
IFCVF_DBG(pdev, "hw->isr = %p\n", hw->isr);
|
||||||
break;
|
break;
|
||||||
case VIRTIO_PCI_CAP_DEVICE_CFG:
|
case VIRTIO_PCI_CAP_DEVICE_CFG:
|
||||||
hw->net_cfg = get_cap_addr(hw, &cap);
|
hw->dev_cfg = get_cap_addr(hw, &cap);
|
||||||
IFCVF_DBG(pdev, "hw->net_cfg = %p\n", hw->net_cfg);
|
IFCVF_DBG(pdev, "hw->dev_cfg = %p\n", hw->dev_cfg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ next:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw->common_cfg == NULL || hw->notify_base == NULL ||
|
if (hw->common_cfg == NULL || hw->notify_base == NULL ||
|
||||||
hw->isr == NULL || hw->net_cfg == NULL) {
|
hw->isr == NULL || hw->dev_cfg == NULL) {
|
||||||
IFCVF_ERR(pdev, "Incomplete PCI capabilities\n");
|
IFCVF_ERR(pdev, "Incomplete PCI capabilities\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ next:
|
||||||
IFCVF_DBG(pdev,
|
IFCVF_DBG(pdev,
|
||||||
"PCI capability mapping: common cfg: %p, notify base: %p\n, isr cfg: %p, device cfg: %p, multiplier: %u\n",
|
"PCI capability mapping: common cfg: %p, notify base: %p\n, isr cfg: %p, device cfg: %p, multiplier: %u\n",
|
||||||
hw->common_cfg, hw->notify_base, hw->isr,
|
hw->common_cfg, hw->notify_base, hw->isr,
|
||||||
hw->net_cfg, hw->notify_off_multiplier);
|
hw->dev_cfg, hw->notify_off_multiplier);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -242,33 +242,54 @@ int ifcvf_verify_min_features(struct ifcvf_hw *hw, u64 features)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifcvf_read_net_config(struct ifcvf_hw *hw, u64 offset,
|
u32 ifcvf_get_config_size(struct ifcvf_hw *hw)
|
||||||
|
{
|
||||||
|
struct ifcvf_adapter *adapter;
|
||||||
|
u32 config_size;
|
||||||
|
|
||||||
|
adapter = vf_to_adapter(hw);
|
||||||
|
switch (hw->dev_type) {
|
||||||
|
case VIRTIO_ID_NET:
|
||||||
|
config_size = sizeof(struct virtio_net_config);
|
||||||
|
break;
|
||||||
|
case VIRTIO_ID_BLOCK:
|
||||||
|
config_size = sizeof(struct virtio_blk_config);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
config_size = 0;
|
||||||
|
IFCVF_ERR(adapter->pdev, "VIRTIO ID %u not supported\n", hw->dev_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return config_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifcvf_read_dev_config(struct ifcvf_hw *hw, u64 offset,
|
||||||
void *dst, int length)
|
void *dst, int length)
|
||||||
{
|
{
|
||||||
u8 old_gen, new_gen, *p;
|
u8 old_gen, new_gen, *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
WARN_ON(offset + length > sizeof(struct virtio_net_config));
|
WARN_ON(offset + length > hw->config_size);
|
||||||
do {
|
do {
|
||||||
old_gen = ifc_ioread8(&hw->common_cfg->config_generation);
|
old_gen = ifc_ioread8(&hw->common_cfg->config_generation);
|
||||||
p = dst;
|
p = dst;
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
*p++ = ifc_ioread8(hw->net_cfg + offset + i);
|
*p++ = ifc_ioread8(hw->dev_cfg + offset + i);
|
||||||
|
|
||||||
new_gen = ifc_ioread8(&hw->common_cfg->config_generation);
|
new_gen = ifc_ioread8(&hw->common_cfg->config_generation);
|
||||||
} while (old_gen != new_gen);
|
} while (old_gen != new_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifcvf_write_net_config(struct ifcvf_hw *hw, u64 offset,
|
void ifcvf_write_dev_config(struct ifcvf_hw *hw, u64 offset,
|
||||||
const void *src, int length)
|
const void *src, int length)
|
||||||
{
|
{
|
||||||
const u8 *p;
|
const u8 *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
p = src;
|
p = src;
|
||||||
WARN_ON(offset + length > sizeof(struct virtio_net_config));
|
WARN_ON(offset + length > hw->config_size);
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
ifc_iowrite8(*p++, hw->net_cfg + offset + i);
|
ifc_iowrite8(*p++, hw->dev_cfg + offset + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features)
|
static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features)
|
||||||
|
|
|
@ -71,12 +71,14 @@ struct ifcvf_hw {
|
||||||
u64 hw_features;
|
u64 hw_features;
|
||||||
u32 dev_type;
|
u32 dev_type;
|
||||||
struct virtio_pci_common_cfg __iomem *common_cfg;
|
struct virtio_pci_common_cfg __iomem *common_cfg;
|
||||||
void __iomem *net_cfg;
|
void __iomem *dev_cfg;
|
||||||
struct vring_info vring[IFCVF_MAX_QUEUES];
|
struct vring_info vring[IFCVF_MAX_QUEUES];
|
||||||
void __iomem * const *base;
|
void __iomem * const *base;
|
||||||
char config_msix_name[256];
|
char config_msix_name[256];
|
||||||
struct vdpa_callback config_cb;
|
struct vdpa_callback config_cb;
|
||||||
unsigned int config_irq;
|
unsigned int config_irq;
|
||||||
|
/* virtio-net or virtio-blk device config size */
|
||||||
|
u32 config_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ifcvf_adapter {
|
struct ifcvf_adapter {
|
||||||
|
@ -105,9 +107,9 @@ int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *dev);
|
||||||
int ifcvf_start_hw(struct ifcvf_hw *hw);
|
int ifcvf_start_hw(struct ifcvf_hw *hw);
|
||||||
void ifcvf_stop_hw(struct ifcvf_hw *hw);
|
void ifcvf_stop_hw(struct ifcvf_hw *hw);
|
||||||
void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid);
|
void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid);
|
||||||
void ifcvf_read_net_config(struct ifcvf_hw *hw, u64 offset,
|
void ifcvf_read_dev_config(struct ifcvf_hw *hw, u64 offset,
|
||||||
void *dst, int length);
|
void *dst, int length);
|
||||||
void ifcvf_write_net_config(struct ifcvf_hw *hw, u64 offset,
|
void ifcvf_write_dev_config(struct ifcvf_hw *hw, u64 offset,
|
||||||
const void *src, int length);
|
const void *src, int length);
|
||||||
u8 ifcvf_get_status(struct ifcvf_hw *hw);
|
u8 ifcvf_get_status(struct ifcvf_hw *hw);
|
||||||
void ifcvf_set_status(struct ifcvf_hw *hw, u8 status);
|
void ifcvf_set_status(struct ifcvf_hw *hw, u8 status);
|
||||||
|
@ -120,4 +122,5 @@ u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid);
|
||||||
int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num);
|
int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num);
|
||||||
struct ifcvf_adapter *vf_to_adapter(struct ifcvf_hw *hw);
|
struct ifcvf_adapter *vf_to_adapter(struct ifcvf_hw *hw);
|
||||||
int ifcvf_probed_virtio_net(struct ifcvf_hw *hw);
|
int ifcvf_probed_virtio_net(struct ifcvf_hw *hw);
|
||||||
|
u32 ifcvf_get_config_size(struct ifcvf_hw *hw);
|
||||||
#endif /* _IFCVF_H_ */
|
#endif /* _IFCVF_H_ */
|
||||||
|
|
|
@ -366,24 +366,9 @@ static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev)
|
||||||
|
|
||||||
static size_t ifcvf_vdpa_get_config_size(struct vdpa_device *vdpa_dev)
|
static size_t ifcvf_vdpa_get_config_size(struct vdpa_device *vdpa_dev)
|
||||||
{
|
{
|
||||||
struct ifcvf_adapter *adapter = vdpa_to_adapter(vdpa_dev);
|
|
||||||
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
|
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
|
||||||
struct pci_dev *pdev = adapter->pdev;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
switch (vf->dev_type) {
|
return vf->config_size;
|
||||||
case VIRTIO_ID_NET:
|
|
||||||
size = sizeof(struct virtio_net_config);
|
|
||||||
break;
|
|
||||||
case VIRTIO_ID_BLOCK:
|
|
||||||
size = sizeof(struct virtio_blk_config);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
size = 0;
|
|
||||||
IFCVF_ERR(pdev, "VIRTIO ID %u not supported\n", vf->dev_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev,
|
static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev,
|
||||||
|
@ -392,8 +377,7 @@ static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev,
|
||||||
{
|
{
|
||||||
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
|
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
|
||||||
|
|
||||||
WARN_ON(offset + len > sizeof(struct virtio_net_config));
|
ifcvf_read_dev_config(vf, offset, buf, len);
|
||||||
ifcvf_read_net_config(vf, offset, buf, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ifcvf_vdpa_set_config(struct vdpa_device *vdpa_dev,
|
static void ifcvf_vdpa_set_config(struct vdpa_device *vdpa_dev,
|
||||||
|
@ -402,8 +386,7 @@ static void ifcvf_vdpa_set_config(struct vdpa_device *vdpa_dev,
|
||||||
{
|
{
|
||||||
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
|
struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
|
||||||
|
|
||||||
WARN_ON(offset + len > sizeof(struct virtio_net_config));
|
ifcvf_write_dev_config(vf, offset, buf, len);
|
||||||
ifcvf_write_net_config(vf, offset, buf, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ifcvf_vdpa_set_config_cb(struct vdpa_device *vdpa_dev,
|
static void ifcvf_vdpa_set_config_cb(struct vdpa_device *vdpa_dev,
|
||||||
|
@ -542,6 +525,7 @@ static int ifcvf_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
|
||||||
vf->vring[i].irq = -EINVAL;
|
vf->vring[i].irq = -EINVAL;
|
||||||
|
|
||||||
vf->hw_features = ifcvf_get_hw_features(vf);
|
vf->hw_features = ifcvf_get_hw_features(vf);
|
||||||
|
vf->config_size = ifcvf_get_config_size(vf);
|
||||||
|
|
||||||
adapter->vdpa.mdev = &ifcvf_mgmt_dev->mdev;
|
adapter->vdpa.mdev = &ifcvf_mgmt_dev->mdev;
|
||||||
ret = _vdpa_register_device(&adapter->vdpa, vf->nr_vring);
|
ret = _vdpa_register_device(&adapter->vdpa, vf->nr_vring);
|
||||||
|
|
Loading…
Reference in New Issue