diff options
author | Jeff Garzik <jgarzik@pretzel.yyz.us> | 2005-06-22 21:50:57 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-22 21:50:57 -0400 |
commit | a5324343955997d1439f26518ddac567cd5d134b (patch) | |
tree | f43558389c41e3a0f076c4ee55d77c4aa1561779 /drivers/scsi/scsi_transport_spi.c | |
parent | 8199d3a79c224bbe5943fa08684e1f93a17881b0 (diff) | |
parent | a4936044001694f033fe4ea94d6034d51a6b465c (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 277 |
1 files changed, 222 insertions, 55 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 28966d05435c..2918b9600db7 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 | \ | ||
243 | static ssize_t \ | ||
244 | show_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 | \ | ||
255 | static ssize_t \ | ||
256 | store_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 | \ |
240 | static ssize_t \ | 271 | static 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) \ | ||
300 | static ssize_t \ | ||
301 | store_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) \ | ||
328 | static 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) \ | ||
336 | static 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: */ |
276 | spi_transport_rd_attr(offset, "%d\n"); | 341 | spi_transport_max_attr(offset, "%d\n"); |
277 | spi_transport_rd_attr(width, "%d\n"); | 342 | spi_transport_max_attr(width, "%d\n"); |
278 | spi_transport_rd_attr(iu, "%d\n"); | 343 | spi_transport_rd_attr(iu, "%d\n"); |
279 | spi_transport_rd_attr(dt, "%d\n"); | 344 | spi_transport_rd_attr(dt, "%d\n"); |
280 | spi_transport_rd_attr(qas, "%d\n"); | 345 | spi_transport_rd_attr(qas, "%d\n"); |
@@ -283,43 +348,39 @@ spi_transport_rd_attr(rd_strm, "%d\n"); | |||
283 | spi_transport_rd_attr(rti, "%d\n"); | 348 | spi_transport_rd_attr(rti, "%d\n"); |
284 | spi_transport_rd_attr(pcomp_en, "%d\n"); | 349 | spi_transport_rd_attr(pcomp_en, "%d\n"); |
285 | 350 | ||
351 | /* we only care about the first child device so we return 1 */ | ||
352 | static int child_iter(struct device *dev, void *data) | ||
353 | { | ||
354 | struct scsi_device *sdev = to_scsi_device(dev); | ||
355 | |||
356 | spi_dv_device(sdev); | ||
357 | return 1; | ||
358 | } | ||
359 | |||
286 | static ssize_t | 360 | static ssize_t |
287 | store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count) | 361 | store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count) |
288 | { | 362 | { |
289 | struct scsi_target *starget = transport_class_to_starget(cdev); | 363 | struct scsi_target *starget = transport_class_to_starget(cdev); |
290 | 364 | ||
291 | /* FIXME: we're relying on an awful lot of device internals | 365 | device_for_each_child(&starget->dev, NULL, child_iter); |
292 | * here. We really need a function to get the first available | ||
293 | * child */ | ||
294 | struct device *dev = container_of(starget->dev.children.next, struct device, node); | ||
295 | struct scsi_device *sdev = to_scsi_device(dev); | ||
296 | spi_dv_device(sdev); | ||
297 | return count; | 366 | return count; |
298 | } | 367 | } |
299 | static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); | 368 | static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); |
300 | 369 | ||
301 | /* Translate the period into ns according to the current spec | 370 | /* Translate the period into ns according to the current spec |
302 | * for SDTR/PPR messages */ | 371 | * for SDTR/PPR messages */ |
303 | static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) | 372 | static ssize_t |
304 | 373 | show_spi_transport_period_helper(struct class_device *cdev, char *buf, | |
374 | int period) | ||
305 | { | 375 | { |
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; | 376 | int len, picosec; |
310 | struct spi_internal *i = to_spi_internal(shost->transportt); | ||
311 | 377 | ||
312 | tp = (struct spi_transport_attrs *)&starget->starget_data; | 378 | if (period < 0 || period > 0xff) { |
313 | |||
314 | if (i->f->get_period) | ||
315 | i->f->get_period(starget); | ||
316 | |||
317 | if (tp->period < 0 || tp->period > 0xff) { | ||
318 | picosec = -1; | 379 | picosec = -1; |
319 | } else if (tp->period <= SPI_STATIC_PPR) { | 380 | } else if (period <= SPI_STATIC_PPR) { |
320 | picosec = ppr_to_ps[tp->period]; | 381 | picosec = ppr_to_ps[period]; |
321 | } else { | 382 | } else { |
322 | picosec = tp->period * 4000; | 383 | picosec = period * 4000; |
323 | } | 384 | } |
324 | 385 | ||
325 | if (picosec == -1) { | 386 | if (picosec == -1) { |
@@ -334,12 +395,9 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) | |||
334 | } | 395 | } |
335 | 396 | ||
336 | static ssize_t | 397 | static ssize_t |
337 | store_spi_transport_period(struct class_device *cdev, const char *buf, | 398 | store_spi_transport_period_helper(struct class_device *cdev, const char *buf, |
338 | size_t count) | 399 | size_t count, int *periodp) |
339 | { | 400 | { |
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; | 401 | int j, picosec, period = -1; |
344 | char *endp; | 402 | char *endp; |
345 | 403 | ||
@@ -368,15 +426,79 @@ store_spi_transport_period(struct class_device *cdev, const char *buf, | |||
368 | if (period > 0xff) | 426 | if (period > 0xff) |
369 | period = 0xff; | 427 | period = 0xff; |
370 | 428 | ||
371 | i->f->set_period(starget, period); | 429 | *periodp = period; |
372 | 430 | ||
373 | return count; | 431 | return count; |
374 | } | 432 | } |
375 | 433 | ||
434 | static ssize_t | ||
435 | show_spi_transport_period(struct class_device *cdev, char *buf) | ||
436 | { | ||
437 | struct scsi_target *starget = transport_class_to_starget(cdev); | ||
438 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
439 | struct spi_internal *i = to_spi_internal(shost->transportt); | ||
440 | struct spi_transport_attrs *tp = | ||
441 | (struct spi_transport_attrs *)&starget->starget_data; | ||
442 | |||
443 | if (i->f->get_period) | ||
444 | i->f->get_period(starget); | ||
445 | |||
446 | return show_spi_transport_period_helper(cdev, buf, tp->period); | ||
447 | } | ||
448 | |||
449 | static ssize_t | ||
450 | store_spi_transport_period(struct class_device *cdev, const char *buf, | ||
451 | size_t count) | ||
452 | { | ||
453 | struct scsi_target *starget = transport_class_to_starget(cdev); | ||
454 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
455 | struct spi_internal *i = to_spi_internal(shost->transportt); | ||
456 | struct spi_transport_attrs *tp = | ||
457 | (struct spi_transport_attrs *)&starget->starget_data; | ||
458 | int period, retval; | ||
459 | |||
460 | retval = store_spi_transport_period_helper(cdev, buf, count, &period); | ||
461 | |||
462 | if (period < tp->min_period) | ||
463 | period = tp->min_period; | ||
464 | |||
465 | i->f->set_period(starget, period); | ||
466 | |||
467 | return retval; | ||
468 | } | ||
469 | |||
376 | static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, | 470 | static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, |
377 | show_spi_transport_period, | 471 | show_spi_transport_period, |
378 | store_spi_transport_period); | 472 | store_spi_transport_period); |
379 | 473 | ||
474 | static ssize_t | ||
475 | show_spi_transport_min_period(struct class_device *cdev, char *buf) | ||
476 | { | ||
477 | struct scsi_target *starget = transport_class_to_starget(cdev); | ||
478 | struct spi_transport_attrs *tp = | ||
479 | (struct spi_transport_attrs *)&starget->starget_data; | ||
480 | |||
481 | return show_spi_transport_period_helper(cdev, buf, tp->min_period); | ||
482 | } | ||
483 | |||
484 | static ssize_t | ||
485 | store_spi_transport_min_period(struct class_device *cdev, const char *buf, | ||
486 | size_t count) | ||
487 | { | ||
488 | struct scsi_target *starget = transport_class_to_starget(cdev); | ||
489 | struct spi_transport_attrs *tp = | ||
490 | (struct spi_transport_attrs *)&starget->starget_data; | ||
491 | |||
492 | return store_spi_transport_period_helper(cdev, buf, count, | ||
493 | &tp->min_period); | ||
494 | } | ||
495 | |||
496 | |||
497 | static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR, | ||
498 | show_spi_transport_min_period, | ||
499 | store_spi_transport_min_period); | ||
500 | |||
501 | |||
380 | static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) | 502 | static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) |
381 | { | 503 | { |
382 | struct Scsi_Host *shost = transport_class_to_shost(cdev); | 504 | struct Scsi_Host *shost = transport_class_to_shost(cdev); |
@@ -551,6 +673,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | |||
551 | { | 673 | { |
552 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); | 674 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); |
553 | struct scsi_device *sdev = sreq->sr_device; | 675 | struct scsi_device *sdev = sreq->sr_device; |
676 | struct scsi_target *starget = sdev->sdev_target; | ||
554 | int period = 0, prevperiod = 0; | 677 | int period = 0, prevperiod = 0; |
555 | enum spi_compare_returns retval; | 678 | enum spi_compare_returns retval; |
556 | 679 | ||
@@ -564,24 +687,40 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | |||
564 | break; | 687 | break; |
565 | 688 | ||
566 | /* OK, retrain, fallback */ | 689 | /* OK, retrain, fallback */ |
690 | if (i->f->get_iu) | ||
691 | i->f->get_iu(starget); | ||
692 | if (i->f->get_qas) | ||
693 | i->f->get_qas(starget); | ||
567 | if (i->f->get_period) | 694 | if (i->f->get_period) |
568 | i->f->get_period(sdev->sdev_target); | 695 | i->f->get_period(sdev->sdev_target); |
569 | newperiod = spi_period(sdev->sdev_target); | 696 | |
570 | period = newperiod > period ? newperiod : period; | 697 | /* Here's the fallback sequence; first try turning off |
571 | if (period < 0x0d) | 698 | * IU, then QAS (if we can control them), then finally |
572 | period++; | 699 | * fall down the periods */ |
573 | else | 700 | if (i->f->set_iu && spi_iu(starget)) { |
574 | period += period >> 1; | 701 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Information Units\n"); |
575 | 702 | DV_SET(iu, 0); | |
576 | if (unlikely(period > 0xff || period == prevperiod)) { | 703 | } else if (i->f->set_qas && spi_qas(starget)) { |
577 | /* Total failure; set to async and return */ | 704 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Quick Arbitration and Selection\n"); |
578 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); | 705 | DV_SET(qas, 0); |
579 | DV_SET(offset, 0); | 706 | } else { |
580 | return SPI_COMPARE_FAILURE; | 707 | newperiod = spi_period(starget); |
708 | period = newperiod > period ? newperiod : period; | ||
709 | if (period < 0x0d) | ||
710 | period++; | ||
711 | else | ||
712 | period += period >> 1; | ||
713 | |||
714 | if (unlikely(period > 0xff || period == prevperiod)) { | ||
715 | /* Total failure; set to async and return */ | ||
716 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); | ||
717 | DV_SET(offset, 0); | ||
718 | return SPI_COMPARE_FAILURE; | ||
719 | } | ||
720 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation detected failure, dropping back\n"); | ||
721 | DV_SET(period, period); | ||
722 | prevperiod = period; | ||
581 | } | 723 | } |
582 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n"); | ||
583 | DV_SET(period, period); | ||
584 | prevperiod = period; | ||
585 | } | 724 | } |
586 | return retval; | 725 | return retval; |
587 | } | 726 | } |
@@ -642,6 +781,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
642 | { | 781 | { |
643 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); | 782 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); |
644 | struct scsi_device *sdev = sreq->sr_device; | 783 | struct scsi_device *sdev = sreq->sr_device; |
784 | struct scsi_target *starget = sdev->sdev_target; | ||
645 | int len = sdev->inquiry_len; | 785 | int len = sdev->inquiry_len; |
646 | /* first set us up for narrow async */ | 786 | /* first set us up for narrow async */ |
647 | DV_SET(offset, 0); | 787 | DV_SET(offset, 0); |
@@ -649,21 +789,21 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
649 | 789 | ||
650 | if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) | 790 | if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) |
651 | != SPI_COMPARE_SUCCESS) { | 791 | != SPI_COMPARE_SUCCESS) { |
652 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); | 792 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); |
653 | /* FIXME: should probably offline the device here? */ | 793 | /* FIXME: should probably offline the device here? */ |
654 | return; | 794 | return; |
655 | } | 795 | } |
656 | 796 | ||
657 | /* test width */ | 797 | /* test width */ |
658 | if (i->f->set_width && sdev->wdtr) { | 798 | if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) { |
659 | i->f->set_width(sdev->sdev_target, 1); | 799 | i->f->set_width(starget, 1); |
660 | 800 | ||
661 | if (spi_dv_device_compare_inquiry(sreq, buffer, | 801 | if (spi_dv_device_compare_inquiry(sreq, buffer, |
662 | buffer + len, | 802 | buffer + len, |
663 | DV_LOOPS) | 803 | DV_LOOPS) |
664 | != SPI_COMPARE_SUCCESS) { | 804 | != SPI_COMPARE_SUCCESS) { |
665 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n"); | 805 | SPI_PRINTK(starget, KERN_ERR, "Wide Transfers Fail\n"); |
666 | i->f->set_width(sdev->sdev_target, 0); | 806 | i->f->set_width(starget, 0); |
667 | } | 807 | } |
668 | } | 808 | } |
669 | 809 | ||
@@ -671,7 +811,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
671 | return; | 811 | return; |
672 | 812 | ||
673 | /* device can't handle synchronous */ | 813 | /* device can't handle synchronous */ |
674 | if(!sdev->ppr && !sdev->sdtr) | 814 | if (!sdev->ppr && !sdev->sdtr) |
675 | return; | 815 | return; |
676 | 816 | ||
677 | /* see if the device has an echo buffer. If it does we can | 817 | /* see if the device has an echo buffer. If it does we can |
@@ -684,18 +824,32 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
684 | retry: | 824 | retry: |
685 | 825 | ||
686 | /* now set up to the maximum */ | 826 | /* now set up to the maximum */ |
687 | DV_SET(offset, 255); | 827 | DV_SET(offset, spi_max_offset(starget)); |
688 | DV_SET(period, 1); | 828 | DV_SET(period, spi_min_period(starget)); |
829 | /* try QAS requests; this should be harmless to set if the | ||
830 | * target supports it */ | ||
831 | DV_SET(qas, 1); | ||
832 | /* Also try IU transfers */ | ||
833 | DV_SET(iu, 1); | ||
834 | if (spi_min_period(starget) < 9) { | ||
835 | /* This u320 (or u640). Ignore the coupled parameters | ||
836 | * like DT and IU, but set the optional ones */ | ||
837 | DV_SET(rd_strm, 1); | ||
838 | DV_SET(wr_flow, 1); | ||
839 | DV_SET(rti, 1); | ||
840 | if (spi_min_period(starget) == 8) | ||
841 | DV_SET(pcomp_en, 1); | ||
842 | } | ||
689 | 843 | ||
690 | if (len == 0) { | 844 | if (len == 0) { |
691 | SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n"); | 845 | SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); |
692 | spi_dv_retrain(sreq, buffer, buffer + len, | 846 | spi_dv_retrain(sreq, buffer, buffer + len, |
693 | spi_dv_device_compare_inquiry); | 847 | spi_dv_device_compare_inquiry); |
694 | return; | 848 | return; |
695 | } | 849 | } |
696 | 850 | ||
697 | if (len > SPI_MAX_ECHO_BUFFER_SIZE) { | 851 | if (len > SPI_MAX_ECHO_BUFFER_SIZE) { |
698 | SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); | 852 | SPI_PRINTK(starget, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); |
699 | len = SPI_MAX_ECHO_BUFFER_SIZE; | 853 | len = SPI_MAX_ECHO_BUFFER_SIZE; |
700 | } | 854 | } |
701 | 855 | ||
@@ -892,6 +1046,16 @@ EXPORT_SYMBOL(spi_display_xfer_agreement); | |||
892 | if (i->f->show_##field) \ | 1046 | if (i->f->show_##field) \ |
893 | count++ | 1047 | count++ |
894 | 1048 | ||
1049 | #define SETUP_RELATED_ATTRIBUTE(field, rel_field) \ | ||
1050 | i->private_attrs[count] = class_device_attr_##field; \ | ||
1051 | if (!i->f->set_##rel_field) { \ | ||
1052 | i->private_attrs[count].attr.mode = S_IRUGO; \ | ||
1053 | i->private_attrs[count].store = NULL; \ | ||
1054 | } \ | ||
1055 | i->attrs[count] = &i->private_attrs[count]; \ | ||
1056 | if (i->f->show_##rel_field) \ | ||
1057 | count++ | ||
1058 | |||
895 | #define SETUP_HOST_ATTRIBUTE(field) \ | 1059 | #define SETUP_HOST_ATTRIBUTE(field) \ |
896 | i->private_host_attrs[count] = class_device_attr_##field; \ | 1060 | i->private_host_attrs[count] = class_device_attr_##field; \ |
897 | if (!i->f->set_##field) { \ | 1061 | if (!i->f->set_##field) { \ |
@@ -975,8 +1139,11 @@ spi_attach_transport(struct spi_function_template *ft) | |||
975 | i->f = ft; | 1139 | i->f = ft; |
976 | 1140 | ||
977 | SETUP_ATTRIBUTE(period); | 1141 | SETUP_ATTRIBUTE(period); |
1142 | SETUP_RELATED_ATTRIBUTE(min_period, period); | ||
978 | SETUP_ATTRIBUTE(offset); | 1143 | SETUP_ATTRIBUTE(offset); |
1144 | SETUP_RELATED_ATTRIBUTE(max_offset, offset); | ||
979 | SETUP_ATTRIBUTE(width); | 1145 | SETUP_ATTRIBUTE(width); |
1146 | SETUP_RELATED_ATTRIBUTE(max_width, width); | ||
980 | SETUP_ATTRIBUTE(iu); | 1147 | SETUP_ATTRIBUTE(iu); |
981 | SETUP_ATTRIBUTE(dt); | 1148 | SETUP_ATTRIBUTE(dt); |
982 | SETUP_ATTRIBUTE(qas); | 1149 | SETUP_ATTRIBUTE(qas); |