Skip to content

Commit c6b9ef5

Browse files
Sakthivel KJames Bottomley
authored andcommitted
[SCSI] pm80xx: NCQ error handling changes
Handled NCQ errors in the low level driver as the FW is not providing the faulty tag for NCQ errors for libsas to recover. [jejb: fix checkpatch issues] Signed-off-by: Anand Kumar S <AnandKumar.Santhanam@pmcs.com> Acked-by: Jack Wang <jack_wang@usish.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
1 parent a33a015 commit c6b9ef5

File tree

5 files changed

+544
-28
lines changed

5 files changed

+544
-28
lines changed

drivers/scsi/pm8001/pm8001_hwi.c

Lines changed: 261 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,123 @@ int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
17071707
return ret;
17081708
}
17091709

1710+
static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
1711+
struct pm8001_device *pm8001_ha_dev)
1712+
{
1713+
int res;
1714+
u32 ccb_tag;
1715+
struct pm8001_ccb_info *ccb;
1716+
struct sas_task *task = NULL;
1717+
struct task_abort_req task_abort;
1718+
struct inbound_queue_table *circularQ;
1719+
u32 opc = OPC_INB_SATA_ABORT;
1720+
int ret;
1721+
1722+
if (!pm8001_ha_dev) {
1723+
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n"));
1724+
return;
1725+
}
1726+
1727+
task = sas_alloc_slow_task(GFP_ATOMIC);
1728+
1729+
if (!task) {
1730+
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
1731+
"allocate task\n"));
1732+
return;
1733+
}
1734+
1735+
task->task_done = pm8001_task_done;
1736+
1737+
res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
1738+
if (res)
1739+
return;
1740+
1741+
ccb = &pm8001_ha->ccb_info[ccb_tag];
1742+
ccb->device = pm8001_ha_dev;
1743+
ccb->ccb_tag = ccb_tag;
1744+
ccb->task = task;
1745+
1746+
circularQ = &pm8001_ha->inbnd_q_tbl[0];
1747+
1748+
memset(&task_abort, 0, sizeof(task_abort));
1749+
task_abort.abort_all = cpu_to_le32(1);
1750+
task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
1751+
task_abort.tag = cpu_to_le32(ccb_tag);
1752+
1753+
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
1754+
1755+
}
1756+
1757+
static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
1758+
struct pm8001_device *pm8001_ha_dev)
1759+
{
1760+
struct sata_start_req sata_cmd;
1761+
int res;
1762+
u32 ccb_tag;
1763+
struct pm8001_ccb_info *ccb;
1764+
struct sas_task *task = NULL;
1765+
struct host_to_dev_fis fis;
1766+
struct domain_device *dev;
1767+
struct inbound_queue_table *circularQ;
1768+
u32 opc = OPC_INB_SATA_HOST_OPSTART;
1769+
1770+
task = sas_alloc_slow_task(GFP_ATOMIC);
1771+
1772+
if (!task) {
1773+
PM8001_FAIL_DBG(pm8001_ha,
1774+
pm8001_printk("cannot allocate task !!!\n"));
1775+
return;
1776+
}
1777+
task->task_done = pm8001_task_done;
1778+
1779+
res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
1780+
if (res) {
1781+
PM8001_FAIL_DBG(pm8001_ha,
1782+
pm8001_printk("cannot allocate tag !!!\n"));
1783+
return;
1784+
}
1785+
1786+
/* allocate domain device by ourselves as libsas
1787+
* is not going to provide any
1788+
*/
1789+
dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
1790+
if (!dev) {
1791+
PM8001_FAIL_DBG(pm8001_ha,
1792+
pm8001_printk("Domain device cannot be allocated\n"));
1793+
sas_free_task(task);
1794+
return;
1795+
} else {
1796+
task->dev = dev;
1797+
task->dev->lldd_dev = pm8001_ha_dev;
1798+
}
1799+
1800+
ccb = &pm8001_ha->ccb_info[ccb_tag];
1801+
ccb->device = pm8001_ha_dev;
1802+
ccb->ccb_tag = ccb_tag;
1803+
ccb->task = task;
1804+
pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
1805+
pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
1806+
1807+
memset(&sata_cmd, 0, sizeof(sata_cmd));
1808+
circularQ = &pm8001_ha->inbnd_q_tbl[0];
1809+
1810+
/* construct read log FIS */
1811+
memset(&fis, 0, sizeof(struct host_to_dev_fis));
1812+
fis.fis_type = 0x27;
1813+
fis.flags = 0x80;
1814+
fis.command = ATA_CMD_READ_LOG_EXT;
1815+
fis.lbal = 0x10;
1816+
fis.sector_count = 0x1;
1817+
1818+
sata_cmd.tag = cpu_to_le32(ccb_tag);
1819+
sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
1820+
sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
1821+
memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
1822+
1823+
res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
1824+
1825+
}
1826+
17101827
/**
17111828
* mpi_ssp_completion- process the event that FW response to the SSP request.
17121829
* @pm8001_ha: our hba card information
@@ -1941,7 +2058,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
19412058
break;
19422059
}
19432060
PM8001_IO_DBG(pm8001_ha,
1944-
pm8001_printk("scsi_status = %x \n ",
2061+
pm8001_printk("scsi_status = %x\n ",
19452062
psspPayload->ssp_resp_iu.status));
19462063
spin_lock_irqsave(&t->task_state_lock, flags);
19472064
t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
@@ -2170,23 +2287,64 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
21702287
status = le32_to_cpu(psataPayload->status);
21712288
tag = le32_to_cpu(psataPayload->tag);
21722289

2290+
if (!tag) {
2291+
PM8001_FAIL_DBG(pm8001_ha,
2292+
pm8001_printk("tag null\n"));
2293+
return;
2294+
}
21732295
ccb = &pm8001_ha->ccb_info[tag];
21742296
param = le32_to_cpu(psataPayload->param);
2175-
t = ccb->task;
2297+
if (ccb) {
2298+
t = ccb->task;
2299+
pm8001_dev = ccb->device;
2300+
} else {
2301+
PM8001_FAIL_DBG(pm8001_ha,
2302+
pm8001_printk("ccb null\n"));
2303+
return;
2304+
}
2305+
2306+
if (t) {
2307+
if (t->dev && (t->dev->lldd_dev))
2308+
pm8001_dev = t->dev->lldd_dev;
2309+
} else {
2310+
PM8001_FAIL_DBG(pm8001_ha,
2311+
pm8001_printk("task null\n"));
2312+
return;
2313+
}
2314+
2315+
if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
2316+
&& unlikely(!t || !t->lldd_task || !t->dev)) {
2317+
PM8001_FAIL_DBG(pm8001_ha,
2318+
pm8001_printk("task or dev null\n"));
2319+
return;
2320+
}
2321+
21762322
ts = &t->task_status;
2177-
pm8001_dev = ccb->device;
2178-
if (status)
2323+
if (!ts) {
21792324
PM8001_FAIL_DBG(pm8001_ha,
2180-
pm8001_printk("sata IO status 0x%x\n", status));
2181-
if (unlikely(!t || !t->lldd_task || !t->dev))
2325+
pm8001_printk("ts null\n"));
21822326
return;
2327+
}
21832328

21842329
switch (status) {
21852330
case IO_SUCCESS:
21862331
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
21872332
if (param == 0) {
21882333
ts->resp = SAS_TASK_COMPLETE;
21892334
ts->stat = SAM_STAT_GOOD;
2335+
/* check if response is for SEND READ LOG */
2336+
if (pm8001_dev &&
2337+
(pm8001_dev->id & NCQ_READ_LOG_FLAG)) {
2338+
/* set new bit for abort_all */
2339+
pm8001_dev->id |= NCQ_ABORT_ALL_FLAG;
2340+
/* clear bit for read log */
2341+
pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF;
2342+
pm8001_send_abort_all(pm8001_ha, pm8001_dev);
2343+
/* Free the tag */
2344+
pm8001_tag_free(pm8001_ha, tag);
2345+
sas_free_task(t);
2346+
return;
2347+
}
21902348
} else {
21912349
u8 len;
21922350
ts->resp = SAS_TASK_COMPLETE;
@@ -2497,6 +2655,29 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
24972655
u32 dev_id = le32_to_cpu(psataPayload->device_id);
24982656
unsigned long flags;
24992657

2658+
ccb = &pm8001_ha->ccb_info[tag];
2659+
2660+
if (ccb) {
2661+
t = ccb->task;
2662+
pm8001_dev = ccb->device;
2663+
} else {
2664+
PM8001_FAIL_DBG(pm8001_ha,
2665+
pm8001_printk("No CCB !!!. returning\n"));
2666+
}
2667+
if (event)
2668+
PM8001_FAIL_DBG(pm8001_ha,
2669+
pm8001_printk("SATA EVENT 0x%x\n", event));
2670+
2671+
/* Check if this is NCQ error */
2672+
if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
2673+
/* find device using device id */
2674+
pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
2675+
/* send read log extension */
2676+
if (pm8001_dev)
2677+
pm8001_send_read_log(pm8001_ha, pm8001_dev);
2678+
return;
2679+
}
2680+
25002681
ccb = &pm8001_ha->ccb_info[tag];
25012682
t = ccb->task;
25022683
pm8001_dev = ccb->device;
@@ -3512,19 +3693,29 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
35123693
u32 status ;
35133694
u32 tag, scp;
35143695
struct task_status_struct *ts;
3696+
struct pm8001_device *pm8001_dev;
35153697

35163698
struct task_abort_resp *pPayload =
35173699
(struct task_abort_resp *)(piomb + 4);
35183700

35193701
status = le32_to_cpu(pPayload->status);
35203702
tag = le32_to_cpu(pPayload->tag);
3703+
if (!tag) {
3704+
PM8001_FAIL_DBG(pm8001_ha,
3705+
pm8001_printk(" TAG NULL. RETURNING !!!"));
3706+
return -1;
3707+
}
3708+
35213709
scp = le32_to_cpu(pPayload->scp);
35223710
ccb = &pm8001_ha->ccb_info[tag];
35233711
t = ccb->task;
3524-
PM8001_IO_DBG(pm8001_ha,
3525-
pm8001_printk(" status = 0x%x\n", status));
3526-
if (t == NULL)
3712+
pm8001_dev = ccb->device; /* retrieve device */
3713+
3714+
if (!t) {
3715+
PM8001_FAIL_DBG(pm8001_ha,
3716+
pm8001_printk(" TASK NULL. RETURNING !!!"));
35273717
return -1;
3718+
}
35283719
ts = &t->task_status;
35293720
if (status != 0)
35303721
PM8001_FAIL_DBG(pm8001_ha,
@@ -3548,7 +3739,15 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
35483739
spin_unlock_irqrestore(&t->task_state_lock, flags);
35493740
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
35503741
mb();
3551-
t->task_done(t);
3742+
3743+
if ((pm8001_dev->id & NCQ_ABORT_ALL_FLAG) && t) {
3744+
pm8001_tag_free(pm8001_ha, tag);
3745+
sas_free_task(t);
3746+
/* clear the flag */
3747+
pm8001_dev->id &= 0xBFFFFFFF;
3748+
} else
3749+
t->task_done(t);
3750+
35523751
return 0;
35533752
}
35543753

@@ -4133,6 +4332,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
41334332
u32 ATAP = 0x0;
41344333
u32 dir;
41354334
struct inbound_queue_table *circularQ;
4335+
unsigned long flags;
41364336
u32 opc = OPC_INB_SATA_HOST_OPSTART;
41374337
memset(&sata_cmd, 0, sizeof(sata_cmd));
41384338
circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -4153,8 +4353,10 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
41534353
PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
41544354
}
41554355
}
4156-
if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag))
4356+
if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
4357+
task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
41574358
ncg_tag = hdr_tag;
4359+
}
41584360
dir = data_dir_flags[task->data_dir] << 8;
41594361
sata_cmd.tag = cpu_to_le32(tag);
41604362
sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
@@ -4185,6 +4387,54 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
41854387
sata_cmd.len = cpu_to_le32(task->total_xfer_len);
41864388
sata_cmd.esgl = 0;
41874389
}
4390+
4391+
/* Check for read log for failed drive and return */
4392+
if (sata_cmd.sata_fis.command == 0x2f) {
4393+
if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
4394+
(pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
4395+
(pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
4396+
struct task_status_struct *ts;
4397+
4398+
pm8001_ha_dev->id &= 0xDFFFFFFF;
4399+
ts = &task->task_status;
4400+
4401+
spin_lock_irqsave(&task->task_state_lock, flags);
4402+
ts->resp = SAS_TASK_COMPLETE;
4403+
ts->stat = SAM_STAT_GOOD;
4404+
task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
4405+
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
4406+
task->task_state_flags |= SAS_TASK_STATE_DONE;
4407+
if (unlikely((task->task_state_flags &
4408+
SAS_TASK_STATE_ABORTED))) {
4409+
spin_unlock_irqrestore(&task->task_state_lock,
4410+
flags);
4411+
PM8001_FAIL_DBG(pm8001_ha,
4412+
pm8001_printk("task 0x%p resp 0x%x "
4413+
" stat 0x%x but aborted by upper layer "
4414+
"\n", task, ts->resp, ts->stat));
4415+
pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
4416+
} else if (task->uldd_task) {
4417+
spin_unlock_irqrestore(&task->task_state_lock,
4418+
flags);
4419+
pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
4420+
mb();/* ditto */
4421+
spin_unlock_irq(&pm8001_ha->lock);
4422+
task->task_done(task);
4423+
spin_lock_irq(&pm8001_ha->lock);
4424+
return 0;
4425+
} else if (!task->uldd_task) {
4426+
spin_unlock_irqrestore(&task->task_state_lock,
4427+
flags);
4428+
pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
4429+
mb();/*ditto*/
4430+
spin_unlock_irq(&pm8001_ha->lock);
4431+
task->task_done(task);
4432+
spin_lock_irq(&pm8001_ha->lock);
4433+
return 0;
4434+
}
4435+
}
4436+
}
4437+
41884438
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
41894439
return ret;
41904440
}

0 commit comments

Comments
 (0)