Skip to content

Commit

Permalink
Merge tag 'hsi-for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/sre/linux-hsi

Pull HSI updates from Sebastian Reichel:

 - proper runtime pm support for omap-ssi and ssi-protocol

 - misc fixes

* tag 'hsi-for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi: (24 commits)
  HSI: omap_ssi: drop pm_runtime_irq_safe
  HSI: omap_ssi_port: use rpm autosuspend API
  HSI: omap_ssi: call msg->complete() from process context
  HSI: omap_ssi_port: ensure clocks are kept enabled during transfer
  HSI: omap_ssi_port: replace pm_runtime_put_sync with non-sync variant
  HSI: omap_ssi_port: avoid calling runtime_pm_*_sync inside spinlock
  HSI: omap_ssi_port: avoid pm_runtime_get_sync in ssi_start_dma and ssi_start_pio
  HSI: omap_ssi_port: switch to threaded pio irq
  HSI: omap_ssi_core: remove pm_runtime_get_sync call from tasklet
  HSI: omap_ssi_core: use pm_runtime_put instead of pm_runtime_put_sync
  HSI: omap_ssi_port: prepare start_tx/stop_tx for blocking pm_runtime calls
  HSI: core: switch port event notifier from atomic to blocking
  HSI: omap_ssi_port: replace wkin_cken with atomic bitmap operations
  HSI: omap_ssi: convert cawake irq handler to thread
  HSI: ssi_protocol: fix ssip_xmit invocation
  HSI: ssi_protocol: replace spin_lock with spin_lock_bh
  HSI: ssi_protocol: avoid ssi_waketest call with held spinlock
  HSI: omap_ssi: do not reset module
  HSI: omap_ssi_port: remove useless newline
  hsi: Only descend into hsi directory when CONFIG_HSI is set
  ...
  • Loading branch information
torvalds committed Jul 27, 2016
2 parents 818e607 + 9c99e5e commit 8448cef
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 190 deletions.
2 changes: 1 addition & 1 deletion Documentation/DocBook/device-drivers.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ X!Ilib/fonts/fonts.c
</para>

!Iinclude/linux/hsi/hsi.h
!Edrivers/hsi/hsi.c
!Edrivers/hsi/hsi_core.c
</chapter>

<chapter id="pwm">
Expand Down
2 changes: 1 addition & 1 deletion drivers/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
obj-$(CONFIG_SPMI) += spmi/
obj-y += hsi/
obj-$(CONFIG_HSI) += hsi/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
Expand Down
3 changes: 2 additions & 1 deletion drivers/hsi/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#
# Makefile for HSI
#
obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o
obj-$(CONFIG_HSI) += hsi.o
hsi-objs := hsi_core.o
hsi-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o
obj-y += controllers/
obj-y += clients/
4 changes: 2 additions & 2 deletions drivers/hsi/clients/cmt_speech.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,8 @@ static void cs_hsi_read_on_control_complete(struct hsi_msg *msg)
hi->control_state &= ~SSI_CHANNEL_STATE_READING;
if (msg->status == HSI_STATUS_ERROR) {
dev_err(&hi->cl->device, "Control RX error detected\n");
cs_hsi_control_read_error(hi, msg);
spin_unlock(&hi->lock);
cs_hsi_control_read_error(hi, msg);
goto out;
}
dev_dbg(&hi->cl->device, "Read on control: %08X\n", cmd);
Expand Down Expand Up @@ -1275,7 +1275,7 @@ static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
if (vma->vm_end < vma->vm_start)
return -EINVAL;

if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) != 1)
if (vma_pages(vma) != 1)
return -EINVAL;

vma->vm_flags |= VM_IO | VM_DONTDUMP | VM_DONTEXPAND;
Expand Down
110 changes: 65 additions & 45 deletions drivers/hsi/clients/ssi_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_SWBREAK_CMD SSIP_CMD(SSIP_SW_BREAK, 0)

#define SSIP_WAKETEST_FLAG 0

/* Main state machine states */
enum {
INIT,
Expand Down Expand Up @@ -116,7 +118,7 @@ enum {
* @main_state: Main state machine
* @send_state: TX 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
* @txid: TX data id
* @txqueue_len: TX queue length
Expand All @@ -137,7 +139,7 @@ struct ssi_protocol {
unsigned int main_state;
unsigned int send_state;
unsigned int recv_state;
unsigned int waketest:1;
unsigned long flags;
u8 rxid;
u8 txid;
unsigned int txqueue_len;
Expand All @@ -148,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;
Expand Down Expand Up @@ -405,15 +408,17 @@ static void ssip_reset(struct hsi_client *cl)
spin_lock_bh(&ssi->lock);
if (ssi->send_state != SEND_IDLE)
hsi_stop_tx(cl);
if (ssi->waketest)
ssi_waketest(cl, 0);
spin_unlock_bh(&ssi->lock);
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->tx_wd);
del_timer(&ssi->keep_alive);
ssi->main_state = 0;
ssi->send_state = 0;
ssi->recv_state = 0;
ssi->waketest = 0;
ssi->flags = 0;
ssi->rxid = 0;
ssi->txid = 0;
list_for_each_safe(head, tmp, &ssi->txqueue) {
Expand All @@ -437,7 +442,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, "CMT %s\n", (ssi->main_state == ACTIVE) ?
"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 TX id: %d\n", ssi->txid);

Expand Down Expand Up @@ -515,17 +521,17 @@ static void ssip_start_rx(struct hsi_client *cl)

dev_dbg(&cl->device, "RX start M(%d) R(%d)\n", ssi->main_state,
ssi->recv_state);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
/*
* We can have two UP events in a row due to a short low
* high transition. Therefore we need to ignore the sencond UP event.
*/
if ((ssi->main_state != ACTIVE) || (ssi->recv_state == RECV_READY)) {
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
ssip_set_rxstate(ssi, RECV_READY);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);

msg = ssip_claim_cmd(ssi);
ssip_set_cmd(msg, SSIP_READY_CMD);
Expand All @@ -539,10 +545,10 @@ static void ssip_stop_rx(struct hsi_client *cl)
struct ssi_protocol *ssi = hsi_client_drvdata(cl);

dev_dbg(&cl->device, "RX stop M(%d)\n", ssi->main_state);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (likely(ssi->main_state == ACTIVE))
ssip_set_rxstate(ssi, RECV_IDLE);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
}

static void ssip_free_strans(struct hsi_msg *msg)
Expand All @@ -559,9 +565,9 @@ static void ssip_strans_complete(struct hsi_msg *msg)

data = msg->context;
ssip_release_cmd(msg);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
ssip_set_txstate(ssi, SENDING);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
hsi_async_write(cl, data);
}

Expand Down Expand Up @@ -666,15 +672,17 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd)
/* Fall through */
case INIT:
case HANDSHAKE:
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
ssi->main_state = HANDSHAKE;
if (!ssi->waketest) {
ssi->waketest = 1;
spin_unlock_bh(&ssi->lock);

if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 1); /* FIXME: To be removed */
}

spin_lock_bh(&ssi->lock);
/* Start boot handshake watchdog */
mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
dev_dbg(&cl->device, "Send BOOTINFO_RESP\n");
if (SSIP_DATA_VERSION(cmd) != SSIP_LOCAL_VERID)
dev_warn(&cl->device, "boot info req verid mismatch\n");
Expand All @@ -696,35 +704,37 @@ static void ssip_rx_bootinforesp(struct hsi_client *cl, u32 cmd)
if (SSIP_DATA_VERSION(cmd) != SSIP_LOCAL_VERID)
dev_warn(&cl->device, "boot info resp verid mismatch\n");

spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (ssi->main_state != ACTIVE)
/* Use tx_wd as a boot watchdog in non ACTIVE state */
mod_timer(&ssi->tx_wd, jiffies + msecs_to_jiffies(SSIP_WDTOUT));
else
dev_dbg(&cl->device, "boot info resp ignored M(%d)\n",
ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
}

static void ssip_rx_waketest(struct hsi_client *cl, u32 cmd)
{
struct ssi_protocol *ssi = hsi_client_drvdata(cl);
unsigned int wkres = SSIP_PAYLOAD(cmd);

spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (ssi->main_state != HANDSHAKE) {
dev_dbg(&cl->device, "wake lines test ignored M(%d)\n",
ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
if (ssi->waketest) {
ssi->waketest = 0;
spin_unlock_bh(&ssi->lock);

if (test_and_clear_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 0); /* FIXME: To be removed */
}

spin_lock_bh(&ssi->lock);
ssi->main_state = ACTIVE;
del_timer(&ssi->tx_wd); /* Stop boot handshake timer */
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);

dev_notice(&cl->device, "WAKELINES TEST %s\n",
wkres & SSIP_WAKETEST_FAILED ? "FAILED" : "OK");
Expand All @@ -741,20 +751,20 @@ static void ssip_rx_ready(struct hsi_client *cl)
{
struct ssi_protocol *ssi = hsi_client_drvdata(cl);

spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (unlikely(ssi->main_state != ACTIVE)) {
dev_dbg(&cl->device, "READY on wrong state: S(%d) M(%d)\n",
ssi->send_state, ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
if (ssi->send_state != WAIT4READY) {
dev_dbg(&cl->device, "Ignore spurious READY command\n");
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
ssip_set_txstate(ssi, SEND_READY);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
ssip_xmit(cl);
}

Expand All @@ -766,22 +776,22 @@ static void ssip_rx_strans(struct hsi_client *cl, u32 cmd)
int len = SSIP_PDU_LENGTH(cmd);

dev_dbg(&cl->device, "RX strans: %d frames\n", len);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (unlikely(ssi->main_state != ACTIVE)) {
dev_err(&cl->device, "START TRANS wrong state: S(%d) M(%d)\n",
ssi->send_state, ssi->main_state);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
return;
}
ssip_set_rxstate(ssi, RECEIVING);
if (unlikely(SSIP_MSG_ID(cmd) != ssi->rxid)) {
dev_err(&cl->device, "START TRANS id %d expected %d\n",
SSIP_MSG_ID(cmd), ssi->rxid);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
goto out1;
}
ssi->rxid++;
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
skb = netdev_alloc_skb(ssi->netdev, len * 4);
if (unlikely(!skb)) {
dev_err(&cl->device, "No memory for rx skb\n");
Expand Down Expand Up @@ -849,17 +859,17 @@ static void ssip_swbreak_complete(struct hsi_msg *msg)
struct ssi_protocol *ssi = hsi_client_drvdata(cl);

ssip_release_cmd(msg);
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (list_empty(&ssi->txqueue)) {
if (atomic_read(&ssi->tx_usecnt)) {
ssip_set_txstate(ssi, SEND_READY);
} else {
ssip_set_txstate(ssi, SEND_IDLE);
hsi_stop_tx(cl);
}
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
} else {
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
ssip_xmit(cl);
}
netif_wake_queue(ssi->netdev);
Expand All @@ -876,17 +886,17 @@ static void ssip_tx_data_complete(struct hsi_msg *msg)
ssip_error(cl);
goto out;
}
spin_lock(&ssi->lock);
spin_lock_bh(&ssi->lock);
if (list_empty(&ssi->txqueue)) {
ssip_set_txstate(ssi, SENDING_SWBREAK);
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
cmsg = ssip_claim_cmd(ssi);
ssip_set_cmd(cmsg, SSIP_SWBREAK_CMD);
cmsg->complete = ssip_swbreak_complete;
dev_dbg(&cl->device, "Send SWBREAK\n");
hsi_async_write(cl, cmsg);
} else {
spin_unlock(&ssi->lock);
spin_unlock_bh(&ssi->lock);
ssip_xmit(cl);
}
out:
Expand Down Expand Up @@ -926,11 +936,11 @@ static int ssip_pn_open(struct net_device *dev)
}
dev_dbg(&cl->device, "Configuring SSI port\n");
hsi_setup(cl);
spin_lock_bh(&ssi->lock);
if (!ssi->waketest) {
ssi->waketest = 1;

if (!test_and_set_bit(SSIP_WAKETEST_FLAG, &ssi->flags))
ssi_waketest(cl, 1); /* FIXME: To be removed */
}

spin_lock_bh(&ssi->lock);
ssi->main_state = HANDSHAKE;
spin_unlock_bh(&ssi->lock);

Expand Down Expand Up @@ -959,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);
Expand Down Expand Up @@ -1011,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);
}
Expand Down Expand Up @@ -1088,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) {
Expand Down
Loading

0 comments on commit 8448cef

Please sign in to comment.