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 <loic.poulain@linaro.org>
This commit is contained in:
Loic Poulain 2018-11-26 18:37:03 +01:00 committed by Anas Nashif
commit c67bb6d440
2 changed files with 105 additions and 92 deletions

View file

@ -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");

View file

@ -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