diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..5227bfb 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -8,3 +8,4 @@ ufshcd-core-objs := ufshcd.o ufs-sysfs.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
+obj-$(CONFIG_SCSI_UFS_ATTRS) += ufs_bsg.o
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
new file mode 100644
index 0000000..71826ba
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SSCSI transport companion for UFS HBA
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#include "ufs_bsg.h"
+
+struct ufs_bsg {
+	struct ufs_hba *hba;
+	struct ufs_port *port;
+};
+static struct ufs_bsg *bsg_host;
+
+static int ufs_bsg_request(struct bsg_job *job);
+
+static struct scsi_transport_template *ufs_transport_template;
+static struct ufs_function_template ufs_transport_functions = {
+	.bsg_request = ufs_bsg_request,
+};
+
+static int ufs_bsg_request(struct bsg_job *job)
+{
+	struct ufs_bsg_request *bsg_request = job->request;
+	struct ufs_bsg_reply *bsg_reply = job->reply;
+	int ret = -ENOTSUPP;
+
+	bsg_reply->reply_payload_rcv_len = 0;
+
+	/* Do Nothing for now */
+	dev_err(job->dev, "unsupported message_code 0x%x\n",
+		bsg_request->msgcode);
+
+	bsg_reply->result = ret;
+	if (ret)
+		job->reply_len = sizeof(uint32_t);
+	else
+		job->reply_len = sizeof(struct ufs_bsg_reply) +
+				 bsg_reply->reply_payload_rcv_len;
+
+	bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+	return ret;
+}
+
+/**
+ * ufs_bsg_attach_transport - instantiate UFS transport template
+ * @hba:	hba to attach the transport template to
+ *
+ * Call this before scsi_add_host() publishes it to the scsi midlayer
+ */
+void ufs_bsg_attach_transport(struct ufs_hba *hba)
+{
+	ufs_transport_template =
+		ufs_attach_transport(&ufs_transport_functions);
+	if (!ufs_transport_template)
+		return;
+
+	hba->host->transportt = ufs_transport_template;
+}
+
+/**
+ * ufs_bsg_remove - detach and remove the added ufs-ports
+ * @shost: scsi host that is parenting the ufs-ports
+ *
+ * Should be called when unloading the driver.
+ */
+void ufs_bsg_remove(struct Scsi_Host *shost)
+{
+	if (!bsg_host)
+		return;
+
+	ufs_remove_host(shost);
+
+	if (ufs_transport_template) {
+		ufs_release_transport(ufs_transport_template);
+		ufs_transport_template = NULL;
+	}
+
+	kfree(bsg_host);
+}
+
+/**
+ * ufs_bsg_probe - Add and report ufs device to ufs transport
+ * @hba: per adapter object
+ *
+ * Called during initial loading of the driver, and before scsi_scan_host.
+ * Should be called only if the attach phase was successful
+ */
+
+int ufs_bsg_probe(struct ufs_hba *hba)
+{
+	struct ufs_port *port;
+	int ret;
+
+	if (WARN_ON(!ufs_transport_template))
+		return -ENODEV;
+
+	bsg_host = kzalloc(sizeof(*bsg_host), GFP_KERNEL);
+	if (!bsg_host) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	port = ufs_port_alloc(hba->host);
+	if (!port) {
+		ret = -ENOMEM;
+		goto out_free_bsg_host;
+	}
+
+	ret = ufs_port_add(port);
+	if (ret)
+		goto out_free_port;
+
+	bsg_host->port = port;
+	bsg_host->hba = hba;
+
+	return 0;
+
+out_free_port:
+	ufs_port_free(port);
+out_free_bsg_host:
+	kfree(bsg_host);
+out:
+	ufs_transport_template = NULL;
+	return ret;
+}
diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
new file mode 100644
index 0000000..de5511f
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_bsg.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#ifndef UFS_BSG_H
+#define UFS_BSG_H
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_ufs.h>
+
+#include <uapi/scsi/scsi_bsg_ufs.h>
+#include "ufshcd.h"
+#include "ufs.h"
+
+#define UPIU_TRANSACTION_UIC_CMD 0x1F
+
+enum {
+	REQ_UPIU_SIZE_DWORDS	= 8,
+	RSP_UPIU_SIZE_DWORDS	= 8,
+};
+
+struct ufs_bsg_request {
+	uint32_t msgcode;
+	struct utp_upiu_header header;
+	union {
+		struct utp_upiu_query		qr;
+		struct utp_upiu_task_req	tr;
+		/* use utp_upiu_query to host the 4 dwards of uic command */
+		struct utp_upiu_query		uc;
+	} tsf;
+	uint8_t data[0];
+} __packed;
+
+
+struct ufs_bsg_reply {
+	/*
+	 * The completion result. Result exists in two forms:
+	 * if negative, it is an -Exxx system errno value. There will
+	 * be no further reply information supplied.
+	 * else, it's the 4-byte scsi error result, with driver, host,
+	 * msg and status fields. The per-msgcode reply structure
+	 * will contain valid data.
+	 */
+	uint32_t result;
+
+	/* If there was reply_payload, how much was recevied ? */
+	uint32_t reply_payload_rcv_len;
+
+	struct utp_upiu_header header;
+	union {
+		struct utp_upiu_query		qr;
+		struct utp_upiu_task_rsp	tr;
+		struct utp_upiu_query		uc;
+	} tsf;
+	uint8_t data[0];
+};
+
+struct ufs_bsg_raw_upiu {
+	struct ufs_bsg_upiu request;
+	struct ufs_bsg_upiu reply;
+};
+
+#ifdef CONFIG_SCSI_UFS_ATTRS
+void ufs_bsg_attach_transport(struct ufs_hba *hba);
+void ufs_bsg_remove(struct Scsi_Host *shost);
+int ufs_bsg_probe(struct ufs_hba *hba);
+#else
+static inline void ufs_bsg_attach_transport(struct ufs_hba *hba) {}
+static inline void ufs_bsg_remove(struct Scsi_Host *shost) {}
+static inline int ufs_bsg_probe(struct ufs_hba *hba) {return 0; }
+#endif
+
+#endif /* UFS_BSG_H */
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
new file mode 100644
index 0000000..5fb37be
--- /dev/null
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * UFS Transport SGIO v4 BSG Message Support
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#ifndef SCSI_BSG_UFS_H
+#define SCSI_BSG_UFS_H
+
+/*
+ * This file intended to be included by both kernel and user space
+ */
+
+
+/**
+ * struct ufs_bsg_upiu - upiu transaction structure
+ *
+ * @header: upiu header
+ * @tsf: Transaction Specific Fields
+ * @data: payload pointer
+ *
+ * This structure supports all ufs transaction types per JEDEC UFSv2.1
+ * paragraph 10.7
+ */
+struct ufs_bsg_upiu {
+	uint32_t header[3];
+	uint32_t tsf[5];
+	uint8_t data[0];
+};
+
+/* request (CDB) structure of the sg_io_v4 */
+struct ufs_bsg_upiu_request {
+	uint32_t msgcode;
+	struct ufs_bsg_upiu upiu;
+} __packed;
+
+/* response (request sense data) structure of the sg_io_v4 */
+struct ufs_bsg_upiu_reply {
+	/*
+	 * The completion result. Result exists in two forms:
+	 * if negative, it is an -Exxx system errno value. There will
+	 * be no further reply information supplied.
+	 * else, it's the 4-byte scsi error result, with driver, host,
+	 * msg and status fields. The per-msgcode reply structure
+	 * will contain valid data.
+	 */
+	uint32_t result;
+
+	/* If there was reply_payload, how much was recevied ? */
+	uint32_t reply_payload_rcv_len;
+
+	struct ufs_bsg_upiu upiu;
+
+};
+
+#endif /* SCSI_BSG_UFS_H */
