diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 220 |
1 files changed, 174 insertions, 46 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index b615390b6b8a..b697da483b70 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include <linux/libata.h> | 46 | #include <linux/libata.h> |
47 | 47 | ||
48 | #define DRV_NAME "ahci" | 48 | #define DRV_NAME "ahci" |
49 | #define DRV_VERSION "2.3" | 49 | #define DRV_VERSION "3.0" |
50 | 50 | ||
51 | 51 | ||
52 | enum { | 52 | enum { |
@@ -96,6 +96,7 @@ enum { | |||
96 | 96 | ||
97 | /* HOST_CAP bits */ | 97 | /* HOST_CAP bits */ |
98 | HOST_CAP_SSC = (1 << 14), /* Slumber capable */ | 98 | HOST_CAP_SSC = (1 << 14), /* Slumber capable */ |
99 | HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ | ||
99 | HOST_CAP_CLO = (1 << 24), /* Command List Override support */ | 100 | HOST_CAP_CLO = (1 << 24), /* Command List Override support */ |
100 | HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ | 101 | HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ |
101 | HOST_CAP_SNTF = (1 << 29), /* SNotification register */ | 102 | HOST_CAP_SNTF = (1 << 29), /* SNotification register */ |
@@ -143,7 +144,8 @@ enum { | |||
143 | PORT_IRQ_IF_ERR | | 144 | PORT_IRQ_IF_ERR | |
144 | PORT_IRQ_CONNECT | | 145 | PORT_IRQ_CONNECT | |
145 | PORT_IRQ_PHYRDY | | 146 | PORT_IRQ_PHYRDY | |
146 | PORT_IRQ_UNK_FIS, | 147 | PORT_IRQ_UNK_FIS | |
148 | PORT_IRQ_BAD_PMP, | ||
147 | PORT_IRQ_ERROR = PORT_IRQ_FREEZE | | 149 | PORT_IRQ_ERROR = PORT_IRQ_FREEZE | |
148 | PORT_IRQ_TF_ERR | | 150 | PORT_IRQ_TF_ERR | |
149 | PORT_IRQ_HBUS_DATA_ERR, | 151 | PORT_IRQ_HBUS_DATA_ERR, |
@@ -153,6 +155,7 @@ enum { | |||
153 | 155 | ||
154 | /* PORT_CMD bits */ | 156 | /* PORT_CMD bits */ |
155 | PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ | 157 | PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ |
158 | PORT_CMD_PMP = (1 << 17), /* PMP attached */ | ||
156 | PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ | 159 | PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ |
157 | PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ | 160 | PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ |
158 | PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ | 161 | PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ |
@@ -204,6 +207,7 @@ struct ahci_host_priv { | |||
204 | }; | 207 | }; |
205 | 208 | ||
206 | struct ahci_port_priv { | 209 | struct ahci_port_priv { |
210 | struct ata_link *active_link; | ||
207 | struct ahci_cmd_hdr *cmd_slot; | 211 | struct ahci_cmd_hdr *cmd_slot; |
208 | dma_addr_t cmd_slot_dma; | 212 | dma_addr_t cmd_slot_dma; |
209 | void *cmd_tbl; | 213 | void *cmd_tbl; |
@@ -229,6 +233,10 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc); | |||
229 | static u8 ahci_check_status(struct ata_port *ap); | 233 | static u8 ahci_check_status(struct ata_port *ap); |
230 | static void ahci_freeze(struct ata_port *ap); | 234 | static void ahci_freeze(struct ata_port *ap); |
231 | static void ahci_thaw(struct ata_port *ap); | 235 | static void ahci_thaw(struct ata_port *ap); |
236 | static void ahci_pmp_attach(struct ata_port *ap); | ||
237 | static void ahci_pmp_detach(struct ata_port *ap); | ||
238 | static int ahci_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val); | ||
239 | static int ahci_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val); | ||
232 | static void ahci_error_handler(struct ata_port *ap); | 240 | static void ahci_error_handler(struct ata_port *ap); |
233 | static void ahci_vt8251_error_handler(struct ata_port *ap); | 241 | static void ahci_vt8251_error_handler(struct ata_port *ap); |
234 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); | 242 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); |
@@ -268,7 +276,7 @@ static const struct ata_port_operations ahci_ops = { | |||
268 | 276 | ||
269 | .tf_read = ahci_tf_read, | 277 | .tf_read = ahci_tf_read, |
270 | 278 | ||
271 | .qc_defer = ata_std_qc_defer, | 279 | .qc_defer = sata_pmp_qc_defer_cmd_switch, |
272 | .qc_prep = ahci_qc_prep, | 280 | .qc_prep = ahci_qc_prep, |
273 | .qc_issue = ahci_qc_issue, | 281 | .qc_issue = ahci_qc_issue, |
274 | 282 | ||
@@ -283,6 +291,11 @@ static const struct ata_port_operations ahci_ops = { | |||
283 | .error_handler = ahci_error_handler, | 291 | .error_handler = ahci_error_handler, |
284 | .post_internal_cmd = ahci_post_internal_cmd, | 292 | .post_internal_cmd = ahci_post_internal_cmd, |
285 | 293 | ||
294 | .pmp_attach = ahci_pmp_attach, | ||
295 | .pmp_detach = ahci_pmp_detach, | ||
296 | .pmp_read = ahci_pmp_read, | ||
297 | .pmp_write = ahci_pmp_write, | ||
298 | |||
286 | #ifdef CONFIG_PM | 299 | #ifdef CONFIG_PM |
287 | .port_suspend = ahci_port_suspend, | 300 | .port_suspend = ahci_port_suspend, |
288 | .port_resume = ahci_port_resume, | 301 | .port_resume = ahci_port_resume, |
@@ -299,7 +312,7 @@ static const struct ata_port_operations ahci_vt8251_ops = { | |||
299 | 312 | ||
300 | .tf_read = ahci_tf_read, | 313 | .tf_read = ahci_tf_read, |
301 | 314 | ||
302 | .qc_defer = ata_std_qc_defer, | 315 | .qc_defer = sata_pmp_qc_defer_cmd_switch, |
303 | .qc_prep = ahci_qc_prep, | 316 | .qc_prep = ahci_qc_prep, |
304 | .qc_issue = ahci_qc_issue, | 317 | .qc_issue = ahci_qc_issue, |
305 | 318 | ||
@@ -314,6 +327,11 @@ static const struct ata_port_operations ahci_vt8251_ops = { | |||
314 | .error_handler = ahci_vt8251_error_handler, | 327 | .error_handler = ahci_vt8251_error_handler, |
315 | .post_internal_cmd = ahci_post_internal_cmd, | 328 | .post_internal_cmd = ahci_post_internal_cmd, |
316 | 329 | ||
330 | .pmp_attach = ahci_pmp_attach, | ||
331 | .pmp_detach = ahci_pmp_detach, | ||
332 | .pmp_read = ahci_pmp_read, | ||
333 | .pmp_write = ahci_pmp_write, | ||
334 | |||
317 | #ifdef CONFIG_PM | 335 | #ifdef CONFIG_PM |
318 | .port_suspend = ahci_port_suspend, | 336 | .port_suspend = ahci_port_suspend, |
319 | .port_resume = ahci_port_resume, | 337 | .port_resume = ahci_port_resume, |
@@ -1114,7 +1132,12 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, | |||
1114 | static int ahci_softreset(struct ata_link *link, unsigned int *class, | 1132 | static int ahci_softreset(struct ata_link *link, unsigned int *class, |
1115 | unsigned long deadline) | 1133 | unsigned long deadline) |
1116 | { | 1134 | { |
1117 | return ahci_do_softreset(link, class, 0, deadline); | 1135 | int pmp = 0; |
1136 | |||
1137 | if (link->ap->flags & ATA_FLAG_PMP) | ||
1138 | pmp = SATA_PMP_CTRL_PORT; | ||
1139 | |||
1140 | return ahci_do_softreset(link, class, pmp, deadline); | ||
1118 | } | 1141 | } |
1119 | 1142 | ||
1120 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | 1143 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, |
@@ -1141,7 +1164,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, | |||
1141 | 1164 | ||
1142 | if (rc == 0 && ata_link_online(link)) | 1165 | if (rc == 0 && ata_link_online(link)) |
1143 | *class = ahci_dev_classify(ap); | 1166 | *class = ahci_dev_classify(ap); |
1144 | if (*class == ATA_DEV_UNKNOWN) | 1167 | if (rc != -EAGAIN && *class == ATA_DEV_UNKNOWN) |
1145 | *class = ATA_DEV_NONE; | 1168 | *class = ATA_DEV_NONE; |
1146 | 1169 | ||
1147 | DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); | 1170 | DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); |
@@ -1196,6 +1219,12 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class) | |||
1196 | } | 1219 | } |
1197 | } | 1220 | } |
1198 | 1221 | ||
1222 | static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class, | ||
1223 | unsigned long deadline) | ||
1224 | { | ||
1225 | return ahci_do_softreset(link, class, link->pmp, deadline); | ||
1226 | } | ||
1227 | |||
1199 | static u8 ahci_check_status(struct ata_port *ap) | 1228 | static u8 ahci_check_status(struct ata_port *ap) |
1200 | { | 1229 | { |
1201 | void __iomem *mmio = ap->ioaddr.cmd_addr; | 1230 | void __iomem *mmio = ap->ioaddr.cmd_addr; |
@@ -1254,7 +1283,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) | |||
1254 | */ | 1283 | */ |
1255 | cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; | 1284 | cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; |
1256 | 1285 | ||
1257 | ata_tf_to_fis(&qc->tf, 0, 1, cmd_tbl); | 1286 | ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl); |
1258 | if (is_atapi) { | 1287 | if (is_atapi) { |
1259 | memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); | 1288 | memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); |
1260 | memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); | 1289 | memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); |
@@ -1267,7 +1296,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) | |||
1267 | /* | 1296 | /* |
1268 | * Fill in command slot information. | 1297 | * Fill in command slot information. |
1269 | */ | 1298 | */ |
1270 | opts = cmd_fis_len | n_elem << 16; | 1299 | opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12); |
1271 | if (qc->tf.flags & ATA_TFLAG_WRITE) | 1300 | if (qc->tf.flags & ATA_TFLAG_WRITE) |
1272 | opts |= AHCI_CMD_WRITE; | 1301 | opts |= AHCI_CMD_WRITE; |
1273 | if (is_atapi) | 1302 | if (is_atapi) |
@@ -1279,65 +1308,85 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) | |||
1279 | static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) | 1308 | static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) |
1280 | { | 1309 | { |
1281 | struct ahci_port_priv *pp = ap->private_data; | 1310 | struct ahci_port_priv *pp = ap->private_data; |
1282 | struct ata_eh_info *ehi = &ap->link.eh_info; | 1311 | struct ata_eh_info *host_ehi = &ap->link.eh_info; |
1283 | unsigned int err_mask = 0, action = 0; | 1312 | struct ata_link *link = NULL; |
1284 | struct ata_queued_cmd *qc; | 1313 | struct ata_queued_cmd *active_qc; |
1314 | struct ata_eh_info *active_ehi; | ||
1285 | u32 serror; | 1315 | u32 serror; |
1286 | 1316 | ||
1287 | ata_ehi_clear_desc(ehi); | 1317 | /* determine active link */ |
1318 | ata_port_for_each_link(link, ap) | ||
1319 | if (ata_link_active(link)) | ||
1320 | break; | ||
1321 | if (!link) | ||
1322 | link = &ap->link; | ||
1323 | |||
1324 | active_qc = ata_qc_from_tag(ap, link->active_tag); | ||
1325 | active_ehi = &link->eh_info; | ||
1326 | |||
1327 | /* record irq stat */ | ||
1328 | ata_ehi_clear_desc(host_ehi); | ||
1329 | ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat); | ||
1288 | 1330 | ||
1289 | /* AHCI needs SError cleared; otherwise, it might lock up */ | 1331 | /* AHCI needs SError cleared; otherwise, it might lock up */ |
1290 | ahci_scr_read(ap, SCR_ERROR, &serror); | 1332 | ahci_scr_read(ap, SCR_ERROR, &serror); |
1291 | ahci_scr_write(ap, SCR_ERROR, serror); | 1333 | ahci_scr_write(ap, SCR_ERROR, serror); |
1292 | 1334 | host_ehi->serror |= serror; | |
1293 | /* analyze @irq_stat */ | ||
1294 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); | ||
1295 | 1335 | ||
1296 | /* some controllers set IRQ_IF_ERR on device errors, ignore it */ | 1336 | /* some controllers set IRQ_IF_ERR on device errors, ignore it */ |
1297 | if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR) | 1337 | if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR) |
1298 | irq_stat &= ~PORT_IRQ_IF_ERR; | 1338 | irq_stat &= ~PORT_IRQ_IF_ERR; |
1299 | 1339 | ||
1300 | if (irq_stat & PORT_IRQ_TF_ERR) { | 1340 | if (irq_stat & PORT_IRQ_TF_ERR) { |
1301 | err_mask |= AC_ERR_DEV; | 1341 | /* If qc is active, charge it; otherwise, the active |
1342 | * link. There's no active qc on NCQ errors. It will | ||
1343 | * be determined by EH by reading log page 10h. | ||
1344 | */ | ||
1345 | if (active_qc) | ||
1346 | active_qc->err_mask |= AC_ERR_DEV; | ||
1347 | else | ||
1348 | active_ehi->err_mask |= AC_ERR_DEV; | ||
1349 | |||
1302 | if (ap->flags & AHCI_FLAG_IGN_SERR_INTERNAL) | 1350 | if (ap->flags & AHCI_FLAG_IGN_SERR_INTERNAL) |
1303 | serror &= ~SERR_INTERNAL; | 1351 | host_ehi->serror &= ~SERR_INTERNAL; |
1352 | } | ||
1353 | |||
1354 | if (irq_stat & PORT_IRQ_UNK_FIS) { | ||
1355 | u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); | ||
1356 | |||
1357 | active_ehi->err_mask |= AC_ERR_HSM; | ||
1358 | active_ehi->action |= ATA_EH_SOFTRESET; | ||
1359 | ata_ehi_push_desc(active_ehi, | ||
1360 | "unknown FIS %08x %08x %08x %08x" , | ||
1361 | unk[0], unk[1], unk[2], unk[3]); | ||
1362 | } | ||
1363 | |||
1364 | if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) { | ||
1365 | active_ehi->err_mask |= AC_ERR_HSM; | ||
1366 | active_ehi->action |= ATA_EH_SOFTRESET; | ||
1367 | ata_ehi_push_desc(active_ehi, "incorrect PMP"); | ||
1304 | } | 1368 | } |
1305 | 1369 | ||
1306 | if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { | 1370 | if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { |
1307 | err_mask |= AC_ERR_HOST_BUS; | 1371 | host_ehi->err_mask |= AC_ERR_HOST_BUS; |
1308 | action |= ATA_EH_SOFTRESET; | 1372 | host_ehi->action |= ATA_EH_SOFTRESET; |
1373 | ata_ehi_push_desc(host_ehi, "host bus error"); | ||
1309 | } | 1374 | } |
1310 | 1375 | ||
1311 | if (irq_stat & PORT_IRQ_IF_ERR) { | 1376 | if (irq_stat & PORT_IRQ_IF_ERR) { |
1312 | err_mask |= AC_ERR_ATA_BUS; | 1377 | host_ehi->err_mask |= AC_ERR_ATA_BUS; |
1313 | action |= ATA_EH_SOFTRESET; | 1378 | host_ehi->action |= ATA_EH_SOFTRESET; |
1314 | ata_ehi_push_desc(ehi, "interface fatal error"); | 1379 | ata_ehi_push_desc(host_ehi, "interface fatal error"); |
1315 | } | 1380 | } |
1316 | 1381 | ||
1317 | if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { | 1382 | if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { |
1318 | ata_ehi_hotplugged(ehi); | 1383 | ata_ehi_hotplugged(host_ehi); |
1319 | ata_ehi_push_desc(ehi, "%s", irq_stat & PORT_IRQ_CONNECT ? | 1384 | ata_ehi_push_desc(host_ehi, "%s", |
1385 | irq_stat & PORT_IRQ_CONNECT ? | ||
1320 | "connection status changed" : "PHY RDY changed"); | 1386 | "connection status changed" : "PHY RDY changed"); |
1321 | } | 1387 | } |
1322 | 1388 | ||
1323 | if (irq_stat & PORT_IRQ_UNK_FIS) { | ||
1324 | u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); | ||
1325 | |||
1326 | err_mask |= AC_ERR_HSM; | ||
1327 | action |= ATA_EH_SOFTRESET; | ||
1328 | ata_ehi_push_desc(ehi, "unknown FIS %08x %08x %08x %08x", | ||
1329 | unk[0], unk[1], unk[2], unk[3]); | ||
1330 | } | ||
1331 | |||
1332 | /* okay, let's hand over to EH */ | 1389 | /* okay, let's hand over to EH */ |
1333 | ehi->serror |= serror; | ||
1334 | ehi->action |= action; | ||
1335 | |||
1336 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | ||
1337 | if (qc) | ||
1338 | qc->err_mask |= err_mask; | ||
1339 | else | ||
1340 | ehi->err_mask |= err_mask; | ||
1341 | 1390 | ||
1342 | if (irq_stat & PORT_IRQ_FREEZE) | 1391 | if (irq_stat & PORT_IRQ_FREEZE) |
1343 | ata_port_freeze(ap); | 1392 | ata_port_freeze(ap); |
@@ -1375,7 +1424,8 @@ static void ahci_port_intr(struct ata_port *ap) | |||
1375 | sata_async_notification(ap); | 1424 | sata_async_notification(ap); |
1376 | } | 1425 | } |
1377 | 1426 | ||
1378 | if (ap->link.sactive) | 1427 | /* pp->active_link is valid iff any command is in flight */ |
1428 | if (ap->qc_active && pp->active_link->sactive) | ||
1379 | qc_active = readl(port_mmio + PORT_SCR_ACT); | 1429 | qc_active = readl(port_mmio + PORT_SCR_ACT); |
1380 | else | 1430 | else |
1381 | qc_active = readl(port_mmio + PORT_CMD_ISSUE); | 1431 | qc_active = readl(port_mmio + PORT_CMD_ISSUE); |
@@ -1513,6 +1563,13 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) | |||
1513 | { | 1563 | { |
1514 | struct ata_port *ap = qc->ap; | 1564 | struct ata_port *ap = qc->ap; |
1515 | void __iomem *port_mmio = ahci_port_base(ap); | 1565 | void __iomem *port_mmio = ahci_port_base(ap); |
1566 | struct ahci_port_priv *pp = ap->private_data; | ||
1567 | |||
1568 | /* Keep track of the currently active link. It will be used | ||
1569 | * in completion path to determine whether NCQ phase is in | ||
1570 | * progress. | ||
1571 | */ | ||
1572 | pp->active_link = qc->dev->link; | ||
1516 | 1573 | ||
1517 | if (qc->tf.protocol == ATA_PROT_NCQ) | 1574 | if (qc->tf.protocol == ATA_PROT_NCQ) |
1518 | writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); | 1575 | writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); |
@@ -1542,8 +1599,11 @@ static void ahci_thaw(struct ata_port *ap) | |||
1542 | writel(tmp, port_mmio + PORT_IRQ_STAT); | 1599 | writel(tmp, port_mmio + PORT_IRQ_STAT); |
1543 | writel(1 << ap->port_no, mmio + HOST_IRQ_STAT); | 1600 | writel(1 << ap->port_no, mmio + HOST_IRQ_STAT); |
1544 | 1601 | ||
1545 | /* turn IRQ back on */ | 1602 | /* turn IRQ back on, ignore BAD_PMP if PMP isn't attached */ |
1546 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); | 1603 | tmp = pp->intr_mask; |
1604 | if (!ap->nr_pmp_links) | ||
1605 | tmp &= ~PORT_IRQ_BAD_PMP; | ||
1606 | writel(tmp, port_mmio + PORT_IRQ_MASK); | ||
1547 | } | 1607 | } |
1548 | 1608 | ||
1549 | static void ahci_error_handler(struct ata_port *ap) | 1609 | static void ahci_error_handler(struct ata_port *ap) |
@@ -1555,8 +1615,10 @@ static void ahci_error_handler(struct ata_port *ap) | |||
1555 | } | 1615 | } |
1556 | 1616 | ||
1557 | /* perform recovery */ | 1617 | /* perform recovery */ |
1558 | ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, | 1618 | sata_pmp_do_eh(ap, ata_std_prereset, ahci_softreset, |
1559 | ahci_postreset); | 1619 | ahci_hardreset, ahci_postreset, |
1620 | sata_pmp_std_prereset, ahci_pmp_softreset, | ||
1621 | sata_pmp_std_hardreset, sata_pmp_std_postreset); | ||
1560 | } | 1622 | } |
1561 | 1623 | ||
1562 | static void ahci_vt8251_error_handler(struct ata_port *ap) | 1624 | static void ahci_vt8251_error_handler(struct ata_port *ap) |
@@ -1581,11 +1643,74 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) | |||
1581 | ahci_kick_engine(ap, 1); | 1643 | ahci_kick_engine(ap, 1); |
1582 | } | 1644 | } |
1583 | 1645 | ||
1646 | static void ahci_pmp_attach(struct ata_port *ap) | ||
1647 | { | ||
1648 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1649 | u32 cmd; | ||
1650 | |||
1651 | cmd = readl(port_mmio + PORT_CMD); | ||
1652 | cmd |= PORT_CMD_PMP; | ||
1653 | writel(cmd, port_mmio + PORT_CMD); | ||
1654 | } | ||
1655 | |||
1656 | static void ahci_pmp_detach(struct ata_port *ap) | ||
1657 | { | ||
1658 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1659 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
1660 | unsigned long flags; | ||
1661 | u32 cmd; | ||
1662 | |||
1663 | cmd = readl(port_mmio + PORT_CMD); | ||
1664 | cmd &= ~PORT_CMD_PMP; | ||
1665 | writel(cmd, port_mmio + PORT_CMD); | ||
1666 | |||
1667 | if (hpriv->cap & HOST_CAP_NCQ) { | ||
1668 | spin_lock_irqsave(ap->lock, flags); | ||
1669 | ap->flags |= ATA_FLAG_NCQ; | ||
1670 | spin_unlock_irqrestore(ap->lock, flags); | ||
1671 | } | ||
1672 | } | ||
1673 | |||
1674 | static int ahci_pmp_read(struct ata_device *dev, int pmp, int reg, u32 *r_val) | ||
1675 | { | ||
1676 | struct ata_port *ap = dev->link->ap; | ||
1677 | struct ata_taskfile tf; | ||
1678 | int rc; | ||
1679 | |||
1680 | ahci_kick_engine(ap, 0); | ||
1681 | |||
1682 | sata_pmp_read_init_tf(&tf, dev, pmp, reg); | ||
1683 | rc = ahci_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0, | ||
1684 | SATA_PMP_SCR_TIMEOUT); | ||
1685 | if (rc == 0) { | ||
1686 | ahci_tf_read(ap, &tf); | ||
1687 | *r_val = sata_pmp_read_val(&tf); | ||
1688 | } | ||
1689 | return rc; | ||
1690 | } | ||
1691 | |||
1692 | static int ahci_pmp_write(struct ata_device *dev, int pmp, int reg, u32 val) | ||
1693 | { | ||
1694 | struct ata_port *ap = dev->link->ap; | ||
1695 | struct ata_taskfile tf; | ||
1696 | |||
1697 | ahci_kick_engine(ap, 0); | ||
1698 | |||
1699 | sata_pmp_write_init_tf(&tf, dev, pmp, reg, val); | ||
1700 | return ahci_exec_polled_cmd(ap, SATA_PMP_CTRL_PORT, &tf, 1, 0, | ||
1701 | SATA_PMP_SCR_TIMEOUT); | ||
1702 | } | ||
1703 | |||
1584 | static int ahci_port_resume(struct ata_port *ap) | 1704 | static int ahci_port_resume(struct ata_port *ap) |
1585 | { | 1705 | { |
1586 | ahci_power_up(ap); | 1706 | ahci_power_up(ap); |
1587 | ahci_start_port(ap); | 1707 | ahci_start_port(ap); |
1588 | 1708 | ||
1709 | if (ap->nr_pmp_links) | ||
1710 | ahci_pmp_attach(ap); | ||
1711 | else | ||
1712 | ahci_pmp_detach(ap); | ||
1713 | |||
1589 | return 0; | 1714 | return 0; |
1590 | } | 1715 | } |
1591 | 1716 | ||
@@ -1866,6 +1991,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1866 | if (hpriv->cap & HOST_CAP_NCQ) | 1991 | if (hpriv->cap & HOST_CAP_NCQ) |
1867 | pi.flags |= ATA_FLAG_NCQ; | 1992 | pi.flags |= ATA_FLAG_NCQ; |
1868 | 1993 | ||
1994 | if (hpriv->cap & HOST_CAP_PMP) | ||
1995 | pi.flags |= ATA_FLAG_PMP; | ||
1996 | |||
1869 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map)); | 1997 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map)); |
1870 | if (!host) | 1998 | if (!host) |
1871 | return -ENOMEM; | 1999 | return -ENOMEM; |