}
 
 static int chcr_init_tcb_fields(struct chcr_ktls_info *tx_info);
+static void clear_conn_resources(struct chcr_ktls_info *tx_info);
 /*
  * chcr_ktls_save_keys: calculate and save crypto keys.
  * @tx_info - driver specific tls info.
                                chcr_get_ktls_tx_context(tls_ctx);
        struct chcr_ktls_info *tx_info = tx_ctx->chcr_info;
        struct ch_ktls_port_stats_debug *port_stats;
+       struct chcr_ktls_uld_ctx *u_ctx;
 
        if (!tx_info)
                return;
 
+       u_ctx = tx_info->adap->uld[CXGB4_ULD_KTLS].handle;
+       if (u_ctx && u_ctx->detach)
+               return;
        /* clear l2t entry */
        if (tx_info->l2te)
                cxgb4_l2t_release(tx_info->l2te);
        if (tx_info->tid != -1) {
                cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
                                 tx_info->tid, tx_info->ip_family);
+
+               xa_erase(&u_ctx->tid_list, tx_info->tid);
        }
 
        port_stats = &tx_info->adap->ch_ktls_stats.ktls_port[tx_info->port_id];
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct ch_ktls_port_stats_debug *port_stats;
        struct chcr_ktls_ofld_ctx_tx *tx_ctx;
+       struct chcr_ktls_uld_ctx *u_ctx;
        struct chcr_ktls_info *tx_info;
        struct dst_entry *dst;
        struct adapter *adap;
        adap = pi->adapter;
        port_stats = &adap->ch_ktls_stats.ktls_port[pi->port_id];
        atomic64_inc(&port_stats->ktls_tx_connection_open);
+       u_ctx = adap->uld[CXGB4_ULD_KTLS].handle;
 
        if (direction == TLS_OFFLOAD_CTX_DIR_RX) {
                pr_err("not expecting for RX direction\n");
        if (tx_ctx->chcr_info)
                goto out;
 
+       if (u_ctx && u_ctx->detach)
+               goto out;
+
        tx_info = kvzalloc(sizeof(*tx_info), GFP_KERNEL);
        if (!tx_info)
                goto out;
        cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
                         tx_info->tid, tx_info->ip_family);
 
+       xa_erase(&u_ctx->tid_list, tx_info->tid);
+
 put_module:
        /* release module refcount */
        module_put(THIS_MODULE);
 {
        const struct cpl_act_open_rpl *p = (void *)input;
        struct chcr_ktls_info *tx_info = NULL;
+       struct chcr_ktls_ofld_ctx_tx *tx_ctx;
+       struct chcr_ktls_uld_ctx *u_ctx;
        unsigned int atid, tid, status;
+       struct tls_context *tls_ctx;
        struct tid_info *t;
+       int ret = 0;
 
        tid = GET_TID(p);
        status = AOPEN_STATUS_G(ntohl(p->atid_status));
        if (!status) {
                tx_info->tid = tid;
                cxgb4_insert_tid(t, tx_info, tx_info->tid, tx_info->ip_family);
+               /* Adding tid */
+               tls_ctx = tls_get_ctx(tx_info->sk);
+               tx_ctx = chcr_get_ktls_tx_context(tls_ctx);
+               u_ctx = adap->uld[CXGB4_ULD_KTLS].handle;
+               if (u_ctx) {
+                       ret = xa_insert_bh(&u_ctx->tid_list, tid, tx_ctx,
+                                          GFP_NOWAIT);
+                       if (ret < 0) {
+                               pr_err("%s: Failed to allocate tid XA entry = %d\n",
+                                      __func__, tx_info->tid);
+                               tx_info->open_state = CH_KTLS_OPEN_FAILURE;
+                               goto out;
+                       }
+               }
                tx_info->open_state = CH_KTLS_OPEN_SUCCESS;
        } else {
                tx_info->open_state = CH_KTLS_OPEN_FAILURE;
        }
+out:
        spin_unlock(&tx_info->lock);
 
        complete(&tx_info->completion);
-       return 0;
+       return ret;
 }
 
 /*
                goto out;
        }
        u_ctx->lldi = *lldi;
+       u_ctx->detach = false;
+       xa_init_flags(&u_ctx->tid_list, XA_FLAGS_LOCK_BH);
 out:
        return u_ctx;
 }
        return 0;
 }
 
+static void clear_conn_resources(struct chcr_ktls_info *tx_info)
+{
+       /* clear l2t entry */
+       if (tx_info->l2te)
+               cxgb4_l2t_release(tx_info->l2te);
+
+#if IS_ENABLED(CONFIG_IPV6)
+       /* clear clip entry */
+       if (tx_info->ip_family == AF_INET6)
+               cxgb4_clip_release(tx_info->netdev, (const u32 *)
+                                  &tx_info->sk->sk_v6_rcv_saddr,
+                                  1);
+#endif
+
+       /* clear tid */
+       if (tx_info->tid != -1)
+               cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
+                                tx_info->tid, tx_info->ip_family);
+}
+
+static void ch_ktls_reset_all_conn(struct chcr_ktls_uld_ctx *u_ctx)
+{
+       struct ch_ktls_port_stats_debug *port_stats;
+       struct chcr_ktls_ofld_ctx_tx *tx_ctx;
+       struct chcr_ktls_info *tx_info;
+       unsigned long index;
+
+       xa_for_each(&u_ctx->tid_list, index, tx_ctx) {
+               tx_info = tx_ctx->chcr_info;
+               clear_conn_resources(tx_info);
+               port_stats = &tx_info->adap->ch_ktls_stats.ktls_port[tx_info->port_id];
+               atomic64_inc(&port_stats->ktls_tx_connection_close);
+               kvfree(tx_info);
+               tx_ctx->chcr_info = NULL;
+               /* release module refcount */
+               module_put(THIS_MODULE);
+       }
+}
+
 static int chcr_ktls_uld_state_change(void *handle, enum cxgb4_state new_state)
 {
        struct chcr_ktls_uld_ctx *u_ctx = handle;
        case CXGB4_STATE_DETACH:
                pr_info("%s: Down\n", pci_name(u_ctx->lldi.pdev));
                mutex_lock(&dev_mutex);
+               u_ctx->detach = true;
                list_del(&u_ctx->entry);
+               ch_ktls_reset_all_conn(u_ctx);
+               xa_destroy(&u_ctx->tid_list);
                mutex_unlock(&dev_mutex);
                break;
        default:
                adap = pci_get_drvdata(u_ctx->lldi.pdev);
                memset(&adap->ch_ktls_stats, 0, sizeof(adap->ch_ktls_stats));
                list_del(&u_ctx->entry);
+               xa_destroy(&u_ctx->tid_list);
                kfree(u_ctx);
        }
        mutex_unlock(&dev_mutex);