aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_spi.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pretzel.yyz.us>2005-06-22 21:50:57 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-06-22 21:50:57 -0400
commita5324343955997d1439f26518ddac567cd5d134b (patch)
treef43558389c41e3a0f076c4ee55d77c4aa1561779 /drivers/scsi/scsi_transport_spi.c
parent8199d3a79c224bbe5943fa08684e1f93a17881b0 (diff)
parenta4936044001694f033fe4ea94d6034d51a6b465c (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
-rw-r--r--drivers/scsi/scsi_transport_spi.c277
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 \
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");
@@ -283,43 +348,39 @@ spi_transport_rd_attr(rd_strm, "%d\n");
283spi_transport_rd_attr(rti, "%d\n"); 348spi_transport_rd_attr(rti, "%d\n");
284spi_transport_rd_attr(pcomp_en, "%d\n"); 349spi_transport_rd_attr(pcomp_en, "%d\n");
285 350
351/* we only care about the first child device so we return 1 */
352static 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
286static ssize_t 360static ssize_t
287store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count) 361store_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}
299static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); 368static 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 */
303static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) 372static ssize_t
304 373show_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
336static ssize_t 397static ssize_t
337store_spi_transport_period(struct class_device *cdev, const char *buf, 398store_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
434static ssize_t
435show_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
449static ssize_t
450store_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
376static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, 470static 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
474static ssize_t
475show_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
484static ssize_t
485store_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
497static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR,
498 show_spi_transport_min_period,
499 store_spi_transport_min_period);
500
501
380static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) 502static 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);