aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_transport_spi.c188
-rw-r--r--include/scsi/scsi_transport_spi.h6
2 files changed, 167 insertions, 27 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 28966d05435c..67c6cc40ce16 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -35,7 +35,7 @@
35 35
36#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a) 36#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a)
37 37
38#define SPI_NUM_ATTRS 10 /* increase this if you add attributes */ 38#define SPI_NUM_ATTRS 13 /* increase this if you add attributes */
39#define SPI_OTHER_ATTRS 1 /* Increase this if you add "always 39#define SPI_OTHER_ATTRS 1 /* Increase this if you add "always
40 * on" attributes */ 40 * on" attributes */
41#define SPI_HOST_ATTRS 1 41#define SPI_HOST_ATTRS 1
@@ -219,8 +219,11 @@ static int spi_setup_transport_attrs(struct device *dev)
219 struct scsi_target *starget = to_scsi_target(dev); 219 struct scsi_target *starget = to_scsi_target(dev);
220 220
221 spi_period(starget) = -1; /* illegal value */ 221 spi_period(starget) = -1; /* illegal value */
222 spi_min_period(starget) = 0;
222 spi_offset(starget) = 0; /* async */ 223 spi_offset(starget) = 0; /* async */
224 spi_max_offset(starget) = 255;
223 spi_width(starget) = 0; /* narrow */ 225 spi_width(starget) = 0; /* narrow */
226 spi_max_width(starget) = 1;
224 spi_iu(starget) = 0; /* no IU */ 227 spi_iu(starget) = 0; /* no IU */
225 spi_dt(starget) = 0; /* ST */ 228 spi_dt(starget) = 0; /* ST */
226 spi_qas(starget) = 0; 229 spi_qas(starget) = 0;
@@ -235,6 +238,34 @@ static int spi_setup_transport_attrs(struct device *dev)
235 return 0; 238 return 0;
236} 239}
237 240
241#define spi_transport_show_simple(field, format_string) \
242 \
243static ssize_t \
244show_spi_transport_##field(struct class_device *cdev, char *buf) \
245{ \
246 struct scsi_target *starget = transport_class_to_starget(cdev); \
247 struct spi_transport_attrs *tp; \
248 \
249 tp = (struct spi_transport_attrs *)&starget->starget_data; \
250 return snprintf(buf, 20, format_string, tp->field); \
251}
252
253#define spi_transport_store_simple(field, format_string) \
254 \
255static ssize_t \
256store_spi_transport_##field(struct class_device *cdev, const char *buf, \
257 size_t count) \
258{ \
259 int val; \
260 struct scsi_target *starget = transport_class_to_starget(cdev); \
261 struct spi_transport_attrs *tp; \
262 \
263 tp = (struct spi_transport_attrs *)&starget->starget_data; \
264 val = simple_strtoul(buf, NULL, 0); \
265 tp->field = val; \
266 return count; \
267}
268
238#define spi_transport_show_function(field, format_string) \ 269#define spi_transport_show_function(field, format_string) \
239 \ 270 \
240static ssize_t \ 271static ssize_t \
@@ -261,6 +292,25 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
261 struct spi_internal *i = to_spi_internal(shost->transportt); \ 292 struct spi_internal *i = to_spi_internal(shost->transportt); \
262 \ 293 \
263 val = simple_strtoul(buf, NULL, 0); \ 294 val = simple_strtoul(buf, NULL, 0); \
295 i->f->set_##field(starget, val); \
296 return count; \
297}
298
299#define spi_transport_store_max(field, format_string) \
300static ssize_t \
301store_spi_transport_##field(struct class_device *cdev, const char *buf, \
302 size_t count) \
303{ \
304 int val; \
305 struct scsi_target *starget = transport_class_to_starget(cdev); \
306 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
307 struct spi_internal *i = to_spi_internal(shost->transportt); \
308 struct spi_transport_attrs *tp \
309 = (struct spi_transport_attrs *)&starget->starget_data; \
310 \
311 val = simple_strtoul(buf, NULL, 0); \
312 if (val > tp->max_##field) \
313 val = tp->max_##field; \
264 i->f->set_##field(starget, val); \ 314 i->f->set_##field(starget, val); \
265 return count; \ 315 return count; \
266} 316}
@@ -272,9 +322,24 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
272 show_spi_transport_##field, \ 322 show_spi_transport_##field, \
273 store_spi_transport_##field); 323 store_spi_transport_##field);
274 324
325#define spi_transport_simple_attr(field, format_string) \
326 spi_transport_show_simple(field, format_string) \
327 spi_transport_store_simple(field, format_string) \
328static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
329 show_spi_transport_##field, \
330 store_spi_transport_##field);
331
332#define spi_transport_max_attr(field, format_string) \
333 spi_transport_show_function(field, format_string) \
334 spi_transport_store_max(field, format_string) \
335 spi_transport_simple_attr(max_##field, format_string) \
336static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
337 show_spi_transport_##field, \
338 store_spi_transport_##field);
339
275/* The Parallel SCSI Tranport Attributes: */ 340/* The Parallel SCSI Tranport Attributes: */
276spi_transport_rd_attr(offset, "%d\n"); 341spi_transport_max_attr(offset, "%d\n");
277spi_transport_rd_attr(width, "%d\n"); 342spi_transport_max_attr(width, "%d\n");
278spi_transport_rd_attr(iu, "%d\n"); 343spi_transport_rd_attr(iu, "%d\n");
279spi_transport_rd_attr(dt, "%d\n"); 344spi_transport_rd_attr(dt, "%d\n");
280spi_transport_rd_attr(qas, "%d\n"); 345spi_transport_rd_attr(qas, "%d\n");
@@ -300,26 +365,18 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
300 365
301/* Translate the period into ns according to the current spec 366/* Translate the period into ns according to the current spec
302 * for SDTR/PPR messages */ 367 * for SDTR/PPR messages */
303static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) 368static ssize_t
304 369show_spi_transport_period_helper(struct class_device *cdev, char *buf,
370 int period)
305{ 371{
306 struct scsi_target *starget = transport_class_to_starget(cdev);
307 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
308 struct spi_transport_attrs *tp;
309 int len, picosec; 372 int len, picosec;
310 struct spi_internal *i = to_spi_internal(shost->transportt);
311
312 tp = (struct spi_transport_attrs *)&starget->starget_data;
313
314 if (i->f->get_period)
315 i->f->get_period(starget);
316 373
317 if (tp->period < 0 || tp->period > 0xff) { 374 if (period < 0 || period > 0xff) {
318 picosec = -1; 375 picosec = -1;
319 } else if (tp->period <= SPI_STATIC_PPR) { 376 } else if (period <= SPI_STATIC_PPR) {
320 picosec = ppr_to_ps[tp->period]; 377 picosec = ppr_to_ps[period];
321 } else { 378 } else {
322 picosec = tp->period * 4000; 379 picosec = period * 4000;
323 } 380 }
324 381
325 if (picosec == -1) { 382 if (picosec == -1) {
@@ -334,12 +391,9 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
334} 391}
335 392
336static ssize_t 393static ssize_t
337store_spi_transport_period(struct class_device *cdev, const char *buf, 394store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
338 size_t count) 395 size_t count, int *periodp)
339{ 396{
340 struct scsi_target *starget = transport_class_to_starget(cdev);
341 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
342 struct spi_internal *i = to_spi_internal(shost->transportt);
343 int j, picosec, period = -1; 397 int j, picosec, period = -1;
344 char *endp; 398 char *endp;
345 399
@@ -368,15 +422,79 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
368 if (period > 0xff) 422 if (period > 0xff)
369 period = 0xff; 423 period = 0xff;
370 424
371 i->f->set_period(starget, period); 425 *periodp = period;
372 426
373 return count; 427 return count;
374} 428}
375 429
430static ssize_t
431show_spi_transport_period(struct class_device *cdev, char *buf)
432{
433 struct scsi_target *starget = transport_class_to_starget(cdev);
434 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
435 struct spi_internal *i = to_spi_internal(shost->transportt);
436 struct spi_transport_attrs *tp =
437 (struct spi_transport_attrs *)&starget->starget_data;
438
439 if (i->f->get_period)
440 i->f->get_period(starget);
441
442 return show_spi_transport_period_helper(cdev, buf, tp->period);
443}
444
445static ssize_t
446store_spi_transport_period(struct class_device *cdev, const char *buf,
447 size_t count)
448{
449 struct scsi_target *starget = transport_class_to_starget(cdev);
450 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
451 struct spi_internal *i = to_spi_internal(shost->transportt);
452 struct spi_transport_attrs *tp =
453 (struct spi_transport_attrs *)&starget->starget_data;
454 int period, retval;
455
456 retval = store_spi_transport_period_helper(cdev, buf, count, &period);
457
458 if (period < tp->min_period)
459 period = tp->min_period;
460
461 i->f->set_period(starget, period);
462
463 return retval;
464}
465
376static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, 466static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR,
377 show_spi_transport_period, 467 show_spi_transport_period,
378 store_spi_transport_period); 468 store_spi_transport_period);
379 469
470static ssize_t
471show_spi_transport_min_period(struct class_device *cdev, char *buf)
472{
473 struct scsi_target *starget = transport_class_to_starget(cdev);
474 struct spi_transport_attrs *tp =
475 (struct spi_transport_attrs *)&starget->starget_data;
476
477 return show_spi_transport_period_helper(cdev, buf, tp->min_period);
478}
479
480static ssize_t
481store_spi_transport_min_period(struct class_device *cdev, const char *buf,
482 size_t count)
483{
484 struct scsi_target *starget = transport_class_to_starget(cdev);
485 struct spi_transport_attrs *tp =
486 (struct spi_transport_attrs *)&starget->starget_data;
487
488 return store_spi_transport_period_helper(cdev, buf, count,
489 &tp->min_period);
490}
491
492
493static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR,
494 show_spi_transport_min_period,
495 store_spi_transport_min_period);
496
497
380static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) 498static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf)
381{ 499{
382 struct Scsi_Host *shost = transport_class_to_shost(cdev); 500 struct Scsi_Host *shost = transport_class_to_shost(cdev);
@@ -642,6 +760,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
642{ 760{
643 struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); 761 struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
644 struct scsi_device *sdev = sreq->sr_device; 762 struct scsi_device *sdev = sreq->sr_device;
763 struct scsi_target *starget = sdev->sdev_target;
645 int len = sdev->inquiry_len; 764 int len = sdev->inquiry_len;
646 /* first set us up for narrow async */ 765 /* first set us up for narrow async */
647 DV_SET(offset, 0); 766 DV_SET(offset, 0);
@@ -655,9 +774,11 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
655 } 774 }
656 775
657 /* test width */ 776 /* test width */
658 if (i->f->set_width && sdev->wdtr) { 777 if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) {
659 i->f->set_width(sdev->sdev_target, 1); 778 i->f->set_width(sdev->sdev_target, 1);
660 779
780 printk("WIDTH IS %d\n", spi_max_width(starget));
781
661 if (spi_dv_device_compare_inquiry(sreq, buffer, 782 if (spi_dv_device_compare_inquiry(sreq, buffer,
662 buffer + len, 783 buffer + len,
663 DV_LOOPS) 784 DV_LOOPS)
@@ -684,8 +805,8 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
684 retry: 805 retry:
685 806
686 /* now set up to the maximum */ 807 /* now set up to the maximum */
687 DV_SET(offset, 255); 808 DV_SET(offset, spi_max_offset(starget));
688 DV_SET(period, 1); 809 DV_SET(period, spi_min_period(starget));
689 810
690 if (len == 0) { 811 if (len == 0) {
691 SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n"); 812 SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
@@ -892,6 +1013,16 @@ EXPORT_SYMBOL(spi_display_xfer_agreement);
892 if (i->f->show_##field) \ 1013 if (i->f->show_##field) \
893 count++ 1014 count++
894 1015
1016#define SETUP_RELATED_ATTRIBUTE(field, rel_field) \
1017 i->private_attrs[count] = class_device_attr_##field; \
1018 if (!i->f->set_##rel_field) { \
1019 i->private_attrs[count].attr.mode = S_IRUGO; \
1020 i->private_attrs[count].store = NULL; \
1021 } \
1022 i->attrs[count] = &i->private_attrs[count]; \
1023 if (i->f->show_##rel_field) \
1024 count++
1025
895#define SETUP_HOST_ATTRIBUTE(field) \ 1026#define SETUP_HOST_ATTRIBUTE(field) \
896 i->private_host_attrs[count] = class_device_attr_##field; \ 1027 i->private_host_attrs[count] = class_device_attr_##field; \
897 if (!i->f->set_##field) { \ 1028 if (!i->f->set_##field) { \
@@ -975,8 +1106,11 @@ spi_attach_transport(struct spi_function_template *ft)
975 i->f = ft; 1106 i->f = ft;
976 1107
977 SETUP_ATTRIBUTE(period); 1108 SETUP_ATTRIBUTE(period);
1109 SETUP_RELATED_ATTRIBUTE(min_period, period);
978 SETUP_ATTRIBUTE(offset); 1110 SETUP_ATTRIBUTE(offset);
1111 SETUP_RELATED_ATTRIBUTE(max_offset, offset);
979 SETUP_ATTRIBUTE(width); 1112 SETUP_ATTRIBUTE(width);
1113 SETUP_RELATED_ATTRIBUTE(max_width, width);
980 SETUP_ATTRIBUTE(iu); 1114 SETUP_ATTRIBUTE(iu);
981 SETUP_ATTRIBUTE(dt); 1115 SETUP_ATTRIBUTE(dt);
982 SETUP_ATTRIBUTE(qas); 1116 SETUP_ATTRIBUTE(qas);
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index 6dcf497bf46d..a30d6cd4c0e8 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -27,8 +27,11 @@ struct scsi_transport_template;
27 27
28struct spi_transport_attrs { 28struct spi_transport_attrs {
29 int period; /* value in the PPR/SDTR command */ 29 int period; /* value in the PPR/SDTR command */
30 int min_period;
30 int offset; 31 int offset;
32 int max_offset;
31 unsigned int width:1; /* 0 - narrow, 1 - wide */ 33 unsigned int width:1; /* 0 - narrow, 1 - wide */
34 unsigned int max_width:1;
32 unsigned int iu:1; /* Information Units enabled */ 35 unsigned int iu:1; /* Information Units enabled */
33 unsigned int dt:1; /* DT clocking enabled */ 36 unsigned int dt:1; /* DT clocking enabled */
34 unsigned int qas:1; /* Quick Arbitration and Selection enabled */ 37 unsigned int qas:1; /* Quick Arbitration and Selection enabled */
@@ -63,8 +66,11 @@ struct spi_host_attrs {
63 66
64/* accessor functions */ 67/* accessor functions */
65#define spi_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->period) 68#define spi_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->period)
69#define spi_min_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->min_period)
66#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->offset) 70#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->offset)
71#define spi_max_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_offset)
67#define spi_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->width) 72#define spi_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->width)
73#define spi_max_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_width)
68#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->starget_data)->iu) 74#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->starget_data)->iu)
69#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dt) 75#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dt)
70#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->starget_data)->qas) 76#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->starget_data)->qas)