diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 168 |
1 files changed, 89 insertions, 79 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 7670919a087a..ef577c8c2182 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -28,14 +28,14 @@ | |||
28 | #include "scsi_priv.h" | 28 | #include "scsi_priv.h" |
29 | #include <scsi/scsi_device.h> | 29 | #include <scsi/scsi_device.h> |
30 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
31 | #include <scsi/scsi_request.h> | 31 | #include <scsi/scsi_cmnd.h> |
32 | #include <scsi/scsi_eh.h> | 32 | #include <scsi/scsi_eh.h> |
33 | #include <scsi/scsi_transport.h> | 33 | #include <scsi/scsi_transport.h> |
34 | #include <scsi/scsi_transport_spi.h> | 34 | #include <scsi/scsi_transport_spi.h> |
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 13 /* increase this if you add attributes */ | 38 | #define SPI_NUM_ATTRS 14 /* 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 |
@@ -106,27 +106,31 @@ static int sprint_frac(char *dest, int value, int denom) | |||
106 | return result; | 106 | return result; |
107 | } | 107 | } |
108 | 108 | ||
109 | /* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions | 109 | static int spi_execute(struct scsi_device *sdev, const void *cmd, |
110 | * resulting from (likely) bus and device resets */ | 110 | enum dma_data_direction dir, |
111 | static void spi_wait_req(struct scsi_request *sreq, const void *cmd, | 111 | void *buffer, unsigned bufflen, |
112 | void *buffer, unsigned bufflen) | 112 | struct scsi_sense_hdr *sshdr) |
113 | { | 113 | { |
114 | int i; | 114 | int i, result; |
115 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; | ||
115 | 116 | ||
116 | for(i = 0; i < DV_RETRIES; i++) { | 117 | for(i = 0; i < DV_RETRIES; i++) { |
117 | sreq->sr_request->flags |= REQ_FAILFAST; | 118 | result = scsi_execute(sdev, cmd, dir, buffer, bufflen, |
118 | 119 | sense, DV_TIMEOUT, /* retries */ 1, | |
119 | scsi_wait_req(sreq, cmd, buffer, bufflen, | 120 | REQ_FAILFAST); |
120 | DV_TIMEOUT, /* retries */ 1); | 121 | if (result & DRIVER_SENSE) { |
121 | if (sreq->sr_result & DRIVER_SENSE) { | 122 | struct scsi_sense_hdr sshdr_tmp; |
122 | struct scsi_sense_hdr sshdr; | 123 | if (!sshdr) |
123 | 124 | sshdr = &sshdr_tmp; | |
124 | if (scsi_request_normalize_sense(sreq, &sshdr) | 125 | |
125 | && sshdr.sense_key == UNIT_ATTENTION) | 126 | if (scsi_normalize_sense(sense, sizeof(*sense), |
127 | sshdr) | ||
128 | && sshdr->sense_key == UNIT_ATTENTION) | ||
126 | continue; | 129 | continue; |
127 | } | 130 | } |
128 | break; | 131 | break; |
129 | } | 132 | } |
133 | return result; | ||
130 | } | 134 | } |
131 | 135 | ||
132 | static struct { | 136 | static struct { |
@@ -162,7 +166,8 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name) | |||
162 | return SPI_SIGNAL_UNKNOWN; | 166 | return SPI_SIGNAL_UNKNOWN; |
163 | } | 167 | } |
164 | 168 | ||
165 | static int spi_host_setup(struct device *dev) | 169 | static int spi_host_setup(struct transport_container *tc, struct device *dev, |
170 | struct class_device *cdev) | ||
166 | { | 171 | { |
167 | struct Scsi_Host *shost = dev_to_shost(dev); | 172 | struct Scsi_Host *shost = dev_to_shost(dev); |
168 | 173 | ||
@@ -196,7 +201,9 @@ static int spi_host_match(struct attribute_container *cont, | |||
196 | return &i->t.host_attrs.ac == cont; | 201 | return &i->t.host_attrs.ac == cont; |
197 | } | 202 | } |
198 | 203 | ||
199 | static int spi_device_configure(struct device *dev) | 204 | static int spi_device_configure(struct transport_container *tc, |
205 | struct device *dev, | ||
206 | struct class_device *cdev) | ||
200 | { | 207 | { |
201 | struct scsi_device *sdev = to_scsi_device(dev); | 208 | struct scsi_device *sdev = to_scsi_device(dev); |
202 | struct scsi_target *starget = sdev->sdev_target; | 209 | struct scsi_target *starget = sdev->sdev_target; |
@@ -214,7 +221,9 @@ static int spi_device_configure(struct device *dev) | |||
214 | return 0; | 221 | return 0; |
215 | } | 222 | } |
216 | 223 | ||
217 | static int spi_setup_transport_attrs(struct device *dev) | 224 | static int spi_setup_transport_attrs(struct transport_container *tc, |
225 | struct device *dev, | ||
226 | struct class_device *cdev) | ||
218 | { | 227 | { |
219 | struct scsi_target *starget = to_scsi_target(dev); | 228 | struct scsi_target *starget = to_scsi_target(dev); |
220 | 229 | ||
@@ -231,6 +240,7 @@ static int spi_setup_transport_attrs(struct device *dev) | |||
231 | spi_rd_strm(starget) = 0; | 240 | spi_rd_strm(starget) = 0; |
232 | spi_rti(starget) = 0; | 241 | spi_rti(starget) = 0; |
233 | spi_pcomp_en(starget) = 0; | 242 | spi_pcomp_en(starget) = 0; |
243 | spi_hold_mcs(starget) = 0; | ||
234 | spi_dv_pending(starget) = 0; | 244 | spi_dv_pending(starget) = 0; |
235 | spi_initial_dv(starget) = 0; | 245 | spi_initial_dv(starget) = 0; |
236 | init_MUTEX(&spi_dv_sem(starget)); | 246 | init_MUTEX(&spi_dv_sem(starget)); |
@@ -347,6 +357,7 @@ spi_transport_rd_attr(wr_flow, "%d\n"); | |||
347 | spi_transport_rd_attr(rd_strm, "%d\n"); | 357 | spi_transport_rd_attr(rd_strm, "%d\n"); |
348 | spi_transport_rd_attr(rti, "%d\n"); | 358 | spi_transport_rd_attr(rti, "%d\n"); |
349 | spi_transport_rd_attr(pcomp_en, "%d\n"); | 359 | spi_transport_rd_attr(pcomp_en, "%d\n"); |
360 | spi_transport_rd_attr(hold_mcs, "%d\n"); | ||
350 | 361 | ||
351 | /* we only care about the first child device so we return 1 */ | 362 | /* we only care about the first child device so we return 1 */ |
352 | static int child_iter(struct device *dev, void *data) | 363 | static int child_iter(struct device *dev, void *data) |
@@ -539,13 +550,13 @@ enum spi_compare_returns { | |||
539 | /* This is for read/write Domain Validation: If the device supports | 550 | /* This is for read/write Domain Validation: If the device supports |
540 | * an echo buffer, we do read/write tests to it */ | 551 | * an echo buffer, we do read/write tests to it */ |
541 | static enum spi_compare_returns | 552 | static enum spi_compare_returns |
542 | spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | 553 | spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer, |
543 | u8 *ptr, const int retries) | 554 | u8 *ptr, const int retries) |
544 | { | 555 | { |
545 | struct scsi_device *sdev = sreq->sr_device; | ||
546 | int len = ptr - buffer; | 556 | int len = ptr - buffer; |
547 | int j, k, r; | 557 | int j, k, r, result; |
548 | unsigned int pattern = 0x0000ffff; | 558 | unsigned int pattern = 0x0000ffff; |
559 | struct scsi_sense_hdr sshdr; | ||
549 | 560 | ||
550 | const char spi_write_buffer[] = { | 561 | const char spi_write_buffer[] = { |
551 | WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0 | 562 | WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0 |
@@ -590,14 +601,12 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
590 | } | 601 | } |
591 | 602 | ||
592 | for (r = 0; r < retries; r++) { | 603 | for (r = 0; r < retries; r++) { |
593 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | 604 | result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE, |
594 | sreq->sr_data_direction = DMA_TO_DEVICE; | 605 | buffer, len, &sshdr); |
595 | spi_wait_req(sreq, spi_write_buffer, buffer, len); | 606 | if(result || !scsi_device_online(sdev)) { |
596 | if(sreq->sr_result || !scsi_device_online(sdev)) { | ||
597 | struct scsi_sense_hdr sshdr; | ||
598 | 607 | ||
599 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 608 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
600 | if (scsi_request_normalize_sense(sreq, &sshdr) | 609 | if (scsi_sense_valid(&sshdr) |
601 | && sshdr.sense_key == ILLEGAL_REQUEST | 610 | && sshdr.sense_key == ILLEGAL_REQUEST |
602 | /* INVALID FIELD IN CDB */ | 611 | /* INVALID FIELD IN CDB */ |
603 | && sshdr.asc == 0x24 && sshdr.ascq == 0x00) | 612 | && sshdr.asc == 0x24 && sshdr.ascq == 0x00) |
@@ -609,14 +618,13 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
609 | return SPI_COMPARE_SKIP_TEST; | 618 | return SPI_COMPARE_SKIP_TEST; |
610 | 619 | ||
611 | 620 | ||
612 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); | 621 | SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result); |
613 | return SPI_COMPARE_FAILURE; | 622 | return SPI_COMPARE_FAILURE; |
614 | } | 623 | } |
615 | 624 | ||
616 | memset(ptr, 0, len); | 625 | memset(ptr, 0, len); |
617 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | 626 | spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE, |
618 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 627 | ptr, len, NULL); |
619 | spi_wait_req(sreq, spi_read_buffer, ptr, len); | ||
620 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 628 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
621 | 629 | ||
622 | if (memcmp(buffer, ptr, len) != 0) | 630 | if (memcmp(buffer, ptr, len) != 0) |
@@ -628,25 +636,22 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | |||
628 | /* This is for the simplest form of Domain Validation: a read test | 636 | /* This is for the simplest form of Domain Validation: a read test |
629 | * on the inquiry data from the device */ | 637 | * on the inquiry data from the device */ |
630 | static enum spi_compare_returns | 638 | static enum spi_compare_returns |
631 | spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, | 639 | spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer, |
632 | u8 *ptr, const int retries) | 640 | u8 *ptr, const int retries) |
633 | { | 641 | { |
634 | int r; | 642 | int r, result; |
635 | const int len = sreq->sr_device->inquiry_len; | 643 | const int len = sdev->inquiry_len; |
636 | struct scsi_device *sdev = sreq->sr_device; | ||
637 | const char spi_inquiry[] = { | 644 | const char spi_inquiry[] = { |
638 | INQUIRY, 0, 0, 0, len, 0 | 645 | INQUIRY, 0, 0, 0, len, 0 |
639 | }; | 646 | }; |
640 | 647 | ||
641 | for (r = 0; r < retries; r++) { | 648 | for (r = 0; r < retries; r++) { |
642 | sreq->sr_cmd_len = 0; /* wait_req to fill in */ | ||
643 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
644 | |||
645 | memset(ptr, 0, len); | 649 | memset(ptr, 0, len); |
646 | 650 | ||
647 | spi_wait_req(sreq, spi_inquiry, ptr, len); | 651 | result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE, |
652 | ptr, len, NULL); | ||
648 | 653 | ||
649 | if(sreq->sr_result || !scsi_device_online(sdev)) { | 654 | if(result || !scsi_device_online(sdev)) { |
650 | scsi_device_set_state(sdev, SDEV_QUIESCE); | 655 | scsi_device_set_state(sdev, SDEV_QUIESCE); |
651 | return SPI_COMPARE_FAILURE; | 656 | return SPI_COMPARE_FAILURE; |
652 | } | 657 | } |
@@ -667,12 +672,11 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, | |||
667 | } | 672 | } |
668 | 673 | ||
669 | static enum spi_compare_returns | 674 | static enum spi_compare_returns |
670 | spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | 675 | spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr, |
671 | enum spi_compare_returns | 676 | enum spi_compare_returns |
672 | (*compare_fn)(struct scsi_request *, u8 *, u8 *, int)) | 677 | (*compare_fn)(struct scsi_device *, u8 *, u8 *, int)) |
673 | { | 678 | { |
674 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); | 679 | struct spi_internal *i = to_spi_internal(sdev->host->transportt); |
675 | struct scsi_device *sdev = sreq->sr_device; | ||
676 | struct scsi_target *starget = sdev->sdev_target; | 680 | struct scsi_target *starget = sdev->sdev_target; |
677 | int period = 0, prevperiod = 0; | 681 | int period = 0, prevperiod = 0; |
678 | enum spi_compare_returns retval; | 682 | enum spi_compare_returns retval; |
@@ -680,7 +684,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | |||
680 | 684 | ||
681 | for (;;) { | 685 | for (;;) { |
682 | int newperiod; | 686 | int newperiod; |
683 | retval = compare_fn(sreq, buffer, ptr, DV_LOOPS); | 687 | retval = compare_fn(sdev, buffer, ptr, DV_LOOPS); |
684 | 688 | ||
685 | if (retval == SPI_COMPARE_SUCCESS | 689 | if (retval == SPI_COMPARE_SUCCESS |
686 | || retval == SPI_COMPARE_SKIP_TEST) | 690 | || retval == SPI_COMPARE_SKIP_TEST) |
@@ -726,9 +730,9 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | |||
726 | } | 730 | } |
727 | 731 | ||
728 | static int | 732 | static int |
729 | spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | 733 | spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer) |
730 | { | 734 | { |
731 | int l; | 735 | int l, result; |
732 | 736 | ||
733 | /* first off do a test unit ready. This can error out | 737 | /* first off do a test unit ready. This can error out |
734 | * because of reservations or some other reason. If it | 738 | * because of reservations or some other reason. If it |
@@ -744,18 +748,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
744 | }; | 748 | }; |
745 | 749 | ||
746 | 750 | ||
747 | sreq->sr_cmd_len = 0; | ||
748 | sreq->sr_data_direction = DMA_NONE; | ||
749 | |||
750 | /* We send a set of three TURs to clear any outstanding | 751 | /* We send a set of three TURs to clear any outstanding |
751 | * unit attention conditions if they exist (Otherwise the | 752 | * unit attention conditions if they exist (Otherwise the |
752 | * buffer tests won't be happy). If the TUR still fails | 753 | * buffer tests won't be happy). If the TUR still fails |
753 | * (reservation conflict, device not ready, etc) just | 754 | * (reservation conflict, device not ready, etc) just |
754 | * skip the write tests */ | 755 | * skip the write tests */ |
755 | for (l = 0; ; l++) { | 756 | for (l = 0; ; l++) { |
756 | spi_wait_req(sreq, spi_test_unit_ready, NULL, 0); | 757 | result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE, |
758 | NULL, 0, NULL); | ||
757 | 759 | ||
758 | if(sreq->sr_result) { | 760 | if(result) { |
759 | if(l >= 3) | 761 | if(l >= 3) |
760 | return 0; | 762 | return 0; |
761 | } else { | 763 | } else { |
@@ -764,12 +766,10 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
764 | } | 766 | } |
765 | } | 767 | } |
766 | 768 | ||
767 | sreq->sr_cmd_len = 0; | 769 | result = spi_execute(sdev, spi_read_buffer_descriptor, |
768 | sreq->sr_data_direction = DMA_FROM_DEVICE; | 770 | DMA_FROM_DEVICE, buffer, 4, NULL); |
769 | |||
770 | spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4); | ||
771 | 771 | ||
772 | if (sreq->sr_result) | 772 | if (result) |
773 | /* Device has no echo buffer */ | 773 | /* Device has no echo buffer */ |
774 | return 0; | 774 | return 0; |
775 | 775 | ||
@@ -777,17 +777,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | |||
777 | } | 777 | } |
778 | 778 | ||
779 | static void | 779 | static void |
780 | spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | 780 | spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) |
781 | { | 781 | { |
782 | struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); | 782 | struct spi_internal *i = to_spi_internal(sdev->host->transportt); |
783 | struct scsi_device *sdev = sreq->sr_device; | ||
784 | struct scsi_target *starget = sdev->sdev_target; | 783 | struct scsi_target *starget = sdev->sdev_target; |
785 | int len = sdev->inquiry_len; | 784 | int len = sdev->inquiry_len; |
786 | /* first set us up for narrow async */ | 785 | /* first set us up for narrow async */ |
787 | DV_SET(offset, 0); | 786 | DV_SET(offset, 0); |
788 | DV_SET(width, 0); | 787 | DV_SET(width, 0); |
789 | 788 | ||
790 | if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) | 789 | if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) |
791 | != SPI_COMPARE_SUCCESS) { | 790 | != SPI_COMPARE_SUCCESS) { |
792 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); | 791 | SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); |
793 | /* FIXME: should probably offline the device here? */ | 792 | /* FIXME: should probably offline the device here? */ |
@@ -799,7 +798,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
799 | scsi_device_wide(sdev)) { | 798 | scsi_device_wide(sdev)) { |
800 | i->f->set_width(starget, 1); | 799 | i->f->set_width(starget, 1); |
801 | 800 | ||
802 | if (spi_dv_device_compare_inquiry(sreq, buffer, | 801 | if (spi_dv_device_compare_inquiry(sdev, buffer, |
803 | buffer + len, | 802 | buffer + len, |
804 | DV_LOOPS) | 803 | DV_LOOPS) |
805 | != SPI_COMPARE_SUCCESS) { | 804 | != SPI_COMPARE_SUCCESS) { |
@@ -820,7 +819,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
820 | 819 | ||
821 | len = 0; | 820 | len = 0; |
822 | if (scsi_device_dt(sdev)) | 821 | if (scsi_device_dt(sdev)) |
823 | len = spi_dv_device_get_echo_buffer(sreq, buffer); | 822 | len = spi_dv_device_get_echo_buffer(sdev, buffer); |
824 | 823 | ||
825 | retry: | 824 | retry: |
826 | 825 | ||
@@ -846,7 +845,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
846 | 845 | ||
847 | if (len == 0) { | 846 | if (len == 0) { |
848 | SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); | 847 | SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); |
849 | spi_dv_retrain(sreq, buffer, buffer + len, | 848 | spi_dv_retrain(sdev, buffer, buffer + len, |
850 | spi_dv_device_compare_inquiry); | 849 | spi_dv_device_compare_inquiry); |
851 | return; | 850 | return; |
852 | } | 851 | } |
@@ -856,7 +855,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
856 | len = SPI_MAX_ECHO_BUFFER_SIZE; | 855 | len = SPI_MAX_ECHO_BUFFER_SIZE; |
857 | } | 856 | } |
858 | 857 | ||
859 | if (spi_dv_retrain(sreq, buffer, buffer + len, | 858 | if (spi_dv_retrain(sdev, buffer, buffer + len, |
860 | spi_dv_device_echo_buffer) | 859 | spi_dv_device_echo_buffer) |
861 | == SPI_COMPARE_SKIP_TEST) { | 860 | == SPI_COMPARE_SKIP_TEST) { |
862 | /* OK, the stupid drive can't do a write echo buffer | 861 | /* OK, the stupid drive can't do a write echo buffer |
@@ -879,16 +878,12 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | |||
879 | void | 878 | void |
880 | spi_dv_device(struct scsi_device *sdev) | 879 | spi_dv_device(struct scsi_device *sdev) |
881 | { | 880 | { |
882 | struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); | ||
883 | struct scsi_target *starget = sdev->sdev_target; | 881 | struct scsi_target *starget = sdev->sdev_target; |
884 | u8 *buffer; | 882 | u8 *buffer; |
885 | const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; | 883 | const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; |
886 | 884 | ||
887 | if (unlikely(!sreq)) | ||
888 | return; | ||
889 | |||
890 | if (unlikely(scsi_device_get(sdev))) | 885 | if (unlikely(scsi_device_get(sdev))) |
891 | goto out_free_req; | 886 | return; |
892 | 887 | ||
893 | buffer = kmalloc(len, GFP_KERNEL); | 888 | buffer = kmalloc(len, GFP_KERNEL); |
894 | 889 | ||
@@ -909,7 +904,7 @@ spi_dv_device(struct scsi_device *sdev) | |||
909 | 904 | ||
910 | SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); | 905 | SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); |
911 | 906 | ||
912 | spi_dv_device_internal(sreq, buffer); | 907 | spi_dv_device_internal(sdev, buffer); |
913 | 908 | ||
914 | SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); | 909 | SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); |
915 | 910 | ||
@@ -924,8 +919,6 @@ spi_dv_device(struct scsi_device *sdev) | |||
924 | kfree(buffer); | 919 | kfree(buffer); |
925 | out_put: | 920 | out_put: |
926 | scsi_device_put(sdev); | 921 | scsi_device_put(sdev); |
927 | out_free_req: | ||
928 | scsi_release_request(sreq); | ||
929 | } | 922 | } |
930 | EXPORT_SYMBOL(spi_dv_device); | 923 | EXPORT_SYMBOL(spi_dv_device); |
931 | 924 | ||
@@ -1028,10 +1021,17 @@ void spi_display_xfer_agreement(struct scsi_target *starget) | |||
1028 | sprint_frac(tmp, picosec, 1000); | 1021 | sprint_frac(tmp, picosec, 1000); |
1029 | 1022 | ||
1030 | dev_info(&starget->dev, | 1023 | dev_info(&starget->dev, |
1031 | "%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n", | 1024 | "%s %sSCSI %d.%d MB/s %s%s%s%s%s%s%s%s (%s ns, offset %d)\n", |
1032 | scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10, | 1025 | scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10, |
1033 | tp->dt ? "DT" : "ST", tp->iu ? " IU" : "", | 1026 | tp->dt ? "DT" : "ST", |
1034 | tp->qas ? " QAS" : "", tmp, tp->offset); | 1027 | tp->iu ? " IU" : "", |
1028 | tp->qas ? " QAS" : "", | ||
1029 | tp->rd_strm ? " RDSTRM" : "", | ||
1030 | tp->rti ? " RTI" : "", | ||
1031 | tp->wr_flow ? " WRFLOW" : "", | ||
1032 | tp->pcomp_en ? " PCOMP" : "", | ||
1033 | tp->hold_mcs ? " HMCS" : "", | ||
1034 | tmp, tp->offset); | ||
1035 | } else { | 1035 | } else { |
1036 | dev_info(&starget->dev, "%sasynchronous.\n", | 1036 | dev_info(&starget->dev, "%sasynchronous.\n", |
1037 | tp->width ? "wide " : ""); | 1037 | tp->width ? "wide " : ""); |
@@ -1073,6 +1073,7 @@ static int spi_device_match(struct attribute_container *cont, | |||
1073 | { | 1073 | { |
1074 | struct scsi_device *sdev; | 1074 | struct scsi_device *sdev; |
1075 | struct Scsi_Host *shost; | 1075 | struct Scsi_Host *shost; |
1076 | struct spi_internal *i; | ||
1076 | 1077 | ||
1077 | if (!scsi_is_sdev_device(dev)) | 1078 | if (!scsi_is_sdev_device(dev)) |
1078 | return 0; | 1079 | return 0; |
@@ -1085,6 +1086,9 @@ static int spi_device_match(struct attribute_container *cont, | |||
1085 | /* Note: this class has no device attributes, so it has | 1086 | /* Note: this class has no device attributes, so it has |
1086 | * no per-HBA allocation and thus we don't need to distinguish | 1087 | * no per-HBA allocation and thus we don't need to distinguish |
1087 | * the attribute containers for the device */ | 1088 | * the attribute containers for the device */ |
1089 | i = to_spi_internal(shost->transportt); | ||
1090 | if (i->f->deny_binding && i->f->deny_binding(sdev->sdev_target)) | ||
1091 | return 0; | ||
1088 | return 1; | 1092 | return 1; |
1089 | } | 1093 | } |
1090 | 1094 | ||
@@ -1092,6 +1096,7 @@ static int spi_target_match(struct attribute_container *cont, | |||
1092 | struct device *dev) | 1096 | struct device *dev) |
1093 | { | 1097 | { |
1094 | struct Scsi_Host *shost; | 1098 | struct Scsi_Host *shost; |
1099 | struct scsi_target *starget; | ||
1095 | struct spi_internal *i; | 1100 | struct spi_internal *i; |
1096 | 1101 | ||
1097 | if (!scsi_is_target_device(dev)) | 1102 | if (!scsi_is_target_device(dev)) |
@@ -1103,7 +1108,11 @@ static int spi_target_match(struct attribute_container *cont, | |||
1103 | return 0; | 1108 | return 0; |
1104 | 1109 | ||
1105 | i = to_spi_internal(shost->transportt); | 1110 | i = to_spi_internal(shost->transportt); |
1106 | 1111 | starget = to_scsi_target(dev); | |
1112 | |||
1113 | if (i->f->deny_binding && i->f->deny_binding(starget)) | ||
1114 | return 0; | ||
1115 | |||
1107 | return &i->t.target_attrs.ac == cont; | 1116 | return &i->t.target_attrs.ac == cont; |
1108 | } | 1117 | } |
1109 | 1118 | ||
@@ -1154,6 +1163,7 @@ spi_attach_transport(struct spi_function_template *ft) | |||
1154 | SETUP_ATTRIBUTE(rd_strm); | 1163 | SETUP_ATTRIBUTE(rd_strm); |
1155 | SETUP_ATTRIBUTE(rti); | 1164 | SETUP_ATTRIBUTE(rti); |
1156 | SETUP_ATTRIBUTE(pcomp_en); | 1165 | SETUP_ATTRIBUTE(pcomp_en); |
1166 | SETUP_ATTRIBUTE(hold_mcs); | ||
1157 | 1167 | ||
1158 | /* if you add an attribute but forget to increase SPI_NUM_ATTRS | 1168 | /* if you add an attribute but forget to increase SPI_NUM_ATTRS |
1159 | * this bug will trigger */ | 1169 | * this bug will trigger */ |