[PATCH] scsi: ufs: revamp string descriptor reading

2018-12-11 Thread Tomas Winkler
Define new a type: uc_string_id for easier string
handling and less casting. Reduce number or string
copies in price of a dynamic allocation.

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufs-sysfs.c |  20 ++---
 drivers/scsi/ufs/ufs.h   |   2 +-
 drivers/scsi/ufs/ufshcd.c| 164 +--
 drivers/scsi/ufs/ufshcd.h|   9 +-
 4 files changed, 115 insertions(+), 80 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 8d9332bb7d0c..0b221c5a244c 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -570,10 +570,11 @@ static ssize_t _name##_show(struct device *dev,   
\
struct ufs_hba *hba = dev_get_drvdata(dev); \
int ret;\
int desc_len = QUERY_DESC_MAX_SIZE; \
-   u8 *desc_buf;   \
+   char *desc_buf; \
+   \
desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC);\
-   if (!desc_buf)  \
-   return -ENOMEM; \
+   if (!desc_buf)  \
+   return -ENOMEM; \
ret = ufshcd_query_descriptor_retry(hba,\
UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \
0, 0, desc_buf, &desc_len); \
@@ -582,14 +583,13 @@ static ssize_t _name##_show(struct device *dev,   
\
goto out;   \
}   \
index = desc_buf[DEVICE_DESC_PARAM##_pname];\
-   memset(desc_buf, 0, QUERY_DESC_MAX_SIZE);   \
-   if (ufshcd_read_string_desc(hba, index, desc_buf,   \
-   QUERY_DESC_MAX_SIZE, true)) {   \
-   ret = -EINVAL;  \
+   kfree(desc_buf);\
+   desc_buf = NULL;\
+   ret = ufshcd_read_string_desc(hba, index, &desc_buf,\
+ SD_ASCII_STD);\
+   if (ret < 0)\
goto out;   \
-   }   \
-   ret = snprintf(buf, PAGE_SIZE, "%s\n",  \
-   desc_buf + QUERY_DESC_HDR_SIZE);\
+   ret = snprintf(buf, PAGE_SIZE, "%s\n", desc_buf);   \
 out:   \
kfree(desc_buf);\
return ret; \
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index dd65fea07687..06ec7bbf5b97 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -543,7 +543,7 @@ struct ufs_dev_info {
  */
 struct ufs_dev_desc {
u16 wmanufacturerid;
-   char model[MAX_MODEL_LEN + 1];
+   char *model;
 };
 
 /**
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 86fe114f1f53..f1845698413c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -298,16 +298,6 @@ static void ufshcd_scsi_block_requests(struct ufs_hba *hba)
scsi_block_requests(hba->host);
 }
 
-/* replace non-printable or non-ASCII characters with spaces */
-static inline void ufshcd_remove_non_printable(char *val)
-{
-   if (!val)
-   return;
-
-   if (*val < 0x20 || *val > 0x7e)
-   *val = ' ';
-}
-
 static void ufshcd_add_cmd_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
 {
@@ -3124,7 +3114,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
   enum desc_idn desc_id,
   int desc_index,
   u8 param_offset,
-  u8 *param_read_buf,
+  void *param_read_buf,
   u8 param_size)
 {
int ret;
@@ -3192,7 +3182,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
 static inline int ufshcd_read_desc(struct ufs_hba *hba,
   enum desc_idn desc_id,
   int desc_index,
-

[PATCH] scsi: ufs: add fall through annotation

2018-11-26 Thread Tomas Winkler
Add /* fallthrough */ annotation, to eliminate compilation warning:
warning: this statement may fall through [-Wimplicit-fallthrough=]

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3807efd895be..b15f5dab0618 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1549,6 +1549,7 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
 * currently running. Hence, fall through to cancel gating
 * work and to enable clocks.
 */
+   /* fallthrough */
case CLKS_OFF:
ufshcd_scsi_block_requests(hba);
hba->clk_gating.state = REQ_CLKS_ON;
@@ -1560,6 +1561,7 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
 * fall through to check if we should wait for this
 * work to be done or not.
 */
+   /* fallthrough */
case REQ_CLKS_ON:
if (async) {
rc = -EAGAIN;
@@ -4618,6 +4620,7 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int 
scsi_status)
switch (scsi_status) {
case SAM_STAT_CHECK_CONDITION:
ufshcd_copy_sense_data(lrbp);
+   /* fallthrough */
case SAM_STAT_GOOD:
result |= DID_OK << 16 |
  COMMAND_COMPLETE << 8 |
-- 
2.17.2



[PATCH] scsi: ufs: ufshcd_dump_regs to use memcpy_fromio

2018-03-06 Thread Tomas Winkler
ufshcd_dump_regs should use memcpy_fromio to read host registers
instead of directly accessing using memcpy.
The same function is utilized in ufs-qcom.

Elminite compilation warning
drivers/scsi/ufs/ufshcd.c:356:9: warning: incorrect type in argument 6 
(different address spaces)
drivers/scsi/ufs/ufshcd.c:356:9:expected void const *buf
drivers/scsi/ufs/ufshcd.c:356:9:got void [noderef] *mmio_base

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufs-qcom.c | 21 ++---
 drivers/scsi/ufs/ufshcd.c   | 35 ---
 drivers/scsi/ufs/ufshcd.h   |  3 +++
 3 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 2b38db2eeafa..77ac98ea80d4 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -50,19 +50,10 @@ static void ufs_qcom_get_default_testbus_cfg(struct 
ufs_qcom_host *host);
 static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
   u32 clk_cycles);
 
-static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
-   char *prefix)
-{
-   print_hex_dump(KERN_ERR, prefix,
-   len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
-   16, 4, (void __force *)hba->mmio_base + offset,
-   len * 4, false);
-}
-
 static void ufs_qcom_dump_regs_wrapper(struct ufs_hba *hba, int offset, int 
len,
-   char *prefix, void *priv)
+  const char *prefix, void *priv)
 {
-   ufs_qcom_dump_regs(hba, offset, len, prefix);
+   ufshcd_dump_regs(hba, offset, len * 4, prefix);
 }
 
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
@@ -1431,7 +1422,7 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
 
 static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba,
void *priv, void (*print_fn)(struct ufs_hba *hba,
-   int offset, int num_regs, char *str, void *priv))
+   int offset, int num_regs, const char *str, void *priv))
 {
u32 reg;
struct ufs_qcom_host *host;
@@ -1613,7 +1604,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
 
 static void ufs_qcom_testbus_read(struct ufs_hba *hba)
 {
-   ufs_qcom_dump_regs(hba, UFS_TEST_BUS, 1, "UFS_TEST_BUS ");
+   ufshcd_dump_regs(hba, UFS_TEST_BUS, 4, "UFS_TEST_BUS ");
 }
 
 static void ufs_qcom_print_unipro_testbus(struct ufs_hba *hba)
@@ -1639,8 +1630,8 @@ static void ufs_qcom_print_unipro_testbus(struct ufs_hba 
*hba)
 
 static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
 {
-   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16,
-   "HCI Vendor Specific Registers ");
+   ufshcd_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16 * 4,
+"HCI Vendor Specific Registers ");
 
/* sleep a bit intermittently as we are dumping too much data */
ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3abcd31646eb..f2e1da77045c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -98,8 +98,29 @@
_ret;   \
})
 
-#define ufshcd_hex_dump(prefix_str, buf, len) \
-print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
+#define ufshcd_hex_dump(prefix_str, buf, len) do {   \
+   size_t __len = (len);\
+   print_hex_dump(KERN_ERR, prefix_str, \
+  __len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,\
+  16, 4, buf, __len, false);\
+} while (0)
+
+int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
+const char *prefix)
+{
+   u8 *regs;
+
+   regs = kzalloc(len, GFP_KERNEL);
+   if (!regs)
+   return -ENOMEM;
+
+   memcpy_fromio(regs, hba->mmio_base + offset, len);
+   ufshcd_hex_dump(prefix, regs, len);
+   kfree(regs);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dump_regs);
 
 enum {
UFSHCD_MAX_CHANNEL  = 0,
@@ -343,15 +364,7 @@ static void ufshcd_print_uic_err_hist(struct ufs_hba *hba,
 
 static void ufshcd_print_host_regs(struct ufs_hba *hba)
 {
-   /*
-* hex_dump reads its data without the readl macro. This might
-* cause inconsistency issues on some platform, as the printed
-* values may be from cache and not the most recent value.
-* To know whether you are looking at an un-cached version verify
-* that IORESOURCE_MEM flag is on when xxx_get_resource() is invoked
-* during platform/pci probe function.
-*/
-

[scsi] scsi: ufshcd-platform: remove the useless cast in ERR_PTR/IS_ERR

2017-03-14 Thread Tomas Winkler
IS_ERR and ERR_PTR already forcefully cast their argument,
hence there is no need for additional (complex) casting.

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd-pltfrm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index a72a4ba78125..8e5e6c04c035 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -309,8 +309,8 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
 
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mmio_base = devm_ioremap_resource(dev, mem_res);
-   if (IS_ERR(*(void **)&mmio_base)) {
-   err = PTR_ERR(*(void **)&mmio_base);
+   if (IS_ERR(mmio_base)) {
+   err = PTR_ERR(mmio_base);
goto out;
}
 
-- 
2.9.3



[scsi] scsi: ufs: don't check unsigned type for a negative value

2017-03-12 Thread Tomas Winkler
Fix compilation warning

drivers/scsi/ufs/ufshcd.c:7645:13: warning: comparison of unsigned
expression < 0 is always false [-Wtype-limits]
if ((value < UFS_PM_LVL_0) || (value >= UFS_PM_LVL_MAX))

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1359913bf840..e8c26e6e6237 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -7642,7 +7642,7 @@ static inline ssize_t ufshcd_pm_lvl_store(struct device 
*dev,
if (kstrtoul(buf, 0, &value))
return -EINVAL;
 
-   if ((value < UFS_PM_LVL_0) || (value >= UFS_PM_LVL_MAX))
+   if (value >= UFS_PM_LVL_MAX)
return -EINVAL;
 
spin_lock_irqsave(hba->host->host_lock, flags);
-- 
2.9.3



[scsi 4/4] scsi: ufs: refactor device descriptor reading

2017-01-04 Thread Tomas Winkler
Pull device descriptor reading out of ufs quirk so it
can be used also for other purposes.

Revamp the fixup setup:
1. Rename ufs_device_info to ufs_dev_desc as very similar
name ufs_dev_info is already in use.
2. Make the handlers static as they are not used out of the
ufshdc.c file.

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufs.h| 12 
 drivers/scsi/ufs/ufs_quirks.h | 28 ++--
 drivers/scsi/ufs/ufshcd.c | 40 +++-
 3 files changed, 37 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 8e6709a3fb6b..318e4a1f76c9 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -523,4 +523,16 @@ struct ufs_dev_info {
bool is_lu_power_on_wp;
 };
 
+#define MAX_MODEL_LEN 16
+/**
+ * ufs_dev_desc - ufs device details from the device descriptor
+ *
+ * @wmanufacturerid: card details
+ * @model: card model
+ */
+struct ufs_dev_desc {
+   u16 wmanufacturerid;
+   char model[MAX_MODEL_LEN + 1];
+};
+
 #endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 08b799d4efcc..71f73d1d1ad1 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -21,41 +21,28 @@
 #define UFS_ANY_VENDOR 0x
 #define UFS_ANY_MODEL  "ANY_MODEL"
 
-#define MAX_MODEL_LEN 16
-
 #define UFS_VENDOR_TOSHIBA 0x198
 #define UFS_VENDOR_SAMSUNG 0x1CE
 #define UFS_VENDOR_SKHYNIX 0x1AD
 
 /**
- * ufs_device_info - ufs device details
- * @wmanufacturerid: card details
- * @model: card model
- */
-struct ufs_device_info {
-   u16 wmanufacturerid;
-   char model[MAX_MODEL_LEN + 1];
-};
-
-/**
  * ufs_dev_fix - ufs device quirk info
  * @card: ufs card details
  * @quirk: device quirk
  */
 struct ufs_dev_fix {
-   struct ufs_device_info card;
+   struct ufs_dev_desc card;
unsigned int quirk;
 };
 
 #define END_FIX { { 0 }, 0 }
 
 /* add specific device quirk */
-#define UFS_FIX(_vendor, _model, _quirk) \
-   { \
-   .card.wmanufacturerid = (_vendor),\
-   .card.model = (_model),   \
-   .quirk = (_quirk),\
-   }
+#define UFS_FIX(_vendor, _model, _quirk) { \
+   .card.wmanufacturerid = (_vendor),\
+   .card.model = (_model),\
+   .quirk = (_quirk), \
+}
 
 /*
  * If UFS device is having issue in processing LCC (Line Control
@@ -144,7 +131,4 @@ struct ufs_dev_fix {
  */
 #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME(1 << 8)
 
-struct ufs_hba;
-void ufs_advertise_fixup_device(struct ufs_hba *hba);
-
 #endif /* UFS_QUIRKS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index fdea08f79b7d..53b3ec40a7b0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5008,8 +5008,8 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
return ret;
 }
 
-static int ufs_get_device_info(struct ufs_hba *hba,
-   struct ufs_device_info *card_data)
+static int ufs_get_device_desc(struct ufs_hba *hba,
+  struct ufs_dev_desc *dev_desc)
 {
int err;
u8 model_index;
@@ -5028,7 +5028,7 @@ static int ufs_get_device_info(struct ufs_hba *hba,
 * getting vendor (manufacturerID) and Bank Index in big endian
 * format
 */
-   card_data->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 |
+   dev_desc->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 |
 desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1];
 
model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
@@ -5042,36 +5042,26 @@ static int ufs_get_device_info(struct ufs_hba *hba,
}
 
str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0';
-   strlcpy(card_data->model, (str_desc_buf + QUERY_DESC_HDR_SIZE),
+   strlcpy(dev_desc->model, (str_desc_buf + QUERY_DESC_HDR_SIZE),
min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET],
  MAX_MODEL_LEN));
 
/* Null terminate the model string */
-   card_data->model[MAX_MODEL_LEN] = '\0';
+   dev_desc->model[MAX_MODEL_LEN] = '\0';
 
 out:
return err;
 }
 
-void ufs_advertise_fixup_device(struct ufs_hba *hba)
+static void ufs_fixup_device_setup(struct ufs_hba *hba,
+  struct ufs_dev_desc *dev_desc)
 {
-   int err;
struct ufs_dev_fix *f;
-   struct ufs_device_info card_data;
-
-   card_data.wmanufacturerid = 0;
-
-   err = ufs_get_device_info(hba, &card_data);
-   if (err) {
-   dev_err(hba->dev, "%s: Failed getting device info. err = %d\n",
-   __func__, err);
-   

[scsi 1/4] scsi: ufs: ufshcd_query_descriptor_retry should be static

2017-01-04 Thread Tomas Winkler
Fix the following compilation warning:

drivers/scsi/ufs/ufshcd.c:2076:5: warning: no previous prototype for
‘ufshcd_query_descriptor_retry’ [-Wmissing-prototypes]

Also do not export the function, it should not be used out of ufs
context.

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 20e5e5fb048c..be3c2900b6bb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2073,9 +2073,11 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
  * The buf_len parameter will contain, on return, the length parameter
  * received on the response.
  */
-int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
-   enum query_opcode opcode, enum desc_idn idn, u8 index,
-   u8 selector, u8 *desc_buf, int *buf_len)
+static int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
+enum query_opcode opcode,
+enum desc_idn idn, u8 index,
+u8 selector,
+u8 *desc_buf, int *buf_len)
 {
int err;
int retries;
@@ -2089,7 +2091,6 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
 
return err;
 }
-EXPORT_SYMBOL(ufshcd_query_descriptor_retry);
 
 /**
  * ufshcd_read_desc_param - read the specified descriptor parameter
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 2/4] scsi: ufs: unexport descritpor reading functions

2017-01-04 Thread Tomas Winkler
Unexport ufshcd_read_device_desc and ufshcd_read_string_desc
there is no really possibility to calling them directly
outside of UFS context.

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 9 -
 drivers/scsi/ufs/ufshcd.h | 7 ---
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index be3c2900b6bb..63d7ae2c3be9 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2208,11 +2208,10 @@ static inline int ufshcd_read_power_desc(struct ufs_hba 
*hba,
return err;
 }
 
-int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size)
+static int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size)
 {
return ufshcd_read_desc(hba, QUERY_DESC_IDN_DEVICE, 0, buf, size);
 }
-EXPORT_SYMBOL(ufshcd_read_device_desc);
 
 /**
  * ufshcd_read_string_desc - read string descriptor
@@ -2224,8 +2223,9 @@ EXPORT_SYMBOL(ufshcd_read_device_desc);
  *
  * Return 0 in case of success, non-zero otherwise
  */
-int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
-   u32 size, bool ascii)
+#define ASCII_STD true
+static int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
+  u8 *buf, u32 size, bool ascii)
 {
int err = 0;
 
@@ -2281,7 +2281,6 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int 
desc_index, u8 *buf,
 out:
return err;
 }
-EXPORT_SYMBOL(ufshcd_read_string_desc);
 
 /**
  * ufshcd_read_unit_desc_param - read the specified unit descriptor parameter
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 08cd26ed2382..00fb82589895 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -713,8 +713,6 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
 }
 
-int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size);
-
 static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
 {
return (pwr_info->pwr_rx == FAST_MODE ||
@@ -723,11 +721,6 @@ static inline bool ufshcd_is_hs_mode(struct 
ufs_pa_layer_attr *pwr_info)
pwr_info->pwr_tx == FASTAUTO_MODE);
 }
 
-#define ASCII_STD true
-
-int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
-   u32 size, bool ascii);
-
 /* Expose Query-Request API */
 int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
enum flag_idn idn, bool *flag_res);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 3/4] scsi: ufs: ufshcd_get_max_icc_level fix endianity handling

2017-01-04 Thread Tomas Winkler
Reading big endian value from a buffer requires explicit cast.
Fix sparse warning:
drivers/scsi/ufs/ufshcd.c:4825:24: warning: cast to restricted __be16

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 63d7ae2c3be9..fdea08f79b7d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4822,7 +4822,7 @@ static u32 ufshcd_get_max_icc_level(int sup_curr_uA, u32 
start_scan, char *buff)
u16 unit;
 
for (i = start_scan; i >= 0; i--) {
-   data = be16_to_cpu(*((u16 *)(buff + 2*i)));
+   data = be16_to_cpup((__be16 *)&buff[2 * i]);
unit = (data & ATTR_ICC_LVL_UNIT_MASK) >>
ATTR_ICC_LVL_UNIT_OFFSET;
curr_uA = data & ATTR_ICC_LVL_VALUE_MASK;
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 03/11] rpmb: add sysfs-class ABI documentation

2016-11-07 Thread Tomas Winkler
V2: resend
V3: add more verbose description
V4: resend
V5: adjust date and kernel version
V6: adjust date and kernel version
V7: adjust date and kernel version

Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-class-rpmb | 20 
 MAINTAINERS|  1 +
 2 files changed, 21 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
new file mode 100644
index ..2ea6dbb91fac
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -0,0 +1,20 @@
+What:  /sys/class/rpmb/
+Date:  Nov 2016
+KernelVersion:  4.10
+Contact:   Tomas Winkler 
+Description:
+   The rpmb/ class sub-directory belongs to RPMB device class.
+
+   Few storage technologies such is EMMC, UFS, and NVMe support
+   Replay Protected Memory Block (RPMB) hardware partition with
+   common protocol and frame layout.
+   Such a partition provides authenticated and replay protected 
access,
+   hence suitable as a secure storage.
+
+What:  /sys/class/rpmb/rpmbN/
+Date:  Nov 2016
+KernelVersion: 4.10
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN directory is created for
+   each RPMB registered device.
diff --git a/MAINTAINERS b/MAINTAINERS
index 7bae7c014af0..4c8ab6c09f3a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10290,6 +10290,7 @@ L:  linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
 F: include/linux/rpmb.h
+F: Documentation/ABI/testing/sysfs-class-rpmb
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 00/11] char:rpmb: Replay Protected Memory Block (RPMB) subsystem

2016-11-07 Thread Tomas Winkler
Few storage technologies such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but by a
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and
PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.

The layer provides two APIs, for rpmb_req_cmd() for issuing one of RPMB
specific commands and rpmb_seq_cmd() for issuing of raw RPMB protocol
frames,  which is close to the functionality provided by emmc multi ioctl
interface.

A TEE driver can claim the RPMB interface, for example, via
class_interface_register ().

A storage device registers its RPMB hardware (eMMC) partition or RPMB
W-LUN (UFS) with the RPMB layer providing an implementation for
rpmb_seq_cmd() handler. The interface enables sending sequence of RPMB
standard frames.

A parallel user space API is provided via /dev/rpmbX character
device with two IOCTL commands.
Simplified one, RPMB_IOC_REQ_CMD, were read result cycles is performed
by the framework on behalf the user and second, RPMB_IOC_SEQ_CMD where
the whole RPMB sequence, including RESULT_READ is supplied by the caller.
The latter is intended for easier adjusting of the applications that
use MMC_IOC_MULTI_CMD ioctl, such as
https://android.googlesource.com/trusty/app/storage/

There is a also sample tool under tools/rpmb/ directory that exercises
these interfaces and a simulation device that implements the device part.

The code is also available from:

https://github.com/tomasbw/linux-mei.git rpmb

V7  1. Special thanks to Avri Altman  for testing emmc 
and ufs.
2. Fix char device interface.
3. Add Documentation
4. Addional small fixes described in individual patches.

Tomas Winkler (11):
  rpmb: add Replay Protected Memory Block (RPMB) subsystem
  rpmb: enable emmc specific read data fixup
  rpmb: add sysfs-class ABI documentation
  char: rpmb: add device attributes
  char: rpmb: provide a user space interface
  char: rpmb: add RPMB simulation device
  tools rpmb: add RPBM access tool
  mmc: block: register RPMB partition with the RPMB subsystem
  scsi: ufs: connect to RPMB subsystem
  scsi: ufs: retrieve rpmb rw size
  char: rpmb: Document Replay Protected Memory Block (RPMB) subsystem

 Documentation/ABI/testing/sysfs-class-rpmb |   47 ++
 Documentation/index.rst|1 +
 Documentation/ioctl/ioctl-number.txt   |1 +
 Documentation/rpmb/conf.py |5 +
 Documentation/rpmb/index.rst   |   18 +
 Documentation/rpmb/introduction.rst|  102 +++
 Documentation/rpmb/rpmb-tool.rst   |   19 +
 Documentation/rpmb/simulation-device.rst   |   19 +
 MAINTAINERS|   11 +
 drivers/char/Kconfig   |2 +
 drivers/char/Makefile  |1 +
 drivers/char/rpmb/Kconfig  |   32 +
 drivers/char/rpmb/Makefile |6 +
 drivers/char/rpmb/cdev.c   |  331 +
 drivers/char/rpmb/core.c   |  523 ++
 drivers/char/rpmb/rpmb-cdev.h  |   25 +
 drivers/char/rpmb/rpmb_sim.c   |  744 
 drivers/mmc/card/Kconfig   |1 +
 drivers/mmc/card/block.c   |  258 ++-
 drivers/scsi/ufs/Kconfig   |1 +
 drivers/scsi/ufs/ufs.h |6 +
 drivers/scsi/ufs/ufshcd.c  |  205 ++
 drivers/scsi/ufs/ufshcd.h  |2 +
 include/linux/rpmb.h   |  167 +
 include/uapi/linux/Kbuild  |1 +
 include/uapi/linux/rpmb.h  |  153 
 tools/Makefile |   14 +-
 tools/rpmb/.gitignore  |2 +
 tools/rpmb/Makefile|   34 +
 tools/rpmb/rpmb.c  | 1035 
 30 files changed, 3758 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb
 create mode 100644 Documentation/rpmb/conf.py
 create mode 100644 Documentation/rpmb/index.rst
 create mode 100644 Documentation/rpmb/introduction.rst
 create mode 100644 Documentation/rpmb/rpmb-tool.rst
 create mode 100644 Documentation/rpmb/simulation-device.rst
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create

[PATCH v7 01/11] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2016-11-07 Thread Tomas Winkler
Few storage technologies such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer,
but by a set of specific commands: WRITE, READ, GET_WRITE_COUNTER,
and PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE device driver can claim the RPMB interface, for example, via
class_interface_register ().
The layer provides two APIs rpmb_cmd_req() for issuing one of RPMB
specific commands and rpmb_cmd_seq() for issuing of raw RPMB protocol
frames sequence.
The major difference between the APIs is that for rpmb_cmd_req() the
framework performs RPMB_RESULT_READ operation on behalf of a user.
The RPMB_RESULT_READ is used for retrieving result of the commands
that carry data in the write cycle and need one more step to retrieve
the result.

A storage device registers its RPMB (eMMC) partition or RPMB
W-LUN (UFS) with the RPMB layer providing an implementation for
rpmb_cmd_seq() handler. The interface enables sending sequence of RPMB
standard frames.

V2: added short workflow description in the commit message
V3: commit message fix
V4: resend
V5: add rpmb sequence interface.
V6: 1. More info in the commit message
2. Define simulation device type
V7: resend

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 MAINTAINERS|   7 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |   8 +
 drivers/char/rpmb/Makefile |   4 +
 drivers/char/rpmb/core.c   | 414 +
 include/linux/rpmb.h   | 232 +
 7 files changed, 668 insertions(+)
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 include/linux/rpmb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 3d838cf49f81..7bae7c014af0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10284,6 +10284,13 @@ F: include/net/rose.h
 F: include/uapi/linux/rose.h
 F: net/rose/
 
+RPMB SUBSYSTEM
+M: Tomas Winkler 
+L: linux-ker...@vger.kernel.org
+S: Supported
+F: drivers/char/rpmb/*
+F: include/linux/rpmb.h
+
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index dc4f35ad19d0..220c86663b25 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -589,5 +589,7 @@ config TILE_SROM
 
 source "drivers/char/xillybus/Kconfig"
 
+source "drivers/char/rpmb/Kconfig"
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 6e6c244a66a0..3a0cac3ff2dc 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -60,3 +60,4 @@ js-rtc-y = rtc.o
 obj-$(CONFIG_TILE_SROM)+= tile-srom.o
 obj-$(CONFIG_XILLYBUS) += xillybus/
 obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
+obj-$(CONFIG_RPMB) += rpmb/
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
new file mode 100644
index ..c5e6e909efce
--- /dev/null
+++ b/drivers/char/rpmb/Kconfig
@@ -0,0 +1,8 @@
+config RPMB
+   tristate "RPMB partition interface"
+   help
+ Unified RPMB partition interface for eMMC and UFS.
+ Provides interface for in kernel security controllers to
+ access RPMB partition.
+
+ If unsure, select N.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
new file mode 100644
index ..812b3ed264c0
--- /dev/null
+++ b/drivers/char/rpmb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RPMB) += rpmb.o
+rpmb-objs += core.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
new file mode 100644
index ..ff10cbb7b644
--- /dev/null
+++ b/drivers/char/rpmb/core.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 

[PATCH v7 02/11] rpmb: enable emmc specific read data fixup

2016-11-07 Thread Tomas Winkler
For eMMC the block count of the RPMB read operation is not indicated in
the original RPMB Data Read Request packet.
This might be different then the implementation of other protocol
standards.
This patch implements a fixup for this behavior.

V6: new in the series
V7: resend

Signed-off-by: Tomas Winkler 
---
 drivers/char/rpmb/core.c | 36 +---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index ff10cbb7b644..8cfbbb721538 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -117,6 +117,35 @@ static int rpmb_request_verify(struct rpmb_dev *rdev, 
struct rpmb_data *rpmbd)
 }
 
 /**
+ * rpmb_cmd_fixup - fixup rpmb command
+ *
+ * @rdev: rpmb device
+ * @cmds: rpmb command list
+ * @ncmds: number of commands
+ *
+ */
+static void rpmb_cmd_fixup(struct rpmb_dev *rdev,
+  struct rpmb_cmd *cmds, u32 ncmds)
+{
+   int i;
+
+   if (rdev->ops->type != RPMB_TYPE_EMMC)
+   return;
+
+   /* Fixup RPMB_READ_DATA specific to eMMC
+* The block count of the RPMB read operation is not indicated
+* in the original RPMB Data Read Request packet.
+* This is different then implementation for other protocol
+* standards.
+*/
+   for (i = 0; i < ncmds; i++)
+   if (cmds->frames->req_resp == cpu_to_be16(RPMB_READ_DATA)) {
+   dev_dbg(&rdev->dev, "Fixing up READ_DATA frame to 
block_count=0\n");
+   cmds->frames->block_count = 0;
+   }
+}
+
+/**
  * rpmb_cmd_seq - send RPMB command sequence
  *
  * @rdev: rpmb device
@@ -136,10 +165,11 @@ int rpmb_cmd_seq(struct rpmb_dev *rdev, struct rpmb_cmd 
*cmds, u32 ncmds)
return -EINVAL;
 
mutex_lock(&rdev->lock);
-   if (rdev->ops && rdev->ops->cmd_seq)
+   err = -EOPNOTSUPP;
+   if (rdev->ops && rdev->ops->cmd_seq) {
+   rpmb_cmd_fixup(rdev, cmds, ncmds);
err = rdev->ops->cmd_seq(rdev->dev.parent, cmds, ncmds);
-   else
-   err = -EOPNOTSUPP;
+   }
mutex_unlock(&rdev->lock);
return err;
 }
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 06/11] char: rpmb: add RPMB simulation device

2016-11-07 Thread Tomas Winkler
The RPMB partition simulation device is a virtual device that
provides simulation of the RPMB protocol and use kernel memory
as storage.

Be aware it doesn't promise any real security. This driver is
suitable only for testing of the RPMB subsystem or RPMB
applications prior to RPMB key provisioning, as RPMB key
programming can be performed only once in the life time of the
storage device.

The module currently supports two configuration options via
module parameters
1. max_wr_blks: for specifying max blocks that can be written
in a single command
2. daunits:  used to set storage capacity in 128K units.

V2: remove .owner setting, it is set automatically
V3: 1. Add shutdown handler (similar to ufshcd)
2. Commit message fix
V4: Use select RPMB in Kconfg to ensure valid configuration.
V5: Revamp the code using the sequence command.
V6: 1. Be more verbose about some errors, after all this is a testing
module.
2. Fix RPMB_READ_DATA:
   a. The number of blocks for eMMC request frame should be 0
   b. Fix missing return before bailing on error
   c. Copy all the frames back
3. Fix RPMB_WRITE_DATA:
   a. Compute MAC on result packet
   b. Also address should be set in the result frame.
4. Remove platform device
5. Update the commit message
V7: Resend.

Signed-off-by: Tomas Winkler 
---
 drivers/char/rpmb/Kconfig|  17 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/rpmb_sim.c | 744 +++
 3 files changed, 762 insertions(+)
 create mode 100644 drivers/char/rpmb/rpmb_sim.c

diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index 6794be9fcc5e..533d813e9ed5 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -13,3 +13,20 @@ config RPMB_INTF_DEV
help
  Say yes here if you want to access RPMB from user space
  via character device interface /dev/rpmb%d
+
+
+config RPMB_SIM
+   tristate "RPMB partition device simulator"
+   default n
+   select RPMB
+   select CRYPTO_SHA256
+   select CRYPTO_HMAC
+   help
+ RPMB partition simulation device is a virtual device that
+ provides simulation of the RPMB protocol and use kernel memory
+ as storage.
+
+ Be aware it doesn't promise any real security. This driver is
+ suitable only for testing of the RPMB subsystem or RPMB applications
+ prior to RPMB key provisioning.
+  Most people should say N here.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index b5dc087b1299..81f924fd9a87 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
 rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
+obj-$(CONFIG_RPMB_SIM) += rpmb_sim.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/rpmb_sim.c b/drivers/char/rpmb/rpmb_sim.c
new file mode 100644
index ..429a08bd67d7
--- /dev/null
+++ b/drivers/char/rpmb/rpmb_sim.c
@@ -0,0 +1,744 @@
+/**
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Corporation.
+ * linux-...@linux.intel.com
+ * http://www.intel.com
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *contributors may be used to endorse or promote products derived
+ *from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

[PATCH v7 05/11] char: rpmb: provide a user space interface

2016-11-07 Thread Tomas Winkler
The user space API is achieved via two synchronous IOCTLs.
Simplified one, RPMB_IOC_REQ_CMD, were read result cycles is performed
by the framework on behalf the user and second, RPMB_IOC_SEQ_CMD where
the whole RPMB sequence including RESULT_READ is supplied by the caller.
The latter is intended for easier adjusting of the applications that
use MMC_IOC_MULTI_CMD ioctl.

V2: use memdup_user
V3: commit message fix
V4: resend
V5: 1. Add RPMB_IOC_SEQ_CMD API.
2. Export uapi rpmb.h header
V6: 1. Remove #include .
2. Add ioctl documentation.
V7: 1. copy_from_user the value of the frame pointer.
2. Fix possible macro side-effect due to macro argument reuse.

Signed-off-by: Tomas Winkler 
---
 Documentation/ioctl/ioctl-number.txt |   1 +
 MAINTAINERS  |   1 +
 drivers/char/rpmb/Kconfig|   7 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/cdev.c | 331 +++
 drivers/char/rpmb/core.c |   9 +-
 drivers/char/rpmb/rpmb-cdev.h|  25 +++
 include/linux/rpmb.h |  81 +
 include/uapi/linux/Kbuild|   1 +
 include/uapi/linux/rpmb.h| 153 
 10 files changed, 536 insertions(+), 74 deletions(-)
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 include/uapi/linux/rpmb.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 81c7f2bb7daf..f645543866c7 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -321,6 +321,7 @@ Code  Seq#(hex) Include FileComments
 0xB1   00-1F   PPPoX   <mailto:mostr...@styx.uwaterloo.ca>
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h<mailto:linux-g...@vger.kernel.org>
+0xB5   00-01   linux/uapi/linux/rpmb.h <mailto:linux-...@linux.intel.com>
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-8F   uapi/scsi/cxlflash_ioctl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 4c8ab6c09f3a..090b6d2d31fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10289,6 +10289,7 @@ M:  Tomas Winkler 
 L: linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
+F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
 
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index c5e6e909efce..6794be9fcc5e 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -6,3 +6,10 @@ config RPMB
  access RPMB partition.
 
  If unsure, select N.
+
+config RPMB_INTF_DEV
+   bool "RPMB character device interface /dev/rpmbN"
+   depends on RPMB
+   help
+ Say yes here if you want to access RPMB from user space
+ via character device interface /dev/rpmb%d
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index 812b3ed264c0..b5dc087b1299 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
+rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
new file mode 100644
index ..9e3ae753a9a1
--- /dev/null
+++ b/drivers/char/rpmb/cdev.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "rpmb-cdev.h"
+
+static dev_t rpmb_devt;
+#define RPMB_MAX_DEVS  MINORMASK
+
+#define RPMB_DEV_OPEN0  /** single open bit (position) */
+/* from MMC_IOC_MAX_CMDS */
+#define RPMB_MAX_FRAMES 255
+
+/**
+ * rpmb_open - the open function
+ *
+ * @inode: pointer to inode structure
+ * @fp: pointer to file structure
+ *
+ * Return: 0 on success, <0 on error
+ */
+static int rpmb_open(struct inode *inode, struct file *fp)
+{
+   struct rpmb_dev *rdev;
+
+   rdev = container_of(inode->i_cdev, struct rpmb_dev, cdev);
+   if (!rdev)
+   return -ENODEV;
+
+   /* the rpmb is single open! */
+   if (test_and_set_bit(RPMB_DEV_OPEN, &rdev->status))
+   return -EBUSY;
+
+   mutex_lock(&rdev->lock);
+
+   fp->private_data = rdev;
+
+   mutex_unlock(&rdev-&g

[PATCH v7 04/11] char: rpmb: add device attributes

2016-11-07 Thread Tomas Winkler
Add attribute type that displays underlay storage type technology
EMMC, UFS, and attribute id, that displays underlay storage device id.
For EMMC this would be content of CID and for UFS serial number from
the device descriptor.

V2: resend
V3: set kernel version to 4.7
V4: update target date to Maj
V5: update date and kernel version
V6: 1. Add simulation device type
2. Update date and kernel version
3. Use binary attribute for id
4. use simple sprintf instead of scnprintf
5. Add more verbose documenation
V7: resend

Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-class-rpmb | 27 +++
 drivers/char/rpmb/core.c   | 72 ++
 2 files changed, 99 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
index 2ea6dbb91fac..3c01925e29dc 100644
--- a/Documentation/ABI/testing/sysfs-class-rpmb
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -18,3 +18,30 @@ Contact: Tomas Winkler 
 Description:
The /sys/class/rpmb/rpmbN directory is created for
each RPMB registered device.
+
+What:  /sys/class/rpmb/rpmbN/type
+Date:  Nov 2016
+KernelVersion: 4.10
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/type file contains device
+   underlaying storage type technology: EMMC, UFS, SIM.
+
+What:  /sys/class/rpmb/rpmbN/id
+Date:  Nov 2016
+KernelVersion: 4.10
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/id file contains unique device id
+   in a binary form as defined by underlying storage device.
+   In case of multiple RPMB devices a user can determine correct
+   device.
+   The content can be parsed according the storage device type.
+
+What:  /sys/class/rpmb/rpmbN/reliable_wr_cnt
+Date:  Nov 2016
+KernelVersion: 4.10
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/reliable_wr_cnt file contains
+   number of blocks that can be reliable written in a single 
request.
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index 8cfbbb721538..f6b4cabb0982 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -338,6 +338,76 @@ struct rpmb_dev *rpmb_dev_find_by_device(struct device 
*parent)
 }
 EXPORT_SYMBOL_GPL(rpmb_dev_find_by_device);
 
+static ssize_t type_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   ssize_t ret;
+
+   switch (rdev->ops->type) {
+   case RPMB_TYPE_EMMC:
+   ret = sprintf(buf, "EMMC\n");
+   break;
+   case RPMB_TYPE_UFS:
+   ret = sprintf(buf, "UFS\n");
+   break;
+   case RPMB_TYPE_SIM:
+   ret = sprintf(buf, "SIM\n");
+   break;
+   default:
+   ret = sprintf(buf, "UNKNOWN\n");
+   break;
+   }
+
+   return ret;
+}
+static DEVICE_ATTR_RO(type);
+
+static ssize_t id_read(struct file *file, struct kobject *kobj,
+  struct bin_attribute *attr, char *buf,
+  loff_t off, size_t count)
+{
+   struct device *dev = kobj_to_dev(kobj);
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   size_t sz = min_t(size_t, rdev->ops->dev_id_len, PAGE_SIZE);
+
+   if (!rdev->ops->dev_id)
+   return 0;
+
+   return memory_read_from_buffer(buf, count, &off, rdev->ops->dev_id, sz);
+}
+static BIN_ATTR_RO(id, 0);
+
+static ssize_t reliable_wr_cnt_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+
+   return sprintf(buf, "%u\n", rdev->ops->reliable_wr_cnt);
+}
+static DEVICE_ATTR_RO(reliable_wr_cnt);
+
+static struct attribute *rpmb_attrs[] = {
+   &dev_attr_type.attr,
+   &dev_attr_reliable_wr_cnt.attr,
+   NULL,
+};
+
+static struct bin_attribute *rpmb_bin_attributes[] = {
+   &bin_attr_id,
+   NULL,
+};
+
+static struct attribute_group rpmb_attr_group = {
+   .attrs = rpmb_attrs,
+   .bin_attrs = rpmb_bin_attributes,
+};
+
+static const struct attribute_group *rpmb_attr_groups[] = {
+   &rpmb_attr_group,
+   NULL
+};
+
 /**
  * rpmb_dev_unregister - unregister RPMB partition from the RPMB subsystem
  *
@@ -407,6 +477,8 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
dev_set_name(&rdev->dev, "rpmb%d", id);
rdev->dev.class = &rpmb_class;
rdev->dev.parent = dev;
+   rdev->dev.groups = rpmb_attr_groups;
+
ret = device_register(&rdev->dev);
if (ret)

[PATCH v7 11/11] char: rpmb: Document Replay Protected Memory Block (RPMB) subsystem

2016-11-07 Thread Tomas Winkler
Add rpmb documentatin in sphinx format.

V7: new in the series

Signed-off-by: Tomas Winkler 
---
 Documentation/index.rst  |   1 +
 Documentation/rpmb/conf.py   |   5 ++
 Documentation/rpmb/index.rst |  18 ++
 Documentation/rpmb/introduction.rst  | 102 +++
 Documentation/rpmb/rpmb-tool.rst |  19 ++
 Documentation/rpmb/simulation-device.rst |  19 ++
 MAINTAINERS  |   1 +
 7 files changed, 165 insertions(+)
 create mode 100644 Documentation/rpmb/conf.py
 create mode 100644 Documentation/rpmb/index.rst
 create mode 100644 Documentation/rpmb/introduction.rst
 create mode 100644 Documentation/rpmb/rpmb-tool.rst
 create mode 100644 Documentation/rpmb/simulation-device.rst

diff --git a/Documentation/index.rst b/Documentation/index.rst
index c53d089455a4..56dd46e9359c 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -18,6 +18,7 @@ Contents:
media/index
gpu/index
80211/index
+   rpmb/index
 
 Indices and tables
 ==
diff --git a/Documentation/rpmb/conf.py b/Documentation/rpmb/conf.py
new file mode 100644
index ..20c7c275ef4a
--- /dev/null
+++ b/Documentation/rpmb/conf.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "Linux 802.11 Driver Developer's Guide"
+
+tags.add("subproject")
diff --git a/Documentation/rpmb/index.rst b/Documentation/rpmb/index.rst
new file mode 100644
index ..876a2603e4b5
--- /dev/null
+++ b/Documentation/rpmb/index.rst
@@ -0,0 +1,18 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+==
+Replay Protected Memory Block (RPMB) subsystem
+==
+
+.. toctree::
+
+   introduction
+   simulation-device.rst
+   rpmb-tool.rst
+
+.. only::  subproject
+
+   Indices
+   ===
+
+   * :ref:`genindex`
diff --git a/Documentation/rpmb/introduction.rst 
b/Documentation/rpmb/introduction.rst
new file mode 100644
index ..f4ded7d18e55
--- /dev/null
+++ b/Documentation/rpmb/introduction.rst
@@ -0,0 +1,102 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+=
+Introduction:
+=
+
+Few storage technologies such is EMMC, UFS, and NVMe support RPMB
+hardware partition with common protocol and frame layout.
+The RPMB partition `cannot` be accessed via standard block layer,
+but by a set of specific commands:
+
+WRITE, READ, GET_WRITE_COUNTER, and PROGRAM_KEY.
+
+The commands and the data are embedded within :c:type:`rpmb_frame 
`.
+
+An RPMB partition provides authenticated and replay protected access,
+hence it is suitable as a secure storage.
+
+In-kernel API
+-
+The RPMB layer aims to provide in-kernel API for Trusted Execution
+Environment (TEE) devices that are capable to securely compute the block
+frame signature. In case a TEE device wish to store a replay protected
+data, it creates an RPMB frame with requested data and computes HMAC of
+the frame, then it requests the storage device via RPMB layer to store
+the data.
+
+The layer provides two APIs, for :c:func:`rpmb_req_cmd()` for issuing one of 
RPMB
+specific commands and :c:func:`rpmb_seq_cmd()` for issuing of raw RPMB protocol
+frames, which is close to the functionality provided by emmc multi ioctl
+interface.
+
+.. c:function:: int rpmb_cmd_req(struct rpmb_dev *rdev, struct rpmb_data 
*data);
+
+.. c:function:: int rpmb_cmd_seq(struct rpmb_dev *rdev, struct rpmb_cmd *cmds, 
u32 ncmds);
+
+
+A TEE driver can claim the RPMB interface, for example, via
+:c:func:`class_interface_register`:
+
+.. code-block:: c
+
+struct class_interface tee_rpmb_intf = {
+.class  = &rpmb_class;
+.add_dev= rpmb_add_device;
+.remove_dev = rpmb_remove_device;
+}
+class_interface_register(&tee_rpmb_intf);
+
+
+RPMB device registeration
+
+
+A storage device registers its RPMB hardware (eMMC) partition or RPMB
+W-LUN (UFS) with the RPMB layer :c:func:`rpmb_dev_register` providing
+an implementation for :c:func:`rpmb_seq_cmd()` handler. The interface
+enables sending sequence of RPMB standard frames.
+
+.. code-block:: c
+
+struct rpmb_ops mmc_rpmb_dev_ops = {
+.cmd_seq = mmc_blk_rpmb_cmd_seq,
+.type = RPMB_TYPE_EMMC,
+...
+}
+rpmb_dev_register(disk_to_dev(part_md->disk), &mmc_rpmb_dev_ops);
+
+
+User space API
+--
+
+A parallel user space API is provided via /dev/rpmbX character
+device with two IOCTL commands.
+Simplified one, ``RPMB_IOC_REQ_CMD``, were read result cycles is performed
+by the framework on behalf the user and second, ``RPMB_IOC_SEQ_CMD`` where
+the whole RPMB sequence, including ``RESULT_READ`` is supplied by the caller.
+The latter is intended for easier adjusting of the applications that
+use ``M

[PATCH v7 09/11] scsi: ufs: connect to RPMB subsystem

2016-11-07 Thread Tomas Winkler
Register UFS RPMB LUN with the RPMB subsystem and provide
implementation for the RPMB access operations. RPMB partition is
accessed via a sequence of security protocol in and security protocol
out commands with UFS specific parameters. This multi step process is
abstracted into 4 basic RPMB commands.

V2: resend
V3: resend
V4: Kconfig: use select RPMB to ensure valid configuration
V5: Revamp code using new sequence command.
V6: Resend
V7: Resend

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/Kconfig  |   1 +
 drivers/scsi/ufs/ufshcd.c | 183 ++
 drivers/scsi/ufs/ufshcd.h |   2 +
 3 files changed, 186 insertions(+)

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e27b4d4e6ae2..8b545a9c51dd 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -38,6 +38,7 @@ config SCSI_UFSHCD
select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select NLS
+   select RPMB
---help---
This selects the support for UFS devices in Linux, say Y and make
  sure that you know the name of your UFS host adapter (the card
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 05c745663c10..95bb9dc7fbfe 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -37,10 +37,13 @@
  * license terms, and distributes only under these terms.
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -4753,6 +4756,178 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 
 }
 
+#define SEC_PROTOCOL_UFS  0xEC
+#define   SEC_SPECIFIC_UFS_RPMB 0x0001
+
+#define SEC_PROTOCOL_CMD_SIZE 12
+#define SEC_PROTOCOL_RETRIES 3
+#define SEC_PROTOCOL_RETRIES_ON_RESET 10
+#define SEC_PROTOCOL_TIMEOUT msecs_to_jiffies(1000)
+
+static int
+ufshcd_rpmb_security_out(struct scsi_device *sdev,
+struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 trans_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_OUT;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0;  /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(trans_len, cmd + 6);  /* transfer length */
+
+retry:
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_TO_DEVICE,
+frames, trans_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /*
+* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   dev_err(&sdev->sdev_gendev, "%s: failed with err %0x\n",
+   __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security out", &sshdr);
+
+   return ret;
+}
+
+static int
+ufshcd_rpmb_security_in(struct scsi_device *sdev,
+   struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 alloc_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_IN;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0; /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(alloc_len, cmd + 6); /* allocation length */
+
+retry:
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_FROM_DEVICE,
+frames, alloc_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /*
+* Device reset might occur several times,
+* give it one more chance
+   */
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+  

[PATCH v7 10/11] scsi: ufs: retrieve rpmb rw size

2016-11-07 Thread Tomas Winkler
Retrieve maximum number of RPMB frames that can be
in a single request.
Currently the limitations is provided only for writes
via reliable_wr_cnt API.

V7: New in the series

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 drivers/scsi/ufs/ufs.h|  6 ++
 drivers/scsi/ufs/ufshcd.c | 22 ++
 2 files changed, 28 insertions(+)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 845b874e2977..84bb8d7c6b63 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -176,6 +176,12 @@ enum ufs_desc_max_size {
QUERY_DESC_RFU_MAX_SIZE = 0x00,
 };
 
+enum geometry_desc_param_offset {
+   GEOMETRY_DESC_LEN   = 0x0,
+   GEOMETRY_DESC_TYPE  = 0x1,
+   GEOMETRY_DESC_RPMB_RW_SIZE  = 0x17,
+};
+
 /* Unit descriptor parameters offsets in bytes*/
 enum unit_desc_param {
UNIT_DESC_PARAM_LEN = 0x0,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 95bb9dc7fbfe..69f5b03f6774 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2196,6 +2196,15 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
  param_offset, param_read_buf, param_size);
 }
 
+static inline int ufshcd_read_geometry_desc_param(struct ufs_hba *hba,
+   enum geometry_desc_param_offset param_offset,
+   u8 *param_read_buf, u32 param_size)
+{
+   return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0,
+ param_offset, param_read_buf, param_size);
+}
+
+
 /**
  * ufshcd_memory_alloc - allocate memory for host memory space data structures
  * @hba: per adapter instance
@@ -4896,6 +4905,19 @@ static struct rpmb_ops ufshcd_rpmb_dev_ops = {
 static inline void ufshcd_rpmb_add(struct ufs_hba *hba)
 {
struct rpmb_dev *rdev;
+   u8 rw_size;
+   int ret;
+
+   ret = ufshcd_read_geometry_desc_param(hba, GEOMETRY_DESC_RPMB_RW_SIZE,
+   &rw_size, sizeof(rw_size));
+   if (ret) {
+   dev_warn(hba->dev, "%s: cannot get rpmb rw limit %d\n",
+dev_name(hba->dev), ret);
+   /* fallback to singel frame write */
+   rw_size = 1;
+   }
+
+   ufshcd_rpmb_dev_ops.reliable_wr_cnt = rw_size;
 
scsi_device_get(hba->sdev_ufs_rpmb);
rdev = rpmb_dev_register(hba->dev, &ufshcd_rpmb_dev_ops);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 08/11] mmc: block: register RPMB partition with the RPMB subsystem

2016-11-07 Thread Tomas Winkler
Register eMMC RPMB partition with the RPMB subsystem and provide
implementation for the RPMB access operations abstracting
actual multi step process.

V2: resend
V3: commit message fix
V4: Kconfig: use select RPMB to ensure valid configuration
Switch back to main area after RPMB access
V5: Revamp code using new sequence command
Support for 8K packets in e.MMC v5.1
V6: Resend.
V7: Resend.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 drivers/mmc/card/Kconfig |   1 +
 drivers/mmc/card/block.c | 258 ++-
 2 files changed, 256 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 5562308699bc..537d0bc82781 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -7,6 +7,7 @@ comment "MMC/SD/SDIO Card Drivers"
 config MMC_BLOCK
tristate "MMC block device driver"
depends on BLOCK
+   select RPMB
default y
help
  Say Y here to enable the MMC block device driver support.
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 709a872ed484..523b2d6afc1c 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -112,6 +113,7 @@ struct mmc_blk_data {
 #define MMC_BLK_WRITE  BIT(1)
 #define MMC_BLK_DISCARDBIT(2)
 #define MMC_BLK_SECDISCARD BIT(3)
+#define MMC_BLK_RPMB   BIT(4)
 
/*
 * Only set in main mmc_blk_data associated
@@ -400,8 +402,8 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd 
__user *ic_ptr,
return 0;
 }
 
-static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
-  u32 retries_max)
+static int mmc_blk_rpmb_status_poll(struct mmc_card *card, u32 *status,
+   u32 retries_max)
 {
int err;
u32 retry_count = 0;
@@ -574,7 +576,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, 
struct mmc_blk_data *md,
 * Ensure RPMB command has completed by polling CMD13
 * "Send Status".
 */
-   err = ioctl_rpmb_card_status_poll(card, &status, 5);
+   err = mmc_blk_rpmb_status_poll(card, &status, 5);
if (err)
dev_err(mmc_dev(card->host),
"%s: Card Status=0x%08X, error %d\n",
@@ -1164,6 +1166,252 @@ int mmc_access_rpmb(struct mmc_queue *mq)
return false;
 }
 
+static int mmc_rpmb_send_cmd(struct mmc_card *card,
+unsigned int data_type, bool do_rel_wr,
+void *buf, u16 blks)
+{
+   int err;
+   u32 status;
+   struct mmc_command sbc = {
+   .opcode = MMC_SET_BLOCK_COUNT,
+   .flags  = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   struct mmc_command cmd = {
+   .flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
+   };
+
+   struct mmc_data data = {
+   .blksz = 512,
+   };
+   struct mmc_request mrq = {
+   .sbc= &sbc,
+   .cmd= &cmd,
+   .data   = &data,
+   .stop   = NULL,
+   };
+   struct scatterlist sg;
+
+   /*  set CMD23 */
+   sbc.arg = blks & 0x;
+   if (do_rel_wr)
+   sbc.arg |= MMC_CMD23_ARG_REL_WR;
+
+   /*  set CMD25/18 */
+   cmd.opcode = (data_type == MMC_DATA_WRITE) ?
+   MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
+
+   sg_init_one(&sg, buf, 512 * blks);
+
+   data.blocks = blks;
+   data.sg = &sg;
+   data.sg_len = 1;
+   data.flags  = data_type;
+   mmc_set_data_timeout(&data, card);
+
+   mmc_wait_for_req(card->host, &mrq);
+
+   if (cmd.error) {
+   dev_err(mmc_dev(card->host), "cmd error (%d)\n", cmd.error);
+   return cmd.error;
+   }
+
+   if (data.error) {
+   dev_err(mmc_dev(card->host), "data error (%d)\n", data.error);
+   return data.error;
+   }
+
+   err = mmc_blk_rpmb_status_poll(card, &status, 5);
+   if (err)
+   dev_err(mmc_dev(card->host), "Card Status=0x%08X, error %d\n",
+   status, err);
+   return err;
+}
+
+static int mmc_blk_rpmb_sequence(struct mmc_card *card,
+struct rpmb_cmd *cmds, u32 ncmds)
+{
+   int err, i;
+   struct rpmb_cmd *cmd;
+   unsigned int data_type;
+   bool do_rel_wr;
+
+   for (err = 0, i = 0; i < ncmds && !err; i++) {
+   cmd = &cmds[i];
+   if (cmd->flags & RPMB_F_WRITE) {
+   data_t

[PATCH v7 07/11] tools rpmb: add RPBM access tool

2016-11-07 Thread Tomas Winkler
Add simple RPMB host testing tool. It can be used
to program key, write and read data block, and retrieve
write counter.

V2: resend
V3: fix missing objtool
V4: add verbose option
V5: 1. Adjust to the new API.
2. Exercise both request and sequence ioctls.
V6: 1. Add includes to openssl/rand.h and endian.h
2. Fix some signed, unsigned comparisons
3. Check results more thoroughly
4. use HOSTCFLAGS in compilation
5. Allocate frames dynamically.
V7: 1. Fix rpmb_alloc_frames, it has always allocated one frame instead of
requested number.
2. Use an inline function instead of macro for rw blocking wrapper

Signed-off-by: Tomas Winkler 
---
 MAINTAINERS   |1 +
 tools/Makefile|   14 +-
 tools/rpmb/.gitignore |2 +
 tools/rpmb/Makefile   |   34 ++
 tools/rpmb/rpmb.c | 1035 +
 5 files changed, 1081 insertions(+), 5 deletions(-)
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 090b6d2d31fb..d9bca5134c7f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10292,6 +10292,7 @@ F:  drivers/char/rpmb/*
 F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
+F: tools/rpmb/
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
diff --git a/tools/Makefile b/tools/Makefile
index daa8fb3e4363..1d481b78063f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -20,6 +20,7 @@ help:
@echo '  lguest - a minimal 32-bit x86 hypervisor'
@echo '  net- misc networking tools'
@echo '  perf   - Linux performance measurement and 
analysis tool'
+   @echo '  rpmb   - Replay protected memory block access 
tool'
@echo '  selftests  - various kernel selftests'
@echo '  spi- spi tools'
@echo '  objtool- an ELF object analysis tool'
@@ -56,7 +57,7 @@ acpi: FORCE
 cpupower: FORCE
$(call descend,power/$@)
 
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio gpio objtool: FORCE
$(call descend,$@)
 
 liblockdep: FORCE
@@ -86,7 +87,7 @@ freefall: FORCE
$(call descend,laptop/$@)
 
 all: acpi cgroup cpupower gpio hv firewire lguest \
-   perf selftests turbostat usb \
+   perf rpmb selftests turbostat usb \
virtio vm net x86_energy_perf_policy \
tmon freefall objtool
 
@@ -96,7 +97,7 @@ acpi_install:
 cpupower_install:
$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install gpio_install hv_install lguest_install 
perf_install usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install gpio_install hv_install lguest_install 
perf_install rpmb_install usb_install virtio_install vm_install net_install 
objtool_install:
$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -116,7 +117,7 @@ kvm_stat_install:
 
 install: acpi_install cgroup_install cpupower_install gpio_install \
hv_install firewire_install lguest_install \
-   perf_install selftests_install turbostat_install usb_install \
+   perf_install rpmb_install selftests_install turbostat_install 
usb_install \
virtio_install vm_install net_install 
x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install
 
@@ -145,6 +146,9 @@ perf_clean:
$(Q)mkdir -p $(PERF_O) .
$(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean
 
+rpmb_clean:
+   $(call descend,$(@:_clean=),clean)
+
 selftests_clean:
$(call descend,testing/$(@:_clean=),clean)
 
@@ -161,7 +165,7 @@ build_clean:
$(call descend,build,clean)
 
 clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean 
lguest_clean \
-   perf_clean selftests_clean turbostat_clean spi_clean usb_clean 
virtio_clean \
+   perf_clean rpmb_clean selftests_clean turbostat_clean spi_clean 
usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean 
tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean 
liblockdep_clean \
gpio_clean objtool_clean
diff --git a/tools/rpmb/.gitignore b/tools/rpmb/.gitignore
new file mode 100644
index ..218f680548e6
--- /dev/null
+++ b/tools/rpmb/.gitignore
@@ -0,0 +1,2 @@
+*.o
+rpmb
diff --git a/tools/rpmb/Makefile b/tools/rpmb/Makefile
new file mode 100644
index ..debb5a6bc208
--- /dev/null
+++ b/tools/rpmb/Makefile
@@ -0,0 +1,34 @@
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+

[PATCH v6 2/9] rpmb: enable emmc specific read data fixup

2016-09-13 Thread Tomas Winkler
For eMMC the block count of the RPMB read operation is not indicated in
the original RPMB Data Read Request packet.
This might be different then the implementation of other protocol
standards.
This patch implements a fixup for this behavior.


Signed-off-by: Tomas Winkler 
---
V6: new in the series

 drivers/char/rpmb/core.c | 36 +---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index ff10cbb7b644..8cfbbb721538 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -117,6 +117,35 @@ static int rpmb_request_verify(struct rpmb_dev *rdev, 
struct rpmb_data *rpmbd)
 }
 
 /**
+ * rpmb_cmd_fixup - fixup rpmb command
+ *
+ * @rdev: rpmb device
+ * @cmds: rpmb command list
+ * @ncmds: number of commands
+ *
+ */
+static void rpmb_cmd_fixup(struct rpmb_dev *rdev,
+  struct rpmb_cmd *cmds, u32 ncmds)
+{
+   int i;
+
+   if (rdev->ops->type != RPMB_TYPE_EMMC)
+   return;
+
+   /* Fixup RPMB_READ_DATA specific to eMMC
+* The block count of the RPMB read operation is not indicated
+* in the original RPMB Data Read Request packet.
+* This is different then implementation for other protocol
+* standards.
+*/
+   for (i = 0; i < ncmds; i++)
+   if (cmds->frames->req_resp == cpu_to_be16(RPMB_READ_DATA)) {
+   dev_dbg(&rdev->dev, "Fixing up READ_DATA frame to 
block_count=0\n");
+   cmds->frames->block_count = 0;
+   }
+}
+
+/**
  * rpmb_cmd_seq - send RPMB command sequence
  *
  * @rdev: rpmb device
@@ -136,10 +165,11 @@ int rpmb_cmd_seq(struct rpmb_dev *rdev, struct rpmb_cmd 
*cmds, u32 ncmds)
return -EINVAL;
 
mutex_lock(&rdev->lock);
-   if (rdev->ops && rdev->ops->cmd_seq)
+   err = -EOPNOTSUPP;
+   if (rdev->ops && rdev->ops->cmd_seq) {
+   rpmb_cmd_fixup(rdev, cmds, ncmds);
err = rdev->ops->cmd_seq(rdev->dev.parent, cmds, ncmds);
-   else
-   err = -EOPNOTSUPP;
+   }
mutex_unlock(&rdev->lock);
return err;
 }
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 8/9] mmc: block: register RPMB partition with the RPMB subsystem

2016-09-13 Thread Tomas Winkler
Register eMMC RPMB partition with the RPMB subsystem and provide
implementation for the RPMB access operations abstracting
actual multi step process.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
V2: resend
V3: commit message fix
V4: Kconfig: use select RPMB to ensure valid configuration
Switch back to main area after RPMB access
V5: Revamp code using new sequence command
Support for 8K packets in e.MMC v5.1
V5: resend

 drivers/mmc/card/Kconfig |   1 +
 drivers/mmc/card/block.c | 258 ++-
 2 files changed, 256 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 5562308699bc..537d0bc82781 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -7,6 +7,7 @@ comment "MMC/SD/SDIO Card Drivers"
 config MMC_BLOCK
tristate "MMC block device driver"
depends on BLOCK
+   select RPMB
default y
help
  Say Y here to enable the MMC block device driver support.
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 2206d4477dbb..51d7e60226f5 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -111,6 +112,7 @@ struct mmc_blk_data {
 #define MMC_BLK_WRITE  BIT(1)
 #define MMC_BLK_DISCARDBIT(2)
 #define MMC_BLK_SECDISCARD BIT(3)
+#define MMC_BLK_RPMB   BIT(4)
 
/*
 * Only set in main mmc_blk_data associated
@@ -401,8 +403,8 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd 
__user *ic_ptr,
return 0;
 }
 
-static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
-  u32 retries_max)
+static int mmc_blk_rpmb_status_poll(struct mmc_card *card, u32 *status,
+   u32 retries_max)
 {
int err;
u32 retry_count = 0;
@@ -575,7 +577,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, 
struct mmc_blk_data *md,
 * Ensure RPMB command has completed by polling CMD13
 * "Send Status".
 */
-   err = ioctl_rpmb_card_status_poll(card, &status, 5);
+   err = mmc_blk_rpmb_status_poll(card, &status, 5);
if (err)
dev_err(mmc_dev(card->host),
"%s: Card Status=0x%08X, error %d\n",
@@ -1165,6 +1167,252 @@ int mmc_access_rpmb(struct mmc_queue *mq)
return false;
 }
 
+static int mmc_rpmb_send_cmd(struct mmc_card *card,
+unsigned int data_type, bool do_rel_wr,
+void *buf, u16 blks)
+{
+   int err;
+   u32 status;
+   struct mmc_command sbc = {
+   .opcode = MMC_SET_BLOCK_COUNT,
+   .flags  = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   struct mmc_command cmd = {
+   .flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
+   };
+
+   struct mmc_data data = {
+   .blksz = 512,
+   };
+   struct mmc_request mrq = {
+   .sbc= &sbc,
+   .cmd= &cmd,
+   .data   = &data,
+   .stop   = NULL,
+   };
+   struct scatterlist sg;
+
+   /*  set CMD23 */
+   sbc.arg = blks & 0x;
+   if (do_rel_wr)
+   sbc.arg |= MMC_CMD23_ARG_REL_WR;
+
+   /*  set CMD25/18 */
+   cmd.opcode = (data_type == MMC_DATA_WRITE) ?
+   MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
+
+   sg_init_one(&sg, buf, 512 * blks);
+
+   data.blocks = blks;
+   data.sg = &sg;
+   data.sg_len = 1;
+   data.flags  = data_type;
+   mmc_set_data_timeout(&data, card);
+
+   mmc_wait_for_req(card->host, &mrq);
+
+   if (cmd.error) {
+   dev_err(mmc_dev(card->host), "cmd error (%d)\n", cmd.error);
+   return cmd.error;
+   }
+
+   if (data.error) {
+   dev_err(mmc_dev(card->host), "data error (%d)\n", data.error);
+   return data.error;
+   }
+
+   err = mmc_blk_rpmb_status_poll(card, &status, 5);
+   if (err)
+   dev_err(mmc_dev(card->host), "Card Status=0x%08X, error %d\n",
+   status, err);
+   return err;
+}
+
+static int mmc_blk_rpmb_sequence(struct mmc_card *card,
+struct rpmb_cmd *cmds, u32 ncmds)
+{
+   int err, i;
+   struct rpmb_cmd *cmd;
+   unsigned int data_type;
+   bool do_rel_wr;
+
+   for (err = 0, i = 0; i < ncmds && !err; i++) {
+   cmd = &cmds[i];
+   if (cmd->flags & RPMB_F_WRITE) {
+   data_type = MMC_DATA_W

[PATCH v6 7/9] tools rpmb: add RPBM access tool

2016-09-13 Thread Tomas Winkler
Add simple RPMB host testing tool. It can be used
to program key, write and read data block, and retrieve
write counter.

Signed-off-by: Tomas Winkler 
---
V2: resend
V3: fix missing objtool
V4: add verbose option
V5: 1. Adjust to the new API.
2. Exercise both request and sequence ioctls.
V6: 1. Add includes to openssl/rand.h and endian.h
2. Fix some signed, unsigned comparisons
3. Check results more thoroughly
4. use HOSTCFLAGS in compilation
5. Allocate frames dynamically.

 MAINTAINERS   |1 +
 tools/Makefile|   14 +-
 tools/rpmb/.gitignore |2 +
 tools/rpmb/Makefile   |   34 ++
 tools/rpmb/rpmb.c | 1031 +
 5 files changed, 1077 insertions(+), 5 deletions(-)
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3a092b90add3..786ed2a1d2bf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10002,6 +10002,7 @@ F:  drivers/char/rpmb/*
 F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
+F: tools/rpmb/
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
diff --git a/tools/Makefile b/tools/Makefile
index daa8fb3e4363..1d481b78063f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -20,6 +20,7 @@ help:
@echo '  lguest - a minimal 32-bit x86 hypervisor'
@echo '  net- misc networking tools'
@echo '  perf   - Linux performance measurement and 
analysis tool'
+   @echo '  rpmb   - Replay protected memory block access 
tool'
@echo '  selftests  - various kernel selftests'
@echo '  spi- spi tools'
@echo '  objtool- an ELF object analysis tool'
@@ -56,7 +57,7 @@ acpi: FORCE
 cpupower: FORCE
$(call descend,power/$@)
 
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio gpio objtool: FORCE
$(call descend,$@)
 
 liblockdep: FORCE
@@ -86,7 +87,7 @@ freefall: FORCE
$(call descend,laptop/$@)
 
 all: acpi cgroup cpupower gpio hv firewire lguest \
-   perf selftests turbostat usb \
+   perf rpmb selftests turbostat usb \
virtio vm net x86_energy_perf_policy \
tmon freefall objtool
 
@@ -96,7 +97,7 @@ acpi_install:
 cpupower_install:
$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install gpio_install hv_install lguest_install 
perf_install usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install gpio_install hv_install lguest_install 
perf_install rpmb_install usb_install virtio_install vm_install net_install 
objtool_install:
$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -116,7 +117,7 @@ kvm_stat_install:
 
 install: acpi_install cgroup_install cpupower_install gpio_install \
hv_install firewire_install lguest_install \
-   perf_install selftests_install turbostat_install usb_install \
+   perf_install rpmb_install selftests_install turbostat_install 
usb_install \
virtio_install vm_install net_install 
x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install
 
@@ -145,6 +146,9 @@ perf_clean:
$(Q)mkdir -p $(PERF_O) .
$(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean
 
+rpmb_clean:
+   $(call descend,$(@:_clean=),clean)
+
 selftests_clean:
$(call descend,testing/$(@:_clean=),clean)
 
@@ -161,7 +165,7 @@ build_clean:
$(call descend,build,clean)
 
 clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean 
lguest_clean \
-   perf_clean selftests_clean turbostat_clean spi_clean usb_clean 
virtio_clean \
+   perf_clean rpmb_clean selftests_clean turbostat_clean spi_clean 
usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean 
tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean 
liblockdep_clean \
gpio_clean objtool_clean
diff --git a/tools/rpmb/.gitignore b/tools/rpmb/.gitignore
new file mode 100644
index ..218f680548e6
--- /dev/null
+++ b/tools/rpmb/.gitignore
@@ -0,0 +1,2 @@
+*.o
+rpmb
diff --git a/tools/rpmb/Makefile b/tools/rpmb/Makefile
new file mode 100644
index ..debb5a6bc208
--- /dev/null
+++ b/tools/rpmb/Makefile
@@ -0,0 +1,34 @@
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Dete

[PATCH v6 1/9] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2016-09-13 Thread Tomas Winkler
Few storage technologies such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer,
but by a set of specific commands: WRITE, READ, GET_WRITE_COUNTER,
and PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE device driver can claim the RPMB interface, for example, via
class_interface_register ().
The layer provides two APIs rpmb_cmd_req() for issuing one of RPMB
specific commands and rpmb_cmd_seq() for issuing of raw RPMB protocol
frames sequence.
The major difference between the APIs is that for rpmb_cmd_req() the
framework performs RPMB_RESULT_READ operation on behalf of a user.
The RPMB_RESULT_READ is used for retrieving result of the commands
that carry data in the write cycle and need one more step to retrieve
the result.

A storage device registers its RPMB (eMMC) partition or RPMB
W-LUN (UFS) with the RPMB layer providing an implementation for
rpmb_cmd_seq() handler. The interface enables sending sequence of RPMB
standard frames.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
V2: added short workflow description in the commit message
V3: commit message fix
V4: resend
V5: add rpmb sequence interface.
V6: 1. More info in the commit message
2. Define simulation device type

 MAINTAINERS|   7 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |   8 +
 drivers/char/rpmb/Makefile |   4 +
 drivers/char/rpmb/core.c   | 414 +
 include/linux/rpmb.h   | 232 +
 7 files changed, 668 insertions(+)
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 include/linux/rpmb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index bd69bc0ed717..d6f5f134f55d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9994,6 +9994,13 @@ F:   include/net/rose.h
 F: include/uapi/linux/rose.h
 F: net/rose/
 
+RPMB SUBSYSTEM
+M: Tomas Winkler 
+L: linux-ker...@vger.kernel.org
+S: Supported
+F: drivers/char/rpmb/*
+F: include/linux/rpmb.h
+
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index dcc09739a54e..f2f4e0474ee6 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -590,5 +590,7 @@ config TILE_SROM
 
 source "drivers/char/xillybus/Kconfig"
 
+source "drivers/char/rpmb/Kconfig"
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 6e6c244a66a0..3a0cac3ff2dc 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -60,3 +60,4 @@ js-rtc-y = rtc.o
 obj-$(CONFIG_TILE_SROM)+= tile-srom.o
 obj-$(CONFIG_XILLYBUS) += xillybus/
 obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
+obj-$(CONFIG_RPMB) += rpmb/
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
new file mode 100644
index ..c5e6e909efce
--- /dev/null
+++ b/drivers/char/rpmb/Kconfig
@@ -0,0 +1,8 @@
+config RPMB
+   tristate "RPMB partition interface"
+   help
+ Unified RPMB partition interface for eMMC and UFS.
+ Provides interface for in kernel security controllers to
+ access RPMB partition.
+
+ If unsure, select N.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
new file mode 100644
index ..812b3ed264c0
--- /dev/null
+++ b/drivers/char/rpmb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RPMB) += rpmb.o
+rpmb-objs += core.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
new file mode 100644
index ..ff10cbb7b644
--- /dev/null
+++ b/drivers/char/rpmb/core.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static DEFINE_IDA(rpmb

[PATCH v6 9/9] scsi: ufs: connect to RPMB subsystem

2016-09-13 Thread Tomas Winkler
Register UFS RPMB LUN with the RPMB subsystem and provide
implementation for the RPMB access operations. RPMB partition is
accessed via a sequence of security protocol in and security protocol
out commands with UFS specific parameters. This multi step process is
abstracted into 4 basic RPMB commands.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
V2: resend
V3: resend
V4: Kconfig: use select RPMB to ensure valid configuration
V5: Revamp code using new sequence command.
V5: resend

 drivers/scsi/ufs/Kconfig  |   1 +
 drivers/scsi/ufs/ufshcd.c | 183 ++
 drivers/scsi/ufs/ufshcd.h |   2 +
 3 files changed, 186 insertions(+)

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 47966909286d..86bbf3a16dbf 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -38,6 +38,7 @@ config SCSI_UFSHCD
select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select NLS
+   select RPMB
---help---
This selects the support for UFS devices in Linux, say Y and make
  sure that you know the name of your UFS host adapter (the card
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f08d41a2d70b..2a18e6b26641 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -37,10 +37,13 @@
  * license terms, and distributes only under these terms.
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -4750,6 +4753,178 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 
 }
 
+#define SEC_PROTOCOL_UFS  0xEC
+#define   SEC_SPECIFIC_UFS_RPMB 0x0001
+
+#define SEC_PROTOCOL_CMD_SIZE 12
+#define SEC_PROTOCOL_RETRIES 3
+#define SEC_PROTOCOL_RETRIES_ON_RESET 10
+#define SEC_PROTOCOL_TIMEOUT msecs_to_jiffies(1000)
+
+static int
+ufshcd_rpmb_security_out(struct scsi_device *sdev,
+struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 trans_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_OUT;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0;  /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(trans_len, cmd + 6);  /* transfer length */
+
+retry:
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_TO_DEVICE,
+frames, trans_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /*
+* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   dev_err(&sdev->sdev_gendev, "%s: failed with err %0x\n",
+   __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security out", &sshdr);
+
+   return ret;
+}
+
+static int
+ufshcd_rpmb_security_in(struct scsi_device *sdev,
+   struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 alloc_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_IN;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0; /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(alloc_len, cmd + 6); /* allocation length */
+
+retry:
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_FROM_DEVICE,
+frames, alloc_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /*
+* Device reset might occur several times,
+* give it one more chance
+   */
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   dev_err(&sdev->sdev_gendev,

[PATCH v6 5/9] char: rpmb: provide a user space interface

2016-09-13 Thread Tomas Winkler
The user space API is achieved via two synchronous IOCTLs.
Simplified one, RPMB_IOC_REQ_CMD, were read result cycles is performed
by the framework on behalf the user and second, RPMB_IOC_SEQ_CMD where
the whole RPMB sequence including RESULT_READ is supplied by the caller.
The latter is intended for easier adjusting of the applications that
use MMC_IOC_MULTI_CMD ioctl.

Signed-off-by: Tomas Winkler 
---
V2: use memdup_user
V3: commit message fix
V4: resend
V5: 1. Add RPMB_IOC_SEQ_CMD API.
2. Export uapi rpmb.h header
V6: 1. remove #include 
2. Add ioctl documentation

 Documentation/ioctl/ioctl-number.txt |   1 +
 MAINTAINERS  |   1 +
 drivers/char/rpmb/Kconfig|   7 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/cdev.c | 317 +++
 drivers/char/rpmb/core.c |   9 +-
 drivers/char/rpmb/rpmb-cdev.h|  25 +++
 include/linux/rpmb.h |  81 +
 include/uapi/linux/Kbuild|   1 +
 include/uapi/linux/rpmb.h| 152 +
 10 files changed, 521 insertions(+), 74 deletions(-)
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 include/uapi/linux/rpmb.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 81c7f2bb7daf..f645543866c7 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -321,6 +321,7 @@ Code  Seq#(hex) Include FileComments
 0xB1   00-1F   PPPoX   <mailto:mostr...@styx.uwaterloo.ca>
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h<mailto:linux-g...@vger.kernel.org>
+0xB5   00-01   linux/uapi/linux/rpmb.h <mailto:linux-...@linux.intel.com>
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-8F   uapi/scsi/cxlflash_ioctl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index d701a972c83a..3a092b90add3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -,6 +9999,7 @@ M:    Tomas Winkler 
 L: linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
+F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
 
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index c5e6e909efce..6794be9fcc5e 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -6,3 +6,10 @@ config RPMB
  access RPMB partition.
 
  If unsure, select N.
+
+config RPMB_INTF_DEV
+   bool "RPMB character device interface /dev/rpmbN"
+   depends on RPMB
+   help
+ Say yes here if you want to access RPMB from user space
+ via character device interface /dev/rpmb%d
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index 812b3ed264c0..b5dc087b1299 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
+rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
new file mode 100644
index ..837c32e722ec
--- /dev/null
+++ b/drivers/char/rpmb/cdev.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "rpmb-cdev.h"
+
+static dev_t rpmb_devt;
+#define RPMB_MAX_DEVS  MINORMASK
+
+#define RPMB_DEV_OPEN0  /** single open bit (position) */
+/* from MMC_IOC_MAX_CMDS */
+#define RPMB_MAX_FRAMES 255
+
+/**
+ * rpmb_open - the open function
+ *
+ * @inode: pointer to inode structure
+ * @fp: pointer to file structure
+ *
+ * Return: 0 on success, <0 on error
+ */
+static int rpmb_open(struct inode *inode, struct file *fp)
+{
+   struct rpmb_dev *rdev;
+
+   rdev = container_of(inode->i_cdev, struct rpmb_dev, cdev);
+   if (!rdev)
+   return -ENODEV;
+
+   /* the rpmb is single open! */
+   if (test_and_set_bit(RPMB_DEV_OPEN, &rdev->status))
+   return -EBUSY;
+
+   mutex_lock(&rdev->lock);
+
+   fp->private_data = rdev;
+
+   mutex_unlock(&rdev->lock);
+
+   return nonseekable_open(inode, fp);
+}
+
+/**
+ * rpmb_open - the open function
+ *
+ * @inode: poin

[PATCH v6 3/9] rpmb: add sysfs-class ABI documentation

2016-09-13 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
---
V2: resend
V3: add more verbose description
V4: resend
V5: adjust date and kernel version
V6: adjust date and kernel version

 Documentation/ABI/testing/sysfs-class-rpmb | 20 
 MAINTAINERS|  1 +
 2 files changed, 21 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
new file mode 100644
index ..9b840e660274
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -0,0 +1,20 @@
+What:  /sys/class/rpmb/
+Date:  Sep 2016
+KernelVersion:  4.9
+Contact:   Tomas Winkler 
+Description:
+   The rpmb/ class sub-directory belongs to RPMB device class.
+
+   Few storage technologies such is EMMC, UFS, and NVMe support
+   Replay Protected Memory Block (RPMB) hardware partition with
+   common protocol and frame layout.
+   Such a partition provides authenticated and replay protected 
access,
+   hence suitable as a secure storage.
+
+What:  /sys/class/rpmb/rpmbN/
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN directory is created for
+   each RPMB registered device.
diff --git a/MAINTAINERS b/MAINTAINERS
index d6f5f134f55d..d701a972c83a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1,6 +1,7 @@ L:  linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
 F: include/linux/rpmb.h
+F: Documentation/ABI/testing/sysfs-class-rpmb
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 4/9] char: rpmb: add device attributes

2016-09-13 Thread Tomas Winkler
Add attribute type that displays underlay storage type technology
EMMC, UFS, and attribute id, that displays underlay storage device id.
For EMMC this would be content of CID and for UFS serial number from
the device descriptor.

Signed-off-by: Tomas Winkler 
---
V2: resend
V3: set kernel version to 4.7
V4: update target date to Maj
V5: update date and kernel version
V6: 1. Add simulation device type
2. Update date and kernel version
3. Use binary attribute for id
4. use simple sprintf instead of scnprintf
5. Add more verbose documenation

 Documentation/ABI/testing/sysfs-class-rpmb | 27 +++
 drivers/char/rpmb/core.c   | 72 ++
 2 files changed, 99 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
index 9b840e660274..2fe100eb5aa7 100644
--- a/Documentation/ABI/testing/sysfs-class-rpmb
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -18,3 +18,30 @@ Contact: Tomas Winkler 
 Description:
The /sys/class/rpmb/rpmbN directory is created for
each RPMB registered device.
+
+What:  /sys/class/rpmb/rpmbN/type
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/type file contains device
+   underlaying storage type technology: EMMC, UFS, SIM.
+
+What:  /sys/class/rpmb/rpmbN/id
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/id file contains unique device id
+   in a binary form as defined by underlying storage device.
+   In case of multiple RPMB devices a user can determine correct
+   device.
+   The content can be parsed according the storage device type.
+
+What:  /sys/class/rpmb/rpmbN/reliable_wr_cnt
+Date:  Sep 2016
+KernelVersion: 4.9
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/reliable_wr_cnt file contains
+   number of blocks that can be reliable written in a single 
request.
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index 8cfbbb721538..f6b4cabb0982 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -338,6 +338,76 @@ struct rpmb_dev *rpmb_dev_find_by_device(struct device 
*parent)
 }
 EXPORT_SYMBOL_GPL(rpmb_dev_find_by_device);
 
+static ssize_t type_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   ssize_t ret;
+
+   switch (rdev->ops->type) {
+   case RPMB_TYPE_EMMC:
+   ret = sprintf(buf, "EMMC\n");
+   break;
+   case RPMB_TYPE_UFS:
+   ret = sprintf(buf, "UFS\n");
+   break;
+   case RPMB_TYPE_SIM:
+   ret = sprintf(buf, "SIM\n");
+   break;
+   default:
+   ret = sprintf(buf, "UNKNOWN\n");
+   break;
+   }
+
+   return ret;
+}
+static DEVICE_ATTR_RO(type);
+
+static ssize_t id_read(struct file *file, struct kobject *kobj,
+  struct bin_attribute *attr, char *buf,
+  loff_t off, size_t count)
+{
+   struct device *dev = kobj_to_dev(kobj);
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   size_t sz = min_t(size_t, rdev->ops->dev_id_len, PAGE_SIZE);
+
+   if (!rdev->ops->dev_id)
+   return 0;
+
+   return memory_read_from_buffer(buf, count, &off, rdev->ops->dev_id, sz);
+}
+static BIN_ATTR_RO(id, 0);
+
+static ssize_t reliable_wr_cnt_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+
+   return sprintf(buf, "%u\n", rdev->ops->reliable_wr_cnt);
+}
+static DEVICE_ATTR_RO(reliable_wr_cnt);
+
+static struct attribute *rpmb_attrs[] = {
+   &dev_attr_type.attr,
+   &dev_attr_reliable_wr_cnt.attr,
+   NULL,
+};
+
+static struct bin_attribute *rpmb_bin_attributes[] = {
+   &bin_attr_id,
+   NULL,
+};
+
+static struct attribute_group rpmb_attr_group = {
+   .attrs = rpmb_attrs,
+   .bin_attrs = rpmb_bin_attributes,
+};
+
+static const struct attribute_group *rpmb_attr_groups[] = {
+   &rpmb_attr_group,
+   NULL
+};
+
 /**
  * rpmb_dev_unregister - unregister RPMB partition from the RPMB subsystem
  *
@@ -407,6 +477,8 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
dev_set_name(&rdev->dev, "rpmb%d", id);
rdev->dev.class = &rpmb_class;
rdev->dev.parent = dev;
+   rdev->dev.groups = rpmb_attr_groups;
+
ret = device_register(&rdev->dev);
if (ret)
goto exit;

[PATCH v6 6/9] char: rpmb: add RPMB simulation device

2016-09-13 Thread Tomas Winkler
The RPMB partition simulation device is a virtual device that
provides simulation of the RPMB protocol and use kernel memory
as storage.

Be aware it doesn't promise any real security. This driver is
suitable only for testing of the RPMB subsystem or RPMB
applications prior to RPMB key provisioning, as RPMB key
programming can be perfomed only once in the life time of the
storage device.

The module currently supports two configuration options via
module parameters
1. max_wr_blks: for specifying max blocks that can be written
in a single command
2. daunits:  used to set storage capacity in 128K units.

V2: remove .owner setting, it is set automatically
V3: 1. Add shutdown handler (similar to ufshcd)
2. Commit message fix
V4: Use select RPMB in Kconfg to ensure valid configuration.
V5: Revamp the code using the sequence command.
V6: 1. Be more verbose about some errors, after all this is a testing
module.
2. Fix RPMB_READ_DATA:
   a. The number of blocks for eMMC request frame should be 0
   b. Fix missing return before bailing on error
   c. Copy all the frames back
3. Fix RPMB_WRITE_DATA:
   a. Compute MAC on result packet
   b. Also address should be set in the result frame.
4. Remove platform device
5. Update the commit message

Signed-off-by: Tomas Winkler 
---
 drivers/char/rpmb/Kconfig|  17 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/rpmb_sim.c | 744 +++
 3 files changed, 762 insertions(+)
 create mode 100644 drivers/char/rpmb/rpmb_sim.c

diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index 6794be9fcc5e..533d813e9ed5 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -13,3 +13,20 @@ config RPMB_INTF_DEV
help
  Say yes here if you want to access RPMB from user space
  via character device interface /dev/rpmb%d
+
+
+config RPMB_SIM
+   tristate "RPMB partition device simulator"
+   default n
+   select RPMB
+   select CRYPTO_SHA256
+   select CRYPTO_HMAC
+   help
+ RPMB partition simulation device is a virtual device that
+ provides simulation of the RPMB protocol and use kernel memory
+ as storage.
+
+ Be aware it doesn't promise any real security. This driver is
+ suitable only for testing of the RPMB subsystem or RPMB applications
+ prior to RPMB key provisioning.
+  Most people should say N here.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index b5dc087b1299..81f924fd9a87 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
 rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
+obj-$(CONFIG_RPMB_SIM) += rpmb_sim.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/rpmb_sim.c b/drivers/char/rpmb/rpmb_sim.c
new file mode 100644
index ..429a08bd67d7
--- /dev/null
+++ b/drivers/char/rpmb/rpmb_sim.c
@@ -0,0 +1,744 @@
+/**
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Corporation.
+ * linux-...@linux.intel.com
+ * http://www.intel.com
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *contributors may be used to endorse or promote products derived
+ *from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "

[PATCH v6 0/9] Replay Protected Memory Block (RPMB) subsystem

2016-09-13 Thread Tomas Winkler

Few storage technologies such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but by a
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and
PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.

The layer provides two APIs, for rpmb_req_cmd() for issuing one of RPMB
specific commands and rpmb_seq_cmd() for issuing of raw RPMB protocol
frames,  which is close to the functionality provided by emmc multi ioctl
interface.

A TEE driver can claim the RPMB interface, for example, via
class_interface_register ().

A storage device registers its RPMB hardware (eMMC) partition or RPMB
W-LUN (UFS) with the RPMB layer providing an implementation for
rpmb_seq_cmd() handler. The interface enables sending sequence of RPMB
standard frames.

A parallel user space API is provided via /dev/rpmbX character
device with two IOCTL commands.
Simplified one, RPMB_IOC_REQ_CMD, were read result cycles is performed
by the framework on behalf the user and second, RPMB_IOC_SEQ_CMD where
the whole RPMB sequence, including RESULT_READ is supplied by the caller.
The latter is intended for easier adjusting of the applications that
use MMC_IOC_MULTI_CMD ioctl, such as
https://android.googlesource.com/trusty/app/storage/

There is a also sample tool under tools/rpmb/ directory that exercises
these interfaces and a simulation device that implements the device part.

The code is also available from:

https://github.com/tomasbw/linux-mei.git rpmb

Tomas Winkler (9):
  rpmb: add Replay Protected Memory Block (RPMB) subsystem
  rpmb: enable emmc specific read data fixup
  rpmb: add sysfs-class ABI documentation
  char: rpmb: add device attributes
  char: rpmb: provide a user space interface
  char: rpmb: add RPMB simulation device
  tools rpmb: add RPBM access tool
  mmc: block: register RPMB partition with the RPMB subsystem
  scsi: ufs: connect to RPMB subsystem

 Documentation/ABI/testing/sysfs-class-rpmb |   47 ++
 Documentation/ioctl/ioctl-number.txt   |1 +
 MAINTAINERS|   10 +
 drivers/char/Kconfig   |2 +
 drivers/char/Makefile  |1 +
 drivers/char/rpmb/Kconfig  |   32 +
 drivers/char/rpmb/Makefile |6 +
 drivers/char/rpmb/cdev.c   |  317 +
 drivers/char/rpmb/core.c   |  523 ++
 drivers/char/rpmb/rpmb-cdev.h  |   25 +
 drivers/char/rpmb/rpmb_sim.c   |  744 
 drivers/mmc/card/Kconfig   |1 +
 drivers/mmc/card/block.c   |  258 ++-
 drivers/scsi/ufs/Kconfig   |1 +
 drivers/scsi/ufs/ufshcd.c  |  183 +
 drivers/scsi/ufs/ufshcd.h  |2 +
 include/linux/rpmb.h   |  167 +
 include/uapi/linux/Kbuild  |1 +
 include/uapi/linux/rpmb.h  |  152 
 tools/Makefile |   14 +-
 tools/rpmb/.gitignore  |2 +
 tools/rpmb/Makefile|   34 +
 tools/rpmb/rpmb.c  | 1031 
 23 files changed, 3546 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 drivers/char/rpmb/rpmb_sim.c
 create mode 100644 include/linux/rpmb.h
 create mode 100644 include/uapi/linux/rpmb.h
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 8/8] scsi: ufs: connect to RPMB subsystem

2016-07-18 Thread Tomas Winkler
Register UFS RPMB LUN with the RPMB subsystem and provide
implementation for the RPMB access operations. RPMB partition is
accessed via a sequence of security protocol in and security protocol
out commands with UFS specific parameters. This multi step process is
abstracted into 4 basic RPMB commands.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
V2: resend
V3: resend
V4: Kconfig: use select RPMB to ensure valid configuration
V5: Revamp code using new sequence command.

 drivers/scsi/ufs/Kconfig  |   1 +
 drivers/scsi/ufs/ufshcd.c | 183 ++
 drivers/scsi/ufs/ufshcd.h |   2 +
 3 files changed, 186 insertions(+)

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 097894a1fab5..e6ff8ecff695 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -38,6 +38,7 @@ config SCSI_UFSHCD
select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select NLS
+   select RPMB
---help---
This selects the support for UFS devices in Linux, say Y and make
  sure that you know the name of your UFS host adapter (the card
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..b41fce16f687 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -37,10 +37,13 @@
  * license terms, and distributes only under these terms.
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -4744,6 +4747,178 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 
 }
 
+#define SEC_PROTOCOL_UFS  0xEC
+#define   SEC_SPECIFIC_UFS_RPMB 0x0001
+
+#define SEC_PROTOCOL_CMD_SIZE 12
+#define SEC_PROTOCOL_RETRIES 3
+#define SEC_PROTOCOL_RETRIES_ON_RESET 10
+#define SEC_PROTOCOL_TIMEOUT msecs_to_jiffies(1000)
+
+static int
+ufshcd_rpmb_security_out(struct scsi_device *sdev,
+struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 trans_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_OUT;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0;  /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(trans_len, cmd + 6);  /* transfer length */
+
+retry:
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_TO_DEVICE,
+frames, trans_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /*
+* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   dev_err(&sdev->sdev_gendev, "%s: failed with err %0x\n",
+   __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security out", &sshdr);
+
+   return ret;
+}
+
+static int
+ufshcd_rpmb_security_in(struct scsi_device *sdev,
+   struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 alloc_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_IN;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0; /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(alloc_len, cmd + 6); /* allocation length */
+
+retry:
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_FROM_DEVICE,
+frames, alloc_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /*
+* Device reset might occur several times,
+* give it one more chance
+   */
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   dev_err(&sdev->sdev_gendev, "

[PATCH v5 7/8] mmc: block: register RPMB partition with the RPMB subsystem

2016-07-18 Thread Tomas Winkler
Register eMMC RPMB partition with the RPMB subsystem and provide
implementation for the RPMB access operations abstracting
actual multi step process.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
V2: resend
V3: commit message fix
V4: Kconfig: use select RPMB to ensure valid configuration
Switch back to main area after RPMB access
V5: Revamp code using new sequence command
Support for 8K packets in e.MMC v5.1

 drivers/mmc/card/Kconfig |   1 +
 drivers/mmc/card/block.c | 258 ++-
 2 files changed, 256 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 5562308699bc..537d0bc82781 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -7,6 +7,7 @@ comment "MMC/SD/SDIO Card Drivers"
 config MMC_BLOCK
tristate "MMC block device driver"
depends on BLOCK
+   select RPMB
default y
help
  Say Y here to enable the MMC block device driver support.
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index e62fde3ac431..0e1f11da40c2 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -110,6 +111,7 @@ struct mmc_blk_data {
 #define MMC_BLK_WRITE  BIT(1)
 #define MMC_BLK_DISCARDBIT(2)
 #define MMC_BLK_SECDISCARD BIT(3)
+#define MMC_BLK_RPMB   BIT(4)
 
/*
 * Only set in main mmc_blk_data associated
@@ -398,8 +400,8 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd 
__user *ic_ptr,
return 0;
 }
 
-static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
-  u32 retries_max)
+static int mmc_blk_rpmb_status_poll(struct mmc_card *card, u32 *status,
+   u32 retries_max)
 {
int err;
u32 retry_count = 0;
@@ -572,7 +574,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, 
struct mmc_blk_data *md,
 * Ensure RPMB command has completed by polling CMD13
 * "Send Status".
 */
-   err = ioctl_rpmb_card_status_poll(card, &status, 5);
+   err = mmc_blk_rpmb_status_poll(card, &status, 5);
if (err)
dev_err(mmc_dev(card->host),
"%s: Card Status=0x%08X, error %d\n",
@@ -1162,6 +1164,252 @@ int mmc_access_rpmb(struct mmc_queue *mq)
return false;
 }
 
+static int mmc_rpmb_send_cmd(struct mmc_card *card,
+unsigned int data_type, bool do_rel_wr,
+void *buf, u16 blks)
+{
+   int err;
+   u32 status;
+   struct mmc_command sbc = {
+   .opcode = MMC_SET_BLOCK_COUNT,
+   .flags  = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   struct mmc_command cmd = {
+   .flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
+   };
+
+   struct mmc_data data = {
+   .blksz = 512,
+   };
+   struct mmc_request mrq = {
+   .sbc= &sbc,
+   .cmd= &cmd,
+   .data   = &data,
+   .stop   = NULL,
+   };
+   struct scatterlist sg;
+
+   /*  set CMD23 */
+   sbc.arg = blks & 0x;
+   if (do_rel_wr)
+   sbc.arg |= MMC_CMD23_ARG_REL_WR;
+
+   /*  set CMD25/18 */
+   cmd.opcode = (data_type == MMC_DATA_WRITE) ?
+   MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
+
+   sg_init_one(&sg, buf, 512 * blks);
+
+   data.blocks = blks;
+   data.sg = &sg;
+   data.sg_len = 1;
+   data.flags  = data_type;
+   mmc_set_data_timeout(&data, card);
+
+   mmc_wait_for_req(card->host, &mrq);
+
+   if (cmd.error) {
+   dev_err(mmc_dev(card->host), "cmd error (%d)\n", cmd.error);
+   return cmd.error;
+   }
+
+   if (data.error) {
+   dev_err(mmc_dev(card->host), "data error (%d)\n", data.error);
+   return data.error;
+   }
+
+   err = mmc_blk_rpmb_status_poll(card, &status, 5);
+   if (err)
+   dev_err(mmc_dev(card->host), "Card Status=0x%08X, error %d\n",
+   status, err);
+   return err;
+}
+
+static int mmc_blk_rpmb_sequence(struct mmc_card *card,
+struct rpmb_cmd *cmds, u32 ncmds)
+{
+   int err, i;
+   struct rpmb_cmd *cmd;
+   unsigned int data_type;
+   bool do_rel_wr;
+
+   for (err = 0, i = 0; i < ncmds && !err; i++) {
+   cmd = &cmds[i];
+   if (cmd->flags & RPMB_F_WRITE) {
+   data_type = MMC_DATA_W

[PATCH v5 0/8] Replay Protected Memory Block (RPMB) subsystem

2016-07-18 Thread Tomas Winkler
Few storage technologies such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but by a
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and
PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE driver can claim the RPMB interface, for example, via
class_interface_register ().
The layer provides two APIs, for rpmb_req_cmd() for issuing one of RPMB
specific commands and rpmb_seq_cmd() for issuing of raw RPMB protocol
frames,  which is close to emmc multi ioctl interface.

A storage device registers its RPMB hardware (eMMC) partition or RPMB
W-LUN (UFS) with the RPMB layer providing an implementation for
rpmb_seq_cmd() handler. The interface enables sending sequence of RPMB
standard frames.

A parallel user space API is provided via /dev/rpmbX character
device with two IOCTL commands.
Simplified one, RPMB_IOC_REQ_CMD, were read result cycles is performed
by the framework on behalf the user and second, RPMB_IOC_SEQ_CMD where
the whole RPMB sequence, including RESULT_READ is supplied by the caller.
The latter is intended for easier adjusting of the applications that
use MMC_IOC_MULTI_CMD ioctl, such as 
https://android.googlesource.com/trusty/app/storage/

There is a also sample tool under tools/rpmb/ directory that exercises
these interfaces and a simulation device that implements the device part.

Tomas Winkler (8):
  rpmb: add Replay Protected Memory Block (RPMB) subsystem
  char: rpmb: add sysfs-class ABI documentation
  char: rpmb: add device attributes
  char: rpmb: provide a user space interface
  char: rpmb: add RPMB simulation device
  tools rpmb: add RPBM access tool
  mmc: block: register RPMB partition with the RPMB subsystem
  scsi: ufs: connect to RPMB subsystem

 Documentation/ABI/testing/sysfs-class-rpmb |  44 ++
 Documentation/ioctl/ioctl-number.txt   |   1 +
 MAINTAINERS|  10 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |  25 +
 drivers/char/rpmb/Makefile |   6 +
 drivers/char/rpmb/cdev.c   | 269 
 drivers/char/rpmb/core.c   | 484 +++
 drivers/char/rpmb/rpmb-cdev.h  |  25 +
 drivers/char/rpmb/rpmb_sim.c   | 668 
 drivers/mmc/card/Kconfig   |   1 +
 drivers/mmc/card/block.c   | 258 +++-
 drivers/scsi/ufs/Kconfig   |   1 +
 drivers/scsi/ufs/ufshcd.c  | 183 ++
 drivers/scsi/ufs/ufshcd.h  |   2 +
 include/linux/rpmb.h   | 165 +
 include/uapi/linux/Kbuild  |   1 +
 include/uapi/linux/rpmb.h  | 152 +
 tools/Makefile |  14 +-
 tools/rpmb/.gitignore  |   2 +
 tools/rpmb/Makefile|  33 +
 tools/rpmb/rpmb.c  | 948 +
 23 files changed, 3287 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 drivers/char/rpmb/rpmb_sim.c
 create mode 100644 include/linux/rpmb.h
 create mode 100644 include/uapi/linux/rpmb.h
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 2/8] char: rpmb: add sysfs-class ABI documentation

2016-07-18 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
---
V2: resend
V3: add more verbose description
V4: resend
V5: adjust date and kernel version

 Documentation/ABI/testing/sysfs-class-rpmb | 20 
 MAINTAINERS|  1 +
 2 files changed, 21 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
new file mode 100644
index ..3ffcd2d1f683
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -0,0 +1,20 @@
+What:  /sys/class/rpmb/
+Date:  Aug 2016
+KernelVersion:  4.8
+Contact:   Tomas Winkler 
+Description:
+   The rpmb/ class sub-directory belongs to RPMB device class.
+
+   Few storage technologies such is EMMC, UFS, and NVMe support
+   Replay Protected Memory Block (RPMB) hardware partition with
+   common protocol and frame layout.
+   Such a partition provides authenticated and replay protected 
access,
+   hence suitable as a secure storage.
+
+What:  /sys/class/rpmb/rpmbN/
+Date:  Aug 2016
+KernelVersion: 4.8
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN directory is created for
+   each RPMB registered device
diff --git a/MAINTAINERS b/MAINTAINERS
index 50143ebc862f..02a6f6f10f48 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9712,6 +9712,7 @@ L:linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
 F: include/linux/rpmb.h
+F: Documentation/ABI/testing/sysfs-class-rpmb
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 6/8] tools rpmb: add RPBM access tool

2016-07-18 Thread Tomas Winkler
Add simple RPMB host testing tool. It can be used
to program key, write and read data block, and retrieve
write counter.

Signed-off-by: Tomas Winkler 
---
V2: resend
V3: fix missing objtool
V4: add verbose option
V5: 1. Adjust to the new API.
2. Exercise both request and sequence ioctls.

 MAINTAINERS   |   1 +
 tools/Makefile|  14 +-
 tools/rpmb/.gitignore |   2 +
 tools/rpmb/Makefile   |  33 ++
 tools/rpmb/rpmb.c | 948 ++
 5 files changed, 993 insertions(+), 5 deletions(-)
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c7c08c6c041b..b842a8be44fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9714,6 +9714,7 @@ F:drivers/char/rpmb/*
 F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
+F: tools/rpmb/
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
diff --git a/tools/Makefile b/tools/Makefile
index f10b64d8c674..b90003945af1 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -20,6 +20,7 @@ help:
@echo '  lguest - a minimal 32-bit x86 hypervisor'
@echo '  net- misc networking tools'
@echo '  perf   - Linux performance measurement and 
analysis tool'
+   @echo '  rpmb   - Replay protected memory block access 
tool'
@echo '  selftests  - various kernel selftests'
@echo '  spi- spi tools'
@echo '  objtool- an ELF object analysis tool'
@@ -56,7 +57,7 @@ acpi: FORCE
 cpupower: FORCE
$(call descend,power/$@)
 
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio gpio objtool: FORCE
$(call descend,$@)
 
 liblockdep: FORCE
@@ -86,7 +87,7 @@ freefall: FORCE
$(call descend,laptop/$@)
 
 all: acpi cgroup cpupower hv firewire lguest \
-   perf selftests turbostat usb \
+   perf rpmb selftests turbostat usb \
virtio vm net x86_energy_perf_policy \
tmon freefall objtool
 
@@ -96,7 +97,7 @@ acpi_install:
 cpupower_install:
$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install hv_install lguest_install perf_install 
usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install hv_install lguest_install perf_install 
rpmb_install usb_install virtio_install vm_install net_install objtool_install:
$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -115,7 +116,7 @@ kvm_stat_install:
$(call descend,kvm/$(@:_install=),install)
 
 install: acpi_install cgroup_install cpupower_install hv_install 
firewire_install lguest_install \
-   perf_install selftests_install turbostat_install usb_install \
+   perf_install rpmb_install selftests_install turbostat_install 
usb_install \
virtio_install vm_install net_install 
x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install
 
@@ -144,6 +145,9 @@ perf_clean:
$(Q)mkdir -p $(PERF_O) .
$(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean
 
+rpmb_clean:
+   $(call descend,$(@:_clean=),clean)
+
 selftests_clean:
$(call descend,testing/$(@:_clean=),clean)
 
@@ -160,7 +164,7 @@ build_clean:
$(call descend,build,clean)
 
 clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean 
lguest_clean \
-   perf_clean selftests_clean turbostat_clean spi_clean usb_clean 
virtio_clean \
+   perf_clean rpmb_clean selftests_clean turbostat_clean spi_clean 
usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean 
tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean 
liblockdep_clean \
gpio_clean objtool_clean
diff --git a/tools/rpmb/.gitignore b/tools/rpmb/.gitignore
new file mode 100644
index ..218f680548e6
--- /dev/null
+++ b/tools/rpmb/.gitignore
@@ -0,0 +1,2 @@
+*.o
+rpmb
diff --git a/tools/rpmb/Makefile b/tools/rpmb/Makefile
new file mode 100644
index ..96275a8579e6
--- /dev/null
+++ b/tools/rpmb/Makefile
@@ -0,0 +1,33 @@
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+INSTALL = install
+prefix ?= /usr/local
+bindir = $(prefix)/bin
+
+
+CFLAGS += -D__EXPORTED_HEADERS__ -g -static
+LDFLAGS += -static
+CFLAGS += -I$(srctree)/include/uapi

[PATCH v5 5/8] char: rpmb: add RPMB simulation device

2016-07-18 Thread Tomas Winkler
This is a simple platform device used for testing
the RPMB subsystem.

The module currently supports two configuration options:
1. max_wr_blks: for specifying max blocks that can be written
in a single command
2. daunits:  used to set storage capacity in 128K units.


Signed-off-by: Tomas Winkler 
---
V2: remove .owner setting, it is set automatically
V3: 1. Add shutdown handler (similar to ufshcd)
2. Commit message fix
V4: Use select RPMB in Kconfg to ensure valid configuration.
V5: Revamp the code using the sequence command.

 drivers/char/rpmb/Kconfig|  10 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/rpmb_sim.c | 668 +++
 3 files changed, 679 insertions(+)
 create mode 100644 drivers/char/rpmb/rpmb_sim.c

diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index 6794be9fcc5e..c21b3934249f 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -13,3 +13,13 @@ config RPMB_INTF_DEV
help
  Say yes here if you want to access RPMB from user space
  via character device interface /dev/rpmb%d
+
+
+config RPMB_SIM
+   tristate "RPMB partition device simulator"
+   default n
+   select RPMB
+   select CRYPTO_SHA256
+   select CRYPTO_HMAC
+   help
+ RPMB partition simulator used for testing the RPMB subsystem
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index b5dc087b1299..81f924fd9a87 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
 rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
+obj-$(CONFIG_RPMB_SIM) += rpmb_sim.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/rpmb_sim.c b/drivers/char/rpmb/rpmb_sim.c
new file mode 100644
index ..e33f6809ae2c
--- /dev/null
+++ b/drivers/char/rpmb/rpmb_sim.c
@@ -0,0 +1,668 @@
+/**
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Corporation.
+ * linux-...@linux.intel.com
+ * http://www.intel.com
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *contributors may be used to endorse or promote products derived
+ *from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static const char id[] = "RPMB:SIM";
+#define CAPACITY_UNIT SZ_128K
+#define CAPACITY_MIN  SZ_128K
+#define CAPACITY_MAX  SZ_16M
+#define BLK_UNIT  SZ_256
+
+static unsigned int max_wr_blks = 1;
+module

[PATCH v5 4/8] char: rpmb: provide a user space interface

2016-07-18 Thread Tomas Winkler
The user space API is achieved via two synchronous IOCTL.
Simplified one, RPMB_IOC_REQ_CMD, were read result cycles is performed
by the framework on behalf the user and second, RPMB_IOC_SEQ_CMD where
the whole RPMB sequence including RESULT_READ is supplied by the caller.
The latter is intended for  easier adjusting  of the  applications that
use MMC_IOC_MULTI_CMD ioctl.

Signed-off-by: Tomas Winkler 
---
V2: use memdup_user
V3: commit message fix
V4: resend
V5: 1. Add RPMB_IOC_SEQ_CMD API.
2. Export uapi rpmb.h header
 Documentation/ioctl/ioctl-number.txt |   1 +
 MAINTAINERS  |   1 +
 drivers/char/rpmb/Kconfig|   7 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/cdev.c | 269 +++
 drivers/char/rpmb/core.c |   9 +-
 drivers/char/rpmb/rpmb-cdev.h|  25 
 include/linux/rpmb.h |  81 ++-
 include/uapi/linux/Kbuild|   1 +
 include/uapi/linux/rpmb.h| 152 
 10 files changed, 473 insertions(+), 74 deletions(-)
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 include/uapi/linux/rpmb.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 9369d3b0f09a..38f57332bf8e 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -320,6 +320,7 @@ Code  Seq#(hex) Include FileComments
 0xB1   00-1F   PPPoX   <mailto:mostr...@styx.uwaterloo.ca>
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h<mailto:linux-g...@vger.kernel.org>
+0xB5   00-01   linux/uapi/linux/rpmb.h <mailto:linux-...@linux.intel.com>
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-8F   uapi/scsi/cxlflash_ioctl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 02a6f6f10f48..c7c08c6c041b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9711,6 +9711,7 @@ M:    Tomas Winkler 
 L: linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
+F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
 
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index c5e6e909efce..6794be9fcc5e 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -6,3 +6,10 @@ config RPMB
  access RPMB partition.
 
  If unsure, select N.
+
+config RPMB_INTF_DEV
+   bool "RPMB character device interface /dev/rpmbN"
+   depends on RPMB
+   help
+ Say yes here if you want to access RPMB from user space
+ via character device interface /dev/rpmb%d
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index 812b3ed264c0..b5dc087b1299 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
+rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
new file mode 100644
index ..f3ad3444f76d
--- /dev/null
+++ b/drivers/char/rpmb/cdev.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "rpmb-cdev.h"
+
+static dev_t rpmb_devt;
+#define RPMB_MAX_DEVS  MINORMASK
+
+#define RPMB_DEV_OPEN0  /** single open bit (position) */
+
+/**
+ * rpmb_open - the open function
+ *
+ * @inode: pointer to inode structure
+ * @fp: pointer to file structure
+ *
+ * Return: 0 on success, <0 on error
+ */
+static int rpmb_open(struct inode *inode, struct file *fp)
+{
+   struct rpmb_dev *rdev;
+
+   rdev = container_of(inode->i_cdev, struct rpmb_dev, cdev);
+   if (!rdev)
+   return -ENODEV;
+
+   /* the rpmb is single open! */
+   if (test_and_set_bit(RPMB_DEV_OPEN, &rdev->status))
+   return -EBUSY;
+
+   mutex_lock(&rdev->lock);
+
+   fp->private_data = rdev;
+
+   mutex_unlock(&rdev->lock);
+
+   return nonseekable_open(inode, fp);
+}
+
+static int rpmb_release(struct inode *inode, struct file *fp)
+{
+   struct rpmb_dev *rdev = fp->private_data;
+
+   clear_bit(RPMB_DEV_OPEN, &a

[PATCH v5 3/8] char: rpmb: add device attributes

2016-07-18 Thread Tomas Winkler
Add attribute type that displays underlay storage type technology
EMMC, UFS, and attribute id, that displays underlay storage device id.
For EMMC this would be content of CID and for UFS serial number from
the device descriptor.


Signed-off-by: Tomas Winkler 
---
V2: resend
V3: set kernel version to 4.7
V4: update target date to Maj
V5: adjust date and kernel version
 Documentation/ABI/testing/sysfs-class-rpmb | 24 
 drivers/char/rpmb/core.c   | 63 ++
 2 files changed, 87 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
index 3ffcd2d1f683..7ca97d86bd97 100644
--- a/Documentation/ABI/testing/sysfs-class-rpmb
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -18,3 +18,27 @@ Contact: Tomas Winkler 
 Description:
The /sys/class/rpmb/rpmbN directory is created for
each RPMB registered device
+
+What:  /sys/class/rpmb/rpmbN/id
+Date:  Aug 2016
+KernelVersion: 4.8
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/id file contains device id
+   in a binary form
+
+What:  /sys/class/rpmb/rpmbN/type
+Date:  Aug 2016
+KernelVersion: 4.8
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/type file contains device
+   underlay storage type technology: EMMC, UFS
+
+What:  /sys/class/rpmb/rpmbN/reliable_wr_cnt
+Date:  Aug 2016
+KernelVersion: 4.8
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/reliable_wr_cnt file contains
+   number of blocks that can be written in a single request
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index ff10cbb7b644..63271c7ed072 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -308,6 +308,67 @@ struct rpmb_dev *rpmb_dev_find_by_device(struct device 
*parent)
 }
 EXPORT_SYMBOL_GPL(rpmb_dev_find_by_device);
 
+static ssize_t type_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   ssize_t ret;
+
+   switch (rdev->ops->type) {
+   case RPMB_TYPE_EMMC:
+   ret = scnprintf(buf, PAGE_SIZE, "EMMC\n");
+   break;
+   case RPMB_TYPE_UFS:
+   ret = scnprintf(buf, PAGE_SIZE, "UFS\n");
+   break;
+   default:
+   ret = scnprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+   break;
+   }
+
+   return ret;
+}
+static DEVICE_ATTR_RO(type);
+
+static ssize_t id_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   size_t sz = min_t(size_t, rdev->ops->dev_id_len, PAGE_SIZE);
+
+   if (!rdev->ops->dev_id)
+   return 0;
+
+   memcpy(buf, rdev->ops->dev_id, sz);
+   return sz;
+}
+static DEVICE_ATTR_RO(id);
+
+static ssize_t reliable_wr_cnt_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", rdev->ops->reliable_wr_cnt);
+}
+static DEVICE_ATTR_RO(reliable_wr_cnt);
+
+static struct attribute *rpmb_attrs[] = {
+   &dev_attr_type.attr,
+   &dev_attr_id.attr,
+   &dev_attr_reliable_wr_cnt.attr,
+   NULL,
+};
+
+static struct attribute_group rpmb_attr_group = {
+   .attrs = rpmb_attrs,
+};
+
+static const struct attribute_group *rpmb_attr_groups[] = {
+   &rpmb_attr_group,
+   NULL
+};
+
 /**
  * rpmb_dev_unregister - unregister RPMB partition from the RPMB subsystem
  *
@@ -377,6 +438,8 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
dev_set_name(&rdev->dev, "rpmb%d", id);
rdev->dev.class = &rpmb_class;
rdev->dev.parent = dev;
+   rdev->dev.groups = rpmb_attr_groups;
+
ret = device_register(&rdev->dev);
if (ret)
goto exit;
-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 1/8] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2016-07-18 Thread Tomas Winkler
Few storage technologies such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but by a
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and
PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE driver can claim the RPMB interface, for example, via
class_interface_register ().
The layer provides two APIs, for rpmb_cmd_req() for issuing one of RPMB
specific commands and rpmb_cmd_seq() for issuing of raw RPMB protocol
frames,  which is close to emmc multi ioctl interface.

A storage device registers its RPMB hardware (eMMC) partition or RPMB
W-LUN (UFS) with the RPMB layer providing an implementation for
rpmb_cmd_seq() handler. The interface enables sending sequence of RPMB
standard frames.


Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
V2: added short workflow description in the commit message
V3: commit message fix
V4: resend
V5: add rpmb sequence interface.

 MAINTAINERS|   7 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |   8 +
 drivers/char/rpmb/Makefile |   4 +
 drivers/char/rpmb/core.c   | 414 +
 include/linux/rpmb.h   | 230 +
 7 files changed, 666 insertions(+)
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 include/linux/rpmb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5ec852e1d94c..50143ebc862f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9706,6 +9706,13 @@ F:   include/net/rose.h
 F: include/uapi/linux/rose.h
 F: net/rose/
 
+RPMB SUBSYSTEM
+M: Tomas Winkler 
+L: linux-ker...@vger.kernel.org
+S: Supported
+F: drivers/char/rpmb/*
+F: include/linux/rpmb.h
+
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 601f64fcc890..2dc9733a6427 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -602,5 +602,7 @@ config TILE_SROM
 
 source "drivers/char/xillybus/Kconfig"
 
+source "drivers/char/rpmb/Kconfig"
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d8a7579300d2..1a5e43c1a9a6 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -60,3 +60,4 @@ js-rtc-y = rtc.o
 
 obj-$(CONFIG_TILE_SROM)+= tile-srom.o
 obj-$(CONFIG_XILLYBUS) += xillybus/
+obj-$(CONFIG_RPMB) += rpmb/
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
new file mode 100644
index ..c5e6e909efce
--- /dev/null
+++ b/drivers/char/rpmb/Kconfig
@@ -0,0 +1,8 @@
+config RPMB
+   tristate "RPMB partition interface"
+   help
+ Unified RPMB partition interface for eMMC and UFS.
+ Provides interface for in kernel security controllers to
+ access RPMB partition.
+
+ If unsure, select N.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
new file mode 100644
index ..812b3ed264c0
--- /dev/null
+++ b/drivers/char/rpmb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RPMB) += rpmb.o
+rpmb-objs += core.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
new file mode 100644
index ..ff10cbb7b644
--- /dev/null
+++ b/drivers/char/rpmb/core.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static DEFINE_IDA(rpmb_ida);
+
+/**
+ * rpmb_dev_get - increase rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+struct rpmb_dev *rpmb_dev_get(struct rpmb_dev *rdev)
+{
+   return get_device(&rdev->dev) ? rdev : NULL;
+}
+EXPORT_SYMBOL_GPL(rpmb_dev_get);
+
+/**
+ * rpmb_dev_put - decrease rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+vo

Re: [PATCH v2] byteswap: try to avoid __builtin_constant_p gcc bug

2016-06-22 Thread Tomas Winkler
On Wed, Jun 22, 2016 at 3:25 PM, Arnd Bergmann  wrote:
> On Wednesday, June 22, 2016 2:44:21 PM CEST Tomas Winkler wrote:
>> >
>> > There are more than 20 files that have the statement: case cpu_to_...
>> > Sparse complains about: case __builtin_bswap, not about 
>> > __builtin_constant_p.
>>
>> There is even much more in the header files used in  initializers,
>> which also require constants.  I wonder if __builtin_bswap produces
>> constant expression correctly under gcc?
>
> In gcc-4.8 or later yes. gcc-4.6/4.7 on powerpc was a special case that we
> have worked around now, as the 16-bit byteswap there was not a constant
> expression, unlike the 32-bit and 64-bit ones.

Can you please give any references to that?
Just to make sure we are on the same line , the  bottom line is that
sparse has to be adjusted.

Thanks
Tomas
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] byteswap: try to avoid __builtin_constant_p gcc bug

2016-06-22 Thread Tomas Winkler
On Wed, Jun 22, 2016 at 1:25 PM, Levy, Amir (Jer)
 wrote:
> On 2016-06-22 Arnd Bergmann wrote:
>> On Wednesday, June 22, 2016 11:24:50 AM CEST Tomas Winkler wrote:
>> > On Tue, Jun 21, 2016 at 12:02 PM, Tomas Winkler 
>> wrote:
>> > > On Tue, May 3, 2016 at 9:36 AM, Arnd Bergmann 
>> wrote:
>> > >> On Monday 02 May 2016 16:32:25 Andrew Morton wrote:
>>
>> > >>  #ifdef __HAVE_BUILTIN_BSWAP32__
>> > >> -#define __swab32(x) __builtin_bswap32((__u32)(x))
>> > >> +#define __swab32(x) (__u32)__builtin_bswap32((__u32)(x))
>> > >>  #else
>> > >>  #define __swab32(x)\
>> > >> (__builtin_constant_p((__u32)(x)) ? \
>> > >
>> > >>
>> > >
>> > > I wonder if this doesn't break switch statement that requires a
>> > > constant expression, there few cases like this over the kernel.
>> > >
>> > > switch(val) {
>> > > case cpu_to_le32(IXGBE_RXDADV_STAT_FCSTAT_FCPRSP):
>> > >
>> > > http://lxr.free-electrons.com/source/drivers/net/ethernet/intel/ixgb
>> > > e/ixgbe_fcoe.c#L458
>> > >
>> >
>> > I'm asking because sparse and checkpatch doesn't agree on that ping
>> > sparse issues
>> > 'error: bad constant expression'
>> > When changing to __constant_cpu_to_le32 sparse is happy but
>> > checkpatch.ps is complaining
>> > __constant_cpu_to_le32 should be cpu_to_le32
>> >
>>
>> That is an interesting problem, as both seem to be reasonable:
>> sparse probably doesn't understand __builtin_constant_p() enough, while
>> avoiding __constant_cpu_to_le32() is a good recommendation in general.
>>
>> How many instances of this do you see in the kernel? If ixgbe is the only 
>> one,
>> I'd just move the byteswap up into the switch statement:
>>
>>   switch (le32_to_cpu(val)) {
>>   case IXGBE_RXDADV_STAT_FCSTAT_FCPRSP:
>>
>> which may cost one or two cycles for the non-constant byteswap, but is also
>> easier to read than the current code.
>>
>>   Arnd
>
> There are more than 20 files that have the statement: case cpu_to_...
> Sparse complains about: case __builtin_bswap, not about __builtin_constant_p.

There is even much more in the header files used in  initializers,
which also require constants.  I wonder if __builtin_bswap produces
constant expression correctly under gcc?

Thanks
Tomas
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] byteswap: try to avoid __builtin_constant_p gcc bug

2016-06-22 Thread Tomas Winkler
On Tue, Jun 21, 2016 at 12:02 PM, Tomas Winkler  wrote:
> On Tue, May 3, 2016 at 9:36 AM, Arnd Bergmann  wrote:
>> On Monday 02 May 2016 16:32:25 Andrew Morton wrote:
>>> On Tue, 03 May 2016 01:10:16 +0200 Arnd Bergmann  wrote:
>>>
>>> > On Monday 02 May 2016 16:02:18 Andrew Morton wrote:
>>> > > On Mon, 02 May 2016 23:48:19 +0200 Arnd Bergmann  wrote:
>>> > >
>>> > > > This is another attempt to avoid a regression in wwn_to_u64() after
>>> > > > that started using get_unaligned_be64(), which in turn ran into a
>>> > > > bug on gcc-4.9 through 6.1.
>>> > >
>>> > > I'm still getting a couple screenfuls of things like
>>> > >
>>> > > net/tipc/name_distr.c: In function 'tipc_named_process_backlog':
>>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>>> > > int', but argument 3 has type 'unsigned int'
>>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>>> > > int', but argument 4 has type 'unsigned int'
>>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>>> > > int', but argument 5 has type 'unsigned int'
>>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>>> > > int', but argument 7 has type 'unsigned int'
>>> >
>>> > I've built a few thousand kernels (arm32 with gcc-6.1) with the patch 
>>> > applied,
>>> > but didn't see this one. What target architecture and compiler version 
>>> > produced
>>> > this? Does it go away if you add a (__u32) cast? I don't even know what 
>>> > the
>>> > warning is trying to tell me.
>>>
>>> heh, I didn't actually read it.
>>>
>>> Hopefully we can write this off as a gcc-4.4.4 glitch. 4.8.4 is OK.
>>
>> Ah, old compiler. I've tried gcc-4.3 now on ARM, and I don't get this warning
>> (just a lot "may be used uninitialized"), but unlike gcc-4.4, my version 
>> doesn't
>> actually get into the code path I have changed because __builtin_bswap32 was 
>> only
>> introduced with 4.4.
>>
>> I don't have gcc-4.4 and 4.5 here, but the warning does show up with 4.6, 4.7
>> and 4.8:
>>
>> drivers/soc/sunxi/sunxi_sram.c: In function ‘sunxi_sram_show’:
>> drivers/soc/sunxi/sunxi_sram.c:103:7: warning: format ‘%x’ expects argument 
>> of type ‘unsigned int’, but argument 3 has type ‘unsigned int’ [-Wformat=]
>>
>> 4.8 is probably still common enough that we should try to address this.
>> This change addresses the problem for me with ARM gcc-4.8, but adding
>> two more type casts. This also makes the 16/32/64 bit swaps all
>> look the same. I would expect this to also have the same effect on 4.4.
>>
>> Please fold into the previous patch.
>>
>> Signed-off-by: Arnd Bergmann 
>>
>> diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h
>> index d737804af181..8f3a8f606fd9 100644
>> --- a/include/uapi/linux/swab.h
>> +++ b/include/uapi/linux/swab.h
>> @@ -97,7 +97,7 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 
>> val)
>>   * @x: value to byteswap
>>   */
>>  #ifdef __HAVE_BUILTIN_BSWAP16__
>> -#define __swab16(x) __builtin_bswap16((__u16)(x))
>> +#define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
>>  #else
>>  #define __swab16(x)\
>> (__builtin_constant_p((__u16)(x)) ? \
>> @@ -110,7 +110,7 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 
>> val)
>>   * @x: value to byteswap
>>   */
>>  #ifdef __HAVE_BUILTIN_BSWAP32__
>> -#define __swab32(x) __builtin_bswap32((__u32)(x))
>> +#define __swab32(x) (__u32)__builtin_bswap32((__u32)(x))
>>  #else
>>  #define __swab32(x)\
>> (__builtin_constant_p((__u32)(x)) ? \
>
>>
>
> I wonder if this doesn't break switch statement that requires a
> constant expression, there few cases like this over the kernel.
>
> switch(val) {
> case cpu_to_le32(IXGBE_RXDADV_STAT_FCSTAT_FCPRSP):
>
> http://lxr.free-electrons.com/source/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c#L458
>

I'm asking because sparse and checkpatch doesn't agree on that ping
sparse issues
'error: bad constant expression'
When changing to __constant_cpu_to_le32 sparse is happy but
checkpatch.ps is complaining
__constant_cpu_to_le32 should be cpu_to_le32



 Thanks
 Tomas
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] byteswap: try to avoid __builtin_constant_p gcc bug

2016-06-21 Thread Tomas Winkler
On Tue, May 3, 2016 at 9:36 AM, Arnd Bergmann  wrote:
> On Monday 02 May 2016 16:32:25 Andrew Morton wrote:
>> On Tue, 03 May 2016 01:10:16 +0200 Arnd Bergmann  wrote:
>>
>> > On Monday 02 May 2016 16:02:18 Andrew Morton wrote:
>> > > On Mon, 02 May 2016 23:48:19 +0200 Arnd Bergmann  wrote:
>> > >
>> > > > This is another attempt to avoid a regression in wwn_to_u64() after
>> > > > that started using get_unaligned_be64(), which in turn ran into a
>> > > > bug on gcc-4.9 through 6.1.
>> > >
>> > > I'm still getting a couple screenfuls of things like
>> > >
>> > > net/tipc/name_distr.c: In function 'tipc_named_process_backlog':
>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>> > > int', but argument 3 has type 'unsigned int'
>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>> > > int', but argument 4 has type 'unsigned int'
>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>> > > int', but argument 5 has type 'unsigned int'
>> > > net/tipc/name_distr.c:330: warning: format '%u' expects type 'unsigned 
>> > > int', but argument 7 has type 'unsigned int'
>> >
>> > I've built a few thousand kernels (arm32 with gcc-6.1) with the patch 
>> > applied,
>> > but didn't see this one. What target architecture and compiler version 
>> > produced
>> > this? Does it go away if you add a (__u32) cast? I don't even know what the
>> > warning is trying to tell me.
>>
>> heh, I didn't actually read it.
>>
>> Hopefully we can write this off as a gcc-4.4.4 glitch. 4.8.4 is OK.
>
> Ah, old compiler. I've tried gcc-4.3 now on ARM, and I don't get this warning
> (just a lot "may be used uninitialized"), but unlike gcc-4.4, my version 
> doesn't
> actually get into the code path I have changed because __builtin_bswap32 was 
> only
> introduced with 4.4.
>
> I don't have gcc-4.4 and 4.5 here, but the warning does show up with 4.6, 4.7
> and 4.8:
>
> drivers/soc/sunxi/sunxi_sram.c: In function ‘sunxi_sram_show’:
> drivers/soc/sunxi/sunxi_sram.c:103:7: warning: format ‘%x’ expects argument 
> of type ‘unsigned int’, but argument 3 has type ‘unsigned int’ [-Wformat=]
>
> 4.8 is probably still common enough that we should try to address this.
> This change addresses the problem for me with ARM gcc-4.8, but adding
> two more type casts. This also makes the 16/32/64 bit swaps all
> look the same. I would expect this to also have the same effect on 4.4.
>
> Please fold into the previous patch.
>
> Signed-off-by: Arnd Bergmann 
>
> diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h
> index d737804af181..8f3a8f606fd9 100644
> --- a/include/uapi/linux/swab.h
> +++ b/include/uapi/linux/swab.h
> @@ -97,7 +97,7 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 
> val)
>   * @x: value to byteswap
>   */
>  #ifdef __HAVE_BUILTIN_BSWAP16__
> -#define __swab16(x) __builtin_bswap16((__u16)(x))
> +#define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
>  #else
>  #define __swab16(x)\
> (__builtin_constant_p((__u16)(x)) ? \
> @@ -110,7 +110,7 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 
> val)
>   * @x: value to byteswap
>   */
>  #ifdef __HAVE_BUILTIN_BSWAP32__
> -#define __swab32(x) __builtin_bswap32((__u32)(x))
> +#define __swab32(x) (__u32)__builtin_bswap32((__u32)(x))
>  #else
>  #define __swab32(x)\
> (__builtin_constant_p((__u32)(x)) ? \

>

I wonder if this doesn't break switch statement that requires a
constant expression, there few cases like this over the kernel.

switch(val) {
case cpu_to_le32(IXGBE_RXDADV_STAT_FCSTAT_FCPRSP):

http://lxr.free-electrons.com/source/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c#L458


Thanks
Tomas
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 0/8] Replay Protected Memory Block (RPMB) subsystem

2016-06-01 Thread Tomas Winkler
Few storage technology such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but
by a set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and
PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

A storage device registers its RPMB hardware (emmc) partition or
RPMB W-LUN (ufs) with the RPMB layer providing an implementation for
send_rpmb_req() handler.
There is as well simulation platform device. This is handy as an RPMB
key can be programmed only once at storage device lifetime.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE driver can claim rpmb interface, for example,
via  class_interface_register ().

A parallel user space API is provided via /dev/rpmbX character
device with a single IOCTL command similar to the one provided by
mmc/ioctl. h
This API may help applications such as 
https://android.googlesource.com/trusty/app/storage/
To be obliviose to the underlaying HW storage technology.

There is a sample tool under tools/rpmb/ directory that exercises
this interface.

Tomas Winkler (8):
  rpmb: add Replay Protected Memory Block (RPMB) subsystem
  char: rpmb: add sysfs-class ABI documentation
  char: rpmb: add device attributes
  char: rpmb: provide user space interface
  char: rpmb: add RPMB simulation device
  tools rpmb: add RPBM access tool
  mmc: block: register RPMB partition with the RPMB subsystem
  scsi: ufs: connect to RPMB subsystem

 Documentation/ABI/testing/sysfs-class-rpmb |  44 ++
 Documentation/ioctl/ioctl-number.txt   |   1 +
 MAINTAINERS|  10 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |  25 +
 drivers/char/rpmb/Makefile |   6 +
 drivers/char/rpmb/cdev.c   | 207 +++
 drivers/char/rpmb/core.c   | 408 ++
 drivers/char/rpmb/rpmb-cdev.h  |  31 ++
 drivers/char/rpmb/rpmb_sim.c   | 589 
 drivers/mmc/card/Kconfig   |   1 +
 drivers/mmc/card/block.c   | 292 ++
 drivers/scsi/ufs/Kconfig   |   1 +
 drivers/scsi/ufs/ufshcd.c  | 219 
 drivers/scsi/ufs/ufshcd.h  |   2 +
 include/linux/rpmb.h   | 138 +
 include/uapi/linux/rpmb.h  | 120 
 tools/Makefile |  14 +-
 tools/rpmb/.gitignore  |   2 +
 tools/rpmb/Makefile|  32 ++
 tools/rpmb/rpmb.c  | 862 +
 22 files changed, 3002 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 drivers/char/rpmb/rpmb_sim.c
 create mode 100644 include/linux/rpmb.h
 create mode 100644 include/uapi/linux/rpmb.h
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 1/8] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2016-06-01 Thread Tomas Winkler
Few storage technologies such is EMMC, UFS, and NVMe support RPMB hardware
partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but by a
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE driver can claim the RPMB interface, for example,
via class_interface_register ().

A storage device registers its RPMB hardware (eMMC) partition or
RPMB W-LUN (UFS) with the RPMB layer providing an implementation
for send_rpmb_req() handler.

V2: added short workflow description in the commit message
V3: commit message fix
V4: resend

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 MAINTAINERS|   7 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |   8 ++
 drivers/char/rpmb/Makefile |   4 +
 drivers/char/rpmb/core.c   | 337 +
 include/linux/rpmb.h   | 200 +++
 7 files changed, 559 insertions(+)
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 include/linux/rpmb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7304d2e37a98..e045c3a43920 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9691,6 +9691,13 @@ F:   include/net/rose.h
 F: include/uapi/linux/rose.h
 F: net/rose/
 
+RPMB SUBSYSTEM
+M: Tomas Winkler 
+L: linux-ker...@vger.kernel.org
+S: Supported
+F: drivers/char/rpmb/*
+F: include/linux/rpmb.h
+
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 601f64fcc890..2dc9733a6427 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -602,5 +602,7 @@ config TILE_SROM
 
 source "drivers/char/xillybus/Kconfig"
 
+source "drivers/char/rpmb/Kconfig"
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d8a7579300d2..1a5e43c1a9a6 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -60,3 +60,4 @@ js-rtc-y = rtc.o
 
 obj-$(CONFIG_TILE_SROM)+= tile-srom.o
 obj-$(CONFIG_XILLYBUS) += xillybus/
+obj-$(CONFIG_RPMB) += rpmb/
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
new file mode 100644
index ..c5e6e909efce
--- /dev/null
+++ b/drivers/char/rpmb/Kconfig
@@ -0,0 +1,8 @@
+config RPMB
+   tristate "RPMB partition interface"
+   help
+ Unified RPMB partition interface for eMMC and UFS.
+ Provides interface for in kernel security controllers to
+ access RPMB partition.
+
+ If unsure, select N.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
new file mode 100644
index ..812b3ed264c0
--- /dev/null
+++ b/drivers/char/rpmb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RPMB) += rpmb.o
+rpmb-objs += core.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
new file mode 100644
index ..c9ea30aca6be
--- /dev/null
+++ b/drivers/char/rpmb/core.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static DEFINE_IDA(rpmb_ida);
+
+/**
+ * rpmb_dev_get - increase rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+struct rpmb_dev *rpmb_dev_get(struct rpmb_dev *rdev)
+{
+   return get_device(&rdev->dev) ? rdev : NULL;
+}
+EXPORT_SYMBOL_GPL(rpmb_dev_get);
+
+/**
+ * rpmb_dev_put - decrease rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+void rpmb_dev_put(struct rpmb_dev *rdev)
+{
+   put_device(&rdev->dev);
+}
+EXPORT_SYMBOL_GPL(rpmb_dev_put);
+
+static int rpmb_request_verify(struct rpmb_dev *rdev, struct rpmb_data *rpmbd)
+{
+   u16 req_type, block_count;
+
+   if (rpmbd->in_frames == NULL  || rpmbd->out_frames == NULL

[PATCH v4 4/8] char: rpmb: provide user space interface

2016-06-01 Thread Tomas Winkler
The user space API is achieved via single synchronous IOCTL.
The request is submitted in in_frames_ptr pointer and received
in out_frames_ptr.

V2: use memdup_user
V3: commit message fix
V4: resend

Signed-off-by: Tomas Winkler 
---
 Documentation/ioctl/ioctl-number.txt |   1 +
 MAINTAINERS  |   1 +
 drivers/char/rpmb/Kconfig|   7 ++
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/cdev.c | 207 +++
 drivers/char/rpmb/core.c |   9 +-
 drivers/char/rpmb/rpmb-cdev.h|  31 ++
 include/linux/rpmb.h |  78 ++---
 include/uapi/linux/rpmb.h| 120 
 9 files changed, 384 insertions(+), 71 deletions(-)
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 include/uapi/linux/rpmb.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 9369d3b0f09a..51a514befa48 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -320,6 +320,7 @@ Code  Seq#(hex) Include FileComments
 0xB1   00-1F   PPPoX   <mailto:mostr...@styx.uwaterloo.ca>
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h<mailto:linux-g...@vger.kernel.org>
+0xB5   00  linux/uapi/linux/rpmb.h <mailto:linux-...@linux.intel.com>
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-8F   uapi/scsi/cxlflash_ioctl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index b4228dd58e06..bf806f2d3e19 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9696,6 +9696,7 @@ M:    Tomas Winkler 
 L: linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
+F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
 
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index c5e6e909efce..6794be9fcc5e 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -6,3 +6,10 @@ config RPMB
  access RPMB partition.
 
  If unsure, select N.
+
+config RPMB_INTF_DEV
+   bool "RPMB character device interface /dev/rpmbN"
+   depends on RPMB
+   help
+ Say yes here if you want to access RPMB from user space
+ via character device interface /dev/rpmb%d
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index 812b3ed264c0..b5dc087b1299 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
+rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
new file mode 100644
index ..67e94943d3e3
--- /dev/null
+++ b/drivers/char/rpmb/cdev.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rpmb-cdev.h"
+
+static dev_t rpmb_devt;
+#define RPMB_MAX_DEVS  MINORMASK
+
+#define RPMB_DEV_OPEN0  /** single open bit (position) */
+
+/**
+ * rpmb_open - the open function
+ *
+ * @inode: pointer to inode structure
+ * @file: pointer to file structure
+ *
+ * Return: 0 on success, <0 on error
+ */
+static int rpmb_open(struct inode *inode, struct file *file)
+{
+   struct rpmb_dev *rdev;
+
+   rdev = container_of(inode->i_cdev, struct rpmb_dev, cdev);
+   if (!rdev)
+   return -ENODEV;
+
+   /* the rpmb is single open! */
+   if (test_and_set_bit(RPMB_DEV_OPEN, &rdev->status))
+   return -EBUSY;
+
+   mutex_lock(&rdev->lock);
+
+   file->private_data = rdev;
+
+   mutex_unlock(&rdev->lock);
+
+   return nonseekable_open(inode, file);
+}
+
+static int rpmb_release(struct inode *inode, struct file *file)
+{
+   struct rpmb_dev *rdev = file->private_data;
+
+   clear_bit(RPMB_DEV_OPEN, &rdev->status);
+
+   return 0;
+}
+
+/*
+ * FIMXE: will be exported by the kernel in future version
+ * helper to convert user pointers passed inside __aligned_u64 fields
+ */
+static void __user *u64_to_ptr(__u64 val)
+{
+   return (void __user *) (unsigned long) val;
+}
+
+static int rpmb_ioctl_cmd(struct rpmb_dev *rdev,
+

[PATCH v4 5/8] char: rpmb: add RPMB simulation device

2016-06-01 Thread Tomas Winkler
This is a simple platform device used for testing
the rpmb subsystem.

The module currently supports two configuration options:
1. max_wr_blks: for specifying max blocks that can be written
in a single command
2. daunits:  used to set storage capacity in 128K units.

V2: remove .owner setting, it is set automatically
V3: 1. Add shutdown handler (similar to ufshcd)
2. Commit message fix
V4: use select RPMB to ensure valid configuration

Signed-off-by: Tomas Winkler 
---
 drivers/char/rpmb/Kconfig|  10 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/rpmb_sim.c | 589 +++
 3 files changed, 600 insertions(+)
 create mode 100644 drivers/char/rpmb/rpmb_sim.c

diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index 6794be9fcc5e..c21b3934249f 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -13,3 +13,13 @@ config RPMB_INTF_DEV
help
  Say yes here if you want to access RPMB from user space
  via character device interface /dev/rpmb%d
+
+
+config RPMB_SIM
+   tristate "RPMB partition device simulator"
+   default n
+   select RPMB
+   select CRYPTO_SHA256
+   select CRYPTO_HMAC
+   help
+ RPMB partition simulator used for testing the RPMB subsystem
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index b5dc087b1299..81f924fd9a87 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
 rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
+obj-$(CONFIG_RPMB_SIM) += rpmb_sim.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/rpmb_sim.c b/drivers/char/rpmb/rpmb_sim.c
new file mode 100644
index ..f2565f406cc1
--- /dev/null
+++ b/drivers/char/rpmb/rpmb_sim.c
@@ -0,0 +1,589 @@
+/**
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Corporation.
+ * linux-...@linux.intel.com
+ * http://www.intel.com
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *contributors may be used to endorse or promote products derived
+ *from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static const char id[] = "RPMB:SIM";
+#define CAPACITY_UNIT SZ_128K
+#define CAPACITY_MIN  SZ_128K
+#define CAPACITY_MAX  SZ_16M
+#define BLK_UNIT  SZ_256
+
+static unsigned int max_wr_blks = 1;
+module_param(max_wr_blks, uint, 0644);
+MODULE_PARM_DESC(max_wr_blks,
+   &

[PATCH v4 3/8] char: rpmb: add device attributes

2016-06-01 Thread Tomas Winkler
Add attribute type that displays underlay storage type technology
EMMC, UFS, and attribute id, that displays underlay storage device id.
For EMMC this would be content of CID and for UFS serial number from
the device descriptor.

V2: resend
V3: set the kernel version to 4.7
V4: set the kernel version to 4.8

Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-class-rpmb | 24 +++
 drivers/char/rpmb/core.c   | 64 ++
 2 files changed, 88 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
index 44ee4d31dc0b..e9027f37ca5b 100644
--- a/Documentation/ABI/testing/sysfs-class-rpmb
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -18,3 +18,27 @@ Contact: Tomas Winkler 
 Description:
The /sys/class/rpmb/rpmbN directory is created for
each RPMB registered device
+
+What:  /sys/class/rpmb/rpmbN/id
+Date:  Maj 2016
+KernelVersion: 4.7
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/id file contains device id
+   in a binary form
+
+What:  /sys/class/rpmb/rpmbN/type
+Date:  Jun 2016
+KernelVersion: 4.8
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/type file contains device
+   underlay storage type technology: EMMC, UFS
+
+What:  /sys/class/rpmb/rpmbN/reliable_wr_cnt
+Date:  Jun 2016
+KernelVersion: 4.8
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/reliable_wr_cnt file contains
+   number of blocks that can be written in a single request
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index c9ea30aca6be..fb401331d345 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -230,6 +230,68 @@ struct rpmb_dev *rpmb_dev_find_by_device(struct device 
*parent)
 }
 EXPORT_SYMBOL_GPL(rpmb_dev_find_by_device);
 
+static ssize_t type_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   ssize_t ret;
+
+   switch (rdev->ops->type) {
+   case RPMB_TYPE_EMMC:
+   ret = scnprintf(buf, PAGE_SIZE, "EMMC\n");
+   break;
+   case RPMB_TYPE_UFS:
+   ret = scnprintf(buf, PAGE_SIZE, "UFS\n");
+   break;
+   default:
+   ret = scnprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+   break;
+   }
+
+   return ret;
+}
+static DEVICE_ATTR_RO(type);
+
+static ssize_t id_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   size_t sz = min_t(size_t, rdev->ops->dev_id_len, PAGE_SIZE);
+
+   if (!rdev->ops->dev_id)
+   return 0;
+
+   memcpy(buf, rdev->ops->dev_id, sz);
+   return sz;
+}
+static DEVICE_ATTR_RO(id);
+
+static ssize_t reliable_wr_cnt_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", rdev->ops->reliable_wr_cnt);
+}
+static DEVICE_ATTR_RO(reliable_wr_cnt);
+
+
+static struct attribute *rpmb_attrs[] = {
+   &dev_attr_type.attr,
+   &dev_attr_id.attr,
+   &dev_attr_reliable_wr_cnt.attr,
+   NULL,
+};
+
+static struct attribute_group rpmb_attr_group = {
+   .attrs = rpmb_attrs,
+};
+
+static const struct attribute_group *rpmb_attr_groups[] = {
+   &rpmb_attr_group,
+   NULL
+};
+
 /**
  * rpmb_dev_unregister - unregister RPMB partition from the RPMB subsystem
  *
@@ -300,6 +362,8 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
dev_set_name(&rdev->dev, "rpmb%d", id);
rdev->dev.class = &rpmb_class;
rdev->dev.parent = dev;
+   rdev->dev.groups = rpmb_attr_groups;
+
ret = device_register(&rdev->dev);
if (ret)
goto exit;
-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/8] char: rpmb: add sysfs-class ABI documentation

2016-06-01 Thread Tomas Winkler
V2: resend
V3: add more verbose description
V4: update kernel version to 4.8

Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-class-rpmb | 20 
 MAINTAINERS|  1 +
 2 files changed, 21 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
new file mode 100644
index ..44ee4d31dc0b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -0,0 +1,20 @@
+What:  /sys/class/rpmb/
+Date:  Jun 2016
+KernelVersion:  4.8
+Contact:   Tomas Winkler 
+Description:
+   The rpmb/ class sub-directory belongs to RPMB device class.
+
+   Few storage technologies such is EMMC, UFS, and NVMe support
+   Replay Protected Memory Block (RPMB) hardware partition with
+   common protocol and frame layout.
+   Such a partition provides authenticated and replay protected 
access,
+   hence suitable as a secure storage.
+
+What:  /sys/class/rpmb/rpmbN/
+Date:  Jun 2016
+KernelVersion: 4.8
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN directory is created for
+   each RPMB registered device
diff --git a/MAINTAINERS b/MAINTAINERS
index e045c3a43920..b4228dd58e06 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9697,6 +9697,7 @@ L:linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
 F: include/linux/rpmb.h
+F: Documentation/ABI/testing/sysfs-class-rpmb
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 6/8] tools rpmb: add RPBM access tool

2016-06-01 Thread Tomas Winkler
Add simple RPMB host testing tool. It can be used
to program key, write and read data block, and retrieve
write counter.

V2: resend
V3: fix missing objtool
V4: add verbose option

Signed-off-by: Tomas Winkler 
---
 MAINTAINERS   |   1 +
 tools/Makefile|  14 +-
 tools/rpmb/.gitignore |   2 +
 tools/rpmb/Makefile   |  32 ++
 tools/rpmb/rpmb.c | 862 ++
 5 files changed, 906 insertions(+), 5 deletions(-)
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bf806f2d3e19..41db922aaf38 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9699,6 +9699,7 @@ F:drivers/char/rpmb/*
 F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
+F: tools/rpmb/
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
diff --git a/tools/Makefile b/tools/Makefile
index f10b64d8c674..b90003945af1 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -20,6 +20,7 @@ help:
@echo '  lguest - a minimal 32-bit x86 hypervisor'
@echo '  net- misc networking tools'
@echo '  perf   - Linux performance measurement and 
analysis tool'
+   @echo '  rpmb   - Replay protected memory block access 
tool'
@echo '  selftests  - various kernel selftests'
@echo '  spi- spi tools'
@echo '  objtool- an ELF object analysis tool'
@@ -56,7 +57,7 @@ acpi: FORCE
 cpupower: FORCE
$(call descend,power/$@)
 
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio gpio objtool: FORCE
$(call descend,$@)
 
 liblockdep: FORCE
@@ -86,7 +87,7 @@ freefall: FORCE
$(call descend,laptop/$@)
 
 all: acpi cgroup cpupower hv firewire lguest \
-   perf selftests turbostat usb \
+   perf rpmb selftests turbostat usb \
virtio vm net x86_energy_perf_policy \
tmon freefall objtool
 
@@ -96,7 +97,7 @@ acpi_install:
 cpupower_install:
$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install hv_install lguest_install perf_install 
usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install hv_install lguest_install perf_install 
rpmb_install usb_install virtio_install vm_install net_install objtool_install:
$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -115,7 +116,7 @@ kvm_stat_install:
$(call descend,kvm/$(@:_install=),install)
 
 install: acpi_install cgroup_install cpupower_install hv_install 
firewire_install lguest_install \
-   perf_install selftests_install turbostat_install usb_install \
+   perf_install rpmb_install selftests_install turbostat_install 
usb_install \
virtio_install vm_install net_install 
x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install
 
@@ -144,6 +145,9 @@ perf_clean:
$(Q)mkdir -p $(PERF_O) .
$(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean
 
+rpmb_clean:
+   $(call descend,$(@:_clean=),clean)
+
 selftests_clean:
$(call descend,testing/$(@:_clean=),clean)
 
@@ -160,7 +164,7 @@ build_clean:
$(call descend,build,clean)
 
 clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean 
lguest_clean \
-   perf_clean selftests_clean turbostat_clean spi_clean usb_clean 
virtio_clean \
+   perf_clean rpmb_clean selftests_clean turbostat_clean spi_clean 
usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean 
tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean 
liblockdep_clean \
gpio_clean objtool_clean
diff --git a/tools/rpmb/.gitignore b/tools/rpmb/.gitignore
new file mode 100644
index ..218f680548e6
--- /dev/null
+++ b/tools/rpmb/.gitignore
@@ -0,0 +1,2 @@
+*.o
+rpmb
diff --git a/tools/rpmb/Makefile b/tools/rpmb/Makefile
new file mode 100644
index ..e0e51f306dac
--- /dev/null
+++ b/tools/rpmb/Makefile
@@ -0,0 +1,32 @@
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+INSTALL = install
+prefix ?= /usr/local
+bindir = $(prefix)/bin
+
+
+CFLAGS += -D__EXPORTED_HEADERS__
+CFLAGS += -I$(srctree)/include/uapi -I$(srctree)/include
+LDLIBS += $(shell $(PKG_CONFIG) --libs libcrypto)
+
+prog := rpmb
+
+all : $(

[PATCH v4 7/8] mmc: block: register RPMB partition with the RPMB subsystem

2016-06-01 Thread Tomas Winkler
Register eMMC RPMB partition with the RPMB subsystem and provide
implementation for the RPMB access operations abstracting
actual multi step process.

V2: resend
V3: commit message fix
V4: Kconfig: use select RPMB to ensure valid configuration
Switch back to main area after RPMB access

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 drivers/mmc/card/Kconfig |   1 +
 drivers/mmc/card/block.c | 292 +++
 2 files changed, 293 insertions(+)

diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 5562308699bc..537d0bc82781 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -7,6 +7,7 @@ comment "MMC/SD/SDIO Card Drivers"
 config MMC_BLOCK
tristate "MMC block device driver"
depends on BLOCK
+   select RPMB
default y
help
  Say Y here to enable the MMC block device driver support.
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index e62fde3ac431..274a21fe8be5 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -110,6 +111,7 @@ struct mmc_blk_data {
 #define MMC_BLK_WRITE  BIT(1)
 #define MMC_BLK_DISCARDBIT(2)
 #define MMC_BLK_SECDISCARD BIT(3)
+#define MMC_BLK_RPMB   BIT(4)
 
/*
 * Only set in main mmc_blk_data associated
@@ -1162,6 +1164,292 @@ int mmc_access_rpmb(struct mmc_queue *mq)
return false;
 }
 
+static int mmc_rpmb_send_cmd(struct mmc_card *card,
+u16 rpmb_type, int data_type,
+u8 *buf, u16 blks)
+{
+   struct mmc_command sbc = {
+   .opcode = MMC_SET_BLOCK_COUNT,
+   .flags  = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   struct mmc_command cmd = {
+   .flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
+   };
+
+   struct mmc_data data = {
+   .blksz = 512,
+   };
+   struct mmc_request mrq = {
+   .sbc= &sbc,
+   .cmd= &cmd,
+   .data   = &data,
+   .stop   = NULL,
+   };
+   struct scatterlist sg;
+   bool do_rel_wr;
+
+   /*  set CMD23 */
+   sbc.arg = blks & 0x;
+   do_rel_wr = (rpmb_type == RPMB_WRITE_DATA ||
+rpmb_type == RPMB_PROGRAM_KEY);
+
+   if (do_rel_wr)
+   sbc.arg |= MMC_CMD23_ARG_REL_WR;
+
+   /*  set CMD25/18 */
+   cmd.opcode = (data_type == MMC_DATA_WRITE) ?
+   MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
+
+   sg_init_one(&sg, buf, 512 * blks);
+
+   data.blocks = blks;
+   data.sg = &sg;
+   data.sg_len = 1;
+   data.flags  = data_type;
+   mmc_set_data_timeout(&data, card);
+
+   mmc_wait_for_req(card->host, &mrq);
+
+   if (cmd.error) {
+   pr_err("%s: %s cmd error (%d)\n",
+   mmc_hostname(card->host), __func__, cmd.error);
+   return cmd.error;
+   }
+   if (data.error) {
+   pr_err("%s: %s data error (%d)\n",
+   mmc_hostname(card->host), __func__, data.error);
+   return data.error;
+   }
+   return 0;
+}
+
+static int mmc_blk_rpmb_sequence(struct mmc_card *card,
+   struct rpmb_data *rpmbd)
+{
+   struct rpmb_frame *in_frames, *out_frames;
+   u8 *in_buf, *out_buf;
+   u16 blks;
+   u16 type;
+   int err;
+
+   in_frames = rpmbd->in_frames;
+   out_frames = rpmbd->out_frames;
+   in_buf = (u8 *)in_frames;
+   out_buf = (u8 *)out_frames;
+
+   type = rpmbd->req_type;
+   blks = be16_to_cpu(in_frames[0].block_count);
+
+   switch (type) {
+   case RPMB_PROGRAM_KEY:
+   blks = 1;
+   /* fall through */
+   case RPMB_WRITE_DATA:
+   /* STEP 1: send request to RPMB partition */
+   err = mmc_rpmb_send_cmd(card, type, MMC_DATA_WRITE,
+   in_buf, blks);
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+   }
+
+   /* STEP 2: check write result (reuse out_frames) */
+   memset(out_frames, 0, 512);
+   out_frames[0].req_resp = cpu_to_be16(RPMB_RESULT_READ);
+   err = mmc_rpmb_send_cmd(card,
+   RPMB_RESULT_READ, MMC_DATA_WRITE, out_buf, 1);
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+  

[PATCH v4 8/8] scsi: ufs: connect to RPMB subsystem

2016-06-01 Thread Tomas Winkler
Register UFS RPMB LUN with the RPMB subsystem and provide
implementation for the RPMB access operations. RPMB partition is
accessed via a sequence of security protocol in and security protocol
out commands with UFS specific parameters. This multi step process is
abstracted into 4 basic RPMB commands.

V2: resend
V3: resend
V4: Kconfig: use select RPMB to ensure valid configuration

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/Kconfig  |   1 +
 drivers/scsi/ufs/ufshcd.c | 219 ++
 drivers/scsi/ufs/ufshcd.h |   2 +
 3 files changed, 222 insertions(+)

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 097894a1fab5..e6ff8ecff695 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -38,6 +38,7 @@ config SCSI_UFSHCD
select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select NLS
+   select RPMB
---help---
This selects the support for UFS devices in Linux, say Y and make
  sure that you know the name of your UFS host adapter (the card
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..c087e9713db3 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -37,10 +37,13 @@
  * license terms, and distributes only under these terms.
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -4744,6 +4747,214 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 
 }
 
+#define SEC_PROTOCOL_UFS  0xEC
+#define   SEC_SPECIFIC_UFS_RPMB 0x0001
+
+#define SEC_PROTOCOL_CMD_SIZE 12
+#define SEC_PROTOCOL_RETRIES 3
+#define SEC_PROTOCOL_RETRIES_ON_RESET 10
+#define SEC_PROTOCOL_TIMEOUT msecs_to_jiffies(1000)
+
+static int
+ufshcd_rpmb_security_out(struct scsi_device *sdev,
+struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 trans_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+retry:
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_OUT;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0;  /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(trans_len, cmd + 6);  /* transfer length */
+
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_TO_DEVICE,
+frames, trans_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   pr_err("%s: failed with err %0x\n", __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security out", &sshdr);
+
+   return ret;
+}
+
+static int
+ufshcd_rpmb_security_in(struct scsi_device *sdev,
+   struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 alloc_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+retry:
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_IN;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0; /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(alloc_len, cmd + 6); /* allocation length */
+
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_FROM_DEVICE,
+frames, alloc_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   pr_err("%s: failed with err %0x\n", __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security in&q

[PATCH fix for v4.6] scsi: ufs: make ufshcd_query_descriptor_retry static

2016-04-04 Thread Tomas Winkler
This function was intended to be exported into the ufshcd
API but after all it is not used outside ufshcd.c
Make it static and drop EXPORT_SYMBOL; this can be restored
when needed.

Fixes
warning: no previous prototype for ‘ufshcd_query_descriptor_retry’
Introduced by
commit a70e91b8bbaa ("scsi: ufs: add retry for query descriptors")'

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..629140c11be6 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1982,7 +1982,7 @@ out:
  * The buf_len parameter will contain, on return, the length parameter
  * received on the response.
  */
-int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
+static int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
enum query_opcode opcode, enum desc_idn idn, u8 index,
u8 selector, u8 *desc_buf, int *buf_len)
 {
@@ -1998,7 +1998,6 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
 
return err;
 }
-EXPORT_SYMBOL(ufshcd_query_descriptor_retry);
 
 /**
  * ufshcd_read_desc_param - read the specified descriptor parameter
-- 
2.4.11

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/8] char: rpmb: add sysfs-class ABI documentation

2016-04-04 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
---
V2: resend
 Documentation/ABI/testing/sysfs-class-rpmb | 15 +++
 MAINTAINERS|  1 +
 2 files changed, 16 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
new file mode 100644
index ..62d1959bf19e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -0,0 +1,15 @@
+What:  /sys/class/rpmb/
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The rpmb/ class sub-directory belongs to RPMB device class
+
+
+What:  /sys/class/rpmb/rpmbN/
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN directory is created for
+   each RPMB registered device
diff --git a/MAINTAINERS b/MAINTAINERS
index 98dcd40ab900..62b9edb8881c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9423,6 +9423,7 @@ L:linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
 F: include/linux/rpmb.h
+F: Documentation/ABI/testing/sysfs-class-rpmb
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/8] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2016-04-04 Thread Tomas Winkler
Few storage technology such is EMMC, UFS, and NVMe support RPMB hardware
partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but by a
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE driver can claim rpmb interface, for example,
via  class_interface_register ().

A storage device registers its RPMB hardware (emmc) partition or
RPMB W-LUN (ufs) with the RPMB layer providing an implementation
for send_rpmb_req() handler.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
V2: added short workflow description in the commit message

 MAINTAINERS|   7 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |   8 ++
 drivers/char/rpmb/Makefile |   4 +
 drivers/char/rpmb/core.c   | 337 +
 include/linux/rpmb.h   | 200 +++
 7 files changed, 559 insertions(+)
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 include/linux/rpmb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 03e00c7c88eb..98dcd40ab900 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9417,6 +9417,13 @@ F:   include/net/rose.h
 F: include/uapi/linux/rose.h
 F: net/rose/
 
+RPMB SUBSYSTEM
+M: Tomas Winkler 
+L: linux-ker...@vger.kernel.org
+S: Supported
+F: drivers/char/rpmb/*
+F: include/linux/rpmb.h
+
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3ec0766ed5e9..b5970f965fa7 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -604,5 +604,7 @@ config TILE_SROM
 
 source "drivers/char/xillybus/Kconfig"
 
+source "drivers/char/rpmb/Kconfig"
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d8a7579300d2..1a5e43c1a9a6 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -60,3 +60,4 @@ js-rtc-y = rtc.o
 
 obj-$(CONFIG_TILE_SROM)+= tile-srom.o
 obj-$(CONFIG_XILLYBUS) += xillybus/
+obj-$(CONFIG_RPMB) += rpmb/
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
new file mode 100644
index ..c5e6e909efce
--- /dev/null
+++ b/drivers/char/rpmb/Kconfig
@@ -0,0 +1,8 @@
+config RPMB
+   tristate "RPMB partition interface"
+   help
+ Unified RPMB partition interface for eMMC and UFS.
+ Provides interface for in kernel security controllers to
+ access RPMB partition.
+
+ If unsure, select N.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
new file mode 100644
index ..812b3ed264c0
--- /dev/null
+++ b/drivers/char/rpmb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RPMB) += rpmb.o
+rpmb-objs += core.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
new file mode 100644
index ..c9ea30aca6be
--- /dev/null
+++ b/drivers/char/rpmb/core.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static DEFINE_IDA(rpmb_ida);
+
+/**
+ * rpmb_dev_get - increase rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+struct rpmb_dev *rpmb_dev_get(struct rpmb_dev *rdev)
+{
+   return get_device(&rdev->dev) ? rdev : NULL;
+}
+EXPORT_SYMBOL_GPL(rpmb_dev_get);
+
+/**
+ * rpmb_dev_put - decrease rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+void rpmb_dev_put(struct rpmb_dev *rdev)
+{
+   put_device(&rdev->dev);
+}
+EXPORT_SYMBOL_GPL(rpmb_dev_put);
+
+static int rpmb_request_verify(struct rpmb_dev *rdev, struct rpmb_data *rpmbd)
+{
+   u16 req_type, block_count;
+
+   if (rpmbd->in_frames == NULL  || rpmbd->out_frames == NULL ||
+   rpmbd

[PATCH v2 3/8] char: rpmb: add device attributes

2016-04-04 Thread Tomas Winkler
Add attribute type that displays underlay storage type technology
EMMC, UFS, and attribute id, that displays underlay storage device id.
For EMMC this would be content of CID and for UFS serial number from
the device descriptor

Signed-off-by: Tomas Winkler 
---
V2: resend
 Documentation/ABI/testing/sysfs-class-rpmb | 24 +++
 drivers/char/rpmb/core.c   | 64 ++
 2 files changed, 88 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
index 62d1959bf19e..9b2bf65dae95 100644
--- a/Documentation/ABI/testing/sysfs-class-rpmb
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -13,3 +13,27 @@ Contact: Tomas Winkler 
 Description:
The /sys/class/rpmb/rpmbN directory is created for
each RPMB registered device
+
+What:  /sys/class/rpmb/rpmbN/id
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/id file contains device id
+   in a binary form
+
+What:  /sys/class/rpmb/rpmbN/type
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/type file contains device
+   underlay storage type technology: EMMC, UFS
+
+What:  /sys/class/rpmb/rpmbN/reliable_wr_cnt
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/reliable_wr_cnt file contains
+   number of blocks that can be written in a single request
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index c9ea30aca6be..fb401331d345 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -230,6 +230,68 @@ struct rpmb_dev *rpmb_dev_find_by_device(struct device 
*parent)
 }
 EXPORT_SYMBOL_GPL(rpmb_dev_find_by_device);
 
+static ssize_t type_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   ssize_t ret;
+
+   switch (rdev->ops->type) {
+   case RPMB_TYPE_EMMC:
+   ret = scnprintf(buf, PAGE_SIZE, "EMMC\n");
+   break;
+   case RPMB_TYPE_UFS:
+   ret = scnprintf(buf, PAGE_SIZE, "UFS\n");
+   break;
+   default:
+   ret = scnprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+   break;
+   }
+
+   return ret;
+}
+static DEVICE_ATTR_RO(type);
+
+static ssize_t id_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   size_t sz = min_t(size_t, rdev->ops->dev_id_len, PAGE_SIZE);
+
+   if (!rdev->ops->dev_id)
+   return 0;
+
+   memcpy(buf, rdev->ops->dev_id, sz);
+   return sz;
+}
+static DEVICE_ATTR_RO(id);
+
+static ssize_t reliable_wr_cnt_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", rdev->ops->reliable_wr_cnt);
+}
+static DEVICE_ATTR_RO(reliable_wr_cnt);
+
+
+static struct attribute *rpmb_attrs[] = {
+   &dev_attr_type.attr,
+   &dev_attr_id.attr,
+   &dev_attr_reliable_wr_cnt.attr,
+   NULL,
+};
+
+static struct attribute_group rpmb_attr_group = {
+   .attrs = rpmb_attrs,
+};
+
+static const struct attribute_group *rpmb_attr_groups[] = {
+   &rpmb_attr_group,
+   NULL
+};
+
 /**
  * rpmb_dev_unregister - unregister RPMB partition from the RPMB subsystem
  *
@@ -300,6 +362,8 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
dev_set_name(&rdev->dev, "rpmb%d", id);
rdev->dev.class = &rpmb_class;
rdev->dev.parent = dev;
+   rdev->dev.groups = rpmb_attr_groups;
+
ret = device_register(&rdev->dev);
if (ret)
goto exit;
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 4/8] char: rpmb: provide user space interface

2016-04-04 Thread Tomas Winkler
The user space API is achieved via single synchronous IOCTL.
The request is submitted in_frames_ptr pointer and received
in out_frames_ptr.

Signed-off-by: Tomas Winkler 
---
V2: use memdup_user

 Documentation/ioctl/ioctl-number.txt |   1 +
 MAINTAINERS  |   1 +
 drivers/char/rpmb/Kconfig|   7 ++
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/cdev.c | 207 +++
 drivers/char/rpmb/core.c |   9 +-
 drivers/char/rpmb/rpmb-cdev.h|  31 ++
 include/linux/rpmb.h |  78 ++---
 include/uapi/linux/rpmb.h| 120 
 9 files changed, 384 insertions(+), 71 deletions(-)
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 include/uapi/linux/rpmb.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 9369d3b0f09a..51a514befa48 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -320,6 +320,7 @@ Code  Seq#(hex) Include FileComments
 0xB1   00-1F   PPPoX   <mailto:mostr...@styx.uwaterloo.ca>
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h<mailto:linux-g...@vger.kernel.org>
+0xB5   00  linux/uapi/linux/rpmb.h <mailto:linux-...@linux.intel.com>
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-8F   uapi/scsi/cxlflash_ioctl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 62b9edb8881c..07bd6f380460 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9422,6 +9422,7 @@ M:    Tomas Winkler 
 L: linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
+F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
 
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index c5e6e909efce..6794be9fcc5e 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -6,3 +6,10 @@ config RPMB
  access RPMB partition.
 
  If unsure, select N.
+
+config RPMB_INTF_DEV
+   bool "RPMB character device interface /dev/rpmbN"
+   depends on RPMB
+   help
+ Say yes here if you want to access RPMB from user space
+ via character device interface /dev/rpmb%d
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index 812b3ed264c0..b5dc087b1299 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
+rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
new file mode 100644
index ..67e94943d3e3
--- /dev/null
+++ b/drivers/char/rpmb/cdev.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rpmb-cdev.h"
+
+static dev_t rpmb_devt;
+#define RPMB_MAX_DEVS  MINORMASK
+
+#define RPMB_DEV_OPEN0  /** single open bit (position) */
+
+/**
+ * rpmb_open - the open function
+ *
+ * @inode: pointer to inode structure
+ * @file: pointer to file structure
+ *
+ * Return: 0 on success, <0 on error
+ */
+static int rpmb_open(struct inode *inode, struct file *file)
+{
+   struct rpmb_dev *rdev;
+
+   rdev = container_of(inode->i_cdev, struct rpmb_dev, cdev);
+   if (!rdev)
+   return -ENODEV;
+
+   /* the rpmb is single open! */
+   if (test_and_set_bit(RPMB_DEV_OPEN, &rdev->status))
+   return -EBUSY;
+
+   mutex_lock(&rdev->lock);
+
+   file->private_data = rdev;
+
+   mutex_unlock(&rdev->lock);
+
+   return nonseekable_open(inode, file);
+}
+
+static int rpmb_release(struct inode *inode, struct file *file)
+{
+   struct rpmb_dev *rdev = file->private_data;
+
+   clear_bit(RPMB_DEV_OPEN, &rdev->status);
+
+   return 0;
+}
+
+/*
+ * FIMXE: will be exported by the kernel in future version
+ * helper to convert user pointers passed inside __aligned_u64 fields
+ */
+static void __user *u64_to_ptr(__u64 val)
+{
+   return (void __user *) (unsigned long) val;
+}
+
+static int rpmb_ioctl_cmd(struct rpmb_dev *rdev,
+ struct rpmb

[PATCH v2 7/8] mmc: block: register rpmb partition with the RPMB subsystem

2016-04-04 Thread Tomas Winkler
Register eMMC rpmb partition with the rpmb subsystem and provide
implementation for the RPMB access operations abstracting
actual multi step process.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
V2: resend
 drivers/mmc/card/block.c | 289 +++
 1 file changed, 289 insertions(+)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 3bdbe50a363f..441754a7d4cf 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -111,6 +112,7 @@ struct mmc_blk_data {
 #define MMC_BLK_WRITE  BIT(1)
 #define MMC_BLK_DISCARDBIT(2)
 #define MMC_BLK_SECDISCARD BIT(3)
+#define MMC_BLK_RPMB   BIT(4)
 
/*
 * Only set in main mmc_blk_data associated
@@ -1138,6 +1140,289 @@ int mmc_access_rpmb(struct mmc_queue *mq)
return false;
 }
 
+static int mmc_rpmb_send_cmd(struct mmc_card *card,
+u16 rpmb_type, int data_type,
+u8 *buf, u16 blks)
+{
+   struct mmc_command sbc = {
+   .opcode = MMC_SET_BLOCK_COUNT,
+   .flags  = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   struct mmc_command cmd = {
+   .flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
+   };
+
+   struct mmc_data data = {
+   .blksz = 512,
+   };
+   struct mmc_request mrq = {
+   .sbc= &sbc,
+   .cmd= &cmd,
+   .data   = &data,
+   .stop   = NULL,
+   };
+   struct scatterlist sg;
+   bool do_rel_wr;
+
+   /*  set CMD23 */
+   sbc.arg = blks & 0x;
+   do_rel_wr = (rpmb_type == RPMB_WRITE_DATA ||
+rpmb_type == RPMB_PROGRAM_KEY);
+
+   if (do_rel_wr)
+   sbc.arg |= MMC_CMD23_ARG_REL_WR;
+
+   /*  set CMD25/18 */
+   cmd.opcode = (data_type == MMC_DATA_WRITE) ?
+   MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
+
+   sg_init_one(&sg, buf, 512 * blks);
+
+   data.blocks = blks;
+   data.sg = &sg;
+   data.sg_len = 1;
+   data.flags  = data_type;
+   mmc_set_data_timeout(&data, card);
+
+   mmc_wait_for_req(card->host, &mrq);
+
+   if (cmd.error) {
+   pr_err("%s: %s cmd error (%d)\n",
+   mmc_hostname(card->host), __func__, cmd.error);
+   return cmd.error;
+   }
+   if (data.error) {
+   pr_err("%s: %s data error (%d)\n",
+   mmc_hostname(card->host), __func__, data.error);
+   return data.error;
+   }
+   return 0;
+}
+
+static int mmc_blk_rpmb_sequence(struct mmc_card *card,
+   struct rpmb_data *rpmbd)
+{
+   struct rpmb_frame *in_frames, *out_frames;
+   u8 *in_buf, *out_buf;
+   u16 blks;
+   u16 type;
+   int err;
+
+   in_frames = rpmbd->in_frames;
+   out_frames = rpmbd->out_frames;
+   in_buf = (u8 *)in_frames;
+   out_buf = (u8 *)out_frames;
+
+   type = rpmbd->req_type;
+   blks = be16_to_cpu(in_frames[0].block_count);
+
+   switch (type) {
+   case RPMB_PROGRAM_KEY:
+   blks = 1;
+   /* fall through */
+   case RPMB_WRITE_DATA:
+   /* STEP 1: send request to RPMB partition */
+   err = mmc_rpmb_send_cmd(card, type, MMC_DATA_WRITE,
+   in_buf, blks);
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+   }
+
+   /* STEP 2: check write result (reuse out_frames) */
+   memset(out_frames, 0, 512);
+   out_frames[0].req_resp = cpu_to_be16(RPMB_RESULT_READ);
+   err = mmc_rpmb_send_cmd(card,
+   RPMB_RESULT_READ, MMC_DATA_WRITE, out_buf, 1);
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+   }
+
+   /* STEP 3: get response from RPMB partition */
+   err = mmc_rpmb_send_cmd(card,
+   RPMB_READ_DATA, MMC_DATA_READ, out_buf, 1);
+
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+   }
+   break;
+
+   case RPMB_GET_WRITE_COUNTER:
+   blks = 1;
+   /* fall through */
+   case RPMB_READ_DATA:
+   /* STEP 1: se

[PATCH v2 6/8] tools rpmb: add RPBM access tool

2016-04-04 Thread Tomas Winkler
Add simple RPMB host testing tool. It can be used
to program key, write and read data block, and retrieve
write counter.

Signed-off-by: Tomas Winkler 
---
V2: resend
 MAINTAINERS   |   1 +
 tools/Makefile|  16 +-
 tools/rpmb/.gitignore |   2 +
 tools/rpmb/Makefile   |  32 ++
 tools/rpmb/rpmb.c | 807 ++
 5 files changed, 853 insertions(+), 5 deletions(-)
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 07bd6f380460..b7966b95c265 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9425,6 +9425,7 @@ F:drivers/char/rpmb/*
 F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
+F: tools/rpmb/
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
diff --git a/tools/Makefile b/tools/Makefile
index 60c7e6c8ff17..5b37ccd95cab 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
@echo '  lguest - a minimal 32-bit x86 hypervisor'
@echo '  net- misc networking tools'
@echo '  perf   - Linux performance measurement and 
analysis tool'
+   @echo '  rpmb   - Replay protected memory block access 
tool'
@echo '  selftests  - various kernel selftests'
@echo '  spi- spi tools'
@echo '  objtool- an ELF object analysis tool'
@@ -55,7 +56,8 @@ acpi: FORCE
 cpupower: FORCE
$(call descend,power/$@)
 
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio: FORCE
$(call descend,$@)
 
 liblockdep: FORCE
@@ -85,7 +87,7 @@ freefall: FORCE
$(call descend,laptop/$@)
 
 all: acpi cgroup cpupower hv firewire lguest \
-   perf selftests turbostat usb \
+   perf rpmb selftests turbostat usb \
virtio vm net x86_energy_perf_policy \
tmon freefall objtool
 
@@ -95,7 +97,8 @@ acpi_install:
 cpupower_install:
$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install hv_install lguest_install perf_install 
usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install hv_install lguest_install perf_install 
rpmb_install usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install hv_install lguest_install perf_install 
rpmb_install usb_install virtio_install vm_install net_install:
$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -111,7 +114,7 @@ freefall_install:
$(call descend,laptop/$(@:_install=),install)
 
 install: acpi_install cgroup_install cpupower_install hv_install 
firewire_install lguest_install \
-   perf_install selftests_install turbostat_install usb_install \
+   perf_install rpmb_install selftests_install turbostat_install 
usb_install \
virtio_install vm_install net_install 
x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install
 
@@ -139,6 +142,9 @@ libsubcmd_clean:
 perf_clean:
$(call descend,$(@:_clean=),clean)
 
+rpmb_clean:
+   $(call descend,$(@:_clean=),clean)
+
 selftests_clean:
$(call descend,testing/$(@:_clean=),clean)
 
@@ -155,7 +161,7 @@ build_clean:
$(call descend,build,clean)
 
 clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean 
lguest_clean \
-   perf_clean selftests_clean turbostat_clean spi_clean usb_clean 
virtio_clean \
+   perf_clean rpmb_clean selftests_clean turbostat_clean spi_clean 
usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean 
tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean 
liblockdep_clean \
gpio_clean objtool_clean
diff --git a/tools/rpmb/.gitignore b/tools/rpmb/.gitignore
new file mode 100644
index ..218f680548e6
--- /dev/null
+++ b/tools/rpmb/.gitignore
@@ -0,0 +1,2 @@
+*.o
+rpmb
diff --git a/tools/rpmb/Makefile b/tools/rpmb/Makefile
new file mode 100644
index ..e0e51f306dac
--- /dev/null
+++ b/tools/rpmb/Makefile
@@ -0,0 +1,32 @@
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+INSTALL = install
+prefix ?= /usr/local
+bindir = $(prefix)/bin
+
+
+CFLAGS += -D__EXPORTED_HEADERS__
+CFLAGS += -I$(srctree)/include/uapi -I$(srctree)/include
+L

[PATCH v2 5/8] char: rpmb: add RPMB simulation device

2016-04-04 Thread Tomas Winkler
This is simple platform device for used for testing
rpmb subystem.

The module currently suppot two configuration options
1.max_wr_blks: for specifying max blocks that can be written
in a single command and.
2. daunits:  used to set storage capacity in 128K units.

Signed-off-by: Tomas Winkler 
---
V2: remove .owner setting, it is set automatically
 drivers/char/rpmb/Kconfig|  10 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/rpmb_sim.c | 583 +++
 3 files changed, 594 insertions(+)
 create mode 100644 drivers/char/rpmb/rpmb_sim.c

diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index 6794be9fcc5e..09225080c7fc 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -13,3 +13,13 @@ config RPMB_INTF_DEV
help
  Say yes here if you want to access RPMB from user space
  via character device interface /dev/rpmb%d
+
+
+config RPMB_SIM
+   tristate "RPMB partition device simulator"
+   default n
+   depends on RPMB
+   select CRYPTO_SHA256
+   select CRYPTO_HMAC
+   help
+ RPMB partition simulator used for testing the RPMB subsystem
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index b5dc087b1299..81f924fd9a87 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
 rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
+obj-$(CONFIG_RPMB_SIM) += rpmb_sim.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/rpmb_sim.c b/drivers/char/rpmb/rpmb_sim.c
new file mode 100644
index ..d2caa80eefb0
--- /dev/null
+++ b/drivers/char/rpmb/rpmb_sim.c
@@ -0,0 +1,583 @@
+/**
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Corporation.
+ * linux-...@linux.intel.com
+ * http://www.intel.com
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *contributors may be used to endorse or promote products derived
+ *from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static const char id[] = "RPMB:SIM";
+#define CAPACITY_UNIT SZ_128K
+#define CAPACITY_MIN  SZ_128K
+#define CAPACITY_MAX  SZ_16M
+#define BLK_UNIT  SZ_256
+
+static unsigned int max_wr_blks = 1;
+module_param(max_wr_blks, uint, 0644);
+MODULE_PARM_DESC(max_wr_blks,
+   "max blocks that can be written in a single command (default: 1)");
+
+static unsigned int daunit

[PATCH v2 8/8] scsi: ufs: connect to RPMB subsystem

2016-04-04 Thread Tomas Winkler
Register UFS RPMB LUN with the RPMB subsystem and provide
implementation for the RPMB access operations. RPMB partition is
accessed via a sequence of security protocol in and security protocol
out commands with UFS specific parameters. This multi step process is
abstracted into 4 basic RPMB commands.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
V2: resend
 drivers/scsi/ufs/ufshcd.c | 219 ++
 drivers/scsi/ufs/ufshcd.h |   2 +
 2 files changed, 221 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..c087e9713db3 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -37,10 +37,13 @@
  * license terms, and distributes only under these terms.
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -4744,6 +4747,214 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 
 }
 
+#define SEC_PROTOCOL_UFS  0xEC
+#define   SEC_SPECIFIC_UFS_RPMB 0x0001
+
+#define SEC_PROTOCOL_CMD_SIZE 12
+#define SEC_PROTOCOL_RETRIES 3
+#define SEC_PROTOCOL_RETRIES_ON_RESET 10
+#define SEC_PROTOCOL_TIMEOUT msecs_to_jiffies(1000)
+
+static int
+ufshcd_rpmb_security_out(struct scsi_device *sdev,
+struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 trans_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+retry:
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_OUT;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0;  /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(trans_len, cmd + 6);  /* transfer length */
+
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_TO_DEVICE,
+frames, trans_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   pr_err("%s: failed with err %0x\n", __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security out", &sshdr);
+
+   return ret;
+}
+
+static int
+ufshcd_rpmb_security_in(struct scsi_device *sdev,
+   struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 alloc_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+retry:
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_IN;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0; /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(alloc_len, cmd + 6); /* allocation length */
+
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_FROM_DEVICE,
+frames, alloc_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   pr_err("%s: failed with err %0x\n", __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security in", &sshdr);
+
+   return ret;
+}
+
+
+static int ufshcd_rpmb_send_req(struct device *dev, struct rpmb_data *rpmbd)
+{
+   unsigned long flags;
+   struct ufs_hba *hba = dev_get_drvdata(dev);
+   struct scsi_device *sdev;
+   struct rpmb_frame *in_frames, *out_frames;
+   u16 blks;
+   u16 type;
+   int ret;
+
+   in_frames = rpmbd->in_frames;
+   out_frames = rpmbd->out_frames;
+
+   type = rpmbd->req_type;
+   blks = be16_to_cpu(in_frames[0].block_count);
+
+   dev_dbg(hba->dev, "RPMB : type =

[PATCH 0/8 V2] Replay Protected Memory Block (RPMB) subsystem

2016-04-04 Thread Tomas Winkler
Few storage technology such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but
by a set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and
PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

A storage device registers its RPMB hardware (emmc) partition or
RPMB W-LUN (ufs) with the RPMB layer providing an implementation for
send_rpmb_req() handler.
Tere is as well simulation platform device. This is handy as an RPMB
key can be programmed only once at storage device lifetime.


ThePMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. In case a TEE device wish to store a replay protected
data, it creates an RPMB frame with requested data and computes HMAC of
the frame, then it requests the storage device via RPMB layer to store
the data.
A TEE driver can claim rpmb interface, for example,
via  class_interface_register ().

A parallel user space API is provided via /dev/rpmbX character
device with a single IOCTL command similar to the one provided by
mmc/ioctl. h
There is a sample tool under tools/rpmb/ directory that exercises
this interface.

Tomas Winkler (8):
  rpmb: add Replay Protected Memory Block (RPMB) subsystem
  char: rpmb: add sysfs-class ABI documentation
  char: rpmb: add device attributes
  char: rpmb: provide user space interface
  char: rpmb: add RPMB simulation device
  tools rpmb: add RPBM access tool
  mmc: block: register rpmb partition with the RPMB subsystem
  scsi: ufs: connect to RPMB subsystem

 Documentation/ABI/testing/sysfs-class-rpmb |  39 ++
 Documentation/ioctl/ioctl-number.txt   |   1 +
 MAINTAINERS|  10 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |  25 +
 drivers/char/rpmb/Makefile |   6 +
 drivers/char/rpmb/cdev.c   | 209 
 drivers/char/rpmb/core.c   | 408 +++
 drivers/char/rpmb/rpmb-cdev.h  |  31 ++
 drivers/char/rpmb/rpmb_sim.c   | 584 +
 drivers/mmc/card/block.c   | 289 +++
 drivers/scsi/ufs/ufshcd.c  | 219 
 drivers/scsi/ufs/ufshcd.h  |   2 +
 include/linux/rpmb.h   | 138 +
 include/uapi/linux/rpmb.h  | 120 +
 tools/Makefile |  16 +-
 tools/rpmb/.gitignore  |   2 +
 tools/rpmb/Makefile|  32 ++
 tools/rpmb/rpmb.c  | 807 +
 20 files changed, 2936 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 drivers/char/rpmb/rpmb_sim.c
 create mode 100644 include/linux/rpmb.h
 create mode 100644 include/uapi/linux/rpmb.h
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/8] char: rpmb: add device attributes

2016-04-03 Thread Tomas Winkler
Add attribute type that displays underlay storage type technology
EMMC, UFS, and attribute id, that displays underlay storage device id.
For EMMC this would be content of CID and for UFS serial number from
the device descriptor

Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-class-rpmb | 24 +++
 drivers/char/rpmb/core.c   | 64 ++
 2 files changed, 88 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
index 62d1959bf19e..9b2bf65dae95 100644
--- a/Documentation/ABI/testing/sysfs-class-rpmb
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -13,3 +13,27 @@ Contact: Tomas Winkler 
 Description:
The /sys/class/rpmb/rpmbN directory is created for
each RPMB registered device
+
+What:  /sys/class/rpmb/rpmbN/id
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/id file contains device id
+   in a binary form
+
+What:  /sys/class/rpmb/rpmbN/type
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/type file contains device
+   underlay storage type technology: EMMC, UFS
+
+What:  /sys/class/rpmb/rpmbN/reliable_wr_cnt
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN/reliable_wr_cnt file contains
+   number of blocks that can be written in a single request
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
index c9ea30aca6be..fb401331d345 100644
--- a/drivers/char/rpmb/core.c
+++ b/drivers/char/rpmb/core.c
@@ -230,6 +230,68 @@ struct rpmb_dev *rpmb_dev_find_by_device(struct device 
*parent)
 }
 EXPORT_SYMBOL_GPL(rpmb_dev_find_by_device);
 
+static ssize_t type_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   ssize_t ret;
+
+   switch (rdev->ops->type) {
+   case RPMB_TYPE_EMMC:
+   ret = scnprintf(buf, PAGE_SIZE, "EMMC\n");
+   break;
+   case RPMB_TYPE_UFS:
+   ret = scnprintf(buf, PAGE_SIZE, "UFS\n");
+   break;
+   default:
+   ret = scnprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+   break;
+   }
+
+   return ret;
+}
+static DEVICE_ATTR_RO(type);
+
+static ssize_t id_show(struct device *dev,
+  struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+   size_t sz = min_t(size_t, rdev->ops->dev_id_len, PAGE_SIZE);
+
+   if (!rdev->ops->dev_id)
+   return 0;
+
+   memcpy(buf, rdev->ops->dev_id, sz);
+   return sz;
+}
+static DEVICE_ATTR_RO(id);
+
+static ssize_t reliable_wr_cnt_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct rpmb_dev *rdev = to_rpmb_dev(dev);
+
+   return scnprintf(buf, PAGE_SIZE, "%u\n", rdev->ops->reliable_wr_cnt);
+}
+static DEVICE_ATTR_RO(reliable_wr_cnt);
+
+
+static struct attribute *rpmb_attrs[] = {
+   &dev_attr_type.attr,
+   &dev_attr_id.attr,
+   &dev_attr_reliable_wr_cnt.attr,
+   NULL,
+};
+
+static struct attribute_group rpmb_attr_group = {
+   .attrs = rpmb_attrs,
+};
+
+static const struct attribute_group *rpmb_attr_groups[] = {
+   &rpmb_attr_group,
+   NULL
+};
+
 /**
  * rpmb_dev_unregister - unregister RPMB partition from the RPMB subsystem
  *
@@ -300,6 +362,8 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
dev_set_name(&rdev->dev, "rpmb%d", id);
rdev->dev.class = &rpmb_class;
rdev->dev.parent = dev;
+   rdev->dev.groups = rpmb_attr_groups;
+
ret = device_register(&rdev->dev);
if (ret)
goto exit;
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/8] mmc: block: register rpmb partition with the RPMB subsystem

2016-04-03 Thread Tomas Winkler
Register eMMC rpmb partition with the rpmb subsystem and provide
implementation for the RPMB access operations abstracting
actual multi step process.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 drivers/mmc/card/block.c | 289 +++
 1 file changed, 289 insertions(+)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 3bdbe50a363f..441754a7d4cf 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -111,6 +112,7 @@ struct mmc_blk_data {
 #define MMC_BLK_WRITE  BIT(1)
 #define MMC_BLK_DISCARDBIT(2)
 #define MMC_BLK_SECDISCARD BIT(3)
+#define MMC_BLK_RPMB   BIT(4)
 
/*
 * Only set in main mmc_blk_data associated
@@ -1138,6 +1140,289 @@ int mmc_access_rpmb(struct mmc_queue *mq)
return false;
 }
 
+static int mmc_rpmb_send_cmd(struct mmc_card *card,
+u16 rpmb_type, int data_type,
+u8 *buf, u16 blks)
+{
+   struct mmc_command sbc = {
+   .opcode = MMC_SET_BLOCK_COUNT,
+   .flags  = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC,
+   };
+
+   struct mmc_command cmd = {
+   .flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC,
+   };
+
+   struct mmc_data data = {
+   .blksz = 512,
+   };
+   struct mmc_request mrq = {
+   .sbc= &sbc,
+   .cmd= &cmd,
+   .data   = &data,
+   .stop   = NULL,
+   };
+   struct scatterlist sg;
+   bool do_rel_wr;
+
+   /*  set CMD23 */
+   sbc.arg = blks & 0x;
+   do_rel_wr = (rpmb_type == RPMB_WRITE_DATA ||
+rpmb_type == RPMB_PROGRAM_KEY);
+
+   if (do_rel_wr)
+   sbc.arg |= MMC_CMD23_ARG_REL_WR;
+
+   /*  set CMD25/18 */
+   cmd.opcode = (data_type == MMC_DATA_WRITE) ?
+   MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
+
+   sg_init_one(&sg, buf, 512 * blks);
+
+   data.blocks = blks;
+   data.sg = &sg;
+   data.sg_len = 1;
+   data.flags  = data_type;
+   mmc_set_data_timeout(&data, card);
+
+   mmc_wait_for_req(card->host, &mrq);
+
+   if (cmd.error) {
+   pr_err("%s: %s cmd error (%d)\n",
+   mmc_hostname(card->host), __func__, cmd.error);
+   return cmd.error;
+   }
+   if (data.error) {
+   pr_err("%s: %s data error (%d)\n",
+   mmc_hostname(card->host), __func__, data.error);
+   return data.error;
+   }
+   return 0;
+}
+
+static int mmc_blk_rpmb_sequence(struct mmc_card *card,
+   struct rpmb_data *rpmbd)
+{
+   struct rpmb_frame *in_frames, *out_frames;
+   u8 *in_buf, *out_buf;
+   u16 blks;
+   u16 type;
+   int err;
+
+   in_frames = rpmbd->in_frames;
+   out_frames = rpmbd->out_frames;
+   in_buf = (u8 *)in_frames;
+   out_buf = (u8 *)out_frames;
+
+   type = rpmbd->req_type;
+   blks = be16_to_cpu(in_frames[0].block_count);
+
+   switch (type) {
+   case RPMB_PROGRAM_KEY:
+   blks = 1;
+   /* fall through */
+   case RPMB_WRITE_DATA:
+   /* STEP 1: send request to RPMB partition */
+   err = mmc_rpmb_send_cmd(card, type, MMC_DATA_WRITE,
+   in_buf, blks);
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+   }
+
+   /* STEP 2: check write result (reuse out_frames) */
+   memset(out_frames, 0, 512);
+   out_frames[0].req_resp = cpu_to_be16(RPMB_RESULT_READ);
+   err = mmc_rpmb_send_cmd(card,
+   RPMB_RESULT_READ, MMC_DATA_WRITE, out_buf, 1);
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+   }
+
+   /* STEP 3: get response from RPMB partition */
+   err = mmc_rpmb_send_cmd(card,
+   RPMB_READ_DATA, MMC_DATA_READ, out_buf, 1);
+
+   if (err) {
+   pr_err("%s: mmc_rpmb_send_cmd failed(%d)\n",
+   mmc_hostname(card->host), err);
+   goto out;
+   }
+   break;
+
+   case RPMB_GET_WRITE_COUNTER:
+   blks = 1;
+   /* fall through */
+   case RPMB_READ_DATA:
+   /* STEP 1: send request to RPMB partiti

[PATCH 6/8] tools rpmb: add RPBM access tool

2016-04-03 Thread Tomas Winkler
Add simple RPMB host testing tool. It can be used
to program key, write and read data block, and retrieve
write counter.

Signed-off-by: Tomas Winkler 
---
 MAINTAINERS   |   1 +
 tools/Makefile|  16 +-
 tools/rpmb/.gitignore |   2 +
 tools/rpmb/Makefile   |  32 ++
 tools/rpmb/rpmb.c | 807 ++
 5 files changed, 853 insertions(+), 5 deletions(-)
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8704b40eaf27..75e63de9283a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9432,6 +9432,7 @@ F:drivers/char/rpmb/*
 F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
+F: tools/rpmb/
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
diff --git a/tools/Makefile b/tools/Makefile
index 60c7e6c8ff17..5b37ccd95cab 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
@echo '  lguest - a minimal 32-bit x86 hypervisor'
@echo '  net- misc networking tools'
@echo '  perf   - Linux performance measurement and 
analysis tool'
+   @echo '  rpmb   - Replay protected memory block access 
tool'
@echo '  selftests  - various kernel selftests'
@echo '  spi- spi tools'
@echo '  objtool- an ELF object analysis tool'
@@ -55,7 +56,8 @@ acpi: FORCE
 cpupower: FORCE
$(call descend,power/$@)
 
-cgroup firewire hv guest spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio gpio objtool: FORCE
+cgroup firewire hv guest rpmb spi usb virtio vm net iio: FORCE
$(call descend,$@)
 
 liblockdep: FORCE
@@ -85,7 +87,7 @@ freefall: FORCE
$(call descend,laptop/$@)
 
 all: acpi cgroup cpupower hv firewire lguest \
-   perf selftests turbostat usb \
+   perf rpmb selftests turbostat usb \
virtio vm net x86_energy_perf_policy \
tmon freefall objtool
 
@@ -95,7 +97,8 @@ acpi_install:
 cpupower_install:
$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install hv_install lguest_install perf_install 
usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install hv_install lguest_install perf_install 
rpmb_install usb_install virtio_install vm_install net_install objtool_install:
+cgroup_install firewire_install hv_install lguest_install perf_install 
rpmb_install usb_install virtio_install vm_install net_install:
$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -111,7 +114,7 @@ freefall_install:
$(call descend,laptop/$(@:_install=),install)
 
 install: acpi_install cgroup_install cpupower_install hv_install 
firewire_install lguest_install \
-   perf_install selftests_install turbostat_install usb_install \
+   perf_install rpmb_install selftests_install turbostat_install 
usb_install \
virtio_install vm_install net_install 
x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install
 
@@ -139,6 +142,9 @@ libsubcmd_clean:
 perf_clean:
$(call descend,$(@:_clean=),clean)
 
+rpmb_clean:
+   $(call descend,$(@:_clean=),clean)
+
 selftests_clean:
$(call descend,testing/$(@:_clean=),clean)
 
@@ -155,7 +161,7 @@ build_clean:
$(call descend,build,clean)
 
 clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean 
lguest_clean \
-   perf_clean selftests_clean turbostat_clean spi_clean usb_clean 
virtio_clean \
+   perf_clean rpmb_clean selftests_clean turbostat_clean spi_clean 
usb_clean virtio_clean \
vm_clean net_clean iio_clean x86_energy_perf_policy_clean 
tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean 
liblockdep_clean \
gpio_clean objtool_clean
diff --git a/tools/rpmb/.gitignore b/tools/rpmb/.gitignore
new file mode 100644
index ..218f680548e6
--- /dev/null
+++ b/tools/rpmb/.gitignore
@@ -0,0 +1,2 @@
+*.o
+rpmb
diff --git a/tools/rpmb/Makefile b/tools/rpmb/Makefile
new file mode 100644
index ..e0e51f306dac
--- /dev/null
+++ b/tools/rpmb/Makefile
@@ -0,0 +1,32 @@
+CC = $(CROSS_COMPILE)gcc
+LD = $(CROSS_COMPILE)ld
+PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+INSTALL = install
+prefix ?= /usr/local
+bindir = $(prefix)/bin
+
+
+CFLAGS += -D__EXPORTED_HEADERS__
+CFLAGS += -I$(srctree)/include/uapi -I$(srctree)/include
+LDLIBS += $(

[PATCH 0/8] Replay Protected Memory Block (RPMB) subsystem

2016-04-03 Thread Tomas Winkler
Few storage technology such is EMMC, UFS, and NVMe support RPMB
hardware partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but
by a set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and
PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

A storage device registers its RPMB hardware (emmc) partition or
RPMB W-LUN (ufs) with the RPMB layer providing an implementation for
send_rpmb_req() handler.
Tere is as well simulation platform device. This is handy as an RPMB
key can be programmed only once at storage device lifetime.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. A TEE driver can claim rpmb interface, for example,
via  class_interface_register ().

A parallel user space API is provided via /dev/rpmbX character
device with a single IOCTL command similar to the one provided by
mmc/ioctl. h
There is a sample tool under tools/rpmb/ directory that exercises
this interface.

Tomas Winkler (8):
  rpmb: add Replay Protected Memory Block (RPMB) subsystem
  char: rpmb: add sysfs-class ABI documentation
  char: rpmb: add device attributes
  char: rpmb: provide user space interface
  char: rpmb: add RPMB simulation device
  tools rpmb: add RPBM access tool
  mmc: block: register rpmb partition with the RPMB subsystem
  scsi: ufs: connect to RPMB subsystem

 Documentation/ABI/testing/sysfs-class-rpmb |  39 ++
 Documentation/ioctl/ioctl-number.txt   |   1 +
 MAINTAINERS|  10 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |  25 +
 drivers/char/rpmb/Makefile |   6 +
 drivers/char/rpmb/cdev.c   | 209 
 drivers/char/rpmb/core.c   | 408 +++
 drivers/char/rpmb/rpmb-cdev.h  |  31 ++
 drivers/char/rpmb/rpmb_sim.c   | 584 +
 drivers/mmc/card/block.c   | 289 +++
 drivers/scsi/ufs/ufshcd.c  | 219 
 drivers/scsi/ufs/ufshcd.h  |   2 +
 include/linux/rpmb.h   | 138 +
 include/uapi/linux/rpmb.h  | 120 +
 tools/Makefile |  16 +-
 tools/rpmb/.gitignore  |   2 +
 tools/rpmb/Makefile|  32 ++
 tools/rpmb/rpmb.c  | 807 +
 20 files changed, 2936 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 drivers/char/rpmb/rpmb_sim.c
 create mode 100644 include/linux/rpmb.h
 create mode 100644 include/uapi/linux/rpmb.h
 create mode 100644 tools/rpmb/.gitignore
 create mode 100644 tools/rpmb/Makefile
 create mode 100644 tools/rpmb/rpmb.c

-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/8] char: rpmb: provide user space interface

2016-04-03 Thread Tomas Winkler
The user space API is achieved via single synchronous IOCTL.
The request is submitted in_frames_ptr pointer and received
in out_frames_ptr.

Signed-off-by: Tomas Winkler 
---
 Documentation/ioctl/ioctl-number.txt |   1 +
 MAINTAINERS  |   1 +
 drivers/char/rpmb/Kconfig|   7 ++
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/cdev.c | 209 +++
 drivers/char/rpmb/core.c |   9 +-
 drivers/char/rpmb/rpmb-cdev.h|  31 ++
 include/linux/rpmb.h |  78 ++---
 include/uapi/linux/rpmb.h| 120 
 9 files changed, 386 insertions(+), 71 deletions(-)
 create mode 100644 drivers/char/rpmb/cdev.c
 create mode 100644 drivers/char/rpmb/rpmb-cdev.h
 create mode 100644 include/uapi/linux/rpmb.h

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index 9369d3b0f09a..51a514befa48 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -320,6 +320,7 @@ Code  Seq#(hex) Include FileComments
 0xB1   00-1F   PPPoX   <mailto:mostr...@styx.uwaterloo.ca>
 0xB3   00  linux/mmc/ioctl.h
 0xB4   00-0F   linux/gpio.h<mailto:linux-g...@vger.kernel.org>
+0xB5   00  linux/uapi/linux/rpmb.h <mailto:linux-...@linux.intel.com>
 0xC0   00-0F   linux/usb/iowarrior.h
 0xCA   00-0F   uapi/misc/cxl.h
 0xCA   80-8F   uapi/scsi/cxlflash_ioctl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 08316d8284ed..8704b40eaf27 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9429,6 +9429,7 @@ M:    Tomas Winkler 
 L: linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
+F: include/uapi/linux/rpmb.h
 F: include/linux/rpmb.h
 F: Documentation/ABI/testing/sysfs-class-rpmb
 
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index c5e6e909efce..6794be9fcc5e 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -6,3 +6,10 @@ config RPMB
  access RPMB partition.
 
  If unsure, select N.
+
+config RPMB_INTF_DEV
+   bool "RPMB character device interface /dev/rpmbN"
+   depends on RPMB
+   help
+ Say yes here if you want to access RPMB from user space
+ via character device interface /dev/rpmb%d
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index 812b3ed264c0..b5dc087b1299 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
+rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/cdev.c b/drivers/char/rpmb/cdev.c
new file mode 100644
index ..a57c08fce70a
--- /dev/null
+++ b/drivers/char/rpmb/cdev.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "rpmb-cdev.h"
+
+static dev_t rpmb_devt;
+#define RPMB_MAX_DEVS  MINORMASK
+
+#define RPMB_DEV_OPEN0  /** single open bit (position) */
+
+/**
+ * rpmb_open - the open function
+ *
+ * @inode: pointer to inode structure
+ * @file: pointer to file structure
+ *
+ * Return: 0 on success, <0 on error
+ */
+static int rpmb_open(struct inode *inode, struct file *file)
+{
+   struct rpmb_dev *rdev;
+
+   rdev = container_of(inode->i_cdev, struct rpmb_dev, cdev);
+   if (!rdev)
+   return -ENODEV;
+
+   /* the rpmb is single open! */
+   if (test_and_set_bit(RPMB_DEV_OPEN, &rdev->status))
+   return -EBUSY;
+
+   mutex_lock(&rdev->lock);
+
+   file->private_data = rdev;
+
+   mutex_unlock(&rdev->lock);
+
+   return nonseekable_open(inode, file);
+}
+
+static int rpmb_release(struct inode *inode, struct file *file)
+{
+   struct rpmb_dev *rdev = file->private_data;
+
+   clear_bit(RPMB_DEV_OPEN, &rdev->status);
+
+   return 0;
+}
+
+/*
+ * FIMXE: will be exported by the kernel in future version
+ * helper to convert user pointers passed inside __aligned_u64 fields
+ */
+static void __user *u64_to_ptr(__u64 val)
+{
+   return (void __user *) (unsigned long) val;
+}
+
+static int rpmb_ioctl_cmd(struct rpmb_dev *rdev,
+ struct rpmb_ioc_cmd __user 

[PATCH 2/8] char: rpmb: add sysfs-class ABI documentation

2016-04-03 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-class-rpmb | 15 +++
 MAINTAINERS|  1 +
 2 files changed, 16 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-rpmb

diff --git a/Documentation/ABI/testing/sysfs-class-rpmb 
b/Documentation/ABI/testing/sysfs-class-rpmb
new file mode 100644
index ..62d1959bf19e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rpmb
@@ -0,0 +1,15 @@
+What:  /sys/class/rpmb/
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The rpmb/ class sub-directory belongs to RPMB device class
+
+
+What:  /sys/class/rpmb/rpmbN/
+Date:  Mar 2016
+KernelVersion: TBD
+Contact:   Tomas Winkler 
+Description:
+   The /sys/class/rpmb/rpmbN directory is created for
+   each RPMB registered device
diff --git a/MAINTAINERS b/MAINTAINERS
index d1d7b7ffedab..08316d8284ed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9430,6 +9430,7 @@ L:linux-ker...@vger.kernel.org
 S: Supported
 F: drivers/char/rpmb/*
 F: include/linux/rpmb.h
+F: Documentation/ABI/testing/sysfs-class-rpmb
 
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/8] scsi: ufs: connect to RPMB subsystem

2016-04-03 Thread Tomas Winkler
Register UFS RPMB LUN with the RPMB subsystem and provide
implementation for the RPMB access operations. RPMB partition is
accessed via a sequence of security protocol in and security protocol
out commands with UFS specific parameters. This multi step process is
abstracted into 4 basic RPMB commands.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 219 ++
 drivers/scsi/ufs/ufshcd.h |   2 +
 2 files changed, 221 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8fa72c31a9d..c087e9713db3 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -37,10 +37,13 @@
  * license terms, and distributes only under these terms.
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
+
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -4744,6 +4747,214 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 
 }
 
+#define SEC_PROTOCOL_UFS  0xEC
+#define   SEC_SPECIFIC_UFS_RPMB 0x0001
+
+#define SEC_PROTOCOL_CMD_SIZE 12
+#define SEC_PROTOCOL_RETRIES 3
+#define SEC_PROTOCOL_RETRIES_ON_RESET 10
+#define SEC_PROTOCOL_TIMEOUT msecs_to_jiffies(1000)
+
+static int
+ufshcd_rpmb_security_out(struct scsi_device *sdev,
+struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 trans_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+retry:
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_OUT;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0;  /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(trans_len, cmd + 6);  /* transfer length */
+
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_TO_DEVICE,
+frames, trans_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   pr_err("%s: failed with err %0x\n", __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security out", &sshdr);
+
+   return ret;
+}
+
+static int
+ufshcd_rpmb_security_in(struct scsi_device *sdev,
+   struct rpmb_frame *frames, u32 cnt)
+{
+   struct scsi_sense_hdr sshdr;
+   u32 alloc_len = cnt * sizeof(struct rpmb_frame);
+   int reset_retries = SEC_PROTOCOL_RETRIES_ON_RESET;
+   int ret;
+   u8 cmd[SEC_PROTOCOL_CMD_SIZE];
+
+retry:
+   memset(cmd, 0, SEC_PROTOCOL_CMD_SIZE);
+   cmd[0] = SECURITY_PROTOCOL_IN;
+   cmd[1] = SEC_PROTOCOL_UFS;
+   put_unaligned_be16(SEC_SPECIFIC_UFS_RPMB, cmd + 2);
+   cmd[4] = 0; /* inc_512 bit 7 set to 0 */
+   put_unaligned_be32(alloc_len, cmd + 6); /* allocation length */
+
+   ret = scsi_execute_req_flags(sdev, cmd, DMA_FROM_DEVICE,
+frames, alloc_len, &sshdr,
+SEC_PROTOCOL_TIMEOUT, SEC_PROTOCOL_RETRIES,
+NULL, 0);
+   if (ret && scsi_sense_valid(&sshdr) &&
+   sshdr.sense_key == UNIT_ATTENTION &&
+   sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+   /* Device reset might occur several times,
+* give it one more chance
+*/
+   if (--reset_retries > 0)
+   goto retry;
+
+   if (ret)
+   pr_err("%s: failed with err %0x\n", __func__, ret);
+
+   if (driver_byte(ret) & DRIVER_SENSE)
+   scsi_print_sense_hdr(sdev, "rpmb: security in", &sshdr);
+
+   return ret;
+}
+
+
+static int ufshcd_rpmb_send_req(struct device *dev, struct rpmb_data *rpmbd)
+{
+   unsigned long flags;
+   struct ufs_hba *hba = dev_get_drvdata(dev);
+   struct scsi_device *sdev;
+   struct rpmb_frame *in_frames, *out_frames;
+   u16 blks;
+   u16 type;
+   int ret;
+
+   in_frames = rpmbd->in_frames;
+   out_frames = rpmbd->out_frames;
+
+   type = rpmbd->req_type;
+   blks = be16_to_cpu(in_frames[0].block_count);
+
+   dev_dbg(hba->dev, "RPMB : type = %d, blocks = %d\n&qu

[PATCH 1/8] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2016-04-03 Thread Tomas Winkler
Few storage technology such is EMMC, UFS, and NVMe support RPMB hardware
partition with common protocol and frame layout.
The RPMB partition cannot be accessed via standard block layer, but by a
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and PROGRAM_KEY.
Such a partition provides authenticated and replay protected access,
hence suitable as a secure storage.

The RPMB layer aims to provide in-kernel API for Trusted Execution
Environment (TEE) devices that are capable to securely compute block
frame signature. A TEE driver can claim rpmb interface, for example,
via  class_interface_register ().

A storage device registers its RPMB hardware (emmc) partition or
RPMB W-LUN (ufs) with the RPMB layer providing an implementation
for send_rpmb_req() handler.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 MAINTAINERS|   7 +
 drivers/char/Kconfig   |   2 +
 drivers/char/Makefile  |   1 +
 drivers/char/rpmb/Kconfig  |   8 ++
 drivers/char/rpmb/Makefile |   4 +
 drivers/char/rpmb/core.c   | 337 +
 include/linux/rpmb.h   | 200 +++
 7 files changed, 559 insertions(+)
 create mode 100644 drivers/char/rpmb/Kconfig
 create mode 100644 drivers/char/rpmb/Makefile
 create mode 100644 drivers/char/rpmb/core.c
 create mode 100644 include/linux/rpmb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 16ccda4d8054..d1d7b7ffedab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9424,6 +9424,13 @@ F:   include/net/rose.h
 F: include/uapi/linux/rose.h
 F: net/rose/
 
+RPMB SUBSYSTEM
+M: Tomas Winkler 
+L: linux-ker...@vger.kernel.org
+S: Supported
+F: drivers/char/rpmb/*
+F: include/linux/rpmb.h
+
 RTL2830 MEDIA DRIVER
 M: Antti Palosaari 
 L: linux-me...@vger.kernel.org
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3ec0766ed5e9..b5970f965fa7 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -604,5 +604,7 @@ config TILE_SROM
 
 source "drivers/char/xillybus/Kconfig"
 
+source "drivers/char/rpmb/Kconfig"
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d8a7579300d2..1a5e43c1a9a6 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -60,3 +60,4 @@ js-rtc-y = rtc.o
 
 obj-$(CONFIG_TILE_SROM)+= tile-srom.o
 obj-$(CONFIG_XILLYBUS) += xillybus/
+obj-$(CONFIG_RPMB) += rpmb/
diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
new file mode 100644
index ..c5e6e909efce
--- /dev/null
+++ b/drivers/char/rpmb/Kconfig
@@ -0,0 +1,8 @@
+config RPMB
+   tristate "RPMB partition interface"
+   help
+ Unified RPMB partition interface for eMMC and UFS.
+ Provides interface for in kernel security controllers to
+ access RPMB partition.
+
+ If unsure, select N.
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
new file mode 100644
index ..812b3ed264c0
--- /dev/null
+++ b/drivers/char/rpmb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_RPMB) += rpmb.o
+rpmb-objs += core.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/core.c b/drivers/char/rpmb/core.c
new file mode 100644
index ..c9ea30aca6be
--- /dev/null
+++ b/drivers/char/rpmb/core.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2015-2016 Intel Corp. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static DEFINE_IDA(rpmb_ida);
+
+/**
+ * rpmb_dev_get - increase rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+struct rpmb_dev *rpmb_dev_get(struct rpmb_dev *rdev)
+{
+   return get_device(&rdev->dev) ? rdev : NULL;
+}
+EXPORT_SYMBOL_GPL(rpmb_dev_get);
+
+/**
+ * rpmb_dev_put - decrease rpmb device ref counter
+ *
+ * @rdev: rpmb device
+ */
+void rpmb_dev_put(struct rpmb_dev *rdev)
+{
+   put_device(&rdev->dev);
+}
+EXPORT_SYMBOL_GPL(rpmb_dev_put);
+
+static int rpmb_request_verify(struct rpmb_dev *rdev, struct rpmb_data *rpmbd)
+{
+   u16 req_type, block_count;
+
+   if (rpmbd->in_frames == NULL  || rpmbd->out_frames == NULL ||
+   rpmbd->in_frames_cnt == 0 || rpmbd->out_frames_cnt == 0)
+   return -EINVAL;
+
+   req_type = be16_to_cpu(rpmbd->in_frames[0].req_resp);
+   block_count = be16_to_cpu(rpmbd->in_frames[0].block_count);
+
+   if (rpmbd->req_type != req_type) {
+ 

[PATCH 5/8] char: rpmb: add RPMB simulation device

2016-04-03 Thread Tomas Winkler
This is simple platform device for used for testing
rpmb subystem.

The module currently suppot two configuration options
1.max_wr_blks: for specifying max blocks that can be written
in a single command and.
2. daunits:  used to set storage capacity in 128K units.

Signed-off-by: Tomas Winkler 
---
 drivers/char/rpmb/Kconfig|  10 +
 drivers/char/rpmb/Makefile   |   1 +
 drivers/char/rpmb/rpmb_sim.c | 584 +++
 3 files changed, 595 insertions(+)
 create mode 100644 drivers/char/rpmb/rpmb_sim.c

diff --git a/drivers/char/rpmb/Kconfig b/drivers/char/rpmb/Kconfig
index 6794be9fcc5e..09225080c7fc 100644
--- a/drivers/char/rpmb/Kconfig
+++ b/drivers/char/rpmb/Kconfig
@@ -13,3 +13,13 @@ config RPMB_INTF_DEV
help
  Say yes here if you want to access RPMB from user space
  via character device interface /dev/rpmb%d
+
+
+config RPMB_SIM
+   tristate "RPMB partition device simulator"
+   default n
+   depends on RPMB
+   select CRYPTO_SHA256
+   select CRYPTO_HMAC
+   help
+ RPMB partition simulator used for testing the RPMB subsystem
diff --git a/drivers/char/rpmb/Makefile b/drivers/char/rpmb/Makefile
index b5dc087b1299..81f924fd9a87 100644
--- a/drivers/char/rpmb/Makefile
+++ b/drivers/char/rpmb/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_RPMB) += rpmb.o
 rpmb-objs += core.o
 rpmb-$(CONFIG_RPMB_INTF_DEV) += cdev.o
+obj-$(CONFIG_RPMB_SIM) += rpmb_sim.o
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/rpmb_sim.c b/drivers/char/rpmb/rpmb_sim.c
new file mode 100644
index ..ddf9c330e59c
--- /dev/null
+++ b/drivers/char/rpmb/rpmb_sim.c
@@ -0,0 +1,584 @@
+/**
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Corporation.
+ * linux-...@linux.intel.com
+ * http://www.intel.com
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *contributors may be used to endorse or promote products derived
+ *from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static const char id[] = "RPMB:SIM";
+#define CAPACITY_UNIT SZ_128K
+#define CAPACITY_MIN  SZ_128K
+#define CAPACITY_MAX  SZ_16M
+#define BLK_UNIT  SZ_256
+
+static unsigned int max_wr_blks = 1;
+module_param(max_wr_blks, uint, 0644);
+MODULE_PARM_DESC(max_wr_blks,
+   "max blocks that can be written in a single command (default: 1)");
+
+static unsigned int daunits = 1;
+module_param(daunits, uint, 0644);
+MODULE_PARM_DESC(daunit

[scsi 1/2] ufs: fix typo: MAZ to MAX

2016-02-09 Thread Tomas Winkler
QUERY_DESC_GEOMETRY_MAZ_SIZE
QUERY_DESC_GEOMETRY_MAX_SIZE

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufs.h| 2 +-
 drivers/scsi/ufs/ufshcd.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a9d3fe..54a16cef0367 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -170,7 +170,7 @@ enum ufs_desc_max_size {
 * of descriptor header.
 */
QUERY_DESC_STRING_MAX_SIZE  = 0xFE,
-   QUERY_DESC_GEOMETRY_MAZ_SIZE= 0x44,
+   QUERY_DESC_GEOMETRY_MAX_SIZE= 0x44,
QUERY_DESC_POWER_MAX_SIZE   = 0x62,
QUERY_DESC_RFU_MAX_SIZE = 0x00,
 };
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 85cd2564c157..a44153401aee 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -92,7 +92,7 @@ static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_INTERCONNECT_MAX_SIZE,
QUERY_DESC_STRING_MAX_SIZE,
QUERY_DESC_RFU_MAX_SIZE,
-   QUERY_DESC_GEOMETRY_MAZ_SIZE,
+   QUERY_DESC_GEOMETRY_MAX_SIZE,
QUERY_DESC_POWER_MAX_SIZE,
QUERY_DESC_RFU_MAX_SIZE,
 };
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 2/2] scsi: ufs: fix few typos in the comments

2016-02-09 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/ufs/ufshcd.c | 4 ++--
 drivers/scsi/ufs/ufshcd.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a44153401aee..07f1fa438fec 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1476,7 +1476,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
if (!time_left) {
err = -ETIMEDOUT;
if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
-   /* sucessfully cleared the command, retry if needed */
+   /* successfully cleared the command, retry if needed */
err = -EAGAIN;
}
 
@@ -2563,7 +2563,7 @@ out:
  * To bring UFS host controller to operational state,
  * 1. Enable required interrupts
  * 2. Configure interrupt aggregation
- * 3. Program UTRL and UTMRL base addres
+ * 3. Program UTRL and UTMRL base address
  * 4. Configure run-stop-registers
  *
  * Returns 0 on success, non-zero value on failure
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 2570d9477b37..18ed160b0ef1 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -177,7 +177,7 @@ struct ufshcd_lrb {
 };
 
 /**
- * struct ufs_query - holds relevent data structures for query request
+ * struct ufs_query - holds relevant data structures for query request
  * @request: request upiu and function
  * @descriptor: buffer for sending/receiving descriptor
  * @response: response upiu and response
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 2/7 RESEND] scsi_debug: use SCSI_W_LUN_REPORT_LUNS instead of SAM2_WLUN_REPORT_LUNS;

2015-07-28 Thread Tomas Winkler
use SCSI_W_LUN_REPORT_LUNS from scsi.h instead of localy defined
SAM2_WLUN_REPORT_LUNS

Signed-off-by: Tomas Winkler 
Acked-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6e6bf0f03cf7..bbe04dae040c 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -204,7 +204,6 @@ static const char *scsi_debug_version_date = "20141022";
 /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
  * or "peripheral device" addressing (value 0) */
 #define SAM2_LUN_ADDRESS_METHOD 0
-#define SAM2_WLUN_REPORT_LUNS 0xc101
 
 /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
  * (for response) at one time. Can be reduced by max_queue option. Command
@@ -701,7 +700,7 @@ static void sdebug_max_tgts_luns(void)
else
hpnt->max_id = scsi_debug_num_tgts;
/* scsi_debug_max_luns; */
-   hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS;
}
spin_unlock(&sdebug_host_list_lock);
 }
@@ -1291,7 +1290,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
if (! arr)
return DID_REQUEUE << 16;
-   have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS);
+   have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS);
if (have_wlun)
pq_pdt = 0x1e;  /* present, wlun */
else if (scsi_debug_no_lun_0 && (0 == devip->lun))
@@ -3367,8 +3366,8 @@ static int resp_report_luns(struct scsi_cmnd * scp,
one_lun[i].scsi_lun[1] = lun & 0xff;
}
if (want_wlun) {
-   one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
-   one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
+   one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
+   one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
i++;
}
alloc_len = (unsigned char *)(one_lun + i) - arr;
@@ -5167,7 +5166,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
}
sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
}
-   has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS);
+   has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS);
if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
return schedule_resp(scp, NULL, errsts_no_connect, 0);
 
@@ -5338,7 +5337,7 @@ static int sdebug_driver_probe(struct device * dev)
hpnt->max_id = scsi_debug_num_tgts + 1;
else
hpnt->max_id = scsi_debug_num_tgts;
-   hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;  /* = scsi_debug_max_luns; */
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
 
host_prot = 0;
 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 3/7 RESEND] scsi_debug: vfree is null safe so drop the check

2015-07-28 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
Acked-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index bbe04dae040c..e2c509e39765 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -4955,10 +4955,8 @@ bus_unreg:
 dev_unreg:
root_device_unregister(pseudo_primary);
 free_vm:
-   if (map_storep)
-   vfree(map_storep);
-   if (dif_storep)
-   vfree(dif_storep);
+   vfree(map_storep);
+   vfree(dif_storep);
vfree(fake_storep);
 
return ret;
@@ -4976,9 +4974,7 @@ static void __exit scsi_debug_exit(void)
bus_unregister(&pseudo_lld_bus);
root_device_unregister(pseudo_primary);
 
-   if (dif_storep)
-   vfree(dif_storep);
-
+   vfree(dif_storep);
vfree(fake_storep);
 }
 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 6/7 RESEND] scsi_debug: fix REPORT LUNS Well Known LU

2015-07-28 Thread Tomas Winkler
The use case to report 'REPORT LUNS WLUN' described
in scsi_debug documentation didn't work because:
scsi_scan_host_selected() checks for:
 lun < shost->max_lun

To fix this we set:
max_lun = SCSI_W_LUN_REPORT_LUNS + 1;

Signed-off-by: Tomas Winkler 
Acked-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index faa4ddd8decf..2e0b3d7dc40f 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -700,7 +700,7 @@ static void sdebug_max_tgts_luns(void)
else
hpnt->max_id = scsi_debug_num_tgts;
/* scsi_debug_max_luns; */
-   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS;
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
}
spin_unlock(&sdebug_host_list_lock);
 }
@@ -5340,7 +5340,8 @@ static int sdebug_driver_probe(struct device * dev)
hpnt->max_id = scsi_debug_num_tgts + 1;
else
hpnt->max_id = scsi_debug_num_tgts;
-   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
+   /* = scsi_debug_max_luns; */
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
 
host_prot = 0;
 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 5/7 RESEND] scsi_debug: schedule_resp fix input variable check

2015-07-28 Thread Tomas Winkler
The function should never be called with cmnd NULL so
put a fat WARN there.
Fix also smatch wraning:
schedule_resp() warn: variable dereferenced before check 'cmnd'

Cc: Douglas Gilbert 
Signed-off-by: Tomas Winkler 
Acked-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 3a70683cf9f9..faa4ddd8decf 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3941,13 +3941,20 @@ schedule_resp(struct scsi_cmnd *cmnd, struct 
sdebug_dev_info *devip,
unsigned long iflags;
int k, num_in_q, qdepth, inject;
struct sdebug_queued_cmd *sqcp = NULL;
-   struct scsi_device *sdp = cmnd->device;
+   struct scsi_device *sdp;
+
+   /* this should never happen */
+   if (WARN_ON(!cmnd))
+   return SCSI_MLQUEUE_HOST_BUSY;
 
-   if (NULL == cmnd || NULL == devip) {
-   pr_warn("called with NULL cmnd or devip pointer\n");
+   if (NULL == devip) {
+   pr_warn("called devip == NULL\n");
/* no particularly good error to report back */
return SCSI_MLQUEUE_HOST_BUSY;
}
+
+   sdp = cmnd->device;
+
if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
__func__, scsi_result);
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 1/7 RESEND] scsi_debug: define pr_fmt() for consistent logging

2015-07-28 Thread Tomas Winkler
Use pr_fmt with both module name and __func__
Also drop few bare printk leftovers

The log format should stay pretty much intact

Signed-off-by: Tomas Winkler 
Acked-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 118 +-
 1 file changed, 53 insertions(+), 65 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 30268bb2ddb6..6e6bf0f03cf7 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -25,6 +25,9 @@
  *module options to "modprobe scsi_debug num_tgts=2" [20021221]
  */
 
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
 #include 
 
 #include 
@@ -2446,8 +2449,7 @@ static int dif_verify(struct sd_dif_tuple *sdt, const 
void *data,
__be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
 
if (sdt->guard_tag != csum) {
-   pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 
0x%04x\n",
-   __func__,
+   pr_err("GUARD check failed on sector %lu rcvd 0x%04x, data 
0x%04x\n",
(unsigned long)sector,
be16_to_cpu(sdt->guard_tag),
be16_to_cpu(csum));
@@ -2455,14 +2457,14 @@ static int dif_verify(struct sd_dif_tuple *sdt, const 
void *data,
}
if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
be32_to_cpu(sdt->ref_tag) != (sector & 0x)) {
-   pr_err("%s: REF check failed on sector %lu\n",
-   __func__, (unsigned long)sector);
+   pr_err("REF check failed on sector %lu\n",
+   (unsigned long)sector);
return 0x03;
}
if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
be32_to_cpu(sdt->ref_tag) != ei_lba) {
-   pr_err("%s: REF check failed on sector %lu\n",
-   __func__, (unsigned long)sector);
+   pr_err("REF check failed on sector %lu\n",
+   (unsigned long)sector);
return 0x03;
}
return 0;
@@ -3449,7 +3451,7 @@ static void sdebug_q_cmd_complete(unsigned long indx)
atomic_inc(&sdebug_completions);
qa_indx = indx;
if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
-   pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
+   pr_err("wild qa_indx=%d\n", qa_indx);
return;
}
spin_lock_irqsave(&queued_arr_lock, iflags);
@@ -3457,21 +3459,21 @@ static void sdebug_q_cmd_complete(unsigned long indx)
scp = sqcp->a_cmnd;
if (NULL == scp) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: scp is NULL\n", __func__);
+   pr_err("scp is NULL\n");
return;
}
devip = (struct sdebug_dev_info *)scp->device->hostdata;
if (devip)
atomic_dec(&devip->num_in_q);
else
-   pr_err("%s: devip=NULL\n", __func__);
+   pr_err("devip=NULL\n");
if (atomic_read(&retired_max_queue) > 0)
retiring = 1;
 
sqcp->a_cmnd = NULL;
if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: Unexpected completion\n", __func__);
+   pr_err("Unexpected completion\n");
return;
}
 
@@ -3481,7 +3483,7 @@ static void sdebug_q_cmd_complete(unsigned long indx)
retval = atomic_read(&retired_max_queue);
if (qa_indx >= retval) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: index %d too large\n", __func__, retval);
+   pr_err("index %d too large\n", retval);
return;
}
k = find_last_bit(queued_in_use_bm, retval);
@@ -3509,7 +3511,7 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
atomic_inc(&sdebug_completions);
qa_indx = sd_hrtp->qa_indx;
if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
-   pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
+   pr_err("wild qa_indx=%d\n", qa_indx);
goto the_end;
}
spin_lock_irqsave(&queued_arr_lock, iflags);
@@ -3517,21 +3519,21 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
scp = sqcp->a_cmnd;
if (NULL == scp) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: scp is NULL\n", __func__);
+  

[scsi 4/7 RESEND] scsi_debug: make dump_sector static

2015-07-28 Thread Tomas Winkler
fixes warning:
warning: no previous prototype for ‘dump_sector’

Signed-off-by: Tomas Winkler 
Acked-by: Douglas Gilbert 
---
 drivers/scsi/scsi_debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index e2c509e39765..3a70683cf9f9 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2681,7 +2681,7 @@ resp_read_dt0(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
return 0;
 }
 
-void dump_sector(unsigned char *buf, int len)
+static void dump_sector(unsigned char *buf, int len)
 {
int i, j, n;
 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 7/7] scsi_debug: resp_request: remove unused variable

2015-07-28 Thread Tomas Winkler
Fixes the following warning

In function ‘resp_requests’:
drivers/scsi//scsi_debug.c:1432:15: warning: variable ‘want_dsense’ set
but not used [-Wunused-but-set-variable]
  bool dsense, want_dsense;

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 2e0b3d7dc40f..dfcc45bb03b1 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1429,12 +1429,11 @@ static int resp_requests(struct scsi_cmnd * scp,
unsigned char * sbuff;
unsigned char *cmd = scp->cmnd;
unsigned char arr[SCSI_SENSE_BUFFERSIZE];
-   bool dsense, want_dsense;
+   bool dsense;
int len = 18;
 
memset(arr, 0, sizeof(arr));
dsense = !!(cmd[1] & 1);
-   want_dsense = dsense || scsi_debug_dsense;
sbuff = scp->sense_buffer;
if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
if (dsense) {
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 1/2] scsi_debug: enable adding more WLUNs

2015-03-01 Thread Tomas Winkler
To add wlun during probe, call sdebug_register_w_lun(WLUN);
prior to setting max luns

hpnt->max_lun = sdebug_max_luns();

Cc: Douglas Gilbert 
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 105 --
 1 file changed, 82 insertions(+), 23 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 0825c0a62a33..5d1bb12adc43 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -683,6 +683,51 @@ static struct sd_dif_tuple *dif_store(sector_t sector)
return dif_storep + sector;
 }
 
+#define  SCSI_W_LUN_MAX 10
+static u8 scsi_debug_w_luns[SCSI_W_LUN_MAX];
+static int scsi_debug_w_luns_count;
+
+static void sdebug_register_w_lun(u8 w_lun_idx)
+{
+   if (WARN_ON(scsi_debug_w_luns_count >= SCSI_W_LUN_MAX))
+   return;
+
+   scsi_debug_w_luns[scsi_debug_w_luns_count++] = w_lun_idx;
+}
+
+static int sdebug_add_w_luns(struct Scsi_Host *hpnt)
+{
+   u64 lun;
+   int i;
+   int ret = 0;
+
+   /* i = 1 skip REPORT LUNS */
+   for (i = 1; i < scsi_debug_w_luns_count; i++) {
+   lun = SCSI_W_LUN_BASE | scsi_debug_w_luns[i];
+   ret = scsi_add_device(hpnt, 0, 0, lun);
+   if (ret)
+   break;
+   }
+
+   return ret;
+}
+
+static u64 sdebug_max_luns(void)
+{
+   u64 max_w_lun;
+   int i;
+
+   max_w_lun = scsi_debug_w_luns[0];
+
+   for (i = 1; i < scsi_debug_w_luns_count; i++) {
+   if (scsi_debug_w_luns[i] > max_w_lun)
+   max_w_lun = scsi_debug_w_luns[i];
+   }
+
+   return SCSI_W_LUN_BASE + max_w_lun + 1;
+}
+
+
 static int sdebug_add_adapter(void);
 static void sdebug_remove_adapter(void);
 
@@ -699,8 +744,8 @@ static void sdebug_max_tgts_luns(void)
hpnt->max_id = scsi_debug_num_tgts + 1;
else
hpnt->max_id = scsi_debug_num_tgts;
-   /* scsi_debug_max_luns; */
-   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
+
+   hpnt->max_lun = sdebug_max_luns();
}
spin_unlock(&sdebug_host_list_lock);
 }
@@ -1284,20 +1329,22 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
unsigned char * arr;
unsigned char *cmd = scp->cmnd;
int alloc_len, n, ret;
-   bool have_wlun;
+   bool is_wlun;
 
alloc_len = (cmd[3] << 8) + cmd[4];
arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
if (! arr)
return DID_REQUEUE << 16;
-   have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS);
-   if (have_wlun)
-   pq_pdt = 0x1e;  /* present, wlun */
+
+   is_wlun = scsi_is_wlun(scp->device->lun);
+   if (is_wlun)
+   pq_pdt = TYPE_WLUN;
else if (scsi_debug_no_lun_0 && (0 == devip->lun))
-   pq_pdt = 0x7f;  /* not present, no device type */
+   pq_pdt = TYPE_NO_LUN;   /* not present, no device type */
else
pq_pdt = (scsi_debug_ptype & 0x1f);
arr[0] = pq_pdt;
+
if (0x2 & cmd[1]) {  /* CMDDT bit set */
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
kfree(arr);
@@ -1311,7 +1358,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
(devip->channel & 0x7f);
if (0 == scsi_debug_vpd_use_hostno)
host_no = 0;
-   lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
+   lu_id_num = is_wlun ? -1 : (((host_no + 1) * 2000) +
(devip->target * 1000) + devip->lun);
target_dev_id = ((host_no + 1) * 2000) +
 (devip->target * 1000) - 3;
@@ -3369,7 +3416,7 @@ static int resp_report_luns(struct scsi_cmnd *scp,
 
/* report w_lun */
if (select_report == 0x01 || select_report == 0x02)
-   wlun_cnt = 1;
+   wlun_cnt = scsi_debug_w_luns_count;
 
rlun_cnt = lun_cnt + wlun_cnt;
 
@@ -3401,9 +3448,11 @@ static int resp_report_luns(struct scsi_cmnd *scp,
for (i = 0; i < lun_cnt; i++)
int_to_scsilun(lun++, one_lun++);
 
-   /* report SCSI_W_LUN_REPORT_LUN */
-   if (wlun_cnt)
-   int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, one_lun++);
+   /* report WLUNs*/
+   for (i = 0; i < wlun_cnt; i++) {
+   lun = SCSI_W_LUN_BASE | scsi_debug_w_luns[i];
+   int_to_scsilun(lun, one_lun++);
+   }
 
rlen = rlun_cnt * sizeof(struct scsi_lun);
 
@@ -5183,7 +5232,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
u32 flags;
u16 sa;
u8 opcode = cmd[0];
-   bool has_wlun_rl;
+   bool is_wlun;
bool debug = !!(SCSI_DEBUG_OPT_NOISE 

[scsi 2/2] scsi_debug: add UFS WLUNs

2015-03-01 Thread Tomas Winkler
Add ufs wluns: ufs, boot, and rpmb
enabled by boolean ufs module parameter.

Cc: Douglas Gilbert 
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 5d1bb12adc43..73557df003c2 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -144,6 +144,7 @@ static const char *scsi_debug_version_date = "20141022";
 #define DEF_WRITESAME_LENGTH 0x
 #define DEF_STRICT 0
 #define DELAY_OVERRIDDEN -
+#define DEF_UFS 0
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -556,6 +557,7 @@ static bool scsi_debug_removable = DEF_REMOVABLE;
 static bool scsi_debug_clustering;
 static bool scsi_debug_host_lock = DEF_HOST_LOCK;
 static bool scsi_debug_strict = DEF_STRICT;
+static bool scsi_debug_ufs = DEF_UFS;
 static bool sdebug_any_injecting_opt;
 
 static atomic_t sdebug_cmnd_count;
@@ -4192,6 +4194,7 @@ module_param_named(vpd_use_hostno, 
scsi_debug_vpd_use_hostno, int,
   S_IRUGO | S_IWUSR);
 module_param_named(write_same_length, scsi_debug_write_same_length, int,
   S_IRUGO | S_IWUSR);
+module_param_named(ufs, scsi_debug_ufs, bool, S_IRUGO | S_IWUSR);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -5426,6 +5429,15 @@ static int sdebug_driver_probe(struct device * dev)
/* REPORT LUNS */
sdebug_register_w_lun(0x01);
 
+   if (scsi_debug_ufs) {
+   /* boot */
+   sdebug_register_w_lun(0x30);
+   /* rpmb */
+   sdebug_register_w_lun(0x44);
+   /* UFS */
+   sdebug_register_w_lun(0x50);
+   }
+
hpnt->max_lun = sdebug_max_luns();
 
host_prot = 0;
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 2/2] scsi_debug: use scsi_device_get_hdata

2015-03-01 Thread Tomas Winkler
Cc: Christoph Hellwig 
Cc: Douglas Gilbert 
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 24 ++--
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 079934c8698e..0825c0a62a33 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3498,7 +3498,7 @@ static void sdebug_q_cmd_complete(unsigned long indx)
pr_err("scp is NULL\n");
return;
}
-   devip = (struct sdebug_dev_info *)scp->device->hostdata;
+   devip = scsi_device_get_hdata(scp->device);
if (devip)
atomic_dec(&devip->num_in_q);
else
@@ -3558,7 +3558,7 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
pr_err("scp is NULL\n");
goto the_end;
}
-   devip = (struct sdebug_dev_info *)scp->device->hostdata;
+   devip = scsi_device_get_hdata(scp->device);
if (devip)
atomic_dec(&devip->num_in_q);
else
@@ -3611,8 +3611,7 @@ static struct sdebug_dev_info * devInfoReg(struct 
scsi_device * sdev)
 {
struct sdebug_host_info * sdbg_host;
struct sdebug_dev_info * open_devip = NULL;
-   struct sdebug_dev_info * devip =
-   (struct sdebug_dev_info *)sdev->hostdata;
+   struct sdebug_dev_info *devip = scsi_device_get_hdata(sdev);
 
if (devip)
return devip;
@@ -3670,7 +3669,7 @@ static int scsi_debug_slave_configure(struct scsi_device 
*sdp)
devip = devInfoReg(sdp);
if (NULL == devip)
return 1;   /* no resources, will be marked offline */
-   sdp->hostdata = devip;
+   scsi_device_set_hdata(sdp, devip);
blk_queue_max_segment_size(sdp->request_queue, -1U);
if (scsi_debug_no_uld)
sdp->no_uld_attach = 1;
@@ -3679,8 +3678,7 @@ static int scsi_debug_slave_configure(struct scsi_device 
*sdp)
 
 static void scsi_debug_slave_destroy(struct scsi_device *sdp)
 {
-   struct sdebug_dev_info *devip =
-   (struct sdebug_dev_info *)sdp->hostdata;
+   struct sdebug_dev_info *devip = scsi_device_get_hdata(sdp);
 
if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
pr_info("slave_destroy <%u %u %u %llu>\n",
@@ -3688,7 +3686,7 @@ static void scsi_debug_slave_destroy(struct scsi_device 
*sdp)
if (devip) {
/* make this slot available for re-use */
devip->used = false;
-   sdp->hostdata = NULL;
+   scsi_device_set_hdata(sdp, NULL);
}
 }
 
@@ -3709,8 +3707,7 @@ static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
if (test_bit(k, queued_in_use_bm)) {
sqcp = &queued_arr[k];
if (cmnd == sqcp->a_cmnd) {
-   devip = (struct sdebug_dev_info *)
-   cmnd->device->hostdata;
+   devip = scsi_device_get_hdata(cmnd->device);
if (devip)
atomic_dec(&devip->num_in_q);
sqcp->a_cmnd = NULL;
@@ -3750,8 +3747,7 @@ static void stop_all_queued(void)
if (test_bit(k, queued_in_use_bm)) {
sqcp = &queued_arr[k];
if (sqcp->a_cmnd) {
-   devip = (struct sdebug_dev_info *)
-   sqcp->a_cmnd->device->hostdata;
+   devip = 
scsi_device_get_hdata(sqcp->a_cmnd->device);
if (devip)
atomic_dec(&devip->num_in_q);
sqcp->a_cmnd = NULL;
@@ -5113,7 +5109,7 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
struct sdebug_dev_info *devip;
 
spin_lock_irqsave(&queued_arr_lock, iflags);
-   devip = (struct sdebug_dev_info *)sdev->hostdata;
+   devip = scsi_device_get_hdata(sdev);
if (NULL == devip) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
return  -ENODEV;
@@ -5212,7 +5208,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
 
sdeb_i = opcode_ind_arr[opcode];/* fully mapped */
oip = &opcode_info_arr[sdeb_i]; /* safe if table consistent */
-   devip = (struct sdebug_dev_info *)sdp->hostdata;
+   devip = scsi_device_get_hdata(sdp);
if (!devip) {
devip = devInfoReg(sdp);
if (NULL == devip)
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 1/2] scsi device: add setters and getters for hostadat

2015-03-01 Thread Tomas Winkler
Add setters and getters for host data of scsi_device
and scsi_target in spirit of  dev_set/get_drvdata

Cc: Christoph Hellwig 
Cc: Douglas Gilbert 
Signed-off-by: Tomas Winkler 
---
 include/scsi/scsi_device.h | 21 +
 1 file changed, 21 insertions(+)

diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index a4c9336811d1..fdf407e8bbed 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -532,6 +532,27 @@ static inline int scsi_device_tpgs(struct scsi_device 
*sdev)
return sdev->inquiry ? (sdev->inquiry[5] >> 4) & 0x3 : 0;
 }
 
+static inline void *scsi_device_get_hdata(struct scsi_device *sdev)
+{
+   return sdev->hostdata;
+}
+
+static inline void scsi_device_set_hdata(struct scsi_device *sdev, void *hdata)
+{
+   sdev->hostdata = hdata;
+}
+
+static inline void *scsi_target_get_hdata(struct scsi_target *starget)
+{
+   return starget->hostdata;
+}
+
+static inline void scsi_target_set_hdata(struct scsi_target *starget,
+ void *hdata)
+{
+   starget->hostdata = hdata;
+}
+
 #define MODULE_ALIAS_SCSI_DEVICE(type) \
MODULE_ALIAS("scsi:t-" __stringify(type) "*")
 #define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATH V2] scsi_debug: rework resp_report_luns

2015-02-25 Thread Tomas Winkler
1. Remove duplicated boundary checks which simplify
the fill-in loop
2. Use more of scsi generic API

Cc: Douglas Gilbert 
Signed-off-by: Tomas Winkler 
---
V2: keep alloc_len < 4 as required by SPC-4 and newer

 drivers/scsi/scsi_debug.c | 119 +-
 1 file changed, 76 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 94c18e300135..079934c8698e 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3320,63 +3320,96 @@ resp_get_lba_status(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
 }
 
-#define SDEBUG_RLUN_ARR_SZ 256
+#define SDEBUG_MAX_RLUNS 31
+#define SDEBUG_RLUN_ARR_SZ ((SDEBUG_MAX_RLUNS * 8) + 8)
 
-static int resp_report_luns(struct scsi_cmnd * scp,
-   struct sdebug_dev_info * devip)
+static int resp_report_luns(struct scsi_cmnd *scp,
+   struct sdebug_dev_info *devip)
 {
+   unsigned char *cmd = scp->cmnd;
unsigned int alloc_len;
-   int lun_cnt, i, upper, num, n, want_wlun, shortish;
+   unsigned char select_report;
+
u64 lun;
-   unsigned char *cmd = scp->cmnd;
-   int select_report = (int)cmd[2];
struct scsi_lun *one_lun;
-   unsigned char arr[SDEBUG_RLUN_ARR_SZ];
-   unsigned char * max_addr;
+   u8 arr[SDEBUG_RLUN_ARR_SZ];
+   unsigned int lun_cnt;  /* LUN count */
+   unsigned int wlun_cnt; /* W_LUN count */
+   unsigned int rlun_cnt; /* reported LUN count */
+   unsigned int rlen; /* reported luns in bytes */
+   unsigned int n;
+   int i;
 
clear_luns_changed_on_target(devip);
-   alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
-   shortish = (alloc_len < 4);
-   if (shortish || (select_report > 2)) {
-   mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
+
+   select_report = cmd[2];
+   alloc_len = get_unaligned_be32(cmd + 6);
+
+   if (alloc_len < 4) {
+   pr_err("alloc len too small %d\n", alloc_len);
+   mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
return check_condition_result;
}
-   /* can produce response with up to 16k luns (lun 0 to lun 16383) */
-   memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
+
+   if (select_report > 0x02) {
+   pr_err("select report invalid %d\n", select_report);
+   mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
+   return check_condition_result;
+   }
+
lun_cnt = scsi_debug_max_luns;
-   if (1 == select_report)
+   wlun_cnt = 0;
+
+   /* report only w_lun */
+   if (select_report == 0x01)
lun_cnt = 0;
-   else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
+
+   if (scsi_debug_no_lun_0 && (lun_cnt > 0))
--lun_cnt;
-   want_wlun = (select_report > 0) ? 1 : 0;
-   num = lun_cnt + want_wlun;
-   arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
-   arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
-   n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
-   sizeof(struct scsi_lun)), num);
-   if (n < num) {
-   want_wlun = 0;
+
+   /* report w_lun */
+   if (select_report == 0x01 || select_report == 0x02)
+   wlun_cnt = 1;
+
+   rlun_cnt = lun_cnt + wlun_cnt;
+
+   /* can produce response with up to 16k luns (lun 0 to lun 16383) */
+   n = min_t(int, SDEBUG_MAX_RLUNS, rlun_cnt);
+   if (n < rlun_cnt) {
+   wlun_cnt = 0;
lun_cnt = n;
}
-   one_lun = (struct scsi_lun *) &arr[8];
-   max_addr = arr + SDEBUG_RLUN_ARR_SZ;
-   for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
- ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
-i++, lun++) {
-   upper = (lun >> 8) & 0x3f;
-   if (upper)
-   one_lun[i].scsi_lun[0] =
-   (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
-   one_lun[i].scsi_lun[1] = lun & 0xff;
-   }
-   if (want_wlun) {
-   one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
-   one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
-   i++;
-   }
-   alloc_len = (unsigned char *)(one_lun + i) - arr;
-   return fill_from_dev_buffer(scp, arr,
-   min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
+
+   pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
+select_report, lun_cnt, wlun_cnt, scsi_debug_no_lun_0);
+
+   lun = 0L

[PATCH] scsi_debug: rework resp_report_luns

2015-02-24 Thread Tomas Winkler
1. Fix the error check: the alloc length should be > 16
and not > 4
2. Remove duplicated boundary checks which simplify
the fill-in loop
3. Use more of scsi generic API

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 119 +-
 1 file changed, 76 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 94c18e300135..4dc8caad6cb2 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3320,63 +3320,96 @@ resp_get_lba_status(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
 }
 
-#define SDEBUG_RLUN_ARR_SZ 256
+#define SDEBUG_MAX_RLUNS 31
+#define SDEBUG_RLUN_ARR_SZ ((SDEBUG_MAX_RLUNS * 8) + 8)
 
-static int resp_report_luns(struct scsi_cmnd * scp,
-   struct sdebug_dev_info * devip)
+static int resp_report_luns(struct scsi_cmnd *scp,
+   struct sdebug_dev_info *devip)
 {
+   unsigned char *cmd = scp->cmnd;
unsigned int alloc_len;
-   int lun_cnt, i, upper, num, n, want_wlun, shortish;
+   unsigned char select_report;
+
u64 lun;
-   unsigned char *cmd = scp->cmnd;
-   int select_report = (int)cmd[2];
struct scsi_lun *one_lun;
-   unsigned char arr[SDEBUG_RLUN_ARR_SZ];
-   unsigned char * max_addr;
+   u8 arr[SDEBUG_RLUN_ARR_SZ];
+   unsigned int lun_cnt;  /* LUN count */
+   unsigned int wlun_cnt; /* W_LUN count */
+   unsigned int rlun_cnt; /* reported LUN count */
+   unsigned int rlen; /* reported luns in bytes */
+   unsigned int n;
+   int i;
 
clear_luns_changed_on_target(devip);
-   alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
-   shortish = (alloc_len < 4);
-   if (shortish || (select_report > 2)) {
-   mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
+
+   select_report = cmd[2];
+   alloc_len = get_unaligned_be32(cmd + 6);
+
+   if (alloc_len < 16) {
+   pr_err("alloc len too small %d\n", alloc_len);
+   mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
return check_condition_result;
}
-   /* can produce response with up to 16k luns (lun 0 to lun 16383) */
-   memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
+
+   if (select_report > 0x02) {
+   pr_err("select report invalid %d\n", select_report);
+   mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
+   return check_condition_result;
+   }
+
lun_cnt = scsi_debug_max_luns;
-   if (1 == select_report)
+   wlun_cnt = 0;
+
+   /* report only w_lun */
+   if (select_report == 0x01)
lun_cnt = 0;
-   else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
+
+   if (scsi_debug_no_lun_0 && (lun_cnt > 0))
--lun_cnt;
-   want_wlun = (select_report > 0) ? 1 : 0;
-   num = lun_cnt + want_wlun;
-   arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
-   arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
-   n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
-   sizeof(struct scsi_lun)), num);
-   if (n < num) {
-   want_wlun = 0;
+
+   /* report w_lun */
+   if (select_report == 0x01 || select_report == 0x02)
+   wlun_cnt = 1;
+
+   rlun_cnt = lun_cnt + wlun_cnt;
+
+   /* can produce response with up to 16k luns (lun 0 to lun 16383) */
+   n = min_t(int, SDEBUG_MAX_RLUNS, rlun_cnt);
+   if (n < rlun_cnt) {
+   wlun_cnt = 0;
lun_cnt = n;
}
-   one_lun = (struct scsi_lun *) &arr[8];
-   max_addr = arr + SDEBUG_RLUN_ARR_SZ;
-   for (i = 0, lun = (scsi_debug_no_lun_0 ? 1 : 0);
- ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
-i++, lun++) {
-   upper = (lun >> 8) & 0x3f;
-   if (upper)
-   one_lun[i].scsi_lun[0] =
-   (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
-   one_lun[i].scsi_lun[1] = lun & 0xff;
-   }
-   if (want_wlun) {
-   one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
-   one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
-   i++;
-   }
-   alloc_len = (unsigned char *)(one_lun + i) - arr;
-   return fill_from_dev_buffer(scp, arr,
-   min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
+
+   pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
+select_report, lun_cnt, wlun_cnt, scsi_debug_no_lun_0);
+
+   lun = 0LL;
+   /* luns

[scsi 1/2 V2] scsi_debug: schedule_resp fix input variable check

2015-02-23 Thread Tomas Winkler
The function should never be called with cmnd NULL so
put a fat WARN there.
Fix also smatch wraning:
schedule_resp() warn: variable dereferenced before check 'cmnd'

Cc: Douglas Gilbert 
Signed-off-by: Tomas Winkler 
---
V2: 1. Actually drop struct scsi_device *sdp = cmnd->device;
2. fix typo in comment
 drivers/scsi/scsi_debug.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index ccbe1282e975..6dda38ca83ee 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3945,13 +3945,20 @@ schedule_resp(struct scsi_cmnd *cmnd, struct 
sdebug_dev_info *devip,
unsigned long iflags;
int k, num_in_q, qdepth, inject;
struct sdebug_queued_cmd *sqcp = NULL;
-   struct scsi_device *sdp = cmnd->device;
+   struct scsi_device *sdp;
+
+   /* this should never happen */
+   if (WARN_ON(!cmnd))
+   return SCSI_MLQUEUE_HOST_BUSY;
 
-   if (NULL == cmnd || NULL == devip) {
-   pr_warn("called with NULL cmnd or devip pointer\n");
+   if (NULL == devip) {
+   pr_warn("called devip == NULL\n");
/* no particularly good error to report back */
return SCSI_MLQUEUE_HOST_BUSY;
}
+
+   sdp = cmnd->device;
+
if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
__func__, scsi_result);
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 2/2] scsi_debug: fix REPORT LUNS Well Known LU

2015-02-23 Thread Tomas Winkler
The use case to report 'REPORT LUNS WLUN' described
in scsi_debug documentation didn't work because:
scsi_scan_host_selected() checks for:
 lun < shost->max_lun

To fix this we set:
max_lun = SCSI_W_LUN_REPORT_LUNS + 1;

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index f032aac75997..2c49ddd8d18b 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -700,7 +700,7 @@ static void sdebug_max_tgts_luns(void)
else
hpnt->max_id = scsi_debug_num_tgts;
/* scsi_debug_max_luns; */
-   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS;
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
}
spin_unlock(&sdebug_host_list_lock);
 }
@@ -5344,7 +5344,8 @@ static int sdebug_driver_probe(struct device * dev)
hpnt->max_id = scsi_debug_num_tgts + 1;
else
hpnt->max_id = scsi_debug_num_tgts;
-   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
+   /* = scsi_debug_max_luns; */
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1;
 
host_prot = 0;
 
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[scsi 1/2] scsi_debug: schedule_resp fix input variable check

2015-02-23 Thread Tomas Winkler
The function should never be called with cmnd NULL so
put a fat WARN there.
Fix also smatch wraning:
schedule_resp() warn: variable dereferenced before check 'cmnd'

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index ccbe1282e975..f032aac75997 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3947,11 +3947,18 @@ schedule_resp(struct scsi_cmnd *cmnd, struct 
sdebug_dev_info *devip,
struct sdebug_queued_cmd *sqcp = NULL;
struct scsi_device *sdp = cmnd->device;
 
-   if (NULL == cmnd || NULL == devip) {
-   pr_warn("called with NULL cmnd or devip pointer\n");
+   /* this should never happend */
+   if (WARN_ON(!cmnd))
+   return SCSI_MLQUEUE_HOST_BUSY;
+
+   if (NULL == devip) {
+   pr_warn("called devip == NULL\n");
/* no particularly good error to report back */
return SCSI_MLQUEUE_HOST_BUSY;
}
+
+   sdp = cmnd->device;
+
if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
__func__, scsi_result);
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/4] scsi_debug cleanup

2015-02-18 Thread Tomas Winkler
I did some minor code cleanups while playing with 
scsi_debug module

Tomas Winkler (4):
  scsi_debug: define pr_fmt() for consistent logging
  scsi_debug: use SCSI_W_LUN_REPORT_LUNS instead of
SAM2_WLUN_REPORT_LUNS;
  scsi_debug: vfree is null safe so drop the check
  scsi_debug: make dump_sector static

 drivers/scsi/scsi_debug.c | 143 --
 1 file changed, 63 insertions(+), 80 deletions(-)

-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/4] scsi_debug: use SCSI_W_LUN_REPORT_LUNS instead of SAM2_WLUN_REPORT_LUNS;

2015-02-18 Thread Tomas Winkler
use SCSI_W_LUN_REPORT_LUNS from scsi.h instead of localy defined
SAM2_WLUN_REPORT_LUNS

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 14e73f27c27f..11774cd1741a 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -204,7 +204,6 @@ static const char *scsi_debug_version_date = "20141022";
 /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
  * or "peripheral device" addressing (value 0) */
 #define SAM2_LUN_ADDRESS_METHOD 0
-#define SAM2_WLUN_REPORT_LUNS 0xc101
 
 /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued
  * (for response) at one time. Can be reduced by max_queue option. Command
@@ -701,7 +700,7 @@ static void sdebug_max_tgts_luns(void)
else
hpnt->max_id = scsi_debug_num_tgts;
/* scsi_debug_max_luns; */
-   hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS;
}
spin_unlock(&sdebug_host_list_lock);
 }
@@ -1291,7 +1290,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
if (! arr)
return DID_REQUEUE << 16;
-   have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS);
+   have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS);
if (have_wlun)
pq_pdt = 0x1e;  /* present, wlun */
else if (scsi_debug_no_lun_0 && (0 == devip->lun))
@@ -3371,8 +3370,8 @@ static int resp_report_luns(struct scsi_cmnd * scp,
one_lun[i].scsi_lun[1] = lun & 0xff;
}
if (want_wlun) {
-   one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
-   one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
+   one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
+   one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
i++;
}
alloc_len = (unsigned char *)(one_lun + i) - arr;
@@ -5171,7 +5170,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
}
sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
}
-   has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS);
+   has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS);
if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
return schedule_resp(scp, NULL, errsts_no_connect, 0);
 
@@ -5342,7 +5341,7 @@ static int sdebug_driver_probe(struct device * dev)
hpnt->max_id = scsi_debug_num_tgts + 1;
else
hpnt->max_id = scsi_debug_num_tgts;
-   hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;  /* = scsi_debug_max_luns; */
+   hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
 
host_prot = 0;
 
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/4] scsi_debug: make dump_sector static

2015-02-18 Thread Tomas Winkler
fixes warning:
warning: no previous prototype for ‘dump_sector’

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 80410f9588ba..ccbe1282e975 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2685,7 +2685,7 @@ resp_read_dt0(struct scsi_cmnd *scp, struct 
sdebug_dev_info *devip)
return 0;
 }
 
-void dump_sector(unsigned char *buf, int len)
+static void dump_sector(unsigned char *buf, int len)
 {
int i, j, n;
 
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4] scsi_debug: define pr_fmt() for consistent logging

2015-02-18 Thread Tomas Winkler
Use pr_fmt with both module name and __func__
Also drop few bare printk leftovers

The log format should stay pretty much intact

Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 118 +-
 1 file changed, 53 insertions(+), 65 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 8bcf6ad0d765..14e73f27c27f 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -25,6 +25,9 @@
  *module options to "modprobe scsi_debug num_tgts=2" [20021221]
  */
 
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
 #include 
 
 #include 
@@ -2450,8 +2453,7 @@ static int dif_verify(struct sd_dif_tuple *sdt, const 
void *data,
__be16 csum = dif_compute_csum(data, scsi_debug_sector_size);
 
if (sdt->guard_tag != csum) {
-   pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 
0x%04x\n",
-   __func__,
+   pr_err("GUARD check failed on sector %lu rcvd 0x%04x, data 
0x%04x\n",
(unsigned long)sector,
be16_to_cpu(sdt->guard_tag),
be16_to_cpu(csum));
@@ -2459,14 +2461,14 @@ static int dif_verify(struct sd_dif_tuple *sdt, const 
void *data,
}
if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
be32_to_cpu(sdt->ref_tag) != (sector & 0x)) {
-   pr_err("%s: REF check failed on sector %lu\n",
-   __func__, (unsigned long)sector);
+   pr_err("REF check failed on sector %lu\n",
+   (unsigned long)sector);
return 0x03;
}
if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
be32_to_cpu(sdt->ref_tag) != ei_lba) {
-   pr_err("%s: REF check failed on sector %lu\n",
-   __func__, (unsigned long)sector);
+   pr_err("REF check failed on sector %lu\n",
+   (unsigned long)sector);
return 0x03;
}
return 0;
@@ -3453,7 +3455,7 @@ static void sdebug_q_cmd_complete(unsigned long indx)
atomic_inc(&sdebug_completions);
qa_indx = indx;
if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
-   pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
+   pr_err("wild qa_indx=%d\n", qa_indx);
return;
}
spin_lock_irqsave(&queued_arr_lock, iflags);
@@ -3461,21 +3463,21 @@ static void sdebug_q_cmd_complete(unsigned long indx)
scp = sqcp->a_cmnd;
if (NULL == scp) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: scp is NULL\n", __func__);
+   pr_err("scp is NULL\n");
return;
}
devip = (struct sdebug_dev_info *)scp->device->hostdata;
if (devip)
atomic_dec(&devip->num_in_q);
else
-   pr_err("%s: devip=NULL\n", __func__);
+   pr_err("devip=NULL\n");
if (atomic_read(&retired_max_queue) > 0)
retiring = 1;
 
sqcp->a_cmnd = NULL;
if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: Unexpected completion\n", __func__);
+   pr_err("Unexpected completion\n");
return;
}
 
@@ -3485,7 +3487,7 @@ static void sdebug_q_cmd_complete(unsigned long indx)
retval = atomic_read(&retired_max_queue);
if (qa_indx >= retval) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: index %d too large\n", __func__, retval);
+   pr_err("index %d too large\n", retval);
return;
}
k = find_last_bit(queued_in_use_bm, retval);
@@ -3513,7 +3515,7 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
atomic_inc(&sdebug_completions);
qa_indx = sd_hrtp->qa_indx;
if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) {
-   pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx);
+   pr_err("wild qa_indx=%d\n", qa_indx);
goto the_end;
}
spin_lock_irqsave(&queued_arr_lock, iflags);
@@ -3521,21 +3523,21 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer)
scp = sqcp->a_cmnd;
if (NULL == scp) {
spin_unlock_irqrestore(&queued_arr_lock, iflags);
-   pr_err("%s: scp is NULL\n", __func__);
+   

[PATCH 3/4] scsi_debug: vfree is null safe so drop the check

2015-02-18 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
---
 drivers/scsi/scsi_debug.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 11774cd1741a..80410f9588ba 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -4959,10 +4959,8 @@ bus_unreg:
 dev_unreg:
root_device_unregister(pseudo_primary);
 free_vm:
-   if (map_storep)
-   vfree(map_storep);
-   if (dif_storep)
-   vfree(dif_storep);
+   vfree(map_storep);
+   vfree(dif_storep);
vfree(fake_storep);
 
return ret;
@@ -4980,9 +4978,7 @@ static void __exit scsi_debug_exit(void)
bus_unregister(&pseudo_lld_bus);
root_device_unregister(pseudo_primary);
 
-   if (dif_storep)
-   vfree(dif_storep);
-
+   vfree(dif_storep);
vfree(fake_storep);
 }
 
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: BUG v3.19: reference count warning when removing scsi_debug device

2015-02-18 Thread Tomas Winkler
On Wed, Feb 18, 2015 at 7:38 PM, David Milburn  wrote:
> On 02/18/2015 07:22 AM, Tomas Winkler wrote:
>>
>> reference count warning when removing scsi_debug device
>>
>> ARNING: CPU: 2 PID: 16732 at kernel/module.c:954 module_put+0xc9/0xd0()
>> [150550.918033] Modules linked in: scsi_debug(-) pci_stub vboxpci(O)
>> vboxnetadp(O) vboxnetflt(O) vboxdrv(O) nfsv3 rfcomm bnep bluetooth
>> rpcsec_gss_krb5 nfsv4 hid_generic usbhid pl2303 hid usbserial
>> snd_hda_codec_hdmi i915 x86_pkg_temp_thermal coretemp kvm_intel
>> drm_kms_helper kvm drm nfsd snd_hda_codec_realtek
>> snd_hda_codec_generic ghash_clmulni_intel snd_hda_intel aesni_intel
>> aes_x86_64 ablk_helper cryptd snd_hda_controller snd_hda_codec
>> auth_rpcgss snd_hwdep snd_pcm oid_registry nfs_acl nfs snd_seq_midi
>> snd_seq_midi_event snd_rawmidi snd_seq lrw gf128mul snd_seq_device
>> snd_timer snd glue_helper microcode mei_me psmouse i2c_algo_bit mei
>> video tpm_infineon tpm_tis r8169 soundcore serio_raw mii lockd lpc_ich
>> mac_hid grace sunrpc fscache binfmt_misc nls_iso8859_1 parport_pc
>> ppdev lp parport [last unloaded: scsi_debug]
>> [150550.918069] CPU: 2 PID: 16732 Comm: modprobe Tainted: GW
>> IO   3.19.0-rc5+ #1
>> [150550.918070] Hardware name: Gigabyte Technology Co., Ltd.
>> H87M-D3H/H87M-D3H, BIOS F6 08/03/2013
>> [150550.918071]  81a85373 880229f9bb88 8175a6cb
>> 
>> [150550.918072]   880229f9bbc8 8105382a
>> 81ccf320
>> [150550.918074]  a070fba0 a070fba0 88022a136010
>> 00800010
>> [150550.918076] Call Trace:
>> [150550.918081]  [] dump_stack+0x4c/0x65
>> [150550.918084]  [] warn_slowpath_common+0x8a/0xc0
>> [150550.918086]  [] warn_slowpath_null+0x1a/0x20
>> [150550.918088]  [] module_put+0xc9/0xd0
>> [150550.918090]  [] scsi_device_put+0x48/0x50
>> [150550.918092]  [] scsi_disk_put+0x32/0x50
>> [150550.918093]  [] sd_shutdown+0x8c/0x150
>> [150550.918095]  [] sd_remove+0x69/0xc0
>> [150550.918097]  [] __device_release_driver+0x7f/0xf0
>> [150550.918099]  [] device_release_driver+0x25/0x40
>> [150550.918101]  [] bus_remove_device+0x124/0x1b0
>> [150550.918103]  [] device_del+0x13e/0x250
>> [150550.918105]  [] __scsi_remove_device+0xcd/0xe0
>> [150550.918107]  [] scsi_forget_host+0x6f/0x80
>> [150550.918108]  [] scsi_remove_host+0x86/0x140
>> [150550.918112]  [] sdebug_driver_remove+0x29/0x90
>> [scsi_debug]
>> [150550.918113]  [] __device_release_driver+0x7f/0xf0
>> [150550.918114]  [] device_release_driver+0x25/0x40
>> [150550.918116]  [] bus_remove_device+0x124/0x1b0
>> [150550.918117]  [] device_del+0x13e/0x250
>> [150550.918119]  [] device_unregister+0x22/0x70
>> [150550.918121]  [] sdebug_remove_adapter+0x50/0x80
>> [scsi_debug]
>> [150550.918123]  [] scsi_debug_exit+0x84/0x85f
>> [scsi_debug]
>> [150550.918125]  [] SyS_delete_module+0x18c/0x210
>> [150550.918129]  [] ? int_with_check+0x27/0x69
>> [150550.918131]  [] system_call_fastpath+0x12/0x17
>> [150550.918132] ---[ end trace 1f300c62b0658728 ]---
>> [150550.935994] sd 7:0:0:1: [sdc] Synchronizing SCSI cache
>> [150550.936017] [ cut here ]
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>>
>
> Hi Tomas,
>
> I think that was fixed 3.19-rc7
>
> commit dc4515ea26d6c7fed3d978cd2bd36adc0d057bc5
> Author: Rusty Russell 
> Date:   Fri Jan 23 13:22:47 2015 +1030
>
> scsi: always increment reference count
>

Thanks, I  was running in 3.19-rc5
Tomas
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


BUG v3.19: reference count warning when removing scsi_debug device

2015-02-18 Thread Tomas Winkler
reference count warning when removing scsi_debug device

ARNING: CPU: 2 PID: 16732 at kernel/module.c:954 module_put+0xc9/0xd0()
[150550.918033] Modules linked in: scsi_debug(-) pci_stub vboxpci(O)
vboxnetadp(O) vboxnetflt(O) vboxdrv(O) nfsv3 rfcomm bnep bluetooth
rpcsec_gss_krb5 nfsv4 hid_generic usbhid pl2303 hid usbserial
snd_hda_codec_hdmi i915 x86_pkg_temp_thermal coretemp kvm_intel
drm_kms_helper kvm drm nfsd snd_hda_codec_realtek
snd_hda_codec_generic ghash_clmulni_intel snd_hda_intel aesni_intel
aes_x86_64 ablk_helper cryptd snd_hda_controller snd_hda_codec
auth_rpcgss snd_hwdep snd_pcm oid_registry nfs_acl nfs snd_seq_midi
snd_seq_midi_event snd_rawmidi snd_seq lrw gf128mul snd_seq_device
snd_timer snd glue_helper microcode mei_me psmouse i2c_algo_bit mei
video tpm_infineon tpm_tis r8169 soundcore serio_raw mii lockd lpc_ich
mac_hid grace sunrpc fscache binfmt_misc nls_iso8859_1 parport_pc
ppdev lp parport [last unloaded: scsi_debug]
[150550.918069] CPU: 2 PID: 16732 Comm: modprobe Tainted: GW
IO   3.19.0-rc5+ #1
[150550.918070] Hardware name: Gigabyte Technology Co., Ltd.
H87M-D3H/H87M-D3H, BIOS F6 08/03/2013
[150550.918071]  81a85373 880229f9bb88 8175a6cb

[150550.918072]   880229f9bbc8 8105382a
81ccf320
[150550.918074]  a070fba0 a070fba0 88022a136010
00800010
[150550.918076] Call Trace:
[150550.918081]  [] dump_stack+0x4c/0x65
[150550.918084]  [] warn_slowpath_common+0x8a/0xc0
[150550.918086]  [] warn_slowpath_null+0x1a/0x20
[150550.918088]  [] module_put+0xc9/0xd0
[150550.918090]  [] scsi_device_put+0x48/0x50
[150550.918092]  [] scsi_disk_put+0x32/0x50
[150550.918093]  [] sd_shutdown+0x8c/0x150
[150550.918095]  [] sd_remove+0x69/0xc0
[150550.918097]  [] __device_release_driver+0x7f/0xf0
[150550.918099]  [] device_release_driver+0x25/0x40
[150550.918101]  [] bus_remove_device+0x124/0x1b0
[150550.918103]  [] device_del+0x13e/0x250
[150550.918105]  [] __scsi_remove_device+0xcd/0xe0
[150550.918107]  [] scsi_forget_host+0x6f/0x80
[150550.918108]  [] scsi_remove_host+0x86/0x140
[150550.918112]  [] sdebug_driver_remove+0x29/0x90
[scsi_debug]
[150550.918113]  [] __device_release_driver+0x7f/0xf0
[150550.918114]  [] device_release_driver+0x25/0x40
[150550.918116]  [] bus_remove_device+0x124/0x1b0
[150550.918117]  [] device_del+0x13e/0x250
[150550.918119]  [] device_unregister+0x22/0x70
[150550.918121]  [] sdebug_remove_adapter+0x50/0x80
[scsi_debug]
[150550.918123]  [] scsi_debug_exit+0x84/0x85f [scsi_debug]
[150550.918125]  [] SyS_delete_module+0x18c/0x210
[150550.918129]  [] ? int_with_check+0x27/0x69
[150550.918131]  [] system_call_fastpath+0x12/0x17
[150550.918132] ---[ end trace 1f300c62b0658728 ]---
[150550.935994] sd 7:0:0:1: [sdc] Synchronizing SCSI cache
[150550.936017] [ cut here ]
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: UFS RPMB

2014-12-15 Thread Tomas Winkler
Can you be more specific about Linux programming API
Thanks

On Mon, Dec 15, 2014 at 6:19 AM, Kyuho Choi  wrote:
> As i know, SECURITY PROTOCOL IN/OUT are support RPMB access for UFS.
>
> On 12/14/14, Tomas Winkler  wrote:
>> Hi, sorry fore a newbie question.
>> What is the current interface for accessing rpmb LUN in a UFS devices.
>> For emmc one need to issue a raw mmc ioctl command  MMC_IOC_CMD.
>>
>> Thanks
>> Tomas
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


UFS RPMB

2014-12-14 Thread Tomas Winkler
Hi, sorry fore a newbie question.
What is the current interface for accessing rpmb LUN in a UFS devices.
For emmc one need to issue a raw mmc ioctl command  MMC_IOC_CMD.

Thanks
Tomas
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html