diff options
Diffstat (limited to 'drivers/scsi/sun3_NCR5380.c')
-rw-r--r-- | drivers/scsi/sun3_NCR5380.c | 98 |
1 files changed, 23 insertions, 75 deletions
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 07eaef1c722b..7e12a2e4e0a3 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c | |||
@@ -49,13 +49,6 @@ | |||
49 | * inside the execution of NCR5380_intr(), leading to recursive | 49 | * inside the execution of NCR5380_intr(), leading to recursive |
50 | * calls. | 50 | * calls. |
51 | * | 51 | * |
52 | * - I've added a function merge_contiguous_buffers() that tries to | ||
53 | * merge scatter-gather buffers that are located at contiguous | ||
54 | * physical addresses and can be processed with the same DMA setup. | ||
55 | * Since most scatter-gather operations work on a page (4K) of | ||
56 | * 4 buffers (1K), in more than 90% of all cases three interrupts and | ||
57 | * DMA setup actions are saved. | ||
58 | * | ||
59 | * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA | 52 | * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA |
60 | * and USLEEP, because these were messing up readability and will never be | 53 | * and USLEEP, because these were messing up readability and will never be |
61 | * needed for Atari SCSI. | 54 | * needed for Atari SCSI. |
@@ -266,8 +259,9 @@ static struct scsi_host_template *the_template = NULL; | |||
266 | (struct NCR5380_hostdata *)(in)->hostdata | 259 | (struct NCR5380_hostdata *)(in)->hostdata |
267 | #define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata) | 260 | #define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata) |
268 | 261 | ||
269 | #define NEXT(cmd) (*(struct scsi_cmnd **)&((cmd)->host_scribble)) | 262 | #define NEXT(cmd) ((struct scsi_cmnd *)(cmd)->host_scribble) |
270 | #define NEXTADDR(cmd) ((struct scsi_cmnd **)&((cmd)->host_scribble)) | 263 | #define SET_NEXT(cmd, next) ((cmd)->host_scribble = (void *)(next)) |
264 | #define NEXTADDR(cmd) ((struct scsi_cmnd **)&((cmd)->host_scribble)) | ||
271 | 265 | ||
272 | #define HOSTNO instance->host_no | 266 | #define HOSTNO instance->host_no |
273 | #define H_NO(cmd) (cmd)->device->host->host_no | 267 | #define H_NO(cmd) (cmd)->device->host->host_no |
@@ -459,47 +453,6 @@ static void free_all_tags( void ) | |||
459 | 453 | ||
460 | 454 | ||
461 | /* | 455 | /* |
462 | * Function: void merge_contiguous_buffers(struct scsi_cmnd *cmd) | ||
463 | * | ||
464 | * Purpose: Try to merge several scatter-gather requests into one DMA | ||
465 | * transfer. This is possible if the scatter buffers lie on | ||
466 | * physical contiguous addresses. | ||
467 | * | ||
468 | * Parameters: struct scsi_cmnd *cmd | ||
469 | * The command to work on. The first scatter buffer's data are | ||
470 | * assumed to be already transferred into ptr/this_residual. | ||
471 | */ | ||
472 | |||
473 | static void merge_contiguous_buffers(struct scsi_cmnd *cmd) | ||
474 | { | ||
475 | unsigned long endaddr; | ||
476 | #if (NDEBUG & NDEBUG_MERGING) | ||
477 | unsigned long oldlen = cmd->SCp.this_residual; | ||
478 | int cnt = 1; | ||
479 | #endif | ||
480 | |||
481 | for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; | ||
482 | cmd->SCp.buffers_residual && | ||
483 | virt_to_phys(SGADDR(&(cmd->SCp.buffer[1]))) == endaddr; ) { | ||
484 | |||
485 | MER_PRINTK("VTOP(%p) == %08lx -> merging\n", | ||
486 | SGADDR(&(cmd->SCp.buffer[1])), endaddr); | ||
487 | #if (NDEBUG & NDEBUG_MERGING) | ||
488 | ++cnt; | ||
489 | #endif | ||
490 | ++cmd->SCp.buffer; | ||
491 | --cmd->SCp.buffers_residual; | ||
492 | cmd->SCp.this_residual += cmd->SCp.buffer->length; | ||
493 | endaddr += cmd->SCp.buffer->length; | ||
494 | } | ||
495 | #if (NDEBUG & NDEBUG_MERGING) | ||
496 | if (oldlen != cmd->SCp.this_residual) | ||
497 | MER_PRINTK("merged %d buffers from %p, new length %08x\n", | ||
498 | cnt, cmd->SCp.ptr, cmd->SCp.this_residual); | ||
499 | #endif | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * Function : void initialize_SCp(struct scsi_cmnd *cmd) | 456 | * Function : void initialize_SCp(struct scsi_cmnd *cmd) |
504 | * | 457 | * |
505 | * Purpose : initialize the saved data pointers for cmd to point to the | 458 | * Purpose : initialize the saved data pointers for cmd to point to the |
@@ -520,11 +473,6 @@ static __inline__ void initialize_SCp(struct scsi_cmnd *cmd) | |||
520 | cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; | 473 | cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; |
521 | cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer); | 474 | cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer); |
522 | cmd->SCp.this_residual = cmd->SCp.buffer->length; | 475 | cmd->SCp.this_residual = cmd->SCp.buffer->length; |
523 | |||
524 | /* ++roman: Try to merge some scatter-buffers if they are at | ||
525 | * contiguous physical addresses. | ||
526 | */ | ||
527 | // merge_contiguous_buffers( cmd ); | ||
528 | } else { | 476 | } else { |
529 | cmd->SCp.buffer = NULL; | 477 | cmd->SCp.buffer = NULL; |
530 | cmd->SCp.buffers_residual = 0; | 478 | cmd->SCp.buffers_residual = 0; |
@@ -841,7 +789,7 @@ static char *lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, char *pos, char *buffer, | |||
841 | * | 789 | * |
842 | */ | 790 | */ |
843 | 791 | ||
844 | static int NCR5380_init (struct Scsi_Host *instance, int flags) | 792 | static int __init NCR5380_init(struct Scsi_Host *instance, int flags) |
845 | { | 793 | { |
846 | int i; | 794 | int i; |
847 | SETUP_HOSTDATA(instance); | 795 | SETUP_HOSTDATA(instance); |
@@ -889,6 +837,11 @@ static int NCR5380_init (struct Scsi_Host *instance, int flags) | |||
889 | return 0; | 837 | return 0; |
890 | } | 838 | } |
891 | 839 | ||
840 | static void NCR5380_exit(struct Scsi_Host *instance) | ||
841 | { | ||
842 | /* Empty, as we didn't schedule any delayed work */ | ||
843 | } | ||
844 | |||
892 | /* | 845 | /* |
893 | * Function : int NCR5380_queue_command (struct scsi_cmnd *cmd, | 846 | * Function : int NCR5380_queue_command (struct scsi_cmnd *cmd, |
894 | * void (*done)(struct scsi_cmnd *)) | 847 | * void (*done)(struct scsi_cmnd *)) |
@@ -962,7 +915,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, | |||
962 | * in a queue | 915 | * in a queue |
963 | */ | 916 | */ |
964 | 917 | ||
965 | NEXT(cmd) = NULL; | 918 | SET_NEXT(cmd, NULL); |
966 | cmd->scsi_done = done; | 919 | cmd->scsi_done = done; |
967 | 920 | ||
968 | cmd->result = 0; | 921 | cmd->result = 0; |
@@ -990,14 +943,14 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, | |||
990 | */ | 943 | */ |
991 | if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { | 944 | if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { |
992 | LIST(cmd, hostdata->issue_queue); | 945 | LIST(cmd, hostdata->issue_queue); |
993 | NEXT(cmd) = hostdata->issue_queue; | 946 | SET_NEXT(cmd, hostdata->issue_queue); |
994 | hostdata->issue_queue = cmd; | 947 | hostdata->issue_queue = cmd; |
995 | } else { | 948 | } else { |
996 | for (tmp = (struct scsi_cmnd *)hostdata->issue_queue; | 949 | for (tmp = (struct scsi_cmnd *)hostdata->issue_queue; |
997 | NEXT(tmp); tmp = NEXT(tmp)) | 950 | NEXT(tmp); tmp = NEXT(tmp)) |
998 | ; | 951 | ; |
999 | LIST(cmd, tmp); | 952 | LIST(cmd, tmp); |
1000 | NEXT(tmp) = cmd; | 953 | SET_NEXT(tmp, cmd); |
1001 | } | 954 | } |
1002 | 955 | ||
1003 | local_irq_restore(flags); | 956 | local_irq_restore(flags); |
@@ -1105,12 +1058,12 @@ static void NCR5380_main (struct work_struct *bl) | |||
1105 | local_irq_disable(); | 1058 | local_irq_disable(); |
1106 | if (prev) { | 1059 | if (prev) { |
1107 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); | 1060 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); |
1108 | NEXT(prev) = NEXT(tmp); | 1061 | SET_NEXT(prev, NEXT(tmp)); |
1109 | } else { | 1062 | } else { |
1110 | REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp)); | 1063 | REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp)); |
1111 | hostdata->issue_queue = NEXT(tmp); | 1064 | hostdata->issue_queue = NEXT(tmp); |
1112 | } | 1065 | } |
1113 | NEXT(tmp) = NULL; | 1066 | SET_NEXT(tmp, NULL); |
1114 | 1067 | ||
1115 | /* reenable interrupts after finding one */ | 1068 | /* reenable interrupts after finding one */ |
1116 | local_irq_restore(flags); | 1069 | local_irq_restore(flags); |
@@ -1144,7 +1097,7 @@ static void NCR5380_main (struct work_struct *bl) | |||
1144 | } else { | 1097 | } else { |
1145 | local_irq_disable(); | 1098 | local_irq_disable(); |
1146 | LIST(tmp, hostdata->issue_queue); | 1099 | LIST(tmp, hostdata->issue_queue); |
1147 | NEXT(tmp) = hostdata->issue_queue; | 1100 | SET_NEXT(tmp, hostdata->issue_queue); |
1148 | hostdata->issue_queue = tmp; | 1101 | hostdata->issue_queue = tmp; |
1149 | #ifdef SUPPORT_TAGS | 1102 | #ifdef SUPPORT_TAGS |
1150 | cmd_free_tag( tmp ); | 1103 | cmd_free_tag( tmp ); |
@@ -1439,7 +1392,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd, | |||
1439 | local_irq_restore(flags); | 1392 | local_irq_restore(flags); |
1440 | 1393 | ||
1441 | /* Wait for arbitration logic to complete */ | 1394 | /* Wait for arbitration logic to complete */ |
1442 | #if NCR_TIMEOUT | 1395 | #ifdef NCR_TIMEOUT |
1443 | { | 1396 | { |
1444 | unsigned long timeout = jiffies + 2*NCR_TIMEOUT; | 1397 | unsigned long timeout = jiffies + 2*NCR_TIMEOUT; |
1445 | 1398 | ||
@@ -2070,11 +2023,6 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) | |||
2070 | --cmd->SCp.buffers_residual; | 2023 | --cmd->SCp.buffers_residual; |
2071 | cmd->SCp.this_residual = cmd->SCp.buffer->length; | 2024 | cmd->SCp.this_residual = cmd->SCp.buffer->length; |
2072 | cmd->SCp.ptr = SGADDR(cmd->SCp.buffer); | 2025 | cmd->SCp.ptr = SGADDR(cmd->SCp.buffer); |
2073 | |||
2074 | /* ++roman: Try to merge some scatter-buffers if | ||
2075 | * they are at contiguous physical addresses. | ||
2076 | */ | ||
2077 | // merge_contiguous_buffers( cmd ); | ||
2078 | INF_PRINTK("scsi%d: %d bytes and %d buffers left\n", | 2026 | INF_PRINTK("scsi%d: %d bytes and %d buffers left\n", |
2079 | HOSTNO, cmd->SCp.this_residual, | 2027 | HOSTNO, cmd->SCp.this_residual, |
2080 | cmd->SCp.buffers_residual); | 2028 | cmd->SCp.buffers_residual); |
@@ -2274,7 +2222,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) | |||
2274 | 2222 | ||
2275 | local_irq_save(flags); | 2223 | local_irq_save(flags); |
2276 | LIST(cmd,hostdata->issue_queue); | 2224 | LIST(cmd,hostdata->issue_queue); |
2277 | NEXT(cmd) = hostdata->issue_queue; | 2225 | SET_NEXT(cmd, hostdata->issue_queue); |
2278 | hostdata->issue_queue = (struct scsi_cmnd *) cmd; | 2226 | hostdata->issue_queue = (struct scsi_cmnd *) cmd; |
2279 | local_irq_restore(flags); | 2227 | local_irq_restore(flags); |
2280 | QU_PRINTK("scsi%d: REQUEST SENSE added to head of " | 2228 | QU_PRINTK("scsi%d: REQUEST SENSE added to head of " |
@@ -2330,7 +2278,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) | |||
2330 | local_irq_save(flags); | 2278 | local_irq_save(flags); |
2331 | cmd->device->disconnect = 1; | 2279 | cmd->device->disconnect = 1; |
2332 | LIST(cmd,hostdata->disconnected_queue); | 2280 | LIST(cmd,hostdata->disconnected_queue); |
2333 | NEXT(cmd) = hostdata->disconnected_queue; | 2281 | SET_NEXT(cmd, hostdata->disconnected_queue); |
2334 | hostdata->connected = NULL; | 2282 | hostdata->connected = NULL; |
2335 | hostdata->disconnected_queue = cmd; | 2283 | hostdata->disconnected_queue = cmd; |
2336 | local_irq_restore(flags); | 2284 | local_irq_restore(flags); |
@@ -2589,12 +2537,12 @@ static void NCR5380_reselect (struct Scsi_Host *instance) | |||
2589 | ) { | 2537 | ) { |
2590 | if (prev) { | 2538 | if (prev) { |
2591 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); | 2539 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); |
2592 | NEXT(prev) = NEXT(tmp); | 2540 | SET_NEXT(prev, NEXT(tmp)); |
2593 | } else { | 2541 | } else { |
2594 | REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp)); | 2542 | REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp)); |
2595 | hostdata->disconnected_queue = NEXT(tmp); | 2543 | hostdata->disconnected_queue = NEXT(tmp); |
2596 | } | 2544 | } |
2597 | NEXT(tmp) = NULL; | 2545 | SET_NEXT(tmp, NULL); |
2598 | break; | 2546 | break; |
2599 | } | 2547 | } |
2600 | } | 2548 | } |
@@ -2762,7 +2710,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) | |||
2762 | if (cmd == tmp) { | 2710 | if (cmd == tmp) { |
2763 | REMOVE(5, *prev, tmp, NEXT(tmp)); | 2711 | REMOVE(5, *prev, tmp, NEXT(tmp)); |
2764 | (*prev) = NEXT(tmp); | 2712 | (*prev) = NEXT(tmp); |
2765 | NEXT(tmp) = NULL; | 2713 | SET_NEXT(tmp, NULL); |
2766 | tmp->result = DID_ABORT << 16; | 2714 | tmp->result = DID_ABORT << 16; |
2767 | local_irq_restore(flags); | 2715 | local_irq_restore(flags); |
2768 | ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n", | 2716 | ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n", |
@@ -2835,7 +2783,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) | |||
2835 | if (cmd == tmp) { | 2783 | if (cmd == tmp) { |
2836 | REMOVE(5, *prev, tmp, NEXT(tmp)); | 2784 | REMOVE(5, *prev, tmp, NEXT(tmp)); |
2837 | *prev = NEXT(tmp); | 2785 | *prev = NEXT(tmp); |
2838 | NEXT(tmp) = NULL; | 2786 | SET_NEXT(tmp, NULL); |
2839 | tmp->result = DID_ABORT << 16; | 2787 | tmp->result = DID_ABORT << 16; |
2840 | /* We must unlock the tag/LUN immediately here, since the | 2788 | /* We must unlock the tag/LUN immediately here, since the |
2841 | * target goes to BUS FREE and doesn't send us another | 2789 | * target goes to BUS FREE and doesn't send us another |
@@ -2943,7 +2891,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) | |||
2943 | 2891 | ||
2944 | for (i = 0; (cmd = disconnected_queue); ++i) { | 2892 | for (i = 0; (cmd = disconnected_queue); ++i) { |
2945 | disconnected_queue = NEXT(cmd); | 2893 | disconnected_queue = NEXT(cmd); |
2946 | NEXT(cmd) = NULL; | 2894 | SET_NEXT(cmd, NULL); |
2947 | cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16); | 2895 | cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16); |
2948 | cmd->scsi_done( cmd ); | 2896 | cmd->scsi_done( cmd ); |
2949 | } | 2897 | } |