Hi,I don't think these enums would be needed. Let me check and remove these otherwise.
Might as well update the unit descriptor size - its 0x2D now,
enum ufs_desc_def_size {
- QUERY_DESC_DEVICE_DEF_SIZE = 0x40,
+ QUERY_DESC_DEVICE_DEF_SIZE = 0x59,
QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90,
QUERY_DESC_UNIT_DEF_SIZE = 0x23,
As you are adding its new fields
QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06,DEVICE_DESC_PARAM_WB_USER_TYPE = 0x53,
@@ -219,6 +226,7 @@ enum unit_desc_param {
UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18,
UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20,
UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22,
+ UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS = 0x29,
};
/* Device descriptor parameters offsets in bytes*/
@@ -258,6 +266,9 @@ enum device_desc_param {
DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25,
DEVICE_DESC_PARAM_PSA_TMT = 0x29,
DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
+ DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP = 0x4F,
+ DEVICE_DESC_PARAM_WB_TYPE = 0x54,
+ DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS = 0x55,
};
+enum ufs_dev_wb_buf_user_cap_config {Maybe better to follow the spec here:
+ UFS_WB_BUFF_PRESERVE_USER_SPACE = 1,
+ UFS_WB_BUFF_USER_SPACE_RED_EN = 2,
+};
Reduced - 0
Preserve - 1
During init the clocks are scaled-up. Hence, WB is set at init.+{Why are you setting WB on init?
+ int ret;
+
+ if (!ufshcd_wb_sup(hba))
+ return;
+
+ ret = ufshcd_wb_ctrl(hba, true);
The design is to enable flush and let the device handle flush when DB's are empty on its own. Hence I'm setting flush at init itself.
+ if (ret)Why set explicit flush on init?
+ dev_err(hba->dev, "%s: Enable WB failed: %d\n", __func__, ret);
+ else
+ dev_info(hba->dev, "%s: Write Booster Configured\n", __func__);
+ ret = ufshcd_wb_toggle_flush_during_h8(hba, true);
+ if (ret)
+ dev_err(hba->dev, "%s: En WB flush during H8: failed: %d\n",
+ __func__, ret);
+ ufshcd_wb_toggle_flush(hba, true);
Thanks, that makes sense.
+The Preserve User Space mode should be read from -
+
+static bool ufshcd_wb_keep_vcc_on(struct ufs_hba *hba)
+{
+ int ret;
+ u32 cur_buf, avail_buf;
+
+ if (!ufshcd_wb_sup(hba))
+ return false;
+ /*
+ * The ufs device needs the vcc to be ON to flush.
+ * With user-space reduction enabled, it's enough to enable flush
+ * by checking only the available buffer. The threshold
+ * defined here is > 90% full.
+ * With user-space preserved enabled, the current-buffer
+ * should be checked too because the wb buffer size can reduce
+ * when disk tends to be full. This info is provided by current
+ * buffer (dCurrentWriteBoosterBufferSize). There's no point in
+ * keeping vcc on when current buffer is empty.
+ */
+ ret = ufshcd_query_attr_retry(hba,
UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE,
+ 0, 0, &avail_buf);
+ if (ret) {
+ dev_warn(hba->dev, "%s dAvailableWriteBoosterBufferSize read
failed %d\n",
+ __func__, ret);
+ return false;
+ }
+
+ ret = ufshcd_vops_get_user_cap_mode(hba);
bWriteBoosterBufferPreserveUserSpaceEn of the device descriptor - 0ffset 0x53.
The driver should have no judgement here.
Based on what is configured, better to attach a helper pointer that will perform the below check,
e.g. ufshcd_wb_preserve_keep_vcc_on() and ufshcd_wb_reduced_keep_vcc_on().
Which will simplify the logic here and make it much more readable.
This makes the preparations you made for ufshcd_vops_get_user_cap_mode,
and your second patch unneeded.
Good idea.
/**Maybe pack the above code in a wb_probe() designated helper,
* ufshcd_exception_event_handler - handle exceptions raised by device
* @work: pointer to work data
@@ -6632,6 +6829,28 @@ static int ufs_get_device_desc(struct ufs_hba
*hba)
desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1];
model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
+ /* Enable WB only for UFS-3.1 */
+ if (dev_info->wspecversion >= 0x310) {
+ hba->dev_info.d_ext_ufs_feature_sup =
+ get_unaligned_be32(desc_buf +
+ DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
+ /*
+ * WB may be supported but not configured while provisioning.
+ * The spec says, in dedicated wb buffer mode,
+ * a max of 1 lun would have wb buffer configured.
+ * Now only shared buffer mode is supported.
+ */
+ hba->dev_info.b_wb_buffer_type =
+ desc_buf[DEVICE_DESC_PARAM_WB_TYPE];
+
+ if (!hba->dev_info.b_wb_buffer_type)
+ goto skip_alloc_unit;
+ hba->dev_info.d_wb_alloc_units =
+ get_unaligned_be32(desc_buf +
+ DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS);
+ }
which will establish if WB is supported or not.
If one of your validation tests fails, maybe you can just
hba->caps &= ~UFSHCD_CAP_WB_EN;
which will further simplify your ufshcd_wb_sup()
if ((req_dev_pwr_mode != hba->curr_dev_pwr_mode) &&Redundant space removal
- ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) ||
- !ufshcd_is_runtime_pm(pm_op))) {
+ ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) ||
+ !ufshcd_is_runtime_pm(pm_op))) {
Thanks,
Avri