Commit b91421749a1840148d8c81637c03c0ace3f35269
Committed by
James Bottomley
1 parent
41e1703b9b
Exists in
master
and in
7 other branches
[SCSI] libsas: make ATA functions selectable by a config option
Not everyone wants libsas automatically to pull in libata. This patch makes the behaviour configurable, so you can build libsas with or without ATA support. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Showing 6 changed files with 436 additions and 397 deletions Side-by-side Diff
drivers/scsi/libsas/Kconfig
... | ... | @@ -30,6 +30,13 @@ |
30 | 30 | This provides transport specific helpers for SAS drivers which |
31 | 31 | use the domain device construct (like the aic94xxx). |
32 | 32 | |
33 | +config SCSI_SAS_ATA | |
34 | + bool "ATA support for libsas (requires libata)" | |
35 | + depends on SCSI_SAS_LIBSAS && ATA | |
36 | + help | |
37 | + Builds in ATA support into libsas. Will necessitate | |
38 | + the loading of libata along with libsas. | |
39 | + | |
33 | 40 | config SCSI_SAS_LIBSAS_DEBUG |
34 | 41 | bool "Compile the SAS Domain Transport Attributes in debug mode" |
35 | 42 | default y |
drivers/scsi/libsas/Makefile
drivers/scsi/libsas/sas_ata.c
... | ... | @@ -21,6 +21,8 @@ |
21 | 21 | * USA |
22 | 22 | */ |
23 | 23 | |
24 | +#include <linux/scatterlist.h> | |
25 | + | |
24 | 26 | #include <scsi/sas_ata.h> |
25 | 27 | #include "sas_internal.h" |
26 | 28 | #include <scsi/scsi_host.h> |
... | ... | @@ -417,5 +419,400 @@ |
417 | 419 | qc->err_mask |= AC_ERR_TIMEOUT; |
418 | 420 | waiting = qc->private_data; |
419 | 421 | complete(waiting); |
422 | +} | |
423 | + | |
424 | +static void sas_task_timedout(unsigned long _task) | |
425 | +{ | |
426 | + struct sas_task *task = (void *) _task; | |
427 | + unsigned long flags; | |
428 | + | |
429 | + spin_lock_irqsave(&task->task_state_lock, flags); | |
430 | + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | |
431 | + task->task_state_flags |= SAS_TASK_STATE_ABORTED; | |
432 | + spin_unlock_irqrestore(&task->task_state_lock, flags); | |
433 | + | |
434 | + complete(&task->completion); | |
435 | +} | |
436 | + | |
437 | +static void sas_disc_task_done(struct sas_task *task) | |
438 | +{ | |
439 | + if (!del_timer(&task->timer)) | |
440 | + return; | |
441 | + complete(&task->completion); | |
442 | +} | |
443 | + | |
444 | +#define SAS_DEV_TIMEOUT 10 | |
445 | + | |
446 | +/** | |
447 | + * sas_execute_task -- Basic task processing for discovery | |
448 | + * @task: the task to be executed | |
449 | + * @buffer: pointer to buffer to do I/O | |
450 | + * @size: size of @buffer | |
451 | + * @pci_dma_dir: PCI_DMA_... | |
452 | + */ | |
453 | +static int sas_execute_task(struct sas_task *task, void *buffer, int size, | |
454 | + int pci_dma_dir) | |
455 | +{ | |
456 | + int res = 0; | |
457 | + struct scatterlist *scatter = NULL; | |
458 | + struct task_status_struct *ts = &task->task_status; | |
459 | + int num_scatter = 0; | |
460 | + int retries = 0; | |
461 | + struct sas_internal *i = | |
462 | + to_sas_internal(task->dev->port->ha->core.shost->transportt); | |
463 | + | |
464 | + if (pci_dma_dir != PCI_DMA_NONE) { | |
465 | + scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); | |
466 | + if (!scatter) | |
467 | + goto out; | |
468 | + | |
469 | + sg_init_one(scatter, buffer, size); | |
470 | + num_scatter = 1; | |
471 | + } | |
472 | + | |
473 | + task->task_proto = task->dev->tproto; | |
474 | + task->scatter = scatter; | |
475 | + task->num_scatter = num_scatter; | |
476 | + task->total_xfer_len = size; | |
477 | + task->data_dir = pci_dma_dir; | |
478 | + task->task_done = sas_disc_task_done; | |
479 | + if (pci_dma_dir != PCI_DMA_NONE && | |
480 | + sas_protocol_ata(task->task_proto)) { | |
481 | + task->num_scatter = pci_map_sg(task->dev->port->ha->pcidev, | |
482 | + task->scatter, | |
483 | + task->num_scatter, | |
484 | + task->data_dir); | |
485 | + } | |
486 | + | |
487 | + for (retries = 0; retries < 5; retries++) { | |
488 | + task->task_state_flags = SAS_TASK_STATE_PENDING; | |
489 | + init_completion(&task->completion); | |
490 | + | |
491 | + task->timer.data = (unsigned long) task; | |
492 | + task->timer.function = sas_task_timedout; | |
493 | + task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; | |
494 | + add_timer(&task->timer); | |
495 | + | |
496 | + res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); | |
497 | + if (res) { | |
498 | + del_timer(&task->timer); | |
499 | + SAS_DPRINTK("executing SAS discovery task failed:%d\n", | |
500 | + res); | |
501 | + goto ex_err; | |
502 | + } | |
503 | + wait_for_completion(&task->completion); | |
504 | + res = -ETASK; | |
505 | + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | |
506 | + int res2; | |
507 | + SAS_DPRINTK("task aborted, flags:0x%x\n", | |
508 | + task->task_state_flags); | |
509 | + res2 = i->dft->lldd_abort_task(task); | |
510 | + SAS_DPRINTK("came back from abort task\n"); | |
511 | + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | |
512 | + if (res2 == TMF_RESP_FUNC_COMPLETE) | |
513 | + continue; /* Retry the task */ | |
514 | + else | |
515 | + goto ex_err; | |
516 | + } | |
517 | + } | |
518 | + if (task->task_status.stat == SAM_BUSY || | |
519 | + task->task_status.stat == SAM_TASK_SET_FULL || | |
520 | + task->task_status.stat == SAS_QUEUE_FULL) { | |
521 | + SAS_DPRINTK("task: q busy, sleeping...\n"); | |
522 | + schedule_timeout_interruptible(HZ); | |
523 | + } else if (task->task_status.stat == SAM_CHECK_COND) { | |
524 | + struct scsi_sense_hdr shdr; | |
525 | + | |
526 | + if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, | |
527 | + &shdr)) { | |
528 | + SAS_DPRINTK("couldn't normalize sense\n"); | |
529 | + continue; | |
530 | + } | |
531 | + if ((shdr.sense_key == 6 && shdr.asc == 0x29) || | |
532 | + (shdr.sense_key == 2 && shdr.asc == 4 && | |
533 | + shdr.ascq == 1)) { | |
534 | + SAS_DPRINTK("device %016llx LUN: %016llx " | |
535 | + "powering up or not ready yet, " | |
536 | + "sleeping...\n", | |
537 | + SAS_ADDR(task->dev->sas_addr), | |
538 | + SAS_ADDR(task->ssp_task.LUN)); | |
539 | + | |
540 | + schedule_timeout_interruptible(5*HZ); | |
541 | + } else if (shdr.sense_key == 1) { | |
542 | + res = 0; | |
543 | + break; | |
544 | + } else if (shdr.sense_key == 5) { | |
545 | + break; | |
546 | + } else { | |
547 | + SAS_DPRINTK("dev %016llx LUN: %016llx " | |
548 | + "sense key:0x%x ASC:0x%x ASCQ:0x%x" | |
549 | + "\n", | |
550 | + SAS_ADDR(task->dev->sas_addr), | |
551 | + SAS_ADDR(task->ssp_task.LUN), | |
552 | + shdr.sense_key, | |
553 | + shdr.asc, shdr.ascq); | |
554 | + } | |
555 | + } else if (task->task_status.resp != SAS_TASK_COMPLETE || | |
556 | + task->task_status.stat != SAM_GOOD) { | |
557 | + SAS_DPRINTK("task finished with resp:0x%x, " | |
558 | + "stat:0x%x\n", | |
559 | + task->task_status.resp, | |
560 | + task->task_status.stat); | |
561 | + goto ex_err; | |
562 | + } else { | |
563 | + res = 0; | |
564 | + break; | |
565 | + } | |
566 | + } | |
567 | +ex_err: | |
568 | + if (pci_dma_dir != PCI_DMA_NONE) { | |
569 | + if (sas_protocol_ata(task->task_proto)) | |
570 | + pci_unmap_sg(task->dev->port->ha->pcidev, | |
571 | + task->scatter, task->num_scatter, | |
572 | + task->data_dir); | |
573 | + kfree(scatter); | |
574 | + } | |
575 | +out: | |
576 | + return res; | |
577 | +} | |
578 | + | |
579 | +/* ---------- SATA ---------- */ | |
580 | + | |
581 | +static void sas_get_ata_command_set(struct domain_device *dev) | |
582 | +{ | |
583 | + struct dev_to_host_fis *fis = | |
584 | + (struct dev_to_host_fis *) dev->frame_rcvd; | |
585 | + | |
586 | + if ((fis->sector_count == 1 && /* ATA */ | |
587 | + fis->lbal == 1 && | |
588 | + fis->lbam == 0 && | |
589 | + fis->lbah == 0 && | |
590 | + fis->device == 0) | |
591 | + || | |
592 | + (fis->sector_count == 0 && /* CE-ATA (mATA) */ | |
593 | + fis->lbal == 0 && | |
594 | + fis->lbam == 0xCE && | |
595 | + fis->lbah == 0xAA && | |
596 | + (fis->device & ~0x10) == 0)) | |
597 | + | |
598 | + dev->sata_dev.command_set = ATA_COMMAND_SET; | |
599 | + | |
600 | + else if ((fis->interrupt_reason == 1 && /* ATAPI */ | |
601 | + fis->lbal == 1 && | |
602 | + fis->byte_count_low == 0x14 && | |
603 | + fis->byte_count_high == 0xEB && | |
604 | + (fis->device & ~0x10) == 0)) | |
605 | + | |
606 | + dev->sata_dev.command_set = ATAPI_COMMAND_SET; | |
607 | + | |
608 | + else if ((fis->sector_count == 1 && /* SEMB */ | |
609 | + fis->lbal == 1 && | |
610 | + fis->lbam == 0x3C && | |
611 | + fis->lbah == 0xC3 && | |
612 | + fis->device == 0) | |
613 | + || | |
614 | + (fis->interrupt_reason == 1 && /* SATA PM */ | |
615 | + fis->lbal == 1 && | |
616 | + fis->byte_count_low == 0x69 && | |
617 | + fis->byte_count_high == 0x96 && | |
618 | + (fis->device & ~0x10) == 0)) | |
619 | + | |
620 | + /* Treat it as a superset? */ | |
621 | + dev->sata_dev.command_set = ATAPI_COMMAND_SET; | |
622 | +} | |
623 | + | |
624 | +/** | |
625 | + * sas_issue_ata_cmd -- Basic SATA command processing for discovery | |
626 | + * @dev: the device to send the command to | |
627 | + * @command: the command register | |
628 | + * @features: the features register | |
629 | + * @buffer: pointer to buffer to do I/O | |
630 | + * @size: size of @buffer | |
631 | + * @pci_dma_dir: PCI_DMA_... | |
632 | + */ | |
633 | +static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, | |
634 | + u8 features, void *buffer, int size, | |
635 | + int pci_dma_dir) | |
636 | +{ | |
637 | + int res = 0; | |
638 | + struct sas_task *task; | |
639 | + struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) | |
640 | + &dev->frame_rcvd[0]; | |
641 | + | |
642 | + res = -ENOMEM; | |
643 | + task = sas_alloc_task(GFP_KERNEL); | |
644 | + if (!task) | |
645 | + goto out; | |
646 | + | |
647 | + task->dev = dev; | |
648 | + | |
649 | + task->ata_task.fis.fis_type = 0x27; | |
650 | + task->ata_task.fis.command = command; | |
651 | + task->ata_task.fis.features = features; | |
652 | + task->ata_task.fis.device = d2h_fis->device; | |
653 | + task->ata_task.retry_count = 1; | |
654 | + | |
655 | + res = sas_execute_task(task, buffer, size, pci_dma_dir); | |
656 | + | |
657 | + sas_free_task(task); | |
658 | +out: | |
659 | + return res; | |
660 | +} | |
661 | + | |
662 | +static void sas_sata_propagate_sas_addr(struct domain_device *dev) | |
663 | +{ | |
664 | + unsigned long flags; | |
665 | + struct asd_sas_port *port = dev->port; | |
666 | + struct asd_sas_phy *phy; | |
667 | + | |
668 | + BUG_ON(dev->parent); | |
669 | + | |
670 | + memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | |
671 | + spin_lock_irqsave(&port->phy_list_lock, flags); | |
672 | + list_for_each_entry(phy, &port->phy_list, port_phy_el) | |
673 | + memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | |
674 | + spin_unlock_irqrestore(&port->phy_list_lock, flags); | |
675 | +} | |
676 | + | |
677 | +#define ATA_IDENTIFY_DEV 0xEC | |
678 | +#define ATA_IDENTIFY_PACKET_DEV 0xA1 | |
679 | +#define ATA_SET_FEATURES 0xEF | |
680 | +#define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 | |
681 | + | |
682 | +/** | |
683 | + * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) | |
684 | + * @dev: STP/SATA device of interest (ATA/ATAPI) | |
685 | + * | |
686 | + * The LLDD has already been notified of this device, so that we can | |
687 | + * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY | |
688 | + * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its | |
689 | + * performance for this device. | |
690 | + */ | |
691 | +static int sas_discover_sata_dev(struct domain_device *dev) | |
692 | +{ | |
693 | + int res; | |
694 | + __le16 *identify_x; | |
695 | + u8 command; | |
696 | + | |
697 | + identify_x = kzalloc(512, GFP_KERNEL); | |
698 | + if (!identify_x) | |
699 | + return -ENOMEM; | |
700 | + | |
701 | + if (dev->sata_dev.command_set == ATA_COMMAND_SET) { | |
702 | + dev->sata_dev.identify_device = identify_x; | |
703 | + command = ATA_IDENTIFY_DEV; | |
704 | + } else { | |
705 | + dev->sata_dev.identify_packet_device = identify_x; | |
706 | + command = ATA_IDENTIFY_PACKET_DEV; | |
707 | + } | |
708 | + | |
709 | + res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | |
710 | + PCI_DMA_FROMDEVICE); | |
711 | + if (res) | |
712 | + goto out_err; | |
713 | + | |
714 | + /* lives on the media? */ | |
715 | + if (le16_to_cpu(identify_x[0]) & 4) { | |
716 | + /* incomplete response */ | |
717 | + SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " | |
718 | + "dev %llx\n", SAS_ADDR(dev->sas_addr)); | |
719 | + if (!le16_to_cpu(identify_x[83] & (1<<6))) | |
720 | + goto cont1; | |
721 | + res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, | |
722 | + ATA_FEATURE_PUP_STBY_SPIN_UP, | |
723 | + NULL, 0, PCI_DMA_NONE); | |
724 | + if (res) | |
725 | + goto cont1; | |
726 | + | |
727 | + schedule_timeout_interruptible(5*HZ); /* More time? */ | |
728 | + res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | |
729 | + PCI_DMA_FROMDEVICE); | |
730 | + if (res) | |
731 | + goto out_err; | |
732 | + } | |
733 | +cont1: | |
734 | + /* Get WWN */ | |
735 | + if (dev->port->oob_mode != SATA_OOB_MODE) { | |
736 | + memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, | |
737 | + SAS_ADDR_SIZE); | |
738 | + } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && | |
739 | + (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) | |
740 | + == 0x5000) { | |
741 | + int i; | |
742 | + | |
743 | + for (i = 0; i < 4; i++) { | |
744 | + dev->sas_addr[2*i] = | |
745 | + (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; | |
746 | + dev->sas_addr[2*i+1] = | |
747 | + le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; | |
748 | + } | |
749 | + } | |
750 | + sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); | |
751 | + if (!dev->parent) | |
752 | + sas_sata_propagate_sas_addr(dev); | |
753 | + | |
754 | + /* XXX Hint: register this SATA device with SATL. | |
755 | + When this returns, dev->sata_dev->lu is alive and | |
756 | + present. | |
757 | + sas_satl_register_dev(dev); | |
758 | + */ | |
759 | + | |
760 | + sas_fill_in_rphy(dev, dev->rphy); | |
761 | + | |
762 | + return 0; | |
763 | +out_err: | |
764 | + dev->sata_dev.identify_packet_device = NULL; | |
765 | + dev->sata_dev.identify_device = NULL; | |
766 | + kfree(identify_x); | |
767 | + return res; | |
768 | +} | |
769 | + | |
770 | +static int sas_discover_sata_pm(struct domain_device *dev) | |
771 | +{ | |
772 | + return -ENODEV; | |
773 | +} | |
774 | + | |
775 | +/** | |
776 | + * sas_discover_sata -- discover an STP/SATA domain device | |
777 | + * @dev: pointer to struct domain_device of interest | |
778 | + * | |
779 | + * First we notify the LLDD of this device, so we can send frames to | |
780 | + * it. Then depending on the type of device we call the appropriate | |
781 | + * discover functions. Once device discover is done, we notify the | |
782 | + * LLDD so that it can fine-tune its parameters for the device, by | |
783 | + * removing it and then adding it. That is, the second time around, | |
784 | + * the driver would have certain fields, that it is looking at, set. | |
785 | + * Finally we initialize the kobj so that the device can be added to | |
786 | + * the system at registration time. Devices directly attached to a HA | |
787 | + * port, have no parents. All other devices do, and should have their | |
788 | + * "parent" pointer set appropriately before calling this function. | |
789 | + */ | |
790 | +int sas_discover_sata(struct domain_device *dev) | |
791 | +{ | |
792 | + int res; | |
793 | + | |
794 | + sas_get_ata_command_set(dev); | |
795 | + | |
796 | + res = sas_notify_lldd_dev_found(dev); | |
797 | + if (res) | |
798 | + return res; | |
799 | + | |
800 | + switch (dev->dev_type) { | |
801 | + case SATA_DEV: | |
802 | + res = sas_discover_sata_dev(dev); | |
803 | + break; | |
804 | + case SATA_PM: | |
805 | + res = sas_discover_sata_pm(dev); | |
806 | + break; | |
807 | + default: | |
808 | + break; | |
809 | + } | |
810 | + sas_notify_lldd_dev_gone(dev); | |
811 | + if (!res) { | |
812 | + sas_notify_lldd_dev_found(dev); | |
813 | + res = sas_rphy_add(dev->rphy); | |
814 | + } | |
815 | + | |
816 | + return res; | |
420 | 817 | } |
drivers/scsi/libsas/sas_discover.c
... | ... | @@ -55,161 +55,6 @@ |
55 | 55 | } |
56 | 56 | } |
57 | 57 | |
58 | -static void sas_task_timedout(unsigned long _task) | |
59 | -{ | |
60 | - struct sas_task *task = (void *) _task; | |
61 | - unsigned long flags; | |
62 | - | |
63 | - spin_lock_irqsave(&task->task_state_lock, flags); | |
64 | - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | |
65 | - task->task_state_flags |= SAS_TASK_STATE_ABORTED; | |
66 | - spin_unlock_irqrestore(&task->task_state_lock, flags); | |
67 | - | |
68 | - complete(&task->completion); | |
69 | -} | |
70 | - | |
71 | -static void sas_disc_task_done(struct sas_task *task) | |
72 | -{ | |
73 | - if (!del_timer(&task->timer)) | |
74 | - return; | |
75 | - complete(&task->completion); | |
76 | -} | |
77 | - | |
78 | -#define SAS_DEV_TIMEOUT 10 | |
79 | - | |
80 | -/** | |
81 | - * sas_execute_task -- Basic task processing for discovery | |
82 | - * @task: the task to be executed | |
83 | - * @buffer: pointer to buffer to do I/O | |
84 | - * @size: size of @buffer | |
85 | - * @pci_dma_dir: PCI_DMA_... | |
86 | - */ | |
87 | -static int sas_execute_task(struct sas_task *task, void *buffer, int size, | |
88 | - int pci_dma_dir) | |
89 | -{ | |
90 | - int res = 0; | |
91 | - struct scatterlist *scatter = NULL; | |
92 | - struct task_status_struct *ts = &task->task_status; | |
93 | - int num_scatter = 0; | |
94 | - int retries = 0; | |
95 | - struct sas_internal *i = | |
96 | - to_sas_internal(task->dev->port->ha->core.shost->transportt); | |
97 | - | |
98 | - if (pci_dma_dir != PCI_DMA_NONE) { | |
99 | - scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); | |
100 | - if (!scatter) | |
101 | - goto out; | |
102 | - | |
103 | - sg_init_one(scatter, buffer, size); | |
104 | - num_scatter = 1; | |
105 | - } | |
106 | - | |
107 | - task->task_proto = task->dev->tproto; | |
108 | - task->scatter = scatter; | |
109 | - task->num_scatter = num_scatter; | |
110 | - task->total_xfer_len = size; | |
111 | - task->data_dir = pci_dma_dir; | |
112 | - task->task_done = sas_disc_task_done; | |
113 | - if (pci_dma_dir != PCI_DMA_NONE && | |
114 | - sas_protocol_ata(task->task_proto)) { | |
115 | - task->num_scatter = pci_map_sg(task->dev->port->ha->pcidev, | |
116 | - task->scatter, | |
117 | - task->num_scatter, | |
118 | - task->data_dir); | |
119 | - } | |
120 | - | |
121 | - for (retries = 0; retries < 5; retries++) { | |
122 | - task->task_state_flags = SAS_TASK_STATE_PENDING; | |
123 | - init_completion(&task->completion); | |
124 | - | |
125 | - task->timer.data = (unsigned long) task; | |
126 | - task->timer.function = sas_task_timedout; | |
127 | - task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; | |
128 | - add_timer(&task->timer); | |
129 | - | |
130 | - res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); | |
131 | - if (res) { | |
132 | - del_timer(&task->timer); | |
133 | - SAS_DPRINTK("executing SAS discovery task failed:%d\n", | |
134 | - res); | |
135 | - goto ex_err; | |
136 | - } | |
137 | - wait_for_completion(&task->completion); | |
138 | - res = -ETASK; | |
139 | - if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | |
140 | - int res2; | |
141 | - SAS_DPRINTK("task aborted, flags:0x%x\n", | |
142 | - task->task_state_flags); | |
143 | - res2 = i->dft->lldd_abort_task(task); | |
144 | - SAS_DPRINTK("came back from abort task\n"); | |
145 | - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | |
146 | - if (res2 == TMF_RESP_FUNC_COMPLETE) | |
147 | - continue; /* Retry the task */ | |
148 | - else | |
149 | - goto ex_err; | |
150 | - } | |
151 | - } | |
152 | - if (task->task_status.stat == SAM_BUSY || | |
153 | - task->task_status.stat == SAM_TASK_SET_FULL || | |
154 | - task->task_status.stat == SAS_QUEUE_FULL) { | |
155 | - SAS_DPRINTK("task: q busy, sleeping...\n"); | |
156 | - schedule_timeout_interruptible(HZ); | |
157 | - } else if (task->task_status.stat == SAM_CHECK_COND) { | |
158 | - struct scsi_sense_hdr shdr; | |
159 | - | |
160 | - if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, | |
161 | - &shdr)) { | |
162 | - SAS_DPRINTK("couldn't normalize sense\n"); | |
163 | - continue; | |
164 | - } | |
165 | - if ((shdr.sense_key == 6 && shdr.asc == 0x29) || | |
166 | - (shdr.sense_key == 2 && shdr.asc == 4 && | |
167 | - shdr.ascq == 1)) { | |
168 | - SAS_DPRINTK("device %016llx LUN: %016llx " | |
169 | - "powering up or not ready yet, " | |
170 | - "sleeping...\n", | |
171 | - SAS_ADDR(task->dev->sas_addr), | |
172 | - SAS_ADDR(task->ssp_task.LUN)); | |
173 | - | |
174 | - schedule_timeout_interruptible(5*HZ); | |
175 | - } else if (shdr.sense_key == 1) { | |
176 | - res = 0; | |
177 | - break; | |
178 | - } else if (shdr.sense_key == 5) { | |
179 | - break; | |
180 | - } else { | |
181 | - SAS_DPRINTK("dev %016llx LUN: %016llx " | |
182 | - "sense key:0x%x ASC:0x%x ASCQ:0x%x" | |
183 | - "\n", | |
184 | - SAS_ADDR(task->dev->sas_addr), | |
185 | - SAS_ADDR(task->ssp_task.LUN), | |
186 | - shdr.sense_key, | |
187 | - shdr.asc, shdr.ascq); | |
188 | - } | |
189 | - } else if (task->task_status.resp != SAS_TASK_COMPLETE || | |
190 | - task->task_status.stat != SAM_GOOD) { | |
191 | - SAS_DPRINTK("task finished with resp:0x%x, " | |
192 | - "stat:0x%x\n", | |
193 | - task->task_status.resp, | |
194 | - task->task_status.stat); | |
195 | - goto ex_err; | |
196 | - } else { | |
197 | - res = 0; | |
198 | - break; | |
199 | - } | |
200 | - } | |
201 | -ex_err: | |
202 | - if (pci_dma_dir != PCI_DMA_NONE) { | |
203 | - if (sas_protocol_ata(task->task_proto)) | |
204 | - pci_unmap_sg(task->dev->port->ha->pcidev, | |
205 | - task->scatter, task->num_scatter, | |
206 | - task->data_dir); | |
207 | - kfree(scatter); | |
208 | - } | |
209 | -out: | |
210 | - return res; | |
211 | -} | |
212 | - | |
213 | 58 | /* ---------- Domain device discovery ---------- */ |
214 | 59 | |
215 | 60 | /** |
... | ... | @@ -313,202 +158,6 @@ |
313 | 158 | |
314 | 159 | /* ---------- Discover and Revalidate ---------- */ |
315 | 160 | |
316 | -/* ---------- SATA ---------- */ | |
317 | - | |
318 | -static void sas_get_ata_command_set(struct domain_device *dev) | |
319 | -{ | |
320 | - struct dev_to_host_fis *fis = | |
321 | - (struct dev_to_host_fis *) dev->frame_rcvd; | |
322 | - | |
323 | - if ((fis->sector_count == 1 && /* ATA */ | |
324 | - fis->lbal == 1 && | |
325 | - fis->lbam == 0 && | |
326 | - fis->lbah == 0 && | |
327 | - fis->device == 0) | |
328 | - || | |
329 | - (fis->sector_count == 0 && /* CE-ATA (mATA) */ | |
330 | - fis->lbal == 0 && | |
331 | - fis->lbam == 0xCE && | |
332 | - fis->lbah == 0xAA && | |
333 | - (fis->device & ~0x10) == 0)) | |
334 | - | |
335 | - dev->sata_dev.command_set = ATA_COMMAND_SET; | |
336 | - | |
337 | - else if ((fis->interrupt_reason == 1 && /* ATAPI */ | |
338 | - fis->lbal == 1 && | |
339 | - fis->byte_count_low == 0x14 && | |
340 | - fis->byte_count_high == 0xEB && | |
341 | - (fis->device & ~0x10) == 0)) | |
342 | - | |
343 | - dev->sata_dev.command_set = ATAPI_COMMAND_SET; | |
344 | - | |
345 | - else if ((fis->sector_count == 1 && /* SEMB */ | |
346 | - fis->lbal == 1 && | |
347 | - fis->lbam == 0x3C && | |
348 | - fis->lbah == 0xC3 && | |
349 | - fis->device == 0) | |
350 | - || | |
351 | - (fis->interrupt_reason == 1 && /* SATA PM */ | |
352 | - fis->lbal == 1 && | |
353 | - fis->byte_count_low == 0x69 && | |
354 | - fis->byte_count_high == 0x96 && | |
355 | - (fis->device & ~0x10) == 0)) | |
356 | - | |
357 | - /* Treat it as a superset? */ | |
358 | - dev->sata_dev.command_set = ATAPI_COMMAND_SET; | |
359 | -} | |
360 | - | |
361 | -/** | |
362 | - * sas_issue_ata_cmd -- Basic SATA command processing for discovery | |
363 | - * @dev: the device to send the command to | |
364 | - * @command: the command register | |
365 | - * @features: the features register | |
366 | - * @buffer: pointer to buffer to do I/O | |
367 | - * @size: size of @buffer | |
368 | - * @pci_dma_dir: PCI_DMA_... | |
369 | - */ | |
370 | -static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, | |
371 | - u8 features, void *buffer, int size, | |
372 | - int pci_dma_dir) | |
373 | -{ | |
374 | - int res = 0; | |
375 | - struct sas_task *task; | |
376 | - struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) | |
377 | - &dev->frame_rcvd[0]; | |
378 | - | |
379 | - res = -ENOMEM; | |
380 | - task = sas_alloc_task(GFP_KERNEL); | |
381 | - if (!task) | |
382 | - goto out; | |
383 | - | |
384 | - task->dev = dev; | |
385 | - | |
386 | - task->ata_task.fis.fis_type = 0x27; | |
387 | - task->ata_task.fis.command = command; | |
388 | - task->ata_task.fis.features = features; | |
389 | - task->ata_task.fis.device = d2h_fis->device; | |
390 | - task->ata_task.retry_count = 1; | |
391 | - | |
392 | - res = sas_execute_task(task, buffer, size, pci_dma_dir); | |
393 | - | |
394 | - sas_free_task(task); | |
395 | -out: | |
396 | - return res; | |
397 | -} | |
398 | - | |
399 | -static void sas_sata_propagate_sas_addr(struct domain_device *dev) | |
400 | -{ | |
401 | - unsigned long flags; | |
402 | - struct asd_sas_port *port = dev->port; | |
403 | - struct asd_sas_phy *phy; | |
404 | - | |
405 | - BUG_ON(dev->parent); | |
406 | - | |
407 | - memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | |
408 | - spin_lock_irqsave(&port->phy_list_lock, flags); | |
409 | - list_for_each_entry(phy, &port->phy_list, port_phy_el) | |
410 | - memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | |
411 | - spin_unlock_irqrestore(&port->phy_list_lock, flags); | |
412 | -} | |
413 | - | |
414 | -#define ATA_IDENTIFY_DEV 0xEC | |
415 | -#define ATA_IDENTIFY_PACKET_DEV 0xA1 | |
416 | -#define ATA_SET_FEATURES 0xEF | |
417 | -#define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 | |
418 | - | |
419 | -/** | |
420 | - * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) | |
421 | - * @dev: STP/SATA device of interest (ATA/ATAPI) | |
422 | - * | |
423 | - * The LLDD has already been notified of this device, so that we can | |
424 | - * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY | |
425 | - * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its | |
426 | - * performance for this device. | |
427 | - */ | |
428 | -static int sas_discover_sata_dev(struct domain_device *dev) | |
429 | -{ | |
430 | - int res; | |
431 | - __le16 *identify_x; | |
432 | - u8 command; | |
433 | - | |
434 | - identify_x = kzalloc(512, GFP_KERNEL); | |
435 | - if (!identify_x) | |
436 | - return -ENOMEM; | |
437 | - | |
438 | - if (dev->sata_dev.command_set == ATA_COMMAND_SET) { | |
439 | - dev->sata_dev.identify_device = identify_x; | |
440 | - command = ATA_IDENTIFY_DEV; | |
441 | - } else { | |
442 | - dev->sata_dev.identify_packet_device = identify_x; | |
443 | - command = ATA_IDENTIFY_PACKET_DEV; | |
444 | - } | |
445 | - | |
446 | - res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | |
447 | - PCI_DMA_FROMDEVICE); | |
448 | - if (res) | |
449 | - goto out_err; | |
450 | - | |
451 | - /* lives on the media? */ | |
452 | - if (le16_to_cpu(identify_x[0]) & 4) { | |
453 | - /* incomplete response */ | |
454 | - SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " | |
455 | - "dev %llx\n", SAS_ADDR(dev->sas_addr)); | |
456 | - if (!le16_to_cpu(identify_x[83] & (1<<6))) | |
457 | - goto cont1; | |
458 | - res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, | |
459 | - ATA_FEATURE_PUP_STBY_SPIN_UP, | |
460 | - NULL, 0, PCI_DMA_NONE); | |
461 | - if (res) | |
462 | - goto cont1; | |
463 | - | |
464 | - schedule_timeout_interruptible(5*HZ); /* More time? */ | |
465 | - res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, | |
466 | - PCI_DMA_FROMDEVICE); | |
467 | - if (res) | |
468 | - goto out_err; | |
469 | - } | |
470 | -cont1: | |
471 | - /* Get WWN */ | |
472 | - if (dev->port->oob_mode != SATA_OOB_MODE) { | |
473 | - memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, | |
474 | - SAS_ADDR_SIZE); | |
475 | - } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && | |
476 | - (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) | |
477 | - == 0x5000) { | |
478 | - int i; | |
479 | - | |
480 | - for (i = 0; i < 4; i++) { | |
481 | - dev->sas_addr[2*i] = | |
482 | - (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; | |
483 | - dev->sas_addr[2*i+1] = | |
484 | - le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; | |
485 | - } | |
486 | - } | |
487 | - sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); | |
488 | - if (!dev->parent) | |
489 | - sas_sata_propagate_sas_addr(dev); | |
490 | - | |
491 | - /* XXX Hint: register this SATA device with SATL. | |
492 | - When this returns, dev->sata_dev->lu is alive and | |
493 | - present. | |
494 | - sas_satl_register_dev(dev); | |
495 | - */ | |
496 | - | |
497 | - sas_fill_in_rphy(dev, dev->rphy); | |
498 | - | |
499 | - return 0; | |
500 | -out_err: | |
501 | - dev->sata_dev.identify_packet_device = NULL; | |
502 | - dev->sata_dev.identify_device = NULL; | |
503 | - kfree(identify_x); | |
504 | - return res; | |
505 | -} | |
506 | - | |
507 | -static int sas_discover_sata_pm(struct domain_device *dev) | |
508 | -{ | |
509 | - return -ENODEV; | |
510 | -} | |
511 | - | |
512 | 161 | int sas_notify_lldd_dev_found(struct domain_device *dev) |
513 | 162 | { |
514 | 163 | int res = 0; |
515 | 164 | |
... | ... | @@ -541,50 +190,7 @@ |
541 | 190 | |
542 | 191 | /* ---------- Common/dispatchers ---------- */ |
543 | 192 | |
544 | -/** | |
545 | - * sas_discover_sata -- discover an STP/SATA domain device | |
546 | - * @dev: pointer to struct domain_device of interest | |
547 | - * | |
548 | - * First we notify the LLDD of this device, so we can send frames to | |
549 | - * it. Then depending on the type of device we call the appropriate | |
550 | - * discover functions. Once device discover is done, we notify the | |
551 | - * LLDD so that it can fine-tune its parameters for the device, by | |
552 | - * removing it and then adding it. That is, the second time around, | |
553 | - * the driver would have certain fields, that it is looking at, set. | |
554 | - * Finally we initialize the kobj so that the device can be added to | |
555 | - * the system at registration time. Devices directly attached to a HA | |
556 | - * port, have no parents. All other devices do, and should have their | |
557 | - * "parent" pointer set appropriately before calling this function. | |
558 | - */ | |
559 | -int sas_discover_sata(struct domain_device *dev) | |
560 | -{ | |
561 | - int res; | |
562 | 193 | |
563 | - sas_get_ata_command_set(dev); | |
564 | - | |
565 | - res = sas_notify_lldd_dev_found(dev); | |
566 | - if (res) | |
567 | - return res; | |
568 | - | |
569 | - switch (dev->dev_type) { | |
570 | - case SATA_DEV: | |
571 | - res = sas_discover_sata_dev(dev); | |
572 | - break; | |
573 | - case SATA_PM: | |
574 | - res = sas_discover_sata_pm(dev); | |
575 | - break; | |
576 | - default: | |
577 | - break; | |
578 | - } | |
579 | - sas_notify_lldd_dev_gone(dev); | |
580 | - if (!res) { | |
581 | - sas_notify_lldd_dev_found(dev); | |
582 | - res = sas_rphy_add(dev->rphy); | |
583 | - } | |
584 | - | |
585 | - return res; | |
586 | -} | |
587 | - | |
588 | 194 | /** |
589 | 195 | * sas_discover_end_dev -- discover an end device (SSP, etc) |
590 | 196 | * @end: pointer to domain device of interest |
591 | 197 | |
592 | 198 | |
... | ... | @@ -690,11 +296,14 @@ |
690 | 296 | case FANOUT_DEV: |
691 | 297 | error = sas_discover_root_expander(dev); |
692 | 298 | break; |
299 | +#ifdef CONFIG_SCSI_SAS_ATA | |
693 | 300 | case SATA_DEV: |
694 | 301 | case SATA_PM: |
695 | 302 | error = sas_discover_sata(dev); |
696 | 303 | break; |
304 | +#endif | |
697 | 305 | default: |
306 | + error = -ENXIO; | |
698 | 307 | SAS_DPRINTK("unhandled device %d\n", dev->dev_type); |
699 | 308 | break; |
700 | 309 | } |
drivers/scsi/libsas/sas_expander.c
... | ... | @@ -535,6 +535,8 @@ |
535 | 535 | |
536 | 536 | } |
537 | 537 | |
538 | +#ifdef CONFIG_SCSI_SAS_ATA | |
539 | + | |
538 | 540 | #define RPS_REQ_SIZE 16 |
539 | 541 | #define RPS_RESP_SIZE 60 |
540 | 542 | |
... | ... | @@ -578,6 +580,7 @@ |
578 | 580 | kfree(rps_req); |
579 | 581 | return res; |
580 | 582 | } |
583 | +#endif | |
581 | 584 | |
582 | 585 | static void sas_ex_get_linkrate(struct domain_device *parent, |
583 | 586 | struct domain_device *child, |
... | ... | @@ -645,6 +648,7 @@ |
645 | 648 | } |
646 | 649 | sas_ex_get_linkrate(parent, child, phy); |
647 | 650 | |
651 | +#ifdef CONFIG_SCSI_SAS_ATA | |
648 | 652 | if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { |
649 | 653 | child->dev_type = SATA_DEV; |
650 | 654 | if (phy->attached_tproto & SAS_PROTO_STP) |
... | ... | @@ -682,7 +686,9 @@ |
682 | 686 | SAS_ADDR(parent->sas_addr), phy_id, res); |
683 | 687 | goto out_list_del; |
684 | 688 | } |
685 | - } else if (phy->attached_tproto & SAS_PROTO_SSP) { | |
689 | + } else | |
690 | +#endif | |
691 | + if (phy->attached_tproto & SAS_PROTO_SSP) { | |
686 | 692 | child->dev_type = SAS_END_DEV; |
687 | 693 | rphy = sas_end_device_alloc(phy->port); |
688 | 694 | /* FIXME: error handling */ |
... | ... | @@ -710,6 +716,7 @@ |
710 | 716 | SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", |
711 | 717 | phy->attached_tproto, SAS_ADDR(parent->sas_addr), |
712 | 718 | phy_id); |
719 | + goto out_free; | |
713 | 720 | } |
714 | 721 | |
715 | 722 | list_add_tail(&child->siblings, &parent_ex->children); |
include/scsi/sas_ata.h
... | ... | @@ -28,6 +28,8 @@ |
28 | 28 | #include <linux/libata.h> |
29 | 29 | #include <scsi/libsas.h> |
30 | 30 | |
31 | +#ifdef CONFIG_SCSI_SAS_ATA | |
32 | + | |
31 | 33 | static inline int dev_is_sata(struct domain_device *dev) |
32 | 34 | { |
33 | 35 | return (dev->rphy->identify.target_port_protocols & SAS_PROTOCOL_SATA); |
... | ... | @@ -37,6 +39,23 @@ |
37 | 39 | struct scsi_target *starget); |
38 | 40 | |
39 | 41 | void sas_ata_task_abort(struct sas_task *task); |
42 | + | |
43 | +#else | |
44 | + | |
45 | + | |
46 | +static inline int dev_is_sata(struct domain_device *dev) | |
47 | +{ | |
48 | + return 0; | |
49 | +} | |
50 | +int sas_ata_init_host_and_port(struct domain_device *found_dev, | |
51 | + struct scsi_target *starget) | |
52 | +{ | |
53 | + return 0; | |
54 | +} | |
55 | +void sas_ata_task_abort(struct sas_task *task) | |
56 | +{ | |
57 | +} | |
58 | +#endif | |
40 | 59 | |
41 | 60 | #endif /* _SAS_ATA_H_ */ |