@@ -5507,12 +5507,12 @@ static int qeth_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
55075507 return rc ;
55085508}
55095509
5510- static int qeth_set_online (struct qeth_card * card )
5510+ static int qeth_set_online (struct qeth_card * card ,
5511+ const struct qeth_discipline * disc )
55115512{
55125513 bool carrier_ok ;
55135514 int rc ;
55145515
5515- mutex_lock (& card -> discipline_mutex );
55165516 mutex_lock (& card -> conf_mutex );
55175517 QETH_CARD_TEXT (card , 2 , "setonlin" );
55185518
@@ -5529,15 +5529,14 @@ static int qeth_set_online(struct qeth_card *card)
55295529 /* no need for locking / error handling at this early stage: */
55305530 qeth_set_real_num_tx_queues (card , qeth_tx_actual_queues (card ));
55315531
5532- rc = card -> discipline -> set_online (card , carrier_ok );
5532+ rc = disc -> set_online (card , carrier_ok );
55335533 if (rc )
55345534 goto err_online ;
55355535
55365536 /* let user_space know that device is online */
55375537 kobject_uevent (& card -> gdev -> dev .kobj , KOBJ_CHANGE );
55385538
55395539 mutex_unlock (& card -> conf_mutex );
5540- mutex_unlock (& card -> discipline_mutex );
55415540 return 0 ;
55425541
55435542err_online :
@@ -5552,15 +5551,14 @@ static int qeth_set_online(struct qeth_card *card)
55525551 qdio_free (CARD_DDEV (card ));
55535552
55545553 mutex_unlock (& card -> conf_mutex );
5555- mutex_unlock (& card -> discipline_mutex );
55565554 return rc ;
55575555}
55585556
5559- int qeth_set_offline (struct qeth_card * card , bool resetting )
5557+ int qeth_set_offline (struct qeth_card * card , const struct qeth_discipline * disc ,
5558+ bool resetting )
55605559{
55615560 int rc , rc2 , rc3 ;
55625561
5563- mutex_lock (& card -> discipline_mutex );
55645562 mutex_lock (& card -> conf_mutex );
55655563 QETH_CARD_TEXT (card , 3 , "setoffl" );
55665564
@@ -5581,7 +5579,7 @@ int qeth_set_offline(struct qeth_card *card, bool resetting)
55815579
55825580 cancel_work_sync (& card -> rx_mode_work );
55835581
5584- card -> discipline -> set_offline (card );
5582+ disc -> set_offline (card );
55855583
55865584 qeth_qdio_clear_card (card , 0 );
55875585 qeth_drain_output_queues (card );
@@ -5602,25 +5600,28 @@ int qeth_set_offline(struct qeth_card *card, bool resetting)
56025600 kobject_uevent (& card -> gdev -> dev .kobj , KOBJ_CHANGE );
56035601
56045602 mutex_unlock (& card -> conf_mutex );
5605- mutex_unlock (& card -> discipline_mutex );
56065603 return 0 ;
56075604}
56085605EXPORT_SYMBOL_GPL (qeth_set_offline );
56095606
56105607static int qeth_do_reset (void * data )
56115608{
5609+ const struct qeth_discipline * disc ;
56125610 struct qeth_card * card = data ;
56135611 int rc ;
56145612
5613+ /* Lock-free, other users will block until we are done. */
5614+ disc = card -> discipline ;
5615+
56155616 QETH_CARD_TEXT (card , 2 , "recover1" );
56165617 if (!qeth_do_run_thread (card , QETH_RECOVER_THREAD ))
56175618 return 0 ;
56185619 QETH_CARD_TEXT (card , 2 , "recover2" );
56195620 dev_warn (& card -> gdev -> dev ,
56205621 "A recovery process has been started for the device\n" );
56215622
5622- qeth_set_offline (card , true);
5623- rc = qeth_set_online (card );
5623+ qeth_set_offline (card , disc , true);
5624+ rc = qeth_set_online (card , disc );
56245625 if (!rc ) {
56255626 dev_info (& card -> gdev -> dev ,
56265627 "Device successfully recovered!\n" );
@@ -6584,6 +6585,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
65846585 break ;
65856586 default :
65866587 card -> info .layer_enforced = true;
6588+ /* It's so early that we don't need the discipline_mutex yet. */
65876589 rc = qeth_core_load_discipline (card , enforced_disc );
65886590 if (rc )
65896591 goto err_load ;
@@ -6616,10 +6618,12 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
66166618
66176619 QETH_CARD_TEXT (card , 2 , "removedv" );
66186620
6621+ mutex_lock (& card -> discipline_mutex );
66196622 if (card -> discipline ) {
66206623 card -> discipline -> remove (gdev );
66216624 qeth_core_free_discipline (card );
66226625 }
6626+ mutex_unlock (& card -> discipline_mutex );
66236627
66246628 qeth_free_qdio_queues (card );
66256629
@@ -6634,6 +6638,7 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
66346638 int rc = 0 ;
66356639 enum qeth_discipline_id def_discipline ;
66366640
6641+ mutex_lock (& card -> discipline_mutex );
66376642 if (!card -> discipline ) {
66386643 def_discipline = IS_IQD (card ) ? QETH_DISCIPLINE_LAYER3 :
66396644 QETH_DISCIPLINE_LAYER2 ;
@@ -6647,16 +6652,23 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
66476652 }
66486653 }
66496654
6650- rc = qeth_set_online (card );
6655+ rc = qeth_set_online (card , card -> discipline );
6656+
66516657err :
6658+ mutex_unlock (& card -> discipline_mutex );
66526659 return rc ;
66536660}
66546661
66556662static int qeth_core_set_offline (struct ccwgroup_device * gdev )
66566663{
66576664 struct qeth_card * card = dev_get_drvdata (& gdev -> dev );
6665+ int rc ;
66586666
6659- return qeth_set_offline (card , false);
6667+ mutex_lock (& card -> discipline_mutex );
6668+ rc = qeth_set_offline (card , card -> discipline , false);
6669+ mutex_unlock (& card -> discipline_mutex );
6670+
6671+ return rc ;
66606672}
66616673
66626674static void qeth_core_shutdown (struct ccwgroup_device * gdev )
0 commit comments