aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2008-02-27 18:27:16 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-27 18:53:43 -0500
commitb31ddd31c266c2ad1b708cad0d3d8e0aa7fa2737 (patch)
treeecc7a9aeb4eb74a103b15423ac6aeb60f4be7420
parent31ed0bf439a15363c28c7a239f52eb127cb6feb3 (diff)
[SCSI] gdth: bugfix for the at-exit problems
gdth_exit would first remove all cards then stop the timer and would not sync with the timer function. This caused a crash in gdth_timer() when module was unloaded. So del_timer_sync the timer before we delete the cards. also the reboot notifier function would crash. So clean that up and fix the crashes. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Tested-by: Joerg Dorchain: <joerg@dorchain.net> Tested-by: Stefan Priebe <s.priebe@allied-internet.ag> Tested-by: Jon Chelton <jchelton@ffpglobal.com> Cc: Stable Tree <stable@kernel.org> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/gdth.c82
1 files changed, 28 insertions, 54 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 6d67f5c0eb8e..23d1a28b929d 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -182,7 +182,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
182 unsigned int cmd, unsigned long arg); 182 unsigned int cmd, unsigned long arg);
183 183
184static void gdth_flush(gdth_ha_str *ha); 184static void gdth_flush(gdth_ha_str *ha);
185static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
186static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); 185static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
187static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, 186static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
188 struct gdth_cmndinfo *cmndinfo); 187 struct gdth_cmndinfo *cmndinfo);
@@ -417,12 +416,6 @@ static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
417#include "gdth_proc.h" 416#include "gdth_proc.h"
418#include "gdth_proc.c" 417#include "gdth_proc.c"
419 418
420/* notifier block to get a notify on system shutdown/halt/reboot */
421static struct notifier_block gdth_notifier = {
422 gdth_halt, NULL, 0
423};
424static int notifier_disabled = 0;
425
426static gdth_ha_str *gdth_find_ha(int hanum) 419static gdth_ha_str *gdth_find_ha(int hanum)
427{ 420{
428 gdth_ha_str *ha; 421 gdth_ha_str *ha;
@@ -3794,6 +3787,8 @@ static void gdth_timeout(ulong data)
3794 gdth_ha_str *ha; 3787 gdth_ha_str *ha;
3795 ulong flags; 3788 ulong flags;
3796 3789
3790 BUG_ON(list_empty(&gdth_instances));
3791
3797 ha = list_first_entry(&gdth_instances, gdth_ha_str, list); 3792 ha = list_first_entry(&gdth_instances, gdth_ha_str, list);
3798 spin_lock_irqsave(&ha->smp_lock, flags); 3793 spin_lock_irqsave(&ha->smp_lock, flags);
3799 3794
@@ -4669,45 +4664,6 @@ static void gdth_flush(gdth_ha_str *ha)
4669 } 4664 }
4670} 4665}
4671 4666
4672/* shutdown routine */
4673static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
4674{
4675 gdth_ha_str *ha;
4676#ifndef __alpha__
4677 gdth_cmd_str gdtcmd;
4678 char cmnd[MAX_COMMAND_SIZE];
4679#endif
4680
4681 if (notifier_disabled)
4682 return NOTIFY_OK;
4683
4684 TRACE2(("gdth_halt() event %d\n",(int)event));
4685 if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
4686 return NOTIFY_DONE;
4687
4688 notifier_disabled = 1;
4689 printk("GDT-HA: Flushing all host drives .. ");
4690 list_for_each_entry(ha, &gdth_instances, list) {
4691 gdth_flush(ha);
4692
4693#ifndef __alpha__
4694 /* controller reset */
4695 memset(cmnd, 0xff, MAX_COMMAND_SIZE);
4696 gdtcmd.BoardNode = LOCALBOARD;
4697 gdtcmd.Service = CACHESERVICE;
4698 gdtcmd.OpCode = GDT_RESET;
4699 TRACE2(("gdth_halt(): reset controller %d\n", ha->hanum));
4700 gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL);
4701#endif
4702 }
4703 printk("Done.\n");
4704
4705#ifdef GDTH_STATISTICS
4706 del_timer(&gdth_timer);
4707#endif
4708 return NOTIFY_OK;
4709}
4710
4711/* configure lun */ 4667/* configure lun */
4712static int gdth_slave_configure(struct scsi_device *sdev) 4668static int gdth_slave_configure(struct scsi_device *sdev)
4713{ 4669{
@@ -5142,13 +5098,13 @@ static void gdth_remove_one(gdth_ha_str *ha)
5142 5098
5143 scsi_remove_host(shp); 5099 scsi_remove_host(shp);
5144 5100
5101 gdth_flush(ha);
5102
5145 if (ha->sdev) { 5103 if (ha->sdev) {
5146 scsi_free_host_dev(ha->sdev); 5104 scsi_free_host_dev(ha->sdev);
5147 ha->sdev = NULL; 5105 ha->sdev = NULL;
5148 } 5106 }
5149 5107
5150 gdth_flush(ha);
5151
5152 if (shp->irq) 5108 if (shp->irq)
5153 free_irq(shp->irq,ha); 5109 free_irq(shp->irq,ha);
5154 5110
@@ -5174,6 +5130,24 @@ static void gdth_remove_one(gdth_ha_str *ha)
5174 scsi_host_put(shp); 5130 scsi_host_put(shp);
5175} 5131}
5176 5132
5133static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
5134{
5135 gdth_ha_str *ha;
5136
5137 TRACE2(("gdth_halt() event %d\n", (int)event));
5138 if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
5139 return NOTIFY_DONE;
5140
5141 list_for_each_entry(ha, &gdth_instances, list)
5142 gdth_flush(ha);
5143
5144 return NOTIFY_OK;
5145}
5146
5147static struct notifier_block gdth_notifier = {
5148 gdth_halt, NULL, 0
5149};
5150
5177static int __init gdth_init(void) 5151static int __init gdth_init(void)
5178{ 5152{
5179 if (disable) { 5153 if (disable) {
@@ -5236,7 +5210,6 @@ static int __init gdth_init(void)
5236 add_timer(&gdth_timer); 5210 add_timer(&gdth_timer);
5237#endif 5211#endif
5238 major = register_chrdev(0,"gdth", &gdth_fops); 5212 major = register_chrdev(0,"gdth", &gdth_fops);
5239 notifier_disabled = 0;
5240 register_reboot_notifier(&gdth_notifier); 5213 register_reboot_notifier(&gdth_notifier);
5241 gdth_polling = FALSE; 5214 gdth_polling = FALSE;
5242 return 0; 5215 return 0;
@@ -5246,14 +5219,15 @@ static void __exit gdth_exit(void)
5246{ 5219{
5247 gdth_ha_str *ha; 5220 gdth_ha_str *ha;
5248 5221
5249 list_for_each_entry(ha, &gdth_instances, list) 5222 unregister_chrdev(major, "gdth");
5250 gdth_remove_one(ha); 5223 unregister_reboot_notifier(&gdth_notifier);
5251 5224
5252#ifdef GDTH_STATISTICS 5225#ifdef GDTH_STATISTICS
5253 del_timer(&gdth_timer); 5226 del_timer_sync(&gdth_timer);
5254#endif 5227#endif
5255 unregister_chrdev(major,"gdth"); 5228
5256 unregister_reboot_notifier(&gdth_notifier); 5229 list_for_each_entry(ha, &gdth_instances, list)
5230 gdth_remove_one(ha);
5257} 5231}
5258 5232
5259module_init(gdth_init); 5233module_init(gdth_init);