@@ -73,11 +73,20 @@ struct mcast_device {
73
73
};
74
74
75
75
enum mcast_state {
76
- MCAST_IDLE ,
77
76
MCAST_JOINING ,
78
77
MCAST_MEMBER ,
78
+ MCAST_ERROR ,
79
+ };
80
+
81
+ enum mcast_group_state {
82
+ MCAST_IDLE ,
79
83
MCAST_BUSY ,
80
- MCAST_ERROR
84
+ MCAST_GROUP_ERROR ,
85
+ MCAST_PKEY_EVENT
86
+ };
87
+
88
+ enum {
89
+ MCAST_INVALID_PKEY_INDEX = 0xFFFF
81
90
};
82
91
83
92
struct mcast_member ;
@@ -93,9 +102,10 @@ struct mcast_group {
93
102
struct mcast_member * last_join ;
94
103
int members [3 ];
95
104
atomic_t refcount ;
96
- enum mcast_state state ;
105
+ enum mcast_group_state state ;
97
106
struct ib_sa_query * query ;
98
107
int query_id ;
108
+ u16 pkey_index ;
99
109
};
100
110
101
111
struct mcast_member {
@@ -378,9 +388,19 @@ static int fail_join(struct mcast_group *group, struct mcast_member *member,
378
388
static void process_group_error (struct mcast_group * group )
379
389
{
380
390
struct mcast_member * member ;
381
- int ret ;
391
+ int ret = 0 ;
392
+ u16 pkey_index ;
393
+
394
+ if (group -> state == MCAST_PKEY_EVENT )
395
+ ret = ib_find_pkey (group -> port -> dev -> device ,
396
+ group -> port -> port_num ,
397
+ be16_to_cpu (group -> rec .pkey ), & pkey_index );
382
398
383
399
spin_lock_irq (& group -> lock );
400
+ if (group -> state == MCAST_PKEY_EVENT && !ret &&
401
+ group -> pkey_index == pkey_index )
402
+ goto out ;
403
+
384
404
while (!list_empty (& group -> active_list )) {
385
405
member = list_entry (group -> active_list .next ,
386
406
struct mcast_member , list );
@@ -399,6 +419,7 @@ static void process_group_error(struct mcast_group *group)
399
419
}
400
420
401
421
group -> rec .join_state = 0 ;
422
+ out :
402
423
group -> state = MCAST_BUSY ;
403
424
spin_unlock_irq (& group -> lock );
404
425
}
@@ -415,9 +436,9 @@ static void mcast_work_handler(struct work_struct *work)
415
436
retest :
416
437
spin_lock_irq (& group -> lock );
417
438
while (!list_empty (& group -> pending_list ) ||
418
- (group -> state == MCAST_ERROR )) {
439
+ (group -> state != MCAST_BUSY )) {
419
440
420
- if (group -> state == MCAST_ERROR ) {
441
+ if (group -> state != MCAST_BUSY ) {
421
442
spin_unlock_irq (& group -> lock );
422
443
process_group_error (group );
423
444
goto retest ;
@@ -494,12 +515,19 @@ static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
494
515
void * context )
495
516
{
496
517
struct mcast_group * group = context ;
518
+ u16 pkey_index = MCAST_INVALID_PKEY_INDEX ;
497
519
498
520
if (status )
499
521
process_join_error (group , status );
500
522
else {
523
+ ib_find_pkey (group -> port -> dev -> device , group -> port -> port_num ,
524
+ be16_to_cpu (rec -> pkey ), & pkey_index );
525
+
501
526
spin_lock_irq (& group -> port -> lock );
502
527
group -> rec = * rec ;
528
+ if (group -> state == MCAST_BUSY &&
529
+ group -> pkey_index == MCAST_INVALID_PKEY_INDEX )
530
+ group -> pkey_index = pkey_index ;
503
531
if (!memcmp (& mgid0 , & group -> rec .mgid , sizeof mgid0 )) {
504
532
rb_erase (& group -> node , & group -> port -> table );
505
533
mcast_insert (group -> port , group , 1 );
@@ -539,6 +567,7 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
539
567
540
568
group -> port = port ;
541
569
group -> rec .mgid = * mgid ;
570
+ group -> pkey_index = MCAST_INVALID_PKEY_INDEX ;
542
571
INIT_LIST_HEAD (& group -> pending_list );
543
572
INIT_LIST_HEAD (& group -> active_list );
544
573
INIT_WORK (& group -> work , mcast_work_handler );
@@ -707,7 +736,8 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
707
736
}
708
737
EXPORT_SYMBOL (ib_init_ah_from_mcmember );
709
738
710
- static void mcast_groups_lost (struct mcast_port * port )
739
+ static void mcast_groups_event (struct mcast_port * port ,
740
+ enum mcast_group_state state )
711
741
{
712
742
struct mcast_group * group ;
713
743
struct rb_node * node ;
@@ -721,7 +751,8 @@ static void mcast_groups_lost(struct mcast_port *port)
721
751
atomic_inc (& group -> refcount );
722
752
queue_work (mcast_wq , & group -> work );
723
753
}
724
- group -> state = MCAST_ERROR ;
754
+ if (group -> state != MCAST_GROUP_ERROR )
755
+ group -> state = state ;
725
756
spin_unlock (& group -> lock );
726
757
}
727
758
spin_unlock_irqrestore (& port -> lock , flags );
@@ -731,16 +762,20 @@ static void mcast_event_handler(struct ib_event_handler *handler,
731
762
struct ib_event * event )
732
763
{
733
764
struct mcast_device * dev ;
765
+ int index ;
734
766
735
767
dev = container_of (handler , struct mcast_device , event_handler );
768
+ index = event -> element .port_num - dev -> start_port ;
736
769
737
770
switch (event -> event ) {
738
771
case IB_EVENT_PORT_ERR :
739
772
case IB_EVENT_LID_CHANGE :
740
773
case IB_EVENT_SM_CHANGE :
741
774
case IB_EVENT_CLIENT_REREGISTER :
742
- mcast_groups_lost (& dev -> port [event -> element .port_num -
743
- dev -> start_port ]);
775
+ mcast_groups_event (& dev -> port [index ], MCAST_GROUP_ERROR );
776
+ break ;
777
+ case IB_EVENT_PKEY_CHANGE :
778
+ mcast_groups_event (& dev -> port [index ], MCAST_PKEY_EVENT );
744
779
break ;
745
780
default :
746
781
break ;
0 commit comments