aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2007-07-22 14:15:55 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-07-22 14:23:13 -0400
commitb91421749a1840148d8c81637c03c0ace3f35269 (patch)
treee3e2f59f9a14051c8277793f214db094380d3ebb
parent41e1703b9b88cf9b5e91cdd2f7dcded3ec3917cb (diff)
[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>
-rw-r--r--drivers/scsi/libsas/Kconfig7
-rw-r--r--drivers/scsi/libsas/Makefile4
-rw-r--r--drivers/scsi/libsas/sas_ata.c397
-rw-r--r--drivers/scsi/libsas/sas_discover.c397
-rw-r--r--drivers/scsi/libsas/sas_expander.c9
-rw-r--r--include/scsi/sas_ata.h19
6 files changed, 436 insertions, 397 deletions
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index aafdc92f8312..3a3c1ac9c6cd 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -30,6 +30,13 @@ config SCSI_SAS_LIBSAS
30 This provides transport specific helpers for SAS drivers which 30 This provides transport specific helpers for SAS drivers which
31 use the domain device construct (like the aic94xxx). 31 use the domain device construct (like the aic94xxx).
32 32
33config 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
33config SCSI_SAS_LIBSAS_DEBUG 40config SCSI_SAS_LIBSAS_DEBUG
34 bool "Compile the SAS Domain Transport Attributes in debug mode" 41 bool "Compile the SAS Domain Transport Attributes in debug mode"
35 default y 42 default y
diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile
index 6383eb58d890..fd387b91856e 100644
--- a/drivers/scsi/libsas/Makefile
+++ b/drivers/scsi/libsas/Makefile
@@ -33,5 +33,5 @@ libsas-y += sas_init.o \
33 sas_dump.o \ 33 sas_dump.o \
34 sas_discover.o \ 34 sas_discover.o \
35 sas_expander.o \ 35 sas_expander.o \
36 sas_scsi_host.o \ 36 sas_scsi_host.o
37 sas_ata.o 37libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 359391f5735f..ced2de32c511 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -21,6 +21,8 @@
21 * USA 21 * USA
22 */ 22 */
23 23
24#include <linux/scatterlist.h>
25
24#include <scsi/sas_ata.h> 26#include <scsi/sas_ata.h>
25#include "sas_internal.h" 27#include "sas_internal.h"
26#include <scsi/scsi_host.h> 28#include <scsi/scsi_host.h>
@@ -418,3 +420,398 @@ void sas_ata_task_abort(struct sas_task *task)
418 waiting = qc->private_data; 420 waiting = qc->private_data;
419 complete(waiting); 421 complete(waiting);
420} 422}
423
424static 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
437static 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 */
453static 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 }
567ex_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 }
575out:
576 return res;
577}
578
579/* ---------- SATA ---------- */
580
581static 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 */
633static 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);
658out:
659 return res;
660}
661
662static 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 */
691static 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 }
733cont1:
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;
763out_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
770static 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 */
790int 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;
817}
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 328a78ad6aa0..6ac9f61d006a 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -55,161 +55,6 @@ void sas_init_dev(struct domain_device *dev)
55 } 55 }
56} 56}
57 57
58static 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
71static 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 */
87static 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 }
201ex_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 }
209out:
210 return res;
211}
212
213/* ---------- Domain device discovery ---------- */ 58/* ---------- Domain device discovery ---------- */
214 59
215/** 60/**
@@ -313,202 +158,6 @@ static int sas_get_port_device(struct asd_sas_port *port)
313 158
314/* ---------- Discover and Revalidate ---------- */ 159/* ---------- Discover and Revalidate ---------- */
315 160
316/* ---------- SATA ---------- */
317
318static 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 */
370static 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);
395out:
396 return res;
397}
398
399static 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 */
428static 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 }
470cont1:
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;
500out_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
507static int sas_discover_sata_pm(struct domain_device *dev)
508{
509 return -ENODEV;
510}
511
512int sas_notify_lldd_dev_found(struct domain_device *dev) 161int sas_notify_lldd_dev_found(struct domain_device *dev)
513{ 162{
514 int res = 0; 163 int res = 0;
@@ -541,49 +190,6 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev)
541 190
542/* ---------- Common/dispatchers ---------- */ 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 */
559int sas_discover_sata(struct domain_device *dev)
560{
561 int res;
562
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 193
588/** 194/**
589 * sas_discover_end_dev -- discover an end device (SSP, etc) 195 * sas_discover_end_dev -- discover an end device (SSP, etc)
@@ -690,11 +296,14 @@ static void sas_discover_domain(struct work_struct *work)
690 case FANOUT_DEV: 296 case FANOUT_DEV:
691 error = sas_discover_root_expander(dev); 297 error = sas_discover_root_expander(dev);
692 break; 298 break;
299#ifdef CONFIG_SCSI_SAS_ATA
693 case SATA_DEV: 300 case SATA_DEV:
694 case SATA_PM: 301 case SATA_PM:
695 error = sas_discover_sata(dev); 302 error = sas_discover_sata(dev);
696 break; 303 break;
304#endif
697 default: 305 default:
306 error = -ENXIO;
698 SAS_DPRINTK("unhandled device %d\n", dev->dev_type); 307 SAS_DPRINTK("unhandled device %d\n", dev->dev_type);
699 break; 308 break;
700 } 309 }
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index eca83e8d8c0d..b500f0c1449c 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -535,6 +535,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy)
535 535
536} 536}
537 537
538#ifdef CONFIG_SCSI_SAS_ATA
539
538#define RPS_REQ_SIZE 16 540#define RPS_REQ_SIZE 16
539#define RPS_RESP_SIZE 60 541#define RPS_RESP_SIZE 60
540 542
@@ -578,6 +580,7 @@ static int sas_get_report_phy_sata(struct domain_device *dev,
578 kfree(rps_req); 580 kfree(rps_req);
579 return res; 581 return res;
580} 582}
583#endif
581 584
582static void sas_ex_get_linkrate(struct domain_device *parent, 585static void sas_ex_get_linkrate(struct domain_device *parent,
583 struct domain_device *child, 586 struct domain_device *child,
@@ -645,6 +648,7 @@ static struct domain_device *sas_ex_discover_end_dev(
645 } 648 }
646 sas_ex_get_linkrate(parent, child, phy); 649 sas_ex_get_linkrate(parent, child, phy);
647 650
651#ifdef CONFIG_SCSI_SAS_ATA
648 if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { 652 if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) {
649 child->dev_type = SATA_DEV; 653 child->dev_type = SATA_DEV;
650 if (phy->attached_tproto & SAS_PROTO_STP) 654 if (phy->attached_tproto & SAS_PROTO_STP)
@@ -682,7 +686,9 @@ static struct domain_device *sas_ex_discover_end_dev(
682 SAS_ADDR(parent->sas_addr), phy_id, res); 686 SAS_ADDR(parent->sas_addr), phy_id, res);
683 goto out_list_del; 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 child->dev_type = SAS_END_DEV; 692 child->dev_type = SAS_END_DEV;
687 rphy = sas_end_device_alloc(phy->port); 693 rphy = sas_end_device_alloc(phy->port);
688 /* FIXME: error handling */ 694 /* FIXME: error handling */
@@ -710,6 +716,7 @@ static struct domain_device *sas_ex_discover_end_dev(
710 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", 716 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n",
711 phy->attached_tproto, SAS_ADDR(parent->sas_addr), 717 phy->attached_tproto, SAS_ADDR(parent->sas_addr),
712 phy_id); 718 phy_id);
719 goto out_free;
713 } 720 }
714 721
715 list_add_tail(&child->siblings, &parent_ex->children); 722 list_add_tail(&child->siblings, &parent_ex->children);
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index 3407c819522d..dd5edc915417 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -28,6 +28,8 @@
28#include <linux/libata.h> 28#include <linux/libata.h>
29#include <scsi/libsas.h> 29#include <scsi/libsas.h>
30 30
31#ifdef CONFIG_SCSI_SAS_ATA
32
31static inline int dev_is_sata(struct domain_device *dev) 33static inline int dev_is_sata(struct domain_device *dev)
32{ 34{
33 return (dev->rphy->identify.target_port_protocols & SAS_PROTOCOL_SATA); 35 return (dev->rphy->identify.target_port_protocols & SAS_PROTOCOL_SATA);
@@ -38,4 +40,21 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
38 40
39void sas_ata_task_abort(struct sas_task *task); 41void sas_ata_task_abort(struct sas_task *task);
40 42
43#else
44
45
46static inline int dev_is_sata(struct domain_device *dev)
47{
48 return 0;
49}
50int sas_ata_init_host_and_port(struct domain_device *found_dev,
51 struct scsi_target *starget)
52{
53 return 0;
54}
55void sas_ata_task_abort(struct sas_task *task)
56{
57}
58#endif
59
41#endif /* _SAS_ATA_H_ */ 60#endif /* _SAS_ATA_H_ */