diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-01-28 11:08:23 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-02-01 12:26:40 -0500 |
commit | 92ba5d02d993ccf4a87b945779fe052f67c3c334 (patch) | |
tree | 83bec429c99badb5b95efadc3d4fefd14290c2e5 | |
parent | 4a537a5518e81dba342eccbffcfa5c27cb5781d4 (diff) |
pata_sl82c105: dual channel support
Use qc_defer to serialize the two channels
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/ata/pata_sl82c105.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 1388cef52c07..81ef207f8265 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/libata.h> | 26 | #include <linux/libata.h> |
27 | 27 | ||
28 | #define DRV_NAME "pata_sl82c105" | 28 | #define DRV_NAME "pata_sl82c105" |
29 | #define DRV_VERSION "0.3.2" | 29 | #define DRV_VERSION "0.3.3" |
30 | 30 | ||
31 | enum { | 31 | enum { |
32 | /* | 32 | /* |
@@ -206,6 +206,34 @@ static void sl82c105_bmdma_stop(struct ata_queued_cmd *qc) | |||
206 | sl82c105_set_piomode(ap, qc->dev); | 206 | sl82c105_set_piomode(ap, qc->dev); |
207 | } | 207 | } |
208 | 208 | ||
209 | /** | ||
210 | * sl82c105_qc_defer - implement serialization | ||
211 | * @qc: command | ||
212 | * | ||
213 | * We must issue one command per host not per channel because | ||
214 | * of the reset bug. | ||
215 | * | ||
216 | * Q: is the scsi host lock sufficient ? | ||
217 | */ | ||
218 | |||
219 | static int sl82c105_qc_defer(struct ata_queued_cmd *qc) | ||
220 | { | ||
221 | struct ata_host *host = qc->ap->host; | ||
222 | struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; | ||
223 | int rc; | ||
224 | |||
225 | /* First apply the usual rules */ | ||
226 | rc = ata_std_qc_defer(qc); | ||
227 | if (rc != 0) | ||
228 | return rc; | ||
229 | |||
230 | /* Now apply serialization rules. Only allow a command if the | ||
231 | other channel state machine is idle */ | ||
232 | if (alt && alt->qc_active) | ||
233 | return ATA_DEFER_PORT; | ||
234 | return 0; | ||
235 | } | ||
236 | |||
209 | static struct scsi_host_template sl82c105_sht = { | 237 | static struct scsi_host_template sl82c105_sht = { |
210 | .module = THIS_MODULE, | 238 | .module = THIS_MODULE, |
211 | .name = DRV_NAME, | 239 | .name = DRV_NAME, |
@@ -245,6 +273,7 @@ static struct ata_port_operations sl82c105_port_ops = { | |||
245 | .bmdma_stop = sl82c105_bmdma_stop, | 273 | .bmdma_stop = sl82c105_bmdma_stop, |
246 | .bmdma_status = ata_bmdma_status, | 274 | .bmdma_status = ata_bmdma_status, |
247 | 275 | ||
276 | .qc_defer = sl82c105_qc_defer, | ||
248 | .qc_prep = ata_qc_prep, | 277 | .qc_prep = ata_qc_prep, |
249 | .qc_issue = ata_qc_issue_prot, | 278 | .qc_issue = ata_qc_issue_prot, |
250 | 279 | ||
@@ -312,7 +341,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id | |||
312 | }; | 341 | }; |
313 | /* for now use only the first port */ | 342 | /* for now use only the first port */ |
314 | const struct ata_port_info *ppi[] = { &info_early, | 343 | const struct ata_port_info *ppi[] = { &info_early, |
315 | &ata_dummy_port_info }; | 344 | NULL }; |
316 | u32 val; | 345 | u32 val; |
317 | int rev; | 346 | int rev; |
318 | 347 | ||