1616#include <linux/switchtec.h>
1717#include <linux/module.h>
1818#include <linux/delay.h>
19- #include <linux/interrupt.h>
2019#include <linux/kthread.h>
20+ #include <linux/interrupt.h>
2121#include <linux/ntb.h>
2222
2323MODULE_DESCRIPTION ("Microsemi Switchtec(tm) NTB Driver" );
@@ -28,7 +28,7 @@ MODULE_AUTHOR("Microsemi Corporation");
2828static ulong max_mw_size = SZ_2M ;
2929module_param (max_mw_size , ulong , 0644 );
3030MODULE_PARM_DESC (max_mw_size ,
31- "Limit the size of the memory windows reported to the upper layer" );
31+ "Max memory window size reported to the upper layer" );
3232
3333static bool use_lut_mws ;
3434module_param (use_lut_mws , bool , 0644 );
@@ -65,11 +65,13 @@ static inline void _iowrite64(u64 val, void __iomem *mmio)
6565#endif
6666
6767#define SWITCHTEC_NTB_MAGIC 0x45CC0001
68+ #define MAX_MWS 128
6869
6970struct shared_mw {
7071 u32 magic ;
7172 u32 link_sta ;
7273 u32 partition_id ;
74+ u64 mw_sizes [MAX_MWS ];
7375 u32 spad [128 ];
7476};
7577
@@ -109,10 +111,13 @@ struct switchtec_ntb {
109111 int nr_lut_mw ;
110112 int direct_mw_to_bar [MAX_DIRECT_MW ];
111113
114+ int peer_nr_direct_mw ;
115+ int peer_nr_lut_mw ;
116+ int peer_direct_mw_to_bar [MAX_DIRECT_MW ];
117+
112118 bool link_is_up ;
113119 enum ntb_speed link_speed ;
114120 enum ntb_width link_width ;
115- struct notifier_block link_notifier ;
116121};
117122
118123static struct switchtec_ntb * ntb_sndev (struct ntb_dev * ntb )
@@ -191,18 +196,25 @@ static int switchtec_ntb_send_msg(struct switchtec_ntb *sndev, int idx,
191196static int switchtec_ntb_mw_count (struct ntb_dev * ntb )
192197{
193198 struct switchtec_ntb * sndev = ntb_sndev (ntb );
199+ int nr_direct_mw = sndev -> peer_nr_direct_mw ;
200+ int nr_lut_mw = sndev -> peer_nr_lut_mw - 1 ;
194201
195- if (use_lut_mws )
196- return sndev -> nr_direct_mw + sndev -> nr_lut_mw - 1 ;
197- else
198- return sndev -> nr_direct_mw ;
202+ if (! use_lut_mws )
203+ nr_lut_mw = 0 ;
204+
205+ return nr_direct_mw + nr_lut_mw ;
199206}
200207
201208static int lut_index (struct switchtec_ntb * sndev , int mw_idx )
202209{
203210 return mw_idx - sndev -> nr_direct_mw + 1 ;
204211}
205212
213+ static int peer_lut_index (struct switchtec_ntb * sndev , int mw_idx )
214+ {
215+ return mw_idx - sndev -> peer_nr_direct_mw + 1 ;
216+ }
217+
206218static int switchtec_ntb_mw_direct_get_range (struct switchtec_ntb * sndev ,
207219 int idx , phys_addr_t * base ,
208220 resource_size_t * size ,
@@ -295,7 +307,7 @@ static int switchtec_ntb_mw_get_range(struct ntb_dev *ntb, int idx,
295307static void switchtec_ntb_mw_clr_direct (struct switchtec_ntb * sndev , int idx )
296308{
297309 struct ntb_ctrl_regs __iomem * ctl = sndev -> mmio_peer_ctrl ;
298- int bar = sndev -> direct_mw_to_bar [idx ];
310+ int bar = sndev -> peer_direct_mw_to_bar [idx ];
299311 u32 ctl_val ;
300312
301313 ctl_val = ioread32 (& ctl -> bar_entry [bar ].ctl );
@@ -309,14 +321,14 @@ static void switchtec_ntb_mw_clr_lut(struct switchtec_ntb *sndev, int idx)
309321{
310322 struct ntb_ctrl_regs __iomem * ctl = sndev -> mmio_peer_ctrl ;
311323
312- iowrite64 (0 , & ctl -> lut_entry [lut_index (sndev , idx )]);
324+ iowrite64 (0 , & ctl -> lut_entry [peer_lut_index (sndev , idx )]);
313325}
314326
315327static void switchtec_ntb_mw_set_direct (struct switchtec_ntb * sndev , int idx ,
316328 dma_addr_t addr , resource_size_t size )
317329{
318330 int xlate_pos = ilog2 (size );
319- int bar = sndev -> direct_mw_to_bar [idx ];
331+ int bar = sndev -> peer_direct_mw_to_bar [idx ];
320332 struct ntb_ctrl_regs __iomem * ctl = sndev -> mmio_peer_ctrl ;
321333 u32 ctl_val ;
322334
@@ -335,7 +347,7 @@ static void switchtec_ntb_mw_set_lut(struct switchtec_ntb *sndev, int idx,
335347 struct ntb_ctrl_regs __iomem * ctl = sndev -> mmio_peer_ctrl ;
336348
337349 iowrite64 ((NTB_CTRL_LUT_EN | (sndev -> self_partition << 1 ) | addr ),
338- & ctl -> lut_entry [lut_index (sndev , idx )]);
350+ & ctl -> lut_entry [peer_lut_index (sndev , idx )]);
339351}
340352
341353static int switchtec_ntb_mw_set_trans (struct ntb_dev * ntb , int idx ,
@@ -344,6 +356,7 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
344356 struct switchtec_ntb * sndev = ntb_sndev (ntb );
345357 struct ntb_ctrl_regs __iomem * ctl = sndev -> mmio_peer_ctrl ;
346358 int xlate_pos = ilog2 (size );
359+ int nr_direct_mw = sndev -> peer_nr_direct_mw ;
347360 int rc ;
348361
349362 dev_dbg (& sndev -> stdev -> dev , "MW %d: %016llx %016llx" , idx , addr , size );
@@ -360,12 +373,12 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
360373 return rc ;
361374
362375 if (addr == 0 || size == 0 ) {
363- if (idx < sndev -> nr_direct_mw )
376+ if (idx < nr_direct_mw )
364377 switchtec_ntb_mw_clr_direct (sndev , idx );
365378 else
366379 switchtec_ntb_mw_clr_lut (sndev , idx );
367380 } else {
368- if (idx < sndev -> nr_direct_mw )
381+ if (idx < nr_direct_mw )
369382 switchtec_ntb_mw_set_direct (sndev , idx , addr , size );
370383 else
371384 switchtec_ntb_mw_set_lut (sndev , idx , addr , size );
@@ -379,7 +392,7 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
379392 "Hardware reported an error configuring mw %d: %08x" ,
380393 idx , ioread32 (& ctl -> bar_error ));
381394
382- if (idx < sndev -> nr_direct_mw )
395+ if (idx < nr_direct_mw )
383396 switchtec_ntb_mw_clr_direct (sndev , idx );
384397 else
385398 switchtec_ntb_mw_clr_lut (sndev , idx );
@@ -461,35 +474,11 @@ static void switchtec_ntb_check_link(struct switchtec_ntb *sndev)
461474 }
462475}
463476
464- static void switchtec_ntb_link_event (struct switchtec_ntb * sndev , int msg )
465- {
466- switchtec_ntb_check_link (sndev );
467- }
468-
469- static int switchtec_ntb_link_notification (struct notifier_block * nb ,
470- unsigned long event , void * data )
477+ static void switchtec_ntb_link_notification (struct switchtec_dev * stdev )
471478{
472- struct switchtec_ntb * sndev = container_of (nb , struct switchtec_ntb ,
473- link_notifier );
479+ struct switchtec_ntb * sndev = stdev -> sndev ;
474480
475- dev_dbg (& sndev -> stdev -> dev , "link message received" );
476481 switchtec_ntb_check_link (sndev );
477-
478- return NOTIFY_OK ;
479- }
480-
481- static int switchtec_ntb_init_link_notifier (struct switchtec_ntb * sndev )
482- {
483- sndev -> link_notifier .notifier_call = switchtec_ntb_link_notification ;
484-
485- return blocking_notifier_chain_register (& sndev -> stdev -> link_notifier ,
486- & sndev -> link_notifier );
487- }
488-
489- static void switchtec_ntb_deinit_link_notifier (struct switchtec_ntb * sndev )
490- {
491- blocking_notifier_chain_unregister (& sndev -> stdev -> link_notifier ,
492- & sndev -> link_notifier );
493482}
494483
495484static int switchtec_ntb_link_is_up (struct ntb_dev * ntb ,
@@ -782,23 +771,42 @@ static void switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
782771 sndev -> mmio_self_dbmsg = & sndev -> mmio_dbmsg [sndev -> self_partition ];
783772}
784773
785- static void switchtec_ntb_init_mw ( struct switchtec_ntb * sndev )
774+ static int map_bars ( int * map , struct ntb_ctrl_regs __iomem * ctrl )
786775{
787776 int i ;
777+ int cnt = 0 ;
788778
789- sndev -> nr_direct_mw = 0 ;
790- for (i = 0 ; i < ARRAY_SIZE (sndev -> mmio_self_ctrl -> bar_entry ); i ++ ) {
791- u32 r = ioread32 (& sndev -> mmio_self_ctrl -> bar_entry [i ].ctl );
779+ for (i = 0 ; i < ARRAY_SIZE (ctrl -> bar_entry ); i ++ ) {
780+ u32 r = ioread32 (& ctrl -> bar_entry [i ].ctl );
792781
793782 if (r & NTB_CTRL_BAR_VALID )
794- sndev -> direct_mw_to_bar [ sndev -> nr_direct_mw ++ ] = i ;
783+ map [ cnt ++ ] = i ;
795784 }
796785
786+ return cnt ;
787+ }
788+
789+ static void switchtec_ntb_init_mw (struct switchtec_ntb * sndev )
790+ {
791+ sndev -> nr_direct_mw = map_bars (sndev -> direct_mw_to_bar ,
792+ sndev -> mmio_self_ctrl );
793+
797794 sndev -> nr_lut_mw = ioread16 (& sndev -> mmio_self_ctrl -> lut_table_entries );
798795 sndev -> nr_lut_mw = rounddown_pow_of_two (sndev -> nr_lut_mw );
799796
800797 dev_dbg (& sndev -> stdev -> dev , "MWs: %d direct, %d lut" ,
801798 sndev -> nr_direct_mw , sndev -> nr_lut_mw );
799+
800+ sndev -> peer_nr_direct_mw = map_bars (sndev -> peer_direct_mw_to_bar ,
801+ sndev -> mmio_peer_ctrl );
802+
803+ sndev -> peer_nr_lut_mw =
804+ ioread16 (& sndev -> mmio_peer_ctrl -> lut_table_entries );
805+ sndev -> peer_nr_lut_mw = rounddown_pow_of_two (sndev -> peer_nr_lut_mw );
806+
807+ dev_dbg (& sndev -> stdev -> dev , "Peer MWs: %d direct, %d lut" ,
808+ sndev -> peer_nr_direct_mw , sndev -> peer_nr_lut_mw );
809+
802810}
803811
804812/*
@@ -887,6 +895,32 @@ static int switchtec_ntb_init_req_id_table(struct switchtec_ntb *sndev)
887895 return rc ;
888896}
889897
898+ static void switchtec_ntb_init_shared (struct switchtec_ntb * sndev )
899+ {
900+ int i ;
901+
902+ memset (sndev -> self_shared , 0 , LUT_SIZE );
903+ sndev -> self_shared -> magic = SWITCHTEC_NTB_MAGIC ;
904+ sndev -> self_shared -> partition_id = sndev -> stdev -> partition ;
905+
906+ for (i = 0 ; i < sndev -> nr_direct_mw ; i ++ ) {
907+ int bar = sndev -> direct_mw_to_bar [i ];
908+ resource_size_t sz = pci_resource_len (sndev -> stdev -> pdev , bar );
909+
910+ if (i == 0 )
911+ sz = min_t (resource_size_t , sz ,
912+ LUT_SIZE * sndev -> nr_lut_mw );
913+
914+ sndev -> self_shared -> mw_sizes [i ] = sz ;
915+ }
916+
917+ for (i = 0 ; i < sndev -> nr_lut_mw ; i ++ ) {
918+ int idx = sndev -> nr_direct_mw + i ;
919+
920+ sndev -> self_shared -> mw_sizes [idx ] = LUT_SIZE ;
921+ }
922+ }
923+
890924static int switchtec_ntb_init_shared_mw (struct switchtec_ntb * sndev )
891925{
892926 struct ntb_ctrl_regs __iomem * ctl = sndev -> mmio_peer_ctrl ;
@@ -904,9 +938,7 @@ static int switchtec_ntb_init_shared_mw(struct switchtec_ntb *sndev)
904938 return - ENOMEM ;
905939 }
906940
907- memset (sndev -> self_shared , 0 , LUT_SIZE );
908- sndev -> self_shared -> magic = SWITCHTEC_NTB_MAGIC ;
909- sndev -> self_shared -> partition_id = sndev -> stdev -> partition ;
941+ switchtec_ntb_init_shared (sndev );
910942
911943 rc = switchtec_ntb_part_op (sndev , ctl , NTB_CTRL_PART_OP_LOCK ,
912944 NTB_CTRL_PART_STATUS_LOCKED );
@@ -989,7 +1021,7 @@ static irqreturn_t switchtec_ntb_message_isr(int irq, void *dev)
9891021 iowrite8 (1 , & sndev -> mmio_self_dbmsg -> imsg [i ].status );
9901022
9911023 if (i == LINK_MESSAGE )
992- switchtec_ntb_link_event (sndev , msg );
1024+ switchtec_ntb_check_link (sndev );
9931025 }
9941026 }
9951027
@@ -1087,22 +1119,19 @@ static int switchtec_ntb_add(struct device *dev,
10871119 if (rc )
10881120 goto deinit_shared_and_exit ;
10891121
1090- rc = switchtec_ntb_init_link_notifier (sndev );
1091- if (rc )
1092- goto denit_db_msg_and_exit ;
1122+ switchtec_ntb_init_mw (sndev );
10931123
10941124 rc = ntb_register_device (& sndev -> ntb );
10951125 if (rc )
10961126 goto deinit_and_exit ;
10971127
10981128 stdev -> sndev = sndev ;
1129+ stdev -> link_notifier = switchtec_ntb_link_notification ;
10991130 dev_info (dev , "NTB device registered" );
11001131
11011132 return 0 ;
11021133
11031134deinit_and_exit :
1104- switchtec_ntb_deinit_link_notifier (sndev );
1105- denit_db_msg_and_exit :
11061135 switchtec_ntb_deinit_db_msg_irq (sndev );
11071136deinit_shared_and_exit :
11081137 switchtec_ntb_deinit_shared_mw (sndev );
@@ -1121,9 +1150,9 @@ void switchtec_ntb_remove(struct device *dev,
11211150 if (!sndev )
11221151 return ;
11231152
1153+ stdev -> link_notifier = NULL ;
11241154 stdev -> sndev = NULL ;
11251155 ntb_unregister_device (& sndev -> ntb );
1126- switchtec_ntb_deinit_link_notifier (sndev );
11271156 switchtec_ntb_deinit_db_msg_irq (sndev );
11281157 switchtec_ntb_deinit_shared_mw (sndev );
11291158 kfree (sndev );
0 commit comments