Display SPI transfer agreement in common code
PATCH 1/1 Display SPI transfer agreement in common code
Introduce a generic SPI function to print the negotiated transfer agreement. It's based on the implementation in sym53c8xx_2/sym_misc.c.
Quoted 1 line
From a quick look, 53c700, ncr53c8xx and sym2 can use it easily.
Other drivers need to be converted to use the SPI transport layer first.
In order to calculate the speed I needed to be able to convert from period factor to period in picoseconds. That required changing (show|store)_spi_transport_period to work in picoseconds rather than a string.
Index: ./drivers/scsi/scsi_transport_spi.c
===================================================================
RCS file: /var/lib/cvs/linux-2.6/drivers/scsi/scsi_transport_spi.c,v retrieving revision 1.10
drivers/scsi/scsi_transport_spi.c +101 -58
@@ -18,15 +18,11 @@* along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/module.h> +#include <linux/ctype.h> #include <linux/init.h> -#include <linux/smp_lock.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/mm.h> +#include <linux/module.h> #include <linux/workqueue.h> -#include <asm/scatterlist.h> -#include <asm/io.h> +#include <asm/semaphore.h> #include <scsi/scsi.h> #include "scsi_priv.h" #include <scsi/scsi_device.h>
@@ -63,22 +59,22 @@ struct spi_internal {#define to_spi_internal (tmpl) container_of(tmpl, struct spi_internal, t) -static const char *const ppr_to_ns[] = { +static const int ppr_to_ps[] = {/* The PPR values 0-6 are reserved, fill them in when * the committee defines them */ -NULL ,/* 0x00 */ -NULL ,/* 0x01 */ -NULL ,/* 0x02 */ -NULL ,/* 0x03 */ -NULL ,/* 0x04 */ -NULL ,/* 0x05 */ -NULL ,/* 0x06 */ -"3.125" ,/* 0x07 */ -"6.25" ,/* 0x08 */ -"12.5" ,/* 0x09 */ -"25" ,/* 0x0a */ -"30.3" ,/* 0x0b */ -"50" ,/* 0x0c */ +-1 ,/* 0x00 */ +-1 ,/* 0x01 */ +-1 ,/* 0x02 */ +-1 ,/* 0x03 */ +-1 ,/* 0x04 */ +-1 ,/* 0x05 */ +-1 ,/* 0x06 */ +3125 ,/* 0x07 */ +6250 ,/* 0x08 */ +12500 ,/* 0x09 */ +25000 ,/* 0x0a */ +30300 ,/* 0x0b */ +50000 ,/* 0x0c */ };/* The PPR values at which you calculate the period in ns by multiplying * by 4 */
@@ -261,7 +257,7 @@ static ssize_t show_spi_transport_periodstruct scsi_target *starget =transport_class_to_starget (cdev);struct Scsi_Host *shost =dev_to_shost (starget->dev.parent);struct spi_transport_attrs *tp; -const char *str; +int picosec;struct spi_internal *i =to_spi_internal (shost->transportt); tp = (struct spi_transport_attrs *)&starget->starget_data;
@@ -269,22 +265,19 @@ static ssize_t show_spi_transport_periodif (i->f->get_period) i->f->get_period (starget); -switch (tp->period) { - - case 0x07 ... SPI_STATIC_PPR: - str = ppr_to_ns[tp->period]; -if (!str) - str ="reserved" ; -break ; - - - case (SPI_STATIC_PPR+1) ... 0xff: -return sprintf (buf,"%d\n" , tp->period *4 ); - -default : - str ="unknown" ; +if (tp->period <0 || tp->period >0xff ) { + picosec =-1 ; + }else if (tp->period <=SPI_STATIC_PPR ) { + picosec = ppr_to_ps[tp->period]; + }else { + picosec = tp->period *4000 ; } -return sprintf (buf,"%s\n" , str); + +if (picosec ==-1 ) +return sprintf (buf,"reserved" ); +if (picosec %1000 ==0 ) +return sprintf (buf,"%d\n" , picosec /1000 ); +return sprintf (buf,"%d.%d\n" , picosec /1000 , picosec %1000 ); } static ssize_t
@@ -294,34 +287,30 @@ store_spi_transport_period(struct class_struct scsi_target *starget =transport_class_to_starget (cdev);struct Scsi_Host *shost =dev_to_shost (starget->dev.parent);struct spi_internal *i =to_spi_internal (shost->transportt); -int j, period =-1 ; +int j, picosec, period =-1 ; +char *endp; -for (j =0 ; j <SPI_STATIC_PPR ; j++) { -int len; - -if (ppr_to_ns[j] ==NULL ) -continue ; - - len =strlen (ppr_to_ns[j]); - -if (strncmp (ppr_to_ns[j], buf, len) !=0 ) -continue ; + picosec =simple_strtoul (buf, &endp,10 ) *1000 ; +if (*endp =='.' ) { +int mult =100 ; +do { + endp++; +if (!isdigit (*endp)) +break ; + picosec += (*endp -'0' ) * mult; + mult /=10 ; + }while (mult >0 ); + } -if (buf[len] !='\n' ) +for (j =0 ; j <=SPI_STATIC_PPR ; j++) { +if (ppr_to_ps[j] < picosec)continue ; - period = j;break ; } -if (period ==-1 ) { -int val =simple_strtoul (buf,NULL ,0 ); - - -/* Should probably check limits here, but this -* gets reasonably close to OK for most things */ - period = val/4 ; - } +if (period ==-1 ) + period = picosec /4000 ;if (period >0xff ) period =0xff ;
@@ -794,6 +783,60 @@ spi_schedule_dv_device(struct scsi_devicschedule_work (&wqw->work); }EXPORT_SYMBOL (spi_schedule_dv_device); + +/** +* spi_display_xfer_agreement - Print the current target transfer agreement +* @starget: The target for which to display the agreement +* +* Each SPI port is required to maintain a transfer agreement for each +* other port on the bus. This function prints a one-line summary of +* the current agreement; more detailed information is available in sysfs. +*/ +void spi_display_xfer_agreement (struct scsi_target *starget) +{ +struct spi_transport_attrs *tp; + tp = (struct spi_transport_attrs *)&starget->starget_data; + +if (tp->offset >0 && tp->period >0 ) { +unsigned int picosec, kb100; +char *scsi ="FAST-?" ; + +if (tp->period <=SPI_STATIC_PPR ) { + picosec = ppr_to_ps[tp->period]; +switch (tp->period) { +case 7 : scsi ="FAST-320" ;break ; +case 8 : scsi ="FAST-160" ;break ; +case 9 : scsi ="FAST-80" ;break ; +case 10 : +case 11 : scsi ="FAST-40" ;break ; +case 12 : scsi ="FAST-20" ;break ; + } + }else { + picosec = tp->period *4000 ; +if (tp->period <25 ) + scsi ="FAST-20" ; +else if (tp->period <50 ) + scsi ="FAST-10" ; +else + scsi ="FAST-5" ; + } + + kb100 = (10000000 + picosec /2 ) / picosec; +if (tp->width) + kb100 *=2 ; + +dev_info (&starget->dev, +"%s %sSCSI %d.%d MB/s %s%s%s (%d.%d ns, offset %d)\n" , + scsi, tp->width ?"WIDE " :"" , kb100/10 , kb100 %10 , + tp->dt ?"DT" :"ST" , tp->iu ?" IU" :"" , + tp->qas ?" QAS" :"" , picosec /1000 , picosec %1000 , + tp->offset); + }else { +dev_info (&starget->dev,"%sasynchronous.\n" , + tp->width ?"wide " :"" ); + } +} +EXPORT_SYMBOL (spi_display_xfer_agreement);#define SETUP_ATTRIBUTE (field) \ i->private_attrs[count] = class_device_attr_##field; \
Index: ./include/scsi/scsi_transport_spi.h
===================================================================
RCS file: /var/lib/cvs/linux-2.6/include/scsi/scsi_transport_spi.h,v retrieving revision 1.5
include/scsi/scsi_transport_spi.h +1 -0
@@ -130,5 +130,6 @@ struct scsi_transport_template *spi_attavoid spi_release_transport (struct scsi_transport_template *);void spi_schedule_dv_device (struct scsi_device *);void spi_dv_device (struct scsi_device *); +void spi_display_xfer_agreement (struct scsi_target *);#endif /* SCSI_TRANSPORT_SPI_H */
Signature · 6 lines
"Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain