conn->local_nls = load_nls("utf8");
        if (!conn->local_nls)
                conn->local_nls = load_nls_default();
+       if (IS_ENABLED(CONFIG_UNICODE))
+               conn->um = utf8_load(UNICODE_AGE(12, 1, 0));
+       else
+               conn->um = ERR_PTR(-EOPNOTSUPP);
+       if (IS_ERR(conn->um))
+               conn->um = NULL;
        atomic_set(&conn->req_running, 0);
        atomic_set(&conn->r_count, 0);
        conn->total_credits = 1;
        wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
 
 
+       if (IS_ENABLED(CONFIG_UNICODE))
+               utf8_unload(conn->um);
        unload_nls(conn->local_nls);
        if (default_conn_ops.terminate_fn)
                default_conn_ops.terminate_fn(conn);
 
        char                            *request_buf;
        struct ksmbd_transport          *transport;
        struct nls_table                *local_nls;
+       struct unicode_map              *um;
        struct list_head                conns_list;
        /* smb session 1 per user */
        struct xarray                   sessions;
 
        struct list_head        list;
 };
 
-static unsigned int share_name_hash(char *name)
+static unsigned int share_name_hash(const char *name)
 {
        return jhash(name, strlen(name), 0);
 }
        return share;
 }
 
-static struct ksmbd_share_config *__share_lookup(char *name)
+static struct ksmbd_share_config *__share_lookup(const char *name)
 {
        struct ksmbd_share_config *share;
        unsigned int key = share_name_hash(name);
        return 0;
 }
 
-static struct ksmbd_share_config *share_config_request(char *name)
+static struct ksmbd_share_config *share_config_request(const char *name)
 {
        struct ksmbd_share_config_response *resp;
        struct ksmbd_share_config *share = NULL;
        return share;
 }
 
-static void strtolower(char *share_name)
-{
-       while (*share_name) {
-               *share_name = tolower(*share_name);
-               share_name++;
-       }
-}
-
-struct ksmbd_share_config *ksmbd_share_config_get(char *name)
+struct ksmbd_share_config *ksmbd_share_config_get(const char *name)
 {
        struct ksmbd_share_config *share;
 
-       strtolower(name);
-
        down_read(&shares_table_lock);
        share = __share_lookup(name);
        if (share)
 
        __ksmbd_share_config_put(share);
 }
 
-struct ksmbd_share_config *ksmbd_share_config_get(char *name);
+struct ksmbd_share_config *ksmbd_share_config_get(const char *name);
 bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
                               const char *filename);
 #endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
 
 
 struct ksmbd_tree_conn_status
 ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
-                       char *share_name)
+                       const char *share_name)
 {
        struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
        struct ksmbd_tree_connect_response *resp = NULL;
 
 
 struct ksmbd_tree_conn_status
 ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
-                       char *share_name);
+                       const char *share_name);
 
 int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
                               struct ksmbd_tree_connect *tree_conn);
 
 #include <linux/kernel.h>
 #include <linux/xattr.h>
 #include <linux/fs.h>
+#include <linux/unicode.h>
 
 #include "misc.h"
 #include "smb_common.h"
        strreplace(path, '/', '\\');
 }
 
+static char *casefold_sharename(struct unicode_map *um, const char *name)
+{
+       char *cf_name;
+       int cf_len;
+
+       cf_name = kzalloc(KSMBD_REQ_MAX_SHARE_NAME, GFP_KERNEL);
+       if (!cf_name)
+               return ERR_PTR(-ENOMEM);
+
+       if (IS_ENABLED(CONFIG_UNICODE) && um) {
+               const struct qstr q_name = {.name = name, .len = strlen(name)};
+
+               cf_len = utf8_casefold(um, &q_name, cf_name,
+                                      KSMBD_REQ_MAX_SHARE_NAME);
+               if (cf_len < 0)
+                       goto out_ascii;
+
+               return cf_name;
+       }
+
+out_ascii:
+       cf_len = strscpy(cf_name, name, KSMBD_REQ_MAX_SHARE_NAME);
+       if (cf_len < 0) {
+               kfree(cf_name);
+               return ERR_PTR(-E2BIG);
+       }
+
+       for (; *cf_name; ++cf_name)
+               *cf_name = isascii(*cf_name) ? tolower(*cf_name) : *cf_name;
+       return cf_name - cf_len;
+}
+
 /**
  * ksmbd_extract_sharename() - get share name from tree connect request
  * @treename:  buffer containing tree name and share name
  *
  * Return:      share name on success, otherwise error
  */
-char *ksmbd_extract_sharename(char *treename)
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
 {
-       char *name = treename;
-       char *dst;
-       char *pos = strrchr(name, '\\');
+       const char *name = treename, *pos = strrchr(name, '\\');
 
        if (pos)
                name = (pos + 1);
 
        /* caller has to free the memory */
-       dst = kstrdup(name, GFP_KERNEL);
-       if (!dst)
-               return ERR_PTR(-ENOMEM);
-       return dst;
+       return casefold_sharename(um, name);
 }
 
 /**
 
 void ksmbd_conv_path_to_unix(char *path);
 void ksmbd_strip_last_slash(char *path);
 void ksmbd_conv_path_to_windows(char *path);
-char *ksmbd_extract_sharename(char *treename);
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
 char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
 
 #define KSMBD_DIR_INFO_ALIGNMENT       8
 
                goto out_err1;
        }
 
-       name = ksmbd_extract_sharename(treename);
+       name = ksmbd_extract_sharename(conn->um, treename);
        if (IS_ERR(name)) {
                status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
                goto out_err1;
 
 #include <asm/byteorder.h>
 #include <linux/types.h>
 #include <linux/nls.h>
+#include <linux/unicode.h>
 
 #define  UNIUPR_NOLOWER                /* Example to not expand lower case tables */
 
                             const struct nls_table *codepage);
 int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
                      const struct nls_table *cp, int mapchars);
-char *ksmbd_extract_sharename(char *treename);
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
 #endif
 
 /*