diff options
| -rw-r--r-- | drivers/ata/libata-core.c | 41 | ||||
| -rw-r--r-- | drivers/ata/pata_ali.c | 40 | ||||
| -rw-r--r-- | include/linux/libata.h | 25 |
3 files changed, 83 insertions, 23 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 48519887f94a..be95fdb69726 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -326,6 +326,44 @@ static void ata_force_horkage(struct ata_device *dev) | |||
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | /** | 328 | /** |
| 329 | * atapi_cmd_type - Determine ATAPI command type from SCSI opcode | ||
| 330 | * @opcode: SCSI opcode | ||
| 331 | * | ||
| 332 | * Determine ATAPI command type from @opcode. | ||
| 333 | * | ||
| 334 | * LOCKING: | ||
| 335 | * None. | ||
| 336 | * | ||
| 337 | * RETURNS: | ||
| 338 | * ATAPI_{READ|WRITE|READ_CD|PASS_THRU|MISC} | ||
| 339 | */ | ||
| 340 | int atapi_cmd_type(u8 opcode) | ||
| 341 | { | ||
| 342 | switch (opcode) { | ||
| 343 | case GPCMD_READ_10: | ||
| 344 | case GPCMD_READ_12: | ||
| 345 | return ATAPI_READ; | ||
| 346 | |||
| 347 | case GPCMD_WRITE_10: | ||
| 348 | case GPCMD_WRITE_12: | ||
| 349 | case GPCMD_WRITE_AND_VERIFY_10: | ||
| 350 | return ATAPI_WRITE; | ||
| 351 | |||
| 352 | case GPCMD_READ_CD: | ||
| 353 | case GPCMD_READ_CD_MSF: | ||
| 354 | return ATAPI_READ_CD; | ||
| 355 | |||
| 356 | case ATA_16: | ||
| 357 | case ATA_12: | ||
| 358 | if (atapi_passthru16) | ||
| 359 | return ATAPI_PASS_THRU; | ||
| 360 | /* fall thru */ | ||
| 361 | default: | ||
| 362 | return ATAPI_MISC; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | /** | ||
| 329 | * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure | 367 | * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure |
| 330 | * @tf: Taskfile to convert | 368 | * @tf: Taskfile to convert |
| 331 | * @pmp: Port multiplier port | 369 | * @pmp: Port multiplier port |
| @@ -2660,7 +2698,7 @@ int ata_bus_probe(struct ata_port *ap) | |||
| 2660 | specific sequence bass-ackwards so that PDIAG- is released by | 2698 | specific sequence bass-ackwards so that PDIAG- is released by |
| 2661 | the slave device */ | 2699 | the slave device */ |
| 2662 | 2700 | ||
| 2663 | ata_link_for_each_dev(dev, &ap->link) { | 2701 | ata_link_for_each_dev_reverse(dev, &ap->link) { |
| 2664 | if (tries[dev->devno]) | 2702 | if (tries[dev->devno]) |
| 2665 | dev->class = classes[dev->devno]; | 2703 | dev->class = classes[dev->devno]; |
| 2666 | 2704 | ||
| @@ -7774,6 +7812,7 @@ EXPORT_SYMBOL_GPL(ata_tf_read); | |||
| 7774 | EXPORT_SYMBOL_GPL(ata_noop_dev_select); | 7812 | EXPORT_SYMBOL_GPL(ata_noop_dev_select); |
| 7775 | EXPORT_SYMBOL_GPL(ata_std_dev_select); | 7813 | EXPORT_SYMBOL_GPL(ata_std_dev_select); |
| 7776 | EXPORT_SYMBOL_GPL(sata_print_link_status); | 7814 | EXPORT_SYMBOL_GPL(sata_print_link_status); |
| 7815 | EXPORT_SYMBOL_GPL(atapi_cmd_type); | ||
| 7777 | EXPORT_SYMBOL_GPL(ata_tf_to_fis); | 7816 | EXPORT_SYMBOL_GPL(ata_tf_to_fis); |
| 7778 | EXPORT_SYMBOL_GPL(ata_tf_from_fis); | 7817 | EXPORT_SYMBOL_GPL(ata_tf_from_fis); |
| 7779 | EXPORT_SYMBOL_GPL(ata_pack_xfermask); | 7818 | EXPORT_SYMBOL_GPL(ata_pack_xfermask); |
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 8786455c901d..ce830fe3a362 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c | |||
| @@ -36,6 +36,10 @@ | |||
| 36 | #define DRV_NAME "pata_ali" | 36 | #define DRV_NAME "pata_ali" |
| 37 | #define DRV_VERSION "0.7.5" | 37 | #define DRV_VERSION "0.7.5" |
| 38 | 38 | ||
| 39 | int ali_atapi_dma = 0; | ||
| 40 | module_param_named(atapi_dma, ali_atapi_dma, int, 0644); | ||
| 41 | MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)"); | ||
| 42 | |||
| 39 | /* | 43 | /* |
| 40 | * Cable special cases | 44 | * Cable special cases |
| 41 | */ | 45 | */ |
| @@ -270,6 +274,27 @@ static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
| 270 | } | 274 | } |
| 271 | 275 | ||
| 272 | /** | 276 | /** |
| 277 | * ali_warn_atapi_dma - Warn about ATAPI DMA disablement | ||
| 278 | * @adev: Device | ||
| 279 | * | ||
| 280 | * Whine about ATAPI DMA disablement if @adev is an ATAPI device. | ||
| 281 | * Can be used as ->dev_config. | ||
| 282 | */ | ||
| 283 | |||
| 284 | static void ali_warn_atapi_dma(struct ata_device *adev) | ||
| 285 | { | ||
| 286 | struct ata_eh_context *ehc = &adev->link->eh_context; | ||
| 287 | int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; | ||
| 288 | |||
| 289 | if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) { | ||
| 290 | ata_dev_printk(adev, KERN_WARNING, | ||
| 291 | "WARNING: ATAPI DMA disabled for reliablity issues. It can be enabled\n"); | ||
| 292 | ata_dev_printk(adev, KERN_WARNING, | ||
| 293 | "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n"); | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | /** | ||
| 273 | * ali_lock_sectors - Keep older devices to 255 sector mode | 298 | * ali_lock_sectors - Keep older devices to 255 sector mode |
| 274 | * @adev: Device | 299 | * @adev: Device |
| 275 | * | 300 | * |
| @@ -283,6 +308,7 @@ static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
| 283 | static void ali_lock_sectors(struct ata_device *adev) | 308 | static void ali_lock_sectors(struct ata_device *adev) |
| 284 | { | 309 | { |
| 285 | adev->max_sectors = 255; | 310 | adev->max_sectors = 255; |
| 311 | ali_warn_atapi_dma(adev); | ||
| 286 | } | 312 | } |
| 287 | 313 | ||
| 288 | /** | 314 | /** |
| @@ -294,6 +320,18 @@ static void ali_lock_sectors(struct ata_device *adev) | |||
| 294 | 320 | ||
| 295 | static int ali_check_atapi_dma(struct ata_queued_cmd *qc) | 321 | static int ali_check_atapi_dma(struct ata_queued_cmd *qc) |
| 296 | { | 322 | { |
| 323 | if (!ali_atapi_dma) { | ||
| 324 | /* FIXME: pata_ali can't do ATAPI DMA reliably but the | ||
| 325 | * IDE alim15x3 driver can. I tried lots of things | ||
| 326 | * but couldn't find what the actual difference was. | ||
| 327 | * If you got an idea, please write it to | ||
| 328 | * linux-ide@vger.kernel.org and cc htejun@gmail.com. | ||
| 329 | * | ||
| 330 | * Disable ATAPI DMA for now. | ||
| 331 | */ | ||
| 332 | return -EOPNOTSUPP; | ||
| 333 | } | ||
| 334 | |||
| 297 | /* If its not a media command, its not worth it */ | 335 | /* If its not a media command, its not worth it */ |
| 298 | if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC) | 336 | if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC) |
| 299 | return -EOPNOTSUPP; | 337 | return -EOPNOTSUPP; |
| @@ -359,6 +397,7 @@ static struct ata_port_operations ali_20_port_ops = { | |||
| 359 | 397 | ||
| 360 | .tf_load = ata_tf_load, | 398 | .tf_load = ata_tf_load, |
| 361 | .tf_read = ata_tf_read, | 399 | .tf_read = ata_tf_read, |
| 400 | .check_atapi_dma = ali_check_atapi_dma, | ||
| 362 | .check_status = ata_check_status, | 401 | .check_status = ata_check_status, |
| 363 | .exec_command = ata_exec_command, | 402 | .exec_command = ata_exec_command, |
| 364 | .dev_select = ata_std_dev_select, | 403 | .dev_select = ata_std_dev_select, |
| @@ -438,6 +477,7 @@ static struct ata_port_operations ali_c5_port_ops = { | |||
| 438 | .check_status = ata_check_status, | 477 | .check_status = ata_check_status, |
| 439 | .exec_command = ata_exec_command, | 478 | .exec_command = ata_exec_command, |
| 440 | .dev_select = ata_std_dev_select, | 479 | .dev_select = ata_std_dev_select, |
| 480 | .dev_config = ali_warn_atapi_dma, | ||
| 441 | 481 | ||
| 442 | .freeze = ata_bmdma_freeze, | 482 | .freeze = ata_bmdma_freeze, |
| 443 | .thaw = ata_bmdma_thaw, | 483 | .thaw = ata_bmdma_thaw, |
diff --git a/include/linux/libata.h b/include/linux/libata.h index b064bfeb69ee..37ee881c42ac 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -350,7 +350,8 @@ enum { | |||
| 350 | ATAPI_READ = 0, /* READs */ | 350 | ATAPI_READ = 0, /* READs */ |
| 351 | ATAPI_WRITE = 1, /* WRITEs */ | 351 | ATAPI_WRITE = 1, /* WRITEs */ |
| 352 | ATAPI_READ_CD = 2, /* READ CD [MSF] */ | 352 | ATAPI_READ_CD = 2, /* READ CD [MSF] */ |
| 353 | ATAPI_MISC = 3, /* the rest */ | 353 | ATAPI_PASS_THRU = 3, /* SAT pass-thru */ |
| 354 | ATAPI_MISC = 4, /* the rest */ | ||
| 354 | }; | 355 | }; |
| 355 | 356 | ||
| 356 | enum ata_xfer_mask { | 357 | enum ata_xfer_mask { |
| @@ -849,6 +850,7 @@ extern unsigned int ata_dev_try_classify(struct ata_device *dev, int present, | |||
| 849 | */ | 850 | */ |
| 850 | extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); | 851 | extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); |
| 851 | extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | 852 | extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf); |
| 853 | extern int atapi_cmd_type(u8 opcode); | ||
| 852 | extern void ata_tf_to_fis(const struct ata_taskfile *tf, | 854 | extern void ata_tf_to_fis(const struct ata_taskfile *tf, |
| 853 | u8 pmp, int is_cmd, u8 *fis); | 855 | u8 pmp, int is_cmd, u8 *fis); |
| 854 | extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf); | 856 | extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf); |
| @@ -1379,27 +1381,6 @@ static inline int ata_try_flush_cache(const struct ata_device *dev) | |||
| 1379 | ata_id_has_flush_ext(dev->id); | 1381 | ata_id_has_flush_ext(dev->id); |
| 1380 | } | 1382 | } |
| 1381 | 1383 | ||
| 1382 | static inline int atapi_cmd_type(u8 opcode) | ||
| 1383 | { | ||
| 1384 | switch (opcode) { | ||
| 1385 | case GPCMD_READ_10: | ||
| 1386 | case GPCMD_READ_12: | ||
| 1387 | return ATAPI_READ; | ||
| 1388 | |||
| 1389 | case GPCMD_WRITE_10: | ||
| 1390 | case GPCMD_WRITE_12: | ||
| 1391 | case GPCMD_WRITE_AND_VERIFY_10: | ||
| 1392 | return ATAPI_WRITE; | ||
| 1393 | |||
| 1394 | case GPCMD_READ_CD: | ||
| 1395 | case GPCMD_READ_CD_MSF: | ||
| 1396 | return ATAPI_READ_CD; | ||
| 1397 | |||
| 1398 | default: | ||
| 1399 | return ATAPI_MISC; | ||
| 1400 | } | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | static inline unsigned int ac_err_mask(u8 status) | 1384 | static inline unsigned int ac_err_mask(u8 status) |
| 1404 | { | 1385 | { |
| 1405 | if (status & (ATA_BUSY | ATA_DRQ)) | 1386 | if (status & (ATA_BUSY | ATA_DRQ)) |
