* [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk'.
@ 2010-04-29 14:28 Xu, Dongxiao
2010-05-03 16:02 ` Konrad Rzeszutek Wilk
2010-05-03 16:05 ` Konrad Rzeszutek Wilk
0 siblings, 2 replies; 6+ messages in thread
From: Xu, Dongxiao @ 2010-04-29 14:28 UTC (permalink / raw)
To: xen-devel@lists.xensource.com; +Cc: Jeremy Fitzhardinge, Steven Smith
[-- Attachment #1: Type: text/plain, Size: 114 bytes --]
Netback: Move global/static variables into struct xen_netbk.
Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
[-- Attachment #2: 0001-Netback-Move-global-static-variables-into-struct-xe.patch --]
[-- Type: application/octet-stream, Size: 29825 bytes --]
From 6f100ed3d56ec8e26fcd521a26cf646a8bd6ed8c Mon Sep 17 00:00:00 2001
From: Dongxiao Xu <dongxiao.xu@intel.com>
Date: Fri, 30 Apr 2010 07:55:48 +0800
Subject: [PATCH] Netback: Move global/static variables into struct xen_netbk.
Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
---
drivers/xen/netback/common.h | 58 +++++++
drivers/xen/netback/netback.c | 379 ++++++++++++++++++++---------------------
2 files changed, 243 insertions(+), 194 deletions(-)
diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h
index 51f97c0..bcb7fa0 100644
--- a/drivers/xen/netback/common.h
+++ b/drivers/xen/netback/common.h
@@ -224,4 +224,62 @@ static inline int netbk_can_sg(struct net_device *dev)
return netif->features & NETIF_F_SG;
}
+struct pending_tx_info {
+ struct xen_netif_tx_request req;
+ struct xen_netif *netif;
+};
+typedef unsigned int pending_ring_idx_t;
+
+struct netbk_rx_meta {
+ skb_frag_t frag;
+ int id;
+};
+
+struct netbk_tx_pending_inuse {
+ struct list_head list;
+ unsigned long alloc_time;
+};
+
+#define MAX_PENDING_REQS 256
+
+struct xen_netbk {
+ struct tasklet_struct net_tx_tasklet;
+ struct tasklet_struct net_rx_tasklet;
+
+ struct sk_buff_head rx_queue;
+ struct sk_buff_head tx_queue;
+
+ struct timer_list net_timer;
+ struct timer_list netbk_tx_pending_timer;
+
+ struct page **mmap_pages;
+
+ struct pending_tx_info pending_tx_info[MAX_PENDING_REQS];
+ struct netbk_tx_pending_inuse pending_inuse[MAX_PENDING_REQS];
+ struct gnttab_unmap_grant_ref tx_unmap_ops[MAX_PENDING_REQS];
+ struct gnttab_map_grant_ref tx_map_ops[MAX_PENDING_REQS];
+
+ grant_handle_t grant_tx_handle[MAX_PENDING_REQS];
+ u16 pending_ring[MAX_PENDING_REQS];
+ u16 dealloc_ring[MAX_PENDING_REQS];
+
+ pending_ring_idx_t pending_prod;
+ pending_ring_idx_t pending_cons;
+ pending_ring_idx_t dealloc_prod;
+ pending_ring_idx_t dealloc_cons;
+
+ struct list_head pending_inuse_head;
+ struct list_head net_schedule_list;
+
+ struct multicall_entry rx_mcl[NET_RX_RING_SIZE+3];
+ struct mmu_update rx_mmu[NET_RX_RING_SIZE];
+ struct gnttab_transfer grant_trans_op[NET_RX_RING_SIZE];
+ struct gnttab_copy grant_copy_op[NET_RX_RING_SIZE];
+ unsigned char rx_notify[NR_IRQS];
+ u16 notify_list[NET_RX_RING_SIZE];
+ struct netbk_rx_meta meta[NET_RX_RING_SIZE];
+
+ spinlock_t net_schedule_list_lock;
+};
+
#endif /* __NETIF__BACKEND__COMMON_H__ */
diff --git a/drivers/xen/netback/netback.c b/drivers/xen/netback/netback.c
index ddc701f..bd53972 100644
--- a/drivers/xen/netback/netback.c
+++ b/drivers/xen/netback/netback.c
@@ -49,16 +49,9 @@
/*define NETBE_DEBUG_INTERRUPT*/
-struct netbk_rx_meta {
- skb_frag_t frag;
- int id;
-};
-
-struct netbk_tx_pending_inuse {
- struct list_head list;
- unsigned long alloc_time;
-};
+static struct xen_netbk *netbk;
+static struct page_foreign_tracker *foreign_page_tracker;
static void netif_idx_release(u16 pending_idx);
static void make_tx_response(struct xen_netif *netif,
@@ -72,22 +65,12 @@ static struct xen_netif_rx_response *make_rx_response(struct xen_netif *netif,
u16 flags);
static void net_tx_action(unsigned long unused);
-static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
static void net_rx_action(unsigned long unused);
-static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
-
-static struct timer_list net_timer;
-static struct timer_list netbk_tx_pending_timer;
-
-#define MAX_PENDING_REQS 256
-static struct sk_buff_head rx_queue;
-
-static struct page **mmap_pages;
static inline unsigned long idx_to_pfn(unsigned int idx)
{
- return page_to_pfn(mmap_pages[idx]);
+ return page_to_pfn(netbk->mmap_pages[idx]);
}
static inline unsigned long idx_to_kaddr(unsigned int idx)
@@ -108,7 +91,7 @@ static inline int netif_page_index(struct page *pg)
if (!PageForeign(pg))
return -1;
- if ((idx >= MAX_PENDING_REQS) || (mmap_pages[idx] != pg))
+ if ((idx >= MAX_PENDING_REQS) || (netbk->mmap_pages[idx] != pg))
return -1;
return idx;
@@ -122,48 +105,17 @@ static inline int netif_page_index(struct page *pg)
*/
#define PKT_PROT_LEN 72
-static struct pending_tx_info {
- struct xen_netif_tx_request req;
- struct xen_netif *netif;
-} pending_tx_info[MAX_PENDING_REQS];
-static u16 pending_ring[MAX_PENDING_REQS];
-typedef unsigned int pending_ring_idx_t;
-
static inline pending_ring_idx_t pending_index(unsigned i)
{
return i & (MAX_PENDING_REQS-1);
}
-static pending_ring_idx_t pending_prod, pending_cons;
-
static inline pending_ring_idx_t nr_pending_reqs(void)
{
- return MAX_PENDING_REQS - pending_prod + pending_cons;
+ return MAX_PENDING_REQS -
+ netbk->pending_prod + netbk->pending_cons;
}
-static struct page_foreign_tracker *foreign_page_tracker;
-
-/* Freed TX SKBs get batched on this ring before return to pending_ring. */
-static u16 dealloc_ring[MAX_PENDING_REQS];
-static pending_ring_idx_t dealloc_prod, dealloc_cons;
-
-/* Doubly-linked list of in-use pending entries. */
-static struct netbk_tx_pending_inuse pending_inuse[MAX_PENDING_REQS];
-static LIST_HEAD(pending_inuse_head);
-
-static struct sk_buff_head tx_queue;
-
-static grant_handle_t grant_tx_handle[MAX_PENDING_REQS];
-static struct gnttab_unmap_grant_ref tx_unmap_ops[MAX_PENDING_REQS];
-static struct gnttab_map_grant_ref tx_map_ops[MAX_PENDING_REQS];
-
-static LIST_HEAD(net_schedule_list);
-static DEFINE_SPINLOCK(net_schedule_list_lock);
-
-#define MAX_MFN_ALLOC 64
-static unsigned long mfn_list[MAX_MFN_ALLOC];
-static unsigned int alloc_index = 0;
-
/* Setting this allows the safe use of this driver without netloop. */
static int MODPARM_copy_skb = 1;
module_param_named(copy_skb, MODPARM_copy_skb, bool, 0);
@@ -171,18 +123,12 @@ MODULE_PARM_DESC(copy_skb, "Copy data received from netfront without netloop");
int netbk_copy_skb_mode;
-static inline unsigned long alloc_mfn(void)
-{
- BUG_ON(alloc_index == 0);
- return mfn_list[--alloc_index];
-}
-
static inline void maybe_schedule_tx_action(void)
{
smp_mb();
if ((nr_pending_reqs() < (MAX_PENDING_REQS/2)) &&
- !list_empty(&net_schedule_list))
- tasklet_schedule(&net_tx_tasklet);
+ !list_empty(&netbk->net_schedule_list))
+ tasklet_schedule(&netbk->net_tx_tasklet);
}
static struct sk_buff *netbk_copy_skb(struct sk_buff *skb)
@@ -331,9 +277,8 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
mod_timer(&netif->tx_queue_timeout, jiffies + HZ/2);
}
}
-
- skb_queue_tail(&rx_queue, skb);
- tasklet_schedule(&net_rx_tasklet);
+ skb_queue_tail(&netbk->rx_queue, skb);
+ tasklet_schedule(&netbk->net_rx_tasklet);
return 0;
@@ -488,30 +433,19 @@ static void net_rx_action(unsigned long unused)
int count;
unsigned long offset;
- /*
- * Putting hundreds of bytes on the stack is considered rude.
- * Static works because a tasklet can only be on one CPU at any time.
- */
- static struct multicall_entry rx_mcl[NET_RX_RING_SIZE+3];
- static struct mmu_update rx_mmu[NET_RX_RING_SIZE];
- static struct gnttab_transfer grant_trans_op[NET_RX_RING_SIZE];
- static struct gnttab_copy grant_copy_op[NET_RX_RING_SIZE];
- static unsigned char rx_notify[NR_IRQS];
- static u16 notify_list[NET_RX_RING_SIZE];
- static struct netbk_rx_meta meta[NET_RX_RING_SIZE];
-
struct netrx_pending_operations npo = {
- mmu: rx_mmu,
- trans: grant_trans_op,
- copy: grant_copy_op,
- mcl: rx_mcl,
- meta: meta};
+ .mmu = netbk->rx_mmu,
+ .trans = netbk->grant_trans_op,
+ .copy = netbk->grant_copy_op,
+ .mcl = netbk->rx_mcl,
+ .meta = netbk->meta,
+ };
skb_queue_head_init(&rxq);
count = 0;
- while ((skb = skb_dequeue(&rx_queue)) != NULL) {
+ while ((skb = skb_dequeue(&netbk->rx_queue)) != NULL) {
nr_frags = skb_shinfo(skb)->nr_frags;
*(int *)skb->cb = nr_frags;
@@ -526,39 +460,39 @@ static void net_rx_action(unsigned long unused)
break;
}
- BUG_ON(npo.meta_prod > ARRAY_SIZE(meta));
+ BUG_ON(npo.meta_prod > ARRAY_SIZE(netbk->meta));
npo.mmu_mcl = npo.mcl_prod;
if (npo.mcl_prod) {
BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
- BUG_ON(npo.mmu_prod > ARRAY_SIZE(rx_mmu));
+ BUG_ON(npo.mmu_prod > ARRAY_SIZE(netbk->rx_mmu));
mcl = npo.mcl + npo.mcl_prod++;
BUG_ON(mcl[-1].op != __HYPERVISOR_update_va_mapping);
mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
mcl->op = __HYPERVISOR_mmu_update;
- mcl->args[0] = (unsigned long)rx_mmu;
+ mcl->args[0] = (unsigned long)netbk->rx_mmu;
mcl->args[1] = npo.mmu_prod;
mcl->args[2] = 0;
mcl->args[3] = DOMID_SELF;
}
if (npo.trans_prod) {
- BUG_ON(npo.trans_prod > ARRAY_SIZE(grant_trans_op));
+ BUG_ON(npo.trans_prod > ARRAY_SIZE(netbk->grant_trans_op));
mcl = npo.mcl + npo.mcl_prod++;
mcl->op = __HYPERVISOR_grant_table_op;
mcl->args[0] = GNTTABOP_transfer;
- mcl->args[1] = (unsigned long)grant_trans_op;
+ mcl->args[1] = (unsigned long)netbk->grant_trans_op;
mcl->args[2] = npo.trans_prod;
}
if (npo.copy_prod) {
- BUG_ON(npo.copy_prod > ARRAY_SIZE(grant_copy_op));
+ BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op));
mcl = npo.mcl + npo.mcl_prod++;
mcl->op = __HYPERVISOR_grant_table_op;
mcl->args[0] = GNTTABOP_copy;
- mcl->args[1] = (unsigned long)grant_copy_op;
+ mcl->args[1] = (unsigned long)netbk->grant_copy_op;
mcl->args[2] = npo.copy_prod;
}
@@ -566,7 +500,7 @@ static void net_rx_action(unsigned long unused)
if (!npo.mcl_prod)
return;
- BUG_ON(npo.mcl_prod > ARRAY_SIZE(rx_mcl));
+ BUG_ON(npo.mcl_prod > ARRAY_SIZE(netbk->rx_mcl));
ret = HYPERVISOR_multicall(npo.mcl, npo.mcl_prod);
BUG_ON(ret != 0);
@@ -583,7 +517,7 @@ static void net_rx_action(unsigned long unused)
status = netbk_check_gop(nr_frags, netif->domid, &npo);
- id = meta[npo.meta_cons].id;
+ id = netbk->meta[npo.meta_cons].id;
flags = nr_frags ? NETRXF_more_data : 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
@@ -596,7 +530,7 @@ static void net_rx_action(unsigned long unused)
resp = make_rx_response(netif, id, status, offset,
skb_headlen(skb), flags);
- if (meta[npo.meta_cons].frag.size) {
+ if (netbk->meta[npo.meta_cons].frag.size) {
struct xen_netif_extra_info *gso =
(struct xen_netif_extra_info *)
RING_GET_RESPONSE(&netif->rx,
@@ -604,7 +538,7 @@ static void net_rx_action(unsigned long unused)
resp->flags |= NETRXF_extra_info;
- gso->u.gso.size = meta[npo.meta_cons].frag.size;
+ gso->u.gso.size = netbk->meta[npo.meta_cons].frag.size;
gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
gso->u.gso.pad = 0;
gso->u.gso.features = 0;
@@ -614,15 +548,15 @@ static void net_rx_action(unsigned long unused)
}
netbk_add_frag_responses(netif, status,
- meta + npo.meta_cons + 1,
- nr_frags);
+ netbk->meta + npo.meta_cons + 1,
+ nr_frags);
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret);
irq = netif->irq;
- if (ret && !rx_notify[irq] &&
+ if (ret && !netbk->rx_notify[irq] &&
(netif->smart_poll != 1)) {
- rx_notify[irq] = 1;
- notify_list[notify_nr++] = irq;
+ netbk->rx_notify[irq] = 1;
+ netbk->notify_list[notify_nr++] = irq;
}
if (netif_queue_stopped(netif->dev) &&
@@ -647,24 +581,25 @@ static void net_rx_action(unsigned long unused)
}
while (notify_nr != 0) {
- irq = notify_list[--notify_nr];
- rx_notify[irq] = 0;
+ irq = netbk->notify_list[--notify_nr];
+ netbk->rx_notify[irq] = 0;
notify_remote_via_irq(irq);
}
/* More work to do? */
- if (!skb_queue_empty(&rx_queue) && !timer_pending(&net_timer))
- tasklet_schedule(&net_rx_tasklet);
+ if (!skb_queue_empty(&netbk->rx_queue) &&
+ !timer_pending(&netbk->net_timer))
+ tasklet_schedule(&netbk->net_rx_tasklet);
}
static void net_alarm(unsigned long unused)
{
- tasklet_schedule(&net_rx_tasklet);
+ tasklet_schedule(&netbk->net_rx_tasklet);
}
static void netbk_tx_pending_timeout(unsigned long unused)
{
- tasklet_schedule(&net_tx_tasklet);
+ tasklet_schedule(&netbk->net_tx_tasklet);
}
struct net_device_stats *netif_be_get_stats(struct net_device *dev)
@@ -680,12 +615,12 @@ static int __on_net_schedule_list(struct xen_netif *netif)
static void remove_from_net_schedule_list(struct xen_netif *netif)
{
- spin_lock_irq(&net_schedule_list_lock);
+ spin_lock_irq(&netbk->net_schedule_list_lock);
if (likely(__on_net_schedule_list(netif))) {
list_del_init(&netif->list);
netif_put(netif);
}
- spin_unlock_irq(&net_schedule_list_lock);
+ spin_unlock_irq(&netbk->net_schedule_list_lock);
}
static void add_to_net_schedule_list_tail(struct xen_netif *netif)
@@ -693,13 +628,13 @@ static void add_to_net_schedule_list_tail(struct xen_netif *netif)
if (__on_net_schedule_list(netif))
return;
- spin_lock_irq(&net_schedule_list_lock);
+ spin_lock_irq(&netbk->net_schedule_list_lock);
if (!__on_net_schedule_list(netif) &&
likely(netif_schedulable(netif))) {
- list_add_tail(&netif->list, &net_schedule_list);
+ list_add_tail(&netif->list, &netbk->net_schedule_list);
netif_get(netif);
}
- spin_unlock_irq(&net_schedule_list_lock);
+ spin_unlock_irq(&netbk->net_schedule_list_lock);
}
void netif_schedule_work(struct xen_netif *netif)
@@ -749,8 +684,9 @@ static void tx_credit_callback(unsigned long data)
static inline int copy_pending_req(pending_ring_idx_t pending_idx)
{
- return gnttab_copy_grant_page(grant_tx_handle[pending_idx],
- &mmap_pages[pending_idx]);
+ return gnttab_copy_grant_page(
+ netbk->grant_tx_handle[pending_idx],
+ &netbk->mmap_pages[pending_idx]);
}
inline static void net_tx_action_dealloc(void)
@@ -763,22 +699,24 @@ inline static void net_tx_action_dealloc(void)
int ret;
LIST_HEAD(list);
- dc = dealloc_cons;
- gop = tx_unmap_ops;
+ dc = netbk->dealloc_cons;
+ gop = netbk->tx_unmap_ops;
/*
* Free up any grants we have finished using
*/
do {
- dp = dealloc_prod;
+ dp = netbk->dealloc_prod;
/* Ensure we see all indices enqueued by netif_idx_release(). */
smp_rmb();
while (dc != dp) {
unsigned long pfn;
+ struct netbk_tx_pending_inuse *pending_inuse =
+ netbk->pending_inuse;
- pending_idx = dealloc_ring[pending_index(dc++)];
+ pending_idx = netbk->dealloc_ring[pending_index(dc++)];
list_move_tail(&pending_inuse[pending_idx].list, &list);
pfn = idx_to_pfn(pending_idx);
@@ -786,24 +724,29 @@ inline static void net_tx_action_dealloc(void)
if (!phys_to_machine_mapping_valid(pfn))
continue;
- stop_tracking_page(mmap_pages[pending_idx]);
+ stop_tracking_page(netbk->mmap_pages[pending_idx]);
- gnttab_set_unmap_op(gop, idx_to_kaddr(pending_idx),
- GNTMAP_host_map,
- grant_tx_handle[pending_idx]);
+ gnttab_set_unmap_op(gop,
+ idx_to_kaddr(pending_idx),
+ GNTMAP_host_map,
+ netbk->grant_tx_handle[pending_idx]);
gop++;
}
if (netbk_copy_skb_mode != NETBK_DELAYED_COPY_SKB ||
- list_empty(&pending_inuse_head))
+ list_empty(&netbk->pending_inuse_head))
break;
/* Copy any entries that have been pending for too long. */
- list_for_each_entry_safe(inuse, n, &pending_inuse_head, list) {
+ list_for_each_entry_safe(inuse, n,
+ &netbk->pending_inuse_head, list) {
+ struct pending_tx_info *pending_tx_info;
+ pending_tx_info = netbk->pending_tx_info;
+
if (time_after(inuse->alloc_time + HZ / 2, jiffies))
break;
- pending_idx = inuse - pending_inuse;
+ pending_idx = inuse - netbk->pending_inuse;
pending_tx_info[pending_idx].netif->nr_copied_skbs++;
@@ -820,16 +763,21 @@ inline static void net_tx_action_dealloc(void)
break;
}
- } while (dp != dealloc_prod);
+ } while (dp != netbk->dealloc_prod);
- dealloc_cons = dc;
+ netbk->dealloc_cons = dc;
ret = HYPERVISOR_grant_table_op(
- GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops);
+ GNTTABOP_unmap_grant_ref, netbk->tx_unmap_ops,
+ gop - netbk->tx_unmap_ops);
BUG_ON(ret);
list_for_each_entry_safe(inuse, n, &list, list) {
- pending_idx = inuse - pending_inuse;
+ struct pending_tx_info *pending_tx_info;
+ pending_ring_idx_t index;
+
+ pending_tx_info = netbk->pending_tx_info;
+ pending_idx = inuse - netbk->pending_inuse;
netif = pending_tx_info[pending_idx].netif;
@@ -837,9 +785,10 @@ inline static void net_tx_action_dealloc(void)
NETIF_RSP_OKAY);
/* Ready for next use. */
- gnttab_reset_grant_page(mmap_pages[pending_idx]);
+ gnttab_reset_grant_page(netbk->mmap_pages[pending_idx]);
- pending_ring[pending_index(pending_prod++)] = pending_idx;
+ index = pending_index(netbk->pending_prod++);
+ netbk->pending_ring[index] = pending_idx;
netif_put(netif);
@@ -847,7 +796,8 @@ inline static void net_tx_action_dealloc(void)
}
}
-static void netbk_tx_err(struct xen_netif *netif, struct xen_netif_tx_request *txp, RING_IDX end)
+static void netbk_tx_err(struct xen_netif *netif,
+ struct xen_netif_tx_request *txp, RING_IDX end)
{
RING_IDX cons = netif->tx.req_cons;
@@ -917,7 +867,12 @@ static struct gnttab_map_grant_ref *netbk_get_requests(struct xen_netif *netif,
start = ((unsigned long)shinfo->frags[0].page == pending_idx);
for (i = start; i < shinfo->nr_frags; i++, txp++) {
- pending_idx = pending_ring[pending_index(pending_cons++)];
+ pending_ring_idx_t index;
+ struct pending_tx_info *pending_tx_info =
+ netbk->pending_tx_info;
+
+ index = pending_index(netbk->pending_cons++);
+ pending_idx = netbk->pending_ring[index];
gnttab_set_map_op(mop++, idx_to_kaddr(pending_idx),
GNTMAP_host_map | GNTMAP_readonly,
@@ -929,7 +884,7 @@ static struct gnttab_map_grant_ref *netbk_get_requests(struct xen_netif *netif,
frags[i].page = (void *)pending_idx;
start_tracking_page(foreign_page_tracker,
- mmap_pages[pending_idx],
+ netbk->mmap_pages[pending_idx],
netif->domid,
pending_tx_info[pending_idx].req.gref,
pending_idx,
@@ -944,6 +899,7 @@ static int netbk_tx_check_mop(struct sk_buff *skb,
{
struct gnttab_map_grant_ref *mop = *mopp;
int pending_idx = *((u16 *)skb->data);
+ struct pending_tx_info *pending_tx_info = netbk->pending_tx_info;
struct xen_netif *netif = pending_tx_info[pending_idx].netif;
struct xen_netif_tx_request *txp;
struct skb_shared_info *shinfo = skb_shinfo(skb);
@@ -953,15 +909,17 @@ static int netbk_tx_check_mop(struct sk_buff *skb,
/* Check status of header. */
err = mop->status;
if (unlikely(err)) {
+ pending_ring_idx_t index;
+ index = pending_index(netbk->pending_prod++);
txp = &pending_tx_info[pending_idx].req;
make_tx_response(netif, txp, NETIF_RSP_ERROR);
- pending_ring[pending_index(pending_prod++)] = pending_idx;
+ netbk->pending_ring[index] = pending_idx;
netif_put(netif);
} else {
set_phys_to_machine(
__pa(idx_to_kaddr(pending_idx)) >> PAGE_SHIFT,
FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT));
- grant_tx_handle[pending_idx] = mop->handle;
+ netbk->grant_tx_handle[pending_idx] = mop->handle;
}
/* Skip first skb fragment if it is on same page as header fragment. */
@@ -969,16 +927,19 @@ static int netbk_tx_check_mop(struct sk_buff *skb,
for (i = start; i < nr_frags; i++) {
int j, newerr;
+ pending_ring_idx_t index;
pending_idx = (unsigned long)shinfo->frags[i].page;
/* Check error status: if okay then remember grant handle. */
newerr = (++mop)->status;
if (likely(!newerr)) {
+ unsigned long addr;
+ addr = idx_to_kaddr(pending_idx);
set_phys_to_machine(
- __pa(idx_to_kaddr(pending_idx))>>PAGE_SHIFT,
+ __pa(addr)>>PAGE_SHIFT,
FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT));
- grant_tx_handle[pending_idx] = mop->handle;
+ netbk->grant_tx_handle[pending_idx] = mop->handle;
/* Had a previous error? Invalidate this fragment. */
if (unlikely(err))
netif_idx_release(pending_idx);
@@ -986,9 +947,10 @@ static int netbk_tx_check_mop(struct sk_buff *skb,
}
/* Error on this fragment: respond to client with an error. */
- txp = &pending_tx_info[pending_idx].req;
+ txp = &netbk->pending_tx_info[pending_idx].req;
make_tx_response(netif, txp, NETIF_RSP_ERROR);
- pending_ring[pending_index(pending_prod++)] = pending_idx;
+ index = pending_index(netbk->pending_prod++);
+ netbk->pending_ring[index] = pending_idx;
netif_put(netif);
/* Not the first error? Preceding frags already invalidated. */
@@ -1024,11 +986,11 @@ static void netbk_fill_frags(struct sk_buff *skb)
pending_idx = (unsigned long)frag->page;
- pending_inuse[pending_idx].alloc_time = jiffies;
- list_add_tail(&pending_inuse[pending_idx].list,
- &pending_inuse_head);
+ netbk->pending_inuse[pending_idx].alloc_time = jiffies;
+ list_add_tail(&netbk->pending_inuse[pending_idx].list,
+ &netbk->pending_inuse_head);
- txp = &pending_tx_info[pending_idx].req;
+ txp = &netbk->pending_tx_info[pending_idx].req;
frag->page = virt_to_page(idx_to_kaddr(pending_idx));
frag->size = txp->size;
frag->page_offset = txp->offset;
@@ -1167,9 +1129,9 @@ static unsigned net_tx_build_mops(void)
struct sk_buff *skb;
int ret;
- mop = tx_map_ops;
+ mop = netbk->tx_map_ops;
while (((nr_pending_reqs() + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
- !list_empty(&net_schedule_list)) {
+ !list_empty(&netbk->net_schedule_list)) {
struct xen_netif *netif;
struct xen_netif_tx_request txreq;
struct xen_netif_tx_request txfrags[MAX_SKB_FRAGS];
@@ -1178,9 +1140,11 @@ static unsigned net_tx_build_mops(void)
RING_IDX idx;
int work_to_do;
unsigned int data_len;
+ pending_ring_idx_t index;
/* Get a netif from the list with work to do. */
- netif = list_first_entry(&net_schedule_list, struct xen_netif, list);
+ netif = list_first_entry(&netbk->net_schedule_list,
+ struct xen_netif, list);
netif_get(netif);
remove_from_net_schedule_list(netif);
@@ -1239,7 +1203,8 @@ static unsigned net_tx_build_mops(void)
continue;
}
- pending_idx = pending_ring[pending_index(pending_cons)];
+ index = pending_index(netbk->pending_cons);
+ pending_idx = netbk->pending_ring[index];
data_len = (txreq.size > PKT_PROT_LEN &&
ret < MAX_SKB_FRAGS) ?
@@ -1273,15 +1238,15 @@ static unsigned net_tx_build_mops(void)
mop++;
start_tracking_page(foreign_page_tracker,
- mmap_pages[pending_idx],
+ netbk->mmap_pages[pending_idx],
netif->domid,
txreq.gref,
pending_idx,
NULL);
- memcpy(&pending_tx_info[pending_idx].req,
+ memcpy(&netbk->pending_tx_info[pending_idx].req,
&txreq, sizeof(txreq));
- pending_tx_info[pending_idx].netif = netif;
+ netbk->pending_tx_info[pending_idx].netif = netif;
*((u16 *)skb->data) = pending_idx;
__skb_put(skb, data_len);
@@ -1296,20 +1261,20 @@ static unsigned net_tx_build_mops(void)
skb_shinfo(skb)->frags[0].page = (void *)~0UL;
}
- __skb_queue_tail(&tx_queue, skb);
+ __skb_queue_tail(&netbk->tx_queue, skb);
- pending_cons++;
+ netbk->pending_cons++;
mop = netbk_get_requests(netif, skb, txfrags, mop);
netif->tx.req_cons = idx;
netif_schedule_work(netif);
- if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops))
+ if ((mop - netbk->tx_map_ops) >= ARRAY_SIZE(netbk->tx_map_ops))
break;
}
- return mop - tx_map_ops;
+ return mop - netbk->tx_map_ops;
}
static void net_tx_submit(void)
@@ -1317,16 +1282,16 @@ static void net_tx_submit(void)
struct gnttab_map_grant_ref *mop;
struct sk_buff *skb;
- mop = tx_map_ops;
- while ((skb = __skb_dequeue(&tx_queue)) != NULL) {
+ mop = netbk->tx_map_ops;
+ while ((skb = __skb_dequeue(&netbk->tx_queue)) != NULL) {
struct xen_netif_tx_request *txp;
struct xen_netif *netif;
u16 pending_idx;
unsigned data_len;
pending_idx = *((u16 *)skb->data);
- netif = pending_tx_info[pending_idx].netif;
- txp = &pending_tx_info[pending_idx].req;
+ netif = netbk->pending_tx_info[pending_idx].netif;
+ txp = &netbk->pending_tx_info[pending_idx].req;
/* Check the remap error code. */
if (unlikely(netbk_tx_check_mop(skb, &mop))) {
@@ -1396,12 +1361,13 @@ static void net_tx_submit(void)
}
if (netbk_copy_skb_mode == NETBK_DELAYED_COPY_SKB &&
- !list_empty(&pending_inuse_head)) {
+ !list_empty(&netbk->pending_inuse_head)) {
struct netbk_tx_pending_inuse *oldest;
- oldest = list_entry(pending_inuse_head.next,
+ oldest = list_entry(netbk->pending_inuse_head.next,
struct netbk_tx_pending_inuse, list);
- mod_timer(&netbk_tx_pending_timer, oldest->alloc_time + HZ);
+ mod_timer(&netbk->netbk_tx_pending_timer,
+ oldest->alloc_time + HZ);
}
}
@@ -1411,7 +1377,7 @@ static void net_tx_action(unsigned long unused)
unsigned nr_mops;
int ret;
- if (dealloc_cons != dealloc_prod)
+ if (netbk->dealloc_cons != netbk->dealloc_prod)
net_tx_action_dealloc();
nr_mops = net_tx_build_mops();
@@ -1420,7 +1386,7 @@ static void net_tx_action(unsigned long unused)
return;
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
- tx_map_ops, nr_mops);
+ netbk->tx_map_ops, nr_mops);
BUG_ON(ret);
net_tx_submit();
@@ -1430,15 +1396,17 @@ static void netif_idx_release(u16 pending_idx)
{
static DEFINE_SPINLOCK(_lock);
unsigned long flags;
+ pending_ring_idx_t index;
spin_lock_irqsave(&_lock, flags);
- dealloc_ring[pending_index(dealloc_prod)] = pending_idx;
+ index = pending_index(netbk->dealloc_prod);
+ netbk->dealloc_ring[index] = pending_idx;
/* Sync with net_tx_action_dealloc: insert idx /then/ incr producer. */
smp_wmb();
- dealloc_prod++;
+ netbk->dealloc_prod++;
spin_unlock_irqrestore(&_lock, flags);
- tasklet_schedule(&net_tx_tasklet);
+ tasklet_schedule(&netbk->net_tx_tasklet);
}
static void netif_page_release(struct page *page, unsigned int order)
@@ -1524,9 +1492,9 @@ static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
int i = 0;
printk(KERN_ALERT "netif_schedule_list:\n");
- spin_lock_irq(&net_schedule_list_lock);
+ spin_lock_irq(&netbk->net_schedule_list_lock);
- list_for_each (ent, &net_schedule_list) {
+ list_for_each(ent, &netbk->net_schedule_list) {
netif = list_entry(ent, struct xen_netif, list);
printk(KERN_ALERT " %d: private(rx_req_cons=%08x "
"rx_resp_prod=%08x\n",
@@ -1543,7 +1511,7 @@ static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
i++;
}
- spin_unlock_irq(&net_schedule_list_lock);
+ spin_unlock_irq(&netbk->net_schedule_list_lock);
printk(KERN_ALERT " ** End of netif_schedule_list **\n");
return IRQ_HANDLED;
@@ -1559,41 +1527,60 @@ static int __init netback_init(void)
if (!xen_domain())
return -ENODEV;
+ netbk = kzalloc(sizeof(struct xen_netbk), GFP_KERNEL);
+ if (!netbk) {
+ printk(KERN_ALERT "%s: out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ foreign_page_tracker =
+ alloc_page_foreign_tracker(MAX_PENDING_REQS);
+ if (!foreign_page_tracker) {
+ rc = -ENOMEM;
+ goto failed_init3;
+ }
+
/* We can increase reservation by this much in net_rx_action(). */
// balloon_update_driver_allowance(NET_RX_RING_SIZE);
- skb_queue_head_init(&rx_queue);
- skb_queue_head_init(&tx_queue);
+ skb_queue_head_init(&netbk->rx_queue);
+ skb_queue_head_init(&netbk->tx_queue);
- init_timer(&net_timer);
- net_timer.data = 0;
- net_timer.function = net_alarm;
+ init_timer(&netbk->net_timer);
+ netbk->net_timer.data = 0;
+ netbk->net_timer.function = net_alarm;
- init_timer(&netbk_tx_pending_timer);
- netbk_tx_pending_timer.data = 0;
- netbk_tx_pending_timer.function = netbk_tx_pending_timeout;
+ init_timer(&netbk->netbk_tx_pending_timer);
+ netbk->netbk_tx_pending_timer.data = 0;
+ netbk->netbk_tx_pending_timer.function = netbk_tx_pending_timeout;
- foreign_page_tracker = alloc_page_foreign_tracker(MAX_PENDING_REQS);
- if (!foreign_page_tracker)
- return -ENOMEM;
- mmap_pages = alloc_empty_pages_and_pagevec(MAX_PENDING_REQS);
- if (mmap_pages == NULL) {
- printk("%s: out of memory\n", __FUNCTION__);
- free_page_foreign_tracker(foreign_page_tracker);
- return -ENOMEM;
+ netbk->mmap_pages =
+ alloc_empty_pages_and_pagevec(MAX_PENDING_REQS);
+ if (!netbk->mmap_pages) {
+ printk(KERN_ALERT "%s: out of memory\n", __func__);
+ rc = -ENOMEM;
+ goto failed_init2;
}
for (i = 0; i < MAX_PENDING_REQS; i++) {
- page = mmap_pages[i];
+ page = netbk->mmap_pages[i];
SetPageForeign(page, netif_page_release);
netif_set_page_index(page, i);
- INIT_LIST_HEAD(&pending_inuse[i].list);
+ INIT_LIST_HEAD(&netbk->pending_inuse[i].list);
}
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
+ netbk->pending_cons = 0;
+ netbk->pending_prod = MAX_PENDING_REQS;
for (i = 0; i < MAX_PENDING_REQS; i++)
- pending_ring[i] = i;
+ netbk->pending_ring[i] = i;
+
+ tasklet_init(&netbk->net_tx_tasklet, net_tx_action, 0);
+ tasklet_init(&netbk->net_rx_tasklet, net_rx_action, 0);
+
+ INIT_LIST_HEAD(&netbk->pending_inuse_head);
+ INIT_LIST_HEAD(&netbk->net_schedule_list);
+
+ spin_lock_init(&netbk->net_schedule_list_lock);
netbk_copy_skb_mode = NETBK_DONT_COPY_SKB;
if (MODPARM_copy_skb) {
@@ -1608,7 +1595,7 @@ static int __init netback_init(void)
rc = netif_xenbus_init();
if (rc)
- goto failed_init;
+ goto failed_init1;
#ifdef NETBE_DEBUG_INTERRUPT
(void)bind_virq_to_irqhandler(VIRQ_DEBUG,
@@ -1621,10 +1608,14 @@ static int __init netback_init(void)
return 0;
-failed_init:
- free_empty_pages_and_pagevec(mmap_pages, MAX_PENDING_REQS);
- del_timer(&netbk_tx_pending_timer);
- del_timer(&net_timer);
+failed_init1:
+ free_empty_pages_and_pagevec(netbk->mmap_pages, MAX_PENDING_REQS);
+failed_init2:
+ free_page_foreign_tracker(foreign_page_tracker);
+ del_timer(&netbk->netbk_tx_pending_timer);
+ del_timer(&netbk->net_timer);
+failed_init3:
+ kfree(netbk);
return rc;
}
--
1.6.0
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk'.
2010-04-29 14:28 [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk' Xu, Dongxiao
@ 2010-05-03 16:02 ` Konrad Rzeszutek Wilk
2010-05-04 0:48 ` Xu, Dongxiao
2010-05-03 16:05 ` Konrad Rzeszutek Wilk
1 sibling, 1 reply; 6+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-05-03 16:02 UTC (permalink / raw)
To: Xu, Dongxiao
Cc: Jeremy Fitzhardinge, xen-devel@lists.xensource.com, Steven Smith
On Thu, Apr 29, 2010 at 10:28:18PM +0800, Xu, Dongxiao wrote:
> Netback: Move global/static variables into struct xen_netbk.
scripts/checkpatch.pl --strict
~/0001-Netback-Move-global-static-variables-into-struct-xe.patch
WARNING: do not add new typedefs
#24: FILE: drivers/xen/netback/common.h:231:
+typedef unsigned int pending_ring_idx_t;
CHECK: spinlock_t definition without comment
#75: FILE: drivers/xen/netback/common.h:282:
+ spinlock_t net_schedule_list_lock;
total: 0 errors, 1 warnings, 1 checks, 876 lines checked
/home/konrad/0001-Netback-Move-global-static-variables-into-struct-xe.patch
has style problems, please review. If any of these errors
are false positives report them to
>
> Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk'.
2010-04-29 14:28 [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk' Xu, Dongxiao
2010-05-03 16:02 ` Konrad Rzeszutek Wilk
@ 2010-05-03 16:05 ` Konrad Rzeszutek Wilk
2010-05-04 0:51 ` Xu, Dongxiao
1 sibling, 1 reply; 6+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-05-03 16:05 UTC (permalink / raw)
To: Xu, Dongxiao
Cc: Jeremy Fitzhardinge, xen-devel@lists.xensource.com, Steven Smith
On Thu, Apr 29, 2010 at 10:28:18PM +0800, Xu, Dongxiao wrote:
> Netback: Move global/static variables into struct xen_netbk.
>
> Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
Hmm..
git checkout jeremy/xen/next -b test-netbk-kthread -f
Branch test-netbk-kthread set up to track remote branch
refs/remotes/jeremy/xen/next.
Switched to a new branch 'test-netbk-kthread'
[konrad@phenom linux]$ git reset --hard
HEAD is now at 5403063 Merge remote branch 'stefano-pvhvm/2.6.32-pvhvm' into xen/next
[konrad@phenom linux]$ patch -p1 < ~/0001-Netback-Move-global-static-variables-into-struct-xe.patch
patching file drivers/xen/netback/common.h
patching file drivers/xen/netback/netback.c
Hunk #1 succeeded at 48 (offset -1 lines).
Hunk #2 succeeded at 64 (offset -1 lines).
Hunk #3 succeeded at 90 (offset -1 lines).
Hunk #4 FAILED at 105.
Hunk #5 succeeded at 151 (offset -3 lines).
Hunk #6 succeeded at 305 (offset -3 lines).
Hunk #7 succeeded at 463 (offset -1 lines).
Hunk #8 succeeded at 490 (offset -1 lines).
Hunk #9 succeeded at 530 (offset -1 lines).
Hunk #10 succeeded at 547 (offset -1 lines).
Hunk #11 succeeded at 560 (offset -1 lines).
.. snip..
5 out of 44 hunks FAILED -- saving rejects to file
drivers/xen/netback/netback.c.rej
... what branch are these patches against?
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk'.
2010-05-03 16:02 ` Konrad Rzeszutek Wilk
@ 2010-05-04 0:48 ` Xu, Dongxiao
0 siblings, 0 replies; 6+ messages in thread
From: Xu, Dongxiao @ 2010-05-04 0:48 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk
Cc: Fitzhardinge, xen-devel@lists.xensource.com, Jeremy, Steven Smith
I didn't add the --strict option. I will change it accordingly.
However for +typedef unsigned int pending_ring_idx_t;
this typedef is moved from netback.c, and not the type.
Thanks,
Dongxiao
Konrad Rzeszutek Wilk wrote:
> On Thu, Apr 29, 2010 at 10:28:18PM +0800, Xu, Dongxiao wrote:
>> Netback: Move global/static variables into struct xen_netbk.
>
> scripts/checkpatch.pl --strict
> ~/0001-Netback-Move-global-static-variables-into-struct-xe.patch
> WARNING: do not add new typedefs
> #24: FILE: drivers/xen/netback/common.h:231:
> +typedef unsigned int pending_ring_idx_t;
>
> CHECK: spinlock_t definition without comment
> #75: FILE: drivers/xen/netback/common.h:282:
> + spinlock_t net_schedule_list_lock;
>
> total: 0 errors, 1 warnings, 1 checks, 876 lines checked
>
> /home/konrad/0001-Netback-Move-global-static-variables-into-struct-xe.patch
> has style problems, please review. If any of these errors
> are false positives report them to
>
>>
>> Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xensource.com
>> http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk'.
2010-05-03 16:05 ` Konrad Rzeszutek Wilk
@ 2010-05-04 0:51 ` Xu, Dongxiao
2010-05-04 2:03 ` Jeremy Fitzhardinge
0 siblings, 1 reply; 6+ messages in thread
From: Xu, Dongxiao @ 2010-05-04 0:51 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk
Cc: Fitzhardinge, xen-devel@lists.xensource.com, Jeremy, Steven Smith
Konrad Rzeszutek Wilk wrote:
The patchset is based on xen/master tree.
I saw some merges in xen/master/netback is not contained in
xen/next/netback, for example, the foreign_page_tracker.
So I rebased my work on xen/master tree.
Thanks,
Dongxiao
> On Thu, Apr 29, 2010 at 10:28:18PM +0800, Xu, Dongxiao wrote:
>> Netback: Move global/static variables into struct xen_netbk.
>>
>> Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
>
> Hmm..
>
> git checkout jeremy/xen/next -b test-netbk-kthread -f
> Branch test-netbk-kthread set up to track remote branch
> refs/remotes/jeremy/xen/next.
> Switched to a new branch 'test-netbk-kthread'
> [konrad@phenom linux]$ git reset --hard
> HEAD is now at 5403063 Merge remote branch
> 'stefano-pvhvm/2.6.32-pvhvm' into xen/next [konrad@phenom linux]$
> patch -p1 <
> ~/0001-Netback-Move-global-static-variables-into-struct-xe.patch
> patching file drivers/xen/netback/common.h
> patching file drivers/xen/netback/netback.c
> Hunk #1 succeeded at 48 (offset -1 lines).
> Hunk #2 succeeded at 64 (offset -1 lines).
> Hunk #3 succeeded at 90 (offset -1 lines).
> Hunk #4 FAILED at 105.
> Hunk #5 succeeded at 151 (offset -3 lines).
> Hunk #6 succeeded at 305 (offset -3 lines).
> Hunk #7 succeeded at 463 (offset -1 lines).
> Hunk #8 succeeded at 490 (offset -1 lines).
> Hunk #9 succeeded at 530 (offset -1 lines).
> Hunk #10 succeeded at 547 (offset -1 lines).
> Hunk #11 succeeded at 560 (offset -1 lines).
> .. snip..
> 5 out of 44 hunks FAILED -- saving rejects to file
> drivers/xen/netback/netback.c.rej
>
> ... what branch are these patches against?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk'.
2010-05-04 0:51 ` Xu, Dongxiao
@ 2010-05-04 2:03 ` Jeremy Fitzhardinge
0 siblings, 0 replies; 6+ messages in thread
From: Jeremy Fitzhardinge @ 2010-05-04 2:03 UTC (permalink / raw)
To: Xu, Dongxiao
Cc: xen-devel@lists.xensource.com, Steven Smith,
Konrad Rzeszutek Wilk
On 05/03/2010 05:51 PM, Xu, Dongxiao wrote:
> Konrad Rzeszutek Wilk wrote:
> The patchset is based on xen/master tree.
> I saw some merges in xen/master/netback is not contained in
> xen/next/netback, for example, the foreign_page_tracker.
>
> So I rebased my work on xen/master tree.
>
Please base on (ideally) xen/dom0/netback, or xen/next. The foreign
page tracker stuff is part of netchannel2, and not (yet?) included in
the 2.6.32+ kernels.
J
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-05-04 2:03 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-29 14:28 [Pv-ops][PATCH 1/4 v2] Netback: Generilize static/global variables into 'struct xen_netbk' Xu, Dongxiao
2010-05-03 16:02 ` Konrad Rzeszutek Wilk
2010-05-04 0:48 ` Xu, Dongxiao
2010-05-03 16:05 ` Konrad Rzeszutek Wilk
2010-05-04 0:51 ` Xu, Dongxiao
2010-05-04 2:03 ` Jeremy Fitzhardinge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).