diff options
Diffstat (limited to 'drivers/scsi/aha152x.c')
-rw-r--r-- | drivers/scsi/aha152x.c | 100 |
1 files changed, 58 insertions, 42 deletions
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index de80cdfb5b9d..fb6a476eb873 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c | |||
@@ -253,6 +253,7 @@ | |||
253 | #include <linux/isapnp.h> | 253 | #include <linux/isapnp.h> |
254 | #include <linux/spinlock.h> | 254 | #include <linux/spinlock.h> |
255 | #include <linux/workqueue.h> | 255 | #include <linux/workqueue.h> |
256 | #include <linux/list.h> | ||
256 | #include <asm/semaphore.h> | 257 | #include <asm/semaphore.h> |
257 | #include <scsi/scsicam.h> | 258 | #include <scsi/scsicam.h> |
258 | 259 | ||
@@ -262,6 +263,8 @@ | |||
262 | #include <scsi/scsi_transport_spi.h> | 263 | #include <scsi/scsi_transport_spi.h> |
263 | #include "aha152x.h" | 264 | #include "aha152x.h" |
264 | 265 | ||
266 | static LIST_HEAD(aha152x_host_list); | ||
267 | |||
265 | 268 | ||
266 | /* DEFINES */ | 269 | /* DEFINES */ |
267 | 270 | ||
@@ -423,8 +426,6 @@ MODULE_DEVICE_TABLE(isapnp, id_table); | |||
423 | 426 | ||
424 | #endif /* !PCMCIA */ | 427 | #endif /* !PCMCIA */ |
425 | 428 | ||
426 | static int registered_count=0; | ||
427 | static struct Scsi_Host *aha152x_host[2]; | ||
428 | static struct scsi_host_template aha152x_driver_template; | 429 | static struct scsi_host_template aha152x_driver_template; |
429 | 430 | ||
430 | /* | 431 | /* |
@@ -541,6 +542,7 @@ struct aha152x_hostdata { | |||
541 | #ifdef __ISAPNP__ | 542 | #ifdef __ISAPNP__ |
542 | struct pnp_dev *pnpdev; | 543 | struct pnp_dev *pnpdev; |
543 | #endif | 544 | #endif |
545 | struct list_head host_list; | ||
544 | }; | 546 | }; |
545 | 547 | ||
546 | 548 | ||
@@ -551,6 +553,11 @@ struct aha152x_hostdata { | |||
551 | struct aha152x_scdata { | 553 | struct aha152x_scdata { |
552 | Scsi_Cmnd *next; /* next sc in queue */ | 554 | Scsi_Cmnd *next; /* next sc in queue */ |
553 | struct semaphore *sem; /* semaphore to block on */ | 555 | struct semaphore *sem; /* semaphore to block on */ |
556 | unsigned char cmd_len; | ||
557 | unsigned char cmnd[MAX_COMMAND_SIZE]; | ||
558 | unsigned short use_sg; | ||
559 | unsigned request_bufflen; | ||
560 | void *request_buffer; | ||
554 | }; | 561 | }; |
555 | 562 | ||
556 | 563 | ||
@@ -750,20 +757,9 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp) | |||
750 | return ptr; | 757 | return ptr; |
751 | } | 758 | } |
752 | 759 | ||
753 | static inline struct Scsi_Host *lookup_irq(int irqno) | ||
754 | { | ||
755 | int i; | ||
756 | |||
757 | for(i=0; i<ARRAY_SIZE(aha152x_host); i++) | ||
758 | if(aha152x_host[i] && aha152x_host[i]->irq==irqno) | ||
759 | return aha152x_host[i]; | ||
760 | |||
761 | return NULL; | ||
762 | } | ||
763 | |||
764 | static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs) | 760 | static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs) |
765 | { | 761 | { |
766 | struct Scsi_Host *shpnt = lookup_irq(irqno); | 762 | struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id; |
767 | 763 | ||
768 | if (!shpnt) { | 764 | if (!shpnt) { |
769 | printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno); | 765 | printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno); |
@@ -786,10 +782,11 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) | |||
786 | return NULL; | 782 | return NULL; |
787 | } | 783 | } |
788 | 784 | ||
789 | /* need to have host registered before triggering any interrupt */ | ||
790 | aha152x_host[registered_count] = shpnt; | ||
791 | |||
792 | memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt)); | 785 | memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt)); |
786 | INIT_LIST_HEAD(&HOSTDATA(shpnt)->host_list); | ||
787 | |||
788 | /* need to have host registered before triggering any interrupt */ | ||
789 | list_add_tail(&HOSTDATA(shpnt)->host_list, &aha152x_host_list); | ||
793 | 790 | ||
794 | shpnt->io_port = setup->io_port; | 791 | shpnt->io_port = setup->io_port; |
795 | shpnt->n_io_port = IO_RANGE; | 792 | shpnt->n_io_port = IO_RANGE; |
@@ -855,7 +852,7 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) | |||
855 | SETPORT(SIMODE0, 0); | 852 | SETPORT(SIMODE0, 0); |
856 | SETPORT(SIMODE1, 0); | 853 | SETPORT(SIMODE1, 0); |
857 | 854 | ||
858 | if( request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) { | 855 | if( request_irq(shpnt->irq, swintr, IRQF_DISABLED|IRQF_SHARED, "aha152x", shpnt) ) { |
859 | printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq); | 856 | printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq); |
860 | goto out_host_put; | 857 | goto out_host_put; |
861 | } | 858 | } |
@@ -889,7 +886,7 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) | |||
889 | SETPORT(SSTAT0, 0x7f); | 886 | SETPORT(SSTAT0, 0x7f); |
890 | SETPORT(SSTAT1, 0xef); | 887 | SETPORT(SSTAT1, 0xef); |
891 | 888 | ||
892 | if ( request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) { | 889 | if ( request_irq(shpnt->irq, intr, IRQF_DISABLED|IRQF_SHARED, "aha152x", shpnt) ) { |
893 | printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq); | 890 | printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq); |
894 | goto out_host_put; | 891 | goto out_host_put; |
895 | } | 892 | } |
@@ -902,12 +899,10 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) | |||
902 | 899 | ||
903 | scsi_scan_host(shpnt); | 900 | scsi_scan_host(shpnt); |
904 | 901 | ||
905 | registered_count++; | ||
906 | |||
907 | return shpnt; | 902 | return shpnt; |
908 | 903 | ||
909 | out_host_put: | 904 | out_host_put: |
910 | aha152x_host[registered_count]=NULL; | 905 | list_del(&HOSTDATA(shpnt)->host_list); |
911 | scsi_host_put(shpnt); | 906 | scsi_host_put(shpnt); |
912 | 907 | ||
913 | return NULL; | 908 | return NULL; |
@@ -932,6 +927,7 @@ void aha152x_release(struct Scsi_Host *shpnt) | |||
932 | #endif | 927 | #endif |
933 | 928 | ||
934 | scsi_remove_host(shpnt); | 929 | scsi_remove_host(shpnt); |
930 | list_del(&HOSTDATA(shpnt)->host_list); | ||
935 | scsi_host_put(shpnt); | 931 | scsi_host_put(shpnt); |
936 | } | 932 | } |
937 | 933 | ||
@@ -1006,11 +1002,20 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int p | |||
1006 | return FAILED; | 1002 | return FAILED; |
1007 | } | 1003 | } |
1008 | } else { | 1004 | } else { |
1005 | struct aha152x_scdata *sc; | ||
1006 | |||
1009 | SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); | 1007 | SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); |
1010 | if(SCpnt->host_scribble==0) { | 1008 | if(SCpnt->host_scribble==0) { |
1011 | printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt)); | 1009 | printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt)); |
1012 | return FAILED; | 1010 | return FAILED; |
1013 | } | 1011 | } |
1012 | |||
1013 | sc = SCDATA(SCpnt); | ||
1014 | memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd)); | ||
1015 | sc->request_buffer = SCpnt->request_buffer; | ||
1016 | sc->request_bufflen = SCpnt->request_bufflen; | ||
1017 | sc->use_sg = SCpnt->use_sg; | ||
1018 | sc->cmd_len = SCpnt->cmd_len; | ||
1014 | } | 1019 | } |
1015 | 1020 | ||
1016 | SCNEXT(SCpnt) = NULL; | 1021 | SCNEXT(SCpnt) = NULL; |
@@ -1165,6 +1170,10 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) | |||
1165 | DECLARE_MUTEX_LOCKED(sem); | 1170 | DECLARE_MUTEX_LOCKED(sem); |
1166 | struct timer_list timer; | 1171 | struct timer_list timer; |
1167 | int ret, issued, disconnected; | 1172 | int ret, issued, disconnected; |
1173 | unsigned char old_cmd_len = SCpnt->cmd_len; | ||
1174 | unsigned short old_use_sg = SCpnt->use_sg; | ||
1175 | void *old_buffer = SCpnt->request_buffer; | ||
1176 | unsigned old_bufflen = SCpnt->request_bufflen; | ||
1168 | unsigned long flags; | 1177 | unsigned long flags; |
1169 | 1178 | ||
1170 | #if defined(AHA152X_DEBUG) | 1179 | #if defined(AHA152X_DEBUG) |
@@ -1198,11 +1207,11 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) | |||
1198 | add_timer(&timer); | 1207 | add_timer(&timer); |
1199 | down(&sem); | 1208 | down(&sem); |
1200 | del_timer(&timer); | 1209 | del_timer(&timer); |
1201 | 1210 | ||
1202 | SCpnt->cmd_len = SCpnt->old_cmd_len; | 1211 | SCpnt->cmd_len = old_cmd_len; |
1203 | SCpnt->use_sg = SCpnt->old_use_sg; | 1212 | SCpnt->use_sg = old_use_sg; |
1204 | SCpnt->request_buffer = SCpnt->buffer; | 1213 | SCpnt->request_buffer = old_buffer; |
1205 | SCpnt->request_bufflen = SCpnt->bufflen; | 1214 | SCpnt->request_bufflen = old_bufflen; |
1206 | 1215 | ||
1207 | DO_LOCK(flags); | 1216 | DO_LOCK(flags); |
1208 | 1217 | ||
@@ -1441,9 +1450,12 @@ static struct work_struct aha152x_tq; | |||
1441 | */ | 1450 | */ |
1442 | static void run(void) | 1451 | static void run(void) |
1443 | { | 1452 | { |
1444 | int i; | 1453 | struct aha152x_hostdata *hd; |
1445 | for (i = 0; i<ARRAY_SIZE(aha152x_host); i++) { | 1454 | |
1446 | is_complete(aha152x_host[i]); | 1455 | list_for_each_entry(hd, &aha152x_host_list, host_list) { |
1456 | struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata); | ||
1457 | |||
1458 | is_complete(shost); | ||
1447 | } | 1459 | } |
1448 | } | 1460 | } |
1449 | 1461 | ||
@@ -1453,7 +1465,7 @@ static void run(void) | |||
1453 | */ | 1465 | */ |
1454 | static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs) | 1466 | static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs) |
1455 | { | 1467 | { |
1456 | struct Scsi_Host *shpnt = lookup_irq(irqno); | 1468 | struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id; |
1457 | unsigned long flags; | 1469 | unsigned long flags; |
1458 | unsigned char rev, dmacntrl0; | 1470 | unsigned char rev, dmacntrl0; |
1459 | 1471 | ||
@@ -1565,6 +1577,9 @@ static void busfree_run(struct Scsi_Host *shpnt) | |||
1565 | #endif | 1577 | #endif |
1566 | 1578 | ||
1567 | if(DONE_SC->SCp.phase & check_condition) { | 1579 | if(DONE_SC->SCp.phase & check_condition) { |
1580 | struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC; | ||
1581 | struct aha152x_scdata *sc = SCDATA(cmd); | ||
1582 | |||
1568 | #if 0 | 1583 | #if 0 |
1569 | if(HOSTDATA(shpnt)->debug & debug_eh) { | 1584 | if(HOSTDATA(shpnt)->debug & debug_eh) { |
1570 | printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC)); | 1585 | printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC)); |
@@ -1573,13 +1588,13 @@ static void busfree_run(struct Scsi_Host *shpnt) | |||
1573 | #endif | 1588 | #endif |
1574 | 1589 | ||
1575 | /* restore old command */ | 1590 | /* restore old command */ |
1576 | memcpy((void *) DONE_SC->cmnd, (void *) DONE_SC->data_cmnd, sizeof(DONE_SC->data_cmnd)); | 1591 | memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd)); |
1577 | DONE_SC->request_buffer = DONE_SC->buffer; | 1592 | cmd->request_buffer = sc->request_buffer; |
1578 | DONE_SC->request_bufflen = DONE_SC->bufflen; | 1593 | cmd->request_bufflen = sc->request_bufflen; |
1579 | DONE_SC->use_sg = DONE_SC->old_use_sg; | 1594 | cmd->use_sg = sc->use_sg; |
1580 | DONE_SC->cmd_len = DONE_SC->old_cmd_len; | 1595 | cmd->cmd_len = sc->cmd_len; |
1581 | 1596 | ||
1582 | DONE_SC->SCp.Status = 0x02; | 1597 | cmd->SCp.Status = 0x02; |
1583 | 1598 | ||
1584 | HOSTDATA(shpnt)->commands--; | 1599 | HOSTDATA(shpnt)->commands--; |
1585 | if (!HOSTDATA(shpnt)->commands) | 1600 | if (!HOSTDATA(shpnt)->commands) |
@@ -3932,16 +3947,17 @@ static int __init aha152x_init(void) | |||
3932 | #endif | 3947 | #endif |
3933 | } | 3948 | } |
3934 | 3949 | ||
3935 | return registered_count>0; | 3950 | return 1; |
3936 | } | 3951 | } |
3937 | 3952 | ||
3938 | static void __exit aha152x_exit(void) | 3953 | static void __exit aha152x_exit(void) |
3939 | { | 3954 | { |
3940 | int i; | 3955 | struct aha152x_hostdata *hd; |
3956 | |||
3957 | list_for_each_entry(hd, &aha152x_host_list, host_list) { | ||
3958 | struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata); | ||
3941 | 3959 | ||
3942 | for(i=0; i<ARRAY_SIZE(setup); i++) { | 3960 | aha152x_release(shost); |
3943 | aha152x_release(aha152x_host[i]); | ||
3944 | aha152x_host[i]=NULL; | ||
3945 | } | 3961 | } |
3946 | } | 3962 | } |
3947 | 3963 | ||