diff options
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r-- | drivers/scsi/ide-scsi.c | 97 |
1 files changed, 57 insertions, 40 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 2e2486b035dd..3d62c9bcbff7 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
47 | #include <linux/ide.h> | 47 | #include <linux/ide.h> |
48 | #include <linux/scatterlist.h> | 48 | #include <linux/scatterlist.h> |
49 | #include <linux/delay.h> | ||
49 | 50 | ||
50 | #include <asm/io.h> | 51 | #include <asm/io.h> |
51 | #include <asm/bitops.h> | 52 | #include <asm/bitops.h> |
@@ -179,8 +180,18 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne | |||
179 | return; | 180 | return; |
180 | } | 181 | } |
181 | count = min(pc->sg->length - pc->b_count, bcount); | 182 | count = min(pc->sg->length - pc->b_count, bcount); |
182 | buf = page_address(pc->sg->page) + pc->sg->offset; | 183 | if (PageHighMem(pc->sg->page)) { |
183 | drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); | 184 | unsigned long flags; |
185 | |||
186 | local_irq_save(flags); | ||
187 | buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset; | ||
188 | drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); | ||
189 | kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); | ||
190 | local_irq_restore(flags); | ||
191 | } else { | ||
192 | buf = page_address(pc->sg->page) + pc->sg->offset; | ||
193 | drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); | ||
194 | } | ||
184 | bcount -= count; pc->b_count += count; | 195 | bcount -= count; pc->b_count += count; |
185 | if (pc->b_count == pc->sg->length) { | 196 | if (pc->b_count == pc->sg->length) { |
186 | pc->sg++; | 197 | pc->sg++; |
@@ -201,8 +212,18 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign | |||
201 | return; | 212 | return; |
202 | } | 213 | } |
203 | count = min(pc->sg->length - pc->b_count, bcount); | 214 | count = min(pc->sg->length - pc->b_count, bcount); |
204 | buf = page_address(pc->sg->page) + pc->sg->offset; | 215 | if (PageHighMem(pc->sg->page)) { |
205 | drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); | 216 | unsigned long flags; |
217 | |||
218 | local_irq_save(flags); | ||
219 | buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset; | ||
220 | drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); | ||
221 | kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); | ||
222 | local_irq_restore(flags); | ||
223 | } else { | ||
224 | buf = page_address(pc->sg->page) + pc->sg->offset; | ||
225 | drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); | ||
226 | } | ||
206 | bcount -= count; pc->b_count += count; | 227 | bcount -= count; pc->b_count += count; |
207 | if (pc->b_count == pc->sg->length) { | 228 | if (pc->b_count == pc->sg->length) { |
208 | pc->sg++; | 229 | pc->sg++; |
@@ -713,7 +734,6 @@ static void idescsi_add_settings(ide_drive_t *drive) | |||
713 | */ | 734 | */ |
714 | static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) | 735 | static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) |
715 | { | 736 | { |
716 | DRIVER(drive)->busy++; | ||
717 | if (drive->id && (drive->id->config & 0x0060) == 0x20) | 737 | if (drive->id && (drive->id->config & 0x0060) == 0x20) |
718 | set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); | 738 | set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); |
719 | set_bit(IDESCSI_TRANSFORM, &scsi->transform); | 739 | set_bit(IDESCSI_TRANSFORM, &scsi->transform); |
@@ -722,17 +742,16 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) | |||
722 | set_bit(IDESCSI_LOG_CMD, &scsi->log); | 742 | set_bit(IDESCSI_LOG_CMD, &scsi->log); |
723 | #endif /* IDESCSI_DEBUG_LOG */ | 743 | #endif /* IDESCSI_DEBUG_LOG */ |
724 | idescsi_add_settings(drive); | 744 | idescsi_add_settings(drive); |
725 | DRIVER(drive)->busy--; | ||
726 | } | 745 | } |
727 | 746 | ||
728 | static int idescsi_cleanup (ide_drive_t *drive) | 747 | static int ide_scsi_remove(struct device *dev) |
729 | { | 748 | { |
749 | ide_drive_t *drive = to_ide_device(dev); | ||
730 | struct Scsi_Host *scsihost = drive->driver_data; | 750 | struct Scsi_Host *scsihost = drive->driver_data; |
731 | struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); | 751 | struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); |
732 | struct gendisk *g = scsi->disk; | 752 | struct gendisk *g = scsi->disk; |
733 | 753 | ||
734 | if (ide_unregister_subdriver(drive)) | 754 | ide_unregister_subdriver(drive, scsi->driver); |
735 | return 1; | ||
736 | 755 | ||
737 | ide_unregister_region(g); | 756 | ide_unregister_region(g); |
738 | 757 | ||
@@ -746,7 +765,7 @@ static int idescsi_cleanup (ide_drive_t *drive) | |||
746 | return 0; | 765 | return 0; |
747 | } | 766 | } |
748 | 767 | ||
749 | static int idescsi_attach(ide_drive_t *drive); | 768 | static int ide_scsi_probe(struct device *); |
750 | 769 | ||
751 | #ifdef CONFIG_PROC_FS | 770 | #ifdef CONFIG_PROC_FS |
752 | static ide_proc_entry_t idescsi_proc[] = { | 771 | static ide_proc_entry_t idescsi_proc[] = { |
@@ -757,24 +776,22 @@ static ide_proc_entry_t idescsi_proc[] = { | |||
757 | # define idescsi_proc NULL | 776 | # define idescsi_proc NULL |
758 | #endif | 777 | #endif |
759 | 778 | ||
760 | /* | ||
761 | * IDE subdriver functions, registered with ide.c | ||
762 | */ | ||
763 | static ide_driver_t idescsi_driver = { | 779 | static ide_driver_t idescsi_driver = { |
764 | .owner = THIS_MODULE, | 780 | .owner = THIS_MODULE, |
765 | .name = "ide-scsi", | 781 | .gen_driver = { |
782 | .name = "ide-scsi", | ||
783 | .bus = &ide_bus_type, | ||
784 | .probe = ide_scsi_probe, | ||
785 | .remove = ide_scsi_remove, | ||
786 | }, | ||
766 | .version = IDESCSI_VERSION, | 787 | .version = IDESCSI_VERSION, |
767 | .media = ide_scsi, | 788 | .media = ide_scsi, |
768 | .busy = 0, | ||
769 | .supports_dsc_overlap = 0, | 789 | .supports_dsc_overlap = 0, |
770 | .proc = idescsi_proc, | 790 | .proc = idescsi_proc, |
771 | .attach = idescsi_attach, | ||
772 | .cleanup = idescsi_cleanup, | ||
773 | .do_request = idescsi_do_request, | 791 | .do_request = idescsi_do_request, |
774 | .end_request = idescsi_end_request, | 792 | .end_request = idescsi_end_request, |
775 | .error = idescsi_atapi_error, | 793 | .error = idescsi_atapi_error, |
776 | .abort = idescsi_atapi_abort, | 794 | .abort = idescsi_atapi_abort, |
777 | .drives = LIST_HEAD_INIT(idescsi_driver.drives), | ||
778 | }; | 795 | }; |
779 | 796 | ||
780 | static int idescsi_ide_open(struct inode *inode, struct file *filp) | 797 | static int idescsi_ide_open(struct inode *inode, struct file *filp) |
@@ -821,8 +838,6 @@ static struct block_device_operations idescsi_ops = { | |||
821 | .ioctl = idescsi_ide_ioctl, | 838 | .ioctl = idescsi_ide_ioctl, |
822 | }; | 839 | }; |
823 | 840 | ||
824 | static int idescsi_attach(ide_drive_t *drive); | ||
825 | |||
826 | static int idescsi_slave_configure(struct scsi_device * sdp) | 841 | static int idescsi_slave_configure(struct scsi_device * sdp) |
827 | { | 842 | { |
828 | /* Configure detected device */ | 843 | /* Configure detected device */ |
@@ -1012,11 +1027,13 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) | |||
1012 | return FAILED; | 1027 | return FAILED; |
1013 | } | 1028 | } |
1014 | 1029 | ||
1015 | spin_lock_irq(&ide_lock); | 1030 | spin_lock_irq(cmd->device->host->host_lock); |
1031 | spin_lock(&ide_lock); | ||
1016 | 1032 | ||
1017 | if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) { | 1033 | if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) { |
1018 | printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n"); | 1034 | printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n"); |
1019 | spin_unlock(&ide_lock); | 1035 | spin_unlock(&ide_lock); |
1036 | spin_unlock_irq(cmd->device->host->host_lock); | ||
1020 | return FAILED; | 1037 | return FAILED; |
1021 | } | 1038 | } |
1022 | 1039 | ||
@@ -1038,16 +1055,15 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) | |||
1038 | HWGROUP(drive)->rq = NULL; | 1055 | HWGROUP(drive)->rq = NULL; |
1039 | HWGROUP(drive)->handler = NULL; | 1056 | HWGROUP(drive)->handler = NULL; |
1040 | HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */ | 1057 | HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */ |
1041 | spin_unlock_irq(&ide_lock); | 1058 | spin_unlock(&ide_lock); |
1042 | 1059 | ||
1043 | ide_do_reset(drive); | 1060 | ide_do_reset(drive); |
1044 | 1061 | ||
1045 | /* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */ | 1062 | /* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */ |
1046 | 1063 | ||
1047 | do { | 1064 | do { |
1048 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1049 | spin_unlock_irq(cmd->device->host->host_lock); | 1065 | spin_unlock_irq(cmd->device->host->host_lock); |
1050 | schedule_timeout(HZ/20); | 1066 | msleep(50); |
1051 | spin_lock_irq(cmd->device->host->host_lock); | 1067 | spin_lock_irq(cmd->device->host->host_lock); |
1052 | } while ( HWGROUP(drive)->handler ); | 1068 | } while ( HWGROUP(drive)->handler ); |
1053 | 1069 | ||
@@ -1058,6 +1074,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) | |||
1058 | ret = FAILED; | 1074 | ret = FAILED; |
1059 | } | 1075 | } |
1060 | 1076 | ||
1077 | spin_unlock_irq(cmd->device->host->host_lock); | ||
1061 | return ret; | 1078 | return ret; |
1062 | } | 1079 | } |
1063 | 1080 | ||
@@ -1095,8 +1112,9 @@ static struct scsi_host_template idescsi_template = { | |||
1095 | .proc_name = "ide-scsi", | 1112 | .proc_name = "ide-scsi", |
1096 | }; | 1113 | }; |
1097 | 1114 | ||
1098 | static int idescsi_attach(ide_drive_t *drive) | 1115 | static int ide_scsi_probe(struct device *dev) |
1099 | { | 1116 | { |
1117 | ide_drive_t *drive = to_ide_device(dev); | ||
1100 | idescsi_scsi_t *idescsi; | 1118 | idescsi_scsi_t *idescsi; |
1101 | struct Scsi_Host *host; | 1119 | struct Scsi_Host *host; |
1102 | struct gendisk *g; | 1120 | struct gendisk *g; |
@@ -1112,7 +1130,7 @@ static int idescsi_attach(ide_drive_t *drive) | |||
1112 | !drive->present || | 1130 | !drive->present || |
1113 | drive->media == ide_disk || | 1131 | drive->media == ide_disk || |
1114 | !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) | 1132 | !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) |
1115 | return 1; | 1133 | return -ENODEV; |
1116 | 1134 | ||
1117 | g = alloc_disk(1 << PARTN_BITS); | 1135 | g = alloc_disk(1 << PARTN_BITS); |
1118 | if (!g) | 1136 | if (!g) |
@@ -1138,20 +1156,19 @@ static int idescsi_attach(ide_drive_t *drive) | |||
1138 | idescsi->host = host; | 1156 | idescsi->host = host; |
1139 | idescsi->disk = g; | 1157 | idescsi->disk = g; |
1140 | g->private_data = &idescsi->driver; | 1158 | g->private_data = &idescsi->driver; |
1141 | err = ide_register_subdriver(drive, &idescsi_driver); | 1159 | ide_register_subdriver(drive, &idescsi_driver); |
1160 | err = 0; | ||
1161 | idescsi_setup(drive, idescsi); | ||
1162 | g->fops = &idescsi_ops; | ||
1163 | ide_register_region(g); | ||
1164 | err = scsi_add_host(host, &drive->gendev); | ||
1142 | if (!err) { | 1165 | if (!err) { |
1143 | idescsi_setup (drive, idescsi); | 1166 | scsi_scan_host(host); |
1144 | g->fops = &idescsi_ops; | 1167 | return 0; |
1145 | ide_register_region(g); | ||
1146 | err = scsi_add_host(host, &drive->gendev); | ||
1147 | if (!err) { | ||
1148 | scsi_scan_host(host); | ||
1149 | return 0; | ||
1150 | } | ||
1151 | /* fall through on error */ | ||
1152 | ide_unregister_region(g); | ||
1153 | ide_unregister_subdriver(drive); | ||
1154 | } | 1168 | } |
1169 | /* fall through on error */ | ||
1170 | ide_unregister_region(g); | ||
1171 | ide_unregister_subdriver(drive, &idescsi_driver); | ||
1155 | 1172 | ||
1156 | put_disk(g); | 1173 | put_disk(g); |
1157 | out_host_put: | 1174 | out_host_put: |
@@ -1161,12 +1178,12 @@ out_host_put: | |||
1161 | 1178 | ||
1162 | static int __init init_idescsi_module(void) | 1179 | static int __init init_idescsi_module(void) |
1163 | { | 1180 | { |
1164 | return ide_register_driver(&idescsi_driver); | 1181 | return driver_register(&idescsi_driver.gen_driver); |
1165 | } | 1182 | } |
1166 | 1183 | ||
1167 | static void __exit exit_idescsi_module(void) | 1184 | static void __exit exit_idescsi_module(void) |
1168 | { | 1185 | { |
1169 | ide_unregister_driver(&idescsi_driver); | 1186 | driver_unregister(&idescsi_driver.gen_driver); |
1170 | } | 1187 | } |
1171 | 1188 | ||
1172 | module_init(init_idescsi_module); | 1189 | module_init(init_idescsi_module); |