caif-hsi: Added recovery check of CA wake status.
authorDaniel Martensson <daniel.martensson@stericsson.com>
Thu, 13 Oct 2011 11:29:29 +0000 (11:29 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 19 Oct 2011 07:25:43 +0000 (03:25 -0400)
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 <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/caif/caif_hsi.c
include/net/caif/caif_hsi.h

index e9e7cbf01a5f56207d38b40079d26f9f5545ccac..073352517adc20f043ac4024b791d2b45bce0766 100644 (file)
@@ -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. */
index 3356769afaee628a8885faaacc49734f9b6a816e..8d552519ff67949c2148e23a75138422b02d715f 100644 (file)
@@ -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;