From: hgchu Date: Fri, 12 Jan 2018 01:12:48 +0000 (+0900) Subject: scsi: ufs: get deivce descriptor information X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=8d65d1bba79fde1c9c7c278756e048c547f2dcaf;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git scsi: ufs: get deivce descriptor information Change-Id: Ifcadfbdbc0e954de726d28a7a33a1c8665123e47 Signed-off-by: hgchu --- diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 54deeb754db5..1ec5fe80f0b2 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -137,10 +137,24 @@ enum flag_idn { /* Attribute idn for Query requests */ enum attr_idn { + QUERY_ATTR_IDN_BOOT_LU_EN = 0x00, + QUERY_ATTR_IDN_RESERVED = 0x01, + QUERY_ATTR_IDN_POWER_MODE = 0x02, QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03, + QUERY_ATTR_IDN_OOO_DATA_EN = 0x04, QUERY_ATTR_IDN_BKOPS_STATUS = 0x05, + QUERY_ATTR_IDN_PURGE_STATUS = 0x06, + QUERY_ATTR_IDN_MAX_DATA_IN = 0x07, + QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08, + QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09, + QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A, + QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B, + QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C, QUERY_ATTR_IDN_EE_CONTROL = 0x0D, QUERY_ATTR_IDN_EE_STATUS = 0x0E, + QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F, + QUERY_ATTR_IDN_CNTX_CONF = 0x10, + QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11, }; /* Descriptor idn for Query requests */ @@ -154,6 +168,8 @@ enum desc_idn { QUERY_DESC_IDN_RFU_1 = 0x6, QUERY_DESC_IDN_GEOMETRY = 0x7, QUERY_DESC_IDN_POWER = 0x8, + QUERY_DESC_IDN_HEALTH = 0x9, + QUERY_DESC_IDN_RFU_2 = 0xA, QUERY_DESC_IDN_MAX, }; @@ -302,6 +318,15 @@ enum { QUERY_RESULT_GENERAL_FAILURE = 0xFF, }; +enum health_device_desc_param { + HEALTH_DEVICE_DESC_PARAM_LEN = 0x0, + HEALTH_DEVICE_DESC_PARAM_IDN =0x1, + HEALTH_DEVICE_DESC_PARAM_INFO =0x2, + HEALTH_DEVICE_DESC_PARAM_LIFETIMEA =0x3, + HEALTH_DEVICE_DESC_PARAM_LIFETIMEB =0x4, + HEALTH_DEVICE_DESC_PARAM_RESERVED =0x5, +}; + /* UTP Transfer Request Command Type (CT) */ enum { UPIU_COMMAND_SET_TYPE_SCSI = 0x0, diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c new file mode 100644 index 000000000000..c1c1ef04ea20 --- /dev/null +++ b/drivers/scsi/ufs/ufs_quirks.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013-2014, 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" + +#ifndef UFS_VENDOR_ID_SAMSUNG +#define UFS_VENDOR_ID_SAMSUNG 0x1ce +#endif + +#define SERIAL_NUM_SIZE 6 +#define TOSHIBA_SERIAL_NUM_SIZE 10 + + +/*UN policy +* 16 digits : mandate + serial number(6byte, hex raw data) +* 18 digits : manid + mandate + serial number(sec, hynix : 6byte hex, +* toshiba : 10byte + 00, ascii) +*/ +void ufs_set_sec_unique_number(struct ufs_hba *hba, u8 *str_desc_buf, u8 *desc_buf) +{ + u8 manid; + u8 snum_buf[UFS_UN_MAX_DIGITS]; + + manid = hba->manufacturer_id & 0xFF; + memset(hba->unique_number, 0, sizeof(hba->unique_number)); + memset(snum_buf, 0, sizeof(snum_buf)); + +#if defined(CONFIG_UFS_UN_18DIGITS) + + memcpy(snum_buf, str_desc_buf + QUERY_DESC_HDR_SIZE, SERIAL_NUM_SIZE); + + sprintf(hba->unique_number, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", + manid, + desc_buf[DEVICE_DESC_PARAM_MANF_DATE], desc_buf[DEVICE_DESC_PARAM_MANF_DATE+1], + snum_buf[0], snum_buf[1], snum_buf[2], snum_buf[3], snum_buf[4], snum_buf[5]); + + /* Null terminate the unique number string */ + hba->unique_number[UFS_UN_18_DIGITS] = '\0'; + +#else + /*default is 16 DIGITS UN*/ + memcpy(snum_buf, str_desc_buf + QUERY_DESC_HDR_SIZE, SERIAL_NUM_SIZE); + + sprintf(hba->unique_number, "%02x%02x%02x%02x%02x%02x%02x%02x", + desc_buf[DEVICE_DESC_PARAM_MANF_DATE], desc_buf[DEVICE_DESC_PARAM_MANF_DATE+1], + snum_buf[0], snum_buf[1], snum_buf[2], snum_buf[3], snum_buf[4], snum_buf[5]); + + /* Null terminate the unique number string */ + hba->unique_number[UFS_UN_16_DIGITS] = '\0'; +#endif +} + + diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 81ad7ba44062..004f96c9f1a3 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -44,6 +44,8 @@ #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" +#include "ufs-exynos.h" +#include "ufs_quirks.h" #define CREATE_TRACE_POINTS #include @@ -3090,6 +3092,25 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba, goto out; } + /* + * While reading variable size descriptors (like string descriptor), + * some UFS devices may report the "LENGTH" (field in "Transaction + * Specific fields" of Query Response UPIU) same as what was requested + * in Query Request UPIU instead of reporting the actual size of the + * variable size descriptor. + * Although it's safe to ignore the "LENGTH" field for variable size + * descriptors as we can always derive the length of the descriptor from + * the descriptor header fields. Hence this change impose the length + * match check only for fixed size descriptors (for which we always + * request the correct size as part of Query Request UPIU). + */ + if ((desc_id != QUERY_DESC_IDN_STRING) && + (buff_len != desc_buf[QUERY_DESC_LENGTH_OFFSET])) { + dev_err(hba->dev, "%s: desc_buf length mismatch: buff_len %d, buff_len(desc_header) %d", + __func__, buff_len, desc_buf[QUERY_DESC_LENGTH_OFFSET]); + ret = -EINVAL; + goto out; + } /* Check wherher we will not copy more data, than available */ if (is_kmalloc && param_size > buff_len) param_size = buff_len; @@ -3219,6 +3240,20 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, param_offset, param_read_buf, param_size); } +int ufshcd_read_health_desc(struct ufs_hba *hba, u8 *buf, u32 size) +{ + int err = 0; + + err = ufshcd_read_desc(hba, + QUERY_DESC_IDN_HEALTH, 0, buf, size); + + if (err) + dev_err(hba->dev, "%s: reading Device Health Desc failed. err = %d\n", + __func__, err); + + return err; +} + /** * ufshcd_memory_alloc - allocate memory for host memory space data structures * @hba: per adapter instance diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 9f1a466d6122..9c08f82795a2 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -996,4 +996,5 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) hba->vops->dbg_register_dump(hba); } +int ufshcd_read_health_desc(struct ufs_hba *hba, u8 *buf, u32 size); #endif /* End of Header */