diff options
author | Alan <alan@lxorguk.ukuu.org.uk> | 2006-11-22 12:23:37 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-01 22:46:46 -0500 |
commit | ad4a42d287546888349ad24d351673a59f429ee8 (patch) | |
tree | e8a5ae897be2ed04e095b566547ddda47b0ec605 /drivers/ata | |
parent | 34d8dfb1e6b51dbd6eefcb449b531c7ee773664c (diff) |
[PATCH] pata_rz1000: Force readahead off on resume
The RZ1000 is a generic device except that it has a readahead fifo flaw
that corrupts. We force this off at init time but we want to be paranoid
and force it off at resume as well. I don't know of any actual hardware
that supports both RZ1000 and suspend to RAM but given its a disk muncher
better safe than sorry.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/pata_rz1000.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index e4e5ea423fef..21567aba82d2 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/libata.h> | 21 | #include <linux/libata.h> |
22 | 22 | ||
23 | #define DRV_NAME "pata_rz1000" | 23 | #define DRV_NAME "pata_rz1000" |
24 | #define DRV_VERSION "0.2.2" | 24 | #define DRV_VERSION "0.2.3" |
25 | 25 | ||
26 | 26 | ||
27 | /** | 27 | /** |
@@ -92,6 +92,8 @@ static struct scsi_host_template rz1000_sht = { | |||
92 | .slave_configure = ata_scsi_slave_config, | 92 | .slave_configure = ata_scsi_slave_config, |
93 | .slave_destroy = ata_scsi_slave_destroy, | 93 | .slave_destroy = ata_scsi_slave_destroy, |
94 | .bios_param = ata_std_bios_param, | 94 | .bios_param = ata_std_bios_param, |
95 | .resume = ata_scsi_device_resume, | ||
96 | .suspend = ata_scsi_device_suspend, | ||
95 | }; | 97 | }; |
96 | 98 | ||
97 | static struct ata_port_operations rz1000_port_ops = { | 99 | static struct ata_port_operations rz1000_port_ops = { |
@@ -129,6 +131,19 @@ static struct ata_port_operations rz1000_port_ops = { | |||
129 | .host_stop = ata_host_stop | 131 | .host_stop = ata_host_stop |
130 | }; | 132 | }; |
131 | 133 | ||
134 | static int rz1000_fifo_disable(struct pci_dev *pdev) | ||
135 | { | ||
136 | u16 reg; | ||
137 | /* Be exceptionally paranoid as we must be sure to apply the fix */ | ||
138 | if (pci_read_config_word(pdev, 0x40, ®) != 0) | ||
139 | return -1; | ||
140 | reg &= 0xDFFF; | ||
141 | if (pci_write_config_word(pdev, 0x40, reg) != 0) | ||
142 | return -1; | ||
143 | printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
132 | /** | 147 | /** |
133 | * rz1000_init_one - Register RZ1000 ATA PCI device with kernel services | 148 | * rz1000_init_one - Register RZ1000 ATA PCI device with kernel services |
134 | * @pdev: PCI device to register | 149 | * @pdev: PCI device to register |
@@ -143,7 +158,6 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en | |||
143 | { | 158 | { |
144 | static int printed_version; | 159 | static int printed_version; |
145 | struct ata_port_info *port_info[2]; | 160 | struct ata_port_info *port_info[2]; |
146 | u16 reg; | ||
147 | static struct ata_port_info info = { | 161 | static struct ata_port_info info = { |
148 | .sht = &rz1000_sht, | 162 | .sht = &rz1000_sht, |
149 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, | 163 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, |
@@ -154,23 +168,25 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en | |||
154 | if (!printed_version++) | 168 | if (!printed_version++) |
155 | printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); | 169 | printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); |
156 | 170 | ||
157 | /* Be exceptionally paranoid as we must be sure to apply the fix */ | 171 | if (rz1000_fifo_disable(pdev) == 0) { |
158 | if (pci_read_config_word(pdev, 0x40, ®) != 0) | 172 | port_info[0] = &info; |
159 | goto fail; | 173 | port_info[1] = &info; |
160 | reg &= 0xDFFF; | 174 | return ata_pci_init_one(pdev, port_info, 2); |
161 | if (pci_write_config_word(pdev, 0x40, reg) != 0) | 175 | } |
162 | goto fail; | ||
163 | printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); | ||
164 | |||
165 | port_info[0] = &info; | ||
166 | port_info[1] = &info; | ||
167 | return ata_pci_init_one(pdev, port_info, 2); | ||
168 | fail: | ||
169 | printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); | 176 | printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); |
170 | /* Not safe to use so skip */ | 177 | /* Not safe to use so skip */ |
171 | return -ENODEV; | 178 | return -ENODEV; |
172 | } | 179 | } |
173 | 180 | ||
181 | static int rz1000_reinit_one(struct pci_dev *pdev) | ||
182 | { | ||
183 | /* If this fails on resume (which is a "cant happen" case), we | ||
184 | must stop as any progress risks data loss */ | ||
185 | if (rz1000_fifo_disable(pdev)) | ||
186 | panic("rz1000 fifo"); | ||
187 | return ata_pci_device_resume(pdev); | ||
188 | } | ||
189 | |||
174 | static const struct pci_device_id pata_rz1000[] = { | 190 | static const struct pci_device_id pata_rz1000[] = { |
175 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, | 191 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, |
176 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), }, | 192 | { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), }, |
@@ -182,7 +198,9 @@ static struct pci_driver rz1000_pci_driver = { | |||
182 | .name = DRV_NAME, | 198 | .name = DRV_NAME, |
183 | .id_table = pata_rz1000, | 199 | .id_table = pata_rz1000, |
184 | .probe = rz1000_init_one, | 200 | .probe = rz1000_init_one, |
185 | .remove = ata_pci_remove_one | 201 | .remove = ata_pci_remove_one, |
202 | .suspend = ata_pci_device_suspend, | ||
203 | .resume = rz1000_reinit_one, | ||
186 | }; | 204 | }; |
187 | 205 | ||
188 | static int __init rz1000_init(void) | 206 | static int __init rz1000_init(void) |