diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 16:04:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 16:04:58 -0500 |
commit | 379e3a820da171cb1d97e8dccd736a69cebfb7c0 (patch) | |
tree | aef459cf9b4de9b85d357f487bb3e1170c9eea98 /drivers/ata/ahci.c | |
parent | 8724fdb53d27d7b59b60c8a399cc67f9abfabb33 (diff) | |
parent | a55ab496ea9c820b7192c15ef1fbf3291edfe638 (diff) |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (38 commits)
sata_via: Delay on vt6420 when starting ATAPI DMA write
ata: Detect Delkin Devices compact flash
pata_efar: Enable parallel scanning
pata_atiixp: enable parallel scan
[libata] pata_atiixp: add locking for parallel scanning
[libata] pata_efar: add locking for parallel scanning
libata: Pass host flags into the pci helper
[libata] pata_marvell: CONFIG_AHCI is really CONFIG_SATA_AHCI
libata: Allow pata_legacy to be built on non-ISA but PCI systems
pata_pdc202xx_old: fix UDMA mode for PDC2026x chipsets
pata_pdc202xx_old: fix UDMA mode for Promise UDMA33 cards
[libata] pata_at91: fix backslash-continued string
pata_via: store UDMA masks in via_isa_bridges table
pata_via: fix address setup timings underlocking
pata_serverworks: fix error message
pata_serverworks: fix PIO setup for the second channel
pata_efar: fix secondary port support
pata_cypress: fix PIO timings underclocking
pata_cs5535: use correct values for PIO1 and PIO2 data timings
pata_cmd64x: remove unused definitions
...
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 235 |
1 files changed, 213 insertions, 22 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a6a736a7dbf2..6bd930b93bcc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -93,6 +93,9 @@ enum { | |||
93 | AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS, | 93 | AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS, |
94 | AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + | 94 | AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + |
95 | AHCI_RX_FIS_SZ, | 95 | AHCI_RX_FIS_SZ, |
96 | AHCI_PORT_PRIV_FBS_DMA_SZ = AHCI_CMD_SLOT_SZ + | ||
97 | AHCI_CMD_TBL_AR_SZ + | ||
98 | (AHCI_RX_FIS_SZ * 16), | ||
96 | AHCI_IRQ_ON_SG = (1 << 31), | 99 | AHCI_IRQ_ON_SG = (1 << 31), |
97 | AHCI_CMD_ATAPI = (1 << 5), | 100 | AHCI_CMD_ATAPI = (1 << 5), |
98 | AHCI_CMD_WRITE = (1 << 6), | 101 | AHCI_CMD_WRITE = (1 << 6), |
@@ -170,6 +173,7 @@ enum { | |||
170 | PORT_SCR_ERR = 0x30, /* SATA phy register: SError */ | 173 | PORT_SCR_ERR = 0x30, /* SATA phy register: SError */ |
171 | PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */ | 174 | PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */ |
172 | PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */ | 175 | PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */ |
176 | PORT_FBS = 0x40, /* FIS-based Switching */ | ||
173 | 177 | ||
174 | /* PORT_IRQ_{STAT,MASK} bits */ | 178 | /* PORT_IRQ_{STAT,MASK} bits */ |
175 | PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ | 179 | PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ |
@@ -208,6 +212,7 @@ enum { | |||
208 | PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */ | 212 | PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */ |
209 | PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ | 213 | PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ |
210 | PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ | 214 | PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ |
215 | PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */ | ||
211 | PORT_CMD_PMP = (1 << 17), /* PMP attached */ | 216 | PORT_CMD_PMP = (1 << 17), /* PMP attached */ |
212 | PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ | 217 | PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ |
213 | PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ | 218 | PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ |
@@ -222,6 +227,14 @@ enum { | |||
222 | PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ | 227 | PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ |
223 | PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ | 228 | PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ |
224 | 229 | ||
230 | PORT_FBS_DWE_OFFSET = 16, /* FBS device with error offset */ | ||
231 | PORT_FBS_ADO_OFFSET = 12, /* FBS active dev optimization offset */ | ||
232 | PORT_FBS_DEV_OFFSET = 8, /* FBS device to issue offset */ | ||
233 | PORT_FBS_DEV_MASK = (0xf << PORT_FBS_DEV_OFFSET), /* FBS.DEV */ | ||
234 | PORT_FBS_SDE = (1 << 2), /* FBS single device error */ | ||
235 | PORT_FBS_DEC = (1 << 1), /* FBS device error clear */ | ||
236 | PORT_FBS_EN = (1 << 0), /* Enable FBS */ | ||
237 | |||
225 | /* hpriv->flags bits */ | 238 | /* hpriv->flags bits */ |
226 | AHCI_HFLAG_NO_NCQ = (1 << 0), | 239 | AHCI_HFLAG_NO_NCQ = (1 << 0), |
227 | AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */ | 240 | AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */ |
@@ -304,6 +317,9 @@ struct ahci_port_priv { | |||
304 | unsigned int ncq_saw_dmas:1; | 317 | unsigned int ncq_saw_dmas:1; |
305 | unsigned int ncq_saw_sdb:1; | 318 | unsigned int ncq_saw_sdb:1; |
306 | u32 intr_mask; /* interrupts to enable */ | 319 | u32 intr_mask; /* interrupts to enable */ |
320 | bool fbs_supported; /* set iff FBS is supported */ | ||
321 | bool fbs_enabled; /* set iff FBS is enabled */ | ||
322 | int fbs_last_dev; /* save FBS.DEV of last FIS */ | ||
307 | /* enclosure management info per PM slot */ | 323 | /* enclosure management info per PM slot */ |
308 | struct ahci_em_priv em_priv[EM_MAX_SLOTS]; | 324 | struct ahci_em_priv em_priv[EM_MAX_SLOTS]; |
309 | }; | 325 | }; |
@@ -315,9 +331,12 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); | |||
315 | static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc); | 331 | static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc); |
316 | static int ahci_port_start(struct ata_port *ap); | 332 | static int ahci_port_start(struct ata_port *ap); |
317 | static void ahci_port_stop(struct ata_port *ap); | 333 | static void ahci_port_stop(struct ata_port *ap); |
334 | static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc); | ||
318 | static void ahci_qc_prep(struct ata_queued_cmd *qc); | 335 | static void ahci_qc_prep(struct ata_queued_cmd *qc); |
319 | static void ahci_freeze(struct ata_port *ap); | 336 | static void ahci_freeze(struct ata_port *ap); |
320 | static void ahci_thaw(struct ata_port *ap); | 337 | static void ahci_thaw(struct ata_port *ap); |
338 | static void ahci_enable_fbs(struct ata_port *ap); | ||
339 | static void ahci_disable_fbs(struct ata_port *ap); | ||
321 | static void ahci_pmp_attach(struct ata_port *ap); | 340 | static void ahci_pmp_attach(struct ata_port *ap); |
322 | static void ahci_pmp_detach(struct ata_port *ap); | 341 | static void ahci_pmp_detach(struct ata_port *ap); |
323 | static int ahci_softreset(struct ata_link *link, unsigned int *class, | 342 | static int ahci_softreset(struct ata_link *link, unsigned int *class, |
@@ -356,10 +375,10 @@ static ssize_t ahci_show_host_version(struct device *dev, | |||
356 | static ssize_t ahci_show_port_cmd(struct device *dev, | 375 | static ssize_t ahci_show_port_cmd(struct device *dev, |
357 | struct device_attribute *attr, char *buf); | 376 | struct device_attribute *attr, char *buf); |
358 | 377 | ||
359 | DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); | 378 | static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); |
360 | DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); | 379 | static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); |
361 | DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); | 380 | static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); |
362 | DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); | 381 | static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); |
363 | 382 | ||
364 | static struct device_attribute *ahci_shost_attrs[] = { | 383 | static struct device_attribute *ahci_shost_attrs[] = { |
365 | &dev_attr_link_power_management_policy, | 384 | &dev_attr_link_power_management_policy, |
@@ -390,7 +409,7 @@ static struct scsi_host_template ahci_sht = { | |||
390 | static struct ata_port_operations ahci_ops = { | 409 | static struct ata_port_operations ahci_ops = { |
391 | .inherits = &sata_pmp_port_ops, | 410 | .inherits = &sata_pmp_port_ops, |
392 | 411 | ||
393 | .qc_defer = sata_pmp_qc_defer_cmd_switch, | 412 | .qc_defer = ahci_pmp_qc_defer, |
394 | .qc_prep = ahci_qc_prep, | 413 | .qc_prep = ahci_qc_prep, |
395 | .qc_issue = ahci_qc_issue, | 414 | .qc_issue = ahci_qc_issue, |
396 | .qc_fill_rtf = ahci_qc_fill_rtf, | 415 | .qc_fill_rtf = ahci_qc_fill_rtf, |
@@ -570,6 +589,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
570 | { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ | 589 | { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ |
571 | { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ | 590 | { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ |
572 | { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ | 591 | { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ |
592 | { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ | ||
593 | { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ | ||
594 | { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ | ||
595 | { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ | ||
596 | { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ | ||
597 | { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ | ||
573 | 598 | ||
574 | /* JMicron 360/1/3/5/6, match class to avoid IDE function */ | 599 | /* JMicron 360/1/3/5/6, match class to avoid IDE function */ |
575 | { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 600 | { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
@@ -2045,6 +2070,17 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) | |||
2045 | return si; | 2070 | return si; |
2046 | } | 2071 | } |
2047 | 2072 | ||
2073 | static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc) | ||
2074 | { | ||
2075 | struct ata_port *ap = qc->ap; | ||
2076 | struct ahci_port_priv *pp = ap->private_data; | ||
2077 | |||
2078 | if (!sata_pmp_attached(ap) || pp->fbs_enabled) | ||
2079 | return ata_std_qc_defer(qc); | ||
2080 | else | ||
2081 | return sata_pmp_qc_defer_cmd_switch(qc); | ||
2082 | } | ||
2083 | |||
2048 | static void ahci_qc_prep(struct ata_queued_cmd *qc) | 2084 | static void ahci_qc_prep(struct ata_queued_cmd *qc) |
2049 | { | 2085 | { |
2050 | struct ata_port *ap = qc->ap; | 2086 | struct ata_port *ap = qc->ap; |
@@ -2083,6 +2119,31 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) | |||
2083 | ahci_fill_cmd_slot(pp, qc->tag, opts); | 2119 | ahci_fill_cmd_slot(pp, qc->tag, opts); |
2084 | } | 2120 | } |
2085 | 2121 | ||
2122 | static void ahci_fbs_dec_intr(struct ata_port *ap) | ||
2123 | { | ||
2124 | struct ahci_port_priv *pp = ap->private_data; | ||
2125 | void __iomem *port_mmio = ahci_port_base(ap); | ||
2126 | u32 fbs = readl(port_mmio + PORT_FBS); | ||
2127 | int retries = 3; | ||
2128 | |||
2129 | DPRINTK("ENTER\n"); | ||
2130 | BUG_ON(!pp->fbs_enabled); | ||
2131 | |||
2132 | /* time to wait for DEC is not specified by AHCI spec, | ||
2133 | * add a retry loop for safety. | ||
2134 | */ | ||
2135 | writel(fbs | PORT_FBS_DEC, port_mmio + PORT_FBS); | ||
2136 | fbs = readl(port_mmio + PORT_FBS); | ||
2137 | while ((fbs & PORT_FBS_DEC) && retries--) { | ||
2138 | udelay(1); | ||
2139 | fbs = readl(port_mmio + PORT_FBS); | ||
2140 | } | ||
2141 | |||
2142 | if (fbs & PORT_FBS_DEC) | ||
2143 | dev_printk(KERN_ERR, ap->host->dev, | ||
2144 | "failed to clear device error\n"); | ||
2145 | } | ||
2146 | |||
2086 | static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) | 2147 | static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) |
2087 | { | 2148 | { |
2088 | struct ahci_host_priv *hpriv = ap->host->private_data; | 2149 | struct ahci_host_priv *hpriv = ap->host->private_data; |
@@ -2091,12 +2152,26 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) | |||
2091 | struct ata_link *link = NULL; | 2152 | struct ata_link *link = NULL; |
2092 | struct ata_queued_cmd *active_qc; | 2153 | struct ata_queued_cmd *active_qc; |
2093 | struct ata_eh_info *active_ehi; | 2154 | struct ata_eh_info *active_ehi; |
2155 | bool fbs_need_dec = false; | ||
2094 | u32 serror; | 2156 | u32 serror; |
2095 | 2157 | ||
2096 | /* determine active link */ | 2158 | /* determine active link with error */ |
2097 | ata_for_each_link(link, ap, EDGE) | 2159 | if (pp->fbs_enabled) { |
2098 | if (ata_link_active(link)) | 2160 | void __iomem *port_mmio = ahci_port_base(ap); |
2099 | break; | 2161 | u32 fbs = readl(port_mmio + PORT_FBS); |
2162 | int pmp = fbs >> PORT_FBS_DWE_OFFSET; | ||
2163 | |||
2164 | if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links) && | ||
2165 | ata_link_online(&ap->pmp_link[pmp])) { | ||
2166 | link = &ap->pmp_link[pmp]; | ||
2167 | fbs_need_dec = true; | ||
2168 | } | ||
2169 | |||
2170 | } else | ||
2171 | ata_for_each_link(link, ap, EDGE) | ||
2172 | if (ata_link_active(link)) | ||
2173 | break; | ||
2174 | |||
2100 | if (!link) | 2175 | if (!link) |
2101 | link = &ap->link; | 2176 | link = &ap->link; |
2102 | 2177 | ||
@@ -2153,8 +2228,13 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) | |||
2153 | } | 2228 | } |
2154 | 2229 | ||
2155 | if (irq_stat & PORT_IRQ_IF_ERR) { | 2230 | if (irq_stat & PORT_IRQ_IF_ERR) { |
2156 | host_ehi->err_mask |= AC_ERR_ATA_BUS; | 2231 | if (fbs_need_dec) |
2157 | host_ehi->action |= ATA_EH_RESET; | 2232 | active_ehi->err_mask |= AC_ERR_DEV; |
2233 | else { | ||
2234 | host_ehi->err_mask |= AC_ERR_ATA_BUS; | ||
2235 | host_ehi->action |= ATA_EH_RESET; | ||
2236 | } | ||
2237 | |||
2158 | ata_ehi_push_desc(host_ehi, "interface fatal error"); | 2238 | ata_ehi_push_desc(host_ehi, "interface fatal error"); |
2159 | } | 2239 | } |
2160 | 2240 | ||
@@ -2169,7 +2249,10 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) | |||
2169 | 2249 | ||
2170 | if (irq_stat & PORT_IRQ_FREEZE) | 2250 | if (irq_stat & PORT_IRQ_FREEZE) |
2171 | ata_port_freeze(ap); | 2251 | ata_port_freeze(ap); |
2172 | else | 2252 | else if (fbs_need_dec) { |
2253 | ata_link_abort(link); | ||
2254 | ahci_fbs_dec_intr(ap); | ||
2255 | } else | ||
2173 | ata_port_abort(ap); | 2256 | ata_port_abort(ap); |
2174 | } | 2257 | } |
2175 | 2258 | ||
@@ -2222,12 +2305,19 @@ static void ahci_port_intr(struct ata_port *ap) | |||
2222 | /* If the 'N' bit in word 0 of the FIS is set, | 2305 | /* If the 'N' bit in word 0 of the FIS is set, |
2223 | * we just received asynchronous notification. | 2306 | * we just received asynchronous notification. |
2224 | * Tell libata about it. | 2307 | * Tell libata about it. |
2308 | * | ||
2309 | * Lack of SNotification should not appear in | ||
2310 | * ahci 1.2, so the workaround is unnecessary | ||
2311 | * when FBS is enabled. | ||
2225 | */ | 2312 | */ |
2226 | const __le32 *f = pp->rx_fis + RX_FIS_SDB; | 2313 | if (pp->fbs_enabled) |
2227 | u32 f0 = le32_to_cpu(f[0]); | 2314 | WARN_ON_ONCE(1); |
2228 | 2315 | else { | |
2229 | if (f0 & (1 << 15)) | 2316 | const __le32 *f = pp->rx_fis + RX_FIS_SDB; |
2230 | sata_async_notification(ap); | 2317 | u32 f0 = le32_to_cpu(f[0]); |
2318 | if (f0 & (1 << 15)) | ||
2319 | sata_async_notification(ap); | ||
2320 | } | ||
2231 | } | 2321 | } |
2232 | } | 2322 | } |
2233 | 2323 | ||
@@ -2321,6 +2411,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) | |||
2321 | 2411 | ||
2322 | if (qc->tf.protocol == ATA_PROT_NCQ) | 2412 | if (qc->tf.protocol == ATA_PROT_NCQ) |
2323 | writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); | 2413 | writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); |
2414 | |||
2415 | if (pp->fbs_enabled && pp->fbs_last_dev != qc->dev->link->pmp) { | ||
2416 | u32 fbs = readl(port_mmio + PORT_FBS); | ||
2417 | fbs &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC); | ||
2418 | fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET; | ||
2419 | writel(fbs, port_mmio + PORT_FBS); | ||
2420 | pp->fbs_last_dev = qc->dev->link->pmp; | ||
2421 | } | ||
2422 | |||
2324 | writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); | 2423 | writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); |
2325 | 2424 | ||
2326 | ahci_sw_activity(qc->dev->link); | 2425 | ahci_sw_activity(qc->dev->link); |
@@ -2333,6 +2432,9 @@ static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) | |||
2333 | struct ahci_port_priv *pp = qc->ap->private_data; | 2432 | struct ahci_port_priv *pp = qc->ap->private_data; |
2334 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; | 2433 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; |
2335 | 2434 | ||
2435 | if (pp->fbs_enabled) | ||
2436 | d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; | ||
2437 | |||
2336 | ata_tf_from_fis(d2h_fis, &qc->result_tf); | 2438 | ata_tf_from_fis(d2h_fis, &qc->result_tf); |
2337 | return true; | 2439 | return true; |
2338 | } | 2440 | } |
@@ -2381,6 +2483,71 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) | |||
2381 | ahci_kick_engine(ap); | 2483 | ahci_kick_engine(ap); |
2382 | } | 2484 | } |
2383 | 2485 | ||
2486 | static void ahci_enable_fbs(struct ata_port *ap) | ||
2487 | { | ||
2488 | struct ahci_port_priv *pp = ap->private_data; | ||
2489 | void __iomem *port_mmio = ahci_port_base(ap); | ||
2490 | u32 fbs; | ||
2491 | int rc; | ||
2492 | |||
2493 | if (!pp->fbs_supported) | ||
2494 | return; | ||
2495 | |||
2496 | fbs = readl(port_mmio + PORT_FBS); | ||
2497 | if (fbs & PORT_FBS_EN) { | ||
2498 | pp->fbs_enabled = true; | ||
2499 | pp->fbs_last_dev = -1; /* initialization */ | ||
2500 | return; | ||
2501 | } | ||
2502 | |||
2503 | rc = ahci_stop_engine(ap); | ||
2504 | if (rc) | ||
2505 | return; | ||
2506 | |||
2507 | writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS); | ||
2508 | fbs = readl(port_mmio + PORT_FBS); | ||
2509 | if (fbs & PORT_FBS_EN) { | ||
2510 | dev_printk(KERN_INFO, ap->host->dev, "FBS is enabled.\n"); | ||
2511 | pp->fbs_enabled = true; | ||
2512 | pp->fbs_last_dev = -1; /* initialization */ | ||
2513 | } else | ||
2514 | dev_printk(KERN_ERR, ap->host->dev, "Failed to enable FBS\n"); | ||
2515 | |||
2516 | ahci_start_engine(ap); | ||
2517 | } | ||
2518 | |||
2519 | static void ahci_disable_fbs(struct ata_port *ap) | ||
2520 | { | ||
2521 | struct ahci_port_priv *pp = ap->private_data; | ||
2522 | void __iomem *port_mmio = ahci_port_base(ap); | ||
2523 | u32 fbs; | ||
2524 | int rc; | ||
2525 | |||
2526 | if (!pp->fbs_supported) | ||
2527 | return; | ||
2528 | |||
2529 | fbs = readl(port_mmio + PORT_FBS); | ||
2530 | if ((fbs & PORT_FBS_EN) == 0) { | ||
2531 | pp->fbs_enabled = false; | ||
2532 | return; | ||
2533 | } | ||
2534 | |||
2535 | rc = ahci_stop_engine(ap); | ||
2536 | if (rc) | ||
2537 | return; | ||
2538 | |||
2539 | writel(fbs & ~PORT_FBS_EN, port_mmio + PORT_FBS); | ||
2540 | fbs = readl(port_mmio + PORT_FBS); | ||
2541 | if (fbs & PORT_FBS_EN) | ||
2542 | dev_printk(KERN_ERR, ap->host->dev, "Failed to disable FBS\n"); | ||
2543 | else { | ||
2544 | dev_printk(KERN_INFO, ap->host->dev, "FBS is disabled.\n"); | ||
2545 | pp->fbs_enabled = false; | ||
2546 | } | ||
2547 | |||
2548 | ahci_start_engine(ap); | ||
2549 | } | ||
2550 | |||
2384 | static void ahci_pmp_attach(struct ata_port *ap) | 2551 | static void ahci_pmp_attach(struct ata_port *ap) |
2385 | { | 2552 | { |
2386 | void __iomem *port_mmio = ahci_port_base(ap); | 2553 | void __iomem *port_mmio = ahci_port_base(ap); |
@@ -2391,6 +2558,8 @@ static void ahci_pmp_attach(struct ata_port *ap) | |||
2391 | cmd |= PORT_CMD_PMP; | 2558 | cmd |= PORT_CMD_PMP; |
2392 | writel(cmd, port_mmio + PORT_CMD); | 2559 | writel(cmd, port_mmio + PORT_CMD); |
2393 | 2560 | ||
2561 | ahci_enable_fbs(ap); | ||
2562 | |||
2394 | pp->intr_mask |= PORT_IRQ_BAD_PMP; | 2563 | pp->intr_mask |= PORT_IRQ_BAD_PMP; |
2395 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); | 2564 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); |
2396 | } | 2565 | } |
@@ -2401,6 +2570,8 @@ static void ahci_pmp_detach(struct ata_port *ap) | |||
2401 | struct ahci_port_priv *pp = ap->private_data; | 2570 | struct ahci_port_priv *pp = ap->private_data; |
2402 | u32 cmd; | 2571 | u32 cmd; |
2403 | 2572 | ||
2573 | ahci_disable_fbs(ap); | ||
2574 | |||
2404 | cmd = readl(port_mmio + PORT_CMD); | 2575 | cmd = readl(port_mmio + PORT_CMD); |
2405 | cmd &= ~PORT_CMD_PMP; | 2576 | cmd &= ~PORT_CMD_PMP; |
2406 | writel(cmd, port_mmio + PORT_CMD); | 2577 | writel(cmd, port_mmio + PORT_CMD); |
@@ -2492,20 +2663,40 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) | |||
2492 | 2663 | ||
2493 | static int ahci_port_start(struct ata_port *ap) | 2664 | static int ahci_port_start(struct ata_port *ap) |
2494 | { | 2665 | { |
2666 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
2495 | struct device *dev = ap->host->dev; | 2667 | struct device *dev = ap->host->dev; |
2496 | struct ahci_port_priv *pp; | 2668 | struct ahci_port_priv *pp; |
2497 | void *mem; | 2669 | void *mem; |
2498 | dma_addr_t mem_dma; | 2670 | dma_addr_t mem_dma; |
2671 | size_t dma_sz, rx_fis_sz; | ||
2499 | 2672 | ||
2500 | pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); | 2673 | pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); |
2501 | if (!pp) | 2674 | if (!pp) |
2502 | return -ENOMEM; | 2675 | return -ENOMEM; |
2503 | 2676 | ||
2504 | mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, | 2677 | /* check FBS capability */ |
2505 | GFP_KERNEL); | 2678 | if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) { |
2679 | void __iomem *port_mmio = ahci_port_base(ap); | ||
2680 | u32 cmd = readl(port_mmio + PORT_CMD); | ||
2681 | if (cmd & PORT_CMD_FBSCP) | ||
2682 | pp->fbs_supported = true; | ||
2683 | else | ||
2684 | dev_printk(KERN_WARNING, dev, | ||
2685 | "The port is not capable of FBS\n"); | ||
2686 | } | ||
2687 | |||
2688 | if (pp->fbs_supported) { | ||
2689 | dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ; | ||
2690 | rx_fis_sz = AHCI_RX_FIS_SZ * 16; | ||
2691 | } else { | ||
2692 | dma_sz = AHCI_PORT_PRIV_DMA_SZ; | ||
2693 | rx_fis_sz = AHCI_RX_FIS_SZ; | ||
2694 | } | ||
2695 | |||
2696 | mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL); | ||
2506 | if (!mem) | 2697 | if (!mem) |
2507 | return -ENOMEM; | 2698 | return -ENOMEM; |
2508 | memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ); | 2699 | memset(mem, 0, dma_sz); |
2509 | 2700 | ||
2510 | /* | 2701 | /* |
2511 | * First item in chunk of DMA memory: 32-slot command table, | 2702 | * First item in chunk of DMA memory: 32-slot command table, |
@@ -2523,8 +2714,8 @@ static int ahci_port_start(struct ata_port *ap) | |||
2523 | pp->rx_fis = mem; | 2714 | pp->rx_fis = mem; |
2524 | pp->rx_fis_dma = mem_dma; | 2715 | pp->rx_fis_dma = mem_dma; |
2525 | 2716 | ||
2526 | mem += AHCI_RX_FIS_SZ; | 2717 | mem += rx_fis_sz; |
2527 | mem_dma += AHCI_RX_FIS_SZ; | 2718 | mem_dma += rx_fis_sz; |
2528 | 2719 | ||
2529 | /* | 2720 | /* |
2530 | * Third item: data area for storing a single command | 2721 | * Third item: data area for storing a single command |