aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-10-27 22:08:47 -0400
committerJeff Garzik <jeff@garzik.org>2006-10-31 20:26:10 -0500
commitcf0e812f0e90ee496af072b136e8bd02770387e6 (patch)
tree2396b3407663ba2e3567c8b20fe1bdf077e51648
parentd5b9b787b5e1618dfe82a2c2a6972374e85b02db (diff)
[PATCH] sata_sis: fix flags handling for the secondary port
sis_init_one() modifies probe_ent->port_flags after allocating and initializing it using ata_pci_init_native_mode(). This makes port_flags for the secondary port (probe_ent->pinfo2->flags) go out of sync resulting in misdetection of device due to incorrectly initialized SCR access flag. This patch make probe_ent alloc/init happen after the final port flags value is determined. This is fragile but probe_ent and all the related mess are scheduled to go away soon for exactly this reason. We just need to hold everything together till then. This has been spotted and diagnosed and tested by Patrick McHardy. Signed-off-by: Tejun Heo <htejun@gmail.com> Cc: Patric McHardy <kaber@trash.net> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/sata_sis.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 0738f52463a9..9d1235ba06b1 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -240,7 +240,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
240 struct ata_probe_ent *probe_ent = NULL; 240 struct ata_probe_ent *probe_ent = NULL;
241 int rc; 241 int rc;
242 u32 genctl; 242 u32 genctl;
243 struct ata_port_info *ppi[2]; 243 struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi };
244 int pci_dev_busy = 0; 244 int pci_dev_busy = 0;
245 u8 pmr; 245 u8 pmr;
246 u8 port2_start; 246 u8 port2_start;
@@ -265,27 +265,20 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
265 if (rc) 265 if (rc)
266 goto err_out_regions; 266 goto err_out_regions;
267 267
268 ppi[0] = ppi[1] = &sis_port_info;
269 probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
270 if (!probe_ent) {
271 rc = -ENOMEM;
272 goto err_out_regions;
273 }
274
275 /* check and see if the SCRs are in IO space or PCI cfg space */ 268 /* check and see if the SCRs are in IO space or PCI cfg space */
276 pci_read_config_dword(pdev, SIS_GENCTL, &genctl); 269 pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
277 if ((genctl & GENCTL_IOMAPPED_SCR) == 0) 270 if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
278 probe_ent->port_flags |= SIS_FLAG_CFGSCR; 271 pi.flags |= SIS_FLAG_CFGSCR;
279 272
280 /* if hardware thinks SCRs are in IO space, but there are 273 /* if hardware thinks SCRs are in IO space, but there are
281 * no IO resources assigned, change to PCI cfg space. 274 * no IO resources assigned, change to PCI cfg space.
282 */ 275 */
283 if ((!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) && 276 if ((!(pi.flags & SIS_FLAG_CFGSCR)) &&
284 ((pci_resource_start(pdev, SIS_SCR_PCI_BAR) == 0) || 277 ((pci_resource_start(pdev, SIS_SCR_PCI_BAR) == 0) ||
285 (pci_resource_len(pdev, SIS_SCR_PCI_BAR) < 128))) { 278 (pci_resource_len(pdev, SIS_SCR_PCI_BAR) < 128))) {
286 genctl &= ~GENCTL_IOMAPPED_SCR; 279 genctl &= ~GENCTL_IOMAPPED_SCR;
287 pci_write_config_dword(pdev, SIS_GENCTL, genctl); 280 pci_write_config_dword(pdev, SIS_GENCTL, genctl);
288 probe_ent->port_flags |= SIS_FLAG_CFGSCR; 281 pi.flags |= SIS_FLAG_CFGSCR;
289 } 282 }
290 283
291 pci_read_config_byte(pdev, SIS_PMR, &pmr); 284 pci_read_config_byte(pdev, SIS_PMR, &pmr);
@@ -306,6 +299,12 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
306 port2_start = 0x20; 299 port2_start = 0x20;
307 } 300 }
308 301
302 probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
303 if (!probe_ent) {
304 rc = -ENOMEM;
305 goto err_out_regions;
306 }
307
309 if (!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) { 308 if (!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) {
310 probe_ent->port[0].scr_addr = 309 probe_ent->port[0].scr_addr =
311 pci_resource_start(pdev, SIS_SCR_PCI_BAR); 310 pci_resource_start(pdev, SIS_SCR_PCI_BAR);