]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From b78152e9dbab6d6175e2adcbd8c62959e8f0f922 Mon Sep 17 00:00:00 2001 |
2 | From: Tejun Heo <tj@kernel.org> | |
3 | Date: Wed, 22 Oct 2008 00:45:57 +0900 | |
4 | Subject: [PATCH] sata_via: load DEVICE register when CTL changes | |
5 | References: bnc#441718 | |
6 | ||
7 | VIA controllers clear DEVICE register when IEN changes. Make sure | |
8 | DEVICE is updated along with CTL. | |
9 | ||
10 | This change is separated from Joseph Chan's larger patch. | |
11 | ||
12 | http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640 | |
13 | ||
14 | Signed-off-by: Tejun Heo <tj@kernel.org> | |
15 | Cc: Joseph Chan <JosephChan@via.com.tw> | |
16 | Signed-off-by: Jeff Garzik <jgarzik@redhat.com> | |
17 | Signed-off-by: Tejun Heo <teheo@suse.de> | |
18 | --- | |
19 | drivers/ata/sata_via.c | 35 ++++++++++++++++++++++++++++++++--- | |
20 | 1 files changed, 32 insertions(+), 3 deletions(-) | |
21 | ||
22 | diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c | |
23 | index 1cfa745..5b72e73 100644 | |
24 | --- a/drivers/ata/sata_via.c | |
25 | +++ b/drivers/ata/sata_via.c | |
26 | @@ -70,6 +70,7 @@ enum { | |
27 | static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | |
28 | static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); | |
29 | static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); | |
30 | +static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); | |
31 | static void svia_noop_freeze(struct ata_port *ap); | |
32 | static int vt6420_prereset(struct ata_link *link, unsigned long deadline); | |
33 | static int vt6421_pata_cable_detect(struct ata_port *ap); | |
34 | @@ -103,21 +104,26 @@ static struct scsi_host_template svia_sht = { | |
35 | ATA_BMDMA_SHT(DRV_NAME), | |
36 | }; | |
37 | ||
38 | -static struct ata_port_operations vt6420_sata_ops = { | |
39 | +static struct ata_port_operations svia_base_ops = { | |
40 | .inherits = &ata_bmdma_port_ops, | |
41 | + .sff_tf_load = svia_tf_load, | |
42 | +}; | |
43 | + | |
44 | +static struct ata_port_operations vt6420_sata_ops = { | |
45 | + .inherits = &svia_base_ops, | |
46 | .freeze = svia_noop_freeze, | |
47 | .prereset = vt6420_prereset, | |
48 | }; | |
49 | ||
50 | static struct ata_port_operations vt6421_pata_ops = { | |
51 | - .inherits = &ata_bmdma_port_ops, | |
52 | + .inherits = &svia_base_ops, | |
53 | .cable_detect = vt6421_pata_cable_detect, | |
54 | .set_piomode = vt6421_set_pio_mode, | |
55 | .set_dmamode = vt6421_set_dma_mode, | |
56 | }; | |
57 | ||
58 | static struct ata_port_operations vt6421_sata_ops = { | |
59 | - .inherits = &ata_bmdma_port_ops, | |
60 | + .inherits = &svia_base_ops, | |
61 | .scr_read = svia_scr_read, | |
62 | .scr_write = svia_scr_write, | |
63 | }; | |
64 | @@ -168,6 +174,29 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) | |
65 | return 0; | |
66 | } | |
67 | ||
68 | +/** | |
69 | + * svia_tf_load - send taskfile registers to host controller | |
70 | + * @ap: Port to which output is sent | |
71 | + * @tf: ATA taskfile register set | |
72 | + * | |
73 | + * Outputs ATA taskfile to standard ATA host controller. | |
74 | + * | |
75 | + * This is to fix the internal bug of via chipsets, which will | |
76 | + * reset the device register after changing the IEN bit on ctl | |
77 | + * register. | |
78 | + */ | |
79 | +static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) | |
80 | +{ | |
81 | + struct ata_taskfile ttf; | |
82 | + | |
83 | + if (tf->ctl != ap->last_ctl) { | |
84 | + ttf = *tf; | |
85 | + ttf.flags |= ATA_TFLAG_DEVICE; | |
86 | + tf = &ttf; | |
87 | + } | |
88 | + ata_sff_tf_load(ap, tf); | |
89 | +} | |
90 | + | |
91 | static void svia_noop_freeze(struct ata_port *ap) | |
92 | { | |
93 | /* Some VIA controllers choke if ATA_NIEN is manipulated in | |
94 | -- | |
95 | 1.5.4.5 | |
96 |