ia64/linux-2.6.18-xen.hg

view drivers/bluetooth/bcm203x.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 /*
2 *
3 * Broadcom Blutonium firmware driver
4 *
5 * Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
6 * Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org>
7 *
8 *
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
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
25 #include <linux/module.h>
27 #include <linux/kernel.h>
28 #include <linux/init.h>
29 #include <linux/slab.h>
30 #include <linux/types.h>
31 #include <linux/errno.h>
32 #include <linux/timer.h>
34 #include <linux/device.h>
35 #include <linux/firmware.h>
37 #include <linux/usb.h>
39 #include <net/bluetooth/bluetooth.h>
41 #ifndef CONFIG_BT_HCIBCM203X_DEBUG
42 #undef BT_DBG
43 #define BT_DBG(D...)
44 #endif
46 #define VERSION "1.0"
48 static int ignore = 0;
50 static struct usb_device_id bcm203x_table[] = {
51 /* Broadcom Blutonium (BCM2033) */
52 { USB_DEVICE(0x0a5c, 0x2033) },
54 { } /* Terminating entry */
55 };
57 MODULE_DEVICE_TABLE(usb, bcm203x_table);
59 #define BCM203X_ERROR 0
60 #define BCM203X_RESET 1
61 #define BCM203X_LOAD_MINIDRV 2
62 #define BCM203X_SELECT_MEMORY 3
63 #define BCM203X_CHECK_MEMORY 4
64 #define BCM203X_LOAD_FIRMWARE 5
65 #define BCM203X_CHECK_FIRMWARE 6
67 #define BCM203X_IN_EP 0x81
68 #define BCM203X_OUT_EP 0x02
70 struct bcm203x_data {
71 struct usb_device *udev;
73 unsigned long state;
75 struct timer_list timer;
77 struct urb *urb;
78 unsigned char *buffer;
80 unsigned char *fw_data;
81 unsigned int fw_size;
82 unsigned int fw_sent;
83 };
85 static void bcm203x_complete(struct urb *urb, struct pt_regs *regs)
86 {
87 struct bcm203x_data *data = urb->context;
88 struct usb_device *udev = urb->dev;
89 int len;
91 BT_DBG("udev %p urb %p", udev, urb);
93 if (urb->status) {
94 BT_ERR("URB failed with status %d", urb->status);
95 data->state = BCM203X_ERROR;
96 return;
97 }
99 switch (data->state) {
100 case BCM203X_LOAD_MINIDRV:
101 memcpy(data->buffer, "#", 1);
103 usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
104 data->buffer, 1, bcm203x_complete, data);
106 data->state = BCM203X_SELECT_MEMORY;
108 mod_timer(&data->timer, jiffies + (HZ / 10));
109 break;
111 case BCM203X_SELECT_MEMORY:
112 usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),
113 data->buffer, 32, bcm203x_complete, data, 1);
115 data->state = BCM203X_CHECK_MEMORY;
117 if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
118 BT_ERR("Can't submit URB");
119 break;
121 case BCM203X_CHECK_MEMORY:
122 if (data->buffer[0] != '#') {
123 BT_ERR("Memory select failed");
124 data->state = BCM203X_ERROR;
125 break;
126 }
128 data->state = BCM203X_LOAD_FIRMWARE;
130 case BCM203X_LOAD_FIRMWARE:
131 if (data->fw_sent == data->fw_size) {
132 usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),
133 data->buffer, 32, bcm203x_complete, data, 1);
135 data->state = BCM203X_CHECK_FIRMWARE;
136 } else {
137 len = min_t(uint, data->fw_size - data->fw_sent, 4096);
139 usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
140 data->fw_data + data->fw_sent, len, bcm203x_complete, data);
142 data->fw_sent += len;
143 }
145 if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
146 BT_ERR("Can't submit URB");
147 break;
149 case BCM203X_CHECK_FIRMWARE:
150 if (data->buffer[0] != '.') {
151 BT_ERR("Firmware loading failed");
152 data->state = BCM203X_ERROR;
153 break;
154 }
156 data->state = BCM203X_RESET;
157 break;
158 }
159 }
161 static void bcm203x_timer(unsigned long user_data)
162 {
163 struct bcm203x_data *data = (struct bcm203x_data *) user_data;
165 if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
166 BT_ERR("Can't submit URB");
167 }
169 static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id *id)
170 {
171 const struct firmware *firmware;
172 struct usb_device *udev = interface_to_usbdev(intf);
173 struct bcm203x_data *data;
174 int size;
176 BT_DBG("intf %p id %p", intf, id);
178 if (ignore || (intf->cur_altsetting->desc.bInterfaceNumber != 0))
179 return -ENODEV;
181 data = kzalloc(sizeof(*data), GFP_KERNEL);
182 if (!data) {
183 BT_ERR("Can't allocate memory for data structure");
184 return -ENOMEM;
185 }
187 data->udev = udev;
188 data->state = BCM203X_LOAD_MINIDRV;
190 data->urb = usb_alloc_urb(0, GFP_KERNEL);
191 if (!data->urb) {
192 BT_ERR("Can't allocate URB");
193 kfree(data);
194 return -ENOMEM;
195 }
197 if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
198 BT_ERR("Mini driver request failed");
199 usb_free_urb(data->urb);
200 kfree(data);
201 return -EIO;
202 }
204 BT_DBG("minidrv data %p size %d", firmware->data, firmware->size);
206 size = max_t(uint, firmware->size, 4096);
208 data->buffer = kmalloc(size, GFP_KERNEL);
209 if (!data->buffer) {
210 BT_ERR("Can't allocate memory for mini driver");
211 release_firmware(firmware);
212 usb_free_urb(data->urb);
213 kfree(data);
214 return -ENOMEM;
215 }
217 memcpy(data->buffer, firmware->data, firmware->size);
219 usb_fill_bulk_urb(data->urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
220 data->buffer, firmware->size, bcm203x_complete, data);
222 release_firmware(firmware);
224 if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) {
225 BT_ERR("Firmware request failed");
226 usb_free_urb(data->urb);
227 kfree(data->buffer);
228 kfree(data);
229 return -EIO;
230 }
232 BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
234 data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
235 if (!data->fw_data) {
236 BT_ERR("Can't allocate memory for firmware image");
237 release_firmware(firmware);
238 usb_free_urb(data->urb);
239 kfree(data->buffer);
240 kfree(data);
241 return -ENOMEM;
242 }
244 memcpy(data->fw_data, firmware->data, firmware->size);
245 data->fw_size = firmware->size;
246 data->fw_sent = 0;
248 release_firmware(firmware);
250 init_timer(&data->timer);
251 data->timer.function = bcm203x_timer;
252 data->timer.data = (unsigned long) data;
254 usb_set_intfdata(intf, data);
256 mod_timer(&data->timer, jiffies + HZ);
258 return 0;
259 }
261 static void bcm203x_disconnect(struct usb_interface *intf)
262 {
263 struct bcm203x_data *data = usb_get_intfdata(intf);
265 BT_DBG("intf %p", intf);
267 usb_kill_urb(data->urb);
269 usb_set_intfdata(intf, NULL);
271 usb_free_urb(data->urb);
272 kfree(data->fw_data);
273 kfree(data->buffer);
274 kfree(data);
275 }
277 static struct usb_driver bcm203x_driver = {
278 .name = "bcm203x",
279 .probe = bcm203x_probe,
280 .disconnect = bcm203x_disconnect,
281 .id_table = bcm203x_table,
282 };
284 static int __init bcm203x_init(void)
285 {
286 int err;
288 BT_INFO("Broadcom Blutonium firmware driver ver %s", VERSION);
290 err = usb_register(&bcm203x_driver);
291 if (err < 0)
292 BT_ERR("Failed to register USB driver");
294 return err;
295 }
297 static void __exit bcm203x_exit(void)
298 {
299 usb_deregister(&bcm203x_driver);
300 }
302 module_init(bcm203x_init);
303 module_exit(bcm203x_exit);
305 module_param(ignore, bool, 0644);
306 MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
308 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
309 MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
310 MODULE_VERSION(VERSION);
311 MODULE_LICENSE("GPL");