]> rtime.felk.cvut.cz Git - linux-lin.git/blobdiff - sllin/sllin.c
sllin: Add LIN ID to timeout frame
[linux-lin.git] / sllin / sllin.c
index c5e174949d831c7ed125c501ca50311c91257cea..61c81348faa9a8e95a18db04b8c3f82c4e879815 100644 (file)
@@ -517,6 +517,9 @@ static void sllin_master_receive_buf(struct tty_struct *tty,
  */
 static void sllin_report_error(struct sllin *sl, int err)
 {
+       unsigned char *lin_buff;
+       int lin_id;
+
        switch (err) {
        case LIN_ERR_CHECKSUM:
                sl->dev->stats.rx_crc_errors++;
@@ -531,7 +534,9 @@ static void sllin_report_error(struct sllin *sl, int err)
                break;
        }
 
-       sllin_send_canfr(sl, 0 | CAN_EFF_FLAG |
+       lin_buff = (sl->lin_master) ? sl->tx_buff : sl->rx_buff;
+       lin_id = lin_buff[SLLIN_BUFF_ID] & LIN_ID_MASK;
+       sllin_send_canfr(sl, lin_id | CAN_EFF_FLAG |
                (err & ~LIN_ID_MASK), NULL, 0);
 }
 
@@ -771,7 +776,6 @@ static void sllin_slave_receive_buf(struct tty_struct *tty,
                        if (sce->dlc > 0) {
                                sl->rx_expect += sce->dlc + 1; /* + checksum */
                                sl->rx_len_unknown = false;
-                               set_bit(SLF_MSGEVENT, &sl->flags);
                                wake_up(&sl->kwt_wq);
                        } else {
                                sl->rx_expect += SLLIN_DATA_MAX + 1; /* + checksum */
@@ -950,7 +954,16 @@ static enum hrtimer_restart sllin_rx_timeout_handler(struct hrtimer *hrtimer)
 {
        struct sllin *sl = container_of(hrtimer, struct sllin, rx_timer);
 
-       if (sl->lin_master) {
+       /*
+        * Signal timeout when:
+        * master: We did not receive as much characters as expected
+        * slave: * we did not receive any data bytes at all
+        *        * we know the length and didn't receive enough
+        */
+       if ((sl->lin_master) ||
+                       (sl->rx_cnt <= SLLIN_BUFF_DATA) ||
+                       ((!sl->rx_len_unknown) &&
+                       (sl->rx_cnt < sl->rx_expect))) {
                sllin_report_error(sl, LIN_ERR_RX_TIMEOUT);
                set_bit(SLF_TMOUTEVENT, &sl->flags);
        } else {
@@ -1001,9 +1014,9 @@ static int sllin_kwthread(void *ptr)
                        test_bit(SLF_TXEVENT, &sl->flags) ||
                        test_bit(SLF_TMOUTEVENT, &sl->flags) ||
                        test_bit(SLF_ERROR, &sl->flags) ||
+                       (sl->lin_state == SLSTATE_ID_RECEIVED) ||
                        (((sl->lin_state == SLSTATE_IDLE) ||
-                               (sl->lin_state == SLSTATE_RESPONSE_WAIT) ||
-                               (sl->lin_state == SLSTATE_ID_RECEIVED))
+                               (sl->lin_state == SLSTATE_RESPONSE_WAIT))
                                && test_bit(SLF_MSGEVENT, &sl->flags)));
 
                if (test_and_clear_bit(SLF_RXEVENT, &sl->flags)) {
@@ -1201,8 +1214,7 @@ slstate_response_wait:
                        spin_lock_irqsave(&sl->linfr_lock, flags);
 
                        if ((sce->frame_fl & LIN_CACHE_RESPONSE)
-                                       && (sce->dlc > 0)
-                                       && (test_bit(SLF_MSGEVENT, &sl->flags))) {
+                                       && (sce->dlc > 0)) {
                                int mode;
 
                                netdev_dbg(sl->dev, "Sending LIN response from linfr_cache\n");
@@ -1234,9 +1246,6 @@ slstate_response_wait:
                                        sllin_send_tx_buff(sl);
                                }
 
-                               clear_bit(SLF_MSGEVENT, &sl->flags);
-                               kfree_skb(sl->tx_req_skb);
-                               netif_wake_queue(sl->dev);
                                hrtimer_start(&sl->rx_timer,
                                        ktime_add(ktime_get(), sl->rx_timer_timeout),
                                        HRTIMER_MODE_ABS);