diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
| -rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index e1a395b438ee..4d3b704ede1c 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
| @@ -238,37 +238,43 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) | |||
| 238 | return true; | 238 | return true; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | static void sas_ata_phy_reset(struct ata_port *ap) | 241 | static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, |
| 242 | unsigned long deadline) | ||
| 242 | { | 243 | { |
| 244 | struct ata_port *ap = link->ap; | ||
| 243 | struct domain_device *dev = ap->private_data; | 245 | struct domain_device *dev = ap->private_data; |
| 244 | struct sas_internal *i = | 246 | struct sas_internal *i = |
| 245 | to_sas_internal(dev->port->ha->core.shost->transportt); | 247 | to_sas_internal(dev->port->ha->core.shost->transportt); |
| 246 | int res = TMF_RESP_FUNC_FAILED; | 248 | int res = TMF_RESP_FUNC_FAILED; |
| 249 | int ret = 0; | ||
| 247 | 250 | ||
| 248 | if (i->dft->lldd_I_T_nexus_reset) | 251 | if (i->dft->lldd_I_T_nexus_reset) |
| 249 | res = i->dft->lldd_I_T_nexus_reset(dev); | 252 | res = i->dft->lldd_I_T_nexus_reset(dev); |
| 250 | 253 | ||
| 251 | if (res != TMF_RESP_FUNC_COMPLETE) | 254 | if (res != TMF_RESP_FUNC_COMPLETE) { |
| 252 | SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__); | 255 | SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__); |
| 256 | ret = -EAGAIN; | ||
| 257 | } | ||
| 253 | 258 | ||
| 254 | switch (dev->sata_dev.command_set) { | 259 | switch (dev->sata_dev.command_set) { |
| 255 | case ATA_COMMAND_SET: | 260 | case ATA_COMMAND_SET: |
| 256 | SAS_DPRINTK("%s: Found ATA device.\n", __func__); | 261 | SAS_DPRINTK("%s: Found ATA device.\n", __func__); |
| 257 | ap->link.device[0].class = ATA_DEV_ATA; | 262 | *class = ATA_DEV_ATA; |
| 258 | break; | 263 | break; |
| 259 | case ATAPI_COMMAND_SET: | 264 | case ATAPI_COMMAND_SET: |
| 260 | SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); | 265 | SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); |
| 261 | ap->link.device[0].class = ATA_DEV_ATAPI; | 266 | *class = ATA_DEV_ATAPI; |
| 262 | break; | 267 | break; |
| 263 | default: | 268 | default: |
| 264 | SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", | 269 | SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", |
| 265 | __func__, | 270 | __func__, |
| 266 | dev->sata_dev.command_set); | 271 | dev->sata_dev.command_set); |
| 267 | ap->link.device[0].class = ATA_DEV_UNKNOWN; | 272 | *class = ATA_DEV_UNKNOWN; |
| 268 | break; | 273 | break; |
| 269 | } | 274 | } |
| 270 | 275 | ||
| 271 | ap->cbl = ATA_CBL_SATA; | 276 | ap->cbl = ATA_CBL_SATA; |
| 277 | return ret; | ||
| 272 | } | 278 | } |
| 273 | 279 | ||
| 274 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) | 280 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) |
| @@ -349,7 +355,11 @@ static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in, | |||
| 349 | } | 355 | } |
| 350 | 356 | ||
| 351 | static struct ata_port_operations sas_sata_ops = { | 357 | static struct ata_port_operations sas_sata_ops = { |
| 352 | .phy_reset = sas_ata_phy_reset, | 358 | .prereset = ata_std_prereset, |
| 359 | .softreset = NULL, | ||
| 360 | .hardreset = sas_ata_hard_reset, | ||
| 361 | .postreset = ata_std_postreset, | ||
| 362 | .error_handler = ata_std_error_handler, | ||
| 353 | .post_internal_cmd = sas_ata_post_internal, | 363 | .post_internal_cmd = sas_ata_post_internal, |
| 354 | .qc_defer = ata_std_qc_defer, | 364 | .qc_defer = ata_std_qc_defer, |
| 355 | .qc_prep = ata_noop_qc_prep, | 365 | .qc_prep = ata_noop_qc_prep, |
| @@ -362,10 +372,9 @@ static struct ata_port_operations sas_sata_ops = { | |||
| 362 | }; | 372 | }; |
| 363 | 373 | ||
| 364 | static struct ata_port_info sata_port_info = { | 374 | static struct ata_port_info sata_port_info = { |
| 365 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | | 375 | .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ, |
| 366 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ, | 376 | .pio_mask = ATA_PIO4, |
| 367 | .pio_mask = 0x1f, /* PIO0-4 */ | 377 | .mwdma_mask = ATA_MWDMA2, |
| 368 | .mwdma_mask = 0x07, /* MWDMA0-2 */ | ||
| 369 | .udma_mask = ATA_UDMA6, | 378 | .udma_mask = ATA_UDMA6, |
| 370 | .port_ops = &sas_sata_ops | 379 | .port_ops = &sas_sata_ops |
| 371 | }; | 380 | }; |
| @@ -781,3 +790,68 @@ int sas_discover_sata(struct domain_device *dev) | |||
| 781 | 790 | ||
| 782 | return res; | 791 | return res; |
| 783 | } | 792 | } |
| 793 | |||
| 794 | void sas_ata_strategy_handler(struct Scsi_Host *shost) | ||
| 795 | { | ||
| 796 | struct scsi_device *sdev; | ||
| 797 | |||
| 798 | shost_for_each_device(sdev, shost) { | ||
| 799 | struct domain_device *ddev = sdev_to_domain_dev(sdev); | ||
| 800 | struct ata_port *ap = ddev->sata_dev.ap; | ||
| 801 | |||
| 802 | if (!dev_is_sata(ddev)) | ||
| 803 | continue; | ||
| 804 | |||
| 805 | ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler"); | ||
| 806 | ata_scsi_port_error_handler(shost, ap); | ||
| 807 | } | ||
| 808 | } | ||
| 809 | |||
| 810 | int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task, | ||
| 811 | enum blk_eh_timer_return *rtn) | ||
| 812 | { | ||
| 813 | struct domain_device *ddev = cmd_to_domain_dev(cmd); | ||
| 814 | |||
| 815 | if (!dev_is_sata(ddev) || task) | ||
| 816 | return 0; | ||
| 817 | |||
| 818 | /* we're a sata device with no task, so this must be a libata | ||
| 819 | * eh timeout. Ideally should hook into libata timeout | ||
| 820 | * handling, but there's no point, it just wants to activate | ||
| 821 | * the eh thread */ | ||
| 822 | *rtn = BLK_EH_NOT_HANDLED; | ||
| 823 | return 1; | ||
| 824 | } | ||
| 825 | |||
| 826 | int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, | ||
| 827 | struct list_head *done_q) | ||
| 828 | { | ||
| 829 | int rtn = 0; | ||
| 830 | struct scsi_cmnd *cmd, *n; | ||
| 831 | struct ata_port *ap; | ||
| 832 | |||
| 833 | do { | ||
| 834 | LIST_HEAD(sata_q); | ||
| 835 | |||
| 836 | ap = NULL; | ||
| 837 | |||
| 838 | list_for_each_entry_safe(cmd, n, work_q, eh_entry) { | ||
| 839 | struct domain_device *ddev = cmd_to_domain_dev(cmd); | ||
| 840 | |||
| 841 | if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd)) | ||
| 842 | continue; | ||
| 843 | if(ap && ap != ddev->sata_dev.ap) | ||
| 844 | continue; | ||
| 845 | ap = ddev->sata_dev.ap; | ||
| 846 | rtn = 1; | ||
| 847 | list_move(&cmd->eh_entry, &sata_q); | ||
| 848 | } | ||
| 849 | |||
| 850 | if (!list_empty(&sata_q)) { | ||
| 851 | ata_port_printk(ap, KERN_DEBUG,"sas eh calling libata cmd error handler\n"); | ||
| 852 | ata_scsi_cmd_error_handler(shost, ap, &sata_q); | ||
| 853 | } | ||
| 854 | } while (ap); | ||
| 855 | |||
| 856 | return rtn; | ||
| 857 | } | ||
