ia64/xen-unstable
changeset 9604:ebbe237bd9e4
Fix a problem that was caused by recent changes to the xenbus's
behavior that cause the .remove function not to be called anymore
during suspend. Due to that the driver allocated one more interrupt on
every suspend/resume cycle. Otherwise some code reformatting,
cleanups and improvements on allocation and freeing of data structure.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
behavior that cause the .remove function not to be called anymore
during suspend. Due to that the driver allocated one more interrupt on
every suspend/resume cycle. Otherwise some code reformatting,
cleanups and improvements on allocation and freeing of data structure.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Thu Apr 06 09:39:30 2006 +0100 (2006-04-06) |
parents | 2a127b1f13b5 |
children | 568b8d8fc782 |
files | linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c |
line diff
1.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Apr 06 09:36:54 2006 +0100 1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Apr 06 09:39:30 2006 +0100 1.3 @@ -65,14 +65,18 @@ static irqreturn_t tpmif_int(int irq, 1.4 void *tpm_priv, 1.5 struct pt_regs *ptregs); 1.6 static void tpmif_rx_action(unsigned long unused); 1.7 -static void tpmif_connect(struct tpm_private *tp, domid_t domid); 1.8 +static int tpmif_connect(struct xenbus_device *dev, 1.9 + struct tpm_private *tp, 1.10 + domid_t domid); 1.11 static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0); 1.12 -static int tpm_allocate_buffers(struct tpm_private *tp); 1.13 +static int tpmif_allocate_tx_buffers(struct tpm_private *tp); 1.14 +static void tpmif_free_tx_buffers(struct tpm_private *tp); 1.15 static void tpmif_set_connected_state(struct tpm_private *tp, 1.16 u8 newstate); 1.17 static int tpm_xmit(struct tpm_private *tp, 1.18 const u8 * buf, size_t count, int userbuffer, 1.19 void *remember); 1.20 +static void destroy_tpmring(struct tpm_private *tp); 1.21 1.22 #define DPRINTK(fmt, args...) \ 1.23 pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) 1.24 @@ -81,6 +85,8 @@ static int tpm_xmit(struct tpm_private * 1.25 #define WPRINTK(fmt, args...) \ 1.26 printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args) 1.27 1.28 +#define GRANT_INVALID_REF 0 1.29 + 1.30 1.31 static inline int 1.32 tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len, 1.33 @@ -119,6 +125,14 @@ static inline struct tx_buffer *tx_buffe 1.34 } 1.35 1.36 1.37 +static inline void tx_buffer_free(struct tx_buffer *txb) 1.38 +{ 1.39 + if (txb) { 1.40 + free_page((long)txb->data); 1.41 + kfree(txb); 1.42 + } 1.43 +} 1.44 + 1.45 /************************************************************** 1.46 Utility function for the tpm_private structure 1.47 **************************************************************/ 1.48 @@ -128,23 +142,29 @@ static inline void tpm_private_init(stru 1.49 init_waitqueue_head(&tp->wait_q); 1.50 } 1.51 1.52 +static inline void tpm_private_free(void) 1.53 +{ 1.54 + tpmif_free_tx_buffers(my_priv); 1.55 + kfree(my_priv); 1.56 + my_priv = NULL; 1.57 +} 1.58 + 1.59 static struct tpm_private *tpm_private_get(void) 1.60 { 1.61 + int err; 1.62 if (!my_priv) { 1.63 my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL); 1.64 if (my_priv) { 1.65 tpm_private_init(my_priv); 1.66 + err = tpmif_allocate_tx_buffers(my_priv); 1.67 + if (err < 0) { 1.68 + tpm_private_free(); 1.69 + } 1.70 } 1.71 } 1.72 return my_priv; 1.73 } 1.74 1.75 -static inline void tpm_private_free(void) 1.76 -{ 1.77 - kfree(my_priv); 1.78 - my_priv = NULL; 1.79 -} 1.80 - 1.81 /************************************************************** 1.82 1.83 The interface to let the tpm plugin register its callback 1.84 @@ -233,6 +253,8 @@ static int setup_tpmring(struct xenbus_d 1.85 tpmif_tx_interface_t *sring; 1.86 int err; 1.87 1.88 + tp->ring_ref = GRANT_INVALID_REF; 1.89 + 1.90 sring = (void *)__get_free_page(GFP_KERNEL); 1.91 if (!sring) { 1.92 xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); 1.93 @@ -240,8 +262,6 @@ static int setup_tpmring(struct xenbus_d 1.94 } 1.95 tp->tx = sring; 1.96 1.97 - tpm_allocate_buffers(tp); 1.98 - 1.99 err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx)); 1.100 if (err < 0) { 1.101 free_page((unsigned long)sring); 1.102 @@ -251,14 +271,13 @@ static int setup_tpmring(struct xenbus_d 1.103 } 1.104 tp->ring_ref = err; 1.105 1.106 - err = xenbus_alloc_evtchn(dev, &tp->evtchn); 1.107 + err = tpmif_connect(dev, tp, dev->otherend_id); 1.108 if (err) 1.109 goto fail; 1.110 1.111 - tpmif_connect(tp, dev->otherend_id); 1.112 - 1.113 return 0; 1.114 fail: 1.115 + destroy_tpmring(tp); 1.116 return err; 1.117 } 1.118 1.119 @@ -266,14 +285,17 @@ fail: 1.120 static void destroy_tpmring(struct tpm_private *tp) 1.121 { 1.122 tpmif_set_connected_state(tp, 0); 1.123 - if (tp->tx != NULL) { 1.124 + 1.125 + if (tp->ring_ref != GRANT_INVALID_REF) { 1.126 gnttab_end_foreign_access(tp->ring_ref, 0, 1.127 (unsigned long)tp->tx); 1.128 + tp->ring_ref = GRANT_INVALID_REF; 1.129 tp->tx = NULL; 1.130 } 1.131 1.132 if (tp->irq) 1.133 - unbind_from_irqhandler(tp->irq, NULL); 1.134 + unbind_from_irqhandler(tp->irq, tp); 1.135 + 1.136 tp->evtchn = tp->irq = 0; 1.137 } 1.138 1.139 @@ -377,6 +399,9 @@ static int tpmfront_probe(struct xenbus_ 1.140 int handle; 1.141 struct tpm_private *tp = tpm_private_get(); 1.142 1.143 + if (!tp) 1.144 + return -ENOMEM; 1.145 + 1.146 err = xenbus_scanf(XBT_NULL, dev->nodename, 1.147 "handle", "%i", &handle); 1.148 if (XENBUS_EXIST_ERR(err)) 1.149 @@ -402,15 +427,14 @@ static int tpmfront_probe(struct xenbus_ 1.150 1.151 static int tpmfront_remove(struct xenbus_device *dev) 1.152 { 1.153 - struct tpm_private *tp = dev->data; 1.154 + struct tpm_private *tp = (struct tpm_private *)dev->data; 1.155 destroy_tpmring(tp); 1.156 return 0; 1.157 } 1.158 1.159 -static int 1.160 -tpmfront_suspend(struct xenbus_device *dev) 1.161 +static int tpmfront_suspend(struct xenbus_device *dev) 1.162 { 1.163 - struct tpm_private *tp = dev->data; 1.164 + struct tpm_private *tp = (struct tpm_private *)dev->data; 1.165 u32 ctr; 1.166 1.167 /* lock, so no app can send */ 1.168 @@ -437,29 +461,35 @@ tpmfront_suspend(struct xenbus_device *d 1.169 return 0; 1.170 } 1.171 1.172 -static int 1.173 -tpmfront_resume(struct xenbus_device *dev) 1.174 +static int tpmfront_resume(struct xenbus_device *dev) 1.175 { 1.176 - struct tpm_private *tp = dev->data; 1.177 + struct tpm_private *tp = (struct tpm_private *)dev->data; 1.178 + destroy_tpmring(tp); 1.179 return talk_to_backend(dev, tp); 1.180 } 1.181 1.182 -static void 1.183 -tpmif_connect(struct tpm_private *tp, domid_t domid) 1.184 +static int tpmif_connect(struct xenbus_device *dev, 1.185 + struct tpm_private *tp, 1.186 + domid_t domid) 1.187 { 1.188 int err; 1.189 1.190 tp->backend_id = domid; 1.191 1.192 + err = xenbus_alloc_evtchn(dev, &tp->evtchn); 1.193 + if (err) 1.194 + return err; 1.195 + 1.196 err = bind_evtchn_to_irqhandler(tp->evtchn, 1.197 tpmif_int, SA_SAMPLE_RANDOM, "tpmif", 1.198 tp); 1.199 if (err <= 0) { 1.200 WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); 1.201 - return; 1.202 + return err; 1.203 } 1.204 1.205 tp->irq = err; 1.206 + return 0; 1.207 } 1.208 1.209 static struct xenbus_device_id tpmfront_ids[] = { 1.210 @@ -488,19 +518,30 @@ static void __exit exit_tpm_xenbus(void) 1.211 xenbus_unregister_driver(&tpmfront); 1.212 } 1.213 1.214 - 1.215 -static int 1.216 -tpm_allocate_buffers(struct tpm_private *tp) 1.217 +static int tpmif_allocate_tx_buffers(struct tpm_private *tp) 1.218 { 1.219 unsigned int i; 1.220 1.221 - for (i = 0; i < TPMIF_TX_RING_SIZE; i++) 1.222 + for (i = 0; i < TPMIF_TX_RING_SIZE; i++) { 1.223 tp->tx_buffers[i] = tx_buffer_alloc(); 1.224 - return 1; 1.225 + if (!tp->tx_buffers[i]) { 1.226 + tpmif_free_tx_buffers(tp); 1.227 + return -ENOMEM; 1.228 + } 1.229 + } 1.230 + return 0; 1.231 } 1.232 1.233 -static void 1.234 -tpmif_rx_action(unsigned long priv) 1.235 +static void tpmif_free_tx_buffers(struct tpm_private *tp) 1.236 +{ 1.237 + unsigned int i; 1.238 + 1.239 + for (i = 0; i < TPMIF_TX_RING_SIZE; i++) { 1.240 + tx_buffer_free(tp->tx_buffers[i]); 1.241 + } 1.242 +} 1.243 + 1.244 +static void tpmif_rx_action(unsigned long priv) 1.245 { 1.246 struct tpm_private *tp = (struct tpm_private *)priv; 1.247 1.248 @@ -545,8 +586,7 @@ exit: 1.249 } 1.250 1.251 1.252 -static irqreturn_t 1.253 -tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs) 1.254 +static irqreturn_t tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs) 1.255 { 1.256 struct tpm_private *tp = tpm_priv; 1.257 unsigned long flags; 1.258 @@ -560,10 +600,9 @@ tpmif_int(int irq, void *tpm_priv, struc 1.259 } 1.260 1.261 1.262 -static int 1.263 -tpm_xmit(struct tpm_private *tp, 1.264 - const u8 * buf, size_t count, int isuserbuffer, 1.265 - void *remember) 1.266 +static int tpm_xmit(struct tpm_private *tp, 1.267 + const u8 * buf, size_t count, int isuserbuffer, 1.268 + void *remember) 1.269 { 1.270 tpmif_tx_request_t *tx; 1.271 TPMIF_RING_IDX i; 1.272 @@ -693,8 +732,7 @@ static void tpmif_set_connected_state(st 1.273 * ================================================================= 1.274 */ 1.275 1.276 -static int __init 1.277 -tpmif_init(void) 1.278 +static int __init tpmif_init(void) 1.279 { 1.280 IPRINTK("Initialising the vTPM driver.\n"); 1.281 if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE, 1.282 @@ -709,8 +747,7 @@ tpmif_init(void) 1.283 1.284 module_init(tpmif_init); 1.285 1.286 -static void __exit 1.287 -tpmif_exit(void) 1.288 +static void __exit tpmif_exit(void) 1.289 { 1.290 exit_tpm_xenbus(); 1.291 gnttab_free_grant_references(gref_head);