drivers: modem: gsm: Use dedicated workq

The driver performs AT commands configurations using the
system workqueue, this can delay the workqueue by up to 6
seconds to wait for the modem replies, which isn't ideal.

This PR creates a dedicated workqueue for the gsm, and
provides a helper function to reschedule work items to the
gsm workqueue.

Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
This commit is contained in:
Yong Cong Sin 2021-12-28 22:25:27 +08:00 committed by Christopher Friedt
commit 522eff91e5
2 changed files with 37 additions and 15 deletions

View file

@ -40,6 +40,13 @@ config MODEM_GSM_RX_STACK_SIZE
help
Sets the stack size which will be used by the GSM RX thread.
config MODEM_GSM_WORKQ_STACK_SIZE
int "Size of the stack allocated for the dedicated gsm workqueue"
default 768
help
Sets the stack size which will be used by the dedicated GSM workqueue
thread.
config MODEM_GSM_INIT_PRIORITY
int "Init priority for the GSM modem driver"
default 42

View file

@ -31,6 +31,7 @@ LOG_MODULE_REGISTER(modem_gsm, CONFIG_MODEM_LOG_LEVEL);
#define GSM_CMD_AT_TIMEOUT K_SECONDS(2)
#define GSM_CMD_SETUP_TIMEOUT K_SECONDS(6)
#define GSM_RX_STACK_SIZE CONFIG_MODEM_GSM_RX_STACK_SIZE
#define GSM_WORKQ_STACK_SIZE CONFIG_MODEM_GSM_WORKQ_STACK_SIZE
#define GSM_RECV_MAX_BUF 30
#define GSM_RECV_BUF_SIZE 128
#define GSM_ATTACH_RETRY_DELAY_MSEC 1000
@ -96,11 +97,18 @@ static struct gsm_modem {
NET_BUF_POOL_DEFINE(gsm_recv_pool, GSM_RECV_MAX_BUF, GSM_RECV_BUF_SIZE,
0, NULL);
K_KERNEL_STACK_DEFINE(gsm_rx_stack, GSM_RX_STACK_SIZE);
K_THREAD_STACK_DEFINE(gsm_workq_stack, GSM_WORKQ_STACK_SIZE);
struct k_thread gsm_rx_thread;
static struct k_work_q gsm_workq;
static struct k_work_delayable rssi_work_handle;
static struct gsm_ppp_modem_info minfo;
static inline int gsm_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay)
{
return k_work_reschedule_for_queue(&gsm_workq, dwork, delay);
}
#if defined(CONFIG_MODEM_GSM_ENABLE_CESQ_RSSI)
/* helper macro to keep readability */
#define ATOI(s_, value_, desc_) modem_atoi(s_, value_, desc_, __func__)
@ -580,9 +588,10 @@ static void rssi_handler(struct k_work *work)
#if defined(CONFIG_GSM_MUX)
#if defined(CONFIG_MODEM_CELL_INFO)
(void) gsm_query_cellinfo(&gsm);
(void)gsm_query_cellinfo(&gsm);
#endif
k_work_reschedule(&rssi_work_handle, K_SECONDS(CONFIG_MODEM_GSM_RSSI_POLLING_PERIOD));
(void)gsm_work_reschedule(&rssi_work_handle,
K_SECONDS(CONFIG_MODEM_GSM_RSSI_POLLING_PERIOD));
#endif
}
@ -611,7 +620,7 @@ static void gsm_finalize_connection(struct gsm_modem *gsm)
if (ret < 0) {
LOG_ERR("modem setup returned %d, %s",
ret, "retrying...");
(void)k_work_reschedule(&gsm->gsm_configure_work,
(void)gsm_work_reschedule(&gsm->gsm_configure_work,
K_SECONDS(1));
return;
}
@ -633,7 +642,7 @@ static void gsm_finalize_connection(struct gsm_modem *gsm)
LOG_ERR("modem setup returned %d, %s",
ret, "retrying...");
(void)k_work_reschedule(&gsm->gsm_configure_work,
(void)gsm_work_reschedule(&gsm->gsm_configure_work,
K_SECONDS(1));
return;
}
@ -647,14 +656,14 @@ static void gsm_finalize_connection(struct gsm_modem *gsm)
if (ret < 0) {
LOG_DBG("modem setup returned %d, %s",
ret, "retrying...");
(void)k_work_reschedule(&gsm->gsm_configure_work, K_SECONDS(1));
(void)gsm_work_reschedule(&gsm->gsm_configure_work, K_SECONDS(1));
return;
}
ret = gsm_query_modem_info(gsm);
if (ret < 0) {
LOG_DBG("Unable to query modem information %d", ret);
(void)k_work_reschedule(&gsm->gsm_configure_work, K_SECONDS(1));
(void)gsm_work_reschedule(&gsm->gsm_configure_work, K_SECONDS(1));
return;
}
@ -681,7 +690,7 @@ attaching:
LOG_DBG("Not attached, %s", "retrying...");
(void)k_work_reschedule(&gsm->gsm_configure_work,
(void)gsm_work_reschedule(&gsm->gsm_configure_work,
K_MSEC(GSM_ATTACH_RETRY_DELAY_MSEC));
return;
}
@ -704,13 +713,13 @@ attaching:
LOG_DBG("Not valid RSSI, %s", "retrying...");
if (gsm->rssi_retries-- > 0) {
(void)k_work_reschedule(&gsm->gsm_configure_work,
(void)gsm_work_reschedule(&gsm->gsm_configure_work,
K_MSEC(GSM_RSSI_RETRY_DELAY_MSEC));
return;
}
}
#if defined(CONFIG_MODEM_CELL_INFO)
(void) gsm_query_cellinfo(gsm);
(void)gsm_query_cellinfo(gsm);
#endif
}
@ -725,7 +734,7 @@ attaching:
if (ret < 0) {
LOG_DBG("modem setup returned %d, %s",
ret, "retrying...");
(void)k_work_reschedule(&gsm->gsm_configure_work, K_SECONDS(1));
(void)gsm_work_reschedule(&gsm->gsm_configure_work, K_SECONDS(1));
return;
}
@ -821,7 +830,7 @@ static int mux_enable(struct gsm_modem *gsm)
static void mux_setup_next(struct gsm_modem *gsm)
{
(void)k_work_reschedule(&gsm->gsm_configure_work, K_MSEC(1));
(void)gsm_work_reschedule(&gsm->gsm_configure_work, K_MSEC(1));
}
static void mux_attach_cb(const struct device *mux, int dlci_address,
@ -976,7 +985,7 @@ static void gsm_configure(struct k_work *work)
if (ret < 0) {
LOG_DBG("modem not ready %d", ret);
(void)k_work_reschedule(&gsm->gsm_configure_work, K_NO_WAIT);
(void)gsm_work_reschedule(&gsm->gsm_configure_work, K_NO_WAIT);
return;
}
@ -990,7 +999,7 @@ static void gsm_configure(struct k_work *work)
gsm->mux_enabled = true;
} else {
gsm->mux_enabled = false;
(void)k_work_reschedule(&gsm->gsm_configure_work,
(void)gsm_work_reschedule(&gsm->gsm_configure_work,
K_NO_WAIT);
return;
}
@ -1004,7 +1013,7 @@ static void gsm_configure(struct k_work *work)
k_work_init_delayable(&gsm->gsm_configure_work,
mux_setup);
(void)k_work_reschedule(&gsm->gsm_configure_work,
(void)gsm_work_reschedule(&gsm->gsm_configure_work,
K_NO_WAIT);
return;
}
@ -1026,7 +1035,7 @@ void gsm_ppp_start(const struct device *dev)
}
k_work_init_delayable(&gsm->gsm_configure_work, gsm_configure);
(void)k_work_reschedule(&gsm->gsm_configure_work, K_NO_WAIT);
(void)gsm_work_reschedule(&gsm->gsm_configure_work, K_NO_WAIT);
#if defined(CONFIG_GSM_MUX)
k_work_init_delayable(&rssi_work_handle, rssi_handler);
@ -1144,6 +1153,12 @@ static int gsm_init(const struct device *dev)
gsm, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
k_thread_name_set(&gsm_rx_thread, "gsm_rx");
/* initialize the work queue */
k_work_queue_init(&gsm_workq);
k_work_queue_start(&gsm_workq, gsm_workq_stack, K_THREAD_STACK_SIZEOF(gsm_workq_stack),
K_PRIO_COOP(7), NULL);
k_thread_name_set(&gsm_workq.thread, "gsm_workq");
gsm->iface = ppp_net_if();
if (!gsm->iface) {
LOG_ERR("Couldn't find ppp net_if!");