diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/DAC960.c | 157 | ||||
-rw-r--r-- | drivers/block/Kconfig | 12 | ||||
-rw-r--r-- | drivers/block/Makefile | 1 | ||||
-rw-r--r-- | drivers/block/amiflop.c | 6 | ||||
-rw-r--r-- | drivers/block/aoe/aoechr.c | 7 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 2 | ||||
-rw-r--r-- | drivers/block/ataflop.c | 4 | ||||
-rw-r--r-- | drivers/block/brd.c | 2 | ||||
-rw-r--r-- | drivers/block/cciss.c | 81 | ||||
-rw-r--r-- | drivers/block/hd.c | 814 | ||||
-rw-r--r-- | drivers/block/paride/pd.c | 20 | ||||
-rw-r--r-- | drivers/block/paride/pg.c | 22 | ||||
-rw-r--r-- | drivers/block/paride/pt.c | 27 | ||||
-rw-r--r-- | drivers/block/pktcdvd.c | 46 | ||||
-rw-r--r-- | drivers/block/viodasd.c | 2 | ||||
-rw-r--r-- | drivers/block/virtio_blk.c | 7 | ||||
-rw-r--r-- | drivers/block/xen-blkfront.c | 48 | ||||
-rw-r--r-- | drivers/block/z2ram.c | 2 |
18 files changed, 1118 insertions, 142 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index cd03473f3547..a002a381df92 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
@@ -6628,15 +6628,18 @@ static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller) | |||
6628 | * DAC960_gam_ioctl is the ioctl function for performing RAID operations. | 6628 | * DAC960_gam_ioctl is the ioctl function for performing RAID operations. |
6629 | */ | 6629 | */ |
6630 | 6630 | ||
6631 | static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | 6631 | static long DAC960_gam_ioctl(struct file *file, unsigned int Request, |
6632 | unsigned int Request, unsigned long Argument) | 6632 | unsigned long Argument) |
6633 | { | 6633 | { |
6634 | int ErrorCode = 0; | 6634 | long ErrorCode = 0; |
6635 | if (!capable(CAP_SYS_ADMIN)) return -EACCES; | 6635 | if (!capable(CAP_SYS_ADMIN)) return -EACCES; |
6636 | |||
6637 | lock_kernel(); | ||
6636 | switch (Request) | 6638 | switch (Request) |
6637 | { | 6639 | { |
6638 | case DAC960_IOCTL_GET_CONTROLLER_COUNT: | 6640 | case DAC960_IOCTL_GET_CONTROLLER_COUNT: |
6639 | return DAC960_ControllerCount; | 6641 | ErrorCode = DAC960_ControllerCount; |
6642 | break; | ||
6640 | case DAC960_IOCTL_GET_CONTROLLER_INFO: | 6643 | case DAC960_IOCTL_GET_CONTROLLER_INFO: |
6641 | { | 6644 | { |
6642 | DAC960_ControllerInfo_T __user *UserSpaceControllerInfo = | 6645 | DAC960_ControllerInfo_T __user *UserSpaceControllerInfo = |
@@ -6644,15 +6647,20 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6644 | DAC960_ControllerInfo_T ControllerInfo; | 6647 | DAC960_ControllerInfo_T ControllerInfo; |
6645 | DAC960_Controller_T *Controller; | 6648 | DAC960_Controller_T *Controller; |
6646 | int ControllerNumber; | 6649 | int ControllerNumber; |
6647 | if (UserSpaceControllerInfo == NULL) return -EINVAL; | 6650 | if (UserSpaceControllerInfo == NULL) |
6648 | ErrorCode = get_user(ControllerNumber, | 6651 | ErrorCode = -EINVAL; |
6652 | else ErrorCode = get_user(ControllerNumber, | ||
6649 | &UserSpaceControllerInfo->ControllerNumber); | 6653 | &UserSpaceControllerInfo->ControllerNumber); |
6650 | if (ErrorCode != 0) return ErrorCode; | 6654 | if (ErrorCode != 0) |
6655 | break;; | ||
6656 | ErrorCode = -ENXIO; | ||
6651 | if (ControllerNumber < 0 || | 6657 | if (ControllerNumber < 0 || |
6652 | ControllerNumber > DAC960_ControllerCount - 1) | 6658 | ControllerNumber > DAC960_ControllerCount - 1) { |
6653 | return -ENXIO; | 6659 | break; |
6660 | } | ||
6654 | Controller = DAC960_Controllers[ControllerNumber]; | 6661 | Controller = DAC960_Controllers[ControllerNumber]; |
6655 | if (Controller == NULL) return -ENXIO; | 6662 | if (Controller == NULL) |
6663 | break;; | ||
6656 | memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); | 6664 | memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); |
6657 | ControllerInfo.ControllerNumber = ControllerNumber; | 6665 | ControllerInfo.ControllerNumber = ControllerNumber; |
6658 | ControllerInfo.FirmwareType = Controller->FirmwareType; | 6666 | ControllerInfo.FirmwareType = Controller->FirmwareType; |
@@ -6665,8 +6673,9 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6665 | ControllerInfo.PCI_Address = Controller->PCI_Address; | 6673 | ControllerInfo.PCI_Address = Controller->PCI_Address; |
6666 | strcpy(ControllerInfo.ModelName, Controller->ModelName); | 6674 | strcpy(ControllerInfo.ModelName, Controller->ModelName); |
6667 | strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion); | 6675 | strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion); |
6668 | return (copy_to_user(UserSpaceControllerInfo, &ControllerInfo, | 6676 | ErrorCode = (copy_to_user(UserSpaceControllerInfo, &ControllerInfo, |
6669 | sizeof(DAC960_ControllerInfo_T)) ? -EFAULT : 0); | 6677 | sizeof(DAC960_ControllerInfo_T)) ? -EFAULT : 0); |
6678 | break; | ||
6670 | } | 6679 | } |
6671 | case DAC960_IOCTL_V1_EXECUTE_COMMAND: | 6680 | case DAC960_IOCTL_V1_EXECUTE_COMMAND: |
6672 | { | 6681 | { |
@@ -6684,30 +6693,39 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6684 | int ControllerNumber, DataTransferLength; | 6693 | int ControllerNumber, DataTransferLength; |
6685 | unsigned char *DataTransferBuffer = NULL; | 6694 | unsigned char *DataTransferBuffer = NULL; |
6686 | dma_addr_t DataTransferBufferDMA; | 6695 | dma_addr_t DataTransferBufferDMA; |
6687 | if (UserSpaceUserCommand == NULL) return -EINVAL; | 6696 | if (UserSpaceUserCommand == NULL) { |
6697 | ErrorCode = -EINVAL; | ||
6698 | break; | ||
6699 | } | ||
6688 | if (copy_from_user(&UserCommand, UserSpaceUserCommand, | 6700 | if (copy_from_user(&UserCommand, UserSpaceUserCommand, |
6689 | sizeof(DAC960_V1_UserCommand_T))) { | 6701 | sizeof(DAC960_V1_UserCommand_T))) { |
6690 | ErrorCode = -EFAULT; | 6702 | ErrorCode = -EFAULT; |
6691 | goto Failure1a; | 6703 | break; |
6692 | } | 6704 | } |
6693 | ControllerNumber = UserCommand.ControllerNumber; | 6705 | ControllerNumber = UserCommand.ControllerNumber; |
6706 | ErrorCode = -ENXIO; | ||
6694 | if (ControllerNumber < 0 || | 6707 | if (ControllerNumber < 0 || |
6695 | ControllerNumber > DAC960_ControllerCount - 1) | 6708 | ControllerNumber > DAC960_ControllerCount - 1) |
6696 | return -ENXIO; | 6709 | break; |
6697 | Controller = DAC960_Controllers[ControllerNumber]; | 6710 | Controller = DAC960_Controllers[ControllerNumber]; |
6698 | if (Controller == NULL) return -ENXIO; | 6711 | if (Controller == NULL) |
6699 | if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; | 6712 | break; |
6713 | ErrorCode = -EINVAL; | ||
6714 | if (Controller->FirmwareType != DAC960_V1_Controller) | ||
6715 | break; | ||
6700 | CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode; | 6716 | CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode; |
6701 | DataTransferLength = UserCommand.DataTransferLength; | 6717 | DataTransferLength = UserCommand.DataTransferLength; |
6702 | if (CommandOpcode & 0x80) return -EINVAL; | 6718 | if (CommandOpcode & 0x80) |
6719 | break; | ||
6703 | if (CommandOpcode == DAC960_V1_DCDB) | 6720 | if (CommandOpcode == DAC960_V1_DCDB) |
6704 | { | 6721 | { |
6705 | if (copy_from_user(&DCDB, UserCommand.DCDB, | 6722 | if (copy_from_user(&DCDB, UserCommand.DCDB, |
6706 | sizeof(DAC960_V1_DCDB_T))) { | 6723 | sizeof(DAC960_V1_DCDB_T))) { |
6707 | ErrorCode = -EFAULT; | 6724 | ErrorCode = -EFAULT; |
6708 | goto Failure1a; | 6725 | break; |
6709 | } | 6726 | } |
6710 | if (DCDB.Channel >= DAC960_V1_MaxChannels) return -EINVAL; | 6727 | if (DCDB.Channel >= DAC960_V1_MaxChannels) |
6728 | break; | ||
6711 | if (!((DataTransferLength == 0 && | 6729 | if (!((DataTransferLength == 0 && |
6712 | DCDB.Direction | 6730 | DCDB.Direction |
6713 | == DAC960_V1_DCDB_NoDataTransfer) || | 6731 | == DAC960_V1_DCDB_NoDataTransfer) || |
@@ -6717,38 +6735,37 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6717 | (DataTransferLength < 0 && | 6735 | (DataTransferLength < 0 && |
6718 | DCDB.Direction | 6736 | DCDB.Direction |
6719 | == DAC960_V1_DCDB_DataTransferSystemToDevice))) | 6737 | == DAC960_V1_DCDB_DataTransferSystemToDevice))) |
6720 | return -EINVAL; | 6738 | break; |
6721 | if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) | 6739 | if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) |
6722 | != abs(DataTransferLength)) | 6740 | != abs(DataTransferLength)) |
6723 | return -EINVAL; | 6741 | break; |
6724 | DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice, | 6742 | DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice, |
6725 | sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA); | 6743 | sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA); |
6726 | if (DCDB_IOBUF == NULL) | 6744 | if (DCDB_IOBUF == NULL) { |
6727 | return -ENOMEM; | 6745 | ErrorCode = -ENOMEM; |
6746 | break; | ||
6747 | } | ||
6728 | } | 6748 | } |
6749 | ErrorCode = -ENOMEM; | ||
6729 | if (DataTransferLength > 0) | 6750 | if (DataTransferLength > 0) |
6730 | { | 6751 | { |
6731 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, | 6752 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, |
6732 | DataTransferLength, &DataTransferBufferDMA); | 6753 | DataTransferLength, &DataTransferBufferDMA); |
6733 | if (DataTransferBuffer == NULL) { | 6754 | if (DataTransferBuffer == NULL) |
6734 | ErrorCode = -ENOMEM; | 6755 | break; |
6735 | goto Failure1; | ||
6736 | } | ||
6737 | memset(DataTransferBuffer, 0, DataTransferLength); | 6756 | memset(DataTransferBuffer, 0, DataTransferLength); |
6738 | } | 6757 | } |
6739 | else if (DataTransferLength < 0) | 6758 | else if (DataTransferLength < 0) |
6740 | { | 6759 | { |
6741 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, | 6760 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, |
6742 | -DataTransferLength, &DataTransferBufferDMA); | 6761 | -DataTransferLength, &DataTransferBufferDMA); |
6743 | if (DataTransferBuffer == NULL) { | 6762 | if (DataTransferBuffer == NULL) |
6744 | ErrorCode = -ENOMEM; | 6763 | break; |
6745 | goto Failure1; | ||
6746 | } | ||
6747 | if (copy_from_user(DataTransferBuffer, | 6764 | if (copy_from_user(DataTransferBuffer, |
6748 | UserCommand.DataTransferBuffer, | 6765 | UserCommand.DataTransferBuffer, |
6749 | -DataTransferLength)) { | 6766 | -DataTransferLength)) { |
6750 | ErrorCode = -EFAULT; | 6767 | ErrorCode = -EFAULT; |
6751 | goto Failure1; | 6768 | break; |
6752 | } | 6769 | } |
6753 | } | 6770 | } |
6754 | if (CommandOpcode == DAC960_V1_DCDB) | 6771 | if (CommandOpcode == DAC960_V1_DCDB) |
@@ -6825,8 +6842,7 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6825 | if (DCDB_IOBUF != NULL) | 6842 | if (DCDB_IOBUF != NULL) |
6826 | pci_free_consistent(Controller->PCIDevice, sizeof(DAC960_V1_DCDB_T), | 6843 | pci_free_consistent(Controller->PCIDevice, sizeof(DAC960_V1_DCDB_T), |
6827 | DCDB_IOBUF, DCDB_IOBUFDMA); | 6844 | DCDB_IOBUF, DCDB_IOBUFDMA); |
6828 | Failure1a: | 6845 | break; |
6829 | return ErrorCode; | ||
6830 | } | 6846 | } |
6831 | case DAC960_IOCTL_V2_EXECUTE_COMMAND: | 6847 | case DAC960_IOCTL_V2_EXECUTE_COMMAND: |
6832 | { | 6848 | { |
@@ -6844,32 +6860,43 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6844 | dma_addr_t DataTransferBufferDMA; | 6860 | dma_addr_t DataTransferBufferDMA; |
6845 | unsigned char *RequestSenseBuffer = NULL; | 6861 | unsigned char *RequestSenseBuffer = NULL; |
6846 | dma_addr_t RequestSenseBufferDMA; | 6862 | dma_addr_t RequestSenseBufferDMA; |
6847 | if (UserSpaceUserCommand == NULL) return -EINVAL; | 6863 | |
6864 | ErrorCode = -EINVAL; | ||
6865 | if (UserSpaceUserCommand == NULL) | ||
6866 | break; | ||
6848 | if (copy_from_user(&UserCommand, UserSpaceUserCommand, | 6867 | if (copy_from_user(&UserCommand, UserSpaceUserCommand, |
6849 | sizeof(DAC960_V2_UserCommand_T))) { | 6868 | sizeof(DAC960_V2_UserCommand_T))) { |
6850 | ErrorCode = -EFAULT; | 6869 | ErrorCode = -EFAULT; |
6851 | goto Failure2a; | 6870 | break; |
6852 | } | 6871 | } |
6872 | ErrorCode = -ENXIO; | ||
6853 | ControllerNumber = UserCommand.ControllerNumber; | 6873 | ControllerNumber = UserCommand.ControllerNumber; |
6854 | if (ControllerNumber < 0 || | 6874 | if (ControllerNumber < 0 || |
6855 | ControllerNumber > DAC960_ControllerCount - 1) | 6875 | ControllerNumber > DAC960_ControllerCount - 1) |
6856 | return -ENXIO; | 6876 | break; |
6857 | Controller = DAC960_Controllers[ControllerNumber]; | 6877 | Controller = DAC960_Controllers[ControllerNumber]; |
6858 | if (Controller == NULL) return -ENXIO; | 6878 | if (Controller == NULL) |
6859 | if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; | 6879 | break; |
6880 | if (Controller->FirmwareType != DAC960_V2_Controller){ | ||
6881 | ErrorCode = -EINVAL; | ||
6882 | break; | ||
6883 | } | ||
6860 | DataTransferLength = UserCommand.DataTransferLength; | 6884 | DataTransferLength = UserCommand.DataTransferLength; |
6885 | ErrorCode = -ENOMEM; | ||
6861 | if (DataTransferLength > 0) | 6886 | if (DataTransferLength > 0) |
6862 | { | 6887 | { |
6863 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, | 6888 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, |
6864 | DataTransferLength, &DataTransferBufferDMA); | 6889 | DataTransferLength, &DataTransferBufferDMA); |
6865 | if (DataTransferBuffer == NULL) return -ENOMEM; | 6890 | if (DataTransferBuffer == NULL) |
6891 | break; | ||
6866 | memset(DataTransferBuffer, 0, DataTransferLength); | 6892 | memset(DataTransferBuffer, 0, DataTransferLength); |
6867 | } | 6893 | } |
6868 | else if (DataTransferLength < 0) | 6894 | else if (DataTransferLength < 0) |
6869 | { | 6895 | { |
6870 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, | 6896 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, |
6871 | -DataTransferLength, &DataTransferBufferDMA); | 6897 | -DataTransferLength, &DataTransferBufferDMA); |
6872 | if (DataTransferBuffer == NULL) return -ENOMEM; | 6898 | if (DataTransferBuffer == NULL) |
6899 | break; | ||
6873 | if (copy_from_user(DataTransferBuffer, | 6900 | if (copy_from_user(DataTransferBuffer, |
6874 | UserCommand.DataTransferBuffer, | 6901 | UserCommand.DataTransferBuffer, |
6875 | -DataTransferLength)) { | 6902 | -DataTransferLength)) { |
@@ -6979,8 +7006,7 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6979 | if (RequestSenseBuffer != NULL) | 7006 | if (RequestSenseBuffer != NULL) |
6980 | pci_free_consistent(Controller->PCIDevice, RequestSenseLength, | 7007 | pci_free_consistent(Controller->PCIDevice, RequestSenseLength, |
6981 | RequestSenseBuffer, RequestSenseBufferDMA); | 7008 | RequestSenseBuffer, RequestSenseBufferDMA); |
6982 | Failure2a: | 7009 | break; |
6983 | return ErrorCode; | ||
6984 | } | 7010 | } |
6985 | case DAC960_IOCTL_V2_GET_HEALTH_STATUS: | 7011 | case DAC960_IOCTL_V2_GET_HEALTH_STATUS: |
6986 | { | 7012 | { |
@@ -6990,21 +7016,33 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
6990 | DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer; | 7016 | DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer; |
6991 | DAC960_Controller_T *Controller; | 7017 | DAC960_Controller_T *Controller; |
6992 | int ControllerNumber; | 7018 | int ControllerNumber; |
6993 | if (UserSpaceGetHealthStatus == NULL) return -EINVAL; | 7019 | if (UserSpaceGetHealthStatus == NULL) { |
7020 | ErrorCode = -EINVAL; | ||
7021 | break; | ||
7022 | } | ||
6994 | if (copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus, | 7023 | if (copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus, |
6995 | sizeof(DAC960_V2_GetHealthStatus_T))) | 7024 | sizeof(DAC960_V2_GetHealthStatus_T))) { |
6996 | return -EFAULT; | 7025 | ErrorCode = -EFAULT; |
7026 | break; | ||
7027 | } | ||
7028 | ErrorCode = -ENXIO; | ||
6997 | ControllerNumber = GetHealthStatus.ControllerNumber; | 7029 | ControllerNumber = GetHealthStatus.ControllerNumber; |
6998 | if (ControllerNumber < 0 || | 7030 | if (ControllerNumber < 0 || |
6999 | ControllerNumber > DAC960_ControllerCount - 1) | 7031 | ControllerNumber > DAC960_ControllerCount - 1) |
7000 | return -ENXIO; | 7032 | break; |
7001 | Controller = DAC960_Controllers[ControllerNumber]; | 7033 | Controller = DAC960_Controllers[ControllerNumber]; |
7002 | if (Controller == NULL) return -ENXIO; | 7034 | if (Controller == NULL) |
7003 | if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; | 7035 | break; |
7036 | if (Controller->FirmwareType != DAC960_V2_Controller) { | ||
7037 | ErrorCode = -EINVAL; | ||
7038 | break; | ||
7039 | } | ||
7004 | if (copy_from_user(&HealthStatusBuffer, | 7040 | if (copy_from_user(&HealthStatusBuffer, |
7005 | GetHealthStatus.HealthStatusBuffer, | 7041 | GetHealthStatus.HealthStatusBuffer, |
7006 | sizeof(DAC960_V2_HealthStatusBuffer_T))) | 7042 | sizeof(DAC960_V2_HealthStatusBuffer_T))) { |
7007 | return -EFAULT; | 7043 | ErrorCode = -EFAULT; |
7044 | break; | ||
7045 | } | ||
7008 | while (Controller->V2.HealthStatusBuffer->StatusChangeCounter | 7046 | while (Controller->V2.HealthStatusBuffer->StatusChangeCounter |
7009 | == HealthStatusBuffer.StatusChangeCounter && | 7047 | == HealthStatusBuffer.StatusChangeCounter && |
7010 | Controller->V2.HealthStatusBuffer->NextEventSequenceNumber | 7048 | Controller->V2.HealthStatusBuffer->NextEventSequenceNumber |
@@ -7012,21 +7050,28 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file, | |||
7012 | { | 7050 | { |
7013 | interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue, | 7051 | interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue, |
7014 | DAC960_MonitoringTimerInterval); | 7052 | DAC960_MonitoringTimerInterval); |
7015 | if (signal_pending(current)) return -EINTR; | 7053 | if (signal_pending(current)) { |
7054 | ErrorCode = -EINTR; | ||
7055 | break; | ||
7056 | } | ||
7016 | } | 7057 | } |
7017 | if (copy_to_user(GetHealthStatus.HealthStatusBuffer, | 7058 | if (copy_to_user(GetHealthStatus.HealthStatusBuffer, |
7018 | Controller->V2.HealthStatusBuffer, | 7059 | Controller->V2.HealthStatusBuffer, |
7019 | sizeof(DAC960_V2_HealthStatusBuffer_T))) | 7060 | sizeof(DAC960_V2_HealthStatusBuffer_T))) |
7020 | return -EFAULT; | 7061 | ErrorCode = -EFAULT; |
7021 | return 0; | 7062 | else |
7063 | ErrorCode = 0; | ||
7022 | } | 7064 | } |
7065 | default: | ||
7066 | ErrorCode = -ENOTTY; | ||
7023 | } | 7067 | } |
7024 | return -EINVAL; | 7068 | unlock_kernel(); |
7069 | return ErrorCode; | ||
7025 | } | 7070 | } |
7026 | 7071 | ||
7027 | static const struct file_operations DAC960_gam_fops = { | 7072 | static const struct file_operations DAC960_gam_fops = { |
7028 | .owner = THIS_MODULE, | 7073 | .owner = THIS_MODULE, |
7029 | .ioctl = DAC960_gam_ioctl | 7074 | .unlocked_ioctl = DAC960_gam_ioctl |
7030 | }; | 7075 | }; |
7031 | 7076 | ||
7032 | static struct miscdevice DAC960_gam_dev = { | 7077 | static struct miscdevice DAC960_gam_dev = { |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 0d1d2133d9bc..61ad8d639ba3 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -433,4 +433,16 @@ config VIRTIO_BLK | |||
433 | This is the virtual block driver for virtio. It can be used with | 433 | This is the virtual block driver for virtio. It can be used with |
434 | lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. | 434 | lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. |
435 | 435 | ||
436 | config BLK_DEV_HD | ||
437 | bool "Very old hard disk (MFM/RLL/IDE) driver" | ||
438 | depends on HAVE_IDE | ||
439 | depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN | ||
440 | help | ||
441 | This is a very old hard disk driver that lacks the enhanced | ||
442 | functionality of the newer ones. | ||
443 | |||
444 | It is required for systems with ancient MFM/RLL/ESDI drives. | ||
445 | |||
446 | If unsure, say N. | ||
447 | |||
436 | endif # BLK_DEV | 448 | endif # BLK_DEV |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 5e584306be99..204332b29578 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
@@ -29,5 +29,6 @@ obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o | |||
29 | obj-$(CONFIG_VIODASD) += viodasd.o | 29 | obj-$(CONFIG_VIODASD) += viodasd.o |
30 | obj-$(CONFIG_BLK_DEV_SX8) += sx8.o | 30 | obj-$(CONFIG_BLK_DEV_SX8) += sx8.o |
31 | obj-$(CONFIG_BLK_DEV_UB) += ub.o | 31 | obj-$(CONFIG_BLK_DEV_UB) += ub.o |
32 | obj-$(CONFIG_BLK_DEV_HD) += hd.o | ||
32 | 33 | ||
33 | obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o | 34 | obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o |
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index c9751b2b57e6..7516baff3bb9 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
@@ -1714,10 +1714,10 @@ static int __init amiga_floppy_init(void) | |||
1714 | int i, ret; | 1714 | int i, ret; |
1715 | 1715 | ||
1716 | if (!MACH_IS_AMIGA) | 1716 | if (!MACH_IS_AMIGA) |
1717 | return -ENXIO; | 1717 | return -ENODEV; |
1718 | 1718 | ||
1719 | if (!AMIGAHW_PRESENT(AMI_FLOPPY)) | 1719 | if (!AMIGAHW_PRESENT(AMI_FLOPPY)) |
1720 | return -ENXIO; | 1720 | return -ENODEV; |
1721 | 1721 | ||
1722 | if (register_blkdev(FLOPPY_MAJOR,"fd")) | 1722 | if (register_blkdev(FLOPPY_MAJOR,"fd")) |
1723 | return -EBUSY; | 1723 | return -EBUSY; |
@@ -1755,7 +1755,7 @@ static int __init amiga_floppy_init(void) | |||
1755 | if (!floppy_queue) | 1755 | if (!floppy_queue) |
1756 | goto out_queue; | 1756 | goto out_queue; |
1757 | 1757 | ||
1758 | ret = -ENXIO; | 1758 | ret = -ENODEV; |
1759 | if (fd_probe_drives() < 1) /* No usable drives */ | 1759 | if (fd_probe_drives() < 1) /* No usable drives */ |
1760 | goto out_probe; | 1760 | goto out_probe; |
1761 | 1761 | ||
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index e8e60e7a2e70..d1de68a31920 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/hdreg.h> | 7 | #include <linux/hdreg.h> |
8 | #include <linux/blkdev.h> | 8 | #include <linux/blkdev.h> |
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/smp_lock.h> | ||
10 | #include "aoe.h" | 11 | #include "aoe.h" |
11 | 12 | ||
12 | enum { | 13 | enum { |
@@ -174,12 +175,16 @@ aoechr_open(struct inode *inode, struct file *filp) | |||
174 | { | 175 | { |
175 | int n, i; | 176 | int n, i; |
176 | 177 | ||
178 | lock_kernel(); | ||
177 | n = iminor(inode); | 179 | n = iminor(inode); |
178 | filp->private_data = (void *) (unsigned long) n; | 180 | filp->private_data = (void *) (unsigned long) n; |
179 | 181 | ||
180 | for (i = 0; i < ARRAY_SIZE(chardevs); ++i) | 182 | for (i = 0; i < ARRAY_SIZE(chardevs); ++i) |
181 | if (chardevs[i].minor == n) | 183 | if (chardevs[i].minor == n) { |
184 | unlock_kernel(); | ||
182 | return 0; | 185 | return 0; |
186 | } | ||
187 | unlock_kernel(); | ||
183 | return -EINVAL; | 188 | return -EINVAL; |
184 | } | 189 | } |
185 | 190 | ||
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 41f818be2f7e..2f1746295d06 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -1003,7 +1003,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
1003 | * Enough people have their dip switches set backwards to | 1003 | * Enough people have their dip switches set backwards to |
1004 | * warrant a loud message for this special case. | 1004 | * warrant a loud message for this special case. |
1005 | */ | 1005 | */ |
1006 | aoemajor = be16_to_cpu(get_unaligned(&h->major)); | 1006 | aoemajor = get_unaligned_be16(&h->major); |
1007 | if (aoemajor == 0xfff) { | 1007 | if (aoemajor == 0xfff) { |
1008 | printk(KERN_ERR "aoe: Warning: shelf address is all ones. " | 1008 | printk(KERN_ERR "aoe: Warning: shelf address is all ones. " |
1009 | "Check shelf dip switches.\n"); | 1009 | "Check shelf dip switches.\n"); |
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 424995073c6b..49f274197b16 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
@@ -1880,11 +1880,11 @@ static int __init atari_floppy_init (void) | |||
1880 | 1880 | ||
1881 | if (!MACH_IS_ATARI) | 1881 | if (!MACH_IS_ATARI) |
1882 | /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */ | 1882 | /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */ |
1883 | return -ENXIO; | 1883 | return -ENODEV; |
1884 | 1884 | ||
1885 | if (MACH_IS_HADES) | 1885 | if (MACH_IS_HADES) |
1886 | /* Hades doesn't have Atari-compatible floppy */ | 1886 | /* Hades doesn't have Atari-compatible floppy */ |
1887 | return -ENXIO; | 1887 | return -ENODEV; |
1888 | 1888 | ||
1889 | if (register_blkdev(FLOPPY_MAJOR,"fd")) | 1889 | if (register_blkdev(FLOPPY_MAJOR,"fd")) |
1890 | return -EBUSY; | 1890 | return -EBUSY; |
diff --git a/drivers/block/brd.c b/drivers/block/brd.c index a196ef7f147f..24b97b0bef99 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c | |||
@@ -397,6 +397,7 @@ module_param(max_part, int, 0); | |||
397 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk"); | 397 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk"); |
398 | MODULE_LICENSE("GPL"); | 398 | MODULE_LICENSE("GPL"); |
399 | MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR); | 399 | MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR); |
400 | MODULE_ALIAS("rd"); | ||
400 | 401 | ||
401 | #ifndef MODULE | 402 | #ifndef MODULE |
402 | /* Legacy boot options - nonmodular */ | 403 | /* Legacy boot options - nonmodular */ |
@@ -447,6 +448,7 @@ static struct brd_device *brd_alloc(int i) | |||
447 | disk->fops = &brd_fops; | 448 | disk->fops = &brd_fops; |
448 | disk->private_data = brd; | 449 | disk->private_data = brd; |
449 | disk->queue = brd->brd_queue; | 450 | disk->queue = brd->brd_queue; |
451 | disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; | ||
450 | sprintf(disk->disk_name, "ram%d", i); | 452 | sprintf(disk->disk_name, "ram%d", i); |
451 | set_capacity(disk, rd_size * 2); | 453 | set_capacity(disk, rd_size * 2); |
452 | 454 | ||
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e336b05fe4a7..d81632cd7d06 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -53,15 +53,16 @@ | |||
53 | #include <linux/scatterlist.h> | 53 | #include <linux/scatterlist.h> |
54 | 54 | ||
55 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) | 55 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) |
56 | #define DRIVER_NAME "HP CISS Driver (v 3.6.14)" | 56 | #define DRIVER_NAME "HP CISS Driver (v 3.6.20)" |
57 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,14) | 57 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 20) |
58 | 58 | ||
59 | /* Embedded module documentation macros - see modules.h */ | 59 | /* Embedded module documentation macros - see modules.h */ |
60 | MODULE_AUTHOR("Hewlett-Packard Company"); | 60 | MODULE_AUTHOR("Hewlett-Packard Company"); |
61 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.14"); | 61 | MODULE_DESCRIPTION("Driver for HP Smart Array Controllers"); |
62 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" | 62 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" |
63 | " SA6i P600 P800 P400 P400i E200 E200i E500"); | 63 | " SA6i P600 P800 P400 P400i E200 E200i E500 P700m" |
64 | MODULE_VERSION("3.6.14"); | 64 | " Smart Array G2 Series SAS/SATA Controllers"); |
65 | MODULE_VERSION("3.6.20"); | ||
65 | MODULE_LICENSE("GPL"); | 66 | MODULE_LICENSE("GPL"); |
66 | 67 | ||
67 | #include "cciss_cmd.h" | 68 | #include "cciss_cmd.h" |
@@ -90,6 +91,11 @@ static const struct pci_device_id cciss_pci_device_id[] = { | |||
90 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, | 91 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, |
91 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237}, | 92 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237}, |
92 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D}, | 93 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D}, |
94 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, | ||
95 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3243}, | ||
96 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, | ||
97 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, | ||
98 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, | ||
93 | {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 99 | {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
94 | PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, | 100 | PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, |
95 | {0,} | 101 | {0,} |
@@ -100,30 +106,34 @@ MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); | |||
100 | /* board_id = Subsystem Device ID & Vendor ID | 106 | /* board_id = Subsystem Device ID & Vendor ID |
101 | * product = Marketing Name for the board | 107 | * product = Marketing Name for the board |
102 | * access = Address of the struct of function pointers | 108 | * access = Address of the struct of function pointers |
103 | * nr_cmds = Number of commands supported by controller | ||
104 | */ | 109 | */ |
105 | static struct board_type products[] = { | 110 | static struct board_type products[] = { |
106 | {0x40700E11, "Smart Array 5300", &SA5_access, 512}, | 111 | {0x40700E11, "Smart Array 5300", &SA5_access}, |
107 | {0x40800E11, "Smart Array 5i", &SA5B_access, 512}, | 112 | {0x40800E11, "Smart Array 5i", &SA5B_access}, |
108 | {0x40820E11, "Smart Array 532", &SA5B_access, 512}, | 113 | {0x40820E11, "Smart Array 532", &SA5B_access}, |
109 | {0x40830E11, "Smart Array 5312", &SA5B_access, 512}, | 114 | {0x40830E11, "Smart Array 5312", &SA5B_access}, |
110 | {0x409A0E11, "Smart Array 641", &SA5_access, 512}, | 115 | {0x409A0E11, "Smart Array 641", &SA5_access}, |
111 | {0x409B0E11, "Smart Array 642", &SA5_access, 512}, | 116 | {0x409B0E11, "Smart Array 642", &SA5_access}, |
112 | {0x409C0E11, "Smart Array 6400", &SA5_access, 512}, | 117 | {0x409C0E11, "Smart Array 6400", &SA5_access}, |
113 | {0x409D0E11, "Smart Array 6400 EM", &SA5_access, 512}, | 118 | {0x409D0E11, "Smart Array 6400 EM", &SA5_access}, |
114 | {0x40910E11, "Smart Array 6i", &SA5_access, 512}, | 119 | {0x40910E11, "Smart Array 6i", &SA5_access}, |
115 | {0x3225103C, "Smart Array P600", &SA5_access, 512}, | 120 | {0x3225103C, "Smart Array P600", &SA5_access}, |
116 | {0x3223103C, "Smart Array P800", &SA5_access, 512}, | 121 | {0x3223103C, "Smart Array P800", &SA5_access}, |
117 | {0x3234103C, "Smart Array P400", &SA5_access, 512}, | 122 | {0x3234103C, "Smart Array P400", &SA5_access}, |
118 | {0x3235103C, "Smart Array P400i", &SA5_access, 512}, | 123 | {0x3235103C, "Smart Array P400i", &SA5_access}, |
119 | {0x3211103C, "Smart Array E200i", &SA5_access, 120}, | 124 | {0x3211103C, "Smart Array E200i", &SA5_access}, |
120 | {0x3212103C, "Smart Array E200", &SA5_access, 120}, | 125 | {0x3212103C, "Smart Array E200", &SA5_access}, |
121 | {0x3213103C, "Smart Array E200i", &SA5_access, 120}, | 126 | {0x3213103C, "Smart Array E200i", &SA5_access}, |
122 | {0x3214103C, "Smart Array E200i", &SA5_access, 120}, | 127 | {0x3214103C, "Smart Array E200i", &SA5_access}, |
123 | {0x3215103C, "Smart Array E200i", &SA5_access, 120}, | 128 | {0x3215103C, "Smart Array E200i", &SA5_access}, |
124 | {0x3237103C, "Smart Array E500", &SA5_access, 512}, | 129 | {0x3237103C, "Smart Array E500", &SA5_access}, |
125 | {0x323D103C, "Smart Array P700m", &SA5_access, 512}, | 130 | {0x323D103C, "Smart Array P700m", &SA5_access}, |
126 | {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120}, | 131 | {0x3241103C, "Smart Array P212", &SA5_access}, |
132 | {0x3243103C, "Smart Array P410", &SA5_access}, | ||
133 | {0x3245103C, "Smart Array P410i", &SA5_access}, | ||
134 | {0x3247103C, "Smart Array P411", &SA5_access}, | ||
135 | {0x3249103C, "Smart Array P812", &SA5_access}, | ||
136 | {0xFFFF103C, "Unknown Smart Array", &SA5_access}, | ||
127 | }; | 137 | }; |
128 | 138 | ||
129 | /* How long to wait (in milliseconds) for board to go into simple mode */ | 139 | /* How long to wait (in milliseconds) for board to go into simple mode */ |
@@ -3075,11 +3085,20 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | |||
3075 | print_cfg_table(c->cfgtable); | 3085 | print_cfg_table(c->cfgtable); |
3076 | #endif /* CCISS_DEBUG */ | 3086 | #endif /* CCISS_DEBUG */ |
3077 | 3087 | ||
3088 | /* Some controllers support Zero Memory Raid (ZMR). | ||
3089 | * When configured in ZMR mode the number of supported | ||
3090 | * commands drops to 64. So instead of just setting an | ||
3091 | * arbitrary value we make the driver a little smarter. | ||
3092 | * We read the config table to tell us how many commands | ||
3093 | * are supported on the controller then subtract 4 to | ||
3094 | * leave a little room for ioctl calls. | ||
3095 | */ | ||
3096 | c->max_commands = readl(&(c->cfgtable->CmdsOutMax)); | ||
3078 | for (i = 0; i < ARRAY_SIZE(products); i++) { | 3097 | for (i = 0; i < ARRAY_SIZE(products); i++) { |
3079 | if (board_id == products[i].board_id) { | 3098 | if (board_id == products[i].board_id) { |
3080 | c->product_name = products[i].product_name; | 3099 | c->product_name = products[i].product_name; |
3081 | c->access = *(products[i].access); | 3100 | c->access = *(products[i].access); |
3082 | c->nr_cmds = products[i].nr_cmds; | 3101 | c->nr_cmds = c->max_commands - 4; |
3083 | break; | 3102 | break; |
3084 | } | 3103 | } |
3085 | } | 3104 | } |
@@ -3099,7 +3118,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | |||
3099 | if (subsystem_vendor_id == PCI_VENDOR_ID_HP) { | 3118 | if (subsystem_vendor_id == PCI_VENDOR_ID_HP) { |
3100 | c->product_name = products[i-1].product_name; | 3119 | c->product_name = products[i-1].product_name; |
3101 | c->access = *(products[i-1].access); | 3120 | c->access = *(products[i-1].access); |
3102 | c->nr_cmds = products[i-1].nr_cmds; | 3121 | c->nr_cmds = c->max_commands - 4; |
3103 | printk(KERN_WARNING "cciss: This is an unknown " | 3122 | printk(KERN_WARNING "cciss: This is an unknown " |
3104 | "Smart Array controller.\n" | 3123 | "Smart Array controller.\n" |
3105 | "cciss: Please update to the latest driver " | 3124 | "cciss: Please update to the latest driver " |
@@ -3535,6 +3554,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3535 | for (j = 0; j <= hba[i]->highest_lun; j++) | 3554 | for (j = 0; j <= hba[i]->highest_lun; j++) |
3536 | add_disk(hba[i]->gendisk[j]); | 3555 | add_disk(hba[i]->gendisk[j]); |
3537 | 3556 | ||
3557 | /* we must register the controller even if no disks exist */ | ||
3558 | if (hba[i]->highest_lun == -1) | ||
3559 | add_disk(hba[i]->gendisk[0]); | ||
3560 | |||
3538 | return 1; | 3561 | return 1; |
3539 | 3562 | ||
3540 | clean4: | 3563 | clean4: |
diff --git a/drivers/block/hd.c b/drivers/block/hd.c new file mode 100644 index 000000000000..682243bf2e46 --- /dev/null +++ b/drivers/block/hd.c | |||
@@ -0,0 +1,814 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
3 | * | ||
4 | * This is the low-level hd interrupt support. It traverses the | ||
5 | * request-list, using interrupts to jump between functions. As | ||
6 | * all the functions are called within interrupts, we may not | ||
7 | * sleep. Special care is recommended. | ||
8 | * | ||
9 | * modified by Drew Eckhardt to check nr of hd's from the CMOS. | ||
10 | * | ||
11 | * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug | ||
12 | * in the early extended-partition checks and added DM partitions | ||
13 | * | ||
14 | * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", | ||
15 | * and general streamlining by Mark Lord. | ||
16 | * | ||
17 | * Removed 99% of above. Use Mark's ide driver for those options. | ||
18 | * This is now a lightweight ST-506 driver. (Paul Gortmaker) | ||
19 | * | ||
20 | * Modified 1995 Russell King for ARM processor. | ||
21 | * | ||
22 | * Bugfix: max_sectors must be <= 255 or the wheels tend to come | ||
23 | * off in a hurry once you queue things up - Paul G. 02/2001 | ||
24 | */ | ||
25 | |||
26 | /* Uncomment the following if you want verbose error reports. */ | ||
27 | /* #define VERBOSE_ERRORS */ | ||
28 | |||
29 | #include <linux/blkdev.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/signal.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/fs.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/genhd.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/string.h> | ||
39 | #include <linux/ioport.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/blkpg.h> | ||
42 | #include <linux/hdreg.h> | ||
43 | |||
44 | #define REALLY_SLOW_IO | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/io.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | |||
49 | #ifdef __arm__ | ||
50 | #undef HD_IRQ | ||
51 | #endif | ||
52 | #include <asm/irq.h> | ||
53 | #ifdef __arm__ | ||
54 | #define HD_IRQ IRQ_HARDDISK | ||
55 | #endif | ||
56 | |||
57 | /* Hd controller regster ports */ | ||
58 | |||
59 | #define HD_DATA 0x1f0 /* _CTL when writing */ | ||
60 | #define HD_ERROR 0x1f1 /* see err-bits */ | ||
61 | #define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */ | ||
62 | #define HD_SECTOR 0x1f3 /* starting sector */ | ||
63 | #define HD_LCYL 0x1f4 /* starting cylinder */ | ||
64 | #define HD_HCYL 0x1f5 /* high byte of starting cyl */ | ||
65 | #define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */ | ||
66 | #define HD_STATUS 0x1f7 /* see status-bits */ | ||
67 | #define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */ | ||
68 | #define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */ | ||
69 | #define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ | ||
70 | |||
71 | #define HD_CMD 0x3f6 /* used for resets */ | ||
72 | #define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */ | ||
73 | |||
74 | /* Bits of HD_STATUS */ | ||
75 | #define ERR_STAT 0x01 | ||
76 | #define INDEX_STAT 0x02 | ||
77 | #define ECC_STAT 0x04 /* Corrected error */ | ||
78 | #define DRQ_STAT 0x08 | ||
79 | #define SEEK_STAT 0x10 | ||
80 | #define SERVICE_STAT SEEK_STAT | ||
81 | #define WRERR_STAT 0x20 | ||
82 | #define READY_STAT 0x40 | ||
83 | #define BUSY_STAT 0x80 | ||
84 | |||
85 | /* Bits for HD_ERROR */ | ||
86 | #define MARK_ERR 0x01 /* Bad address mark */ | ||
87 | #define TRK0_ERR 0x02 /* couldn't find track 0 */ | ||
88 | #define ABRT_ERR 0x04 /* Command aborted */ | ||
89 | #define MCR_ERR 0x08 /* media change request */ | ||
90 | #define ID_ERR 0x10 /* ID field not found */ | ||
91 | #define MC_ERR 0x20 /* media changed */ | ||
92 | #define ECC_ERR 0x40 /* Uncorrectable ECC error */ | ||
93 | #define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ | ||
94 | #define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ | ||
95 | |||
96 | static DEFINE_SPINLOCK(hd_lock); | ||
97 | static struct request_queue *hd_queue; | ||
98 | |||
99 | #define MAJOR_NR HD_MAJOR | ||
100 | #define QUEUE (hd_queue) | ||
101 | #define CURRENT elv_next_request(hd_queue) | ||
102 | |||
103 | #define TIMEOUT_VALUE (6*HZ) | ||
104 | #define HD_DELAY 0 | ||
105 | |||
106 | #define MAX_ERRORS 16 /* Max read/write errors/sector */ | ||
107 | #define RESET_FREQ 8 /* Reset controller every 8th retry */ | ||
108 | #define RECAL_FREQ 4 /* Recalibrate every 4th retry */ | ||
109 | #define MAX_HD 2 | ||
110 | |||
111 | #define STAT_OK (READY_STAT|SEEK_STAT) | ||
112 | #define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) | ||
113 | |||
114 | static void recal_intr(void); | ||
115 | static void bad_rw_intr(void); | ||
116 | |||
117 | static int reset; | ||
118 | static int hd_error; | ||
119 | |||
120 | /* | ||
121 | * This struct defines the HD's and their types. | ||
122 | */ | ||
123 | struct hd_i_struct { | ||
124 | unsigned int head, sect, cyl, wpcom, lzone, ctl; | ||
125 | int unit; | ||
126 | int recalibrate; | ||
127 | int special_op; | ||
128 | }; | ||
129 | |||
130 | #ifdef HD_TYPE | ||
131 | static struct hd_i_struct hd_info[] = { HD_TYPE }; | ||
132 | static int NR_HD = ARRAY_SIZE(hd_info); | ||
133 | #else | ||
134 | static struct hd_i_struct hd_info[MAX_HD]; | ||
135 | static int NR_HD; | ||
136 | #endif | ||
137 | |||
138 | static struct gendisk *hd_gendisk[MAX_HD]; | ||
139 | |||
140 | static struct timer_list device_timer; | ||
141 | |||
142 | #define TIMEOUT_VALUE (6*HZ) | ||
143 | |||
144 | #define SET_TIMER \ | ||
145 | do { \ | ||
146 | mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ | ||
147 | } while (0) | ||
148 | |||
149 | static void (*do_hd)(void) = NULL; | ||
150 | #define SET_HANDLER(x) \ | ||
151 | if ((do_hd = (x)) != NULL) \ | ||
152 | SET_TIMER; \ | ||
153 | else \ | ||
154 | del_timer(&device_timer); | ||
155 | |||
156 | |||
157 | #if (HD_DELAY > 0) | ||
158 | |||
159 | #include <asm/i8253.h> | ||
160 | |||
161 | unsigned long last_req; | ||
162 | |||
163 | unsigned long read_timer(void) | ||
164 | { | ||
165 | unsigned long t, flags; | ||
166 | int i; | ||
167 | |||
168 | spin_lock_irqsave(&i8253_lock, flags); | ||
169 | t = jiffies * 11932; | ||
170 | outb_p(0, 0x43); | ||
171 | i = inb_p(0x40); | ||
172 | i |= inb(0x40) << 8; | ||
173 | spin_unlock_irqrestore(&i8253_lock, flags); | ||
174 | return(t - i); | ||
175 | } | ||
176 | #endif | ||
177 | |||
178 | static void __init hd_setup(char *str, int *ints) | ||
179 | { | ||
180 | int hdind = 0; | ||
181 | |||
182 | if (ints[0] != 3) | ||
183 | return; | ||
184 | if (hd_info[0].head != 0) | ||
185 | hdind = 1; | ||
186 | hd_info[hdind].head = ints[2]; | ||
187 | hd_info[hdind].sect = ints[3]; | ||
188 | hd_info[hdind].cyl = ints[1]; | ||
189 | hd_info[hdind].wpcom = 0; | ||
190 | hd_info[hdind].lzone = ints[1]; | ||
191 | hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); | ||
192 | NR_HD = hdind+1; | ||
193 | } | ||
194 | |||
195 | static void dump_status(const char *msg, unsigned int stat) | ||
196 | { | ||
197 | char *name = "hd?"; | ||
198 | if (CURRENT) | ||
199 | name = CURRENT->rq_disk->disk_name; | ||
200 | |||
201 | #ifdef VERBOSE_ERRORS | ||
202 | printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); | ||
203 | if (stat & BUSY_STAT) printk("Busy "); | ||
204 | if (stat & READY_STAT) printk("DriveReady "); | ||
205 | if (stat & WRERR_STAT) printk("WriteFault "); | ||
206 | if (stat & SEEK_STAT) printk("SeekComplete "); | ||
207 | if (stat & DRQ_STAT) printk("DataRequest "); | ||
208 | if (stat & ECC_STAT) printk("CorrectedError "); | ||
209 | if (stat & INDEX_STAT) printk("Index "); | ||
210 | if (stat & ERR_STAT) printk("Error "); | ||
211 | printk("}\n"); | ||
212 | if ((stat & ERR_STAT) == 0) { | ||
213 | hd_error = 0; | ||
214 | } else { | ||
215 | hd_error = inb(HD_ERROR); | ||
216 | printk("%s: %s: error=0x%02x { ", name, msg, hd_error & 0xff); | ||
217 | if (hd_error & BBD_ERR) printk("BadSector "); | ||
218 | if (hd_error & ECC_ERR) printk("UncorrectableError "); | ||
219 | if (hd_error & ID_ERR) printk("SectorIdNotFound "); | ||
220 | if (hd_error & ABRT_ERR) printk("DriveStatusError "); | ||
221 | if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); | ||
222 | if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); | ||
223 | printk("}"); | ||
224 | if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { | ||
225 | printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), | ||
226 | inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); | ||
227 | if (CURRENT) | ||
228 | printk(", sector=%ld", CURRENT->sector); | ||
229 | } | ||
230 | printk("\n"); | ||
231 | } | ||
232 | #else | ||
233 | printk("%s: %s: status=0x%02x.\n", name, msg, stat & 0xff); | ||
234 | if ((stat & ERR_STAT) == 0) { | ||
235 | hd_error = 0; | ||
236 | } else { | ||
237 | hd_error = inb(HD_ERROR); | ||
238 | printk("%s: %s: error=0x%02x.\n", name, msg, hd_error & 0xff); | ||
239 | } | ||
240 | #endif | ||
241 | } | ||
242 | |||
243 | static void check_status(void) | ||
244 | { | ||
245 | int i = inb_p(HD_STATUS); | ||
246 | |||
247 | if (!OK_STATUS(i)) { | ||
248 | dump_status("check_status", i); | ||
249 | bad_rw_intr(); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static int controller_busy(void) | ||
254 | { | ||
255 | int retries = 100000; | ||
256 | unsigned char status; | ||
257 | |||
258 | do { | ||
259 | status = inb_p(HD_STATUS); | ||
260 | } while ((status & BUSY_STAT) && --retries); | ||
261 | return status; | ||
262 | } | ||
263 | |||
264 | static int status_ok(void) | ||
265 | { | ||
266 | unsigned char status = inb_p(HD_STATUS); | ||
267 | |||
268 | if (status & BUSY_STAT) | ||
269 | return 1; /* Ancient, but does it make sense??? */ | ||
270 | if (status & WRERR_STAT) | ||
271 | return 0; | ||
272 | if (!(status & READY_STAT)) | ||
273 | return 0; | ||
274 | if (!(status & SEEK_STAT)) | ||
275 | return 0; | ||
276 | return 1; | ||
277 | } | ||
278 | |||
279 | static int controller_ready(unsigned int drive, unsigned int head) | ||
280 | { | ||
281 | int retry = 100; | ||
282 | |||
283 | do { | ||
284 | if (controller_busy() & BUSY_STAT) | ||
285 | return 0; | ||
286 | outb_p(0xA0 | (drive<<4) | head, HD_CURRENT); | ||
287 | if (status_ok()) | ||
288 | return 1; | ||
289 | } while (--retry); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static void hd_out(struct hd_i_struct *disk, | ||
294 | unsigned int nsect, | ||
295 | unsigned int sect, | ||
296 | unsigned int head, | ||
297 | unsigned int cyl, | ||
298 | unsigned int cmd, | ||
299 | void (*intr_addr)(void)) | ||
300 | { | ||
301 | unsigned short port; | ||
302 | |||
303 | #if (HD_DELAY > 0) | ||
304 | while (read_timer() - last_req < HD_DELAY) | ||
305 | /* nothing */; | ||
306 | #endif | ||
307 | if (reset) | ||
308 | return; | ||
309 | if (!controller_ready(disk->unit, head)) { | ||
310 | reset = 1; | ||
311 | return; | ||
312 | } | ||
313 | SET_HANDLER(intr_addr); | ||
314 | outb_p(disk->ctl, HD_CMD); | ||
315 | port = HD_DATA; | ||
316 | outb_p(disk->wpcom >> 2, ++port); | ||
317 | outb_p(nsect, ++port); | ||
318 | outb_p(sect, ++port); | ||
319 | outb_p(cyl, ++port); | ||
320 | outb_p(cyl >> 8, ++port); | ||
321 | outb_p(0xA0 | (disk->unit << 4) | head, ++port); | ||
322 | outb_p(cmd, ++port); | ||
323 | } | ||
324 | |||
325 | static void hd_request (void); | ||
326 | |||
327 | static int drive_busy(void) | ||
328 | { | ||
329 | unsigned int i; | ||
330 | unsigned char c; | ||
331 | |||
332 | for (i = 0; i < 500000 ; i++) { | ||
333 | c = inb_p(HD_STATUS); | ||
334 | if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) | ||
335 | return 0; | ||
336 | } | ||
337 | dump_status("reset timed out", c); | ||
338 | return 1; | ||
339 | } | ||
340 | |||
341 | static void reset_controller(void) | ||
342 | { | ||
343 | int i; | ||
344 | |||
345 | outb_p(4, HD_CMD); | ||
346 | for (i = 0; i < 1000; i++) barrier(); | ||
347 | outb_p(hd_info[0].ctl & 0x0f, HD_CMD); | ||
348 | for (i = 0; i < 1000; i++) barrier(); | ||
349 | if (drive_busy()) | ||
350 | printk("hd: controller still busy\n"); | ||
351 | else if ((hd_error = inb(HD_ERROR)) != 1) | ||
352 | printk("hd: controller reset failed: %02x\n", hd_error); | ||
353 | } | ||
354 | |||
355 | static void reset_hd(void) | ||
356 | { | ||
357 | static int i; | ||
358 | |||
359 | repeat: | ||
360 | if (reset) { | ||
361 | reset = 0; | ||
362 | i = -1; | ||
363 | reset_controller(); | ||
364 | } else { | ||
365 | check_status(); | ||
366 | if (reset) | ||
367 | goto repeat; | ||
368 | } | ||
369 | if (++i < NR_HD) { | ||
370 | struct hd_i_struct *disk = &hd_info[i]; | ||
371 | disk->special_op = disk->recalibrate = 1; | ||
372 | hd_out(disk, disk->sect, disk->sect, disk->head-1, | ||
373 | disk->cyl, WIN_SPECIFY, &reset_hd); | ||
374 | if (reset) | ||
375 | goto repeat; | ||
376 | } else | ||
377 | hd_request(); | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Ok, don't know what to do with the unexpected interrupts: on some machines | ||
382 | * doing a reset and a retry seems to result in an eternal loop. Right now I | ||
383 | * ignore it, and just set the timeout. | ||
384 | * | ||
385 | * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the | ||
386 | * drive enters "idle", "standby", or "sleep" mode, so if the status looks | ||
387 | * "good", we just ignore the interrupt completely. | ||
388 | */ | ||
389 | static void unexpected_hd_interrupt(void) | ||
390 | { | ||
391 | unsigned int stat = inb_p(HD_STATUS); | ||
392 | |||
393 | if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { | ||
394 | dump_status("unexpected interrupt", stat); | ||
395 | SET_TIMER; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | /* | ||
400 | * bad_rw_intr() now tries to be a bit smarter and does things | ||
401 | * according to the error returned by the controller. | ||
402 | * -Mika Liljeberg (liljeber@cs.Helsinki.FI) | ||
403 | */ | ||
404 | static void bad_rw_intr(void) | ||
405 | { | ||
406 | struct request *req = CURRENT; | ||
407 | if (req != NULL) { | ||
408 | struct hd_i_struct *disk = req->rq_disk->private_data; | ||
409 | if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { | ||
410 | end_request(req, 0); | ||
411 | disk->special_op = disk->recalibrate = 1; | ||
412 | } else if (req->errors % RESET_FREQ == 0) | ||
413 | reset = 1; | ||
414 | else if ((hd_error & TRK0_ERR) || req->errors % RECAL_FREQ == 0) | ||
415 | disk->special_op = disk->recalibrate = 1; | ||
416 | /* Otherwise just retry */ | ||
417 | } | ||
418 | } | ||
419 | |||
420 | static inline int wait_DRQ(void) | ||
421 | { | ||
422 | int retries; | ||
423 | int stat; | ||
424 | |||
425 | for (retries = 0; retries < 100000; retries++) { | ||
426 | stat = inb_p(HD_STATUS); | ||
427 | if (stat & DRQ_STAT) | ||
428 | return 0; | ||
429 | } | ||
430 | dump_status("wait_DRQ", stat); | ||
431 | return -1; | ||
432 | } | ||
433 | |||
434 | static void read_intr(void) | ||
435 | { | ||
436 | struct request *req; | ||
437 | int i, retries = 100000; | ||
438 | |||
439 | do { | ||
440 | i = (unsigned) inb_p(HD_STATUS); | ||
441 | if (i & BUSY_STAT) | ||
442 | continue; | ||
443 | if (!OK_STATUS(i)) | ||
444 | break; | ||
445 | if (i & DRQ_STAT) | ||
446 | goto ok_to_read; | ||
447 | } while (--retries > 0); | ||
448 | dump_status("read_intr", i); | ||
449 | bad_rw_intr(); | ||
450 | hd_request(); | ||
451 | return; | ||
452 | ok_to_read: | ||
453 | req = CURRENT; | ||
454 | insw(HD_DATA, req->buffer, 256); | ||
455 | req->sector++; | ||
456 | req->buffer += 512; | ||
457 | req->errors = 0; | ||
458 | i = --req->nr_sectors; | ||
459 | --req->current_nr_sectors; | ||
460 | #ifdef DEBUG | ||
461 | printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n", | ||
462 | req->rq_disk->disk_name, req->sector, req->nr_sectors, | ||
463 | req->buffer+512); | ||
464 | #endif | ||
465 | if (req->current_nr_sectors <= 0) | ||
466 | end_request(req, 1); | ||
467 | if (i > 0) { | ||
468 | SET_HANDLER(&read_intr); | ||
469 | return; | ||
470 | } | ||
471 | (void) inb_p(HD_STATUS); | ||
472 | #if (HD_DELAY > 0) | ||
473 | last_req = read_timer(); | ||
474 | #endif | ||
475 | if (elv_next_request(QUEUE)) | ||
476 | hd_request(); | ||
477 | return; | ||
478 | } | ||
479 | |||
480 | static void write_intr(void) | ||
481 | { | ||
482 | struct request *req = CURRENT; | ||
483 | int i; | ||
484 | int retries = 100000; | ||
485 | |||
486 | do { | ||
487 | i = (unsigned) inb_p(HD_STATUS); | ||
488 | if (i & BUSY_STAT) | ||
489 | continue; | ||
490 | if (!OK_STATUS(i)) | ||
491 | break; | ||
492 | if ((req->nr_sectors <= 1) || (i & DRQ_STAT)) | ||
493 | goto ok_to_write; | ||
494 | } while (--retries > 0); | ||
495 | dump_status("write_intr", i); | ||
496 | bad_rw_intr(); | ||
497 | hd_request(); | ||
498 | return; | ||
499 | ok_to_write: | ||
500 | req->sector++; | ||
501 | i = --req->nr_sectors; | ||
502 | --req->current_nr_sectors; | ||
503 | req->buffer += 512; | ||
504 | if (!i || (req->bio && req->current_nr_sectors <= 0)) | ||
505 | end_request(req, 1); | ||
506 | if (i > 0) { | ||
507 | SET_HANDLER(&write_intr); | ||
508 | outsw(HD_DATA, req->buffer, 256); | ||
509 | local_irq_enable(); | ||
510 | } else { | ||
511 | #if (HD_DELAY > 0) | ||
512 | last_req = read_timer(); | ||
513 | #endif | ||
514 | hd_request(); | ||
515 | } | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | static void recal_intr(void) | ||
520 | { | ||
521 | check_status(); | ||
522 | #if (HD_DELAY > 0) | ||
523 | last_req = read_timer(); | ||
524 | #endif | ||
525 | hd_request(); | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * This is another of the error-routines I don't know what to do with. The | ||
530 | * best idea seems to just set reset, and start all over again. | ||
531 | */ | ||
532 | static void hd_times_out(unsigned long dummy) | ||
533 | { | ||
534 | char *name; | ||
535 | |||
536 | do_hd = NULL; | ||
537 | |||
538 | if (!CURRENT) | ||
539 | return; | ||
540 | |||
541 | disable_irq(HD_IRQ); | ||
542 | local_irq_enable(); | ||
543 | reset = 1; | ||
544 | name = CURRENT->rq_disk->disk_name; | ||
545 | printk("%s: timeout\n", name); | ||
546 | if (++CURRENT->errors >= MAX_ERRORS) { | ||
547 | #ifdef DEBUG | ||
548 | printk("%s: too many errors\n", name); | ||
549 | #endif | ||
550 | end_request(CURRENT, 0); | ||
551 | } | ||
552 | local_irq_disable(); | ||
553 | hd_request(); | ||
554 | enable_irq(HD_IRQ); | ||
555 | } | ||
556 | |||
557 | static int do_special_op(struct hd_i_struct *disk, struct request *req) | ||
558 | { | ||
559 | if (disk->recalibrate) { | ||
560 | disk->recalibrate = 0; | ||
561 | hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr); | ||
562 | return reset; | ||
563 | } | ||
564 | if (disk->head > 16) { | ||
565 | printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); | ||
566 | end_request(req, 0); | ||
567 | } | ||
568 | disk->special_op = 0; | ||
569 | return 1; | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * The driver enables interrupts as much as possible. In order to do this, | ||
574 | * (a) the device-interrupt is disabled before entering hd_request(), | ||
575 | * and (b) the timeout-interrupt is disabled before the sti(). | ||
576 | * | ||
577 | * Interrupts are still masked (by default) whenever we are exchanging | ||
578 | * data/cmds with a drive, because some drives seem to have very poor | ||
579 | * tolerance for latency during I/O. The IDE driver has support to unmask | ||
580 | * interrupts for non-broken hardware, so use that driver if required. | ||
581 | */ | ||
582 | static void hd_request(void) | ||
583 | { | ||
584 | unsigned int block, nsect, sec, track, head, cyl; | ||
585 | struct hd_i_struct *disk; | ||
586 | struct request *req; | ||
587 | |||
588 | if (do_hd) | ||
589 | return; | ||
590 | repeat: | ||
591 | del_timer(&device_timer); | ||
592 | local_irq_enable(); | ||
593 | |||
594 | req = CURRENT; | ||
595 | if (!req) { | ||
596 | do_hd = NULL; | ||
597 | return; | ||
598 | } | ||
599 | |||
600 | if (reset) { | ||
601 | local_irq_disable(); | ||
602 | reset_hd(); | ||
603 | return; | ||
604 | } | ||
605 | disk = req->rq_disk->private_data; | ||
606 | block = req->sector; | ||
607 | nsect = req->nr_sectors; | ||
608 | if (block >= get_capacity(req->rq_disk) || | ||
609 | ((block+nsect) > get_capacity(req->rq_disk))) { | ||
610 | printk("%s: bad access: block=%d, count=%d\n", | ||
611 | req->rq_disk->disk_name, block, nsect); | ||
612 | end_request(req, 0); | ||
613 | goto repeat; | ||
614 | } | ||
615 | |||
616 | if (disk->special_op) { | ||
617 | if (do_special_op(disk, req)) | ||
618 | goto repeat; | ||
619 | return; | ||
620 | } | ||
621 | sec = block % disk->sect + 1; | ||
622 | track = block / disk->sect; | ||
623 | head = track % disk->head; | ||
624 | cyl = track / disk->head; | ||
625 | #ifdef DEBUG | ||
626 | printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n", | ||
627 | req->rq_disk->disk_name, | ||
628 | req_data_dir(req) == READ ? "read" : "writ", | ||
629 | cyl, head, sec, nsect, req->buffer); | ||
630 | #endif | ||
631 | if (blk_fs_request(req)) { | ||
632 | switch (rq_data_dir(req)) { | ||
633 | case READ: | ||
634 | hd_out(disk, nsect, sec, head, cyl, WIN_READ, | ||
635 | &read_intr); | ||
636 | if (reset) | ||
637 | goto repeat; | ||
638 | break; | ||
639 | case WRITE: | ||
640 | hd_out(disk, nsect, sec, head, cyl, WIN_WRITE, | ||
641 | &write_intr); | ||
642 | if (reset) | ||
643 | goto repeat; | ||
644 | if (wait_DRQ()) { | ||
645 | bad_rw_intr(); | ||
646 | goto repeat; | ||
647 | } | ||
648 | outsw(HD_DATA, req->buffer, 256); | ||
649 | break; | ||
650 | default: | ||
651 | printk("unknown hd-command\n"); | ||
652 | end_request(req, 0); | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | } | ||
657 | |||
658 | static void do_hd_request(struct request_queue *q) | ||
659 | { | ||
660 | disable_irq(HD_IRQ); | ||
661 | hd_request(); | ||
662 | enable_irq(HD_IRQ); | ||
663 | } | ||
664 | |||
665 | static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
666 | { | ||
667 | struct hd_i_struct *disk = bdev->bd_disk->private_data; | ||
668 | |||
669 | geo->heads = disk->head; | ||
670 | geo->sectors = disk->sect; | ||
671 | geo->cylinders = disk->cyl; | ||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Releasing a block device means we sync() it, so that it can safely | ||
677 | * be forgotten about... | ||
678 | */ | ||
679 | |||
680 | static irqreturn_t hd_interrupt(int irq, void *dev_id) | ||
681 | { | ||
682 | void (*handler)(void) = do_hd; | ||
683 | |||
684 | do_hd = NULL; | ||
685 | del_timer(&device_timer); | ||
686 | if (!handler) | ||
687 | handler = unexpected_hd_interrupt; | ||
688 | handler(); | ||
689 | local_irq_enable(); | ||
690 | return IRQ_HANDLED; | ||
691 | } | ||
692 | |||
693 | static struct block_device_operations hd_fops = { | ||
694 | .getgeo = hd_getgeo, | ||
695 | }; | ||
696 | |||
697 | /* | ||
698 | * This is the hard disk IRQ description. The IRQF_DISABLED in sa_flags | ||
699 | * means we run the IRQ-handler with interrupts disabled: this is bad for | ||
700 | * interrupt latency, but anything else has led to problems on some | ||
701 | * machines. | ||
702 | * | ||
703 | * We enable interrupts in some of the routines after making sure it's | ||
704 | * safe. | ||
705 | */ | ||
706 | |||
707 | static int __init hd_init(void) | ||
708 | { | ||
709 | int drive; | ||
710 | |||
711 | if (register_blkdev(MAJOR_NR, "hd")) | ||
712 | return -1; | ||
713 | |||
714 | hd_queue = blk_init_queue(do_hd_request, &hd_lock); | ||
715 | if (!hd_queue) { | ||
716 | unregister_blkdev(MAJOR_NR, "hd"); | ||
717 | return -ENOMEM; | ||
718 | } | ||
719 | |||
720 | blk_queue_max_sectors(hd_queue, 255); | ||
721 | init_timer(&device_timer); | ||
722 | device_timer.function = hd_times_out; | ||
723 | blk_queue_hardsect_size(hd_queue, 512); | ||
724 | |||
725 | if (!NR_HD) { | ||
726 | /* | ||
727 | * We don't know anything about the drive. This means | ||
728 | * that you *MUST* specify the drive parameters to the | ||
729 | * kernel yourself. | ||
730 | * | ||
731 | * If we were on an i386, we used to read this info from | ||
732 | * the BIOS or CMOS. This doesn't work all that well, | ||
733 | * since this assumes that this is a primary or secondary | ||
734 | * drive, and if we're using this legacy driver, it's | ||
735 | * probably an auxilliary controller added to recover | ||
736 | * legacy data off an ST-506 drive. Either way, it's | ||
737 | * definitely safest to have the user explicitly specify | ||
738 | * the information. | ||
739 | */ | ||
740 | printk("hd: no drives specified - use hd=cyl,head,sectors" | ||
741 | " on kernel command line\n"); | ||
742 | goto out; | ||
743 | } | ||
744 | |||
745 | for (drive = 0 ; drive < NR_HD ; drive++) { | ||
746 | struct gendisk *disk = alloc_disk(64); | ||
747 | struct hd_i_struct *p = &hd_info[drive]; | ||
748 | if (!disk) | ||
749 | goto Enomem; | ||
750 | disk->major = MAJOR_NR; | ||
751 | disk->first_minor = drive << 6; | ||
752 | disk->fops = &hd_fops; | ||
753 | sprintf(disk->disk_name, "hd%c", 'a'+drive); | ||
754 | disk->private_data = p; | ||
755 | set_capacity(disk, p->head * p->sect * p->cyl); | ||
756 | disk->queue = hd_queue; | ||
757 | p->unit = drive; | ||
758 | hd_gendisk[drive] = disk; | ||
759 | printk("%s: %luMB, CHS=%d/%d/%d\n", | ||
760 | disk->disk_name, (unsigned long)get_capacity(disk)/2048, | ||
761 | p->cyl, p->head, p->sect); | ||
762 | } | ||
763 | |||
764 | if (request_irq(HD_IRQ, hd_interrupt, IRQF_DISABLED, "hd", NULL)) { | ||
765 | printk("hd: unable to get IRQ%d for the hard disk driver\n", | ||
766 | HD_IRQ); | ||
767 | goto out1; | ||
768 | } | ||
769 | if (!request_region(HD_DATA, 8, "hd")) { | ||
770 | printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); | ||
771 | goto out2; | ||
772 | } | ||
773 | if (!request_region(HD_CMD, 1, "hd(cmd)")) { | ||
774 | printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); | ||
775 | goto out3; | ||
776 | } | ||
777 | |||
778 | /* Let them fly */ | ||
779 | for (drive = 0; drive < NR_HD; drive++) | ||
780 | add_disk(hd_gendisk[drive]); | ||
781 | |||
782 | return 0; | ||
783 | |||
784 | out3: | ||
785 | release_region(HD_DATA, 8); | ||
786 | out2: | ||
787 | free_irq(HD_IRQ, NULL); | ||
788 | out1: | ||
789 | for (drive = 0; drive < NR_HD; drive++) | ||
790 | put_disk(hd_gendisk[drive]); | ||
791 | NR_HD = 0; | ||
792 | out: | ||
793 | del_timer(&device_timer); | ||
794 | unregister_blkdev(MAJOR_NR, "hd"); | ||
795 | blk_cleanup_queue(hd_queue); | ||
796 | return -1; | ||
797 | Enomem: | ||
798 | while (drive--) | ||
799 | put_disk(hd_gendisk[drive]); | ||
800 | goto out; | ||
801 | } | ||
802 | |||
803 | static int __init parse_hd_setup(char *line) | ||
804 | { | ||
805 | int ints[6]; | ||
806 | |||
807 | (void) get_options(line, ARRAY_SIZE(ints), ints); | ||
808 | hd_setup(NULL, ints); | ||
809 | |||
810 | return 1; | ||
811 | } | ||
812 | __setup("hd=", parse_hd_setup); | ||
813 | |||
814 | late_initcall(hd_init); | ||
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 570f3b70dce7..5fdfa7c888ce 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c | |||
@@ -712,19 +712,17 @@ static void do_pd_request(struct request_queue * q) | |||
712 | static int pd_special_command(struct pd_unit *disk, | 712 | static int pd_special_command(struct pd_unit *disk, |
713 | enum action (*func)(struct pd_unit *disk)) | 713 | enum action (*func)(struct pd_unit *disk)) |
714 | { | 714 | { |
715 | DECLARE_COMPLETION_ONSTACK(wait); | 715 | struct request *rq; |
716 | struct request rq; | ||
717 | int err = 0; | 716 | int err = 0; |
718 | 717 | ||
719 | blk_rq_init(NULL, &rq); | 718 | rq = blk_get_request(disk->gd->queue, READ, __GFP_WAIT); |
720 | rq.rq_disk = disk->gd; | 719 | |
721 | rq.end_io_data = &wait; | 720 | rq->cmd_type = REQ_TYPE_SPECIAL; |
722 | rq.end_io = blk_end_sync_rq; | 721 | rq->special = func; |
723 | blk_insert_request(disk->gd->queue, &rq, 0, func); | 722 | |
724 | wait_for_completion(&wait); | 723 | err = blk_execute_rq(disk->gd->queue, disk->gd, rq, 0); |
725 | if (rq.errors) | 724 | |
726 | err = -EIO; | 725 | blk_put_request(rq); |
727 | blk_put_request(&rq); | ||
728 | return err; | 726 | return err; |
729 | } | 727 | } |
730 | 728 | ||
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index ab86e23ddc69..9d92636350e5 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c | |||
@@ -162,6 +162,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; | |||
162 | #include <linux/pg.h> | 162 | #include <linux/pg.h> |
163 | #include <linux/device.h> | 163 | #include <linux/device.h> |
164 | #include <linux/sched.h> /* current, TASK_* */ | 164 | #include <linux/sched.h> /* current, TASK_* */ |
165 | #include <linux/smp_lock.h> | ||
165 | #include <linux/jiffies.h> | 166 | #include <linux/jiffies.h> |
166 | 167 | ||
167 | #include <asm/uaccess.h> | 168 | #include <asm/uaccess.h> |
@@ -515,12 +516,18 @@ static int pg_open(struct inode *inode, struct file *file) | |||
515 | { | 516 | { |
516 | int unit = iminor(inode) & 0x7f; | 517 | int unit = iminor(inode) & 0x7f; |
517 | struct pg *dev = &devices[unit]; | 518 | struct pg *dev = &devices[unit]; |
519 | int ret = 0; | ||
518 | 520 | ||
519 | if ((unit >= PG_UNITS) || (!dev->present)) | 521 | lock_kernel(); |
520 | return -ENODEV; | 522 | if ((unit >= PG_UNITS) || (!dev->present)) { |
523 | ret = -ENODEV; | ||
524 | goto out; | ||
525 | } | ||
521 | 526 | ||
522 | if (test_and_set_bit(0, &dev->access)) | 527 | if (test_and_set_bit(0, &dev->access)) { |
523 | return -EBUSY; | 528 | ret = -EBUSY; |
529 | goto out; | ||
530 | } | ||
524 | 531 | ||
525 | if (dev->busy) { | 532 | if (dev->busy) { |
526 | pg_reset(dev); | 533 | pg_reset(dev); |
@@ -533,12 +540,15 @@ static int pg_open(struct inode *inode, struct file *file) | |||
533 | if (dev->bufptr == NULL) { | 540 | if (dev->bufptr == NULL) { |
534 | clear_bit(0, &dev->access); | 541 | clear_bit(0, &dev->access); |
535 | printk("%s: buffer allocation failed\n", dev->name); | 542 | printk("%s: buffer allocation failed\n", dev->name); |
536 | return -ENOMEM; | 543 | ret = -ENOMEM; |
544 | goto out; | ||
537 | } | 545 | } |
538 | 546 | ||
539 | file->private_data = dev; | 547 | file->private_data = dev; |
540 | 548 | ||
541 | return 0; | 549 | out: |
550 | unlock_kernel(); | ||
551 | return ret; | ||
542 | } | 552 | } |
543 | 553 | ||
544 | static int pg_release(struct inode *inode, struct file *file) | 554 | static int pg_release(struct inode *inode, struct file *file) |
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 8b9549ab4a4e..5c74c3574a5a 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c | |||
@@ -146,6 +146,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; | |||
146 | #include <linux/mtio.h> | 146 | #include <linux/mtio.h> |
147 | #include <linux/device.h> | 147 | #include <linux/device.h> |
148 | #include <linux/sched.h> /* current, TASK_*, schedule_timeout() */ | 148 | #include <linux/sched.h> /* current, TASK_*, schedule_timeout() */ |
149 | #include <linux/smp_lock.h> | ||
149 | 150 | ||
150 | #include <asm/uaccess.h> | 151 | #include <asm/uaccess.h> |
151 | 152 | ||
@@ -189,8 +190,7 @@ module_param_array(drive3, int, NULL, 0); | |||
189 | #define ATAPI_LOG_SENSE 0x4d | 190 | #define ATAPI_LOG_SENSE 0x4d |
190 | 191 | ||
191 | static int pt_open(struct inode *inode, struct file *file); | 192 | static int pt_open(struct inode *inode, struct file *file); |
192 | static int pt_ioctl(struct inode *inode, struct file *file, | 193 | static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
193 | unsigned int cmd, unsigned long arg); | ||
194 | static int pt_release(struct inode *inode, struct file *file); | 194 | static int pt_release(struct inode *inode, struct file *file); |
195 | static ssize_t pt_read(struct file *filp, char __user *buf, | 195 | static ssize_t pt_read(struct file *filp, char __user *buf, |
196 | size_t count, loff_t * ppos); | 196 | size_t count, loff_t * ppos); |
@@ -236,7 +236,7 @@ static const struct file_operations pt_fops = { | |||
236 | .owner = THIS_MODULE, | 236 | .owner = THIS_MODULE, |
237 | .read = pt_read, | 237 | .read = pt_read, |
238 | .write = pt_write, | 238 | .write = pt_write, |
239 | .ioctl = pt_ioctl, | 239 | .unlocked_ioctl = pt_ioctl, |
240 | .open = pt_open, | 240 | .open = pt_open, |
241 | .release = pt_release, | 241 | .release = pt_release, |
242 | }; | 242 | }; |
@@ -650,8 +650,11 @@ static int pt_open(struct inode *inode, struct file *file) | |||
650 | struct pt_unit *tape = pt + unit; | 650 | struct pt_unit *tape = pt + unit; |
651 | int err; | 651 | int err; |
652 | 652 | ||
653 | if (unit >= PT_UNITS || (!tape->present)) | 653 | lock_kernel(); |
654 | if (unit >= PT_UNITS || (!tape->present)) { | ||
655 | unlock_kernel(); | ||
654 | return -ENODEV; | 656 | return -ENODEV; |
657 | } | ||
655 | 658 | ||
656 | err = -EBUSY; | 659 | err = -EBUSY; |
657 | if (!atomic_dec_and_test(&tape->available)) | 660 | if (!atomic_dec_and_test(&tape->available)) |
@@ -678,15 +681,16 @@ static int pt_open(struct inode *inode, struct file *file) | |||
678 | } | 681 | } |
679 | 682 | ||
680 | file->private_data = tape; | 683 | file->private_data = tape; |
684 | unlock_kernel(); | ||
681 | return 0; | 685 | return 0; |
682 | 686 | ||
683 | out: | 687 | out: |
684 | atomic_inc(&tape->available); | 688 | atomic_inc(&tape->available); |
689 | unlock_kernel(); | ||
685 | return err; | 690 | return err; |
686 | } | 691 | } |
687 | 692 | ||
688 | static int pt_ioctl(struct inode *inode, struct file *file, | 693 | static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
689 | unsigned int cmd, unsigned long arg) | ||
690 | { | 694 | { |
691 | struct pt_unit *tape = file->private_data; | 695 | struct pt_unit *tape = file->private_data; |
692 | struct mtop __user *p = (void __user *)arg; | 696 | struct mtop __user *p = (void __user *)arg; |
@@ -700,23 +704,26 @@ static int pt_ioctl(struct inode *inode, struct file *file, | |||
700 | switch (mtop.mt_op) { | 704 | switch (mtop.mt_op) { |
701 | 705 | ||
702 | case MTREW: | 706 | case MTREW: |
707 | lock_kernel(); | ||
703 | pt_rewind(tape); | 708 | pt_rewind(tape); |
709 | unlock_kernel(); | ||
704 | return 0; | 710 | return 0; |
705 | 711 | ||
706 | case MTWEOF: | 712 | case MTWEOF: |
713 | lock_kernel(); | ||
707 | pt_write_fm(tape); | 714 | pt_write_fm(tape); |
715 | unlock_kernel(); | ||
708 | return 0; | 716 | return 0; |
709 | 717 | ||
710 | default: | 718 | default: |
711 | printk("%s: Unimplemented mt_op %d\n", tape->name, | 719 | /* FIXME: rate limit ?? */ |
720 | printk(KERN_DEBUG "%s: Unimplemented mt_op %d\n", tape->name, | ||
712 | mtop.mt_op); | 721 | mtop.mt_op); |
713 | return -EINVAL; | 722 | return -EINVAL; |
714 | } | 723 | } |
715 | 724 | ||
716 | default: | 725 | default: |
717 | printk("%s: Unimplemented ioctl 0x%x\n", tape->name, cmd); | 726 | return -ENOTTY; |
718 | return -EINVAL; | ||
719 | |||
720 | } | 727 | } |
721 | } | 728 | } |
722 | 729 | ||
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 3ba1df93e9e3..45bee918c46a 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/types.h> | 49 | #include <linux/types.h> |
50 | #include <linux/kernel.h> | 50 | #include <linux/kernel.h> |
51 | #include <linux/kthread.h> | 51 | #include <linux/kthread.h> |
52 | #include <linux/smp_lock.h> | ||
52 | #include <linux/errno.h> | 53 | #include <linux/errno.h> |
53 | #include <linux/spinlock.h> | 54 | #include <linux/spinlock.h> |
54 | #include <linux/file.h> | 55 | #include <linux/file.h> |
@@ -2079,7 +2080,6 @@ static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd, | |||
2079 | unsigned char buf[64]; | 2080 | unsigned char buf[64]; |
2080 | int ret; | 2081 | int ret; |
2081 | 2082 | ||
2082 | memset(buf, 0, sizeof(buf)); | ||
2083 | init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); | 2083 | init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); |
2084 | cgc.sense = &sense; | 2084 | cgc.sense = &sense; |
2085 | cgc.buflen = pd->mode_offset + 12; | 2085 | cgc.buflen = pd->mode_offset + 12; |
@@ -2126,7 +2126,6 @@ static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd, | |||
2126 | unsigned char *cap_buf; | 2126 | unsigned char *cap_buf; |
2127 | int ret, offset; | 2127 | int ret, offset; |
2128 | 2128 | ||
2129 | memset(buf, 0, sizeof(buf)); | ||
2130 | cap_buf = &buf[sizeof(struct mode_page_header) + pd->mode_offset]; | 2129 | cap_buf = &buf[sizeof(struct mode_page_header) + pd->mode_offset]; |
2131 | init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_UNKNOWN); | 2130 | init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_UNKNOWN); |
2132 | cgc.sense = &sense; | 2131 | cgc.sense = &sense; |
@@ -2633,11 +2632,12 @@ end_io: | |||
2633 | 2632 | ||
2634 | 2633 | ||
2635 | 2634 | ||
2636 | static int pkt_merge_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *bvec) | 2635 | static int pkt_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd, |
2636 | struct bio_vec *bvec) | ||
2637 | { | 2637 | { |
2638 | struct pktcdvd_device *pd = q->queuedata; | 2638 | struct pktcdvd_device *pd = q->queuedata; |
2639 | sector_t zone = ZONE(bio->bi_sector, pd); | 2639 | sector_t zone = ZONE(bmd->bi_sector, pd); |
2640 | int used = ((bio->bi_sector - zone) << 9) + bio->bi_size; | 2640 | int used = ((bmd->bi_sector - zone) << 9) + bmd->bi_size; |
2641 | int remaining = (pd->settings.size << 9) - used; | 2641 | int remaining = (pd->settings.size << 9) - used; |
2642 | int remaining2; | 2642 | int remaining2; |
2643 | 2643 | ||
@@ -2645,7 +2645,7 @@ static int pkt_merge_bvec(struct request_queue *q, struct bio *bio, struct bio_v | |||
2645 | * A bio <= PAGE_SIZE must be allowed. If it crosses a packet | 2645 | * A bio <= PAGE_SIZE must be allowed. If it crosses a packet |
2646 | * boundary, pkt_make_request() will split the bio. | 2646 | * boundary, pkt_make_request() will split the bio. |
2647 | */ | 2647 | */ |
2648 | remaining2 = PAGE_SIZE - bio->bi_size; | 2648 | remaining2 = PAGE_SIZE - bmd->bi_size; |
2649 | remaining = max(remaining, remaining2); | 2649 | remaining = max(remaining, remaining2); |
2650 | 2650 | ||
2651 | BUG_ON(remaining < 0); | 2651 | BUG_ON(remaining < 0); |
@@ -2796,9 +2796,14 @@ out_mem: | |||
2796 | return ret; | 2796 | return ret; |
2797 | } | 2797 | } |
2798 | 2798 | ||
2799 | static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 2799 | static long pkt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
2800 | { | 2800 | { |
2801 | struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data; | 2801 | struct inode *inode = file->f_path.dentry->d_inode; |
2802 | struct pktcdvd_device *pd; | ||
2803 | long ret; | ||
2804 | |||
2805 | lock_kernel(); | ||
2806 | pd = inode->i_bdev->bd_disk->private_data; | ||
2802 | 2807 | ||
2803 | VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode)); | 2808 | VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode)); |
2804 | 2809 | ||
@@ -2811,7 +2816,8 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u | |||
2811 | case CDROM_LAST_WRITTEN: | 2816 | case CDROM_LAST_WRITTEN: |
2812 | case CDROM_SEND_PACKET: | 2817 | case CDROM_SEND_PACKET: |
2813 | case SCSI_IOCTL_SEND_COMMAND: | 2818 | case SCSI_IOCTL_SEND_COMMAND: |
2814 | return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); | 2819 | ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); |
2820 | break; | ||
2815 | 2821 | ||
2816 | case CDROMEJECT: | 2822 | case CDROMEJECT: |
2817 | /* | 2823 | /* |
@@ -2820,14 +2826,15 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u | |||
2820 | */ | 2826 | */ |
2821 | if (pd->refcnt == 1) | 2827 | if (pd->refcnt == 1) |
2822 | pkt_lock_door(pd, 0); | 2828 | pkt_lock_door(pd, 0); |
2823 | return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); | 2829 | ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); |
2830 | break; | ||
2824 | 2831 | ||
2825 | default: | 2832 | default: |
2826 | VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd); | 2833 | VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd); |
2827 | return -ENOTTY; | 2834 | ret = -ENOTTY; |
2828 | } | 2835 | } |
2829 | 2836 | unlock_kernel(); | |
2830 | return 0; | 2837 | return ret; |
2831 | } | 2838 | } |
2832 | 2839 | ||
2833 | static int pkt_media_changed(struct gendisk *disk) | 2840 | static int pkt_media_changed(struct gendisk *disk) |
@@ -2849,7 +2856,7 @@ static struct block_device_operations pktcdvd_ops = { | |||
2849 | .owner = THIS_MODULE, | 2856 | .owner = THIS_MODULE, |
2850 | .open = pkt_open, | 2857 | .open = pkt_open, |
2851 | .release = pkt_close, | 2858 | .release = pkt_close, |
2852 | .ioctl = pkt_ioctl, | 2859 | .unlocked_ioctl = pkt_ioctl, |
2853 | .media_changed = pkt_media_changed, | 2860 | .media_changed = pkt_media_changed, |
2854 | }; | 2861 | }; |
2855 | 2862 | ||
@@ -3014,7 +3021,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) | |||
3014 | mutex_unlock(&ctl_mutex); | 3021 | mutex_unlock(&ctl_mutex); |
3015 | } | 3022 | } |
3016 | 3023 | ||
3017 | static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 3024 | static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, |
3025 | unsigned long arg) | ||
3018 | { | 3026 | { |
3019 | void __user *argp = (void __user *)arg; | 3027 | void __user *argp = (void __user *)arg; |
3020 | struct pkt_ctrl_command ctrl_cmd; | 3028 | struct pkt_ctrl_command ctrl_cmd; |
@@ -3031,16 +3039,22 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm | |||
3031 | case PKT_CTRL_CMD_SETUP: | 3039 | case PKT_CTRL_CMD_SETUP: |
3032 | if (!capable(CAP_SYS_ADMIN)) | 3040 | if (!capable(CAP_SYS_ADMIN)) |
3033 | return -EPERM; | 3041 | return -EPERM; |
3042 | lock_kernel(); | ||
3034 | ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); | 3043 | ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); |
3035 | ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); | 3044 | ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); |
3045 | unlock_kernel(); | ||
3036 | break; | 3046 | break; |
3037 | case PKT_CTRL_CMD_TEARDOWN: | 3047 | case PKT_CTRL_CMD_TEARDOWN: |
3038 | if (!capable(CAP_SYS_ADMIN)) | 3048 | if (!capable(CAP_SYS_ADMIN)) |
3039 | return -EPERM; | 3049 | return -EPERM; |
3050 | lock_kernel(); | ||
3040 | ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); | 3051 | ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); |
3052 | unlock_kernel(); | ||
3041 | break; | 3053 | break; |
3042 | case PKT_CTRL_CMD_STATUS: | 3054 | case PKT_CTRL_CMD_STATUS: |
3055 | lock_kernel(); | ||
3043 | pkt_get_status(&ctrl_cmd); | 3056 | pkt_get_status(&ctrl_cmd); |
3057 | unlock_kernel(); | ||
3044 | break; | 3058 | break; |
3045 | default: | 3059 | default: |
3046 | return -ENOTTY; | 3060 | return -ENOTTY; |
@@ -3053,7 +3067,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm | |||
3053 | 3067 | ||
3054 | 3068 | ||
3055 | static const struct file_operations pkt_ctl_fops = { | 3069 | static const struct file_operations pkt_ctl_fops = { |
3056 | .ioctl = pkt_ctl_ioctl, | 3070 | .unlocked_ioctl = pkt_ctl_ioctl, |
3057 | .owner = THIS_MODULE, | 3071 | .owner = THIS_MODULE, |
3058 | }; | 3072 | }; |
3059 | 3073 | ||
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index ebfe038d859e..f1c8feb5510b 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Authors: Dave Boutcher <boutcher@us.ibm.com> | 3 | * Authors: Dave Boutcher <boutcher@us.ibm.com> |
4 | * Ryan Arnold <ryanarn@us.ibm.com> | 4 | * Ryan Arnold <ryanarn@us.ibm.com> |
5 | * Colin Devilbiss <devilbis@us.ibm.com> | 5 | * Colin Devilbiss <devilbis@us.ibm.com> |
6 | * Stephen Rothwell <sfr@au1.ibm.com> | 6 | * Stephen Rothwell |
7 | * | 7 | * |
8 | * (C) Copyright 2000-2004 IBM Corporation | 8 | * (C) Copyright 2000-2004 IBM Corporation |
9 | * | 9 | * |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 84e064ffee52..dd7ea203f940 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -260,6 +260,10 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
260 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | 260 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) |
261 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 261 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
262 | 262 | ||
263 | /* If disk is read-only in the host, the guest should obey */ | ||
264 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) | ||
265 | set_disk_ro(vblk->disk, 1); | ||
266 | |||
263 | /* Host must always specify the capacity. */ | 267 | /* Host must always specify the capacity. */ |
264 | vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), | 268 | vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), |
265 | &cap, sizeof(cap)); | 269 | &cap, sizeof(cap)); |
@@ -311,6 +315,7 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
311 | /* Stop all the virtqueues. */ | 315 | /* Stop all the virtqueues. */ |
312 | vdev->config->reset(vdev); | 316 | vdev->config->reset(vdev); |
313 | 317 | ||
318 | del_gendisk(vblk->disk); | ||
314 | blk_cleanup_queue(vblk->disk->queue); | 319 | blk_cleanup_queue(vblk->disk->queue); |
315 | put_disk(vblk->disk); | 320 | put_disk(vblk->disk); |
316 | mempool_destroy(vblk->pool); | 321 | mempool_destroy(vblk->pool); |
@@ -325,7 +330,7 @@ static struct virtio_device_id id_table[] = { | |||
325 | 330 | ||
326 | static unsigned int features[] = { | 331 | static unsigned int features[] = { |
327 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 332 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
328 | VIRTIO_BLK_F_GEOMETRY, | 333 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, |
329 | }; | 334 | }; |
330 | 335 | ||
331 | static struct virtio_driver virtio_blk = { | 336 | static struct virtio_driver virtio_blk = { |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index f2fff5799ddf..9ae05c584234 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
39 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
40 | #include <linux/hdreg.h> | 40 | #include <linux/hdreg.h> |
41 | #include <linux/cdrom.h> | ||
41 | #include <linux/module.h> | 42 | #include <linux/module.h> |
42 | 43 | ||
43 | #include <xen/xenbus.h> | 44 | #include <xen/xenbus.h> |
@@ -153,6 +154,40 @@ static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg) | |||
153 | return 0; | 154 | return 0; |
154 | } | 155 | } |
155 | 156 | ||
157 | int blkif_ioctl(struct inode *inode, struct file *filep, | ||
158 | unsigned command, unsigned long argument) | ||
159 | { | ||
160 | struct blkfront_info *info = | ||
161 | inode->i_bdev->bd_disk->private_data; | ||
162 | int i; | ||
163 | |||
164 | dev_dbg(&info->xbdev->dev, "command: 0x%x, argument: 0x%lx\n", | ||
165 | command, (long)argument); | ||
166 | |||
167 | switch (command) { | ||
168 | case CDROMMULTISESSION: | ||
169 | dev_dbg(&info->xbdev->dev, "FIXME: support multisession CDs later\n"); | ||
170 | for (i = 0; i < sizeof(struct cdrom_multisession); i++) | ||
171 | if (put_user(0, (char __user *)(argument + i))) | ||
172 | return -EFAULT; | ||
173 | return 0; | ||
174 | |||
175 | case CDROM_GET_CAPABILITY: { | ||
176 | struct gendisk *gd = info->gd; | ||
177 | if (gd->flags & GENHD_FL_CD) | ||
178 | return 0; | ||
179 | return -EINVAL; | ||
180 | } | ||
181 | |||
182 | default: | ||
183 | /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", | ||
184 | command);*/ | ||
185 | return -EINVAL; /* same return as native Linux */ | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
156 | /* | 191 | /* |
157 | * blkif_queue_request | 192 | * blkif_queue_request |
158 | * | 193 | * |
@@ -324,6 +359,9 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) | |||
324 | /* Make sure buffer addresses are sector-aligned. */ | 359 | /* Make sure buffer addresses are sector-aligned. */ |
325 | blk_queue_dma_alignment(rq, 511); | 360 | blk_queue_dma_alignment(rq, 511); |
326 | 361 | ||
362 | /* Make sure we don't use bounce buffers. */ | ||
363 | blk_queue_bounce_limit(rq, BLK_BOUNCE_ANY); | ||
364 | |||
327 | gd->queue = rq; | 365 | gd->queue = rq; |
328 | 366 | ||
329 | return 0; | 367 | return 0; |
@@ -546,7 +584,7 @@ static int setup_blkring(struct xenbus_device *dev, | |||
546 | 584 | ||
547 | info->ring_ref = GRANT_INVALID_REF; | 585 | info->ring_ref = GRANT_INVALID_REF; |
548 | 586 | ||
549 | sring = (struct blkif_sring *)__get_free_page(GFP_KERNEL); | 587 | sring = (struct blkif_sring *)__get_free_page(GFP_NOIO | __GFP_HIGH); |
550 | if (!sring) { | 588 | if (!sring) { |
551 | xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); | 589 | xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); |
552 | return -ENOMEM; | 590 | return -ENOMEM; |
@@ -703,7 +741,8 @@ static int blkif_recover(struct blkfront_info *info) | |||
703 | int j; | 741 | int j; |
704 | 742 | ||
705 | /* Stage 1: Make a safe copy of the shadow state. */ | 743 | /* Stage 1: Make a safe copy of the shadow state. */ |
706 | copy = kmalloc(sizeof(info->shadow), GFP_KERNEL); | 744 | copy = kmalloc(sizeof(info->shadow), |
745 | GFP_NOIO | __GFP_REPEAT | __GFP_HIGH); | ||
707 | if (!copy) | 746 | if (!copy) |
708 | return -ENOMEM; | 747 | return -ENOMEM; |
709 | memcpy(copy, info->shadow, sizeof(info->shadow)); | 748 | memcpy(copy, info->shadow, sizeof(info->shadow)); |
@@ -959,7 +998,7 @@ static int blkif_release(struct inode *inode, struct file *filep) | |||
959 | struct xenbus_device *dev = info->xbdev; | 998 | struct xenbus_device *dev = info->xbdev; |
960 | enum xenbus_state state = xenbus_read_driver_state(dev->otherend); | 999 | enum xenbus_state state = xenbus_read_driver_state(dev->otherend); |
961 | 1000 | ||
962 | if (state == XenbusStateClosing) | 1001 | if (state == XenbusStateClosing && info->is_ready) |
963 | blkfront_closing(dev); | 1002 | blkfront_closing(dev); |
964 | } | 1003 | } |
965 | return 0; | 1004 | return 0; |
@@ -971,6 +1010,7 @@ static struct block_device_operations xlvbd_block_fops = | |||
971 | .open = blkif_open, | 1010 | .open = blkif_open, |
972 | .release = blkif_release, | 1011 | .release = blkif_release, |
973 | .getgeo = blkif_getgeo, | 1012 | .getgeo = blkif_getgeo, |
1013 | .ioctl = blkif_ioctl, | ||
974 | }; | 1014 | }; |
975 | 1015 | ||
976 | 1016 | ||
@@ -1006,7 +1046,7 @@ static int __init xlblk_init(void) | |||
1006 | module_init(xlblk_init); | 1046 | module_init(xlblk_init); |
1007 | 1047 | ||
1008 | 1048 | ||
1009 | static void xlblk_exit(void) | 1049 | static void __exit xlblk_exit(void) |
1010 | { | 1050 | { |
1011 | return xenbus_unregister_driver(&blkfront); | 1051 | return xenbus_unregister_driver(&blkfront); |
1012 | } | 1052 | } |
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 2d5853cbd4b0..be20a67f1fa8 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c | |||
@@ -332,7 +332,7 @@ z2_init(void) | |||
332 | int ret; | 332 | int ret; |
333 | 333 | ||
334 | if (!MACH_IS_AMIGA) | 334 | if (!MACH_IS_AMIGA) |
335 | return -ENXIO; | 335 | return -ENODEV; |
336 | 336 | ||
337 | ret = -EBUSY; | 337 | ret = -EBUSY; |
338 | if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME)) | 338 | if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME)) |