diff options
author | Sebastian Reichel <sre@kernel.org> | 2016-06-17 18:55:22 -0400 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2016-06-27 18:37:58 -0400 |
commit | 6d6c30973b62f1979e39f5e768b3b31c6dc81c4e (patch) | |
tree | 66af0939f8d48fdbdc0841af1fcc00b84a904014 /drivers/hsi | |
parent | b6616be32412a4c9a0f04aec247d2760fcad8cfd (diff) |
HSI: ssi_protocol: avoid ssi_waketest call with held spinlock
This avoids calling ssi_waketest(), while a spinlock is
being hold, since ssi_waketest may sleep once irq_safe
runtime pm is disabled.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Tested-by: Pavel Machek <pavel@ucw.cz>
Diffstat (limited to 'drivers/hsi')
-rw-r--r-- | drivers/hsi/clients/ssi_protocol.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 6595d2091268..8534efda8140 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c | |||
@@ -88,6 +88,8 @@ void ssi_waketest(struct hsi_client *cl, unsigned int enable); | |||
88 | #define SSIP_READY_CMD SSIP_CMD(SSIP_READY, 0) | 88 | #define SSIP_READY_CMD SSIP_CMD(SSIP_READY, 0) |
89 | #define SSIP_SWBREAK_CMD SSIP_CMD(SSIP_SW_BREAK, 0) | 89 | #define SSIP_SWBREAK_CMD SSIP_CMD(SSIP_SW_BREAK, 0) |
90 | 90 | ||
91 | #define SSIP_WAKETEST_FLAG 0 | ||
92 | |||
91 | /* Main state machine states */ | 93 | /* Main state machine states */ |
92 | enum { | 94 | enum { |
93 | INIT, | 95 | INIT, |
@@ -116,7 +118,7 @@ enum { | |||
116 | * @main_state: Main state machine | 118 | * @main_state: Main state machine |
117 | * @send_state: TX state machine | 119 | * @send_state: TX state machine |
118 | * @recv_state: RX state machine | 120 | * @recv_state: RX state machine |
119 | * @waketest: Flag to follow wake line test | 121 | * @flags: Flags, currently only used to follow wake line test |
120 | * @rxid: RX data id | 122 | * @rxid: RX data id |
121 | * @txid: TX data id | 123 | * @txid: TX data id |
122 | * @txqueue_len: TX queue length | 124 | * @txqueue_len: TX queue length |
@@ -137,7 +139,7 @@ struct ssi_protocol { | |||
137 | unsigned int main_state; | 139 | unsigned int main_state; |
138 | unsigned int send_state; | 140 | unsigned int send_state; |
139 | unsigned int recv_state; | 141 | unsigned int recv_state; |
140 | unsigned int waketest:1; | 142 | unsigned long flags; |
141 | u8 rxid; | 143 | u8 rxid; |
142 | u8 txid; | 144 | u8 txid; |
143 | unsigned int txqueue_len; | 145 | unsigned int txqueue_len; |
@@ -405,15 +407,17 @@ static void ssip_reset(struct hsi_client *cl) | |||
405 | spin_lock_bh(&ssi->lock); | 407 | spin_lock_bh(&ssi->lock); |
406 | if (ssi->send_state != SEND_IDLE) | 408 | if (ssi->send_state != SEND_IDLE) |
407 | hsi_stop_tx(cl); | 409 | hsi_stop_tx(cl); |
408 | if (ssi->waketest) | 410 | spin_unlock_bh(&ssi->lock); |
409 | ssi_waketest(cl, 0); | 411 | if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags)) |
412 | ssi_waketest(cl, 0); /* FIXME: To be removed */ | ||
413 | spin_lock_bh(&ssi->lock); | ||
410 | del_timer(&ssi->rx_wd); | 414 | del_timer(&ssi->rx_wd); |
411 | del_timer(&ssi->tx_wd); | 415 | del_timer(&ssi->tx_wd); |
412 | del_timer(&ssi->keep_alive); | 416 | del_timer(&ssi->keep_alive); |
413 | ssi->main_state = 0; | 417 | ssi->main_state = 0; |
414 | ssi->send_state = 0; | 418 | ssi->send_state = 0; |
415 | ssi->recv_state = 0; | 419 | ssi->recv_state = 0; |
416 | ssi->waketest = 0; | 420 | ssi->flags = 0; |
417 | ssi->rxid = 0; | 421 | ssi->rxid = 0; |
418 | ssi->txid = 0; | 422 | ssi->txid = 0; |
419 | list_for_each_safe(head, tmp, &ssi->txqueue) { | 423 | list_for_each_safe(head, tmp, &ssi->txqueue) { |
@@ -437,7 +441,8 @@ static void ssip_dump_state(struct hsi_client *cl) | |||
437 | dev_err(&cl->device, "Send state: %d\n", ssi->send_state); | 441 | dev_err(&cl->device, "Send state: %d\n", ssi->send_state); |
438 | dev_err(&cl->device, "CMT %s\n", (ssi->main_state == ACTIVE) ? | 442 | dev_err(&cl->device, "CMT %s\n", (ssi->main_state == ACTIVE) ? |
439 | "Online" : "Offline"); | 443 | "Online" : "Offline"); |
440 | dev_err(&cl->device, "Wake test %d\n", ssi->waketest); | 444 | dev_err(&cl->device, "Wake test %d\n", |
445 | test_bit(SSIP_WAKETEST_FLAG, &ssi->flags)); | ||
441 | dev_err(&cl->device, "Data RX id: %d\n", ssi->rxid); | 446 | dev_err(&cl->device, "Data RX id: %d\n", ssi->rxid); |
442 | dev_err(&cl->device, "Data TX id: %d\n", ssi->txid); | 447 | dev_err(&cl->device, "Data TX id: %d\n", ssi->txid); |
443 | 448 | ||
@@ -668,10 +673,12 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd) | |||
668 | case HANDSHAKE: | 673 | case HANDSHAKE: |
669 | spin_lock(&ssi->lock); | 674 | spin_lock(&ssi->lock); |
670 | ssi->main_state = HANDSHAKE; | 675 | ssi->main_state = HANDSHAKE; |
671 | if (!ssi->waketest) { | 676 | spin_unlock(&ssi->lock); |
672 | ssi->waketest = 1; | 677 | |
678 | if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags)) | ||
673 | ssi_waketest(cl, 1); /* FIXME: To be removed */ | 679 | ssi_waketest(cl, 1); /* FIXME: To be removed */ |
674 | } | 680 | |
681 | spin_lock(&ssi->lock); | ||
675 | /* Start boot handshake watchdog */ | 682 | /* Start boot handshake watchdog */ |
676 | mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT)); | 683 | mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT)); |
677 | spin_unlock(&ssi->lock); | 684 | spin_unlock(&ssi->lock); |
@@ -718,10 +725,12 @@ static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd) | |||
718 | spin_unlock(&ssi->lock); | 725 | spin_unlock(&ssi->lock); |
719 | return; | 726 | return; |
720 | } | 727 | } |
721 | if (ssi->waketest) { | 728 | spin_unlock(&ssi->lock); |
722 | ssi->waketest = 0; | 729 | |
730 | if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags)) | ||
723 | ssi_waketest(cl, 0); /* FIXME: To be removed */ | 731 | ssi_waketest(cl, 0); /* FIXME: To be removed */ |
724 | } | 732 | |
733 | spin_lock(&ssi->lock); | ||
725 | ssi->main_state = ACTIVE; | 734 | ssi->main_state = ACTIVE; |
726 | del_timer(&ssi->tx_wd); /* Stop boot handshake timer */ | 735 | del_timer(&ssi->tx_wd); /* Stop boot handshake timer */ |
727 | spin_unlock(&ssi->lock); | 736 | spin_unlock(&ssi->lock); |
@@ -926,11 +935,11 @@ static int ssip_pn_open(struct net_device *dev) | |||
926 | } | 935 | } |
927 | dev_dbg(&cl->device, "Configuring SSI port\n"); | 936 | dev_dbg(&cl->device, "Configuring SSI port\n"); |
928 | hsi_setup(cl); | 937 | hsi_setup(cl); |
929 | spin_lock_bh(&ssi->lock); | 938 | |
930 | if (!ssi->waketest) { | 939 | if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags)) |
931 | ssi->waketest = 1; | ||
932 | ssi_waketest(cl, 1); /* FIXME: To be removed */ | 940 | ssi_waketest(cl, 1); /* FIXME: To be removed */ |
933 | } | 941 | |
942 | spin_lock_bh(&ssi->lock); | ||
934 | ssi->main_state = HANDSHAKE; | 943 | ssi->main_state = HANDSHAKE; |
935 | spin_unlock_bh(&ssi->lock); | 944 | spin_unlock_bh(&ssi->lock); |
936 | 945 | ||