update spi transport class so that u320 Domain Validation works
PATCH 1/1 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.
James
drivers/scsi/scsi_transport_spi.c +53 -24
@@ -669,6 +669,7 @@ spi_dv_retrain(struct scsi_request *sreq {struct spi_internal *i =to_spi_internal (sreq->sr_host->transportt);struct scsi_device *sdev = sreq->sr_device; +struct scsi_target *starget = sdev->sdev_target;int period =0 , prevperiod =0 ;enum spi_compare_returns retval;
@@ -682,24 +683,40 @@ spi_dv_retrain(struct scsi_request *sreqbreak ;/* OK, retrain, fallback */ +if (i->f->get_iu) + i->f->get_iu (starget); +if (i->f->get_qas) + i->f->get_qas (starget);if (i->f->get_period) i->f->get_period (sdev->sdev_target); - newperiod =spi_period (sdev->sdev_target); - period = newperiod > period ? newperiod : period; -if (period <0x0d ) - period++; -else - period += period >>1 ; - -if (unlikely (period >0xff || period == prevperiod)) { -/* Total failure; set to async and return */ -SPI_PRINTK (sdev->sdev_target,KERN_ERR ,"Domain Validation Failure, dropping back to Asynchronous\n" ); -DV_SET (offset,0 ); -return SPI_COMPARE_FAILURE ; + +/* Here's the fallback sequence; first try turning off +* IU, then QAS (if we can control them), then finally +* fall down the periods */ +if (i->f->set_iu &&spi_iu (starget)) { +SPI_PRINTK (starget,KERN_ERR ,"Domain Validation Disabing Information Units\n" ); +DV_SET (iu,0 ); + }else if (i->f->set_qas &&spi_qas (starget)) { +SPI_PRINTK (starget,KERN_ERR ,"Domain Validation Disabing Quick Arbitration and Selection\n" ); +DV_SET (qas,0 ); + }else { + newperiod =spi_period (starget); + period = newperiod > period ? newperiod : period; +if (period <0x0d ) + period++; +else + period += period >>1 ; + +if (unlikely (period >0xff || period == prevperiod)) { +/* Total failure; set to async and return */ +SPI_PRINTK (starget,KERN_ERR ,"Domain Validation Failure, dropping back to Asynchronous\n" ); +DV_SET (offset,0 ); +return SPI_COMPARE_FAILURE ; + } +SPI_PRINTK (starget,KERN_ERR ,"Domain Validation detected failure, dropping back\n" ); +DV_SET (period, period); + prevperiod = period; } -SPI_PRINTK (sdev->sdev_target,KERN_ERR ,"Domain Validation detected failure, dropping back\n" ); -DV_SET (period, period); - prevperiod = period; }return retval; }
@@ -768,23 +785,21 @@ spi_dv_device_internal(struct scsi_requeif (spi_dv_device_compare_inquiry (sreq, buffer, buffer,DV_LOOPS ) !=SPI_COMPARE_SUCCESS ) { -SPI_PRINTK (sdev->sdev_target,KERN_ERR ,"Domain Validation Initial Inquiry Failed\n" ); +SPI_PRINTK (starget,KERN_ERR ,"Domain Validation Initial Inquiry Failed\n" );/* FIXME: should probably offline the device here? */ return ; }/* test width */ if (i->f->set_width &&spi_max_width (starget) && sdev->wdtr) { - i->f->set_width (sdev->sdev_target,1 ); - -printk ("WIDTH IS %d\n" ,spi_max_width (starget)); + i->f->set_width (starget,1 );if (spi_dv_device_compare_inquiry (sreq, buffer, buffer + len,DV_LOOPS ) !=SPI_COMPARE_SUCCESS ) { -SPI_PRINTK (sdev->sdev_target,KERN_ERR ,"Wide Transfers Fail\n" ); - i->f->set_width (sdev->sdev_target,0 ); +SPI_PRINTK (starget,KERN_ERR ,"Wide Transfers Fail\n" ); + i->f->set_width (starget,0 ); } }
@@ -792,7 +807,7 @@ spi_dv_device_internal(struct scsi_requereturn ;/* device can't handle synchronous */ -if (!sdev->ppr && !sdev->sdtr) +if (!sdev->ppr && !sdev->sdtr)return ;/* see if the device has an echo buffer. If it does we can
@@ -807,16 +822,30 @@ spi_dv_device_internal(struct scsi_reque/* now set up to the maximum */ DV_SET (offset,spi_max_offset (starget));DV_SET (period,spi_min_period (starget)); +/* try QAS requests; this should be harmless to set if the +* target supports it */ +DV_SET (qas,1 ); +/* Also try IU transfers */ +DV_SET (iu,1 ); +if (spi_min_period (starget) <9 ) { +/* This u320 (or u640). Ignore the coupled parameters +* like DT and IU, but set the optional ones */ +DV_SET (rd_strm,1 ); +DV_SET (wr_flow,1 ); +DV_SET (rti,1 ); +if (spi_min_period (starget) ==8 ) +DV_SET (pcomp_en,1 ); + }if (len ==0 ) { -SPI_PRINTK (sdev->sdev_target,KERN_INFO ,"Domain Validation skipping write tests\n" ); +SPI_PRINTK (starget,KERN_INFO ,"Domain Validation skipping write tests\n" );spi_dv_retrain (sreq, buffer, buffer + len, spi_dv_device_compare_inquiry);return ; }if (len >SPI_MAX_ECHO_BUFFER_SIZE ) { -SPI_PRINTK (sdev->sdev_target,KERN_WARNING ,"Echo buffer size %d is too big, trimming to %d\n" , len,SPI_MAX_ECHO_BUFFER_SIZE ); +SPI_PRINTK (starget,KERN_WARNING ,"Echo buffer size %d is too big, trimming to %d\n" , len,SPI_MAX_ECHO_BUFFER_SIZE ); len =SPI_MAX_ECHO_BUFFER_SIZE ; }