ia64/linux-2.6.18-xen.hg

view drivers/bluetooth/hci_h4.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 * Bluetooth HCI UART driver
4 *
5 * Copyright (C) 2000-2001 Qualcomm Incorporated
6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7 * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
26 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/init.h>
30 #include <linux/sched.h>
31 #include <linux/types.h>
32 #include <linux/fcntl.h>
33 #include <linux/interrupt.h>
34 #include <linux/ptrace.h>
35 #include <linux/poll.h>
37 #include <linux/slab.h>
38 #include <linux/tty.h>
39 #include <linux/errno.h>
40 #include <linux/string.h>
41 #include <linux/signal.h>
42 #include <linux/ioctl.h>
43 #include <linux/skbuff.h>
45 #include <net/bluetooth/bluetooth.h>
46 #include <net/bluetooth/hci_core.h>
48 #include "hci_uart.h"
50 #ifndef CONFIG_BT_HCIUART_DEBUG
51 #undef BT_DBG
52 #define BT_DBG( A... )
53 #endif
55 #define VERSION "1.2"
57 struct h4_struct {
58 unsigned long rx_state;
59 unsigned long rx_count;
60 struct sk_buff *rx_skb;
61 struct sk_buff_head txq;
62 };
64 /* H4 receiver States */
65 #define H4_W4_PACKET_TYPE 0
66 #define H4_W4_EVENT_HDR 1
67 #define H4_W4_ACL_HDR 2
68 #define H4_W4_SCO_HDR 3
69 #define H4_W4_DATA 4
71 /* Initialize protocol */
72 static int h4_open(struct hci_uart *hu)
73 {
74 struct h4_struct *h4;
76 BT_DBG("hu %p", hu);
78 h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
79 if (!h4)
80 return -ENOMEM;
82 skb_queue_head_init(&h4->txq);
84 hu->priv = h4;
85 return 0;
86 }
88 /* Flush protocol data */
89 static int h4_flush(struct hci_uart *hu)
90 {
91 struct h4_struct *h4 = hu->priv;
93 BT_DBG("hu %p", hu);
95 skb_queue_purge(&h4->txq);
97 return 0;
98 }
100 /* Close protocol */
101 static int h4_close(struct hci_uart *hu)
102 {
103 struct h4_struct *h4 = hu->priv;
105 hu->priv = NULL;
107 BT_DBG("hu %p", hu);
109 skb_queue_purge(&h4->txq);
111 if (h4->rx_skb)
112 kfree_skb(h4->rx_skb);
114 hu->priv = NULL;
115 kfree(h4);
117 return 0;
118 }
120 /* Enqueue frame for transmittion (padding, crc, etc) */
121 static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
122 {
123 struct h4_struct *h4 = hu->priv;
125 BT_DBG("hu %p skb %p", hu, skb);
127 /* Prepend skb with frame type */
128 memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
129 skb_queue_tail(&h4->txq, skb);
131 return 0;
132 }
134 static inline int h4_check_data_len(struct h4_struct *h4, int len)
135 {
136 register int room = skb_tailroom(h4->rx_skb);
138 BT_DBG("len %d room %d", len, room);
140 if (!len) {
141 hci_recv_frame(h4->rx_skb);
142 } else if (len > room) {
143 BT_ERR("Data length is too large");
144 kfree_skb(h4->rx_skb);
145 } else {
146 h4->rx_state = H4_W4_DATA;
147 h4->rx_count = len;
148 return len;
149 }
151 h4->rx_state = H4_W4_PACKET_TYPE;
152 h4->rx_skb = NULL;
153 h4->rx_count = 0;
155 return 0;
156 }
158 /* Recv data */
159 static int h4_recv(struct hci_uart *hu, void *data, int count)
160 {
161 struct h4_struct *h4 = hu->priv;
162 register char *ptr;
163 struct hci_event_hdr *eh;
164 struct hci_acl_hdr *ah;
165 struct hci_sco_hdr *sh;
166 register int len, type, dlen;
168 BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
169 hu, count, h4->rx_state, h4->rx_count);
171 ptr = data;
172 while (count) {
173 if (h4->rx_count) {
174 len = min_t(unsigned int, h4->rx_count, count);
175 memcpy(skb_put(h4->rx_skb, len), ptr, len);
176 h4->rx_count -= len; count -= len; ptr += len;
178 if (h4->rx_count)
179 continue;
181 switch (h4->rx_state) {
182 case H4_W4_DATA:
183 BT_DBG("Complete data");
185 hci_recv_frame(h4->rx_skb);
187 h4->rx_state = H4_W4_PACKET_TYPE;
188 h4->rx_skb = NULL;
189 continue;
191 case H4_W4_EVENT_HDR:
192 eh = (struct hci_event_hdr *) h4->rx_skb->data;
194 BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
196 h4_check_data_len(h4, eh->plen);
197 continue;
199 case H4_W4_ACL_HDR:
200 ah = (struct hci_acl_hdr *) h4->rx_skb->data;
201 dlen = __le16_to_cpu(ah->dlen);
203 BT_DBG("ACL header: dlen %d", dlen);
205 h4_check_data_len(h4, dlen);
206 continue;
208 case H4_W4_SCO_HDR:
209 sh = (struct hci_sco_hdr *) h4->rx_skb->data;
211 BT_DBG("SCO header: dlen %d", sh->dlen);
213 h4_check_data_len(h4, sh->dlen);
214 continue;
215 }
216 }
218 /* H4_W4_PACKET_TYPE */
219 switch (*ptr) {
220 case HCI_EVENT_PKT:
221 BT_DBG("Event packet");
222 h4->rx_state = H4_W4_EVENT_HDR;
223 h4->rx_count = HCI_EVENT_HDR_SIZE;
224 type = HCI_EVENT_PKT;
225 break;
227 case HCI_ACLDATA_PKT:
228 BT_DBG("ACL packet");
229 h4->rx_state = H4_W4_ACL_HDR;
230 h4->rx_count = HCI_ACL_HDR_SIZE;
231 type = HCI_ACLDATA_PKT;
232 break;
234 case HCI_SCODATA_PKT:
235 BT_DBG("SCO packet");
236 h4->rx_state = H4_W4_SCO_HDR;
237 h4->rx_count = HCI_SCO_HDR_SIZE;
238 type = HCI_SCODATA_PKT;
239 break;
241 default:
242 BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
243 hu->hdev->stat.err_rx++;
244 ptr++; count--;
245 continue;
246 };
248 ptr++; count--;
250 /* Allocate packet */
251 h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
252 if (!h4->rx_skb) {
253 BT_ERR("Can't allocate mem for new packet");
254 h4->rx_state = H4_W4_PACKET_TYPE;
255 h4->rx_count = 0;
256 return 0;
257 }
259 h4->rx_skb->dev = (void *) hu->hdev;
260 bt_cb(h4->rx_skb)->pkt_type = type;
261 }
263 return count;
264 }
266 static struct sk_buff *h4_dequeue(struct hci_uart *hu)
267 {
268 struct h4_struct *h4 = hu->priv;
269 return skb_dequeue(&h4->txq);
270 }
272 static struct hci_uart_proto h4p = {
273 .id = HCI_UART_H4,
274 .open = h4_open,
275 .close = h4_close,
276 .recv = h4_recv,
277 .enqueue = h4_enqueue,
278 .dequeue = h4_dequeue,
279 .flush = h4_flush,
280 };
282 int h4_init(void)
283 {
284 int err = hci_uart_register_proto(&h4p);
286 if (!err)
287 BT_INFO("HCI H4 protocol initialized");
288 else
289 BT_ERR("HCI H4 protocol registration failed");
291 return err;
292 }
294 int h4_deinit(void)
295 {
296 return hci_uart_unregister_proto(&h4p);
297 }