drivers/scsi/pm8001/pm8001_sas.c
Source file repositories/reference/linux-study-clean/drivers/scsi/pm8001/pm8001_sas.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/scsi/pm8001/pm8001_sas.c- Extension
.c- Size
- 36761 bytes
- Lines
- 1265
- Domain
- Driver Families
- Bucket
- drivers/scsi
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/slab.hpm8001_sas.hpm80xx_tracepoints.h
Detected Declarations
function pm8001_find_tagfunction pm8001_tag_freefunction pm8001_tag_allocfunction pm80xx_get_tag_opcodesfunction pm80xx_get_local_phy_idfunction pm80xx_show_pending_commandsfunction pm8001_mem_allocfunction pm8001_phy_controlfunction pm8001_scan_startfunction pm8001_scan_finishedfunction pm8001_task_prep_smpfunction pm8001_get_ncq_tagfunction pm8001_task_prep_atafunction pm8001_task_prep_internal_abortfunction pm8001_task_prep_ssp_tmfunction pm8001_task_prep_sspfunction pm8001_deliver_commandfunction pm8001_queue_commandfunction pm8001_ccb_task_freefunction pm8001_init_devfunction pm8001_free_devfunction IDfunction pm8001_dev_foundfunction pm8001_dev_gone_notifyfunction pm8001_dev_gonefunction pm8001_open_reject_retryfunction pm8001_I_T_nexus_resetfunction pm8001_I_T_nexus_event_handlerfunction pm8001_lu_resetfunction pm8001_query_taskfunction pm8001_abort_taskfunction pm8001_clear_task_setfunction pm8001_port_formedfunction pm8001_setds_completionfunction pm8001_tmf_aborted
Annotated Snippet
if (qc) {
*ata_op = qc->tf.command;
*ata_tag = qc->tag;
}
}
}
u32 pm80xx_get_local_phy_id(struct domain_device *dev)
{
struct pm8001_device *pm8001_dev = dev->lldd_dev;
if (dev_parent_is_expander(dev))
return dev->parent->ex_dev.ex_phy->phy_id;
return pm8001_dev->attached_phy;
}
void pm80xx_show_pending_commands(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *target_pm8001_dev)
{
int i = 0, ata_op = 0, ata_tag = -1;
struct pm8001_ccb_info *ccb = NULL;
struct sas_task *task = NULL;
struct pm8001_device *pm8001_dev = NULL;
bool task_aborted;
for (i = 0; i < pm8001_ha->ccb_count; i++) {
ccb = &pm8001_ha->ccb_info[i];
if (ccb->ccb_tag == PM8001_INVALID_TAG)
continue;
pm8001_dev = ccb->device;
if (target_pm8001_dev && pm8001_dev &&
target_pm8001_dev != pm8001_dev)
continue;
task = ccb->task;
pm80xx_get_tag_opcodes(task, &ata_op, &ata_tag, &task_aborted);
pm8001_dbg(pm8001_ha, FAIL,
"tag %#x, device %#x task %p task aborted %d ata opcode %#x ata tag %d\n",
ccb->ccb_tag,
(pm8001_dev ? pm8001_dev->device_id : 0),
task, task_aborted,
ata_op, ata_tag);
}
}
/**
* pm8001_mem_alloc - allocate memory for pm8001.
* @pdev: pci device.
* @virt_addr: the allocated virtual address
* @pphys_addr: DMA address for this device
* @pphys_addr_hi: the physical address high byte address.
* @pphys_addr_lo: the physical address low byte address.
* @mem_size: memory size.
* @align: requested byte alignment
*/
int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
dma_addr_t *pphys_addr, u32 *pphys_addr_hi,
u32 *pphys_addr_lo, u32 mem_size, u32 align)
{
caddr_t mem_virt_alloc;
dma_addr_t mem_dma_handle;
u64 phys_align;
u64 align_offset = 0;
if (align)
align_offset = (dma_addr_t)align - 1;
mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align,
&mem_dma_handle, GFP_KERNEL);
if (!mem_virt_alloc)
return -ENOMEM;
*pphys_addr = mem_dma_handle;
phys_align = (*pphys_addr + align_offset) & ~align_offset;
*virt_addr = (void *)mem_virt_alloc + phys_align - *pphys_addr;
*pphys_addr_hi = upper_32_bits(phys_align);
*pphys_addr_lo = lower_32_bits(phys_align);
return 0;
}
/**
* pm8001_find_ha_by_dev - from domain device which come from sas layer to
* find out our hba struct.
* @dev: the domain device which from sas layer.
*/
static
struct pm8001_hba_info *pm8001_find_ha_by_dev(struct domain_device *dev)
{
struct sas_ha_struct *sha = dev->port->ha;
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
return pm8001_ha;
}
Annotation
- Immediate include surface: `linux/slab.h`, `pm8001_sas.h`, `pm80xx_tracepoints.h`.
- Detected declarations: `function pm8001_find_tag`, `function pm8001_tag_free`, `function pm8001_tag_alloc`, `function pm80xx_get_tag_opcodes`, `function pm80xx_get_local_phy_id`, `function pm80xx_show_pending_commands`, `function pm8001_mem_alloc`, `function pm8001_phy_control`, `function pm8001_scan_start`, `function pm8001_scan_finished`.
- Atlas domain: Driver Families / drivers/scsi.
- Implementation status: source 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.