diff --git a/.github/workflows/check-pr.yml b/.github/workflows/check-commits.yml similarity index 59% rename from .github/workflows/check-pr.yml rename to .github/workflows/check-commits.yml index 1c7569b2f0..d294f37836 100644 --- a/.github/workflows/check-pr.yml +++ b/.github/workflows/check-commits.yml @@ -1,18 +1,8 @@ -name: check-pr +name: check-commits on: pull_request: - types: [opened, reopened, labeled, unlabeled, synchronize] - pull_request_review: - types: [submitted, dismissed] + types: [opened, reopened, synchronize] jobs: - check-labels: - runs-on: ubuntu-latest - steps: - - uses: RIOT-OS/check-labels-action@v1.0.0 - with: - access_token: ${{ secrets.GITHUB_TOKEN }} - unset_labels: 'CI: needs squashing,State: waiting for CI update,State: waiting for other PR,Process: blocked by feature freeze' - cond_labels: '(Process: needs >1 ACK,review.approvals>1),(Area: RDM,review.approvals>2)' check-commits: runs-on: ubuntu-latest if: ${{ github.base_ref }} diff --git a/.github/workflows/check-labels.yml b/.github/workflows/check-labels.yml new file mode 100644 index 0000000000..37d9dcd3ee --- /dev/null +++ b/.github/workflows/check-labels.yml @@ -0,0 +1,15 @@ +name: check-labels +on: + pull_request: + types: [opened, reopened, labeled, unlabeled] + pull_request_review: + types: [submitted, dismissed] +jobs: + check-labels: + runs-on: ubuntu-latest + steps: + - uses: RIOT-OS/check-labels-action@v1.0.0 + with: + access_token: ${{ secrets.GITHUB_TOKEN }} + unset_labels: 'CI: needs squashing,State: waiting for CI update,State: waiting for other PR,Process: blocked by feature freeze' + cond_labels: '(Process: needs >1 ACK,review.approvals>1),(Area: RDM,review.approvals>2)' diff --git a/drivers/include/slipdev.h b/drivers/include/slipdev.h index 85a467aa4e..332b4578ec 100644 --- a/drivers/include/slipdev.h +++ b/drivers/include/slipdev.h @@ -72,6 +72,14 @@ enum { * @brief Device writes received data to stdin */ SLIPDEV_STATE_STDIN, + /** + * @brief Device is in standby, will wake up when sending data + */ + SLIPDEV_STATE_STANDBY, + /** + * @brief Device is in sleep mode + */ + SLIPDEV_STATE_SLEEP, }; /** @} */ diff --git a/drivers/slipdev/slipdev.c b/drivers/slipdev/slipdev.c index 8a042cc155..1b15c9e6f0 100644 --- a/drivers/slipdev/slipdev.c +++ b/drivers/slipdev/slipdev.c @@ -32,6 +32,8 @@ #include "mutex.h" #include "stdio_uart.h" +static int _check_state(slipdev_t *dev); + static inline void slipdev_lock(void) { if (IS_USED(MODULE_SLIPDEV_STDIO)) { @@ -74,6 +76,23 @@ check_end: } } +static void _poweron(slipdev_t *dev) +{ + if ((dev->state != SLIPDEV_STATE_STANDBY) || + (dev->state != SLIPDEV_STATE_SLEEP)) { + return; + } + + dev->state = 0; + uart_init(dev->config.uart, dev->config.baudrate, _slip_rx_cb, dev); +} + +static inline void _poweroff(slipdev_t *dev, uint8_t state) +{ + uart_poweroff(dev->config.uart); + dev->state = state; +} + static int _init(netdev_t *netdev) { slipdev_t *dev = (slipdev_t *)netdev; @@ -150,10 +169,33 @@ unsigned slipdev_unstuff_readbyte(uint8_t *buf, uint8_t byte, bool *escaped) return res; } +static int _check_state(slipdev_t *dev) +{ + /* power states not supported when multiplexing stdio */ + if (IS_USED(MODULE_SLIPDEV_STDIO)) { + return 0; + } + + /* discard data when interface is in SLEEP mode */ + if (dev->state == SLIPDEV_STATE_SLEEP) { + return -ENETDOWN; + } + + /* sending data wakes the interface from STANDBY */ + if (dev->state == SLIPDEV_STATE_STANDBY) { + _poweron(dev); + } + + return 0; +} + static int _send(netdev_t *netdev, const iolist_t *iolist) { slipdev_t *dev = (slipdev_t *)netdev; - int bytes = 0; + int bytes = _check_state(dev); + if (bytes) { + return bytes; + } DEBUG("slipdev: sending iolist\n"); slipdev_lock(); @@ -233,6 +275,45 @@ static void _isr(netdev_t *netdev) } } +#if !IS_USED(MODULE_SLIPDEV_STDIO) +static int _set_state(slipdev_t *dev, netopt_state_t state) +{ + if (IS_USED(MODULE_SLIPDEV_STDIO)) { + return -ENOTSUP; + } + + switch (state) { + case NETOPT_STATE_STANDBY: + _poweroff(dev, SLIPDEV_STATE_STANDBY); + break; + case NETOPT_STATE_SLEEP: + _poweroff(dev, SLIPDEV_STATE_SLEEP); + break; + case NETOPT_STATE_IDLE: + _poweron(dev); + break; + default: + return -ENOTSUP; + } + + return sizeof(netopt_state_t); +} + +static int _set(netdev_t *netdev, netopt_t opt, const void *value, size_t max_len) +{ + (void)max_len; + + slipdev_t *dev = (slipdev_t *)netdev; + switch (opt) { + case NETOPT_STATE: + assert(max_len <= sizeof(netopt_state_t)); + return _set_state(dev, *((const netopt_state_t *)value)); + default: + return -ENOTSUP; + } +} +#endif /* !MODULE_SLIPDEV_STDIO */ + static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len) { (void)netdev; @@ -262,7 +343,11 @@ static const netdev_driver_t slip_driver = { .init = _init, .isr = _isr, .get = _get, +#if IS_USED(MODULE_SLIPDEV_STDIO) .set = netdev_set_notsup, +#else + .set = _set, +#endif }; void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params, uint8_t index) diff --git a/sys/net/gnrc/pktbuf/include/pktbuf_internal.h b/sys/net/gnrc/pktbuf/include/pktbuf_internal.h index c48db7b82d..029c39ee56 100644 --- a/sys/net/gnrc/pktbuf/include/pktbuf_internal.h +++ b/sys/net/gnrc/pktbuf/include/pktbuf_internal.h @@ -41,15 +41,6 @@ extern "C" { */ extern mutex_t gnrc_pktbuf_mutex; -#if IS_USED(MODULE_GNRC_PKTBUF_STATIC) || DOXYGEN -/** - * @brief The actual static buffer used when module gnrc_pktbuf_static is used - * - * @warning This is an internal buffer and should not be touched by external code - */ -extern uint8_t *gnrc_pktbuf_static_buf; -#endif - /** * @brief Check if the given pointer is indeed part of the packet buffer * @@ -61,16 +52,7 @@ extern uint8_t *gnrc_pktbuf_static_buf; * the packet buffer * @retval false @p ptr does not point to data in the packet buffer */ -static inline bool gnrc_pktbuf_contains(void *ptr) -{ -#if IS_USED(MODULE_GNRC_PKTBUF_STATIC) - return ((uintptr_t)ptr >= (uintptr_t)gnrc_pktbuf_static_buf) && - ((uintptr_t)ptr < (uintptr_t)gnrc_pktbuf_static_buf + CONFIG_GNRC_PKTBUF_SIZE); -#else - (void)ptr; - return true; -#endif -} +bool gnrc_pktbuf_contains(void *ptr); /** * @brief Release an internal buffer diff --git a/sys/net/gnrc/pktbuf_malloc/gnrc_pktbuf_malloc.c b/sys/net/gnrc/pktbuf_malloc/gnrc_pktbuf_malloc.c index 8decd931c5..dd5e38fe9f 100644 --- a/sys/net/gnrc/pktbuf_malloc/gnrc_pktbuf_malloc.c +++ b/sys/net/gnrc/pktbuf_malloc/gnrc_pktbuf_malloc.c @@ -288,4 +288,12 @@ void gnrc_pktbuf_free_internal(void *data, size_t size) _free(data); } +bool gnrc_pktbuf_contains(void *ptr) +{ + (void)ptr; + /* tracking the memory areas malloced is to expensive, so this function + * only is useful with gnrc_pktbuf_static */ + return true; +} + /** @} */ diff --git a/sys/net/gnrc/pktbuf_static/gnrc_pktbuf_static.c b/sys/net/gnrc/pktbuf_static/gnrc_pktbuf_static.c index 041d2e9a12..5ac2708886 100644 --- a/sys/net/gnrc/pktbuf_static/gnrc_pktbuf_static.c +++ b/sys/net/gnrc/pktbuf_static/gnrc_pktbuf_static.c @@ -18,9 +18,10 @@ #include #include #include +#include #include -#include #include +#include #include #include "mutex.h" @@ -45,11 +46,9 @@ #define CANARY 0x55 -/* The static buffer needs to be aligned to word size, so that its start - * address can be casted to `_unused_t *` safely. Just allocating an array of - * (word sized) uintptr_t is a trivial way to do this */ -static uintptr_t _pktbuf_buf[CONFIG_GNRC_PKTBUF_SIZE / sizeof(uintptr_t)]; -uint8_t *gnrc_pktbuf_static_buf = (uint8_t *)_pktbuf_buf; +static alignas(sizeof(_unused_t)) uint8_t _static_buf[CONFIG_GNRC_PKTBUF_SIZE]; +static_assert((CONFIG_GNRC_PKTBUF_SIZE % sizeof(_unused_t)) == 0, + "CONFIG_GNRC_PKTBUF_SIZE has to be a multiple of 8"); static _unused_t *_first_unused; #ifdef DEVELHELP @@ -91,11 +90,13 @@ void gnrc_pktbuf_init(void) { mutex_lock(&gnrc_pktbuf_mutex); if (CONFIG_GNRC_PKTBUF_CHECK_USE_AFTER_FREE) { - memset(_pktbuf_buf, CANARY, sizeof(_pktbuf_buf)); + memset(_static_buf, CANARY, sizeof(_static_buf)); } - _first_unused = (_unused_t *)_pktbuf_buf; + /* Silence false -Wcast-align: _static_buf has qualifier + * `alignas(_unused_t)`, so it is guaranteed to be safe */ + _first_unused = (_unused_t *)(uintptr_t)_static_buf; _first_unused->next = NULL; - _first_unused->size = sizeof(_pktbuf_buf); + _first_unused->size = sizeof(_static_buf); mutex_unlock(&gnrc_pktbuf_mutex); } @@ -282,12 +283,12 @@ void gnrc_pktbuf_stats(void) { #ifdef MODULE_OD _unused_t *ptr = _first_unused; - uint8_t *chunk = &gnrc_pktbuf_static_buf[0]; + uint8_t *chunk = &_static_buf[0]; int count = 0; printf("packet buffer: first byte: %p, last byte: %p (size: %u)\n", - (void *)&gnrc_pktbuf_static_buf[0], - (void *)&gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE], + (void *)&_static_buf[0], + (void *)&_static_buf[CONFIG_GNRC_PKTBUF_SIZE], CONFIG_GNRC_PKTBUF_SIZE); printf(" position of last byte used: %" PRIu16 "\n", max_byte_count); if (ptr == NULL) { /* packet buffer is completely full */ @@ -313,8 +314,8 @@ void gnrc_pktbuf_stats(void) ptr = ptr->next; } - if (chunk <= &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE - 1]) { - _print_chunk(chunk, &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE] - chunk, count); + if (chunk <= &_static_buf[CONFIG_GNRC_PKTBUF_SIZE - 1]) { + _print_chunk(chunk, &_static_buf[CONFIG_GNRC_PKTBUF_SIZE] - chunk, count); } #else DEBUG("pktbuf: needs od module\n"); @@ -325,8 +326,8 @@ void gnrc_pktbuf_stats(void) #ifdef TEST_SUITES bool gnrc_pktbuf_is_empty(void) { - return ((uintptr_t)_first_unused == (uintptr_t)gnrc_pktbuf_static_buf) && - (_first_unused->size == sizeof(_pktbuf_buf)); + return ((uintptr_t)_first_unused == (uintptr_t)_static_buf) && + (_first_unused->size == sizeof(_static_buf)); } bool gnrc_pktbuf_is_sane(void) @@ -336,8 +337,8 @@ bool gnrc_pktbuf_is_sane(void) /* Invariants of this implementation: * - the head of _unused_t list is _first_unused * - if _unused_t list is empty the packet buffer is full and _first_unused is NULL - * - forall ptr_in _unused_t list: &gnrc_pktbuf_static_buf[0] < ptr - * && ptr < &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE] + * - forall ptr_in _unused_t list: &_static_buf[0] < ptr + * && ptr < &_static_buf[CONFIG_GNRC_PKTBUF_SIZE] * - forall ptr in _unused_t list: ptr->next == NULL || ptr < ptr->next * - forall ptr in _unused_t list: (ptr->next != NULL && ptr->size <= (ptr->next - ptr)) || * (ptr->next == NULL @@ -345,14 +346,14 @@ bool gnrc_pktbuf_is_sane(void) */ while (ptr) { - if ((&gnrc_pktbuf_static_buf[0] >= (uint8_t *)ptr) - && ((uint8_t *)ptr >= &gnrc_pktbuf_static_buf[CONFIG_GNRC_PKTBUF_SIZE])) { + if ((&_static_buf[0] >= (uint8_t *)ptr) + && ((uint8_t *)ptr >= &_static_buf[CONFIG_GNRC_PKTBUF_SIZE])) { return false; } if ((ptr->next != NULL) && (ptr >= ptr->next)) { return false; } - size_t pos_in_buf = (uint8_t *)ptr - &gnrc_pktbuf_static_buf[0]; + size_t pos_in_buf = (uint8_t *)ptr - &_static_buf[0]; if (((ptr->next == NULL) || (ptr->size > (size_t)((uint8_t *)(ptr->next) - (uint8_t *)ptr))) && ((ptr->next != NULL) || (ptr->size != CONFIG_GNRC_PKTBUF_SIZE - pos_in_buf))) { return false; @@ -416,7 +417,7 @@ static void *_pktbuf_alloc(size_t size) * We cast to uintptr_t as intermediate step to silence -Wcast-align */ _unused_t *new = (_unused_t *)((uintptr_t)ptr + size); - if (((((uint8_t *)new) - &(gnrc_pktbuf_static_buf[0])) + sizeof(_unused_t)) + if (((((uint8_t *)new) - &(_static_buf[0])) + sizeof(_unused_t)) > CONFIG_GNRC_PKTBUF_SIZE) { /* content of new would exceed packet buffer size so set to NULL */ _first_unused = NULL; @@ -431,7 +432,7 @@ static void *_pktbuf_alloc(size_t size) new->size = ptr->size - size; } #ifdef DEVELHELP - uint16_t last_byte = (uint16_t)((((uint8_t *)ptr) + size) - &(gnrc_pktbuf_static_buf[0])); + uint16_t last_byte = (uint16_t)((((uint8_t *)ptr) + size) - &(_static_buf[0])); if (last_byte > max_byte_count) { max_byte_count = last_byte; } @@ -489,7 +490,7 @@ void gnrc_pktbuf_free_internal(void *data, size_t size) new->size = _align(size); /* calculate number of bytes between new _unused_t chunk and end of packet * buffer */ - bytes_at_end = ((&gnrc_pktbuf_static_buf[0] + CONFIG_GNRC_PKTBUF_SIZE) + bytes_at_end = ((&_static_buf[0] + CONFIG_GNRC_PKTBUF_SIZE) - (((uint8_t *)new) + new->size)); if (bytes_at_end < sizeof(_unused_t)) { /* new is very last segment and there is a little bit of memory left @@ -510,4 +511,12 @@ void gnrc_pktbuf_free_internal(void *data, size_t size) } } +bool gnrc_pktbuf_contains(void *ptr) +{ + const uintptr_t start = (uintptr_t)_static_buf; + const uintptr_t end = start + sizeof(_static_buf); + uintptr_t pos = (uintptr_t)ptr; + return ((pos >= start) && (pos < end)); +} + /** @} */