cregit-Linux how code gets into the kernel

Release 4.11 drivers/scsi/ufs/ufshcd.c

Directory: drivers/scsi/ufs
/*
 * Universal Flash Storage Host controller driver Core
 *
 * This code is based on drivers/scsi/ufs/ufshcd.c
 * Copyright (C) 2011-2013 Samsung India Software Operations
 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
 *
 * Authors:
 *      Santosh Yaraganavi <santosh.sy@samsung.com>
 *      Vinayak Holikatti <h.vinayak@samsung.com>
 *
 * 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; either version 2
 * of the License, or (at your option) any later version.
 * See the COPYING file in the top-level directory or visit
 * <http://www.gnu.org/licenses/gpl-2.0.html>
 *
 * 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.
 *
 * This program is provided "AS IS" and "WITH ALL FAULTS" and
 * without warranty of any kind. You are solely responsible for
 * determining the appropriateness of using and distributing
 * the program and assume all risks associated with your exercise
 * of rights with respect to the program, including but not limited
 * to infringement of third party rights, the risks and costs of
 * program errors, damage to or loss of data, programs or equipment,
 * and unavailability or interruption of operations. Under no
 * circumstances will the contributor of this Program be liable for
 * any damages of any kind arising from your use or distribution of
 * this program.
 *
 * The Linux Foundation chooses to take subject only to the GPLv2
 * license terms, and distributes only under these terms.
 */

#include <linux/async.h>
#include <linux/devfreq.h>
#include <linux/nls.h>
#include <linux/of.h>
#include "ufshcd.h"
#include "ufs_quirks.h"
#include "unipro.h"


#define CREATE_TRACE_POINTS
#include <trace/events/ufs.h>


#define UFSHCD_REQ_SENSE_SIZE	18


#define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
                                 UTP_TASK_REQ_COMPL |\
                                 UFSHCD_ERROR_MASK)
/* UIC command timeout, unit: ms */

#define UIC_CMD_TIMEOUT	500

/* NOP OUT retries waiting for NOP IN response */

#define NOP_OUT_RETRIES    10
/* Timeout after 30 msecs if NOP OUT hangs without response */

#define NOP_OUT_TIMEOUT    30 
/* msecs */

/* Query request retries */

#define QUERY_REQ_RETRIES 3
/* Query request timeout */

#define QUERY_REQ_TIMEOUT 1500 
/* 1.5 seconds */

/* Task management command timeout */

#define TM_CMD_TIMEOUT	100 
/* msecs */

/* maximum number of retries for a general UIC command  */

#define UFS_UIC_COMMAND_RETRIES 3

/* maximum number of link-startup retries */

#define DME_LINKSTARTUP_RETRIES 3

/* Maximum retries for Hibern8 enter */

#define UIC_HIBERN8_ENTER_RETRIES 3

/* maximum number of reset retries before giving up */

#define MAX_HOST_RESET_RETRIES 5

/* Expose the flag value from utp_upiu_query.value */

#define MASK_QUERY_UPIU_FLAG_LOC 0xFF

/* Interrupt aggregation default timeout, unit: 40us */

#define INT_AGGR_DEF_TO	0x02


#define ufshcd_toggle_vreg(_dev, _vreg, _on)				\
	({                                                              \
                int _ret;                                               \
                if (_on)                                                \
                        _ret = ufshcd_enable_vreg(_dev, _vreg);         \
                else                                                    \
                        _ret = ufshcd_disable_vreg(_dev, _vreg);        \
                _ret;                                                   \
        })


#define ufshcd_hex_dump(prefix_str, buf, len) \
print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false)

enum {
	
UFSHCD_MAX_CHANNEL	= 0,
	
UFSHCD_MAX_ID		= 1,
	
UFSHCD_CMD_PER_LUN	= 32,
	
UFSHCD_CAN_QUEUE	= 32,
};

/* UFSHCD states */
enum {
	
UFSHCD_STATE_RESET,
	
UFSHCD_STATE_ERROR,
	
UFSHCD_STATE_OPERATIONAL,
	
UFSHCD_STATE_EH_SCHEDULED,
};

/* UFSHCD error handling flags */
enum {
	
UFSHCD_EH_IN_PROGRESS = (1 << 0),
};

/* UFSHCD UIC layer error flags */
enum {
	
UFSHCD_UIC_DL_PA_INIT_ERROR = (1 << 0), /* Data link layer error */
	
UFSHCD_UIC_DL_NAC_RECEIVED_ERROR = (1 << 1), /* Data link layer error */
	
UFSHCD_UIC_DL_TCx_REPLAY_ERROR = (1 << 2), /* Data link layer error */
	
UFSHCD_UIC_NL_ERROR = (1 << 3), /* Network layer error */
	
UFSHCD_UIC_TL_ERROR = (1 << 4), /* Transport Layer error */
	
UFSHCD_UIC_DME_ERROR = (1 << 5), /* DME error */
};

/* Interrupt configuration options */
enum {
	
UFSHCD_INT_DISABLE,
	
UFSHCD_INT_ENABLE,
	
UFSHCD_INT_CLEAR,
};


#define ufshcd_set_eh_in_progress(h) \
	(h->eh_flags |= UFSHCD_EH_IN_PROGRESS)

#define ufshcd_eh_in_progress(h) \
	(h->eh_flags & UFSHCD_EH_IN_PROGRESS)

#define ufshcd_clear_eh_in_progress(h) \
	(h->eh_flags &= ~UFSHCD_EH_IN_PROGRESS)


#define ufshcd_set_ufs_dev_active(h) \
	((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE)

#define ufshcd_set_ufs_dev_sleep(h) \
	((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)

#define ufshcd_set_ufs_dev_poweroff(h) \
	((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)

#define ufshcd_is_ufs_dev_active(h) \
	((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)

#define ufshcd_is_ufs_dev_sleep(h) \
	((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)

#define ufshcd_is_ufs_dev_poweroff(h) \
	((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)


static struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
	{UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE},
	{UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE},
	{UFS_SLEEP_PWR_MODE, UIC_LINK_ACTIVE_STATE},
	{UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
};


static inline enum ufs_dev_pwr_mode ufs_get_pm_lvl_to_dev_pwr_mode(enum ufs_pm_level lvl) { return ufs_pm_lvl_states[lvl].dev_state; }

Contributors

PersonTokensPropCommitsCommitProp
Subhash Jadavani20100.00%1100.00%
Total20100.00%1100.00%


static inline enum uic_link_state ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl) { return ufs_pm_lvl_states[lvl].link_state; }

Contributors

PersonTokensPropCommitsCommitProp
Subhash Jadavani20100.00%1100.00%
Total20100.00%1100.00%


static inline enum ufs_pm_level ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state, enum uic_link_state link_state) { enum ufs_pm_level lvl; for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) { if ((ufs_pm_lvl_states[lvl].dev_state == dev_state) && (ufs_pm_lvl_states[lvl].link_state == link_state)) return lvl; } /* if no match found, return the level 0 */ return UFS_PM_LVL_0; }

Contributors

PersonTokensPropCommitsCommitProp
Subhash Jadavani66100.00%1100.00%
Total66100.00%1100.00%

static struct ufs_dev_fix ufs_fixups[] = { /* UFS cards deviations table */ UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM), 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_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM), UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG", UFS_DEVICE_QUIRK_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG", UFS_DEVICE_QUIRK_PA_TACTIVATE), UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ), UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), END_FIX }; static void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd); static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); static void ufshcd_hba_exit(struct ufs_hba *hba); static int ufshcd_probe_hba(struct ufs_hba *hba); static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, bool skip_ref_clk); static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); static int ufshcd_set_vccq_rail_unused(struct ufs_hba *hba, bool unused); static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); static int ufshcd_host_reset_and_restore(struct ufs_hba *hba); static void ufshcd_resume_clkscaling(struct ufs_hba *hba); static void ufshcd_suspend_clkscaling(struct ufs_hba *hba); static void __ufshcd_suspend_clkscaling(struct ufs_hba *hba); static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up); static irqreturn_t ufshcd_intr(int irq, void *__hba); static int ufshcd_config_pwr_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *desired_pwr_mode); static int ufshcd_change_power_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *pwr_mode);
static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) { return tag >= 0 && tag < hba->nutrs; }

Contributors

PersonTokensPropCommitsCommitProp
Yaniv Gardi26100.00%1100.00%
Total26100.00%1100.00%


static inline int ufshcd_enable_irq(struct ufs_hba *hba) { int ret = 0; if (!hba->is_irq_enabled) { ret = request_irq(hba->irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba); if (ret) dev_err(hba->dev, "%s: request_irq failed, ret=%d\n", __func__, ret); hba->is_irq_enabled = true; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Subhash Jadavani69100.00%1100.00%
Total69100.00%1100.00%


static inline void ufshcd_disable_irq(struct ufs_hba *hba) { if (hba->is_irq_enabled) { free_irq(hba->irq, hba); hba->is_irq_enabled = false; } }

Contributors

PersonTokensPropCommitsCommitProp
Subhash Jadavani35100.00%1100.00%
Total35100.00%1100.00%

/* 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 = ' '; }

Contributors

PersonTokensPropCommitsCommitProp
Yaniv Gardi34100.00%1100.00%
Total34100.00%1100.00%


static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag, const char *str) { sector_t lba = -1; u8 opcode = 0; u32 intr, doorbell; struct ufshcd_lrb *lrbp; int transfer_len = -1; if (!trace_ufshcd_command_enabled()) return; lrbp = &hba->lrb[tag]; if (lrbp->cmd) { /* data phase exists */ opcode = (u8)(*lrbp->cmd->cmnd); if ((opcode == READ_10) || (opcode == WRITE_10)) { /* * Currently we only fully trace read(10) and write(10) * commands */ if (lrbp->cmd->request && lrbp->cmd->request->bio) lba = lrbp->cmd->request->bio->bi_iter.bi_sector; transfer_len = be32_to_cpu( lrbp->ucd_req_ptr->sc.exp_data_transfer_len); } } intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS); doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); trace_ufshcd_command(dev_name(hba->dev), str, tag, doorbell, transfer_len, intr, lba, opcode); }

Contributors

PersonTokensPropCommitsCommitProp
Lee Susman189100.00%1100.00%
Total189100.00%1100.00%


static void ufshcd_print_clk_freqs(struct ufs_hba *hba) { struct ufs_clk_info *clki; struct list_head *head = &hba->clk_list_head; if (!head || list_empty(head)) return; list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk) && clki->min_freq && clki->max_freq) dev_err(hba->dev, "clk: %s, rate: %u\n", clki->name, clki->curr_freq); } }

Contributors

PersonTokensPropCommitsCommitProp
Dolev Raviv82100.00%1100.00%
Total82100.00%1100.00%


static void ufshcd_print_uic_err_hist(struct ufs_hba *hba, struct ufs_uic_err_reg_hist *err_hist, char *err_name) { int i; for (i = 0; i < UIC_ERR_REG_HIST_LENGTH; i++) { int p = (i + err_hist->pos - 1) % UIC_ERR_REG_HIST_LENGTH; if (err_hist->reg[p] == 0) continue; dev_err(hba->dev, "%s[%d] = 0x%x at %lld us\n", err_name, i, err_hist->reg[p], ktime_to_us(err_hist->tstamp[p])); } }

Contributors

PersonTokensPropCommitsCommitProp
Dolev Raviv95100.00%1100.00%
Total95100.00%1100.00%


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. */ ufshcd_hex_dump("host regs: ", hba->mmio_base, UFSHCI_REG_SPACE_SIZE); dev_err(hba->dev, "hba->ufs_version = 0x%x, hba->capabilities = 0x%x\n", hba->ufs_version, hba->capabilities); dev_err(hba->dev, "hba->outstanding_reqs = 0x%x, hba->outstanding_tasks = 0x%x\n", (u32)hba->outstanding_reqs, (u32)hba->outstanding_tasks); dev_err(hba->dev, "last_hibern8_exit_tstamp at %lld us, hibern8_exit_cnt = %d\n", ktime_to_us(hba->ufs_stats.last_hibern8_exit_tstamp), hba->ufs_stats.hibern8_exit_cnt); ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.pa_err, "pa_err"); ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.dl_err, "dl_err"); ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); ufshcd_print_uic_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); ufshcd_print_clk_freqs(hba); if (hba->vops && hba->vops->dbg_register_dump) hba->vops->dbg_register_dump(hba); }

Contributors

PersonTokensPropCommitsCommitProp
Dolev Raviv183100.00%2100.00%
Total183100.00%2100.00%


static void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt) { struct ufshcd_lrb *lrbp; int prdt_length; int tag; for_each_set_bit(tag, &bitmap, hba->nutrs) { lrbp = &hba->lrb[tag]; dev_err(hba->dev, "UPIU[%d] - issue time %lld us\n", tag, ktime_to_us(lrbp->issue_time_stamp)); dev_err(hba->dev, "UPIU[%d] - Transfer Request Descriptor phys@0x%llx\n", tag, (u64)lrbp->utrd_dma_addr); ufshcd_hex_dump("UPIU TRD: ", lrbp->utr_descriptor_ptr, sizeof(struct utp_transfer_req_desc)); dev_err(hba->dev, "UPIU[%d] - Request UPIU phys@0x%llx\n", tag, (u64)lrbp->ucd_req_dma_addr); ufshcd_hex_dump("UPIU REQ: ", lrbp->ucd_req_ptr, sizeof(struct utp_upiu_req)); dev_err(hba->dev, "UPIU[%d] - Response UPIU phys@0x%llx\n", tag, (u64)lrbp->ucd_rsp_dma_addr); ufshcd_hex_dump("UPIU RSP: ", lrbp->ucd_rsp_ptr, sizeof(struct utp_upiu_rsp)); prdt_length = le16_to_cpu( lrbp->utr_descriptor_ptr->prd_table_length); dev_err(hba->dev, "UPIU[%d] - PRDT - %d entries phys@0x%llx\n", tag, prdt_length, (u64)lrbp->ucd_prdt_dma_addr); if (pr_prdt) ufshcd_hex_dump("UPIU PRDT: ", lrbp->ucd_prdt_ptr, sizeof(struct ufshcd_sg_entry) * prdt_length); } }

Contributors

PersonTokensPropCommitsCommitProp
Dolev Raviv20995.87%266.67%
Gilad Broner94.13%133.33%
Total218100.00%3100.00%


static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap) { struct utp_task_req_desc *tmrdp; int tag; for_each_set_bit(tag, &bitmap, hba->nutmrs) { tmrdp = &hba->utmrdl_base_addr[tag]; dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag); ufshcd_hex_dump("TM TRD: ", &tmrdp->header, sizeof(struct request_desc_header)); dev_err(hba->dev, "TM[%d] - Task Management Request UPIU\n", tag); ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu, sizeof(struct utp_upiu_req)); dev_err(hba->dev, "TM[%d] - Task Management Response UPIU\n", tag); ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu, sizeof(struct utp_task_req_desc)); } }

Contributors

PersonTokensPropCommitsCommitProp
Dolev Raviv122100.00%1100.00%
Total122100.00%1100.00%


static void ufshcd_print_host_state(struct ufs_hba *hba) { dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state); dev_err(hba->dev, "lrb in use=0x%lx, outstanding reqs=0x%lx tasks=0x%lx\n", hba->lrb_in_use, hba->outstanding_tasks, hba->outstanding_reqs); dev_err(hba->dev, "saved_err=0x%x, saved_uic_err=0x%x\n", hba->saved_err, hba->saved_uic_err); dev_err(hba->dev, "Device power mode=%d, UIC link state=%d\n", hba->curr_dev_pwr_mode, hba->uic_link_state); dev_err(hba->dev, "PM in progress=%d, sys. suspended=%d\n", hba->pm_op_in_progress, hba->is_sys_suspended); dev_err(hba->dev, "Auto BKOPS=%d, Host self-block=%d\n", hba->auto_bkops_enabled, hba->host->host_self_blocked); dev_err(hba->dev, "Clk gate=%d\n", hba->clk_gating.state); dev_err(hba->dev, "error handling flags=0x%x, req. abort count=%d\n", hba->eh_flags, hba->req_abort_count); dev_err(hba->dev, "Host capabilities=0x%x, caps=0x%x\n", hba->capabilities, hba->caps); dev_err(hba->dev, "quirks=0x%x, dev. quirks=0x%x\n", hba->quirks, hba->dev_quirks); }

Contributors

PersonTokensPropCommitsCommitProp
Gilad Broner181100.00%1100.00%
Total181100.00%1100.00%

/** * ufshcd_print_pwr_info - print power params as saved in hba * power info * @hba: per-adapter instance */
static void ufshcd_print_pwr_info(struct ufs_hba *hba) { static const char * const names[] = { "INVALID MODE", "FAST MODE", "SLOW_MODE", "INVALID MODE", "FASTAUTO_MODE", "SLOWAUTO_MODE", "INVALID MODE", }; dev_err(hba->dev, "%s:[RX, TX]: gear=[%d, %d], lane[%d, %d], pwr[%s, %s], rate = %d\n", __func__, hba->pwr_info.gear_rx, hba->pwr_info.gear_tx, hba->pwr_info.lane_rx, hba->pwr_info.lane_tx, names[hba->pwr_info.pwr_rx], names[hba->pwr_info.pwr_tx], hba->pwr_info.hs_rate); }

Contributors

PersonTokensPropCommitsCommitProp
Dolev Raviv94100.00%1100.00%
Total94100.00%1100.00%

/* * ufshcd_wait_for_register - wait for register value to change * @hba - per-adapter interface * @reg - mmio register offset * @mask - mask to apply to read register value * @val - wait condition * @interval_us - polling interval in microsecs * @timeout_ms - timeout in millisecs * @can_sleep - perform sleep or just spin * * Returns -ETIMEDOUT on error, zero on success */
int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, u32 val, unsigned long interval_us, unsigned long timeout_ms, bool can_sleep) { int err = 0; unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); /* ignore bits that we don't intend to wait on */ val = val & mask; while ((ufshcd_readl(hba, reg) & mask) != val) { if (can_sleep) usleep_range(interval_us, interval_us + 50); else udelay(interval_us); if (time_after(jiffies, timeout)) { if ((ufshcd_readl(hba, reg) & mask) != val) err = -ETIMEDOUT; break; } } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Sujit Reddy Thumma11189.52%150.00%
Yaniv Gardi1310.48%150.00%
Total124100.00%2100.00%

/** * ufshcd_get_intr_mask - Get the interrupt bit mask * @hba - Pointer to adapter instance * * Returns interrupt bit mask per version */
static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba) { u32 intr_mask = 0; switch (hba->ufs_version) { case UFSHCI_VERSION_10: intr_mask = INTERRUPT_MASK_ALL_VER_10; break; /* allow fall through */ case UFSHCI_VERSION_11: case UFSHCI_VERSION_20: intr_mask = INTERRUPT_MASK_ALL_VER_11; break; /* allow fall through */ case UFSHCI_VERSION_21: default: intr_mask = INTERRUPT_MASK_ALL_VER_21; } return intr_mask; }

Contributors

PersonTokensPropCommitsCommitProp
Yaniv Gardi3764.91%150.00%
Seungwon Jeon2035.09%150.00%
Total57100.00%2100.00%

/** * ufshcd_get_ufs_version - Get the UFS version supported by the HBA * @hba - Pointer to adapter instance * * Returns UFSHCI version supported by the controller */
static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba) { if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) return ufshcd_vops_get_ufs_hci_version(hba); return ufshcd_readl(hba, REG_UFS_VERSION); }

Contributors

PersonTokensPropCommitsCommitProp
Vinayak Holikatti1647.06%120.00%
Yaniv Gardi1441.18%240.00%
Seungwon Jeon25.88%120.00%
Santosh Yaraganavi25.88%120.00%
Total34100.00%5100.00%

/** * ufshcd_is_device_present - Check if any device connected to * the host controller * @hba: pointer to adapter instance * * Returns 1 if device present, 0 if no device detected */
static inline int ufshcd_is_device_present(struct ufs_hba *hba) { return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & DEVICE_PRESENT) ? 1 : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vinayak Holikatti1657.14%133.33%
Sujit Reddy Thumma1139.29%133.33%
Santosh Yaraganavi13.57%133.33%
Total28100.00%3100.00%

/** * ufshcd_get_tr_ocs - Get the UTRD Overall Command Status * @lrb: pointer to local command reference block * * This function is used to get the OCS field from UTRD * Returns the OCS field in the UTRD */
static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp) { return le32_to_cpu(lrbp->utr_descriptor_ptr->header.dword_2) & MASK_OCS; }

Contributors

PersonTokensPropCommitsCommitProp
Vinayak Holikatti2180.77%133.33%
Sujit Reddy Thumma311.54%133.33%
Santosh Yaraganavi27.69%133.33%
Total26100.00%3100.00%

/** * ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status * @task_req_descp: pointer to utp_task_req_desc structure * * This function is used to get the OCS field from UTMRD * Returns the OCS field in the UTMRD */
static inline int ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp) { return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS; }

Contributors

PersonTokensPropCommitsCommitProp
Vinayak Holikatti1875.00%133.33%
Santosh Yaraganavi312.50%133.33%
Sujit Reddy Thumma312.50%133.33%
Total24100.00%3100.00%

/** * ufshcd_get_tm_free_slot - get a free slot for task management request * @hba: per adapter instance * @free_slot: pointer to variable with available slot value * * Get a free tag and lock it until ufshcd_put_tm_slot() is called. * Returns 0 if free slot is not available, else return 1 with tag value * in @free_slot. */
static bool ufshcd_get_tm_free_slot(struct ufs_hba *hba, int *free_slot) { int tag; bool ret = false; if (!free_slot) goto out; do { tag = find_first_zero_bit(&hba->tm_slots_in_use, hba->nutmrs); if (tag >= hba->nutmrs) goto out; } while (test_and_set_bit_lock(tag, &hba->tm_slots_in_use)); *free_slot = tag; ret = true; out: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sujit Reddy Thumma6575.58%133.33%
Santosh Yaraganavi1719.77%133.33%
Vinayak Holikatti44.65%133.33%
Total86100.00%3100.00%


static inline void ufshcd_put_tm_slot(struct ufs_hba *hba, int slot) { clear_bit_unlock(slot, &hba->tm_slots_in_use); }

Contributors

PersonTokensPropCommitsCommitProp
Sujit Reddy Thumma25100.00%1100.00%
Total25100.00%1100.00%

/** * ufshcd_utrl_clear - Clear a bit in UTRLCLR register * @hba: per adapter instance * @pos: position of the bit to be cleared */
static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) { ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); }

Contributors

PersonTokensPropCommitsCommitProp
Santosh Yaraganavi2689.66%150.00%
Seungwon Jeon310.34%150.00%
Total29100.00%2100.00%

/** * ufshcd_outstanding_req_clear - Clear a bit in outstanding request field * @hba: per adapter instance * @tag: position of the bit to be cleared */
static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int tag) { __clear_bit(tag, &hba->outstanding_reqs); }

Contributors

PersonTokensPropCommitsCommitProp
Yaniv Gardi25100.00%1100.00%
Total25100.00%1100.00%

/** * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY * @reg: Register value of host controller status * * Returns integer, 0 on Success and positive value if failed */
static inline int ufshcd_get_lists_status(u32 reg) { /* * The mask 0xFF is for the following HCS register bits * Bit Description * 0 Device Present * 1 UTRLRDY * 2 UTMRLRDY * 3 UCRDY * 4-7 reserved */ return ((reg & 0xFF) >> 1) ^ 0x07; }

Contributors

PersonTokensPropCommitsCommitProp
Santosh Yaraganavi2395.83%150.00%
Yaniv Gardi14.17%150.00%
Total24100.00%2100.00%

/** * ufshcd_get_uic_cmd_result - Get the UIC command result * @hba: Pointer to adapter instance * * This function gets the result of UIC command completion * Returns 0 on success, non zero value on error */
static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) { return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) & MASK_UIC_COMMAND_RESULT; }

Contributors

PersonTokensPropCommitsCommitProp
Santosh Yaraganavi2090.91%150.00%
Seungwon Jeon29.09%150.00%
Total22100.00%2100.00%

/** * ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command * @hba: Pointer to adapter instance * * This function gets UIC command argument3 * Returns 0 on success, non zero value on error */
static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) { return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3); }

Contributors

PersonTokensPropCommitsCommitProp
Seungwon Jeon20100.00%1100.00%
Total20100.00%1100.00%

/** * ufshcd_get_req_rsp - returns the TR response transaction type * @ucd_rsp_ptr: pointer to response UPIU */
static inline int ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr) { return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24; }

Contributors

PersonTokensPropCommitsCommitProp
Santosh Yaraganavi2395.83%150.00%
Sujit Reddy Thumma14.17%150.00%
Total24100.00%2100.00%

/** * ufshcd_get_rsp_upiu_result - Get the result from response UPIU * @ucd_rsp_ptr: pointer to response UPIU * * This function gets the response status and scsi_status from response UPIU * Returns the response result code. */
static inline int ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp *ucd_rsp_ptr) { return be32_to_cpu(ucd_rsp_ptr->header.dword_1) & MASK_RSP_UPIU_RESULT; }

Contributors

PersonTokensPropCommitsCommitProp
Santosh Yaraganavi24100.00%1100.00%
Total24100.00%1100.00%

/* * ufshcd_get_rsp_upiu_data_seg_len - Get the data segment length * from response UPIU * @ucd_rsp_ptr: pointer to response UPIU * * Return the data segment length. */
static inline unsigned int ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr) { return be32_to_cpu(ucd_rsp_ptr->header.dword_2) & MASK_RSP_UPIU_DATA_SEG_LEN; }

Contributors

PersonTokensPropCommitsCommitProp
Seungwon Jeon25100.00%1100.00%
Total25100.00%1100.00%

/** * ufshcd_is_exception_event - Check if the device raised an exception event * @ucd_rsp_ptr: pointer to response UPIU * * The function checks if the device raised an exception event indicated in * the Device Information field of response UPIU. * * Returns true if exception is raised, false otherwise. */
static inline bool ufshcd_is_exception_event(struct utp_upiu_rsp *ucd_rsp_ptr) { return be32_to_cpu(ucd_rsp_ptr->header.dword_2) & MASK_RSP_EXCEPTION_EVENT ? true : false; }

Contributors

PersonTokensPropCommitsCommitProp
Sujit Reddy Thumma28100.00%1100.00%
Total28100.00%1100.00%

/** * ufshcd_reset_intr_aggr - Reset interrupt aggregation values. * @hba: per adapter instance */
static inline void ufshcd_reset_intr_aggr(struct ufs_hba *hba) { ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_COUNTER_AND_TIMER_RESET, REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL); }

Contributors

PersonTokensPropCommitsCommitProp
Santosh Yaraganavi1878.26%133.33%
Seungwon Jeon521.74%266.67%
Total23100.00%3100.00%

/** * ufshcd_config_intr_aggr - Configure interrupt aggregation values. * @hba: per adapter instance * @cnt: Interrupt aggregation counter threshold * @tmout: Interrupt aggregation timeout value */
static inline void ufshcd_config_intr_aggr(struct ufs_hba *hba, u8 cnt, u8 tmout) { ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE | INT_AGGR_COUNTER_THLD_VAL(cnt) | INT_AGGR_TIMEOUT_VAL(tmout), REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL); }

Contributors

PersonTokensPropCommitsCommitProp
Seungwon Jeon2871.79%266.67%
Santosh Yaraganavi1128.21%133.33%
Total39100.00%3100.00%

/** * ufshcd_disable_intr_aggr - Disables interrupt aggregation. * @hba: per adapter instance */
static inline void ufshcd_disable_intr_aggr(struct ufs_hba *hba) { ufshcd_writel(hba, 0, REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL); }

Contributors

PersonTokensPropCommitsCommitProp
Yaniv Gardi21100.00%1100.00%
Total21100.00%1100.00%

/** * ufshcd_enable_run_stop_reg - Enable run-stop registers, * When run-stop registers are set to 1, it indicates the * host controller that it can process the requests * @hba: per adapter instance */
static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba) { ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT, REG_UTP_TASK_REQ_LIST_RUN_STOP); ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT, REG_UTP_TRANSFER_REQ_LIST_RUN_STOP); }

Contributors

PersonTokensPropCommitsCommitProp
Sahitya Tummala1551.72%133.33%
Santosh Yaraganavi1137.93%133.33%
Seungwon Jeon310.34%133.33%
Total29100.00%3100.00%

/** * ufshcd_hba_start - Start controller initialization sequence * @hba: per adapter instance */
static inline void ufshcd_hba_start(struct ufs_hba *hba) { ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE); }

Contributors

PersonTokensPropCommitsCommitProp
Sahitya Tummala21100.00%1100.00%
Total21100.00%1100.00%

/** * ufshcd_is_hba_active - Get controller state * @hba: per adapter instance * * Returns zero if controller is active, 1 otherwise */
static inline int ufshcd_is_hba_active(struct ufs_hba *hba) { return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1