diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 94 |
1 files changed, 33 insertions, 61 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 278e0c99b2ae..3f3accd6cd46 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1615,7 +1615,7 @@ void scsi_exit_queue(void) | |||
1615 | /** | 1615 | /** |
1616 | * __scsi_mode_sense - issue a mode sense, falling back from 10 to | 1616 | * __scsi_mode_sense - issue a mode sense, falling back from 10 to |
1617 | * six bytes if necessary. | 1617 | * six bytes if necessary. |
1618 | * @sreq: SCSI request to fill in with the MODE_SENSE | 1618 | * @sdev: SCSI device to be queried |
1619 | * @dbd: set if mode sense will allow block descriptors to be returned | 1619 | * @dbd: set if mode sense will allow block descriptors to be returned |
1620 | * @modepage: mode page being requested | 1620 | * @modepage: mode page being requested |
1621 | * @buffer: request buffer (may not be smaller than eight bytes) | 1621 | * @buffer: request buffer (may not be smaller than eight bytes) |
@@ -1623,26 +1623,38 @@ void scsi_exit_queue(void) | |||
1623 | * @timeout: command timeout | 1623 | * @timeout: command timeout |
1624 | * @retries: number of retries before failing | 1624 | * @retries: number of retries before failing |
1625 | * @data: returns a structure abstracting the mode header data | 1625 | * @data: returns a structure abstracting the mode header data |
1626 | * @sense: place to put sense data (or NULL if no sense to be collected). | ||
1627 | * must be SCSI_SENSE_BUFFERSIZE big. | ||
1626 | * | 1628 | * |
1627 | * Returns zero if unsuccessful, or the header offset (either 4 | 1629 | * Returns zero if unsuccessful, or the header offset (either 4 |
1628 | * or 8 depending on whether a six or ten byte command was | 1630 | * or 8 depending on whether a six or ten byte command was |
1629 | * issued) if successful. | 1631 | * issued) if successful. |
1630 | **/ | 1632 | **/ |
1631 | int | 1633 | int |
1632 | __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, | 1634 | scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, |
1633 | unsigned char *buffer, int len, int timeout, int retries, | 1635 | unsigned char *buffer, int len, int timeout, int retries, |
1634 | struct scsi_mode_data *data) { | 1636 | struct scsi_mode_data *data, char *sense) { |
1635 | unsigned char cmd[12]; | 1637 | unsigned char cmd[12]; |
1636 | int use_10_for_ms; | 1638 | int use_10_for_ms; |
1637 | int header_length; | 1639 | int header_length; |
1640 | int result; | ||
1641 | char *sense_buffer = NULL; | ||
1638 | 1642 | ||
1639 | memset(data, 0, sizeof(*data)); | 1643 | memset(data, 0, sizeof(*data)); |
1640 | memset(&cmd[0], 0, 12); | 1644 | memset(&cmd[0], 0, 12); |
1641 | cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ | 1645 | cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ |
1642 | cmd[2] = modepage; | 1646 | cmd[2] = modepage; |
1643 | 1647 | ||
1648 | if (!sense) { | ||
1649 | sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); | ||
1650 | if (!sense_buffer) { | ||
1651 | dev_printk(KERN_ERR, &sdev->sdev_gendev, "failed to allocate sense buffer\n"); | ||
1652 | return 0; | ||
1653 | } | ||
1654 | sense = sense_buffer; | ||
1655 | } | ||
1644 | retry: | 1656 | retry: |
1645 | use_10_for_ms = sreq->sr_device->use_10_for_ms; | 1657 | use_10_for_ms = sdev->use_10_for_ms; |
1646 | 1658 | ||
1647 | if (use_10_for_ms) { | 1659 | if (use_10_for_ms) { |
1648 | if (len < 8) | 1660 | if (len < 8) |
@@ -1660,36 +1672,35 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, | |||
1660 | header_length = 4; | 1672 | header_length = 4; |
1661 | } | 1673 | } |
1662 | 1674 | ||
1663 | sreq->sr_cmd_len = 0; | 1675 | memset(sense, 0, SCSI_SENSE_BUFFERSIZE); |
1664 | memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer)); | ||
1665 | sreq->sr_data_direction = DMA_FROM_DEVICE; | ||
1666 | 1676 | ||
1667 | memset(buffer, 0, len); | 1677 | memset(buffer, 0, len); |
1668 | 1678 | ||
1669 | scsi_wait_req(sreq, cmd, buffer, len, timeout, retries); | 1679 | result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, |
1680 | sense, timeout, retries); | ||
1670 | 1681 | ||
1671 | /* This code looks awful: what it's doing is making sure an | 1682 | /* This code looks awful: what it's doing is making sure an |
1672 | * ILLEGAL REQUEST sense return identifies the actual command | 1683 | * ILLEGAL REQUEST sense return identifies the actual command |
1673 | * byte as the problem. MODE_SENSE commands can return | 1684 | * byte as the problem. MODE_SENSE commands can return |
1674 | * ILLEGAL REQUEST if the code page isn't supported */ | 1685 | * ILLEGAL REQUEST if the code page isn't supported */ |
1675 | 1686 | ||
1676 | if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) && | 1687 | if (use_10_for_ms && !scsi_status_is_good(result) && |
1677 | (driver_byte(sreq->sr_result) & DRIVER_SENSE)) { | 1688 | (driver_byte(result) & DRIVER_SENSE)) { |
1678 | struct scsi_sense_hdr sshdr; | 1689 | struct scsi_sense_hdr sshdr; |
1679 | 1690 | ||
1680 | if (scsi_request_normalize_sense(sreq, &sshdr)) { | 1691 | if (scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) { |
1681 | if ((sshdr.sense_key == ILLEGAL_REQUEST) && | 1692 | if ((sshdr.sense_key == ILLEGAL_REQUEST) && |
1682 | (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { | 1693 | (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { |
1683 | /* | 1694 | /* |
1684 | * Invalid command operation code | 1695 | * Invalid command operation code |
1685 | */ | 1696 | */ |
1686 | sreq->sr_device->use_10_for_ms = 0; | 1697 | sdev->use_10_for_ms = 0; |
1687 | goto retry; | 1698 | goto retry; |
1688 | } | 1699 | } |
1689 | } | 1700 | } |
1690 | } | 1701 | } |
1691 | 1702 | ||
1692 | if(scsi_status_is_good(sreq->sr_result)) { | 1703 | if(scsi_status_is_good(result)) { |
1693 | data->header_length = header_length; | 1704 | data->header_length = header_length; |
1694 | if(use_10_for_ms) { | 1705 | if(use_10_for_ms) { |
1695 | data->length = buffer[0]*256 + buffer[1] + 2; | 1706 | data->length = buffer[0]*256 + buffer[1] + 2; |
@@ -1706,73 +1717,34 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, | |||
1706 | } | 1717 | } |
1707 | } | 1718 | } |
1708 | 1719 | ||
1709 | return sreq->sr_result; | 1720 | kfree(sense_buffer); |
1710 | } | 1721 | return result; |
1711 | EXPORT_SYMBOL(__scsi_mode_sense); | ||
1712 | |||
1713 | /** | ||
1714 | * scsi_mode_sense - issue a mode sense, falling back from 10 to | ||
1715 | * six bytes if necessary. | ||
1716 | * @sdev: scsi device to send command to. | ||
1717 | * @dbd: set if mode sense will disable block descriptors in the return | ||
1718 | * @modepage: mode page being requested | ||
1719 | * @buffer: request buffer (may not be smaller than eight bytes) | ||
1720 | * @len: length of request buffer. | ||
1721 | * @timeout: command timeout | ||
1722 | * @retries: number of retries before failing | ||
1723 | * | ||
1724 | * Returns zero if unsuccessful, or the header offset (either 4 | ||
1725 | * or 8 depending on whether a six or ten byte command was | ||
1726 | * issued) if successful. | ||
1727 | **/ | ||
1728 | int | ||
1729 | scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, | ||
1730 | unsigned char *buffer, int len, int timeout, int retries, | ||
1731 | struct scsi_mode_data *data) | ||
1732 | { | ||
1733 | struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); | ||
1734 | int ret; | ||
1735 | |||
1736 | if (!sreq) | ||
1737 | return -1; | ||
1738 | |||
1739 | ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len, | ||
1740 | timeout, retries, data); | ||
1741 | |||
1742 | scsi_release_request(sreq); | ||
1743 | |||
1744 | return ret; | ||
1745 | } | 1722 | } |
1746 | EXPORT_SYMBOL(scsi_mode_sense); | 1723 | EXPORT_SYMBOL(scsi_mode_sense); |
1747 | 1724 | ||
1748 | int | 1725 | int |
1749 | scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) | 1726 | scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) |
1750 | { | 1727 | { |
1751 | struct scsi_request *sreq; | ||
1752 | char cmd[] = { | 1728 | char cmd[] = { |
1753 | TEST_UNIT_READY, 0, 0, 0, 0, 0, | 1729 | TEST_UNIT_READY, 0, 0, 0, 0, 0, |
1754 | }; | 1730 | }; |
1731 | char sense[SCSI_SENSE_BUFFERSIZE]; | ||
1755 | int result; | 1732 | int result; |
1756 | 1733 | ||
1757 | sreq = scsi_allocate_request(sdev, GFP_KERNEL); | 1734 | result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sense, |
1758 | if (!sreq) | 1735 | timeout, retries); |
1759 | return -ENOMEM; | ||
1760 | |||
1761 | sreq->sr_data_direction = DMA_NONE; | ||
1762 | scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); | ||
1763 | 1736 | ||
1764 | if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) { | 1737 | if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { |
1765 | struct scsi_sense_hdr sshdr; | 1738 | struct scsi_sense_hdr sshdr; |
1766 | 1739 | ||
1767 | if ((scsi_request_normalize_sense(sreq, &sshdr)) && | 1740 | if ((scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, |
1741 | &sshdr)) && | ||
1768 | ((sshdr.sense_key == UNIT_ATTENTION) || | 1742 | ((sshdr.sense_key == UNIT_ATTENTION) || |
1769 | (sshdr.sense_key == NOT_READY))) { | 1743 | (sshdr.sense_key == NOT_READY))) { |
1770 | sdev->changed = 1; | 1744 | sdev->changed = 1; |
1771 | sreq->sr_result = 0; | 1745 | result = 0; |
1772 | } | 1746 | } |
1773 | } | 1747 | } |
1774 | result = sreq->sr_result; | ||
1775 | scsi_release_request(sreq); | ||
1776 | return result; | 1748 | return result; |
1777 | } | 1749 | } |
1778 | EXPORT_SYMBOL(scsi_test_unit_ready); | 1750 | EXPORT_SYMBOL(scsi_test_unit_ready); |