Skip to content

Commit 54a86bf

Browse files
author
Jeff Garzik
committed
Merge branch 'upstream-fixes' into upstream
2 parents 81ce3c4 + ac2164d commit 54a86bf

File tree

2 files changed

+134
-7
lines changed

2 files changed

+134
-7
lines changed

drivers/ata/ata_piix.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@ static struct ata_port_info piix_port_info[] = {
390390
/* ich5_sata */
391391
{
392392
.sht = &piix_sht,
393-
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
393+
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
394+
PIIX_FLAG_IGNORE_PCS,
394395
.pio_mask = 0x1f, /* pio0-4 */
395396
.mwdma_mask = 0x07, /* mwdma0-2 */
396397
.udma_mask = 0x7f, /* udma0-6 */
@@ -467,6 +468,11 @@ MODULE_LICENSE("GPL");
467468
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
468469
MODULE_VERSION(DRV_VERSION);
469470

471+
static int force_pcs = 0;
472+
module_param(force_pcs, int, 0444);
473+
MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
474+
"device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");
475+
470476
/**
471477
* piix_pata_cbl_detect - Probe host controller cable detect info
472478
* @ap: Port for which cable detect info is desired
@@ -811,6 +817,7 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
811817
}
812818

813819
static void __devinit piix_init_pcs(struct pci_dev *pdev,
820+
struct ata_port_info *pinfo,
814821
const struct piix_map_db *map_db)
815822
{
816823
u16 pcs, new_pcs;
@@ -824,6 +831,18 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
824831
pci_write_config_word(pdev, ICH5_PCS, new_pcs);
825832
msleep(150);
826833
}
834+
835+
if (force_pcs == 1) {
836+
dev_printk(KERN_INFO, &pdev->dev,
837+
"force ignoring PCS (0x%x)\n", new_pcs);
838+
pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS;
839+
pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS;
840+
} else if (force_pcs == 2) {
841+
dev_printk(KERN_INFO, &pdev->dev,
842+
"force honoring PCS (0x%x)\n", new_pcs);
843+
pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
844+
pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
845+
}
827846
}
828847

829848
static void __devinit piix_init_sata_map(struct pci_dev *pdev,
@@ -932,7 +951,8 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
932951
if (host_flags & ATA_FLAG_SATA) {
933952
piix_init_sata_map(pdev, port_info,
934953
piix_map_db_table[ent->driver_data]);
935-
piix_init_pcs(pdev, piix_map_db_table[ent->driver_data]);
954+
piix_init_pcs(pdev, port_info,
955+
piix_map_db_table[ent->driver_data]);
936956
}
937957

938958
/* On ICH5, some BIOSen disable the interrupt using the

drivers/ata/sata_via.c

Lines changed: 112 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ enum {
7474
static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
7575
static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
7676
static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
77+
static void vt6420_error_handler(struct ata_port *ap);
7778

7879
static const struct pci_device_id svia_pci_tbl[] = {
7980
{ 0x1106, 0x0591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
@@ -108,7 +109,38 @@ static struct scsi_host_template svia_sht = {
108109
.bios_param = ata_std_bios_param,
109110
};
110111

111-
static const struct ata_port_operations svia_sata_ops = {
112+
static const struct ata_port_operations vt6420_sata_ops = {
113+
.port_disable = ata_port_disable,
114+
115+
.tf_load = ata_tf_load,
116+
.tf_read = ata_tf_read,
117+
.check_status = ata_check_status,
118+
.exec_command = ata_exec_command,
119+
.dev_select = ata_std_dev_select,
120+
121+
.bmdma_setup = ata_bmdma_setup,
122+
.bmdma_start = ata_bmdma_start,
123+
.bmdma_stop = ata_bmdma_stop,
124+
.bmdma_status = ata_bmdma_status,
125+
126+
.qc_prep = ata_qc_prep,
127+
.qc_issue = ata_qc_issue_prot,
128+
.data_xfer = ata_pio_data_xfer,
129+
130+
.freeze = ata_bmdma_freeze,
131+
.thaw = ata_bmdma_thaw,
132+
.error_handler = vt6420_error_handler,
133+
.post_internal_cmd = ata_bmdma_post_internal_cmd,
134+
135+
.irq_handler = ata_interrupt,
136+
.irq_clear = ata_bmdma_irq_clear,
137+
138+
.port_start = ata_port_start,
139+
.port_stop = ata_port_stop,
140+
.host_stop = ata_host_stop,
141+
};
142+
143+
static const struct ata_port_operations vt6421_sata_ops = {
112144
.port_disable = ata_port_disable,
113145

114146
.tf_load = ata_tf_load,
@@ -142,13 +174,13 @@ static const struct ata_port_operations svia_sata_ops = {
142174
.host_stop = ata_host_stop,
143175
};
144176

145-
static struct ata_port_info svia_port_info = {
177+
static struct ata_port_info vt6420_port_info = {
146178
.sht = &svia_sht,
147179
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
148180
.pio_mask = 0x1f,
149181
.mwdma_mask = 0x07,
150182
.udma_mask = 0x7f,
151-
.port_ops = &svia_sata_ops,
183+
.port_ops = &vt6420_sata_ops,
152184
};
153185

154186
MODULE_AUTHOR("Jeff Garzik");
@@ -171,6 +203,81 @@ static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
171203
outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
172204
}
173205

206+
/**
207+
* vt6420_prereset - prereset for vt6420
208+
* @ap: target ATA port
209+
*
210+
* SCR registers on vt6420 are pieces of shit and may hang the
211+
* whole machine completely if accessed with the wrong timing.
212+
* To avoid such catastrophe, vt6420 doesn't provide generic SCR
213+
* access operations, but uses SStatus and SControl only during
214+
* boot probing in controlled way.
215+
*
216+
* As the old (pre EH update) probing code is proven to work, we
217+
* strictly follow the access pattern.
218+
*
219+
* LOCKING:
220+
* Kernel thread context (may sleep)
221+
*
222+
* RETURNS:
223+
* 0 on success, -errno otherwise.
224+
*/
225+
static int vt6420_prereset(struct ata_port *ap)
226+
{
227+
struct ata_eh_context *ehc = &ap->eh_context;
228+
unsigned long timeout = jiffies + (HZ * 5);
229+
u32 sstatus, scontrol;
230+
int online;
231+
232+
/* don't do any SCR stuff if we're not loading */
233+
if (!ATA_PFLAG_LOADING)
234+
goto skip_scr;
235+
236+
/* Resume phy. This is the old resume sequence from
237+
* __sata_phy_reset().
238+
*/
239+
svia_scr_write(ap, SCR_CONTROL, 0x300);
240+
svia_scr_read(ap, SCR_CONTROL); /* flush */
241+
242+
/* wait for phy to become ready, if necessary */
243+
do {
244+
msleep(200);
245+
if ((svia_scr_read(ap, SCR_STATUS) & 0xf) != 1)
246+
break;
247+
} while (time_before(jiffies, timeout));
248+
249+
/* open code sata_print_link_status() */
250+
sstatus = svia_scr_read(ap, SCR_STATUS);
251+
scontrol = svia_scr_read(ap, SCR_CONTROL);
252+
253+
online = (sstatus & 0xf) == 0x3;
254+
255+
ata_port_printk(ap, KERN_INFO,
256+
"SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
257+
online ? "up" : "down", sstatus, scontrol);
258+
259+
/* SStatus is read one more time */
260+
svia_scr_read(ap, SCR_STATUS);
261+
262+
if (!online) {
263+
/* tell EH to bail */
264+
ehc->i.action &= ~ATA_EH_RESET_MASK;
265+
return 0;
266+
}
267+
268+
skip_scr:
269+
/* wait for !BSY */
270+
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
271+
272+
return 0;
273+
}
274+
275+
static void vt6420_error_handler(struct ata_port *ap)
276+
{
277+
return ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset,
278+
NULL, ata_std_postreset);
279+
}
280+
174281
static const unsigned int svia_bar_sizes[] = {
175282
8, 4, 8, 4, 16, 256
176283
};
@@ -211,7 +318,7 @@ static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
211318
static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
212319
{
213320
struct ata_probe_ent *probe_ent;
214-
struct ata_port_info *ppi = &svia_port_info;
321+
struct ata_port_info *ppi = &vt6420_port_info;
215322

216323
probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
217324
if (!probe_ent)
@@ -240,7 +347,7 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
240347

241348
probe_ent->sht = &svia_sht;
242349
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
243-
probe_ent->port_ops = &svia_sata_ops;
350+
probe_ent->port_ops = &vt6421_sata_ops;
244351
probe_ent->n_ports = N_PORTS;
245352
probe_ent->irq = pdev->irq;
246353
probe_ent->irq_flags = IRQF_SHARED;

0 commit comments

Comments
 (0)