aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Bottomley <jejb@titanic.(none)>2005-08-28 12:31:14 -0400
committerJames Bottomley <jejb@titanic.(none)>2005-08-28 12:31:14 -0400
commit33aa687db90dd8541bd5e9a762eebf880eaee767 (patch)
treedac741e1f3f43a1de2433a21b874a093783717f3 /drivers
parent1cf72699c1530c3e4ac3d58344f6a6a40a2f46d3 (diff)
[SCSI] convert SPI transport class to scsi_execute
This one's slightly more difficult. The transport class uses REQ_FAILFAST, so another interface (scsi_execute) had to be invented to take the extra flag. Also, the sense functions are shifted around to allow spi_execute to place data directly into a struct scsi_sense_hdr. With this change, there's probably a lot of unnecessary sense buffer allocation going on which we can fix later. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/scsi_error.c6
-rw-r--r--drivers/scsi/scsi_lib.c13
-rw-r--r--drivers/scsi/scsi_transport_spi.c124
3 files changed, 69 insertions, 74 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index e9c451ba71fc..2686d5672e5e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1847,12 +1847,16 @@ EXPORT_SYMBOL(scsi_reset_provider);
1847int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, 1847int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
1848 struct scsi_sense_hdr *sshdr) 1848 struct scsi_sense_hdr *sshdr)
1849{ 1849{
1850 if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70) 1850 if (!sense_buffer || !sb_len)
1851 return 0; 1851 return 0;
1852 1852
1853 memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); 1853 memset(sshdr, 0, sizeof(struct scsi_sense_hdr));
1854 1854
1855 sshdr->response_code = (sense_buffer[0] & 0x7f); 1855 sshdr->response_code = (sense_buffer[0] & 0x7f);
1856
1857 if (!scsi_sense_valid(sshdr))
1858 return 0;
1859
1856 if (sshdr->response_code >= 0x72) { 1860 if (sshdr->response_code >= 0x72) {
1857 /* 1861 /*
1858 * descriptor format 1862 * descriptor format
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 3f3accd6cd46..42edf29223ab 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -282,7 +282,7 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
282EXPORT_SYMBOL(scsi_wait_req); 282EXPORT_SYMBOL(scsi_wait_req);
283 283
284/** 284/**
285 * scsi_execute_req - insert request and wait for the result 285 * scsi_execute - insert request and wait for the result
286 * @sdev: scsi device 286 * @sdev: scsi device
287 * @cmd: scsi command 287 * @cmd: scsi command
288 * @data_direction: data direction 288 * @data_direction: data direction
@@ -291,13 +291,14 @@ EXPORT_SYMBOL(scsi_wait_req);
291 * @sense: optional sense buffer 291 * @sense: optional sense buffer
292 * @timeout: request timeout in seconds 292 * @timeout: request timeout in seconds
293 * @retries: number of times to retry request 293 * @retries: number of times to retry request
294 * @flags: or into request flags;
294 * 295 *
295 * scsi_execute_req returns the req->errors value which is the 296 * scsi_execute_req returns the req->errors value which is the
296 * the scsi_cmnd result field. 297 * the scsi_cmnd result field.
297 **/ 298 **/
298int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, 299int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
299 int data_direction, void *buffer, unsigned bufflen, 300 int data_direction, void *buffer, unsigned bufflen,
300 unsigned char *sense, int timeout, int retries) 301 unsigned char *sense, int timeout, int retries, int flags)
301{ 302{
302 struct request *req; 303 struct request *req;
303 int write = (data_direction == DMA_TO_DEVICE); 304 int write = (data_direction == DMA_TO_DEVICE);
@@ -314,7 +315,7 @@ int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd,
314 req->sense = sense; 315 req->sense = sense;
315 req->sense_len = 0; 316 req->sense_len = 0;
316 req->timeout = timeout; 317 req->timeout = timeout;
317 req->flags |= REQ_BLOCK_PC | REQ_SPECIAL; 318 req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL;
318 319
319 /* 320 /*
320 * head injection *required* here otherwise quiesce won't work 321 * head injection *required* here otherwise quiesce won't work
@@ -328,7 +329,7 @@ int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd,
328 return ret; 329 return ret;
329} 330}
330 331
331EXPORT_SYMBOL(scsi_execute_req); 332EXPORT_SYMBOL(scsi_execute);
332 333
333/* 334/*
334 * Function: scsi_init_cmd_errh() 335 * Function: scsi_init_cmd_errh()
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 89f6b7feb9c2..874042f1899d 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -28,7 +28,7 @@
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>
@@ -108,25 +108,33 @@ static int sprint_frac(char *dest, int value, int denom)
108 108
109/* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions 109/* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions
110 * resulting from (likely) bus and device resets */ 110 * resulting from (likely) bus and device resets */
111static void spi_wait_req(struct scsi_request *sreq, const void *cmd, 111static int spi_execute(struct scsi_device *sdev, const void *cmd,
112 void *buffer, unsigned bufflen) 112 enum dma_data_direction dir,
113 void *buffer, unsigned bufflen,
114 struct scsi_sense_hdr *sshdr)
113{ 115{
114 int i; 116 int i, result;
117 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
115 118
116 for(i = 0; i < DV_RETRIES; i++) { 119 for(i = 0; i < DV_RETRIES; i++) {
117 sreq->sr_request->flags |= REQ_FAILFAST;
118
119 scsi_wait_req(sreq, cmd, buffer, bufflen,
120 DV_TIMEOUT, /* retries */ 1);
121 if (sreq->sr_result & DRIVER_SENSE) {
122 struct scsi_sense_hdr sshdr;
123 120
124 if (scsi_request_normalize_sense(sreq, &sshdr) 121 /* FIXME: need to set REQ_FAILFAST */
125 && sshdr.sense_key == UNIT_ATTENTION) 122 result = scsi_execute(sdev, cmd, dir, buffer, bufflen,
123 sense, DV_TIMEOUT, /* retries */ 1,
124 REQ_FAILFAST);
125 if (result & DRIVER_SENSE) {
126 struct scsi_sense_hdr sshdr_tmp;
127 if (!sshdr)
128 sshdr = &sshdr_tmp;
129
130 if (scsi_normalize_sense(sense, sizeof(*sense),
131 sshdr)
132 && sshdr->sense_key == UNIT_ATTENTION)
126 continue; 133 continue;
127 } 134 }
128 break; 135 break;
129 } 136 }
137 return result;
130} 138}
131 139
132static struct { 140static struct {
@@ -546,13 +554,13 @@ enum spi_compare_returns {
546/* This is for read/write Domain Validation: If the device supports 554/* This is for read/write Domain Validation: If the device supports
547 * an echo buffer, we do read/write tests to it */ 555 * an echo buffer, we do read/write tests to it */
548static enum spi_compare_returns 556static enum spi_compare_returns
549spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, 557spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
550 u8 *ptr, const int retries) 558 u8 *ptr, const int retries)
551{ 559{
552 struct scsi_device *sdev = sreq->sr_device;
553 int len = ptr - buffer; 560 int len = ptr - buffer;
554 int j, k, r; 561 int j, k, r, result;
555 unsigned int pattern = 0x0000ffff; 562 unsigned int pattern = 0x0000ffff;
563 struct scsi_sense_hdr sshdr;
556 564
557 const char spi_write_buffer[] = { 565 const char spi_write_buffer[] = {
558 WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0 566 WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0
@@ -597,14 +605,12 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
597 } 605 }
598 606
599 for (r = 0; r < retries; r++) { 607 for (r = 0; r < retries; r++) {
600 sreq->sr_cmd_len = 0; /* wait_req to fill in */ 608 result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE,
601 sreq->sr_data_direction = DMA_TO_DEVICE; 609 buffer, len, &sshdr);
602 spi_wait_req(sreq, spi_write_buffer, buffer, len); 610 if(result || !scsi_device_online(sdev)) {
603 if(sreq->sr_result || !scsi_device_online(sdev)) {
604 struct scsi_sense_hdr sshdr;
605 611
606 scsi_device_set_state(sdev, SDEV_QUIESCE); 612 scsi_device_set_state(sdev, SDEV_QUIESCE);
607 if (scsi_request_normalize_sense(sreq, &sshdr) 613 if (scsi_sense_valid(&sshdr)
608 && sshdr.sense_key == ILLEGAL_REQUEST 614 && sshdr.sense_key == ILLEGAL_REQUEST
609 /* INVALID FIELD IN CDB */ 615 /* INVALID FIELD IN CDB */
610 && sshdr.asc == 0x24 && sshdr.ascq == 0x00) 616 && sshdr.asc == 0x24 && sshdr.ascq == 0x00)
@@ -616,14 +622,13 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
616 return SPI_COMPARE_SKIP_TEST; 622 return SPI_COMPARE_SKIP_TEST;
617 623
618 624
619 SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); 625 SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result);
620 return SPI_COMPARE_FAILURE; 626 return SPI_COMPARE_FAILURE;
621 } 627 }
622 628
623 memset(ptr, 0, len); 629 memset(ptr, 0, len);
624 sreq->sr_cmd_len = 0; /* wait_req to fill in */ 630 spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE,
625 sreq->sr_data_direction = DMA_FROM_DEVICE; 631 ptr, len, NULL);
626 spi_wait_req(sreq, spi_read_buffer, ptr, len);
627 scsi_device_set_state(sdev, SDEV_QUIESCE); 632 scsi_device_set_state(sdev, SDEV_QUIESCE);
628 633
629 if (memcmp(buffer, ptr, len) != 0) 634 if (memcmp(buffer, ptr, len) != 0)
@@ -635,25 +640,22 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
635/* This is for the simplest form of Domain Validation: a read test 640/* This is for the simplest form of Domain Validation: a read test
636 * on the inquiry data from the device */ 641 * on the inquiry data from the device */
637static enum spi_compare_returns 642static enum spi_compare_returns
638spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, 643spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer,
639 u8 *ptr, const int retries) 644 u8 *ptr, const int retries)
640{ 645{
641 int r; 646 int r, result;
642 const int len = sreq->sr_device->inquiry_len; 647 const int len = sdev->inquiry_len;
643 struct scsi_device *sdev = sreq->sr_device;
644 const char spi_inquiry[] = { 648 const char spi_inquiry[] = {
645 INQUIRY, 0, 0, 0, len, 0 649 INQUIRY, 0, 0, 0, len, 0
646 }; 650 };
647 651
648 for (r = 0; r < retries; r++) { 652 for (r = 0; r < retries; r++) {
649 sreq->sr_cmd_len = 0; /* wait_req to fill in */
650 sreq->sr_data_direction = DMA_FROM_DEVICE;
651
652 memset(ptr, 0, len); 653 memset(ptr, 0, len);
653 654
654 spi_wait_req(sreq, spi_inquiry, ptr, len); 655 result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE,
656 ptr, len, NULL);
655 657
656 if(sreq->sr_result || !scsi_device_online(sdev)) { 658 if(result || !scsi_device_online(sdev)) {
657 scsi_device_set_state(sdev, SDEV_QUIESCE); 659 scsi_device_set_state(sdev, SDEV_QUIESCE);
658 return SPI_COMPARE_FAILURE; 660 return SPI_COMPARE_FAILURE;
659 } 661 }
@@ -674,12 +676,11 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
674} 676}
675 677
676static enum spi_compare_returns 678static enum spi_compare_returns
677spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, 679spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr,
678 enum spi_compare_returns 680 enum spi_compare_returns
679 (*compare_fn)(struct scsi_request *, u8 *, u8 *, int)) 681 (*compare_fn)(struct scsi_device *, u8 *, u8 *, int))
680{ 682{
681 struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); 683 struct spi_internal *i = to_spi_internal(sdev->host->transportt);
682 struct scsi_device *sdev = sreq->sr_device;
683 struct scsi_target *starget = sdev->sdev_target; 684 struct scsi_target *starget = sdev->sdev_target;
684 int period = 0, prevperiod = 0; 685 int period = 0, prevperiod = 0;
685 enum spi_compare_returns retval; 686 enum spi_compare_returns retval;
@@ -687,7 +688,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
687 688
688 for (;;) { 689 for (;;) {
689 int newperiod; 690 int newperiod;
690 retval = compare_fn(sreq, buffer, ptr, DV_LOOPS); 691 retval = compare_fn(sdev, buffer, ptr, DV_LOOPS);
691 692
692 if (retval == SPI_COMPARE_SUCCESS 693 if (retval == SPI_COMPARE_SUCCESS
693 || retval == SPI_COMPARE_SKIP_TEST) 694 || retval == SPI_COMPARE_SKIP_TEST)
@@ -733,9 +734,9 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
733} 734}
734 735
735static int 736static int
736spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) 737spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer)
737{ 738{
738 int l; 739 int l, result;
739 740
740 /* first off do a test unit ready. This can error out 741 /* first off do a test unit ready. This can error out
741 * because of reservations or some other reason. If it 742 * because of reservations or some other reason. If it
@@ -751,18 +752,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
751 }; 752 };
752 753
753 754
754 sreq->sr_cmd_len = 0;
755 sreq->sr_data_direction = DMA_NONE;
756
757 /* We send a set of three TURs to clear any outstanding 755 /* We send a set of three TURs to clear any outstanding
758 * unit attention conditions if they exist (Otherwise the 756 * unit attention conditions if they exist (Otherwise the
759 * buffer tests won't be happy). If the TUR still fails 757 * buffer tests won't be happy). If the TUR still fails
760 * (reservation conflict, device not ready, etc) just 758 * (reservation conflict, device not ready, etc) just
761 * skip the write tests */ 759 * skip the write tests */
762 for (l = 0; ; l++) { 760 for (l = 0; ; l++) {
763 spi_wait_req(sreq, spi_test_unit_ready, NULL, 0); 761 result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE,
762 NULL, 0, NULL);
764 763
765 if(sreq->sr_result) { 764 if(result) {
766 if(l >= 3) 765 if(l >= 3)
767 return 0; 766 return 0;
768 } else { 767 } else {
@@ -771,12 +770,10 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
771 } 770 }
772 } 771 }
773 772
774 sreq->sr_cmd_len = 0; 773 result = spi_execute(sdev, spi_read_buffer_descriptor,
775 sreq->sr_data_direction = DMA_FROM_DEVICE; 774 DMA_FROM_DEVICE, buffer, 4, NULL);
776 775
777 spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4); 776 if (result)
778
779 if (sreq->sr_result)
780 /* Device has no echo buffer */ 777 /* Device has no echo buffer */
781 return 0; 778 return 0;
782 779
@@ -784,17 +781,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer)
784} 781}
785 782
786static void 783static void
787spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) 784spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
788{ 785{
789 struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); 786 struct spi_internal *i = to_spi_internal(sdev->host->transportt);
790 struct scsi_device *sdev = sreq->sr_device;
791 struct scsi_target *starget = sdev->sdev_target; 787 struct scsi_target *starget = sdev->sdev_target;
792 int len = sdev->inquiry_len; 788 int len = sdev->inquiry_len;
793 /* first set us up for narrow async */ 789 /* first set us up for narrow async */
794 DV_SET(offset, 0); 790 DV_SET(offset, 0);
795 DV_SET(width, 0); 791 DV_SET(width, 0);
796 792
797 if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) 793 if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS)
798 != SPI_COMPARE_SUCCESS) { 794 != SPI_COMPARE_SUCCESS) {
799 SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); 795 SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
800 /* FIXME: should probably offline the device here? */ 796 /* FIXME: should probably offline the device here? */
@@ -806,7 +802,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
806 scsi_device_wide(sdev)) { 802 scsi_device_wide(sdev)) {
807 i->f->set_width(starget, 1); 803 i->f->set_width(starget, 1);
808 804
809 if (spi_dv_device_compare_inquiry(sreq, buffer, 805 if (spi_dv_device_compare_inquiry(sdev, buffer,
810 buffer + len, 806 buffer + len,
811 DV_LOOPS) 807 DV_LOOPS)
812 != SPI_COMPARE_SUCCESS) { 808 != SPI_COMPARE_SUCCESS) {
@@ -827,7 +823,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
827 823
828 len = 0; 824 len = 0;
829 if (scsi_device_dt(sdev)) 825 if (scsi_device_dt(sdev))
830 len = spi_dv_device_get_echo_buffer(sreq, buffer); 826 len = spi_dv_device_get_echo_buffer(sdev, buffer);
831 827
832 retry: 828 retry:
833 829
@@ -853,7 +849,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
853 849
854 if (len == 0) { 850 if (len == 0) {
855 SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); 851 SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n");
856 spi_dv_retrain(sreq, buffer, buffer + len, 852 spi_dv_retrain(sdev, buffer, buffer + len,
857 spi_dv_device_compare_inquiry); 853 spi_dv_device_compare_inquiry);
858 return; 854 return;
859 } 855 }
@@ -863,7 +859,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
863 len = SPI_MAX_ECHO_BUFFER_SIZE; 859 len = SPI_MAX_ECHO_BUFFER_SIZE;
864 } 860 }
865 861
866 if (spi_dv_retrain(sreq, buffer, buffer + len, 862 if (spi_dv_retrain(sdev, buffer, buffer + len,
867 spi_dv_device_echo_buffer) 863 spi_dv_device_echo_buffer)
868 == SPI_COMPARE_SKIP_TEST) { 864 == SPI_COMPARE_SKIP_TEST) {
869 /* OK, the stupid drive can't do a write echo buffer 865 /* OK, the stupid drive can't do a write echo buffer
@@ -886,16 +882,12 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
886void 882void
887spi_dv_device(struct scsi_device *sdev) 883spi_dv_device(struct scsi_device *sdev)
888{ 884{
889 struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
890 struct scsi_target *starget = sdev->sdev_target; 885 struct scsi_target *starget = sdev->sdev_target;
891 u8 *buffer; 886 u8 *buffer;
892 const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; 887 const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
893 888
894 if (unlikely(!sreq))
895 return;
896
897 if (unlikely(scsi_device_get(sdev))) 889 if (unlikely(scsi_device_get(sdev)))
898 goto out_free_req; 890 return;
899 891
900 buffer = kmalloc(len, GFP_KERNEL); 892 buffer = kmalloc(len, GFP_KERNEL);
901 893
@@ -916,7 +908,7 @@ spi_dv_device(struct scsi_device *sdev)
916 908
917 SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); 909 SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n");
918 910
919 spi_dv_device_internal(sreq, buffer); 911 spi_dv_device_internal(sdev, buffer);
920 912
921 SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); 913 SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n");
922 914
@@ -931,8 +923,6 @@ spi_dv_device(struct scsi_device *sdev)
931 kfree(buffer); 923 kfree(buffer);
932 out_put: 924 out_put:
933 scsi_device_put(sdev); 925 scsi_device_put(sdev);
934 out_free_req:
935 scsi_release_request(sreq);
936} 926}
937EXPORT_SYMBOL(spi_dv_device); 927EXPORT_SYMBOL(spi_dv_device);
938 928