Re: [PATCH] 2.6 aacraid: shutdown notification

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The pci_driver->shutdown method should be used instead of registering
a reboot notifier.

Brian

Mark Haverkamp wrote:
> Received from Mark Salyzyn at Adaptec
> 
> Add in reboot notification 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.
> 
> 
> Patch against scsi-misc-2.6 git tree.
> 
> Signed-off-by: Mark Haverkamp <markh@xxxxxxxx>
> 
>  aacraid.h |    4 ++++
>  linit.c   |   28 +++++++++++++++++++++++++++-
>  rkt.c     |   20 ++++++++++++++++++++
>  rx.c      |   20 ++++++++++++++++++++
>  sa.c      |   22 ++++++++++++++++++++--
>  5 files changed, 91 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
> --- a/drivers/scsi/aacraid/aacraid.h
> +++ b/drivers/scsi/aacraid/aacraid.h
> @@ -460,6 +460,7 @@ struct adapter_ops
>  {
>  	void (*adapter_interrupt)(struct aac_dev *dev);
>  	void (*adapter_notify)(struct aac_dev *dev, u32 event);
> +	void (*adapter_disable_int)(struct aac_dev *dev);
>  	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);
>  	int  (*adapter_check_health)(struct aac_dev *dev);
>  };
> @@ -970,6 +971,9 @@ struct aac_dev
>  #define aac_adapter_notify(dev, event) \
>  	(dev)->a_ops.adapter_notify(dev, event)
>  
> +#define aac_adapter_disable_int(dev) \
> +	(dev)->a_ops.adapter_disable_int(dev)
> +
>  #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
>  	(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
>  
> diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
> --- a/drivers/scsi/aacraid/linit.c
> +++ b/drivers/scsi/aacraid/linit.c
> @@ -55,6 +55,7 @@
>  #include <scsi/scsi_tcq.h>
>  #include <scsi/scsicam.h>
>  #include <scsi/scsi_eh.h>
> +#include <linux/reboot.h>
>  
>  #include "aacraid.h"
>  
> @@ -815,11 +816,12 @@ static int __devinit aac_probe_one(struc
>  
>  	return 0;
>  
> -out_deinit:
> + out_deinit:
>  	kill_proc(aac->thread_pid, SIGKILL, 0);
>  	wait_for_completion(&aac->aif_completion);
>  
>  	aac_send_shutdown(aac);
> +	aac_adapter_disable_int(aac);
>  	fib_map_free(aac);
>  	pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
>  	kfree(aac->queues);
> @@ -847,6 +849,7 @@ static void __devexit aac_remove_one(str
>  	wait_for_completion(&aac->aif_completion);
>  
>  	aac_send_shutdown(aac);
> +	aac_adapter_disable_int(aac);
>  	fib_map_free(aac);
>  	pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
>  			aac->comm_phys);
> @@ -869,6 +872,26 @@ static struct pci_driver aac_pci_driver 
>  	.remove		= __devexit_p(aac_remove_one),
>  };
>  
> +static int aac_reboot_event(struct notifier_block * n, ulong code, void *p)
> +{
> +	if ((code == SYS_RESTART) ||
> +	  (code == SYS_HALT) ||
> +	  (code == SYS_POWER_OFF)) {
> +		struct aac_dev *aac;
> +
> +		list_for_each_entry(aac, &aac_devices, entry)
> +			aac_send_shutdown(aac);
> +	}
> +	return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block aac_reboot_notifier =
> +{
> +	aac_reboot_event,
> +	NULL,
> +	0
> +};
> +
>  static int __init aac_init(void)
>  {
>  	int error;
> @@ -885,12 +908,15 @@ static int __init aac_init(void)
>  		printk(KERN_WARNING
>  		       "aacraid: unable to register \"aac\" device.\n");
>  	}
> +	register_reboot_notifier(&aac_reboot_notifier);
> +
>  	return 0;
>  }
>  
>  static void __exit aac_exit(void)
>  {
>  	unregister_chrdev(aac_cfg_major, "aac");
> +	unregister_reboot_notifier(&aac_reboot_notifier);
>  	pci_unregister_driver(&aac_pci_driver);
>  }
>  
> diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
> --- a/drivers/scsi/aacraid/rkt.c
> +++ b/drivers/scsi/aacraid/rkt.c
> @@ -88,6 +88,16 @@ static irqreturn_t aac_rkt_intr(int irq,
>  }
>  
>  /**
> + *	aac_rkt_disable_interrupt	-	Disable interrupts
> + *	@dev: Adapter
> + */
> +
> +static void aac_rkt_disable_interrupt(struct aac_dev *dev)
> +{
> +	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
> +}
> +
> +/**
>   *	rkt_sync_cmd	-	send a command and wait
>   *	@dev: Adapter
>   *	@command: Command to execute
> @@ -412,10 +422,19 @@ int aac_rkt_init(struct aac_dev *dev)
>  	 *	Fill in the function dispatch table.
>  	 */
>  	dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
> +	dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
>  	dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
>  	dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
>  	dev->a_ops.adapter_check_health = aac_rkt_check_health;
>  
> +	/*
> +	 *	First clear out all interrupts.  Then enable the one's that we
> +	 *	can handle.
> +	 */
> +	rkt_writeb(dev, MUnit.OIMR, 0xff);
> +	rkt_writel(dev, MUnit.ODR, 0xffffffff);
> +	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
> +
>  	if (aac_init_adapter(dev) == NULL)
>  		goto error_irq;
>  	/*
> @@ -438,6 +457,7 @@ error_kfree:
>  	kfree(dev->queues);
>  
>  error_irq:
> +	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
>  	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
>  
>  error_iounmap:
> diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
> --- a/drivers/scsi/aacraid/rx.c
> +++ b/drivers/scsi/aacraid/rx.c
> @@ -88,6 +88,16 @@ static irqreturn_t aac_rx_intr(int irq, 
>  }
>  
>  /**
> + *	aac_rx_disable_interrupt	-	Disable interrupts
> + *	@dev: Adapter
> + */
> +
> +static void aac_rx_disable_interrupt(struct aac_dev *dev)
> +{
> +	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
> +}
> +
> +/**
>   *	rx_sync_cmd	-	send a command and wait
>   *	@dev: Adapter
>   *	@command: Command to execute
> @@ -412,10 +422,19 @@ int aac_rx_init(struct aac_dev *dev)
>  	 *	Fill in the function dispatch table.
>  	 */
>  	dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
> +	dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
>  	dev->a_ops.adapter_notify = aac_rx_notify_adapter;
>  	dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
>  	dev->a_ops.adapter_check_health = aac_rx_check_health;
>  
> +	/*
> +	 *	First clear out all interrupts.  Then enable the one's that we
> +	 *	can handle.
> +	 */
> +	rx_writeb(dev, MUnit.OIMR, 0xff);
> +	rx_writel(dev, MUnit.ODR, 0xffffffff);
> +	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
> +
>  	if (aac_init_adapter(dev) == NULL)
>  		goto error_irq;
>  	/*
> @@ -438,6 +457,7 @@ error_kfree:
>  	kfree(dev->queues);
>  
>  error_irq:
> +	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
>  	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
>  
>  error_iounmap:
> diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
> --- a/drivers/scsi/aacraid/sa.c
> +++ b/drivers/scsi/aacraid/sa.c
> @@ -82,6 +82,16 @@ static irqreturn_t aac_sa_intr(int irq, 
>  }
>  
>  /**
> + *	aac_sa_disable_interrupt	-	disable interrupt
> + *	@dev: Which adapter to enable.
> + */
> +
> +static void aac_sa_disable_interrupt (struct aac_dev *dev)
> +{
> +	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
> +}
> +
> +/**
>   *	aac_sa_notify_adapter		-	handle adapter notification
>   *	@dev:	Adapter that notification is for
>   *	@event:	Event to notidy
> @@ -214,9 +224,8 @@ static int sa_sync_cmd(struct aac_dev *d
>   
>  static void aac_sa_interrupt_adapter (struct aac_dev *dev)
>  {
> -	u32 ret;
>  	sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
> -			&ret, NULL, NULL, NULL, NULL);
> +			NULL, NULL, NULL, NULL, NULL);
>  }
>  
>  /**
> @@ -352,10 +361,18 @@ int aac_sa_init(struct aac_dev *dev)
>  	 */
>  
>  	dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
> +	dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
>  	dev->a_ops.adapter_notify = aac_sa_notify_adapter;
>  	dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
>  	dev->a_ops.adapter_check_health = aac_sa_check_health;
>  
> +	/*
> +	 *	First clear out all interrupts.  Then enable the one's that 
> +	 *	we can handle.
> +	 */
> +	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
> +	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | 
> +				DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
>  
>  	if(aac_init_adapter(dev) == NULL)
>  		goto error_irq;
> @@ -381,6 +398,7 @@ error_kfree:
>  	kfree(dev->queues);
>  
>  error_irq:
> +	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
>  	free_irq(dev->scsi_host_ptr->irq, (void *)dev);
>  
>  error_iounmap:
> 


-- 
Brian King
eServer Storage I/O
IBM Linux Technology Center
-
: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux