net: wwan: iosm: release data channel in case no active IP session
authorM Chetan Kumar <m.chetan.kumar@linux.intel.com>
Thu, 9 Dec 2021 14:32:28 +0000 (20:02 +0530)
committerJakub Kicinski <kuba@kernel.org>
Sat, 11 Dec 2021 04:53:56 +0000 (20:53 -0800)
If there is no active IP session (interface up & running) then
release the data channel.

Use nr_sessions variable to track current active IP sessions.
If the count drops to 0, then send pipe close ctrl message to
release the data channel.

Signed-off-by: M Chetan Kumar <m.chetan.kumar@linux.intel.com>
Reviewed-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/wwan/iosm/iosm_ipc_imem.c
drivers/net/wwan/iosm/iosm_ipc_mux.c
drivers/net/wwan/iosm/iosm_ipc_mux.h
drivers/net/wwan/iosm/iosm_ipc_mux_codec.c

index fb4e58b..f9e8e0e 100644 (file)
@@ -134,7 +134,6 @@ static int ipc_imem_setup_cp_mux_cap_init(struct iosm_imem *ipc_imem,
         * for channel alloc function.
         */
        cfg->instance_id = IPC_MEM_MUX_IP_CH_IF_ID;
-       cfg->nr_sessions = IPC_MEM_MUX_IP_SESSION_ENTRIES;
 
        return 0;
 }
index c1c77ce..8e66ffe 100644 (file)
@@ -97,7 +97,7 @@ static bool ipc_mux_session_open(struct iosm_mux *ipc_mux,
 
        /* Search for a free session interface id. */
        if_id = le32_to_cpu(session_open->if_id);
-       if (if_id < 0 || if_id >= ipc_mux->nr_sessions) {
+       if (if_id < 0 || if_id >= IPC_MEM_MUX_IP_SESSION_ENTRIES) {
                dev_err(ipc_mux->dev, "invalid interface id=%d", if_id);
                return false;
        }
@@ -129,6 +129,7 @@ static bool ipc_mux_session_open(struct iosm_mux *ipc_mux,
 
        /* Save and return the assigned if id. */
        session_open->if_id = cpu_to_le32(if_id);
+       ipc_mux->nr_sessions++;
 
        return true;
 }
@@ -151,7 +152,7 @@ static void ipc_mux_session_close(struct iosm_mux *ipc_mux,
        /* Copy the session interface id. */
        if_id = le32_to_cpu(msg->if_id);
 
-       if (if_id < 0 || if_id >= ipc_mux->nr_sessions) {
+       if (if_id < 0 || if_id >= IPC_MEM_MUX_IP_SESSION_ENTRIES) {
                dev_err(ipc_mux->dev, "invalid session id %d", if_id);
                return;
        }
@@ -170,6 +171,7 @@ static void ipc_mux_session_close(struct iosm_mux *ipc_mux,
        ipc_mux->session[if_id].flow_ctl_mask = 0;
 
        ipc_mux_session_reset(ipc_mux, if_id);
+       ipc_mux->nr_sessions--;
 }
 
 static void ipc_mux_channel_close(struct iosm_mux *ipc_mux,
@@ -178,7 +180,7 @@ static void ipc_mux_channel_close(struct iosm_mux *ipc_mux,
        int i;
 
        /* Free pending session UL packet. */
-       for (i = 0; i < ipc_mux->nr_sessions; i++)
+       for (i = 0; i < IPC_MEM_MUX_IP_SESSION_ENTRIES; i++)
                if (ipc_mux->session[i].wwan)
                        ipc_mux_session_reset(ipc_mux, i);
 
@@ -244,6 +246,11 @@ static int ipc_mux_schedule(struct iosm_mux *ipc_mux, union mux_msg *msg)
                        /* Release an IP session. */
                        ipc_mux->event = MUX_E_MUX_SESSION_CLOSE;
                        ipc_mux_session_close(ipc_mux, &msg->session_close);
+                       if (!ipc_mux->nr_sessions) {
+                               ipc_mux->event = MUX_E_MUX_CHANNEL_CLOSE;
+                               ipc_mux_channel_close(ipc_mux,
+                                                     &msg->channel_close);
+                       }
                        ret = ipc_mux->channel_id;
                        goto out;
 
@@ -281,7 +288,6 @@ struct iosm_mux *ipc_mux_init(struct ipc_mux_config *mux_cfg,
 
        ipc_mux->protocol = mux_cfg->protocol;
        ipc_mux->ul_flow = mux_cfg->ul_flow;
-       ipc_mux->nr_sessions = mux_cfg->nr_sessions;
        ipc_mux->instance_id = mux_cfg->instance_id;
        ipc_mux->wwan_q_offset = 0;
 
@@ -340,7 +346,7 @@ static void ipc_mux_restart_tx_for_all_sessions(struct iosm_mux *ipc_mux)
        struct mux_session *session;
        int idx;
 
-       for (idx = 0; idx < ipc_mux->nr_sessions; idx++) {
+       for (idx = 0; idx < IPC_MEM_MUX_IP_SESSION_ENTRIES; idx++) {
                session = &ipc_mux->session[idx];
 
                if (!session->wwan)
@@ -365,7 +371,7 @@ static void ipc_mux_stop_netif_for_all_sessions(struct iosm_mux *ipc_mux)
        struct mux_session *session;
        int idx;
 
-       for (idx = 0; idx < ipc_mux->nr_sessions; idx++) {
+       for (idx = 0; idx < IPC_MEM_MUX_IP_SESSION_ENTRIES; idx++) {
                session = &ipc_mux->session[idx];
 
                if (!session->wwan)
@@ -387,7 +393,7 @@ void ipc_mux_check_n_restart_tx(struct iosm_mux *ipc_mux)
 
 int ipc_mux_get_max_sessions(struct iosm_mux *ipc_mux)
 {
-       return ipc_mux ? ipc_mux->nr_sessions : -EFAULT;
+       return ipc_mux ? IPC_MEM_MUX_IP_SESSION_ENTRIES : -EFAULT;
 }
 
 enum ipc_mux_protocol ipc_mux_get_active_protocol(struct iosm_mux *ipc_mux)
@@ -435,9 +441,11 @@ void ipc_mux_deinit(struct iosm_mux *ipc_mux)
                return;
        ipc_mux_stop_netif_for_all_sessions(ipc_mux);
 
-       channel_close = &mux_msg.channel_close;
-       channel_close->event = MUX_E_MUX_CHANNEL_CLOSE;
-       ipc_mux_schedule(ipc_mux, &mux_msg);
+       if (ipc_mux->state == MUX_S_ACTIVE) {
+               channel_close = &mux_msg.channel_close;
+               channel_close->event = MUX_E_MUX_CHANNEL_CLOSE;
+               ipc_mux_schedule(ipc_mux, &mux_msg);
+       }
 
        /* Empty the ADB free list. */
        free_list = &ipc_mux->ul_adb.free_list;
index ddd2cd0..88debaa 100644 (file)
@@ -278,7 +278,6 @@ struct iosm_mux {
 struct ipc_mux_config {
        enum ipc_mux_protocol protocol;
        enum ipc_mux_ul_flow ul_flow;
-       int nr_sessions;
        int instance_id;
 };
 
index bdb2d32..40fb54a 100644 (file)
@@ -175,7 +175,7 @@ static int ipc_mux_dl_dlcmds_decode_process(struct iosm_mux *ipc_mux,
        switch (le32_to_cpu(cmdh->command_type)) {
        case MUX_LITE_CMD_FLOW_CTL:
 
-               if (cmdh->if_id >= ipc_mux->nr_sessions) {
+               if (cmdh->if_id >= IPC_MEM_MUX_IP_SESSION_ENTRIES) {
                        dev_err(ipc_mux->dev, "if_id [%d] not valid",
                                cmdh->if_id);
                        return -EINVAL; /* No session interface id. */
@@ -307,13 +307,13 @@ static void ipc_mux_dl_fcth_decode(struct iosm_mux *ipc_mux,
        }
 
        if_id = fct->if_id;
-       if (if_id >= ipc_mux->nr_sessions) {
+       if (if_id >= IPC_MEM_MUX_IP_SESSION_ENTRIES) {
                dev_err(ipc_mux->dev, "not supported if_id: %d", if_id);
                return;
        }
 
        /* Is the session active ? */
-       if_id = array_index_nospec(if_id, ipc_mux->nr_sessions);
+       if_id = array_index_nospec(if_id, IPC_MEM_MUX_IP_SESSION_ENTRIES);
        wwan = ipc_mux->session[if_id].wwan;
        if (!wwan) {
                dev_err(ipc_mux->dev, "session Net ID is NULL");
@@ -355,13 +355,13 @@ static void ipc_mux_dl_adgh_decode(struct iosm_mux *ipc_mux,
        }
 
        if_id = adgh->if_id;
-       if (if_id >= ipc_mux->nr_sessions) {
+       if (if_id >= IPC_MEM_MUX_IP_SESSION_ENTRIES) {
                dev_err(ipc_mux->dev, "invalid if_id while decoding %d", if_id);
                return;
        }
 
        /* Is the session active ? */
-       if_id = array_index_nospec(if_id, ipc_mux->nr_sessions);
+       if_id = array_index_nospec(if_id, IPC_MEM_MUX_IP_SESSION_ENTRIES);
        wwan = ipc_mux->session[if_id].wwan;
        if (!wwan) {
                dev_err(ipc_mux->dev, "session Net ID is NULL");
@@ -538,7 +538,7 @@ static void ipc_mux_stop_tx_for_all_sessions(struct iosm_mux *ipc_mux)
        struct mux_session *session;
        int idx;
 
-       for (idx = 0; idx < ipc_mux->nr_sessions; idx++) {
+       for (idx = 0; idx < IPC_MEM_MUX_IP_SESSION_ENTRIES; idx++) {
                session = &ipc_mux->session[idx];
 
                if (!session->wwan)
@@ -563,7 +563,7 @@ static bool ipc_mux_lite_send_qlt(struct iosm_mux *ipc_mux)
        qlt_size = offsetof(struct ipc_mem_lite_gen_tbl, vfl) +
                   MUX_QUEUE_LEVEL * sizeof(struct mux_lite_vfl);
 
-       for (i = 0; i < ipc_mux->nr_sessions; i++) {
+       for (i = 0; i < IPC_MEM_MUX_IP_SESSION_ENTRIES; i++) {
                session = &ipc_mux->session[i];
 
                if (!session->wwan || session->flow_ctl_mask)
@@ -777,13 +777,13 @@ bool ipc_mux_ul_data_encode(struct iosm_mux *ipc_mux)
 
        ipc_mux->adb_prep_ongoing = true;
 
-       for (i = 0; i < ipc_mux->nr_sessions; i++) {
+       for (i = 0; i < IPC_MEM_MUX_IP_SESSION_ENTRIES; i++) {
                session_id = ipc_mux->rr_next_session;
                session = &ipc_mux->session[session_id];
 
                /* Go to next handle rr_next_session overflow */
                ipc_mux->rr_next_session++;
-               if (ipc_mux->rr_next_session >= ipc_mux->nr_sessions)
+               if (ipc_mux->rr_next_session >= IPC_MEM_MUX_IP_SESSION_ENTRIES)
                        ipc_mux->rr_next_session = 0;
 
                if (!session->wwan || session->flow_ctl_mask ||