@@ -45,6 +45,8 @@ MODULE_LICENSE("Dual BSD/GPL");
4545 (VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK | \
4646 VIRTIO_CONFIG_S_FEATURES_OK | VIRTIO_CONFIG_S_NEEDS_RESET | VIRTIO_CONFIG_S_FAILED)
4747
48+ #define MLX5_FEATURE (_mvdev , _feature ) (!!((_mvdev)->actual_features & BIT_ULL(_feature)))
49+
4850struct mlx5_vdpa_net_resources {
4951 u32 tisn ;
5052 u32 tdn ;
@@ -133,6 +135,14 @@ struct mlx5_vdpa_virtqueue {
133135 */
134136#define MLX5_MAX_SUPPORTED_VQS 16
135137
138+ static bool is_index_valid (struct mlx5_vdpa_dev * mvdev , u16 idx )
139+ {
140+ if (unlikely (idx > mvdev -> max_idx ))
141+ return false;
142+
143+ return true;
144+ }
145+
136146struct mlx5_vdpa_net {
137147 struct mlx5_vdpa_dev mvdev ;
138148 struct mlx5_vdpa_net_resources res ;
@@ -1354,6 +1364,9 @@ static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx)
13541364 struct mlx5_vdpa_net * ndev = to_mlx5_vdpa_ndev (mvdev );
13551365 struct mlx5_vdpa_virtqueue * mvq = & ndev -> vqs [idx ];
13561366
1367+ if (!is_index_valid (mvdev , idx ))
1368+ return ;
1369+
13571370 if (unlikely (!mvq -> ready ))
13581371 return ;
13591372
@@ -1367,6 +1380,9 @@ static int mlx5_vdpa_set_vq_address(struct vdpa_device *vdev, u16 idx, u64 desc_
13671380 struct mlx5_vdpa_net * ndev = to_mlx5_vdpa_ndev (mvdev );
13681381 struct mlx5_vdpa_virtqueue * mvq = & ndev -> vqs [idx ];
13691382
1383+ if (!is_index_valid (mvdev , idx ))
1384+ return - EINVAL ;
1385+
13701386 mvq -> desc_addr = desc_area ;
13711387 mvq -> device_addr = device_area ;
13721388 mvq -> driver_addr = driver_area ;
@@ -1379,6 +1395,9 @@ static void mlx5_vdpa_set_vq_num(struct vdpa_device *vdev, u16 idx, u32 num)
13791395 struct mlx5_vdpa_net * ndev = to_mlx5_vdpa_ndev (mvdev );
13801396 struct mlx5_vdpa_virtqueue * mvq ;
13811397
1398+ if (!is_index_valid (mvdev , idx ))
1399+ return ;
1400+
13821401 mvq = & ndev -> vqs [idx ];
13831402 mvq -> num_ent = num ;
13841403}
@@ -1397,6 +1416,9 @@ static void mlx5_vdpa_set_vq_ready(struct vdpa_device *vdev, u16 idx, bool ready
13971416 struct mlx5_vdpa_net * ndev = to_mlx5_vdpa_ndev (mvdev );
13981417 struct mlx5_vdpa_virtqueue * mvq = & ndev -> vqs [idx ];
13991418
1419+ if (!is_index_valid (mvdev , idx ))
1420+ return ;
1421+
14001422 if (!ready )
14011423 suspend_vq (ndev , mvq );
14021424
@@ -1409,6 +1431,9 @@ static bool mlx5_vdpa_get_vq_ready(struct vdpa_device *vdev, u16 idx)
14091431 struct mlx5_vdpa_net * ndev = to_mlx5_vdpa_ndev (mvdev );
14101432 struct mlx5_vdpa_virtqueue * mvq = & ndev -> vqs [idx ];
14111433
1434+ if (!is_index_valid (mvdev , idx ))
1435+ return false;
1436+
14121437 return mvq -> ready ;
14131438}
14141439
@@ -1419,6 +1444,9 @@ static int mlx5_vdpa_set_vq_state(struct vdpa_device *vdev, u16 idx,
14191444 struct mlx5_vdpa_net * ndev = to_mlx5_vdpa_ndev (mvdev );
14201445 struct mlx5_vdpa_virtqueue * mvq = & ndev -> vqs [idx ];
14211446
1447+ if (!is_index_valid (mvdev , idx ))
1448+ return - EINVAL ;
1449+
14221450 if (mvq -> fw_state == MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY ) {
14231451 mlx5_vdpa_warn (mvdev , "can't modify available index\n" );
14241452 return - EINVAL ;
@@ -1437,6 +1465,9 @@ static int mlx5_vdpa_get_vq_state(struct vdpa_device *vdev, u16 idx, struct vdpa
14371465 struct mlx5_virtq_attr attr ;
14381466 int err ;
14391467
1468+ if (!is_index_valid (mvdev , idx ))
1469+ return - EINVAL ;
1470+
14401471 /* If the virtq object was destroyed, use the value saved at
14411472 * the last minute of suspend_vq. This caters for userspace
14421473 * that cares about emulating the index after vq is stopped.
@@ -1556,6 +1587,24 @@ static __virtio16 cpu_to_mlx5vdpa16(struct mlx5_vdpa_dev *mvdev, u16 val)
15561587 return __cpu_to_virtio16 (mlx5_vdpa_is_little_endian (mvdev ), val );
15571588}
15581589
1590+ static void update_cvq_info (struct mlx5_vdpa_dev * mvdev )
1591+ {
1592+ if (MLX5_FEATURE (mvdev , VIRTIO_NET_F_CTRL_VQ )) {
1593+ if (MLX5_FEATURE (mvdev , VIRTIO_NET_F_MQ )) {
1594+ /* MQ supported. CVQ index is right above the last data virtqueue's */
1595+ mvdev -> max_idx = mvdev -> max_vqs ;
1596+ } else {
1597+ /* Only CVQ supportted. data virtqueues occupy indices 0 and 1.
1598+ * CVQ gets index 2
1599+ */
1600+ mvdev -> max_idx = 2 ;
1601+ }
1602+ } else {
1603+ /* Two data virtqueues only: one for rx and one for tx */
1604+ mvdev -> max_idx = 1 ;
1605+ }
1606+ }
1607+
15591608static int mlx5_vdpa_set_features (struct vdpa_device * vdev , u64 features )
15601609{
15611610 struct mlx5_vdpa_dev * mvdev = to_mvdev (vdev );
@@ -1571,6 +1620,7 @@ static int mlx5_vdpa_set_features(struct vdpa_device *vdev, u64 features)
15711620 ndev -> mvdev .actual_features = features & ndev -> mvdev .mlx_features ;
15721621 ndev -> config .mtu = cpu_to_mlx5vdpa16 (mvdev , ndev -> mtu );
15731622 ndev -> config .status |= cpu_to_mlx5vdpa16 (mvdev , VIRTIO_NET_S_LINK_UP );
1623+ update_cvq_info (mvdev );
15741624 return err ;
15751625}
15761626
@@ -1792,6 +1842,7 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
17921842 ndev -> mvdev .status = 0 ;
17931843 ndev -> mvdev .mlx_features = 0 ;
17941844 memset (ndev -> event_cbs , 0 , sizeof (ndev -> event_cbs ));
1845+ ndev -> mvdev .actual_features = 0 ;
17951846 ++ mvdev -> generation ;
17961847 if (MLX5_CAP_GEN (mvdev -> mdev , umem_uid_0 )) {
17971848 if (mlx5_vdpa_create_mr (mvdev , NULL ))
@@ -1892,6 +1943,9 @@ static struct vdpa_notification_area mlx5_get_vq_notification(struct vdpa_device
18921943 struct mlx5_vdpa_net * ndev ;
18931944 phys_addr_t addr ;
18941945
1946+ if (!is_index_valid (mvdev , idx ))
1947+ return ret ;
1948+
18951949 /* If SF BAR size is smaller than PAGE_SIZE, do not use direct
18961950 * notification to avoid the risk of mapping pages that contain BAR of more
18971951 * than one SF
0 commit comments