|
@@ -305,8 +305,8 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
|
|
static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
|
|
static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
|
|
static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
|
|
static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
|
|
|
|
|
|
-static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
|
|
|
|
- unsigned long deadline);
|
|
|
|
|
|
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
|
|
|
|
+ unsigned long deadline);
|
|
static void nv_nf2_freeze(struct ata_port *ap);
|
|
static void nv_nf2_freeze(struct ata_port *ap);
|
|
static void nv_nf2_thaw(struct ata_port *ap);
|
|
static void nv_nf2_thaw(struct ata_port *ap);
|
|
static void nv_ck804_freeze(struct ata_port *ap);
|
|
static void nv_ck804_freeze(struct ata_port *ap);
|
|
@@ -406,49 +406,82 @@ static struct scsi_host_template nv_swncq_sht = {
|
|
.slave_configure = nv_swncq_slave_config,
|
|
.slave_configure = nv_swncq_slave_config,
|
|
};
|
|
};
|
|
|
|
|
|
-static struct ata_port_operations nv_common_ops = {
|
|
|
|
|
|
+/*
|
|
|
|
+ * NV SATA controllers have various different problems with hardreset
|
|
|
|
+ * protocol depending on the specific controller and device.
|
|
|
|
+ *
|
|
|
|
+ * GENERIC:
|
|
|
|
+ *
|
|
|
|
+ * bko11195 reports that link doesn't come online after hardreset on
|
|
|
|
+ * generic nv's and there have been several other similar reports on
|
|
|
|
+ * linux-ide.
|
|
|
|
+ *
|
|
|
|
+ * bko12351#c23 reports that warmplug on MCP61 doesn't work with
|
|
|
|
+ * softreset.
|
|
|
|
+ *
|
|
|
|
+ * NF2/3:
|
|
|
|
+ *
|
|
|
|
+ * bko3352 reports nf2/3 controllers can't determine device signature
|
|
|
|
+ * reliably after hardreset. The following thread reports detection
|
|
|
|
+ * failure on cold boot with the standard debouncing timing.
|
|
|
|
+ *
|
|
|
|
+ * http://thread.gmane.org/gmane.linux.ide/34098
|
|
|
|
+ *
|
|
|
|
+ * bko12176 reports that hardreset fails to bring up the link during
|
|
|
|
+ * boot on nf2.
|
|
|
|
+ *
|
|
|
|
+ * CK804:
|
|
|
|
+ *
|
|
|
|
+ * For initial probing after boot and hot plugging, hardreset mostly
|
|
|
|
+ * works fine on CK804 but curiously, reprobing on the initial port
|
|
|
|
+ * by rescanning or rmmod/insmod fails to acquire the initial D2H Reg
|
|
|
|
+ * FIS in somewhat undeterministic way.
|
|
|
|
+ *
|
|
|
|
+ * SWNCQ:
|
|
|
|
+ *
|
|
|
|
+ * bko12351 reports that when SWNCQ is enabled, for hotplug to work,
|
|
|
|
+ * hardreset should be used and hardreset can't report proper
|
|
|
|
+ * signature, which suggests that mcp5x is closer to nf2 as long as
|
|
|
|
+ * reset quirkiness is concerned.
|
|
|
|
+ *
|
|
|
|
+ * bko12703 reports that boot probing fails for intel SSD with
|
|
|
|
+ * hardreset. Link fails to come online. Softreset works fine.
|
|
|
|
+ *
|
|
|
|
+ * The failures are varied but the following patterns seem true for
|
|
|
|
+ * all flavors.
|
|
|
|
+ *
|
|
|
|
+ * - Softreset during boot always works.
|
|
|
|
+ *
|
|
|
|
+ * - Hardreset during boot sometimes fails to bring up the link on
|
|
|
|
+ * certain comibnations and device signature acquisition is
|
|
|
|
+ * unreliable.
|
|
|
|
+ *
|
|
|
|
+ * - Hardreset is often necessary after hotplug.
|
|
|
|
+ *
|
|
|
|
+ * So, preferring softreset for boot probing and error handling (as
|
|
|
|
+ * hardreset might bring down the link) but using hardreset for
|
|
|
|
+ * post-boot probing should work around the above issues in most
|
|
|
|
+ * cases. Define nv_hardreset() which only kicks in for post-boot
|
|
|
|
+ * probing and use it for all variants.
|
|
|
|
+ */
|
|
|
|
+static struct ata_port_operations nv_generic_ops = {
|
|
.inherits = &ata_bmdma_port_ops,
|
|
.inherits = &ata_bmdma_port_ops,
|
|
.lost_interrupt = ATA_OP_NULL,
|
|
.lost_interrupt = ATA_OP_NULL,
|
|
.scr_read = nv_scr_read,
|
|
.scr_read = nv_scr_read,
|
|
.scr_write = nv_scr_write,
|
|
.scr_write = nv_scr_write,
|
|
|
|
+ .hardreset = nv_hardreset,
|
|
};
|
|
};
|
|
|
|
|
|
-/* OSDL bz11195 reports that link doesn't come online after hardreset
|
|
|
|
- * on generic nv's and there have been several other similar reports
|
|
|
|
- * on linux-ide. Disable hardreset for generic nv's.
|
|
|
|
- */
|
|
|
|
-static struct ata_port_operations nv_generic_ops = {
|
|
|
|
- .inherits = &nv_common_ops,
|
|
|
|
- .hardreset = ATA_OP_NULL,
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-/* nf2 is ripe with hardreset related problems.
|
|
|
|
- *
|
|
|
|
- * kernel bz#3352 reports nf2/3 controllers can't determine device
|
|
|
|
- * signature reliably. The following thread reports detection failure
|
|
|
|
- * on cold boot with the standard debouncing timing.
|
|
|
|
- *
|
|
|
|
- * http://thread.gmane.org/gmane.linux.ide/34098
|
|
|
|
- *
|
|
|
|
- * And bz#12176 reports that hardreset simply doesn't work on nf2.
|
|
|
|
- * Give up on it and just don't do hardreset.
|
|
|
|
- */
|
|
|
|
static struct ata_port_operations nv_nf2_ops = {
|
|
static struct ata_port_operations nv_nf2_ops = {
|
|
.inherits = &nv_generic_ops,
|
|
.inherits = &nv_generic_ops,
|
|
.freeze = nv_nf2_freeze,
|
|
.freeze = nv_nf2_freeze,
|
|
.thaw = nv_nf2_thaw,
|
|
.thaw = nv_nf2_thaw,
|
|
};
|
|
};
|
|
|
|
|
|
-/* For initial probing after boot and hot plugging, hardreset mostly
|
|
|
|
- * works fine on CK804 but curiously, reprobing on the initial port by
|
|
|
|
- * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
|
|
|
|
- * in somewhat undeterministic way. Use noclassify hardreset.
|
|
|
|
- */
|
|
|
|
static struct ata_port_operations nv_ck804_ops = {
|
|
static struct ata_port_operations nv_ck804_ops = {
|
|
- .inherits = &nv_common_ops,
|
|
|
|
|
|
+ .inherits = &nv_generic_ops,
|
|
.freeze = nv_ck804_freeze,
|
|
.freeze = nv_ck804_freeze,
|
|
.thaw = nv_ck804_thaw,
|
|
.thaw = nv_ck804_thaw,
|
|
- .hardreset = nv_noclassify_hardreset,
|
|
|
|
.host_stop = nv_ck804_host_stop,
|
|
.host_stop = nv_ck804_host_stop,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -476,19 +509,8 @@ static struct ata_port_operations nv_adma_ops = {
|
|
.host_stop = nv_adma_host_stop,
|
|
.host_stop = nv_adma_host_stop,
|
|
};
|
|
};
|
|
|
|
|
|
-/* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to
|
|
|
|
- * work, hardreset should be used and hardreset can't report proper
|
|
|
|
- * signature, which suggests that mcp5x is closer to nf2 as long as
|
|
|
|
- * reset quirkiness is concerned. Define separate ops for mcp5x with
|
|
|
|
- * nv_noclassify_hardreset().
|
|
|
|
- */
|
|
|
|
-static struct ata_port_operations nv_mcp5x_ops = {
|
|
|
|
- .inherits = &nv_common_ops,
|
|
|
|
- .hardreset = nv_noclassify_hardreset,
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
static struct ata_port_operations nv_swncq_ops = {
|
|
static struct ata_port_operations nv_swncq_ops = {
|
|
- .inherits = &nv_mcp5x_ops,
|
|
|
|
|
|
+ .inherits = &nv_generic_ops,
|
|
|
|
|
|
.qc_defer = ata_std_qc_defer,
|
|
.qc_defer = ata_std_qc_defer,
|
|
.qc_prep = nv_swncq_qc_prep,
|
|
.qc_prep = nv_swncq_qc_prep,
|
|
@@ -557,7 +579,7 @@ static const struct ata_port_info nv_port_info[] = {
|
|
.pio_mask = NV_PIO_MASK,
|
|
.pio_mask = NV_PIO_MASK,
|
|
.mwdma_mask = NV_MWDMA_MASK,
|
|
.mwdma_mask = NV_MWDMA_MASK,
|
|
.udma_mask = NV_UDMA_MASK,
|
|
.udma_mask = NV_UDMA_MASK,
|
|
- .port_ops = &nv_mcp5x_ops,
|
|
|
|
|
|
+ .port_ops = &nv_generic_ops,
|
|
.private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
|
|
.private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
|
|
},
|
|
},
|
|
/* SWNCQ */
|
|
/* SWNCQ */
|
|
@@ -1559,15 +1581,24 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
|
|
|
|
- unsigned long deadline)
|
|
|
|
|
|
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
|
|
|
|
+ unsigned long deadline)
|
|
{
|
|
{
|
|
- bool online;
|
|
|
|
- int rc;
|
|
|
|
|
|
+ struct ata_eh_context *ehc = &link->eh_context;
|
|
|
|
|
|
- rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
|
|
|
|
- &online, NULL);
|
|
|
|
- return online ? -EAGAIN : rc;
|
|
|
|
|
|
+ /* Do hardreset iff it's post-boot probing, please read the
|
|
|
|
+ * comment above port ops for details.
|
|
|
|
+ */
|
|
|
|
+ if (!(link->ap->pflags & ATA_PFLAG_LOADING) &&
|
|
|
|
+ !ata_dev_enabled(link->device))
|
|
|
|
+ sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
|
|
|
|
+ NULL, NULL);
|
|
|
|
+ else if (!(ehc->i.flags & ATA_EHI_QUIET))
|
|
|
|
+ ata_link_printk(link, KERN_INFO,
|
|
|
|
+ "nv: skipping hardreset on occupied port\n");
|
|
|
|
+
|
|
|
|
+ /* device signature acquisition is unreliable */
|
|
|
|
+ return -EAGAIN;
|
|
}
|
|
}
|
|
|
|
|
|
static void nv_nf2_freeze(struct ata_port *ap)
|
|
static void nv_nf2_freeze(struct ata_port *ap)
|