diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 67 |
1 files changed, 39 insertions, 28 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 42edf29223a..bdea26b56dc 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -293,8 +293,8 @@ EXPORT_SYMBOL(scsi_wait_req); | |||
293 | * @retries: number of times to retry request | 293 | * @retries: number of times to retry request |
294 | * @flags: or into request flags; | 294 | * @flags: or into request flags; |
295 | * | 295 | * |
296 | * scsi_execute_req returns the req->errors value which is the | 296 | * returns the req->errors value which is the the scsi_cmnd result |
297 | * the scsi_cmnd result field. | 297 | * field. |
298 | **/ | 298 | **/ |
299 | int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | 299 | int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, |
300 | int data_direction, void *buffer, unsigned bufflen, | 300 | int data_direction, void *buffer, unsigned bufflen, |
@@ -328,9 +328,31 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
328 | 328 | ||
329 | return ret; | 329 | return ret; |
330 | } | 330 | } |
331 | |||
332 | EXPORT_SYMBOL(scsi_execute); | 331 | EXPORT_SYMBOL(scsi_execute); |
333 | 332 | ||
333 | |||
334 | int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | ||
335 | int data_direction, void *buffer, unsigned bufflen, | ||
336 | struct scsi_sense_hdr *sshdr, int timeout, int retries) | ||
337 | { | ||
338 | char *sense = NULL; | ||
339 | |||
340 | if (sshdr) { | ||
341 | sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); | ||
342 | if (!sense) | ||
343 | return DRIVER_ERROR << 24; | ||
344 | memset(sense, 0, sizeof(*sense)); | ||
345 | } | ||
346 | int result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, | ||
347 | sense, timeout, retries, 0); | ||
348 | if (sshdr) | ||
349 | scsi_normalize_sense(sense, sizeof(*sense), sshdr); | ||
350 | |||
351 | kfree(sense); | ||
352 | return result; | ||
353 | } | ||
354 | EXPORT_SYMBOL(scsi_execute_req); | ||
355 | |||
334 | /* | 356 | /* |
335 | * Function: scsi_init_cmd_errh() | 357 | * Function: scsi_init_cmd_errh() |
336 | * | 358 | * |
@@ -1614,7 +1636,7 @@ void scsi_exit_queue(void) | |||
1614 | } | 1636 | } |
1615 | } | 1637 | } |
1616 | /** | 1638 | /** |
1617 | * __scsi_mode_sense - issue a mode sense, falling back from 10 to | 1639 | * scsi_mode_sense - issue a mode sense, falling back from 10 to |
1618 | * six bytes if necessary. | 1640 | * six bytes if necessary. |
1619 | * @sdev: SCSI device to be queried | 1641 | * @sdev: SCSI device to be queried |
1620 | * @dbd: set if mode sense will allow block descriptors to be returned | 1642 | * @dbd: set if mode sense will allow block descriptors to be returned |
@@ -1634,26 +1656,22 @@ void scsi_exit_queue(void) | |||
1634 | int | 1656 | int |
1635 | scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, | 1657 | scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, |
1636 | unsigned char *buffer, int len, int timeout, int retries, | 1658 | unsigned char *buffer, int len, int timeout, int retries, |
1637 | struct scsi_mode_data *data, char *sense) { | 1659 | struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { |
1638 | unsigned char cmd[12]; | 1660 | unsigned char cmd[12]; |
1639 | int use_10_for_ms; | 1661 | int use_10_for_ms; |
1640 | int header_length; | 1662 | int header_length; |
1641 | int result; | 1663 | int result; |
1642 | char *sense_buffer = NULL; | 1664 | struct scsi_sense_hdr my_sshdr; |
1643 | 1665 | ||
1644 | memset(data, 0, sizeof(*data)); | 1666 | memset(data, 0, sizeof(*data)); |
1645 | memset(&cmd[0], 0, 12); | 1667 | memset(&cmd[0], 0, 12); |
1646 | cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ | 1668 | cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ |
1647 | cmd[2] = modepage; | 1669 | cmd[2] = modepage; |
1648 | 1670 | ||
1649 | if (!sense) { | 1671 | /* caller might not be interested in sense, but we need it */ |
1650 | sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); | 1672 | if (!sshdr) |
1651 | if (!sense_buffer) { | 1673 | sshdr = &my_sshdr; |
1652 | dev_printk(KERN_ERR, &sdev->sdev_gendev, "failed to allocate sense buffer\n"); | 1674 | |
1653 | return 0; | ||
1654 | } | ||
1655 | sense = sense_buffer; | ||
1656 | } | ||
1657 | retry: | 1675 | retry: |
1658 | use_10_for_ms = sdev->use_10_for_ms; | 1676 | use_10_for_ms = sdev->use_10_for_ms; |
1659 | 1677 | ||
@@ -1673,12 +1691,10 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, | |||
1673 | header_length = 4; | 1691 | header_length = 4; |
1674 | } | 1692 | } |
1675 | 1693 | ||
1676 | memset(sense, 0, SCSI_SENSE_BUFFERSIZE); | ||
1677 | |||
1678 | memset(buffer, 0, len); | 1694 | memset(buffer, 0, len); |
1679 | 1695 | ||
1680 | result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, | 1696 | result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, |
1681 | sense, timeout, retries); | 1697 | sshdr, timeout, retries); |
1682 | 1698 | ||
1683 | /* This code looks awful: what it's doing is making sure an | 1699 | /* This code looks awful: what it's doing is making sure an |
1684 | * ILLEGAL REQUEST sense return identifies the actual command | 1700 | * ILLEGAL REQUEST sense return identifies the actual command |
@@ -1687,11 +1703,9 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, | |||
1687 | 1703 | ||
1688 | if (use_10_for_ms && !scsi_status_is_good(result) && | 1704 | if (use_10_for_ms && !scsi_status_is_good(result) && |
1689 | (driver_byte(result) & DRIVER_SENSE)) { | 1705 | (driver_byte(result) & DRIVER_SENSE)) { |
1690 | struct scsi_sense_hdr sshdr; | 1706 | if (scsi_sense_valid(sshdr)) { |
1691 | 1707 | if ((sshdr->sense_key == ILLEGAL_REQUEST) && | |
1692 | if (scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) { | 1708 | (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { |
1693 | if ((sshdr.sense_key == ILLEGAL_REQUEST) && | ||
1694 | (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { | ||
1695 | /* | 1709 | /* |
1696 | * Invalid command operation code | 1710 | * Invalid command operation code |
1697 | */ | 1711 | */ |
@@ -1718,7 +1732,6 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, | |||
1718 | } | 1732 | } |
1719 | } | 1733 | } |
1720 | 1734 | ||
1721 | kfree(sense_buffer); | ||
1722 | return result; | 1735 | return result; |
1723 | } | 1736 | } |
1724 | EXPORT_SYMBOL(scsi_mode_sense); | 1737 | EXPORT_SYMBOL(scsi_mode_sense); |
@@ -1729,17 +1742,15 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) | |||
1729 | char cmd[] = { | 1742 | char cmd[] = { |
1730 | TEST_UNIT_READY, 0, 0, 0, 0, 0, | 1743 | TEST_UNIT_READY, 0, 0, 0, 0, 0, |
1731 | }; | 1744 | }; |
1732 | char sense[SCSI_SENSE_BUFFERSIZE]; | 1745 | struct scsi_sense_hdr sshdr; |
1733 | int result; | 1746 | int result; |
1734 | 1747 | ||
1735 | result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sense, | 1748 | result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, |
1736 | timeout, retries); | 1749 | timeout, retries); |
1737 | 1750 | ||
1738 | if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { | 1751 | if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { |
1739 | struct scsi_sense_hdr sshdr; | ||
1740 | 1752 | ||
1741 | if ((scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, | 1753 | if ((scsi_sense_valid(&sshdr)) && |
1742 | &sshdr)) && | ||
1743 | ((sshdr.sense_key == UNIT_ATTENTION) || | 1754 | ((sshdr.sense_key == UNIT_ATTENTION) || |
1744 | (sshdr.sense_key == NOT_READY))) { | 1755 | (sshdr.sense_key == NOT_READY))) { |
1745 | sdev->changed = 1; | 1756 | sdev->changed = 1; |