diff options
author | Sakthivel K <Sakthivel.SaravananKamalRaju@pmcs.com> | 2013-03-19 08:38:08 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-10 10:47:51 -0400 |
commit | c6b9ef5779c3e1edfa9de949d2a51252bc347663 (patch) | |
tree | a4902f4076effc0b56848ceb3aa497ced5537b33 /drivers/scsi | |
parent | a33a0155dae5a8fdc85a9853ca06d6d57b90a4d9 (diff) |
[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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 272 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 22 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 15 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 262 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.h | 1 |
5 files changed, 544 insertions, 28 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 5710364dc5da..dbdd9d386f10 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -1707,6 +1707,123 @@ int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data, | |||
1707 | return ret; | 1707 | return ret; |
1708 | } | 1708 | } |
1709 | 1709 | ||
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 | |||
1710 | /** | 1827 | /** |
1711 | * mpi_ssp_completion- process the event that FW response to the SSP request. | 1828 | * mpi_ssp_completion- process the event that FW response to the SSP request. |
1712 | * @pm8001_ha: our hba card information | 1829 | * @pm8001_ha: our hba card information |
@@ -1941,7 +2058,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1941 | break; | 2058 | break; |
1942 | } | 2059 | } |
1943 | PM8001_IO_DBG(pm8001_ha, | 2060 | PM8001_IO_DBG(pm8001_ha, |
1944 | pm8001_printk("scsi_status = %x \n ", | 2061 | pm8001_printk("scsi_status = %x\n ", |
1945 | psspPayload->ssp_resp_iu.status)); | 2062 | psspPayload->ssp_resp_iu.status)); |
1946 | spin_lock_irqsave(&t->task_state_lock, flags); | 2063 | spin_lock_irqsave(&t->task_state_lock, flags); |
1947 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | 2064 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; |
@@ -2170,16 +2287,44 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2170 | status = le32_to_cpu(psataPayload->status); | 2287 | status = le32_to_cpu(psataPayload->status); |
2171 | tag = le32_to_cpu(psataPayload->tag); | 2288 | tag = le32_to_cpu(psataPayload->tag); |
2172 | 2289 | ||
2290 | if (!tag) { | ||
2291 | PM8001_FAIL_DBG(pm8001_ha, | ||
2292 | pm8001_printk("tag null\n")); | ||
2293 | return; | ||
2294 | } | ||
2173 | ccb = &pm8001_ha->ccb_info[tag]; | 2295 | ccb = &pm8001_ha->ccb_info[tag]; |
2174 | param = le32_to_cpu(psataPayload->param); | 2296 | 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 | |||
2176 | ts = &t->task_status; | 2322 | ts = &t->task_status; |
2177 | pm8001_dev = ccb->device; | 2323 | if (!ts) { |
2178 | if (status) | ||
2179 | PM8001_FAIL_DBG(pm8001_ha, | 2324 | PM8001_FAIL_DBG(pm8001_ha, |
2180 | pm8001_printk("sata IO status 0x%x\n", status)); | 2325 | pm8001_printk("ts null\n")); |
2181 | if (unlikely(!t || !t->lldd_task || !t->dev)) | ||
2182 | return; | 2326 | return; |
2327 | } | ||
2183 | 2328 | ||
2184 | switch (status) { | 2329 | switch (status) { |
2185 | case IO_SUCCESS: | 2330 | case IO_SUCCESS: |
@@ -2187,6 +2332,19 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2187 | if (param == 0) { | 2332 | if (param == 0) { |
2188 | ts->resp = SAS_TASK_COMPLETE; | 2333 | ts->resp = SAS_TASK_COMPLETE; |
2189 | ts->stat = SAM_STAT_GOOD; | 2334 | 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 | } | ||
2190 | } else { | 2348 | } else { |
2191 | u8 len; | 2349 | u8 len; |
2192 | ts->resp = SAS_TASK_COMPLETE; | 2350 | ts->resp = SAS_TASK_COMPLETE; |
@@ -2498,6 +2656,29 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
2498 | unsigned long flags; | 2656 | unsigned long flags; |
2499 | 2657 | ||
2500 | ccb = &pm8001_ha->ccb_info[tag]; | 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 | |||
2681 | ccb = &pm8001_ha->ccb_info[tag]; | ||
2501 | t = ccb->task; | 2682 | t = ccb->task; |
2502 | pm8001_dev = ccb->device; | 2683 | pm8001_dev = ccb->device; |
2503 | if (event) | 2684 | if (event) |
@@ -3512,19 +3693,29 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
3512 | u32 status ; | 3693 | u32 status ; |
3513 | u32 tag, scp; | 3694 | u32 tag, scp; |
3514 | struct task_status_struct *ts; | 3695 | struct task_status_struct *ts; |
3696 | struct pm8001_device *pm8001_dev; | ||
3515 | 3697 | ||
3516 | struct task_abort_resp *pPayload = | 3698 | struct task_abort_resp *pPayload = |
3517 | (struct task_abort_resp *)(piomb + 4); | 3699 | (struct task_abort_resp *)(piomb + 4); |
3518 | 3700 | ||
3519 | status = le32_to_cpu(pPayload->status); | 3701 | status = le32_to_cpu(pPayload->status); |
3520 | tag = le32_to_cpu(pPayload->tag); | 3702 | 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 | |||
3521 | scp = le32_to_cpu(pPayload->scp); | 3709 | scp = le32_to_cpu(pPayload->scp); |
3522 | ccb = &pm8001_ha->ccb_info[tag]; | 3710 | ccb = &pm8001_ha->ccb_info[tag]; |
3523 | t = ccb->task; | 3711 | t = ccb->task; |
3524 | PM8001_IO_DBG(pm8001_ha, | 3712 | pm8001_dev = ccb->device; /* retrieve device */ |
3525 | pm8001_printk(" status = 0x%x\n", status)); | 3713 | |
3526 | if (t == NULL) | 3714 | if (!t) { |
3715 | PM8001_FAIL_DBG(pm8001_ha, | ||
3716 | pm8001_printk(" TASK NULL. RETURNING !!!")); | ||
3527 | return -1; | 3717 | return -1; |
3718 | } | ||
3528 | ts = &t->task_status; | 3719 | ts = &t->task_status; |
3529 | if (status != 0) | 3720 | if (status != 0) |
3530 | PM8001_FAIL_DBG(pm8001_ha, | 3721 | PM8001_FAIL_DBG(pm8001_ha, |
@@ -3548,7 +3739,15 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
3548 | spin_unlock_irqrestore(&t->task_state_lock, flags); | 3739 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
3549 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 3740 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
3550 | mb(); | 3741 | 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 | |||
3552 | return 0; | 3751 | return 0; |
3553 | } | 3752 | } |
3554 | 3753 | ||
@@ -4133,6 +4332,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
4133 | u32 ATAP = 0x0; | 4332 | u32 ATAP = 0x0; |
4134 | u32 dir; | 4333 | u32 dir; |
4135 | struct inbound_queue_table *circularQ; | 4334 | struct inbound_queue_table *circularQ; |
4335 | unsigned long flags; | ||
4136 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | 4336 | u32 opc = OPC_INB_SATA_HOST_OPSTART; |
4137 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | 4337 | memset(&sata_cmd, 0, sizeof(sata_cmd)); |
4138 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4338 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
@@ -4153,8 +4353,10 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
4153 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); | 4353 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); |
4154 | } | 4354 | } |
4155 | } | 4355 | } |
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); | ||
4157 | ncg_tag = hdr_tag; | 4358 | ncg_tag = hdr_tag; |
4359 | } | ||
4158 | dir = data_dir_flags[task->data_dir] << 8; | 4360 | dir = data_dir_flags[task->data_dir] << 8; |
4159 | sata_cmd.tag = cpu_to_le32(tag); | 4361 | sata_cmd.tag = cpu_to_le32(tag); |
4160 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | 4362 | 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, | |||
4185 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); | 4387 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); |
4186 | sata_cmd.esgl = 0; | 4388 | sata_cmd.esgl = 0; |
4187 | } | 4389 | } |
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 | |||
4188 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); | 4438 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); |
4189 | return ret; | 4439 | return ret; |
4190 | } | 4440 | } |
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 6bba59c7d657..c720917d1388 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
@@ -68,7 +68,7 @@ static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag) | |||
68 | clear_bit(tag, bitmap); | 68 | clear_bit(tag, bitmap); |
69 | } | 69 | } |
70 | 70 | ||
71 | static void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) | 71 | void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) |
72 | { | 72 | { |
73 | pm8001_tag_clear(pm8001_ha, tag); | 73 | pm8001_tag_clear(pm8001_ha, tag); |
74 | } | 74 | } |
@@ -565,6 +565,24 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha) | |||
565 | } | 565 | } |
566 | return NULL; | 566 | return NULL; |
567 | } | 567 | } |
568 | /** | ||
569 | * pm8001_find_dev - find a matching pm8001_device | ||
570 | * @pm8001_ha: our hba card information | ||
571 | */ | ||
572 | struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | ||
573 | u32 device_id) | ||
574 | { | ||
575 | u32 dev; | ||
576 | for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) { | ||
577 | if (pm8001_ha->devices[dev].device_id == device_id) | ||
578 | return &pm8001_ha->devices[dev]; | ||
579 | } | ||
580 | if (dev == PM8001_MAX_DEVICES) { | ||
581 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("NO MATCHING " | ||
582 | "DEVICE FOUND !!!\n")); | ||
583 | } | ||
584 | return NULL; | ||
585 | } | ||
568 | 586 | ||
569 | static void pm8001_free_dev(struct pm8001_device *pm8001_dev) | 587 | static void pm8001_free_dev(struct pm8001_device *pm8001_dev) |
570 | { | 588 | { |
@@ -653,7 +671,7 @@ int pm8001_dev_found(struct domain_device *dev) | |||
653 | return pm8001_dev_found_notify(dev); | 671 | return pm8001_dev_found_notify(dev); |
654 | } | 672 | } |
655 | 673 | ||
656 | static void pm8001_task_done(struct sas_task *task) | 674 | void pm8001_task_done(struct sas_task *task) |
657 | { | 675 | { |
658 | if (!del_timer(&task->slow_task->timer)) | 676 | if (!del_timer(&task->slow_task->timer)) |
659 | return; | 677 | return; |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 89dc2273623e..ab30193f235f 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
@@ -321,7 +321,9 @@ union main_cfg_table { | |||
321 | u32 inbound_queue_offset; | 321 | u32 inbound_queue_offset; |
322 | u32 outbound_queue_offset; | 322 | u32 outbound_queue_offset; |
323 | u32 inbound_q_nppd_hppd; | 323 | u32 inbound_q_nppd_hppd; |
324 | u32 rsvd[10]; | 324 | u32 rsvd[8]; |
325 | u32 crc_core_dump; | ||
326 | u32 rsvd1; | ||
325 | u32 upper_event_log_addr; | 327 | u32 upper_event_log_addr; |
326 | u32 lower_event_log_addr; | 328 | u32 lower_event_log_addr; |
327 | u32 event_log_size; | 329 | u32 event_log_size; |
@@ -493,6 +495,9 @@ struct pm8001_fw_image_header { | |||
493 | #define FLASH_UPDATE_DNLD_NOT_SUPPORTED 0x10 | 495 | #define FLASH_UPDATE_DNLD_NOT_SUPPORTED 0x10 |
494 | #define FLASH_UPDATE_DISABLED 0x11 | 496 | #define FLASH_UPDATE_DISABLED 0x11 |
495 | 497 | ||
498 | #define NCQ_READ_LOG_FLAG 0x80000000 | ||
499 | #define NCQ_ABORT_ALL_FLAG 0x40000000 | ||
500 | #define NCQ_2ND_RLE_FLAG 0x20000000 | ||
496 | /** | 501 | /** |
497 | * brief param structure for firmware flash update. | 502 | * brief param structure for firmware flash update. |
498 | */ | 503 | */ |
@@ -567,7 +572,6 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, | |||
567 | dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo, | 572 | dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo, |
568 | u32 mem_size, u32 align); | 573 | u32 mem_size, u32 align); |
569 | 574 | ||
570 | /********** functions common to spc & spcv - begins ************/ | ||
571 | void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha); | 575 | void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha); |
572 | int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, | 576 | int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, |
573 | struct inbound_queue_table *circularQ, | 577 | struct inbound_queue_table *circularQ, |
@@ -615,7 +619,12 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, | |||
615 | void *piomb); | 619 | void *piomb); |
616 | int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb); | 620 | int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb); |
617 | int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); | 621 | int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); |
618 | /*********** functions common to spc & spcv - ends ************/ | 622 | struct sas_task *pm8001_alloc_task(void); |
623 | void pm8001_task_done(struct sas_task *task); | ||
624 | void pm8001_free_task(struct sas_task *task); | ||
625 | void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag); | ||
626 | struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | ||
627 | u32 device_id); | ||
619 | 628 | ||
620 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 629 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
621 | 630 | ||
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 7dee46716a58..f0dbe79b049c 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
@@ -270,6 +270,9 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) | |||
270 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01; | 270 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01; |
271 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01; | 271 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01; |
272 | 272 | ||
273 | /* Disable end to end CRC checking */ | ||
274 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16); | ||
275 | |||
273 | for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { | 276 | for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { |
274 | pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = | 277 | pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = |
275 | PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30); | 278 | PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30); |
@@ -353,6 +356,8 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) | |||
353 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity); | 356 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity); |
354 | pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, | 357 | pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, |
355 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); | 358 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); |
359 | pm8001_mw32(address, MAIN_EVENT_CRC_CHECK, | ||
360 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump); | ||
356 | 361 | ||
357 | /* SPCv specific */ | 362 | /* SPCv specific */ |
358 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping &= 0xCFFFFFFF; | 363 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping &= 0xCFFFFFFF; |
@@ -1026,6 +1031,123 @@ pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec) | |||
1026 | pm80xx_chip_intx_interrupt_disable(pm8001_ha); | 1031 | pm80xx_chip_intx_interrupt_disable(pm8001_ha); |
1027 | } | 1032 | } |
1028 | 1033 | ||
1034 | static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, | ||
1035 | struct pm8001_device *pm8001_ha_dev) | ||
1036 | { | ||
1037 | int res; | ||
1038 | u32 ccb_tag; | ||
1039 | struct pm8001_ccb_info *ccb; | ||
1040 | struct sas_task *task = NULL; | ||
1041 | struct task_abort_req task_abort; | ||
1042 | struct inbound_queue_table *circularQ; | ||
1043 | u32 opc = OPC_INB_SATA_ABORT; | ||
1044 | int ret; | ||
1045 | |||
1046 | if (!pm8001_ha_dev) { | ||
1047 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n")); | ||
1048 | return; | ||
1049 | } | ||
1050 | |||
1051 | task = sas_alloc_slow_task(GFP_ATOMIC); | ||
1052 | |||
1053 | if (!task) { | ||
1054 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot " | ||
1055 | "allocate task\n")); | ||
1056 | return; | ||
1057 | } | ||
1058 | |||
1059 | task->task_done = pm8001_task_done; | ||
1060 | |||
1061 | res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); | ||
1062 | if (res) | ||
1063 | return; | ||
1064 | |||
1065 | ccb = &pm8001_ha->ccb_info[ccb_tag]; | ||
1066 | ccb->device = pm8001_ha_dev; | ||
1067 | ccb->ccb_tag = ccb_tag; | ||
1068 | ccb->task = task; | ||
1069 | |||
1070 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
1071 | |||
1072 | memset(&task_abort, 0, sizeof(task_abort)); | ||
1073 | task_abort.abort_all = cpu_to_le32(1); | ||
1074 | task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | ||
1075 | task_abort.tag = cpu_to_le32(ccb_tag); | ||
1076 | |||
1077 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); | ||
1078 | |||
1079 | } | ||
1080 | |||
1081 | static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, | ||
1082 | struct pm8001_device *pm8001_ha_dev) | ||
1083 | { | ||
1084 | struct sata_start_req sata_cmd; | ||
1085 | int res; | ||
1086 | u32 ccb_tag; | ||
1087 | struct pm8001_ccb_info *ccb; | ||
1088 | struct sas_task *task = NULL; | ||
1089 | struct host_to_dev_fis fis; | ||
1090 | struct domain_device *dev; | ||
1091 | struct inbound_queue_table *circularQ; | ||
1092 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | ||
1093 | |||
1094 | task = sas_alloc_slow_task(GFP_ATOMIC); | ||
1095 | |||
1096 | if (!task) { | ||
1097 | PM8001_FAIL_DBG(pm8001_ha, | ||
1098 | pm8001_printk("cannot allocate task !!!\n")); | ||
1099 | return; | ||
1100 | } | ||
1101 | task->task_done = pm8001_task_done; | ||
1102 | |||
1103 | res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); | ||
1104 | if (res) { | ||
1105 | PM8001_FAIL_DBG(pm8001_ha, | ||
1106 | pm8001_printk("cannot allocate tag !!!\n")); | ||
1107 | return; | ||
1108 | } | ||
1109 | |||
1110 | /* allocate domain device by ourselves as libsas | ||
1111 | * is not going to provide any | ||
1112 | */ | ||
1113 | dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); | ||
1114 | if (!dev) { | ||
1115 | PM8001_FAIL_DBG(pm8001_ha, | ||
1116 | pm8001_printk("Domain device cannot be allocated\n")); | ||
1117 | sas_free_task(task); | ||
1118 | return; | ||
1119 | } else { | ||
1120 | task->dev = dev; | ||
1121 | task->dev->lldd_dev = pm8001_ha_dev; | ||
1122 | } | ||
1123 | |||
1124 | ccb = &pm8001_ha->ccb_info[ccb_tag]; | ||
1125 | ccb->device = pm8001_ha_dev; | ||
1126 | ccb->ccb_tag = ccb_tag; | ||
1127 | ccb->task = task; | ||
1128 | pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG; | ||
1129 | pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG; | ||
1130 | |||
1131 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | ||
1132 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
1133 | |||
1134 | /* construct read log FIS */ | ||
1135 | memset(&fis, 0, sizeof(struct host_to_dev_fis)); | ||
1136 | fis.fis_type = 0x27; | ||
1137 | fis.flags = 0x80; | ||
1138 | fis.command = ATA_CMD_READ_LOG_EXT; | ||
1139 | fis.lbal = 0x10; | ||
1140 | fis.sector_count = 0x1; | ||
1141 | |||
1142 | sata_cmd.tag = cpu_to_le32(ccb_tag); | ||
1143 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | ||
1144 | sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9)); | ||
1145 | memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); | ||
1146 | |||
1147 | res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); | ||
1148 | |||
1149 | } | ||
1150 | |||
1029 | /** | 1151 | /** |
1030 | * mpi_ssp_completion- process the event that FW response to the SSP request. | 1152 | * mpi_ssp_completion- process the event that FW response to the SSP request. |
1031 | * @pm8001_ha: our hba card information | 1153 | * @pm8001_ha: our hba card information |
@@ -1480,22 +1602,50 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1480 | struct ata_task_resp *resp ; | 1602 | struct ata_task_resp *resp ; |
1481 | u32 *sata_resp; | 1603 | u32 *sata_resp; |
1482 | struct pm8001_device *pm8001_dev; | 1604 | struct pm8001_device *pm8001_dev; |
1483 | unsigned long flags = 0; | 1605 | unsigned long flags; |
1484 | 1606 | ||
1485 | psataPayload = (struct sata_completion_resp *)(piomb + 4); | 1607 | psataPayload = (struct sata_completion_resp *)(piomb + 4); |
1486 | status = le32_to_cpu(psataPayload->status); | 1608 | status = le32_to_cpu(psataPayload->status); |
1487 | tag = le32_to_cpu(psataPayload->tag); | 1609 | tag = le32_to_cpu(psataPayload->tag); |
1488 | 1610 | ||
1611 | if (!tag) { | ||
1612 | PM8001_FAIL_DBG(pm8001_ha, | ||
1613 | pm8001_printk("tag null\n")); | ||
1614 | return; | ||
1615 | } | ||
1489 | ccb = &pm8001_ha->ccb_info[tag]; | 1616 | ccb = &pm8001_ha->ccb_info[tag]; |
1490 | param = le32_to_cpu(psataPayload->param); | 1617 | param = le32_to_cpu(psataPayload->param); |
1491 | t = ccb->task; | 1618 | if (ccb) { |
1619 | t = ccb->task; | ||
1620 | pm8001_dev = ccb->device; | ||
1621 | } else { | ||
1622 | PM8001_FAIL_DBG(pm8001_ha, | ||
1623 | pm8001_printk("ccb null\n")); | ||
1624 | return; | ||
1625 | } | ||
1626 | |||
1627 | if (t) { | ||
1628 | if (t->dev && (t->dev->lldd_dev)) | ||
1629 | pm8001_dev = t->dev->lldd_dev; | ||
1630 | } else { | ||
1631 | PM8001_FAIL_DBG(pm8001_ha, | ||
1632 | pm8001_printk("task null\n")); | ||
1633 | return; | ||
1634 | } | ||
1635 | |||
1636 | if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG)) | ||
1637 | && unlikely(!t || !t->lldd_task || !t->dev)) { | ||
1638 | PM8001_FAIL_DBG(pm8001_ha, | ||
1639 | pm8001_printk("task or dev null\n")); | ||
1640 | return; | ||
1641 | } | ||
1642 | |||
1492 | ts = &t->task_status; | 1643 | ts = &t->task_status; |
1493 | pm8001_dev = ccb->device; | 1644 | if (!ts) { |
1494 | if (status) | ||
1495 | PM8001_FAIL_DBG(pm8001_ha, | 1645 | PM8001_FAIL_DBG(pm8001_ha, |
1496 | pm8001_printk("sata IO status 0x%x\n", status)); | 1646 | pm8001_printk("ts null\n")); |
1497 | if (unlikely(!t || !t->lldd_task || !t->dev)) | ||
1498 | return; | 1647 | return; |
1648 | } | ||
1499 | 1649 | ||
1500 | switch (status) { | 1650 | switch (status) { |
1501 | case IO_SUCCESS: | 1651 | case IO_SUCCESS: |
@@ -1503,6 +1653,19 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1503 | if (param == 0) { | 1653 | if (param == 0) { |
1504 | ts->resp = SAS_TASK_COMPLETE; | 1654 | ts->resp = SAS_TASK_COMPLETE; |
1505 | ts->stat = SAM_STAT_GOOD; | 1655 | ts->stat = SAM_STAT_GOOD; |
1656 | /* check if response is for SEND READ LOG */ | ||
1657 | if (pm8001_dev && | ||
1658 | (pm8001_dev->id & NCQ_READ_LOG_FLAG)) { | ||
1659 | /* set new bit for abort_all */ | ||
1660 | pm8001_dev->id |= NCQ_ABORT_ALL_FLAG; | ||
1661 | /* clear bit for read log */ | ||
1662 | pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF; | ||
1663 | pm80xx_send_abort_all(pm8001_ha, pm8001_dev); | ||
1664 | /* Free the tag */ | ||
1665 | pm8001_tag_free(pm8001_ha, tag); | ||
1666 | sas_free_task(t); | ||
1667 | return; | ||
1668 | } | ||
1506 | } else { | 1669 | } else { |
1507 | u8 len; | 1670 | u8 len; |
1508 | ts->resp = SAS_TASK_COMPLETE; | 1671 | ts->resp = SAS_TASK_COMPLETE; |
@@ -1807,16 +1970,39 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1807 | u32 event = le32_to_cpu(psataPayload->event); | 1970 | u32 event = le32_to_cpu(psataPayload->event); |
1808 | u32 tag = le32_to_cpu(psataPayload->tag); | 1971 | u32 tag = le32_to_cpu(psataPayload->tag); |
1809 | u32 port_id = le32_to_cpu(psataPayload->port_id); | 1972 | u32 port_id = le32_to_cpu(psataPayload->port_id); |
1810 | unsigned long flags = 0; | 1973 | u32 dev_id = le32_to_cpu(psataPayload->device_id); |
1974 | unsigned long flags; | ||
1811 | 1975 | ||
1812 | ccb = &pm8001_ha->ccb_info[tag]; | 1976 | ccb = &pm8001_ha->ccb_info[tag]; |
1813 | t = ccb->task; | 1977 | |
1814 | pm8001_dev = ccb->device; | 1978 | if (ccb) { |
1979 | t = ccb->task; | ||
1980 | pm8001_dev = ccb->device; | ||
1981 | } else { | ||
1982 | PM8001_FAIL_DBG(pm8001_ha, | ||
1983 | pm8001_printk("No CCB !!!. returning\n")); | ||
1984 | return; | ||
1985 | } | ||
1815 | if (event) | 1986 | if (event) |
1816 | PM8001_FAIL_DBG(pm8001_ha, | 1987 | PM8001_FAIL_DBG(pm8001_ha, |
1817 | pm8001_printk("sata IO status 0x%x\n", event)); | 1988 | pm8001_printk("SATA EVENT 0x%x\n", event)); |
1818 | if (unlikely(!t || !t->lldd_task || !t->dev)) | 1989 | |
1990 | /* Check if this is NCQ error */ | ||
1991 | if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) { | ||
1992 | /* find device using device id */ | ||
1993 | pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id); | ||
1994 | /* send read log extension */ | ||
1995 | if (pm8001_dev) | ||
1996 | pm80xx_send_read_log(pm8001_ha, pm8001_dev); | ||
1997 | return; | ||
1998 | } | ||
1999 | |||
2000 | if (unlikely(!t || !t->lldd_task || !t->dev)) { | ||
2001 | PM8001_FAIL_DBG(pm8001_ha, | ||
2002 | pm8001_printk("task or dev null\n")); | ||
1819 | return; | 2003 | return; |
2004 | } | ||
2005 | |||
1820 | ts = &t->task_status; | 2006 | ts = &t->task_status; |
1821 | PM8001_IO_DBG(pm8001_ha, | 2007 | PM8001_IO_DBG(pm8001_ha, |
1822 | pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", | 2008 | pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", |
@@ -3414,6 +3600,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3414 | u32 ATAP = 0x0; | 3600 | u32 ATAP = 0x0; |
3415 | u32 dir; | 3601 | u32 dir; |
3416 | struct inbound_queue_table *circularQ; | 3602 | struct inbound_queue_table *circularQ; |
3603 | unsigned long flags; | ||
3417 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | 3604 | u32 opc = OPC_INB_SATA_HOST_OPSTART; |
3418 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | 3605 | memset(&sata_cmd, 0, sizeof(sata_cmd)); |
3419 | circularQ = &pm8001_ha->inbnd_q_tbl[inb++]; | 3606 | circularQ = &pm8001_ha->inbnd_q_tbl[inb++]; |
@@ -3438,8 +3625,10 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3438 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); | 3625 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); |
3439 | } | 3626 | } |
3440 | } | 3627 | } |
3441 | if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) | 3628 | if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) { |
3629 | task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3); | ||
3442 | ncg_tag = hdr_tag; | 3630 | ncg_tag = hdr_tag; |
3631 | } | ||
3443 | dir = data_dir_flags[task->data_dir] << 8; | 3632 | dir = data_dir_flags[task->data_dir] << 8; |
3444 | sata_cmd.tag = cpu_to_le32(tag); | 3633 | sata_cmd.tag = cpu_to_le32(tag); |
3445 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | 3634 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); |
@@ -3547,6 +3736,55 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3547 | (task->ata_task.atapi_packet[14] << 16) | | 3736 | (task->ata_task.atapi_packet[14] << 16) | |
3548 | (task->ata_task.atapi_packet[15] << 24))); | 3737 | (task->ata_task.atapi_packet[15] << 24))); |
3549 | } | 3738 | } |
3739 | |||
3740 | /* Check for read log for failed drive and return */ | ||
3741 | if (sata_cmd.sata_fis.command == 0x2f) { | ||
3742 | if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) || | ||
3743 | (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) || | ||
3744 | (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) { | ||
3745 | struct task_status_struct *ts; | ||
3746 | |||
3747 | pm8001_ha_dev->id &= 0xDFFFFFFF; | ||
3748 | ts = &task->task_status; | ||
3749 | |||
3750 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
3751 | ts->resp = SAS_TASK_COMPLETE; | ||
3752 | ts->stat = SAM_STAT_GOOD; | ||
3753 | task->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
3754 | task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
3755 | task->task_state_flags |= SAS_TASK_STATE_DONE; | ||
3756 | if (unlikely((task->task_state_flags & | ||
3757 | SAS_TASK_STATE_ABORTED))) { | ||
3758 | spin_unlock_irqrestore(&task->task_state_lock, | ||
3759 | flags); | ||
3760 | PM8001_FAIL_DBG(pm8001_ha, | ||
3761 | pm8001_printk("task 0x%p resp 0x%x " | ||
3762 | " stat 0x%x but aborted by upper layer " | ||
3763 | "\n", task, ts->resp, ts->stat)); | ||
3764 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
3765 | return 0; | ||
3766 | } else if (task->uldd_task) { | ||
3767 | spin_unlock_irqrestore(&task->task_state_lock, | ||
3768 | flags); | ||
3769 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
3770 | mb();/* ditto */ | ||
3771 | spin_unlock_irq(&pm8001_ha->lock); | ||
3772 | task->task_done(task); | ||
3773 | spin_lock_irq(&pm8001_ha->lock); | ||
3774 | return 0; | ||
3775 | } else if (!task->uldd_task) { | ||
3776 | spin_unlock_irqrestore(&task->task_state_lock, | ||
3777 | flags); | ||
3778 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
3779 | mb();/*ditto*/ | ||
3780 | spin_unlock_irq(&pm8001_ha->lock); | ||
3781 | task->task_done(task); | ||
3782 | spin_lock_irq(&pm8001_ha->lock); | ||
3783 | return 0; | ||
3784 | } | ||
3785 | } | ||
3786 | } | ||
3787 | |||
3550 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | 3788 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, |
3551 | &sata_cmd, outb++); | 3789 | &sata_cmd, outb++); |
3552 | 3790 | ||
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index e281d71f897a..b7c864f16402 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h | |||
@@ -1278,6 +1278,7 @@ struct ssp_coalesced_comp_resp { | |||
1278 | #define MAIN_IQNPPD_HPPD_OFFSET 0x24 /* DWORD 0x09 */ | 1278 | #define MAIN_IQNPPD_HPPD_OFFSET 0x24 /* DWORD 0x09 */ |
1279 | 1279 | ||
1280 | /* 0x28 - 0x4C - RSVD */ | 1280 | /* 0x28 - 0x4C - RSVD */ |
1281 | #define MAIN_EVENT_CRC_CHECK 0x48 /* DWORD 0x12 */ | ||
1281 | #define MAIN_EVENT_LOG_ADDR_HI 0x50 /* DWORD 0x14 */ | 1282 | #define MAIN_EVENT_LOG_ADDR_HI 0x50 /* DWORD 0x14 */ |
1282 | #define MAIN_EVENT_LOG_ADDR_LO 0x54 /* DWORD 0x15 */ | 1283 | #define MAIN_EVENT_LOG_ADDR_LO 0x54 /* DWORD 0x15 */ |
1283 | #define MAIN_EVENT_LOG_BUFF_SIZE 0x58 /* DWORD 0x16 */ | 1284 | #define MAIN_EVENT_LOG_BUFF_SIZE 0x58 /* DWORD 0x16 */ |