diff options
Diffstat (limited to 'drivers/scsi/mvsas/mv_sas.c')
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 201 |
1 files changed, 133 insertions, 68 deletions
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 0d2138641214..f5e321791903 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c | |||
@@ -259,8 +259,6 @@ static inline void mvs_free_reg_set(struct mvs_info *mvi, | |||
259 | mv_printk("device has been free.\n"); | 259 | mv_printk("device has been free.\n"); |
260 | return; | 260 | return; |
261 | } | 261 | } |
262 | if (dev->runing_req != 0) | ||
263 | return; | ||
264 | if (dev->taskfileset == MVS_ID_NOT_MAPPED) | 262 | if (dev->taskfileset == MVS_ID_NOT_MAPPED) |
265 | return; | 263 | return; |
266 | MVS_CHIP_DISP->free_reg_set(mvi, &dev->taskfileset); | 264 | MVS_CHIP_DISP->free_reg_set(mvi, &dev->taskfileset); |
@@ -762,8 +760,6 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi, | |||
762 | } | 760 | } |
763 | if (is_tmf) | 761 | if (is_tmf) |
764 | flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT); | 762 | flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT); |
765 | else | ||
766 | flags |= (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT); | ||
767 | hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT)); | 763 | hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT)); |
768 | hdr->tags = cpu_to_le32(tag); | 764 | hdr->tags = cpu_to_le32(tag); |
769 | hdr->data_len = cpu_to_le32(task->total_xfer_len); | 765 | hdr->data_len = cpu_to_le32(task->total_xfer_len); |
@@ -878,14 +874,15 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, | |||
878 | struct mvs_slot_info *slot; | 874 | struct mvs_slot_info *slot; |
879 | u32 tag = 0xdeadbeef, rc, n_elem = 0; | 875 | u32 tag = 0xdeadbeef, rc, n_elem = 0; |
880 | u32 n = num, pass = 0; | 876 | u32 n = num, pass = 0; |
881 | unsigned long flags = 0; | 877 | unsigned long flags = 0, flags_libsas = 0; |
882 | 878 | ||
883 | if (!dev->port) { | 879 | if (!dev->port) { |
884 | struct task_status_struct *tsm = &t->task_status; | 880 | struct task_status_struct *tsm = &t->task_status; |
885 | 881 | ||
886 | tsm->resp = SAS_TASK_UNDELIVERED; | 882 | tsm->resp = SAS_TASK_UNDELIVERED; |
887 | tsm->stat = SAS_PHY_DOWN; | 883 | tsm->stat = SAS_PHY_DOWN; |
888 | t->task_done(t); | 884 | if (dev->dev_type != SATA_DEV) |
885 | t->task_done(t); | ||
889 | return 0; | 886 | return 0; |
890 | } | 887 | } |
891 | 888 | ||
@@ -910,12 +907,25 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, | |||
910 | else | 907 | else |
911 | tei.port = &mvi->port[dev->port->id]; | 908 | tei.port = &mvi->port[dev->port->id]; |
912 | 909 | ||
913 | if (!tei.port->port_attached) { | 910 | if (tei.port && !tei.port->port_attached) { |
914 | if (sas_protocol_ata(t->task_proto)) { | 911 | if (sas_protocol_ata(t->task_proto)) { |
912 | struct task_status_struct *ts = &t->task_status; | ||
913 | |||
915 | mv_dprintk("port %d does not" | 914 | mv_dprintk("port %d does not" |
916 | "attached device.\n", dev->port->id); | 915 | "attached device.\n", dev->port->id); |
917 | rc = SAS_PHY_DOWN; | 916 | ts->stat = SAS_PROTO_RESPONSE; |
918 | goto out_done; | 917 | ts->stat = SAS_PHY_DOWN; |
918 | spin_unlock_irqrestore(dev->sata_dev.ap->lock, | ||
919 | flags_libsas); | ||
920 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
921 | t->task_done(t); | ||
922 | spin_lock_irqsave(&mvi->lock, flags); | ||
923 | spin_lock_irqsave(dev->sata_dev.ap->lock, | ||
924 | flags_libsas); | ||
925 | if (n > 1) | ||
926 | t = list_entry(t->list.next, | ||
927 | struct sas_task, list); | ||
928 | continue; | ||
919 | } else { | 929 | } else { |
920 | struct task_status_struct *ts = &t->task_status; | 930 | struct task_status_struct *ts = &t->task_status; |
921 | ts->resp = SAS_TASK_UNDELIVERED; | 931 | ts->resp = SAS_TASK_UNDELIVERED; |
@@ -973,8 +983,8 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, | |||
973 | break; | 983 | break; |
974 | default: | 984 | default: |
975 | dev_printk(KERN_ERR, mvi->dev, | 985 | dev_printk(KERN_ERR, mvi->dev, |
976 | "unknown sas_task proto: 0x%x\n", | 986 | "unknown sas_task proto: 0x%x\n", |
977 | t->task_proto); | 987 | t->task_proto); |
978 | rc = -EINVAL; | 988 | rc = -EINVAL; |
979 | break; | 989 | break; |
980 | } | 990 | } |
@@ -993,11 +1003,15 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, | |||
993 | spin_unlock(&t->task_state_lock); | 1003 | spin_unlock(&t->task_state_lock); |
994 | 1004 | ||
995 | mvs_hba_memory_dump(mvi, tag, t->task_proto); | 1005 | mvs_hba_memory_dump(mvi, tag, t->task_proto); |
996 | mvi_dev->runing_req++; | 1006 | mvi_dev->running_req++; |
997 | ++pass; | 1007 | ++pass; |
998 | mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); | 1008 | mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); |
999 | if (n > 1) | 1009 | if (n > 1) |
1000 | t = list_entry(t->list.next, struct sas_task, list); | 1010 | t = list_entry(t->list.next, struct sas_task, list); |
1011 | if (likely(pass)) | ||
1012 | MVS_CHIP_DISP->start_delivery(mvi, (mvi->tx_prod - 1) & | ||
1013 | (MVS_CHIP_SLOT_SZ - 1)); | ||
1014 | |||
1001 | } while (--n); | 1015 | } while (--n); |
1002 | rc = 0; | 1016 | rc = 0; |
1003 | goto out_done; | 1017 | goto out_done; |
@@ -1012,10 +1026,6 @@ err_out: | |||
1012 | dma_unmap_sg(mvi->dev, t->scatter, n_elem, | 1026 | dma_unmap_sg(mvi->dev, t->scatter, n_elem, |
1013 | t->data_dir); | 1027 | t->data_dir); |
1014 | out_done: | 1028 | out_done: |
1015 | if (likely(pass)) { | ||
1016 | MVS_CHIP_DISP->start_delivery(mvi, | ||
1017 | (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); | ||
1018 | } | ||
1019 | spin_unlock_irqrestore(&mvi->lock, flags); | 1029 | spin_unlock_irqrestore(&mvi->lock, flags); |
1020 | return rc; | 1030 | return rc; |
1021 | } | 1031 | } |
@@ -1187,7 +1197,7 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st) | |||
1187 | MVS_CHIP_DISP->phy_reset(mvi, i, 0); | 1197 | MVS_CHIP_DISP->phy_reset(mvi, i, 0); |
1188 | goto out_done; | 1198 | goto out_done; |
1189 | } | 1199 | } |
1190 | } else if (phy->phy_type & PORT_TYPE_SAS | 1200 | } else if (phy->phy_type & PORT_TYPE_SAS |
1191 | || phy->att_dev_info & PORT_SSP_INIT_MASK) { | 1201 | || phy->att_dev_info & PORT_SSP_INIT_MASK) { |
1192 | phy->phy_attached = 1; | 1202 | phy->phy_attached = 1; |
1193 | phy->identify.device_type = | 1203 | phy->identify.device_type = |
@@ -1256,7 +1266,20 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock) | |||
1256 | 1266 | ||
1257 | static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock) | 1267 | static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock) |
1258 | { | 1268 | { |
1259 | /*Nothing*/ | 1269 | struct domain_device *dev; |
1270 | struct mvs_phy *phy = sas_phy->lldd_phy; | ||
1271 | struct mvs_info *mvi = phy->mvi; | ||
1272 | struct asd_sas_port *port = sas_phy->port; | ||
1273 | int phy_no = 0; | ||
1274 | |||
1275 | while (phy != &mvi->phy[phy_no]) { | ||
1276 | phy_no++; | ||
1277 | if (phy_no >= MVS_MAX_PHYS) | ||
1278 | return; | ||
1279 | } | ||
1280 | list_for_each_entry(dev, &port->dev_list, dev_list_node) | ||
1281 | mvs_do_release_task(phy->mvi, phy_no, NULL); | ||
1282 | |||
1260 | } | 1283 | } |
1261 | 1284 | ||
1262 | 1285 | ||
@@ -1316,6 +1339,7 @@ int mvs_dev_found_notify(struct domain_device *dev, int lock) | |||
1316 | goto found_out; | 1339 | goto found_out; |
1317 | } | 1340 | } |
1318 | dev->lldd_dev = mvi_device; | 1341 | dev->lldd_dev = mvi_device; |
1342 | mvi_device->dev_status = MVS_DEV_NORMAL; | ||
1319 | mvi_device->dev_type = dev->dev_type; | 1343 | mvi_device->dev_type = dev->dev_type; |
1320 | mvi_device->mvi_info = mvi; | 1344 | mvi_device->mvi_info = mvi; |
1321 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { | 1345 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { |
@@ -1351,18 +1375,18 @@ int mvs_dev_found(struct domain_device *dev) | |||
1351 | return mvs_dev_found_notify(dev, 1); | 1375 | return mvs_dev_found_notify(dev, 1); |
1352 | } | 1376 | } |
1353 | 1377 | ||
1354 | void mvs_dev_gone_notify(struct domain_device *dev, int lock) | 1378 | void mvs_dev_gone_notify(struct domain_device *dev) |
1355 | { | 1379 | { |
1356 | unsigned long flags = 0; | 1380 | unsigned long flags = 0; |
1357 | struct mvs_device *mvi_dev = dev->lldd_dev; | 1381 | struct mvs_device *mvi_dev = dev->lldd_dev; |
1358 | struct mvs_info *mvi = mvi_dev->mvi_info; | 1382 | struct mvs_info *mvi = mvi_dev->mvi_info; |
1359 | 1383 | ||
1360 | if (lock) | 1384 | spin_lock_irqsave(&mvi->lock, flags); |
1361 | spin_lock_irqsave(&mvi->lock, flags); | ||
1362 | 1385 | ||
1363 | if (mvi_dev) { | 1386 | if (mvi_dev) { |
1364 | mv_dprintk("found dev[%d:%x] is gone.\n", | 1387 | mv_dprintk("found dev[%d:%x] is gone.\n", |
1365 | mvi_dev->device_id, mvi_dev->dev_type); | 1388 | mvi_dev->device_id, mvi_dev->dev_type); |
1389 | mvs_release_task(mvi, dev); | ||
1366 | mvs_free_reg_set(mvi, mvi_dev); | 1390 | mvs_free_reg_set(mvi, mvi_dev); |
1367 | mvs_free_dev(mvi_dev); | 1391 | mvs_free_dev(mvi_dev); |
1368 | } else { | 1392 | } else { |
@@ -1370,14 +1394,13 @@ void mvs_dev_gone_notify(struct domain_device *dev, int lock) | |||
1370 | } | 1394 | } |
1371 | dev->lldd_dev = NULL; | 1395 | dev->lldd_dev = NULL; |
1372 | 1396 | ||
1373 | if (lock) | 1397 | spin_unlock_irqrestore(&mvi->lock, flags); |
1374 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1375 | } | 1398 | } |
1376 | 1399 | ||
1377 | 1400 | ||
1378 | void mvs_dev_gone(struct domain_device *dev) | 1401 | void mvs_dev_gone(struct domain_device *dev) |
1379 | { | 1402 | { |
1380 | mvs_dev_gone_notify(dev, 1); | 1403 | mvs_dev_gone_notify(dev); |
1381 | } | 1404 | } |
1382 | 1405 | ||
1383 | static struct sas_task *mvs_alloc_task(void) | 1406 | static struct sas_task *mvs_alloc_task(void) |
@@ -1540,7 +1563,7 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun) | |||
1540 | num = mvs_find_dev_phyno(dev, phyno); | 1563 | num = mvs_find_dev_phyno(dev, phyno); |
1541 | spin_lock_irqsave(&mvi->lock, flags); | 1564 | spin_lock_irqsave(&mvi->lock, flags); |
1542 | for (i = 0; i < num; i++) | 1565 | for (i = 0; i < num; i++) |
1543 | mvs_release_task(mvi, phyno[i], dev); | 1566 | mvs_release_task(mvi, dev); |
1544 | spin_unlock_irqrestore(&mvi->lock, flags); | 1567 | spin_unlock_irqrestore(&mvi->lock, flags); |
1545 | } | 1568 | } |
1546 | /* If failed, fall-through I_T_Nexus reset */ | 1569 | /* If failed, fall-through I_T_Nexus reset */ |
@@ -1552,8 +1575,8 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun) | |||
1552 | int mvs_I_T_nexus_reset(struct domain_device *dev) | 1575 | int mvs_I_T_nexus_reset(struct domain_device *dev) |
1553 | { | 1576 | { |
1554 | unsigned long flags; | 1577 | unsigned long flags; |
1555 | int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED; | 1578 | int rc = TMF_RESP_FUNC_FAILED; |
1556 | struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev; | 1579 | struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev; |
1557 | struct mvs_info *mvi = mvi_dev->mvi_info; | 1580 | struct mvs_info *mvi = mvi_dev->mvi_info; |
1558 | 1581 | ||
1559 | if (mvi_dev->dev_status != MVS_DEV_EH) | 1582 | if (mvi_dev->dev_status != MVS_DEV_EH) |
@@ -1563,10 +1586,8 @@ int mvs_I_T_nexus_reset(struct domain_device *dev) | |||
1563 | __func__, mvi_dev->device_id, rc); | 1586 | __func__, mvi_dev->device_id, rc); |
1564 | 1587 | ||
1565 | /* housekeeper */ | 1588 | /* housekeeper */ |
1566 | num = mvs_find_dev_phyno(dev, phyno); | ||
1567 | spin_lock_irqsave(&mvi->lock, flags); | 1589 | spin_lock_irqsave(&mvi->lock, flags); |
1568 | for (i = 0; i < num; i++) | 1590 | mvs_release_task(mvi, dev); |
1569 | mvs_release_task(mvi, phyno[i], dev); | ||
1570 | spin_unlock_irqrestore(&mvi->lock, flags); | 1591 | spin_unlock_irqrestore(&mvi->lock, flags); |
1571 | 1592 | ||
1572 | return rc; | 1593 | return rc; |
@@ -1603,6 +1624,9 @@ int mvs_query_task(struct sas_task *task) | |||
1603 | case TMF_RESP_FUNC_FAILED: | 1624 | case TMF_RESP_FUNC_FAILED: |
1604 | case TMF_RESP_FUNC_COMPLETE: | 1625 | case TMF_RESP_FUNC_COMPLETE: |
1605 | break; | 1626 | break; |
1627 | default: | ||
1628 | rc = TMF_RESP_FUNC_COMPLETE; | ||
1629 | break; | ||
1606 | } | 1630 | } |
1607 | } | 1631 | } |
1608 | mv_printk("%s:rc= %d\n", __func__, rc); | 1632 | mv_printk("%s:rc= %d\n", __func__, rc); |
@@ -1621,8 +1645,11 @@ int mvs_abort_task(struct sas_task *task) | |||
1621 | unsigned long flags; | 1645 | unsigned long flags; |
1622 | u32 tag; | 1646 | u32 tag; |
1623 | 1647 | ||
1624 | if (mvi->exp_req) | 1648 | if (!mvi_dev) { |
1625 | mvi->exp_req--; | 1649 | mv_printk("%s:%d TMF_RESP_FUNC_FAILED\n", __func__, __LINE__); |
1650 | rc = TMF_RESP_FUNC_FAILED; | ||
1651 | } | ||
1652 | |||
1626 | spin_lock_irqsave(&task->task_state_lock, flags); | 1653 | spin_lock_irqsave(&task->task_state_lock, flags); |
1627 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { | 1654 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { |
1628 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 1655 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
@@ -1630,6 +1657,7 @@ int mvs_abort_task(struct sas_task *task) | |||
1630 | goto out; | 1657 | goto out; |
1631 | } | 1658 | } |
1632 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 1659 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
1660 | mvi_dev->dev_status = MVS_DEV_EH; | ||
1633 | if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { | 1661 | if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { |
1634 | struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; | 1662 | struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; |
1635 | 1663 | ||
@@ -1654,12 +1682,31 @@ int mvs_abort_task(struct sas_task *task) | |||
1654 | if (task->lldd_task) { | 1682 | if (task->lldd_task) { |
1655 | slot = task->lldd_task; | 1683 | slot = task->lldd_task; |
1656 | slot_no = (u32) (slot - mvi->slot_info); | 1684 | slot_no = (u32) (slot - mvi->slot_info); |
1685 | spin_lock_irqsave(&mvi->lock, flags); | ||
1657 | mvs_slot_complete(mvi, slot_no, 1); | 1686 | mvs_slot_complete(mvi, slot_no, 1); |
1687 | spin_unlock_irqrestore(&mvi->lock, flags); | ||
1658 | } | 1688 | } |
1659 | } | 1689 | } |
1690 | |||
1660 | } else if (task->task_proto & SAS_PROTOCOL_SATA || | 1691 | } else if (task->task_proto & SAS_PROTOCOL_SATA || |
1661 | task->task_proto & SAS_PROTOCOL_STP) { | 1692 | task->task_proto & SAS_PROTOCOL_STP) { |
1662 | /* to do free register_set */ | 1693 | /* to do free register_set */ |
1694 | if (SATA_DEV == dev->dev_type) { | ||
1695 | struct mvs_slot_info *slot = task->lldd_task; | ||
1696 | struct task_status_struct *tstat; | ||
1697 | u32 slot_idx = (u32)(slot - mvi->slot_info); | ||
1698 | tstat = &task->task_status; | ||
1699 | mv_dprintk(KERN_DEBUG "mv_abort_task() mvi=%p task=%p " | ||
1700 | "slot=%p slot_idx=x%x\n", | ||
1701 | mvi, task, slot, slot_idx); | ||
1702 | tstat->stat = SAS_ABORTED_TASK; | ||
1703 | if (mvi_dev && mvi_dev->running_req) | ||
1704 | mvi_dev->running_req--; | ||
1705 | if (sas_protocol_ata(task->task_proto)) | ||
1706 | mvs_free_reg_set(mvi, mvi_dev); | ||
1707 | mvs_slot_task_free(mvi, task, slot, slot_idx); | ||
1708 | return -1; | ||
1709 | } | ||
1663 | } else { | 1710 | } else { |
1664 | /* SMP */ | 1711 | /* SMP */ |
1665 | 1712 | ||
@@ -1717,8 +1764,13 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, | |||
1717 | SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset), | 1764 | SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset), |
1718 | sizeof(struct dev_to_host_fis)); | 1765 | sizeof(struct dev_to_host_fis)); |
1719 | tstat->buf_valid_size = sizeof(*resp); | 1766 | tstat->buf_valid_size = sizeof(*resp); |
1720 | if (unlikely(err)) | 1767 | if (unlikely(err)) { |
1721 | stat = SAS_PROTO_RESPONSE; | 1768 | if (unlikely(err & CMD_ISS_STPD)) |
1769 | stat = SAS_OPEN_REJECT; | ||
1770 | else | ||
1771 | stat = SAS_PROTO_RESPONSE; | ||
1772 | } | ||
1773 | |||
1722 | return stat; | 1774 | return stat; |
1723 | } | 1775 | } |
1724 | 1776 | ||
@@ -1753,9 +1805,7 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, | |||
1753 | mv_printk("find reserved error, why?\n"); | 1805 | mv_printk("find reserved error, why?\n"); |
1754 | 1806 | ||
1755 | task->ata_task.use_ncq = 0; | 1807 | task->ata_task.use_ncq = 0; |
1756 | stat = SAS_PROTO_RESPONSE; | 1808 | mvs_sata_done(mvi, task, slot_idx, err_dw0); |
1757 | mvs_sata_done(mvi, task, slot_idx, 1); | ||
1758 | |||
1759 | } | 1809 | } |
1760 | break; | 1810 | break; |
1761 | default: | 1811 | default: |
@@ -1772,18 +1822,20 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) | |||
1772 | struct sas_task *task = slot->task; | 1822 | struct sas_task *task = slot->task; |
1773 | struct mvs_device *mvi_dev = NULL; | 1823 | struct mvs_device *mvi_dev = NULL; |
1774 | struct task_status_struct *tstat; | 1824 | struct task_status_struct *tstat; |
1825 | struct domain_device *dev; | ||
1826 | u32 aborted; | ||
1775 | 1827 | ||
1776 | bool aborted; | ||
1777 | void *to; | 1828 | void *to; |
1778 | enum exec_status sts; | 1829 | enum exec_status sts; |
1779 | 1830 | ||
1780 | if (mvi->exp_req) | 1831 | if (mvi->exp_req) |
1781 | mvi->exp_req--; | 1832 | mvi->exp_req--; |
1782 | if (unlikely(!task || !task->lldd_task)) | 1833 | if (unlikely(!task || !task->lldd_task || !task->dev)) |
1783 | return -1; | 1834 | return -1; |
1784 | 1835 | ||
1785 | tstat = &task->task_status; | 1836 | tstat = &task->task_status; |
1786 | mvi_dev = task->dev->lldd_dev; | 1837 | dev = task->dev; |
1838 | mvi_dev = dev->lldd_dev; | ||
1787 | 1839 | ||
1788 | mvs_hba_cq_dump(mvi); | 1840 | mvs_hba_cq_dump(mvi); |
1789 | 1841 | ||
@@ -1800,8 +1852,8 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) | |||
1800 | 1852 | ||
1801 | if (unlikely(aborted)) { | 1853 | if (unlikely(aborted)) { |
1802 | tstat->stat = SAS_ABORTED_TASK; | 1854 | tstat->stat = SAS_ABORTED_TASK; |
1803 | if (mvi_dev) | 1855 | if (mvi_dev && mvi_dev->running_req) |
1804 | mvi_dev->runing_req--; | 1856 | mvi_dev->running_req--; |
1805 | if (sas_protocol_ata(task->task_proto)) | 1857 | if (sas_protocol_ata(task->task_proto)) |
1806 | mvs_free_reg_set(mvi, mvi_dev); | 1858 | mvs_free_reg_set(mvi, mvi_dev); |
1807 | 1859 | ||
@@ -1809,24 +1861,17 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) | |||
1809 | return -1; | 1861 | return -1; |
1810 | } | 1862 | } |
1811 | 1863 | ||
1812 | if (unlikely(!mvi_dev || !slot->port->port_attached || flags)) { | 1864 | if (unlikely(!mvi_dev || flags)) { |
1813 | mv_dprintk("port has not device.\n"); | 1865 | if (!mvi_dev) |
1866 | mv_dprintk("port has not device.\n"); | ||
1814 | tstat->stat = SAS_PHY_DOWN; | 1867 | tstat->stat = SAS_PHY_DOWN; |
1815 | goto out; | 1868 | goto out; |
1816 | } | 1869 | } |
1817 | 1870 | ||
1818 | /* | ||
1819 | if (unlikely((rx_desc & RXQ_ERR) || (*(u64 *) slot->response))) { | ||
1820 | mv_dprintk("Find device[%016llx] RXQ_ERR %X, | ||
1821 | err info:%016llx\n", | ||
1822 | SAS_ADDR(task->dev->sas_addr), | ||
1823 | rx_desc, (u64)(*(u64 *) slot->response)); | ||
1824 | } | ||
1825 | */ | ||
1826 | |||
1827 | /* error info record present */ | 1871 | /* error info record present */ |
1828 | if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) { | 1872 | if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) { |
1829 | tstat->stat = mvs_slot_err(mvi, task, slot_idx); | 1873 | tstat->stat = mvs_slot_err(mvi, task, slot_idx); |
1874 | tstat->resp = SAS_TASK_COMPLETE; | ||
1830 | goto out; | 1875 | goto out; |
1831 | } | 1876 | } |
1832 | 1877 | ||
@@ -1868,11 +1913,16 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) | |||
1868 | tstat->stat = SAM_CHECK_COND; | 1913 | tstat->stat = SAM_CHECK_COND; |
1869 | break; | 1914 | break; |
1870 | } | 1915 | } |
1916 | if (!slot->port->port_attached) { | ||
1917 | mv_dprintk("port %d has removed.\n", slot->port->sas_port.id); | ||
1918 | tstat->stat = SAS_PHY_DOWN; | ||
1919 | } | ||
1920 | |||
1871 | 1921 | ||
1872 | out: | 1922 | out: |
1873 | if (mvi_dev) { | 1923 | if (mvi_dev && mvi_dev->running_req) { |
1874 | mvi_dev->runing_req--; | 1924 | mvi_dev->running_req--; |
1875 | if (sas_protocol_ata(task->task_proto)) | 1925 | if (sas_protocol_ata(task->task_proto) && !mvi_dev->running_req) |
1876 | mvs_free_reg_set(mvi, mvi_dev); | 1926 | mvs_free_reg_set(mvi, mvi_dev); |
1877 | } | 1927 | } |
1878 | mvs_slot_task_free(mvi, task, slot, slot_idx); | 1928 | mvs_slot_task_free(mvi, task, slot, slot_idx); |
@@ -1888,10 +1938,10 @@ out: | |||
1888 | return sts; | 1938 | return sts; |
1889 | } | 1939 | } |
1890 | 1940 | ||
1891 | void mvs_release_task(struct mvs_info *mvi, | 1941 | void mvs_do_release_task(struct mvs_info *mvi, |
1892 | int phy_no, struct domain_device *dev) | 1942 | int phy_no, struct domain_device *dev) |
1893 | { | 1943 | { |
1894 | int i = 0; u32 slot_idx; | 1944 | u32 slot_idx; |
1895 | struct mvs_phy *phy; | 1945 | struct mvs_phy *phy; |
1896 | struct mvs_port *port; | 1946 | struct mvs_port *port; |
1897 | struct mvs_slot_info *slot, *slot2; | 1947 | struct mvs_slot_info *slot, *slot2; |
@@ -1900,6 +1950,10 @@ void mvs_release_task(struct mvs_info *mvi, | |||
1900 | port = phy->port; | 1950 | port = phy->port; |
1901 | if (!port) | 1951 | if (!port) |
1902 | return; | 1952 | return; |
1953 | /* clean cmpl queue in case request is already finished */ | ||
1954 | mvs_int_rx(mvi, false); | ||
1955 | |||
1956 | |||
1903 | 1957 | ||
1904 | list_for_each_entry_safe(slot, slot2, &port->list, entry) { | 1958 | list_for_each_entry_safe(slot, slot2, &port->list, entry) { |
1905 | struct sas_task *task; | 1959 | struct sas_task *task; |
@@ -1911,18 +1965,22 @@ void mvs_release_task(struct mvs_info *mvi, | |||
1911 | 1965 | ||
1912 | mv_printk("Release slot [%x] tag[%x], task [%p]:\n", | 1966 | mv_printk("Release slot [%x] tag[%x], task [%p]:\n", |
1913 | slot_idx, slot->slot_tag, task); | 1967 | slot_idx, slot->slot_tag, task); |
1914 | 1968 | MVS_CHIP_DISP->command_active(mvi, slot_idx); | |
1915 | if (task->task_proto & SAS_PROTOCOL_SSP) { | ||
1916 | mv_printk("attached with SSP task CDB["); | ||
1917 | for (i = 0; i < 16; i++) | ||
1918 | mv_printk(" %02x", task->ssp_task.cdb[i]); | ||
1919 | mv_printk(" ]\n"); | ||
1920 | } | ||
1921 | 1969 | ||
1922 | mvs_slot_complete(mvi, slot_idx, 1); | 1970 | mvs_slot_complete(mvi, slot_idx, 1); |
1923 | } | 1971 | } |
1924 | } | 1972 | } |
1925 | 1973 | ||
1974 | void mvs_release_task(struct mvs_info *mvi, | ||
1975 | struct domain_device *dev) | ||
1976 | { | ||
1977 | int i, phyno[WIDE_PORT_MAX_PHY], num; | ||
1978 | /* housekeeper */ | ||
1979 | num = mvs_find_dev_phyno(dev, phyno); | ||
1980 | for (i = 0; i < num; i++) | ||
1981 | mvs_do_release_task(mvi, phyno[i], dev); | ||
1982 | } | ||
1983 | |||
1926 | static void mvs_phy_disconnected(struct mvs_phy *phy) | 1984 | static void mvs_phy_disconnected(struct mvs_phy *phy) |
1927 | { | 1985 | { |
1928 | phy->phy_attached = 0; | 1986 | phy->phy_attached = 0; |
@@ -2029,16 +2087,18 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) | |||
2029 | * we need check the interrupt status which belongs to per port. | 2087 | * we need check the interrupt status which belongs to per port. |
2030 | */ | 2088 | */ |
2031 | 2089 | ||
2032 | if (phy->irq_status & PHYEV_DCDR_ERR) | 2090 | if (phy->irq_status & PHYEV_DCDR_ERR) { |
2033 | mv_dprintk("port %d STP decoding error.\n", | 2091 | mv_dprintk("port %d STP decoding error.\n", |
2034 | phy_no+mvi->id*mvi->chip->n_phy); | 2092 | phy_no + mvi->id*mvi->chip->n_phy); |
2093 | } | ||
2035 | 2094 | ||
2036 | if (phy->irq_status & PHYEV_POOF) { | 2095 | if (phy->irq_status & PHYEV_POOF) { |
2037 | if (!(phy->phy_event & PHY_PLUG_OUT)) { | 2096 | if (!(phy->phy_event & PHY_PLUG_OUT)) { |
2038 | int dev_sata = phy->phy_type & PORT_TYPE_SATA; | 2097 | int dev_sata = phy->phy_type & PORT_TYPE_SATA; |
2039 | int ready; | 2098 | int ready; |
2040 | mvs_release_task(mvi, phy_no, NULL); | 2099 | mvs_do_release_task(mvi, phy_no, NULL); |
2041 | phy->phy_event |= PHY_PLUG_OUT; | 2100 | phy->phy_event |= PHY_PLUG_OUT; |
2101 | MVS_CHIP_DISP->clear_srs_irq(mvi, 0, 1); | ||
2042 | mvs_handle_event(mvi, | 2102 | mvs_handle_event(mvi, |
2043 | (void *)(unsigned long)phy_no, | 2103 | (void *)(unsigned long)phy_no, |
2044 | PHY_PLUG_EVENT); | 2104 | PHY_PLUG_EVENT); |
@@ -2085,6 +2145,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) | |||
2085 | phy_no, tmp); | 2145 | phy_no, tmp); |
2086 | } | 2146 | } |
2087 | mvs_update_phyinfo(mvi, phy_no, 0); | 2147 | mvs_update_phyinfo(mvi, phy_no, 0); |
2148 | if (phy->phy_type & PORT_TYPE_SAS) { | ||
2149 | MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2); | ||
2150 | mdelay(10); | ||
2151 | } | ||
2152 | |||
2088 | mvs_bytes_dmaed(mvi, phy_no); | 2153 | mvs_bytes_dmaed(mvi, phy_no); |
2089 | /* whether driver is going to handle hot plug */ | 2154 | /* whether driver is going to handle hot plug */ |
2090 | if (phy->phy_event & PHY_PLUG_OUT) { | 2155 | if (phy->phy_event & PHY_PLUG_OUT) { |