drivers/scsi/pm8001/pm80xx_hwi.c
Source file repositories/reference/linux-study-clean/drivers/scsi/pm8001/pm80xx_hwi.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/scsi/pm8001/pm80xx_hwi.c- Extension
.c- Size
- 165537 bytes
- Lines
- 5007
- 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.
- 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/slab.hpm8001_sas.hpm80xx_hwi.hpm8001_chips.hpm8001_ctl.hpm80xx_tracepoints.h
Detected Declarations
function pm80xx_bar4_shiftfunction pm80xx_pci_mem_copyfunction pm80xx_get_fatal_dumpfunction pm80xx_get_non_fatal_dumpfunction read_main_config_tablefunction read_general_status_tablefunction read_phy_attr_tablefunction read_inbnd_queue_tablefunction read_outbnd_queue_tablefunction init_default_table_valuesfunction update_main_config_tablefunction update_inbnd_queue_tablefunction update_outbnd_queue_tablefunction mpi_init_checkfunction check_fw_readyfunction init_pci_device_addressesfunction pm80xx_set_thermal_configfunction pm80xx_set_sas_protocol_timer_configfunction pm80xx_get_encrypt_infofunction pm80xx_encrypt_updatefunction pm80xx_chip_initfunction pm80xx_chip_post_initfunction mpi_uninit_checkfunction pm80xx_fatal_error_uevent_emitfunction pm80xx_fatal_errorsfunction pm80xx_chip_soft_rstfunction pm80xx_hw_chip_rstfunction pm80xx_chip_interrupt_enablefunction pm80xx_chip_interrupt_disablefunction mpi_ssp_completionfunction mpi_ssp_eventfunction mpi_sata_completionfunction mpi_sata_eventfunction mpi_smp_completionfunction pm80xx_hw_event_ack_reqfunction hw_event_port_recoverfunction hw_event_sas_phy_upfunction hw_event_sata_phy_upfunction hw_event_phy_downfunction mpi_phy_start_respfunction mpi_thermal_hw_eventfunction mpi_hw_eventfunction mpi_phy_stop_respfunction mpi_set_controller_config_respfunction mpi_get_controller_config_respfunction mpi_get_phy_profile_respfunction mpi_flash_op_ext_respfunction mpi_set_phy_profile_resp
Annotated Snippet
if (offset < (64 * 1024)) {
value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
*destination = cpu_to_le32(value);
}
}
return;
}
ssize_t pm80xx_get_fatal_dump(struct device *cdev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(cdev);
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;
u32 accum_len, reg_val, index, *temp;
u32 status = 1;
unsigned long start;
u8 *direct_data;
char *fatal_error_data = buf;
u32 length_to_read;
u32 offset;
pm8001_ha->forensic_info.data_buf.direct_data = buf;
if (pm8001_ha->chip_id == chip_8001) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
"Not supported for SPC controller");
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
/* initialize variables for very first call from host application */
if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
pm8001_dbg(pm8001_ha, IO,
"forensic_info TYPE_NON_FATAL..............\n");
direct_data = (u8 *)fatal_error_data;
pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;
pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;
pm8001_ha->forensic_info.data_buf.direct_offset = 0;
pm8001_ha->forensic_info.data_buf.read_len = 0;
pm8001_ha->forensic_preserved_accumulated_transfer = 0;
/* Write signature to fatal dump table */
pm8001_mw32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);
pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
pm8001_dbg(pm8001_ha, IO, "ossaHwCB: status1 %d\n", status);
pm8001_dbg(pm8001_ha, IO, "ossaHwCB: read_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.read_len);
pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_len);
pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_offset 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_offset);
}
if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
/* start to get data */
/* Program the MEMBASE II Shifting Register with 0x00.*/
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
pm8001_ha->fatal_forensic_shift_offset);
pm8001_ha->forensic_last_offset = 0;
pm8001_ha->forensic_fatal_step = 0;
pm8001_ha->fatal_bar_loc = 0;
}
/* Read until accum_len is retrieved */
accum_len = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
/* Determine length of data between previously stored transfer length
* and current accumulated transfer length
*/
length_to_read =
accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;
pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: accum_len 0x%x\n",
accum_len);
pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: length_to_read 0x%x\n",
length_to_read);
pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: last_offset 0x%x\n",
pm8001_ha->forensic_last_offset);
pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: read_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.read_len);
pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_len 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_len);
pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_offset 0x%x\n",
pm8001_ha->forensic_info.data_buf.direct_offset);
/* If accumulated length failed to read correctly fail the attempt.*/
if (accum_len == 0xFFFFFFFF) {
pm8001_dbg(pm8001_ha, IO,
"Possible PCI issue 0x%x not expected\n",
Annotation
- Immediate include surface: `linux/slab.h`, `pm8001_sas.h`, `pm80xx_hwi.h`, `pm8001_chips.h`, `pm8001_ctl.h`, `pm80xx_tracepoints.h`.
- Detected declarations: `function pm80xx_bar4_shift`, `function pm80xx_pci_mem_copy`, `function pm80xx_get_fatal_dump`, `function pm80xx_get_non_fatal_dump`, `function read_main_config_table`, `function read_general_status_table`, `function read_phy_attr_table`, `function read_inbnd_queue_table`, `function read_outbnd_queue_table`, `function init_default_table_values`.
- 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.