aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_via.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-08-24 02:51:38 -0400
committerJeff Garzik <jeff@garzik.org>2006-08-24 02:51:38 -0400
commit54a86bfc3d4601be9c36cd4e8a1bdc580c98fa6a (patch)
tree41956fc365923a8c85037c51b8085076d7d8a303 /drivers/ata/sata_via.c
parent81ce3c4b4d3771866ce74b1c3856b45c3e2549fc (diff)
parentac2164d5e425fa4755bdbab9641d8dab7239b6f5 (diff)
Merge branch 'upstream-fixes' into upstream
Diffstat (limited to 'drivers/ata/sata_via.c')
-rw-r--r--drivers/ata/sata_via.c117
1 files changed, 112 insertions, 5 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 6529189a2880..a0699a1728d4 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -74,6 +74,7 @@ enum {
74static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); 74static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
75static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg); 75static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
76static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); 76static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
77static void vt6420_error_handler(struct ata_port *ap);
77 78
78static const struct pci_device_id svia_pci_tbl[] = { 79static const struct pci_device_id svia_pci_tbl[] = {
79 { 0x1106, 0x0591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 }, 80 { 0x1106, 0x0591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
@@ -108,7 +109,38 @@ static struct scsi_host_template svia_sht = {
108 .bios_param = ata_std_bios_param, 109 .bios_param = ata_std_bios_param,
109}; 110};
110 111
111static const struct ata_port_operations svia_sata_ops = { 112static 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
143static const struct ata_port_operations vt6421_sata_ops = {
112 .port_disable = ata_port_disable, 144 .port_disable = ata_port_disable,
113 145
114 .tf_load = ata_tf_load, 146 .tf_load = ata_tf_load,
@@ -142,13 +174,13 @@ static const struct ata_port_operations svia_sata_ops = {
142 .host_stop = ata_host_stop, 174 .host_stop = ata_host_stop,
143}; 175};
144 176
145static struct ata_port_info svia_port_info = { 177static struct ata_port_info vt6420_port_info = {
146 .sht = &svia_sht, 178 .sht = &svia_sht,
147 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, 179 .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
148 .pio_mask = 0x1f, 180 .pio_mask = 0x1f,
149 .mwdma_mask = 0x07, 181 .mwdma_mask = 0x07,
150 .udma_mask = 0x7f, 182 .udma_mask = 0x7f,
151 .port_ops = &svia_sata_ops, 183 .port_ops = &vt6420_sata_ops,
152}; 184};
153 185
154MODULE_AUTHOR("Jeff Garzik"); 186MODULE_AUTHOR("Jeff Garzik");
@@ -171,6 +203,81 @@ static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
171 outl(val, ap->ioaddr.scr_addr + (4 * sc_reg)); 203 outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
172} 204}
173 205
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 */
225static 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
275static 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
174static const unsigned int svia_bar_sizes[] = { 281static const unsigned int svia_bar_sizes[] = {
175 8, 4, 8, 4, 16, 256 282 8, 4, 8, 4, 16, 256
176}; 283};
@@ -211,7 +318,7 @@ static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
211static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev) 318static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
212{ 319{
213 struct ata_probe_ent *probe_ent; 320 struct ata_probe_ent *probe_ent;
214 struct ata_port_info *ppi = &svia_port_info; 321 struct ata_port_info *ppi = &vt6420_port_info;
215 322
216 probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); 323 probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
217 if (!probe_ent) 324 if (!probe_ent)
@@ -240,7 +347,7 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
240 347
241 probe_ent->sht = &svia_sht; 348 probe_ent->sht = &svia_sht;
242 probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; 349 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;
244 probe_ent->n_ports = N_PORTS; 351 probe_ent->n_ports = N_PORTS;
245 probe_ent->irq = pdev->irq; 352 probe_ent->irq = pdev->irq;
246 probe_ent->irq_flags = IRQF_SHARED; 353 probe_ent->irq_flags = IRQF_SHARED;