X-Git-Url: http://rtime.felk.cvut.cz/gitweb/linux-lin.git/blobdiff_plain/258d510bf0d298d32de4565e223c58bdc3b1a5f5..45653655d66c6631a7993781ae87d521cbff9e56:/sllin/sllin.c diff --git a/sllin/sllin.c b/sllin/sllin.c index 61c8134..1febab2 100644 --- a/sllin/sllin.c +++ b/sllin/sllin.c @@ -41,7 +41,7 @@ * Funded by: Volkswagen Group Research */ -#define DEBUG 1 /* Enables pr_debug() printouts */ +//#define DEBUG 1 /* Enables pr_debug() printouts */ #include #include @@ -210,7 +210,11 @@ static int sltty_change_speed(struct tty_struct *tty, unsigned speed) struct ktermios old_termios, termios; int cflag; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) mutex_lock(&tty->termios_mutex); +#else + down_write(&tty->termios_rwsem); +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) old_termios = termios = *(tty->termios); @@ -238,7 +242,11 @@ static int sltty_change_speed(struct tty_struct *tty, unsigned speed) if (tty->ops->set_termios) tty->ops->set_termios(tty, &old_termios); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) mutex_unlock(&tty->termios_mutex); +#else + up_write(&tty->termios_rwsem); +#endif return 0; } @@ -311,7 +319,12 @@ static void sllin_write_wakeup(struct tty_struct *tty) return; /* ongoing concurrent processing */ clear_bit(SLF_TXBUFF_RQ, &sl->flags); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) smp_mb__after_clear_bit(); +#else + smp_mb__after_atomic(); +#endif if (sl->lin_state != SLSTATE_BREAK_SENT) remains = sl->tx_lim - sl->tx_cnt; @@ -325,7 +338,11 @@ static void sllin_write_wakeup(struct tty_struct *tty) remains -= actual; } clear_bit(SLF_TXBUFF_INPR, &sl->flags); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) smp_mb__after_clear_bit(); +#else + smp_mb__after_atomic(); +#endif } while (unlikely(test_bit(SLF_TXBUFF_RQ, &sl->flags))); @@ -716,10 +733,12 @@ static void sllin_slave_receive_buf(struct tty_struct *tty, 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 + * and received at least the LIN ID, we received here + * the break of the next message. + * Evaluate the previous one before continuing. */ - if (sl->rx_len_unknown == true) + if ((sl->rx_len_unknown == true) && + (sl->rx_cnt >= SLLIN_BUFF_ID)) { hrtimer_cancel(&sl->rx_timer); sllin_slave_finish_rx_msg(sl); @@ -836,7 +855,11 @@ static int sllin_send_tx_buff(struct sllin *sl) return 0; /* ongoing concurrent processing */ clear_bit(SLF_TXBUFF_RQ, &sl->flags); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) smp_mb__after_clear_bit(); +#else + smp_mb__after_atomic(); +#endif #ifdef BREAK_BY_BAUD if (sl->lin_state != SLSTATE_BREAK_SENT) @@ -870,7 +893,11 @@ static int sllin_send_tx_buff(struct sllin *sl) sl->tx_cnt, remains); clear_bit(SLF_TXBUFF_INPR, &sl->flags); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) smp_mb__after_clear_bit(); +#else + smp_mb__after_atomic(); +#endif } while (unlikely(test_bit(SLF_TXBUFF_RQ, &sl->flags))); @@ -986,6 +1013,7 @@ static int sllin_kwthread(void *ptr) struct sched_param schparam = { .sched_priority = 40 }; int tx_bytes = 0; /* Used for Network statistics */ unsigned long flags; + int mode; int lin_id; struct sllin_conf_entry *sce; @@ -1056,8 +1084,12 @@ static int sllin_kwthread(void *ptr) if (!test_bit(SLF_MSGEVENT, &sl->flags)) break; + mode = 0; cf = (struct can_frame *)sl->tx_req_skb->data; + if (cf->can_id & LIN_CHECKSUM_EXTENDED) + mode |= SLLIN_STPMSG_CHCKSUM_ENH; + /* SFF RTR CAN frame -> LIN header */ if (cf->can_id & CAN_RTR_FLAG) { struct sllin_conf_entry *sce; @@ -1067,11 +1099,16 @@ static int sllin_kwthread(void *ptr) sce = &sl->linfr_cache[cf->can_id & LIN_ID_MASK]; spin_lock_irqsave(&sl->linfr_lock, flags); + if (sce->frame_fl & LIN_CHECKSUM_EXTENDED) + mode |= SLLIN_STPMSG_CHCKSUM_ENH; /* Is there Slave response in linfr_cache to be sent? */ if ((sce->frame_fl & LIN_CACHE_RESPONSE) && (sce->dlc > 0)) { + if (sce->frame_fl & LIN_SINGLE_RESPONSE) + sce->frame_fl &= ~LIN_CACHE_RESPONSE; + netdev_dbg(sl->dev, "Sending LIN response from linfr_cache\n"); lin_data = sce->data; @@ -1087,9 +1124,15 @@ static int sllin_kwthread(void *ptr) spin_unlock_irqrestore(&sl->linfr_lock, flags); } else { /* SFF NON-RTR CAN frame -> LIN header + LIN response */ + struct sllin_conf_entry *sce; + netdev_dbg(sl->dev, "%s: NON-RTR SFF CAN frame, ID = %x\n", __func__, (int)cf->can_id & LIN_ID_MASK); + sce = &sl->linfr_cache[cf->can_id & LIN_ID_MASK]; + if (sce->frame_fl & LIN_CHECKSUM_EXTENDED) + mode |= SLLIN_STPMSG_CHCKSUM_ENH; + lin_data = cf->data; lin_dlc = cf->can_dlc; if (lin_dlc > SLLIN_DATA_MAX) @@ -1097,7 +1140,7 @@ static int sllin_kwthread(void *ptr) tx_bytes = lin_dlc; } - if (sllin_setup_msg(sl, 0, cf->can_id & LIN_ID_MASK, + if (sllin_setup_msg(sl, mode, cf->can_id & LIN_ID_MASK, lin_data, lin_dlc) != -1) { sl->id_to_send = true; @@ -1215,7 +1258,9 @@ slstate_response_wait: if ((sce->frame_fl & LIN_CACHE_RESPONSE) && (sce->dlc > 0)) { - int mode; + + if (sce->frame_fl & LIN_SINGLE_RESPONSE) + sce->frame_fl &= ~LIN_CACHE_RESPONSE; netdev_dbg(sl->dev, "Sending LIN response from linfr_cache\n"); @@ -1335,7 +1380,12 @@ static struct sllin *sll_alloc(dev_t line) char name[IFNAMSIZ]; sprintf(name, "sllin%d", i); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) dev = alloc_netdev(sizeof(*sl), name, sll_setup); +#else + dev = alloc_netdev(sizeof(*sl), name, NET_NAME_UNKNOWN, sll_setup); +#endif + if (!dev) return NULL; dev->base_addr = i;