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>
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);