@@ -83,6 +83,7 @@ struct mlx5_vq_restore_info {
8383 u64 driver_addr ;
8484 u16 avail_index ;
8585 u16 used_index ;
86+ struct msi_map map ;
8687 bool ready ;
8788 bool restore ;
8889};
@@ -118,6 +119,7 @@ struct mlx5_vdpa_virtqueue {
118119 u16 avail_idx ;
119120 u16 used_idx ;
120121 int fw_state ;
122+ struct msi_map map ;
121123
122124 /* keep last in the struct */
123125 struct mlx5_vq_restore_info ri ;
@@ -808,6 +810,13 @@ static bool counters_supported(const struct mlx5_vdpa_dev *mvdev)
808810 BIT_ULL (MLX5_OBJ_TYPE_VIRTIO_Q_COUNTERS );
809811}
810812
813+ static bool msix_mode_supported (struct mlx5_vdpa_dev * mvdev )
814+ {
815+ return MLX5_CAP_DEV_VDPA_EMULATION (mvdev -> mdev , event_mode ) &
816+ (1 << MLX5_VIRTIO_Q_EVENT_MODE_MSIX_MODE ) &&
817+ pci_msix_can_alloc_dyn (mvdev -> mdev -> pdev );
818+ }
819+
811820static int create_virtqueue (struct mlx5_vdpa_net * ndev , struct mlx5_vdpa_virtqueue * mvq )
812821{
813822 int inlen = MLX5_ST_SZ_BYTES (create_virtio_net_q_in );
@@ -849,9 +858,15 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque
849858 if (vq_is_tx (mvq -> index ))
850859 MLX5_SET (virtio_net_q_object , obj_context , tisn_or_qpn , ndev -> res .tisn );
851860
852- MLX5_SET (virtio_q , vq_ctx , event_mode , MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE );
861+ if (mvq -> map .virq ) {
862+ MLX5_SET (virtio_q , vq_ctx , event_mode , MLX5_VIRTIO_Q_EVENT_MODE_MSIX_MODE );
863+ MLX5_SET (virtio_q , vq_ctx , event_qpn_or_msix , mvq -> map .index );
864+ } else {
865+ MLX5_SET (virtio_q , vq_ctx , event_mode , MLX5_VIRTIO_Q_EVENT_MODE_QP_MODE );
866+ MLX5_SET (virtio_q , vq_ctx , event_qpn_or_msix , mvq -> fwqp .mqp .qpn );
867+ }
868+
853869 MLX5_SET (virtio_q , vq_ctx , queue_index , mvq -> index );
854- MLX5_SET (virtio_q , vq_ctx , event_qpn_or_msix , mvq -> fwqp .mqp .qpn );
855870 MLX5_SET (virtio_q , vq_ctx , queue_size , mvq -> num_ent );
856871 MLX5_SET (virtio_q , vq_ctx , virtio_version_1_0 ,
857872 !!(ndev -> mvdev .actual_features & BIT_ULL (VIRTIO_F_VERSION_1 )));
@@ -1194,6 +1209,56 @@ static void counter_set_dealloc(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_vir
11941209 mlx5_vdpa_warn (& ndev -> mvdev , "dealloc counter set 0x%x\n" , mvq -> counter_set_id );
11951210}
11961211
1212+ static irqreturn_t mlx5_vdpa_int_handler (int irq , void * priv )
1213+ {
1214+ struct vdpa_callback * cb = priv ;
1215+
1216+ if (cb -> callback )
1217+ return cb -> callback (cb -> private );
1218+
1219+ return IRQ_HANDLED ;
1220+ }
1221+
1222+ static void alloc_vector (struct mlx5_vdpa_net * ndev ,
1223+ struct mlx5_vdpa_virtqueue * mvq )
1224+ {
1225+ struct mlx5_vdpa_irq_pool * irqp = & ndev -> irqp ;
1226+ struct mlx5_vdpa_irq_pool_entry * ent ;
1227+ int err ;
1228+ int i ;
1229+
1230+ for (i = 0 ; i < irqp -> num_ent ; i ++ ) {
1231+ ent = & irqp -> entries [i ];
1232+ if (!ent -> used ) {
1233+ snprintf (ent -> name , MLX5_VDPA_IRQ_NAME_LEN , "%s-vq-%d" ,
1234+ dev_name (& ndev -> mvdev .vdev .dev ), mvq -> index );
1235+ ent -> dev_id = & ndev -> event_cbs [mvq -> index ];
1236+ err = request_irq (ent -> map .virq , mlx5_vdpa_int_handler , 0 ,
1237+ ent -> name , ent -> dev_id );
1238+ if (err )
1239+ return ;
1240+
1241+ ent -> used = true;
1242+ mvq -> map = ent -> map ;
1243+ return ;
1244+ }
1245+ }
1246+ }
1247+
1248+ static void dealloc_vector (struct mlx5_vdpa_net * ndev ,
1249+ struct mlx5_vdpa_virtqueue * mvq )
1250+ {
1251+ struct mlx5_vdpa_irq_pool * irqp = & ndev -> irqp ;
1252+ int i ;
1253+
1254+ for (i = 0 ; i < irqp -> num_ent ; i ++ )
1255+ if (mvq -> map .virq == irqp -> entries [i ].map .virq ) {
1256+ free_irq (mvq -> map .virq , irqp -> entries [i ].dev_id );
1257+ irqp -> entries [i ].used = false;
1258+ return ;
1259+ }
1260+ }
1261+
11971262static int setup_vq (struct mlx5_vdpa_net * ndev , struct mlx5_vdpa_virtqueue * mvq )
11981263{
11991264 u16 idx = mvq -> index ;
@@ -1223,27 +1288,31 @@ static int setup_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq)
12231288
12241289 err = counter_set_alloc (ndev , mvq );
12251290 if (err )
1226- goto err_counter ;
1291+ goto err_connect ;
12271292
1293+ alloc_vector (ndev , mvq );
12281294 err = create_virtqueue (ndev , mvq );
12291295 if (err )
1230- goto err_connect ;
1296+ goto err_vq ;
12311297
12321298 if (mvq -> ready ) {
12331299 err = modify_virtqueue (ndev , mvq , MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY );
12341300 if (err ) {
12351301 mlx5_vdpa_warn (& ndev -> mvdev , "failed to modify to ready vq idx %d(%d)\n" ,
12361302 idx , err );
1237- goto err_connect ;
1303+ goto err_modify ;
12381304 }
12391305 }
12401306
12411307 mvq -> initialized = true;
12421308 return 0 ;
12431309
1244- err_connect :
1310+ err_modify :
1311+ destroy_virtqueue (ndev , mvq );
1312+ err_vq :
1313+ dealloc_vector (ndev , mvq );
12451314 counter_set_dealloc (ndev , mvq );
1246- err_counter :
1315+ err_connect :
12471316 qp_destroy (ndev , & mvq -> vqqp );
12481317err_vqqp :
12491318 qp_destroy (ndev , & mvq -> fwqp );
@@ -1288,6 +1357,7 @@ static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *
12881357
12891358 suspend_vq (ndev , mvq );
12901359 destroy_virtqueue (ndev , mvq );
1360+ dealloc_vector (ndev , mvq );
12911361 counter_set_dealloc (ndev , mvq );
12921362 qp_destroy (ndev , & mvq -> vqqp );
12931363 qp_destroy (ndev , & mvq -> fwqp );
@@ -2505,6 +2575,7 @@ static int save_channel_info(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqu
25052575 ri -> desc_addr = mvq -> desc_addr ;
25062576 ri -> device_addr = mvq -> device_addr ;
25072577 ri -> driver_addr = mvq -> driver_addr ;
2578+ ri -> map = mvq -> map ;
25082579 ri -> restore = true;
25092580 return 0 ;
25102581}
@@ -2549,6 +2620,7 @@ static void restore_channels_info(struct mlx5_vdpa_net *ndev)
25492620 mvq -> desc_addr = ri -> desc_addr ;
25502621 mvq -> device_addr = ri -> device_addr ;
25512622 mvq -> driver_addr = ri -> driver_addr ;
2623+ mvq -> map = ri -> map ;
25522624 }
25532625}
25542626
@@ -2833,6 +2905,25 @@ static struct device *mlx5_get_vq_dma_dev(struct vdpa_device *vdev, u16 idx)
28332905 return mvdev -> vdev .dma_dev ;
28342906}
28352907
2908+ static void free_irqs (struct mlx5_vdpa_net * ndev )
2909+ {
2910+ struct mlx5_vdpa_irq_pool_entry * ent ;
2911+ int i ;
2912+
2913+ if (!msix_mode_supported (& ndev -> mvdev ))
2914+ return ;
2915+
2916+ if (!ndev -> irqp .entries )
2917+ return ;
2918+
2919+ for (i = ndev -> irqp .num_ent - 1 ; i >= 0 ; i -- ) {
2920+ ent = ndev -> irqp .entries + i ;
2921+ if (ent -> map .virq )
2922+ pci_msix_free_irq (ndev -> mvdev .mdev -> pdev , ent -> map );
2923+ }
2924+ kfree (ndev -> irqp .entries );
2925+ }
2926+
28362927static void mlx5_vdpa_free (struct vdpa_device * vdev )
28372928{
28382929 struct mlx5_vdpa_dev * mvdev = to_mvdev (vdev );
@@ -2848,6 +2939,7 @@ static void mlx5_vdpa_free(struct vdpa_device *vdev)
28482939 mlx5_mpfs_del_mac (pfmdev , ndev -> config .mac );
28492940 }
28502941 mlx5_vdpa_free_resources (& ndev -> mvdev );
2942+ free_irqs (ndev );
28512943 kfree (ndev -> event_cbs );
28522944 kfree (ndev -> vqs );
28532945}
@@ -2876,9 +2968,23 @@ static struct vdpa_notification_area mlx5_get_vq_notification(struct vdpa_device
28762968 return ret ;
28772969}
28782970
2879- static int mlx5_get_vq_irq (struct vdpa_device * vdv , u16 idx )
2971+ static int mlx5_get_vq_irq (struct vdpa_device * vdev , u16 idx )
28802972{
2881- return - EOPNOTSUPP ;
2973+ struct mlx5_vdpa_dev * mvdev = to_mvdev (vdev );
2974+ struct mlx5_vdpa_net * ndev = to_mlx5_vdpa_ndev (mvdev );
2975+ struct mlx5_vdpa_virtqueue * mvq ;
2976+
2977+ if (!is_index_valid (mvdev , idx ))
2978+ return - EINVAL ;
2979+
2980+ if (is_ctrl_vq_idx (mvdev , idx ))
2981+ return - EOPNOTSUPP ;
2982+
2983+ mvq = & ndev -> vqs [idx ];
2984+ if (!mvq -> map .virq )
2985+ return - EOPNOTSUPP ;
2986+
2987+ return mvq -> map .virq ;
28822988}
28832989
28842990static u64 mlx5_vdpa_get_driver_features (struct vdpa_device * vdev )
@@ -3155,6 +3261,34 @@ static int config_func_mtu(struct mlx5_core_dev *mdev, u16 mtu)
31553261 return err ;
31563262}
31573263
3264+ static void allocate_irqs (struct mlx5_vdpa_net * ndev )
3265+ {
3266+ struct mlx5_vdpa_irq_pool_entry * ent ;
3267+ int i ;
3268+
3269+ if (!msix_mode_supported (& ndev -> mvdev ))
3270+ return ;
3271+
3272+ if (!ndev -> mvdev .mdev -> pdev )
3273+ return ;
3274+
3275+ ndev -> irqp .entries = kcalloc (ndev -> mvdev .max_vqs , sizeof (* ndev -> irqp .entries ), GFP_KERNEL );
3276+ if (!ndev -> irqp .entries )
3277+ return ;
3278+
3279+
3280+ for (i = 0 ; i < ndev -> mvdev .max_vqs ; i ++ ) {
3281+ ent = ndev -> irqp .entries + i ;
3282+ snprintf (ent -> name , MLX5_VDPA_IRQ_NAME_LEN , "%s-vq-%d" ,
3283+ dev_name (& ndev -> mvdev .vdev .dev ), i );
3284+ ent -> map = pci_msix_alloc_irq_at (ndev -> mvdev .mdev -> pdev , MSI_ANY_INDEX , NULL );
3285+ if (!ent -> map .virq )
3286+ return ;
3287+
3288+ ndev -> irqp .num_ent ++ ;
3289+ }
3290+ }
3291+
31583292static int mlx5_vdpa_dev_add (struct vdpa_mgmt_dev * v_mdev , const char * name ,
31593293 const struct vdpa_dev_set_config * add_config )
31603294{
@@ -3233,6 +3367,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
32333367 }
32343368
32353369 init_mvqs (ndev );
3370+ allocate_irqs (ndev );
32363371 init_rwsem (& ndev -> reslock );
32373372 config = & ndev -> config ;
32383373
@@ -3413,6 +3548,17 @@ static void mlx5v_remove(struct auxiliary_device *adev)
34133548 kfree (mgtdev );
34143549}
34153550
3551+ static void mlx5v_shutdown (struct auxiliary_device * auxdev )
3552+ {
3553+ struct mlx5_vdpa_mgmtdev * mgtdev ;
3554+ struct mlx5_vdpa_net * ndev ;
3555+
3556+ mgtdev = auxiliary_get_drvdata (auxdev );
3557+ ndev = mgtdev -> ndev ;
3558+
3559+ free_irqs (ndev );
3560+ }
3561+
34163562static const struct auxiliary_device_id mlx5v_id_table [] = {
34173563 { .name = MLX5_ADEV_NAME ".vnet" , },
34183564 {},
@@ -3424,6 +3570,7 @@ static struct auxiliary_driver mlx5v_driver = {
34243570 .name = "vnet" ,
34253571 .probe = mlx5v_probe ,
34263572 .remove = mlx5v_remove ,
3573+ .shutdown = mlx5v_shutdown ,
34273574 .id_table = mlx5v_id_table ,
34283575};
34293576
0 commit comments