aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ide-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r--drivers/scsi/ide-scsi.c97
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 */
714static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) 735static 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
728static int idescsi_cleanup (ide_drive_t *drive) 747static 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
749static int idescsi_attach(ide_drive_t *drive); 768static int ide_scsi_probe(struct device *);
750 769
751#ifdef CONFIG_PROC_FS 770#ifdef CONFIG_PROC_FS
752static ide_proc_entry_t idescsi_proc[] = { 771static 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 */
763static ide_driver_t idescsi_driver = { 779static 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
780static int idescsi_ide_open(struct inode *inode, struct file *filp) 797static 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
824static int idescsi_attach(ide_drive_t *drive);
825
826static int idescsi_slave_configure(struct scsi_device * sdp) 841static 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
1098static int idescsi_attach(ide_drive_t *drive) 1115static 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);
1157out_host_put: 1174out_host_put:
@@ -1161,12 +1178,12 @@ out_host_put:
1161 1178
1162static int __init init_idescsi_module(void) 1179static 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
1167static void __exit exit_idescsi_module(void) 1184static 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
1172module_init(init_idescsi_module); 1189module_init(init_idescsi_module);