aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2005-05-31 19:35:39 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-06-03 13:39:53 -0400
commit9a8bc9b84b783fd92315e56ce4d4ee78a2c6819c (patch)
tree752bf5545d8a7a9c6045cf6994deff1f96636391 /drivers/scsi
parent597487b9ba875785f3ee9bd541073e9edd2e700a (diff)
[SCSI] update spi transport class so that u320 Domain Validation works
There are several extra things that have to be considered when running Domain Validation on a u320 target (notably how you fall back). Hopefully this should help us when someone adds this transport class to aic79xx. I've tested this on the lsi1030, so I know it works correctly up to u320. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_transport_spi.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 67c6cc40ce16..c87ae469d707 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -669,6 +669,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
669{ 669{
670 struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); 670 struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
671 struct scsi_device *sdev = sreq->sr_device; 671 struct scsi_device *sdev = sreq->sr_device;
672 struct scsi_target *starget = sdev->sdev_target;
672 int period = 0, prevperiod = 0; 673 int period = 0, prevperiod = 0;
673 enum spi_compare_returns retval; 674 enum spi_compare_returns retval;
674 675
@@ -682,24 +683,40 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
682 break; 683 break;
683 684
684 /* OK, retrain, fallback */ 685 /* OK, retrain, fallback */
686 if (i->f->get_iu)
687 i->f->get_iu(starget);
688 if (i->f->get_qas)
689 i->f->get_qas(starget);
685 if (i->f->get_period) 690 if (i->f->get_period)
686 i->f->get_period(sdev->sdev_target); 691 i->f->get_period(sdev->sdev_target);
687 newperiod = spi_period(sdev->sdev_target); 692
688 period = newperiod > period ? newperiod : period; 693 /* Here's the fallback sequence; first try turning off
689 if (period < 0x0d) 694 * IU, then QAS (if we can control them), then finally
690 period++; 695 * fall down the periods */
691 else 696 if (i->f->set_iu && spi_iu(starget)) {
692 period += period >> 1; 697 SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Information Units\n");
693 698 DV_SET(iu, 0);
694 if (unlikely(period > 0xff || period == prevperiod)) { 699 } else if (i->f->set_qas && spi_qas(starget)) {
695 /* Total failure; set to async and return */ 700 SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Quick Arbitration and Selection\n");
696 SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); 701 DV_SET(qas, 0);
697 DV_SET(offset, 0); 702 } else {
698 return SPI_COMPARE_FAILURE; 703 newperiod = spi_period(starget);
704 period = newperiod > period ? newperiod : period;
705 if (period < 0x0d)
706 period++;
707 else
708 period += period >> 1;
709
710 if (unlikely(period > 0xff || period == prevperiod)) {
711 /* Total failure; set to async and return */
712 SPI_PRINTK(starget, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
713 DV_SET(offset, 0);
714 return SPI_COMPARE_FAILURE;
715 }
716 SPI_PRINTK(starget, KERN_ERR, "Domain Validation detected failure, dropping back\n");
717 DV_SET(period, period);
718 prevperiod = period;
699 } 719 }
700 SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
701 DV_SET(period, period);
702 prevperiod = period;
703 } 720 }
704 return retval; 721 return retval;
705} 722}
@@ -768,23 +785,21 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
768 785
769 if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) 786 if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
770 != SPI_COMPARE_SUCCESS) { 787 != SPI_COMPARE_SUCCESS) {
771 SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); 788 SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
772 /* FIXME: should probably offline the device here? */ 789 /* FIXME: should probably offline the device here? */
773 return; 790 return;
774 } 791 }
775 792
776 /* test width */ 793 /* test width */
777 if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) { 794 if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) {
778 i->f->set_width(sdev->sdev_target, 1); 795 i->f->set_width(starget, 1);
779
780 printk("WIDTH IS %d\n", spi_max_width(starget));
781 796
782 if (spi_dv_device_compare_inquiry(sreq, buffer, 797 if (spi_dv_device_compare_inquiry(sreq, buffer,
783 buffer + len, 798 buffer + len,
784 DV_LOOPS) 799 DV_LOOPS)
785 != SPI_COMPARE_SUCCESS) { 800 != SPI_COMPARE_SUCCESS) {
786 SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n"); 801 SPI_PRINTK(starget, KERN_ERR, "Wide Transfers Fail\n");
787 i->f->set_width(sdev->sdev_target, 0); 802 i->f->set_width(starget, 0);
788 } 803 }
789 } 804 }
790 805
@@ -792,7 +807,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
792 return; 807 return;
793 808
794 /* device can't handle synchronous */ 809 /* device can't handle synchronous */
795 if(!sdev->ppr && !sdev->sdtr) 810 if (!sdev->ppr && !sdev->sdtr)
796 return; 811 return;
797 812
798 /* see if the device has an echo buffer. If it does we can 813 /* see if the device has an echo buffer. If it does we can
@@ -807,16 +822,30 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
807 /* now set up to the maximum */ 822 /* now set up to the maximum */
808 DV_SET(offset, spi_max_offset(starget)); 823 DV_SET(offset, spi_max_offset(starget));
809 DV_SET(period, spi_min_period(starget)); 824 DV_SET(period, spi_min_period(starget));
825 /* try QAS requests; this should be harmless to set if the
826 * target supports it */
827 DV_SET(qas, 1);
828 /* Also try IU transfers */
829 DV_SET(iu, 1);
830 if (spi_min_period(starget) < 9) {
831 /* This u320 (or u640). Ignore the coupled parameters
832 * like DT and IU, but set the optional ones */
833 DV_SET(rd_strm, 1);
834 DV_SET(wr_flow, 1);
835 DV_SET(rti, 1);
836 if (spi_min_period(starget) == 8)
837 DV_SET(pcomp_en, 1);
838 }
810 839
811 if (len == 0) { 840 if (len == 0) {
812 SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n"); 841 SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n");
813 spi_dv_retrain(sreq, buffer, buffer + len, 842 spi_dv_retrain(sreq, buffer, buffer + len,
814 spi_dv_device_compare_inquiry); 843 spi_dv_device_compare_inquiry);
815 return; 844 return;
816 } 845 }
817 846
818 if (len > SPI_MAX_ECHO_BUFFER_SIZE) { 847 if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
819 SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); 848 SPI_PRINTK(starget, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
820 len = SPI_MAX_ECHO_BUFFER_SIZE; 849 len = SPI_MAX_ECHO_BUFFER_SIZE;
821 } 850 }
822 851