@@ -64,6 +64,7 @@ static inline void _iowrite64(u64 val, void __iomem *mmio)
64
64
65
65
struct shared_mw {
66
66
u32 magic ;
67
+ u32 link_sta ;
67
68
u32 partition_id ;
68
69
u64 mw_sizes [MAX_MWS ];
69
70
};
@@ -104,8 +105,17 @@ struct switchtec_ntb {
104
105
int peer_nr_direct_mw ;
105
106
int peer_nr_lut_mw ;
106
107
int peer_direct_mw_to_bar [MAX_DIRECT_MW ];
108
+
109
+ bool link_is_up ;
110
+ enum ntb_speed link_speed ;
111
+ enum ntb_width link_width ;
107
112
};
108
113
114
+ static struct switchtec_ntb * ntb_sndev (struct ntb_dev * ntb )
115
+ {
116
+ return container_of (ntb , struct switchtec_ntb , ntb );
117
+ }
118
+
109
119
static int switchtec_ntb_part_op (struct switchtec_ntb * sndev ,
110
120
struct ntb_ctrl_regs __iomem * ctl ,
111
121
u32 op , int wait_status )
@@ -163,6 +173,17 @@ static int switchtec_ntb_part_op(struct switchtec_ntb *sndev,
163
173
return - EIO ;
164
174
}
165
175
176
+ static int switchtec_ntb_send_msg (struct switchtec_ntb * sndev , int idx ,
177
+ u32 val )
178
+ {
179
+ if (idx < 0 || idx >= ARRAY_SIZE (sndev -> mmio_self_dbmsg -> omsg ))
180
+ return - EINVAL ;
181
+
182
+ iowrite32 (val , & sndev -> mmio_self_dbmsg -> omsg [idx ].msg );
183
+
184
+ return 0 ;
185
+ }
186
+
166
187
static int switchtec_ntb_mw_count (struct ntb_dev * ntb , int pidx )
167
188
{
168
189
return 0 ;
@@ -194,22 +215,124 @@ static int switchtec_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
194
215
return 0 ;
195
216
}
196
217
218
+ static void switchtec_ntb_part_link_speed (struct switchtec_ntb * sndev ,
219
+ int partition ,
220
+ enum ntb_speed * speed ,
221
+ enum ntb_width * width )
222
+ {
223
+ struct switchtec_dev * stdev = sndev -> stdev ;
224
+
225
+ u32 pff = ioread32 (& stdev -> mmio_part_cfg [partition ].vep_pff_inst_id );
226
+ u32 linksta = ioread32 (& stdev -> mmio_pff_csr [pff ].pci_cap_region [13 ]);
227
+
228
+ if (speed )
229
+ * speed = (linksta >> 16 ) & 0xF ;
230
+
231
+ if (width )
232
+ * width = (linksta >> 20 ) & 0x3F ;
233
+ }
234
+
235
+ static void switchtec_ntb_set_link_speed (struct switchtec_ntb * sndev )
236
+ {
237
+ enum ntb_speed self_speed , peer_speed ;
238
+ enum ntb_width self_width , peer_width ;
239
+
240
+ if (!sndev -> link_is_up ) {
241
+ sndev -> link_speed = NTB_SPEED_NONE ;
242
+ sndev -> link_width = NTB_WIDTH_NONE ;
243
+ return ;
244
+ }
245
+
246
+ switchtec_ntb_part_link_speed (sndev , sndev -> self_partition ,
247
+ & self_speed , & self_width );
248
+ switchtec_ntb_part_link_speed (sndev , sndev -> peer_partition ,
249
+ & peer_speed , & peer_width );
250
+
251
+ sndev -> link_speed = min (self_speed , peer_speed );
252
+ sndev -> link_width = min (self_width , peer_width );
253
+ }
254
+
255
+ enum {
256
+ LINK_MESSAGE = 0 ,
257
+ MSG_LINK_UP = 1 ,
258
+ MSG_LINK_DOWN = 2 ,
259
+ MSG_CHECK_LINK = 3 ,
260
+ };
261
+
262
+ static void switchtec_ntb_check_link (struct switchtec_ntb * sndev )
263
+ {
264
+ int link_sta ;
265
+ int old = sndev -> link_is_up ;
266
+
267
+ link_sta = sndev -> self_shared -> link_sta ;
268
+ if (link_sta ) {
269
+ u64 peer = ioread64 (& sndev -> peer_shared -> magic );
270
+
271
+ if ((peer & 0xFFFFFFFF ) == SWITCHTEC_NTB_MAGIC )
272
+ link_sta = peer >> 32 ;
273
+ else
274
+ link_sta = 0 ;
275
+ }
276
+
277
+ sndev -> link_is_up = link_sta ;
278
+ switchtec_ntb_set_link_speed (sndev );
279
+
280
+ if (link_sta != old ) {
281
+ switchtec_ntb_send_msg (sndev , LINK_MESSAGE , MSG_CHECK_LINK );
282
+ ntb_link_event (& sndev -> ntb );
283
+ dev_info (& sndev -> stdev -> dev , "ntb link %s" ,
284
+ link_sta ? "up" : "down" );
285
+ }
286
+ }
287
+
288
+ static void switchtec_ntb_link_notification (struct switchtec_dev * stdev )
289
+ {
290
+ struct switchtec_ntb * sndev = stdev -> sndev ;
291
+
292
+ switchtec_ntb_check_link (sndev );
293
+ }
294
+
197
295
static u64 switchtec_ntb_link_is_up (struct ntb_dev * ntb ,
198
296
enum ntb_speed * speed ,
199
297
enum ntb_width * width )
200
298
{
201
- return 0 ;
299
+ struct switchtec_ntb * sndev = ntb_sndev (ntb );
300
+
301
+ if (speed )
302
+ * speed = sndev -> link_speed ;
303
+ if (width )
304
+ * width = sndev -> link_width ;
305
+
306
+ return sndev -> link_is_up ;
202
307
}
203
308
204
309
static int switchtec_ntb_link_enable (struct ntb_dev * ntb ,
205
310
enum ntb_speed max_speed ,
206
311
enum ntb_width max_width )
207
312
{
313
+ struct switchtec_ntb * sndev = ntb_sndev (ntb );
314
+
315
+ dev_dbg (& sndev -> stdev -> dev , "enabling link" );
316
+
317
+ sndev -> self_shared -> link_sta = 1 ;
318
+ switchtec_ntb_send_msg (sndev , LINK_MESSAGE , MSG_LINK_UP );
319
+
320
+ switchtec_ntb_check_link (sndev );
321
+
208
322
return 0 ;
209
323
}
210
324
211
325
static int switchtec_ntb_link_disable (struct ntb_dev * ntb )
212
326
{
327
+ struct switchtec_ntb * sndev = ntb_sndev (ntb );
328
+
329
+ dev_dbg (& sndev -> stdev -> dev , "disabling link" );
330
+
331
+ sndev -> self_shared -> link_sta = 0 ;
332
+ switchtec_ntb_send_msg (sndev , LINK_MESSAGE , MSG_LINK_UP );
333
+
334
+ switchtec_ntb_check_link (sndev );
335
+
213
336
return 0 ;
214
337
}
215
338
@@ -577,6 +700,9 @@ static irqreturn_t switchtec_ntb_message_isr(int irq, void *dev)
577
700
dev_dbg (& sndev -> stdev -> dev , "message: %d %08x\n" , i ,
578
701
(u32 )msg );
579
702
iowrite8 (1 , & sndev -> mmio_self_dbmsg -> imsg [i ].status );
703
+
704
+ if (i == LINK_MESSAGE )
705
+ switchtec_ntb_check_link (sndev );
580
706
}
581
707
}
582
708
@@ -679,6 +805,7 @@ static int switchtec_ntb_add(struct device *dev,
679
805
goto deinit_and_exit ;
680
806
681
807
stdev -> sndev = sndev ;
808
+ stdev -> link_notifier = switchtec_ntb_link_notification ;
682
809
dev_info (dev , "NTB device registered" );
683
810
684
811
return 0 ;
@@ -702,6 +829,7 @@ void switchtec_ntb_remove(struct device *dev,
702
829
if (!sndev )
703
830
return ;
704
831
832
+ stdev -> link_notifier = NULL ;
705
833
stdev -> sndev = NULL ;
706
834
ntb_unregister_device (& sndev -> ntb );
707
835
switchtec_ntb_deinit_db_msg_irq (sndev );
0 commit comments