From c67bb6d440fdd1b1f5349a4940b9f94333c4715e Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 26 Nov 2018 18:37:03 +0100 Subject: [PATCH] wifi: eswifi: Fix/clean TCP receive This patch adds support for blocking tcp receive (with timeout). This patch removes dedicated socket polling thread to use common eswifi workqueue instead. Signed-off-by: Loic Poulain --- drivers/wifi/eswifi/eswifi_offload.c | 195 ++++++++++++++------------- drivers/wifi/eswifi/eswifi_offload.h | 2 + 2 files changed, 105 insertions(+), 92 deletions(-) diff --git a/drivers/wifi/eswifi/eswifi_offload.c b/drivers/wifi/eswifi/eswifi_offload.c index 4512752524f..5770ecf3a82 100644 --- a/drivers/wifi/eswifi/eswifi_offload.c +++ b/drivers/wifi/eswifi/eswifi_offload.c @@ -20,14 +20,6 @@ LOG_MODULE_REGISTER(wifi_eswifi_offload); #include "eswifi.h" -#define ESWIFI_OFFLOAD_THREAD_STACK_SIZE 1024 -K_THREAD_STACK_MEMBER(eswifi_data_read_stack, ESWIFI_OFFLOAD_THREAD_STACK_SIZE); -struct k_thread data_read_thread; - -struct eswifi_offload { - struct eswifi_off_socket socket[ESWIFI_OFFLOAD_MAX_SOCKETS]; -}; - static int __select_socket(struct eswifi_dev *eswifi, u8_t idx) { int err; @@ -86,6 +78,65 @@ static int __read_data(struct eswifi_dev *eswifi, size_t len) return read; } +static inline +struct eswifi_dev *eswifi_socket_to_dev(struct eswifi_off_socket *socket) +{ + return CONTAINER_OF(socket - socket->index, struct eswifi_dev, socket); +} + +static void eswifi_off_read_work(struct k_work *work) +{ + struct eswifi_off_socket *socket; + struct eswifi_dev *eswifi; + struct net_pkt *pkt; + int err, len; + + LOG_DBG(""); + + socket = CONTAINER_OF(work, struct eswifi_off_socket, read_work); + eswifi = eswifi_socket_to_dev(socket); + + eswifi_lock(eswifi); + + if (socket->state != ESWIFI_SOCKET_STATE_CONNECTED) { + goto done; + } + + __select_socket(eswifi, socket->index); + + len = __read_data(eswifi, 1460); /* 1460 is max size */ + if (len <= 0 || !socket->recv_cb) { + goto done; + } + + LOG_DBG("payload sz = %d", len); + + pkt = net_pkt_get_reserve_rx(0, K_NO_WAIT); + if (!pkt) { + LOG_ERR("Cannot allocate rx packet"); + goto done; + } + + if (!net_pkt_append_all(pkt, len, eswifi->buf + AT_RSP_DELIMITER_LEN, + K_NO_WAIT)) { + LOG_WRN("Incomplete buffer copy"); + } + + socket->recv_cb(socket->context, pkt, 0, socket->user_data); + k_sem_give(&socket->read_sem); + k_yield(); + +done: + err = k_delayed_work_submit_to_queue(&eswifi->work_q, + &socket->read_work, + 500); + if (err) { + LOG_ERR("Rescheduling socket read error"); + } + + eswifi_unlock(eswifi); +} + static int eswifi_off_bind(struct net_context *context, const struct sockaddr *addr, socklen_t addrlen) @@ -123,15 +174,29 @@ static int eswifi_off_bind(struct net_context *context, static int eswifi_off_listen(struct net_context *context, int backlog) { + struct eswifi_off_socket *socket = context->offload_context; + struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface); + char *cmd = "P5=1\r"; + int err; + /* TODO */ LOG_ERR(""); - return -ENOTSUP; -} -static inline -struct eswifi_dev *eswifi_socket_to_dev(struct eswifi_off_socket *socket) -{ - return CONTAINER_OF(socket - socket->index, struct eswifi_dev, socket); + eswifi_lock(eswifi); + + __select_socket(eswifi, socket->index); + + /* Start TCP Server */ + err = eswifi_request(eswifi, cmd, strlen(cmd), eswifi->buf, + sizeof(eswifi->buf)); + if (err || !eswifi_is_buf_at_ok(eswifi->buf)) { + LOG_ERR("Unable to start TCP server"); + eswifi_unlock(eswifi); + return -EIO; + } + eswifi_unlock(eswifi); + + return -ENOTSUP; } static int __eswifi_off_connect(struct eswifi_dev *eswifi, @@ -172,7 +237,7 @@ static int __eswifi_off_connect(struct eswifi_dev *eswifi, err = eswifi_request(eswifi, eswifi->buf, strlen(eswifi->buf), eswifi->buf, sizeof(eswifi->buf)); if (err || !eswifi_is_buf_at_ok(eswifi->buf)) { - LOG_ERR("Unable to connect %s"); + LOG_ERR("Unable to connect"); return -EIO; } @@ -264,9 +329,8 @@ static int eswifi_off_connect(struct net_context *context, } static int eswifi_off_accept(struct net_context *context, - net_tcp_accept_cb_t cb, - s32_t timeout, - void *user_data) + net_tcp_accept_cb_t cb, s32_t timeout, + void *user_data) { /* TODO */ LOG_DBG(""); @@ -411,16 +475,28 @@ static int eswifi_off_recv(struct net_context *context, { struct eswifi_off_socket *socket = context->offload_context; struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface); + int err; + - /* TODO */ LOG_DBG(""); eswifi_lock(eswifi); socket->recv_cb = cb; socket->user_data = user_data; + k_sem_reset(&socket->read_sem); eswifi_unlock(eswifi); - return 0; + if (timeout == K_NO_WAIT) + return 0; + + err = k_sem_take(&socket->read_sem, timeout); + + /* Unregister cakkback */ + eswifi_lock(eswifi); + socket->recv_cb = NULL; + eswifi_unlock(eswifi); + + return err; } static int eswifi_off_put(struct net_context *context) @@ -440,6 +516,8 @@ static int eswifi_off_put(struct net_context *context) __select_socket(eswifi, socket->index); + k_delayed_work_cancel(&socket->read_work); + socket->context = NULL; socket->state = ESWIFI_SOCKET_STATE_NONE; @@ -500,6 +578,8 @@ static int eswifi_off_get(sa_family_t family, k_work_init(&socket->connect_work, eswifi_off_connect_work); k_work_init(&socket->send_work, eswifi_off_send_work); + k_delayed_work_init(&socket->read_work, eswifi_off_read_work); + k_sem_init(&socket->read_sem, 1, 1); err = __select_socket(eswifi, socket->index); if (err) { @@ -519,6 +599,9 @@ static int eswifi_off_get(sa_family_t family, return -EIO; } + k_delayed_work_submit_to_queue(&eswifi->work_q, &socket->read_work, + 500); + eswifi_unlock(eswifi); return 0; @@ -536,72 +619,6 @@ static struct net_offload eswifi_offload = { .put = eswifi_off_put, }; -static void eswifi_off_read_data(struct eswifi_dev *eswifi) -{ - int i; - - LOG_DBG(""); - - eswifi_lock(eswifi); - - if (!eswifi->iface) { /* not yet initialized */ - eswifi_unlock(eswifi); - return; - } - - for (i = 0; i < ESWIFI_OFFLOAD_MAX_SOCKETS; i++) { - struct eswifi_off_socket *socket = &eswifi->socket[i]; - struct net_pkt *pkt; - int err, len; - - if (socket->state != ESWIFI_SOCKET_STATE_CONNECTED) { - continue; - } - - err = __select_socket(eswifi, i); - if (err) { - continue; - } - - len = __read_data(eswifi, 1460); /* 1460 is max size */ - if (len <= 0 /*|| !socket->recv_cb*/) { - continue; - } - - LOG_DBG("payload sz = %d", len); - - pkt = net_pkt_get_reserve_rx(0, K_NO_WAIT); - if (!pkt) { - LOG_ERR("Cannot allocate rx packet"); - continue; - } - - if (!net_pkt_append_all(pkt, len, - eswifi->buf + AT_RSP_DELIMITER_LEN, - K_NO_WAIT)) { - LOG_WRN("Incomplete buffer copy"); - } - - if (!socket->recv_cb) { - net_pkt_unref(pkt); - continue; - } - socket->recv_cb(socket->context, pkt, 0, socket->user_data); - } - - eswifi_unlock(eswifi); -} - -static void eswifi_off_data_read_thread(void *p1) -{ - struct eswifi_dev *eswifi = p1; - - while (1) { - k_sleep(K_MSEC(500)); - eswifi_off_read_data(eswifi); - } -} - static int eswifi_off_enable_dhcp(struct eswifi_dev *eswifi) { char cmd[] = "C4=1\r"; @@ -649,12 +666,6 @@ int eswifi_offload_init(struct eswifi_dev *eswifi) eswifi->iface->if_dev->offload = &eswifi_offload; int err; - k_thread_create(&data_read_thread, eswifi_data_read_stack, - ESWIFI_OFFLOAD_THREAD_STACK_SIZE, - (k_thread_entry_t)&eswifi_off_data_read_thread, eswifi, - NULL, NULL, K_PRIO_COOP(CONFIG_WIFI_ESWIFI_THREAD_PRIO), - 0, K_NO_WAIT); - err = eswifi_off_enable_dhcp(eswifi); if (err) { LOG_ERR("Unable to configure dhcp"); diff --git a/drivers/wifi/eswifi/eswifi_offload.h b/drivers/wifi/eswifi/eswifi_offload.h index 887e4bc8380..99eb427d4e0 100644 --- a/drivers/wifi/eswifi/eswifi_offload.h +++ b/drivers/wifi/eswifi/eswifi_offload.h @@ -39,7 +39,9 @@ struct eswifi_off_socket { struct net_pkt *tx_pkt; struct k_work connect_work; struct k_work send_work; + struct k_delayed_work read_work; struct sockaddr peer_addr; + struct k_sem read_sem; }; #endif