diff options
author | Sebastian Reichel <sre@kernel.org> | 2016-06-18 00:58:39 +0200 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2016-06-28 00:38:37 +0200 |
commit | df26d639e2f4628732a8da5a0f71e4e652ce809b (patch) | |
tree | b53db2bdb9b8799b662b2b967d2bf22a74d61f59 /drivers | |
parent | HSI: ssi_protocol: replace spin_lock with spin_lock_bh (diff) | |
download | linux-df26d639e2f4628732a8da5a0f71e4e652ce809b.tar.xz linux-df26d639e2f4628732a8da5a0f71e4e652ce809b.zip |
HSI: ssi_protocol: fix ssip_xmit invocation
ssip_xmit should be called from process context,
since it calls hsi_async_write.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Tested-by: Pavel Machek <pavel@ucw.cz>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hsi/clients/ssi_protocol.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 2388857db14b..6031cd146556 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -150,6 +150,7 @@ struct ssi_protocol { struct net_device *netdev; struct list_head txqueue; struct list_head cmdqueue; + struct work_struct work; struct hsi_client *cl; struct list_head link; atomic_t tx_usecnt; @@ -968,6 +969,15 @@ static int ssip_pn_set_mtu(struct net_device *dev, int new_mtu) return 0; } +static void ssip_xmit_work(struct work_struct *work) +{ + struct ssi_protocol *ssi = + container_of(work, struct ssi_protocol, work); + struct hsi_client *cl = ssi->cl; + + ssip_xmit(cl); +} + static int ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev) { struct hsi_client *cl = to_hsi_client(dev->dev.parent); @@ -1020,7 +1030,7 @@ static int ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev) dev_dbg(&cl->device, "Start TX on SEND READY qlen %d\n", ssi->txqueue_len); spin_unlock_bh(&ssi->lock); - ssip_xmit(cl); + schedule_work(&ssi->work); } else { spin_unlock_bh(&ssi->lock); } @@ -1097,6 +1107,7 @@ static int ssi_protocol_probe(struct device *dev) atomic_set(&ssi->tx_usecnt, 0); hsi_client_set_drvdata(cl, ssi); ssi->cl = cl; + INIT_WORK(&ssi->work, ssip_xmit_work); ssi->channel_id_cmd = hsi_get_channel_id_by_name(cl, "mcsaab-control"); if (ssi->channel_id_cmd < 0) { |