diff options
-rw-r--r-- | drivers/scsi/3w-9xxx.c | 101 | ||||
-rw-r--r-- | drivers/scsi/3w-9xxx.h | 2 |
2 files changed, 100 insertions, 3 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" |
103 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; | 104 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; |
104 | static unsigned int twa_device_extension_count; | 105 | static unsigned int twa_device_extension_count; |
105 | static int twa_major = -1; | 106 | static 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 */ | ||
2188 | static 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 */ | ||
2217 | static 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 | |||
2270 | out_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 */ |
2186 | static struct pci_device_id twa_pci_tbl[] __devinitdata = { | 2279 | static 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 | ||
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 1729a8785fea..2893eec78ed2 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h | |||
@@ -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 |