[PATCH v6 06/17] scsi: ufs: separate device and host quirks

2016-03-06 Thread Yaniv Gardi
Currently we use the host quirks mechanism in order to
handle both device and host controller quirks.
In order to support various of UFS devices we should separate
handling the device quirks from the host controller's.

Reviewed-by: Gilad Broner 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/Makefile |   2 +-
 drivers/scsi/ufs/ufs.h|  31 +++
 drivers/scsi/ufs/ufs_quirks.c | 100 ++
 drivers/scsi/ufs/ufs_quirks.h | 124 ++
 drivers/scsi/ufs/ufshcd.c |   2 +
 drivers/scsi/ufs/ufshcd.h |   3 +
 6 files changed, 261 insertions(+), 1 deletion(-)
 create mode 100644 drivers/scsi/ufs/ufs_quirks.c
 create mode 100644 drivers/scsi/ufs/ufs_quirks.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..8570d41 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,5 +1,5 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
-obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o ufs_quirks.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index aacb235..8ec6356 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -196,6 +196,37 @@ enum unit_desc_param {
UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1  = 0x22,
 };
 
+/* Device descriptor parameters offsets in bytes*/
+enum device_desc_param {
+   DEVICE_DESC_PARAM_LEN   = 0x0,
+   DEVICE_DESC_PARAM_TYPE  = 0x1,
+   DEVICE_DESC_PARAM_DEVICE_TYPE   = 0x2,
+   DEVICE_DESC_PARAM_DEVICE_CLASS  = 0x3,
+   DEVICE_DESC_PARAM_DEVICE_SUB_CLASS  = 0x4,
+   DEVICE_DESC_PARAM_PRTCL = 0x5,
+   DEVICE_DESC_PARAM_NUM_LU= 0x6,
+   DEVICE_DESC_PARAM_NUM_WLU   = 0x7,
+   DEVICE_DESC_PARAM_BOOT_ENBL = 0x8,
+   DEVICE_DESC_PARAM_DESC_ACCSS_ENBL   = 0x9,
+   DEVICE_DESC_PARAM_INIT_PWR_MODE = 0xA,
+   DEVICE_DESC_PARAM_HIGH_PR_LUN   = 0xB,
+   DEVICE_DESC_PARAM_SEC_RMV_TYPE  = 0xC,
+   DEVICE_DESC_PARAM_SEC_LU= 0xD,
+   DEVICE_DESC_PARAM_BKOP_TERM_LT  = 0xE,
+   DEVICE_DESC_PARAM_ACTVE_ICC_LVL = 0xF,
+   DEVICE_DESC_PARAM_SPEC_VER  = 0x10,
+   DEVICE_DESC_PARAM_MANF_DATE = 0x12,
+   DEVICE_DESC_PARAM_MANF_NAME = 0x14,
+   DEVICE_DESC_PARAM_PRDCT_NAME= 0x15,
+   DEVICE_DESC_PARAM_SN= 0x16,
+   DEVICE_DESC_PARAM_OEM_ID= 0x17,
+   DEVICE_DESC_PARAM_MANF_ID   = 0x18,
+   DEVICE_DESC_PARAM_UD_OFFSET = 0x1A,
+   DEVICE_DESC_PARAM_UD_LEN= 0x1B,
+   DEVICE_DESC_PARAM_RTT_CAP   = 0x1C,
+   DEVICE_DESC_PARAM_FRQ_RTC   = 0x1D,
+};
+
 /*
  * Logical Unit Write Protect
  * 00h: LU not write protected
diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c
new file mode 100644
index 000..476ed01
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_quirks.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013-2016, The Linux Foundation. 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 version 2 and
+ * only version 2 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.
+ */
+
+#include "ufshcd.h"
+#include "ufs_quirks.h"
+
+static struct ufs_dev_fix ufs_fixups[] = {
+   /* UFS cards deviations table */
+   UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
+   UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+   UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
+   UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+   UFS_DEVICE_NO_FASTAUTO),
+   UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
+   UFS_DEVICE_QUIRK_PA_TACTIVATE),
+   UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
+   UFS_DEVICE_QUIRK_PA_TACTIVATE),
+
+   END_FIX
+};
+
+static int ufs_get_device_info(struct ufs_hba *hba,
+   struct ufs_device_info *card_data)
+{
+   int err;
+   u8 model_index;
+   u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1] = {0};
+   u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];
+
+   err = ufshcd_read_device_desc(hba, desc_buf,
+   QUERY_DESC_DEVICE_MAX_SIZE);
+   if (err) {
+   

[PATCH v6 06/17] scsi: ufs: separate device and host quirks

2016-03-06 Thread Yaniv Gardi
Currently we use the host quirks mechanism in order to
handle both device and host controller quirks.
In order to support various of UFS devices we should separate
handling the device quirks from the host controller's.

Reviewed-by: Gilad Broner 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/Makefile |   2 +-
 drivers/scsi/ufs/ufs.h|  31 +++
 drivers/scsi/ufs/ufs_quirks.c | 100 ++
 drivers/scsi/ufs/ufs_quirks.h | 124 ++
 drivers/scsi/ufs/ufshcd.c |   2 +
 drivers/scsi/ufs/ufshcd.h |   3 +
 6 files changed, 261 insertions(+), 1 deletion(-)
 create mode 100644 drivers/scsi/ufs/ufs_quirks.c
 create mode 100644 drivers/scsi/ufs/ufs_quirks.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..8570d41 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,5 +1,5 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
-obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o ufs_quirks.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index aacb235..8ec6356 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -196,6 +196,37 @@ enum unit_desc_param {
UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1  = 0x22,
 };
 
+/* Device descriptor parameters offsets in bytes*/
+enum device_desc_param {
+   DEVICE_DESC_PARAM_LEN   = 0x0,
+   DEVICE_DESC_PARAM_TYPE  = 0x1,
+   DEVICE_DESC_PARAM_DEVICE_TYPE   = 0x2,
+   DEVICE_DESC_PARAM_DEVICE_CLASS  = 0x3,
+   DEVICE_DESC_PARAM_DEVICE_SUB_CLASS  = 0x4,
+   DEVICE_DESC_PARAM_PRTCL = 0x5,
+   DEVICE_DESC_PARAM_NUM_LU= 0x6,
+   DEVICE_DESC_PARAM_NUM_WLU   = 0x7,
+   DEVICE_DESC_PARAM_BOOT_ENBL = 0x8,
+   DEVICE_DESC_PARAM_DESC_ACCSS_ENBL   = 0x9,
+   DEVICE_DESC_PARAM_INIT_PWR_MODE = 0xA,
+   DEVICE_DESC_PARAM_HIGH_PR_LUN   = 0xB,
+   DEVICE_DESC_PARAM_SEC_RMV_TYPE  = 0xC,
+   DEVICE_DESC_PARAM_SEC_LU= 0xD,
+   DEVICE_DESC_PARAM_BKOP_TERM_LT  = 0xE,
+   DEVICE_DESC_PARAM_ACTVE_ICC_LVL = 0xF,
+   DEVICE_DESC_PARAM_SPEC_VER  = 0x10,
+   DEVICE_DESC_PARAM_MANF_DATE = 0x12,
+   DEVICE_DESC_PARAM_MANF_NAME = 0x14,
+   DEVICE_DESC_PARAM_PRDCT_NAME= 0x15,
+   DEVICE_DESC_PARAM_SN= 0x16,
+   DEVICE_DESC_PARAM_OEM_ID= 0x17,
+   DEVICE_DESC_PARAM_MANF_ID   = 0x18,
+   DEVICE_DESC_PARAM_UD_OFFSET = 0x1A,
+   DEVICE_DESC_PARAM_UD_LEN= 0x1B,
+   DEVICE_DESC_PARAM_RTT_CAP   = 0x1C,
+   DEVICE_DESC_PARAM_FRQ_RTC   = 0x1D,
+};
+
 /*
  * Logical Unit Write Protect
  * 00h: LU not write protected
diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c
new file mode 100644
index 000..476ed01
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_quirks.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013-2016, The Linux Foundation. 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 version 2 and
+ * only version 2 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.
+ */
+
+#include "ufshcd.h"
+#include "ufs_quirks.h"
+
+static struct ufs_dev_fix ufs_fixups[] = {
+   /* UFS cards deviations table */
+   UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
+   UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+   UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
+   UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+   UFS_DEVICE_NO_FASTAUTO),
+   UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
+   UFS_DEVICE_QUIRK_PA_TACTIVATE),
+   UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
+   UFS_DEVICE_QUIRK_PA_TACTIVATE),
+
+   END_FIX
+};
+
+static int ufs_get_device_info(struct ufs_hba *hba,
+   struct ufs_device_info *card_data)
+{
+   int err;
+   u8 model_index;
+   u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1] = {0};
+   u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];
+
+   err = ufshcd_read_device_desc(hba, desc_buf,
+   QUERY_DESC_DEVICE_MAX_SIZE);
+   if (err) {
+   dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n",
+