drivers/ufs/core/ufshcd.c
Source file repositories/reference/linux-study-clean/drivers/ufs/core/ufshcd.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/ufs/core/ufshcd.c- Extension
.c- Size
- 316438 bytes
- Lines
- 11553
- Domain
- Driver Families
- Bucket
- drivers/ufs
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/async.hlinux/devfreq.hlinux/nls.hlinux/of.hlinux/bitfield.hlinux/blk-pm.hlinux/blkdev.hlinux/clk.hlinux/delay.hlinux/hex.hlinux/interrupt.hlinux/module.hlinux/pm_opp.hlinux/regulator/consumer.hlinux/sched/clock.hlinux/sizes.hlinux/iopoll.hscsi/scsi_cmnd.hscsi/scsi_dbg.hscsi/scsi_driver.hscsi/scsi_eh.hscsi/scsi_tcq.hufshcd-priv.hufs/ufs_quirks.hufs/unipro.hufs-sysfs.hufs-debugfs.hufs-fault-injection.hufs_bsg.hufshcd-crypto.hlinux/unaligned.hufs_trace.h
Detected Declarations
struct uc_string_idstruct ufs_ref_clkfunction is_mcq_supportedfunction uic_cmd_timeout_setfunction dev_cmd_timeout_setfunction ufshcd_dump_regsfunction ufs_get_pm_lvl_to_dev_pwr_modefunction ufs_get_pm_lvl_to_link_pwr_statefunction ufs_get_desired_pm_lvl_for_dev_link_statefunction ufshcd_has_pending_tasksfunction ufshcd_is_ufs_dev_busyfunction ufshcd_enable_irqfunction ufshcd_disable_irqfunction ufshcd_enable_intrfunction ufshcd_disable_intrfunction ufshcd_configure_wbfunction ufshcd_add_cmd_upiu_tracefunction ufshcd_add_query_upiu_tracefunction ufshcd_add_tm_upiu_tracefunction ufshcd_add_uic_command_tracefunction ufshcd_add_command_tracefunction ufshcd_print_clk_freqsfunction list_for_each_entryfunction ufshcd_print_evtfunction ufshcd_print_evt_histfunction ufshcd_print_trfunction ufshcd_print_tr_iterfunction ufshcd_print_trs_allfunction ufshcd_print_tmrsfunction for_each_set_bitfunction ufshcd_print_host_statefunction ufshcd_print_pwr_infofunction ufshcd_device_resetfunction ufshcd_delay_usfunction ufshcd_wait_for_registerfunction ufshcd_get_intr_maskfunction ufshcd_get_ufs_versionfunction ufshcd_is_device_presentfunction ufshcd_get_tr_ocsfunction ufshcd_utrl_clearfunction ufshcd_utmrl_clearfunction ufshcd_get_lists_statusfunction ufshcd_get_req_rspfunction ufshcd_is_exception_eventfunction ufshcd_reset_intr_aggrfunction ufshcd_config_intr_aggrfunction ufshcd_disable_intr_aggrfunction ufshcd_enable_run_stop_reg
Annotated Snippet
static const struct blk_mq_ops ufshcd_tmf_ops = {
.queue_rq = ufshcd_queue_tmf,
};
static int ufshcd_add_scsi_host(struct ufs_hba *hba)
{
int err;
WARN_ON_ONCE(!hba->host->can_queue);
WARN_ON_ONCE(!hba->host->cmd_per_lun);
if (is_mcq_supported(hba)) {
ufshcd_mcq_enable(hba);
err = ufshcd_alloc_mcq(hba);
if (err) {
/* Continue with SDB mode */
ufshcd_mcq_disable(hba);
use_mcq_mode = false;
dev_err(hba->dev, "MCQ mode is disabled, err=%d\n",
err);
}
}
if (!is_mcq_supported(hba) && !hba->lsdb_sup) {
dev_err(hba->dev,
"%s: failed to initialize (legacy doorbell mode not supported)\n",
__func__);
return -EINVAL;
}
err = scsi_add_host(hba->host, hba->dev);
if (err) {
dev_err(hba->dev, "scsi_add_host failed\n");
return err;
}
hba->scsi_host_added = true;
hba->tmf_tag_set = (struct blk_mq_tag_set) {
.nr_hw_queues = 1,
.queue_depth = hba->nutmrs,
.ops = &ufshcd_tmf_ops,
};
err = blk_mq_alloc_tag_set(&hba->tmf_tag_set);
if (err < 0)
goto remove_scsi_host;
hba->tmf_queue = blk_mq_alloc_queue(&hba->tmf_tag_set, NULL, NULL);
if (IS_ERR(hba->tmf_queue)) {
err = PTR_ERR(hba->tmf_queue);
goto free_tmf_tag_set;
}
hba->tmf_rqs = devm_kcalloc(hba->dev, hba->nutmrs,
sizeof(*hba->tmf_rqs), GFP_KERNEL);
if (!hba->tmf_rqs) {
err = -ENOMEM;
goto free_tmf_queue;
}
return 0;
free_tmf_queue:
blk_mq_destroy_queue(hba->tmf_queue);
blk_put_queue(hba->tmf_queue);
free_tmf_tag_set:
blk_mq_free_tag_set(&hba->tmf_tag_set);
remove_scsi_host:
if (hba->scsi_host_added)
scsi_remove_host(hba->host);
return err;
}
/**
* ufshcd_init - Driver initialization routine
* @hba: per-adapter instance
* @mmio_base: base register address
* @irq: Interrupt line of device
*
* Return: 0 on success; < 0 on failure.
*/
int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
{
int err;
struct Scsi_Host *host = hba->host;
struct device *dev = hba->dev;
/*
* dev_set_drvdata() must be called before any callbacks are registered
* that use dev_get_drvdata() (frequency scaling, clock scaling, hwmon,
* sysfs).
Annotation
- Immediate include surface: `linux/async.h`, `linux/devfreq.h`, `linux/nls.h`, `linux/of.h`, `linux/bitfield.h`, `linux/blk-pm.h`, `linux/blkdev.h`, `linux/clk.h`.
- Detected declarations: `struct uc_string_id`, `struct ufs_ref_clk`, `function is_mcq_supported`, `function uic_cmd_timeout_set`, `function dev_cmd_timeout_set`, `function ufshcd_dump_regs`, `function ufs_get_pm_lvl_to_dev_pwr_mode`, `function ufs_get_pm_lvl_to_link_pwr_state`, `function ufs_get_desired_pm_lvl_for_dev_link_state`, `function ufshcd_has_pending_tasks`.
- Atlas domain: Driver Families / drivers/ufs.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.