aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2006-08-10 22:19:47 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-07-18 12:12:53 -0400
commitfa1c1e8f1ece48c7baa3ba529bfd0d10a0bdf4eb (patch)
tree8de54ce8b590c720f528c511c2434e71abd34f0c
parent8b4a40809e5330c9da5d20107d693d92d73b31dc (diff)
[SCSI] Add SATA support to libsas
Hook the scsi_host_template functions in libsas to delegate functionality to libata when appropriate. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Misc code changes and merge fixes and update for libata->drivers/ata move Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c3
-rw-r--r--drivers/scsi/libsas/sas_discover.c11
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c342
-rw-r--r--include/scsi/libsas.h12
4 files changed, 366 insertions, 2 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 1c0d7578e791..b9cf46078fc6 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -81,6 +81,9 @@ static struct scsi_host_template aic94xx_sht = {
81 .use_clustering = ENABLE_CLUSTERING, 81 .use_clustering = ENABLE_CLUSTERING,
82 .eh_device_reset_handler = sas_eh_device_reset_handler, 82 .eh_device_reset_handler = sas_eh_device_reset_handler,
83 .eh_bus_reset_handler = sas_eh_bus_reset_handler, 83 .eh_bus_reset_handler = sas_eh_bus_reset_handler,
84 .slave_alloc = sas_slave_alloc,
85 .target_destroy = sas_target_destroy,
86 .ioctl = sas_ioctl,
84}; 87};
85 88
86static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) 89static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha)
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index a65598b1e536..5252143b6297 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -255,6 +255,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
255 255
256 switch (dev->dev_type) { 256 switch (dev->dev_type) {
257 case SAS_END_DEV: 257 case SAS_END_DEV:
258 case SATA_DEV:
258 rphy = sas_end_device_alloc(port->port); 259 rphy = sas_end_device_alloc(port->port);
259 break; 260 break;
260 case EDGE_DEV: 261 case EDGE_DEV:
@@ -265,7 +266,6 @@ static int sas_get_port_device(struct asd_sas_port *port)
265 rphy = sas_expander_alloc(port->port, 266 rphy = sas_expander_alloc(port->port,
266 SAS_FANOUT_EXPANDER_DEVICE); 267 SAS_FANOUT_EXPANDER_DEVICE);
267 break; 268 break;
268 case SATA_DEV:
269 default: 269 default:
270 printk("ERROR: Unidentified device type %d\n", dev->dev_type); 270 printk("ERROR: Unidentified device type %d\n", dev->dev_type);
271 rphy = NULL; 271 rphy = NULL;
@@ -480,7 +480,14 @@ cont1:
480 present. 480 present.
481 sas_satl_register_dev(dev); 481 sas_satl_register_dev(dev);
482 */ 482 */
483 return 0; 483
484 sas_fill_in_rphy(dev, dev->rphy);
485
486 res = sas_rphy_add(dev->rphy);
487 if (res)
488 goto out_err;
489
490 return res;
484out_err: 491out_err:
485 dev->sata_dev.identify_packet_device = NULL; 492 dev->sata_dev.identify_packet_device = NULL;
486 dev->sata_dev.identify_device = NULL; 493 dev->sata_dev.identify_device = NULL;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 9c5342e7a69c..3220b3fc6b20 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -42,6 +42,7 @@
42#include <linux/blkdev.h> 42#include <linux/blkdev.h>
43#include <linux/freezer.h> 43#include <linux/freezer.h>
44#include <linux/scatterlist.h> 44#include <linux/scatterlist.h>
45#include <linux/libata.h>
45 46
46/* ---------- SCSI Host glue ---------- */ 47/* ---------- SCSI Host glue ---------- */
47 48
@@ -192,6 +193,11 @@ static int sas_queue_up(struct sas_task *task)
192 return 0; 193 return 0;
193} 194}
194 195
196static inline int dev_is_sata(struct domain_device *dev)
197{
198 return (dev->rphy->identify.target_port_protocols & SAS_PROTOCOL_SATA);
199}
200
195/** 201/**
196 * sas_queuecommand -- Enqueue a command for processing 202 * sas_queuecommand -- Enqueue a command for processing
197 * @parameters: See SCSI Core documentation 203 * @parameters: See SCSI Core documentation
@@ -213,6 +219,12 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
213 struct sas_ha_struct *sas_ha = dev->port->ha; 219 struct sas_ha_struct *sas_ha = dev->port->ha;
214 struct sas_task *task; 220 struct sas_task *task;
215 221
222 if (dev_is_sata(dev)) {
223 res = ata_sas_queuecmd(cmd, scsi_done,
224 dev->sata_dev.ap);
225 goto out;
226 }
227
216 res = -ENOMEM; 228 res = -ENOMEM;
217 task = sas_create_task(cmd, dev, GFP_ATOMIC); 229 task = sas_create_task(cmd, dev, GFP_ATOMIC);
218 if (!task) 230 if (!task)
@@ -684,6 +696,279 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
684 return EH_NOT_HANDLED; 696 return EH_NOT_HANDLED;
685} 697}
686 698
699
700static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts)
701{
702 /* Cheesy attempt to translate SAS errors into ATA. Hah! */
703
704 /* transport error */
705 if (ts->resp == SAS_TASK_UNDELIVERED)
706 return AC_ERR_ATA_BUS;
707
708 /* ts->resp == SAS_TASK_COMPLETE */
709 /* task delivered, what happened afterwards? */
710 switch (ts->stat) {
711 case SAS_DEV_NO_RESPONSE:
712 return AC_ERR_TIMEOUT;
713
714 case SAS_INTERRUPTED:
715 case SAS_PHY_DOWN:
716 case SAS_NAK_R_ERR:
717 return AC_ERR_ATA_BUS;
718
719
720 case SAS_DATA_UNDERRUN:
721 /*
722 * Some programs that use the taskfile interface
723 * (smartctl in particular) can cause underrun
724 * problems. Ignore these errors, perhaps at our
725 * peril.
726 */
727 return 0;
728
729 case SAS_DATA_OVERRUN:
730 case SAS_QUEUE_FULL:
731 case SAS_DEVICE_UNKNOWN:
732 case SAS_SG_ERR:
733 return AC_ERR_INVALID;
734
735 case SAM_CHECK_COND:
736 case SAS_OPEN_TO:
737 case SAS_OPEN_REJECT:
738 case SAS_PROTO_RESPONSE:
739 SAS_DPRINTK("%s: Saw error %d. What to do?\n",
740 __FUNCTION__, ts->stat);
741 return AC_ERR_OTHER;
742
743 case SAS_ABORTED_TASK:
744 return AC_ERR_DEV;
745
746 default:
747 return 0;
748 }
749}
750
751static void sas_ata_task_done(struct sas_task *task)
752{
753 struct ata_queued_cmd *qc = task->uldd_task;
754 struct domain_device *dev = qc->ap->private_data;
755 struct task_status_struct *stat = &task->task_status;
756 struct ata_task_resp *resp = (struct ata_task_resp *)stat->buf;
757 enum ata_completion_errors ac;
758
759 ac = sas_to_ata_err(stat);
760 if (ac) {
761 SAS_DPRINTK("%s: SAS error %x\n", __FUNCTION__, stat->stat);
762 /* We saw a SAS error. Send a vague error. */
763 qc->err_mask = ac;
764 dev->sata_dev.tf.feature = 0x04; /* status err */
765 dev->sata_dev.tf.command = ATA_ERR;
766 goto end;
767 }
768
769 ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
770 qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
771 dev->sata_dev.sstatus = resp->sstatus;
772 dev->sata_dev.serror = resp->serror;
773 dev->sata_dev.scontrol = resp->scontrol;
774 dev->sata_dev.ap->sactive = resp->sactive;
775end:
776 ata_qc_complete(qc);
777 list_del_init(&task->list);
778 sas_free_task(task);
779}
780
781int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
782{
783 struct domain_device *dev = sdev_to_domain_dev(sdev);
784
785 if (dev_is_sata(dev))
786 return ata_scsi_ioctl(sdev, cmd, arg);
787
788 return -EINVAL;
789}
790
791static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
792{
793 int res = -ENOMEM;
794 struct sas_task *task;
795 struct domain_device *dev = qc->ap->private_data;
796 struct sas_ha_struct *sas_ha = dev->port->ha;
797 struct Scsi_Host *host = sas_ha->core.shost;
798 struct sas_internal *i = to_sas_internal(host->transportt);
799 struct scatterlist *sg;
800 unsigned int num = 0;
801 unsigned int xfer = 0;
802
803 task = sas_alloc_task(GFP_ATOMIC);
804 if (!task)
805 goto out;
806 task->dev = dev;
807 task->task_proto = SAS_PROTOCOL_STP;
808 task->task_done = sas_ata_task_done;
809
810 ata_tf_to_fis(&qc->tf, (u8*)&task->ata_task.fis, 0);
811 task->uldd_task = qc;
812 if (is_atapi_taskfile(&qc->tf)) {
813 memcpy(task->ata_task.atapi_packet, qc->cdb, ATAPI_CDB_LEN);
814 task->total_xfer_len = qc->nbytes + qc->pad_len;
815 task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem;
816 } else {
817 ata_for_each_sg(sg, qc) {
818 num++;
819 xfer += sg->length;
820 }
821
822 task->total_xfer_len = xfer;
823 task->num_scatter = num;
824 }
825
826 task->data_dir = qc->dma_dir;
827 task->scatter = qc->__sg;
828 task->ata_task.retry_count = 1;
829 task->task_state_flags = SAS_TASK_STATE_PENDING;
830
831 if (qc->tf.protocol == ATA_PROT_DMA)
832 task->ata_task.dma_xfer = 1;
833
834 if (sas_ha->lldd_max_execute_num < 2)
835 res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
836 else
837 res = sas_queue_up(task);
838
839 /* Examine */
840 if (res) {
841 SAS_DPRINTK("lldd_execute_task returned: %d\n", res);
842
843 sas_free_task(task);
844 if (res == -SAS_QUEUE_FULL)
845 return -ENOMEM;
846 }
847
848out:
849 return res;
850}
851
852static u8 sas_ata_check_status(struct ata_port *ap)
853{
854 struct domain_device *dev = ap->private_data;
855 return dev->sata_dev.tf.command;
856}
857
858static void sas_ata_phy_reset(struct ata_port *ap)
859{
860 struct domain_device *dev = ap->private_data;
861 struct sas_internal *i =
862 to_sas_internal(dev->port->ha->core.shost->transportt);
863 int res = 0;
864
865 if (i->dft->lldd_I_T_nexus_reset)
866 res = i->dft->lldd_I_T_nexus_reset(dev);
867
868 if (res)
869 SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__);
870
871 switch (dev->sata_dev.command_set) {
872 case ATA_COMMAND_SET:
873 SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__);
874 ap->device[0].class = ATA_DEV_ATA;
875 break;
876 case ATAPI_COMMAND_SET:
877 SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__);
878 ap->device[0].class = ATA_DEV_ATAPI;
879 break;
880 default:
881 SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
882 __FUNCTION__,
883 dev->sata_dev.command_set);
884 ap->device[0].class = ATA_DEV_ATA;
885 break;
886 }
887
888 ap->cbl = ATA_CBL_SATA;
889}
890
891static void sas_ata_post_internal(struct ata_queued_cmd *qc)
892{
893 if (qc->flags & ATA_QCFLAG_FAILED)
894 qc->err_mask |= AC_ERR_OTHER;
895
896 if (qc->err_mask)
897 SAS_DPRINTK("%s: Failure; reset phy!\n", __FUNCTION__);
898}
899
900static void sas_ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
901{
902 struct domain_device *dev = ap->private_data;
903 memcpy(tf, &dev->sata_dev.tf, sizeof (*tf));
904}
905
906static void sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
907 u32 val)
908{
909 struct domain_device *dev = ap->private_data;
910
911 SAS_DPRINTK("STUB %s\n", __FUNCTION__);
912 switch (sc_reg_in) {
913 case SCR_STATUS:
914 dev->sata_dev.sstatus = val;
915 break;
916 case SCR_CONTROL:
917 dev->sata_dev.scontrol = val;
918 break;
919 case SCR_ERROR:
920 dev->sata_dev.serror = val;
921 break;
922 case SCR_ACTIVE:
923 dev->sata_dev.ap->sactive = val;
924 break;
925 }
926}
927
928static u32 sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in)
929{
930 struct domain_device *dev = ap->private_data;
931
932 SAS_DPRINTK("STUB %s\n", __FUNCTION__);
933 switch (sc_reg_in) {
934 case SCR_STATUS:
935 return dev->sata_dev.sstatus;
936 case SCR_CONTROL:
937 return dev->sata_dev.scontrol;
938 case SCR_ERROR:
939 return dev->sata_dev.serror;
940 case SCR_ACTIVE:
941 return dev->sata_dev.ap->sactive;
942 default:
943 return 0xffffffffU;
944 }
945}
946
947static struct ata_port_operations sas_sata_ops = {
948 .port_disable = ata_port_disable,
949 .check_status = sas_ata_check_status,
950 .check_altstatus = sas_ata_check_status,
951 .dev_select = ata_noop_dev_select,
952 .phy_reset = sas_ata_phy_reset,
953 .post_internal_cmd = sas_ata_post_internal,
954 .tf_read = sas_ata_tf_read,
955 .qc_prep = ata_noop_qc_prep,
956 .qc_issue = sas_ata_qc_issue,
957 .port_start = ata_sas_port_start,
958 .port_stop = ata_sas_port_stop,
959 .scr_read = sas_ata_scr_read,
960 .scr_write = sas_ata_scr_write
961};
962
963static struct ata_port_info sata_port_info = {
964 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET |
965 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
966 .pio_mask = 0x1f, /* PIO0-4 */
967 .mwdma_mask = 0x07, /* MWDMA0-2 */
968 .udma_mask = ATA_UDMA6,
969 .port_ops = &sas_sata_ops
970};
971
687struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) 972struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy)
688{ 973{
689 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent); 974 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent);
@@ -722,11 +1007,33 @@ static inline struct domain_device *sas_find_target(struct scsi_target *starget)
722 1007
723int sas_target_alloc(struct scsi_target *starget) 1008int sas_target_alloc(struct scsi_target *starget)
724{ 1009{
1010 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1011 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
725 struct domain_device *found_dev = sas_find_target(starget); 1012 struct domain_device *found_dev = sas_find_target(starget);
726 1013
727 if (!found_dev) 1014 if (!found_dev)
728 return -ENODEV; 1015 return -ENODEV;
729 1016
1017 if (dev_is_sata(found_dev)) {
1018 struct ata_port *ap;
1019
1020 ata_host_init(&found_dev->sata_dev.ata_host,
1021 &ha->pcidev->dev,
1022 sata_port_info.flags,
1023 &sas_sata_ops);
1024 ap = ata_sas_port_alloc(&found_dev->sata_dev.ata_host,
1025 &sata_port_info,
1026 shost);
1027 if (!ap) {
1028 SAS_DPRINTK("ata_sas_port_alloc failed.\n");
1029 return -ENODEV;
1030 }
1031
1032 ap->private_data = found_dev;
1033 ap->cbl = ATA_CBL_SATA;
1034 found_dev->sata_dev.ap = ap;
1035 }
1036
730 starget->hostdata = found_dev; 1037 starget->hostdata = found_dev;
731 return 0; 1038 return 0;
732} 1039}
@@ -741,6 +1048,11 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
741 1048
742 BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE); 1049 BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE);
743 1050
1051 if (dev_is_sata(dev)) {
1052 ata_sas_slave_configure(scsi_dev, dev->sata_dev.ap);
1053 return 0;
1054 }
1055
744 sas_ha = dev->port->ha; 1056 sas_ha = dev->port->ha;
745 1057
746 sas_read_port_mode_page(scsi_dev); 1058 sas_read_port_mode_page(scsi_dev);
@@ -764,6 +1076,10 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
764 1076
765void sas_slave_destroy(struct scsi_device *scsi_dev) 1077void sas_slave_destroy(struct scsi_device *scsi_dev)
766{ 1078{
1079 struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
1080
1081 if (dev_is_sata(dev))
1082 ata_port_disable(dev->sata_dev.ap);
767} 1083}
768 1084
769int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth) 1085int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth)
@@ -984,6 +1300,29 @@ void sas_task_abort(struct sas_task *task)
984 scsi_schedule_eh(sc->device->host); 1300 scsi_schedule_eh(sc->device->host);
985} 1301}
986 1302
1303int sas_slave_alloc(struct scsi_device *scsi_dev)
1304{
1305 struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
1306
1307 if (dev_is_sata(dev))
1308 return ata_sas_port_init(dev->sata_dev.ap);
1309
1310 return 0;
1311}
1312
1313void sas_target_destroy(struct scsi_target *starget)
1314{
1315 struct domain_device *found_dev = sas_find_target(starget);
1316
1317 if (!found_dev)
1318 return;
1319
1320 if (dev_is_sata(found_dev))
1321 ata_sas_port_destroy(found_dev->sata_dev.ap);
1322
1323 return;
1324}
1325
987EXPORT_SYMBOL_GPL(sas_queuecommand); 1326EXPORT_SYMBOL_GPL(sas_queuecommand);
988EXPORT_SYMBOL_GPL(sas_target_alloc); 1327EXPORT_SYMBOL_GPL(sas_target_alloc);
989EXPORT_SYMBOL_GPL(sas_slave_configure); 1328EXPORT_SYMBOL_GPL(sas_slave_configure);
@@ -997,3 +1336,6 @@ EXPORT_SYMBOL_GPL(sas_phy_reset);
997EXPORT_SYMBOL_GPL(sas_phy_enable); 1336EXPORT_SYMBOL_GPL(sas_phy_enable);
998EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); 1337EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
999EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); 1338EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
1339EXPORT_SYMBOL_GPL(sas_slave_alloc);
1340EXPORT_SYMBOL_GPL(sas_target_destroy);
1341EXPORT_SYMBOL_GPL(sas_ioctl);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 2e6bdc4e7a0a..ce20177069a4 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -30,6 +30,7 @@
30#include <linux/timer.h> 30#include <linux/timer.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <scsi/sas.h> 32#include <scsi/sas.h>
33#include <linux/libata.h>
33#include <linux/list.h> 34#include <linux/list.h>
34#include <asm/semaphore.h> 35#include <asm/semaphore.h>
35#include <scsi/scsi_device.h> 36#include <scsi/scsi_device.h>
@@ -165,6 +166,13 @@ struct sata_device {
165 166
166 u8 port_no; /* port number, if this is a PM (Port) */ 167 u8 port_no; /* port number, if this is a PM (Port) */
167 struct list_head children; /* PM Ports if this is a PM */ 168 struct list_head children; /* PM Ports if this is a PM */
169
170 struct ata_port *ap;
171 struct ata_host ata_host;
172 struct ata_taskfile tf;
173 u32 sstatus;
174 u32 serror;
175 u32 scontrol;
168}; 176};
169 177
170/* ---------- Domain device ---------- */ 178/* ---------- Domain device ---------- */
@@ -661,4 +669,8 @@ int __sas_task_abort(struct sas_task *);
661int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); 669int sas_eh_device_reset_handler(struct scsi_cmnd *cmd);
662int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd); 670int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd);
663 671
672extern void sas_target_destroy(struct scsi_target *);
673extern int sas_slave_alloc(struct scsi_device *);
674extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg);
675
664#endif /* _SASLIB_H_ */ 676#endif /* _SASLIB_H_ */