]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From be77e43abb433c2d6f2fc69352289e34dcbf040a Mon Sep 17 00:00:00 2001 |
2 | From: Tejun Heo <tj@kernel.org> | |
3 | Date: Thu, 31 Jul 2008 17:02:44 +0900 | |
4 | Subject: [PATCH] ata_piix: drop merged SCR access and use slave_link instead | |
5 | References: bnc#441420 | |
6 | ||
7 | Now that libata has slave_link, there's no need to keep ugly merged | |
8 | SCR access. Drop it and use slave_link instead. This results in | |
9 | simpler code and much better separate link handling for master and | |
10 | slave. | |
11 | ||
12 | Signed-off-by: Tejun Heo <tj@kernel.org> | |
13 | Signed-off-by: Jeff Garzik <jgarzik@redhat.com> | |
14 | Signed-off-by: Tejun Heo <teheo@suse.de> | |
15 | --- | |
16 | drivers/ata/ata_piix.c | 168 +++++++++++-------------------------------------- | |
17 | 1 file changed, 41 insertions(+), 127 deletions(-) | |
18 | ||
19 | --- a/drivers/ata/ata_piix.c | |
20 | +++ b/drivers/ata/ata_piix.c | |
21 | @@ -887,23 +887,9 @@ static void ich_set_dmamode(struct ata_p | |
22 | * Serial ATA Index/Data Pair Superset Registers access | |
23 | * | |
24 | * Beginning from ICH8, there's a sane way to access SCRs using index | |
25 | - * and data register pair located at BAR5. This creates an | |
26 | - * interesting problem of mapping two SCRs to one port. | |
27 | - * | |
28 | - * Although they have separate SCRs, the master and slave aren't | |
29 | - * independent enough to be treated as separate links - e.g. softreset | |
30 | - * resets both. Also, there's no protocol defined for hard resetting | |
31 | - * singled device sharing the virtual port (no defined way to acquire | |
32 | - * device signature). This is worked around by merging the SCR values | |
33 | - * into one sensible value and requesting follow-up SRST after | |
34 | - * hardreset. | |
35 | - * | |
36 | - * SCR merging is perfomed in nibbles which is the unit contents in | |
37 | - * SCRs are organized. If two values are equal, the value is used. | |
38 | - * When they differ, merge table which lists precedence of possible | |
39 | - * values is consulted and the first match or the last entry when | |
40 | - * nothing matches is used. When there's no merge table for the | |
41 | - * specific nibble, value from the first port is used. | |
42 | + * and data register pair located at BAR5 which means that we have | |
43 | + * separate SCRs for master and slave. This is handled using libata | |
44 | + * slave_link facility. | |
45 | */ | |
46 | static const int piix_sidx_map[] = { | |
47 | [SCR_STATUS] = 0, | |
48 | @@ -911,125 +897,38 @@ static const int piix_sidx_map[] = { | |
49 | [SCR_CONTROL] = 1, | |
50 | }; | |
51 | ||
52 | -static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg) | |
53 | +static void piix_sidpr_sel(struct ata_link *link, unsigned int reg) | |
54 | { | |
55 | - struct ata_port *ap = dev->link->ap; | |
56 | + struct ata_port *ap = link->ap; | |
57 | struct piix_host_priv *hpriv = ap->host->private_data; | |
58 | ||
59 | - iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg], | |
60 | + iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg], | |
61 | hpriv->sidpr + PIIX_SIDPR_IDX); | |
62 | } | |
63 | ||
64 | -static int piix_sidpr_read(struct ata_device *dev, unsigned int reg) | |
65 | -{ | |
66 | - struct piix_host_priv *hpriv = dev->link->ap->host->private_data; | |
67 | - | |
68 | - piix_sidpr_sel(dev, reg); | |
69 | - return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); | |
70 | -} | |
71 | - | |
72 | -static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val) | |
73 | -{ | |
74 | - struct piix_host_priv *hpriv = dev->link->ap->host->private_data; | |
75 | - | |
76 | - piix_sidpr_sel(dev, reg); | |
77 | - iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); | |
78 | -} | |
79 | - | |
80 | -static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl) | |
81 | -{ | |
82 | - u32 val = 0; | |
83 | - int i, mi; | |
84 | - | |
85 | - for (i = 0, mi = 0; i < 32 / 4; i++) { | |
86 | - u8 c0 = (val0 >> (i * 4)) & 0xf; | |
87 | - u8 c1 = (val1 >> (i * 4)) & 0xf; | |
88 | - u8 merged = c0; | |
89 | - const int *cur; | |
90 | - | |
91 | - /* if no merge preference, assume the first value */ | |
92 | - cur = merge_tbl[mi]; | |
93 | - if (!cur) | |
94 | - goto done; | |
95 | - mi++; | |
96 | - | |
97 | - /* if two values equal, use it */ | |
98 | - if (c0 == c1) | |
99 | - goto done; | |
100 | - | |
101 | - /* choose the first match or the last from the merge table */ | |
102 | - while (*cur != -1) { | |
103 | - if (c0 == *cur || c1 == *cur) | |
104 | - break; | |
105 | - cur++; | |
106 | - } | |
107 | - if (*cur == -1) | |
108 | - cur--; | |
109 | - merged = *cur; | |
110 | - done: | |
111 | - val |= merged << (i * 4); | |
112 | - } | |
113 | - | |
114 | - return val; | |
115 | -} | |
116 | - | |
117 | static int piix_sidpr_scr_read(struct ata_link *link, | |
118 | unsigned int reg, u32 *val) | |
119 | { | |
120 | - struct ata_port *ap = link->ap; | |
121 | - const int * const sstatus_merge_tbl[] = { | |
122 | - /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 }, | |
123 | - /* SPD */ (const int []){ 2, 1, 0, -1 }, | |
124 | - /* IPM */ (const int []){ 6, 2, 1, 0, -1 }, | |
125 | - NULL, | |
126 | - }; | |
127 | - const int * const scontrol_merge_tbl[] = { | |
128 | - /* DET */ (const int []){ 1, 0, 4, 0, -1 }, | |
129 | - /* SPD */ (const int []){ 0, 2, 1, 0, -1 }, | |
130 | - /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 }, | |
131 | - NULL, | |
132 | - }; | |
133 | - u32 v0, v1; | |
134 | + struct piix_host_priv *hpriv = link->ap->host->private_data; | |
135 | ||
136 | if (reg >= ARRAY_SIZE(piix_sidx_map)) | |
137 | return -EINVAL; | |
138 | ||
139 | - if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) { | |
140 | - *val = piix_sidpr_read(&ap->link.device[0], reg); | |
141 | - return 0; | |
142 | - } | |
143 | - | |
144 | - v0 = piix_sidpr_read(&ap->link.device[0], reg); | |
145 | - v1 = piix_sidpr_read(&ap->link.device[1], reg); | |
146 | - | |
147 | - switch (reg) { | |
148 | - case SCR_STATUS: | |
149 | - *val = piix_merge_scr(v0, v1, sstatus_merge_tbl); | |
150 | - break; | |
151 | - case SCR_ERROR: | |
152 | - *val = v0 | v1; | |
153 | - break; | |
154 | - case SCR_CONTROL: | |
155 | - *val = piix_merge_scr(v0, v1, scontrol_merge_tbl); | |
156 | - break; | |
157 | - } | |
158 | - | |
159 | + piix_sidpr_sel(link, reg); | |
160 | + *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); | |
161 | return 0; | |
162 | } | |
163 | ||
164 | static int piix_sidpr_scr_write(struct ata_link *link, | |
165 | unsigned int reg, u32 val) | |
166 | { | |
167 | - struct ata_port *ap = link->ap; | |
168 | + struct piix_host_priv *hpriv = link->ap->host->private_data; | |
169 | ||
170 | if (reg >= ARRAY_SIZE(piix_sidx_map)) | |
171 | return -EINVAL; | |
172 | ||
173 | - piix_sidpr_write(&ap->link.device[0], reg, val); | |
174 | - | |
175 | - if (ap->flags & ATA_FLAG_SLAVE_POSS) | |
176 | - piix_sidpr_write(&ap->link.device[1], reg, val); | |
177 | - | |
178 | + piix_sidpr_sel(link, reg); | |
179 | + iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); | |
180 | return 0; | |
181 | } | |
182 | ||
183 | @@ -1403,32 +1302,33 @@ static bool piix_no_sidpr(struct ata_hos | |
184 | return false; | |
185 | } | |
186 | ||
187 | -static void __devinit piix_init_sidpr(struct ata_host *host) | |
188 | +static int __devinit piix_init_sidpr(struct ata_host *host) | |
189 | { | |
190 | struct pci_dev *pdev = to_pci_dev(host->dev); | |
191 | struct piix_host_priv *hpriv = host->private_data; | |
192 | - struct ata_device *dev0 = &host->ports[0]->link.device[0]; | |
193 | + struct ata_link *link0 = &host->ports[0]->link; | |
194 | u32 scontrol; | |
195 | int i; | |
196 | + int rc; | |
197 | ||
198 | /* check for availability */ | |
199 | for (i = 0; i < 4; i++) | |
200 | if (hpriv->map[i] == IDE) | |
201 | - return; | |
202 | + return 0; | |
203 | ||
204 | /* is it blacklisted? */ | |
205 | if (piix_no_sidpr(host)) | |
206 | - return; | |
207 | + return 0; | |
208 | ||
209 | if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) | |
210 | - return; | |
211 | + return 0; | |
212 | ||
213 | if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 || | |
214 | pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN) | |
215 | - return; | |
216 | + return 0; | |
217 | ||
218 | if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME)) | |
219 | - return; | |
220 | + return 0; | |
221 | ||
222 | hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR]; | |
223 | ||
224 | @@ -1436,7 +1336,7 @@ static void __devinit piix_init_sidpr(st | |
225 | * Give it a test drive by inhibiting power save modes which | |
226 | * we'll do anyway. | |
227 | */ | |
228 | - scontrol = piix_sidpr_read(dev0, SCR_CONTROL); | |
229 | + piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); | |
230 | ||
231 | /* if IPM is already 3, SCR access is probably working. Don't | |
232 | * un-inhibit power save modes as BIOS might have inhibited | |
233 | @@ -1444,18 +1344,30 @@ static void __devinit piix_init_sidpr(st | |
234 | */ | |
235 | if ((scontrol & 0xf00) != 0x300) { | |
236 | scontrol |= 0x300; | |
237 | - piix_sidpr_write(dev0, SCR_CONTROL, scontrol); | |
238 | - scontrol = piix_sidpr_read(dev0, SCR_CONTROL); | |
239 | + piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol); | |
240 | + piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); | |
241 | ||
242 | if ((scontrol & 0xf00) != 0x300) { | |
243 | dev_printk(KERN_INFO, host->dev, "SCR access via " | |
244 | "SIDPR is available but doesn't work\n"); | |
245 | - return; | |
246 | + return 0; | |
247 | } | |
248 | } | |
249 | ||
250 | - host->ports[0]->ops = &piix_sidpr_sata_ops; | |
251 | - host->ports[1]->ops = &piix_sidpr_sata_ops; | |
252 | + /* okay, SCRs available, set ops and ask libata for slave_link */ | |
253 | + for (i = 0; i < 2; i++) { | |
254 | + struct ata_port *ap = host->ports[i]; | |
255 | + | |
256 | + ap->ops = &piix_sidpr_sata_ops; | |
257 | + | |
258 | + if (ap->flags & ATA_FLAG_SLAVE_POSS) { | |
259 | + rc = ata_slave_link_init(ap); | |
260 | + if (rc) | |
261 | + return rc; | |
262 | + } | |
263 | + } | |
264 | + | |
265 | + return 0; | |
266 | } | |
267 | ||
268 | static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) | |
269 | @@ -1565,7 +1477,9 @@ static int __devinit piix_init_one(struc | |
270 | /* initialize controller */ | |
271 | if (port_flags & ATA_FLAG_SATA) { | |
272 | piix_init_pcs(host, piix_map_db_table[ent->driver_data]); | |
273 | - piix_init_sidpr(host); | |
274 | + rc = piix_init_sidpr(host); | |
275 | + if (rc) | |
276 | + return rc; | |
277 | } | |
278 | ||
279 | /* apply IOCFG bit18 quirk */ |