summaryrefslogtreecommitdiffstats
path: root/drivers/hsi
diff options
context:
space:
mode:
authorSebastian Reichel <sre@kernel.org>2016-06-18 00:58:39 +0200
committerSebastian Reichel <sre@kernel.org>2016-06-28 00:38:37 +0200
commitdf26d639e2f4628732a8da5a0f71e4e652ce809b (patch)
treeb53db2bdb9b8799b662b2b967d2bf22a74d61f59 /drivers/hsi
parentHSI: ssi_protocol: replace spin_lock with spin_lock_bh (diff)
downloadlinux-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/hsi')
-rw-r--r--drivers/hsi/clients/ssi_protocol.c13
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) {