From: Daniel Martensson Date: Thu, 13 Oct 2011 11:29:29 +0000 (+0000) Subject: caif-hsi: Added recovery check of CA wake status. X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=5ea2ef5f8b006ff9e970327e7fea78f1f5841c44;p=linux-beck.git caif-hsi: Added recovery check of CA wake status. Added recovery check of CA wake status in case of wake up timeout. Added check of CA wake status in case of wake down timeout. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index e9e7cbf01a5f..073352517adc 100644 --- a/drivers/net/caif/caif_hsi.c +++ b/drivers/net/caif/caif_hsi.c @@ -674,6 +674,7 @@ static void cfhsi_wake_up(struct work_struct *work) /* It happenes when wakeup is requested by * both ends at the same time. */ clear_bit(CFHSI_WAKE_UP, &cfhsi->bits); + clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits); return; } @@ -690,19 +691,47 @@ static void cfhsi_wake_up(struct work_struct *work) &cfhsi->bits), ret); if (unlikely(ret < 0)) { /* Interrupted by signal. */ - dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n", + dev_err(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n", __func__, ret); + clear_bit(CFHSI_WAKE_UP, &cfhsi->bits); cfhsi->dev->cfhsi_wake_down(cfhsi->dev); return; } else if (!ret) { + bool ca_wake = false; + size_t fifo_occupancy = 0; + /* Wakeup timeout */ dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n", __func__); + + /* Check FIFO to check if modem has sent something. */ + WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev, + &fifo_occupancy)); + + dev_err(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n", + __func__, (unsigned) fifo_occupancy); + + /* Check if we misssed the interrupt. */ + WARN_ON(cfhsi->dev->cfhsi_get_peer_wake(cfhsi->dev, + &ca_wake)); + + if (ca_wake) { + dev_err(&cfhsi->ndev->dev, "%s: CA Wake missed !.\n", + __func__); + + /* Clear the CFHSI_WAKE_UP_ACK bit to prevent race. */ + clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits); + + /* Continue execution. */ + goto wake_ack; + } + clear_bit(CFHSI_WAKE_UP, &cfhsi->bits); cfhsi->dev->cfhsi_wake_down(cfhsi->dev); return; } +wake_ack: dev_dbg(&cfhsi->ndev->dev, "%s: Woken.\n", __func__); @@ -779,12 +808,21 @@ static void cfhsi_wake_down(struct work_struct *work) &cfhsi->bits), ret); if (ret < 0) { /* Interrupted by signal. */ - dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n", + dev_err(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n", __func__, ret); return; } else if (!ret) { + bool ca_wake = true; + /* Timeout */ dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n", __func__); + + /* Check if we misssed the interrupt. */ + WARN_ON(cfhsi->dev->cfhsi_get_peer_wake(cfhsi->dev, + &ca_wake)); + if (!ca_wake) + dev_err(&cfhsi->ndev->dev, "%s: CA Wake missed !.\n", + __func__); } /* Check FIFO occupancy. */ diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h index 3356769afaee..8d552519ff67 100644 --- a/include/net/caif/caif_hsi.h +++ b/include/net/caif/caif_hsi.h @@ -108,6 +108,7 @@ struct cfhsi_dev { int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_dev *dev); int (*cfhsi_wake_up) (struct cfhsi_dev *dev); int (*cfhsi_wake_down) (struct cfhsi_dev *dev); + int (*cfhsi_get_peer_wake) (struct cfhsi_dev *dev, bool *status); int (*cfhsi_fifo_occupancy)(struct cfhsi_dev *dev, size_t *occupancy); int (*cfhsi_rx_cancel)(struct cfhsi_dev *dev); struct cfhsi_drv *drv;