scsi: pm80xx: Improve debugging for aborted commands

Improves the debugging capabilities of the driver by adding more context to
debug messages:

 1. Introduce a new function to show pending commands.

 2. Include the tag number in NCQ EH path debug messages.

 3. Add logging for ata_tag along with pm80xx tag to map I/Os aborted with
    ATA logs.

Signed-off-by: Vishakha Channapattan <vishakhavc@google.com>
Signed-off-by: Salomon Dushimirimana <salomondush@google.com>
Link: https://lore.kernel.org/r/20241126225546.975441-1-salomondush@google.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Vishakha Channapattan 2024-11-26 22:55:46 +00:00 committed by Martin K. Petersen
parent b64004dbcd
commit 5efff64c6b
4 changed files with 77 additions and 9 deletions

View File

@ -3472,12 +3472,13 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
status, tag, scp);
switch (status) {
case IO_SUCCESS:
pm8001_dbg(pm8001_ha, EH, "IO_SUCCESS\n");
pm8001_dbg(pm8001_ha, FAIL, "ABORT IO_SUCCESS for tag %#x\n",
tag);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_SAM_STAT_GOOD;
break;
case IO_NOT_VALID:
pm8001_dbg(pm8001_ha, EH, "IO_NOT_VALID\n");
pm8001_dbg(pm8001_ha, FAIL, "IO_NOT_VALID for tag %#x\n", tag);
ts->resp = TMF_RESP_FUNC_FAILED;
break;
}

View File

@ -101,6 +101,63 @@ int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
return 0;
}
static void pm80xx_get_tag_opcodes(struct sas_task *task, int *ata_op,
int *ata_tag, bool *task_aborted)
{
unsigned long flags;
struct ata_queued_cmd *qc = NULL;
*ata_op = 0;
*ata_tag = -1;
*task_aborted = false;
if (!task)
return;
spin_lock_irqsave(&task->task_state_lock, flags);
if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED)))
*task_aborted = true;
spin_unlock_irqrestore(&task->task_state_lock, flags);
if (task->task_proto == SAS_PROTOCOL_STP) {
// sas_ata_qc_issue path uses SAS_PROTOCOL_STP.
// This only works for scsi + libsas + libata users.
qc = task->uldd_task;
if (qc) {
*ata_op = qc->tf.command;
*ata_tag = qc->tag;
}
}
}
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.

View File

@ -787,6 +787,8 @@ static inline void pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
}
void pm8001_setds_completion(struct domain_device *dev);
void pm8001_tmf_aborted(struct sas_task *task);
void pm80xx_show_pending_commands(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *dev);
#endif

View File

@ -2246,7 +2246,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
u32 param;
u32 status;
u32 tag;
int i, j;
int i, j, ata_tag = -1;
u8 sata_addr_low[4];
u32 temp_sata_addr_low, temp_sata_addr_hi;
u8 sata_addr_hi[4];
@ -2256,6 +2256,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
u32 *sata_resp;
struct pm8001_device *pm8001_dev;
unsigned long flags;
struct ata_queued_cmd *qc;
psataPayload = (struct sata_completion_resp *)(piomb + 4);
status = le32_to_cpu(psataPayload->status);
@ -2267,8 +2268,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
pm8001_dev = ccb->device;
if (t) {
if (t->dev && (t->dev->lldd_dev))
if (t->dev && (t->dev->lldd_dev)) {
pm8001_dev = t->dev->lldd_dev;
qc = t->uldd_task;
ata_tag = qc ? qc->tag : -1;
}
} else {
pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",
ccb->ccb_tag);
@ -2276,16 +2280,14 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
return;
}
if (pm8001_dev && unlikely(!t->lldd_task || !t->dev))
return;
ts = &t->task_status;
if (status != IO_SUCCESS) {
pm8001_dbg(pm8001_ha, FAIL,
"IO failed device_id %u status 0x%x tag %d\n",
pm8001_dev->device_id, status, tag);
"IO failed status %#x pm80xx tag %#x ata tag %d\n",
status, tag, ata_tag);
}
/* Print sas address of IO failed device */
@ -2667,13 +2669,19 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha,
/* Check if this is NCQ error */
if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
/* tag value is invalid with this event */
pm8001_dbg(pm8001_ha, FAIL, "NCQ ERROR for device %#x tag %#x\n",
dev_id, tag);
/* find device using device id */
pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
/* send read log extension by aborting the link - libata does what we want */
if (pm8001_dev)
if (pm8001_dev) {
pm80xx_show_pending_commands(pm8001_ha, pm8001_dev);
pm8001_handle_event(pm8001_ha,
pm8001_dev,
IO_XFER_ERROR_ABORTED_NCQ_MODE);
}
return;
}