diff options
| author | James Bottomley <jejb@titanic.(none)> | 2005-08-28 12:31:14 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@titanic.(none)> | 2005-08-28 12:31:14 -0400 |
| commit | 33aa687db90dd8541bd5e9a762eebf880eaee767 (patch) | |
| tree | dac741e1f3f43a1de2433a21b874a093783717f3 | |
| parent | 1cf72699c1530c3e4ac3d58344f6a6a40a2f46d3 (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>
| -rw-r--r-- | drivers/scsi/scsi_error.c | 6 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 13 | ||||
| -rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 124 | ||||
| -rw-r--r-- | include/scsi/scsi_device.h | 13 | ||||
| -rw-r--r-- | include/scsi/scsi_eh.h | 8 | ||||
| -rw-r--r-- | include/scsi/scsi_request.h | 4 |
6 files changed, 90 insertions, 78 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); | |||
| 1847 | int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, | 1847 | int 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, | |||
| 282 | EXPORT_SYMBOL(scsi_wait_req); | 282 | EXPORT_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 | **/ |
| 298 | int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, | 299 | int 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 | ||
| 331 | EXPORT_SYMBOL(scsi_execute_req); | 332 | EXPORT_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 */ |
| 111 | static void spi_wait_req(struct scsi_request *sreq, const void *cmd, | 111 | static 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 | ||
| 132 | static struct { | 140 | static 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 */ |
| 548 | static enum spi_compare_returns | 556 | static enum spi_compare_returns |
| 549 | spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, | 557 | spi_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 */ |
| 637 | static enum spi_compare_returns | 642 | static enum spi_compare_returns |
| 638 | spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, | 643 | spi_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 | ||
| 676 | static enum spi_compare_returns | 678 | static enum spi_compare_returns |
| 677 | spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, | 679 | spi_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 | ||
| 735 | static int | 736 | static int |
| 736 | spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) | 737 | spi_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 | ||
| 786 | static void | 783 | static void |
| 787 | spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) | 784 | spi_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) | |||
| 886 | void | 882 | void |
| 887 | spi_dv_device(struct scsi_device *sdev) | 883 | spi_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 | } |
| 937 | EXPORT_SYMBOL(spi_dv_device); | 927 | EXPORT_SYMBOL(spi_dv_device); |
| 938 | 928 | ||
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 9181068883ce..5ad08b70763c 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
| @@ -256,6 +256,19 @@ extern void int_to_scsilun(unsigned int, struct scsi_lun *); | |||
| 256 | extern const char *scsi_device_state_name(enum scsi_device_state); | 256 | extern const char *scsi_device_state_name(enum scsi_device_state); |
| 257 | extern int scsi_is_sdev_device(const struct device *); | 257 | extern int scsi_is_sdev_device(const struct device *); |
| 258 | extern int scsi_is_target_device(const struct device *); | 258 | extern int scsi_is_target_device(const struct device *); |
| 259 | extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | ||
| 260 | int data_direction, void *buffer, unsigned bufflen, | ||
| 261 | unsigned char *sense, int timeout, int retries, | ||
| 262 | int flag); | ||
| 263 | |||
| 264 | static inline int | ||
| 265 | scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | ||
| 266 | int data_direction, void *buffer, unsigned bufflen, | ||
| 267 | unsigned char *sense, int timeout, int retries) | ||
| 268 | { | ||
| 269 | return scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, | ||
| 270 | timeout, retries, 0); | ||
| 271 | } | ||
| 259 | static inline int scsi_device_online(struct scsi_device *sdev) | 272 | static inline int scsi_device_online(struct scsi_device *sdev) |
| 260 | { | 273 | { |
| 261 | return sdev->sdev_state != SDEV_OFFLINE; | 274 | return sdev->sdev_state != SDEV_OFFLINE; |
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 80557f879e3e..b24d224281bd 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h | |||
| @@ -26,6 +26,14 @@ struct scsi_sense_hdr { /* See SPC-3 section 4.5 */ | |||
| 26 | u8 additional_length; /* always 0 for fixed sense format */ | 26 | u8 additional_length; /* always 0 for fixed sense format */ |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr) | ||
| 30 | { | ||
| 31 | if (!sshdr) | ||
| 32 | return 0; | ||
| 33 | |||
| 34 | return (sshdr->response_code & 0x70) == 0x70; | ||
| 35 | } | ||
| 36 | |||
| 29 | 37 | ||
| 30 | extern void scsi_add_timer(struct scsi_cmnd *, int, | 38 | extern void scsi_add_timer(struct scsi_cmnd *, int, |
| 31 | void (*)(struct scsi_cmnd *)); | 39 | void (*)(struct scsi_cmnd *)); |
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index f5dfdfec9fea..6a140020d7cb 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h | |||
| @@ -54,8 +54,4 @@ extern void scsi_do_req(struct scsi_request *, const void *cmnd, | |||
| 54 | void *buffer, unsigned bufflen, | 54 | void *buffer, unsigned bufflen, |
| 55 | void (*done) (struct scsi_cmnd *), | 55 | void (*done) (struct scsi_cmnd *), |
| 56 | int timeout, int retries); | 56 | int timeout, int retries); |
| 57 | extern int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, | ||
| 58 | int data_direction, void *buffer, unsigned bufflen, | ||
| 59 | unsigned char *sense, int timeout, int retries); | ||
| 60 | |||
| 61 | #endif /* _SCSI_SCSI_REQUEST_H */ | 57 | #endif /* _SCSI_SCSI_REQUEST_H */ |
