@@ -93,6 +93,12 @@ static bool use_dma;
93
93
module_param (use_dma , bool , 0644 );
94
94
MODULE_PARM_DESC (use_dma , "Use DMA engine to perform large data copy" );
95
95
96
+ static bool use_msi ;
97
+ #ifdef CONFIG_NTB_MSI
98
+ module_param (use_msi , bool , 0644 );
99
+ MODULE_PARM_DESC (use_msi , "Use MSI interrupts instead of doorbells" );
100
+ #endif
101
+
96
102
static struct dentry * nt_debugfs_dir ;
97
103
98
104
/* Only two-ports NTB devices are supported */
@@ -188,6 +194,11 @@ struct ntb_transport_qp {
188
194
u64 tx_err_no_buf ;
189
195
u64 tx_memcpy ;
190
196
u64 tx_async ;
197
+
198
+ bool use_msi ;
199
+ int msi_irq ;
200
+ struct ntb_msi_desc msi_desc ;
201
+ struct ntb_msi_desc peer_msi_desc ;
191
202
};
192
203
193
204
struct ntb_transport_mw {
@@ -221,6 +232,10 @@ struct ntb_transport_ctx {
221
232
u64 qp_bitmap ;
222
233
u64 qp_bitmap_free ;
223
234
235
+ bool use_msi ;
236
+ unsigned int msi_spad_offset ;
237
+ u64 msi_db_mask ;
238
+
224
239
bool link_is_up ;
225
240
struct delayed_work link_work ;
226
241
struct work_struct link_cleanup ;
@@ -667,6 +682,114 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
667
682
return 0 ;
668
683
}
669
684
685
+ static irqreturn_t ntb_transport_isr (int irq , void * dev )
686
+ {
687
+ struct ntb_transport_qp * qp = dev ;
688
+
689
+ tasklet_schedule (& qp -> rxc_db_work );
690
+
691
+ return IRQ_HANDLED ;
692
+ }
693
+
694
+ static void ntb_transport_setup_qp_peer_msi (struct ntb_transport_ctx * nt ,
695
+ unsigned int qp_num )
696
+ {
697
+ struct ntb_transport_qp * qp = & nt -> qp_vec [qp_num ];
698
+ int spad = qp_num * 2 + nt -> msi_spad_offset ;
699
+
700
+ if (!nt -> use_msi )
701
+ return ;
702
+
703
+ if (spad >= ntb_spad_count (nt -> ndev ))
704
+ return ;
705
+
706
+ qp -> peer_msi_desc .addr_offset =
707
+ ntb_peer_spad_read (qp -> ndev , PIDX , spad );
708
+ qp -> peer_msi_desc .data =
709
+ ntb_peer_spad_read (qp -> ndev , PIDX , spad + 1 );
710
+
711
+ dev_dbg (& qp -> ndev -> pdev -> dev , "QP%d Peer MSI addr=%x data=%x\n" ,
712
+ qp_num , qp -> peer_msi_desc .addr_offset , qp -> peer_msi_desc .data );
713
+
714
+ if (qp -> peer_msi_desc .addr_offset ) {
715
+ qp -> use_msi = true;
716
+ dev_info (& qp -> ndev -> pdev -> dev ,
717
+ "Using MSI interrupts for QP%d\n" , qp_num );
718
+ }
719
+ }
720
+
721
+ static void ntb_transport_setup_qp_msi (struct ntb_transport_ctx * nt ,
722
+ unsigned int qp_num )
723
+ {
724
+ struct ntb_transport_qp * qp = & nt -> qp_vec [qp_num ];
725
+ int spad = qp_num * 2 + nt -> msi_spad_offset ;
726
+ int rc ;
727
+
728
+ if (!nt -> use_msi )
729
+ return ;
730
+
731
+ if (spad >= ntb_spad_count (nt -> ndev )) {
732
+ dev_warn_once (& qp -> ndev -> pdev -> dev ,
733
+ "Not enough SPADS to use MSI interrupts\n" );
734
+ return ;
735
+ }
736
+
737
+ ntb_spad_write (qp -> ndev , spad , 0 );
738
+ ntb_spad_write (qp -> ndev , spad + 1 , 0 );
739
+
740
+ if (!qp -> msi_irq ) {
741
+ qp -> msi_irq = ntbm_msi_request_irq (qp -> ndev , ntb_transport_isr ,
742
+ KBUILD_MODNAME , qp ,
743
+ & qp -> msi_desc );
744
+ if (qp -> msi_irq < 0 ) {
745
+ dev_warn (& qp -> ndev -> pdev -> dev ,
746
+ "Unable to allocate MSI interrupt for qp%d\n" ,
747
+ qp_num );
748
+ return ;
749
+ }
750
+ }
751
+
752
+ rc = ntb_spad_write (qp -> ndev , spad , qp -> msi_desc .addr_offset );
753
+ if (rc )
754
+ goto err_free_interrupt ;
755
+
756
+ rc = ntb_spad_write (qp -> ndev , spad + 1 , qp -> msi_desc .data );
757
+ if (rc )
758
+ goto err_free_interrupt ;
759
+
760
+ dev_dbg (& qp -> ndev -> pdev -> dev , "QP%d MSI %d addr=%x data=%x\n" ,
761
+ qp_num , qp -> msi_irq , qp -> msi_desc .addr_offset ,
762
+ qp -> msi_desc .data );
763
+
764
+ return ;
765
+
766
+ err_free_interrupt :
767
+ devm_free_irq (& nt -> ndev -> dev , qp -> msi_irq , qp );
768
+ }
769
+
770
+ static void ntb_transport_msi_peer_desc_changed (struct ntb_transport_ctx * nt )
771
+ {
772
+ int i ;
773
+
774
+ dev_dbg (& nt -> ndev -> pdev -> dev , "Peer MSI descriptors changed" );
775
+
776
+ for (i = 0 ; i < nt -> qp_count ; i ++ )
777
+ ntb_transport_setup_qp_peer_msi (nt , i );
778
+ }
779
+
780
+ static void ntb_transport_msi_desc_changed (void * data )
781
+ {
782
+ struct ntb_transport_ctx * nt = data ;
783
+ int i ;
784
+
785
+ dev_dbg (& nt -> ndev -> pdev -> dev , "MSI descriptors changed" );
786
+
787
+ for (i = 0 ; i < nt -> qp_count ; i ++ )
788
+ ntb_transport_setup_qp_msi (nt , i );
789
+
790
+ ntb_peer_db_set (nt -> ndev , nt -> msi_db_mask );
791
+ }
792
+
670
793
static void ntb_free_mw (struct ntb_transport_ctx * nt , int num_mw )
671
794
{
672
795
struct ntb_transport_mw * mw = & nt -> mw_vec [num_mw ];
@@ -905,6 +1028,20 @@ static void ntb_transport_link_work(struct work_struct *work)
905
1028
int rc = 0 , i , spad ;
906
1029
907
1030
/* send the local info, in the opposite order of the way we read it */
1031
+
1032
+ if (nt -> use_msi ) {
1033
+ rc = ntb_msi_setup_mws (ndev );
1034
+ if (rc ) {
1035
+ dev_warn (& pdev -> dev ,
1036
+ "Failed to register MSI memory window: %d\n" ,
1037
+ rc );
1038
+ nt -> use_msi = false;
1039
+ }
1040
+ }
1041
+
1042
+ for (i = 0 ; i < nt -> qp_count ; i ++ )
1043
+ ntb_transport_setup_qp_msi (nt , i );
1044
+
908
1045
for (i = 0 ; i < nt -> mw_count ; i ++ ) {
909
1046
size = nt -> mw_vec [i ].phys_size ;
910
1047
@@ -962,6 +1099,7 @@ static void ntb_transport_link_work(struct work_struct *work)
962
1099
struct ntb_transport_qp * qp = & nt -> qp_vec [i ];
963
1100
964
1101
ntb_transport_setup_qp_mw (nt , i );
1102
+ ntb_transport_setup_qp_peer_msi (nt , i );
965
1103
966
1104
if (qp -> client_ready )
967
1105
schedule_delayed_work (& qp -> link_work , 0 );
@@ -1135,6 +1273,19 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
1135
1273
return - ENOMEM ;
1136
1274
1137
1275
nt -> ndev = ndev ;
1276
+
1277
+ /*
1278
+ * If we are using MSI, and have at least one extra memory window,
1279
+ * we will reserve the last MW for the MSI window.
1280
+ */
1281
+ if (use_msi && mw_count > 1 ) {
1282
+ rc = ntb_msi_init (ndev , ntb_transport_msi_desc_changed );
1283
+ if (!rc ) {
1284
+ mw_count -= 1 ;
1285
+ nt -> use_msi = true;
1286
+ }
1287
+ }
1288
+
1138
1289
spad_count = ntb_spad_count (ndev );
1139
1290
1140
1291
/* Limit the MW's based on the availability of scratchpads */
@@ -1148,6 +1299,8 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
1148
1299
max_mw_count_for_spads = (spad_count - MW0_SZ_HIGH ) / 2 ;
1149
1300
nt -> mw_count = min (mw_count , max_mw_count_for_spads );
1150
1301
1302
+ nt -> msi_spad_offset = nt -> mw_count * 2 + MW0_SZ_HIGH ;
1303
+
1151
1304
nt -> mw_vec = kcalloc_node (mw_count , sizeof (* nt -> mw_vec ),
1152
1305
GFP_KERNEL , node );
1153
1306
if (!nt -> mw_vec ) {
@@ -1178,6 +1331,12 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
1178
1331
qp_bitmap = ntb_db_valid_mask (ndev );
1179
1332
1180
1333
qp_count = ilog2 (qp_bitmap );
1334
+ if (nt -> use_msi ) {
1335
+ qp_count -= 1 ;
1336
+ nt -> msi_db_mask = 1 << qp_count ;
1337
+ ntb_db_clear_mask (ndev , nt -> msi_db_mask );
1338
+ }
1339
+
1181
1340
if (max_num_clients && max_num_clients < qp_count )
1182
1341
qp_count = max_num_clients ;
1183
1342
else if (nt -> mw_count < qp_count )
@@ -1601,7 +1760,10 @@ static void ntb_tx_copy_callback(void *data,
1601
1760
1602
1761
iowrite32 (entry -> flags | DESC_DONE_FLAG , & hdr -> flags );
1603
1762
1604
- ntb_peer_db_set (qp -> ndev , BIT_ULL (qp -> qp_num ));
1763
+ if (qp -> use_msi )
1764
+ ntb_msi_peer_trigger (qp -> ndev , PIDX , & qp -> peer_msi_desc );
1765
+ else
1766
+ ntb_peer_db_set (qp -> ndev , BIT_ULL (qp -> qp_num ));
1605
1767
1606
1768
/* The entry length can only be zero if the packet is intended to be a
1607
1769
* "link down" or similar. Since no payload is being sent in these
@@ -2269,6 +2431,11 @@ static void ntb_transport_doorbell_callback(void *data, int vector)
2269
2431
u64 db_bits ;
2270
2432
unsigned int qp_num ;
2271
2433
2434
+ if (ntb_db_read (nt -> ndev ) & nt -> msi_db_mask ) {
2435
+ ntb_transport_msi_peer_desc_changed (nt );
2436
+ ntb_db_clear (nt -> ndev , nt -> msi_db_mask );
2437
+ }
2438
+
2272
2439
db_bits = (nt -> qp_bitmap & ~nt -> qp_bitmap_free &
2273
2440
ntb_db_vector_mask (nt -> ndev , vector ));
2274
2441
0 commit comments