aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/3w-9xxx.c
diff options
context:
space:
mode:
authoradam radford <aradford@gmail.com>2009-03-09 16:15:01 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-13 16:46:42 -0400
commit7a252fe7bcf64f1174b55c5c696ef2506b849f80 (patch)
treebee05c44f4864b300c78cfc63ad399461bea6fc8 /drivers/scsi/3w-9xxx.c
parent4ab3b73f85ca2e99d9dbdb55ac13e57327a7e915 (diff)
[SCSI] 3w-9xxx: add power management support
Signed-off-by: Adam Radford <aradford@gmail.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/3w-9xxx.c')
-rw-r--r--drivers/scsi/3w-9xxx.c101
1 files changed, 99 insertions, 2 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 5311317c2e4c..a12783ebb42d 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -4,7 +4,7 @@
4 Written By: Adam Radford <linuxraid@amcc.com> 4 Written By: Adam Radford <linuxraid@amcc.com>
5 Modifications By: Tom Couch <linuxraid@amcc.com> 5 Modifications By: Tom Couch <linuxraid@amcc.com>
6 6
7 Copyright (C) 2004-2008 Applied Micro Circuits Corporation. 7 Copyright (C) 2004-2009 Applied Micro Circuits Corporation.
8 8
9 This program is free software; you can redistribute it and/or modify 9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
@@ -75,6 +75,7 @@
75 Add MSI support and "use_msi" module parameter. 75 Add MSI support and "use_msi" module parameter.
76 Fix bug in twa_get_param() on 4GB+. 76 Fix bug in twa_get_param() on 4GB+.
77 Use pci_resource_len() for ioremap(). 77 Use pci_resource_len() for ioremap().
78 2.26.02.012 - Add power management support.
78*/ 79*/
79 80
80#include <linux/module.h> 81#include <linux/module.h>
@@ -99,7 +100,7 @@
99#include "3w-9xxx.h" 100#include "3w-9xxx.h"
100 101
101/* Globals */ 102/* Globals */
102#define TW_DRIVER_VERSION "2.26.02.011" 103#define TW_DRIVER_VERSION "2.26.02.012"
103static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; 104static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
104static unsigned int twa_device_extension_count; 105static unsigned int twa_device_extension_count;
105static int twa_major = -1; 106static int twa_major = -1;
@@ -2182,6 +2183,98 @@ static void twa_remove(struct pci_dev *pdev)
2182 twa_device_extension_count--; 2183 twa_device_extension_count--;
2183} /* End twa_remove() */ 2184} /* End twa_remove() */
2184 2185
2186#ifdef CONFIG_PM
2187/* This function is called on PCI suspend */
2188static int twa_suspend(struct pci_dev *pdev, pm_message_t state)
2189{
2190 struct Scsi_Host *host = pci_get_drvdata(pdev);
2191 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
2192
2193 printk(KERN_WARNING "3w-9xxx: Suspending host %d.\n", tw_dev->host->host_no);
2194
2195 TW_DISABLE_INTERRUPTS(tw_dev);
2196 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
2197
2198 if (test_bit(TW_USING_MSI, &tw_dev->flags))
2199 pci_disable_msi(pdev);
2200
2201 /* Tell the card we are shutting down */
2202 if (twa_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) {
2203 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x38, "Connection shutdown failed during suspend");
2204 } else {
2205 printk(KERN_WARNING "3w-9xxx: Suspend complete.\n");
2206 }
2207 TW_CLEAR_ALL_INTERRUPTS(tw_dev);
2208
2209 pci_save_state(pdev);
2210 pci_disable_device(pdev);
2211 pci_set_power_state(pdev, pci_choose_state(pdev, state));
2212
2213 return 0;
2214} /* End twa_suspend() */
2215
2216/* This function is called on PCI resume */
2217static int twa_resume(struct pci_dev *pdev)
2218{
2219 int retval = 0;
2220 struct Scsi_Host *host = pci_get_drvdata(pdev);
2221 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
2222
2223 printk(KERN_WARNING "3w-9xxx: Resuming host %d.\n", tw_dev->host->host_no);
2224 pci_set_power_state(pdev, PCI_D0);
2225 pci_enable_wake(pdev, PCI_D0, 0);
2226 pci_restore_state(pdev);
2227
2228 retval = pci_enable_device(pdev);
2229 if (retval) {
2230 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x39, "Enable device failed during resume");
2231 return retval;
2232 }
2233
2234 pci_set_master(pdev);
2235 pci_try_set_mwi(pdev);
2236
2237 if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)
2238 || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
2239 if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)
2240 || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
2241 TW_PRINTK(host, TW_DRIVER, 0x40, "Failed to set dma mask during resume");
2242 retval = -ENODEV;
2243 goto out_disable_device;
2244 }
2245
2246 /* Initialize the card */
2247 if (twa_reset_sequence(tw_dev, 0)) {
2248 retval = -ENODEV;
2249 goto out_disable_device;
2250 }
2251
2252 /* Now setup the interrupt handler */
2253 retval = request_irq(pdev->irq, twa_interrupt, IRQF_SHARED, "3w-9xxx", tw_dev);
2254 if (retval) {
2255 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x42, "Error requesting IRQ during resume");
2256 retval = -ENODEV;
2257 goto out_disable_device;
2258 }
2259
2260 /* Now enable MSI if enabled */
2261 if (test_bit(TW_USING_MSI, &tw_dev->flags))
2262 pci_enable_msi(pdev);
2263
2264 /* Re-enable interrupts on the card */
2265 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
2266
2267 printk(KERN_WARNING "3w-9xxx: Resume complete.\n");
2268 return 0;
2269
2270out_disable_device:
2271 scsi_remove_host(host);
2272 pci_disable_device(pdev);
2273
2274 return retval;
2275} /* End twa_resume() */
2276#endif
2277
2185/* PCI Devices supported by this driver */ 2278/* PCI Devices supported by this driver */
2186static struct pci_device_id twa_pci_tbl[] __devinitdata = { 2279static struct pci_device_id twa_pci_tbl[] __devinitdata = {
2187 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000, 2280 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000,
@@ -2202,6 +2295,10 @@ static struct pci_driver twa_driver = {
2202 .id_table = twa_pci_tbl, 2295 .id_table = twa_pci_tbl,
2203 .probe = twa_probe, 2296 .probe = twa_probe,
2204 .remove = twa_remove, 2297 .remove = twa_remove,
2298#ifdef CONFIG_PM
2299 .suspend = twa_suspend,
2300 .resume = twa_resume,
2301#endif
2205 .shutdown = twa_shutdown 2302 .shutdown = twa_shutdown
2206}; 2303};
2207 2304