Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 344c16c9 authored by Subhash Jadavani's avatar Subhash Jadavani
Browse files

scsi: ufs: read device descriptor once



We are reading the device descriptor once for applying the device
quirks and then device descriptor isn't saved anywhere for future
use. Now that we also need the bDeviceSubClass parameter (of device
descriptor), this change refactors the code to read the device
descriptor once and save the imprortant parameters for later use
by driver.

Change-Id: Icb5d0380a9dcac0e7bd042d9be3abd8bcf6ead48
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
parent ea0f3de2
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -495,7 +495,14 @@ struct ufs_vreg_info {
};

struct ufs_dev_info {
	/* device descriptor info */
	u8	b_device_sub_class;
	u16	w_manufacturer_id;
	u8	i_product_name;

	/* query flags */
	bool f_power_on_wp_en;

	/* Keeps information if any of the LU is power on write protected */
	bool is_lu_power_on_wp;
};
+16 −48
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 * 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
@@ -34,73 +34,41 @@ static struct ufs_card_fix ufs_fixups[] = {
	END_FIX
};

static int ufs_get_device_info(struct ufs_hba *hba,
				struct ufs_card_info *card_data)
void ufs_advertise_fixup_device(struct ufs_hba *hba)
{
	int err;
	u8 model_index;
	u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1];
	u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];
	char *model;
	struct ufs_card_fix *f;

	err = ufshcd_read_device_desc(hba, desc_buf,
					QUERY_DESC_DEVICE_MAX_SIZE);
	if (err)
	model = kmalloc(MAX_MODEL_LEN + 1, GFP_KERNEL);
	if (!model)
		goto out;

	/*
	 * getting vendor (manufacturerID) and Bank Index in big endian
	 * format
	 */
	card_data->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];

	memset(str_desc_buf, 0, QUERY_DESC_STRING_MAX_SIZE);
	err = ufshcd_read_string_desc(hba, model_index, str_desc_buf,
					QUERY_DESC_STRING_MAX_SIZE, ASCII_STD);
	err = ufshcd_read_string_desc(hba, hba->dev_info.i_product_name,
			str_desc_buf, QUERY_DESC_STRING_MAX_SIZE, ASCII_STD);
	if (err)
		goto out;

	str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0';
	strlcpy(card_data->model, (str_desc_buf + QUERY_DESC_HDR_SIZE),
	strlcpy(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';

out:
	return err;
}

void ufs_advertise_fixup_device(struct ufs_hba *hba)
{
	int err;
	struct ufs_card_fix *f;
	struct ufs_card_info card_data;

	card_data.wmanufacturerid = 0;
	card_data.model = kmalloc(MAX_MODEL_LEN + 1, GFP_KERNEL);
	if (!card_data.model)
		goto out;

	/* get device data*/
	err = ufs_get_device_info(hba, &card_data);
	if (err) {
		dev_err(hba->dev, "%s: Failed getting device info\n", __func__);
		goto out;
	}
	model[MAX_MODEL_LEN] = '\0';

	for (f = ufs_fixups; f->quirk; f++) {
		/* if same wmanufacturerid */
		if (((f->card.wmanufacturerid == card_data.wmanufacturerid) ||
		     (f->card.wmanufacturerid == UFS_ANY_VENDOR)) &&
		if (((f->w_manufacturer_id ==
			hba->dev_info.w_manufacturer_id) ||
		     (f->w_manufacturer_id == UFS_ANY_VENDOR)) &&
		    /* and same model */
		    (STR_PRFX_EQUAL(f->card.model, card_data.model) ||
		     !strcmp(f->card.model, UFS_ANY_MODEL)))
		    (STR_PRFX_EQUAL(f->model, model) ||
		     !strcmp(f->model, UFS_ANY_MODEL)))
			/* update quirks */
			hba->dev_quirks |= f->quirk;
	}
out:
	kfree(card_data.model);
	kfree(model);
}
+6 −15
Original line number Diff line number Diff line
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-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
@@ -30,33 +30,24 @@
#define UFS_MODEL_TOSHIBA_32GB "THGLF2G8D4KBADR"
#define UFS_MODEL_TOSHIBA_64GB "THGLF2G9D8KBADG"

/**
 * ufs_card_info - ufs device details
 * @wmanufacturerid: card details
 * @model: card model
 */
struct ufs_card_info {
	u16 wmanufacturerid;
	char *model;
};

/**
 * ufs_card_fix - ufs device quirk info
 * @card: ufs card details
 * @quirk: device quirk
 */
struct ufs_card_fix {
	struct ufs_card_info card;
	u16 w_manufacturer_id;
	char *model;
	unsigned int quirk;
};

#define END_FIX { { 0 } , 0 }
#define END_FIX { 0 }

/* add specific device quirk */
#define UFS_FIX(_vendor, _model, _quirk) \
		{						  \
				.card.wmanufacturerid = (_vendor),\
				.card.model = (_model),		  \
				.w_manufacturer_id = (_vendor),\
				.model = (_model),		  \
				.quirk = (_quirk),		  \
		}

+28 −0
Original line number Diff line number Diff line
@@ -6895,6 +6895,29 @@ static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba)
	return err;
}

static int ufs_read_device_desc_data(struct ufs_hba *hba)
{
	int err;
	u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];

	err = ufshcd_read_device_desc(hba, desc_buf, sizeof(desc_buf));
	if (err)
		return err;

	/*
	 * getting vendor (manufacturerID) and Bank Index in big endian
	 * format
	 */
	hba->dev_info.w_manufacturer_id =
		desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 |
		desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1];
	hba->dev_info.b_device_sub_class =
		desc_buf[DEVICE_DESC_PARAM_DEVICE_SUB_CLASS];
	hba->dev_info.i_product_name = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];

	return 0;
}

/**
 * ufshcd_probe_hba - probe hba to detect device and initialize
 * @hba: per-adapter instance
@@ -6932,6 +6955,11 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
	if (ret)
		goto out;

	/* cache important parameters from device descriptor for later use */
	ret = ufs_read_device_desc_data(hba);
	if (ret)
		goto out;

	ufs_advertise_fixup_device(hba);
	ufshcd_tune_unipro_params(hba);