Re: [PATCH] scsi: ufs: add support for BLKSECDISCARD

2016-10-11 Thread Subhash Jadavani

Hi Szymon,

On 2016-10-11 04:15, Mielczarek, SzymonX wrote:

Hi Jadavani,

_> Now it make sense, i wasn't expecting that this patch is to prevent
die level attack. Do you want to make that explicit in the commit
text?_

No problem with that. Please see the update below:

Add BLKSECDISCARD feature support if LU is configured in the secure
mode

(bProvisioningType = 3).

To perform BLKSECDISCARD, the driver issues Purge operation after each
SCSI

Discard command with REQ_SECURE flag set, and delays operation

completion, or calling scsi_done(), until Purge is completed.

Due to flash technology specifics, the Purge operation might take

significant time, thus all requests from SCSI layer are blocked for

the time of Purge.

Purge operation is required to protect against die level attacks
(JESD220B



This commit text updates look good.
My concern is that there might be case where certain end products 
doesn't require us to protect against the die level attacks and in such 
case, it would be good to skip the purge. How do we handle these 2 
different requirements? Should we have the kernel config for purge? or 
some other way to disable purge if not needed?



12.2.2.4). Once the secure mode is enabled on partition (TPRZ = 1),

the Read will return all-zeros, however the data can still reside in
unmapped

memory on flash (JESD220B 12.2.2.2). Purge operation ensures all
unmapped

data is actually removed from physical flash.

_> Yes, for BLKSECDISCARD, isn't it good to issue purge for TPRZ=0
(bProvisioningType = 3) to make sure we can't read back data?_

Issuing purge operation only for TPRZ=1 (bProvisioningType = 3)
ensures that secure operation is performed on Logical Units that have
secure mode enabled (12.2.3.5).

The patch assumes that only such LUs will hold data subject to secure
removal.

_> That's true._

_> Purge time depends on flash state and it also varies a lot from
vendor to vendor._

_> Anything over a min may not be good for user experience (especially
for_

_> mobile) and user may simply abort (phone restart) thinking that
device isn't stuck._

The secure discard feature should be used mainly during factory reset
which is supposed to be done no more than a few times for a live of a
product.

Typically, the user is informed that the factory reset operation will
take significant time.


Agreed, factory data reset should issue BLKSECDISCARD and we shouldn't 
be able to read the data back after that. Again this doesn't mean we 
always need to protect against the die level attacks, this requirement 
may differ from product to product.


Thanks,
Subhash



Unfortunately we are not able to state even approximate time as the
purge time is not deterministic.

BR,

Szymon

-Original Message-
From: Subhash Jadavani [mailto:subha...@codeaurora.org]
Sent: Wednesday, October 5, 2016 7:41 PM
To: Mielczarek, SzymonX 
Cc: Pielaszkiewicz, Tomasz ;
Wodkowski, PawelX ;
linux-scsi@vger.kernel.org; hun...@vger.kernel.org; Hunter, Adrian
; pielaszkiew...@vger.kernel.org;
ja...@vger.kernel.org; Janca, Grzegorz ;
linux-scsi-ow...@vger.kernel.org
Subject: Re: [PATCH] scsi: ufs: add support for BLKSECDISCARD

Hi SzymonX,

On 2016-10-04 05:55, Mielczarek, SzymonX wrote:


Hi Jadavani,







_> Did you mean sending purge when bProvisioningType is set to 02h



(TPRZ = 0)? why do we want to send the purge if TPRZ is 1?_







By doing Purge we want to protect from die level attacks (JESD220B



12.2.3.3). Once Erase is enabled on partition, the Read will return



zeros, however data can still reside in unmapped memory on flash



(behind mapping/translation table) (12.2.2.2). We expose

BLKSECDISCARD


on "Erase enabled" partitions just to remove possibility on die

level


attacks.


Now it make sense, i wasn't expecting that this patch is to prevent
die level attack. Do you want to make that explicit in the commit
text?






Are you suggesting that this check is not required, and in any TPRZ



(thus 02h and 03h) BLKSECDISCARD (this Purge) shall be enabled?

That's


also possible.


Yes, for BLKSECDISCARD, isn't it good to issue purge for TPRZ=0
(bProvisioningType = 3) to make sure we can't read back data?






_> We had seen purge taking few mins to complete with some of the

UFS


device vendors._







_> Did you run any experiments to major the time taken for purge to



complete?_







Yes, we did several experiments around Dec 2015, and the time of

Purge


operation with software overhead was varying between 100-500 seconds




(!), with typical time approx. 350 seconds! We also consulted one



vendor on this observation, and got response that Purge times over 1




min are possible, depending on flash state.


That's true.

Purge time depends on flash state and it also varies a lot from vendor
to vendor.

Anything over a min may not be good for user experience (especially
for

mobil

Re: [PATCH] scsi: ufs: add support for BLKSECDISCARD

2016-10-05 Thread Subhash Jadavani

Hi SzymonX,

On 2016-10-04 05:55, Mielczarek, SzymonX wrote:

Hi Jadavani,

_> Did you mean sending purge when bProvisioningType is set to 02h
(TPRZ = 0)? why do we want to send the purge if TPRZ is 1?_

By doing Purge we want to protect from die level attacks (JESD220B
12.2.3.3). Once Erase is enabled on partition, the Read will return
zeros, however data can still reside in unmapped memory on flash
(behind mapping/translation table) (12.2.2.2). We expose BLKSECDISCARD
on "Erase enabled" partitions just to remove possibility on die level
attacks.


Now it make sense, i wasn't expecting that this patch is to prevent die 
level attack. Do you want to make that explicit in the commit text?




Are you suggesting that this check is not required, and in any TPRZ
(thus 02h and 03h) BLKSECDISCARD (this Purge) shall be enabled? That's
also possible.


Yes, for BLKSECDISCARD, isn't it good to issue purge for TPRZ=0 
(bProvisioningType = 3) to make sure we can't read back data?




_> We had seen purge taking few mins to complete with some of the UFS
device vendors._

_> Did you run any experiments to major the time taken for purge to
complete?_

Yes, we did several experiments around Dec 2015, and the time of Purge
operation with software overhead was varying between 100-500 seconds
(!), with typical time approx. 350 seconds! We also consulted one
vendor on this observation, and got response that Purge times over 1
min are possible, depending on flash state.


That's true.
Purge time depends on flash state and it also varies a lot from vendor 
to vendor.
Anything over a min may not be good for user experience (especially for 
mobile) and user may simply abort (phone restart) thinking that device 
isn't stuck.




BR,

Szymon

-Original Message-
From: Pielaszkiewicz, Tomasz
Sent: Tuesday, October 4, 2016 1:41 PM
To: subha...@codeaurora.org; Wodkowski, PawelX
; Mielczarek, SzymonX

Cc: linux-scsi@vger.kernel.org; hun...@vger.kernel.org; Hunter, Adrian
; pielaszkiew...@vger.kernel.org;
ja...@vger.kernel.org; Janca, Grzegorz ;
linux-scsi-ow...@vger.kernel.org
Subject: RE: [PATCH] scsi: ufs: add support for BLKSECDISCARD

Hi,

Adding Szymon, who took over Pawel's work.

Tomek

-Original Message-

From: subha...@codeaurora.org [mailto:subha...@codeaurora.org]

Sent: Tuesday, September 27, 2016 10:18 PM

To: Wodkowski, PawelX

Cc: linux-scsi@vger.kernel.org; hun...@vger.kernel.org; Hunter,
Adrian; pielaszkiew...@vger.kernel.org; Pielaszkiewicz, Tomasz;
ja...@vger.kernel.org; Janca, Grzegorz;
linux-scsi-ow...@vger.kernel.org

Subject: Re: [PATCH] scsi: ufs: add support for BLKSECDISCARD

Hi Pawel,

Please find some comments inline.

On 2016-07-26 04:56, Pawel Wodkowski wrote:


Add BLKSECDISCAD feature support if LU is provisioned for TPRZ



(bProvisioningType = 3).


Did you mean sending purge when bProvisioningType is set to 02h (TPRZ
= 0)? why do we want to send the purge if TPRZ is 1?






To perform BLKSECDISCAD driver issue purge operation after each



discard SCSI command with REQ_SECURE flag set, and delay calling



scsi_done() till purge finish. This operation might long so block



requests from SCSI layer in ufshcd_queueucommand() and then unblock

it


after purge finish.


We had seen purge taking few mins to complete with some of the UFS
device vendors.

Did you run any experiments to major the time taken for purge to
complete?






Signed-off-by: Pawel Wodkowski 



---



 drivers/scsi/ufs/ufs.h|  19 +



 drivers/scsi/ufs/ufshcd.c | 187



+-



 drivers/scsi/ufs/ufshcd.h |   6 ++



 3 files changed, 208 insertions(+), 4 deletions(-)







diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index



b291fa6ed2ad..2f769974fda1 100644



--- a/drivers/scsi/ufs/ufs.h



+++ b/drivers/scsi/ufs/ufs.h



@@ -132,12 +132,14 @@ enum flag_idn {



QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,



QUERY_FLAG_IDN_PWR_ON_WPE = 0x03,



QUERY_FLAG_IDN_BKOPS_EN = 0x04,



+  QUERY_FLAG_IDN_PURGE_EN = 0x06,



 };







 /* Attribute idn for Query requests */  enum attr_idn {



QUERY_ATTR_IDN_ACTIVE_ICC_LVL  = 0x03,



QUERY_ATTR_IDN_BKOPS_STATUS= 0x05,



+  QUERY_ATTR_IDN_PURGE_STATUS   = 0x06,



QUERY_ATTR_IDN_EE_CONTROL = 0x0D,



QUERY_ATTR_IDN_EE_STATUS = 0x0E,



 };



@@ -247,6 +249,13 @@ enum {



UFSHCD_AMP   = 3,



 };







+/* Provisioning type */



+enum unit_desc_param_provisioning_type {



+  THIN_PROVISIONING_DISABLED  =

0x00,


+  THIN_PROVISIONING_ENABLED_TPRZ_0 = 0x02,



+  THIN_PROVISIONING_ENABLED_TPRZ_1 = 0x03,



+};



+



 #define POWER_DESC_MAX_SIZE

0x62


 #define POWER_DESC_MAX_ACTV_ICC

RE: [PATCH] scsi: ufs: add support for BLKSECDISCARD

2016-10-04 Thread Pielaszkiewicz, Tomasz
Hi,
Adding Szymon, who took over Pawel's work.

Tomek

-Original Message-
From: subha...@codeaurora.org [mailto:subha...@codeaurora.org] 
Sent: Tuesday, September 27, 2016 10:18 PM
To: Wodkowski, PawelX
Cc: linux-scsi@vger.kernel.org; hun...@vger.kernel.org; Hunter, Adrian; 
pielaszkiew...@vger.kernel.org; Pielaszkiewicz, Tomasz; ja...@vger.kernel.org; 
Janca, Grzegorz; linux-scsi-ow...@vger.kernel.org
Subject: Re: [PATCH] scsi: ufs: add support for BLKSECDISCARD

Hi Pawel,

Please find some comments inline.

On 2016-07-26 04:56, Pawel Wodkowski wrote:
> Add BLKSECDISCAD feature support if LU is provisioned for TPRZ 
> (bProvisioningType = 3).

Did you mean sending purge when bProvisioningType is set to 02h (TPRZ = 0)? why 
do we want to send the purge if TPRZ is 1?

> 
> To perform BLKSECDISCAD driver issue purge operation after each 
> discard SCSI command with REQ_SECURE flag set, and delay calling 
> scsi_done() till purge finish. This operation might long so block 
> requests from SCSI layer in ufshcd_queueucommand() and then unblock it 
> after purge finish.

We had seen purge taking few mins to complete with some of the UFS device 
vendors.
Did you run any experiments to major the time taken for purge to complete?

> 
> Signed-off-by: Pawel Wodkowski 
> ---
>  drivers/scsi/ufs/ufs.h|  19 +
>  drivers/scsi/ufs/ufshcd.c | 187
> +-
>  drivers/scsi/ufs/ufshcd.h |   6 ++
>  3 files changed, 208 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 
> b291fa6ed2ad..2f769974fda1 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -132,12 +132,14 @@ enum flag_idn {
>   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
>   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
>   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
> + QUERY_FLAG_IDN_PURGE_EN = 0x06,
>  };
> 
>  /* Attribute idn for Query requests */  enum attr_idn {
>   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
>   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
> + QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
>   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
>   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
>  };
> @@ -247,6 +249,13 @@ enum {
>   UFSHCD_AMP  = 3,
>  };
> 
> +/* Provisioning type */
> +enum unit_desc_param_provisioning_type {
> + THIN_PROVISIONING_DISABLED  = 0x00,
> + THIN_PROVISIONING_ENABLED_TPRZ_0= 0x02,
> + THIN_PROVISIONING_ENABLED_TPRZ_1= 0x03,
> +};
> +
>  #define POWER_DESC_MAX_SIZE  0x62
>  #define POWER_DESC_MAX_ACTV_ICC_LVLS 16
> 
> @@ -279,6 +288,16 @@ enum bkops_status {
>   BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
>  };
> 
> +/* Purge operation status */
> +enum purge_status {
> + PURGE_STATUS_IDLE = 0x0,
> + PURGE_STATUS_IN_PROGRESS  = 0x1,
> + PURGE_STATUS_STOP_BY_HOST = 0x2,
> + PURGE_STATUS_SUCCESS  = 0x3,
> + PURGE_STATUS_QUEUE_NOT_EMPTY  = 0x4,
> + PURGE_STATUS_GENERAL_FAIL = 0x5
> +};
> +
>  /* UTP QUERY Transaction Specific Fields OpCode */  enum query_opcode 
> {
>   UPIU_QUERY_OPCODE_NOP   = 0x0,
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c 
> index f8fa72c31a9d..4ca15a6f294c 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -70,6 +70,9 @@
>  /* Task management command timeout */
>  #define TM_CMD_TIMEOUT   100 /* msecs */
> 
> +/* Purge operation timeout */
> +#define PURGE_TIMEOUT 9000 /* msecs */
> +
>  /* maximum number of retries for a general UIC command  */  #define 
> UFS_UIC_COMMAND_RETRIES 3
> 
> @@ -1382,11 +1385,13 @@ static int ufshcd_queuecommand(struct 
> Scsi_Host *host, struct scsi_cmnd *cmd)
>   struct ufshcd_lrb *lrbp;
>   struct ufs_hba *hba;
>   unsigned long flags;
> + bool secure;
>   int tag;
>   int err = 0;
> 
>   hba = shost_priv(host);
> 
> + secure = !!(cmd->request->cmd_flags & REQ_SECURE);
>   tag = cmd->request->tag;
>   if (!ufshcd_valid_tag(hba, tag)) {
>   dev_err(hba->dev,
> @@ -1420,6 +1425,17 @@ static int ufshcd_queuecommand(struct Scsi_Host 
> *host, struct scsi_cmnd *cmd)
>   cmd->scsi_done(cmd);
>   goto out_unlock;
>   }
> +
> + if (secure) {
> + if (hba->is_purge_in_progress) {
> + secure = false;
> + err = SCSI_MLQUEUE_HOST_BUSY;
> + goto out_unlock;
> + }
> +
> + hba->is_purge_in_progress 

Re: [PATCH] scsi: ufs: add support for BLKSECDISCARD

2016-09-27 Thread subhashj

Hi Pawel,

Please find some comments inline.

On 2016-07-26 04:56, Pawel Wodkowski wrote:

Add BLKSECDISCAD feature support if LU is provisioned for TPRZ
(bProvisioningType = 3).


Did you mean sending purge when bProvisioningType is set to 02h (TPRZ = 
0)? why do we want to send the purge if TPRZ is 1?




To perform BLKSECDISCAD driver issue purge operation after each discard
SCSI command with REQ_SECURE flag set, and delay calling scsi_done()
till purge finish. This operation might long so block requests from 
SCSI

layer in ufshcd_queueucommand() and then unblock it after purge finish.


We had seen purge taking few mins to complete with some of the UFS 
device vendors.
Did you run any experiments to major the time taken for purge to 
complete?




Signed-off-by: Pawel Wodkowski 
---
 drivers/scsi/ufs/ufs.h|  19 +
 drivers/scsi/ufs/ufshcd.c | 187 
+-

 drivers/scsi/ufs/ufshcd.h |   6 ++
 3 files changed, 208 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index b291fa6ed2ad..2f769974fda1 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -132,12 +132,14 @@ enum flag_idn {
QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
QUERY_FLAG_IDN_BKOPS_EN = 0x04,
+   QUERY_FLAG_IDN_PURGE_EN = 0x06,
 };

 /* Attribute idn for Query requests */
 enum attr_idn {
QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
+   QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
QUERY_ATTR_IDN_EE_STATUS= 0x0E,
 };
@@ -247,6 +249,13 @@ enum {
UFSHCD_AMP  = 3,
 };

+/* Provisioning type */
+enum unit_desc_param_provisioning_type {
+   THIN_PROVISIONING_DISABLED  = 0x00,
+   THIN_PROVISIONING_ENABLED_TPRZ_0= 0x02,
+   THIN_PROVISIONING_ENABLED_TPRZ_1= 0x03,
+};
+
 #define POWER_DESC_MAX_SIZE0x62
 #define POWER_DESC_MAX_ACTV_ICC_LVLS   16

@@ -279,6 +288,16 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };

+/* Purge operation status */
+enum purge_status {
+   PURGE_STATUS_IDLE = 0x0,
+   PURGE_STATUS_IN_PROGRESS  = 0x1,
+   PURGE_STATUS_STOP_BY_HOST = 0x2,
+   PURGE_STATUS_SUCCESS  = 0x3,
+   PURGE_STATUS_QUEUE_NOT_EMPTY  = 0x4,
+   PURGE_STATUS_GENERAL_FAIL = 0x5
+};
+
 /* UTP QUERY Transaction Specific Fields OpCode */
 enum query_opcode {
UPIU_QUERY_OPCODE_NOP   = 0x0,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..4ca15a6f294c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -70,6 +70,9 @@
 /* Task management command timeout */
 #define TM_CMD_TIMEOUT 100 /* msecs */

+/* Purge operation timeout */
+#define PURGE_TIMEOUT 9000 /* msecs */
+
 /* maximum number of retries for a general UIC command  */
 #define UFS_UIC_COMMAND_RETRIES 3

@@ -1382,11 +1385,13 @@ static int ufshcd_queuecommand(struct
Scsi_Host *host, struct scsi_cmnd *cmd)
struct ufshcd_lrb *lrbp;
struct ufs_hba *hba;
unsigned long flags;
+   bool secure;
int tag;
int err = 0;

hba = shost_priv(host);

+   secure = !!(cmd->request->cmd_flags & REQ_SECURE);
tag = cmd->request->tag;
if (!ufshcd_valid_tag(hba, tag)) {
dev_err(hba->dev,
@@ -1420,6 +1425,17 @@ static int ufshcd_queuecommand(struct Scsi_Host
*host, struct scsi_cmnd *cmd)
cmd->scsi_done(cmd);
goto out_unlock;
}
+
+   if (secure) {
+   if (hba->is_purge_in_progress) {
+   secure = false;
+   err = SCSI_MLQUEUE_HOST_BUSY;
+   goto out_unlock;
+   }
+
+   hba->is_purge_in_progress = true;
+   }
+
spin_unlock_irqrestore(hba->host->host_lock, flags);

/* acquire the tag to make sure device cmds don't use it */
@@ -1465,9 +1481,19 @@ static int ufshcd_queuecommand(struct Scsi_Host
*host, struct scsi_cmnd *cmd)
/* issue command to the controller */
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_send_command(hba, tag);
+
+   if (secure) {
+   hba->purge_timeout = jiffies + msecs_to_jiffies(PURGE_TIMEOUT);
+
+   scsi_block_requests(hba->host);
+   }
+
 out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
 out:
+   if (err && secure && hba->is_purge_in_progress)
+   hba->is_purge_in_progress = false;
+
return err;
 }

@@ -1641,7 +1667,7 @@ static inline void ufshcd_put_dev_cmd_tag(struct
ufs_hba *hba, int tag)
  * ufshcd_exec_dev_cmd - API for sending device management requests
  * @hba - UFS hba
  * @cmd_type - specifi

[PATCH] scsi: ufs: add support for BLKSECDISCARD

2016-07-26 Thread Pawel Wodkowski
Add BLKSECDISCAD feature support if LU is provisioned for TPRZ
(bProvisioningType = 3).

To perform BLKSECDISCAD driver issue purge operation after each discard
SCSI command with REQ_SECURE flag set, and delay calling scsi_done()
till purge finish. This operation might long so block requests from SCSI
layer in ufshcd_queueucommand() and then unblock it after purge finish.

Signed-off-by: Pawel Wodkowski 
---
 drivers/scsi/ufs/ufs.h|  19 +
 drivers/scsi/ufs/ufshcd.c | 187 +-
 drivers/scsi/ufs/ufshcd.h |   6 ++
 3 files changed, 208 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index b291fa6ed2ad..2f769974fda1 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -132,12 +132,14 @@ enum flag_idn {
QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
QUERY_FLAG_IDN_BKOPS_EN = 0x04,
+   QUERY_FLAG_IDN_PURGE_EN = 0x06,
 };
 
 /* Attribute idn for Query requests */
 enum attr_idn {
QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
+   QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
QUERY_ATTR_IDN_EE_STATUS= 0x0E,
 };
@@ -247,6 +249,13 @@ enum {
UFSHCD_AMP  = 3,
 };
 
+/* Provisioning type */
+enum unit_desc_param_provisioning_type {
+   THIN_PROVISIONING_DISABLED  = 0x00,
+   THIN_PROVISIONING_ENABLED_TPRZ_0= 0x02,
+   THIN_PROVISIONING_ENABLED_TPRZ_1= 0x03,
+};
+
 #define POWER_DESC_MAX_SIZE0x62
 #define POWER_DESC_MAX_ACTV_ICC_LVLS   16
 
@@ -279,6 +288,16 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
+/* Purge operation status */
+enum purge_status {
+   PURGE_STATUS_IDLE = 0x0,
+   PURGE_STATUS_IN_PROGRESS  = 0x1,
+   PURGE_STATUS_STOP_BY_HOST = 0x2,
+   PURGE_STATUS_SUCCESS  = 0x3,
+   PURGE_STATUS_QUEUE_NOT_EMPTY  = 0x4,
+   PURGE_STATUS_GENERAL_FAIL = 0x5
+};
+
 /* UTP QUERY Transaction Specific Fields OpCode */
 enum query_opcode {
UPIU_QUERY_OPCODE_NOP   = 0x0,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..4ca15a6f294c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -70,6 +70,9 @@
 /* Task management command timeout */
 #define TM_CMD_TIMEOUT 100 /* msecs */
 
+/* Purge operation timeout */
+#define PURGE_TIMEOUT 9000 /* msecs */
+
 /* maximum number of retries for a general UIC command  */
 #define UFS_UIC_COMMAND_RETRIES 3
 
@@ -1382,11 +1385,13 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
struct ufshcd_lrb *lrbp;
struct ufs_hba *hba;
unsigned long flags;
+   bool secure;
int tag;
int err = 0;
 
hba = shost_priv(host);
 
+   secure = !!(cmd->request->cmd_flags & REQ_SECURE);
tag = cmd->request->tag;
if (!ufshcd_valid_tag(hba, tag)) {
dev_err(hba->dev,
@@ -1420,6 +1425,17 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
cmd->scsi_done(cmd);
goto out_unlock;
}
+
+   if (secure) {
+   if (hba->is_purge_in_progress) {
+   secure = false;
+   err = SCSI_MLQUEUE_HOST_BUSY;
+   goto out_unlock;
+   }
+
+   hba->is_purge_in_progress = true;
+   }
+
spin_unlock_irqrestore(hba->host->host_lock, flags);
 
/* acquire the tag to make sure device cmds don't use it */
@@ -1465,9 +1481,19 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
/* issue command to the controller */
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_send_command(hba, tag);
+
+   if (secure) {
+   hba->purge_timeout = jiffies + msecs_to_jiffies(PURGE_TIMEOUT);
+
+   scsi_block_requests(hba->host);
+   }
+
 out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
 out:
+   if (err && secure && hba->is_purge_in_progress)
+   hba->is_purge_in_progress = false;
+
return err;
 }
 
@@ -1641,7 +1667,7 @@ static inline void ufshcd_put_dev_cmd_tag(struct ufs_hba 
*hba, int tag)
  * ufshcd_exec_dev_cmd - API for sending device management requests
  * @hba - UFS hba
  * @cmd_type - specifies the type (NOP, Query...)
- * @timeout - time in seconds
+ * @timeout - time in miliseconds
  *
  * NOTE: Since there is only one available tag for device management commands,
  * it is expected you hold the hba->dev_cmd.lock mutex.
@@ -3306,6 +3332,18 @@ static int ufshcd_change_queue_depth(struct scsi_device 
*sdev, int depth)
 static int ufshcd_slave_configure(struct s