X-Git-Url: https://rtime.felk.cvut.cz/gitweb/linux-lin.git/blobdiff_plain/f3a1f9389debdca4544367e83883468d42a483d2..4d395daeab8a91e2eb519fba8b213a84f33d1ea0:/sllin/sllin.c diff --git a/sllin/sllin.c b/sllin/sllin.c index e8aca08..36f23a5 100644 --- a/sllin/sllin.c +++ b/sllin/sllin.c @@ -670,6 +670,23 @@ static int sllin_rx_validate(struct sllin *sl) return 0; } +static void sllin_slave_finish_rx_msg(struct sllin *sl) +{ + if (sllin_rx_validate(sl) == -1) { + netdev_dbg(sl->dev, "sllin: RX validation failed.\n"); + sllin_report_error(sl, LIN_ERR_CHECKSUM); + } else { + /* Send CAN non-RTR frame with data */ + netdev_dbg(sl->dev, "sllin: sending NON-RTR CAN frame with LIN payload."); + sll_bump(sl); /* send packet to the network layer */ + } + /* Prepare for reception of new header */ + sl->rx_cnt = 0; + sl->rx_expect = SLLIN_BUFF_ID + 1; + sl->rx_len_unknown = false; /* We do know exact length of the header */ + sl->header_received = false; +} + static void sllin_slave_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { @@ -681,6 +698,20 @@ static void sllin_slave_receive_buf(struct tty_struct *tty, /* Read the characters out of the buffer */ while (count--) { if (fp && *fp++) { + /* + * If we don't know the length of the current message + * we received the break of the next message. + * Evaluate the previous one before continuing + */ + if (sl->rx_len_unknown == true) + { + hrtimer_cancel(&sl->rx_timer); + sllin_slave_finish_rx_msg(sl); + + set_bit(SLF_RXEVENT, &sl->flags); + wake_up(&sl->kwt_wq); + } + netdev_dbg(sl->dev, "sllin_slave_receive_buf char 0x%02x ignored " "due marker 0x%02x, flags 0x%lx\n", *cp, *(fp-1), sl->flags); @@ -736,25 +767,23 @@ static void sllin_slave_receive_buf(struct tty_struct *tty, sl->header_received = true; + hrtimer_start(&sl->rx_timer, + ktime_add(ktime_get(), sl->rx_timer_timeout), + HRTIMER_MODE_ABS); sll_send_rtr(sl); continue; } /* Response received */ if ((sl->header_received == true) && - ((sl->rx_cnt >= sl->rx_expect) || - ((sl->rx_len_unknown == true) && (count == 0)))) { + ((sl->rx_cnt >= sl->rx_expect))) { - sll_bump(sl); + hrtimer_cancel(&sl->rx_timer); netdev_dbg(sl->dev, "Received LIN header & LIN response. " "rx_cnt = %u, rx_expect = %u\n", sl->rx_cnt, sl->rx_expect); + sllin_slave_finish_rx_msg(sl); - /* Prepare for reception of new header */ - sl->rx_cnt = 0; - sl->rx_expect = SLLIN_BUFF_ID + 1; - sl->rx_len_unknown = false; /* We do know exact length of the header */ - sl->header_received = false; } } } @@ -905,8 +934,13 @@ static enum hrtimer_restart sllin_rx_timeout_handler(struct hrtimer *hrtimer) { struct sllin *sl = container_of(hrtimer, struct sllin, rx_timer); - sllin_report_error(sl, LIN_ERR_RX_TIMEOUT); - set_bit(SLF_TMOUTEVENT, &sl->flags); + if (sl->lin_master) { + sllin_report_error(sl, LIN_ERR_RX_TIMEOUT); + set_bit(SLF_TMOUTEVENT, &sl->flags); + } else { + sllin_slave_finish_rx_msg(sl); + set_bit(SLF_RXEVENT, &sl->flags); + } wake_up(&sl->kwt_wq); return HRTIMER_NORESTART;