From a6e556d31ce3932fb24ab7eab0ab1cebdd3ff7b4 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 16 May 2017 10:56:49 -0600 Subject: [PATCH 01/14] I had to make following change to fix interrupt context syslog (INTBUFFER untested) --- drivers/syslog/syslog_write.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/syslog/syslog_write.c b/drivers/syslog/syslog_write.c index a3100702ca4..390f594237d 100644 --- a/drivers/syslog/syslog_write.c +++ b/drivers/syslog/syslog_write.c @@ -40,6 +40,7 @@ #include #include +#include #include #include "syslog.h" @@ -100,8 +101,21 @@ ssize_t syslog_default_write(FAR const char *buffer, size_t buflen) ssize_t syslog_write(FAR const char *buffer, size_t buflen) { #ifdef CONFIG_SYSLOG_WRITE - return g_syslog_channel->sc_write(buffer, buflen); -#else - return syslog_default_write(buffer, buflen); + if (!up_interrupt_context() && !sched_idletask()) + { +#ifdef CONFIG_SYSLOG_INTBUFFER + /* Flush any characters that may have been added to the interrupt + * buffer. + */ + + (void)syslog_flush_intbuffer(g_syslog_channel, false); #endif + + return g_syslog_channel->sc_write(buffer, buflen); + } + else +#endif + { + return syslog_default_write(buffer, buflen); + } } From 6a3800f611854e61f3183c89c706c24841cc8eea Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 16 May 2017 11:03:35 -0600 Subject: [PATCH 02/14] There can be a failure in IOB allocation to some asynchronous behavior caused by the use of sem_post(). Consider this scenario: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task A holds an IOB.  There are no further IOBs.  The value of semcount is zero. Task B calls iob_alloc().  Since there are not IOBs, it calls sem_wait().  The v alue of semcount is now -1. Task A frees the IOB.  iob_free() adds the IOB to the free list and calls sem_post() this makes Task B ready to run and sets semcount to zero NOT 1.  There is one IOB in the free list and semcount is zero.  When Task B wakes up it would increment the sem_count back to the correct value. But an interrupt or another task runs occurs before Task B executes.  The interrupt or other tak takes the IOB off of the free list and decrements the semcount.  But since semcount is then < 0, this causes the assertion because that is an invalid state in the interrupt handler. So I think that the root cause is that there the asynchrony between incrementing the semcount. This change separates the list of IOBs: Currently there is only a free list of IOBs. The problem, I believe, is because of asynchronies due sem_post() post cause the semcount and the list content to become out of sync. This change adds a new 'committed' list: When there is a task waiting for an IOB, it will go into the committed list rather than the free list before the semaphore is posted. On the waiting side, when awakened from the semaphore wait, it will expect to find its IOB in the committed list, rather than free list. In this way, the content of the free list and the value of the semaphore count always remain in sync. --- mm/iob/Kconfig | 5 +- mm/iob/iob.h | 10 ++- mm/iob/iob_alloc.c | 138 +++++++++++++++++++++++++------------- mm/iob/iob_alloc_qentry.c | 137 ++++++++++++++++++++++++------------- mm/iob/iob_free.c | 34 ++++++++-- mm/iob/iob_free_qentry.c | 35 ++++++++-- mm/iob/iob_initialize.c | 25 ++++++- 7 files changed, 271 insertions(+), 113 deletions(-) diff --git a/mm/iob/Kconfig b/mm/iob/Kconfig index 3d603fde380..0790961a794 100644 --- a/mm/iob/Kconfig +++ b/mm/iob/Kconfig @@ -63,12 +63,15 @@ config IOB_THROTTLE config IOB_DEBUG bool "Force I/O buffer debug" default n - depends on DEBUG_FEATURES + depends on DEBUG_FEATURES && !SYSLOG_BUFFER ---help--- This option will force debug output from I/O buffer logic. This is not normally something that would want to do but is convenient if you are debugging the I/O buffer logic and do not want to get overloaded with other un-related debug output. + NOTE that this selection is not avaiable with IOBs are being used + to syslog buffering logic (CONFIG_SYSLOG_BUFFER=y)! + endif # MM_IOB endmenu # Common I/O buffer support diff --git a/mm/iob/iob.h b/mm/iob/iob.h index 5f4436980c1..9f43612d710 100644 --- a/mm/iob/iob.h +++ b/mm/iob/iob.h @@ -91,10 +91,18 @@ extern FAR struct iob_s *g_iob_freelist; -/* A list of all free, unallocated I/O buffer queue containers */ +/* A list of I/O buffers that are committed for allocation */ + +extern FAR struct iob_s *g_iob_committed; #if CONFIG_IOB_NCHAINS > 0 +/* A list of all free, unallocated I/O buffer queue containers */ + extern FAR struct iob_qentry_s *g_iob_freeqlist; + +/* A list of I/O buffer queue containers that are committed for allocation */ + +extern FAR struct iob_s *g_iob_qcommitted; #endif /* Counting semaphores that tracks the number of free IOBs/qentries */ diff --git a/mm/iob/iob_alloc.c b/mm/iob/iob_alloc.c index 27de2946706..9aee7ab8d43 100644 --- a/mm/iob/iob_alloc.c +++ b/mm/iob/iob_alloc.c @@ -1,7 +1,7 @@ /**************************************************************************** * mm/iob/iob_alloc.c * - * Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -54,6 +54,47 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: iob_alloc_committed + * + * Description: + * Allocate an I/O buffer by taking the buffer at the head of the committed + * list. + * + ****************************************************************************/ + +static FAR struct iob_s *iob_alloc_committed(void) +{ + FAR struct iob_s *iob = NULL; + irqstate_t flags; + + /* We don't know what context we are called from so we use extreme measures + * to protect the committed list: We disable interrupts very briefly. + */ + + flags = enter_critical_section(); + + /* Take the I/O buffer from the head of the committed list */ + + iob = g_iob_committed; + if (iob != NULL) + { + /* Remove the I/O buffer from the committed list */ + + g_iob_committed = iob->io_flink; + + /* Put the I/O buffer in a known state */ + + iob->io_flink = NULL; /* Not in a chain */ + iob->io_len = 0; /* Length of the data in the entry */ + iob->io_offset = 0; /* Offset to the beginning of data */ + iob->io_pktlen = 0; /* Total length of the packet */ + } + + leave_critical_section(flags); + return iob; +} + /**************************************************************************** * Name: iob_allocwait * @@ -85,73 +126,76 @@ static FAR struct iob_s *iob_allocwait(bool throttled) */ flags = enter_critical_section(); - do + + /* Try to get an I/O buffer. If successful, the semaphore count will be + * decremented atomically. + */ + + iob = iob_tryalloc(throttled); + while (ret == OK && iob == NULL) { - /* Try to get an I/O buffer. If successful, the semaphore count - * will be decremented atomically. + /* If not successful, then the semaphore count was less than or equal + * to zero (meaning that there are no free buffers). We need to wait + * for an I/O buffer to be released and placed in the committed + * list. */ - iob = iob_tryalloc(throttled); - if (!iob) + ret = sem_wait(sem); + if (ret < 0) { - /* If not successful, then the semaphore count was less than or - * equal to zero (meaning that there are no free buffers). We - * need to wait for an I/O buffer to be released when the semaphore - * count will be incremented. + int errcode = get_errno(); + + /* EINTR is not an error! EINTR simply means that we were + * awakened by a signal and we should try again. + * + * REVISIT: Many end-user interfaces are required to return with + * an error if EINTR is set. Most uses of this function are in + * internal, non-user logic. But are there cases where the error + * should be returned. */ - ret = sem_wait(sem); - if (ret < 0) + if (errcode == EINTR) { - int errcode = get_errno(); + /* Force a success indication so that we will continue looping. */ - /* EINTR is not an error! EINTR simply means that we were - * awakened by a signal and we should try again. - * - * REVISIT: Many end-user interfaces are required to return - * with an error if EINTR is set. Most uses of this function - * is in internal, non-user logic. But are there cases where - * the error should be returned. - */ - - if (errcode == EINTR) - { - /* Force a success indication so that we will continue - * looping. - */ - - ret = 0; - } - else - { - /* Stop the loop and return a error */ - - DEBUGASSERT(errcode > 0); - ret = -errcode; - } + ret = 0; } else { - /* When we wake up from wait successfully, an I/O buffer was - * returned to the free list. However, if there are concurrent - * allocations from interrupt handling, then I suspect that - * there is a race condition. But no harm, we will just wait - * again in that case. + /* Stop the loop and return a error */ + + DEBUGASSERT(errcode > 0); + ret = -errcode; + } + } + else + { + /* When we wake up from wait successfully, an I/O buffer was + * freed and we hold a count for one IOB. Unless somehting + * failed, we should have an IOB waiting for us in the + * committed list. + */ + + iob = iob_alloc_committed(); + DEBUGASSERT(iob != NULL); + + if (iob == NULL) + { + /* This should not fail, but we allow for that possibility to + * handle any potential, non-obvious race condition. Perhaps + * the free IOB ended up in the g_iob_free list? * * We need release our count so that it is available to * iob_tryalloc(), perhaps allowing another thread to take our * count. In that event, iob_tryalloc() will fail above and * we will have to wait again. - * - * TODO: Consider a design modification to permit us to - * complete the allocation without losing our count. */ sem_post(sem); + iob = iob_tryalloc(throttled); } } } - while (ret == OK && iob == NULL); leave_critical_section(flags); return iob; @@ -225,7 +269,7 @@ FAR struct iob_s *iob_tryalloc(bool throttled) /* Take the I/O buffer from the head of the free list */ iob = g_iob_freelist; - if (iob) + if (iob != NULL) { /* Remove the I/O buffer from the free list and decrement the * counting semaphore(s) that tracks the number of available diff --git a/mm/iob/iob_alloc_qentry.c b/mm/iob/iob_alloc_qentry.c index a1d4044bc45..2a54358b71f 100644 --- a/mm/iob/iob_alloc_qentry.c +++ b/mm/iob/iob_alloc_qentry.c @@ -55,6 +55,44 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: iob_alloc_qcommitted + * + * Description: + * Allocate an I/O buffer by taking the buffer at the head of the committed + * list. + * + ****************************************************************************/ + +FAR struct iob_qentry_s *iob_alloc_qcommitted(void) +{ + FAR struct iob_qentry_s *iobq = NULL; + irqstate_t flags; + + /* We don't know what context we are called from so we use extreme measures + * to protect the committed list: We disable interrupts very briefly. + */ + + flags = enter_critical_section(); + + /* Take the I/O buffer from the head of the committed list */ + + iobq = g_iob_qcommitted; + if (iobq != NULL) + { + /* Remove the I/O buffer from the committed list */ + + g_iob_qcommitted = iobq->io_flink; + + /* Put the I/O buffer in a known state */ + + iobq->qe_head = NULL; /* Nothing is contained */ + } + + leave_critical_section(flags); + return iobq; +} + /**************************************************************************** * Name: iob_allocwait_qentry * @@ -78,73 +116,78 @@ static FAR struct iob_qentry_s *iob_allocwait_qentry(void) */ flags = enter_critical_section(); - do + + /* Try to get an I/O buffer chain container. If successful, the semaphore + * count will bedecremented atomically. + */ + + qentry = iob_tryalloc_qentry(); + while (ret == OK && qentry == NULL) { - /* Try to get an I/O buffer chain container. If successful, the - * semaphore count will be decremented atomically. + /* If not successful, then the semaphore count was less than or equal + * to zero (meaning that there are no free buffers). We need to wait + * for an I/O buffer chain container to be released when the + * semaphore count will be incremented. */ - qentry = iob_tryalloc_qentry(); - if (!qentry) + ret = sem_wait(&g_qentry_sem); + if (ret < 0) { - /* If not successful, then the semaphore count was less than or - * equal to zero (meaning that there are no free buffers). We - * need to wait for an I/O buffer chain container to be released - * when the semaphore count will be incremented. + int errcode = get_errno(); + + /* EINTR is not an error! EINTR simply means that we were + * awakened by a signal and we should try again. + * + * REVISIT: Many end-user interfaces are required to return + * with an error if EINTR is set. Most uses of this function + * is in internal, non-user logic. But are there cases where + * the error should be returned. */ - ret = sem_wait(&g_qentry_sem); - if (ret < 0) + if (errcode == EINTR) { - int errcode = get_errno(); - - /* EINTR is not an error! EINTR simply means that we were - * awakened by a signal and we should try again. - * - * REVISIT: Many end-user interfaces are required to return - * with an error if EINTR is set. Most uses of this function - * is in internal, non-user logic. But are there cases where - * the error should be returned. + /* Force a success indication so that we will continue + * looping. */ - if (errcode == EINTR) - { - /* Force a success indication so that we will continue - * looping. - */ - - ret = 0; - } - else - { - /* Stop the loop and return a error */ - - DEBUGASSERT(errcode > 0); - ret = -errcode; - } + ret = 0; } else { - /* When we wake up from wait successfully, an I/O buffer chain - * container was returned to the free list. However, if there - * are concurrent allocations from interrupt handling, then I - * suspect that there is a race condition. But no harm, we - * will just wait again in that case. + /* Stop the loop and return a error */ + + DEBUGASSERT(errcode > 0); + ret = -errcode; + } + } + else + { + /* When we wake up from wait successfully, an I/O buffer chain container was + * freed and we hold a count for one IOB. Unless somehting + * failed, we should have an IOB waiting for us in the + * committed list. + */ + + qentry = iob_alloc_qcommitted(); + DEBUGASSERT(qentry != NULL); + + if (qentry == NULL) + { + /* This should not fail, but we allow for that possibility to + * handle any potential, non-obvious race condition. Perhaps + * the free IOB ended up in the g_iob_free list? * * We need release our count so that it is available to - * iob_tryalloc_qentry(), perhaps allowing another thread to - * take our count. In that event, iob_tryalloc_qentry() will - * fail above and we will have to wait again. - * - * TODO: Consider a design modification to permit us to - * complete the allocation without losing our count. + * iob_tryalloc(), perhaps allowing another thread to take our + * count. In that event, iob_tryalloc() will fail above and + * we will have to wait again. */ sem_post(&g_qentry_sem); + qentry = iob_tryalloc_qentry(); } } } - while (ret == OK && !qentry); leave_critical_section(flags); return qentry; diff --git a/mm/iob/iob_free.c b/mm/iob/iob_free.c index 75a01cf89b6..0265e2d899a 100644 --- a/mm/iob/iob_free.c +++ b/mm/iob/iob_free.c @@ -74,7 +74,7 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob) * the next entry. */ - if (next) + if (next != NULL) { /* Copy and decrement the total packet length, being careful to * do nothing too crazy. @@ -101,16 +101,36 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob) next, next->io_pktlen, next->io_len); } - /* Free the I/O buffer by adding it to the head of the free list. We don't - * know what context we are called from so we use extreme measures to - * protect the free list: We disable interrupts very briefly. + /* Free the I/O buffer by adding it to the head of the free or the + * committed list. We don't know what context we are called from so + * we use extreme measures to protect the free list: We disable + * interrupts very briefly. */ flags = enter_critical_section(); - iob->io_flink = g_iob_freelist; - g_iob_freelist = iob; - /* Signal that an IOB is available */ + /* Which list? If there is a task waiting for an IOB, then put + * the IOB on either the free list or on the committed list where + * it is reserved for that allocation (and not available to + * iob_tryalloc()). + */ + + if (g_iob_sem.semcount < 0) + { + iob->io_flink = g_iob_committed; + g_iob_committed = iob; + } + else + { + iob->io_flink = g_iob_freelist; + g_iob_freelist = iob; + } + + /* Signal that an IOB is available. If there is a thread waiting + * for an IOB, this will wake up exactly one thread. The semaphore + * count will correctly indicated that the awakened task owns an + * IOB and should find it in the committed list. + */ sem_post(&g_iob_sem); #if CONFIG_IOB_THROTTLE > 0 diff --git a/mm/iob/iob_free_qentry.c b/mm/iob/iob_free_qentry.c index 393f0ee47b6..135cd3ae3ae 100644 --- a/mm/iob/iob_free_qentry.c +++ b/mm/iob/iob_free_qentry.c @@ -1,7 +1,7 @@ /**************************************************************************** * mm/iob/iob_free_qentry.c * - * Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -68,16 +68,37 @@ FAR struct iob_qentry_s *iob_free_qentry(FAR struct iob_qentry_s *iobq) FAR struct iob_qentry_s *nextq = iobq->qe_flink; irqstate_t flags; - /* Free the I/O buffer chain container by adding it to the head of the free - * list. We don't know what context we are called from so we use extreme - * measures to protect the free list: We disable interrupts very briefly. + /* Free the I/O buffer chain container by adding it to the head of the + * free or the committed list. We don't know what context we are called + * from so we use extreme measures to protect the free list: We disable + * interrupts very briefly. */ flags = enter_critical_section(); - iobq->qe_flink = g_iob_freeqlist; - g_iob_freeqlist = iobq; - /* Signal that an I/O buffer chain container is available */ + /* Which list? If there is a task waiting for an IOB, then put + * the IOB on either the free list or on the committed list where + * it is reserved for that allocation (and not available to + * iob_tryalloc()). + */ + + if (g_iob_sem.semcount < 0) + { + iobq->qe_flink = g_iob_qcommitted; + g_iob_qcommitted = iobq; + } + else + { + iobq->qe_flink = g_iob_freeqlist; + g_iob_freeqlist = iobq; + } + + /* Signal that an I/O buffer chain container is available. If there + * is a thread waiting for an I/O buffer chain container, this will + * wake up exactly one thread. The semaphore count will correctly + * indicated that the awakened task owns an I/O buffer chain container + * and should find it in the committed list. + */ sem_post(&g_qentry_sem); leave_critical_section(flags); diff --git a/mm/iob/iob_initialize.c b/mm/iob/iob_initialize.c index 1662fe47728..6c0df544549 100644 --- a/mm/iob/iob_initialize.c +++ b/mm/iob/iob_initialize.c @@ -1,7 +1,7 @@ /**************************************************************************** * mm/iob/iob_initialize.c * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,14 @@ #include "iob.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef NULL +# define NULL ((FAR void *)0) +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -65,10 +73,18 @@ static struct iob_qentry_s g_iob_qpool[CONFIG_IOB_NCHAINS]; FAR struct iob_s *g_iob_freelist; -/* A list of all free, unallocated I/O buffer queue containers */ +/* A list of I/O buffers that are committed for allocation */ + +FAR struct iob_s *g_iob_committed; #if CONFIG_IOB_NCHAINS > 0 +/* A list of all free, unallocated I/O buffer queue containers */ + FAR struct iob_qentry_s *g_iob_freeqlist; + +/* A list of I/O buffer queue containers that are committed for allocation */ + +extern FAR struct iob_s *g_iob_qcommitted; #endif /* Counting semaphores that tracks the number of free IOBs/qentries */ @@ -114,8 +130,9 @@ void iob_initialize(void) g_iob_freelist = iob; } - sem_init(&g_iob_sem, 0, CONFIG_IOB_NBUFFERS); + g_iob_committed = NULL; + sem_init(&g_iob_sem, 0, CONFIG_IOB_NBUFFERS); #if CONFIG_IOB_THROTTLE > 0 sem_init(&g_throttle_sem, 0, CONFIG_IOB_NBUFFERS - CONFIG_IOB_THROTTLE); #endif @@ -133,6 +150,8 @@ void iob_initialize(void) g_iob_freeqlist = iobq; } + g_iob_qcommitted = NULL; + sem_init(&g_qentry_sem, 0, CONFIG_IOB_NCHAINS); #endif initialized = true; From 5ce2ece1344d2fff24a3c303571a34800d689d11 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 16 May 2017 12:26:23 -0600 Subject: [PATCH 03/14] syslog: Add header file inclusion to eliminate a warning; mm/iob: private function needs static storage class. --- drivers/syslog/syslog_write.c | 2 ++ mm/iob/iob_alloc_qentry.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/syslog/syslog_write.c b/drivers/syslog/syslog_write.c index 390f594237d..02efde09ff4 100644 --- a/drivers/syslog/syslog_write.c +++ b/drivers/syslog/syslog_write.c @@ -40,6 +40,8 @@ #include #include + +#include #include #include diff --git a/mm/iob/iob_alloc_qentry.c b/mm/iob/iob_alloc_qentry.c index 2a54358b71f..4caba97a9c7 100644 --- a/mm/iob/iob_alloc_qentry.c +++ b/mm/iob/iob_alloc_qentry.c @@ -64,7 +64,7 @@ * ****************************************************************************/ -FAR struct iob_qentry_s *iob_alloc_qcommitted(void) +static FAR struct iob_qentry_s *iob_alloc_qcommitted(void) { FAR struct iob_qentry_s *iobq = NULL; irqstate_t flags; From 9169ff6a15fe65ba4af134b470dbf89220274c19 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 17 May 2017 06:50:46 -0600 Subject: [PATCH 04/14] stm32_serial: fix freezing serial port. Serial interrupt enable/disable functions do not disable interrupts and can freeze device when serial interrupt is received while execution is at those functions. Trivially triggered with two or more threads write to regular syslog stream and to emergency stream. In this case, freeze happens because of mismatch of priv->ie (TXEIE == 0) and actually enabled interrupts in USART registers (TXEIE == 1), which leads to unhandled TXE interrupt and causes interrupt storm for USART. --- arch/arm/src/stm32/stm32_serial.c | 29 +++++++++++++++++++---- arch/arm/src/stm32f0/stm32f0_serial.c | 32 +++++++++++++++++++++---- arch/arm/src/stm32f7/stm32_serial.c | 30 +++++++++++++++++++---- arch/arm/src/stm32l4/stm32l4_serial.c | 34 ++++++++++++++++++++++----- 4 files changed, 106 insertions(+), 19 deletions(-) diff --git a/arch/arm/src/stm32/stm32_serial.c b/arch/arm/src/stm32/stm32_serial.c index 77c07ea68e0..7aa362c38f5 100644 --- a/arch/arm/src/stm32/stm32_serial.c +++ b/arch/arm/src/stm32/stm32_serial.c @@ -1050,10 +1050,10 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu } /**************************************************************************** - * Name: up_restoreusartint + * Name: up_setusartint ****************************************************************************/ -static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) +static inline void up_setusartint(struct up_dev_s *priv, uint16_t ie) { uint32_t cr; @@ -1074,12 +1074,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) up_serialout(priv, STM32_USART_CR3_OFFSET, cr); } +/**************************************************************************** + * Name: up_restoreusartint + ****************************************************************************/ + +static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + up_setusartint(priv, ie); + + leave_critical_section(flags); +} + /**************************************************************************** * Name: up_disableusartint ****************************************************************************/ -static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) +static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) { + irqstate_t flags; + + flags = enter_critical_section(); + if (ie) { uint32_t cr1; @@ -1116,7 +1135,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) /* Disable all interrupts */ - up_restoreusartint(priv, 0); + up_setusartint(priv, 0); + + leave_critical_section(flags); } /**************************************************************************** diff --git a/arch/arm/src/stm32f0/stm32f0_serial.c b/arch/arm/src/stm32f0/stm32f0_serial.c index f0975fad2ca..788967c231d 100644 --- a/arch/arm/src/stm32f0/stm32f0_serial.c +++ b/arch/arm/src/stm32f0/stm32f0_serial.c @@ -769,10 +769,10 @@ static inline void stm32f0serial_putreg(FAR struct stm32f0_serial_s *priv, } /**************************************************************************** - * Name: stm32f0serial_restoreusartint + * Name: stm32f0serial_setusartint ****************************************************************************/ -static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv, +static void stm32f0serial_setusartint(FAR struct stm32f0_serial_s *priv, uint16_t ie) { uint32_t cr; @@ -794,13 +794,33 @@ static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv, stm32f0serial_putreg(priv, STM32F0_USART_CR3_OFFSET, cr); } +/**************************************************************************** + * Name: stm32f0serial_restoreusartint + ****************************************************************************/ + +static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv, + uint16_t ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + stm32f0serial_setusartint(priv, ie); + + leave_critical_section(flags); +} + /**************************************************************************** * Name: stm32f0serial_disableusartint ****************************************************************************/ -static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv, - FAR uint16_t *ie) +static void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv, + FAR uint16_t *ie) { + irqstate_t flags; + + flags = enter_critical_section(); + if (ie) { uint32_t cr1; @@ -837,7 +857,9 @@ static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *pr /* Disable all interrupts */ - stm32f0serial_restoreusartint(priv, 0); + stm32f0serial_setusartint(priv, 0); + + leave_critical_section(flags); } /**************************************************************************** diff --git a/arch/arm/src/stm32f7/stm32_serial.c b/arch/arm/src/stm32f7/stm32_serial.c index ce6e7db9a72..f400a9b379c 100644 --- a/arch/arm/src/stm32f7/stm32_serial.c +++ b/arch/arm/src/stm32f7/stm32_serial.c @@ -1096,10 +1096,10 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu } /**************************************************************************** - * Name: up_restoreusartint + * Name: up_setusartint ****************************************************************************/ -static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) +static inline void up_setusartint(struct up_dev_s *priv, uint16_t ie) { uint32_t cr; @@ -1120,12 +1120,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) up_serialout(priv, STM32_USART_CR3_OFFSET, cr); } +/**************************************************************************** + * Name: up_restoreusartint + ****************************************************************************/ + +static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + up_setusartint(priv, ie); + + leave_critical_section(flags); +} + /**************************************************************************** * Name: up_disableusartint ****************************************************************************/ -static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) +static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) { + irqstate_t flags; + + flags = enter_critical_section(); + if (ie) { uint32_t cr1; @@ -1162,7 +1181,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) /* Disable all interrupts */ - up_restoreusartint(priv, 0); + up_setusartint(priv, 0); + + leave_critical_section(flags); } /**************************************************************************** @@ -2868,6 +2889,7 @@ int up_putc(int ch) up_lowputc(ch); up_restoreusartint(priv, ie); + #endif return ch; } diff --git a/arch/arm/src/stm32l4/stm32l4_serial.c b/arch/arm/src/stm32l4/stm32l4_serial.c index 15b9cbd120c..f1a5550212c 100644 --- a/arch/arm/src/stm32l4/stm32l4_serial.c +++ b/arch/arm/src/stm32l4/stm32l4_serial.c @@ -765,11 +765,11 @@ static inline void stm32l4serial_putreg(FAR struct stm32l4_serial_s *priv, } /**************************************************************************** - * Name: stm32l4serial_restoreusartint + * Name: stm32l4serial_setusartint ****************************************************************************/ -static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv, - uint16_t ie) +static inline void stm32l4serial_setusartint(FAR struct stm32l4_serial_s *priv, + uint16_t ie) { uint32_t cr; @@ -790,13 +790,33 @@ static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv, stm32l4serial_putreg(priv, STM32L4_USART_CR3_OFFSET, cr); } +/**************************************************************************** + * Name: up_restoreusartint + ****************************************************************************/ + +static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv, + uint16_t ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + stm32l4serial_setusartint(priv, ie); + + leave_critical_section(flags); +} + /**************************************************************************** * Name: stm32l4serial_disableusartint ****************************************************************************/ -static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv, - FAR uint16_t *ie) +static void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv, + FAR uint16_t *ie) { + irqstate_t flags; + + flags = enter_critical_section(); + if (ie) { uint32_t cr1; @@ -833,7 +853,9 @@ static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *pr /* Disable all interrupts */ - stm32l4serial_restoreusartint(priv, 0); + stm32l4serial_setusartint(priv, 0); + + leave_critical_section(flags); } /**************************************************************************** From 8896f91f5352b2b1c8e6be8c7559b13214d04582 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Wed, 17 May 2017 08:05:24 -0600 Subject: [PATCH 05/14] STM32L4: remove duplicate USART selects from Kconfig --- arch/arm/src/stm32l4/Kconfig | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index 76d2dae6136..2721ca3871e 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -1008,14 +1008,6 @@ config STM32L4_SPI3 select SPI select STM32L4_SPI -config STM32L4_USART1 - bool "USART1" - default n - depends on STM32L4_HAVE_USART1 - select ARCH_HAVE_SERIAL_TERMIOS - select USART1_SERIALDRIVER - select STM32L4_USART - config STM32L4_USART2 bool "USART2" default n @@ -1155,8 +1147,9 @@ config STM32L4_TIM8 config STM32L4_USART1 bool "USART1" default n - select USART1_SERIALDRIVER + depends on STM32L4_HAVE_USART1 select ARCH_HAVE_SERIAL_TERMIOS + select USART1_SERIALDRIVER select STM32L4_USART config STM32L4_TIM15 @@ -1306,9 +1299,6 @@ config STM32L4_SAI2PLL Set this true and provide configuration parameters in board.h to use this PLL. -config STM32L4_USART - bool - menu "Timer Configuration" if SCHED_TICKLESS From 2c6ea23aee8e7f2341c8ce78b30c929088eeab8d Mon Sep 17 00:00:00 2001 From: Sebastien Lorquet Date: Wed, 17 May 2017 10:04:49 -0600 Subject: [PATCH 06/14] STM32 Ethernet: Add support for KSZ8081 PHY interrupts. --- arch/arm/src/stm32/stm32_eth.c | 50 ++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c index 2b02b5e3455..10494798920 100644 --- a/arch/arm/src/stm32/stm32_eth.c +++ b/arch/arm/src/stm32/stm32_eth.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -189,6 +190,40 @@ # endif #endif +/* These definitions are used to enable the PHY interrupts */ + +#if defined( CONFIG_ETH0_PHY_AM79C874) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_KS8721) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_KSZ8041) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_KSZ8051) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_KSZ8061) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_KSZ8081) +# define MII_INT_REG MII_KSZ8081_INT +# define MII_INT_SETEN MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN +# define MII_INT_CLREN 0 +#elif defined( CONFIG_ETH0_PHY_KSZ90x1) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_DP83848C) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_LAN8720) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_LAN8740) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_LAN8740A) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_LAN8742A) +# error missing logic +#elif defined( CONFIG_ETH0_PHY_DM9161) +# error missing logic +#else +# error unknown PHY +#endif + #ifdef CONFIG_STM32_ETH_PTP # warning "CONFIG_STM32_ETH_PTP is not yet supported" #endif @@ -2889,8 +2924,19 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) #if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) static int stm32_phyintenable(struct stm32_ethmac_s *priv) { -#warning Missing logic - return -ENOSYS; + uint16_t phyval; + int ret; + + ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_INT_REG, &phyval); + if (ret == OK) + { + /* Enable link up/down interrupts */ + + ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_INT_REG, + (phyval & ~MII_INT_CLREN) | MII_INT_SETEN); + } + + return 0; } #endif From aac3a3df8e0a49e1be77513cceb6125465bdc6ac Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 17 May 2017 10:07:09 -0600 Subject: [PATCH 07/14] STM32 Ethernet: Should not stm32_phyintenable() return a failure if it could not enable the PHY interrupt? --- arch/arm/src/stm32/stm32_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c index 10494798920..db7c5a6e814 100644 --- a/arch/arm/src/stm32/stm32_eth.c +++ b/arch/arm/src/stm32/stm32_eth.c @@ -2936,7 +2936,7 @@ static int stm32_phyintenable(struct stm32_ethmac_s *priv) (phyval & ~MII_INT_CLREN) | MII_INT_SETEN); } - return 0; + return ret; } #endif From 989195cec81b40704d8911e7122f0d062ea32746 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 17 May 2017 15:36:57 -0600 Subject: [PATCH 08/14] STM32 Ethernet: Last patch breaks every board that does not use the KSZ80801 PHY. --- arch/arm/src/stm32/stm32_eth.c | 62 ++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c index db7c5a6e814..77493cd880c 100644 --- a/arch/arm/src/stm32/stm32_eth.c +++ b/arch/arm/src/stm32/stm32_eth.c @@ -192,36 +192,38 @@ /* These definitions are used to enable the PHY interrupts */ -#if defined( CONFIG_ETH0_PHY_AM79C874) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_KS8721) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_KSZ8041) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_KSZ8051) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_KSZ8061) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_KSZ8081) -# define MII_INT_REG MII_KSZ8081_INT -# define MII_INT_SETEN MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN -# define MII_INT_CLREN 0 -#elif defined( CONFIG_ETH0_PHY_KSZ90x1) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_DP83848C) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_LAN8720) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_LAN8740) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_LAN8740A) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_LAN8742A) -# error missing logic -#elif defined( CONFIG_ETH0_PHY_DM9161) -# error missing logic -#else -# error unknown PHY +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) +# if defined( CONFIG_ETH0_PHY_AM79C874) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KS8721) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8041) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8051) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8061) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_KSZ8081) +# define MII_INT_REG MII_KSZ8081_INT +# define MII_INT_SETEN MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN +# define MII_INT_CLREN 0 +# elif defined( CONFIG_ETH0_PHY_KSZ90x1) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_DP83848C) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8720) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8740) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8740A) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_LAN8742A) +# error missing logic +# elif defined( CONFIG_ETH0_PHY_DM9161) +# error missing logic +# else +# error unknown PHY +# endif #endif #ifdef CONFIG_STM32_ETH_PTP From f10e10e465fcf876907712cd104830886fc9ea3d Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Thu, 18 May 2017 12:57:29 +0900 Subject: [PATCH 09/14] IOBs: Fix build break Signed-off-by: Masayuki Ishikawa --- mm/iob/iob_alloc_qentry.c | 2 +- mm/iob/iob_initialize.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/iob/iob_alloc_qentry.c b/mm/iob/iob_alloc_qentry.c index 4caba97a9c7..10bc1123d7a 100644 --- a/mm/iob/iob_alloc_qentry.c +++ b/mm/iob/iob_alloc_qentry.c @@ -82,7 +82,7 @@ static FAR struct iob_qentry_s *iob_alloc_qcommitted(void) { /* Remove the I/O buffer from the committed list */ - g_iob_qcommitted = iobq->io_flink; + g_iob_qcommitted = iobq->qe_flink; /* Put the I/O buffer in a known state */ diff --git a/mm/iob/iob_initialize.c b/mm/iob/iob_initialize.c index 6c0df544549..adab03c228c 100644 --- a/mm/iob/iob_initialize.c +++ b/mm/iob/iob_initialize.c @@ -84,7 +84,7 @@ FAR struct iob_qentry_s *g_iob_freeqlist; /* A list of I/O buffer queue containers that are committed for allocation */ -extern FAR struct iob_s *g_iob_qcommitted; +FAR struct iob_s *g_iob_qcommitted; #endif /* Counting semaphores that tracks the number of free IOBs/qentries */ From 980b17d951281886f43e5d83e99975c9eedeffa6 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Thu, 18 May 2017 09:22:33 +0900 Subject: [PATCH 10/14] IPv6: Fix net_ipv6_pref2mask() Signed-off-by: Masayuki Ishikawa --- net/utils/net_ipv6_pref2mask.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/utils/net_ipv6_pref2mask.c b/net/utils/net_ipv6_pref2mask.c index 6b046354131..7155f5856b6 100644 --- a/net/utils/net_ipv6_pref2mask.c +++ b/net/utils/net_ipv6_pref2mask.c @@ -82,7 +82,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask) * 1..6 7..2 3..8 9..4 5..0 1..6 7..2 3..8 */ - for (i = 0; i < 7; i++) + for (i = 0; i < 8; i++) { /* bit = {0, 16, 32, 48, 64, 80, 96, 112} */ @@ -92,7 +92,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask) { /* Eg. preflen = 38, bit = {0, 16, 32} */ - if (preflen > (bit + 16)) + if (preflen >= (bit + 16)) { /* Eg. preflen = 38, bit = {0, 16} */ @@ -102,7 +102,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask) { /* Eg. preflen = 38, bit = {32} * bit - preflen = 6 - * make = 0xffff << (16-6) + * mask = 0xffff << (16-6) * = 0xfc00 */ @@ -111,7 +111,7 @@ void net_ipv6_pref2mask(uint8_t preflen, net_ipv6addr_t mask) } else { - /* Eg. preflen=38, bit= {48, 64, 80, 112} */ + /* Eg. preflen=38, bit= {48, 64, 80, 96, 112} */ mask[i] = 0x0000; } From 49a70079c17bb962acc243aa7681726e430c7b73 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 18 May 2017 09:50:54 -0600 Subject: [PATCH 11/14] Update TODO list --- TODO | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index 25e5127b8d4..3d3755b679a 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated April 15, 2017) +NuttX TODO List (Last updated May 18, 2017) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -25,7 +25,7 @@ nuttx/: (12) Libraries (libc/, libm/) (10) File system/Generic drivers (fs/, drivers/) (9) Graphics Subsystem (graphics/) - (2) Build system / Toolchains + (3) Build system / Toolchains (3) Linux/Cywgin simulation (arch/sim) (4) ARM (arch/arm/) @@ -1825,6 +1825,43 @@ o Build system Priority: Low, since I am not aware of anyone using the Windows Native build. But, of course, very high if you want to use it. + Title: CONTROL-C CAN BREAK DEPENDENCIES + Description: If you control C out of a make, then there are things that can go + wrong. For one, you can break the dependencies in this scenario: + + - The build in a given directory begins with all of the compilations. + On terminal, this the long phase with CC: on each line. As each + .o file is created, it is timestamped with the current time. + + - The dependencies on each .o are such that the C file will be re- + compile if the .o file is OLDER that the corresponding .a archive + file. + + - The compilation phase is followed by a single, relatively short + AR: phase that adds each of the file to the .a archive file. As + each file is added to archive, the timestamp of the of archive is + updated to the current time. After the first .o file has been + added, then archive file will have a newly timestamp than any of + the newly compiled .o file. + + - If the user aborts with control-C during this AR: phase, then we + are left with: (1) not all of the files have bee added to the + archive, and (2) the archive file has a newer timestamp than any + of the .o file. + + So when the make is restarted after a control, the dependencies will + see that the .a archive file has the newer time stamp and those .o + file will never be added to the archive until the directory is cleaned + or some other dependency changes. + Status Open + Priority: Medium-High. It is a rare event that control-C happens at just the + point in time. However, when it does occur the resulting code may + have binary incompatiblies in the code taken from the out-of-sync + archives and cost a lot of debug time before you realize the issue. + + A work-around is to do 'make clean' if you ever decide to control-C + out of a make. + o Other drivers (drivers/) ^^^^^^^^^^^^^^^^^^^^^^^^ From 0260891c96d2e23b78d23e329381671e0730442a Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Thu, 18 May 2017 16:30:12 +0900 Subject: [PATCH 12/14] net procfs: Fix buffer corruption and refactor netdev_statistics.c Signed-off-by: Masayuki Ishikawa --- net/procfs/netdev_statistics.c | 50 ++++++++++++++++++++++------------ net/procfs/procfs.h | 2 +- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/net/procfs/netdev_statistics.c b/net/procfs/netdev_statistics.c index 109f4cdca28..cd7dde177d9 100644 --- a/net/procfs/netdev_statistics.c +++ b/net/procfs/netdev_statistics.c @@ -61,9 +61,12 @@ ****************************************************************************/ static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile); -static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile); +#ifdef CONFIG_NET_IPv4 +static int netprocfs_inet4addresses(FAR struct netprocfs_file_s *netfile); +#endif #ifdef CONFIG_NET_IPv6 -static int netprocfs_dripaddress(FAR struct netprocfs_file_s *netfile); +static int netprocfs_inet6address(FAR struct netprocfs_file_s *netfile); +static int netprocfs_inet6draddress(FAR struct netprocfs_file_s *netfile); #endif #ifdef CONFIG_NETDEV_STATISTICS static int netprocfs_rxstatistics_header(FAR struct netprocfs_file_s *netfile); @@ -83,10 +86,13 @@ static int netprocfs_errors(FAR struct netprocfs_file_s *netfile); static const linegen_t g_linegen[] = { - netprocfs_linklayer, - netprocfs_ipaddresses + netprocfs_linklayer +#ifdef CONFIG_NET_IPv4 + , netprocfs_inet4addresses +#endif #ifdef CONFIG_NET_IPv6 - , netprocfs_dripaddress + , netprocfs_inet6address + , netprocfs_inet6draddress #endif #ifdef CONFIG_NETDEV_STATISTICS , netprocfs_rxstatistics_header, @@ -255,25 +261,19 @@ static int netprocfs_linklayer(FAR struct netprocfs_file_s *netfile) } /**************************************************************************** - * Name: netprocfs_ipaddresses + * Name: netprocfs_inet4addresses ****************************************************************************/ -static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile) +#ifdef CONFIG_NET_IPv4 +static int netprocfs_inet4addresses(FAR struct netprocfs_file_s *netfile) { FAR struct net_driver_s *dev; -#ifdef CONFIG_NET_IPv4 struct in_addr addr; -#endif -#ifdef CONFIG_NET_IPv6 - char addrstr[INET6_ADDRSTRLEN]; - uint8_t preflen; -#endif int len = 0; DEBUGASSERT(netfile != NULL && netfile->dev != NULL); dev = netfile->dev; -#ifdef CONFIG_NET_IPv4 /* Show the IPv4 address */ addr.s_addr = dev->d_ipaddr; @@ -291,9 +291,25 @@ static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile) addr.s_addr = dev->d_netmask; len += snprintf(&netfile->line[len], NET_LINELEN - len, "Mask:%s\n\n", inet_ntoa(addr)); + return len; +} #endif +/**************************************************************************** + * Name: netprocfs_inet6address + ****************************************************************************/ + #ifdef CONFIG_NET_IPv6 +static int netprocfs_inet6address(FAR struct netprocfs_file_s *netfile) +{ + FAR struct net_driver_s *dev; + char addrstr[INET6_ADDRSTRLEN]; + uint8_t preflen; + int len = 0; + + DEBUGASSERT(netfile != NULL && netfile->dev != NULL); + dev = netfile->dev; + /* Convert the 128 network mask to a human friendly prefix length */ preflen = net_ipv6_mask2pref(dev->d_ipv6netmask); @@ -305,17 +321,17 @@ static int netprocfs_ipaddresses(FAR struct netprocfs_file_s *netfile) len += snprintf(&netfile->line[len], NET_LINELEN - len, "\tinet6 addr:%s/%d\n", addrstr, preflen); } -#endif return len; } +#endif /**************************************************************************** - * Name: netprocfs_dripaddress + * Name: netprocfs_inet6draddress ****************************************************************************/ #ifdef CONFIG_NET_IPv6 -static int netprocfs_dripaddress(FAR struct netprocfs_file_s *netfile) +static int netprocfs_inet6draddress(FAR struct netprocfs_file_s *netfile) { FAR struct net_driver_s *dev; char addrstr[INET6_ADDRSTRLEN]; diff --git a/net/procfs/procfs.h b/net/procfs/procfs.h index 889f3507256..9b0d7bfd49f 100644 --- a/net/procfs/procfs.h +++ b/net/procfs/procfs.h @@ -54,7 +54,7 @@ * to handle the longest line generated by this logic. */ -#define NET_LINELEN 64 +#define NET_LINELEN 80 /**************************************************************************** * Public Type Definitions From b1008477ac921bdb56edab43e07141d79674216c Mon Sep 17 00:00:00 2001 From: Yasuhiro Osaki Date: Thu, 11 Sep 2014 09:44:09 +0900 Subject: [PATCH 13/14] binfmt: Fix .dtor memory allocation Jira: PDFW15IS-265 Coverity-ID: 11053 Signed-off-by: Masayuki Ishikawa --- binfmt/libelf/libelf_dtors.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/binfmt/libelf/libelf_dtors.c b/binfmt/libelf/libelf_dtors.c index 6d0b0cff1a4..9e10f703f72 100644 --- a/binfmt/libelf/libelf_dtors.c +++ b/binfmt/libelf/libelf_dtors.c @@ -163,14 +163,14 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo) { /* Allocate memory to hold a copy of the .dtor section */ - loadinfo->ctoralloc = (binfmt_dtor_t *)kumm_malloc(dtorsize); - if (!loadinfo->ctoralloc) + loadinfo->dtoralloc = (binfmt_dtor_t *)kumm_malloc(dtorsize); + if (!loadinfo->dtoralloc) { berr("Failed to allocate memory for .dtors\n"); return -ENOMEM; } - loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc; + loadinfo->dtors = (binfmt_dtor_t *)loadinfo->dtoralloc; /* Read the section header table into memory */ From 819a6e049efcc50e8b209b5f889a22bf9c7ce069 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Fri, 19 May 2017 07:15:27 -0600 Subject: [PATCH 14/14] stm32_i2c: make private symbols static --- arch/arm/src/stm32/stm32f30xxx_i2c.c | 8 +- arch/arm/src/stm32f0/stm32f0_i2c.c | 8 +- arch/arm/src/stm32f7/stm32_i2c.c | 252 +++++++++++++-------------- arch/arm/src/stm32l4/stm32l4_i2c.c | 12 +- 4 files changed, 140 insertions(+), 140 deletions(-) diff --git a/arch/arm/src/stm32/stm32f30xxx_i2c.c b/arch/arm/src/stm32/stm32f30xxx_i2c.c index 539305194d7..e779c040ede 100644 --- a/arch/arm/src/stm32/stm32f30xxx_i2c.c +++ b/arch/arm/src/stm32/stm32f30xxx_i2c.c @@ -318,7 +318,7 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev); /* Device Structures, Instantiation */ -const struct i2c_ops_s stm32_i2c_ops = +static const struct i2c_ops_s stm32_i2c_ops = { .transfer = stm32_i2c_transfer #ifdef CONFIG_I2C_RESET @@ -340,7 +340,7 @@ static const struct stm32_i2c_config_s stm32_i2c1_config = #endif }; -struct stm32_i2c_priv_s stm32_i2c1_priv = +static struct stm32_i2c_priv_s stm32_i2c1_priv = { .ops = &stm32_i2c_ops, .config = &stm32_i2c1_config, @@ -369,7 +369,7 @@ static const struct stm32_i2c_config_s stm32_i2c2_config = #endif }; -struct stm32_i2c_priv_s stm32_i2c2_priv = +static struct stm32_i2c_priv_s stm32_i2c2_priv = { .ops = &stm32_i2c_ops, .config = &stm32_i2c2_config, @@ -398,7 +398,7 @@ static const struct stm32_i2c_config_s stm32_i2c3_config = #endif }; -struct stm32_i2c_priv_s stm32_i2c3_priv = +static struct stm32_i2c_priv_s stm32_i2c3_priv = { .ops = &stm32_i2c_ops, .config = &stm32_i2c3_config, diff --git a/arch/arm/src/stm32f0/stm32f0_i2c.c b/arch/arm/src/stm32f0/stm32f0_i2c.c index c782754fc34..69c5a1b53fe 100644 --- a/arch/arm/src/stm32f0/stm32f0_i2c.c +++ b/arch/arm/src/stm32f0/stm32f0_i2c.c @@ -307,7 +307,7 @@ static int stm32f0_i2c_reset(FAR struct i2c_master_s *dev); /* Device Structures, Instantiation */ -const struct i2c_ops_s stm32f0_i2c_ops = +static const struct i2c_ops_s stm32f0_i2c_ops = { .transfer = stm32f0_i2c_transfer #ifdef CONFIG_I2C_RESET @@ -328,7 +328,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c1_config = #endif }; -struct stm32f0_i2c_priv_s stm32f0_i2c1_priv = +static struct stm32f0_i2c_priv_s stm32f0_i2c1_priv = { .ops = &stm32f0_i2c_ops, .config = &stm32f0_i2c1_config, @@ -356,7 +356,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c2_config = #endif }; -struct stm32f0_i2c_priv_s stm32f0_i2c2_priv = +static struct stm32f0_i2c_priv_s stm32f0_i2c2_priv = { .ops = &stm32f0_i2c_ops, .config = &stm32f0_i2c2_config, @@ -384,7 +384,7 @@ static const struct stm32f0_i2c_config_s stm32f0_i2c3_config = #endif }; -struct stm32f0_i2c_priv_s stm32f0_i2c3_priv = +static struct stm32f0_i2c_priv_s stm32f0_i2c3_priv = { .ops = &stm32f0_i2c_ops, .config = &stm32f0_i2c3_config, diff --git a/arch/arm/src/stm32f7/stm32_i2c.c b/arch/arm/src/stm32f7/stm32_i2c.c index 38c1f08268a..c9ae5710946 100644 --- a/arch/arm/src/stm32f7/stm32_i2c.c +++ b/arch/arm/src/stm32f7/stm32_i2c.c @@ -290,7 +290,7 @@ #if !defined(CONFIG_STM32F7_I2CTIMEOSEC) && !defined(CONFIG_STM32F7_I2CTIMEOMS) # define CONFIG_STM32F7_I2CTIMEOSEC 0 # define CONFIG_STM32F7_I2CTIMEOMS 500 /* Default is 500 milliseconds */ -# warning "Using Defualt 500 Ms Timeout" +# warning "Using Default 500 Ms Timeout" #elif !defined(CONFIG_STM32F7_I2CTIMEOSEC) # define CONFIG_STM32F7_I2CTIMEOSEC 0 /* User provided milliseconds */ #elif !defined(CONFIG_STM32F7_I2CTIMEOMS) @@ -445,7 +445,7 @@ struct stm32_i2c_priv_s struct stm32_i2c_inst_s { - struct i2c_ops_s *ops; /* Standard I2C operations */ + const struct i2c_ops_s *ops; /* Standard I2C operations */ struct stm32_i2c_priv_s *priv; /* Common driver private data structure */ }; @@ -495,7 +495,7 @@ static int stm32_i2c_process(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs, int count); #ifdef CONFIG_I2C_RESET -int stm32_i2c_reset(FAR struct i2c_master_s * dev); +static int stm32_i2c_reset(FAR struct i2c_master_s * dev); #endif /************************************************************************************ @@ -516,7 +516,7 @@ static const struct stm32_i2c_config_s stm32_i2c1_config = #endif }; -struct stm32_i2c_priv_s stm32_i2c1_priv = +static struct stm32_i2c_priv_s stm32_i2c1_priv = { .config = &stm32_i2c1_config, .refs = 0, @@ -545,7 +545,7 @@ static const struct stm32_i2c_config_s stm32_i2c2_config = #endif }; -struct stm32_i2c_priv_s stm32_i2c2_priv = +static struct stm32_i2c_priv_s stm32_i2c2_priv = { .config = &stm32_i2c2_config, .refs = 0, @@ -574,7 +574,7 @@ static const struct stm32_i2c_config_s stm32_i2c3_config = #endif }; -struct stm32_i2c_priv_s stm32_i2c3_priv = +static struct stm32_i2c_priv_s stm32_i2c3_priv = { .config = &stm32_i2c3_config, .refs = 0, @@ -603,7 +603,7 @@ static const struct stm32_i2c_config_s stm32_i2c4_config = #endif }; -struct stm32_i2c_priv_s stm32_i2c4_priv = +static struct stm32_i2c_priv_s stm32_i2c4_priv = { .config = &stm32_i2c4_config, .refs = 0, @@ -620,7 +620,7 @@ struct stm32_i2c_priv_s stm32_i2c4_priv = /* Device Structures, Instantiation */ -struct i2c_ops_s stm32_i2c_ops = +static const struct i2c_ops_s stm32_i2c_ops = { .transfer = stm32_i2c_transfer #ifdef CONFIG_I2C_RESET @@ -2485,6 +2485,124 @@ static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s return stm32_i2c_process(dev, msgs, count); } +/************************************************************************************ + * Name: stm32_i2c_reset + * + * Description: + * Reset an I2C bus + * + ************************************************************************************/ + +#ifdef CONFIG_I2C_RESET +static int stm32_i2c_reset(FAR struct i2c_master_s * dev) +{ + struct stm32_i2c_priv_s * priv; + unsigned int clock_count; + unsigned int stretch_count; + uint32_t scl_gpio; + uint32_t sda_gpio; + int ret = ERROR; + + ASSERT(dev); + + /* Get I2C private structure */ + + priv = ((struct stm32_i2c_inst_s *)dev)->priv; + + /* Our caller must own a ref */ + + ASSERT(priv->refs > 0); + + /* Lock out other clients */ + + stm32_i2c_sem_wait(dev); + + /* De-init the port */ + + stm32_i2c_deinit(priv); + + /* Use GPIO configuration to un-wedge the bus */ + + scl_gpio = MKI2C_OUTPUT(priv->config->scl_pin); + sda_gpio = MKI2C_OUTPUT(priv->config->sda_pin); + + /* Let SDA go high */ + + stm32_gpiowrite(sda_gpio, 1); + + /* Clock the bus until any slaves currently driving it let it go. */ + + clock_count = 0; + while (!stm32_gpioread(sda_gpio)) + { + /* Give up if we have tried too hard */ + + if (clock_count++ > 10) + { + goto out; + } + + /* Sniff to make sure that clock stretching has finished. + * + * If the bus never relaxes, the reset has failed. + */ + + stretch_count = 0; + while (!stm32_gpioread(scl_gpio)) + { + /* Give up if we have tried too hard */ + + if (stretch_count++ > 10) + { + goto out; + } + + up_udelay(10); + } + + /* Drive SCL low */ + + stm32_gpiowrite(scl_gpio, 0); + up_udelay(10); + + /* Drive SCL high again */ + + stm32_gpiowrite(scl_gpio, 1); + up_udelay(10); + } + + /* Generate a start followed by a stop to reset slave + * state machines. + */ + + stm32_gpiowrite(sda_gpio, 0); + up_udelay(10); + stm32_gpiowrite(scl_gpio, 0); + up_udelay(10); + stm32_gpiowrite(scl_gpio, 1); + up_udelay(10); + stm32_gpiowrite(sda_gpio, 1); + up_udelay(10); + + /* Revert the GPIO configuration. */ + + stm32_unconfiggpio(sda_gpio); + stm32_unconfiggpio(scl_gpio); + + /* Re-init the port */ + + stm32_i2c_init(priv); + ret = OK; + +out: + + /* Release the port for re-use by other clients */ + + stm32_i2c_sem_post(dev); + return ret; +} +#endif /* CONFIG_I2C_RESET */ + /************************************************************************************ * Public Functions ************************************************************************************/ @@ -2608,122 +2726,4 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev) return OK; } -/************************************************************************************ - * Name: stm32_i2c_reset - * - * Description: - * Reset an I2C bus - * - ************************************************************************************/ - -#ifdef CONFIG_I2C_RESET -int stm32_i2c_reset(FAR struct i2c_master_s * dev) -{ - struct stm32_i2c_priv_s * priv; - unsigned int clock_count; - unsigned int stretch_count; - uint32_t scl_gpio; - uint32_t sda_gpio; - int ret = ERROR; - - ASSERT(dev); - - /* Get I2C private structure */ - - priv = ((struct stm32_i2c_inst_s *)dev)->priv; - - /* Our caller must own a ref */ - - ASSERT(priv->refs > 0); - - /* Lock out other clients */ - - stm32_i2c_sem_wait(dev); - - /* De-init the port */ - - stm32_i2c_deinit(priv); - - /* Use GPIO configuration to un-wedge the bus */ - - scl_gpio = MKI2C_OUTPUT(priv->config->scl_pin); - sda_gpio = MKI2C_OUTPUT(priv->config->sda_pin); - - /* Let SDA go high */ - - stm32_gpiowrite(sda_gpio, 1); - - /* Clock the bus until any slaves currently driving it let it go. */ - - clock_count = 0; - while (!stm32_gpioread(sda_gpio)) - { - /* Give up if we have tried too hard */ - - if (clock_count++ > 10) - { - goto out; - } - - /* Sniff to make sure that clock stretching has finished. - * - * If the bus never relaxes, the reset has failed. - */ - - stretch_count = 0; - while (!stm32_gpioread(scl_gpio)) - { - /* Give up if we have tried too hard */ - - if (stretch_count++ > 10) - { - goto out; - } - - up_udelay(10); - } - - /* Drive SCL low */ - - stm32_gpiowrite(scl_gpio, 0); - up_udelay(10); - - /* Drive SCL high again */ - - stm32_gpiowrite(scl_gpio, 1); - up_udelay(10); - } - - /* Generate a start followed by a stop to reset slave - * state machines. - */ - - stm32_gpiowrite(sda_gpio, 0); - up_udelay(10); - stm32_gpiowrite(scl_gpio, 0); - up_udelay(10); - stm32_gpiowrite(scl_gpio, 1); - up_udelay(10); - stm32_gpiowrite(sda_gpio, 1); - up_udelay(10); - - /* Revert the GPIO configuration. */ - - stm32_unconfiggpio(sda_gpio); - stm32_unconfiggpio(scl_gpio); - - /* Re-init the port */ - - stm32_i2c_init(priv); - ret = OK; - -out: - - /* Release the port for re-use by other clients */ - - stm32_i2c_sem_post(dev); - return ret; -} -#endif /* CONFIG_I2C_RESET */ - #endif /* CONFIG_STM32F7_I2C1 || CONFIG_STM32F7_I2C2 || CONFIG_STM32F7_I2C3 */ diff --git a/arch/arm/src/stm32l4/stm32l4_i2c.c b/arch/arm/src/stm32l4/stm32l4_i2c.c index 18da3a2d268..892cde5f69e 100644 --- a/arch/arm/src/stm32l4/stm32l4_i2c.c +++ b/arch/arm/src/stm32l4/stm32l4_i2c.c @@ -307,7 +307,7 @@ static int stm32l4_i2c_reset(FAR struct i2c_master_s *dev); /* Device Structures, Instantiation */ -const struct i2c_ops_s stm32l4_i2c_ops = +static const struct i2c_ops_s stm32l4_i2c_ops = { .transfer = stm32l4_i2c_transfer #ifdef CONFIG_I2C_RESET @@ -329,7 +329,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c1_config = #endif }; -struct stm32l4_i2c_priv_s stm32l4_i2c1_priv = +static struct stm32l4_i2c_priv_s stm32l4_i2c1_priv = { .ops = &stm32l4_i2c_ops, .config = &stm32l4_i2c1_config, @@ -358,7 +358,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c2_config = #endif }; -struct stm32l4_i2c_priv_s stm32l4_i2c2_priv = +static struct stm32l4_i2c_priv_s stm32l4_i2c2_priv = { .ops = &stm32l4_i2c_ops, .config = &stm32l4_i2c2_config, @@ -387,7 +387,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c3_config = #endif }; -struct stm32l4_i2c_priv_s stm32l4_i2c3_priv = +static struct stm32l4_i2c_priv_s stm32l4_i2c3_priv = { .ops = &stm32l4_i2c_ops, .config = &stm32l4_i2c3_config, @@ -416,7 +416,7 @@ static const struct stm32l4_i2c_config_s stm32l4_i2c4_config = #endif }; -struct stm32l4_i2c_priv_s stm32l4_i2c4_priv = +static struct stm32l4_i2c_priv_s stm32l4_i2c4_priv = { .ops = &stm32l4_i2c_ops, .config = &stm32l4_i2c4_config, @@ -1831,7 +1831,7 @@ static int stm32l4_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg * dev - Device-specific state data * * Returned Value: - * Zero (OK) on success; a negated errno value on failure. + * Zero (OK) on success; negative value on failure. * ************************************************************************************/