diff options
author | Brian King <brking@linux.vnet.ibm.com> | 2010-02-21 11:37:57 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-03-03 08:02:41 -0500 |
commit | 64355b929dec0cb6271e4ac7834c9cf262961e40 (patch) | |
tree | aa1768917c57fdb95f7320a499f27bf76af55d08 /drivers/scsi/ibmvscsi | |
parent | c03af1ae1cce97a5530b907ea03625ce6e00214e (diff) |
[SCSI] ibmvscsi: Add suspend/resume support
Adds support for resuming from suspend for IBM VSCSI devices. We may have
lost an interrupt over the suspend, so we just kick the interrupt handler
to process anything that is outstanding. We expect to find a transport event
indicating we need to reestablish our CRQ.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/ibmvscsi')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 19 | ||||
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.h | 1 | ||||
-rw-r--r-- | drivers/scsi/ibmvscsi/iseries_vscsi.c | 6 | ||||
-rw-r--r-- | drivers/scsi/ibmvscsi/rpa_vscsi.c | 13 |
4 files changed, 39 insertions, 0 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index e3a18e0ef276..dc1bcbe3b176 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -71,6 +71,7 @@ | |||
71 | #include <linux/dma-mapping.h> | 71 | #include <linux/dma-mapping.h> |
72 | #include <linux/delay.h> | 72 | #include <linux/delay.h> |
73 | #include <linux/of.h> | 73 | #include <linux/of.h> |
74 | #include <linux/pm.h> | ||
74 | #include <asm/firmware.h> | 75 | #include <asm/firmware.h> |
75 | #include <asm/vio.h> | 76 | #include <asm/vio.h> |
76 | #include <scsi/scsi.h> | 77 | #include <scsi/scsi.h> |
@@ -1991,6 +1992,19 @@ static int ibmvscsi_remove(struct vio_dev *vdev) | |||
1991 | } | 1992 | } |
1992 | 1993 | ||
1993 | /** | 1994 | /** |
1995 | * ibmvscsi_resume: Resume from suspend | ||
1996 | * @dev: device struct | ||
1997 | * | ||
1998 | * We may have lost an interrupt across suspend/resume, so kick the | ||
1999 | * interrupt handler | ||
2000 | */ | ||
2001 | static int ibmvscsi_resume(struct device *dev) | ||
2002 | { | ||
2003 | struct ibmvscsi_host_data *hostdata = dev_get_drvdata(dev); | ||
2004 | return ibmvscsi_ops->resume(hostdata); | ||
2005 | } | ||
2006 | |||
2007 | /** | ||
1994 | * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we | 2008 | * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we |
1995 | * support. | 2009 | * support. |
1996 | */ | 2010 | */ |
@@ -2000,6 +2014,10 @@ static struct vio_device_id ibmvscsi_device_table[] __devinitdata = { | |||
2000 | }; | 2014 | }; |
2001 | MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table); | 2015 | MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table); |
2002 | 2016 | ||
2017 | static struct dev_pm_ops ibmvscsi_pm_ops = { | ||
2018 | .resume = ibmvscsi_resume | ||
2019 | }; | ||
2020 | |||
2003 | static struct vio_driver ibmvscsi_driver = { | 2021 | static struct vio_driver ibmvscsi_driver = { |
2004 | .id_table = ibmvscsi_device_table, | 2022 | .id_table = ibmvscsi_device_table, |
2005 | .probe = ibmvscsi_probe, | 2023 | .probe = ibmvscsi_probe, |
@@ -2008,6 +2026,7 @@ static struct vio_driver ibmvscsi_driver = { | |||
2008 | .driver = { | 2026 | .driver = { |
2009 | .name = "ibmvscsi", | 2027 | .name = "ibmvscsi", |
2010 | .owner = THIS_MODULE, | 2028 | .owner = THIS_MODULE, |
2029 | .pm = &ibmvscsi_pm_ops, | ||
2011 | } | 2030 | } |
2012 | }; | 2031 | }; |
2013 | 2032 | ||
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 76425303def0..9cb7c6a773e1 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h | |||
@@ -120,6 +120,7 @@ struct ibmvscsi_ops { | |||
120 | struct ibmvscsi_host_data *hostdata); | 120 | struct ibmvscsi_host_data *hostdata); |
121 | int (*send_crq)(struct ibmvscsi_host_data *hostdata, | 121 | int (*send_crq)(struct ibmvscsi_host_data *hostdata, |
122 | u64 word1, u64 word2); | 122 | u64 word1, u64 word2); |
123 | int (*resume) (struct ibmvscsi_host_data *hostdata); | ||
123 | }; | 124 | }; |
124 | 125 | ||
125 | extern struct ibmvscsi_ops iseriesvscsi_ops; | 126 | extern struct ibmvscsi_ops iseriesvscsi_ops; |
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c index 0775fdee5fa8..f4776451a754 100644 --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c | |||
@@ -158,10 +158,16 @@ static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata, | |||
158 | 0); | 158 | 0); |
159 | } | 159 | } |
160 | 160 | ||
161 | static int iseriesvscsi_resume(struct ibmvscsi_host_data *hostdata) | ||
162 | { | ||
163 | return 0; | ||
164 | } | ||
165 | |||
161 | struct ibmvscsi_ops iseriesvscsi_ops = { | 166 | struct ibmvscsi_ops iseriesvscsi_ops = { |
162 | .init_crq_queue = iseriesvscsi_init_crq_queue, | 167 | .init_crq_queue = iseriesvscsi_init_crq_queue, |
163 | .release_crq_queue = iseriesvscsi_release_crq_queue, | 168 | .release_crq_queue = iseriesvscsi_release_crq_queue, |
164 | .reset_crq_queue = iseriesvscsi_reset_crq_queue, | 169 | .reset_crq_queue = iseriesvscsi_reset_crq_queue, |
165 | .reenable_crq_queue = iseriesvscsi_reenable_crq_queue, | 170 | .reenable_crq_queue = iseriesvscsi_reenable_crq_queue, |
166 | .send_crq = iseriesvscsi_send_crq, | 171 | .send_crq = iseriesvscsi_send_crq, |
172 | .resume = iseriesvscsi_resume, | ||
167 | }; | 173 | }; |
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 462a8574dad9..63a30cbbf9de 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c | |||
@@ -334,10 +334,23 @@ static int rpavscsi_reenable_crq_queue(struct crq_queue *queue, | |||
334 | return rc; | 334 | return rc; |
335 | } | 335 | } |
336 | 336 | ||
337 | /** | ||
338 | * rpavscsi_resume: - resume after suspend | ||
339 | * @hostdata: ibmvscsi_host_data of host | ||
340 | * | ||
341 | */ | ||
342 | static int rpavscsi_resume(struct ibmvscsi_host_data *hostdata) | ||
343 | { | ||
344 | vio_disable_interrupts(to_vio_dev(hostdata->dev)); | ||
345 | tasklet_schedule(&hostdata->srp_task); | ||
346 | return 0; | ||
347 | } | ||
348 | |||
337 | struct ibmvscsi_ops rpavscsi_ops = { | 349 | struct ibmvscsi_ops rpavscsi_ops = { |
338 | .init_crq_queue = rpavscsi_init_crq_queue, | 350 | .init_crq_queue = rpavscsi_init_crq_queue, |
339 | .release_crq_queue = rpavscsi_release_crq_queue, | 351 | .release_crq_queue = rpavscsi_release_crq_queue, |
340 | .reset_crq_queue = rpavscsi_reset_crq_queue, | 352 | .reset_crq_queue = rpavscsi_reset_crq_queue, |
341 | .reenable_crq_queue = rpavscsi_reenable_crq_queue, | 353 | .reenable_crq_queue = rpavscsi_reenable_crq_queue, |
342 | .send_crq = rpavscsi_send_crq, | 354 | .send_crq = rpavscsi_send_crq, |
355 | .resume = rpavscsi_resume, | ||
343 | }; | 356 | }; |