aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Haverkamp <markh@osdl.org>2005-08-03 18:39:01 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-08-05 17:51:11 -0400
commitbd1aac809ddbcf7772cfd809d8cfb29c729c6cf9 (patch)
tree7ec25f58f22929ee48495addf8facda797668852
parentc7f476023f57145357df32346b7de9202ce47d5f (diff)
[SCSI] aacraid: driver shutdown method
Add in pci shutdown method so that the adapter shuts down correctly and flushes its cache. Shutdown should also disable the adapter's interrupt when shutdown (in particularly if the driver is rmmod'd) to prevent spurious hardware activities. Signed-off-by: Mark Haverkamp <markh@osdl.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/aacraid/aacraid.h4
-rw-r--r--drivers/scsi/aacraid/linit.c13
-rw-r--r--drivers/scsi/aacraid/rkt.c20
-rw-r--r--drivers/scsi/aacraid/rx.c20
-rw-r--r--drivers/scsi/aacraid/sa.c22
5 files changed, 76 insertions, 3 deletions
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index ddbbb85b3a7c..6f4906ee9a5e 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -460,6 +460,7 @@ struct adapter_ops
460{ 460{
461 void (*adapter_interrupt)(struct aac_dev *dev); 461 void (*adapter_interrupt)(struct aac_dev *dev);
462 void (*adapter_notify)(struct aac_dev *dev, u32 event); 462 void (*adapter_notify)(struct aac_dev *dev, u32 event);
463 void (*adapter_disable_int)(struct aac_dev *dev);
463 int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); 464 int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
464 int (*adapter_check_health)(struct aac_dev *dev); 465 int (*adapter_check_health)(struct aac_dev *dev);
465}; 466};
@@ -994,6 +995,9 @@ struct aac_dev
994#define aac_adapter_notify(dev, event) \ 995#define aac_adapter_notify(dev, event) \
995 (dev)->a_ops.adapter_notify(dev, event) 996 (dev)->a_ops.adapter_notify(dev, event)
996 997
998#define aac_adapter_disable_int(dev) \
999 (dev)->a_ops.adapter_disable_int(dev)
1000
997#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \ 1001#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
998 (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) 1002 (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
999 1003
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index b6dda99f5083..41255f7893d0 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -849,11 +849,12 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
849 849
850 return 0; 850 return 0;
851 851
852out_deinit: 852 out_deinit:
853 kill_proc(aac->thread_pid, SIGKILL, 0); 853 kill_proc(aac->thread_pid, SIGKILL, 0);
854 wait_for_completion(&aac->aif_completion); 854 wait_for_completion(&aac->aif_completion);
855 855
856 aac_send_shutdown(aac); 856 aac_send_shutdown(aac);
857 aac_adapter_disable_int(aac);
857 fib_map_free(aac); 858 fib_map_free(aac);
858 pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); 859 pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
859 kfree(aac->queues); 860 kfree(aac->queues);
@@ -870,6 +871,13 @@ out_deinit:
870 return error; 871 return error;
871} 872}
872 873
874static void aac_shutdown(struct pci_dev *dev)
875{
876 struct Scsi_Host *shost = pci_get_drvdata(dev);
877 struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
878 aac_send_shutdown(aac);
879}
880
873static void __devexit aac_remove_one(struct pci_dev *pdev) 881static void __devexit aac_remove_one(struct pci_dev *pdev)
874{ 882{
875 struct Scsi_Host *shost = pci_get_drvdata(pdev); 883 struct Scsi_Host *shost = pci_get_drvdata(pdev);
@@ -881,6 +889,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
881 wait_for_completion(&aac->aif_completion); 889 wait_for_completion(&aac->aif_completion);
882 890
883 aac_send_shutdown(aac); 891 aac_send_shutdown(aac);
892 aac_adapter_disable_int(aac);
884 fib_map_free(aac); 893 fib_map_free(aac);
885 pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, 894 pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
886 aac->comm_phys); 895 aac->comm_phys);
@@ -901,6 +910,7 @@ static struct pci_driver aac_pci_driver = {
901 .id_table = aac_pci_tbl, 910 .id_table = aac_pci_tbl,
902 .probe = aac_probe_one, 911 .probe = aac_probe_one,
903 .remove = __devexit_p(aac_remove_one), 912 .remove = __devexit_p(aac_remove_one),
913 .shutdown = aac_shutdown,
904}; 914};
905 915
906static int __init aac_init(void) 916static int __init aac_init(void)
@@ -919,6 +929,7 @@ static int __init aac_init(void)
919 printk(KERN_WARNING 929 printk(KERN_WARNING
920 "aacraid: unable to register \"aac\" device.\n"); 930 "aacraid: unable to register \"aac\" device.\n");
921 } 931 }
932
922 return 0; 933 return 0;
923} 934}
924 935
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 7d68b7825137..557287a0b80b 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
88} 88}
89 89
90/** 90/**
91 * aac_rkt_disable_interrupt - Disable interrupts
92 * @dev: Adapter
93 */
94
95static void aac_rkt_disable_interrupt(struct aac_dev *dev)
96{
97 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
98}
99
100/**
91 * rkt_sync_cmd - send a command and wait 101 * rkt_sync_cmd - send a command and wait
92 * @dev: Adapter 102 * @dev: Adapter
93 * @command: Command to execute 103 * @command: Command to execute
@@ -412,10 +422,19 @@ int aac_rkt_init(struct aac_dev *dev)
412 * Fill in the function dispatch table. 422 * Fill in the function dispatch table.
413 */ 423 */
414 dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; 424 dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
425 dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
415 dev->a_ops.adapter_notify = aac_rkt_notify_adapter; 426 dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
416 dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; 427 dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
417 dev->a_ops.adapter_check_health = aac_rkt_check_health; 428 dev->a_ops.adapter_check_health = aac_rkt_check_health;
418 429
430 /*
431 * First clear out all interrupts. Then enable the one's that we
432 * can handle.
433 */
434 rkt_writeb(dev, MUnit.OIMR, 0xff);
435 rkt_writel(dev, MUnit.ODR, 0xffffffff);
436 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
437
419 if (aac_init_adapter(dev) == NULL) 438 if (aac_init_adapter(dev) == NULL)
420 goto error_irq; 439 goto error_irq;
421 /* 440 /*
@@ -438,6 +457,7 @@ error_kfree:
438 kfree(dev->queues); 457 kfree(dev->queues);
439 458
440error_irq: 459error_irq:
460 rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
441 free_irq(dev->scsi_host_ptr->irq, (void *)dev); 461 free_irq(dev->scsi_host_ptr->irq, (void *)dev);
442 462
443error_iounmap: 463error_iounmap:
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 1ff25f49fada..a8459faf87ca 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -88,6 +88,16 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
88} 88}
89 89
90/** 90/**
91 * aac_rx_disable_interrupt - Disable interrupts
92 * @dev: Adapter
93 */
94
95static void aac_rx_disable_interrupt(struct aac_dev *dev)
96{
97 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
98}
99
100/**
91 * rx_sync_cmd - send a command and wait 101 * rx_sync_cmd - send a command and wait
92 * @dev: Adapter 102 * @dev: Adapter
93 * @command: Command to execute 103 * @command: Command to execute
@@ -412,10 +422,19 @@ int aac_rx_init(struct aac_dev *dev)
412 * Fill in the function dispatch table. 422 * Fill in the function dispatch table.
413 */ 423 */
414 dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; 424 dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
425 dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
415 dev->a_ops.adapter_notify = aac_rx_notify_adapter; 426 dev->a_ops.adapter_notify = aac_rx_notify_adapter;
416 dev->a_ops.adapter_sync_cmd = rx_sync_cmd; 427 dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
417 dev->a_ops.adapter_check_health = aac_rx_check_health; 428 dev->a_ops.adapter_check_health = aac_rx_check_health;
418 429
430 /*
431 * First clear out all interrupts. Then enable the one's that we
432 * can handle.
433 */
434 rx_writeb(dev, MUnit.OIMR, 0xff);
435 rx_writel(dev, MUnit.ODR, 0xffffffff);
436 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
437
419 if (aac_init_adapter(dev) == NULL) 438 if (aac_init_adapter(dev) == NULL)
420 goto error_irq; 439 goto error_irq;
421 /* 440 /*
@@ -438,6 +457,7 @@ error_kfree:
438 kfree(dev->queues); 457 kfree(dev->queues);
439 458
440error_irq: 459error_irq:
460 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
441 free_irq(dev->scsi_host_ptr->irq, (void *)dev); 461 free_irq(dev->scsi_host_ptr->irq, (void *)dev);
442 462
443error_iounmap: 463error_iounmap:
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 0680249ab861..3900abc5850d 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -82,6 +82,16 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
82} 82}
83 83
84/** 84/**
85 * aac_sa_disable_interrupt - disable interrupt
86 * @dev: Which adapter to enable.
87 */
88
89static void aac_sa_disable_interrupt (struct aac_dev *dev)
90{
91 sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
92}
93
94/**
85 * aac_sa_notify_adapter - handle adapter notification 95 * aac_sa_notify_adapter - handle adapter notification
86 * @dev: Adapter that notification is for 96 * @dev: Adapter that notification is for
87 * @event: Event to notidy 97 * @event: Event to notidy
@@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
214 224
215static void aac_sa_interrupt_adapter (struct aac_dev *dev) 225static void aac_sa_interrupt_adapter (struct aac_dev *dev)
216{ 226{
217 u32 ret;
218 sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, 227 sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
219 &ret, NULL, NULL, NULL, NULL); 228 NULL, NULL, NULL, NULL, NULL);
220} 229}
221 230
222/** 231/**
@@ -352,10 +361,18 @@ int aac_sa_init(struct aac_dev *dev)
352 */ 361 */
353 362
354 dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; 363 dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
364 dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
355 dev->a_ops.adapter_notify = aac_sa_notify_adapter; 365 dev->a_ops.adapter_notify = aac_sa_notify_adapter;
356 dev->a_ops.adapter_sync_cmd = sa_sync_cmd; 366 dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
357 dev->a_ops.adapter_check_health = aac_sa_check_health; 367 dev->a_ops.adapter_check_health = aac_sa_check_health;
358 368
369 /*
370 * First clear out all interrupts. Then enable the one's that
371 * we can handle.
372 */
373 sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
374 sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 |
375 DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
359 376
360 if(aac_init_adapter(dev) == NULL) 377 if(aac_init_adapter(dev) == NULL)
361 goto error_irq; 378 goto error_irq;
@@ -381,6 +398,7 @@ error_kfree:
381 kfree(dev->queues); 398 kfree(dev->queues);
382 399
383error_irq: 400error_irq:
401 sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
384 free_irq(dev->scsi_host_ptr->irq, (void *)dev); 402 free_irq(dev->scsi_host_ptr->irq, (void *)dev);
385 403
386error_iounmap: 404error_iounmap: