aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2005-05-06 19:05:20 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-05-20 16:54:32 -0400
commit62a8612972eaea804e1e42c63ee403cd4e14cc35 (patch)
tree15411e03ce3030849bb99e5d89874bb4032e32e6 /drivers/scsi
parent88d7bd8cb9eb8d64bf7997600b0d64f7834047c5 (diff)
[SCSI] implement parameter limits in the SPI transport class
There's a basic need not to have parameters go under or over certain values when doing domain validation. The basic ones are max_offset, max_width and min_period This patch makes the transport class take and enforce these three limits. Currently they can be set by the user, although they could obviously be read from the HBA's on-board NVRAM area during slave_configure (if it has one). Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_transport_spi.c188
1 files changed, 161 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);