Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 147103
b: refs/heads/master
c: 7f4774b
h: refs/heads/master
i:
  147101: 1cf41ef
  147099: 2a84d13
  147095: 68aae63
  147087: ba1c1a0
  147071: 47ad9ae
v: v3
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Jun 10, 2009
1 parent f739be8 commit c68aabb
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 51 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 58a09b38cfcd700b796ea07ae3d2e0efbb28b561
refs/heads/master: 7f4774b38ee6270bbc6c3015cb3fa6c415ffb340
131 changes: 81 additions & 50 deletions trunk/drivers/ata/sata_nv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_thaw(struct ata_port *ap);
static void nv_ck804_freeze(struct ata_port *ap);
Expand Down Expand Up @@ -406,49 +406,82 @@ static struct scsi_host_template nv_swncq_sht = {
.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,
.lost_interrupt = ATA_OP_NULL,
.scr_read = nv_scr_read,
.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 = {
.inherits = &nv_generic_ops,
.freeze = nv_nf2_freeze,
.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 = {
.inherits = &nv_common_ops,
.inherits = &nv_generic_ops,
.freeze = nv_ck804_freeze,
.thaw = nv_ck804_thaw,
.hardreset = nv_noclassify_hardreset,
.host_stop = nv_ck804_host_stop,
};

Expand Down Expand Up @@ -476,19 +509,8 @@ static struct ata_port_operations nv_adma_ops = {
.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 = {
.inherits = &nv_mcp5x_ops,
.inherits = &nv_generic_ops,

.qc_defer = ata_std_qc_defer,
.qc_prep = nv_swncq_qc_prep,
Expand Down Expand Up @@ -557,7 +579,7 @@ static const struct ata_port_info nv_port_info[] = {
.pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_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),
},
/* SWNCQ */
Expand Down Expand Up @@ -1559,15 +1581,24 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
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)
Expand Down

0 comments on commit c68aabb

Please sign in to comment.