aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_sis.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-09-01 10:19:10 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-09-08 21:17:36 -0400
commit72fee3823d2938fa98f2f3113301f46803f4c711 (patch)
tree3acf7bfd1a6d2690c7a0ade426720a255343c5b4 /drivers/ata/sata_sis.c
parent4f1a0ee11d6f9c104c8e6a13dae995709a6922a8 (diff)
sata_sis: convert to slave_link
During introduction of slave_link, sata_sis slipped through the crack and left with ad-hoc merged SCR access. As SCR status was shared for both the master and slave devices, when only one of the device is online, libata EH would think both are online but would only get valid device signature for the actually present one, which in turn trigger the probing safety net mechanism and make EH retry causing large delay during boot. This patch converts sata_sis to slave_link mechanism. This bug was reported by TAXI in bko#14075. http://bugzilla.kernel.org/show_bug.cgi?id=14075 Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: TAXI <taxi@a-city.de> Cc: Uwe Koziolek <uwe.koziolek@gmx.net> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_sis.c')
-rw-r--r--drivers/ata/sata_sis.c75
1 files changed, 25 insertions, 50 deletions
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 8f9833228619..f8a91bfd66a8 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -109,8 +109,9 @@ MODULE_LICENSE("GPL");
109MODULE_DEVICE_TABLE(pci, sis_pci_tbl); 109MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
110MODULE_VERSION(DRV_VERSION); 110MODULE_VERSION(DRV_VERSION);
111 111
112static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) 112static unsigned int get_scr_cfg_addr(struct ata_link *link, unsigned int sc_reg)
113{ 113{
114 struct ata_port *ap = link->ap;
114 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 115 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
115 unsigned int addr = SIS_SCR_BASE + (4 * sc_reg); 116 unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
116 u8 pmr; 117 u8 pmr;
@@ -131,6 +132,9 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
131 break; 132 break;
132 } 133 }
133 } 134 }
135 if (link->pmp)
136 addr += 0x10;
137
134 return addr; 138 return addr;
135} 139}
136 140
@@ -138,24 +142,12 @@ static u32 sis_scr_cfg_read(struct ata_link *link,
138 unsigned int sc_reg, u32 *val) 142 unsigned int sc_reg, u32 *val)
139{ 143{
140 struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); 144 struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
141 unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg); 145 unsigned int cfg_addr = get_scr_cfg_addr(link, sc_reg);
142 u32 val2 = 0;
143 u8 pmr;
144 146
145 if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ 147 if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
146 return -EINVAL; 148 return -EINVAL;
147 149
148 pci_read_config_byte(pdev, SIS_PMR, &pmr);
149
150 pci_read_config_dword(pdev, cfg_addr, val); 150 pci_read_config_dword(pdev, cfg_addr, val);
151
152 if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
153 (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
154 pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
155
156 *val |= val2;
157 *val &= 0xfffffffb; /* avoid problems with powerdowned ports */
158
159 return 0; 151 return 0;
160} 152}
161 153
@@ -163,28 +155,16 @@ static int sis_scr_cfg_write(struct ata_link *link,
163 unsigned int sc_reg, u32 val) 155 unsigned int sc_reg, u32 val)
164{ 156{
165 struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); 157 struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
166 unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg); 158 unsigned int cfg_addr = get_scr_cfg_addr(link, sc_reg);
167 u8 pmr;
168
169 if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
170 return -EINVAL;
171
172 pci_read_config_byte(pdev, SIS_PMR, &pmr);
173 159
174 pci_write_config_dword(pdev, cfg_addr, val); 160 pci_write_config_dword(pdev, cfg_addr, val);
175
176 if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
177 (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
178 pci_write_config_dword(pdev, cfg_addr+0x10, val);
179
180 return 0; 161 return 0;
181} 162}
182 163
183static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) 164static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
184{ 165{
185 struct ata_port *ap = link->ap; 166 struct ata_port *ap = link->ap;
186 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 167 void __iomem *base = ap->ioaddr.scr_addr + link->pmp * 0x10;
187 u8 pmr;
188 168
189 if (sc_reg > SCR_CONTROL) 169 if (sc_reg > SCR_CONTROL)
190 return -EINVAL; 170 return -EINVAL;
@@ -192,39 +172,23 @@ static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
192 if (ap->flags & SIS_FLAG_CFGSCR) 172 if (ap->flags & SIS_FLAG_CFGSCR)
193 return sis_scr_cfg_read(link, sc_reg, val); 173 return sis_scr_cfg_read(link, sc_reg, val);
194 174
195 pci_read_config_byte(pdev, SIS_PMR, &pmr); 175 *val = ioread32(base + sc_reg * 4);
196
197 *val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
198
199 if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
200 (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
201 *val |= ioread32(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
202
203 *val &= 0xfffffffb;
204
205 return 0; 176 return 0;
206} 177}
207 178
208static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) 179static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
209{ 180{
210 struct ata_port *ap = link->ap; 181 struct ata_port *ap = link->ap;
211 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 182 void __iomem *base = ap->ioaddr.scr_addr + link->pmp * 0x10;
212 u8 pmr;
213 183
214 if (sc_reg > SCR_CONTROL) 184 if (sc_reg > SCR_CONTROL)
215 return -EINVAL; 185 return -EINVAL;
216 186
217 pci_read_config_byte(pdev, SIS_PMR, &pmr);
218
219 if (ap->flags & SIS_FLAG_CFGSCR) 187 if (ap->flags & SIS_FLAG_CFGSCR)
220 return sis_scr_cfg_write(link, sc_reg, val); 188 return sis_scr_cfg_write(link, sc_reg, val);
221 else { 189
222 iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)); 190 iowrite32(val, base + (sc_reg * 4));
223 if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || 191 return 0;
224 (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
225 iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
226 return 0;
227 }
228} 192}
229 193
230static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 194static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -236,7 +200,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
236 u32 genctl, val; 200 u32 genctl, val;
237 u8 pmr; 201 u8 pmr;
238 u8 port2_start = 0x20; 202 u8 port2_start = 0x20;
239 int rc; 203 int i, rc;
240 204
241 if (!printed_version++) 205 if (!printed_version++)
242 dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); 206 dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
@@ -319,6 +283,17 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
319 if (rc) 283 if (rc)
320 return rc; 284 return rc;
321 285
286 for (i = 0; i < 2; i++) {
287 struct ata_port *ap = host->ports[i];
288
289 if (ap->flags & ATA_FLAG_SATA &&
290 ap->flags & ATA_FLAG_SLAVE_POSS) {
291 rc = ata_slave_link_init(ap);
292 if (rc)
293 return rc;
294 }
295 }
296
322 if (!(pi.flags & SIS_FLAG_CFGSCR)) { 297 if (!(pi.flags & SIS_FLAG_CFGSCR)) {
323 void __iomem *mmio; 298 void __iomem *mmio;
324 299