Commit 6d6c3097 authored by Sebastian Reichel's avatar Sebastian Reichel

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: default avatarSebastian Reichel <sre@kernel.org>
Tested-by: default avatarPavel Machek <pavel@ucw.cz>
parent b6616be3
...@@ -88,6 +88,8 @@ void ssi_waketest(struct hsi_client *cl, unsigned int enable); ...@@ -88,6 +88,8 @@ void ssi_waketest(struct hsi_client *cl, unsigned int enable);
#define SSIP_READY_CMD SSIP_CMD(SSIP_READY, 0) #define SSIP_READY_CMD SSIP_CMD(SSIP_READY, 0)
#define SSIP_SWBREAK_CMD SSIP_CMD(SSIP_SW_BREAK, 0) #define SSIP_SWBREAK_CMD SSIP_CMD(SSIP_SW_BREAK, 0)
#define SSIP_WAKETEST_FLAG 0
/* Main state machine states */ /* Main state machine states */
enum { enum {
INIT, INIT,
...@@ -116,7 +118,7 @@ enum { ...@@ -116,7 +118,7 @@ enum {
* @main_state: Main state machine * @main_state: Main state machine
* @send_state: TX state machine * @send_state: TX state machine
* @recv_state: RX state machine * @recv_state: RX state machine
* @waketest: Flag to follow wake line test * @flags: Flags, currently only used to follow wake line test
* @rxid: RX data id * @rxid: RX data id
* @txid: TX data id * @txid: TX data id
* @txqueue_len: TX queue length * @txqueue_len: TX queue length
...@@ -137,7 +139,7 @@ struct ssi_protocol { ...@@ -137,7 +139,7 @@ struct ssi_protocol {
unsigned int main_state; unsigned int main_state;
unsigned int send_state; unsigned int send_state;
unsigned int recv_state; unsigned int recv_state;
unsigned int waketest:1; unsigned long flags;
u8 rxid; u8 rxid;
u8 txid; u8 txid;
unsigned int txqueue_len; unsigned int txqueue_len;
...@@ -405,15 +407,17 @@ static void ssip_reset(struct hsi_client *cl) ...@@ -405,15 +407,17 @@ static void ssip_reset(struct hsi_client *cl)
spin_lock_bh(&ssi->lock); spin_lock_bh(&ssi->lock);
if (ssi->send_state != SEND_IDLE) if (ssi->send_state != SEND_IDLE)
hsi_stop_tx(cl); hsi_stop_tx(cl);
if (ssi->waketest) spin_unlock_bh(&ssi->lock);
ssi_waketest(cl, 0); if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 0); /* FIXME: To be removed */
spin_lock_bh(&ssi->lock);
del_timer(&ssi->rx_wd); del_timer(&ssi->rx_wd);
del_timer(&ssi->tx_wd); del_timer(&ssi->tx_wd);
del_timer(&ssi->keep_alive); del_timer(&ssi->keep_alive);
ssi->main_state = 0; ssi->main_state = 0;
ssi->send_state = 0; ssi->send_state = 0;
ssi->recv_state = 0; ssi->recv_state = 0;
ssi->waketest = 0; ssi->flags = 0;
ssi->rxid = 0; ssi->rxid = 0;
ssi->txid = 0; ssi->txid = 0;
list_for_each_safe(head, tmp, &ssi->txqueue) { list_for_each_safe(head, tmp, &ssi->txqueue) {
...@@ -437,7 +441,8 @@ static void ssip_dump_state(struct hsi_client *cl) ...@@ -437,7 +441,8 @@ static void ssip_dump_state(struct hsi_client *cl)
dev_err(&cl->device, "Send state: %d\n", ssi->send_state); dev_err(&cl->device, "Send state: %d\n", ssi->send_state);
dev_err(&cl->device, "CMT %s\n", (ssi->main_state == ACTIVE) ? dev_err(&cl->device, "CMT %s\n", (ssi->main_state == ACTIVE) ?
"Online" : "Offline"); "Online" : "Offline");
dev_err(&cl->device, "Wake test %d\n", ssi->waketest); dev_err(&cl->device, "Wake test %d\n",
test_bit(SSIP_WAKETEST_FLAG, &ssi->flags));
dev_err(&cl->device, "Data RX id: %d\n", ssi->rxid); dev_err(&cl->device, "Data RX id: %d\n", ssi->rxid);
dev_err(&cl->device, "Data TX id: %d\n", ssi->txid); dev_err(&cl->device, "Data TX id: %d\n", ssi->txid);
...@@ -668,10 +673,12 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd) ...@@ -668,10 +673,12 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd)
case HANDSHAKE: case HANDSHAKE:
spin_lock(&ssi->lock); spin_lock(&ssi->lock);
ssi->main_state = HANDSHAKE; ssi->main_state = HANDSHAKE;
if (!ssi->waketest) { spin_unlock(&ssi->lock);
ssi->waketest = 1;
if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 1); /* FIXME: To be removed */ ssi_waketest(cl, 1); /* FIXME: To be removed */
}
spin_lock(&ssi->lock);
/* Start boot handshake watchdog */ /* Start boot handshake watchdog */
mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT)); mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
spin_unlock(&ssi->lock); spin_unlock(&ssi->lock);
...@@ -718,10 +725,12 @@ static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd) ...@@ -718,10 +725,12 @@ static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd)
spin_unlock(&ssi->lock); spin_unlock(&ssi->lock);
return; return;
} }
if (ssi->waketest) { spin_unlock(&ssi->lock);
ssi->waketest = 0;
if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 0); /* FIXME: To be removed */ ssi_waketest(cl, 0); /* FIXME: To be removed */
}
spin_lock(&ssi->lock);
ssi->main_state = ACTIVE; ssi->main_state = ACTIVE;
del_timer(&ssi->tx_wd); /* Stop boot handshake timer */ del_timer(&ssi->tx_wd); /* Stop boot handshake timer */
spin_unlock(&ssi->lock); spin_unlock(&ssi->lock);
...@@ -926,11 +935,11 @@ static int ssip_pn_open(struct net_device *dev) ...@@ -926,11 +935,11 @@ static int ssip_pn_open(struct net_device *dev)
} }
dev_dbg(&cl->device, "Configuring SSI port\n"); dev_dbg(&cl->device, "Configuring SSI port\n");
hsi_setup(cl); hsi_setup(cl);
spin_lock_bh(&ssi->lock);
if (!ssi->waketest) { if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi->waketest = 1;
ssi_waketest(cl, 1); /* FIXME: To be removed */ ssi_waketest(cl, 1); /* FIXME: To be removed */
}
spin_lock_bh(&ssi->lock);
ssi->main_state = HANDSHAKE; ssi->main_state = HANDSHAKE;
spin_unlock_bh(&ssi->lock); spin_unlock_bh(&ssi->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment