ia64/linux-2.6.18-xen.hg

view drivers/telephony/ixj_pcmcia.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 #include "ixj-ver.h"
3 #include <linux/module.h>
5 #include <linux/init.h>
6 #include <linux/sched.h>
7 #include <linux/kernel.h> /* printk() */
8 #include <linux/fs.h> /* everything... */
9 #include <linux/errno.h> /* error codes */
10 #include <linux/slab.h>
12 #include <pcmcia/cs_types.h>
13 #include <pcmcia/cs.h>
14 #include <pcmcia/cistpl.h>
15 #include <pcmcia/ds.h>
17 #include "ixj.h"
19 /*
20 * PCMCIA service support for Quicknet cards
21 */
23 #ifdef PCMCIA_DEBUG
24 static int pc_debug = PCMCIA_DEBUG;
25 module_param(pc_debug, int, 0644);
26 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
27 #else
28 #define DEBUG(n, args...)
29 #endif
31 typedef struct ixj_info_t {
32 int ndev;
33 dev_node_t node;
34 struct ixj *port;
35 } ixj_info_t;
37 static void ixj_detach(struct pcmcia_device *p_dev);
38 static int ixj_config(struct pcmcia_device * link);
39 static void ixj_cs_release(struct pcmcia_device * link);
41 static int ixj_probe(struct pcmcia_device *p_dev)
42 {
43 DEBUG(0, "ixj_attach()\n");
44 /* Create new ixj device */
45 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
46 p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
47 p_dev->io.IOAddrLines = 3;
48 p_dev->conf.IntType = INT_MEMORY_AND_IO;
49 p_dev->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
50 if (!p_dev->priv) {
51 return -ENOMEM;
52 }
53 memset(p_dev->priv, 0, sizeof(struct ixj_info_t));
55 return ixj_config(p_dev);
56 }
58 static void ixj_detach(struct pcmcia_device *link)
59 {
60 DEBUG(0, "ixj_detach(0x%p)\n", link);
62 ixj_cs_release(link);
64 kfree(link->priv);
65 }
67 #define CS_CHECK(fn, ret) \
68 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
70 static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
71 {
72 tuple_t tuple;
73 u_short buf[128];
74 char *str;
75 int last_ret, last_fn, i, place;
76 DEBUG(0, "ixj_get_serial(0x%p)\n", link);
77 tuple.TupleData = (cisdata_t *) buf;
78 tuple.TupleOffset = 0;
79 tuple.TupleDataMax = 80;
80 tuple.Attributes = 0;
81 tuple.DesiredTuple = CISTPL_VERS_1;
82 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
83 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
84 str = (char *) buf;
85 printk("PCMCIA Version %d.%d\n", str[0], str[1]);
86 str += 2;
87 printk("%s", str);
88 str = str + strlen(str) + 1;
89 printk(" %s", str);
90 str = str + strlen(str) + 1;
91 place = 1;
92 for (i = strlen(str) - 1; i >= 0; i--) {
93 switch (str[i]) {
94 case '0':
95 case '1':
96 case '2':
97 case '3':
98 case '4':
99 case '5':
100 case '6':
101 case '7':
102 case '8':
103 case '9':
104 j->serial += (str[i] - 48) * place;
105 break;
106 case 'A':
107 case 'B':
108 case 'C':
109 case 'D':
110 case 'E':
111 case 'F':
112 j->serial += (str[i] - 55) * place;
113 break;
114 case 'a':
115 case 'b':
116 case 'c':
117 case 'd':
118 case 'e':
119 case 'f':
120 j->serial += (str[i] - 87) * place;
121 break;
122 }
123 place = place * 0x10;
124 }
125 str = str + strlen(str) + 1;
126 printk(" version %s\n", str);
127 cs_failed:
128 return;
129 }
131 static int ixj_config(struct pcmcia_device * link)
132 {
133 IXJ *j;
134 ixj_info_t *info;
135 tuple_t tuple;
136 u_short buf[128];
137 cisparse_t parse;
138 cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
139 cistpl_cftable_entry_t dflt =
140 {
141 0
142 };
143 int last_ret, last_fn;
144 info = link->priv;
145 DEBUG(0, "ixj_config(0x%p)\n", link);
146 tuple.TupleData = (cisdata_t *) buf;
147 tuple.TupleOffset = 0;
148 tuple.TupleDataMax = 255;
149 tuple.Attributes = 0;
150 tuple.DesiredTuple = CISTPL_CONFIG;
151 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
152 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
153 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
154 link->conf.ConfigBase = parse.config.base;
155 link->conf.Present = parse.config.rmask[0];
156 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
157 tuple.Attributes = 0;
158 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
159 while (1) {
160 if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
161 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
162 goto next_entry;
163 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
164 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
165 link->conf.ConfigIndex = cfg->index;
166 link->io.BasePort1 = io->win[0].base;
167 link->io.NumPorts1 = io->win[0].len;
168 if (io->nwin == 2) {
169 link->io.BasePort2 = io->win[1].base;
170 link->io.NumPorts2 = io->win[1].len;
171 }
172 if (pcmcia_request_io(link, &link->io) != 0)
173 goto next_entry;
174 /* If we've got this far, we're done */
175 break;
176 }
177 next_entry:
178 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
179 dflt = *cfg;
180 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
181 }
183 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
185 /*
186 * Register the card with the core.
187 */
188 j=ixj_pcmcia_probe(link->io.BasePort1,link->io.BasePort1 + 0x10);
190 info->ndev = 1;
191 info->node.major = PHONE_MAJOR;
192 link->dev_node = &info->node;
193 ixj_get_serial(link, j);
194 return 0;
195 cs_failed:
196 cs_error(link, last_fn, last_ret);
197 ixj_cs_release(link);
198 return -ENODEV;
199 }
201 static void ixj_cs_release(struct pcmcia_device *link)
202 {
203 ixj_info_t *info = link->priv;
204 DEBUG(0, "ixj_cs_release(0x%p)\n", link);
205 info->ndev = 0;
206 pcmcia_disable_device(link);
207 }
209 static struct pcmcia_device_id ixj_ids[] = {
210 PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600),
211 PCMCIA_DEVICE_NULL
212 };
213 MODULE_DEVICE_TABLE(pcmcia, ixj_ids);
215 static struct pcmcia_driver ixj_driver = {
216 .owner = THIS_MODULE,
217 .drv = {
218 .name = "ixj_cs",
219 },
220 .probe = ixj_probe,
221 .remove = ixj_detach,
222 .id_table = ixj_ids,
223 };
225 static int __init ixj_pcmcia_init(void)
226 {
227 return pcmcia_register_driver(&ixj_driver);
228 }
230 static void ixj_pcmcia_exit(void)
231 {
232 pcmcia_unregister_driver(&ixj_driver);
233 }
235 module_init(ixj_pcmcia_init);
236 module_exit(ixj_pcmcia_exit);
238 MODULE_LICENSE("GPL");