@@ -186,6 +186,26 @@ static inline void smc_llc_flow_qentry_set(struct smc_llc_flow *flow,
186
186
flow -> qentry = qentry ;
187
187
}
188
188
189
+ static void smc_llc_flow_parallel (struct smc_link_group * lgr , u8 flow_type ,
190
+ struct smc_llc_qentry * qentry )
191
+ {
192
+ u8 msg_type = qentry -> msg .raw .hdr .common .type ;
193
+
194
+ if ((msg_type == SMC_LLC_ADD_LINK || msg_type == SMC_LLC_DELETE_LINK ) &&
195
+ flow_type != msg_type && !lgr -> delayed_event ) {
196
+ lgr -> delayed_event = qentry ;
197
+ return ;
198
+ }
199
+ /* drop parallel or already-in-progress llc requests */
200
+ if (flow_type != msg_type )
201
+ pr_warn_once ("smc: SMC-R lg %*phN dropped parallel "
202
+ "LLC msg: msg %d flow %d role %d\n" ,
203
+ SMC_LGR_ID_SIZE , & lgr -> id ,
204
+ qentry -> msg .raw .hdr .common .type ,
205
+ flow_type , lgr -> role );
206
+ kfree (qentry );
207
+ }
208
+
189
209
/* try to start a new llc flow, initiated by an incoming llc msg */
190
210
static bool smc_llc_flow_start (struct smc_llc_flow * flow ,
191
211
struct smc_llc_qentry * qentry )
@@ -195,14 +215,7 @@ static bool smc_llc_flow_start(struct smc_llc_flow *flow,
195
215
spin_lock_bh (& lgr -> llc_flow_lock );
196
216
if (flow -> type ) {
197
217
/* a flow is already active */
198
- if ((qentry -> msg .raw .hdr .common .type == SMC_LLC_ADD_LINK ||
199
- qentry -> msg .raw .hdr .common .type == SMC_LLC_DELETE_LINK ) &&
200
- !lgr -> delayed_event ) {
201
- lgr -> delayed_event = qentry ;
202
- } else {
203
- /* forget this llc request */
204
- kfree (qentry );
205
- }
218
+ smc_llc_flow_parallel (lgr , flow -> type , qentry );
206
219
spin_unlock_bh (& lgr -> llc_flow_lock );
207
220
return false;
208
221
}
@@ -222,8 +235,8 @@ static bool smc_llc_flow_start(struct smc_llc_flow *flow,
222
235
}
223
236
if (qentry == lgr -> delayed_event )
224
237
lgr -> delayed_event = NULL ;
225
- spin_unlock_bh (& lgr -> llc_flow_lock );
226
238
smc_llc_flow_qentry_set (flow , qentry );
239
+ spin_unlock_bh (& lgr -> llc_flow_lock );
227
240
return true;
228
241
}
229
242
@@ -251,11 +264,11 @@ int smc_llc_flow_initiate(struct smc_link_group *lgr,
251
264
return 0 ;
252
265
}
253
266
spin_unlock_bh (& lgr -> llc_flow_lock );
254
- rc = wait_event_interruptible_timeout (lgr -> llc_waiter ,
255
- (lgr -> llc_flow_lcl .type == SMC_LLC_FLOW_NONE &&
256
- (lgr -> llc_flow_rmt .type == SMC_LLC_FLOW_NONE ||
257
- lgr -> llc_flow_rmt .type == allowed_remote )),
258
- SMC_LLC_WAIT_TIME );
267
+ rc = wait_event_timeout (lgr -> llc_flow_waiter , ( list_empty ( & lgr -> list ) ||
268
+ (lgr -> llc_flow_lcl .type == SMC_LLC_FLOW_NONE &&
269
+ (lgr -> llc_flow_rmt .type == SMC_LLC_FLOW_NONE ||
270
+ lgr -> llc_flow_rmt .type == allowed_remote ) )),
271
+ SMC_LLC_WAIT_TIME * 10 );
259
272
if (!rc )
260
273
return - ETIMEDOUT ;
261
274
goto again ;
@@ -272,7 +285,7 @@ void smc_llc_flow_stop(struct smc_link_group *lgr, struct smc_llc_flow *flow)
272
285
flow == & lgr -> llc_flow_lcl )
273
286
schedule_work (& lgr -> llc_event_work );
274
287
else
275
- wake_up_interruptible (& lgr -> llc_waiter );
288
+ wake_up (& lgr -> llc_flow_waiter );
276
289
}
277
290
278
291
/* lnk is optional and used for early wakeup when link goes down, useful in
@@ -283,26 +296,32 @@ struct smc_llc_qentry *smc_llc_wait(struct smc_link_group *lgr,
283
296
int time_out , u8 exp_msg )
284
297
{
285
298
struct smc_llc_flow * flow = & lgr -> llc_flow_lcl ;
299
+ u8 rcv_msg ;
286
300
287
- wait_event_interruptible_timeout (lgr -> llc_waiter ,
288
- (flow -> qentry ||
289
- (lnk && !smc_link_usable (lnk )) ||
290
- list_empty (& lgr -> list )),
291
- time_out );
301
+ wait_event_timeout (lgr -> llc_msg_waiter ,
302
+ (flow -> qentry ||
303
+ (lnk && !smc_link_usable (lnk )) ||
304
+ list_empty (& lgr -> list )),
305
+ time_out );
292
306
if (!flow -> qentry ||
293
307
(lnk && !smc_link_usable (lnk )) || list_empty (& lgr -> list )) {
294
308
smc_llc_flow_qentry_del (flow );
295
309
goto out ;
296
310
}
297
- if (exp_msg && flow -> qentry -> msg .raw .hdr .common .type != exp_msg ) {
311
+ rcv_msg = flow -> qentry -> msg .raw .hdr .common .type ;
312
+ if (exp_msg && rcv_msg != exp_msg ) {
298
313
if (exp_msg == SMC_LLC_ADD_LINK &&
299
- flow -> qentry -> msg .raw .hdr .common .type ==
300
- SMC_LLC_DELETE_LINK ) {
314
+ rcv_msg == SMC_LLC_DELETE_LINK ) {
301
315
/* flow_start will delay the unexpected msg */
302
316
smc_llc_flow_start (& lgr -> llc_flow_lcl ,
303
317
smc_llc_flow_qentry_clr (flow ));
304
318
return NULL ;
305
319
}
320
+ pr_warn_once ("smc: SMC-R lg %*phN dropped unexpected LLC msg: "
321
+ "msg %d exp %d flow %d role %d flags %x\n" ,
322
+ SMC_LGR_ID_SIZE , & lgr -> id , rcv_msg , exp_msg ,
323
+ flow -> type , lgr -> role ,
324
+ flow -> qentry -> msg .raw .hdr .flags );
306
325
smc_llc_flow_qentry_del (flow );
307
326
}
308
327
out :
@@ -1459,7 +1478,7 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
1459
1478
/* a flow is waiting for this message */
1460
1479
smc_llc_flow_qentry_set (& lgr -> llc_flow_lcl ,
1461
1480
qentry );
1462
- wake_up_interruptible (& lgr -> llc_waiter );
1481
+ wake_up (& lgr -> llc_msg_waiter );
1463
1482
} else if (smc_llc_flow_start (& lgr -> llc_flow_lcl ,
1464
1483
qentry )) {
1465
1484
schedule_work (& lgr -> llc_add_link_work );
@@ -1474,7 +1493,7 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
1474
1493
if (lgr -> llc_flow_lcl .type != SMC_LLC_FLOW_NONE ) {
1475
1494
/* a flow is waiting for this message */
1476
1495
smc_llc_flow_qentry_set (& lgr -> llc_flow_lcl , qentry );
1477
- wake_up_interruptible (& lgr -> llc_waiter );
1496
+ wake_up (& lgr -> llc_msg_waiter );
1478
1497
return ;
1479
1498
}
1480
1499
break ;
@@ -1485,7 +1504,7 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
1485
1504
/* DEL LINK REQ during ADD LINK SEQ */
1486
1505
smc_llc_flow_qentry_set (& lgr -> llc_flow_lcl ,
1487
1506
qentry );
1488
- wake_up_interruptible (& lgr -> llc_waiter );
1507
+ wake_up (& lgr -> llc_msg_waiter );
1489
1508
} else if (smc_llc_flow_start (& lgr -> llc_flow_lcl ,
1490
1509
qentry )) {
1491
1510
schedule_work (& lgr -> llc_del_link_work );
@@ -1496,7 +1515,7 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
1496
1515
/* DEL LINK REQ during ADD LINK SEQ */
1497
1516
smc_llc_flow_qentry_set (& lgr -> llc_flow_lcl ,
1498
1517
qentry );
1499
- wake_up_interruptible (& lgr -> llc_waiter );
1518
+ wake_up (& lgr -> llc_msg_waiter );
1500
1519
} else if (smc_llc_flow_start (& lgr -> llc_flow_lcl ,
1501
1520
qentry )) {
1502
1521
schedule_work (& lgr -> llc_del_link_work );
@@ -1581,7 +1600,7 @@ static void smc_llc_rx_response(struct smc_link *link,
1581
1600
case SMC_LLC_DELETE_RKEY :
1582
1601
/* assign responses to the local flow, we requested them */
1583
1602
smc_llc_flow_qentry_set (& link -> lgr -> llc_flow_lcl , qentry );
1584
- wake_up_interruptible (& link -> lgr -> llc_waiter );
1603
+ wake_up (& link -> lgr -> llc_msg_waiter );
1585
1604
return ;
1586
1605
case SMC_LLC_CONFIRM_RKEY_CONT :
1587
1606
/* not used because max links is 3 */
@@ -1616,7 +1635,7 @@ static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc)
1616
1635
spin_lock_irqsave (& lgr -> llc_event_q_lock , flags );
1617
1636
list_add_tail (& qentry -> list , & lgr -> llc_event_q );
1618
1637
spin_unlock_irqrestore (& lgr -> llc_event_q_lock , flags );
1619
- schedule_work (& link -> lgr -> llc_event_work );
1638
+ schedule_work (& lgr -> llc_event_work );
1620
1639
}
1621
1640
1622
1641
/* copy received msg and add it to the event queue */
@@ -1677,7 +1696,8 @@ void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc)
1677
1696
INIT_LIST_HEAD (& lgr -> llc_event_q );
1678
1697
spin_lock_init (& lgr -> llc_event_q_lock );
1679
1698
spin_lock_init (& lgr -> llc_flow_lock );
1680
- init_waitqueue_head (& lgr -> llc_waiter );
1699
+ init_waitqueue_head (& lgr -> llc_flow_waiter );
1700
+ init_waitqueue_head (& lgr -> llc_msg_waiter );
1681
1701
mutex_init (& lgr -> llc_conf_mutex );
1682
1702
lgr -> llc_testlink_time = net -> ipv4 .sysctl_tcp_keepalive_time ;
1683
1703
}
@@ -1686,7 +1706,8 @@ void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc)
1686
1706
void smc_llc_lgr_clear (struct smc_link_group * lgr )
1687
1707
{
1688
1708
smc_llc_event_flush (lgr );
1689
- wake_up_interruptible_all (& lgr -> llc_waiter );
1709
+ wake_up_all (& lgr -> llc_flow_waiter );
1710
+ wake_up_all (& lgr -> llc_msg_waiter );
1690
1711
cancel_work_sync (& lgr -> llc_event_work );
1691
1712
cancel_work_sync (& lgr -> llc_add_link_work );
1692
1713
cancel_work_sync (& lgr -> llc_del_link_work );
0 commit comments