diff options
-rw-r--r-- | drivers/net/caif/caif_hsi.c | 42 | ||||
-rw-r--r-- | include/net/caif/caif_hsi.h | 1 |
2 files changed, 41 insertions, 2 deletions
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; |